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