]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/mpr/mpr_user.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / sys / dev / mpr / mpr_user.c
1 /*-
2  * Copyright (c) 2008 Yahoo!, Inc.
3  * All rights reserved.
4  * Written by: John Baldwin <jhb@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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.
17  *
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
28  * SUCH DAMAGE.
29  *
30  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
31  */
32 /*-
33  * Copyright (c) 2011-2015 LSI Corp.
34  * Copyright (c) 2013-2016 Avago Technologies
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56  * SUCH DAMAGE.
57  *
58  * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
59  *
60  * $FreeBSD$
61  */
62
63 #include <sys/cdefs.h>
64 __FBSDID("$FreeBSD$");
65
66 #include "opt_compat.h"
67
68 /* TODO Move headers to mprvar */
69 #include <sys/types.h>
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/kernel.h>
73 #include <sys/selinfo.h>
74 #include <sys/module.h>
75 #include <sys/bus.h>
76 #include <sys/conf.h>
77 #include <sys/bio.h>
78 #include <sys/malloc.h>
79 #include <sys/uio.h>
80 #include <sys/sysctl.h>
81 #include <sys/ioccom.h>
82 #include <sys/endian.h>
83 #include <sys/queue.h>
84 #include <sys/kthread.h>
85 #include <sys/taskqueue.h>
86 #include <sys/proc.h>
87 #include <sys/sysent.h>
88
89 #include <machine/bus.h>
90 #include <machine/resource.h>
91 #include <sys/rman.h>
92
93 #include <cam/cam.h>
94 #include <cam/cam_ccb.h>
95
96 #include <dev/mpr/mpi/mpi2_type.h>
97 #include <dev/mpr/mpi/mpi2.h>
98 #include <dev/mpr/mpi/mpi2_ioc.h>
99 #include <dev/mpr/mpi/mpi2_cnfg.h>
100 #include <dev/mpr/mpi/mpi2_init.h>
101 #include <dev/mpr/mpi/mpi2_tool.h>
102 #include <dev/mpr/mpi/mpi2_pci.h>
103 #include <dev/mpr/mpr_ioctl.h>
104 #include <dev/mpr/mprvar.h>
105 #include <dev/mpr/mpr_table.h>
106 #include <dev/mpr/mpr_sas.h>
107 #include <dev/pci/pcivar.h>
108 #include <dev/pci/pcireg.h>
109
110 static d_open_t         mpr_open;
111 static d_close_t        mpr_close;
112 static d_ioctl_t        mpr_ioctl_devsw;
113
114 static struct cdevsw mpr_cdevsw = {
115         .d_version =    D_VERSION,
116         .d_flags =      0,
117         .d_open =       mpr_open,
118         .d_close =      mpr_close,
119         .d_ioctl =      mpr_ioctl_devsw,
120         .d_name =       "mpr",
121 };
122
123 typedef int (mpr_user_f)(struct mpr_command *, struct mpr_usr_command *);
124 static mpr_user_f       mpi_pre_ioc_facts;
125 static mpr_user_f       mpi_pre_port_facts;
126 static mpr_user_f       mpi_pre_fw_download;
127 static mpr_user_f       mpi_pre_fw_upload;
128 static mpr_user_f       mpi_pre_sata_passthrough;
129 static mpr_user_f       mpi_pre_smp_passthrough;
130 static mpr_user_f       mpi_pre_config;
131 static mpr_user_f       mpi_pre_sas_io_unit_control;
132
133 static int mpr_user_read_cfg_header(struct mpr_softc *,
134     struct mpr_cfg_page_req *);
135 static int mpr_user_read_cfg_page(struct mpr_softc *,
136     struct mpr_cfg_page_req *, void *);
137 static int mpr_user_read_extcfg_header(struct mpr_softc *,
138     struct mpr_ext_cfg_page_req *);
139 static int mpr_user_read_extcfg_page(struct mpr_softc *,
140     struct mpr_ext_cfg_page_req *, void *);
141 static int mpr_user_write_cfg_page(struct mpr_softc *,
142     struct mpr_cfg_page_req *, void *);
143 static int mpr_user_setup_request(struct mpr_command *,
144     struct mpr_usr_command *);
145 static int mpr_user_command(struct mpr_softc *, struct mpr_usr_command *);
146
147 static int mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data);
148 static void mpr_user_get_adapter_data(struct mpr_softc *sc,
149     mpr_adapter_data_t *data);
150 static void mpr_user_read_pci_info(struct mpr_softc *sc, mpr_pci_info_t *data);
151 static uint8_t mpr_get_fw_diag_buffer_number(struct mpr_softc *sc,
152     uint32_t unique_id);
153 static int mpr_post_fw_diag_buffer(struct mpr_softc *sc,
154     mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
155 static int mpr_release_fw_diag_buffer(struct mpr_softc *sc,
156     mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
157     uint32_t diag_type);
158 static int mpr_diag_register(struct mpr_softc *sc,
159     mpr_fw_diag_register_t *diag_register, uint32_t *return_code);
160 static int mpr_diag_unregister(struct mpr_softc *sc,
161     mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
162 static int mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query,
163     uint32_t *return_code);
164 static int mpr_diag_read_buffer(struct mpr_softc *sc,
165     mpr_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
166     uint32_t *return_code);
167 static int mpr_diag_release(struct mpr_softc *sc,
168     mpr_fw_diag_release_t *diag_release, uint32_t *return_code);
169 static int mpr_do_diag_action(struct mpr_softc *sc, uint32_t action,
170     uint8_t *diag_action, uint32_t length, uint32_t *return_code);
171 static int mpr_user_diag_action(struct mpr_softc *sc, mpr_diag_action_t *data);
172 static void mpr_user_event_query(struct mpr_softc *sc, mpr_event_query_t *data);
173 static void mpr_user_event_enable(struct mpr_softc *sc,
174     mpr_event_enable_t *data);
175 static int mpr_user_event_report(struct mpr_softc *sc,
176     mpr_event_report_t *data);
177 static int mpr_user_reg_access(struct mpr_softc *sc, mpr_reg_access_t *data);
178 static int mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data);
179
180 static MALLOC_DEFINE(M_MPRUSER, "mpr_user", "Buffers for mpr(4) ioctls");
181
182 /* Macros from compat/freebsd32/freebsd32.h */
183 #define PTRIN(v)        (void *)(uintptr_t)(v)
184 #define PTROUT(v)       (uint32_t)(uintptr_t)(v)
185
186 #define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
187 #define PTRIN_CP(src,dst,fld)                           \
188         do { (dst).fld = PTRIN((src).fld); } while (0)
189 #define PTROUT_CP(src,dst,fld) \
190         do { (dst).fld = PTROUT((src).fld); } while (0)
191
192 /*
193  * MPI functions that support IEEE SGLs for SAS3.
194  */
195 static uint8_t ieee_sgl_func_list[] = {
196         MPI2_FUNCTION_SCSI_IO_REQUEST,
197         MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH,
198         MPI2_FUNCTION_SMP_PASSTHROUGH,
199         MPI2_FUNCTION_SATA_PASSTHROUGH,
200         MPI2_FUNCTION_FW_UPLOAD,
201         MPI2_FUNCTION_FW_DOWNLOAD,
202         MPI2_FUNCTION_TARGET_ASSIST,
203         MPI2_FUNCTION_TARGET_STATUS_SEND,
204         MPI2_FUNCTION_TOOLBOX
205 };
206
207 int
208 mpr_attach_user(struct mpr_softc *sc)
209 {
210         int unit;
211
212         unit = device_get_unit(sc->mpr_dev);
213         sc->mpr_cdev = make_dev(&mpr_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640,
214             "mpr%d", unit);
215
216         if (sc->mpr_cdev == NULL)
217                 return (ENOMEM);
218
219         sc->mpr_cdev->si_drv1 = sc;
220         return (0);
221 }
222
223 void
224 mpr_detach_user(struct mpr_softc *sc)
225 {
226
227         /* XXX: do a purge of pending requests? */
228         if (sc->mpr_cdev != NULL)
229                 destroy_dev(sc->mpr_cdev);
230 }
231
232 static int
233 mpr_open(struct cdev *dev, int flags, int fmt, struct thread *td)
234 {
235
236         return (0);
237 }
238
239 static int
240 mpr_close(struct cdev *dev, int flags, int fmt, struct thread *td)
241 {
242
243         return (0);
244 }
245
246 static int
247 mpr_user_read_cfg_header(struct mpr_softc *sc,
248     struct mpr_cfg_page_req *page_req)
249 {
250         MPI2_CONFIG_PAGE_HEADER *hdr;
251         struct mpr_config_params params;
252         int         error;
253
254         hdr = &params.hdr.Struct;
255         params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
256         params.page_address = le32toh(page_req->page_address);
257         hdr->PageVersion = 0;
258         hdr->PageLength = 0;
259         hdr->PageNumber = page_req->header.PageNumber;
260         hdr->PageType = page_req->header.PageType;
261         params.buffer = NULL;
262         params.length = 0;
263         params.callback = NULL;
264
265         if ((error = mpr_read_config_page(sc, &params)) != 0) {
266                 /*
267                  * Leave the request. Without resetting the chip, it's
268                  * still owned by it and we'll just get into trouble
269                  * freeing it now. Mark it as abandoned so that if it
270                  * shows up later it can be freed.
271                  */
272                 mpr_printf(sc, "read_cfg_header timed out\n");
273                 return (ETIMEDOUT);
274         }
275
276         page_req->ioc_status = htole16(params.status);
277         if ((page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
278             MPI2_IOCSTATUS_SUCCESS) {
279                 bcopy(hdr, &page_req->header, sizeof(page_req->header));
280         }
281
282         return (0);
283 }
284
285 static int
286 mpr_user_read_cfg_page(struct mpr_softc *sc, struct mpr_cfg_page_req *page_req,
287     void *buf)
288 {
289         MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
290         struct mpr_config_params params;
291         int           error;
292
293         reqhdr = buf;
294         hdr = &params.hdr.Struct;
295         hdr->PageVersion = reqhdr->PageVersion;
296         hdr->PageLength = reqhdr->PageLength;
297         hdr->PageNumber = reqhdr->PageNumber;
298         hdr->PageType = reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK;
299         params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
300         params.page_address = le32toh(page_req->page_address);
301         params.buffer = buf;
302         params.length = le32toh(page_req->len);
303         params.callback = NULL;
304
305         if ((error = mpr_read_config_page(sc, &params)) != 0) {
306                 mpr_printf(sc, "mpr_user_read_cfg_page timed out\n");
307                 return (ETIMEDOUT);
308         }
309
310         page_req->ioc_status = htole16(params.status);
311         return (0);
312 }
313
314 static int
315 mpr_user_read_extcfg_header(struct mpr_softc *sc,
316     struct mpr_ext_cfg_page_req *ext_page_req)
317 {
318         MPI2_CONFIG_EXTENDED_PAGE_HEADER *hdr;
319         struct mpr_config_params params;
320         int         error;
321
322         hdr = &params.hdr.Ext;
323         params.action = MPI2_CONFIG_ACTION_PAGE_HEADER;
324         hdr->PageVersion = ext_page_req->header.PageVersion;
325         hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
326         hdr->ExtPageLength = 0;
327         hdr->PageNumber = ext_page_req->header.PageNumber;
328         hdr->ExtPageType = ext_page_req->header.ExtPageType;
329         params.page_address = le32toh(ext_page_req->page_address);
330         params.buffer = NULL;
331         params.length = 0;
332         params.callback = NULL;
333
334         if ((error = mpr_read_config_page(sc, &params)) != 0) {
335                 /*
336                  * Leave the request. Without resetting the chip, it's
337                  * still owned by it and we'll just get into trouble
338                  * freeing it now. Mark it as abandoned so that if it
339                  * shows up later it can be freed.
340                  */
341                 mpr_printf(sc, "mpr_user_read_extcfg_header timed out\n");
342                 return (ETIMEDOUT);
343         }
344
345         ext_page_req->ioc_status = htole16(params.status);
346         if ((ext_page_req->ioc_status & MPI2_IOCSTATUS_MASK) ==
347             MPI2_IOCSTATUS_SUCCESS) {
348                 ext_page_req->header.PageVersion = hdr->PageVersion;
349                 ext_page_req->header.PageNumber = hdr->PageNumber;
350                 ext_page_req->header.PageType = hdr->PageType;
351                 ext_page_req->header.ExtPageLength = hdr->ExtPageLength;
352                 ext_page_req->header.ExtPageType = hdr->ExtPageType;
353         }
354
355         return (0);
356 }
357
358 static int
359 mpr_user_read_extcfg_page(struct mpr_softc *sc,
360     struct mpr_ext_cfg_page_req *ext_page_req, void *buf)
361 {
362         MPI2_CONFIG_EXTENDED_PAGE_HEADER *reqhdr, *hdr;
363         struct mpr_config_params params;
364         int error;
365
366         reqhdr = buf;
367         hdr = &params.hdr.Ext;
368         params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
369         params.page_address = le32toh(ext_page_req->page_address);
370         hdr->PageVersion = reqhdr->PageVersion;
371         hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
372         hdr->PageNumber = reqhdr->PageNumber;
373         hdr->ExtPageType = reqhdr->ExtPageType;
374         hdr->ExtPageLength = reqhdr->ExtPageLength;
375         params.buffer = buf;
376         params.length = le32toh(ext_page_req->len);
377         params.callback = NULL;
378
379         if ((error = mpr_read_config_page(sc, &params)) != 0) {
380                 mpr_printf(sc, "mpr_user_read_extcfg_page timed out\n");
381                 return (ETIMEDOUT);
382         }
383
384         ext_page_req->ioc_status = htole16(params.status);
385         return (0);
386 }
387
388 static int
389 mpr_user_write_cfg_page(struct mpr_softc *sc,
390     struct mpr_cfg_page_req *page_req, void *buf)
391 {
392         MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
393         struct mpr_config_params params;
394         u_int         hdr_attr;
395         int           error;
396
397         reqhdr = buf;
398         hdr = &params.hdr.Struct;
399         hdr_attr = reqhdr->PageType & MPI2_CONFIG_PAGEATTR_MASK;
400         if (hdr_attr != MPI2_CONFIG_PAGEATTR_CHANGEABLE &&
401             hdr_attr != MPI2_CONFIG_PAGEATTR_PERSISTENT) {
402                 mpr_printf(sc, "page type 0x%x not changeable\n",
403                         reqhdr->PageType & MPI2_CONFIG_PAGETYPE_MASK);
404                 return (EINVAL);
405         }
406
407         /*
408          * There isn't any point in restoring stripped out attributes
409          * if you then mask them going down to issue the request.
410          */
411
412         hdr->PageVersion = reqhdr->PageVersion;
413         hdr->PageLength = reqhdr->PageLength;
414         hdr->PageNumber = reqhdr->PageNumber;
415         hdr->PageType = reqhdr->PageType;
416         params.action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
417         params.page_address = le32toh(page_req->page_address);
418         params.buffer = buf;
419         params.length = le32toh(page_req->len);
420         params.callback = NULL;
421
422         if ((error = mpr_write_config_page(sc, &params)) != 0) {
423                 mpr_printf(sc, "mpr_write_cfg_page timed out\n");
424                 return (ETIMEDOUT);
425         }
426
427         page_req->ioc_status = htole16(params.status);
428         return (0);
429 }
430
431 void
432 mpr_init_sge(struct mpr_command *cm, void *req, void *sge)
433 {
434         int off, space;
435
436         space = (int)cm->cm_sc->facts->IOCRequestFrameSize * 4;
437         off = (uintptr_t)sge - (uintptr_t)req;
438
439         KASSERT(off < space, ("bad pointers %p %p, off %d, space %d",
440             req, sge, off, space));
441
442         cm->cm_sge = sge;
443         cm->cm_sglsize = space - off;
444 }
445
446 /*
447  * Prepare the mpr_command for an IOC_FACTS request.
448  */
449 static int
450 mpi_pre_ioc_facts(struct mpr_command *cm, struct mpr_usr_command *cmd)
451 {
452         MPI2_IOC_FACTS_REQUEST *req = (void *)cm->cm_req;
453         MPI2_IOC_FACTS_REPLY *rpl;
454
455         if (cmd->req_len != sizeof *req)
456                 return (EINVAL);
457         if (cmd->rpl_len != sizeof *rpl)
458                 return (EINVAL);
459
460         cm->cm_sge = NULL;
461         cm->cm_sglsize = 0;
462         return (0);
463 }
464
465 /*
466  * Prepare the mpr_command for a PORT_FACTS request.
467  */
468 static int
469 mpi_pre_port_facts(struct mpr_command *cm, struct mpr_usr_command *cmd)
470 {
471         MPI2_PORT_FACTS_REQUEST *req = (void *)cm->cm_req;
472         MPI2_PORT_FACTS_REPLY *rpl;
473
474         if (cmd->req_len != sizeof *req)
475                 return (EINVAL);
476         if (cmd->rpl_len != sizeof *rpl)
477                 return (EINVAL);
478
479         cm->cm_sge = NULL;
480         cm->cm_sglsize = 0;
481         return (0);
482 }
483
484 /*
485  * Prepare the mpr_command for a FW_DOWNLOAD request.
486  */
487 static int
488 mpi_pre_fw_download(struct mpr_command *cm, struct mpr_usr_command *cmd)
489 {
490         MPI25_FW_DOWNLOAD_REQUEST *req = (void *)cm->cm_req;
491         MPI2_FW_DOWNLOAD_REPLY *rpl;
492         int error;
493
494         if (cmd->req_len != sizeof *req)
495                 return (EINVAL);
496         if (cmd->rpl_len != sizeof *rpl)
497                 return (EINVAL);
498
499         if (cmd->len == 0)
500                 return (EINVAL);
501
502         error = copyin(cmd->buf, cm->cm_data, cmd->len);
503         if (error != 0)
504                 return (error);
505
506         mpr_init_sge(cm, req, &req->SGL);
507
508         /*
509          * For now, the F/W image must be provided in a single request.
510          */
511         if ((req->MsgFlags & MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT) == 0)
512                 return (EINVAL);
513         if (req->TotalImageSize != cmd->len)
514                 return (EINVAL);
515
516         req->ImageOffset = 0;
517         req->ImageSize = cmd->len;
518
519         cm->cm_flags |= MPR_CM_FLAGS_DATAOUT;
520
521         return (mpr_push_ieee_sge(cm, &req->SGL, 0));
522 }
523
524 /*
525  * Prepare the mpr_command for a FW_UPLOAD request.
526  */
527 static int
528 mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd)
529 {
530         MPI25_FW_UPLOAD_REQUEST *req = (void *)cm->cm_req;
531         MPI2_FW_UPLOAD_REPLY *rpl;
532
533         if (cmd->req_len != sizeof *req)
534                 return (EINVAL);
535         if (cmd->rpl_len != sizeof *rpl)
536                 return (EINVAL);
537
538         mpr_init_sge(cm, req, &req->SGL);
539         if (cmd->len == 0) {
540                 /* Perhaps just asking what the size of the fw is? */
541                 return (0);
542         }
543
544         req->ImageOffset = 0;
545         req->ImageSize = cmd->len;
546
547         cm->cm_flags |= MPR_CM_FLAGS_DATAIN;
548
549         return (mpr_push_ieee_sge(cm, &req->SGL, 0));
550 }
551
552 /*
553  * Prepare the mpr_command for a SATA_PASSTHROUGH request.
554  */
555 static int
556 mpi_pre_sata_passthrough(struct mpr_command *cm, struct mpr_usr_command *cmd)
557 {
558         MPI2_SATA_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
559         MPI2_SATA_PASSTHROUGH_REPLY *rpl;
560
561         if (cmd->req_len != sizeof *req)
562                 return (EINVAL);
563         if (cmd->rpl_len != sizeof *rpl)
564                 return (EINVAL);
565
566         mpr_init_sge(cm, req, &req->SGL);
567         return (0);
568 }
569
570 /*
571  * Prepare the mpr_command for a SMP_PASSTHROUGH request.
572  */
573 static int
574 mpi_pre_smp_passthrough(struct mpr_command *cm, struct mpr_usr_command *cmd)
575 {
576         MPI2_SMP_PASSTHROUGH_REQUEST *req = (void *)cm->cm_req;
577         MPI2_SMP_PASSTHROUGH_REPLY *rpl;
578
579         if (cmd->req_len != sizeof *req)
580                 return (EINVAL);
581         if (cmd->rpl_len != sizeof *rpl)
582                 return (EINVAL);
583
584         mpr_init_sge(cm, req, &req->SGL);
585         return (0);
586 }
587
588 /*
589  * Prepare the mpr_command for a CONFIG request.
590  */
591 static int
592 mpi_pre_config(struct mpr_command *cm, struct mpr_usr_command *cmd)
593 {
594         MPI2_CONFIG_REQUEST *req = (void *)cm->cm_req;
595         MPI2_CONFIG_REPLY *rpl;
596
597         if (cmd->req_len != sizeof *req)
598                 return (EINVAL);
599         if (cmd->rpl_len != sizeof *rpl)
600                 return (EINVAL);
601
602         mpr_init_sge(cm, req, &req->PageBufferSGE);
603         return (0);
604 }
605
606 /*
607  * Prepare the mpr_command for a SAS_IO_UNIT_CONTROL request.
608  */
609 static int
610 mpi_pre_sas_io_unit_control(struct mpr_command *cm,
611                              struct mpr_usr_command *cmd)
612 {
613
614         cm->cm_sge = NULL;
615         cm->cm_sglsize = 0;
616         return (0);
617 }
618
619 /*
620  * A set of functions to prepare an mpr_command for the various
621  * supported requests.
622  */
623 struct mpr_user_func {
624         U8              Function;
625         mpr_user_f      *f_pre;
626 } mpr_user_func_list[] = {
627         { MPI2_FUNCTION_IOC_FACTS,              mpi_pre_ioc_facts },
628         { MPI2_FUNCTION_PORT_FACTS,             mpi_pre_port_facts },
629         { MPI2_FUNCTION_FW_DOWNLOAD,            mpi_pre_fw_download },
630         { MPI2_FUNCTION_FW_UPLOAD,              mpi_pre_fw_upload },
631         { MPI2_FUNCTION_SATA_PASSTHROUGH,       mpi_pre_sata_passthrough },
632         { MPI2_FUNCTION_SMP_PASSTHROUGH,        mpi_pre_smp_passthrough},
633         { MPI2_FUNCTION_CONFIG,                 mpi_pre_config},
634         { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL,    mpi_pre_sas_io_unit_control },
635         { 0xFF,                                 NULL } /* list end */
636 };
637
638 static int
639 mpr_user_setup_request(struct mpr_command *cm, struct mpr_usr_command *cmd)
640 {
641         MPI2_REQUEST_HEADER *hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;   
642         struct mpr_user_func *f;
643
644         for (f = mpr_user_func_list; f->f_pre != NULL; f++) {
645                 if (hdr->Function == f->Function)
646                         return (f->f_pre(cm, cmd));
647         }
648         return (EINVAL);
649 }       
650
651 static int
652 mpr_user_command(struct mpr_softc *sc, struct mpr_usr_command *cmd)
653 {
654         MPI2_REQUEST_HEADER *hdr;       
655         MPI2_DEFAULT_REPLY *rpl = NULL;
656         void *buf = NULL;
657         struct mpr_command *cm = NULL;
658         int err = 0;
659         int sz;
660
661         mpr_lock(sc);
662         cm = mpr_alloc_command(sc);
663
664         if (cm == NULL) {
665                 mpr_printf(sc, "%s: no mpr requests\n", __func__);
666                 err = ENOMEM;
667                 goto RetFree;
668         }
669         mpr_unlock(sc);
670
671         hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
672
673         mpr_dprint(sc, MPR_USER, "%s: req %p %d  rpl %p %d\n", __func__,
674             cmd->req, cmd->req_len, cmd->rpl, cmd->rpl_len);
675
676         if (cmd->req_len > (int)sc->facts->IOCRequestFrameSize * 4) {
677                 err = EINVAL;
678                 goto RetFreeUnlocked;
679         }
680         err = copyin(cmd->req, hdr, cmd->req_len);
681         if (err != 0)
682                 goto RetFreeUnlocked;
683
684         mpr_dprint(sc, MPR_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
685             hdr->Function, hdr->MsgFlags);
686
687         if (cmd->len > 0) {
688                 buf = malloc(cmd->len, M_MPRUSER, M_WAITOK|M_ZERO);
689                 cm->cm_data = buf;
690                 cm->cm_length = cmd->len;
691         } else {
692                 cm->cm_data = NULL;
693                 cm->cm_length = 0;
694         }
695
696         cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE;
697         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
698
699         err = mpr_user_setup_request(cm, cmd);
700         if (err == EINVAL) {
701                 mpr_printf(sc, "%s: unsupported parameter or unsupported "
702                     "function in request (function = 0x%X)\n", __func__,
703                     hdr->Function);
704         }
705         if (err != 0)
706                 goto RetFreeUnlocked;
707
708         mpr_lock(sc);
709         err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
710
711         if (err || (cm == NULL)) {
712                 mpr_printf(sc, "%s: invalid request: error %d\n",
713                     __func__, err);
714                 goto RetFree;
715         }
716
717         if (cm != NULL)
718                 rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
719         if (rpl != NULL)
720                 sz = rpl->MsgLength * 4;
721         else
722                 sz = 0;
723         
724         if (sz > cmd->rpl_len) {
725                 mpr_printf(sc, "%s: user reply buffer (%d) smaller than "
726                     "returned buffer (%d)\n", __func__, cmd->rpl_len, sz);
727                 sz = cmd->rpl_len;
728         }       
729
730         mpr_unlock(sc);
731         copyout(rpl, cmd->rpl, sz);
732         if (buf != NULL)
733                 copyout(buf, cmd->buf, cmd->len);
734         mpr_dprint(sc, MPR_USER, "%s: reply size %d\n", __func__, sz);
735
736 RetFreeUnlocked:
737         mpr_lock(sc);
738 RetFree:
739         if (cm != NULL)
740                 mpr_free_command(sc, cm);
741         mpr_unlock(sc);
742         if (buf != NULL)
743                 free(buf, M_MPRUSER);
744         return (err);
745 }
746
747 static int
748 mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
749 {
750         MPI2_REQUEST_HEADER     *hdr, tmphdr;   
751         MPI2_DEFAULT_REPLY      *rpl;
752         Mpi26NVMeEncapsulatedErrorReply_t *nvme_error_reply = NULL;
753         Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL;
754         struct mpr_command      *cm = NULL;
755         int                     i, err = 0, dir = 0, sz;
756         uint8_t                 tool, function = 0;
757         u_int                   sense_len;
758         struct mprsas_target    *targ = NULL;
759
760         /*
761          * Only allow one passthru command at a time.  Use the MPR_FLAGS_BUSY
762          * bit to denote that a passthru is being processed.
763          */
764         mpr_lock(sc);
765         if (sc->mpr_flags & MPR_FLAGS_BUSY) {
766                 mpr_dprint(sc, MPR_USER, "%s: Only one passthru command "
767                     "allowed at a single time.", __func__);
768                 mpr_unlock(sc);
769                 return (EBUSY);
770         }
771         sc->mpr_flags |= MPR_FLAGS_BUSY;
772         mpr_unlock(sc);
773
774         /*
775          * Do some validation on data direction.  Valid cases are:
776          *    1) DataSize is 0 and direction is NONE
777          *    2) DataSize is non-zero and one of:
778          *        a) direction is READ or
779          *        b) direction is WRITE or
780          *        c) direction is BOTH and DataOutSize is non-zero
781          * If valid and the direction is BOTH, change the direction to READ.
782          * if valid and the direction is not BOTH, make sure DataOutSize is 0.
783          */
784         if (((data->DataSize == 0) &&
785             (data->DataDirection == MPR_PASS_THRU_DIRECTION_NONE)) ||
786             ((data->DataSize != 0) &&
787             ((data->DataDirection == MPR_PASS_THRU_DIRECTION_READ) ||
788             (data->DataDirection == MPR_PASS_THRU_DIRECTION_WRITE) ||
789             ((data->DataDirection == MPR_PASS_THRU_DIRECTION_BOTH) &&
790             (data->DataOutSize != 0))))) {
791                 if (data->DataDirection == MPR_PASS_THRU_DIRECTION_BOTH)
792                         data->DataDirection = MPR_PASS_THRU_DIRECTION_READ;
793                 else
794                         data->DataOutSize = 0;
795         } else
796                 return (EINVAL);
797
798         mpr_dprint(sc, MPR_USER, "%s: req 0x%jx %d  rpl 0x%jx %d "
799             "data in 0x%jx %d data out 0x%jx %d data dir %d\n", __func__,
800             data->PtrRequest, data->RequestSize, data->PtrReply,
801             data->ReplySize, data->PtrData, data->DataSize,
802             data->PtrDataOut, data->DataOutSize, data->DataDirection);
803
804         /*
805          * copy in the header so we know what we're dealing with before we
806          * commit to allocating a command for it.
807          */
808         err = copyin(PTRIN(data->PtrRequest), &tmphdr, data->RequestSize);
809         if (err != 0)
810                 goto RetFreeUnlocked;
811
812         if (data->RequestSize > (int)sc->facts->IOCRequestFrameSize * 4) {
813                 err = EINVAL;
814                 goto RetFreeUnlocked;
815         }
816
817         function = tmphdr.Function;
818         mpr_dprint(sc, MPR_USER, "%s: Function %02X MsgFlags %02X\n", __func__,
819             function, tmphdr.MsgFlags);
820
821         /*
822          * Handle a passthru TM request.
823          */
824         if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
825                 MPI2_SCSI_TASK_MANAGE_REQUEST   *task;
826
827                 mpr_lock(sc);
828                 cm = mprsas_alloc_tm(sc);
829                 if (cm == NULL) {
830                         err = EINVAL;
831                         goto Ret;
832                 }
833
834                 /* Copy the header in.  Only a small fixup is needed. */
835                 task = (MPI2_SCSI_TASK_MANAGE_REQUEST *)cm->cm_req;
836                 bcopy(&tmphdr, task, data->RequestSize);
837                 task->TaskMID = cm->cm_desc.Default.SMID;
838
839                 cm->cm_data = NULL;
840                 cm->cm_desc.HighPriority.RequestFlags =
841                     MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
842                 cm->cm_complete = NULL;
843                 cm->cm_complete_data = NULL;
844
845                 targ = mprsas_find_target_by_handle(sc->sassc, 0,
846                     task->DevHandle);
847                 if (targ == NULL) {
848                         mpr_dprint(sc, MPR_INFO,
849                            "%s %d : invalid handle for requested TM 0x%x \n",
850                            __func__, __LINE__, task->DevHandle);
851                         err = 1;
852                 } else {
853                         mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
854                         err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
855                 }
856
857                 if (err != 0) {
858                         err = EIO;
859                         mpr_dprint(sc, MPR_FAULT, "%s: task management failed",
860                             __func__);
861                 }
862                 /*
863                  * Copy the reply data and sense data to user space.
864                  */
865                 if ((cm != NULL) && (cm->cm_reply != NULL)) {
866                         rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
867                         sz = rpl->MsgLength * 4;
868         
869                         if (sz > data->ReplySize) {
870                                 mpr_printf(sc, "%s: user reply buffer (%d) "
871                                     "smaller than returned buffer (%d)\n",
872                                     __func__, data->ReplySize, sz);
873                         }
874                         mpr_unlock(sc);
875                         copyout(cm->cm_reply, PTRIN(data->PtrReply),
876                             data->ReplySize);
877                         mpr_lock(sc);
878                 }
879                 mprsas_free_tm(sc, cm);
880                 goto Ret;
881         }
882
883         mpr_lock(sc);
884         cm = mpr_alloc_command(sc);
885
886         if (cm == NULL) {
887                 mpr_printf(sc, "%s: no mpr requests\n", __func__);
888                 err = ENOMEM;
889                 goto Ret;
890         }
891         mpr_unlock(sc);
892
893         hdr = (MPI2_REQUEST_HEADER *)cm->cm_req;
894         bcopy(&tmphdr, hdr, data->RequestSize);
895
896         /*
897          * Do some checking to make sure the IOCTL request contains a valid
898          * request.  Then set the SGL info.
899          */
900         mpr_init_sge(cm, hdr, (void *)((uint8_t *)hdr + data->RequestSize));
901
902         /*
903          * Set up for read, write or both.  From check above, DataOutSize will
904          * be 0 if direction is READ or WRITE, but it will have some non-zero
905          * value if the direction is BOTH.  So, just use the biggest size to get
906          * the cm_data buffer size.  If direction is BOTH, 2 SGLs need to be set
907          * up; the first is for the request and the second will contain the
908          * response data. cm_out_len needs to be set here and this will be used
909          * when the SGLs are set up.
910          */
911         cm->cm_data = NULL;
912         cm->cm_length = MAX(data->DataSize, data->DataOutSize);
913         cm->cm_out_len = data->DataOutSize;
914         cm->cm_flags = 0;
915         if (cm->cm_length != 0) {
916                 cm->cm_data = malloc(cm->cm_length, M_MPRUSER, M_WAITOK |
917                     M_ZERO);
918                 cm->cm_flags = MPR_CM_FLAGS_DATAIN;
919                 if (data->DataOutSize) {
920                         cm->cm_flags |= MPR_CM_FLAGS_DATAOUT;
921                         err = copyin(PTRIN(data->PtrDataOut),
922                             cm->cm_data, data->DataOutSize);
923                 } else if (data->DataDirection ==
924                     MPR_PASS_THRU_DIRECTION_WRITE) {
925                         cm->cm_flags = MPR_CM_FLAGS_DATAOUT;
926                         err = copyin(PTRIN(data->PtrData),
927                             cm->cm_data, data->DataSize);
928                 }
929                 if (err != 0)
930                         mpr_dprint(sc, MPR_FAULT, "%s: failed to copy IOCTL "
931                             "data from user space\n", __func__);
932         }
933         /*
934          * Set this flag only if processing a command that does not need an
935          * IEEE SGL.  The CLI Tool within the Toolbox uses IEEE SGLs, so clear
936          * the flag only for that tool if processing a Toolbox function.
937          */
938         cm->cm_flags |= MPR_CM_FLAGS_SGE_SIMPLE;
939         for (i = 0; i < sizeof (ieee_sgl_func_list); i++) {
940                 if (function == ieee_sgl_func_list[i]) {
941                         if (function == MPI2_FUNCTION_TOOLBOX)
942                         {
943                                 tool = (uint8_t)hdr->FunctionDependent1;
944                                 if (tool != MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL)
945                                         break;
946                         }
947                         cm->cm_flags &= ~MPR_CM_FLAGS_SGE_SIMPLE;
948                         break;
949                 }
950         }
951         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
952
953         if (function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
954                 nvme_encap_request =
955                     (Mpi26NVMeEncapsulatedRequest_t *)cm->cm_req;
956                 cm->cm_desc.Default.RequestFlags =
957                     MPI26_REQ_DESCRIPT_FLAGS_PCIE_ENCAPSULATED;
958
959                 /*
960                  * Get the Physical Address of the sense buffer.
961                  * Save the user's Error Response buffer address and use that
962                  *   field to hold the sense buffer address.
963                  * Clear the internal sense buffer, which will potentially hold
964                  *   the Completion Queue Entry on return, or 0 if no Entry.
965                  * Build the PRPs and set direction bits.
966                  * Send the request.
967                  */
968                 cm->nvme_error_response =
969                     (uint64_t *)(uintptr_t)(((uint64_t)nvme_encap_request->
970                     ErrorResponseBaseAddress.High << 32) |
971                     (uint64_t)nvme_encap_request->
972                     ErrorResponseBaseAddress.Low);
973                 nvme_encap_request->ErrorResponseBaseAddress.High =
974                     htole32((uint32_t)((uint64_t)cm->cm_sense_busaddr >> 32));
975                 nvme_encap_request->ErrorResponseBaseAddress.Low =
976                     htole32(cm->cm_sense_busaddr);
977                 memset(cm->cm_sense, 0, NVME_ERROR_RESPONSE_SIZE);
978                 mpr_build_nvme_prp(sc, cm, nvme_encap_request, cm->cm_data,
979                     data->DataSize, data->DataOutSize);
980         }
981
982         /*
983          * Set up Sense buffer and SGL offset for IO passthru.  SCSI IO request
984          * uses SCSI IO or Fast Path SCSI IO descriptor.
985          */
986         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
987             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
988                 MPI2_SCSI_IO_REQUEST    *scsi_io_req;
989
990                 scsi_io_req = (MPI2_SCSI_IO_REQUEST *)hdr;
991                 /*
992                  * Put SGE for data and data_out buffer at the end of
993                  * scsi_io_request message header (64 bytes in total).
994                  * Following above SGEs, the residual space will be used by
995                  * sense data.
996                  */
997                 scsi_io_req->SenseBufferLength = (uint8_t)(data->RequestSize -
998                     64);
999                 scsi_io_req->SenseBufferLowAddress =
1000                     htole32(cm->cm_sense_busaddr);
1001
1002                 /*
1003                  * Set SGLOffset0 value.  This is the number of dwords that SGL
1004                  * is offset from the beginning of MPI2_SCSI_IO_REQUEST struct.
1005                  */
1006                 scsi_io_req->SGLOffset0 = 24;
1007
1008                 /*
1009                  * Setup descriptor info.  RAID passthrough must use the
1010                  * default request descriptor which is already set, so if this
1011                  * is a SCSI IO request, change the descriptor to SCSI IO or
1012                  * Fast Path SCSI IO.  Also, if this is a SCSI IO request,
1013                  * handle the reply in the mprsas_scsio_complete function.
1014                  */
1015                 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
1016                         targ = mprsas_find_target_by_handle(sc->sassc, 0,
1017                             scsi_io_req->DevHandle);
1018
1019                         if (!targ) {
1020                                 printf("No Target found for handle %d\n",
1021                                     scsi_io_req->DevHandle);
1022                                 err = EINVAL;
1023                                 goto RetFreeUnlocked;
1024                         }
1025
1026                         if (targ->scsi_req_desc_type ==
1027                             MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO) {
1028                                 cm->cm_desc.FastPathSCSIIO.RequestFlags =
1029                                     MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
1030                                 if (!sc->atomic_desc_capable) {
1031                                         cm->cm_desc.FastPathSCSIIO.DevHandle =
1032                                             scsi_io_req->DevHandle;
1033                                 }
1034                                 scsi_io_req->IoFlags |=
1035                                     MPI25_SCSIIO_IOFLAGS_FAST_PATH;
1036                         } else {
1037                                 cm->cm_desc.SCSIIO.RequestFlags =
1038                                     MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
1039                                 if (!sc->atomic_desc_capable) {
1040                                         cm->cm_desc.SCSIIO.DevHandle =
1041                                             scsi_io_req->DevHandle;
1042                                 }
1043                         }
1044
1045                         /*
1046                          * Make sure the DevHandle is not 0 because this is a
1047                          * likely error.
1048                          */
1049                         if (scsi_io_req->DevHandle == 0) {
1050                                 err = EINVAL;
1051                                 goto RetFreeUnlocked;
1052                         }
1053                 }
1054         }
1055
1056         mpr_lock(sc);
1057
1058         err = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
1059
1060         if (err || (cm == NULL)) {
1061                 mpr_printf(sc, "%s: invalid request: error %d\n", __func__,
1062                     err);
1063                 goto RetFree;
1064         }
1065
1066         /*
1067          * Sync the DMA data, if any.  Then copy the data to user space.
1068          */
1069         if (cm->cm_data != NULL) {
1070                 if (cm->cm_flags & MPR_CM_FLAGS_DATAIN)
1071                         dir = BUS_DMASYNC_POSTREAD;
1072                 else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT)
1073                         dir = BUS_DMASYNC_POSTWRITE;
1074                 bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
1075                 bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
1076
1077                 if (cm->cm_flags & MPR_CM_FLAGS_DATAIN) {
1078                         mpr_unlock(sc);
1079                         err = copyout(cm->cm_data,
1080                             PTRIN(data->PtrData), data->DataSize);
1081                         mpr_lock(sc);
1082                         if (err != 0)
1083                                 mpr_dprint(sc, MPR_FAULT, "%s: failed to copy "
1084                                     "IOCTL data to user space\n", __func__);
1085                 }
1086         }
1087
1088         /*
1089          * Copy the reply data and sense data to user space.
1090          */
1091         if (cm->cm_reply != NULL) {
1092                 rpl = (MPI2_DEFAULT_REPLY *)cm->cm_reply;
1093                 sz = rpl->MsgLength * 4;
1094
1095                 if (sz > data->ReplySize) {
1096                         mpr_printf(sc, "%s: user reply buffer (%d) smaller "
1097                             "than returned buffer (%d)\n", __func__,
1098                             data->ReplySize, sz);
1099                 }
1100                 mpr_unlock(sc);
1101                 copyout(cm->cm_reply, PTRIN(data->PtrReply), data->ReplySize);
1102                 mpr_lock(sc);
1103
1104                 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
1105                     (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
1106                         if (((MPI2_SCSI_IO_REPLY *)rpl)->SCSIState &
1107                             MPI2_SCSI_STATE_AUTOSENSE_VALID) {
1108                                 sense_len =
1109                                     MIN((le32toh(((MPI2_SCSI_IO_REPLY *)rpl)->
1110                                     SenseCount)), sizeof(struct
1111                                     scsi_sense_data));
1112                                 mpr_unlock(sc);
1113                                 copyout(cm->cm_sense, cm->cm_req + 64,
1114                                     sense_len);
1115                                 mpr_lock(sc);
1116                         }
1117                 }
1118
1119                 /*
1120                  * Copy out the NVMe Error Reponse to user. The Error Response
1121                  * buffer is given by the user, but a sense buffer is used to
1122                  * get that data from the IOC. The user's
1123                  * ErrorResponseBaseAddress is saved in the
1124                  * 'nvme_error_response' field before the command because that
1125                  * field is set to a sense buffer. When the command is
1126                  * complete, the Error Response data from the IOC is copied to
1127                  * that user address after it is checked for validity.
1128                  * Also note that 'sense' buffers are not defined for
1129                  * NVMe commands. Sense terminalogy is only used here so that
1130                  * the same IOCTL structure and sense buffers can be used for
1131                  * NVMe.
1132                  */
1133                 if (function == MPI2_FUNCTION_NVME_ENCAPSULATED) {
1134                         if (cm->nvme_error_response == NULL) {
1135                                 mpr_dprint(sc, MPR_INFO, "NVMe Error Response "
1136                                     "buffer is NULL. Response data will not be "
1137                                     "returned.\n");
1138                                 mpr_unlock(sc);
1139                                 goto RetFreeUnlocked;
1140                         }
1141
1142                         nvme_error_reply =
1143                             (Mpi26NVMeEncapsulatedErrorReply_t *)cm->cm_reply;
1144                         sz = MIN(le32toh(nvme_error_reply->ErrorResponseCount),
1145                             NVME_ERROR_RESPONSE_SIZE);
1146                         mpr_unlock(sc);
1147                         copyout(cm->cm_sense, cm->nvme_error_response, sz);
1148                         mpr_lock(sc);
1149                 }
1150         }
1151         mpr_unlock(sc);
1152
1153 RetFreeUnlocked:
1154         mpr_lock(sc);
1155
1156 RetFree:
1157         if (cm != NULL) {
1158                 if (cm->cm_data)
1159                         free(cm->cm_data, M_MPRUSER);
1160                 mpr_free_command(sc, cm);
1161         }
1162 Ret:
1163         sc->mpr_flags &= ~MPR_FLAGS_BUSY;
1164         mpr_unlock(sc);
1165
1166         return (err);
1167 }
1168
1169 static void
1170 mpr_user_get_adapter_data(struct mpr_softc *sc, mpr_adapter_data_t *data)
1171 {
1172         Mpi2ConfigReply_t       mpi_reply;
1173         Mpi2BiosPage3_t         config_page;
1174
1175         /*
1176          * Use the PCI interface functions to get the Bus, Device, and Function
1177          * information.
1178          */
1179         data->PciInformation.u.bits.BusNumber = pci_get_bus(sc->mpr_dev);
1180         data->PciInformation.u.bits.DeviceNumber = pci_get_slot(sc->mpr_dev);
1181         data->PciInformation.u.bits.FunctionNumber =
1182             pci_get_function(sc->mpr_dev);
1183
1184         /*
1185          * Get the FW version that should already be saved in IOC Facts.
1186          */
1187         data->MpiFirmwareVersion = sc->facts->FWVersion.Word;
1188
1189         /*
1190          * General device info.
1191          */
1192         data->AdapterType = MPRIOCTL_ADAPTER_TYPE_SAS3;
1193         data->PCIDeviceHwId = pci_get_device(sc->mpr_dev);
1194         data->PCIDeviceHwRev = pci_read_config(sc->mpr_dev, PCIR_REVID, 1);
1195         data->SubSystemId = pci_get_subdevice(sc->mpr_dev);
1196         data->SubsystemVendorId = pci_get_subvendor(sc->mpr_dev);
1197
1198         /*
1199          * Get the driver version.
1200          */
1201         strcpy((char *)&data->DriverVersion[0], MPR_DRIVER_VERSION);
1202
1203         /*
1204          * Need to get BIOS Config Page 3 for the BIOS Version.
1205          */
1206         data->BiosVersion = 0;
1207         mpr_lock(sc);
1208         if (mpr_config_get_bios_pg3(sc, &mpi_reply, &config_page))
1209                 printf("%s: Error while retrieving BIOS Version\n", __func__);
1210         else
1211                 data->BiosVersion = config_page.BiosVersion;
1212         mpr_unlock(sc);
1213 }
1214
1215 static void
1216 mpr_user_read_pci_info(struct mpr_softc *sc, mpr_pci_info_t *data)
1217 {
1218         int     i;
1219
1220         /*
1221          * Use the PCI interface functions to get the Bus, Device, and Function
1222          * information.
1223          */
1224         data->BusNumber = pci_get_bus(sc->mpr_dev);
1225         data->DeviceNumber = pci_get_slot(sc->mpr_dev);
1226         data->FunctionNumber = pci_get_function(sc->mpr_dev);
1227
1228         /*
1229          * Now get the interrupt vector and the pci header.  The vector can
1230          * only be 0 right now.  The header is the first 256 bytes of config
1231          * space.
1232          */
1233         data->InterruptVector = 0;
1234         for (i = 0; i < sizeof (data->PciHeader); i++) {
1235                 data->PciHeader[i] = pci_read_config(sc->mpr_dev, i, 1);
1236         }
1237 }
1238
1239 static uint8_t
1240 mpr_get_fw_diag_buffer_number(struct mpr_softc *sc, uint32_t unique_id)
1241 {
1242         uint8_t index;
1243
1244         for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
1245                 if (sc->fw_diag_buffer_list[index].unique_id == unique_id) {
1246                         return (index);
1247                 }
1248         }
1249
1250         return (MPR_FW_DIAGNOSTIC_UID_NOT_FOUND);
1251 }
1252
1253 static int
1254 mpr_post_fw_diag_buffer(struct mpr_softc *sc,
1255     mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
1256 {
1257         MPI2_DIAG_BUFFER_POST_REQUEST   *req;
1258         MPI2_DIAG_BUFFER_POST_REPLY     *reply;
1259         struct mpr_command              *cm = NULL;
1260         int                             i, status;
1261
1262         /*
1263          * If buffer is not enabled, just leave.
1264          */
1265         *return_code = MPR_FW_DIAG_ERROR_POST_FAILED;
1266         if (!pBuffer->enabled) {
1267                 return (MPR_DIAG_FAILURE);
1268         }
1269
1270         /*
1271          * Clear some flags initially.
1272          */
1273         pBuffer->force_release = FALSE;
1274         pBuffer->valid_data = FALSE;
1275         pBuffer->owned_by_firmware = FALSE;
1276
1277         /*
1278          * Get a command.
1279          */
1280         cm = mpr_alloc_command(sc);
1281         if (cm == NULL) {
1282                 mpr_printf(sc, "%s: no mpr requests\n", __func__);
1283                 return (MPR_DIAG_FAILURE);
1284         }
1285
1286         /*
1287          * Build the request for releasing the FW Diag Buffer and send it.
1288          */
1289         req = (MPI2_DIAG_BUFFER_POST_REQUEST *)cm->cm_req;
1290         req->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
1291         req->BufferType = pBuffer->buffer_type;
1292         req->ExtendedType = pBuffer->extended_type;
1293         req->BufferLength = pBuffer->size;
1294         for (i = 0; i < (sizeof(req->ProductSpecific) / 4); i++)
1295                 req->ProductSpecific[i] = pBuffer->product_specific[i];
1296         mpr_from_u64(sc->fw_diag_busaddr, &req->BufferAddress);
1297         cm->cm_data = NULL;
1298         cm->cm_length = 0;
1299         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1300         cm->cm_complete_data = NULL;
1301
1302         /*
1303          * Send command synchronously.
1304          */
1305         status = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
1306         if (status || (cm == NULL)) {
1307                 mpr_printf(sc, "%s: invalid request: error %d\n", __func__,
1308                     status);
1309                 status = MPR_DIAG_FAILURE;
1310                 goto done;
1311         }
1312
1313         /*
1314          * Process POST reply.
1315          */
1316         reply = (MPI2_DIAG_BUFFER_POST_REPLY *)cm->cm_reply;
1317         if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
1318             MPI2_IOCSTATUS_SUCCESS) {
1319                 status = MPR_DIAG_FAILURE;
1320                 mpr_dprint(sc, MPR_FAULT, "%s: post of FW  Diag Buffer failed "
1321                     "with IOCStatus = 0x%x, IOCLogInfo = 0x%x and "
1322                     "TransferLength = 0x%x\n", __func__,
1323                     le16toh(reply->IOCStatus), le32toh(reply->IOCLogInfo),
1324                     le32toh(reply->TransferLength));
1325                 goto done;
1326         }
1327
1328         /*
1329          * Post was successful.
1330          */
1331         pBuffer->valid_data = TRUE;
1332         pBuffer->owned_by_firmware = TRUE;
1333         *return_code = MPR_FW_DIAG_ERROR_SUCCESS;
1334         status = MPR_DIAG_SUCCESS;
1335
1336 done:
1337         if (cm != NULL)
1338                 mpr_free_command(sc, cm);
1339         return (status);
1340 }
1341
1342 static int
1343 mpr_release_fw_diag_buffer(struct mpr_softc *sc,
1344     mpr_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
1345     uint32_t diag_type)
1346 {
1347         MPI2_DIAG_RELEASE_REQUEST       *req;
1348         MPI2_DIAG_RELEASE_REPLY         *reply;
1349         struct mpr_command              *cm = NULL;
1350         int                             status;
1351
1352         /*
1353          * If buffer is not enabled, just leave.
1354          */
1355         *return_code = MPR_FW_DIAG_ERROR_RELEASE_FAILED;
1356         if (!pBuffer->enabled) {
1357                 mpr_dprint(sc, MPR_USER, "%s: This buffer type is not "
1358                     "supported by the IOC", __func__);
1359                 return (MPR_DIAG_FAILURE);
1360         }
1361
1362         /*
1363          * Clear some flags initially.
1364          */
1365         pBuffer->force_release = FALSE;
1366         pBuffer->valid_data = FALSE;
1367         pBuffer->owned_by_firmware = FALSE;
1368
1369         /*
1370          * Get a command.
1371          */
1372         cm = mpr_alloc_command(sc);
1373         if (cm == NULL) {
1374                 mpr_printf(sc, "%s: no mpr requests\n", __func__);
1375                 return (MPR_DIAG_FAILURE);
1376         }
1377
1378         /*
1379          * Build the request for releasing the FW Diag Buffer and send it.
1380          */
1381         req = (MPI2_DIAG_RELEASE_REQUEST *)cm->cm_req;
1382         req->Function = MPI2_FUNCTION_DIAG_RELEASE;
1383         req->BufferType = pBuffer->buffer_type;
1384         cm->cm_data = NULL;
1385         cm->cm_length = 0;
1386         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1387         cm->cm_complete_data = NULL;
1388
1389         /*
1390          * Send command synchronously.
1391          */
1392         status = mpr_wait_command(sc, &cm, 30, CAN_SLEEP);
1393         if (status || (cm == NULL)) {
1394                 mpr_printf(sc, "%s: invalid request: error %d\n", __func__,
1395                     status);
1396                 status = MPR_DIAG_FAILURE;
1397                 goto done;
1398         }
1399
1400         /*
1401          * Process RELEASE reply.
1402          */
1403         reply = (MPI2_DIAG_RELEASE_REPLY *)cm->cm_reply;
1404         if (((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
1405             MPI2_IOCSTATUS_SUCCESS) || pBuffer->owned_by_firmware) {
1406                 status = MPR_DIAG_FAILURE;
1407                 mpr_dprint(sc, MPR_FAULT, "%s: release of FW Diag Buffer "
1408                     "failed with IOCStatus = 0x%x and IOCLogInfo = 0x%x\n",
1409                     __func__, le16toh(reply->IOCStatus),
1410                     le32toh(reply->IOCLogInfo));
1411                 goto done;
1412         }
1413
1414         /*
1415          * Release was successful.
1416          */
1417         *return_code = MPR_FW_DIAG_ERROR_SUCCESS;
1418         status = MPR_DIAG_SUCCESS;
1419
1420         /*
1421          * If this was for an UNREGISTER diag type command, clear the unique ID.
1422          */
1423         if (diag_type == MPR_FW_DIAG_TYPE_UNREGISTER) {
1424                 pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID;
1425         }
1426
1427 done:
1428         if (cm != NULL)
1429                 mpr_free_command(sc, cm);
1430
1431         return (status);
1432 }
1433
1434 static int
1435 mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register,
1436     uint32_t *return_code)
1437 {
1438         mpr_fw_diagnostic_buffer_t      *pBuffer;
1439         uint8_t                         extended_type, buffer_type, i;
1440         uint32_t                        buffer_size;
1441         uint32_t                        unique_id;
1442         int                             status;
1443
1444         extended_type = diag_register->ExtendedType;
1445         buffer_type = diag_register->BufferType;
1446         buffer_size = diag_register->RequestedBufferSize;
1447         unique_id = diag_register->UniqueId;
1448
1449         /*
1450          * Check for valid buffer type
1451          */
1452         if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
1453                 *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1454                 return (MPR_DIAG_FAILURE);
1455         }
1456
1457         /*
1458          * Get the current buffer and look up the unique ID.  The unique ID
1459          * should not be found.  If it is, the ID is already in use.
1460          */
1461         i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1462         pBuffer = &sc->fw_diag_buffer_list[buffer_type];
1463         if (i != MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1464                 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1465                 return (MPR_DIAG_FAILURE);
1466         }
1467
1468         /*
1469          * The buffer's unique ID should not be registered yet, and the given
1470          * unique ID cannot be 0.
1471          */
1472         if ((pBuffer->unique_id != MPR_FW_DIAG_INVALID_UID) ||
1473             (unique_id == MPR_FW_DIAG_INVALID_UID)) {
1474                 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1475                 return (MPR_DIAG_FAILURE);
1476         }
1477
1478         /*
1479          * If this buffer is already posted as immediate, just change owner.
1480          */
1481         if (pBuffer->immediate && pBuffer->owned_by_firmware &&
1482             (pBuffer->unique_id == MPR_FW_DIAG_INVALID_UID)) {
1483                 pBuffer->immediate = FALSE;
1484                 pBuffer->unique_id = unique_id;
1485                 return (MPR_DIAG_SUCCESS);
1486         }
1487
1488         /*
1489          * Post a new buffer after checking if it's enabled.  The DMA buffer
1490          * that is allocated will be contiguous (nsegments = 1).
1491          */
1492         if (!pBuffer->enabled) {
1493                 *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1494                 return (MPR_DIAG_FAILURE);
1495         }
1496         if (bus_dma_tag_create( sc->mpr_parent_dmat,    /* parent */
1497                                 1, 0,                   /* algnmnt, boundary */
1498                                 BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
1499                                 BUS_SPACE_MAXADDR,      /* highaddr */
1500                                 NULL, NULL,             /* filter, filterarg */
1501                                 buffer_size,            /* maxsize */
1502                                 1,                      /* nsegments */
1503                                 buffer_size,            /* maxsegsize */
1504                                 0,                      /* flags */
1505                                 NULL, NULL,             /* lockfunc, lockarg */
1506                                 &sc->fw_diag_dmat)) {
1507                 device_printf(sc->mpr_dev, "Cannot allocate FW diag buffer DMA "
1508                     "tag\n");
1509                 return (ENOMEM);
1510         }
1511         if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer,
1512             BUS_DMA_NOWAIT, &sc->fw_diag_map)) {
1513                 device_printf(sc->mpr_dev, "Cannot allocate FW diag buffer "
1514                     "memory\n");
1515                 return (ENOMEM);
1516         }
1517         bzero(sc->fw_diag_buffer, buffer_size);
1518         bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map, sc->fw_diag_buffer,
1519             buffer_size, mpr_memaddr_cb, &sc->fw_diag_busaddr, 0);
1520         pBuffer->size = buffer_size;
1521
1522         /*
1523          * Copy the given info to the diag buffer and post the buffer.
1524          */
1525         pBuffer->buffer_type = buffer_type;
1526         pBuffer->immediate = FALSE;
1527         if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
1528                 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
1529                     i++) {
1530                         pBuffer->product_specific[i] =
1531                             diag_register->ProductSpecific[i];
1532                 }
1533         }
1534         pBuffer->extended_type = extended_type;
1535         pBuffer->unique_id = unique_id;
1536         status = mpr_post_fw_diag_buffer(sc, pBuffer, return_code);
1537
1538         /*
1539          * In case there was a failure, free the DMA buffer.
1540          */
1541         if (status == MPR_DIAG_FAILURE) {
1542                 if (sc->fw_diag_busaddr != 0)
1543                         bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
1544                 if (sc->fw_diag_buffer != NULL)
1545                         bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
1546                             sc->fw_diag_map);
1547                 if (sc->fw_diag_dmat != NULL)
1548                         bus_dma_tag_destroy(sc->fw_diag_dmat);
1549         }
1550
1551         return (status);
1552 }
1553
1554 static int
1555 mpr_diag_unregister(struct mpr_softc *sc,
1556     mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
1557 {
1558         mpr_fw_diagnostic_buffer_t      *pBuffer;
1559         uint8_t                         i;
1560         uint32_t                        unique_id;
1561         int                             status;
1562
1563         unique_id = diag_unregister->UniqueId;
1564
1565         /*
1566          * Get the current buffer and look up the unique ID.  The unique ID
1567          * should be there.
1568          */
1569         i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1570         if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1571                 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1572                 return (MPR_DIAG_FAILURE);
1573         }
1574
1575         pBuffer = &sc->fw_diag_buffer_list[i];
1576
1577         /*
1578          * Try to release the buffer from FW before freeing it.  If release
1579          * fails, don't free the DMA buffer in case FW tries to access it
1580          * later.  If buffer is not owned by firmware, can't release it.
1581          */
1582         if (!pBuffer->owned_by_firmware) {
1583                 status = MPR_DIAG_SUCCESS;
1584         } else {
1585                 status = mpr_release_fw_diag_buffer(sc, pBuffer, return_code,
1586                     MPR_FW_DIAG_TYPE_UNREGISTER);
1587         }
1588
1589         /*
1590          * At this point, return the current status no matter what happens with
1591          * the DMA buffer.
1592          */
1593         pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID;
1594         if (status == MPR_DIAG_SUCCESS) {
1595                 if (sc->fw_diag_busaddr != 0)
1596                         bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
1597                 if (sc->fw_diag_buffer != NULL)
1598                         bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
1599                             sc->fw_diag_map);
1600                 if (sc->fw_diag_dmat != NULL)
1601                         bus_dma_tag_destroy(sc->fw_diag_dmat);
1602         }
1603
1604         return (status);
1605 }
1606
1607 static int
1608 mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query,
1609     uint32_t *return_code)
1610 {
1611         mpr_fw_diagnostic_buffer_t      *pBuffer;
1612         uint8_t                         i;
1613         uint32_t                        unique_id;
1614
1615         unique_id = diag_query->UniqueId;
1616
1617         /*
1618          * If ID is valid, query on ID.
1619          * If ID is invalid, query on buffer type.
1620          */
1621         if (unique_id == MPR_FW_DIAG_INVALID_UID) {
1622                 i = diag_query->BufferType;
1623                 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
1624                         *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1625                         return (MPR_DIAG_FAILURE);
1626                 }
1627         } else {
1628                 i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1629                 if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1630                         *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1631                         return (MPR_DIAG_FAILURE);
1632                 }
1633         }
1634
1635         /*
1636          * Fill query structure with the diag buffer info.
1637          */
1638         pBuffer = &sc->fw_diag_buffer_list[i];
1639         diag_query->BufferType = pBuffer->buffer_type;
1640         diag_query->ExtendedType = pBuffer->extended_type;
1641         if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
1642                 for (i = 0; i < (sizeof(diag_query->ProductSpecific) / 4);
1643                     i++) {
1644                         diag_query->ProductSpecific[i] =
1645                             pBuffer->product_specific[i];
1646                 }
1647         }
1648         diag_query->TotalBufferSize = pBuffer->size;
1649         diag_query->DriverAddedBufferSize = 0;
1650         diag_query->UniqueId = pBuffer->unique_id;
1651         diag_query->ApplicationFlags = 0;
1652         diag_query->DiagnosticFlags = 0;
1653
1654         /*
1655          * Set/Clear application flags
1656          */
1657         if (pBuffer->immediate) {
1658                 diag_query->ApplicationFlags &= ~MPR_FW_DIAG_FLAG_APP_OWNED;
1659         } else {
1660                 diag_query->ApplicationFlags |= MPR_FW_DIAG_FLAG_APP_OWNED;
1661         }
1662         if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
1663                 diag_query->ApplicationFlags |= MPR_FW_DIAG_FLAG_BUFFER_VALID;
1664         } else {
1665                 diag_query->ApplicationFlags &= ~MPR_FW_DIAG_FLAG_BUFFER_VALID;
1666         }
1667         if (pBuffer->owned_by_firmware) {
1668                 diag_query->ApplicationFlags |=
1669                     MPR_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
1670         } else {
1671                 diag_query->ApplicationFlags &=
1672                     ~MPR_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
1673         }
1674
1675         return (MPR_DIAG_SUCCESS);
1676 }
1677
1678 static int
1679 mpr_diag_read_buffer(struct mpr_softc *sc,
1680     mpr_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
1681     uint32_t *return_code)
1682 {
1683         mpr_fw_diagnostic_buffer_t      *pBuffer;
1684         uint8_t                         i, *pData;
1685         uint32_t                        unique_id;
1686         int                             status;
1687
1688         unique_id = diag_read_buffer->UniqueId;
1689
1690         /*
1691          * Get the current buffer and look up the unique ID.  The unique ID
1692          * should be there.
1693          */
1694         i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1695         if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1696                 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1697                 return (MPR_DIAG_FAILURE);
1698         }
1699
1700         pBuffer = &sc->fw_diag_buffer_list[i];
1701
1702         /*
1703          * Make sure requested read is within limits
1704          */
1705         if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
1706             pBuffer->size) {
1707                 *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1708                 return (MPR_DIAG_FAILURE);
1709         }
1710
1711         /*
1712          * Copy the requested data from DMA to the diag_read_buffer.  The DMA
1713          * buffer that was allocated is one contiguous buffer.
1714          */
1715         pData = (uint8_t *)(sc->fw_diag_buffer +
1716             diag_read_buffer->StartingOffset);
1717         if (copyout(pData, ioctl_buf, diag_read_buffer->BytesToRead) != 0)
1718                 return (MPR_DIAG_FAILURE);
1719         diag_read_buffer->Status = 0;
1720
1721         /*
1722          * Set or clear the Force Release flag.
1723          */
1724         if (pBuffer->force_release) {
1725                 diag_read_buffer->Flags |= MPR_FW_DIAG_FLAG_FORCE_RELEASE;
1726         } else {
1727                 diag_read_buffer->Flags &= ~MPR_FW_DIAG_FLAG_FORCE_RELEASE;
1728         }
1729
1730         /*
1731          * If buffer is to be reregistered, make sure it's not already owned by
1732          * firmware first.
1733          */
1734         status = MPR_DIAG_SUCCESS;
1735         if (!pBuffer->owned_by_firmware) {
1736                 if (diag_read_buffer->Flags & MPR_FW_DIAG_FLAG_REREGISTER) {
1737                         status = mpr_post_fw_diag_buffer(sc, pBuffer,
1738                             return_code);
1739                 }
1740         }
1741
1742         return (status);
1743 }
1744
1745 static int
1746 mpr_diag_release(struct mpr_softc *sc, mpr_fw_diag_release_t *diag_release,
1747     uint32_t *return_code)
1748 {
1749         mpr_fw_diagnostic_buffer_t      *pBuffer;
1750         uint8_t                         i;
1751         uint32_t                        unique_id;
1752         int                             status;
1753
1754         unique_id = diag_release->UniqueId;
1755
1756         /*
1757          * Get the current buffer and look up the unique ID.  The unique ID
1758          * should be there.
1759          */
1760         i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1761         if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1762                 *return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1763                 return (MPR_DIAG_FAILURE);
1764         }
1765
1766         pBuffer = &sc->fw_diag_buffer_list[i];
1767
1768         /*
1769          * If buffer is not owned by firmware, it's already been released.
1770          */
1771         if (!pBuffer->owned_by_firmware) {
1772                 *return_code = MPR_FW_DIAG_ERROR_ALREADY_RELEASED;
1773                 return (MPR_DIAG_FAILURE);
1774         }
1775
1776         /*
1777          * Release the buffer.
1778          */
1779         status = mpr_release_fw_diag_buffer(sc, pBuffer, return_code,
1780             MPR_FW_DIAG_TYPE_RELEASE);
1781         return (status);
1782 }
1783
1784 static int
1785 mpr_do_diag_action(struct mpr_softc *sc, uint32_t action, uint8_t *diag_action,
1786     uint32_t length, uint32_t *return_code)
1787 {
1788         mpr_fw_diag_register_t          diag_register;
1789         mpr_fw_diag_unregister_t        diag_unregister;
1790         mpr_fw_diag_query_t             diag_query;
1791         mpr_diag_read_buffer_t          diag_read_buffer;
1792         mpr_fw_diag_release_t           diag_release;
1793         int                             status = MPR_DIAG_SUCCESS;
1794         uint32_t                        original_return_code;
1795
1796         original_return_code = *return_code;
1797         *return_code = MPR_FW_DIAG_ERROR_SUCCESS;
1798
1799         switch (action) {
1800                 case MPR_FW_DIAG_TYPE_REGISTER:
1801                         if (!length) {
1802                                 *return_code =
1803                                     MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1804                                 status = MPR_DIAG_FAILURE;
1805                                 break;
1806                         }
1807                         if (copyin(diag_action, &diag_register,
1808                             sizeof(diag_register)) != 0)
1809                                 return (MPR_DIAG_FAILURE);
1810                         status = mpr_diag_register(sc, &diag_register,
1811                             return_code);
1812                         break;
1813
1814                 case MPR_FW_DIAG_TYPE_UNREGISTER:
1815                         if (length < sizeof(diag_unregister)) {
1816                                 *return_code =
1817                                     MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1818                                 status = MPR_DIAG_FAILURE;
1819                                 break;
1820                         }
1821                         if (copyin(diag_action, &diag_unregister,
1822                             sizeof(diag_unregister)) != 0)
1823                                 return (MPR_DIAG_FAILURE);
1824                         status = mpr_diag_unregister(sc, &diag_unregister,
1825                             return_code);
1826                         break;
1827
1828                 case MPR_FW_DIAG_TYPE_QUERY:
1829                         if (length < sizeof (diag_query)) {
1830                                 *return_code =
1831                                     MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1832                                 status = MPR_DIAG_FAILURE;
1833                                 break;
1834                         }
1835                         if (copyin(diag_action, &diag_query, sizeof(diag_query))
1836                             != 0)
1837                                 return (MPR_DIAG_FAILURE);
1838                         status = mpr_diag_query(sc, &diag_query, return_code);
1839                         if (status == MPR_DIAG_SUCCESS)
1840                                 if (copyout(&diag_query, diag_action,
1841                                     sizeof (diag_query)) != 0)
1842                                         return (MPR_DIAG_FAILURE);
1843                         break;
1844
1845                 case MPR_FW_DIAG_TYPE_READ_BUFFER:
1846                         if (copyin(diag_action, &diag_read_buffer,
1847                             sizeof(diag_read_buffer)) != 0)
1848                                 return (MPR_DIAG_FAILURE);
1849                         if (length < diag_read_buffer.BytesToRead) {
1850                                 *return_code =
1851                                     MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1852                                 status = MPR_DIAG_FAILURE;
1853                                 break;
1854                         }
1855                         status = mpr_diag_read_buffer(sc, &diag_read_buffer,
1856                             PTRIN(diag_read_buffer.PtrDataBuffer),
1857                             return_code);
1858                         if (status == MPR_DIAG_SUCCESS) {
1859                                 if (copyout(&diag_read_buffer, diag_action,
1860                                     sizeof(diag_read_buffer) -
1861                                     sizeof(diag_read_buffer.PtrDataBuffer)) !=
1862                                     0)
1863                                         return (MPR_DIAG_FAILURE);
1864                         }
1865                         break;
1866
1867                 case MPR_FW_DIAG_TYPE_RELEASE:
1868                         if (length < sizeof(diag_release)) {
1869                                 *return_code =
1870                                     MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1871                                 status = MPR_DIAG_FAILURE;
1872                                 break;
1873                         }
1874                         if (copyin(diag_action, &diag_release,
1875                             sizeof(diag_release)) != 0)
1876                                 return (MPR_DIAG_FAILURE);
1877                         status = mpr_diag_release(sc, &diag_release,
1878                             return_code);
1879                         break;
1880
1881                 default:
1882                         *return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1883                         status = MPR_DIAG_FAILURE;
1884                         break;
1885         }
1886
1887         if ((status == MPR_DIAG_FAILURE) &&
1888             (original_return_code == MPR_FW_DIAG_NEW) &&
1889             (*return_code != MPR_FW_DIAG_ERROR_SUCCESS))
1890                 status = MPR_DIAG_SUCCESS;
1891
1892         return (status);
1893 }
1894
1895 static int
1896 mpr_user_diag_action(struct mpr_softc *sc, mpr_diag_action_t *data)
1897 {
1898         int                     status;
1899
1900         /*
1901          * Only allow one diag action at one time.
1902          */
1903         if (sc->mpr_flags & MPR_FLAGS_BUSY) {
1904                 mpr_dprint(sc, MPR_USER, "%s: Only one FW diag command "
1905                     "allowed at a single time.", __func__);
1906                 return (EBUSY);
1907         }
1908         sc->mpr_flags |= MPR_FLAGS_BUSY;
1909
1910         /*
1911          * Send diag action request
1912          */
1913         if (data->Action == MPR_FW_DIAG_TYPE_REGISTER ||
1914             data->Action == MPR_FW_DIAG_TYPE_UNREGISTER ||
1915             data->Action == MPR_FW_DIAG_TYPE_QUERY ||
1916             data->Action == MPR_FW_DIAG_TYPE_READ_BUFFER ||
1917             data->Action == MPR_FW_DIAG_TYPE_RELEASE) {
1918                 status = mpr_do_diag_action(sc, data->Action,
1919                     PTRIN(data->PtrDiagAction), data->Length,
1920                     &data->ReturnCode);
1921         } else
1922                 status = EINVAL;
1923
1924         sc->mpr_flags &= ~MPR_FLAGS_BUSY;
1925         return (status);
1926 }
1927
1928 /*
1929  * Copy the event recording mask and the event queue size out.  For
1930  * clarification, the event recording mask (events_to_record) is not the same
1931  * thing as the event mask (event_mask).  events_to_record has a bit set for
1932  * every event type that is to be recorded by the driver, and event_mask has a
1933  * bit cleared for every event that is allowed into the driver from the IOC.
1934  * They really have nothing to do with each other.
1935  */
1936 static void
1937 mpr_user_event_query(struct mpr_softc *sc, mpr_event_query_t *data)
1938 {
1939         uint8_t i;
1940
1941         mpr_lock(sc);
1942         data->Entries = MPR_EVENT_QUEUE_SIZE;
1943
1944         for (i = 0; i < 4; i++) {
1945                 data->Types[i] = sc->events_to_record[i];
1946         }
1947         mpr_unlock(sc);
1948 }
1949
1950 /*
1951  * Set the driver's event mask according to what's been given.  See
1952  * mpr_user_event_query for explanation of the event recording mask and the IOC
1953  * event mask.  It's the app's responsibility to enable event logging by setting
1954  * the bits in events_to_record.  Initially, no events will be logged.
1955  */
1956 static void
1957 mpr_user_event_enable(struct mpr_softc *sc, mpr_event_enable_t *data)
1958 {
1959         uint8_t i;
1960
1961         mpr_lock(sc);
1962         for (i = 0; i < 4; i++) {
1963                 sc->events_to_record[i] = data->Types[i];
1964         }
1965         mpr_unlock(sc);
1966 }
1967
1968 /*
1969  * Copy out the events that have been recorded, up to the max events allowed.
1970  */
1971 static int
1972 mpr_user_event_report(struct mpr_softc *sc, mpr_event_report_t *data)
1973 {
1974         int             status = 0;
1975         uint32_t        size;
1976
1977         mpr_lock(sc);
1978         size = data->Size;
1979         if ((size >= sizeof(sc->recorded_events)) && (status == 0)) {
1980                 mpr_unlock(sc);
1981                 if (copyout((void *)sc->recorded_events,
1982                     PTRIN(data->PtrEvents), size) != 0)
1983                         status = EFAULT;
1984                 mpr_lock(sc);
1985         } else {
1986                 /*
1987                  * data->Size value is not large enough to copy event data.
1988                  */
1989                 status = EFAULT;
1990         }
1991
1992         /*
1993          * Change size value to match the number of bytes that were copied.
1994          */
1995         if (status == 0)
1996                 data->Size = sizeof(sc->recorded_events);
1997         mpr_unlock(sc);
1998
1999         return (status);
2000 }
2001
2002 /*
2003  * Record events into the driver from the IOC if they are not masked.
2004  */
2005 void
2006 mprsas_record_event(struct mpr_softc *sc,
2007     MPI2_EVENT_NOTIFICATION_REPLY *event_reply)
2008 {
2009         uint32_t        event;
2010         int             i, j;
2011         uint16_t        event_data_len;
2012         boolean_t       sendAEN = FALSE;
2013
2014         event = event_reply->Event;
2015
2016         /*
2017          * Generate a system event to let anyone who cares know that a
2018          * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
2019          * event mask is set to.
2020          */
2021         if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
2022                 sendAEN = TRUE;
2023         }
2024
2025         /*
2026          * Record the event only if its corresponding bit is set in
2027          * events_to_record.  event_index is the index into recorded_events and
2028          * event_number is the overall number of an event being recorded since
2029          * start-of-day.  event_index will roll over; event_number will never
2030          * roll over.
2031          */
2032         i = (uint8_t)(event / 32);
2033         j = (uint8_t)(event % 32);
2034         if ((i < 4) && ((1 << j) & sc->events_to_record[i])) {
2035                 i = sc->event_index;
2036                 sc->recorded_events[i].Type = event;
2037                 sc->recorded_events[i].Number = ++sc->event_number;
2038                 bzero(sc->recorded_events[i].Data, MPR_MAX_EVENT_DATA_LENGTH *
2039                     4);
2040                 event_data_len = event_reply->EventDataLength;
2041
2042                 if (event_data_len > 0) {
2043                         /*
2044                          * Limit data to size in m_event entry
2045                          */
2046                         if (event_data_len > MPR_MAX_EVENT_DATA_LENGTH) {
2047                                 event_data_len = MPR_MAX_EVENT_DATA_LENGTH;
2048                         }
2049                         for (j = 0; j < event_data_len; j++) {
2050                                 sc->recorded_events[i].Data[j] =
2051                                     event_reply->EventData[j];
2052                         }
2053
2054                         /*
2055                          * check for index wrap-around
2056                          */
2057                         if (++i == MPR_EVENT_QUEUE_SIZE) {
2058                                 i = 0;
2059                         }
2060                         sc->event_index = (uint8_t)i;
2061
2062                         /*
2063                          * Set flag to send the event.
2064                          */
2065                         sendAEN = TRUE;
2066                 }
2067         }
2068
2069         /*
2070          * Generate a system event if flag is set to let anyone who cares know
2071          * that an event has occurred.
2072          */
2073         if (sendAEN) {
2074 //SLM-how to send a system event (see kqueue, kevent)
2075 //              (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
2076 //                  "SAS", NULL, NULL, DDI_NOSLEEP);
2077         }
2078 }
2079
2080 static int
2081 mpr_user_reg_access(struct mpr_softc *sc, mpr_reg_access_t *data)
2082 {
2083         int     status = 0;
2084
2085         switch (data->Command) {
2086                 /*
2087                  * IO access is not supported.
2088                  */
2089                 case REG_IO_READ:
2090                 case REG_IO_WRITE:
2091                         mpr_dprint(sc, MPR_USER, "IO access is not supported. "
2092                             "Use memory access.");
2093                         status = EINVAL;
2094                         break;
2095
2096                 case REG_MEM_READ:
2097                         data->RegData = mpr_regread(sc, data->RegOffset);
2098                         break;
2099
2100                 case REG_MEM_WRITE:
2101                         mpr_regwrite(sc, data->RegOffset, data->RegData);
2102                         break;
2103
2104                 default:
2105                         status = EINVAL;
2106                         break;
2107         }
2108
2109         return (status);
2110 }
2111
2112 static int
2113 mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data)
2114 {
2115         uint8_t         bt2dh = FALSE;
2116         uint8_t         dh2bt = FALSE;
2117         uint16_t        dev_handle, bus, target;
2118
2119         bus = data->Bus;
2120         target = data->TargetID;
2121         dev_handle = data->DevHandle;
2122
2123         /*
2124          * When DevHandle is 0xFFFF and Bus/Target are not 0xFFFF, use Bus/
2125          * Target to get DevHandle.  When Bus/Target are 0xFFFF and DevHandle is
2126          * not 0xFFFF, use DevHandle to get Bus/Target.  Anything else is
2127          * invalid.
2128          */
2129         if ((bus == 0xFFFF) && (target == 0xFFFF) && (dev_handle != 0xFFFF))
2130                 dh2bt = TRUE;
2131         if ((dev_handle == 0xFFFF) && (bus != 0xFFFF) && (target != 0xFFFF))
2132                 bt2dh = TRUE;
2133         if (!dh2bt && !bt2dh)
2134                 return (EINVAL);
2135
2136         /*
2137          * Only handle bus of 0.  Make sure target is within range.
2138          */
2139         if (bt2dh) {
2140                 if (bus != 0)
2141                         return (EINVAL);
2142
2143                 if (target > sc->max_devices) {
2144                         mpr_dprint(sc, MPR_XINFO, "Target ID is out of range "
2145                            "for Bus/Target to DevHandle mapping.");
2146                         return (EINVAL);
2147                 }
2148                 dev_handle = sc->mapping_table[target].dev_handle;
2149                 if (dev_handle)
2150                         data->DevHandle = dev_handle;
2151         } else {
2152                 bus = 0;
2153                 target = mpr_mapping_get_tid_from_handle(sc, dev_handle);
2154                 data->Bus = bus;
2155                 data->TargetID = target;
2156         }
2157
2158         return (0);
2159 }
2160
2161 static int
2162 mpr_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
2163     struct thread *td)
2164 {
2165         struct mpr_softc *sc;
2166         struct mpr_cfg_page_req *page_req;
2167         struct mpr_ext_cfg_page_req *ext_page_req;
2168         void *mpr_page;
2169         int error, msleep_ret;
2170
2171         mpr_page = NULL;
2172         sc = dev->si_drv1;
2173         page_req = (void *)arg;
2174         ext_page_req = (void *)arg;
2175
2176         switch (cmd) {
2177         case MPRIO_READ_CFG_HEADER:
2178                 mpr_lock(sc);
2179                 error = mpr_user_read_cfg_header(sc, page_req);
2180                 mpr_unlock(sc);
2181                 break;
2182         case MPRIO_READ_CFG_PAGE:
2183                 mpr_page = malloc(page_req->len, M_MPRUSER, M_WAITOK | M_ZERO);
2184                 error = copyin(page_req->buf, mpr_page,
2185                     sizeof(MPI2_CONFIG_PAGE_HEADER));
2186                 if (error)
2187                         break;
2188                 mpr_lock(sc);
2189                 error = mpr_user_read_cfg_page(sc, page_req, mpr_page);
2190                 mpr_unlock(sc);
2191                 if (error)
2192                         break;
2193                 error = copyout(mpr_page, page_req->buf, page_req->len);
2194                 break;
2195         case MPRIO_READ_EXT_CFG_HEADER:
2196                 mpr_lock(sc);
2197                 error = mpr_user_read_extcfg_header(sc, ext_page_req);
2198                 mpr_unlock(sc);
2199                 break;
2200         case MPRIO_READ_EXT_CFG_PAGE:
2201                 mpr_page = malloc(ext_page_req->len, M_MPRUSER,
2202                     M_WAITOK | M_ZERO);
2203                 error = copyin(ext_page_req->buf, mpr_page,
2204                     sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2205                 if (error)
2206                         break;
2207                 mpr_lock(sc);
2208                 error = mpr_user_read_extcfg_page(sc, ext_page_req, mpr_page);
2209                 mpr_unlock(sc);
2210                 if (error)
2211                         break;
2212                 error = copyout(mpr_page, ext_page_req->buf, ext_page_req->len);
2213                 break;
2214         case MPRIO_WRITE_CFG_PAGE:
2215                 mpr_page = malloc(page_req->len, M_MPRUSER, M_WAITOK|M_ZERO);
2216                 error = copyin(page_req->buf, mpr_page, page_req->len);
2217                 if (error)
2218                         break;
2219                 mpr_lock(sc);
2220                 error = mpr_user_write_cfg_page(sc, page_req, mpr_page);
2221                 mpr_unlock(sc);
2222                 break;
2223         case MPRIO_MPR_COMMAND:
2224                 error = mpr_user_command(sc, (struct mpr_usr_command *)arg);
2225                 break;
2226         case MPTIOCTL_PASS_THRU:
2227                 /*
2228                  * The user has requested to pass through a command to be
2229                  * executed by the MPT firmware.  Call our routine which does
2230                  * this.  Only allow one passthru IOCTL at one time.
2231                  */
2232                 error = mpr_user_pass_thru(sc, (mpr_pass_thru_t *)arg);
2233                 break;
2234         case MPTIOCTL_GET_ADAPTER_DATA:
2235                 /*
2236                  * The user has requested to read adapter data.  Call our
2237                  * routine which does this.
2238                  */
2239                 error = 0;
2240                 mpr_user_get_adapter_data(sc, (mpr_adapter_data_t *)arg);
2241                 break;
2242         case MPTIOCTL_GET_PCI_INFO:
2243                 /*
2244                  * The user has requested to read pci info.  Call
2245                  * our routine which does this.
2246                  */
2247                 mpr_lock(sc);
2248                 error = 0;
2249                 mpr_user_read_pci_info(sc, (mpr_pci_info_t *)arg);
2250                 mpr_unlock(sc);
2251                 break;
2252         case MPTIOCTL_RESET_ADAPTER:
2253                 mpr_lock(sc);
2254                 sc->port_enable_complete = 0;
2255                 uint32_t reinit_start = time_uptime;
2256                 error = mpr_reinit(sc);
2257                 /* Sleep for 300 second. */
2258                 msleep_ret = msleep(&sc->port_enable_complete, &sc->mpr_mtx,
2259                     PRIBIO, "mpr_porten", 300 * hz);
2260                 mpr_unlock(sc);
2261                 if (msleep_ret)
2262                         printf("Port Enable did not complete after Diag "
2263                             "Reset msleep error %d.\n", msleep_ret);
2264                 else
2265                         mpr_dprint(sc, MPR_USER, "Hard Reset with Port Enable "
2266                             "completed in %d seconds.\n",
2267                             (uint32_t)(time_uptime - reinit_start));
2268                 break;
2269         case MPTIOCTL_DIAG_ACTION:
2270                 /*
2271                  * The user has done a diag buffer action.  Call our routine
2272                  * which does this.  Only allow one diag action at one time.
2273                  */
2274                 mpr_lock(sc);
2275                 error = mpr_user_diag_action(sc, (mpr_diag_action_t *)arg);
2276                 mpr_unlock(sc);
2277                 break;
2278         case MPTIOCTL_EVENT_QUERY:
2279                 /*
2280                  * The user has done an event query. Call our routine which does
2281                  * this.
2282                  */
2283                 error = 0;
2284                 mpr_user_event_query(sc, (mpr_event_query_t *)arg);
2285                 break;
2286         case MPTIOCTL_EVENT_ENABLE:
2287                 /*
2288                  * The user has done an event enable. Call our routine which
2289                  * does this.
2290                  */
2291                 error = 0;
2292                 mpr_user_event_enable(sc, (mpr_event_enable_t *)arg);
2293                 break;
2294         case MPTIOCTL_EVENT_REPORT:
2295                 /*
2296                  * The user has done an event report. Call our routine which
2297                  * does this.
2298                  */
2299                 error = mpr_user_event_report(sc, (mpr_event_report_t *)arg);
2300                 break;
2301         case MPTIOCTL_REG_ACCESS:
2302                 /*
2303                  * The user has requested register access.  Call our routine
2304                  * which does this.
2305                  */
2306                 mpr_lock(sc);
2307                 error = mpr_user_reg_access(sc, (mpr_reg_access_t *)arg);
2308                 mpr_unlock(sc);
2309                 break;
2310         case MPTIOCTL_BTDH_MAPPING:
2311                 /*
2312                  * The user has requested to translate a bus/target to a
2313                  * DevHandle or a DevHandle to a bus/target.  Call our routine
2314                  * which does this.
2315                  */
2316                 error = mpr_user_btdh(sc, (mpr_btdh_mapping_t *)arg);
2317                 break;
2318         default:
2319                 error = ENOIOCTL;
2320                 break;
2321         }
2322
2323         if (mpr_page != NULL)
2324                 free(mpr_page, M_MPRUSER);
2325
2326         return (error);
2327 }
2328
2329 #ifdef COMPAT_FREEBSD32
2330
2331 struct mpr_cfg_page_req32 {
2332         MPI2_CONFIG_PAGE_HEADER header;
2333         uint32_t page_address;
2334         uint32_t buf;
2335         int     len;    
2336         uint16_t ioc_status;
2337 };
2338
2339 struct mpr_ext_cfg_page_req32 {
2340         MPI2_CONFIG_EXTENDED_PAGE_HEADER header;
2341         uint32_t page_address;
2342         uint32_t buf;
2343         int     len;
2344         uint16_t ioc_status;
2345 };
2346
2347 struct mpr_raid_action32 {
2348         uint8_t action;
2349         uint8_t volume_bus;
2350         uint8_t volume_id;
2351         uint8_t phys_disk_num;
2352         uint32_t action_data_word;
2353         uint32_t buf;
2354         int len;
2355         uint32_t volume_status;
2356         uint32_t action_data[4];
2357         uint16_t action_status;
2358         uint16_t ioc_status;
2359         uint8_t write;
2360 };
2361
2362 struct mpr_usr_command32 {
2363         uint32_t req;
2364         uint32_t req_len;
2365         uint32_t rpl;
2366         uint32_t rpl_len;
2367         uint32_t buf;
2368         int len;
2369         uint32_t flags;
2370 };
2371
2372 #define MPRIO_READ_CFG_HEADER32 _IOWR('M', 200, struct mpr_cfg_page_req32)
2373 #define MPRIO_READ_CFG_PAGE32   _IOWR('M', 201, struct mpr_cfg_page_req32)
2374 #define MPRIO_READ_EXT_CFG_HEADER32 _IOWR('M', 202, struct mpr_ext_cfg_page_req32)
2375 #define MPRIO_READ_EXT_CFG_PAGE32 _IOWR('M', 203, struct mpr_ext_cfg_page_req32)
2376 #define MPRIO_WRITE_CFG_PAGE32  _IOWR('M', 204, struct mpr_cfg_page_req32)
2377 #define MPRIO_RAID_ACTION32     _IOWR('M', 205, struct mpr_raid_action32)
2378 #define MPRIO_MPR_COMMAND32     _IOWR('M', 210, struct mpr_usr_command32)
2379
2380 static int
2381 mpr_ioctl32(struct cdev *dev, u_long cmd32, void *_arg, int flag,
2382     struct thread *td)
2383 {
2384         struct mpr_cfg_page_req32 *page32 = _arg;
2385         struct mpr_ext_cfg_page_req32 *ext32 = _arg;
2386         struct mpr_raid_action32 *raid32 = _arg;
2387         struct mpr_usr_command32 *user32 = _arg;
2388         union {
2389                 struct mpr_cfg_page_req page;
2390                 struct mpr_ext_cfg_page_req ext;
2391                 struct mpr_raid_action raid;
2392                 struct mpr_usr_command user;
2393         } arg;
2394         u_long cmd;
2395         int error;
2396
2397         switch (cmd32) {
2398         case MPRIO_READ_CFG_HEADER32:
2399         case MPRIO_READ_CFG_PAGE32:
2400         case MPRIO_WRITE_CFG_PAGE32:
2401                 if (cmd32 == MPRIO_READ_CFG_HEADER32)
2402                         cmd = MPRIO_READ_CFG_HEADER;
2403                 else if (cmd32 == MPRIO_READ_CFG_PAGE32)
2404                         cmd = MPRIO_READ_CFG_PAGE;
2405                 else
2406                         cmd = MPRIO_WRITE_CFG_PAGE;
2407                 CP(*page32, arg.page, header);
2408                 CP(*page32, arg.page, page_address);
2409                 PTRIN_CP(*page32, arg.page, buf);
2410                 CP(*page32, arg.page, len);
2411                 CP(*page32, arg.page, ioc_status);
2412                 break;
2413
2414         case MPRIO_READ_EXT_CFG_HEADER32:
2415         case MPRIO_READ_EXT_CFG_PAGE32:
2416                 if (cmd32 == MPRIO_READ_EXT_CFG_HEADER32)
2417                         cmd = MPRIO_READ_EXT_CFG_HEADER;
2418                 else
2419                         cmd = MPRIO_READ_EXT_CFG_PAGE;
2420                 CP(*ext32, arg.ext, header);
2421                 CP(*ext32, arg.ext, page_address);
2422                 PTRIN_CP(*ext32, arg.ext, buf);
2423                 CP(*ext32, arg.ext, len);
2424                 CP(*ext32, arg.ext, ioc_status);
2425                 break;
2426
2427         case MPRIO_RAID_ACTION32:
2428                 cmd = MPRIO_RAID_ACTION;
2429                 CP(*raid32, arg.raid, action);
2430                 CP(*raid32, arg.raid, volume_bus);
2431                 CP(*raid32, arg.raid, volume_id);
2432                 CP(*raid32, arg.raid, phys_disk_num);
2433                 CP(*raid32, arg.raid, action_data_word);
2434                 PTRIN_CP(*raid32, arg.raid, buf);
2435                 CP(*raid32, arg.raid, len);
2436                 CP(*raid32, arg.raid, volume_status);
2437                 bcopy(raid32->action_data, arg.raid.action_data,
2438                     sizeof arg.raid.action_data);
2439                 CP(*raid32, arg.raid, ioc_status);
2440                 CP(*raid32, arg.raid, write);
2441                 break;
2442
2443         case MPRIO_MPR_COMMAND32:
2444                 cmd = MPRIO_MPR_COMMAND;
2445                 PTRIN_CP(*user32, arg.user, req);
2446                 CP(*user32, arg.user, req_len);
2447                 PTRIN_CP(*user32, arg.user, rpl);
2448                 CP(*user32, arg.user, rpl_len);
2449                 PTRIN_CP(*user32, arg.user, buf);
2450                 CP(*user32, arg.user, len);
2451                 CP(*user32, arg.user, flags);
2452                 break;
2453         default:
2454                 return (ENOIOCTL);
2455         }
2456
2457         error = mpr_ioctl(dev, cmd, &arg, flag, td);
2458         if (error == 0 && (cmd32 & IOC_OUT) != 0) {
2459                 switch (cmd32) {
2460                 case MPRIO_READ_CFG_HEADER32:
2461                 case MPRIO_READ_CFG_PAGE32:
2462                 case MPRIO_WRITE_CFG_PAGE32:
2463                         CP(arg.page, *page32, header);
2464                         CP(arg.page, *page32, page_address);
2465                         PTROUT_CP(arg.page, *page32, buf);
2466                         CP(arg.page, *page32, len);
2467                         CP(arg.page, *page32, ioc_status);
2468                         break;
2469
2470                 case MPRIO_READ_EXT_CFG_HEADER32:
2471                 case MPRIO_READ_EXT_CFG_PAGE32:
2472                         CP(arg.ext, *ext32, header);
2473                         CP(arg.ext, *ext32, page_address);
2474                         PTROUT_CP(arg.ext, *ext32, buf);
2475                         CP(arg.ext, *ext32, len);
2476                         CP(arg.ext, *ext32, ioc_status);
2477                         break;
2478
2479                 case MPRIO_RAID_ACTION32:
2480                         CP(arg.raid, *raid32, action);
2481                         CP(arg.raid, *raid32, volume_bus);
2482                         CP(arg.raid, *raid32, volume_id);
2483                         CP(arg.raid, *raid32, phys_disk_num);
2484                         CP(arg.raid, *raid32, action_data_word);
2485                         PTROUT_CP(arg.raid, *raid32, buf);
2486                         CP(arg.raid, *raid32, len);
2487                         CP(arg.raid, *raid32, volume_status);
2488                         bcopy(arg.raid.action_data, raid32->action_data,
2489                             sizeof arg.raid.action_data);
2490                         CP(arg.raid, *raid32, ioc_status);
2491                         CP(arg.raid, *raid32, write);
2492                         break;
2493
2494                 case MPRIO_MPR_COMMAND32:
2495                         PTROUT_CP(arg.user, *user32, req);
2496                         CP(arg.user, *user32, req_len);
2497                         PTROUT_CP(arg.user, *user32, rpl);
2498                         CP(arg.user, *user32, rpl_len);
2499                         PTROUT_CP(arg.user, *user32, buf);
2500                         CP(arg.user, *user32, len);
2501                         CP(arg.user, *user32, flags);
2502                         break;
2503                 }
2504         }
2505
2506         return (error);
2507 }
2508 #endif /* COMPAT_FREEBSD32 */
2509
2510 static int
2511 mpr_ioctl_devsw(struct cdev *dev, u_long com, caddr_t arg, int flag,
2512     struct thread *td)
2513 {
2514 #ifdef COMPAT_FREEBSD32
2515         if (SV_CURPROC_FLAG(SV_ILP32))
2516                 return (mpr_ioctl32(dev, com, arg, flag, td));
2517 #endif
2518         return (mpr_ioctl(dev, com, arg, flag, td));
2519 }