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 2005 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 /*
  27  * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
  28  */
  29 
  30 /*
  31  * nx1394.c
  32  *    1394 Services Layer Nexus Support Routines
  33  *    Routines in this file implement nexus bus_ops.
  34  */
  35 
  36 #include <sys/conf.h>
  37 #include <sys/ddi.h>
  38 #include <sys/modctl.h>
  39 #include <sys/sunddi.h>
  40 #include <sys/cmn_err.h>
  41 #include <sys/types.h>
  42 #include <sys/ddi_impldefs.h>
  43 
  44 #include <sys/tnf_probe.h>
  45 
  46 #include <sys/1394/t1394.h>
  47 #include <sys/1394/s1394.h>
  48 #include <sys/1394/h1394.h>
  49 
  50 static int nx1394_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
  51     ddi_dma_attr_t *attr, int (*waitfnp)(caddr_t), caddr_t arg,
  52     ddi_dma_handle_t *handlep);
  53 
  54 static int nx1394_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
  55     void *arg, void *result);
  56 
  57 static int nx1394_get_event_cookie(dev_info_t *dip, dev_info_t *rdip,
  58     char *name, ddi_eventcookie_t *event_cookiep);
  59 
  60 static int nx1394_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
  61     ddi_eventcookie_t eventhdl, void (*callback)(), void *arg,
  62     ddi_callback_id_t *cb_id);
  63 
  64 static int nx1394_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id);
  65 
  66 static int nx1394_post_event(dev_info_t *dip, dev_info_t *rdip,
  67     ddi_eventcookie_t eventhdl, void *impl_data);
  68 
  69 struct bus_ops nx1394_busops = {
  70         BUSO_REV,
  71         nullbusmap,                     /* bus_map */
  72         NULL,                           /* bus_get_intrspec */
  73         NULL,                           /* bus_add_intrspec */
  74         NULL,                           /* bus_remove_intrspec */
  75         i_ddi_map_fault,                /* XXXX bus_map_fault */
  76         NULL,                           /* bus_dma_map */
  77         nx1394_dma_allochdl,
  78         ddi_dma_freehdl,
  79         ddi_dma_bindhdl,
  80         ddi_dma_unbindhdl,
  81         ddi_dma_flush,
  82         ddi_dma_win,
  83         ddi_dma_mctl,                   /* bus_dma_ctl */
  84         nx1394_bus_ctl,                 /* bus_ctl */
  85         ddi_bus_prop_op,                /* bus_prop_op */
  86         nx1394_get_event_cookie,        /* (*bus_get_eventcookie() */
  87         nx1394_add_eventcall,           /* (*bus_add_eventcall)(); */
  88         nx1394_remove_eventcall,        /* (*bus_remove_eventcall)(); */
  89         nx1394_post_event,              /* (*bus_post_event)(); */
  90         0,                              /* (*interrupt control)();      */
  91         0,                              /* (*bus_config)();     */
  92         0,                              /* (*bus_unconfig)();   */
  93         0,                              /* (*bus_fm_init)();    */
  94         0,                              /* (*bus_fm_fini)();    */
  95         0,                              /* (*bus_fm_access_enter)();    */
  96         0,                              /* (*bus_fm_access_exit)();     */
  97         0,                              /* (*bus_power)();      */
  98         i_ddi_intr_ops                  /* (*bus_intr_op)();    */
  99 };
 100 
 101 /*
 102  * removal/insertion/reset events
 103  */
 104 #define NX1394_EVENT_TAG_HOT_REMOVAL            0
 105 #define NX1394_EVENT_TAG_HOT_INSERTION          1
 106 #define NX1394_EVENT_TAG_BUS_RESET              2
 107 
 108 static ndi_event_definition_t nx1394_event_defs[] = {
 109         {NX1394_EVENT_TAG_HOT_REMOVAL, DDI_DEVI_REMOVE_EVENT, EPL_KERNEL,
 110             NDI_EVENT_POST_TO_TGT},
 111         {NX1394_EVENT_TAG_HOT_INSERTION, DDI_DEVI_INSERT_EVENT, EPL_KERNEL,
 112             NDI_EVENT_POST_TO_TGT},
 113         {NX1394_EVENT_TAG_BUS_RESET, DDI_DEVI_BUS_RESET_EVENT, EPL_KERNEL,
 114             NDI_EVENT_POST_TO_ALL},
 115 };
 116 
 117 #define NX1394_N_EVENTS \
 118         (sizeof (nx1394_event_defs) / sizeof (ndi_event_definition_t))
 119 
 120 static ndi_event_set_t nx1394_events = {
 121         NDI_EVENTS_REV1, NX1394_N_EVENTS, nx1394_event_defs
 122 };
 123 
 124 /*
 125  * nx1394_bus_ctl()
 126  *    This routine implements nexus bus ctl operations. Of importance are
 127  *    DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD
 128  *    and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup
 129  *    reg property on the child node and builds and sets the name
 130  *    (name is of the form GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA], where
 131  *    GGGGGGGGGGGGGGGG is the GUID and AAAAAAAAAAAA is the optional unit
 132  *    address).
 133  */
 134 static int
 135 nx1394_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
 136     void *result)
 137 {
 138         int status;
 139 
 140         TNF_PROBE_0_DEBUG(nx1394_bus_ctl_enter, S1394_TNF_SL_NEXUS_STACK, "");
 141 
 142         switch (op) {
 143         case DDI_CTLOPS_REPORTDEV: {
 144                 dev_info_t *pdip = ddi_get_parent(rdip);
 145                 cmn_err(CE_CONT, "?%s%d at %s%d",
 146                     ddi_node_name(rdip), ddi_get_instance(rdip),
 147                     ddi_node_name(pdip), ddi_get_instance(pdip));
 148                 TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
 149                     "");
 150                 return (DDI_SUCCESS);
 151         }
 152 
 153         case DDI_CTLOPS_INITCHILD: {
 154                 dev_info_t *ocdip, *cdip = (dev_info_t *)arg;
 155                 dev_info_t *pdip = ddi_get_parent(cdip);
 156                 int reglen, i;
 157                 uint32_t *regptr;
 158                 char addr[MAXNAMELEN];
 159 
 160                 TNF_PROBE_1(nx1394_bus_ctl_init_child,
 161                     S1394_TNF_SL_HOTPLUG_STACK, "", tnf_opaque, dip, cdip);
 162 
 163                 i = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
 164                     DDI_PROP_DONTPASS, "reg", (int **)&regptr,
 165                     (uint_t *)&reglen);
 166 
 167                 if (i != DDI_PROP_SUCCESS) {
 168                         cmn_err(CE_NOTE, "!%s(%d): \"reg\" property not found",
 169                             ddi_node_name(cdip), ddi_get_instance(cdip));
 170                         TNF_PROBE_2(nx1394_bus_ctl,
 171                             S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg,
 172                             "Reg property not found", tnf_int, reason, i);
 173                         TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
 174                             S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op,
 175                             "initchild");
 176                         return (DDI_NOT_WELL_FORMED);
 177                 }
 178 
 179                 ASSERT(reglen != 0);
 180 
 181                 /*
 182                  * addr is of the format GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA]
 183                  */
 184                 if (regptr[2] || regptr[3]) {
 185                         (void) sprintf(addr, "%08x%08x,%04x%08x", regptr[0],
 186                             regptr[1], regptr[2], regptr[3]);
 187                 } else {
 188                         (void) sprintf(addr, "%08x%08x", regptr[0], regptr[1]);
 189                 }
 190                 ddi_prop_free(regptr);
 191                 ddi_set_name_addr(cdip, addr);
 192 
 193                 /*
 194                  * Check for a node with the same name & addr as the current
 195                  * node. If such a node exists, return failure.
 196                  */
 197                 if ((ocdip = ndi_devi_find(pdip, ddi_node_name(cdip), addr)) !=
 198                     NULL && ocdip != cdip) {
 199                         cmn_err(CE_NOTE,
 200                             "!%s(%d): Duplicate dev_info node found %s@%s",
 201                             ddi_node_name(cdip), ddi_get_instance(cdip),
 202                             ddi_node_name(ocdip), addr);
 203                         TNF_PROBE_1(nx1394_bus_ctl,
 204                             S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg,
 205                             "Duplicate nodes");
 206                         TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
 207                             S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op,
 208                             "initchild");
 209                         ddi_set_name_addr(cdip, NULL);
 210                         return (DDI_NOT_WELL_FORMED);
 211                 }
 212 
 213                 /*
 214                  * If HAL (parent dip) has "active-dma-flush" property, then
 215                  * add property to child as well.  Workaround for active
 216                  * context flushing bug in Schizo rev 2.1 and 2.2.
 217                  */
 218                 if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
 219                     "active-dma-flush") != 0) {
 220                         status = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
 221                             "active-dma-flush", 1);
 222                         if (status != NDI_SUCCESS) {
 223                                 cmn_err(CE_NOTE, "!%s(%d): Unable to add "
 224                                     "\"active-dma-flush\" property",
 225                                     ddi_node_name(cdip),
 226                                     ddi_get_instance(cdip));
 227                                 TNF_PROBE_1(nx1394_bus_ctl,
 228                                     S1394_TNF_SL_NEXUS_ERROR, "", tnf_string,
 229                                     msg, "Unable to add \"active-dma-flush\" "
 230                                     "property");
 231                                 TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
 232                                     S1394_TNF_SL_NEXUS_STACK, "", tnf_string,
 233                                     op, "initchild");
 234                                 ddi_set_name_addr(cdip, NULL);
 235                                 return (DDI_NOT_WELL_FORMED);
 236                         }
 237                 }
 238 
 239                 TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
 240                     S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op, "initchild");
 241                 return (DDI_SUCCESS);
 242         }
 243 
 244         case DDI_CTLOPS_UNINITCHILD: {
 245                 ddi_prop_remove_all((dev_info_t *)arg);
 246                 ddi_set_name_addr((dev_info_t *)arg, NULL);
 247                 TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
 248                     "", tnf_string, op, "uninitchild");
 249                 return (DDI_SUCCESS);
 250         }
 251 
 252         case DDI_CTLOPS_IOMIN: {
 253                 status = ddi_ctlops(dip, rdip, op, arg, result);
 254                 TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
 255                     "", tnf_string, op, "iomin");
 256                 return (status);
 257         }
 258 
 259         case DDI_CTLOPS_POWER: {
 260                 return (DDI_SUCCESS);
 261         }
 262 
 263         /*
 264          * These ops correspond to functions that "shouldn't" be called
 265          * by a 1394 client driver.
 266          */
 267         case DDI_CTLOPS_DMAPMAPC:
 268         case DDI_CTLOPS_REPORTINT:
 269         case DDI_CTLOPS_REGSIZE:
 270         case DDI_CTLOPS_NREGS:
 271         case DDI_CTLOPS_SIDDEV:
 272         case DDI_CTLOPS_SLAVEONLY:
 273         case DDI_CTLOPS_AFFINITY:
 274         case DDI_CTLOPS_POKE:
 275         case DDI_CTLOPS_PEEK: {
 276                 cmn_err(CE_CONT, "!%s(%d): invalid op (%d) from %s(%d)",
 277                     ddi_node_name(dip), ddi_get_instance(dip),
 278                     op, ddi_node_name(rdip), ddi_get_instance(rdip));
 279                 TNF_PROBE_2(nx1394_bus_ctl, S1394_TNF_SL_NEXUS_ERROR, "",
 280                     tnf_string, msg, "invalid op", tnf_int, op, op);
 281                 TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
 282                     "");
 283                 return (DDI_FAILURE);
 284         }
 285 
 286         /*
 287          * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up
 288          */
 289         default: {
 290                 status = ddi_ctlops(dip, rdip, op, arg, result);
 291                 TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
 292                     "");
 293                 return (status);
 294         }
 295         }
 296 }
 297 
 298 /*
 299  * nx1394_dma_allochdl()
 300  *    Merges the ddi_dma_attr_t passed in by the target (using
 301  *    ddi_dma_alloc_handle() call) with that of the hal and passes the alloc
 302  *    handle request up the device by calling ddi_dma_allochdl().
 303  */
 304 static int
 305 nx1394_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
 306     int (*waitfnp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
 307 {
 308         s1394_hal_t *hal;
 309         ddi_dma_attr_t *hal_attr;
 310         int status;
 311 
 312         _NOTE(SCHEME_PROTECTS_DATA("unique (per thread)", ddi_dma_attr_t))
 313 
 314         TNF_PROBE_0_DEBUG(nx1394_dma_allochdl_enter, S1394_TNF_SL_NEXUS_STACK,
 315             "");
 316 
 317         /*
 318          * If hal calls ddi_dma_alloc_handle, dip == rdip == hal dip.
 319          * Unfortunately, we cannot verify this (by way of looking up for hal
 320          * dip) here because h1394_attach() may happen much later.
 321          */
 322         if (dip != rdip) {
 323                 hal = s1394_dip_to_hal(ddi_get_parent(rdip));
 324                 ASSERT(hal);
 325                 hal_attr = &hal->halinfo.dma_attr;
 326                 ASSERT(hal_attr);
 327                 ddi_dma_attr_merge(attr, hal_attr);
 328         }
 329         status = ddi_dma_allochdl(dip, rdip, attr, waitfnp, arg, handlep);
 330         TNF_PROBE_1_DEBUG(nx1394_dma_allochdl_exit, S1394_TNF_SL_NEXUS_STACK,
 331             "", tnf_int, status, status);
 332         return (status);
 333 }
 334 
 335 /*
 336  * nx1394_get_event_cookie()
 337  *    Called when a child node calls ddi_get_eventcookie().
 338  *    Returns event cookie corresponding to event "name".
 339  */
 340 static int
 341 nx1394_get_event_cookie(dev_info_t *dip, dev_info_t *rdip, char *name,
 342     ddi_eventcookie_t *event_cookiep)
 343 {
 344         int ret;
 345         s1394_hal_t *hal;
 346 
 347         TNF_PROBE_1_DEBUG(nx1394_get_event_cookie_enter,
 348             S1394_TNF_SL_NEXUS_STACK, "", tnf_string, name, name);
 349 
 350         hal = s1394_dip_to_hal(dip);
 351         ASSERT(hal);
 352 
 353         ret = ndi_event_retrieve_cookie(hal->hal_ndi_event_hdl,
 354             rdip, name, event_cookiep, 0);
 355 
 356         TNF_PROBE_4_DEBUG(nx1394_get_event_cookie_exit,
 357             S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip, (void *)dip,
 358             tnf_opaque, requestor_dip, (void *)rdip, tnf_string, event_name,
 359             name, tnf_int, request_status, ret);
 360 
 361         return (ret);
 362 
 363 }
 364 
 365 /*
 366  * nx1394_add_eventcall()
 367  *    This gets called when a child node calls ddi_add_eventcall(). Registers
 368  *    the specified callback for the requested event cookie with the ndi
 369  *    event framework.
 370  *    dip is the hal dip. This routine calls ndi_event_add_callback(),
 371  *    allowing requests for events we don't generate to pass up the tree.
 372  */
 373 static int
 374 nx1394_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
 375     ddi_eventcookie_t cookie, void (*callback)(), void *arg,
 376     ddi_callback_id_t *cb_id)
 377 {
 378         int ret;
 379         s1394_hal_t *hal;
 380 #if defined(DEBUG)
 381         char *event_name = NULL;
 382 #endif
 383 
 384         hal = s1394_dip_to_hal(dip);
 385         ASSERT(hal);
 386 
 387         TNF_PROBE_0_DEBUG(nx1394_add_eventcall_enter, S1394_TNF_SL_NEXUS_STACK,
 388             "");
 389 
 390         ret = ndi_event_add_callback(hal->hal_ndi_event_hdl, rdip, cookie,
 391             callback, arg, NDI_NOSLEEP, cb_id);
 392 #if defined(DEBUG)
 393         event_name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie);
 394         if (event_name == NULL)
 395                 event_name = "";
 396 #endif
 397         TNF_PROBE_4_DEBUG(nx1394_add_eventcall_exit, S1394_TNF_SL_NEXUS_STACK,
 398             "", tnf_opaque, parent_dip, (void *)dip, tnf_opaque, requestor_dip,
 399             (void *)rdip, tnf_string, event_name, event_name, tnf_int,
 400             request_status, ret);
 401 
 402         return (ret);
 403 }
 404 
 405 /*
 406  * nx1394_remove_eventcall()
 407  *    Called as a result of a child node calling ddi_remove_eventcall().
 408  *    Unregisters the callback corresponding to the callback id passed in.
 409  */
 410 static int
 411 nx1394_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
 412 {
 413         int ret;
 414         s1394_hal_t *hal;
 415         ddi_eventcookie_t cookie;
 416 #if defined(DEBUG)
 417         char *event_name = NULL;
 418 #endif
 419 
 420         ASSERT(cb_id);
 421         cookie = ((ndi_event_callbacks_t *)cb_id)->ndi_evtcb_cookie;
 422 
 423         hal = s1394_dip_to_hal(dip);
 424         ASSERT(hal);
 425 
 426         TNF_PROBE_0_DEBUG(nx1394_remove_eventcall_enter,
 427             S1394_TNF_SL_NEXUS_STACK, "");
 428 
 429         ret = ndi_event_remove_callback(hal->hal_ndi_event_hdl, cb_id);
 430 
 431 #if defined(DEBUG)
 432         event_name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie);
 433         if (event_name == NULL)
 434                 event_name = "";
 435 
 436         TNF_PROBE_4_DEBUG(nx1394_remove_eventcall_exit,
 437             S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip, (void *)dip,
 438             tnf_opaque, callback_id, (void *)cb_id, tnf_string, event_name,
 439             event_name, tnf_int, request_status, ret);
 440 #endif
 441 
 442         return (ret);
 443 }
 444 
 445 /*
 446  * nx1394_post_event()
 447  *    Called when a child node calls ddi_post_event. If the event is one of
 448  *    the events supported by us (bus reset/insert/remove, for now), builds
 449  *    a t1394_localinfo_t structure and calls ndi_event_run_callbacks(). This
 450  *    will result in all registered callbacks being invoked with
 451  *    t1394_localinfo_t as the impl_data. (see ddi_add_eventcall for callback
 452  *    arguments.) If the event is not defined by us, the request is
 453  *    propagated up the device tree by calling ndi_post_event().
 454  */
 455 static int
 456 nx1394_post_event(dev_info_t *dip, dev_info_t *rdip, ddi_eventcookie_t cookie,
 457     void *impl_data)
 458 {
 459         int ret;
 460         char *name;
 461         s1394_hal_t *hal;
 462         t1394_localinfo_t localinfo;
 463 
 464         hal = s1394_dip_to_hal(dip);
 465         ASSERT(hal);
 466 
 467         TNF_PROBE_0_DEBUG(nx1394_post_event_enter, S1394_TNF_SL_NEXUS_STACK,
 468             "");
 469 
 470         name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie);
 471         /* name is NULL if we don't generate the event */
 472         if (name != NULL) {
 473 
 474                 mutex_enter(&hal->topology_tree_mutex);
 475                 localinfo.bus_generation = hal->generation_count;
 476                 localinfo.local_nodeID = hal->node_id;
 477                 mutex_exit(&hal->topology_tree_mutex);
 478                 impl_data = &localinfo;
 479 
 480                 ret = ndi_event_run_callbacks(hal->hal_ndi_event_hdl,
 481                     rdip, cookie, impl_data);
 482 
 483                 TNF_PROBE_4_DEBUG(nx1394_post_event_exit,
 484                     S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip,
 485                     (void *)dip, tnf_opaque, requestor_dip, (void *)rdip,
 486                     tnf_string, event_name, name, tnf_int, request_status, ret);
 487                 return (ret);
 488 
 489         } else {
 490                 ret = ndi_post_event(ddi_get_parent(dip), rdip, cookie,
 491                     impl_data);
 492                 TNF_PROBE_2_DEBUG(nx1394_post_event_exit,
 493                     S1394_TNF_SL_NEXUS_STACK, "", tnf_string, msg,
 494                     "Not our event", tnf_int, ret, ret);
 495                 return (ret);
 496         }
 497 }
 498 
 499 /*
 500  * nx1394_define_events()
 501  *    Allocates event handle for the hal dip and binds event set to it.
 502  */
 503 int
 504 nx1394_define_events(s1394_hal_t *hal)
 505 {
 506         int ret;
 507 
 508         TNF_PROBE_0_DEBUG(nx1394_define_events_enter, S1394_TNF_SL_NEXUS_STACK,
 509             "");
 510 
 511         /* get event handle */
 512         ret = ndi_event_alloc_hdl(hal->halinfo.dip, hal->halinfo.hw_interrupt,
 513             &hal->hal_ndi_event_hdl, NDI_SLEEP);
 514         if (ret != NDI_SUCCESS) {
 515                 TNF_PROBE_1(nx1394_define_events_alloc_fail,
 516                     S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret);
 517         } else {
 518                 /* and bind to it */
 519                 ret = ndi_event_bind_set(hal->hal_ndi_event_hdl, &nx1394_events,
 520                     NDI_SLEEP);
 521                 if (ret != NDI_SUCCESS) {
 522                         TNF_PROBE_1(nx1394_define_events_bind_fail,
 523                             S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret);
 524                         (void) ndi_event_free_hdl(hal->hal_ndi_event_hdl);
 525                         TNF_PROBE_0_DEBUG(nx1394_define_events_exit,
 526                             S1394_TNF_SL_NEXUS_STACK, "");
 527                         return (DDI_FAILURE);
 528                 }
 529         }
 530 
 531         TNF_PROBE_0_DEBUG(nx1394_define_events_exit, S1394_TNF_SL_NEXUS_STACK,
 532             "");
 533 
 534         return (DDI_SUCCESS);
 535 }
 536 
 537 /*
 538  * nx1394_undefine_events()
 539  *    Unbinds event set bound to the hal and frees the event handle.
 540  */
 541 void
 542 nx1394_undefine_events(s1394_hal_t *hal)
 543 {
 544         int ret;
 545 
 546         TNF_PROBE_0_DEBUG(nx1394_undefine_events_enter,
 547             S1394_TNF_SL_NEXUS_STACK, "");
 548 
 549         ret = ndi_event_unbind_set(hal->hal_ndi_event_hdl, &nx1394_events,
 550             NDI_SLEEP);
 551         if (ret != NDI_SUCCESS) {
 552                 TNF_PROBE_1(nx1394_undefine_events_unbind_fail,
 553                     S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret);
 554         } else {
 555                 ret = ndi_event_free_hdl(hal->hal_ndi_event_hdl);
 556                 if (ret != NDI_SUCCESS) {
 557                         TNF_PROBE_1(nx1394_undefine_events_free_hdl_fail,
 558                             S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret);
 559                 }
 560         }
 561 
 562         TNF_PROBE_0_DEBUG(nx1394_undefine_events_exit,
 563             S1394_TNF_SL_NEXUS_STACK, "");
 564 }