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 #include "ndievents.h"
30 #include <sys/sunndi.h>
31 #include <sys/ndi_impldefs.h>
32 #include <sys/dditypes.h>
33 #include <sys/ddi_impldefs.h>
34 #include <sys/sunddi.h>
35 #include <sys/param.h>
36
37
38 int
dip_to_pathname(struct dev_info * device,char * path,int buflen)39 dip_to_pathname(struct dev_info *device, char *path, int buflen) {
40
41 char *bp;
42 char *addr;
43 char addr_str[32];
44 char nodename[MAXNAMELEN];
45 struct dev_info devi_parent;
46
47 if (!device) {
48 mdb_warn("Unable to access devinfo.");
49 return (-1);
50 }
51
52 if (device->devi_parent == NULL) {
53 if (mdb_readstr(nodename, sizeof (nodename),
54 (uintptr_t)device->devi_node_name) == -1) {
55 return (-1);
56 }
57
58 if (sizeof (nodename) > (buflen - strlen(path))) {
59 return (-1);
60 }
61
62 strncpy(path, nodename, sizeof (nodename));
63 return (0);
64 }
65
66 if (mdb_vread(&devi_parent, sizeof (struct dev_info),
67 (uintptr_t)device->devi_parent) == -1) {
68 mdb_warn("Unable to access devi_parent at %p",
69 (uintptr_t)device->devi_parent);
70 return (-1);
71 }
72
73 if (dip_to_pathname(&devi_parent, path, buflen) == -1) {
74 return (-1);
75 }
76
77 if (mdb_readstr(nodename, sizeof (nodename),
78 (uintptr_t)device->devi_node_name) == -1) {
79 return (-1);
80 }
81
82 if (device->devi_node_state < DS_INITIALIZED) {
83 strncpy(addr_str, '\0', sizeof ('\0'));
84 } else {
85 addr = device->devi_addr;
86 if (mdb_readstr(addr_str, sizeof (addr_str),
87 (uintptr_t)addr) == -1) {
88 return (-1);
89 }
90 }
91
92 bp = path + strlen(path);
93
94 if (addr_str[0] == '\0') {
95 (void) mdb_snprintf(bp, buflen - strlen(path), "/%s", nodename);
96 } else {
97 (void) mdb_snprintf(bp, buflen - strlen(path), "/%s@%s",
98 nodename, addr_str);
99 }
100 return (0);
101
102 }
103
104 /*ARGSUSED*/
105 int
ndi_callback_print(struct ndi_event_cookie * cookie,uint_t flags)106 ndi_callback_print(struct ndi_event_cookie *cookie, uint_t flags)
107 {
108
109 struct ndi_event_callbacks *callback_list;
110 struct ndi_event_callbacks cb;
111 char device_path[MAXPATHLEN];
112 struct dev_info devi;
113
114 if (!cookie) {
115 return (DCMD_ERR);
116 }
117
118 callback_list = cookie->callback_list;
119
120 while (callback_list != NULL) {
121 if (mdb_vread(&cb, sizeof (struct ndi_event_callbacks),
122 (uintptr_t)callback_list) == -1) {
123 mdb_warn("Could not read callback structure at"
124 " %p", callback_list);
125 return (DCMD_ERR);
126 }
127
128 if (mdb_vread(&devi, sizeof (struct dev_info),
129 (uintptr_t)cb.ndi_evtcb_dip) == -1) {
130 mdb_warn("Could not read devinfo structure at"
131 " %p", cb.ndi_evtcb_dip);
132 return (DCMD_ERR);
133 }
134
135 if (dip_to_pathname(&devi, device_path, sizeof (device_path))
136 == -1) {
137 return (DCMD_ERR);
138 }
139
140 mdb_printf("\t\tCallback Registered By: %s\n", device_path);
141 mdb_printf("\t\t Callback Address:\t%-?p\n"
142 "\t\t Callback Function:\t%-p\n"
143 "\t\t Callback Args:\t%-?p\n"
144 "\t\t Callback Cookie:\t%-?p\n",
145 callback_list, cb.ndi_evtcb_callback, cb.ndi_evtcb_arg,
146 cb.ndi_evtcb_cookie);
147
148 callback_list = cb.ndi_evtcb_next;
149
150 }
151
152 return (DCMD_OK);
153 }
154
155 int
ndi_event_print(struct ndi_event_hdl * hdl,uint_t flags)156 ndi_event_print(struct ndi_event_hdl *hdl, uint_t flags)
157 {
158
159 struct ndi_event_definition def;
160 struct ndi_event_cookie cookie;
161 struct ndi_event_cookie *cookie_list;
162 char ndi_event_name[256];
163
164 if (!hdl)
165 return (DCMD_ERR);
166
167 cookie_list = hdl->ndi_evthdl_cookie_list;
168 if (cookie_list == NULL) {
169 mdb_printf("\tNo cookies defined for this handle.\n");
170 return (DCMD_OK);
171 }
172
173 while (cookie_list != NULL) {
174 if (mdb_vread(&cookie, sizeof (struct ndi_event_cookie),
175 (uintptr_t)cookie_list) == -1) {
176 mdb_warn("Unable to access cookie list");
177 return (DCMD_ERR);
178 }
179
180 if (mdb_vread(&def, sizeof (struct ndi_event_definition),
181 (uintptr_t)cookie.definition) == -1) {
182 mdb_warn("Unable to access definition at %p",
183 cookie.definition);
184 return (DCMD_ERR);
185 }
186
187 if (mdb_readstr(ndi_event_name, sizeof (ndi_event_name),
188 (uintptr_t)def.ndi_event_name) == -1) {
189 mdb_warn("Unable to read cookie name.");
190 return (DCMD_ERR);
191 }
192
193 mdb_printf("\tCookie(%s %p) :Plevel(%d)\n\tddip(%p)"
194 " : Attr(%d)\n",
195 ndi_event_name, cookie_list, def.ndi_event_plevel,
196 cookie.ddip, def.ndi_event_attributes);
197
198 ndi_callback_print(&cookie, flags);
199 cookie_list = cookie.next_cookie;
200
201 }
202 return (0);
203 }
204
205 /*ARGSUSED*/
206 int
ndi_event_hdl(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)207 ndi_event_hdl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
208 {
209
210 struct dev_info devi;
211 struct ndi_event_hdl handle;
212 char path[MAXPATHLEN];
213 int done;
214
215 if (!(flags & DCMD_ADDRSPEC)) {
216 return (DCMD_USAGE);
217 }
218
219 if (mdb_vread(&handle, sizeof (struct ndi_event_hdl), addr) == -1) {
220 mdb_warn("failed to read ndi_event_hdl at %p", addr);
221 return (DCMD_ERR);
222 }
223
224 if (mdb_vread(&devi, sizeof (struct dev_info),
225 (uintptr_t)handle.ndi_evthdl_dip)
226 == -1) {
227 mdb_warn("failed to read devinfo node at %p",
228 handle.ndi_evthdl_dip);
229 return (DCMD_ERR);
230 }
231
232 if (dip_to_pathname(&devi, path, sizeof (path)) == -1) {
233 return (DCMD_ERR);
234 }
235
236 done = 0;
237 while (!done) {
238
239 mdb_printf("%<b>Handle%</b> (%p) :%<b> Path%</b> (%s) : %<b>"
240 "dip %</b>(%p) \n", addr, path, handle.ndi_evthdl_dip);
241
242 mdb_printf("mutexes: handle(%p) callback(%p)\n",
243 handle.ndi_evthdl_mutex, handle.ndi_evthdl_cb_mutex);
244
245 ndi_event_print(&handle, flags);
246
247 if (handle.ndi_next_hdl == NULL) {
248 done = 1;
249 } else {
250 addr = (uintptr_t)handle.ndi_next_hdl;
251 if (mdb_vread(&handle, sizeof (struct ndi_event_hdl),
252 (uintptr_t)addr) == -1) {
253 mdb_warn("failed to read ndi_event_hdl at %p",
254 addr);
255 break;
256 }
257
258 }
259 }
260
261 return (0);
262 }
263