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 * h1394.c 31*7c478bd9Sstevel@tonic-gate * 1394 Services Layer HAL Interface 32*7c478bd9Sstevel@tonic-gate * Contains all of the routines that define the HAL to Services Layer 33*7c478bd9Sstevel@tonic-gate * interface 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/modctl.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/thread.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/disp.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/devctl.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/tnf_probe.h> 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #include <sys/1394/t1394.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/1394/s1394.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/1394/ieee1394.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate extern struct bus_ops nx1394_busops; 58*7c478bd9Sstevel@tonic-gate extern int nx1394_define_events(s1394_hal_t *hal); 59*7c478bd9Sstevel@tonic-gate extern void nx1394_undefine_events(s1394_hal_t *hal); 60*7c478bd9Sstevel@tonic-gate extern int s1394_ignore_invalid_gap_cnt; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate /* 63*7c478bd9Sstevel@tonic-gate * Function: h1394_init() 64*7c478bd9Sstevel@tonic-gate * Input(s): modlp The structure containing all of the 65*7c478bd9Sstevel@tonic-gate * HAL's relevant information 66*7c478bd9Sstevel@tonic-gate * 67*7c478bd9Sstevel@tonic-gate * Output(s): 68*7c478bd9Sstevel@tonic-gate * 69*7c478bd9Sstevel@tonic-gate * Description: h1394_init() is called by the HAL's _init function and is 70*7c478bd9Sstevel@tonic-gate * used to set up the nexus bus ops. 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate int 73*7c478bd9Sstevel@tonic-gate h1394_init(struct modlinkage *modlp) 74*7c478bd9Sstevel@tonic-gate { 75*7c478bd9Sstevel@tonic-gate struct dev_ops *devops; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_init_enter, S1394_TNF_SL_STACK, ""); 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate devops = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops; 80*7c478bd9Sstevel@tonic-gate devops->devo_bus_ops = &nx1394_busops; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_init_exit, S1394_TNF_SL_STACK, ""); 83*7c478bd9Sstevel@tonic-gate return (0); 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate /* 87*7c478bd9Sstevel@tonic-gate * Function: h1394_fini() 88*7c478bd9Sstevel@tonic-gate * Input(s): modlp The structure containing all of the 89*7c478bd9Sstevel@tonic-gate * HAL's relevant information 90*7c478bd9Sstevel@tonic-gate * 91*7c478bd9Sstevel@tonic-gate * Output(s): 92*7c478bd9Sstevel@tonic-gate * 93*7c478bd9Sstevel@tonic-gate * Description: h1394_fini() is called by the HAL's _fini function and is 94*7c478bd9Sstevel@tonic-gate * used to NULL out the nexus bus ops. 95*7c478bd9Sstevel@tonic-gate */ 96*7c478bd9Sstevel@tonic-gate void 97*7c478bd9Sstevel@tonic-gate h1394_fini(struct modlinkage *modlp) 98*7c478bd9Sstevel@tonic-gate { 99*7c478bd9Sstevel@tonic-gate struct dev_ops *devops; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_fini_enter, S1394_TNF_SL_STACK, ""); 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate devops = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops; 104*7c478bd9Sstevel@tonic-gate devops->devo_bus_ops = NULL; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_fini_enter, S1394_TNF_SL_STACK, ""); 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * Function: h1394_attach() 111*7c478bd9Sstevel@tonic-gate * Input(s): halinfo The structure containing all of the 112*7c478bd9Sstevel@tonic-gate * HAL's relevant information 113*7c478bd9Sstevel@tonic-gate * cmd The ddi_attach_cmd_t that tells us 114*7c478bd9Sstevel@tonic-gate * if this is a RESUME or a regular 115*7c478bd9Sstevel@tonic-gate * attach() call 116*7c478bd9Sstevel@tonic-gate * 117*7c478bd9Sstevel@tonic-gate * Output(s): sl_private The HAL "handle" to be used for 118*7c478bd9Sstevel@tonic-gate * all subsequent calls into the 119*7c478bd9Sstevel@tonic-gate * 1394 Software Framework 120*7c478bd9Sstevel@tonic-gate * 121*7c478bd9Sstevel@tonic-gate * Description: h1394_attach() registers the HAL with the 1394 Software 122*7c478bd9Sstevel@tonic-gate * Framework. It returns a HAL "handle" to be used for 123*7c478bd9Sstevel@tonic-gate * all subsequent calls into the 1394 Software Framework. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate int 126*7c478bd9Sstevel@tonic-gate h1394_attach(h1394_halinfo_t *halinfo, ddi_attach_cmd_t cmd, void **sl_private) 127*7c478bd9Sstevel@tonic-gate { 128*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 129*7c478bd9Sstevel@tonic-gate int ret; 130*7c478bd9Sstevel@tonic-gate char buf[32]; 131*7c478bd9Sstevel@tonic-gate uint_t cmd_size; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_enter, S1394_TNF_SL_STACK, ""); 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate ASSERT(sl_private != NULL); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate /* If this is a DDI_RESUME, return success */ 138*7c478bd9Sstevel@tonic-gate if (cmd == DDI_RESUME) { 139*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)(*sl_private); 140*7c478bd9Sstevel@tonic-gate /* If we have a 1394A PHY, then reset the "contender bit" */ 141*7c478bd9Sstevel@tonic-gate if (hal->halinfo.phy == H1394_PHY_1394A) 142*7c478bd9Sstevel@tonic-gate (void) HAL_CALL(hal).set_contender_bit( 143*7c478bd9Sstevel@tonic-gate hal->halinfo.hal_private); 144*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_exit, S1394_TNF_SL_STACK, 145*7c478bd9Sstevel@tonic-gate ""); 146*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 147*7c478bd9Sstevel@tonic-gate } else if (cmd != DDI_ATTACH) { 148*7c478bd9Sstevel@tonic-gate TNF_PROBE_2(h1394_attach_error, S1394_TNF_SL_ERROR, "", 149*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid ddi_attach_cmd received", 150*7c478bd9Sstevel@tonic-gate tnf_uint, attach_cmd, (uint_t)cmd); 151*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_exit, S1394_TNF_SL_STACK, 152*7c478bd9Sstevel@tonic-gate ""); 153*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* Allocate space for s1394_hal_t */ 157*7c478bd9Sstevel@tonic-gate hal = kmem_zalloc(sizeof (s1394_hal_t), KM_SLEEP); 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate /* Setup HAL state */ 160*7c478bd9Sstevel@tonic-gate hal->hal_state = S1394_HAL_INIT; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate /* Copy in the halinfo struct */ 163*7c478bd9Sstevel@tonic-gate hal->halinfo = *halinfo; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* Create the topology tree mutex */ 166*7c478bd9Sstevel@tonic-gate mutex_init(&hal->topology_tree_mutex, NULL, MUTEX_DRIVER, 167*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* Create the Cycle Mater timer mutex */ 170*7c478bd9Sstevel@tonic-gate mutex_init(&hal->cm_timer_mutex, NULL, MUTEX_DRIVER, 171*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate /* Initialize the Isoch CEC list */ 174*7c478bd9Sstevel@tonic-gate hal->isoch_cec_list_head = NULL; 175*7c478bd9Sstevel@tonic-gate hal->isoch_cec_list_tail = NULL; 176*7c478bd9Sstevel@tonic-gate mutex_init(&hal->isoch_cec_list_mutex, NULL, MUTEX_DRIVER, 177*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* Initialize the Bus Manager node ID mutex and cv */ 180*7c478bd9Sstevel@tonic-gate mutex_init(&hal->bus_mgr_node_mutex, NULL, MUTEX_DRIVER, 181*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 182*7c478bd9Sstevel@tonic-gate cv_init(&hal->bus_mgr_node_cv, NULL, CV_DRIVER, 183*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* Initialize the Bus Manager node ID - "-1" means undetermined */ 186*7c478bd9Sstevel@tonic-gate hal->bus_mgr_node = -1; 187*7c478bd9Sstevel@tonic-gate hal->incumbent_bus_mgr = B_FALSE; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* Initialize the Target list */ 190*7c478bd9Sstevel@tonic-gate hal->target_head = NULL; 191*7c478bd9Sstevel@tonic-gate hal->target_tail = NULL; 192*7c478bd9Sstevel@tonic-gate rw_init(&hal->target_list_rwlock, NULL, RW_DRIVER, 193*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate /* Setup Request Q's */ 196*7c478bd9Sstevel@tonic-gate hal->outstanding_q_head = NULL; 197*7c478bd9Sstevel@tonic-gate hal->outstanding_q_tail = NULL; 198*7c478bd9Sstevel@tonic-gate mutex_init(&hal->outstanding_q_mutex, NULL, MUTEX_DRIVER, 199*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 200*7c478bd9Sstevel@tonic-gate hal->pending_q_head = NULL; 201*7c478bd9Sstevel@tonic-gate hal->pending_q_tail = NULL; 202*7c478bd9Sstevel@tonic-gate mutex_init(&hal->pending_q_mutex, NULL, MUTEX_DRIVER, 203*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate /* Create the kmem_cache for command allocations */ 206*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "hal%d_cache", ddi_get_instance(hal->halinfo.dip)); 207*7c478bd9Sstevel@tonic-gate cmd_size = sizeof (cmd1394_cmd_t) + sizeof (s1394_cmd_priv_t) + 208*7c478bd9Sstevel@tonic-gate hal->halinfo.hal_overhead; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate hal->hal_kmem_cachep = kmem_cache_create(buf, cmd_size, 8, NULL, NULL, 211*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0); 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* Setup the event stuff */ 214*7c478bd9Sstevel@tonic-gate ret = nx1394_define_events(hal); 215*7c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 216*7c478bd9Sstevel@tonic-gate /* Clean up before leaving */ 217*7c478bd9Sstevel@tonic-gate s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL0); 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_attach_error, S1394_TNF_SL_ERROR, "", 220*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Unable to define attach events"); 221*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_exit, S1394_TNF_SL_STACK, 222*7c478bd9Sstevel@tonic-gate ""); 223*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* Initialize the mutexes and cv's used by the bus reset thread */ 227*7c478bd9Sstevel@tonic-gate mutex_init(&hal->br_thread_mutex, NULL, MUTEX_DRIVER, 228*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 229*7c478bd9Sstevel@tonic-gate cv_init(&hal->br_thread_cv, NULL, CV_DRIVER, hal->halinfo.hw_interrupt); 230*7c478bd9Sstevel@tonic-gate mutex_init(&hal->br_cmplq_mutex, NULL, MUTEX_DRIVER, 231*7c478bd9Sstevel@tonic-gate hal->halinfo.hw_interrupt); 232*7c478bd9Sstevel@tonic-gate cv_init(&hal->br_cmplq_cv, NULL, CV_DRIVER, hal->halinfo.hw_interrupt); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * Create a bus reset thread to handle the device discovery. 236*7c478bd9Sstevel@tonic-gate * It should take the default stack sizes, it should run 237*7c478bd9Sstevel@tonic-gate * the s1394_br_thread() routine at the start, passing the 238*7c478bd9Sstevel@tonic-gate * HAL pointer as its argument. The thread should be put 239*7c478bd9Sstevel@tonic-gate * on processor p0, its state should be set to runnable, 240*7c478bd9Sstevel@tonic-gate * but not yet on a processor, and its scheduling priority 241*7c478bd9Sstevel@tonic-gate * should be the minimum level of any system class. 242*7c478bd9Sstevel@tonic-gate */ 243*7c478bd9Sstevel@tonic-gate hal->br_thread = thread_create((caddr_t)NULL, 0, s1394_br_thread, 244*7c478bd9Sstevel@tonic-gate hal, 0, &p0, TS_RUN, minclsyspri); 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate /* Until we see a bus reset this HAL has no nodes */ 247*7c478bd9Sstevel@tonic-gate hal->number_of_nodes = 0; 248*7c478bd9Sstevel@tonic-gate hal->num_bus_reset_till_fail = NUM_BR_FAIL; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate /* Initialize the SelfID Info */ 251*7c478bd9Sstevel@tonic-gate hal->current_buffer = 0; 252*7c478bd9Sstevel@tonic-gate hal->selfid_buf0 = kmem_zalloc(S1394_SELFID_BUF_SIZE, KM_SLEEP); 253*7c478bd9Sstevel@tonic-gate hal->selfid_buf1 = kmem_zalloc(S1394_SELFID_BUF_SIZE, KM_SLEEP); 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* Initialize kstat structures */ 256*7c478bd9Sstevel@tonic-gate ret = s1394_kstat_init(hal); 257*7c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 258*7c478bd9Sstevel@tonic-gate /* Clean up before leaving */ 259*7c478bd9Sstevel@tonic-gate s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL3); 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_attach_error, S1394_TNF_SL_ERROR, "", 262*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Failure in s1394_kstat_init"); 263*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_exit, S1394_TNF_SL_STACK, 264*7c478bd9Sstevel@tonic-gate ""); 265*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate hal->hal_kstats->guid = hal->halinfo.guid; 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate /* Setup the node tree pointers */ 270*7c478bd9Sstevel@tonic-gate hal->old_tree = &hal->last_valid_tree[0]; 271*7c478bd9Sstevel@tonic-gate hal->topology_tree = &hal->current_tree[0]; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /* Initialize the local Config ROM entry */ 274*7c478bd9Sstevel@tonic-gate ret = s1394_init_local_config_rom(hal); 275*7c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 276*7c478bd9Sstevel@tonic-gate /* Clean up before leaving */ 277*7c478bd9Sstevel@tonic-gate s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL4); 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_attach_error, S1394_TNF_SL_ERROR, "", 280*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Failure in s1394_init_local_config_rom"); 281*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_exit, S1394_TNF_SL_STACK, ""); 282*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* Initialize 1394 Address Space */ 286*7c478bd9Sstevel@tonic-gate ret = s1394_init_addr_space(hal); 287*7c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 288*7c478bd9Sstevel@tonic-gate /* Clean up before leaving */ 289*7c478bd9Sstevel@tonic-gate s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL5); 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_attach_error, S1394_TNF_SL_ERROR, "", 292*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid 1394 address space"); 293*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_exit, S1394_TNF_SL_STACK, 294*7c478bd9Sstevel@tonic-gate ""); 295*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate /* Initialize FCP subsystem */ 299*7c478bd9Sstevel@tonic-gate ret = s1394_fcp_hal_init(hal); 300*7c478bd9Sstevel@tonic-gate if (ret != DDI_SUCCESS) { 301*7c478bd9Sstevel@tonic-gate /* Clean up before leaving */ 302*7c478bd9Sstevel@tonic-gate s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL6); 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_attach_error, S1394_TNF_SL_ERROR, "", 305*7c478bd9Sstevel@tonic-gate tnf_string, msg, "FCP initialization failure"); 306*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_exit, S1394_TNF_SL_STACK, 307*7c478bd9Sstevel@tonic-gate ""); 308*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate /* Initialize the IRM node ID - "-1" means invalid, undetermined */ 312*7c478bd9Sstevel@tonic-gate hal->IRM_node = -1; 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate /* If we have a 1394A PHY, then set the "contender bit" */ 315*7c478bd9Sstevel@tonic-gate if (hal->halinfo.phy == H1394_PHY_1394A) 316*7c478bd9Sstevel@tonic-gate (void) HAL_CALL(hal).set_contender_bit( 317*7c478bd9Sstevel@tonic-gate hal->halinfo.hal_private); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate /* Add into linked list */ 320*7c478bd9Sstevel@tonic-gate mutex_enter(&s1394_statep->hal_list_mutex); 321*7c478bd9Sstevel@tonic-gate if ((s1394_statep->hal_head == NULL) && 322*7c478bd9Sstevel@tonic-gate (s1394_statep->hal_tail == NULL)) { 323*7c478bd9Sstevel@tonic-gate s1394_statep->hal_head = hal; 324*7c478bd9Sstevel@tonic-gate s1394_statep->hal_tail = hal; 325*7c478bd9Sstevel@tonic-gate } else { 326*7c478bd9Sstevel@tonic-gate s1394_statep->hal_tail->hal_next = hal; 327*7c478bd9Sstevel@tonic-gate hal->hal_prev = s1394_statep->hal_tail; 328*7c478bd9Sstevel@tonic-gate s1394_statep->hal_tail = hal; 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate mutex_exit(&s1394_statep->hal_list_mutex); 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* Fill in services layer private info */ 333*7c478bd9Sstevel@tonic-gate *sl_private = (void *)hal; 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_attach_exit, S1394_TNF_SL_STACK, ""); 336*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /* 340*7c478bd9Sstevel@tonic-gate * Function: h1394_detach() 341*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 342*7c478bd9Sstevel@tonic-gate * h1394_attach() 343*7c478bd9Sstevel@tonic-gate * cmd The ddi_detach_cmd_t that tells us 344*7c478bd9Sstevel@tonic-gate * if this is a SUSPEND or a regular 345*7c478bd9Sstevel@tonic-gate * detach() call 346*7c478bd9Sstevel@tonic-gate * 347*7c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS HAL successfully detached 348*7c478bd9Sstevel@tonic-gate * DDI_FAILURE HAL failed to detach 349*7c478bd9Sstevel@tonic-gate * 350*7c478bd9Sstevel@tonic-gate * Description: h1394_detach() unregisters the HAL from the 1394 Software 351*7c478bd9Sstevel@tonic-gate * Framework. It can be called during a SUSPEND operation or 352*7c478bd9Sstevel@tonic-gate * for a real detach() event. 353*7c478bd9Sstevel@tonic-gate */ 354*7c478bd9Sstevel@tonic-gate int 355*7c478bd9Sstevel@tonic-gate h1394_detach(void **sl_private, ddi_detach_cmd_t cmd) 356*7c478bd9Sstevel@tonic-gate { 357*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_detach_enter, S1394_TNF_SL_STACK, ""); 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)(*sl_private); 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate switch (cmd) { 364*7c478bd9Sstevel@tonic-gate case DDI_DETACH: 365*7c478bd9Sstevel@tonic-gate /* Clean up before leaving */ 366*7c478bd9Sstevel@tonic-gate s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL7); 367*7c478bd9Sstevel@tonic-gate /* NULL out the HAL "handle" */ 368*7c478bd9Sstevel@tonic-gate *sl_private = NULL; 369*7c478bd9Sstevel@tonic-gate break; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 372*7c478bd9Sstevel@tonic-gate /* Turn off any timers that might be set */ 373*7c478bd9Sstevel@tonic-gate s1394_destroy_timers(hal); 374*7c478bd9Sstevel@tonic-gate /* Set the hal_was_suspended bit */ 375*7c478bd9Sstevel@tonic-gate hal->hal_was_suspended = B_TRUE; 376*7c478bd9Sstevel@tonic-gate break; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate default: 379*7c478bd9Sstevel@tonic-gate TNF_PROBE_2(h1394_attach_error, S1394_TNF_SL_ERROR, "", 380*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid ddi_detach_cmd_t type specified", 381*7c478bd9Sstevel@tonic-gate tnf_uint, detach_cmd, (uint_t)cmd); 382*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_detach_exit, S1394_TNF_SL_STACK, ""); 383*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_detach_exit, S1394_TNF_SL_STACK, ""); 387*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate /* 391*7c478bd9Sstevel@tonic-gate * Function: h1394_alloc_cmd() 392*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 393*7c478bd9Sstevel@tonic-gate * h1394_attach() 394*7c478bd9Sstevel@tonic-gate * flags The flags parameter is described below 395*7c478bd9Sstevel@tonic-gate * 396*7c478bd9Sstevel@tonic-gate * Output(s): cmdp Pointer to the newly allocated command 397*7c478bd9Sstevel@tonic-gate * hal_priv_ptr Offset into the command, points to 398*7c478bd9Sstevel@tonic-gate * the HAL's private area 399*7c478bd9Sstevel@tonic-gate * 400*7c478bd9Sstevel@tonic-gate * Description: h1394_alloc_cmd() allocates a command for use with the 401*7c478bd9Sstevel@tonic-gate * h1394_read_request(), h1394_write_request(), or 402*7c478bd9Sstevel@tonic-gate * h1394_lock_request() interfaces of the 1394 Software Framework. 403*7c478bd9Sstevel@tonic-gate * By default, h1394_alloc_cmd() may sleep while allocating 404*7c478bd9Sstevel@tonic-gate * memory for the command structure. If this is undesirable, 405*7c478bd9Sstevel@tonic-gate * the HAL may set the H1394_ALLOC_CMD_NOSLEEP bit in the flags 406*7c478bd9Sstevel@tonic-gate * parameter. 407*7c478bd9Sstevel@tonic-gate */ 408*7c478bd9Sstevel@tonic-gate int 409*7c478bd9Sstevel@tonic-gate h1394_alloc_cmd(void *sl_private, uint_t flags, cmd1394_cmd_t **cmdp, 410*7c478bd9Sstevel@tonic-gate h1394_cmd_priv_t **hal_priv_ptr) 411*7c478bd9Sstevel@tonic-gate { 412*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 413*7c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_alloc_cmd_enter, S1394_TNF_SL_ARREQ_STACK, 416*7c478bd9Sstevel@tonic-gate ""); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate if (s1394_alloc_cmd(hal, flags, cmdp) != DDI_SUCCESS) { 421*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_alloc_cmd_error, S1394_TNF_SL_ARREQ_ERROR, "", 422*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Failed to allocate command structure"); 423*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_alloc_cmd_exit, 424*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 425*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 429*7c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(*cmdp); 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate *hal_priv_ptr = &s_priv->hal_cmd_private; 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_alloc_cmd_exit, S1394_TNF_SL_ARREQ_STACK, 434*7c478bd9Sstevel@tonic-gate ""); 435*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate /* 439*7c478bd9Sstevel@tonic-gate * Function: h1394_free_cmd() 440*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 441*7c478bd9Sstevel@tonic-gate * h1394_attach() 442*7c478bd9Sstevel@tonic-gate * cmdp Pointer to the command to be freed 443*7c478bd9Sstevel@tonic-gate * 444*7c478bd9Sstevel@tonic-gate * Output(s): DDI_SUCCESS HAL successfully freed command 445*7c478bd9Sstevel@tonic-gate * DDI_FAILURE HAL failed to free command 446*7c478bd9Sstevel@tonic-gate * 447*7c478bd9Sstevel@tonic-gate * Description: h1394_free_cmd() attempts to free a command that has previously 448*7c478bd9Sstevel@tonic-gate * been allocated by the HAL. It is possible for h1394_free_cmd() 449*7c478bd9Sstevel@tonic-gate * to fail because the command is currently in-use by the 1394 450*7c478bd9Sstevel@tonic-gate * Software Framework. 451*7c478bd9Sstevel@tonic-gate */ 452*7c478bd9Sstevel@tonic-gate int 453*7c478bd9Sstevel@tonic-gate h1394_free_cmd(void *sl_private, cmd1394_cmd_t **cmdp) 454*7c478bd9Sstevel@tonic-gate { 455*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 456*7c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_free_cmd_enter, S1394_TNF_SL_ARREQ_STACK, 459*7c478bd9Sstevel@tonic-gate ""); 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 464*7c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(*cmdp); 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate /* Check that command isn't in use */ 467*7c478bd9Sstevel@tonic-gate if (s_priv->cmd_in_use == B_TRUE) { 468*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_free_cmd_error, S1394_TNF_SL_ARREQ_ERROR, "", 469*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Attempted to free an in-use command"); 470*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_free_cmd_exit, S1394_TNF_SL_ARREQ_STACK, 471*7c478bd9Sstevel@tonic-gate ""); 472*7c478bd9Sstevel@tonic-gate ASSERT(s_priv->cmd_in_use == B_FALSE); 473*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate kmem_cache_free(hal->hal_kmem_cachep, *cmdp); 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate /* Command pointer is set to NULL before returning */ 479*7c478bd9Sstevel@tonic-gate *cmdp = NULL; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate /* kstats - number of cmds freed */ 482*7c478bd9Sstevel@tonic-gate hal->hal_kstats->cmd_free++; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_free_cmd_exit, S1394_TNF_SL_ARREQ_STACK, 485*7c478bd9Sstevel@tonic-gate ""); 486*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * Function: h1394_cmd_is_complete() 491*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 492*7c478bd9Sstevel@tonic-gate * h1394_attach() 493*7c478bd9Sstevel@tonic-gate * command_id Pointer to the command that has 494*7c478bd9Sstevel@tonic-gate * just completed 495*7c478bd9Sstevel@tonic-gate * cmd_type AT_RESP => AT response or ATREQ = 496*7c478bd9Sstevel@tonic-gate * AT request 497*7c478bd9Sstevel@tonic-gate * status Command's completion status 498*7c478bd9Sstevel@tonic-gate * 499*7c478bd9Sstevel@tonic-gate * Output(s): None 500*7c478bd9Sstevel@tonic-gate * 501*7c478bd9Sstevel@tonic-gate * Description: h1394_cmd_is_complete() is called by the HAL whenever an 502*7c478bd9Sstevel@tonic-gate * outstanding command has completed (successfully or otherwise). 503*7c478bd9Sstevel@tonic-gate * After determining whether it was an AT request or and AT 504*7c478bd9Sstevel@tonic-gate * response that we are handling, the command is dispatched to 505*7c478bd9Sstevel@tonic-gate * the appropriate handler in the 1394 Software Framework. 506*7c478bd9Sstevel@tonic-gate */ 507*7c478bd9Sstevel@tonic-gate void 508*7c478bd9Sstevel@tonic-gate h1394_cmd_is_complete(void *sl_private, cmd1394_cmd_t *command_id, 509*7c478bd9Sstevel@tonic-gate uint32_t cmd_type, int status) 510*7c478bd9Sstevel@tonic-gate { 511*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 512*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_cmd_is_complete_enter, 515*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_ATRESP_STACK, ""); 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* Is it AT_RESP or AT_REQ? */ 520*7c478bd9Sstevel@tonic-gate switch (cmd_type) { 521*7c478bd9Sstevel@tonic-gate case H1394_AT_REQ: 522*7c478bd9Sstevel@tonic-gate s1394_atreq_cmd_complete(hal, command_id, status); 523*7c478bd9Sstevel@tonic-gate break; 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate case H1394_AT_RESP: 526*7c478bd9Sstevel@tonic-gate s1394_atresp_cmd_complete(hal, command_id, status); 527*7c478bd9Sstevel@tonic-gate break; 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate default: 530*7c478bd9Sstevel@tonic-gate dip = hal->halinfo.dip; 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate /* An unexpected error in the HAL */ 533*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 534*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip)); 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate /* Disable the HAL */ 537*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_TRUE); 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_cmd_is_complete_error, 540*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_ATRESP_ERROR, "", 541*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid command type specified"); 542*7c478bd9Sstevel@tonic-gate break; 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_cmd_is_complete_exit, 546*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ATREQ_ATRESP_STACK, ""); 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate /* 550*7c478bd9Sstevel@tonic-gate * Function: h1394_bus_reset() 551*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 552*7c478bd9Sstevel@tonic-gate * h1394_attach() 553*7c478bd9Sstevel@tonic-gate * 554*7c478bd9Sstevel@tonic-gate * Output(s): selfid_buf_addr The pointer to a buffer into which 555*7c478bd9Sstevel@tonic-gate * any Self ID packets should be put 556*7c478bd9Sstevel@tonic-gate * 557*7c478bd9Sstevel@tonic-gate * Description: h1394_bus_reset() is called whenever a 1394 bus reset event 558*7c478bd9Sstevel@tonic-gate * is detected by the HAL. This routine simply prepares for 559*7c478bd9Sstevel@tonic-gate * the subsequent Self ID packets. 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate void 562*7c478bd9Sstevel@tonic-gate h1394_bus_reset(void *sl_private, void **selfid_buf_addr) 563*7c478bd9Sstevel@tonic-gate { 564*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_bus_reset_enter, S1394_TNF_SL_BR_STACK, ""); 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex); 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate /* Update the HAL's state */ 573*7c478bd9Sstevel@tonic-gate if (hal->hal_state != S1394_HAL_SHUTDOWN) { 574*7c478bd9Sstevel@tonic-gate hal->hal_state = S1394_HAL_RESET; 575*7c478bd9Sstevel@tonic-gate } else { 576*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 577*7c478bd9Sstevel@tonic-gate return; 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate if (hal->initiated_bus_reset == B_TRUE) { 581*7c478bd9Sstevel@tonic-gate hal->initiated_bus_reset = B_FALSE; 582*7c478bd9Sstevel@tonic-gate if (hal->num_bus_reset_till_fail > 0) { 583*7c478bd9Sstevel@tonic-gate hal->num_bus_reset_till_fail--; 584*7c478bd9Sstevel@tonic-gate } else { 585*7c478bd9Sstevel@tonic-gate TNF_PROBE_2(h1394_bus_reset_error, 586*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_BR_ERROR, "", 587*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Bus reset fail (too many resets)", 588*7c478bd9Sstevel@tonic-gate tnf_uint, br_type, hal->initiated_br_reason); 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate } else { 591*7c478bd9Sstevel@tonic-gate hal->num_bus_reset_till_fail = NUM_BR_FAIL; 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate /* Reset the IRM node ID */ 595*7c478bd9Sstevel@tonic-gate hal->IRM_node = -1; 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate /* Slowest node defaults to IEEE1394_S400 */ 598*7c478bd9Sstevel@tonic-gate hal->slowest_node_speed = IEEE1394_S400; 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate /* Pick a SelfID buffer to give */ 601*7c478bd9Sstevel@tonic-gate if (hal->current_buffer == 0) { 602*7c478bd9Sstevel@tonic-gate *selfid_buf_addr = (void *)hal->selfid_buf1; 603*7c478bd9Sstevel@tonic-gate hal->current_buffer = 1; 604*7c478bd9Sstevel@tonic-gate } else { 605*7c478bd9Sstevel@tonic-gate *selfid_buf_addr = (void *)hal->selfid_buf0; 606*7c478bd9Sstevel@tonic-gate hal->current_buffer = 0; 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate /* Disable the CSR topology_map (temporarily) */ 610*7c478bd9Sstevel@tonic-gate s1394_CSR_topology_map_disable(hal); 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate /* Reset the Bus Manager node ID */ 615*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->bus_mgr_node_mutex); 616*7c478bd9Sstevel@tonic-gate hal->bus_mgr_node = -1; 617*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->bus_mgr_node_mutex); 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_bus_reset_exit, S1394_TNF_SL_BR_STACK, ""); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate /* 623*7c478bd9Sstevel@tonic-gate * Function: h1394_self_ids() 624*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 625*7c478bd9Sstevel@tonic-gate * h1394_attach() 626*7c478bd9Sstevel@tonic-gate * selfid_buf_addr Pointer to the Self ID buffer 627*7c478bd9Sstevel@tonic-gate * selfid_size The size of the filled part of the 628*7c478bd9Sstevel@tonic-gate * Self ID buffer 629*7c478bd9Sstevel@tonic-gate * node_id The local (host) node ID for the 630*7c478bd9Sstevel@tonic-gate * current generation 631*7c478bd9Sstevel@tonic-gate * generation_count The current generation number 632*7c478bd9Sstevel@tonic-gate * 633*7c478bd9Sstevel@tonic-gate * Output(s): None 634*7c478bd9Sstevel@tonic-gate * 635*7c478bd9Sstevel@tonic-gate * Description: h1394_self_ids() does alot of the work at bus reset. It 636*7c478bd9Sstevel@tonic-gate * takes the Self ID packets and parses them, builds a topology 637*7c478bd9Sstevel@tonic-gate * tree representation of them, calculates gap count, IRM, speed 638*7c478bd9Sstevel@tonic-gate * map, does any node matching that's possible, and then wakes 639*7c478bd9Sstevel@tonic-gate * up the br_thread. 640*7c478bd9Sstevel@tonic-gate */ 641*7c478bd9Sstevel@tonic-gate void 642*7c478bd9Sstevel@tonic-gate h1394_self_ids(void *sl_private, void *selfid_buf_addr, uint32_t selfid_size, 643*7c478bd9Sstevel@tonic-gate uint32_t node_id, uint32_t generation_count) 644*7c478bd9Sstevel@tonic-gate { 645*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 646*7c478bd9Sstevel@tonic-gate int diameter; 647*7c478bd9Sstevel@tonic-gate uint_t gen_diff, gen_rollover; 648*7c478bd9Sstevel@tonic-gate boolean_t tree_copied = B_FALSE; 649*7c478bd9Sstevel@tonic-gate ushort_t saved_number_of_nodes; 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate /* 652*7c478bd9Sstevel@tonic-gate * NOTE: current topology tree is referred to as topology_tree 653*7c478bd9Sstevel@tonic-gate * and the old topology tree is referred to as old_tree. 654*7c478bd9Sstevel@tonic-gate * tree_valid indicates selfID buffer checked out OK and we were 655*7c478bd9Sstevel@tonic-gate * able to build the topology tree. 656*7c478bd9Sstevel@tonic-gate * tree_processed indicates we read the config ROMs as needed. 657*7c478bd9Sstevel@tonic-gate */ 658*7c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(h1394_self_ids_enter, S1394_TNF_SL_BR_STACK, "", 659*7c478bd9Sstevel@tonic-gate tnf_uint, hal_generation, generation_count); 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* Lock the topology tree */ 664*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex); 665*7c478bd9Sstevel@tonic-gate if (hal->hal_state == S1394_HAL_SHUTDOWN) { 666*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 667*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_exit, S1394_TNF_SL_BR_STACK, 668*7c478bd9Sstevel@tonic-gate ""); 669*7c478bd9Sstevel@tonic-gate return; 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate /* kstats - number of selfid completes */ 673*7c478bd9Sstevel@tonic-gate hal->hal_kstats->selfid_complete++; 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate if (generation_count > hal->generation_count) { 676*7c478bd9Sstevel@tonic-gate gen_diff = generation_count - hal->generation_count; 677*7c478bd9Sstevel@tonic-gate hal->hal_kstats->bus_reset += gen_diff; 678*7c478bd9Sstevel@tonic-gate } else { 679*7c478bd9Sstevel@tonic-gate gen_diff = hal->generation_count - generation_count; 680*7c478bd9Sstevel@tonic-gate /* Use max_generation to determine how many bus resets */ 681*7c478bd9Sstevel@tonic-gate hal->hal_kstats->bus_reset += 682*7c478bd9Sstevel@tonic-gate (hal->halinfo.max_generation - gen_diff); 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate /* 686*7c478bd9Sstevel@tonic-gate * If the current tree has a valid topology tree (selfids 687*7c478bd9Sstevel@tonic-gate * checked out OK etc) and config roms read as needed, 688*7c478bd9Sstevel@tonic-gate * then make it the old tree before building a new one. 689*7c478bd9Sstevel@tonic-gate */ 690*7c478bd9Sstevel@tonic-gate if ((hal->topology_tree_valid == B_TRUE) && 691*7c478bd9Sstevel@tonic-gate (hal->topology_tree_processed == B_TRUE)) { 692*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_tree_copy, 693*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_BR_STACK, ""); 694*7c478bd9Sstevel@tonic-gate /* Trees are switched after the copy completes */ 695*7c478bd9Sstevel@tonic-gate s1394_copy_old_tree(hal); 696*7c478bd9Sstevel@tonic-gate tree_copied = B_TRUE; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* Set the new generation and node id */ 700*7c478bd9Sstevel@tonic-gate hal->node_id = node_id; 701*7c478bd9Sstevel@tonic-gate hal->generation_count = generation_count; 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate /* Invalidate the current topology tree */ 704*7c478bd9Sstevel@tonic-gate hal->topology_tree_valid = B_FALSE; 705*7c478bd9Sstevel@tonic-gate hal->topology_tree_processed = B_FALSE; 706*7c478bd9Sstevel@tonic-gate hal->cfgroms_being_read = 0; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_parse_selfid, S1394_TNF_SL_BR_STACK, 709*7c478bd9Sstevel@tonic-gate ""); 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate /* 712*7c478bd9Sstevel@tonic-gate * Save the number of nodes prior to parsing the self id buffer. 713*7c478bd9Sstevel@tonic-gate * We need this saved value while initializing the topology tree 714*7c478bd9Sstevel@tonic-gate * (for non-copy case). 715*7c478bd9Sstevel@tonic-gate */ 716*7c478bd9Sstevel@tonic-gate saved_number_of_nodes = hal->number_of_nodes; 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate /* Parse the SelfID buffer */ 719*7c478bd9Sstevel@tonic-gate if (s1394_parse_selfid_buffer(hal, selfid_buf_addr, selfid_size) != 720*7c478bd9Sstevel@tonic-gate DDI_SUCCESS) { 721*7c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 722*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 723*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_self_ids_error, S1394_TNF_SL_BR_ERROR, "", 724*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Unable to parse selfID buffer"); 725*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_exit, S1394_TNF_SL_BR_STACK, 726*7c478bd9Sstevel@tonic-gate ""); 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate /* kstats - SelfID buffer error */ 729*7c478bd9Sstevel@tonic-gate hal->hal_kstats->selfid_buffer_error++; 730*7c478bd9Sstevel@tonic-gate return; /* Error parsing SelfIDs */ 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate /* Sort the SelfID packets by node number (if it's a 1995 PHY) */ 734*7c478bd9Sstevel@tonic-gate if (hal->halinfo.phy == H1394_PHY_1995) { 735*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_sort, S1394_TNF_SL_BR_STACK, 736*7c478bd9Sstevel@tonic-gate ""); 737*7c478bd9Sstevel@tonic-gate s1394_sort_selfids(hal); 738*7c478bd9Sstevel@tonic-gate } 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate /* 741*7c478bd9Sstevel@tonic-gate * Update the cycle master timer - if the timer is set and 742*7c478bd9Sstevel@tonic-gate * we were the root but we are not anymore, then disable it. 743*7c478bd9Sstevel@tonic-gate */ 744*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->cm_timer_mutex); 745*7c478bd9Sstevel@tonic-gate if ((hal->cm_timer_set == B_TRUE) && 746*7c478bd9Sstevel@tonic-gate ((hal->old_number_of_nodes - 1) == 747*7c478bd9Sstevel@tonic-gate IEEE1394_NODE_NUM(hal->old_node_id)) && 748*7c478bd9Sstevel@tonic-gate ((hal->number_of_nodes - 1) != 749*7c478bd9Sstevel@tonic-gate IEEE1394_NODE_NUM(hal->node_id))) { 750*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->cm_timer_mutex); 751*7c478bd9Sstevel@tonic-gate (void) untimeout(hal->cm_timer); 752*7c478bd9Sstevel@tonic-gate } else { 753*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->cm_timer_mutex); 754*7c478bd9Sstevel@tonic-gate } 755*7c478bd9Sstevel@tonic-gate 756*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_init_topology, S1394_TNF_SL_BR_STACK, 757*7c478bd9Sstevel@tonic-gate ""); 758*7c478bd9Sstevel@tonic-gate s1394_init_topology_tree(hal, tree_copied, saved_number_of_nodes); 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate /* Determine the 1394 bus gap count */ 761*7c478bd9Sstevel@tonic-gate hal->gap_count = s1394_get_current_gap_count(hal); 762*7c478bd9Sstevel@tonic-gate /* If gap counts are inconsistent, reset */ 763*7c478bd9Sstevel@tonic-gate if (hal->gap_count == -1) { 764*7c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 765*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 766*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_self_ids_error, S1394_TNF_SL_BR_ERROR, "", 767*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid gap counts in SelfID pkts"); 768*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_exit, S1394_TNF_SL_BR_STACK, 769*7c478bd9Sstevel@tonic-gate ""); 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate /* kstats - SelfID buffer error (invalid gap counts) */ 772*7c478bd9Sstevel@tonic-gate hal->hal_kstats->selfid_buffer_error++; 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate if (s1394_ignore_invalid_gap_cnt == 1) { 775*7c478bd9Sstevel@tonic-gate /* Lock the topology tree again */ 776*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex); 777*7c478bd9Sstevel@tonic-gate hal->gap_count = 0x3F; 778*7c478bd9Sstevel@tonic-gate } else { 779*7c478bd9Sstevel@tonic-gate return; /* Invalid gap counts in SelfID buffer */ 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(h1394_self_ids_get_gap_count, S1394_TNF_SL_BR_STACK, 784*7c478bd9Sstevel@tonic-gate "", tnf_uint, gap_count, hal->gap_count); 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate /* Determine the Isoch Resource Manager */ 787*7c478bd9Sstevel@tonic-gate hal->IRM_node = s1394_get_isoch_rsrc_mgr(hal); 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(h1394_self_ids_IRM_node, S1394_TNF_SL_BR_STACK, "", 790*7c478bd9Sstevel@tonic-gate tnf_int, IRM_node, hal->IRM_node); 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_build_topology_tree, 793*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_BR_STACK, ""); 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate /* Build the topology tree */ 796*7c478bd9Sstevel@tonic-gate if (s1394_topology_tree_build(hal) != DDI_SUCCESS) { 797*7c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 798*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 799*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_self_ids_error, S1394_TNF_SL_BR_ERROR, "", 800*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Error building the topology tree"); 801*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_exit, S1394_TNF_SL_BR_STACK, 802*7c478bd9Sstevel@tonic-gate ""); 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* kstats - SelfID buffer error (Invalid topology tree) */ 805*7c478bd9Sstevel@tonic-gate hal->hal_kstats->selfid_buffer_error++; 806*7c478bd9Sstevel@tonic-gate return; /* Error building topology tree from SelfIDs */ 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_topology_CSRs, S1394_TNF_SL_BR_STACK, 810*7c478bd9Sstevel@tonic-gate ""); 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate /* Update the CSR topology_map */ 813*7c478bd9Sstevel@tonic-gate s1394_CSR_topology_map_update(hal); 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate /* Calculate the diameter */ 816*7c478bd9Sstevel@tonic-gate diameter = s1394_topology_tree_calculate_diameter(hal); 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate /* Determine the optimum gap count */ 819*7c478bd9Sstevel@tonic-gate hal->optimum_gap_count = s1394_gap_count_optimize(diameter); 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(h1394_self_ids_diameter_and_gap_count, 822*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_BR_STACK, "", 823*7c478bd9Sstevel@tonic-gate tnf_uint, optimum_gap, hal->optimum_gap_count); 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_speed_map, S1394_TNF_SL_BR_STACK, ""); 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate /* Fill in the speed map */ 828*7c478bd9Sstevel@tonic-gate s1394_speed_map_fill(hal); 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* Initialize the two trees (for tree walking) */ 831*7c478bd9Sstevel@tonic-gate s1394_topology_tree_mark_all_unvisited(hal); 832*7c478bd9Sstevel@tonic-gate s1394_old_tree_mark_all_unvisited(hal); 833*7c478bd9Sstevel@tonic-gate s1394_old_tree_mark_all_unmatched(hal); 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate /* Are both trees (old and new) valid? */ 836*7c478bd9Sstevel@tonic-gate if ((hal->old_tree_valid == B_TRUE) && 837*7c478bd9Sstevel@tonic-gate (hal->topology_tree_valid == B_TRUE)) { 838*7c478bd9Sstevel@tonic-gate /* If HAL was in a suspended state, then do no matching */ 839*7c478bd9Sstevel@tonic-gate if (hal->hal_was_suspended == B_TRUE) { 840*7c478bd9Sstevel@tonic-gate hal->hal_was_suspended = B_FALSE; 841*7c478bd9Sstevel@tonic-gate } else { 842*7c478bd9Sstevel@tonic-gate gen_rollover = hal->halinfo.max_generation + 1; 843*7c478bd9Sstevel@tonic-gate /* If only one bus reset occurred, match the trees */ 844*7c478bd9Sstevel@tonic-gate if (((hal->old_generation_count + 1) % gen_rollover) == 845*7c478bd9Sstevel@tonic-gate generation_count) { 846*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_tree_matching, 847*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_BR_STACK, ""); 848*7c478bd9Sstevel@tonic-gate s1394_match_tree_nodes(hal); 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate } 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate /* Unlock the topology tree */ 854*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate /* Wake up the bus reset processing thread */ 857*7c478bd9Sstevel@tonic-gate s1394_tickle_bus_reset_thread(hal); 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_self_ids_exit, 860*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_BR_STACK, ""); 861*7c478bd9Sstevel@tonic-gate } 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate /* 864*7c478bd9Sstevel@tonic-gate * Function: h1394_read_request() 865*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 866*7c478bd9Sstevel@tonic-gate * h1394_attach() 867*7c478bd9Sstevel@tonic-gate * req The incoming AR request 868*7c478bd9Sstevel@tonic-gate * 869*7c478bd9Sstevel@tonic-gate * Output(s): None 870*7c478bd9Sstevel@tonic-gate * 871*7c478bd9Sstevel@tonic-gate * Description: h1394_read_request() receives incoming AR requests. These 872*7c478bd9Sstevel@tonic-gate * asynchronous read requests are dispatched to the appropriate 873*7c478bd9Sstevel@tonic-gate * target (if one has registered) or are handled by the 1394 874*7c478bd9Sstevel@tonic-gate * Software Framework, which will send out an appropriate 875*7c478bd9Sstevel@tonic-gate * response. 876*7c478bd9Sstevel@tonic-gate */ 877*7c478bd9Sstevel@tonic-gate void 878*7c478bd9Sstevel@tonic-gate h1394_read_request(void *sl_private, cmd1394_cmd_t *req) 879*7c478bd9Sstevel@tonic-gate { 880*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 881*7c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 882*7c478bd9Sstevel@tonic-gate s1394_addr_space_blk_t *addr_blk; 883*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 884*7c478bd9Sstevel@tonic-gate uint64_t end_of_request; 885*7c478bd9Sstevel@tonic-gate uint32_t offset; 886*7c478bd9Sstevel@tonic-gate size_t cmd_length; 887*7c478bd9Sstevel@tonic-gate uchar_t *bufp_addr; 888*7c478bd9Sstevel@tonic-gate uchar_t *begin_ptr; 889*7c478bd9Sstevel@tonic-gate uchar_t *end_ptr; 890*7c478bd9Sstevel@tonic-gate uchar_t *tmp_ptr; 891*7c478bd9Sstevel@tonic-gate void (*recv_read_req)(cmd1394_cmd_t *); 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_enter, S1394_TNF_SL_ARREQ_STACK, 894*7c478bd9Sstevel@tonic-gate ""); 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 899*7c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(req); 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate s_priv->cmd_priv_xfer_type = S1394_CMD_READ; 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate switch (req->cmd_type) { 904*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_RD_QUAD: 905*7c478bd9Sstevel@tonic-gate cmd_length = IEEE1394_QUADLET; 906*7c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_quad_rd++; 907*7c478bd9Sstevel@tonic-gate break; 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_RD_BLOCK: 910*7c478bd9Sstevel@tonic-gate cmd_length = req->cmd_u.b.blk_length; 911*7c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_blk_rd++; 912*7c478bd9Sstevel@tonic-gate break; 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate default: 915*7c478bd9Sstevel@tonic-gate dip = hal->halinfo.dip; 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate /* An unexpected error in the HAL */ 918*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 919*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip)); 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate /* Disable the HAL */ 922*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_TRUE); 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_read_request_error, 925*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", 926*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Invalid command type specified"); 927*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, 928*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 929*7c478bd9Sstevel@tonic-gate return; 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate /* Lock the "used" tree */ 933*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->addr_space_used_mutex); 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate /* Has the 1394 address been allocated? */ 936*7c478bd9Sstevel@tonic-gate addr_blk = s1394_used_tree_search(hal, req->cmd_addr); 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_addr_search, 939*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate /* If it wasn't found, it isn't owned... */ 942*7c478bd9Sstevel@tonic-gate if (addr_blk == NULL) { 943*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 944*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 945*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR; 946*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 947*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, 948*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 949*7c478bd9Sstevel@tonic-gate return; 950*7c478bd9Sstevel@tonic-gate } 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate /* Does the WHOLE request fit in the allocated block? */ 953*7c478bd9Sstevel@tonic-gate end_of_request = (req->cmd_addr + cmd_length) - 1; 954*7c478bd9Sstevel@tonic-gate if (end_of_request > addr_blk->addr_hi) { 955*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 956*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 957*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR; 958*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 959*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, 960*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 961*7c478bd9Sstevel@tonic-gate return; 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate /* Is a read request valid for this address space? */ 965*7c478bd9Sstevel@tonic-gate if (!(addr_blk->addr_enable & T1394_ADDR_RDENBL)) { 966*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 967*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 968*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_TYPE_ERROR; 969*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 970*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, 971*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 972*7c478bd9Sstevel@tonic-gate return; 973*7c478bd9Sstevel@tonic-gate } 974*7c478bd9Sstevel@tonic-gate 975*7c478bd9Sstevel@tonic-gate /* Make sure quadlet requests are quadlet-aligned */ 976*7c478bd9Sstevel@tonic-gate offset = req->cmd_addr - addr_blk->addr_lo; 977*7c478bd9Sstevel@tonic-gate if ((req->cmd_type == CMD1394_ASYNCH_RD_QUAD) && 978*7c478bd9Sstevel@tonic-gate ((offset & 0x3) != 0)) { 979*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 980*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 981*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_TYPE_ERROR; 982*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 983*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, 984*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 985*7c478bd9Sstevel@tonic-gate return; 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate /* Fill in the backing store if necessary */ 989*7c478bd9Sstevel@tonic-gate if (addr_blk->kmem_bufp != NULL) { 990*7c478bd9Sstevel@tonic-gate offset = req->cmd_addr - addr_blk->addr_lo; 991*7c478bd9Sstevel@tonic-gate bufp_addr = (uchar_t *)addr_blk->kmem_bufp + offset; 992*7c478bd9Sstevel@tonic-gate 993*7c478bd9Sstevel@tonic-gate switch (req->cmd_type) { 994*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_RD_QUAD: 995*7c478bd9Sstevel@tonic-gate bcopy((void *)bufp_addr, 996*7c478bd9Sstevel@tonic-gate (void *)&(req->cmd_u.q.quadlet_data), cmd_length); 997*7c478bd9Sstevel@tonic-gate break; 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_RD_BLOCK: 1000*7c478bd9Sstevel@tonic-gate begin_ptr = req->cmd_u.b.data_block->b_wptr; 1001*7c478bd9Sstevel@tonic-gate end_ptr = begin_ptr + cmd_length; 1002*7c478bd9Sstevel@tonic-gate tmp_ptr = req->cmd_u.b.data_block->b_datap->db_lim; 1003*7c478bd9Sstevel@tonic-gate if (end_ptr <= tmp_ptr) { 1004*7c478bd9Sstevel@tonic-gate bcopy((void *)bufp_addr, (void *)begin_ptr, 1005*7c478bd9Sstevel@tonic-gate cmd_length); 1006*7c478bd9Sstevel@tonic-gate /* Update b_wptr to refelect the new data */ 1007*7c478bd9Sstevel@tonic-gate req->cmd_u.b.data_block->b_wptr = end_ptr; 1008*7c478bd9Sstevel@tonic-gate } else { 1009*7c478bd9Sstevel@tonic-gate dip = hal->halinfo.dip; 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate /* An unexpected error in the HAL */ 1012*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 1013*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip)); 1014*7c478bd9Sstevel@tonic-gate 1015*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1016*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1017*7c478bd9Sstevel@tonic-gate 1018*7c478bd9Sstevel@tonic-gate /* Disable the HAL */ 1019*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_TRUE); 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_read_request_error, 1022*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, 1023*7c478bd9Sstevel@tonic-gate msg, "Error - mblk too small for request"); 1024*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, 1025*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1026*7c478bd9Sstevel@tonic-gate return; 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate break; 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate default: 1031*7c478bd9Sstevel@tonic-gate dip = hal->halinfo.dip; 1032*7c478bd9Sstevel@tonic-gate 1033*7c478bd9Sstevel@tonic-gate /* An unexpected error in the HAL */ 1034*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 1035*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip)); 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1038*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate /* Disable the HAL */ 1041*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_TRUE); 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_read_request_error, 1044*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, msg, 1045*7c478bd9Sstevel@tonic-gate "Invalid command type specified"); 1046*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, 1047*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1048*7c478bd9Sstevel@tonic-gate return; 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate } 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate /* Fill in the rest of the info in the request */ 1053*7c478bd9Sstevel@tonic-gate s_priv->arreq_valid_addr = B_TRUE; 1054*7c478bd9Sstevel@tonic-gate req->cmd_callback_arg = addr_blk->addr_arg; 1055*7c478bd9Sstevel@tonic-gate recv_read_req = addr_blk->addr_events.recv_read_request; 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1058*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1059*7c478bd9Sstevel@tonic-gate 1060*7c478bd9Sstevel@tonic-gate /* 1061*7c478bd9Sstevel@tonic-gate * Add no code that modifies the command after the target 1062*7c478bd9Sstevel@tonic-gate * callback is called or after the response is sent to the 1063*7c478bd9Sstevel@tonic-gate * HAL. 1064*7c478bd9Sstevel@tonic-gate */ 1065*7c478bd9Sstevel@tonic-gate if (recv_read_req != NULL) { 1066*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_do_callback, 1067*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1068*7c478bd9Sstevel@tonic-gate recv_read_req(req); 1069*7c478bd9Sstevel@tonic-gate } else { 1070*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_COMPLETE; 1071*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1072*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, 1073*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1074*7c478bd9Sstevel@tonic-gate return; 1075*7c478bd9Sstevel@tonic-gate } 1076*7c478bd9Sstevel@tonic-gate 1077*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_read_request_exit, S1394_TNF_SL_ARREQ_STACK, 1078*7c478bd9Sstevel@tonic-gate ""); 1079*7c478bd9Sstevel@tonic-gate } 1080*7c478bd9Sstevel@tonic-gate 1081*7c478bd9Sstevel@tonic-gate /* 1082*7c478bd9Sstevel@tonic-gate * Function: h1394_write_request() 1083*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 1084*7c478bd9Sstevel@tonic-gate * h1394_attach() 1085*7c478bd9Sstevel@tonic-gate * req The incoming AR request 1086*7c478bd9Sstevel@tonic-gate * 1087*7c478bd9Sstevel@tonic-gate * Output(s): None 1088*7c478bd9Sstevel@tonic-gate * 1089*7c478bd9Sstevel@tonic-gate * Description: h1394_write_request() receives incoming AR requests. These 1090*7c478bd9Sstevel@tonic-gate * asynchronous write requests are dispatched to the appropriate 1091*7c478bd9Sstevel@tonic-gate * target (if one has registered) or are handled by the 1394 1092*7c478bd9Sstevel@tonic-gate * Software Framework, which will send out an appropriate 1093*7c478bd9Sstevel@tonic-gate * response. 1094*7c478bd9Sstevel@tonic-gate */ 1095*7c478bd9Sstevel@tonic-gate void 1096*7c478bd9Sstevel@tonic-gate h1394_write_request(void *sl_private, cmd1394_cmd_t *req) 1097*7c478bd9Sstevel@tonic-gate { 1098*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 1099*7c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 1100*7c478bd9Sstevel@tonic-gate h1394_cmd_priv_t *h_priv; 1101*7c478bd9Sstevel@tonic-gate s1394_addr_space_blk_t *addr_blk; 1102*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 1103*7c478bd9Sstevel@tonic-gate uint32_t offset; 1104*7c478bd9Sstevel@tonic-gate size_t cmd_length; 1105*7c478bd9Sstevel@tonic-gate uchar_t *bufp_addr; 1106*7c478bd9Sstevel@tonic-gate uchar_t *begin_ptr; 1107*7c478bd9Sstevel@tonic-gate uchar_t *end_ptr; 1108*7c478bd9Sstevel@tonic-gate uchar_t *tmp_ptr; 1109*7c478bd9Sstevel@tonic-gate uint64_t end_of_request; 1110*7c478bd9Sstevel@tonic-gate boolean_t posted_write = B_FALSE; 1111*7c478bd9Sstevel@tonic-gate boolean_t write_error = B_FALSE; 1112*7c478bd9Sstevel@tonic-gate void (*recv_write_req)(cmd1394_cmd_t *); 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_enter, S1394_TNF_SL_ARREQ_STACK, 1115*7c478bd9Sstevel@tonic-gate ""); 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 1120*7c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(req); 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate s_priv->cmd_priv_xfer_type = S1394_CMD_WRITE; 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate switch (req->cmd_type) { 1125*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_WR_QUAD: 1126*7c478bd9Sstevel@tonic-gate cmd_length = IEEE1394_QUADLET; 1127*7c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_quad_wr++; 1128*7c478bd9Sstevel@tonic-gate break; 1129*7c478bd9Sstevel@tonic-gate 1130*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_WR_BLOCK: 1131*7c478bd9Sstevel@tonic-gate cmd_length = req->cmd_u.b.blk_length; 1132*7c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_blk_wr++; 1133*7c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_blk_wr_size += cmd_length; 1134*7c478bd9Sstevel@tonic-gate break; 1135*7c478bd9Sstevel@tonic-gate 1136*7c478bd9Sstevel@tonic-gate default: 1137*7c478bd9Sstevel@tonic-gate dip = hal->halinfo.dip; 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate /* An unexpected error in the HAL */ 1140*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 1141*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip)); 1142*7c478bd9Sstevel@tonic-gate 1143*7c478bd9Sstevel@tonic-gate /* Disable the HAL */ 1144*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_TRUE); 1145*7c478bd9Sstevel@tonic-gate 1146*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_write_request_error, 1147*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, msg, 1148*7c478bd9Sstevel@tonic-gate "Invalid command type specified"); 1149*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_exit, 1150*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1151*7c478bd9Sstevel@tonic-gate return; 1152*7c478bd9Sstevel@tonic-gate } 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate /* Lock the "used" tree */ 1155*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->addr_space_used_mutex); 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate /* Has the 1394 address been allocated? */ 1158*7c478bd9Sstevel@tonic-gate addr_blk = s1394_used_tree_search(hal, req->cmd_addr); 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_addr_search, 1161*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1162*7c478bd9Sstevel@tonic-gate 1163*7c478bd9Sstevel@tonic-gate /* Is this a posted write request? */ 1164*7c478bd9Sstevel@tonic-gate posted_write = s1394_is_posted_write(hal, req->cmd_addr); 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate /* If it wasn't found, it isn't owned... */ 1167*7c478bd9Sstevel@tonic-gate if (addr_blk == NULL) { 1168*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR; 1169*7c478bd9Sstevel@tonic-gate write_error = B_TRUE; 1170*7c478bd9Sstevel@tonic-gate goto write_error_check; 1171*7c478bd9Sstevel@tonic-gate } 1172*7c478bd9Sstevel@tonic-gate 1173*7c478bd9Sstevel@tonic-gate /* Does the WHOLE request fit in the allocated block? */ 1174*7c478bd9Sstevel@tonic-gate end_of_request = (req->cmd_addr + cmd_length) - 1; 1175*7c478bd9Sstevel@tonic-gate if (end_of_request > addr_blk->addr_hi) { 1176*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR; 1177*7c478bd9Sstevel@tonic-gate write_error = B_TRUE; 1178*7c478bd9Sstevel@tonic-gate goto write_error_check; 1179*7c478bd9Sstevel@tonic-gate } 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate /* Is a write request valid for this address space? */ 1182*7c478bd9Sstevel@tonic-gate if (!(addr_blk->addr_enable & T1394_ADDR_WRENBL)) { 1183*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_TYPE_ERROR; 1184*7c478bd9Sstevel@tonic-gate write_error = B_TRUE; 1185*7c478bd9Sstevel@tonic-gate goto write_error_check; 1186*7c478bd9Sstevel@tonic-gate } 1187*7c478bd9Sstevel@tonic-gate 1188*7c478bd9Sstevel@tonic-gate /* Make sure quadlet request is quadlet aligned */ 1189*7c478bd9Sstevel@tonic-gate offset = req->cmd_addr - addr_blk->addr_lo; 1190*7c478bd9Sstevel@tonic-gate if ((req->cmd_type == CMD1394_ASYNCH_WR_QUAD) && 1191*7c478bd9Sstevel@tonic-gate ((offset & 0x3) != 0)) { 1192*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_TYPE_ERROR; 1193*7c478bd9Sstevel@tonic-gate write_error = B_TRUE; 1194*7c478bd9Sstevel@tonic-gate goto write_error_check; 1195*7c478bd9Sstevel@tonic-gate } 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate write_error_check: 1198*7c478bd9Sstevel@tonic-gate /* Check if posted-write when sending error responses */ 1199*7c478bd9Sstevel@tonic-gate if (write_error == B_TRUE) { 1200*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1201*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate if (posted_write == B_TRUE) { 1204*7c478bd9Sstevel@tonic-gate /* Get a pointer to the HAL private struct */ 1205*7c478bd9Sstevel@tonic-gate h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private; 1206*7c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_posted_write_error++; 1207*7c478bd9Sstevel@tonic-gate /* Free the command - Pass it back to the HAL */ 1208*7c478bd9Sstevel@tonic-gate HAL_CALL(hal).response_complete( 1209*7c478bd9Sstevel@tonic-gate hal->halinfo.hal_private, req, h_priv); 1210*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_exit, 1211*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1212*7c478bd9Sstevel@tonic-gate return; 1213*7c478bd9Sstevel@tonic-gate } else { 1214*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1215*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_exit, 1216*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1217*7c478bd9Sstevel@tonic-gate return; 1218*7c478bd9Sstevel@tonic-gate } 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate 1221*7c478bd9Sstevel@tonic-gate /* Fill in the backing store if necessary */ 1222*7c478bd9Sstevel@tonic-gate if (addr_blk->kmem_bufp != NULL) { 1223*7c478bd9Sstevel@tonic-gate offset = req->cmd_addr - addr_blk->addr_lo; 1224*7c478bd9Sstevel@tonic-gate bufp_addr = (uchar_t *)addr_blk->kmem_bufp + offset; 1225*7c478bd9Sstevel@tonic-gate switch (req->cmd_type) { 1226*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_WR_QUAD: 1227*7c478bd9Sstevel@tonic-gate bcopy((void *)&(req->cmd_u.q.quadlet_data), 1228*7c478bd9Sstevel@tonic-gate (void *)bufp_addr, cmd_length); 1229*7c478bd9Sstevel@tonic-gate break; 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_WR_BLOCK: 1232*7c478bd9Sstevel@tonic-gate begin_ptr = req->cmd_u.b.data_block->b_rptr; 1233*7c478bd9Sstevel@tonic-gate end_ptr = begin_ptr + cmd_length; 1234*7c478bd9Sstevel@tonic-gate tmp_ptr = req->cmd_u.b.data_block->b_wptr; 1235*7c478bd9Sstevel@tonic-gate if (end_ptr <= tmp_ptr) { 1236*7c478bd9Sstevel@tonic-gate bcopy((void *)begin_ptr, (void *)bufp_addr, 1237*7c478bd9Sstevel@tonic-gate cmd_length); 1238*7c478bd9Sstevel@tonic-gate } else { 1239*7c478bd9Sstevel@tonic-gate dip = hal->halinfo.dip; 1240*7c478bd9Sstevel@tonic-gate 1241*7c478bd9Sstevel@tonic-gate /* An unexpected error in the HAL */ 1242*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 1243*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip)); 1244*7c478bd9Sstevel@tonic-gate 1245*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1246*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1247*7c478bd9Sstevel@tonic-gate 1248*7c478bd9Sstevel@tonic-gate /* Disable the HAL */ 1249*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_TRUE); 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_write_request_error, 1252*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, 1253*7c478bd9Sstevel@tonic-gate msg, "Error - mblk too small for request"); 1254*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_exit, 1255*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1256*7c478bd9Sstevel@tonic-gate return; 1257*7c478bd9Sstevel@tonic-gate } 1258*7c478bd9Sstevel@tonic-gate break; 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate default: 1261*7c478bd9Sstevel@tonic-gate dip = hal->halinfo.dip; 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate /* An unexpected error in the HAL */ 1264*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 1265*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip)); 1266*7c478bd9Sstevel@tonic-gate 1267*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1268*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate /* Disable the HAL */ 1271*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_TRUE); 1272*7c478bd9Sstevel@tonic-gate 1273*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_write_request_error, 1274*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, msg, 1275*7c478bd9Sstevel@tonic-gate "Invalid command type specified"); 1276*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_exit, 1277*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1278*7c478bd9Sstevel@tonic-gate return; 1279*7c478bd9Sstevel@tonic-gate } 1280*7c478bd9Sstevel@tonic-gate } 1281*7c478bd9Sstevel@tonic-gate 1282*7c478bd9Sstevel@tonic-gate /* Fill in the rest of the info in the request */ 1283*7c478bd9Sstevel@tonic-gate if (addr_blk->addr_type == T1394_ADDR_POSTED_WRITE) 1284*7c478bd9Sstevel@tonic-gate s_priv->posted_write = B_TRUE; 1285*7c478bd9Sstevel@tonic-gate 1286*7c478bd9Sstevel@tonic-gate s_priv->arreq_valid_addr = B_TRUE; 1287*7c478bd9Sstevel@tonic-gate req->cmd_callback_arg = addr_blk->addr_arg; 1288*7c478bd9Sstevel@tonic-gate recv_write_req = addr_blk->addr_events.recv_write_request; 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1291*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate /* 1294*7c478bd9Sstevel@tonic-gate * Add no code that modifies the command after the target 1295*7c478bd9Sstevel@tonic-gate * callback is called or after the response is sent to the 1296*7c478bd9Sstevel@tonic-gate * HAL. 1297*7c478bd9Sstevel@tonic-gate */ 1298*7c478bd9Sstevel@tonic-gate if (recv_write_req != NULL) { 1299*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_do_callback, 1300*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1301*7c478bd9Sstevel@tonic-gate recv_write_req(req); 1302*7c478bd9Sstevel@tonic-gate } else { 1303*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_COMPLETE; 1304*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1305*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_exit, 1306*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1307*7c478bd9Sstevel@tonic-gate return; 1308*7c478bd9Sstevel@tonic-gate } 1309*7c478bd9Sstevel@tonic-gate 1310*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_write_request_exit, 1311*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1312*7c478bd9Sstevel@tonic-gate } 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate /* 1315*7c478bd9Sstevel@tonic-gate * Function: h1394_lock_request() 1316*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 1317*7c478bd9Sstevel@tonic-gate * h1394_attach() 1318*7c478bd9Sstevel@tonic-gate * req The incoming AR request 1319*7c478bd9Sstevel@tonic-gate * 1320*7c478bd9Sstevel@tonic-gate * Output(s): None 1321*7c478bd9Sstevel@tonic-gate * 1322*7c478bd9Sstevel@tonic-gate * Description: h1394_lock_request() receives incoming AR requests. These 1323*7c478bd9Sstevel@tonic-gate * asynchronous lock requests are dispatched to the appropriate 1324*7c478bd9Sstevel@tonic-gate * target (if one has registered) or are handled by the 1394 1325*7c478bd9Sstevel@tonic-gate * Software Framework, which will send out an appropriate 1326*7c478bd9Sstevel@tonic-gate * response. 1327*7c478bd9Sstevel@tonic-gate */ 1328*7c478bd9Sstevel@tonic-gate void 1329*7c478bd9Sstevel@tonic-gate h1394_lock_request(void *sl_private, cmd1394_cmd_t *req) 1330*7c478bd9Sstevel@tonic-gate { 1331*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 1332*7c478bd9Sstevel@tonic-gate s1394_cmd_priv_t *s_priv; 1333*7c478bd9Sstevel@tonic-gate s1394_addr_space_blk_t *addr_blk; 1334*7c478bd9Sstevel@tonic-gate dev_info_t *dip; 1335*7c478bd9Sstevel@tonic-gate uint64_t end_of_request; 1336*7c478bd9Sstevel@tonic-gate uint32_t offset; 1337*7c478bd9Sstevel@tonic-gate uchar_t *bufp_addr; 1338*7c478bd9Sstevel@tonic-gate cmd1394_lock_type_t lock_type; 1339*7c478bd9Sstevel@tonic-gate void (*recv_lock_req)(cmd1394_cmd_t *); 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_enter, 1342*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1343*7c478bd9Sstevel@tonic-gate 1344*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate /* Get the Services Layer private area */ 1347*7c478bd9Sstevel@tonic-gate s_priv = S1394_GET_CMD_PRIV(req); 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate s_priv->cmd_priv_xfer_type = S1394_CMD_LOCK; 1350*7c478bd9Sstevel@tonic-gate 1351*7c478bd9Sstevel@tonic-gate /* Lock the "used" tree */ 1352*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->addr_space_used_mutex); 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate /* Has the 1394 address been allocated? */ 1355*7c478bd9Sstevel@tonic-gate addr_blk = s1394_used_tree_search(hal, req->cmd_addr); 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate /* If it wasn't found, it isn't owned... */ 1358*7c478bd9Sstevel@tonic-gate if (addr_blk == NULL) { 1359*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1360*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1361*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR; 1362*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1363*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_exit, 1364*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1365*7c478bd9Sstevel@tonic-gate return; 1366*7c478bd9Sstevel@tonic-gate } 1367*7c478bd9Sstevel@tonic-gate 1368*7c478bd9Sstevel@tonic-gate /* Does the WHOLE request fit in the allocated block? */ 1369*7c478bd9Sstevel@tonic-gate switch (req->cmd_type) { 1370*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_LOCK_32: 1371*7c478bd9Sstevel@tonic-gate end_of_request = (req->cmd_addr + IEEE1394_QUADLET) - 1; 1372*7c478bd9Sstevel@tonic-gate /* kstats - 32-bit lock request */ 1373*7c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_lock32++; 1374*7c478bd9Sstevel@tonic-gate break; 1375*7c478bd9Sstevel@tonic-gate 1376*7c478bd9Sstevel@tonic-gate case CMD1394_ASYNCH_LOCK_64: 1377*7c478bd9Sstevel@tonic-gate end_of_request = (req->cmd_addr + IEEE1394_OCTLET) - 1; 1378*7c478bd9Sstevel@tonic-gate /* kstats - 64-bit lock request */ 1379*7c478bd9Sstevel@tonic-gate hal->hal_kstats->arreq_lock64++; 1380*7c478bd9Sstevel@tonic-gate break; 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate default: 1383*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1384*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1385*7c478bd9Sstevel@tonic-gate 1386*7c478bd9Sstevel@tonic-gate dip = hal->halinfo.dip; 1387*7c478bd9Sstevel@tonic-gate 1388*7c478bd9Sstevel@tonic-gate /* An unexpected error in the HAL */ 1389*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, HALT_ERROR_MESSAGE, 1390*7c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip)); 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate /* Disable the HAL */ 1393*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_TRUE); 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_lock_request_error, 1396*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, msg, 1397*7c478bd9Sstevel@tonic-gate "Invalid command type specified"); 1398*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_exit, 1399*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1400*7c478bd9Sstevel@tonic-gate return; 1401*7c478bd9Sstevel@tonic-gate } 1402*7c478bd9Sstevel@tonic-gate 1403*7c478bd9Sstevel@tonic-gate if (end_of_request > addr_blk->addr_hi) { 1404*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1405*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1406*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR; 1407*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1408*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_exit, 1409*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1410*7c478bd9Sstevel@tonic-gate return; 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate /* Is a lock request valid for this address space? */ 1414*7c478bd9Sstevel@tonic-gate if (!(addr_blk->addr_enable & T1394_ADDR_LKENBL)) { 1415*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1416*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1417*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_TYPE_ERROR; 1418*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1419*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_exit, 1420*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1421*7c478bd9Sstevel@tonic-gate return; 1422*7c478bd9Sstevel@tonic-gate } 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate /* Fill in the backing store if necessary */ 1425*7c478bd9Sstevel@tonic-gate if (addr_blk->kmem_bufp != NULL) { 1426*7c478bd9Sstevel@tonic-gate offset = req->cmd_addr - addr_blk->addr_lo; 1427*7c478bd9Sstevel@tonic-gate bufp_addr = (uchar_t *)addr_blk->kmem_bufp + offset; 1428*7c478bd9Sstevel@tonic-gate 1429*7c478bd9Sstevel@tonic-gate if (req->cmd_type == CMD1394_ASYNCH_LOCK_32) { 1430*7c478bd9Sstevel@tonic-gate uint32_t old_value; 1431*7c478bd9Sstevel@tonic-gate uint32_t arg_value; 1432*7c478bd9Sstevel@tonic-gate uint32_t data_value; 1433*7c478bd9Sstevel@tonic-gate uint32_t new_value; 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate arg_value = req->cmd_u.l32.arg_value; 1436*7c478bd9Sstevel@tonic-gate data_value = req->cmd_u.l32.data_value; 1437*7c478bd9Sstevel@tonic-gate lock_type = req->cmd_u.l32.lock_type; 1438*7c478bd9Sstevel@tonic-gate bcopy((void *)bufp_addr, (void *)&old_value, 1439*7c478bd9Sstevel@tonic-gate IEEE1394_QUADLET); 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate switch (lock_type) { 1442*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_MASK_SWAP: 1443*7c478bd9Sstevel@tonic-gate /* Mask-Swap (see P1394A - Table 1.7) */ 1444*7c478bd9Sstevel@tonic-gate new_value = (data_value & arg_value) | 1445*7c478bd9Sstevel@tonic-gate (old_value & ~arg_value); 1446*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1447*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, (void *)bufp_addr, 1448*7c478bd9Sstevel@tonic-gate IEEE1394_QUADLET); 1449*7c478bd9Sstevel@tonic-gate req->cmd_u.l32.old_value = old_value; 1450*7c478bd9Sstevel@tonic-gate break; 1451*7c478bd9Sstevel@tonic-gate 1452*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_COMPARE_SWAP: 1453*7c478bd9Sstevel@tonic-gate /* Compare-Swap */ 1454*7c478bd9Sstevel@tonic-gate if (old_value == arg_value) { 1455*7c478bd9Sstevel@tonic-gate new_value = data_value; 1456*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1457*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, 1458*7c478bd9Sstevel@tonic-gate (void *)bufp_addr, 1459*7c478bd9Sstevel@tonic-gate IEEE1394_QUADLET); 1460*7c478bd9Sstevel@tonic-gate } 1461*7c478bd9Sstevel@tonic-gate req->cmd_u.l32.old_value = old_value; 1462*7c478bd9Sstevel@tonic-gate break; 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_FETCH_ADD: 1465*7c478bd9Sstevel@tonic-gate /* Fetch-Add (see P1394A - Table 1.7) */ 1466*7c478bd9Sstevel@tonic-gate old_value = T1394_DATA32(old_value); 1467*7c478bd9Sstevel@tonic-gate new_value = old_value + data_value; 1468*7c478bd9Sstevel@tonic-gate new_value = T1394_DATA32(new_value); 1469*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1470*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, (void *)bufp_addr, 1471*7c478bd9Sstevel@tonic-gate IEEE1394_QUADLET); 1472*7c478bd9Sstevel@tonic-gate req->cmd_u.l32.old_value = old_value; 1473*7c478bd9Sstevel@tonic-gate break; 1474*7c478bd9Sstevel@tonic-gate 1475*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_LITTLE_ADD: 1476*7c478bd9Sstevel@tonic-gate /* Little-Add (see P1394A - Table 1.7) */ 1477*7c478bd9Sstevel@tonic-gate old_value = T1394_DATA32(old_value); 1478*7c478bd9Sstevel@tonic-gate new_value = old_value + data_value; 1479*7c478bd9Sstevel@tonic-gate new_value = T1394_DATA32(new_value); 1480*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1481*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, (void *)bufp_addr, 1482*7c478bd9Sstevel@tonic-gate IEEE1394_QUADLET); 1483*7c478bd9Sstevel@tonic-gate req->cmd_u.l32.old_value = old_value; 1484*7c478bd9Sstevel@tonic-gate break; 1485*7c478bd9Sstevel@tonic-gate 1486*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_BOUNDED_ADD: 1487*7c478bd9Sstevel@tonic-gate /* Bounded-Add (see P1394A - Table 1.7) */ 1488*7c478bd9Sstevel@tonic-gate old_value = T1394_DATA32(old_value); 1489*7c478bd9Sstevel@tonic-gate if (old_value != arg_value) { 1490*7c478bd9Sstevel@tonic-gate new_value = old_value + data_value; 1491*7c478bd9Sstevel@tonic-gate new_value = T1394_DATA32(new_value); 1492*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1493*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, 1494*7c478bd9Sstevel@tonic-gate (void *)bufp_addr, 1495*7c478bd9Sstevel@tonic-gate IEEE1394_QUADLET); 1496*7c478bd9Sstevel@tonic-gate } 1497*7c478bd9Sstevel@tonic-gate req->cmd_u.l32.old_value = old_value; 1498*7c478bd9Sstevel@tonic-gate break; 1499*7c478bd9Sstevel@tonic-gate 1500*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_WRAP_ADD: 1501*7c478bd9Sstevel@tonic-gate /* Wrap-Add (see P1394A - Table 1.7) */ 1502*7c478bd9Sstevel@tonic-gate old_value = T1394_DATA32(old_value); 1503*7c478bd9Sstevel@tonic-gate if (old_value != arg_value) { 1504*7c478bd9Sstevel@tonic-gate new_value = old_value + data_value; 1505*7c478bd9Sstevel@tonic-gate } else { 1506*7c478bd9Sstevel@tonic-gate new_value = data_value; 1507*7c478bd9Sstevel@tonic-gate } 1508*7c478bd9Sstevel@tonic-gate new_value = T1394_DATA32(new_value); 1509*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1510*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, (void *)bufp_addr, 1511*7c478bd9Sstevel@tonic-gate IEEE1394_QUADLET); 1512*7c478bd9Sstevel@tonic-gate req->cmd_u.l32.old_value = old_value; 1513*7c478bd9Sstevel@tonic-gate break; 1514*7c478bd9Sstevel@tonic-gate 1515*7c478bd9Sstevel@tonic-gate default: 1516*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1517*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1518*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_TYPE_ERROR; 1519*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1520*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_lock_request_error, 1521*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, 1522*7c478bd9Sstevel@tonic-gate msg, "Invalid lock_type"); 1523*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_exit, 1524*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1525*7c478bd9Sstevel@tonic-gate return; 1526*7c478bd9Sstevel@tonic-gate } 1527*7c478bd9Sstevel@tonic-gate } else { 1528*7c478bd9Sstevel@tonic-gate /* Handling for the 8-byte (64-bit) lock requests */ 1529*7c478bd9Sstevel@tonic-gate uint64_t old_value; 1530*7c478bd9Sstevel@tonic-gate uint64_t arg_value; 1531*7c478bd9Sstevel@tonic-gate uint64_t data_value; 1532*7c478bd9Sstevel@tonic-gate uint64_t new_value; 1533*7c478bd9Sstevel@tonic-gate 1534*7c478bd9Sstevel@tonic-gate arg_value = req->cmd_u.l64.arg_value; 1535*7c478bd9Sstevel@tonic-gate data_value = req->cmd_u.l64.data_value; 1536*7c478bd9Sstevel@tonic-gate lock_type = req->cmd_u.l64.lock_type; 1537*7c478bd9Sstevel@tonic-gate bcopy((void *)bufp_addr, (void *)&old_value, 1538*7c478bd9Sstevel@tonic-gate IEEE1394_OCTLET); 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate switch (lock_type) { 1541*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_MASK_SWAP: 1542*7c478bd9Sstevel@tonic-gate /* Mask-Swap (see P1394A - Table 1.7) */ 1543*7c478bd9Sstevel@tonic-gate new_value = (data_value & arg_value) | 1544*7c478bd9Sstevel@tonic-gate (old_value & ~arg_value); 1545*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1546*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, (void *)bufp_addr, 1547*7c478bd9Sstevel@tonic-gate IEEE1394_OCTLET); 1548*7c478bd9Sstevel@tonic-gate req->cmd_u.l64.old_value = old_value; 1549*7c478bd9Sstevel@tonic-gate break; 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_COMPARE_SWAP: 1552*7c478bd9Sstevel@tonic-gate /* Compare-Swap */ 1553*7c478bd9Sstevel@tonic-gate if (old_value == arg_value) { 1554*7c478bd9Sstevel@tonic-gate new_value = data_value; 1555*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1556*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, 1557*7c478bd9Sstevel@tonic-gate (void *)bufp_addr, 1558*7c478bd9Sstevel@tonic-gate IEEE1394_OCTLET); 1559*7c478bd9Sstevel@tonic-gate } 1560*7c478bd9Sstevel@tonic-gate req->cmd_u.l64.old_value = old_value; 1561*7c478bd9Sstevel@tonic-gate break; 1562*7c478bd9Sstevel@tonic-gate 1563*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_FETCH_ADD: 1564*7c478bd9Sstevel@tonic-gate /* Fetch-Add (see P1394A - Table 1.7) */ 1565*7c478bd9Sstevel@tonic-gate old_value = T1394_DATA64(old_value); 1566*7c478bd9Sstevel@tonic-gate new_value = old_value + data_value; 1567*7c478bd9Sstevel@tonic-gate new_value = T1394_DATA64(new_value); 1568*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1569*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, (void *)bufp_addr, 1570*7c478bd9Sstevel@tonic-gate IEEE1394_OCTLET); 1571*7c478bd9Sstevel@tonic-gate req->cmd_u.l64.old_value = old_value; 1572*7c478bd9Sstevel@tonic-gate break; 1573*7c478bd9Sstevel@tonic-gate 1574*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_LITTLE_ADD: 1575*7c478bd9Sstevel@tonic-gate /* Little-Add (see P1394A - Table 1.7) */ 1576*7c478bd9Sstevel@tonic-gate old_value = T1394_DATA64(old_value); 1577*7c478bd9Sstevel@tonic-gate new_value = old_value + data_value; 1578*7c478bd9Sstevel@tonic-gate new_value = T1394_DATA64(new_value); 1579*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1580*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, (void *)bufp_addr, 1581*7c478bd9Sstevel@tonic-gate IEEE1394_OCTLET); 1582*7c478bd9Sstevel@tonic-gate req->cmd_u.l64.old_value = old_value; 1583*7c478bd9Sstevel@tonic-gate break; 1584*7c478bd9Sstevel@tonic-gate 1585*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_BOUNDED_ADD: 1586*7c478bd9Sstevel@tonic-gate /* Bounded-Add (see P1394A - Table 1.7) */ 1587*7c478bd9Sstevel@tonic-gate old_value = T1394_DATA64(old_value); 1588*7c478bd9Sstevel@tonic-gate if (old_value != arg_value) { 1589*7c478bd9Sstevel@tonic-gate new_value = old_value + data_value; 1590*7c478bd9Sstevel@tonic-gate new_value = T1394_DATA64(new_value); 1591*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1592*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, 1593*7c478bd9Sstevel@tonic-gate (void *)bufp_addr, 1594*7c478bd9Sstevel@tonic-gate IEEE1394_OCTLET); 1595*7c478bd9Sstevel@tonic-gate } 1596*7c478bd9Sstevel@tonic-gate req->cmd_u.l64.old_value = old_value; 1597*7c478bd9Sstevel@tonic-gate break; 1598*7c478bd9Sstevel@tonic-gate 1599*7c478bd9Sstevel@tonic-gate case CMD1394_LOCK_WRAP_ADD: 1600*7c478bd9Sstevel@tonic-gate /* Wrap-Add (see P1394A - Table 1.7) */ 1601*7c478bd9Sstevel@tonic-gate old_value = T1394_DATA64(old_value); 1602*7c478bd9Sstevel@tonic-gate if (old_value != arg_value) { 1603*7c478bd9Sstevel@tonic-gate new_value = old_value + data_value; 1604*7c478bd9Sstevel@tonic-gate } else { 1605*7c478bd9Sstevel@tonic-gate new_value = data_value; 1606*7c478bd9Sstevel@tonic-gate } 1607*7c478bd9Sstevel@tonic-gate new_value = T1394_DATA64(new_value); 1608*7c478bd9Sstevel@tonic-gate /* Copy new_value into backing store */ 1609*7c478bd9Sstevel@tonic-gate bcopy((void *)&new_value, (void *)bufp_addr, 1610*7c478bd9Sstevel@tonic-gate IEEE1394_OCTLET); 1611*7c478bd9Sstevel@tonic-gate req->cmd_u.l64.old_value = old_value; 1612*7c478bd9Sstevel@tonic-gate break; 1613*7c478bd9Sstevel@tonic-gate 1614*7c478bd9Sstevel@tonic-gate default: 1615*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1616*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1617*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_TYPE_ERROR; 1618*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1619*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_lock_request_error, 1620*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_ERROR, "", tnf_string, 1621*7c478bd9Sstevel@tonic-gate msg, "Invalid lock_type"); 1622*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_exit, 1623*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1624*7c478bd9Sstevel@tonic-gate return; 1625*7c478bd9Sstevel@tonic-gate } 1626*7c478bd9Sstevel@tonic-gate } 1627*7c478bd9Sstevel@tonic-gate } 1628*7c478bd9Sstevel@tonic-gate 1629*7c478bd9Sstevel@tonic-gate /* Fill in the rest of the info in the request */ 1630*7c478bd9Sstevel@tonic-gate s_priv->arreq_valid_addr = B_TRUE; 1631*7c478bd9Sstevel@tonic-gate req->cmd_callback_arg = addr_blk->addr_arg; 1632*7c478bd9Sstevel@tonic-gate recv_lock_req = addr_blk->addr_events.recv_lock_request; 1633*7c478bd9Sstevel@tonic-gate 1634*7c478bd9Sstevel@tonic-gate /* Unlock the "used" tree */ 1635*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->addr_space_used_mutex); 1636*7c478bd9Sstevel@tonic-gate 1637*7c478bd9Sstevel@tonic-gate /* 1638*7c478bd9Sstevel@tonic-gate * Add no code that modifies the command after the target 1639*7c478bd9Sstevel@tonic-gate * callback is called or after the response is sent to the 1640*7c478bd9Sstevel@tonic-gate * HAL. 1641*7c478bd9Sstevel@tonic-gate */ 1642*7c478bd9Sstevel@tonic-gate if (recv_lock_req != NULL) { 1643*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_do_callback, 1644*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1645*7c478bd9Sstevel@tonic-gate recv_lock_req(req); 1646*7c478bd9Sstevel@tonic-gate } else { 1647*7c478bd9Sstevel@tonic-gate req->cmd_result = IEEE1394_RESP_COMPLETE; 1648*7c478bd9Sstevel@tonic-gate (void) s1394_send_response(hal, req); 1649*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_exit, 1650*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1651*7c478bd9Sstevel@tonic-gate return; 1652*7c478bd9Sstevel@tonic-gate } 1653*7c478bd9Sstevel@tonic-gate 1654*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_lock_request_exit, 1655*7c478bd9Sstevel@tonic-gate S1394_TNF_SL_ARREQ_STACK, ""); 1656*7c478bd9Sstevel@tonic-gate } 1657*7c478bd9Sstevel@tonic-gate 1658*7c478bd9Sstevel@tonic-gate /* 1659*7c478bd9Sstevel@tonic-gate * Function: h1394_ioctl() 1660*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 1661*7c478bd9Sstevel@tonic-gate * h1394_attach() 1662*7c478bd9Sstevel@tonic-gate * cmd ioctl cmd 1663*7c478bd9Sstevel@tonic-gate * arg argument for the ioctl cmd 1664*7c478bd9Sstevel@tonic-gate * mode mode bits (see ioctl(9e)) 1665*7c478bd9Sstevel@tonic-gate * cred_p cred structure pointer 1666*7c478bd9Sstevel@tonic-gate * rval_p pointer to return value (see ioctl(9e)) 1667*7c478bd9Sstevel@tonic-gate * 1668*7c478bd9Sstevel@tonic-gate * Output(s): EINVAL if not a DEVCTL ioctl, else return value from s1394_ioctl 1669*7c478bd9Sstevel@tonic-gate * 1670*7c478bd9Sstevel@tonic-gate * Description: h1394_ioctl() implements non-HAL specific ioctls. Currently, 1671*7c478bd9Sstevel@tonic-gate * DEVCTL ioctls are the only generic ioctls supported. 1672*7c478bd9Sstevel@tonic-gate */ 1673*7c478bd9Sstevel@tonic-gate int 1674*7c478bd9Sstevel@tonic-gate h1394_ioctl(void *sl_private, int cmd, intptr_t arg, int mode, cred_t *cred_p, 1675*7c478bd9Sstevel@tonic-gate int *rval_p) 1676*7c478bd9Sstevel@tonic-gate { 1677*7c478bd9Sstevel@tonic-gate int status; 1678*7c478bd9Sstevel@tonic-gate 1679*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_ioctl_enter, S1394_TNF_SL_IOCTL_STACK, ""); 1680*7c478bd9Sstevel@tonic-gate 1681*7c478bd9Sstevel@tonic-gate if ((cmd & DEVCTL_IOC) != DEVCTL_IOC) 1682*7c478bd9Sstevel@tonic-gate return (EINVAL); 1683*7c478bd9Sstevel@tonic-gate 1684*7c478bd9Sstevel@tonic-gate status = s1394_ioctl((s1394_hal_t *)sl_private, cmd, arg, mode, 1685*7c478bd9Sstevel@tonic-gate cred_p, rval_p); 1686*7c478bd9Sstevel@tonic-gate 1687*7c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(h1394_ioctl_exit, S1394_TNF_SL_IOCTL_STACK, "", 1688*7c478bd9Sstevel@tonic-gate tnf_int, status, status); 1689*7c478bd9Sstevel@tonic-gate return (status); 1690*7c478bd9Sstevel@tonic-gate } 1691*7c478bd9Sstevel@tonic-gate 1692*7c478bd9Sstevel@tonic-gate /* 1693*7c478bd9Sstevel@tonic-gate * Function: h1394_phy_packet() 1694*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 1695*7c478bd9Sstevel@tonic-gate * h1394_attach() 1696*7c478bd9Sstevel@tonic-gate * packet_data Pointer to a buffer of packet data 1697*7c478bd9Sstevel@tonic-gate * quadlet_count Length of the buffer 1698*7c478bd9Sstevel@tonic-gate * timestamp Timestamp indicating time of arrival 1699*7c478bd9Sstevel@tonic-gate * 1700*7c478bd9Sstevel@tonic-gate * Output(s): None 1701*7c478bd9Sstevel@tonic-gate * 1702*7c478bd9Sstevel@tonic-gate * Description: h1394_phy_packet() is not implemented currently, but would 1703*7c478bd9Sstevel@tonic-gate * be used to process the responses to PHY ping packets in P1394A 1704*7c478bd9Sstevel@tonic-gate * When one is sent out, a timestamp is given indicating its time 1705*7c478bd9Sstevel@tonic-gate * of departure. Comparing that old timestamp with this new 1706*7c478bd9Sstevel@tonic-gate * timestamp, we can determine the time of flight and can use 1707*7c478bd9Sstevel@tonic-gate * those times to optimize the gap count. 1708*7c478bd9Sstevel@tonic-gate */ 1709*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1710*7c478bd9Sstevel@tonic-gate void 1711*7c478bd9Sstevel@tonic-gate h1394_phy_packet(void *sl_private, uint32_t *packet_data, uint_t quadlet_count, 1712*7c478bd9Sstevel@tonic-gate uint_t timestamp) 1713*7c478bd9Sstevel@tonic-gate { 1714*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_phy_packet_enter, S1394_TNF_SL_STACK, ""); 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate /* This interface is not yet implemented */ 1717*7c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(h1394_phy_packet, S1394_TNF_SL_STACK, "", 1718*7c478bd9Sstevel@tonic-gate tnf_string, msg, "h1394_phy_packet: Received"); 1719*7c478bd9Sstevel@tonic-gate 1720*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_phy_packet_exit, S1394_TNF_SL_STACK, ""); 1721*7c478bd9Sstevel@tonic-gate } 1722*7c478bd9Sstevel@tonic-gate 1723*7c478bd9Sstevel@tonic-gate /* 1724*7c478bd9Sstevel@tonic-gate * Function: h1394_error_detected() 1725*7c478bd9Sstevel@tonic-gate * Input(s): sl_private The HAL "handle" returned by 1726*7c478bd9Sstevel@tonic-gate * h1394_attach() 1727*7c478bd9Sstevel@tonic-gate * type The type of error the HAL detected 1728*7c478bd9Sstevel@tonic-gate * arg Pointer to any extra information 1729*7c478bd9Sstevel@tonic-gate * 1730*7c478bd9Sstevel@tonic-gate * Output(s): None 1731*7c478bd9Sstevel@tonic-gate * 1732*7c478bd9Sstevel@tonic-gate * Description: h1394_error_detected() is used by the HAL to report errors 1733*7c478bd9Sstevel@tonic-gate * to the 1394 Software Framework. 1734*7c478bd9Sstevel@tonic-gate */ 1735*7c478bd9Sstevel@tonic-gate void 1736*7c478bd9Sstevel@tonic-gate h1394_error_detected(void *sl_private, h1394_error_t type, void *arg) 1737*7c478bd9Sstevel@tonic-gate { 1738*7c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 1739*7c478bd9Sstevel@tonic-gate uint_t hal_node_num; 1740*7c478bd9Sstevel@tonic-gate uint_t IRM_node_num; 1741*7c478bd9Sstevel@tonic-gate 1742*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_error_detected_enter, S1394_TNF_SL_STACK, ""); 1743*7c478bd9Sstevel@tonic-gate 1744*7c478bd9Sstevel@tonic-gate hal = (s1394_hal_t *)sl_private; 1745*7c478bd9Sstevel@tonic-gate 1746*7c478bd9Sstevel@tonic-gate switch (type) { 1747*7c478bd9Sstevel@tonic-gate case H1394_LOCK_RESP_ERR: 1748*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_error_detected, S1394_TNF_SL_ERROR, "", 1749*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Lock response error"); 1750*7c478bd9Sstevel@tonic-gate /* If we are the IRM, then initiate a bus reset */ 1751*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex); 1752*7c478bd9Sstevel@tonic-gate hal_node_num = IEEE1394_NODE_NUM(hal->node_id); 1753*7c478bd9Sstevel@tonic-gate IRM_node_num = hal->IRM_node; 1754*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 1755*7c478bd9Sstevel@tonic-gate if (IRM_node_num == hal_node_num) 1756*7c478bd9Sstevel@tonic-gate s1394_initiate_hal_reset(hal, NON_CRITICAL); 1757*7c478bd9Sstevel@tonic-gate break; 1758*7c478bd9Sstevel@tonic-gate 1759*7c478bd9Sstevel@tonic-gate case H1394_POSTED_WR_ERR: 1760*7c478bd9Sstevel@tonic-gate TNF_PROBE_2(h1394_error_detected, S1394_TNF_SL_ERROR, "", 1761*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Posted write error detected", 1762*7c478bd9Sstevel@tonic-gate tnf_opaque, addr, ((h1394_posted_wr_err_t *)arg)->addr); 1763*7c478bd9Sstevel@tonic-gate break; 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate case H1394_SELF_INITIATED_SHUTDOWN: 1766*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_error_detected, S1394_TNF_SL_ERROR, "", 1767*7c478bd9Sstevel@tonic-gate tnf_string, msg, "HAL self-initiated shutdown"); 1768*7c478bd9Sstevel@tonic-gate s1394_hal_shutdown(hal, B_FALSE); 1769*7c478bd9Sstevel@tonic-gate break; 1770*7c478bd9Sstevel@tonic-gate 1771*7c478bd9Sstevel@tonic-gate case H1394_CYCLE_TOO_LONG: 1772*7c478bd9Sstevel@tonic-gate /* Set a timer to become cycle master after 1 second */ 1773*7c478bd9Sstevel@tonic-gate mutex_enter(&hal->cm_timer_mutex); 1774*7c478bd9Sstevel@tonic-gate hal->cm_timer_set = B_TRUE; 1775*7c478bd9Sstevel@tonic-gate mutex_exit(&hal->cm_timer_mutex); 1776*7c478bd9Sstevel@tonic-gate hal->cm_timer = timeout(s1394_cycle_too_long_callback, hal, 1777*7c478bd9Sstevel@tonic-gate drv_usectohz(CYCLE_MASTER_TIMER * 1000)); 1778*7c478bd9Sstevel@tonic-gate 1779*7c478bd9Sstevel@tonic-gate TNF_PROBE_1(h1394_error_detected, S1394_TNF_SL_ERROR, "", 1780*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Isochronous cycle too long error"); 1781*7c478bd9Sstevel@tonic-gate break; 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate default: 1784*7c478bd9Sstevel@tonic-gate TNF_PROBE_2(h1394_error_detected, S1394_TNF_SL_ERROR, "", 1785*7c478bd9Sstevel@tonic-gate tnf_string, msg, "Unknown error type received", 1786*7c478bd9Sstevel@tonic-gate tnf_uint, type, type); 1787*7c478bd9Sstevel@tonic-gate break; 1788*7c478bd9Sstevel@tonic-gate } 1789*7c478bd9Sstevel@tonic-gate 1790*7c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(h1394_error_detected_exit, S1394_TNF_SL_STACK, ""); 1791*7c478bd9Sstevel@tonic-gate } 1792