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