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