xref: /illumos-gate/usr/src/uts/common/io/1394/adapters/hci1394_ioctl.c (revision 2570281cf351044b6936651ce26dbe1f801dcbd8)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * hci1394_ioctl.c
29*7c478bd9Sstevel@tonic-gate  *   Test ioctl's to support test/debug of the 1394 HW. hci1394_ioctl_enum_t is
30*7c478bd9Sstevel@tonic-gate  *   passed in cmd and a pointer to the appropriate structure (i.e.
31*7c478bd9Sstevel@tonic-gate  *   hci1394_ioctl_wrreg_t) is passed in arg.
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394_extern.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394_ioctl.h>
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate /* HCI1394_IOCTL_READ_SELFID for 32-bit apps in 64-bit kernel */
51*7c478bd9Sstevel@tonic-gate typedef struct hci1394_ioctl_readselfid32_s {
52*7c478bd9Sstevel@tonic-gate 	uint32_t buf;
53*7c478bd9Sstevel@tonic-gate 	uint_t count;
54*7c478bd9Sstevel@tonic-gate } hci1394_ioctl_readselfid32_t;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_wrreg(hci1394_state_t *soft_state, void *arg,
58*7c478bd9Sstevel@tonic-gate     int mode);
59*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_rdreg(hci1394_state_t *soft_state, void *arg,
60*7c478bd9Sstevel@tonic-gate     int mode);
61*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_wrvreg(hci1394_state_t *soft_state, void *arg,
62*7c478bd9Sstevel@tonic-gate     int mode);
63*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_rdvreg(hci1394_state_t *soft_state, void *arg,
64*7c478bd9Sstevel@tonic-gate     int mode);
65*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_selfid_cnt(hci1394_state_t *soft_state, void *arg,
66*7c478bd9Sstevel@tonic-gate     int mode);
67*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_busgen_cnt(hci1394_state_t *soft_state, void *arg,
68*7c478bd9Sstevel@tonic-gate     int mode);
69*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_wrphy(hci1394_state_t *soft_state, void *arg,
70*7c478bd9Sstevel@tonic-gate     int mode);
71*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_rdphy(hci1394_state_t *soft_state, void *arg,
72*7c478bd9Sstevel@tonic-gate     int mode);
73*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_hbainfo(hci1394_state_t *soft_state, void *arg,
74*7c478bd9Sstevel@tonic-gate     int mode);
75*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_read_selfid(hci1394_state_t *soft_state, void *arg,
76*7c478bd9Sstevel@tonic-gate     int mode);
77*7c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
78*7c478bd9Sstevel@tonic-gate static int hci1394_ioctl_read_selfid32(hci1394_state_t *soft_state,
79*7c478bd9Sstevel@tonic-gate     hci1394_ioctl_readselfid32_t *read_selfid, int mode);
80*7c478bd9Sstevel@tonic-gate #endif
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
84*7c478bd9Sstevel@tonic-gate int
hci1394_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)85*7c478bd9Sstevel@tonic-gate hci1394_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
86*7c478bd9Sstevel@tonic-gate     int *rvalp)
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate 	hci1394_state_t *soft_state;
89*7c478bd9Sstevel@tonic-gate 	int instance;
90*7c478bd9Sstevel@tonic-gate 	int status;
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 	instance = getminor(dev);
93*7c478bd9Sstevel@tonic-gate 	if (instance == -1) {
94*7c478bd9Sstevel@tonic-gate 		return (EBADF);
95*7c478bd9Sstevel@tonic-gate 	}
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	soft_state = ddi_get_soft_state(hci1394_statep, instance);
98*7c478bd9Sstevel@tonic-gate 	if (soft_state == NULL) {
99*7c478bd9Sstevel@tonic-gate 		return (EBADF);
100*7c478bd9Sstevel@tonic-gate 	}
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 	status = 0;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
105*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_WRITE_REG:
106*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_wrreg(soft_state, (void *)arg, mode);
107*7c478bd9Sstevel@tonic-gate 		break;
108*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_READ_REG:
109*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_rdreg(soft_state, (void *)arg, mode);
110*7c478bd9Sstevel@tonic-gate 		break;
111*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_READ_VREG:
112*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_rdvreg(soft_state, (void *)arg, mode);
113*7c478bd9Sstevel@tonic-gate 		break;
114*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_WRITE_VREG:
115*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_wrvreg(soft_state, (void *)arg, mode);
116*7c478bd9Sstevel@tonic-gate 		break;
117*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_RESET_BUS:
118*7c478bd9Sstevel@tonic-gate 		status = hci1394_ohci_bus_reset(soft_state->ohci);
119*7c478bd9Sstevel@tonic-gate 		break;
120*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_SELFID_CNT:
121*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_selfid_cnt(soft_state, (void *)arg,
122*7c478bd9Sstevel@tonic-gate 		    mode);
123*7c478bd9Sstevel@tonic-gate 		break;
124*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_BUSGEN_CNT:
125*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_busgen_cnt(soft_state, (void *)arg,
126*7c478bd9Sstevel@tonic-gate 		    mode);
127*7c478bd9Sstevel@tonic-gate 		break;
128*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_READ_SELFID:
129*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_read_selfid(soft_state, (void *)arg,
130*7c478bd9Sstevel@tonic-gate 		    mode);
131*7c478bd9Sstevel@tonic-gate 		break;
132*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_READ_PHY:
133*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_rdphy(soft_state, (void *)arg, mode);
134*7c478bd9Sstevel@tonic-gate 		break;
135*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_WRITE_PHY:
136*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_wrphy(soft_state, (void *)arg, mode);
137*7c478bd9Sstevel@tonic-gate 		break;
138*7c478bd9Sstevel@tonic-gate 	case HCI1394_IOCTL_HBA_INFO:
139*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_hbainfo(soft_state, (void *)arg, mode);
140*7c478bd9Sstevel@tonic-gate 		break;
141*7c478bd9Sstevel@tonic-gate 	default:
142*7c478bd9Sstevel@tonic-gate 		/*
143*7c478bd9Sstevel@tonic-gate 		 * if we don't know what the ioctl is, forward it on to the
144*7c478bd9Sstevel@tonic-gate 		 * services layer.  The services layer will handle the devctl
145*7c478bd9Sstevel@tonic-gate 		 * ioctl's along with any services layer private ioctls that
146*7c478bd9Sstevel@tonic-gate 		 * it has defined.
147*7c478bd9Sstevel@tonic-gate 		 */
148*7c478bd9Sstevel@tonic-gate 		status = h1394_ioctl(soft_state->drvinfo.di_sl_private, cmd,
149*7c478bd9Sstevel@tonic-gate 		    arg, mode, credp, rvalp);
150*7c478bd9Sstevel@tonic-gate 		break;
151*7c478bd9Sstevel@tonic-gate 	}
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	return (status);
154*7c478bd9Sstevel@tonic-gate }
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_wrreg(hci1394_state_t * soft_state,void * arg,int mode)158*7c478bd9Sstevel@tonic-gate hci1394_ioctl_wrreg(hci1394_state_t *soft_state, void *arg, int mode)
159*7c478bd9Sstevel@tonic-gate {
160*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_wrreg_t wrreg;
161*7c478bd9Sstevel@tonic-gate 	int status;
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
165*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	status = ddi_copyin(arg, &wrreg, sizeof (hci1394_ioctl_wrreg_t), mode);
168*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
169*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
170*7c478bd9Sstevel@tonic-gate 	}
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	hci1394_ohci_reg_write(soft_state->ohci, wrreg.addr, wrreg.data);
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 	return (0);
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_rdreg(hci1394_state_t * soft_state,void * arg,int mode)179*7c478bd9Sstevel@tonic-gate hci1394_ioctl_rdreg(hci1394_state_t *soft_state, void *arg, int mode)
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_rdreg_t rdreg;
182*7c478bd9Sstevel@tonic-gate 	int status;
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
186*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 	status = ddi_copyin(arg, &rdreg, sizeof (hci1394_ioctl_rdreg_t), mode);
189*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
190*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
191*7c478bd9Sstevel@tonic-gate 	}
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	hci1394_ohci_reg_read(soft_state->ohci, rdreg.addr, &rdreg.data);
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	status = ddi_copyout(&rdreg, arg, sizeof (hci1394_ioctl_rdreg_t), mode);
196*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
197*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
198*7c478bd9Sstevel@tonic-gate 	}
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 	return (0);
201*7c478bd9Sstevel@tonic-gate }
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_wrvreg(hci1394_state_t * soft_state,void * arg,int mode)205*7c478bd9Sstevel@tonic-gate hci1394_ioctl_wrvreg(hci1394_state_t *soft_state, void *arg, int mode)
206*7c478bd9Sstevel@tonic-gate {
207*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_wrvreg_t wrvreg;
208*7c478bd9Sstevel@tonic-gate 	int status;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
212*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	status = ddi_copyin(arg, &wrvreg, sizeof (hci1394_ioctl_wrvreg_t),
215*7c478bd9Sstevel@tonic-gate 	    mode);
216*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
217*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
218*7c478bd9Sstevel@tonic-gate 	}
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	status = hci1394_vendor_reg_write(soft_state->vendor,
221*7c478bd9Sstevel@tonic-gate 	    wrvreg.regset, wrvreg.addr, wrvreg.data);
222*7c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
223*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
224*7c478bd9Sstevel@tonic-gate 	}
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	return (0);
227*7c478bd9Sstevel@tonic-gate }
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_rdvreg(hci1394_state_t * soft_state,void * arg,int mode)231*7c478bd9Sstevel@tonic-gate hci1394_ioctl_rdvreg(hci1394_state_t *soft_state, void *arg, int mode)
232*7c478bd9Sstevel@tonic-gate {
233*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_rdvreg_t rdvreg;
234*7c478bd9Sstevel@tonic-gate 	int status;
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
238*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	status = ddi_copyin(arg, &rdvreg, sizeof (hci1394_ioctl_rdvreg_t),
241*7c478bd9Sstevel@tonic-gate 	    mode);
242*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
243*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	status = hci1394_vendor_reg_read(soft_state->vendor,
247*7c478bd9Sstevel@tonic-gate 	    rdvreg.regset, rdvreg.addr, &rdvreg.data);
248*7c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
249*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
250*7c478bd9Sstevel@tonic-gate 	}
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 	status = ddi_copyout(&rdvreg, arg, sizeof (hci1394_ioctl_rdvreg_t),
253*7c478bd9Sstevel@tonic-gate 	    mode);
254*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
255*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
256*7c478bd9Sstevel@tonic-gate 	}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	return (0);
259*7c478bd9Sstevel@tonic-gate }
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_selfid_cnt(hci1394_state_t * soft_state,void * arg,int mode)263*7c478bd9Sstevel@tonic-gate hci1394_ioctl_selfid_cnt(hci1394_state_t *soft_state, void *arg, int mode)
264*7c478bd9Sstevel@tonic-gate {
265*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_selfid_cnt_t selfid_cnt;
266*7c478bd9Sstevel@tonic-gate 	int status;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
270*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	selfid_cnt.count = soft_state->drvinfo.di_stats.st_selfid_count;
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	status = ddi_copyout(&selfid_cnt, arg,
275*7c478bd9Sstevel@tonic-gate 	    sizeof (hci1394_ioctl_selfid_cnt_t), mode);
276*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
277*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
278*7c478bd9Sstevel@tonic-gate 	}
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	return (0);
281*7c478bd9Sstevel@tonic-gate }
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_busgen_cnt(hci1394_state_t * soft_state,void * arg,int mode)285*7c478bd9Sstevel@tonic-gate hci1394_ioctl_busgen_cnt(hci1394_state_t *soft_state, void *arg, int mode)
286*7c478bd9Sstevel@tonic-gate {
287*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_busgen_cnt_t busgen_cnt;
288*7c478bd9Sstevel@tonic-gate 	int status;
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
292*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	busgen_cnt.count = hci1394_ohci_current_busgen(soft_state->ohci);
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 	status = ddi_copyout(&busgen_cnt, arg,
297*7c478bd9Sstevel@tonic-gate 	    sizeof (hci1394_ioctl_busgen_cnt_t), mode);
298*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
299*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
300*7c478bd9Sstevel@tonic-gate 	}
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	return (0);
303*7c478bd9Sstevel@tonic-gate }
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_wrphy(hci1394_state_t * soft_state,void * arg,int mode)307*7c478bd9Sstevel@tonic-gate hci1394_ioctl_wrphy(hci1394_state_t *soft_state, void *arg, int mode)
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_wrphy_t wrphy;
310*7c478bd9Sstevel@tonic-gate 	int status;
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
314*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 	status = ddi_copyin(arg, &wrphy, sizeof (hci1394_ioctl_wrphy_t), mode);
317*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
318*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
319*7c478bd9Sstevel@tonic-gate 	}
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_write(soft_state->ohci, wrphy.addr,
322*7c478bd9Sstevel@tonic-gate 	    wrphy.data);
323*7c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
324*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
325*7c478bd9Sstevel@tonic-gate 	}
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate 	return (0);
328*7c478bd9Sstevel@tonic-gate }
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_rdphy(hci1394_state_t * soft_state,void * arg,int mode)332*7c478bd9Sstevel@tonic-gate hci1394_ioctl_rdphy(hci1394_state_t *soft_state, void *arg, int mode)
333*7c478bd9Sstevel@tonic-gate {
334*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_rdphy_t rdphy;
335*7c478bd9Sstevel@tonic-gate 	int status;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
339*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	status = ddi_copyin(arg, &rdphy, sizeof (hci1394_ioctl_rdphy_t), mode);
342*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
343*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
344*7c478bd9Sstevel@tonic-gate 	}
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read(soft_state->ohci, rdphy.addr,
347*7c478bd9Sstevel@tonic-gate 	    &rdphy.data);
348*7c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
349*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
350*7c478bd9Sstevel@tonic-gate 	}
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	status = ddi_copyout(&rdphy, arg, sizeof (hci1394_ioctl_rdphy_t), mode);
353*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
354*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
355*7c478bd9Sstevel@tonic-gate 	}
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 	return (0);
358*7c478bd9Sstevel@tonic-gate }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_hbainfo(hci1394_state_t * soft_state,void * arg,int mode)362*7c478bd9Sstevel@tonic-gate hci1394_ioctl_hbainfo(hci1394_state_t *soft_state, void *arg, int mode)
363*7c478bd9Sstevel@tonic-gate {
364*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_hbainfo_t hbainfo;
365*7c478bd9Sstevel@tonic-gate 	int status;
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
369*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 	hbainfo.pci_vendor_id = soft_state->vendor_info.vendor_id;
372*7c478bd9Sstevel@tonic-gate 	hbainfo.pci_device_id = soft_state->vendor_info.device_id;
373*7c478bd9Sstevel@tonic-gate 	hbainfo.pci_revision_id = soft_state->vendor_info.revision_id;
374*7c478bd9Sstevel@tonic-gate 	hbainfo.ohci_version = soft_state->vendor_info.ohci_version;
375*7c478bd9Sstevel@tonic-gate 	hbainfo.ohci_vendor_id = soft_state->vendor_info.ohci_vendor_id;
376*7c478bd9Sstevel@tonic-gate 	hbainfo.ohci_vregset_cnt = soft_state->vendor_info.vendor_reg_count;
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate 	status = ddi_copyout(&hbainfo, arg, sizeof (hci1394_ioctl_hbainfo_t),
379*7c478bd9Sstevel@tonic-gate 	    mode);
380*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
381*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
382*7c478bd9Sstevel@tonic-gate 	}
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	return (0);
385*7c478bd9Sstevel@tonic-gate }
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_read_selfid(hci1394_state_t * soft_state,void * arg,int mode)389*7c478bd9Sstevel@tonic-gate hci1394_ioctl_read_selfid(hci1394_state_t *soft_state, void *arg, int mode)
390*7c478bd9Sstevel@tonic-gate {
391*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_read_selfid_t read_selfid;
392*7c478bd9Sstevel@tonic-gate 	int status;
393*7c478bd9Sstevel@tonic-gate 	uint_t offset;
394*7c478bd9Sstevel@tonic-gate 	uint32_t data;
395*7c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
396*7c478bd9Sstevel@tonic-gate 	hci1394_ioctl_readselfid32_t read_selfid32;
397*7c478bd9Sstevel@tonic-gate #endif
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
401*7c478bd9Sstevel@tonic-gate 	ASSERT(arg != NULL);
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
404*7c478bd9Sstevel@tonic-gate 	switch (ddi_model_convert_from(mode & FMODELS)) {
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 		/* 32-bit app in 64-bit kernel */
407*7c478bd9Sstevel@tonic-gate 	case DDI_MODEL_ILP32:
408*7c478bd9Sstevel@tonic-gate 		/* copy in the 32-bit version of the args */
409*7c478bd9Sstevel@tonic-gate 		status = ddi_copyin(arg, &read_selfid32,
410*7c478bd9Sstevel@tonic-gate 		    sizeof (hci1394_ioctl_readselfid32_t), mode);
411*7c478bd9Sstevel@tonic-gate 		if (status != 0) {
412*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
413*7c478bd9Sstevel@tonic-gate 		}
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 		/*
416*7c478bd9Sstevel@tonic-gate 		 * Use a special function to process the 32-bit user address
417*7c478bd9Sstevel@tonic-gate 		 * pointer embedded in the structure we pass in arg.
418*7c478bd9Sstevel@tonic-gate 		 */
419*7c478bd9Sstevel@tonic-gate 		status = hci1394_ioctl_read_selfid32(soft_state,
420*7c478bd9Sstevel@tonic-gate 		    &read_selfid32, mode);
421*7c478bd9Sstevel@tonic-gate 		return (status);
422*7c478bd9Sstevel@tonic-gate 	default:
423*7c478bd9Sstevel@tonic-gate 		break;
424*7c478bd9Sstevel@tonic-gate 	}
425*7c478bd9Sstevel@tonic-gate #endif
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	/*
428*7c478bd9Sstevel@tonic-gate 	 * if we got here, we either are a 64-bit app in a 64-bit kernel or a
429*7c478bd9Sstevel@tonic-gate 	 * 32-bit app in a 32-bit kernel
430*7c478bd9Sstevel@tonic-gate 	 */
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	/* copy in the args. We don't need to do any special conversions */
433*7c478bd9Sstevel@tonic-gate 	status = ddi_copyin(arg, &read_selfid,
434*7c478bd9Sstevel@tonic-gate 	    sizeof (hci1394_ioctl_read_selfid_t), mode);
435*7c478bd9Sstevel@tonic-gate 	if (status != 0) {
436*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
437*7c478bd9Sstevel@tonic-gate 	}
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 	/*
440*7c478bd9Sstevel@tonic-gate 	 * make sure we are not trying to copy more data than the selfid buffer
441*7c478bd9Sstevel@tonic-gate 	 * can hold.  count is in quadlets and max_selfid_size is in bytes.
442*7c478bd9Sstevel@tonic-gate 	 */
443*7c478bd9Sstevel@tonic-gate 	if ((read_selfid.count * 4) > OHCI_MAX_SELFID_SIZE) {
444*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	/*
448*7c478bd9Sstevel@tonic-gate 	 * copy the selfid buffer one word at a time into the user buffer. The
449*7c478bd9Sstevel@tonic-gate 	 * combination between having to do ddi_get32's (for endian reasons)
450*7c478bd9Sstevel@tonic-gate 	 * and a ddi_copyout() make it easier to do it one word at a time.
451*7c478bd9Sstevel@tonic-gate 	 */
452*7c478bd9Sstevel@tonic-gate 	for (offset = 0; offset < read_selfid.count; offset++) {
453*7c478bd9Sstevel@tonic-gate 		/* read word from selfid buffer */
454*7c478bd9Sstevel@tonic-gate 		hci1394_ohci_selfid_read(soft_state->ohci, offset, &data);
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 		/* copy the selfid word into the user buffer */
457*7c478bd9Sstevel@tonic-gate 		status = ddi_copyout(&data, &read_selfid.buf[offset], 4, mode);
458*7c478bd9Sstevel@tonic-gate 		if (status != 0) {
459*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
460*7c478bd9Sstevel@tonic-gate 		}
461*7c478bd9Sstevel@tonic-gate 	}
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	return (0);
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate #ifdef	_MULTI_DATAMODEL
468*7c478bd9Sstevel@tonic-gate static int
hci1394_ioctl_read_selfid32(hci1394_state_t * soft_state,hci1394_ioctl_readselfid32_t * read_selfid,int mode)469*7c478bd9Sstevel@tonic-gate hci1394_ioctl_read_selfid32(hci1394_state_t *soft_state,
470*7c478bd9Sstevel@tonic-gate     hci1394_ioctl_readselfid32_t *read_selfid, int mode)
471*7c478bd9Sstevel@tonic-gate {
472*7c478bd9Sstevel@tonic-gate 	int status;
473*7c478bd9Sstevel@tonic-gate 	uint_t offset;
474*7c478bd9Sstevel@tonic-gate 	uint32_t data;
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 	ASSERT(soft_state != NULL);
478*7c478bd9Sstevel@tonic-gate 	ASSERT(read_selfid != NULL);
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	/*
481*7c478bd9Sstevel@tonic-gate 	 * make sure we are not trying to copy more data than the selfid buffer
482*7c478bd9Sstevel@tonic-gate 	 * can hold.  count is in quadlets and max_selfid_size is in bytes.
483*7c478bd9Sstevel@tonic-gate 	 */
484*7c478bd9Sstevel@tonic-gate 	if ((read_selfid->count * 4) > OHCI_MAX_SELFID_SIZE) {
485*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
486*7c478bd9Sstevel@tonic-gate 	}
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	/*
489*7c478bd9Sstevel@tonic-gate 	 * copy the selfid buffer one word at a time into the user buffer. The
490*7c478bd9Sstevel@tonic-gate 	 * combination between having to do ddi_get32's (for endian reasons) and
491*7c478bd9Sstevel@tonic-gate 	 * a ddi_copyout() make it easier to do it one word at a time.
492*7c478bd9Sstevel@tonic-gate 	 */
493*7c478bd9Sstevel@tonic-gate 	for (offset = 0; offset < read_selfid->count; offset++) {
494*7c478bd9Sstevel@tonic-gate 		/* read word from selfid buffer */
495*7c478bd9Sstevel@tonic-gate 		hci1394_ohci_selfid_read(soft_state->ohci, offset, &data);
496*7c478bd9Sstevel@tonic-gate 		/* copy the selfid word into the user buffer */
497*7c478bd9Sstevel@tonic-gate 		status = ddi_copyout(&data,
498*7c478bd9Sstevel@tonic-gate 		    (void *)(uintptr_t)(read_selfid->buf + (offset * 4)),
499*7c478bd9Sstevel@tonic-gate 		    4, mode);
500*7c478bd9Sstevel@tonic-gate 		if (status != 0) {
501*7c478bd9Sstevel@tonic-gate 			return (EFAULT);
502*7c478bd9Sstevel@tonic-gate 		}
503*7c478bd9Sstevel@tonic-gate 	}
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	return (0);
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate #endif
508