xref: /freebsd/sys/dev/mpt/mpt_user.c (revision 7ee37807)
1ee98c4a5SJohn Baldwin /*-
2ee98c4a5SJohn Baldwin  * Copyright (c) 2008 Yahoo!, Inc.
3ee98c4a5SJohn Baldwin  * All rights reserved.
4ee98c4a5SJohn Baldwin  * Written by: John Baldwin <jhb@FreeBSD.org>
5ee98c4a5SJohn Baldwin  *
6ee98c4a5SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
7ee98c4a5SJohn Baldwin  * modification, are permitted provided that the following conditions
8ee98c4a5SJohn Baldwin  * are met:
9ee98c4a5SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
10ee98c4a5SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
11ee98c4a5SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
12ee98c4a5SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
13ee98c4a5SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
14ee98c4a5SJohn Baldwin  * 3. Neither the name of the author nor the names of any co-contributors
15ee98c4a5SJohn Baldwin  *    may be used to endorse or promote products derived from this software
16ee98c4a5SJohn Baldwin  *    without specific prior written permission.
17ee98c4a5SJohn Baldwin  *
18ee98c4a5SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19ee98c4a5SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ee98c4a5SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ee98c4a5SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22ee98c4a5SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ee98c4a5SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ee98c4a5SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ee98c4a5SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26ee98c4a5SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27ee98c4a5SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28ee98c4a5SJohn Baldwin  * SUCH DAMAGE.
29ee98c4a5SJohn Baldwin  *
30ee98c4a5SJohn Baldwin  * LSI MPT-Fusion Host Adapter FreeBSD userland interface
31ee98c4a5SJohn Baldwin  */
32ee98c4a5SJohn Baldwin 
33ee98c4a5SJohn Baldwin #include <sys/cdefs.h>
34ee98c4a5SJohn Baldwin __FBSDID("$FreeBSD$");
35ee98c4a5SJohn Baldwin 
36ee98c4a5SJohn Baldwin #include <sys/param.h>
37ee98c4a5SJohn Baldwin #include <sys/conf.h>
38ee98c4a5SJohn Baldwin #include <sys/errno.h>
39ee98c4a5SJohn Baldwin #include <sys/ioccom.h>
40ee98c4a5SJohn Baldwin #include <sys/mpt_ioctl.h>
41ee98c4a5SJohn Baldwin 
42ee98c4a5SJohn Baldwin #include <dev/mpt/mpt.h>
43ee98c4a5SJohn Baldwin 
44ee98c4a5SJohn Baldwin struct mpt_user_raid_action_result {
45ee98c4a5SJohn Baldwin 	uint32_t	volume_status;
46ee98c4a5SJohn Baldwin 	uint32_t	action_data[4];
47ee98c4a5SJohn Baldwin 	uint16_t	action_status;
48ee98c4a5SJohn Baldwin };
49ee98c4a5SJohn Baldwin 
504124f62eSJohn Baldwin struct mpt_page_memory {
514124f62eSJohn Baldwin 	bus_dma_tag_t	tag;
524124f62eSJohn Baldwin 	bus_dmamap_t	map;
534124f62eSJohn Baldwin 	bus_addr_t	paddr;
544124f62eSJohn Baldwin 	void		*vaddr;
554124f62eSJohn Baldwin };
564124f62eSJohn Baldwin 
57ee98c4a5SJohn Baldwin static mpt_probe_handler_t	mpt_user_probe;
58ee98c4a5SJohn Baldwin static mpt_attach_handler_t	mpt_user_attach;
59ee98c4a5SJohn Baldwin static mpt_enable_handler_t	mpt_user_enable;
60ee98c4a5SJohn Baldwin static mpt_ready_handler_t	mpt_user_ready;
61ee98c4a5SJohn Baldwin static mpt_event_handler_t	mpt_user_event;
62ee98c4a5SJohn Baldwin static mpt_reset_handler_t	mpt_user_reset;
63ee98c4a5SJohn Baldwin static mpt_detach_handler_t	mpt_user_detach;
64ee98c4a5SJohn Baldwin 
65ee98c4a5SJohn Baldwin static struct mpt_personality mpt_user_personality = {
66ee98c4a5SJohn Baldwin 	.name		= "mpt_user",
67ee98c4a5SJohn Baldwin 	.probe		= mpt_user_probe,
68ee98c4a5SJohn Baldwin 	.attach		= mpt_user_attach,
69ee98c4a5SJohn Baldwin 	.enable		= mpt_user_enable,
70ee98c4a5SJohn Baldwin 	.ready		= mpt_user_ready,
71ee98c4a5SJohn Baldwin 	.event		= mpt_user_event,
72ee98c4a5SJohn Baldwin 	.reset		= mpt_user_reset,
73ee98c4a5SJohn Baldwin 	.detach		= mpt_user_detach,
74ee98c4a5SJohn Baldwin };
75ee98c4a5SJohn Baldwin 
76ee98c4a5SJohn Baldwin DECLARE_MPT_PERSONALITY(mpt_user, SI_ORDER_SECOND);
77ee98c4a5SJohn Baldwin 
78ee98c4a5SJohn Baldwin static mpt_reply_handler_t	mpt_user_reply_handler;
79ee98c4a5SJohn Baldwin 
80ee98c4a5SJohn Baldwin static d_open_t		mpt_open;
81ee98c4a5SJohn Baldwin static d_close_t	mpt_close;
82ee98c4a5SJohn Baldwin static d_ioctl_t	mpt_ioctl;
83ee98c4a5SJohn Baldwin 
84ee98c4a5SJohn Baldwin static struct cdevsw mpt_cdevsw = {
85ee98c4a5SJohn Baldwin 	.d_version =	D_VERSION,
86ee98c4a5SJohn Baldwin 	.d_flags =	0,
87ee98c4a5SJohn Baldwin 	.d_open =	mpt_open,
88ee98c4a5SJohn Baldwin 	.d_close =	mpt_close,
89ee98c4a5SJohn Baldwin 	.d_ioctl =	mpt_ioctl,
90ee98c4a5SJohn Baldwin 	.d_name =	"mpt",
91ee98c4a5SJohn Baldwin };
92ee98c4a5SJohn Baldwin 
93ee98c4a5SJohn Baldwin static MALLOC_DEFINE(M_MPTUSER, "mpt_user", "Buffers for mpt(4) ioctls");
94ee98c4a5SJohn Baldwin 
95ee98c4a5SJohn Baldwin static uint32_t user_handler_id = MPT_HANDLER_ID_NONE;
96ee98c4a5SJohn Baldwin 
97ee98c4a5SJohn Baldwin int
98ee98c4a5SJohn Baldwin mpt_user_probe(struct mpt_softc *mpt)
99ee98c4a5SJohn Baldwin {
100ee98c4a5SJohn Baldwin 
101ee98c4a5SJohn Baldwin 	/* Attach to every controller. */
102ee98c4a5SJohn Baldwin 	return (0);
103ee98c4a5SJohn Baldwin }
104ee98c4a5SJohn Baldwin 
105ee98c4a5SJohn Baldwin int
106ee98c4a5SJohn Baldwin mpt_user_attach(struct mpt_softc *mpt)
107ee98c4a5SJohn Baldwin {
108ee98c4a5SJohn Baldwin 	mpt_handler_t handler;
109ee98c4a5SJohn Baldwin 	int error, unit;
110ee98c4a5SJohn Baldwin 
111ee98c4a5SJohn Baldwin 	MPT_LOCK(mpt);
112ee98c4a5SJohn Baldwin 	handler.reply_handler = mpt_user_reply_handler;
113ee98c4a5SJohn Baldwin 	error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
114ee98c4a5SJohn Baldwin 				     &user_handler_id);
115ee98c4a5SJohn Baldwin 	MPT_UNLOCK(mpt);
116ee98c4a5SJohn Baldwin 	if (error != 0) {
117ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "Unable to register user handler!\n");
118ee98c4a5SJohn Baldwin 		return (error);
119ee98c4a5SJohn Baldwin 	}
120ee98c4a5SJohn Baldwin 	unit = device_get_unit(mpt->dev);
121ee98c4a5SJohn Baldwin 	mpt->cdev = make_dev(&mpt_cdevsw, unit, UID_ROOT, GID_OPERATOR, 0640,
122ee98c4a5SJohn Baldwin 	    "mpt%d", unit);
123ee98c4a5SJohn Baldwin 	if (mpt->cdev == NULL) {
124ee98c4a5SJohn Baldwin 		MPT_LOCK(mpt);
125ee98c4a5SJohn Baldwin 		mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
126ee98c4a5SJohn Baldwin 		    user_handler_id);
127ee98c4a5SJohn Baldwin 		MPT_UNLOCK(mpt);
128ee98c4a5SJohn Baldwin 		return (ENOMEM);
129ee98c4a5SJohn Baldwin 	}
130ee98c4a5SJohn Baldwin 	mpt->cdev->si_drv1 = mpt;
131ee98c4a5SJohn Baldwin 	return (0);
132ee98c4a5SJohn Baldwin }
133ee98c4a5SJohn Baldwin 
134ee98c4a5SJohn Baldwin int
135ee98c4a5SJohn Baldwin mpt_user_enable(struct mpt_softc *mpt)
136ee98c4a5SJohn Baldwin {
137ee98c4a5SJohn Baldwin 
138ee98c4a5SJohn Baldwin 	return (0);
139ee98c4a5SJohn Baldwin }
140ee98c4a5SJohn Baldwin 
141ee98c4a5SJohn Baldwin void
142ee98c4a5SJohn Baldwin mpt_user_ready(struct mpt_softc *mpt)
143ee98c4a5SJohn Baldwin {
144ee98c4a5SJohn Baldwin }
145ee98c4a5SJohn Baldwin 
146ee98c4a5SJohn Baldwin int
147ee98c4a5SJohn Baldwin mpt_user_event(struct mpt_softc *mpt, request_t *req,
148ee98c4a5SJohn Baldwin     MSG_EVENT_NOTIFY_REPLY *msg)
149ee98c4a5SJohn Baldwin {
150ee98c4a5SJohn Baldwin 
151ee98c4a5SJohn Baldwin 	/* Someday we may want to let a user daemon listen for events? */
152ee98c4a5SJohn Baldwin 	return (0);
153ee98c4a5SJohn Baldwin }
154ee98c4a5SJohn Baldwin 
155ee98c4a5SJohn Baldwin void
156ee98c4a5SJohn Baldwin mpt_user_reset(struct mpt_softc *mpt, int type)
157ee98c4a5SJohn Baldwin {
158ee98c4a5SJohn Baldwin }
159ee98c4a5SJohn Baldwin 
160ee98c4a5SJohn Baldwin void
161ee98c4a5SJohn Baldwin mpt_user_detach(struct mpt_softc *mpt)
162ee98c4a5SJohn Baldwin {
163ee98c4a5SJohn Baldwin 	mpt_handler_t handler;
164ee98c4a5SJohn Baldwin 
165ee98c4a5SJohn Baldwin 	/* XXX: do a purge of pending requests? */
166ee98c4a5SJohn Baldwin 	destroy_dev(mpt->cdev);
167ee98c4a5SJohn Baldwin 
168ee98c4a5SJohn Baldwin 	MPT_LOCK(mpt);
169ee98c4a5SJohn Baldwin 	handler.reply_handler = mpt_user_reply_handler;
170ee98c4a5SJohn Baldwin 	mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
171ee98c4a5SJohn Baldwin 	    user_handler_id);
172ee98c4a5SJohn Baldwin 	MPT_UNLOCK(mpt);
173ee98c4a5SJohn Baldwin }
174ee98c4a5SJohn Baldwin 
175ee98c4a5SJohn Baldwin static int
176ee98c4a5SJohn Baldwin mpt_open(struct cdev *dev, int flags, int fmt, d_thread_t *td)
177ee98c4a5SJohn Baldwin {
178ee98c4a5SJohn Baldwin 
179ee98c4a5SJohn Baldwin 	return (0);
180ee98c4a5SJohn Baldwin }
181ee98c4a5SJohn Baldwin 
182ee98c4a5SJohn Baldwin static int
183ee98c4a5SJohn Baldwin mpt_close(struct cdev *dev, int flags, int fmt, d_thread_t *td)
184ee98c4a5SJohn Baldwin {
185ee98c4a5SJohn Baldwin 
186ee98c4a5SJohn Baldwin 	return (0);
187ee98c4a5SJohn Baldwin }
188ee98c4a5SJohn Baldwin 
189ee98c4a5SJohn Baldwin static int
1904124f62eSJohn Baldwin mpt_alloc_buffer(struct mpt_softc *mpt, struct mpt_page_memory *page_mem,
1914124f62eSJohn Baldwin     size_t len)
1924124f62eSJohn Baldwin {
1934124f62eSJohn Baldwin 	struct mpt_map_info mi;
1944124f62eSJohn Baldwin 	int error;
1954124f62eSJohn Baldwin 
1964124f62eSJohn Baldwin 	page_mem->vaddr = NULL;
1974124f62eSJohn Baldwin 
1984124f62eSJohn Baldwin 	/* Limit requests to 16M. */
1994124f62eSJohn Baldwin 	if (len > 16 * 1024 * 1024)
2004124f62eSJohn Baldwin 		return (ENOSPC);
2014124f62eSJohn Baldwin 	error = mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 0,
2024124f62eSJohn Baldwin 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
2034124f62eSJohn Baldwin 	    len, 1, len, 0, &page_mem->tag);
2044124f62eSJohn Baldwin 	if (error)
2054124f62eSJohn Baldwin 		return (error);
2064124f62eSJohn Baldwin 	error = bus_dmamem_alloc(page_mem->tag, &page_mem->vaddr,
2074124f62eSJohn Baldwin 	    BUS_DMA_NOWAIT, &page_mem->map);
2084124f62eSJohn Baldwin 	if (error) {
2094124f62eSJohn Baldwin 		bus_dma_tag_destroy(page_mem->tag);
2104124f62eSJohn Baldwin 		return (error);
2114124f62eSJohn Baldwin 	}
2124124f62eSJohn Baldwin 	mi.mpt = mpt;
2134124f62eSJohn Baldwin 	error = bus_dmamap_load(page_mem->tag, page_mem->map, page_mem->vaddr,
2144124f62eSJohn Baldwin 	    len, mpt_map_rquest, &mi, BUS_DMA_NOWAIT);
2154124f62eSJohn Baldwin 	if (error == 0)
2164124f62eSJohn Baldwin 		error = mi.error;
2174124f62eSJohn Baldwin 	if (error) {
2184124f62eSJohn Baldwin 		bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map);
2194124f62eSJohn Baldwin 		bus_dma_tag_destroy(page_mem->tag);
2204124f62eSJohn Baldwin 		page_mem->vaddr = NULL;
2214124f62eSJohn Baldwin 		return (error);
2224124f62eSJohn Baldwin 	}
2234124f62eSJohn Baldwin 	page_mem->paddr = mi.phys;
2244124f62eSJohn Baldwin 	return (0);
2254124f62eSJohn Baldwin }
2264124f62eSJohn Baldwin 
2274124f62eSJohn Baldwin static void
2284124f62eSJohn Baldwin mpt_free_buffer(struct mpt_page_memory *page_mem)
2294124f62eSJohn Baldwin {
2304124f62eSJohn Baldwin 
2314124f62eSJohn Baldwin 	if (page_mem->vaddr == NULL)
2324124f62eSJohn Baldwin 		return;
2334124f62eSJohn Baldwin 	bus_dmamap_unload(page_mem->tag, page_mem->map);
2344124f62eSJohn Baldwin 	bus_dmamem_free(page_mem->tag, page_mem->vaddr, page_mem->map);
2354124f62eSJohn Baldwin 	bus_dma_tag_destroy(page_mem->tag);
2364124f62eSJohn Baldwin 	page_mem->vaddr = NULL;
2374124f62eSJohn Baldwin }
2384124f62eSJohn Baldwin 
2394124f62eSJohn Baldwin static int
240ee98c4a5SJohn Baldwin mpt_user_read_cfg_header(struct mpt_softc *mpt,
241ee98c4a5SJohn Baldwin     struct mpt_cfg_page_req *page_req)
242ee98c4a5SJohn Baldwin {
243ee98c4a5SJohn Baldwin 	request_t  *req;
244ee98c4a5SJohn Baldwin 	cfgparms_t params;
245ee98c4a5SJohn Baldwin 	MSG_CONFIG *cfgp;
246ee98c4a5SJohn Baldwin 	int	    error;
247ee98c4a5SJohn Baldwin 
248ee98c4a5SJohn Baldwin 	req = mpt_get_request(mpt, TRUE);
249ee98c4a5SJohn Baldwin 	if (req == NULL) {
250ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_user_read_cfg_header: Get request failed!\n");
251ee98c4a5SJohn Baldwin 		return (ENOMEM);
252ee98c4a5SJohn Baldwin 	}
253ee98c4a5SJohn Baldwin 
254ee98c4a5SJohn Baldwin 	params.Action = MPI_CONFIG_ACTION_PAGE_HEADER;
255ee98c4a5SJohn Baldwin 	params.PageVersion = 0;
256ee98c4a5SJohn Baldwin 	params.PageLength = 0;
257ee98c4a5SJohn Baldwin 	params.PageNumber = page_req->header.PageNumber;
258ee98c4a5SJohn Baldwin 	params.PageType = page_req->header.PageType;
2597ee37807SMarius Strobl 	params.PageAddress = le32toh(page_req->page_address);
260ee98c4a5SJohn Baldwin 	error = mpt_issue_cfg_req(mpt, req, &params, /*addr*/0, /*len*/0,
261ee98c4a5SJohn Baldwin 				  TRUE, 5000);
262ee98c4a5SJohn Baldwin 	if (error != 0) {
263ee98c4a5SJohn Baldwin 		/*
264ee98c4a5SJohn Baldwin 		 * Leave the request. Without resetting the chip, it's
265ee98c4a5SJohn Baldwin 		 * still owned by it and we'll just get into trouble
266ee98c4a5SJohn Baldwin 		 * freeing it now. Mark it as abandoned so that if it
267ee98c4a5SJohn Baldwin 		 * shows up later it can be freed.
268ee98c4a5SJohn Baldwin 		 */
269ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "read_cfg_header timed out\n");
270ee98c4a5SJohn Baldwin 		return (ETIMEDOUT);
271ee98c4a5SJohn Baldwin 	}
272ee98c4a5SJohn Baldwin 
2737ee37807SMarius Strobl 	page_req->ioc_status = htole16(req->IOCStatus);
274ee98c4a5SJohn Baldwin 	if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) {
275ee98c4a5SJohn Baldwin 		cfgp = req->req_vbuf;
276ee98c4a5SJohn Baldwin 		bcopy(&cfgp->Header, &page_req->header,
277ee98c4a5SJohn Baldwin 		    sizeof(page_req->header));
278ee98c4a5SJohn Baldwin 	}
279ee98c4a5SJohn Baldwin 	mpt_free_request(mpt, req);
280ee98c4a5SJohn Baldwin 	return (0);
281ee98c4a5SJohn Baldwin }
282ee98c4a5SJohn Baldwin 
283ee98c4a5SJohn Baldwin static int
284ee98c4a5SJohn Baldwin mpt_user_read_cfg_page(struct mpt_softc *mpt, struct mpt_cfg_page_req *page_req,
2854124f62eSJohn Baldwin     struct mpt_page_memory *mpt_page)
286ee98c4a5SJohn Baldwin {
287ee98c4a5SJohn Baldwin 	CONFIG_PAGE_HEADER *hdr;
288ee98c4a5SJohn Baldwin 	request_t    *req;
289ee98c4a5SJohn Baldwin 	cfgparms_t    params;
290ee98c4a5SJohn Baldwin 	int	      error;
291ee98c4a5SJohn Baldwin 
292ee98c4a5SJohn Baldwin 	req = mpt_get_request(mpt, TRUE);
293ee98c4a5SJohn Baldwin 	if (req == NULL) {
294ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_user_read_cfg_page: Get request failed!\n");
295ee98c4a5SJohn Baldwin 		return (ENOMEM);
296ee98c4a5SJohn Baldwin 	}
297ee98c4a5SJohn Baldwin 
2984124f62eSJohn Baldwin 	hdr = mpt_page->vaddr;
299ee98c4a5SJohn Baldwin 	params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
300ee98c4a5SJohn Baldwin 	params.PageVersion = hdr->PageVersion;
301ee98c4a5SJohn Baldwin 	params.PageLength = hdr->PageLength;
302ee98c4a5SJohn Baldwin 	params.PageNumber = hdr->PageNumber;
303ee98c4a5SJohn Baldwin 	params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK;
3047ee37807SMarius Strobl 	params.PageAddress = le32toh(page_req->page_address);
3054124f62eSJohn Baldwin 	error = mpt_issue_cfg_req(mpt, req, &params, mpt_page->paddr,
3067ee37807SMarius Strobl 	    le32toh(page_req->len), TRUE, 5000);
307ee98c4a5SJohn Baldwin 	if (error != 0) {
308ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_user_read_cfg_page timed out\n");
309ee98c4a5SJohn Baldwin 		return (ETIMEDOUT);
310ee98c4a5SJohn Baldwin 	}
311ee98c4a5SJohn Baldwin 
3127ee37807SMarius Strobl 	page_req->ioc_status = htole16(req->IOCStatus);
3134124f62eSJohn Baldwin 	if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS)
3144124f62eSJohn Baldwin 		bus_dmamap_sync(mpt_page->tag, mpt_page->map,
315ee98c4a5SJohn Baldwin 		    BUS_DMASYNC_POSTREAD);
316ee98c4a5SJohn Baldwin 	mpt_free_request(mpt, req);
317ee98c4a5SJohn Baldwin 	return (0);
318ee98c4a5SJohn Baldwin }
319ee98c4a5SJohn Baldwin 
320ee98c4a5SJohn Baldwin static int
321ee98c4a5SJohn Baldwin mpt_user_read_extcfg_header(struct mpt_softc *mpt,
322ee98c4a5SJohn Baldwin     struct mpt_ext_cfg_page_req *ext_page_req)
323ee98c4a5SJohn Baldwin {
324ee98c4a5SJohn Baldwin 	request_t  *req;
325ee98c4a5SJohn Baldwin 	cfgparms_t params;
326ee98c4a5SJohn Baldwin 	MSG_CONFIG_REPLY *cfgp;
327ee98c4a5SJohn Baldwin 	int	    error;
328ee98c4a5SJohn Baldwin 
329ee98c4a5SJohn Baldwin 	req = mpt_get_request(mpt, TRUE);
330ee98c4a5SJohn Baldwin 	if (req == NULL) {
331ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_user_read_extcfg_header: Get request failed!\n");
332ee98c4a5SJohn Baldwin 		return (ENOMEM);
333ee98c4a5SJohn Baldwin 	}
334ee98c4a5SJohn Baldwin 
335ee98c4a5SJohn Baldwin 	params.Action = MPI_CONFIG_ACTION_PAGE_HEADER;
336ee98c4a5SJohn Baldwin 	params.PageVersion = ext_page_req->header.PageVersion;
337ee98c4a5SJohn Baldwin 	params.PageLength = 0;
338ee98c4a5SJohn Baldwin 	params.PageNumber = ext_page_req->header.PageNumber;
339ee98c4a5SJohn Baldwin 	params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
3407ee37807SMarius Strobl 	params.PageAddress = le32toh(ext_page_req->page_address);
341ee98c4a5SJohn Baldwin 	params.ExtPageType = ext_page_req->header.ExtPageType;
342ee98c4a5SJohn Baldwin 	params.ExtPageLength = 0;
343ee98c4a5SJohn Baldwin 	error = mpt_issue_cfg_req(mpt, req, &params, /*addr*/0, /*len*/0,
344ee98c4a5SJohn Baldwin 				  TRUE, 5000);
345ee98c4a5SJohn Baldwin 	if (error != 0) {
346ee98c4a5SJohn Baldwin 		/*
347ee98c4a5SJohn Baldwin 		 * Leave the request. Without resetting the chip, it's
348ee98c4a5SJohn Baldwin 		 * still owned by it and we'll just get into trouble
349ee98c4a5SJohn Baldwin 		 * freeing it now. Mark it as abandoned so that if it
350ee98c4a5SJohn Baldwin 		 * shows up later it can be freed.
351ee98c4a5SJohn Baldwin 		 */
352ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_user_read_extcfg_header timed out\n");
353ee98c4a5SJohn Baldwin 		return (ETIMEDOUT);
354ee98c4a5SJohn Baldwin 	}
355ee98c4a5SJohn Baldwin 
3567ee37807SMarius Strobl 	ext_page_req->ioc_status = htole16(req->IOCStatus);
357ee98c4a5SJohn Baldwin 	if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS) {
358ee98c4a5SJohn Baldwin 		cfgp = req->req_vbuf;
359ee98c4a5SJohn Baldwin 		ext_page_req->header.PageVersion = cfgp->Header.PageVersion;
360ee98c4a5SJohn Baldwin 		ext_page_req->header.PageNumber = cfgp->Header.PageNumber;
361ee98c4a5SJohn Baldwin 		ext_page_req->header.PageType = cfgp->Header.PageType;
362ee98c4a5SJohn Baldwin 		ext_page_req->header.ExtPageLength = cfgp->ExtPageLength;
363ee98c4a5SJohn Baldwin 		ext_page_req->header.ExtPageType = cfgp->ExtPageType;
364ee98c4a5SJohn Baldwin 	}
365ee98c4a5SJohn Baldwin 	mpt_free_request(mpt, req);
366ee98c4a5SJohn Baldwin 	return (0);
367ee98c4a5SJohn Baldwin }
368ee98c4a5SJohn Baldwin 
369ee98c4a5SJohn Baldwin static int
370ee98c4a5SJohn Baldwin mpt_user_read_extcfg_page(struct mpt_softc *mpt,
3714124f62eSJohn Baldwin     struct mpt_ext_cfg_page_req *ext_page_req, struct mpt_page_memory *mpt_page)
372ee98c4a5SJohn Baldwin {
373ee98c4a5SJohn Baldwin 	CONFIG_EXTENDED_PAGE_HEADER *hdr;
374ee98c4a5SJohn Baldwin 	request_t    *req;
375ee98c4a5SJohn Baldwin 	cfgparms_t    params;
376ee98c4a5SJohn Baldwin 	int	      error;
377ee98c4a5SJohn Baldwin 
378ee98c4a5SJohn Baldwin 	req = mpt_get_request(mpt, TRUE);
379ee98c4a5SJohn Baldwin 	if (req == NULL) {
380ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_user_read_extcfg_page: Get request failed!\n");
381ee98c4a5SJohn Baldwin 		return (ENOMEM);
382ee98c4a5SJohn Baldwin 	}
383ee98c4a5SJohn Baldwin 
3844124f62eSJohn Baldwin 	hdr = mpt_page->vaddr;
385ee98c4a5SJohn Baldwin 	params.Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
386ee98c4a5SJohn Baldwin 	params.PageVersion = hdr->PageVersion;
387ee98c4a5SJohn Baldwin 	params.PageLength = 0;
388ee98c4a5SJohn Baldwin 	params.PageNumber = hdr->PageNumber;
389ee98c4a5SJohn Baldwin 	params.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
3907ee37807SMarius Strobl 	params.PageAddress = le32toh(ext_page_req->page_address);
391ee98c4a5SJohn Baldwin 	params.ExtPageType = hdr->ExtPageType;
392ee98c4a5SJohn Baldwin 	params.ExtPageLength = hdr->ExtPageLength;
3934124f62eSJohn Baldwin 	error = mpt_issue_cfg_req(mpt, req, &params, mpt_page->paddr,
3947ee37807SMarius Strobl 	    le32toh(ext_page_req->len), TRUE, 5000);
395ee98c4a5SJohn Baldwin 	if (error != 0) {
396ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_user_read_extcfg_page timed out\n");
397ee98c4a5SJohn Baldwin 		return (ETIMEDOUT);
398ee98c4a5SJohn Baldwin 	}
399ee98c4a5SJohn Baldwin 
4007ee37807SMarius Strobl 	ext_page_req->ioc_status = htole16(req->IOCStatus);
4014124f62eSJohn Baldwin 	if ((req->IOCStatus & MPI_IOCSTATUS_MASK) == MPI_IOCSTATUS_SUCCESS)
4024124f62eSJohn Baldwin 		bus_dmamap_sync(mpt_page->tag, mpt_page->map,
403ee98c4a5SJohn Baldwin 		    BUS_DMASYNC_POSTREAD);
404ee98c4a5SJohn Baldwin 	mpt_free_request(mpt, req);
405ee98c4a5SJohn Baldwin 	return (0);
406ee98c4a5SJohn Baldwin }
407ee98c4a5SJohn Baldwin 
408ee98c4a5SJohn Baldwin static int
409ee98c4a5SJohn Baldwin mpt_user_write_cfg_page(struct mpt_softc *mpt,
4104124f62eSJohn Baldwin     struct mpt_cfg_page_req *page_req, struct mpt_page_memory *mpt_page)
411ee98c4a5SJohn Baldwin {
412ee98c4a5SJohn Baldwin 	CONFIG_PAGE_HEADER *hdr;
413ee98c4a5SJohn Baldwin 	request_t    *req;
414ee98c4a5SJohn Baldwin 	cfgparms_t    params;
415ee98c4a5SJohn Baldwin 	u_int	      hdr_attr;
416ee98c4a5SJohn Baldwin 	int	      error;
417ee98c4a5SJohn Baldwin 
4184124f62eSJohn Baldwin 	hdr = mpt_page->vaddr;
419ee98c4a5SJohn Baldwin 	hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
420ee98c4a5SJohn Baldwin 	if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
421ee98c4a5SJohn Baldwin 	    hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
422ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "page type 0x%x not changeable\n",
423ee98c4a5SJohn Baldwin 			hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
424ee98c4a5SJohn Baldwin 		return (EINVAL);
425ee98c4a5SJohn Baldwin 	}
426ee98c4a5SJohn Baldwin 
427ee98c4a5SJohn Baldwin #if	0
428ee98c4a5SJohn Baldwin 	/*
429ee98c4a5SJohn Baldwin 	 * We shouldn't mask off other bits here.
430ee98c4a5SJohn Baldwin 	 */
431ee98c4a5SJohn Baldwin 	hdr->PageType &= ~MPI_CONFIG_PAGETYPE_MASK;
432ee98c4a5SJohn Baldwin #endif
433ee98c4a5SJohn Baldwin 
434ee98c4a5SJohn Baldwin 	req = mpt_get_request(mpt, TRUE);
435ee98c4a5SJohn Baldwin 	if (req == NULL)
436ee98c4a5SJohn Baldwin 		return (ENOMEM);
437ee98c4a5SJohn Baldwin 
4384124f62eSJohn Baldwin 	bus_dmamap_sync(mpt_page->tag, mpt_page->map, BUS_DMASYNC_PREWRITE);
439ee98c4a5SJohn Baldwin 
440ee98c4a5SJohn Baldwin 	/*
441ee98c4a5SJohn Baldwin 	 * There isn't any point in restoring stripped out attributes
442ee98c4a5SJohn Baldwin 	 * if you then mask them going down to issue the request.
443ee98c4a5SJohn Baldwin 	 */
444ee98c4a5SJohn Baldwin 
445ee98c4a5SJohn Baldwin 	params.Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
446ee98c4a5SJohn Baldwin 	params.PageVersion = hdr->PageVersion;
447ee98c4a5SJohn Baldwin 	params.PageLength = hdr->PageLength;
448ee98c4a5SJohn Baldwin 	params.PageNumber = hdr->PageNumber;
4497ee37807SMarius Strobl 	params.PageAddress = le32toh(page_req->page_address);
450ee98c4a5SJohn Baldwin #if	0
451ee98c4a5SJohn Baldwin 	/* Restore stripped out attributes */
452ee98c4a5SJohn Baldwin 	hdr->PageType |= hdr_attr;
453ee98c4a5SJohn Baldwin 	params.PageType = hdr->PageType & MPI_CONFIG_PAGETYPE_MASK;
454ee98c4a5SJohn Baldwin #else
455ee98c4a5SJohn Baldwin 	params.PageType = hdr->PageType;
456ee98c4a5SJohn Baldwin #endif
4574124f62eSJohn Baldwin 	error = mpt_issue_cfg_req(mpt, req, &params, mpt_page->paddr,
4587ee37807SMarius Strobl 	    le32toh(page_req->len), TRUE, 5000);
459ee98c4a5SJohn Baldwin 	if (error != 0) {
460ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_write_cfg_page timed out\n");
461ee98c4a5SJohn Baldwin 		return (ETIMEDOUT);
462ee98c4a5SJohn Baldwin 	}
463ee98c4a5SJohn Baldwin 
4647ee37807SMarius Strobl 	page_req->ioc_status = htole16(req->IOCStatus);
465ee98c4a5SJohn Baldwin 	mpt_free_request(mpt, req);
466ee98c4a5SJohn Baldwin 	return (0);
467ee98c4a5SJohn Baldwin }
468ee98c4a5SJohn Baldwin 
469ee98c4a5SJohn Baldwin static int
470ee98c4a5SJohn Baldwin mpt_user_reply_handler(struct mpt_softc *mpt, request_t *req,
471ee98c4a5SJohn Baldwin     uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
472ee98c4a5SJohn Baldwin {
473ee98c4a5SJohn Baldwin 	MSG_RAID_ACTION_REPLY *reply;
474ee98c4a5SJohn Baldwin 	struct mpt_user_raid_action_result *res;
475ee98c4a5SJohn Baldwin 
476ee98c4a5SJohn Baldwin 	if (req == NULL)
477ee98c4a5SJohn Baldwin 		return (TRUE);
478ee98c4a5SJohn Baldwin 
479ee98c4a5SJohn Baldwin 	if (reply_frame != NULL) {
480ee98c4a5SJohn Baldwin 		bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
481ee98c4a5SJohn Baldwin 		    BUS_DMASYNC_POSTREAD);
482ee98c4a5SJohn Baldwin 		reply = (MSG_RAID_ACTION_REPLY *)reply_frame;
483ee98c4a5SJohn Baldwin 		req->IOCStatus = le16toh(reply->IOCStatus);
484ee98c4a5SJohn Baldwin 		res = (struct mpt_user_raid_action_result *)
485ee98c4a5SJohn Baldwin 		    (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt));
486ee98c4a5SJohn Baldwin 		res->action_status = reply->ActionStatus;
487ee98c4a5SJohn Baldwin 		res->volume_status = reply->VolumeStatus;
488ee98c4a5SJohn Baldwin 		bcopy(&reply->ActionData, res->action_data,
489ee98c4a5SJohn Baldwin 		    sizeof(res->action_data));
490ee98c4a5SJohn Baldwin 	}
491ee98c4a5SJohn Baldwin 
492ee98c4a5SJohn Baldwin 	req->state &= ~REQ_STATE_QUEUED;
493ee98c4a5SJohn Baldwin 	req->state |= REQ_STATE_DONE;
494ee98c4a5SJohn Baldwin 	TAILQ_REMOVE(&mpt->request_pending_list, req, links);
495ee98c4a5SJohn Baldwin 
496ee98c4a5SJohn Baldwin 	if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
497ee98c4a5SJohn Baldwin 		wakeup(req);
498ee98c4a5SJohn Baldwin 	} else if ((req->state & REQ_STATE_TIMEDOUT) != 0) {
499ee98c4a5SJohn Baldwin 		/*
500ee98c4a5SJohn Baldwin 		 * Whew- we can free this request (late completion)
501ee98c4a5SJohn Baldwin 		 */
502ee98c4a5SJohn Baldwin 		mpt_free_request(mpt, req);
503ee98c4a5SJohn Baldwin 	}
504ee98c4a5SJohn Baldwin 
505ee98c4a5SJohn Baldwin 	return (TRUE);
506ee98c4a5SJohn Baldwin }
507ee98c4a5SJohn Baldwin 
508ee98c4a5SJohn Baldwin /*
509ee98c4a5SJohn Baldwin  * We use the first part of the request buffer after the request frame
510ee98c4a5SJohn Baldwin  * to hold the action data and action status from the RAID reply.  The
511ee98c4a5SJohn Baldwin  * rest of the request buffer is used to hold the buffer for the
512ee98c4a5SJohn Baldwin  * action SGE.
513ee98c4a5SJohn Baldwin  */
514ee98c4a5SJohn Baldwin static int
515ee98c4a5SJohn Baldwin mpt_user_raid_action(struct mpt_softc *mpt, struct mpt_raid_action *raid_act,
5164124f62eSJohn Baldwin 	struct mpt_page_memory *mpt_page)
517ee98c4a5SJohn Baldwin {
518ee98c4a5SJohn Baldwin 	request_t *req;
519ee98c4a5SJohn Baldwin 	struct mpt_user_raid_action_result *res;
520ee98c4a5SJohn Baldwin 	MSG_RAID_ACTION_REQUEST *rap;
521ee98c4a5SJohn Baldwin 	SGE_SIMPLE32 *se;
522ee98c4a5SJohn Baldwin 	int error;
523ee98c4a5SJohn Baldwin 
524ee98c4a5SJohn Baldwin 	req = mpt_get_request(mpt, TRUE);
525ee98c4a5SJohn Baldwin 	if (req == NULL)
526ee98c4a5SJohn Baldwin 		return (ENOMEM);
527ee98c4a5SJohn Baldwin 	rap = req->req_vbuf;
528ee98c4a5SJohn Baldwin 	memset(rap, 0, sizeof *rap);
529ee98c4a5SJohn Baldwin 	rap->Action = raid_act->action;
530ee98c4a5SJohn Baldwin 	rap->ActionDataWord = raid_act->action_data_word;
531ee98c4a5SJohn Baldwin 	rap->Function = MPI_FUNCTION_RAID_ACTION;
532ee98c4a5SJohn Baldwin 	rap->VolumeID = raid_act->volume_id;
533ee98c4a5SJohn Baldwin 	rap->VolumeBus = raid_act->volume_bus;
534ee98c4a5SJohn Baldwin 	rap->PhysDiskNum = raid_act->phys_disk_num;
535ee98c4a5SJohn Baldwin 	se = (SGE_SIMPLE32 *)&rap->ActionDataSGE;
5364124f62eSJohn Baldwin 	if (mpt_page->vaddr != NULL && raid_act->len != 0) {
5374124f62eSJohn Baldwin 		bus_dmamap_sync(mpt_page->tag, mpt_page->map,
5384124f62eSJohn Baldwin 		    BUS_DMASYNC_PREWRITE);
5397ee37807SMarius Strobl 		se->Address = htole32(mpt_page->paddr);
5407ee37807SMarius Strobl 		MPI_pSGE_SET_LENGTH(se, le32toh(raid_act->len));
541ee98c4a5SJohn Baldwin 		MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
542ee98c4a5SJohn Baldwin 		    MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
543ee98c4a5SJohn Baldwin 		    MPI_SGE_FLAGS_END_OF_LIST |
544ee98c4a5SJohn Baldwin 		    raid_act->write ? MPI_SGE_FLAGS_HOST_TO_IOC :
545ee98c4a5SJohn Baldwin 		    MPI_SGE_FLAGS_IOC_TO_HOST));
546ee98c4a5SJohn Baldwin 	}
5477ee37807SMarius Strobl 	se->FlagsLength = htole32(se->FlagsLength);
548ee98c4a5SJohn Baldwin 	rap->MsgContext = htole32(req->index | user_handler_id);
549ee98c4a5SJohn Baldwin 
550ee98c4a5SJohn Baldwin 	mpt_check_doorbell(mpt);
551ee98c4a5SJohn Baldwin 	mpt_send_cmd(mpt, req);
552ee98c4a5SJohn Baldwin 
553ee98c4a5SJohn Baldwin 	error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, TRUE,
554ee98c4a5SJohn Baldwin 	    2000);
555ee98c4a5SJohn Baldwin 	if (error != 0) {
556ee98c4a5SJohn Baldwin 		/*
557ee98c4a5SJohn Baldwin 		 * Leave request so it can be cleaned up later.
558ee98c4a5SJohn Baldwin 		 */
559ee98c4a5SJohn Baldwin 		mpt_prt(mpt, "mpt_user_raid_action timed out\n");
560ee98c4a5SJohn Baldwin 		return (error);
561ee98c4a5SJohn Baldwin 	}
562ee98c4a5SJohn Baldwin 
5637ee37807SMarius Strobl 	raid_act->ioc_status = htole16(req->IOCStatus);
564ee98c4a5SJohn Baldwin 	if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
565ee98c4a5SJohn Baldwin 		mpt_free_request(mpt, req);
566ee98c4a5SJohn Baldwin 		return (0);
567ee98c4a5SJohn Baldwin 	}
568ee98c4a5SJohn Baldwin 
569ee98c4a5SJohn Baldwin 	res = (struct mpt_user_raid_action_result *)
570ee98c4a5SJohn Baldwin 	    (((uint8_t *)req->req_vbuf) + MPT_RQSL(mpt));
571ee98c4a5SJohn Baldwin 	raid_act->volume_status = res->volume_status;
572ee98c4a5SJohn Baldwin 	raid_act->action_status = res->action_status;
573ee98c4a5SJohn Baldwin 	bcopy(res->action_data, raid_act->action_data,
574ee98c4a5SJohn Baldwin 	    sizeof(res->action_data));
5754124f62eSJohn Baldwin 	if (mpt_page->vaddr != NULL)
5764124f62eSJohn Baldwin 		bus_dmamap_sync(mpt_page->tag, mpt_page->map,
5774124f62eSJohn Baldwin 		    BUS_DMASYNC_POSTREAD);
578ee98c4a5SJohn Baldwin 	mpt_free_request(mpt, req);
579ee98c4a5SJohn Baldwin 	return (0);
580ee98c4a5SJohn Baldwin }
581ee98c4a5SJohn Baldwin 
582ee98c4a5SJohn Baldwin #ifdef __amd64__
583ee98c4a5SJohn Baldwin #define	PTRIN(p)		((void *)(uintptr_t)(p))
584ee98c4a5SJohn Baldwin #define PTROUT(v)		((u_int32_t)(uintptr_t)(v))
585ee98c4a5SJohn Baldwin #endif
586ee98c4a5SJohn Baldwin 
587ee98c4a5SJohn Baldwin static int
588ee98c4a5SJohn Baldwin mpt_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
589ee98c4a5SJohn Baldwin {
590ee98c4a5SJohn Baldwin 	struct mpt_softc *mpt;
591ee98c4a5SJohn Baldwin 	struct mpt_cfg_page_req *page_req;
592ee98c4a5SJohn Baldwin 	struct mpt_ext_cfg_page_req *ext_page_req;
593ee98c4a5SJohn Baldwin 	struct mpt_raid_action *raid_act;
5944124f62eSJohn Baldwin 	struct mpt_page_memory mpt_page;
595ee98c4a5SJohn Baldwin #ifdef __amd64__
596ee98c4a5SJohn Baldwin 	struct mpt_cfg_page_req32 *page_req32;
597ee98c4a5SJohn Baldwin 	struct mpt_cfg_page_req page_req_swab;
598ee98c4a5SJohn Baldwin 	struct mpt_ext_cfg_page_req32 *ext_page_req32;
599ee98c4a5SJohn Baldwin 	struct mpt_ext_cfg_page_req ext_page_req_swab;
600ee98c4a5SJohn Baldwin 	struct mpt_raid_action32 *raid_act32;
601ee98c4a5SJohn Baldwin 	struct mpt_raid_action raid_act_swab;
602ee98c4a5SJohn Baldwin #endif
603ee98c4a5SJohn Baldwin 	int error;
604ee98c4a5SJohn Baldwin 
605ee98c4a5SJohn Baldwin 	mpt = dev->si_drv1;
606ee98c4a5SJohn Baldwin 	page_req = (void *)arg;
607ee98c4a5SJohn Baldwin 	ext_page_req = (void *)arg;
608ee98c4a5SJohn Baldwin 	raid_act = (void *)arg;
6094124f62eSJohn Baldwin 	mpt_page.vaddr = NULL;
610ee98c4a5SJohn Baldwin 
611ee98c4a5SJohn Baldwin #ifdef __amd64__
612ee98c4a5SJohn Baldwin 	/* Convert 32-bit structs to native ones. */
613ee98c4a5SJohn Baldwin 	page_req32 = (void *)arg;
614ee98c4a5SJohn Baldwin 	ext_page_req32 = (void *)arg;
615ee98c4a5SJohn Baldwin 	raid_act32 = (void *)arg;
616ee98c4a5SJohn Baldwin 	switch (cmd) {
617ee98c4a5SJohn Baldwin 	case MPTIO_READ_CFG_HEADER32:
618ee98c4a5SJohn Baldwin 	case MPTIO_READ_CFG_PAGE32:
619ee98c4a5SJohn Baldwin 	case MPTIO_WRITE_CFG_PAGE32:
620ee98c4a5SJohn Baldwin 		page_req = &page_req_swab;
621ee98c4a5SJohn Baldwin 		page_req->header = page_req32->header;
622ee98c4a5SJohn Baldwin 		page_req->page_address = page_req32->page_address;
623ee98c4a5SJohn Baldwin 		page_req->buf = PTRIN(page_req32->buf);
624ee98c4a5SJohn Baldwin 		page_req->len = page_req32->len;
625ee98c4a5SJohn Baldwin 		page_req->ioc_status = page_req32->ioc_status;
626ee98c4a5SJohn Baldwin 		break;
627ee98c4a5SJohn Baldwin 	case MPTIO_READ_EXT_CFG_HEADER32:
628ee98c4a5SJohn Baldwin 	case MPTIO_READ_EXT_CFG_PAGE32:
629ee98c4a5SJohn Baldwin 		ext_page_req = &ext_page_req_swab;
630ee98c4a5SJohn Baldwin 		ext_page_req->header = ext_page_req32->header;
631ee98c4a5SJohn Baldwin 		ext_page_req->page_address = ext_page_req32->page_address;
632ee98c4a5SJohn Baldwin 		ext_page_req->buf = PTRIN(ext_page_req32->buf);
633ee98c4a5SJohn Baldwin 		ext_page_req->len = ext_page_req32->len;
634ee98c4a5SJohn Baldwin 		ext_page_req->ioc_status = ext_page_req32->ioc_status;
635ee98c4a5SJohn Baldwin 		break;
636ee98c4a5SJohn Baldwin 	case MPTIO_RAID_ACTION32:
637ee98c4a5SJohn Baldwin 		raid_act = &raid_act_swab;
638ee98c4a5SJohn Baldwin 		raid_act->action = raid_act32->action;
639ee98c4a5SJohn Baldwin 		raid_act->volume_bus = raid_act32->volume_bus;
640ee98c4a5SJohn Baldwin 		raid_act->volume_id = raid_act32->volume_id;
641ee98c4a5SJohn Baldwin 		raid_act->phys_disk_num = raid_act32->phys_disk_num;
642ee98c4a5SJohn Baldwin 		raid_act->action_data_word = raid_act32->action_data_word;
643ee98c4a5SJohn Baldwin 		raid_act->buf = PTRIN(raid_act32->buf);
644ee98c4a5SJohn Baldwin 		raid_act->len = raid_act32->len;
645ee98c4a5SJohn Baldwin 		raid_act->volume_status = raid_act32->volume_status;
646ee98c4a5SJohn Baldwin 		bcopy(raid_act32->action_data, raid_act->action_data,
647ee98c4a5SJohn Baldwin 		    sizeof(raid_act->action_data));
648ee98c4a5SJohn Baldwin 		raid_act->action_status = raid_act32->action_status;
649ee98c4a5SJohn Baldwin 		raid_act->ioc_status = raid_act32->ioc_status;
650ee98c4a5SJohn Baldwin 		raid_act->write = raid_act32->write;
651ee98c4a5SJohn Baldwin 		break;
652ee98c4a5SJohn Baldwin 	}
653ee98c4a5SJohn Baldwin #endif
654ee98c4a5SJohn Baldwin 
655ee98c4a5SJohn Baldwin 	switch (cmd) {
656ee98c4a5SJohn Baldwin #ifdef __amd64__
657ee98c4a5SJohn Baldwin 	case MPTIO_READ_CFG_HEADER32:
658ee98c4a5SJohn Baldwin #endif
659ee98c4a5SJohn Baldwin 	case MPTIO_READ_CFG_HEADER:
660ee98c4a5SJohn Baldwin 		MPT_LOCK(mpt);
661ee98c4a5SJohn Baldwin 		error = mpt_user_read_cfg_header(mpt, page_req);
662ee98c4a5SJohn Baldwin 		MPT_UNLOCK(mpt);
663ee98c4a5SJohn Baldwin 		break;
664ee98c4a5SJohn Baldwin #ifdef __amd64__
665ee98c4a5SJohn Baldwin 	case MPTIO_READ_CFG_PAGE32:
666ee98c4a5SJohn Baldwin #endif
667ee98c4a5SJohn Baldwin 	case MPTIO_READ_CFG_PAGE:
6684124f62eSJohn Baldwin 		error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len);
6694124f62eSJohn Baldwin 		if (error)
670ee98c4a5SJohn Baldwin 			break;
6714124f62eSJohn Baldwin 		error = copyin(page_req->buf, mpt_page.vaddr,
672ee98c4a5SJohn Baldwin 		    sizeof(CONFIG_PAGE_HEADER));
673ee98c4a5SJohn Baldwin 		if (error)
674ee98c4a5SJohn Baldwin 			break;
675ee98c4a5SJohn Baldwin 		MPT_LOCK(mpt);
6764124f62eSJohn Baldwin 		error = mpt_user_read_cfg_page(mpt, page_req, &mpt_page);
677ee98c4a5SJohn Baldwin 		MPT_UNLOCK(mpt);
678ee98c4a5SJohn Baldwin 		if (error)
679ee98c4a5SJohn Baldwin 			break;
6804124f62eSJohn Baldwin 		error = copyout(mpt_page.vaddr, page_req->buf, page_req->len);
681ee98c4a5SJohn Baldwin 		break;
682ee98c4a5SJohn Baldwin #ifdef __amd64__
683ee98c4a5SJohn Baldwin 	case MPTIO_READ_EXT_CFG_HEADER32:
684ee98c4a5SJohn Baldwin #endif
685ee98c4a5SJohn Baldwin 	case MPTIO_READ_EXT_CFG_HEADER:
686ee98c4a5SJohn Baldwin 		MPT_LOCK(mpt);
687ee98c4a5SJohn Baldwin 		error = mpt_user_read_extcfg_header(mpt, ext_page_req);
688ee98c4a5SJohn Baldwin 		MPT_UNLOCK(mpt);
689ee98c4a5SJohn Baldwin 		break;
690ee98c4a5SJohn Baldwin #ifdef __amd64__
691ee98c4a5SJohn Baldwin 	case MPTIO_READ_EXT_CFG_PAGE32:
692ee98c4a5SJohn Baldwin #endif
693ee98c4a5SJohn Baldwin 	case MPTIO_READ_EXT_CFG_PAGE:
6944124f62eSJohn Baldwin 		error = mpt_alloc_buffer(mpt, &mpt_page, ext_page_req->len);
6954124f62eSJohn Baldwin 		if (error)
696ee98c4a5SJohn Baldwin 			break;
6974124f62eSJohn Baldwin 		error = copyin(ext_page_req->buf, mpt_page.vaddr,
698ee98c4a5SJohn Baldwin 		    sizeof(CONFIG_EXTENDED_PAGE_HEADER));
699ee98c4a5SJohn Baldwin 		if (error)
700ee98c4a5SJohn Baldwin 			break;
701ee98c4a5SJohn Baldwin 		MPT_LOCK(mpt);
7024124f62eSJohn Baldwin 		error = mpt_user_read_extcfg_page(mpt, ext_page_req, &mpt_page);
703ee98c4a5SJohn Baldwin 		MPT_UNLOCK(mpt);
704ee98c4a5SJohn Baldwin 		if (error)
705ee98c4a5SJohn Baldwin 			break;
7064124f62eSJohn Baldwin 		error = copyout(mpt_page.vaddr, ext_page_req->buf,
7074124f62eSJohn Baldwin 		    ext_page_req->len);
708ee98c4a5SJohn Baldwin 		break;
709ee98c4a5SJohn Baldwin #ifdef __amd64__
710ee98c4a5SJohn Baldwin 	case MPTIO_WRITE_CFG_PAGE32:
711ee98c4a5SJohn Baldwin #endif
712ee98c4a5SJohn Baldwin 	case MPTIO_WRITE_CFG_PAGE:
7134124f62eSJohn Baldwin 		error = mpt_alloc_buffer(mpt, &mpt_page, page_req->len);
7144124f62eSJohn Baldwin 		if (error)
715ee98c4a5SJohn Baldwin 			break;
7164124f62eSJohn Baldwin 		error = copyin(page_req->buf, mpt_page.vaddr, page_req->len);
717ee98c4a5SJohn Baldwin 		if (error)
718ee98c4a5SJohn Baldwin 			break;
719ee98c4a5SJohn Baldwin 		MPT_LOCK(mpt);
7204124f62eSJohn Baldwin 		error = mpt_user_write_cfg_page(mpt, page_req, &mpt_page);
721ee98c4a5SJohn Baldwin 		MPT_UNLOCK(mpt);
722ee98c4a5SJohn Baldwin 		break;
723ee98c4a5SJohn Baldwin #ifdef __amd64__
724ee98c4a5SJohn Baldwin 	case MPTIO_RAID_ACTION32:
725ee98c4a5SJohn Baldwin #endif
726ee98c4a5SJohn Baldwin 	case MPTIO_RAID_ACTION:
727ee98c4a5SJohn Baldwin 		if (raid_act->buf != NULL) {
7284124f62eSJohn Baldwin 			error = mpt_alloc_buffer(mpt, &mpt_page, raid_act->len);
7294124f62eSJohn Baldwin 			if (error)
730ee98c4a5SJohn Baldwin 				break;
7314124f62eSJohn Baldwin 			error = copyin(raid_act->buf, mpt_page.vaddr,
7324124f62eSJohn Baldwin 			    raid_act->len);
733ee98c4a5SJohn Baldwin 			if (error)
734ee98c4a5SJohn Baldwin 				break;
735ee98c4a5SJohn Baldwin 		}
736ee98c4a5SJohn Baldwin 		MPT_LOCK(mpt);
7374124f62eSJohn Baldwin 		error = mpt_user_raid_action(mpt, raid_act, &mpt_page);
738ee98c4a5SJohn Baldwin 		MPT_UNLOCK(mpt);
739ee98c4a5SJohn Baldwin 		if (error)
740ee98c4a5SJohn Baldwin 			break;
7414124f62eSJohn Baldwin 		if (raid_act->buf != NULL)
7424124f62eSJohn Baldwin 			error = copyout(mpt_page.vaddr, raid_act->buf,
7434124f62eSJohn Baldwin 			    raid_act->len);
744ee98c4a5SJohn Baldwin 		break;
745ee98c4a5SJohn Baldwin 	default:
746ee98c4a5SJohn Baldwin 		error = ENOIOCTL;
747ee98c4a5SJohn Baldwin 		break;
748ee98c4a5SJohn Baldwin 	}
749ee98c4a5SJohn Baldwin 
7504124f62eSJohn Baldwin 	mpt_free_buffer(&mpt_page);
751ee98c4a5SJohn Baldwin 
752ee98c4a5SJohn Baldwin 	if (error)
753ee98c4a5SJohn Baldwin 		return (error);
754ee98c4a5SJohn Baldwin 
755ee98c4a5SJohn Baldwin #ifdef __amd64__
756ee98c4a5SJohn Baldwin 	/* Convert native structs to 32-bit ones. */
757ee98c4a5SJohn Baldwin 	switch (cmd) {
758ee98c4a5SJohn Baldwin 	case MPTIO_READ_CFG_HEADER32:
759ee98c4a5SJohn Baldwin 	case MPTIO_READ_CFG_PAGE32:
760ee98c4a5SJohn Baldwin 	case MPTIO_WRITE_CFG_PAGE32:
761ee98c4a5SJohn Baldwin 		page_req32->header = page_req->header;
762ee98c4a5SJohn Baldwin 		page_req32->page_address = page_req->page_address;
763ee98c4a5SJohn Baldwin 		page_req32->buf = PTROUT(page_req->buf);
764ee98c4a5SJohn Baldwin 		page_req32->len = page_req->len;
765ee98c4a5SJohn Baldwin 		page_req32->ioc_status = page_req->ioc_status;
766ee98c4a5SJohn Baldwin 		break;
767ee98c4a5SJohn Baldwin 	case MPTIO_READ_EXT_CFG_HEADER32:
768ee98c4a5SJohn Baldwin 	case MPTIO_READ_EXT_CFG_PAGE32:
769ee98c4a5SJohn Baldwin 		ext_page_req32->header = ext_page_req->header;
770ee98c4a5SJohn Baldwin 		ext_page_req32->page_address = ext_page_req->page_address;
771ee98c4a5SJohn Baldwin 		ext_page_req32->buf = PTROUT(ext_page_req->buf);
772ee98c4a5SJohn Baldwin 		ext_page_req32->len = ext_page_req->len;
773ee98c4a5SJohn Baldwin 		ext_page_req32->ioc_status = ext_page_req->ioc_status;
774ee98c4a5SJohn Baldwin 		break;
775ee98c4a5SJohn Baldwin 	case MPTIO_RAID_ACTION32:
776ee98c4a5SJohn Baldwin 		raid_act32->action = raid_act->action;
777ee98c4a5SJohn Baldwin 		raid_act32->volume_bus = raid_act->volume_bus;
778ee98c4a5SJohn Baldwin 		raid_act32->volume_id = raid_act->volume_id;
779ee98c4a5SJohn Baldwin 		raid_act32->phys_disk_num = raid_act->phys_disk_num;
780ee98c4a5SJohn Baldwin 		raid_act32->action_data_word = raid_act->action_data_word;
781ee98c4a5SJohn Baldwin 		raid_act32->buf = PTROUT(raid_act->buf);
782ee98c4a5SJohn Baldwin 		raid_act32->len = raid_act->len;
783ee98c4a5SJohn Baldwin 		raid_act32->volume_status = raid_act->volume_status;
784ee98c4a5SJohn Baldwin 		bcopy(raid_act->action_data, raid_act32->action_data,
785ee98c4a5SJohn Baldwin 		    sizeof(raid_act->action_data));
786ee98c4a5SJohn Baldwin 		raid_act32->action_status = raid_act->action_status;
787ee98c4a5SJohn Baldwin 		raid_act32->ioc_status = raid_act->ioc_status;
788ee98c4a5SJohn Baldwin 		raid_act32->write = raid_act->write;
789ee98c4a5SJohn Baldwin 		break;
790ee98c4a5SJohn Baldwin 	}
791ee98c4a5SJohn Baldwin #endif
792ee98c4a5SJohn Baldwin 
793ee98c4a5SJohn Baldwin 	return (0);
794ee98c4a5SJohn Baldwin }
795