xref: /titanic_51/usr/src/uts/common/io/1394/s1394_misc.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * s1394_misc.c
31*7c478bd9Sstevel@tonic-gate  *    1394 Services Layer Miscellaneous Routines
32*7c478bd9Sstevel@tonic-gate  *    This file contains miscellaneous routines used as "helper" functions
33*7c478bd9Sstevel@tonic-gate  *    by various other files in the Services Layer.
34*7c478bd9Sstevel@tonic-gate  */
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/tnf_probe.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #include <sys/1394/t1394.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/1394/s1394.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/1394/ieee1394.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate int s1394_print_guids = 0;		/* patch to print GUIDs */
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate extern void nx1394_undefine_events(s1394_hal_t *hal);
53*7c478bd9Sstevel@tonic-gate static void s1394_cleanup_node_cfgrom(s1394_hal_t *hal);
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /*
56*7c478bd9Sstevel@tonic-gate  * s1394_cleanup_for_detach()
57*7c478bd9Sstevel@tonic-gate  *    is used to do all of the necessary cleanup to handle a detach or a
58*7c478bd9Sstevel@tonic-gate  *    failure in h1394_attach().  The cleanup_level specifies how far we
59*7c478bd9Sstevel@tonic-gate  *    got in h1394_attach() before failure.
60*7c478bd9Sstevel@tonic-gate  */
61*7c478bd9Sstevel@tonic-gate void
62*7c478bd9Sstevel@tonic-gate s1394_cleanup_for_detach(s1394_hal_t *hal, uint_t cleanup_level)
63*7c478bd9Sstevel@tonic-gate {
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_cleanup_for_detach_enter, S1394_TNF_SL_STACK,
66*7c478bd9Sstevel@tonic-gate 	    "");
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate 	switch (cleanup_level) {
69*7c478bd9Sstevel@tonic-gate 	case H1394_CLEANUP_LEVEL7:
70*7c478bd9Sstevel@tonic-gate 		/* remove HAL from the global HAL list */
71*7c478bd9Sstevel@tonic-gate 		mutex_enter(&s1394_statep->hal_list_mutex);
72*7c478bd9Sstevel@tonic-gate 		if ((s1394_statep->hal_head == hal) &&
73*7c478bd9Sstevel@tonic-gate 		    (s1394_statep->hal_tail == hal)) {
74*7c478bd9Sstevel@tonic-gate 			s1394_statep->hal_head = NULL;
75*7c478bd9Sstevel@tonic-gate 			s1394_statep->hal_tail = NULL;
76*7c478bd9Sstevel@tonic-gate 		} else {
77*7c478bd9Sstevel@tonic-gate 			if (hal->hal_prev)
78*7c478bd9Sstevel@tonic-gate 				hal->hal_prev->hal_next = hal->hal_next;
79*7c478bd9Sstevel@tonic-gate 			if (hal->hal_next)
80*7c478bd9Sstevel@tonic-gate 				hal->hal_next->hal_prev = hal->hal_prev;
81*7c478bd9Sstevel@tonic-gate 			if (s1394_statep->hal_head == hal)
82*7c478bd9Sstevel@tonic-gate 				s1394_statep->hal_head = hal->hal_next;
83*7c478bd9Sstevel@tonic-gate 			if (s1394_statep->hal_tail == hal)
84*7c478bd9Sstevel@tonic-gate 				s1394_statep->hal_tail = hal->hal_prev;
85*7c478bd9Sstevel@tonic-gate 		}
86*7c478bd9Sstevel@tonic-gate 		mutex_exit(&s1394_statep->hal_list_mutex);
87*7c478bd9Sstevel@tonic-gate 		/*
88*7c478bd9Sstevel@tonic-gate 		 * No FCP cleanup needed at this time -- the following call
89*7c478bd9Sstevel@tonic-gate 		 * to s1394_destroy_addr_space() takes care of everything.
90*7c478bd9Sstevel@tonic-gate 		 */
91*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 	case H1394_CLEANUP_LEVEL6:
94*7c478bd9Sstevel@tonic-gate 		s1394_destroy_addr_space(hal);
95*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	case H1394_CLEANUP_LEVEL5:
98*7c478bd9Sstevel@tonic-gate 		s1394_destroy_local_config_rom(hal);
99*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 	case H1394_CLEANUP_LEVEL4:
102*7c478bd9Sstevel@tonic-gate 		/* Undo all the kstat stuff */
103*7c478bd9Sstevel@tonic-gate 		(void) s1394_kstat_delete(hal);
104*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	case H1394_CLEANUP_LEVEL3:
107*7c478bd9Sstevel@tonic-gate 		/* Free up the memory for selfID buffer #1 */
108*7c478bd9Sstevel@tonic-gate 		kmem_free(hal->selfid_buf1, S1394_SELFID_BUF_SIZE);
109*7c478bd9Sstevel@tonic-gate 		/* Free up the memory for selfID buffer #0 */
110*7c478bd9Sstevel@tonic-gate 		kmem_free(hal->selfid_buf0, S1394_SELFID_BUF_SIZE);
111*7c478bd9Sstevel@tonic-gate 		/* Turn off any timers that might be set */
112*7c478bd9Sstevel@tonic-gate 		s1394_destroy_timers(hal);
113*7c478bd9Sstevel@tonic-gate 		/* Destroy the bus_reset thread */
114*7c478bd9Sstevel@tonic-gate 		s1394_destroy_br_thread(hal);
115*7c478bd9Sstevel@tonic-gate 		/* Cleanup the Config ROM buffers in the topology_tree */
116*7c478bd9Sstevel@tonic-gate 		s1394_cleanup_node_cfgrom(hal);
117*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	case H1394_CLEANUP_LEVEL2:
120*7c478bd9Sstevel@tonic-gate 		/* Destroy the br_cmplq_cv and br_cmplq_mutex */
121*7c478bd9Sstevel@tonic-gate 		cv_destroy(&hal->br_cmplq_cv);
122*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&hal->br_cmplq_mutex);
123*7c478bd9Sstevel@tonic-gate 		/* Destroy the br_thread_cv and br_thread_mutex */
124*7c478bd9Sstevel@tonic-gate 		cv_destroy(&hal->br_thread_cv);
125*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&hal->br_thread_mutex);
126*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	case H1394_CLEANUP_LEVEL1:
129*7c478bd9Sstevel@tonic-gate 		(void) ddi_prop_remove_all(hal->halinfo.dip);
130*7c478bd9Sstevel@tonic-gate 		nx1394_undefine_events(hal);
131*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	case H1394_CLEANUP_LEVEL0:
134*7c478bd9Sstevel@tonic-gate 		kmem_cache_destroy(hal->hal_kmem_cachep);
135*7c478bd9Sstevel@tonic-gate 		/* Destroy pending_q_mutex and outstanding_q_mutex */
136*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&hal->pending_q_mutex);
137*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&hal->outstanding_q_mutex);
138*7c478bd9Sstevel@tonic-gate 		/* Destroy target_list_rwlock */
139*7c478bd9Sstevel@tonic-gate 		rw_destroy(&hal->target_list_rwlock);
140*7c478bd9Sstevel@tonic-gate 		/* Destroy bus_mgr_node_mutex and bus_mgr_node_cv */
141*7c478bd9Sstevel@tonic-gate 		cv_destroy(&hal->bus_mgr_node_cv);
142*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&hal->bus_mgr_node_mutex);
143*7c478bd9Sstevel@tonic-gate 		/* Destroy isoch_cec_list_mutex */
144*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&hal->isoch_cec_list_mutex);
145*7c478bd9Sstevel@tonic-gate 		/* Destroy the Cycle Master timer mutex */
146*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&hal->cm_timer_mutex);
147*7c478bd9Sstevel@tonic-gate 		/* Destroy topology_tree_mutex */
148*7c478bd9Sstevel@tonic-gate 		mutex_destroy(&hal->topology_tree_mutex);
149*7c478bd9Sstevel@tonic-gate 		/* Free the hal structure */
150*7c478bd9Sstevel@tonic-gate 		kmem_free(hal, sizeof (s1394_hal_t));
151*7c478bd9Sstevel@tonic-gate 		break;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	default:
154*7c478bd9Sstevel@tonic-gate 		/* Error */
155*7c478bd9Sstevel@tonic-gate 		TNF_PROBE_1(s1394_cleanup_for_detach_error,
156*7c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ERROR, "", tnf_string, msg,
157*7c478bd9Sstevel@tonic-gate 		    "Invalid cleanup_level");
158*7c478bd9Sstevel@tonic-gate 		break;
159*7c478bd9Sstevel@tonic-gate 	}
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_cleanup_for_detach_exit, S1394_TNF_SL_STACK,
162*7c478bd9Sstevel@tonic-gate 	    "");
163*7c478bd9Sstevel@tonic-gate }
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate /*
166*7c478bd9Sstevel@tonic-gate  * s1394_hal_shutdown()
167*7c478bd9Sstevel@tonic-gate  *    is used to shutdown the HAL.  If the HAL indicates that an error
168*7c478bd9Sstevel@tonic-gate  *    condition (hardware or software) has occurred, it is shutdown. This
169*7c478bd9Sstevel@tonic-gate  *    routine is also called when HAL informs the services layer of a shutdown
170*7c478bd9Sstevel@tonic-gate  *    (due an internal shutdown, for eg). disable_hal indicates whether the
171*7c478bd9Sstevel@tonic-gate  *    caller intends to inform the hal of the (services layer) shutdown or not.
172*7c478bd9Sstevel@tonic-gate  */
173*7c478bd9Sstevel@tonic-gate void
174*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(s1394_hal_t *hal, boolean_t disable_hal)
175*7c478bd9Sstevel@tonic-gate {
176*7c478bd9Sstevel@tonic-gate 	ddi_eventcookie_t cookie;
177*7c478bd9Sstevel@tonic-gate 	t1394_localinfo_t localinfo;
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_hal_shutdown_enter, S1394_TNF_SL_STACK, "");
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	if (hal->hal_state == S1394_HAL_SHUTDOWN) {
184*7c478bd9Sstevel@tonic-gate 		mutex_exit(&hal->topology_tree_mutex);
185*7c478bd9Sstevel@tonic-gate 		if (disable_hal == B_TRUE)
186*7c478bd9Sstevel@tonic-gate 			HAL_CALL(hal).shutdown(hal->halinfo.hal_private);
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_hal_shutdown_exit_already,
189*7c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_STACK, "");
190*7c478bd9Sstevel@tonic-gate 		return;
191*7c478bd9Sstevel@tonic-gate 	}
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	hal->hal_state = S1394_HAL_SHUTDOWN;
194*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
195*7c478bd9Sstevel@tonic-gate 	/* Disable the HAL */
196*7c478bd9Sstevel@tonic-gate 	if (disable_hal == B_TRUE)
197*7c478bd9Sstevel@tonic-gate 		HAL_CALL(hal).shutdown(hal->halinfo.hal_private);
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	/*
200*7c478bd9Sstevel@tonic-gate 	 * Send a remove event to all interested parties
201*7c478bd9Sstevel@tonic-gate 	 */
202*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
203*7c478bd9Sstevel@tonic-gate 	localinfo.bus_generation = hal->generation_count;
204*7c478bd9Sstevel@tonic-gate 	localinfo.local_nodeID	 = hal->node_id;
205*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	if (ndi_event_retrieve_cookie(hal->hal_ndi_event_hdl, NULL,
208*7c478bd9Sstevel@tonic-gate 	    DDI_DEVI_REMOVE_EVENT, &cookie, NDI_EVENT_NOPASS) ==
209*7c478bd9Sstevel@tonic-gate 	    NDI_SUCCESS)
210*7c478bd9Sstevel@tonic-gate 		(void) ndi_event_run_callbacks(hal->hal_ndi_event_hdl, NULL,
211*7c478bd9Sstevel@tonic-gate 		    cookie, &localinfo);
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_hal_shutdown_exit, S1394_TNF_SL_STACK, "");
214*7c478bd9Sstevel@tonic-gate }
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate /*
217*7c478bd9Sstevel@tonic-gate  * s1394_initiate_hal_reset()
218*7c478bd9Sstevel@tonic-gate  *    sets up the HAL structure to indicate a self-initiated bus reset and
219*7c478bd9Sstevel@tonic-gate  *    calls the appropriate HAL entry point.  If too many bus resets have
220*7c478bd9Sstevel@tonic-gate  *    happened, a message is printed out and the call is ignored.
221*7c478bd9Sstevel@tonic-gate  */
222*7c478bd9Sstevel@tonic-gate void
223*7c478bd9Sstevel@tonic-gate s1394_initiate_hal_reset(s1394_hal_t *hal, int reason)
224*7c478bd9Sstevel@tonic-gate {
225*7c478bd9Sstevel@tonic-gate 	int ret;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_initiate_hal_reset_enter, S1394_TNF_SL_BR_STACK,
228*7c478bd9Sstevel@tonic-gate 	    "");
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	if (hal->num_bus_reset_till_fail > 0) {
231*7c478bd9Sstevel@tonic-gate 		hal->initiated_bus_reset = B_TRUE;
232*7c478bd9Sstevel@tonic-gate 		hal->initiated_br_reason = reason;
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 		/* Reset the bus */
235*7c478bd9Sstevel@tonic-gate 		ret = HAL_CALL(hal).bus_reset(hal->halinfo.hal_private);
236*7c478bd9Sstevel@tonic-gate 		if (ret != DDI_SUCCESS) {
237*7c478bd9Sstevel@tonic-gate 			TNF_PROBE_1(s1394_initiate_hal_reset_error,
238*7c478bd9Sstevel@tonic-gate 			    S1394_TNF_SL_ERROR, "", tnf_string, msg,
239*7c478bd9Sstevel@tonic-gate 			    "Error initiating bus reset");
240*7c478bd9Sstevel@tonic-gate 		}
241*7c478bd9Sstevel@tonic-gate 	} else {
242*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "Unable to reenumerate the 1394 bus - If new"
243*7c478bd9Sstevel@tonic-gate 		    " devices have recently been added, remove them.");
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_initiate_hal_reset_exit, S1394_TNF_SL_BR_STACK,
247*7c478bd9Sstevel@tonic-gate 	    "");
248*7c478bd9Sstevel@tonic-gate }
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate /*
251*7c478bd9Sstevel@tonic-gate  * s1394_on_br_thread()
252*7c478bd9Sstevel@tonic-gate  *    is used to determine if the current thread of execution is the same
253*7c478bd9Sstevel@tonic-gate  *    as the bus reset thread.  This is useful during bus reset callbacks
254*7c478bd9Sstevel@tonic-gate  *    to determine whether or not a target may block.
255*7c478bd9Sstevel@tonic-gate  */
256*7c478bd9Sstevel@tonic-gate boolean_t
257*7c478bd9Sstevel@tonic-gate s1394_on_br_thread(s1394_hal_t *hal)
258*7c478bd9Sstevel@tonic-gate {
259*7c478bd9Sstevel@tonic-gate 	if (hal->br_thread == curthread)
260*7c478bd9Sstevel@tonic-gate 		return (B_TRUE);
261*7c478bd9Sstevel@tonic-gate 	else
262*7c478bd9Sstevel@tonic-gate 		return (B_FALSE);
263*7c478bd9Sstevel@tonic-gate }
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate /*
266*7c478bd9Sstevel@tonic-gate  * s1394_destroy_br_thread()
267*7c478bd9Sstevel@tonic-gate  *    is used in h1394_detach() to signal the bus reset thread to go away.
268*7c478bd9Sstevel@tonic-gate  */
269*7c478bd9Sstevel@tonic-gate void
270*7c478bd9Sstevel@tonic-gate s1394_destroy_br_thread(s1394_hal_t *hal)
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_destroy_br_thread_enter, S1394_TNF_SL_STACK,
273*7c478bd9Sstevel@tonic-gate 	    "");
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	/* Send the signal to the reset thread to go away */
276*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->br_thread_mutex);
277*7c478bd9Sstevel@tonic-gate 	hal->br_thread_ev_type |= BR_THR_GO_AWAY;
278*7c478bd9Sstevel@tonic-gate 	cv_signal(&hal->br_thread_cv);
279*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->br_thread_mutex);
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	/* Wakeup the bus_reset thread if waiting for bus_mgr timer */
282*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->bus_mgr_node_mutex);
283*7c478bd9Sstevel@tonic-gate 	hal->bus_mgr_node = S1394_INVALID_NODE_NUM;
284*7c478bd9Sstevel@tonic-gate 	cv_signal(&hal->bus_mgr_node_cv);
285*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->bus_mgr_node_mutex);
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->br_cmplq_mutex);
288*7c478bd9Sstevel@tonic-gate 	cv_signal(&hal->br_cmplq_cv);
289*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->br_cmplq_mutex);
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 	/* Wait for the br_thread to be done */
292*7c478bd9Sstevel@tonic-gate 	while (hal->br_thread_ev_type & BR_THR_GO_AWAY)
293*7c478bd9Sstevel@tonic-gate 		delay(drv_usectohz(10));
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_destroy_br_thread_exit, S1394_TNF_SL_STACK,
296*7c478bd9Sstevel@tonic-gate 	    "");
297*7c478bd9Sstevel@tonic-gate }
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate /*
300*7c478bd9Sstevel@tonic-gate  * s1394_tickle_bus_reset_thread()
301*7c478bd9Sstevel@tonic-gate  *    is used to wakeup the bus reset thread after the interrupt routine
302*7c478bd9Sstevel@tonic-gate  *    has completed its bus reset processing.
303*7c478bd9Sstevel@tonic-gate  */
304*7c478bd9Sstevel@tonic-gate void
305*7c478bd9Sstevel@tonic-gate s1394_tickle_bus_reset_thread(s1394_hal_t *hal)
306*7c478bd9Sstevel@tonic-gate {
307*7c478bd9Sstevel@tonic-gate 	if (hal->topology_tree_processed != B_TRUE) {
308*7c478bd9Sstevel@tonic-gate 		/* Send the signal to the reset thread */
309*7c478bd9Sstevel@tonic-gate 		mutex_enter(&hal->br_thread_mutex);
310*7c478bd9Sstevel@tonic-gate 		hal->br_thread_ev_type |= BR_THR_CFGROM_SCAN;
311*7c478bd9Sstevel@tonic-gate 		cv_signal(&hal->br_thread_cv);
312*7c478bd9Sstevel@tonic-gate 		mutex_exit(&hal->br_thread_mutex);
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate 		/* Signal the msgq wait, too (just in case) */
315*7c478bd9Sstevel@tonic-gate 		mutex_enter(&hal->br_cmplq_mutex);
316*7c478bd9Sstevel@tonic-gate 		cv_signal(&hal->br_cmplq_cv);
317*7c478bd9Sstevel@tonic-gate 		mutex_exit(&hal->br_cmplq_mutex);
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 		/* Signal the bus_mgr wait, too (just in case) */
320*7c478bd9Sstevel@tonic-gate 		mutex_enter(&hal->bus_mgr_node_mutex);
321*7c478bd9Sstevel@tonic-gate 		cv_signal(&hal->bus_mgr_node_cv);
322*7c478bd9Sstevel@tonic-gate 		mutex_exit(&hal->bus_mgr_node_mutex);
323*7c478bd9Sstevel@tonic-gate 	}
324*7c478bd9Sstevel@tonic-gate }
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate /*
327*7c478bd9Sstevel@tonic-gate  * s1394_block_on_asynch_cmd()
328*7c478bd9Sstevel@tonic-gate  *    is used by many of the asynch routines to block (if necessary)
329*7c478bd9Sstevel@tonic-gate  *    while waiting for command completion.
330*7c478bd9Sstevel@tonic-gate  */
331*7c478bd9Sstevel@tonic-gate void
332*7c478bd9Sstevel@tonic-gate s1394_block_on_asynch_cmd(cmd1394_cmd_t	*cmd)
333*7c478bd9Sstevel@tonic-gate {
334*7c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t  *s_priv;
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_block_on_asynch_cmd_enter,
337*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	/* Get the Services Layer private area */
340*7c478bd9Sstevel@tonic-gate 	s_priv = S1394_GET_CMD_PRIV(cmd);
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate 	/* Is this a blocking command? */
343*7c478bd9Sstevel@tonic-gate 	if (cmd->cmd_options & CMD1394_BLOCKING) {
344*7c478bd9Sstevel@tonic-gate 		/* Block until command completes */
345*7c478bd9Sstevel@tonic-gate 		mutex_enter(&s_priv->blocking_mutex);
346*7c478bd9Sstevel@tonic-gate 		while (s_priv->blocking_flag != B_TRUE)
347*7c478bd9Sstevel@tonic-gate 			cv_wait(&s_priv->blocking_cv, &s_priv->blocking_mutex);
348*7c478bd9Sstevel@tonic-gate 		s_priv->blocking_flag = B_FALSE;
349*7c478bd9Sstevel@tonic-gate 		mutex_exit(&s_priv->blocking_mutex);
350*7c478bd9Sstevel@tonic-gate 	}
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_block_on_asynch_cmd_exit,
353*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
354*7c478bd9Sstevel@tonic-gate }
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate /*
357*7c478bd9Sstevel@tonic-gate  * s1394_HAL_asynch_error()
358*7c478bd9Sstevel@tonic-gate  *    is used by many of the asynch routines to determine what error
359*7c478bd9Sstevel@tonic-gate  *    code is expected in a given situation (based on HAL state).
360*7c478bd9Sstevel@tonic-gate  */
361*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
362*7c478bd9Sstevel@tonic-gate int
363*7c478bd9Sstevel@tonic-gate s1394_HAL_asynch_error(s1394_hal_t *hal, cmd1394_cmd_t *cmd,
364*7c478bd9Sstevel@tonic-gate     s1394_hal_state_t state)
365*7c478bd9Sstevel@tonic-gate {
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	switch (state) {
370*7c478bd9Sstevel@tonic-gate 	case S1394_HAL_RESET:
371*7c478bd9Sstevel@tonic-gate 		/* "dreq" bit is set (CSR) */
372*7c478bd9Sstevel@tonic-gate 		if (hal->disable_requests_bit == 1)
373*7c478bd9Sstevel@tonic-gate 			return (CMD1394_ENO_ATREQ);
374*7c478bd9Sstevel@tonic-gate 		else
375*7c478bd9Sstevel@tonic-gate 			return (CMD1394_CMDSUCCESS);
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	case S1394_HAL_DREQ:
378*7c478bd9Sstevel@tonic-gate 		/* "dreq" bit is set (CSR) */
379*7c478bd9Sstevel@tonic-gate 		return (CMD1394_ENO_ATREQ);
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	case S1394_HAL_SHUTDOWN:
382*7c478bd9Sstevel@tonic-gate 		return (CMD1394_EFATAL_ERROR);
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	default:
385*7c478bd9Sstevel@tonic-gate 		return (CMD1394_CMDSUCCESS);
386*7c478bd9Sstevel@tonic-gate 	}
387*7c478bd9Sstevel@tonic-gate }
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate /*
390*7c478bd9Sstevel@tonic-gate  * s1394_mblk_too_small()
391*7c478bd9Sstevel@tonic-gate  *    is used to determine if the mlbk_t structure(s) given in an asynch
392*7c478bd9Sstevel@tonic-gate  *    block request are sufficient to hold the amount of data requested.
393*7c478bd9Sstevel@tonic-gate  */
394*7c478bd9Sstevel@tonic-gate boolean_t
395*7c478bd9Sstevel@tonic-gate s1394_mblk_too_small(cmd1394_cmd_t *cmd)
396*7c478bd9Sstevel@tonic-gate {
397*7c478bd9Sstevel@tonic-gate 	mblk_t	  *curr_blk;
398*7c478bd9Sstevel@tonic-gate 	boolean_t flag;
399*7c478bd9Sstevel@tonic-gate 	size_t	  msgb_len;
400*7c478bd9Sstevel@tonic-gate 	size_t	  size;
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_mblk_too_small_enter, S1394_TNF_SL_ATREQ_STACK,
403*7c478bd9Sstevel@tonic-gate 	    "");
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	curr_blk = cmd->cmd_u.b.data_block;
406*7c478bd9Sstevel@tonic-gate 	msgb_len = 0;
407*7c478bd9Sstevel@tonic-gate 	flag = B_TRUE;
408*7c478bd9Sstevel@tonic-gate 	size = cmd->cmd_u.b.blk_length;
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	while (curr_blk != NULL) {
411*7c478bd9Sstevel@tonic-gate 		if (cmd->cmd_type == CMD1394_ASYNCH_WR_BLOCK) {
412*7c478bd9Sstevel@tonic-gate 			msgb_len += (curr_blk->b_wptr - curr_blk->b_rptr);
413*7c478bd9Sstevel@tonic-gate 		} else {
414*7c478bd9Sstevel@tonic-gate 			msgb_len +=
415*7c478bd9Sstevel@tonic-gate 			    (curr_blk->b_datap->db_lim - curr_blk->b_wptr);
416*7c478bd9Sstevel@tonic-gate 		}
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 		if (msgb_len >= size) {
419*7c478bd9Sstevel@tonic-gate 			flag = B_FALSE;
420*7c478bd9Sstevel@tonic-gate 			break;
421*7c478bd9Sstevel@tonic-gate 		}
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 		curr_blk = curr_blk->b_cont;
424*7c478bd9Sstevel@tonic-gate 	}
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_mblk_too_small_exit, S1394_TNF_SL_ATREQ_STACK,
427*7c478bd9Sstevel@tonic-gate 	    "");
428*7c478bd9Sstevel@tonic-gate 	return (flag);
429*7c478bd9Sstevel@tonic-gate }
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate /*
432*7c478bd9Sstevel@tonic-gate  * s1394_address_rollover()
433*7c478bd9Sstevel@tonic-gate  *    is used to determine if the address given will rollover the 48-bit
434*7c478bd9Sstevel@tonic-gate  *    address space.
435*7c478bd9Sstevel@tonic-gate  */
436*7c478bd9Sstevel@tonic-gate boolean_t
437*7c478bd9Sstevel@tonic-gate s1394_address_rollover(cmd1394_cmd_t *cmd)
438*7c478bd9Sstevel@tonic-gate {
439*7c478bd9Sstevel@tonic-gate 	uint64_t addr_before;
440*7c478bd9Sstevel@tonic-gate 	uint64_t addr_after;
441*7c478bd9Sstevel@tonic-gate 	size_t	 length;
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_address_rollover_enter,
444*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 	switch (cmd->cmd_type) {
447*7c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_QUAD:
448*7c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_QUAD:
449*7c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_32:
450*7c478bd9Sstevel@tonic-gate 		length = IEEE1394_QUADLET;
451*7c478bd9Sstevel@tonic-gate 		break;
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_LOCK_64:
454*7c478bd9Sstevel@tonic-gate 		length = IEEE1394_OCTLET;
455*7c478bd9Sstevel@tonic-gate 		break;
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_RD_BLOCK:
458*7c478bd9Sstevel@tonic-gate 	case CMD1394_ASYNCH_WR_BLOCK:
459*7c478bd9Sstevel@tonic-gate 		length = cmd->cmd_u.b.blk_length;
460*7c478bd9Sstevel@tonic-gate 		break;
461*7c478bd9Sstevel@tonic-gate 	}
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	addr_before = cmd->cmd_addr & IEEE1394_ADDR_OFFSET_MASK;
464*7c478bd9Sstevel@tonic-gate 	addr_after = (addr_before + length) & IEEE1394_ADDR_OFFSET_MASK;
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 	if (addr_after < addr_before) {
467*7c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_address_rollover_exit,
468*7c478bd9Sstevel@tonic-gate 		    S1394_TNF_SL_ATREQ_STACK, "");
469*7c478bd9Sstevel@tonic-gate 		return (B_TRUE);
470*7c478bd9Sstevel@tonic-gate 	}
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_address_rollover_exit,
473*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_ATREQ_STACK, "");
474*7c478bd9Sstevel@tonic-gate 	return (B_FALSE);
475*7c478bd9Sstevel@tonic-gate }
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate /*
478*7c478bd9Sstevel@tonic-gate  * s1394_stoi()
479*7c478bd9Sstevel@tonic-gate  *    returns the integer value of the string of hex/dec/oct numeric characters
480*7c478bd9Sstevel@tonic-gate  *    beginning at *p. Does no overflow checking.
481*7c478bd9Sstevel@tonic-gate  */
482*7c478bd9Sstevel@tonic-gate uint_t
483*7c478bd9Sstevel@tonic-gate s1394_stoi(char *p, int len, int base)
484*7c478bd9Sstevel@tonic-gate {
485*7c478bd9Sstevel@tonic-gate 	int	n;
486*7c478bd9Sstevel@tonic-gate 	int	c;
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	if (len == 0)
489*7c478bd9Sstevel@tonic-gate 		return (0);
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 	for (n = 0; len && (c = *p); p++, len--) {
492*7c478bd9Sstevel@tonic-gate 		if (c >= '0' && c <= '9')
493*7c478bd9Sstevel@tonic-gate 			c = c - '0';
494*7c478bd9Sstevel@tonic-gate 		else if (c >= 'a' && c <= 'f')
495*7c478bd9Sstevel@tonic-gate 			c = c - 'a' + 10;
496*7c478bd9Sstevel@tonic-gate 		else if (c >= 'A' && c <= 'F')
497*7c478bd9Sstevel@tonic-gate 			c = c - 'F' + 10;
498*7c478bd9Sstevel@tonic-gate 		n = (n * base) + c;
499*7c478bd9Sstevel@tonic-gate 	}
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	return (n);
502*7c478bd9Sstevel@tonic-gate }
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate /*
505*7c478bd9Sstevel@tonic-gate  * s1394_CRC16()
506*7c478bd9Sstevel@tonic-gate  *    implements ISO/IEC 13213:1994, ANSI/IEEE Std 1212, 1994 - 8.1.5
507*7c478bd9Sstevel@tonic-gate  */
508*7c478bd9Sstevel@tonic-gate uint_t
509*7c478bd9Sstevel@tonic-gate s1394_CRC16(uint_t *d, uint_t crc_length)
510*7c478bd9Sstevel@tonic-gate {
511*7c478bd9Sstevel@tonic-gate 	uint_t	CRC = 0;
512*7c478bd9Sstevel@tonic-gate 	uint_t	data;
513*7c478bd9Sstevel@tonic-gate 	uint_t	next;
514*7c478bd9Sstevel@tonic-gate 	uint_t	sum;
515*7c478bd9Sstevel@tonic-gate 	int	shift;
516*7c478bd9Sstevel@tonic-gate 	int	i;
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_CRC16_enter, S1394_TNF_SL_STACK, "");
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < crc_length; i++) {
521*7c478bd9Sstevel@tonic-gate 		data = d[i];
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 		/* Another check should be made with "shift > 0" in  */
524*7c478bd9Sstevel@tonic-gate 		/* order to support any devices that coded it wrong. */
525*7c478bd9Sstevel@tonic-gate 		for (next = CRC, shift = 28; shift >= 0; shift -= 4) {
526*7c478bd9Sstevel@tonic-gate 			sum = ((next >> 12) ^ (data >> shift)) & 0xF;
527*7c478bd9Sstevel@tonic-gate 			next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
528*7c478bd9Sstevel@tonic-gate 		}
529*7c478bd9Sstevel@tonic-gate 		CRC = next & IEEE1394_CRC16_MASK;
530*7c478bd9Sstevel@tonic-gate 	}
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_CRC16_exit, S1394_TNF_SL_STACK, "",
533*7c478bd9Sstevel@tonic-gate 	    tnf_uint, crc, CRC);
534*7c478bd9Sstevel@tonic-gate 	return (CRC);
535*7c478bd9Sstevel@tonic-gate }
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate /*
538*7c478bd9Sstevel@tonic-gate  * s1394_CRC16_old()
539*7c478bd9Sstevel@tonic-gate  *    implements a slightly modified version of ISO/IEC 13213:1994,
540*7c478bd9Sstevel@tonic-gate  *    ANSI/IEEE Std 1212, 1994 - 8.1.5.  In the original IEEE 1212-1994
541*7c478bd9Sstevel@tonic-gate  *    specification the C code example was incorrect and some devices
542*7c478bd9Sstevel@tonic-gate  *    were manufactured using this incorrect CRC.  On CRC16 failures
543*7c478bd9Sstevel@tonic-gate  *    this CRC is tried in case it is a legacy device.
544*7c478bd9Sstevel@tonic-gate  */
545*7c478bd9Sstevel@tonic-gate uint_t
546*7c478bd9Sstevel@tonic-gate s1394_CRC16_old(uint_t *d, uint_t crc_length)
547*7c478bd9Sstevel@tonic-gate {
548*7c478bd9Sstevel@tonic-gate 	uint_t	CRC = 0;
549*7c478bd9Sstevel@tonic-gate 	uint_t	data;
550*7c478bd9Sstevel@tonic-gate 	uint_t	next;
551*7c478bd9Sstevel@tonic-gate 	uint_t	sum;
552*7c478bd9Sstevel@tonic-gate 	int	shift;
553*7c478bd9Sstevel@tonic-gate 	int	i;
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_CRC16_old_enter, S1394_TNF_SL_STACK, "");
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < crc_length; i++) {
558*7c478bd9Sstevel@tonic-gate 		data = d[i];
559*7c478bd9Sstevel@tonic-gate 		for (next = CRC, shift = 28; shift > 0; shift -= 4) {
560*7c478bd9Sstevel@tonic-gate 			sum = ((next >> 12) ^ (data >> shift)) & 0xF;
561*7c478bd9Sstevel@tonic-gate 			next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
562*7c478bd9Sstevel@tonic-gate 		}
563*7c478bd9Sstevel@tonic-gate 		CRC = next & IEEE1394_CRC16_MASK;
564*7c478bd9Sstevel@tonic-gate 	}
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_1_DEBUG(s1394_CRC16_old_exit, S1394_TNF_SL_STACK, "",
567*7c478bd9Sstevel@tonic-gate 	    tnf_uint, crc, CRC);
568*7c478bd9Sstevel@tonic-gate 	return (CRC);
569*7c478bd9Sstevel@tonic-gate }
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate /*
572*7c478bd9Sstevel@tonic-gate  * s1394_ioctl()
573*7c478bd9Sstevel@tonic-gate  *    implements generic ioctls (eg. devctl support) and any non-HAL ioctls.
574*7c478bd9Sstevel@tonic-gate  *    Only ioctls required for devctl support are implemented at present.
575*7c478bd9Sstevel@tonic-gate  */
576*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
577*7c478bd9Sstevel@tonic-gate int
578*7c478bd9Sstevel@tonic-gate s1394_ioctl(s1394_hal_t *hal, int cmd, intptr_t arg, int mode, cred_t *cred_p,
579*7c478bd9Sstevel@tonic-gate     int *rval_p)
580*7c478bd9Sstevel@tonic-gate {
581*7c478bd9Sstevel@tonic-gate 	struct devctl_iocdata	*dcp;
582*7c478bd9Sstevel@tonic-gate 	dev_info_t		*self;
583*7c478bd9Sstevel@tonic-gate 	int			rv = 0;
584*7c478bd9Sstevel@tonic-gate 	int			ret;
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_ioctl_enter, S1394_TNF_SL_IOCTL_STACK, "");
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	self = hal->halinfo.dip;
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate 	/*
591*7c478bd9Sstevel@tonic-gate 	 * We can use the generic implementation for these ioctls
592*7c478bd9Sstevel@tonic-gate 	 */
593*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
594*7c478bd9Sstevel@tonic-gate 	case DEVCTL_DEVICE_GETSTATE:
595*7c478bd9Sstevel@tonic-gate 	case DEVCTL_DEVICE_ONLINE:
596*7c478bd9Sstevel@tonic-gate 	case DEVCTL_DEVICE_OFFLINE:
597*7c478bd9Sstevel@tonic-gate 	case DEVCTL_DEVICE_REMOVE:
598*7c478bd9Sstevel@tonic-gate 	case DEVCTL_BUS_GETSTATE:
599*7c478bd9Sstevel@tonic-gate 		return (ndi_devctl_ioctl(self, cmd, arg, mode, 0));
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	/* Read devctl ioctl data */
603*7c478bd9Sstevel@tonic-gate 	if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) {
604*7c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_ioctl_exit, S1394_TNF_SL_IOCTL_STACK,
605*7c478bd9Sstevel@tonic-gate 		    "");
606*7c478bd9Sstevel@tonic-gate 		return (EFAULT);
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate 	case DEVCTL_DEVICE_RESET:
612*7c478bd9Sstevel@tonic-gate 	case DEVCTL_DEVICE_REMOVE:
613*7c478bd9Sstevel@tonic-gate 		rv = ENOTSUP;
614*7c478bd9Sstevel@tonic-gate 		break;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	case DEVCTL_BUS_CONFIGURE:
617*7c478bd9Sstevel@tonic-gate 	case DEVCTL_BUS_UNCONFIGURE:
618*7c478bd9Sstevel@tonic-gate 		rv = ENOTSUP;
619*7c478bd9Sstevel@tonic-gate 		break;
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 	case DEVCTL_BUS_QUIESCE:
622*7c478bd9Sstevel@tonic-gate 	case DEVCTL_BUS_UNQUIESCE:
623*7c478bd9Sstevel@tonic-gate 		rv = ENOTSUP;	/* Or call up the tree? */
624*7c478bd9Sstevel@tonic-gate 		break;
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	case DEVCTL_BUS_RESET:
627*7c478bd9Sstevel@tonic-gate 	case DEVCTL_BUS_RESETALL:
628*7c478bd9Sstevel@tonic-gate 		if (hal->halinfo.phy == H1394_PHY_1394A) {
629*7c478bd9Sstevel@tonic-gate 			ret = HAL_CALL(hal).short_bus_reset(
630*7c478bd9Sstevel@tonic-gate 			    hal->halinfo.hal_private);
631*7c478bd9Sstevel@tonic-gate 			if (ret != DDI_SUCCESS) {
632*7c478bd9Sstevel@tonic-gate 				TNF_PROBE_1(s1394_ioctl_error,
633*7c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ERROR, "", tnf_string, msg,
634*7c478bd9Sstevel@tonic-gate 				    "Error initiating short bus reset");
635*7c478bd9Sstevel@tonic-gate 			}
636*7c478bd9Sstevel@tonic-gate 		} else {
637*7c478bd9Sstevel@tonic-gate 			ret = HAL_CALL(hal).bus_reset(hal->halinfo.hal_private);
638*7c478bd9Sstevel@tonic-gate 			if (ret != DDI_SUCCESS) {
639*7c478bd9Sstevel@tonic-gate 				TNF_PROBE_1(t1394_initiate_bus_reset_error,
640*7c478bd9Sstevel@tonic-gate 				    S1394_TNF_SL_ERROR, "", tnf_string, msg,
641*7c478bd9Sstevel@tonic-gate 				    "Error initiating bus reset");
642*7c478bd9Sstevel@tonic-gate 			}
643*7c478bd9Sstevel@tonic-gate 		}
644*7c478bd9Sstevel@tonic-gate 		break;
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 	default:
647*7c478bd9Sstevel@tonic-gate 		rv = ENOTTY;
648*7c478bd9Sstevel@tonic-gate 	}
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate 	ndi_dc_freehdl(dcp);
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_ioctl_exit, S1394_TNF_SL_IOCTL_STACK, "");
653*7c478bd9Sstevel@tonic-gate 	return (rv);
654*7c478bd9Sstevel@tonic-gate }
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate /*
657*7c478bd9Sstevel@tonic-gate  * s1394_kstat_init()
658*7c478bd9Sstevel@tonic-gate  *    is used to initialize and the Services Layer's kernel statistics.
659*7c478bd9Sstevel@tonic-gate  */
660*7c478bd9Sstevel@tonic-gate int
661*7c478bd9Sstevel@tonic-gate s1394_kstat_init(s1394_hal_t *hal)
662*7c478bd9Sstevel@tonic-gate {
663*7c478bd9Sstevel@tonic-gate 	int instance;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_kstat_init_enter, S1394_TNF_SL_STACK, "");
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	hal->hal_kstats = (s1394_kstat_t *)kmem_zalloc(sizeof (s1394_kstat_t),
668*7c478bd9Sstevel@tonic-gate 	    KM_SLEEP);
669*7c478bd9Sstevel@tonic-gate 
670*7c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(hal->halinfo.dip);
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate 	hal->hal_ksp = kstat_create("s1394", instance, "stats", "misc",
673*7c478bd9Sstevel@tonic-gate 	    KSTAT_TYPE_RAW, sizeof (s1394_kstat_t), KSTAT_FLAG_VIRTUAL);
674*7c478bd9Sstevel@tonic-gate 	if (hal->hal_ksp != NULL) {
675*7c478bd9Sstevel@tonic-gate 		hal->hal_ksp->ks_private = (void *)hal;
676*7c478bd9Sstevel@tonic-gate 		hal->hal_ksp->ks_update = s1394_kstat_update;
677*7c478bd9Sstevel@tonic-gate 		kstat_install(hal->hal_ksp);
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_kstat_init_exit, S1394_TNF_SL_STACK,
680*7c478bd9Sstevel@tonic-gate 		    "");
681*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
682*7c478bd9Sstevel@tonic-gate 	} else {
683*7c478bd9Sstevel@tonic-gate 		kmem_free((void *)hal->hal_kstats, sizeof (s1394_kstat_t));
684*7c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_kstat_init_exit, S1394_TNF_SL_STACK,
685*7c478bd9Sstevel@tonic-gate 		    "");
686*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
687*7c478bd9Sstevel@tonic-gate 	}
688*7c478bd9Sstevel@tonic-gate }
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate /*
691*7c478bd9Sstevel@tonic-gate  * s1394_kstat_delete()
692*7c478bd9Sstevel@tonic-gate  *    is used (in h1394_detach()) to cleanup/free and the Services Layer's
693*7c478bd9Sstevel@tonic-gate  *    kernel statistics.
694*7c478bd9Sstevel@tonic-gate  */
695*7c478bd9Sstevel@tonic-gate int
696*7c478bd9Sstevel@tonic-gate s1394_kstat_delete(s1394_hal_t *hal)
697*7c478bd9Sstevel@tonic-gate {
698*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_kstat_delete_enter, S1394_TNF_SL_STACK, "");
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate 	kstat_delete(hal->hal_ksp);
701*7c478bd9Sstevel@tonic-gate 	kmem_free((void *)hal->hal_kstats, sizeof (s1394_kstat_t));
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_kstat_delete_exit, S1394_TNF_SL_STACK, "");
704*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
705*7c478bd9Sstevel@tonic-gate }
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate /*
708*7c478bd9Sstevel@tonic-gate  * s1394_kstat_update()
709*7c478bd9Sstevel@tonic-gate  *    is a callback that is called whenever a request to read the kernel
710*7c478bd9Sstevel@tonic-gate  *    statistics is made.
711*7c478bd9Sstevel@tonic-gate  */
712*7c478bd9Sstevel@tonic-gate int
713*7c478bd9Sstevel@tonic-gate s1394_kstat_update(kstat_t *ksp, int rw)
714*7c478bd9Sstevel@tonic-gate {
715*7c478bd9Sstevel@tonic-gate 	s1394_hal_t	*hal;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_kstat_update_enter, S1394_TNF_SL_STACK, "");
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 	hal = ksp->ks_private;
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 	if (rw == KSTAT_WRITE) {
722*7c478bd9Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(s1394_kstat_update_exit, S1394_TNF_SL_STACK,
723*7c478bd9Sstevel@tonic-gate 		    "");
724*7c478bd9Sstevel@tonic-gate 		return (EACCES);
725*7c478bd9Sstevel@tonic-gate 	} else {
726*7c478bd9Sstevel@tonic-gate 		ksp->ks_data = hal->hal_kstats;
727*7c478bd9Sstevel@tonic-gate 	}
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_kstat_update_exit, S1394_TNF_SL_STACK, "");
730*7c478bd9Sstevel@tonic-gate 	return (0);
731*7c478bd9Sstevel@tonic-gate }
732*7c478bd9Sstevel@tonic-gate 
733*7c478bd9Sstevel@tonic-gate /*
734*7c478bd9Sstevel@tonic-gate  * s1394_addr_alloc_kstat()
735*7c478bd9Sstevel@tonic-gate  *    is used by the kernel statistics to update the count for each type of
736*7c478bd9Sstevel@tonic-gate  *    address allocation.
737*7c478bd9Sstevel@tonic-gate  */
738*7c478bd9Sstevel@tonic-gate void
739*7c478bd9Sstevel@tonic-gate s1394_addr_alloc_kstat(s1394_hal_t *hal, uint64_t addr)
740*7c478bd9Sstevel@tonic-gate {
741*7c478bd9Sstevel@tonic-gate 	/* kstats - number of addr allocs */
742*7c478bd9Sstevel@tonic-gate 	if (s1394_is_posted_write(hal, addr) == B_TRUE)
743*7c478bd9Sstevel@tonic-gate 		hal->hal_kstats->addr_posted_alloc++;
744*7c478bd9Sstevel@tonic-gate 	else if (s1394_is_normal_addr(hal, addr) == B_TRUE)
745*7c478bd9Sstevel@tonic-gate 		hal->hal_kstats->addr_normal_alloc++;
746*7c478bd9Sstevel@tonic-gate 	else if (s1394_is_csr_addr(hal, addr) == B_TRUE)
747*7c478bd9Sstevel@tonic-gate 		hal->hal_kstats->addr_csr_alloc++;
748*7c478bd9Sstevel@tonic-gate 	else if (s1394_is_physical_addr(hal, addr) == B_TRUE)
749*7c478bd9Sstevel@tonic-gate 		hal->hal_kstats->addr_phys_alloc++;
750*7c478bd9Sstevel@tonic-gate }
751*7c478bd9Sstevel@tonic-gate 
752*7c478bd9Sstevel@tonic-gate /*
753*7c478bd9Sstevel@tonic-gate  * s1394_print_node_info()
754*7c478bd9Sstevel@tonic-gate  *    is used to print speed map and GUID information on the console.
755*7c478bd9Sstevel@tonic-gate  */
756*7c478bd9Sstevel@tonic-gate void
757*7c478bd9Sstevel@tonic-gate s1394_print_node_info(s1394_hal_t *hal)
758*7c478bd9Sstevel@tonic-gate {
759*7c478bd9Sstevel@tonic-gate 	int	i, j;
760*7c478bd9Sstevel@tonic-gate 	uint_t	hal_node_num;
761*7c478bd9Sstevel@tonic-gate 	char	str[200], tmp[200];
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate 	/* These are in common/os/logsubr.c */
764*7c478bd9Sstevel@tonic-gate 	extern void log_enter(void);
765*7c478bd9Sstevel@tonic-gate 	extern void log_exit(void);
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate 	if (s1394_print_guids == 0)
768*7c478bd9Sstevel@tonic-gate 		return;
769*7c478bd9Sstevel@tonic-gate 
770*7c478bd9Sstevel@tonic-gate 	hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	log_enter();
773*7c478bd9Sstevel@tonic-gate 
774*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, "Speed Map (%d):\n",
775*7c478bd9Sstevel@tonic-gate 	    ddi_get_instance(hal->halinfo.dip));
776*7c478bd9Sstevel@tonic-gate 
777*7c478bd9Sstevel@tonic-gate 	(void) strcpy(str, "    |");
778*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < hal->number_of_nodes; i++) {
779*7c478bd9Sstevel@tonic-gate 	    (void) sprintf(tmp, " %2d ", i);
780*7c478bd9Sstevel@tonic-gate 	    (void) strcat(str, tmp);
781*7c478bd9Sstevel@tonic-gate 	}
782*7c478bd9Sstevel@tonic-gate 	(void) strcat(str, "  |       GUID\n");
783*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, str);
784*7c478bd9Sstevel@tonic-gate 
785*7c478bd9Sstevel@tonic-gate 	(void) strcpy(str, "----|");
786*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < hal->number_of_nodes; i++) {
787*7c478bd9Sstevel@tonic-gate 	    (void) sprintf(tmp, "----");
788*7c478bd9Sstevel@tonic-gate 	    (void) strcat(str, tmp);
789*7c478bd9Sstevel@tonic-gate 	}
790*7c478bd9Sstevel@tonic-gate 	(void) strcat(str, "--|------------------\n");
791*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, str);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < hal->number_of_nodes; i++) {
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	    (void) sprintf(str, " %2d |", i);
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate 	    for (j = 0; j < hal->number_of_nodes; j++) {
798*7c478bd9Sstevel@tonic-gate 		(void) sprintf(tmp, " %3d", hal->speed_map[i][j]);
799*7c478bd9Sstevel@tonic-gate 		(void) strcat(str, tmp);
800*7c478bd9Sstevel@tonic-gate 	    }
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate 	    if (i == hal_node_num) {
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 		(void) strcat(str, "  | Local OHCI Card\n");
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate 	    } else if (CFGROM_BIB_READ(&hal->topology_tree[i])) {
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 		(void) sprintf(tmp, "  | %08x%08x\n",
809*7c478bd9Sstevel@tonic-gate 				    hal->topology_tree[i].node_guid_hi,
810*7c478bd9Sstevel@tonic-gate 				    hal->topology_tree[i].node_guid_lo);
811*7c478bd9Sstevel@tonic-gate 		(void) strcat(str, tmp);
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 	    } else if (hal->topology_tree[i].link_active == 0) {
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 		(void) strcat(str, "  | Link off\n");
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	    } else {
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate 		(void) strcat(str, "  | ????????????????\n");
820*7c478bd9Sstevel@tonic-gate 	    }
821*7c478bd9Sstevel@tonic-gate 	    cmn_err(CE_CONT, str);
822*7c478bd9Sstevel@tonic-gate 	}
823*7c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, "\n");
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate 	log_exit();
826*7c478bd9Sstevel@tonic-gate }
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate /*
829*7c478bd9Sstevel@tonic-gate  * s1394_dip_to_hal()
830*7c478bd9Sstevel@tonic-gate  *    is used to lookup a HAL's structure pointer by its dip.
831*7c478bd9Sstevel@tonic-gate  */
832*7c478bd9Sstevel@tonic-gate s1394_hal_t *
833*7c478bd9Sstevel@tonic-gate s1394_dip_to_hal(dev_info_t *hal_dip)
834*7c478bd9Sstevel@tonic-gate {
835*7c478bd9Sstevel@tonic-gate 	s1394_hal_t	*current_hal = NULL;
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_dip_to_hal_enter,
838*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_HOTPLUG_STACK, "");
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 	mutex_enter(&s1394_statep->hal_list_mutex);
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate 	/* Search the HAL list for this dip */
843*7c478bd9Sstevel@tonic-gate 	current_hal = s1394_statep->hal_head;
844*7c478bd9Sstevel@tonic-gate 	while (current_hal != NULL) {
845*7c478bd9Sstevel@tonic-gate 		if (current_hal->halinfo.dip == hal_dip) {
846*7c478bd9Sstevel@tonic-gate 			break;
847*7c478bd9Sstevel@tonic-gate 		}
848*7c478bd9Sstevel@tonic-gate 		current_hal = current_hal->hal_next;
849*7c478bd9Sstevel@tonic-gate 	}
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate 	mutex_exit(&s1394_statep->hal_list_mutex);
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_dip_to_hal_exit,
854*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_HOTPLUG_STACK, "");
855*7c478bd9Sstevel@tonic-gate 	return (current_hal);
856*7c478bd9Sstevel@tonic-gate }
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate /*
859*7c478bd9Sstevel@tonic-gate  * s1394_target_from_dip_locked()
860*7c478bd9Sstevel@tonic-gate  *    searches target_list on the HAL for target corresponding to tdip;
861*7c478bd9Sstevel@tonic-gate  *    if found, target is returned, else returns NULL. This routine assumes
862*7c478bd9Sstevel@tonic-gate  *    target_list_rwlock is locked.
863*7c478bd9Sstevel@tonic-gate  *    NOTE: the callers may have the list locked in either write mode or read
864*7c478bd9Sstevel@tonic-gate  *    mode. Currently, there is no ddi-compliant way we can assert on the lock
865*7c478bd9Sstevel@tonic-gate  *    being held in write mode.
866*7c478bd9Sstevel@tonic-gate  */
867*7c478bd9Sstevel@tonic-gate s1394_target_t *
868*7c478bd9Sstevel@tonic-gate s1394_target_from_dip_locked(s1394_hal_t *hal, dev_info_t *tdip)
869*7c478bd9Sstevel@tonic-gate {
870*7c478bd9Sstevel@tonic-gate 	s1394_target_t	*temp;
871*7c478bd9Sstevel@tonic-gate 
872*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_target_from_dip_locked_enter,
873*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 	temp = hal->target_head;
876*7c478bd9Sstevel@tonic-gate 	while (temp != NULL) {
877*7c478bd9Sstevel@tonic-gate 	    if (temp->target_dip == tdip) {
878*7c478bd9Sstevel@tonic-gate 		return (temp);
879*7c478bd9Sstevel@tonic-gate 	    }
880*7c478bd9Sstevel@tonic-gate 	    temp = temp->target_next;
881*7c478bd9Sstevel@tonic-gate 	}
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_target_from_dip_locked_exit,
884*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
885*7c478bd9Sstevel@tonic-gate 	return (NULL);
886*7c478bd9Sstevel@tonic-gate }
887*7c478bd9Sstevel@tonic-gate /*
888*7c478bd9Sstevel@tonic-gate  * s1394_target_from_dip()
889*7c478bd9Sstevel@tonic-gate  *    searches target_list on the HAL for target corresponding to tdip;
890*7c478bd9Sstevel@tonic-gate  *    if found, target is returned locked.
891*7c478bd9Sstevel@tonic-gate  */
892*7c478bd9Sstevel@tonic-gate s1394_target_t *
893*7c478bd9Sstevel@tonic-gate s1394_target_from_dip(s1394_hal_t *hal, dev_info_t *tdip)
894*7c478bd9Sstevel@tonic-gate {
895*7c478bd9Sstevel@tonic-gate 	s1394_target_t	*target;
896*7c478bd9Sstevel@tonic-gate 
897*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_target_from_dip_enter, S1394_TNF_SL_STACK, "");
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate 	rw_enter(&hal->target_list_rwlock, RW_READER);
900*7c478bd9Sstevel@tonic-gate 	target = s1394_target_from_dip_locked(hal, tdip);
901*7c478bd9Sstevel@tonic-gate 	rw_exit(&hal->target_list_rwlock);
902*7c478bd9Sstevel@tonic-gate 
903*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_target_from_dip_exit, S1394_TNF_SL_STACK, "");
904*7c478bd9Sstevel@tonic-gate 	return (target);
905*7c478bd9Sstevel@tonic-gate }
906*7c478bd9Sstevel@tonic-gate 
907*7c478bd9Sstevel@tonic-gate /*
908*7c478bd9Sstevel@tonic-gate  * s1394_destroy_timers()
909*7c478bd9Sstevel@tonic-gate  *    turns off any outstanding timers in preparation for detach or suspend.
910*7c478bd9Sstevel@tonic-gate  */
911*7c478bd9Sstevel@tonic-gate void
912*7c478bd9Sstevel@tonic-gate s1394_destroy_timers(s1394_hal_t *hal)
913*7c478bd9Sstevel@tonic-gate {
914*7c478bd9Sstevel@tonic-gate 	/* Destroy both of the Bus Mgr timers */
915*7c478bd9Sstevel@tonic-gate 	(void) untimeout(hal->bus_mgr_timeout_id);
916*7c478bd9Sstevel@tonic-gate 	(void) untimeout(hal->bus_mgr_query_timeout_id);
917*7c478bd9Sstevel@tonic-gate 
918*7c478bd9Sstevel@tonic-gate 	/* Destroy the Cycle Master timer */
919*7c478bd9Sstevel@tonic-gate 	(void) untimeout(hal->cm_timer);
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 	/* Wait for the Config ROM timer (if necessary) */
922*7c478bd9Sstevel@tonic-gate 	while (hal->config_rom_timer_set == B_TRUE) {
923*7c478bd9Sstevel@tonic-gate 		delay(drv_usectohz(10));
924*7c478bd9Sstevel@tonic-gate 	}
925*7c478bd9Sstevel@tonic-gate }
926*7c478bd9Sstevel@tonic-gate 
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate /*
929*7c478bd9Sstevel@tonic-gate  * s1394_cleanup_node_cfgrom()
930*7c478bd9Sstevel@tonic-gate  *    frees up all of the Config ROM in use by nodes in the topology_tree
931*7c478bd9Sstevel@tonic-gate  */
932*7c478bd9Sstevel@tonic-gate static void
933*7c478bd9Sstevel@tonic-gate s1394_cleanup_node_cfgrom(s1394_hal_t *hal)
934*7c478bd9Sstevel@tonic-gate {
935*7c478bd9Sstevel@tonic-gate 	uint32_t *cfgrom;
936*7c478bd9Sstevel@tonic-gate 	int	 i;
937*7c478bd9Sstevel@tonic-gate 
938*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < IEEE1394_MAX_NODES; i++) {
939*7c478bd9Sstevel@tonic-gate 		if ((cfgrom = hal->topology_tree[i].cfgrom) != NULL)
940*7c478bd9Sstevel@tonic-gate 			kmem_free(cfgrom, IEEE1394_CONFIG_ROM_SZ);
941*7c478bd9Sstevel@tonic-gate 	}
942*7c478bd9Sstevel@tonic-gate }
943*7c478bd9Sstevel@tonic-gate 
944*7c478bd9Sstevel@tonic-gate /*
945*7c478bd9Sstevel@tonic-gate  * s1394_cycle_too_long_callback()
946*7c478bd9Sstevel@tonic-gate  *    turns on the cycle master bit of the root node (current Cycle Master)
947*7c478bd9Sstevel@tonic-gate  */
948*7c478bd9Sstevel@tonic-gate void
949*7c478bd9Sstevel@tonic-gate s1394_cycle_too_long_callback(void *arg)
950*7c478bd9Sstevel@tonic-gate {
951*7c478bd9Sstevel@tonic-gate 	s1394_hal_t	*hal;
952*7c478bd9Sstevel@tonic-gate 	ushort_t	root_node_num;
953*7c478bd9Sstevel@tonic-gate 	ushort_t	hal_node_num;
954*7c478bd9Sstevel@tonic-gate 	uint32_t	data;
955*7c478bd9Sstevel@tonic-gate 	uint_t		offset;
956*7c478bd9Sstevel@tonic-gate 
957*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_cycle_too_long_callback_enter,
958*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
959*7c478bd9Sstevel@tonic-gate 
960*7c478bd9Sstevel@tonic-gate 	hal = (s1394_hal_t *)arg;
961*7c478bd9Sstevel@tonic-gate 
962*7c478bd9Sstevel@tonic-gate 	/* Clear the cm_timer_cet bit */
963*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->topology_tree_mutex);
964*7c478bd9Sstevel@tonic-gate 	mutex_enter(&hal->cm_timer_mutex);
965*7c478bd9Sstevel@tonic-gate 	hal->cm_timer_set = B_FALSE;
966*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->cm_timer_mutex);
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 	/* Get the root node and host node numbers */
969*7c478bd9Sstevel@tonic-gate 	root_node_num = hal->number_of_nodes - 1;
970*7c478bd9Sstevel@tonic-gate 	hal_node_num  = IEEE1394_NODE_NUM(hal->node_id);
971*7c478bd9Sstevel@tonic-gate 	mutex_exit(&hal->topology_tree_mutex);
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate 	/* If we are the root node, set the cycle master bit */
974*7c478bd9Sstevel@tonic-gate 	if (hal_node_num == root_node_num) {
975*7c478bd9Sstevel@tonic-gate 		data	= IEEE1394_CSR_STATE_CMSTR;
976*7c478bd9Sstevel@tonic-gate 		offset  = (IEEE1394_CSR_STATE_SET & IEEE1394_CSR_OFFSET_MASK);
977*7c478bd9Sstevel@tonic-gate 		(void) HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
978*7c478bd9Sstevel@tonic-gate 		    offset, data);
979*7c478bd9Sstevel@tonic-gate 	}
980*7c478bd9Sstevel@tonic-gate 
981*7c478bd9Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(s1394_cycle_too_long_callback_exit,
982*7c478bd9Sstevel@tonic-gate 	    S1394_TNF_SL_STACK, "");
983*7c478bd9Sstevel@tonic-gate }
984