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