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