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