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
  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
 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
 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
 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 }