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