xref: /illumos-gate/usr/src/uts/common/io/1394/nx1394.c (revision 069e6b7e31ba5dcbc5441b98af272714d9a5455c)
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 }
565