xref: /freebsd/sys/compat/freebsd32/freebsd32_ioctl.c (revision 51369649b03ece2aed3eb61b0c8214b9aa5b2fa2)
1ae528485SDavid E. O'Brien /*-
2*51369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3*51369649SPedro F. Giffuni  *
4ae528485SDavid E. O'Brien  * Copyright (c) 2008 David E. O'Brien
5ae528485SDavid E. O'Brien  * All rights reserved.
6ae528485SDavid E. O'Brien  *
7ae528485SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
8ae528485SDavid E. O'Brien  * modification, are permitted provided that the following conditions
9ae528485SDavid E. O'Brien  * are met:
10ae528485SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
11ae528485SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
12ae528485SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
13ae528485SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
14ae528485SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
15ae528485SDavid E. O'Brien  * 3. Neither the name of the author nor the names of its contributors
16ae528485SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
17ae528485SDavid E. O'Brien  *    without specific prior written permission.
18ae528485SDavid E. O'Brien  *
19ae528485SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20ae528485SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21ae528485SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22ae528485SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23ae528485SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24ae528485SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25ae528485SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26ae528485SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27ae528485SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28ae528485SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29ae528485SDavid E. O'Brien  * SUCH DAMAGE.
30ae528485SDavid E. O'Brien  */
31ae528485SDavid E. O'Brien 
32ae528485SDavid E. O'Brien #include <sys/cdefs.h>
33ae528485SDavid E. O'Brien __FBSDID("$FreeBSD$");
34ae528485SDavid E. O'Brien 
35ae528485SDavid E. O'Brien #include "opt_compat.h"
36ae528485SDavid E. O'Brien 
37ae528485SDavid E. O'Brien #include <sys/param.h>
384a144410SRobert Watson #include <sys/capsicum.h>
39ae528485SDavid E. O'Brien #include <sys/cdio.h>
40ae528485SDavid E. O'Brien #include <sys/fcntl.h>
417eac36edSEd Schouten #include <sys/filio.h>
42ae528485SDavid E. O'Brien #include <sys/file.h>
43ae528485SDavid E. O'Brien #include <sys/ioccom.h>
44bfac1583SKonstantin Belousov #include <sys/malloc.h>
45ae528485SDavid E. O'Brien #include <sys/mdioctl.h>
46bfac1583SKonstantin Belousov #include <sys/memrange.h>
474ee107ddSKonstantin Belousov #include <sys/pciio.h>
48ae528485SDavid E. O'Brien #include <sys/proc.h>
49ae528485SDavid E. O'Brien #include <sys/syscall.h>
50ae528485SDavid E. O'Brien #include <sys/syscallsubr.h>
51ae528485SDavid E. O'Brien #include <sys/sysctl.h>
52ae528485SDavid E. O'Brien #include <sys/sysent.h>
53ae528485SDavid E. O'Brien #include <sys/sysproto.h>
54ae528485SDavid E. O'Brien #include <sys/systm.h>
55ae528485SDavid E. O'Brien 
56ae528485SDavid E. O'Brien #include <compat/freebsd32/freebsd32.h>
57ae528485SDavid E. O'Brien #include <compat/freebsd32/freebsd32_ioctl.h>
58ae528485SDavid E. O'Brien #include <compat/freebsd32/freebsd32_proto.h>
59ae528485SDavid E. O'Brien 
60f76de5ddSMaxim Sobolev CTASSERT((sizeof(struct md_ioctl32)) == 436);
61c750e17cSDavid E. O'Brien CTASSERT(sizeof(struct ioc_read_toc_entry32) == 8);
62bfac1583SKonstantin Belousov CTASSERT(sizeof(struct mem_range_op32) == 12);
634ee107ddSKonstantin Belousov CTASSERT(sizeof(struct pci_conf_io32) == 36);
644ee107ddSKonstantin Belousov CTASSERT(sizeof(struct pci_match_conf32) == 44);
654ee107ddSKonstantin Belousov CTASSERT(sizeof(struct pci_conf32) == 44);
66ae528485SDavid E. O'Brien 
67ae528485SDavid E. O'Brien 
68ae528485SDavid E. O'Brien static int
69ae528485SDavid E. O'Brien freebsd32_ioctl_md(struct thread *td, struct freebsd32_ioctl_args *uap,
70ae528485SDavid E. O'Brien     struct file *fp)
71ae528485SDavid E. O'Brien {
72ae528485SDavid E. O'Brien 	struct md_ioctl mdv;
73ae528485SDavid E. O'Brien 	struct md_ioctl32 md32;
74ae528485SDavid E. O'Brien 	u_long com = 0;
75bc13c742SKonstantin Belousov 	int i, error;
76ae528485SDavid E. O'Brien 
77ae528485SDavid E. O'Brien 	if (uap->com & IOC_IN) {
78ae528485SDavid E. O'Brien 		if ((error = copyin(uap->data, &md32, sizeof(md32)))) {
79ae528485SDavid E. O'Brien 			return (error);
80ae528485SDavid E. O'Brien 		}
81ae528485SDavid E. O'Brien 		CP(md32, mdv, md_version);
82ae528485SDavid E. O'Brien 		CP(md32, mdv, md_unit);
83ae528485SDavid E. O'Brien 		CP(md32, mdv, md_type);
84ae528485SDavid E. O'Brien 		PTRIN_CP(md32, mdv, md_file);
85ae528485SDavid E. O'Brien 		CP(md32, mdv, md_mediasize);
86ae528485SDavid E. O'Brien 		CP(md32, mdv, md_sectorsize);
87ae528485SDavid E. O'Brien 		CP(md32, mdv, md_options);
88ae528485SDavid E. O'Brien 		CP(md32, mdv, md_base);
89ae528485SDavid E. O'Brien 		CP(md32, mdv, md_fwheads);
90ae528485SDavid E. O'Brien 		CP(md32, mdv, md_fwsectors);
91f76de5ddSMaxim Sobolev 		PTRIN_CP(md32, mdv, md_label);
92ae528485SDavid E. O'Brien 	} else if (uap->com & IOC_OUT) {
93ae528485SDavid E. O'Brien 		/*
94ae528485SDavid E. O'Brien 		 * Zero the buffer so the user always
95ae528485SDavid E. O'Brien 		 * gets back something deterministic.
96ae528485SDavid E. O'Brien 		 */
97ae528485SDavid E. O'Brien 		bzero(&mdv, sizeof mdv);
98ae528485SDavid E. O'Brien 	}
99ae528485SDavid E. O'Brien 
100ae528485SDavid E. O'Brien 	switch (uap->com) {
101ae528485SDavid E. O'Brien 	case MDIOCATTACH_32:
102ae528485SDavid E. O'Brien 		com = MDIOCATTACH;
103ae528485SDavid E. O'Brien 		break;
104ae528485SDavid E. O'Brien 	case MDIOCDETACH_32:
105ae528485SDavid E. O'Brien 		com = MDIOCDETACH;
106ae528485SDavid E. O'Brien 		break;
107ae528485SDavid E. O'Brien 	case MDIOCQUERY_32:
108ae528485SDavid E. O'Brien 		com = MDIOCQUERY;
109ae528485SDavid E. O'Brien 		break;
110ae528485SDavid E. O'Brien 	case MDIOCLIST_32:
111ae528485SDavid E. O'Brien 		com = MDIOCLIST;
112ae528485SDavid E. O'Brien 		break;
113ae528485SDavid E. O'Brien 	default:
114ae528485SDavid E. O'Brien 		panic("%s: unknown MDIOC %#x", __func__, uap->com);
115ae528485SDavid E. O'Brien 	}
116ae528485SDavid E. O'Brien 	error = fo_ioctl(fp, com, (caddr_t)&mdv, td->td_ucred, td);
117ae528485SDavid E. O'Brien 	if (error == 0 && (com & IOC_OUT)) {
118ae528485SDavid E. O'Brien 		CP(mdv, md32, md_version);
119ae528485SDavid E. O'Brien 		CP(mdv, md32, md_unit);
120ae528485SDavid E. O'Brien 		CP(mdv, md32, md_type);
121ae528485SDavid E. O'Brien 		PTROUT_CP(mdv, md32, md_file);
122ae528485SDavid E. O'Brien 		CP(mdv, md32, md_mediasize);
123ae528485SDavid E. O'Brien 		CP(mdv, md32, md_sectorsize);
124ae528485SDavid E. O'Brien 		CP(mdv, md32, md_options);
125ae528485SDavid E. O'Brien 		CP(mdv, md32, md_base);
126ae528485SDavid E. O'Brien 		CP(mdv, md32, md_fwheads);
127ae528485SDavid E. O'Brien 		CP(mdv, md32, md_fwsectors);
128f76de5ddSMaxim Sobolev 		PTROUT_CP(mdv, md32, md_label);
129bc13c742SKonstantin Belousov 		if (com == MDIOCLIST) {
130bc13c742SKonstantin Belousov 			/*
131bc13c742SKonstantin Belousov 			 * Use MDNPAD, and not MDNPAD32.  Padding is
132bc13c742SKonstantin Belousov 			 * allocated and used by compat32 ABI.
133bc13c742SKonstantin Belousov 			 */
134bc13c742SKonstantin Belousov 			for (i = 0; i < MDNPAD; i++)
135bc13c742SKonstantin Belousov 				CP(mdv, md32, md_pad[i]);
136bc13c742SKonstantin Belousov 		}
137ae528485SDavid E. O'Brien 		error = copyout(&md32, uap->data, sizeof(md32));
138ae528485SDavid E. O'Brien 	}
139ae528485SDavid E. O'Brien 	return error;
140ae528485SDavid E. O'Brien }
141ae528485SDavid E. O'Brien 
142ae528485SDavid E. O'Brien 
143c750e17cSDavid E. O'Brien static int
144c750e17cSDavid E. O'Brien freebsd32_ioctl_ioc_read_toc(struct thread *td,
145c750e17cSDavid E. O'Brien     struct freebsd32_ioctl_args *uap, struct file *fp)
146c750e17cSDavid E. O'Brien {
147c750e17cSDavid E. O'Brien 	struct ioc_read_toc_entry toce;
148c750e17cSDavid E. O'Brien 	struct ioc_read_toc_entry32 toce32;
149c750e17cSDavid E. O'Brien 	int error;
150c750e17cSDavid E. O'Brien 
151c750e17cSDavid E. O'Brien 	if ((error = copyin(uap->data, &toce32, sizeof(toce32))))
152c750e17cSDavid E. O'Brien 		return (error);
153c750e17cSDavid E. O'Brien 	CP(toce32, toce, address_format);
154c750e17cSDavid E. O'Brien 	CP(toce32, toce, starting_track);
155c750e17cSDavid E. O'Brien 	CP(toce32, toce, data_len);
156c750e17cSDavid E. O'Brien 	PTRIN_CP(toce32, toce, data);
157c750e17cSDavid E. O'Brien 
158c750e17cSDavid E. O'Brien 	if ((error = fo_ioctl(fp, CDIOREADTOCENTRYS, (caddr_t)&toce,
159c750e17cSDavid E. O'Brien 	    td->td_ucred, td))) {
160c750e17cSDavid E. O'Brien 		CP(toce, toce32, address_format);
161c750e17cSDavid E. O'Brien 		CP(toce, toce32, starting_track);
162c750e17cSDavid E. O'Brien 		CP(toce, toce32, data_len);
163c750e17cSDavid E. O'Brien 		PTROUT_CP(toce, toce32, data);
164c750e17cSDavid E. O'Brien 		error = copyout(&toce32, uap->data, sizeof(toce32));
165c750e17cSDavid E. O'Brien 	}
166c750e17cSDavid E. O'Brien 	return error;
167c750e17cSDavid E. O'Brien }
168c750e17cSDavid E. O'Brien 
1697eac36edSEd Schouten static int
1707eac36edSEd Schouten freebsd32_ioctl_fiodgname(struct thread *td,
1717eac36edSEd Schouten     struct freebsd32_ioctl_args *uap, struct file *fp)
1727eac36edSEd Schouten {
1737eac36edSEd Schouten 	struct fiodgname_arg fgn;
1747eac36edSEd Schouten 	struct fiodgname_arg32 fgn32;
1757eac36edSEd Schouten 	int error;
1767eac36edSEd Schouten 
1777eac36edSEd Schouten 	if ((error = copyin(uap->data, &fgn32, sizeof fgn32)) != 0)
1787eac36edSEd Schouten 		return (error);
1797eac36edSEd Schouten 	CP(fgn32, fgn, len);
1807eac36edSEd Schouten 	PTRIN_CP(fgn32, fgn, buf);
1817eac36edSEd Schouten 	error = fo_ioctl(fp, FIODGNAME, (caddr_t)&fgn, td->td_ucred, td);
1827eac36edSEd Schouten 	return (error);
1837eac36edSEd Schouten }
184c750e17cSDavid E. O'Brien 
185bfac1583SKonstantin Belousov static int
186bfac1583SKonstantin Belousov freebsd32_ioctl_memrange(struct thread *td,
187bfac1583SKonstantin Belousov     struct freebsd32_ioctl_args *uap, struct file *fp)
188bfac1583SKonstantin Belousov {
189bfac1583SKonstantin Belousov 	struct mem_range_op mro;
190bfac1583SKonstantin Belousov 	struct mem_range_op32 mro32;
191bfac1583SKonstantin Belousov 	int error;
192bfac1583SKonstantin Belousov 	u_long com;
193bfac1583SKonstantin Belousov 
194bfac1583SKonstantin Belousov 	if ((error = copyin(uap->data, &mro32, sizeof(mro32))) != 0)
195bfac1583SKonstantin Belousov 		return (error);
196bfac1583SKonstantin Belousov 
197bfac1583SKonstantin Belousov 	PTRIN_CP(mro32, mro, mo_desc);
198bfac1583SKonstantin Belousov 	CP(mro32, mro, mo_arg[0]);
199bfac1583SKonstantin Belousov 	CP(mro32, mro, mo_arg[1]);
200bfac1583SKonstantin Belousov 
201bfac1583SKonstantin Belousov 	com = 0;
202bfac1583SKonstantin Belousov 	switch (uap->com) {
203bfac1583SKonstantin Belousov 	case MEMRANGE_GET32:
204bfac1583SKonstantin Belousov 		com = MEMRANGE_GET;
205bfac1583SKonstantin Belousov 		break;
206bfac1583SKonstantin Belousov 
207bfac1583SKonstantin Belousov 	case MEMRANGE_SET32:
208bfac1583SKonstantin Belousov 		com = MEMRANGE_SET;
209bfac1583SKonstantin Belousov 		break;
210bfac1583SKonstantin Belousov 
211bfac1583SKonstantin Belousov 	default:
212bfac1583SKonstantin Belousov 		panic("%s: unknown MEMRANGE %#x", __func__, uap->com);
213bfac1583SKonstantin Belousov 	}
214bfac1583SKonstantin Belousov 
215bfac1583SKonstantin Belousov 	if ((error = fo_ioctl(fp, com, (caddr_t)&mro, td->td_ucred, td)) != 0)
216bfac1583SKonstantin Belousov 		return (error);
217bfac1583SKonstantin Belousov 
218bfac1583SKonstantin Belousov 	if ( (com & IOC_OUT) ) {
219bfac1583SKonstantin Belousov 		CP(mro, mro32, mo_arg[0]);
220bfac1583SKonstantin Belousov 		CP(mro, mro32, mo_arg[1]);
221bfac1583SKonstantin Belousov 
222bfac1583SKonstantin Belousov 		error = copyout(&mro32, uap->data, sizeof(mro32));
223bfac1583SKonstantin Belousov 	}
224bfac1583SKonstantin Belousov 
225bfac1583SKonstantin Belousov 	return (error);
226bfac1583SKonstantin Belousov }
227bfac1583SKonstantin Belousov 
22878272eedSKonstantin Belousov static int
22978272eedSKonstantin Belousov freebsd32_ioctl_pciocgetconf(struct thread *td,
23078272eedSKonstantin Belousov     struct freebsd32_ioctl_args *uap, struct file *fp)
23178272eedSKonstantin Belousov {
23278272eedSKonstantin Belousov 	struct pci_conf_io pci;
23378272eedSKonstantin Belousov 	struct pci_conf_io32 pci32;
23478272eedSKonstantin Belousov 	struct pci_match_conf32 pmc32;
23578272eedSKonstantin Belousov 	struct pci_match_conf32 *pmc32p;
23678272eedSKonstantin Belousov 	struct pci_match_conf pmc;
23778272eedSKonstantin Belousov 	struct pci_match_conf *pmcp;
23878272eedSKonstantin Belousov 	struct pci_conf32 pc32;
23978272eedSKonstantin Belousov 	struct pci_conf32 *pc32p;
24078272eedSKonstantin Belousov 	struct pci_conf pc;
24178272eedSKonstantin Belousov 	struct pci_conf *pcp;
24278272eedSKonstantin Belousov 	u_int32_t i;
24378272eedSKonstantin Belousov 	u_int32_t npat_to_convert;
24478272eedSKonstantin Belousov 	u_int32_t nmatch_to_convert;
24578272eedSKonstantin Belousov 	vm_offset_t addr;
24678272eedSKonstantin Belousov 	int error;
24778272eedSKonstantin Belousov 
24878272eedSKonstantin Belousov 	if ((error = copyin(uap->data, &pci32, sizeof(pci32))) != 0)
24978272eedSKonstantin Belousov 		return (error);
25078272eedSKonstantin Belousov 
25178272eedSKonstantin Belousov 	CP(pci32, pci, num_patterns);
25278272eedSKonstantin Belousov 	CP(pci32, pci, offset);
25378272eedSKonstantin Belousov 	CP(pci32, pci, generation);
25478272eedSKonstantin Belousov 
25578272eedSKonstantin Belousov 	npat_to_convert = pci32.pat_buf_len / sizeof(struct pci_match_conf32);
25678272eedSKonstantin Belousov 	pci.pat_buf_len = npat_to_convert * sizeof(struct pci_match_conf);
25778272eedSKonstantin Belousov 	pci.patterns = NULL;
25878272eedSKonstantin Belousov 	nmatch_to_convert = pci32.match_buf_len / sizeof(struct pci_conf32);
25978272eedSKonstantin Belousov 	pci.match_buf_len = nmatch_to_convert * sizeof(struct pci_conf);
26078272eedSKonstantin Belousov 	pci.matches = NULL;
26178272eedSKonstantin Belousov 
26278272eedSKonstantin Belousov 	if ((error = copyout_map(td, &addr, pci.pat_buf_len)) != 0)
26378272eedSKonstantin Belousov 		goto cleanup;
26478272eedSKonstantin Belousov 	pci.patterns = (struct pci_match_conf *)addr;
26578272eedSKonstantin Belousov 	if ((error = copyout_map(td, &addr, pci.match_buf_len)) != 0)
26678272eedSKonstantin Belousov 		goto cleanup;
26778272eedSKonstantin Belousov 	pci.matches = (struct pci_conf *)addr;
26878272eedSKonstantin Belousov 
26978272eedSKonstantin Belousov 	npat_to_convert = min(npat_to_convert, pci.num_patterns);
27078272eedSKonstantin Belousov 
27178272eedSKonstantin Belousov 	for (i = 0, pmc32p = (struct pci_match_conf32 *)PTRIN(pci32.patterns),
27278272eedSKonstantin Belousov 	     pmcp = pci.patterns;
27378272eedSKonstantin Belousov 	     i < npat_to_convert; i++, pmc32p++, pmcp++) {
27478272eedSKonstantin Belousov 		if ((error = copyin(pmc32p, &pmc32, sizeof(pmc32))) != 0)
27578272eedSKonstantin Belousov 			goto cleanup;
27678272eedSKonstantin Belousov 		CP(pmc32,pmc,pc_sel);
27778272eedSKonstantin Belousov 		strlcpy(pmc.pd_name, pmc32.pd_name, sizeof(pmc.pd_name));
27878272eedSKonstantin Belousov 		CP(pmc32,pmc,pd_unit);
27978272eedSKonstantin Belousov 		CP(pmc32,pmc,pc_vendor);
28078272eedSKonstantin Belousov 		CP(pmc32,pmc,pc_device);
28178272eedSKonstantin Belousov 		CP(pmc32,pmc,pc_class);
28278272eedSKonstantin Belousov 		CP(pmc32,pmc,flags);
28378272eedSKonstantin Belousov 		if ((error = copyout(&pmc, pmcp, sizeof(pmc))) != 0)
28478272eedSKonstantin Belousov 			goto cleanup;
28578272eedSKonstantin Belousov 	}
28678272eedSKonstantin Belousov 
28778272eedSKonstantin Belousov 	if ((error = fo_ioctl(fp, PCIOCGETCONF, (caddr_t)&pci,
28878272eedSKonstantin Belousov 			      td->td_ucred, td)) != 0)
28978272eedSKonstantin Belousov 		goto cleanup;
29078272eedSKonstantin Belousov 
29178272eedSKonstantin Belousov 	nmatch_to_convert = min(nmatch_to_convert, pci.num_matches);
29278272eedSKonstantin Belousov 
29378272eedSKonstantin Belousov 	for (i = 0, pcp = pci.matches,
29478272eedSKonstantin Belousov 	     pc32p = (struct pci_conf32 *)PTRIN(pci32.matches);
29578272eedSKonstantin Belousov 	     i < nmatch_to_convert; i++, pcp++, pc32p++) {
29678272eedSKonstantin Belousov 		if ((error = copyin(pcp, &pc, sizeof(pc))) != 0)
29778272eedSKonstantin Belousov 			goto cleanup;
29878272eedSKonstantin Belousov 		CP(pc,pc32,pc_sel);
29978272eedSKonstantin Belousov 		CP(pc,pc32,pc_hdr);
30078272eedSKonstantin Belousov 		CP(pc,pc32,pc_subvendor);
30178272eedSKonstantin Belousov 		CP(pc,pc32,pc_subdevice);
30278272eedSKonstantin Belousov 		CP(pc,pc32,pc_vendor);
30378272eedSKonstantin Belousov 		CP(pc,pc32,pc_device);
30478272eedSKonstantin Belousov 		CP(pc,pc32,pc_class);
30578272eedSKonstantin Belousov 		CP(pc,pc32,pc_subclass);
30678272eedSKonstantin Belousov 		CP(pc,pc32,pc_progif);
30778272eedSKonstantin Belousov 		CP(pc,pc32,pc_revid);
30878272eedSKonstantin Belousov 		strlcpy(pc32.pd_name, pc.pd_name, sizeof(pc32.pd_name));
30978272eedSKonstantin Belousov 		CP(pc,pc32,pd_unit);
31078272eedSKonstantin Belousov 		if ((error = copyout(&pc32, pc32p, sizeof(pc32))) != 0)
31178272eedSKonstantin Belousov 			goto cleanup;
31278272eedSKonstantin Belousov 	}
31378272eedSKonstantin Belousov 
31478272eedSKonstantin Belousov 	CP(pci, pci32, num_matches);
31578272eedSKonstantin Belousov 	CP(pci, pci32, offset);
31678272eedSKonstantin Belousov 	CP(pci, pci32, generation);
31778272eedSKonstantin Belousov 	CP(pci, pci32, status);
31878272eedSKonstantin Belousov 
31978272eedSKonstantin Belousov 	error = copyout(&pci32, uap->data, sizeof(pci32));
32078272eedSKonstantin Belousov 
32178272eedSKonstantin Belousov cleanup:
32278272eedSKonstantin Belousov 	if (pci.patterns)
32378272eedSKonstantin Belousov 		copyout_unmap(td, (vm_offset_t)pci.patterns, pci.pat_buf_len);
32478272eedSKonstantin Belousov 	if (pci.matches)
32578272eedSKonstantin Belousov 		copyout_unmap(td, (vm_offset_t)pci.matches, pci.match_buf_len);
32678272eedSKonstantin Belousov 
32778272eedSKonstantin Belousov 	return (error);
32878272eedSKonstantin Belousov }
32978272eedSKonstantin Belousov 
330fcaf473cSAlexander Motin static int
331fcaf473cSAlexander Motin freebsd32_ioctl_sg(struct thread *td,
332fcaf473cSAlexander Motin     struct freebsd32_ioctl_args *uap, struct file *fp)
333fcaf473cSAlexander Motin {
334fcaf473cSAlexander Motin 	struct sg_io_hdr io;
335fcaf473cSAlexander Motin 	struct sg_io_hdr32 io32;
336fcaf473cSAlexander Motin 	int error;
337fcaf473cSAlexander Motin 
338fcaf473cSAlexander Motin 	if ((error = copyin(uap->data, &io32, sizeof(io32))) != 0)
339fcaf473cSAlexander Motin 		return (error);
340fcaf473cSAlexander Motin 
341fcaf473cSAlexander Motin 	CP(io32, io, interface_id);
342fcaf473cSAlexander Motin 	CP(io32, io, dxfer_direction);
343fcaf473cSAlexander Motin 	CP(io32, io, cmd_len);
344fcaf473cSAlexander Motin 	CP(io32, io, mx_sb_len);
345fcaf473cSAlexander Motin 	CP(io32, io, iovec_count);
346fcaf473cSAlexander Motin 	CP(io32, io, dxfer_len);
347fcaf473cSAlexander Motin 	PTRIN_CP(io32, io, dxferp);
348fcaf473cSAlexander Motin 	PTRIN_CP(io32, io, cmdp);
349fcaf473cSAlexander Motin 	PTRIN_CP(io32, io, sbp);
350fcaf473cSAlexander Motin 	CP(io32, io, timeout);
351fcaf473cSAlexander Motin 	CP(io32, io, flags);
352fcaf473cSAlexander Motin 	CP(io32, io, pack_id);
353fcaf473cSAlexander Motin 	PTRIN_CP(io32, io, usr_ptr);
354fcaf473cSAlexander Motin 	CP(io32, io, status);
355fcaf473cSAlexander Motin 	CP(io32, io, masked_status);
356fcaf473cSAlexander Motin 	CP(io32, io, msg_status);
357fcaf473cSAlexander Motin 	CP(io32, io, sb_len_wr);
358fcaf473cSAlexander Motin 	CP(io32, io, host_status);
359fcaf473cSAlexander Motin 	CP(io32, io, driver_status);
360fcaf473cSAlexander Motin 	CP(io32, io, resid);
361fcaf473cSAlexander Motin 	CP(io32, io, duration);
362fcaf473cSAlexander Motin 	CP(io32, io, info);
363fcaf473cSAlexander Motin 
364fcaf473cSAlexander Motin 	if ((error = fo_ioctl(fp, SG_IO, (caddr_t)&io, td->td_ucred, td)) != 0)
365fcaf473cSAlexander Motin 		return (error);
366fcaf473cSAlexander Motin 
367fcaf473cSAlexander Motin 	CP(io, io32, interface_id);
368fcaf473cSAlexander Motin 	CP(io, io32, dxfer_direction);
369fcaf473cSAlexander Motin 	CP(io, io32, cmd_len);
370fcaf473cSAlexander Motin 	CP(io, io32, mx_sb_len);
371fcaf473cSAlexander Motin 	CP(io, io32, iovec_count);
372fcaf473cSAlexander Motin 	CP(io, io32, dxfer_len);
373fcaf473cSAlexander Motin 	PTROUT_CP(io, io32, dxferp);
374fcaf473cSAlexander Motin 	PTROUT_CP(io, io32, cmdp);
375fcaf473cSAlexander Motin 	PTROUT_CP(io, io32, sbp);
376fcaf473cSAlexander Motin 	CP(io, io32, timeout);
377fcaf473cSAlexander Motin 	CP(io, io32, flags);
378fcaf473cSAlexander Motin 	CP(io, io32, pack_id);
379fcaf473cSAlexander Motin 	PTROUT_CP(io, io32, usr_ptr);
380fcaf473cSAlexander Motin 	CP(io, io32, status);
381fcaf473cSAlexander Motin 	CP(io, io32, masked_status);
382fcaf473cSAlexander Motin 	CP(io, io32, msg_status);
383fcaf473cSAlexander Motin 	CP(io, io32, sb_len_wr);
384fcaf473cSAlexander Motin 	CP(io, io32, host_status);
385fcaf473cSAlexander Motin 	CP(io, io32, driver_status);
386fcaf473cSAlexander Motin 	CP(io, io32, resid);
387fcaf473cSAlexander Motin 	CP(io, io32, duration);
388fcaf473cSAlexander Motin 	CP(io, io32, info);
389fcaf473cSAlexander Motin 
390fcaf473cSAlexander Motin 	error = copyout(&io32, uap->data, sizeof(io32));
391fcaf473cSAlexander Motin 
392fcaf473cSAlexander Motin 	return (error);
393fcaf473cSAlexander Motin }
394fcaf473cSAlexander Motin 
395ae528485SDavid E. O'Brien int
396ae528485SDavid E. O'Brien freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap)
397ae528485SDavid E. O'Brien {
398ae528485SDavid E. O'Brien 	struct ioctl_args ap /*{
399ae528485SDavid E. O'Brien 		int	fd;
400ae528485SDavid E. O'Brien 		u_long	com;
401ae528485SDavid E. O'Brien 		caddr_t	data;
402ae528485SDavid E. O'Brien 	}*/ ;
403ae528485SDavid E. O'Brien 	struct file *fp;
4047008be5bSPawel Jakub Dawidek 	cap_rights_t rights;
405ae528485SDavid E. O'Brien 	int error;
406ae528485SDavid E. O'Brien 
4077008be5bSPawel Jakub Dawidek 	error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
4087008be5bSPawel Jakub Dawidek 	if (error != 0)
409ae528485SDavid E. O'Brien 		return (error);
410ae528485SDavid E. O'Brien 	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
411ae528485SDavid E. O'Brien 		fdrop(fp, td);
412ae528485SDavid E. O'Brien 		return (EBADF);
413ae528485SDavid E. O'Brien 	}
414ae528485SDavid E. O'Brien 
415ae528485SDavid E. O'Brien 	switch (uap->com) {
416ae528485SDavid E. O'Brien 	case MDIOCATTACH_32:	/* FALLTHROUGH */
417ae528485SDavid E. O'Brien 	case MDIOCDETACH_32:	/* FALLTHROUGH */
418ae528485SDavid E. O'Brien 	case MDIOCQUERY_32:	/* FALLTHROUGH */
419ae528485SDavid E. O'Brien 	case MDIOCLIST_32:
4201e67ebb1SKonstantin Belousov 		error = freebsd32_ioctl_md(td, uap, fp);
4211e67ebb1SKonstantin Belousov 		break;
422ae528485SDavid E. O'Brien 
423c750e17cSDavid E. O'Brien 	case CDIOREADTOCENTRYS_32:
4241e67ebb1SKonstantin Belousov 		error = freebsd32_ioctl_ioc_read_toc(td, uap, fp);
4251e67ebb1SKonstantin Belousov 		break;
426c750e17cSDavid E. O'Brien 
4277eac36edSEd Schouten 	case FIODGNAME_32:
4281e67ebb1SKonstantin Belousov 		error = freebsd32_ioctl_fiodgname(td, uap, fp);
4291e67ebb1SKonstantin Belousov 		break;
4307eac36edSEd Schouten 
431bfac1583SKonstantin Belousov 	case MEMRANGE_GET32:	/* FALLTHROUGH */
432bfac1583SKonstantin Belousov 	case MEMRANGE_SET32:
433bfac1583SKonstantin Belousov 		error = freebsd32_ioctl_memrange(td, uap, fp);
434bfac1583SKonstantin Belousov 		break;
435bfac1583SKonstantin Belousov 
43678272eedSKonstantin Belousov 	case PCIOCGETCONF_32:
43778272eedSKonstantin Belousov 		error = freebsd32_ioctl_pciocgetconf(td, uap, fp);
43878272eedSKonstantin Belousov 		break;
43978272eedSKonstantin Belousov 
440fcaf473cSAlexander Motin 	case SG_IO_32:
441fcaf473cSAlexander Motin 		error = freebsd32_ioctl_sg(td, uap, fp);
442fcaf473cSAlexander Motin 		break;
443fcaf473cSAlexander Motin 
444ae528485SDavid E. O'Brien 	default:
445ae528485SDavid E. O'Brien 		fdrop(fp, td);
446ae528485SDavid E. O'Brien 		ap.fd = uap->fd;
447ae528485SDavid E. O'Brien 		ap.com = uap->com;
448ae528485SDavid E. O'Brien 		PTRIN_CP(*uap, ap, data);
4498451d0ddSKip Macy 		return sys_ioctl(td, &ap);
450ae528485SDavid E. O'Brien 	}
4511e67ebb1SKonstantin Belousov 
4521e67ebb1SKonstantin Belousov 	fdrop(fp, td);
4531e67ebb1SKonstantin Belousov 	return error;
454ae528485SDavid E. O'Brien }
455