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
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.
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
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.
37 #include <sys/modctl.h>
38 #include <sys/mkdev.h>
41 #include <sys/types.h>
42 #include <sys/errno.h>
44 #include <sys/sunddi.h>
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>
52 /* HCI1394_IOCTL_READ_SELFID for 32-bit apps in 64-bit kernel */
53 typedef struct hci1394_ioctl_readselfid32_s
{
56 } hci1394_ioctl_readselfid32_t
;
59 static int hci1394_ioctl_wrreg(hci1394_state_t
*soft_state
, void *arg
,
61 static int hci1394_ioctl_rdreg(hci1394_state_t
*soft_state
, void *arg
,
63 static int hci1394_ioctl_wrvreg(hci1394_state_t
*soft_state
, void *arg
,
65 static int hci1394_ioctl_rdvreg(hci1394_state_t
*soft_state
, void *arg
,
67 static int hci1394_ioctl_selfid_cnt(hci1394_state_t
*soft_state
, void *arg
,
69 static int hci1394_ioctl_busgen_cnt(hci1394_state_t
*soft_state
, void *arg
,
71 static int hci1394_ioctl_wrphy(hci1394_state_t
*soft_state
, void *arg
,
73 static int hci1394_ioctl_rdphy(hci1394_state_t
*soft_state
, void *arg
,
75 static int hci1394_ioctl_hbainfo(hci1394_state_t
*soft_state
, void *arg
,
77 static int hci1394_ioctl_read_selfid(hci1394_state_t
*soft_state
, void *arg
,
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
);
87 hci1394_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*credp
,
90 hci1394_state_t
*soft_state
;
94 instance
= getminor(dev
);
99 soft_state
= ddi_get_soft_state(hci1394_statep
, instance
);
100 if (soft_state
== NULL
) {
107 case HCI1394_IOCTL_WRITE_REG
:
108 status
= hci1394_ioctl_wrreg(soft_state
, (void *)arg
, mode
);
110 case HCI1394_IOCTL_READ_REG
:
111 status
= hci1394_ioctl_rdreg(soft_state
, (void *)arg
, mode
);
113 case HCI1394_IOCTL_READ_VREG
:
114 status
= hci1394_ioctl_rdvreg(soft_state
, (void *)arg
, mode
);
116 case HCI1394_IOCTL_WRITE_VREG
:
117 status
= hci1394_ioctl_wrvreg(soft_state
, (void *)arg
, mode
);
119 case HCI1394_IOCTL_RESET_BUS
:
120 status
= hci1394_ohci_bus_reset(soft_state
->ohci
);
122 case HCI1394_IOCTL_SELFID_CNT
:
123 status
= hci1394_ioctl_selfid_cnt(soft_state
, (void *)arg
,
126 case HCI1394_IOCTL_BUSGEN_CNT
:
127 status
= hci1394_ioctl_busgen_cnt(soft_state
, (void *)arg
,
130 case HCI1394_IOCTL_READ_SELFID
:
131 status
= hci1394_ioctl_read_selfid(soft_state
, (void *)arg
,
134 case HCI1394_IOCTL_READ_PHY
:
135 status
= hci1394_ioctl_rdphy(soft_state
, (void *)arg
, mode
);
137 case HCI1394_IOCTL_WRITE_PHY
:
138 status
= hci1394_ioctl_wrphy(soft_state
, (void *)arg
, mode
);
140 case HCI1394_IOCTL_HBA_INFO
:
141 status
= hci1394_ioctl_hbainfo(soft_state
, (void *)arg
, mode
);
145 * if we don't know what the ioctl is, forward it on to the
146 * services layer. The services layer will handle the devctl
147 * ioctl's along with any services layer private ioctls that
150 status
= h1394_ioctl(soft_state
->drvinfo
.di_sl_private
, cmd
,
151 arg
, mode
, credp
, rvalp
);
160 hci1394_ioctl_wrreg(hci1394_state_t
*soft_state
, void *arg
, int mode
)
162 hci1394_ioctl_wrreg_t wrreg
;
166 ASSERT(soft_state
!= NULL
);
169 status
= ddi_copyin(arg
, &wrreg
, sizeof (hci1394_ioctl_wrreg_t
), mode
);
174 hci1394_ohci_reg_write(soft_state
->ohci
, wrreg
.addr
, wrreg
.data
);
181 hci1394_ioctl_rdreg(hci1394_state_t
*soft_state
, void *arg
, int mode
)
183 hci1394_ioctl_rdreg_t rdreg
;
187 ASSERT(soft_state
!= NULL
);
190 status
= ddi_copyin(arg
, &rdreg
, sizeof (hci1394_ioctl_rdreg_t
), mode
);
195 hci1394_ohci_reg_read(soft_state
->ohci
, rdreg
.addr
, &rdreg
.data
);
197 status
= ddi_copyout(&rdreg
, arg
, sizeof (hci1394_ioctl_rdreg_t
), mode
);
207 hci1394_ioctl_wrvreg(hci1394_state_t
*soft_state
, void *arg
, int mode
)
209 hci1394_ioctl_wrvreg_t wrvreg
;
213 ASSERT(soft_state
!= NULL
);
216 status
= ddi_copyin(arg
, &wrvreg
, sizeof (hci1394_ioctl_wrvreg_t
),
222 status
= hci1394_vendor_reg_write(soft_state
->vendor
,
223 wrvreg
.regset
, wrvreg
.addr
, wrvreg
.data
);
224 if (status
!= DDI_SUCCESS
) {
233 hci1394_ioctl_rdvreg(hci1394_state_t
*soft_state
, void *arg
, int mode
)
235 hci1394_ioctl_rdvreg_t rdvreg
;
239 ASSERT(soft_state
!= NULL
);
242 status
= ddi_copyin(arg
, &rdvreg
, sizeof (hci1394_ioctl_rdvreg_t
),
248 status
= hci1394_vendor_reg_read(soft_state
->vendor
,
249 rdvreg
.regset
, rdvreg
.addr
, &rdvreg
.data
);
250 if (status
!= DDI_SUCCESS
) {
254 status
= ddi_copyout(&rdvreg
, arg
, sizeof (hci1394_ioctl_rdvreg_t
),
265 hci1394_ioctl_selfid_cnt(hci1394_state_t
*soft_state
, void *arg
, int mode
)
267 hci1394_ioctl_selfid_cnt_t selfid_cnt
;
271 ASSERT(soft_state
!= NULL
);
274 selfid_cnt
.count
= soft_state
->drvinfo
.di_stats
.st_selfid_count
;
276 status
= ddi_copyout(&selfid_cnt
, arg
,
277 sizeof (hci1394_ioctl_selfid_cnt_t
), mode
);
287 hci1394_ioctl_busgen_cnt(hci1394_state_t
*soft_state
, void *arg
, int mode
)
289 hci1394_ioctl_busgen_cnt_t busgen_cnt
;
293 ASSERT(soft_state
!= NULL
);
296 busgen_cnt
.count
= hci1394_ohci_current_busgen(soft_state
->ohci
);
298 status
= ddi_copyout(&busgen_cnt
, arg
,
299 sizeof (hci1394_ioctl_busgen_cnt_t
), mode
);
309 hci1394_ioctl_wrphy(hci1394_state_t
*soft_state
, void *arg
, int mode
)
311 hci1394_ioctl_wrphy_t wrphy
;
315 ASSERT(soft_state
!= NULL
);
318 status
= ddi_copyin(arg
, &wrphy
, sizeof (hci1394_ioctl_wrphy_t
), mode
);
323 status
= hci1394_ohci_phy_write(soft_state
->ohci
, wrphy
.addr
,
325 if (status
!= DDI_SUCCESS
) {
334 hci1394_ioctl_rdphy(hci1394_state_t
*soft_state
, void *arg
, int mode
)
336 hci1394_ioctl_rdphy_t rdphy
;
340 ASSERT(soft_state
!= NULL
);
343 status
= ddi_copyin(arg
, &rdphy
, sizeof (hci1394_ioctl_rdphy_t
), mode
);
348 status
= hci1394_ohci_phy_read(soft_state
->ohci
, rdphy
.addr
,
350 if (status
!= DDI_SUCCESS
) {
354 status
= ddi_copyout(&rdphy
, arg
, sizeof (hci1394_ioctl_rdphy_t
), mode
);
364 hci1394_ioctl_hbainfo(hci1394_state_t
*soft_state
, void *arg
, int mode
)
366 hci1394_ioctl_hbainfo_t hbainfo
;
370 ASSERT(soft_state
!= NULL
);
373 hbainfo
.pci_vendor_id
= soft_state
->vendor_info
.vendor_id
;
374 hbainfo
.pci_device_id
= soft_state
->vendor_info
.device_id
;
375 hbainfo
.pci_revision_id
= soft_state
->vendor_info
.revision_id
;
376 hbainfo
.ohci_version
= soft_state
->vendor_info
.ohci_version
;
377 hbainfo
.ohci_vendor_id
= soft_state
->vendor_info
.ohci_vendor_id
;
378 hbainfo
.ohci_vregset_cnt
= soft_state
->vendor_info
.vendor_reg_count
;
380 status
= ddi_copyout(&hbainfo
, arg
, sizeof (hci1394_ioctl_hbainfo_t
),
391 hci1394_ioctl_read_selfid(hci1394_state_t
*soft_state
, void *arg
, int mode
)
393 hci1394_ioctl_read_selfid_t read_selfid
;
397 #ifdef _MULTI_DATAMODEL
398 hci1394_ioctl_readselfid32_t read_selfid32
;
402 ASSERT(soft_state
!= NULL
);
405 #ifdef _MULTI_DATAMODEL
406 switch (ddi_model_convert_from(mode
& FMODELS
)) {
408 /* 32-bit app in 64-bit kernel */
409 case DDI_MODEL_ILP32
:
410 /* copy in the 32-bit version of the args */
411 status
= ddi_copyin(arg
, &read_selfid32
,
412 sizeof (hci1394_ioctl_readselfid32_t
), mode
);
418 * Use a special function to process the 32-bit user address
419 * pointer embedded in the structure we pass in arg.
421 status
= hci1394_ioctl_read_selfid32(soft_state
,
422 &read_selfid32
, mode
);
430 * if we got here, we either are a 64-bit app in a 64-bit kernel or a
431 * 32-bit app in a 32-bit kernel
434 /* copy in the args. We don't need to do any special conversions */
435 status
= ddi_copyin(arg
, &read_selfid
,
436 sizeof (hci1394_ioctl_read_selfid_t
), mode
);
442 * make sure we are not trying to copy more data than the selfid buffer
443 * can hold. count is in quadlets and max_selfid_size is in bytes.
445 if ((read_selfid
.count
* 4) > OHCI_MAX_SELFID_SIZE
) {
450 * copy the selfid buffer one word at a time into the user buffer. The
451 * combination between having to do ddi_get32's (for endian reasons)
452 * and a ddi_copyout() make it easier to do it one word at a time.
454 for (offset
= 0; offset
< read_selfid
.count
; offset
++) {
455 /* read word from selfid buffer */
456 hci1394_ohci_selfid_read(soft_state
->ohci
, offset
, &data
);
458 /* copy the selfid word into the user buffer */
459 status
= ddi_copyout(&data
, &read_selfid
.buf
[offset
], 4, mode
);
469 #ifdef _MULTI_DATAMODEL
471 hci1394_ioctl_read_selfid32(hci1394_state_t
*soft_state
,
472 hci1394_ioctl_readselfid32_t
*read_selfid
, int mode
)
479 ASSERT(soft_state
!= NULL
);
480 ASSERT(read_selfid
!= NULL
);
483 * make sure we are not trying to copy more data than the selfid buffer
484 * can hold. count is in quadlets and max_selfid_size is in bytes.
486 if ((read_selfid
->count
* 4) > OHCI_MAX_SELFID_SIZE
) {
491 * copy the selfid buffer one word at a time into the user buffer. The
492 * combination between having to do ddi_get32's (for endian reasons) and
493 * a ddi_copyout() make it easier to do it one word at a time.
495 for (offset
= 0; offset
< read_selfid
->count
; offset
++) {
496 /* read word from selfid buffer */
497 hci1394_ohci_selfid_read(soft_state
->ohci
, offset
, &data
);
498 /* copy the selfid word into the user buffer */
499 status
= ddi_copyout(&data
,
500 (void *)(uintptr_t)(read_selfid
->buf
+ (offset
* 4)),