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