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