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