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	mpr_fw_diagnostic_buffer_t	*pBuffer;
1447	struct mpr_busdma_context	*ctx;
1448	uint8_t				extended_type, buffer_type, i;
1449	uint32_t			buffer_size;
1450	uint32_t			unique_id;
1451	int				status;
1452	int				error;
1453
1454	extended_type = diag_register->ExtendedType;
1455	buffer_type = diag_register->BufferType;
1456	buffer_size = diag_register->RequestedBufferSize;
1457	unique_id = diag_register->UniqueId;
1458	ctx = NULL;
1459	error = 0;
1460
1461	/*
1462	 * Check for valid buffer type
1463	 */
1464	if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
1465		*return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1466		return (MPR_DIAG_FAILURE);
1467	}
1468
1469	/*
1470	 * Get the current buffer and look up the unique ID.  The unique ID
1471	 * should not be found.  If it is, the ID is already in use.
1472	 */
1473	i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1474	pBuffer = &sc->fw_diag_buffer_list[buffer_type];
1475	if (i != MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1476		*return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1477		return (MPR_DIAG_FAILURE);
1478	}
1479
1480	/*
1481	 * The buffer's unique ID should not be registered yet, and the given
1482	 * unique ID cannot be 0.
1483	 */
1484	if ((pBuffer->unique_id != MPR_FW_DIAG_INVALID_UID) ||
1485	    (unique_id == MPR_FW_DIAG_INVALID_UID)) {
1486		*return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1487		return (MPR_DIAG_FAILURE);
1488	}
1489
1490	/*
1491	 * If this buffer is already posted as immediate, just change owner.
1492	 */
1493	if (pBuffer->immediate && pBuffer->owned_by_firmware &&
1494	    (pBuffer->unique_id == MPR_FW_DIAG_INVALID_UID)) {
1495		pBuffer->immediate = FALSE;
1496		pBuffer->unique_id = unique_id;
1497		return (MPR_DIAG_SUCCESS);
1498	}
1499
1500	/*
1501	 * Post a new buffer after checking if it's enabled.  The DMA buffer
1502	 * that is allocated will be contiguous (nsegments = 1).
1503	 */
1504	if (!pBuffer->enabled) {
1505		*return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1506		return (MPR_DIAG_FAILURE);
1507	}
1508	if (bus_dma_tag_create( sc->mpr_parent_dmat,    /* parent */
1509				1, 0,			/* algnmnt, boundary */
1510				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
1511				BUS_SPACE_MAXADDR,	/* highaddr */
1512				NULL, NULL,		/* filter, filterarg */
1513                                buffer_size,		/* maxsize */
1514                                1,			/* nsegments */
1515                                buffer_size,		/* maxsegsize */
1516                                0,			/* flags */
1517                                NULL, NULL,		/* lockfunc, lockarg */
1518                                &sc->fw_diag_dmat)) {
1519		mpr_dprint(sc, MPR_ERROR,
1520		    "Cannot allocate FW diag buffer DMA tag\n");
1521		*return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1522		status = MPR_DIAG_FAILURE;
1523		goto bailout;
1524	}
1525        if (bus_dmamem_alloc(sc->fw_diag_dmat, (void **)&sc->fw_diag_buffer,
1526	    BUS_DMA_NOWAIT, &sc->fw_diag_map)) {
1527		mpr_dprint(sc, MPR_ERROR,
1528		    "Cannot allocate FW diag buffer memory\n");
1529		*return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1530		status = MPR_DIAG_FAILURE;
1531		goto bailout;
1532	}
1533	bzero(sc->fw_diag_buffer, buffer_size);
1534
1535	ctx = malloc(sizeof(*ctx), M_MPR, M_WAITOK | M_ZERO);
1536	ctx->addr = &sc->fw_diag_busaddr;
1537	ctx->buffer_dmat = sc->fw_diag_dmat;
1538	ctx->buffer_dmamap = sc->fw_diag_map;
1539	ctx->softc = sc;
1540	error = bus_dmamap_load(sc->fw_diag_dmat, sc->fw_diag_map,
1541	    sc->fw_diag_buffer, buffer_size, mpr_memaddr_wait_cb,
1542	    ctx, 0);
1543	if (error == EINPROGRESS) {
1544
1545		/* XXX KDM */
1546		device_printf(sc->mpr_dev, "%s: Deferred bus_dmamap_load\n",
1547		    __func__);
1548		/*
1549		 * Wait for the load to complete.  If we're interrupted,
1550		 * bail out.
1551		 */
1552		mpr_lock(sc);
1553		if (ctx->completed == 0) {
1554			error = msleep(ctx, &sc->mpr_mtx, PCATCH, "mprwait", 0);
1555			if (error != 0) {
1556				/*
1557				 * We got an error from msleep(9).  This is
1558				 * most likely due to a signal.  Tell
1559				 * mpr_memaddr_wait_cb() that we've abandoned
1560				 * the context, so it needs to clean up when
1561				 * it is called.
1562				 */
1563				ctx->abandoned = 1;
1564
1565				/* The callback will free this memory */
1566				ctx = NULL;
1567				mpr_unlock(sc);
1568
1569				device_printf(sc->mpr_dev, "Cannot "
1570				    "bus_dmamap_load FW diag buffer, error = "
1571				    "%d returned from msleep\n", error);
1572				*return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1573				status = MPR_DIAG_FAILURE;
1574				goto bailout;
1575			}
1576		}
1577		mpr_unlock(sc);
1578	}
1579
1580	if ((error != 0) || (ctx->error != 0)) {
1581		device_printf(sc->mpr_dev, "Cannot bus_dmamap_load FW diag "
1582		    "buffer, %serror = %d\n", error ? "" : "callback ",
1583		    error ? error : ctx->error);
1584		*return_code = MPR_FW_DIAG_ERROR_NO_BUFFER;
1585		status = MPR_DIAG_FAILURE;
1586		goto bailout;
1587	}
1588
1589	bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map, BUS_DMASYNC_PREREAD);
1590
1591	pBuffer->size = buffer_size;
1592
1593	/*
1594	 * Copy the given info to the diag buffer and post the buffer.
1595	 */
1596	pBuffer->buffer_type = buffer_type;
1597	pBuffer->immediate = FALSE;
1598	if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
1599		for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
1600		    i++) {
1601			pBuffer->product_specific[i] =
1602			    diag_register->ProductSpecific[i];
1603		}
1604	}
1605	pBuffer->extended_type = extended_type;
1606	pBuffer->unique_id = unique_id;
1607	status = mpr_post_fw_diag_buffer(sc, pBuffer, return_code);
1608
1609bailout:
1610
1611	/*
1612	 * In case there was a failure, free the DMA buffer.
1613	 */
1614	if (status == MPR_DIAG_FAILURE) {
1615		if (sc->fw_diag_busaddr != 0) {
1616			bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
1617			sc->fw_diag_busaddr = 0;
1618		}
1619		if (sc->fw_diag_buffer != NULL) {
1620			bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
1621			    sc->fw_diag_map);
1622			sc->fw_diag_buffer = NULL;
1623		}
1624		if (sc->fw_diag_dmat != NULL) {
1625			bus_dma_tag_destroy(sc->fw_diag_dmat);
1626			sc->fw_diag_dmat = NULL;
1627		}
1628	}
1629
1630	if (ctx != NULL)
1631		free(ctx, M_MPR);
1632
1633	return (status);
1634}
1635
1636static int
1637mpr_diag_unregister(struct mpr_softc *sc,
1638    mpr_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
1639{
1640	mpr_fw_diagnostic_buffer_t	*pBuffer;
1641	uint8_t				i;
1642	uint32_t			unique_id;
1643	int				status;
1644
1645	unique_id = diag_unregister->UniqueId;
1646
1647	/*
1648	 * Get the current buffer and look up the unique ID.  The unique ID
1649	 * should be there.
1650	 */
1651	i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1652	if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1653		*return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1654		return (MPR_DIAG_FAILURE);
1655	}
1656
1657	pBuffer = &sc->fw_diag_buffer_list[i];
1658
1659	/*
1660	 * Try to release the buffer from FW before freeing it.  If release
1661	 * fails, don't free the DMA buffer in case FW tries to access it
1662	 * later.  If buffer is not owned by firmware, can't release it.
1663	 */
1664	if (!pBuffer->owned_by_firmware) {
1665		status = MPR_DIAG_SUCCESS;
1666	} else {
1667		status = mpr_release_fw_diag_buffer(sc, pBuffer, return_code,
1668		    MPR_FW_DIAG_TYPE_UNREGISTER);
1669	}
1670
1671	/*
1672	 * At this point, return the current status no matter what happens with
1673	 * the DMA buffer.
1674	 */
1675	pBuffer->unique_id = MPR_FW_DIAG_INVALID_UID;
1676	if (status == MPR_DIAG_SUCCESS) {
1677		if (sc->fw_diag_busaddr != 0) {
1678			bus_dmamap_unload(sc->fw_diag_dmat, sc->fw_diag_map);
1679			sc->fw_diag_busaddr = 0;
1680		}
1681		if (sc->fw_diag_buffer != NULL) {
1682			bus_dmamem_free(sc->fw_diag_dmat, sc->fw_diag_buffer,
1683			    sc->fw_diag_map);
1684			sc->fw_diag_buffer = NULL;
1685		}
1686		if (sc->fw_diag_dmat != NULL) {
1687			bus_dma_tag_destroy(sc->fw_diag_dmat);
1688			sc->fw_diag_dmat = NULL;
1689		}
1690	}
1691
1692	return (status);
1693}
1694
1695static int
1696mpr_diag_query(struct mpr_softc *sc, mpr_fw_diag_query_t *diag_query,
1697    uint32_t *return_code)
1698{
1699	mpr_fw_diagnostic_buffer_t	*pBuffer;
1700	uint8_t				i;
1701	uint32_t			unique_id;
1702
1703	unique_id = diag_query->UniqueId;
1704
1705	/*
1706	 * If ID is valid, query on ID.
1707	 * If ID is invalid, query on buffer type.
1708	 */
1709	if (unique_id == MPR_FW_DIAG_INVALID_UID) {
1710		i = diag_query->BufferType;
1711		if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
1712			*return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1713			return (MPR_DIAG_FAILURE);
1714		}
1715	} else {
1716		i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1717		if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1718			*return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1719			return (MPR_DIAG_FAILURE);
1720		}
1721	}
1722
1723	/*
1724	 * Fill query structure with the diag buffer info.
1725	 */
1726	pBuffer = &sc->fw_diag_buffer_list[i];
1727	diag_query->BufferType = pBuffer->buffer_type;
1728	diag_query->ExtendedType = pBuffer->extended_type;
1729	if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
1730		for (i = 0; i < (sizeof(diag_query->ProductSpecific) / 4);
1731		    i++) {
1732			diag_query->ProductSpecific[i] =
1733			    pBuffer->product_specific[i];
1734		}
1735	}
1736	diag_query->TotalBufferSize = pBuffer->size;
1737	diag_query->DriverAddedBufferSize = 0;
1738	diag_query->UniqueId = pBuffer->unique_id;
1739	diag_query->ApplicationFlags = 0;
1740	diag_query->DiagnosticFlags = 0;
1741
1742	/*
1743	 * Set/Clear application flags
1744	 */
1745	if (pBuffer->immediate) {
1746		diag_query->ApplicationFlags &= ~MPR_FW_DIAG_FLAG_APP_OWNED;
1747	} else {
1748		diag_query->ApplicationFlags |= MPR_FW_DIAG_FLAG_APP_OWNED;
1749	}
1750	if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
1751		diag_query->ApplicationFlags |= MPR_FW_DIAG_FLAG_BUFFER_VALID;
1752	} else {
1753		diag_query->ApplicationFlags &= ~MPR_FW_DIAG_FLAG_BUFFER_VALID;
1754	}
1755	if (pBuffer->owned_by_firmware) {
1756		diag_query->ApplicationFlags |=
1757		    MPR_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
1758	} else {
1759		diag_query->ApplicationFlags &=
1760		    ~MPR_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
1761	}
1762
1763	return (MPR_DIAG_SUCCESS);
1764}
1765
1766static int
1767mpr_diag_read_buffer(struct mpr_softc *sc,
1768    mpr_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
1769    uint32_t *return_code)
1770{
1771	mpr_fw_diagnostic_buffer_t	*pBuffer;
1772	uint8_t				i, *pData;
1773	uint32_t			unique_id;
1774	int				status;
1775
1776	unique_id = diag_read_buffer->UniqueId;
1777
1778	/*
1779	 * Get the current buffer and look up the unique ID.  The unique ID
1780	 * should be there.
1781	 */
1782	i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1783	if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1784		*return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1785		return (MPR_DIAG_FAILURE);
1786	}
1787
1788	pBuffer = &sc->fw_diag_buffer_list[i];
1789
1790	/*
1791	 * Make sure requested read is within limits
1792	 */
1793	if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
1794	    pBuffer->size) {
1795		*return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1796		return (MPR_DIAG_FAILURE);
1797	}
1798
1799	/* Sync the DMA map before we copy to userland. */
1800	bus_dmamap_sync(sc->fw_diag_dmat, sc->fw_diag_map,
1801	    BUS_DMASYNC_POSTREAD);
1802
1803	/*
1804	 * Copy the requested data from DMA to the diag_read_buffer.  The DMA
1805	 * buffer that was allocated is one contiguous buffer.
1806	 */
1807	pData = (uint8_t *)(sc->fw_diag_buffer +
1808	    diag_read_buffer->StartingOffset);
1809	if (copyout(pData, ioctl_buf, diag_read_buffer->BytesToRead) != 0)
1810		return (MPR_DIAG_FAILURE);
1811	diag_read_buffer->Status = 0;
1812
1813	/*
1814	 * Set or clear the Force Release flag.
1815	 */
1816	if (pBuffer->force_release) {
1817		diag_read_buffer->Flags |= MPR_FW_DIAG_FLAG_FORCE_RELEASE;
1818	} else {
1819		diag_read_buffer->Flags &= ~MPR_FW_DIAG_FLAG_FORCE_RELEASE;
1820	}
1821
1822	/*
1823	 * If buffer is to be reregistered, make sure it's not already owned by
1824	 * firmware first.
1825	 */
1826	status = MPR_DIAG_SUCCESS;
1827	if (!pBuffer->owned_by_firmware) {
1828		if (diag_read_buffer->Flags & MPR_FW_DIAG_FLAG_REREGISTER) {
1829			status = mpr_post_fw_diag_buffer(sc, pBuffer,
1830			    return_code);
1831		}
1832	}
1833
1834	return (status);
1835}
1836
1837static int
1838mpr_diag_release(struct mpr_softc *sc, mpr_fw_diag_release_t *diag_release,
1839    uint32_t *return_code)
1840{
1841	mpr_fw_diagnostic_buffer_t	*pBuffer;
1842	uint8_t				i;
1843	uint32_t			unique_id;
1844	int				status;
1845
1846	unique_id = diag_release->UniqueId;
1847
1848	/*
1849	 * Get the current buffer and look up the unique ID.  The unique ID
1850	 * should be there.
1851	 */
1852	i = mpr_get_fw_diag_buffer_number(sc, unique_id);
1853	if (i == MPR_FW_DIAGNOSTIC_UID_NOT_FOUND) {
1854		*return_code = MPR_FW_DIAG_ERROR_INVALID_UID;
1855		return (MPR_DIAG_FAILURE);
1856	}
1857
1858	pBuffer = &sc->fw_diag_buffer_list[i];
1859
1860	/*
1861	 * If buffer is not owned by firmware, it's already been released.
1862	 */
1863	if (!pBuffer->owned_by_firmware) {
1864		*return_code = MPR_FW_DIAG_ERROR_ALREADY_RELEASED;
1865		return (MPR_DIAG_FAILURE);
1866	}
1867
1868	/*
1869	 * Release the buffer.
1870	 */
1871	status = mpr_release_fw_diag_buffer(sc, pBuffer, return_code,
1872	    MPR_FW_DIAG_TYPE_RELEASE);
1873	return (status);
1874}
1875
1876static int
1877mpr_do_diag_action(struct mpr_softc *sc, uint32_t action, uint8_t *diag_action,
1878    uint32_t length, uint32_t *return_code)
1879{
1880	mpr_fw_diag_register_t		diag_register;
1881	mpr_fw_diag_unregister_t	diag_unregister;
1882	mpr_fw_diag_query_t		diag_query;
1883	mpr_diag_read_buffer_t		diag_read_buffer;
1884	mpr_fw_diag_release_t		diag_release;
1885	int				status = MPR_DIAG_SUCCESS;
1886	uint32_t			original_return_code;
1887
1888	original_return_code = *return_code;
1889	*return_code = MPR_FW_DIAG_ERROR_SUCCESS;
1890
1891	switch (action) {
1892		case MPR_FW_DIAG_TYPE_REGISTER:
1893			if (!length) {
1894				*return_code =
1895				    MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1896				status = MPR_DIAG_FAILURE;
1897				break;
1898			}
1899			if (copyin(diag_action, &diag_register,
1900			    sizeof(diag_register)) != 0)
1901				return (MPR_DIAG_FAILURE);
1902			status = mpr_diag_register(sc, &diag_register,
1903			    return_code);
1904			break;
1905
1906		case MPR_FW_DIAG_TYPE_UNREGISTER:
1907			if (length < sizeof(diag_unregister)) {
1908				*return_code =
1909				    MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1910				status = MPR_DIAG_FAILURE;
1911				break;
1912			}
1913			if (copyin(diag_action, &diag_unregister,
1914			    sizeof(diag_unregister)) != 0)
1915				return (MPR_DIAG_FAILURE);
1916			status = mpr_diag_unregister(sc, &diag_unregister,
1917			    return_code);
1918			break;
1919
1920		case MPR_FW_DIAG_TYPE_QUERY:
1921			if (length < sizeof (diag_query)) {
1922				*return_code =
1923				    MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1924				status = MPR_DIAG_FAILURE;
1925				break;
1926			}
1927			if (copyin(diag_action, &diag_query, sizeof(diag_query))
1928			    != 0)
1929				return (MPR_DIAG_FAILURE);
1930			status = mpr_diag_query(sc, &diag_query, return_code);
1931			if (status == MPR_DIAG_SUCCESS)
1932				if (copyout(&diag_query, diag_action,
1933				    sizeof (diag_query)) != 0)
1934					return (MPR_DIAG_FAILURE);
1935			break;
1936
1937		case MPR_FW_DIAG_TYPE_READ_BUFFER:
1938			if (copyin(diag_action, &diag_read_buffer,
1939			    sizeof(diag_read_buffer)) != 0)
1940				return (MPR_DIAG_FAILURE);
1941			if (length < diag_read_buffer.BytesToRead) {
1942				*return_code =
1943				    MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1944				status = MPR_DIAG_FAILURE;
1945				break;
1946			}
1947			status = mpr_diag_read_buffer(sc, &diag_read_buffer,
1948			    PTRIN(diag_read_buffer.PtrDataBuffer),
1949			    return_code);
1950			if (status == MPR_DIAG_SUCCESS) {
1951				if (copyout(&diag_read_buffer, diag_action,
1952				    sizeof(diag_read_buffer) -
1953				    sizeof(diag_read_buffer.PtrDataBuffer)) !=
1954				    0)
1955					return (MPR_DIAG_FAILURE);
1956			}
1957			break;
1958
1959		case MPR_FW_DIAG_TYPE_RELEASE:
1960			if (length < sizeof(diag_release)) {
1961				*return_code =
1962				    MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1963				status = MPR_DIAG_FAILURE;
1964				break;
1965			}
1966			if (copyin(diag_action, &diag_release,
1967			    sizeof(diag_release)) != 0)
1968				return (MPR_DIAG_FAILURE);
1969			status = mpr_diag_release(sc, &diag_release,
1970			    return_code);
1971			break;
1972
1973		default:
1974			*return_code = MPR_FW_DIAG_ERROR_INVALID_PARAMETER;
1975			status = MPR_DIAG_FAILURE;
1976			break;
1977	}
1978
1979	if ((status == MPR_DIAG_FAILURE) &&
1980	    (original_return_code == MPR_FW_DIAG_NEW) &&
1981	    (*return_code != MPR_FW_DIAG_ERROR_SUCCESS))
1982		status = MPR_DIAG_SUCCESS;
1983
1984	return (status);
1985}
1986
1987static int
1988mpr_user_diag_action(struct mpr_softc *sc, mpr_diag_action_t *data)
1989{
1990	int			status;
1991
1992	/*
1993	 * Only allow one diag action at one time.
1994	 */
1995	if (sc->mpr_flags & MPR_FLAGS_BUSY) {
1996		mpr_dprint(sc, MPR_USER, "%s: Only one FW diag command "
1997		    "allowed at a single time.", __func__);
1998		return (EBUSY);
1999	}
2000	sc->mpr_flags |= MPR_FLAGS_BUSY;
2001
2002	/*
2003	 * Send diag action request
2004	 */
2005	if (data->Action == MPR_FW_DIAG_TYPE_REGISTER ||
2006	    data->Action == MPR_FW_DIAG_TYPE_UNREGISTER ||
2007	    data->Action == MPR_FW_DIAG_TYPE_QUERY ||
2008	    data->Action == MPR_FW_DIAG_TYPE_READ_BUFFER ||
2009	    data->Action == MPR_FW_DIAG_TYPE_RELEASE) {
2010		status = mpr_do_diag_action(sc, data->Action,
2011		    PTRIN(data->PtrDiagAction), data->Length,
2012		    &data->ReturnCode);
2013	} else
2014		status = EINVAL;
2015
2016	sc->mpr_flags &= ~MPR_FLAGS_BUSY;
2017	return (status);
2018}
2019
2020/*
2021 * Copy the event recording mask and the event queue size out.  For
2022 * clarification, the event recording mask (events_to_record) is not the same
2023 * thing as the event mask (event_mask).  events_to_record has a bit set for
2024 * every event type that is to be recorded by the driver, and event_mask has a
2025 * bit cleared for every event that is allowed into the driver from the IOC.
2026 * They really have nothing to do with each other.
2027 */
2028static void
2029mpr_user_event_query(struct mpr_softc *sc, mpr_event_query_t *data)
2030{
2031	uint8_t	i;
2032
2033	mpr_lock(sc);
2034	data->Entries = MPR_EVENT_QUEUE_SIZE;
2035
2036	for (i = 0; i < 4; i++) {
2037		data->Types[i] = sc->events_to_record[i];
2038	}
2039	mpr_unlock(sc);
2040}
2041
2042/*
2043 * Set the driver's event mask according to what's been given.  See
2044 * mpr_user_event_query for explanation of the event recording mask and the IOC
2045 * event mask.  It's the app's responsibility to enable event logging by setting
2046 * the bits in events_to_record.  Initially, no events will be logged.
2047 */
2048static void
2049mpr_user_event_enable(struct mpr_softc *sc, mpr_event_enable_t *data)
2050{
2051	uint8_t	i;
2052
2053	mpr_lock(sc);
2054	for (i = 0; i < 4; i++) {
2055		sc->events_to_record[i] = data->Types[i];
2056	}
2057	mpr_unlock(sc);
2058}
2059
2060/*
2061 * Copy out the events that have been recorded, up to the max events allowed.
2062 */
2063static int
2064mpr_user_event_report(struct mpr_softc *sc, mpr_event_report_t *data)
2065{
2066	int		status = 0;
2067	uint32_t	size;
2068
2069	mpr_lock(sc);
2070	size = data->Size;
2071	if ((size >= sizeof(sc->recorded_events)) && (status == 0)) {
2072		mpr_unlock(sc);
2073		if (copyout((void *)sc->recorded_events,
2074		    PTRIN(data->PtrEvents), size) != 0)
2075			status = EFAULT;
2076		mpr_lock(sc);
2077	} else {
2078		/*
2079		 * data->Size value is not large enough to copy event data.
2080		 */
2081		status = EFAULT;
2082	}
2083
2084	/*
2085	 * Change size value to match the number of bytes that were copied.
2086	 */
2087	if (status == 0)
2088		data->Size = sizeof(sc->recorded_events);
2089	mpr_unlock(sc);
2090
2091	return (status);
2092}
2093
2094/*
2095 * Record events into the driver from the IOC if they are not masked.
2096 */
2097void
2098mprsas_record_event(struct mpr_softc *sc,
2099    MPI2_EVENT_NOTIFICATION_REPLY *event_reply)
2100{
2101	uint32_t	event;
2102	int		i, j;
2103	uint16_t	event_data_len;
2104	boolean_t	sendAEN = FALSE;
2105
2106	event = event_reply->Event;
2107
2108	/*
2109	 * Generate a system event to let anyone who cares know that a
2110	 * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
2111	 * event mask is set to.
2112	 */
2113	if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
2114		sendAEN = TRUE;
2115	}
2116
2117	/*
2118	 * Record the event only if its corresponding bit is set in
2119	 * events_to_record.  event_index is the index into recorded_events and
2120	 * event_number is the overall number of an event being recorded since
2121	 * start-of-day.  event_index will roll over; event_number will never
2122	 * roll over.
2123	 */
2124	i = (uint8_t)(event / 32);
2125	j = (uint8_t)(event % 32);
2126	if ((i < 4) && ((1 << j) & sc->events_to_record[i])) {
2127		i = sc->event_index;
2128		sc->recorded_events[i].Type = event;
2129		sc->recorded_events[i].Number = ++sc->event_number;
2130		bzero(sc->recorded_events[i].Data, MPR_MAX_EVENT_DATA_LENGTH *
2131		    4);
2132		event_data_len = event_reply->EventDataLength;
2133
2134		if (event_data_len > 0) {
2135			/*
2136			 * Limit data to size in m_event entry
2137			 */
2138			if (event_data_len > MPR_MAX_EVENT_DATA_LENGTH) {
2139				event_data_len = MPR_MAX_EVENT_DATA_LENGTH;
2140			}
2141			for (j = 0; j < event_data_len; j++) {
2142				sc->recorded_events[i].Data[j] =
2143				    event_reply->EventData[j];
2144			}
2145
2146			/*
2147			 * check for index wrap-around
2148			 */
2149			if (++i == MPR_EVENT_QUEUE_SIZE) {
2150				i = 0;
2151			}
2152			sc->event_index = (uint8_t)i;
2153
2154			/*
2155			 * Set flag to send the event.
2156			 */
2157			sendAEN = TRUE;
2158		}
2159	}
2160
2161	/*
2162	 * Generate a system event if flag is set to let anyone who cares know
2163	 * that an event has occurred.
2164	 */
2165	if (sendAEN) {
2166//SLM-how to send a system event (see kqueue, kevent)
2167//		(void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
2168//		    "SAS", NULL, NULL, DDI_NOSLEEP);
2169	}
2170}
2171
2172static int
2173mpr_user_reg_access(struct mpr_softc *sc, mpr_reg_access_t *data)
2174{
2175	int	status = 0;
2176
2177	switch (data->Command) {
2178		/*
2179		 * IO access is not supported.
2180		 */
2181		case REG_IO_READ:
2182		case REG_IO_WRITE:
2183			mpr_dprint(sc, MPR_USER, "IO access is not supported. "
2184			    "Use memory access.");
2185			status = EINVAL;
2186			break;
2187
2188		case REG_MEM_READ:
2189			data->RegData = mpr_regread(sc, data->RegOffset);
2190			break;
2191
2192		case REG_MEM_WRITE:
2193			mpr_regwrite(sc, data->RegOffset, data->RegData);
2194			break;
2195
2196		default:
2197			status = EINVAL;
2198			break;
2199	}
2200
2201	return (status);
2202}
2203
2204static int
2205mpr_user_btdh(struct mpr_softc *sc, mpr_btdh_mapping_t *data)
2206{
2207	uint8_t		bt2dh = FALSE;
2208	uint8_t		dh2bt = FALSE;
2209	uint16_t	dev_handle, bus, target;
2210
2211	bus = data->Bus;
2212	target = data->TargetID;
2213	dev_handle = data->DevHandle;
2214
2215	/*
2216	 * When DevHandle is 0xFFFF and Bus/Target are not 0xFFFF, use Bus/
2217	 * Target to get DevHandle.  When Bus/Target are 0xFFFF and DevHandle is
2218	 * not 0xFFFF, use DevHandle to get Bus/Target.  Anything else is
2219	 * invalid.
2220	 */
2221	if ((bus == 0xFFFF) && (target == 0xFFFF) && (dev_handle != 0xFFFF))
2222		dh2bt = TRUE;
2223	if ((dev_handle == 0xFFFF) && (bus != 0xFFFF) && (target != 0xFFFF))
2224		bt2dh = TRUE;
2225	if (!dh2bt && !bt2dh)
2226		return (EINVAL);
2227
2228	/*
2229	 * Only handle bus of 0.  Make sure target is within range.
2230	 */
2231	if (bt2dh) {
2232		if (bus != 0)
2233			return (EINVAL);
2234
2235		if (target >= sc->max_devices) {
2236			mpr_dprint(sc, MPR_XINFO, "Target ID is out of range "
2237			   "for Bus/Target to DevHandle mapping.");
2238			return (EINVAL);
2239		}
2240		dev_handle = sc->mapping_table[target].dev_handle;
2241		if (dev_handle)
2242			data->DevHandle = dev_handle;
2243	} else {
2244		bus = 0;
2245		target = mpr_mapping_get_tid_from_handle(sc, dev_handle);
2246		data->Bus = bus;
2247		data->TargetID = target;
2248	}
2249
2250	return (0);
2251}
2252
2253static int
2254mpr_ioctl(struct cdev *dev, u_long cmd, void *arg, int flag,
2255    struct thread *td)
2256{
2257	struct mpr_softc *sc;
2258	struct mpr_cfg_page_req *page_req;
2259	struct mpr_ext_cfg_page_req *ext_page_req;
2260	void *mpr_page;
2261	int error, msleep_ret;
2262
2263	mpr_page = NULL;
2264	sc = dev->si_drv1;
2265	page_req = (void *)arg;
2266	ext_page_req = (void *)arg;
2267
2268	switch (cmd) {
2269	case MPRIO_READ_CFG_HEADER:
2270		mpr_lock(sc);
2271		error = mpr_user_read_cfg_header(sc, page_req);
2272		mpr_unlock(sc);
2273		break;
2274	case MPRIO_READ_CFG_PAGE:
2275		mpr_page = malloc(page_req->len, M_MPRUSER, M_WAITOK | M_ZERO);
2276		error = copyin(page_req->buf, mpr_page,
2277		    sizeof(MPI2_CONFIG_PAGE_HEADER));
2278		if (error)
2279			break;
2280		mpr_lock(sc);
2281		error = mpr_user_read_cfg_page(sc, page_req, mpr_page);
2282		mpr_unlock(sc);
2283		if (error)
2284			break;
2285		error = copyout(mpr_page, page_req->buf, page_req->len);
2286		break;
2287	case MPRIO_READ_EXT_CFG_HEADER:
2288		mpr_lock(sc);
2289		error = mpr_user_read_extcfg_header(sc, ext_page_req);
2290		mpr_unlock(sc);
2291		break;
2292	case MPRIO_READ_EXT_CFG_PAGE:
2293		mpr_page = malloc(ext_page_req->len, M_MPRUSER,
2294		    M_WAITOK | M_ZERO);
2295		error = copyin(ext_page_req->buf, mpr_page,
2296		    sizeof(MPI2_CONFIG_EXTENDED_PAGE_HEADER));
2297		if (error)
2298			break;
2299		mpr_lock(sc);
2300		error = mpr_user_read_extcfg_page(sc, ext_page_req, mpr_page);
2301		mpr_unlock(sc);
2302		if (error)
2303			break;
2304		error = copyout(mpr_page, ext_page_req->buf, ext_page_req->len);
2305		break;
2306	case MPRIO_WRITE_CFG_PAGE:
2307		mpr_page = malloc(page_req->len, M_MPRUSER, M_WAITOK|M_ZERO);
2308		error = copyin(page_req->buf, mpr_page, page_req->len);
2309		if (error)
2310			break;
2311		mpr_lock(sc);
2312		error = mpr_user_write_cfg_page(sc, page_req, mpr_page);
2313		mpr_unlock(sc);
2314		break;
2315	case MPRIO_MPR_COMMAND:
2316		error = mpr_user_command(sc, (struct mpr_usr_command *)arg);
2317		break;
2318	case MPTIOCTL_PASS_THRU:
2319		/*
2320		 * The user has requested to pass through a command to be
2321		 * executed by the MPT firmware.  Call our routine which does
2322		 * this.  Only allow one passthru IOCTL at one time.
2323		 */
2324		error = mpr_user_pass_thru(sc, (mpr_pass_thru_t *)arg);
2325		break;
2326	case MPTIOCTL_GET_ADAPTER_DATA:
2327		/*
2328		 * The user has requested to read adapter data.  Call our
2329		 * routine which does this.
2330		 */
2331		error = 0;
2332		mpr_user_get_adapter_data(sc, (mpr_adapter_data_t *)arg);
2333		break;
2334	case MPTIOCTL_GET_PCI_INFO:
2335		/*
2336		 * The user has requested to read pci info.  Call
2337		 * our routine which does this.
2338		 */
2339		mpr_lock(sc);
2340		error = 0;
2341		mpr_user_read_pci_info(sc, (mpr_pci_info_t *)arg);
2342		mpr_unlock(sc);
2343		break;
2344	case MPTIOCTL_RESET_ADAPTER:
2345		mpr_lock(sc);
2346		sc->port_enable_complete = 0;
2347		uint32_t reinit_start = time_uptime;
2348		error = mpr_reinit(sc);
2349		/* Sleep for 300 second. */
2350		msleep_ret = msleep(&sc->port_enable_complete, &sc->mpr_mtx,
2351		    PRIBIO, "mpr_porten", 300 * hz);
2352		mpr_unlock(sc);
2353		if (msleep_ret)
2354			printf("Port Enable did not complete after Diag "
2355			    "Reset msleep error %d.\n", msleep_ret);
2356		else
2357			mpr_dprint(sc, MPR_USER, "Hard Reset with Port Enable "
2358			    "completed in %d seconds.\n",
2359			    (uint32_t)(time_uptime - reinit_start));
2360		break;
2361	case MPTIOCTL_DIAG_ACTION:
2362		/*
2363		 * The user has done a diag buffer action.  Call our routine
2364		 * which does this.  Only allow one diag action at one time.
2365		 */
2366		mpr_lock(sc);
2367		error = mpr_user_diag_action(sc, (mpr_diag_action_t *)arg);
2368		mpr_unlock(sc);
2369		break;
2370	case MPTIOCTL_EVENT_QUERY:
2371		/*
2372		 * The user has done an event query. Call our routine which does
2373		 * this.
2374		 */
2375		error = 0;
2376		mpr_user_event_query(sc, (mpr_event_query_t *)arg);
2377		break;
2378	case MPTIOCTL_EVENT_ENABLE:
2379		/*
2380		 * The user has done an event enable. Call our routine which
2381		 * does this.
2382		 */
2383		error = 0;
2384		mpr_user_event_enable(sc, (mpr_event_enable_t *)arg);
2385		break;
2386	case MPTIOCTL_EVENT_REPORT:
2387		/*
2388		 * The user has done an event report. Call our routine which
2389		 * does this.
2390		 */
2391		error = mpr_user_event_report(sc, (mpr_event_report_t *)arg);
2392		break;
2393	case MPTIOCTL_REG_ACCESS:
2394		/*
2395		 * The user has requested register access.  Call our routine
2396		 * which does this.
2397		 */
2398		mpr_lock(sc);
2399		error = mpr_user_reg_access(sc, (mpr_reg_access_t *)arg);
2400		mpr_unlock(sc);
2401		break;
2402	case MPTIOCTL_BTDH_MAPPING:
2403		/*
2404		 * The user has requested to translate a bus/target to a
2405		 * DevHandle or a DevHandle to a bus/target.  Call our routine
2406		 * which does this.
2407		 */
2408		error = mpr_user_btdh(sc, (mpr_btdh_mapping_t *)arg);
2409		break;
2410	default:
2411		error = ENOIOCTL;
2412		break;
2413	}
2414
2415	if (mpr_page != NULL)
2416		free(mpr_page, M_MPRUSER);
2417
2418	return (error);
2419}
2420
2421#ifdef COMPAT_FREEBSD32
2422
2423struct mpr_cfg_page_req32 {
2424	MPI2_CONFIG_PAGE_HEADER header;
2425	uint32_t page_address;
2426	uint32_t buf;
2427	int	len;
2428	uint16_t ioc_status;
2429};
2430
2431struct mpr_ext_cfg_page_req32 {
2432	MPI2_CONFIG_EXTENDED_PAGE_HEADER header;
2433	uint32_t page_address;
2434	uint32_t buf;
2435	int	len;
2436	uint16_t ioc_status;
2437};
2438
2439struct mpr_raid_action32 {
2440	uint8_t action;
2441	uint8_t volume_bus;
2442	uint8_t volume_id;
2443	uint8_t phys_disk_num;
2444	uint32_t action_data_word;
2445	uint32_t buf;
2446	int len;
2447	uint32_t volume_status;
2448	uint32_t action_data[4];
2449	uint16_t action_status;
2450	uint16_t ioc_status;
2451	uint8_t write;
2452};
2453
2454struct mpr_usr_command32 {
2455	uint32_t req;
2456	uint32_t req_len;
2457	uint32_t rpl;
2458	uint32_t rpl_len;
2459	uint32_t buf;
2460	int len;
2461	uint32_t flags;
2462};
2463
2464#define	MPRIO_READ_CFG_HEADER32	_IOWR('M', 200, struct mpr_cfg_page_req32)
2465#define	MPRIO_READ_CFG_PAGE32	_IOWR('M', 201, struct mpr_cfg_page_req32)
2466#define	MPRIO_READ_EXT_CFG_HEADER32 _IOWR('M', 202, struct mpr_ext_cfg_page_req32)
2467#define	MPRIO_READ_EXT_CFG_PAGE32 _IOWR('M', 203, struct mpr_ext_cfg_page_req32)
2468#define	MPRIO_WRITE_CFG_PAGE32	_IOWR('M', 204, struct mpr_cfg_page_req32)
2469#define	MPRIO_RAID_ACTION32	_IOWR('M', 205, struct mpr_raid_action32)
2470#define	MPRIO_MPR_COMMAND32	_IOWR('M', 210, struct mpr_usr_command32)
2471
2472static int
2473mpr_ioctl32(struct cdev *dev, u_long cmd32, void *_arg, int flag,
2474    struct thread *td)
2475{
2476	struct mpr_cfg_page_req32 *page32 = _arg;
2477	struct mpr_ext_cfg_page_req32 *ext32 = _arg;
2478	struct mpr_raid_action32 *raid32 = _arg;
2479	struct mpr_usr_command32 *user32 = _arg;
2480	union {
2481		struct mpr_cfg_page_req page;
2482		struct mpr_ext_cfg_page_req ext;
2483		struct mpr_raid_action raid;
2484		struct mpr_usr_command user;
2485	} arg;
2486	u_long cmd;
2487	int error;
2488
2489	switch (cmd32) {
2490	case MPRIO_READ_CFG_HEADER32:
2491	case MPRIO_READ_CFG_PAGE32:
2492	case MPRIO_WRITE_CFG_PAGE32:
2493		if (cmd32 == MPRIO_READ_CFG_HEADER32)
2494			cmd = MPRIO_READ_CFG_HEADER;
2495		else if (cmd32 == MPRIO_READ_CFG_PAGE32)
2496			cmd = MPRIO_READ_CFG_PAGE;
2497		else
2498			cmd = MPRIO_WRITE_CFG_PAGE;
2499		CP(*page32, arg.page, header);
2500		CP(*page32, arg.page, page_address);
2501		PTRIN_CP(*page32, arg.page, buf);
2502		CP(*page32, arg.page, len);
2503		CP(*page32, arg.page, ioc_status);
2504		break;
2505
2506	case MPRIO_READ_EXT_CFG_HEADER32:
2507	case MPRIO_READ_EXT_CFG_PAGE32:
2508		if (cmd32 == MPRIO_READ_EXT_CFG_HEADER32)
2509			cmd = MPRIO_READ_EXT_CFG_HEADER;
2510		else
2511			cmd = MPRIO_READ_EXT_CFG_PAGE;
2512		CP(*ext32, arg.ext, header);
2513		CP(*ext32, arg.ext, page_address);
2514		PTRIN_CP(*ext32, arg.ext, buf);
2515		CP(*ext32, arg.ext, len);
2516		CP(*ext32, arg.ext, ioc_status);
2517		break;
2518
2519	case MPRIO_RAID_ACTION32:
2520		cmd = MPRIO_RAID_ACTION;
2521		CP(*raid32, arg.raid, action);
2522		CP(*raid32, arg.raid, volume_bus);
2523		CP(*raid32, arg.raid, volume_id);
2524		CP(*raid32, arg.raid, phys_disk_num);
2525		CP(*raid32, arg.raid, action_data_word);
2526		PTRIN_CP(*raid32, arg.raid, buf);
2527		CP(*raid32, arg.raid, len);
2528		CP(*raid32, arg.raid, volume_status);
2529		bcopy(raid32->action_data, arg.raid.action_data,
2530		    sizeof arg.raid.action_data);
2531		CP(*raid32, arg.raid, ioc_status);
2532		CP(*raid32, arg.raid, write);
2533		break;
2534
2535	case MPRIO_MPR_COMMAND32:
2536		cmd = MPRIO_MPR_COMMAND;
2537		PTRIN_CP(*user32, arg.user, req);
2538		CP(*user32, arg.user, req_len);
2539		PTRIN_CP(*user32, arg.user, rpl);
2540		CP(*user32, arg.user, rpl_len);
2541		PTRIN_CP(*user32, arg.user, buf);
2542		CP(*user32, arg.user, len);
2543		CP(*user32, arg.user, flags);
2544		break;
2545	default:
2546		return (ENOIOCTL);
2547	}
2548
2549	error = mpr_ioctl(dev, cmd, &arg, flag, td);
2550	if (error == 0 && (cmd32 & IOC_OUT) != 0) {
2551		switch (cmd32) {
2552		case MPRIO_READ_CFG_HEADER32:
2553		case MPRIO_READ_CFG_PAGE32:
2554		case MPRIO_WRITE_CFG_PAGE32:
2555			CP(arg.page, *page32, header);
2556			CP(arg.page, *page32, page_address);
2557			PTROUT_CP(arg.page, *page32, buf);
2558			CP(arg.page, *page32, len);
2559			CP(arg.page, *page32, ioc_status);
2560			break;
2561
2562		case MPRIO_READ_EXT_CFG_HEADER32:
2563		case MPRIO_READ_EXT_CFG_PAGE32:
2564			CP(arg.ext, *ext32, header);
2565			CP(arg.ext, *ext32, page_address);
2566			PTROUT_CP(arg.ext, *ext32, buf);
2567			CP(arg.ext, *ext32, len);
2568			CP(arg.ext, *ext32, ioc_status);
2569			break;
2570
2571		case MPRIO_RAID_ACTION32:
2572			CP(arg.raid, *raid32, action);
2573			CP(arg.raid, *raid32, volume_bus);
2574			CP(arg.raid, *raid32, volume_id);
2575			CP(arg.raid, *raid32, phys_disk_num);
2576			CP(arg.raid, *raid32, action_data_word);
2577			PTROUT_CP(arg.raid, *raid32, buf);
2578			CP(arg.raid, *raid32, len);
2579			CP(arg.raid, *raid32, volume_status);
2580			bcopy(arg.raid.action_data, raid32->action_data,
2581			    sizeof arg.raid.action_data);
2582			CP(arg.raid, *raid32, ioc_status);
2583			CP(arg.raid, *raid32, write);
2584			break;
2585
2586		case MPRIO_MPR_COMMAND32:
2587			PTROUT_CP(arg.user, *user32, req);
2588			CP(arg.user, *user32, req_len);
2589			PTROUT_CP(arg.user, *user32, rpl);
2590			CP(arg.user, *user32, rpl_len);
2591			PTROUT_CP(arg.user, *user32, buf);
2592			CP(arg.user, *user32, len);
2593			CP(arg.user, *user32, flags);
2594			break;
2595		}
2596	}
2597
2598	return (error);
2599}
2600#endif /* COMPAT_FREEBSD32 */
2601
2602static int
2603mpr_ioctl_devsw(struct cdev *dev, u_long com, caddr_t arg, int flag,
2604    struct thread *td)
2605{
2606#ifdef COMPAT_FREEBSD32
2607	if (SV_CURPROC_FLAG(SV_ILP32))
2608		return (mpr_ioctl32(dev, com, arg, flag, td));
2609#endif
2610	return (mpr_ioctl(dev, com, arg, flag, td));
2611}
2612