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