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