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 2000-2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Routines extracted from usr/src/uts/common/io/usb/usba/usba.c.
29 */
30
31 #include <sys/mdb_modapi.h>
32 #include <sys/usb/usba.h>
33 #include <sys/usb/usba/usba_types.h>
34 #include <sys/usb/usba/usba_impl.h>
35 #include <sys/usb/usba/hcdi_impl.h>
36 #include <sys/file.h>
37 #include <sys/sunndi.h>
38
39
40 /*
41 * check whether this dip is the root hub.
42 * dip_addr is address of the devinfo struct in the core image (not local space)
43 */
44 static int
mdb_usba_is_root_hub(struct dev_info * dip)45 mdb_usba_is_root_hub(struct dev_info *dip)
46 {
47 uintptr_t p = (uintptr_t)dip->devi_hw_prop_ptr;
48
49 while (p != 0) {
50 ddi_prop_t prop;
51 char prop_name[128];
52
53 if (mdb_vread(&prop, sizeof (prop), p) == -1) {
54 mdb_warn("failed to read property");
55 break;
56 }
57 if (mdb_readstr(prop_name, sizeof (prop_name),
58 (uintptr_t)prop.prop_name) == -1) {
59 mdb_warn("failed to read property name");
60 }
61
62 if (strcmp(prop_name, "root-hub") == 0) {
63
64 return (1);
65 }
66
67 p = (uintptr_t)prop.prop_next;
68 }
69
70 return (0);
71 }
72
73
74 /*
75 * retrieve hcdi structure from the dip
76 *
77 * dip_addr is address of the devinfo struct in the core image (not local space)
78 */
79 uintptr_t
mdb_usba_hcdi_get_hcdi(struct dev_info * dip)80 mdb_usba_hcdi_get_hcdi(struct dev_info *dip)
81 {
82 return ((uintptr_t)dip->devi_driver_data);
83 }
84
85
86 /*
87 * get usba_device pointer in the devi
88 *
89 * dip_addr is address of the devinfo struct in the core image (not local space)
90 */
91 uintptr_t
mdb_usba_get_usba_device(uintptr_t dip_addr)92 mdb_usba_get_usba_device(uintptr_t dip_addr)
93 {
94 struct dev_info devinfo;
95
96 if (mdb_vread(&devinfo, sizeof (struct dev_info), dip_addr) == -1) {
97 mdb_warn("failed to read dev_info at %p", dip_addr);
98
99 return (0);
100 }
101
102 /*
103 * we cannot use parent_data in the usb node because its
104 * bus parent (eg. PCI nexus driver) uses this data
105 *
106 * we cannot use driver data in the other usb nodes since
107 * usb drivers may need to use this
108 */
109 if (mdb_usba_is_root_hub(&devinfo)) {
110 usba_hcdi_t hcdi_struct;
111 uintptr_t hcdi_addr = mdb_usba_hcdi_get_hcdi(&devinfo);
112
113 if (!hcdi_addr) {
114
115 return (0);
116 }
117
118 /* Read hcdi struct into local address space. */
119 if (mdb_vread(&hcdi_struct, sizeof (usba_hcdi_t),
120 hcdi_addr) == -1) {
121 mdb_warn("failed to read hcdi struct");
122
123 return (0);
124 }
125
126 return ((uintptr_t)hcdi_struct.hcdi_usba_device);
127
128 } else {
129 struct dev_info devinfo;
130
131 if (mdb_vread(&devinfo, sizeof (struct dev_info),
132 dip_addr) == -1) {
133 mdb_warn("failed to read dev_info at %p", dip_addr);
134
135 return (0);
136 }
137
138 /* casts needed to keep lint happy */
139 return ((uintptr_t)devinfo.devi_parent_data);
140 }
141 }
142