17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*fa9e4066Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * s1394_hotplug.c 317c478bd9Sstevel@tonic-gate * 1394 Services Layer Hotplug Routines 327c478bd9Sstevel@tonic-gate * This file contains routines that walk the old and topology 337c478bd9Sstevel@tonic-gate * trees, at bus reset time, creating devinfo's for new nodes and offlining 347c478bd9Sstevel@tonic-gate * nodes that are removed. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include <sys/conf.h> 387c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 397c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 407c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 417c478bd9Sstevel@tonic-gate #include <sys/sunndi.h> 427c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 437c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 447c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 457c478bd9Sstevel@tonic-gate #include <sys/types.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #include <sys/tnf_probe.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include <sys/1394/t1394.h> 507c478bd9Sstevel@tonic-gate #include <sys/1394/s1394.h> 517c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h> 527c478bd9Sstevel@tonic-gate #include <sys/1394/ieee1394.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static void s1394_send_remove_event(s1394_hal_t *hal, dev_info_t *dip, 557c478bd9Sstevel@tonic-gate t1394_localinfo_t *localinfo); 567c478bd9Sstevel@tonic-gate static void s1394_send_insert_event(s1394_hal_t *hal, dev_info_t *dip, 577c478bd9Sstevel@tonic-gate t1394_localinfo_t *localinfo); 587c478bd9Sstevel@tonic-gate static dev_info_t *s1394_create_devinfo(s1394_hal_t *hal, s1394_node_t *node, 597c478bd9Sstevel@tonic-gate uint32_t *unit_dir, int nunit); 607c478bd9Sstevel@tonic-gate static void s1394_update_unit_dir_location(s1394_hal_t *hal, dev_info_t *tdip, 617c478bd9Sstevel@tonic-gate uint_t offset); 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate /* 647c478bd9Sstevel@tonic-gate * s1394_send_remove_event() 657c478bd9Sstevel@tonic-gate * Invokes any "remove event" callback registered for dip. Passes 667c478bd9Sstevel@tonic-gate * t1394_localinfo_t as impl_data for the callback. 677c478bd9Sstevel@tonic-gate */ 687c478bd9Sstevel@tonic-gate static void 697c478bd9Sstevel@tonic-gate s1394_send_remove_event(s1394_hal_t *hal, dev_info_t *dip, 707c478bd9Sstevel@tonic-gate t1394_localinfo_t *localinfo) 717c478bd9Sstevel@tonic-gate { 727c478bd9Sstevel@tonic-gate char name[128]; 737c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate (void) sprintf(name, "%s%d", ddi_driver_name(dip), 767c478bd9Sstevel@tonic-gate ddi_get_instance(dip)); 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_send_remove_event_enter, 797c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_string, device, 807c478bd9Sstevel@tonic-gate name); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate if (ndi_event_retrieve_cookie(hal->hal_ndi_event_hdl, dip, 837c478bd9Sstevel@tonic-gate DDI_DEVI_REMOVE_EVENT, &cookie, NDI_EVENT_NOPASS) 847c478bd9Sstevel@tonic-gate == NDI_SUCCESS) { 857c478bd9Sstevel@tonic-gate (void) ndi_event_run_callbacks(hal->hal_ndi_event_hdl, dip, 867c478bd9Sstevel@tonic-gate cookie, localinfo); 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_send_remove_event_exit, 897c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * s1394_send_insert_event() 947c478bd9Sstevel@tonic-gate * Invokes any "insert event" callback registered for dip. Passes 957c478bd9Sstevel@tonic-gate * t1394_localinfo_t as impl_data for the callback. 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate static void 987c478bd9Sstevel@tonic-gate s1394_send_insert_event(s1394_hal_t *hal, dev_info_t *dip, 997c478bd9Sstevel@tonic-gate t1394_localinfo_t *localinfo) 1007c478bd9Sstevel@tonic-gate { 1017c478bd9Sstevel@tonic-gate char name[128]; 1027c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate (void) sprintf(name, "%s%d", ddi_driver_name(dip), 1057c478bd9Sstevel@tonic-gate ddi_get_instance(dip)); 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_send_insert_event_enter, 1087c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_string, device, 1097c478bd9Sstevel@tonic-gate name); 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate if (ndi_event_retrieve_cookie(hal->hal_ndi_event_hdl, dip, 1127c478bd9Sstevel@tonic-gate DDI_DEVI_INSERT_EVENT, &cookie, NDI_EVENT_NOPASS) == 1137c478bd9Sstevel@tonic-gate NDI_SUCCESS) 1147c478bd9Sstevel@tonic-gate (void) ndi_event_run_callbacks(hal->hal_ndi_event_hdl, dip, 1157c478bd9Sstevel@tonic-gate cookie, localinfo); 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_send_insert_event_exit, 1187c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * s1394_create_devinfo() 1237c478bd9Sstevel@tonic-gate * This routine creates a devinfo corresponding to the unit_dir passed in. 1247c478bd9Sstevel@tonic-gate * It adds "hp-node", "reg", "compatible" properties to the devinfo 1257c478bd9Sstevel@tonic-gate * (formats for "reg" and "compatible" properties are specified by 1275 1267c478bd9Sstevel@tonic-gate * binding for IEEE1394). If unable to create the devinfo and/or add the 1277c478bd9Sstevel@tonic-gate * the properties, returns NULL, otherwise, returns the devinfo created. 1287c478bd9Sstevel@tonic-gate * 1297c478bd9Sstevel@tonic-gate * NOTE: All ndi_* routines are interrupt callable (and thus won't sleep). 1307c478bd9Sstevel@tonic-gate * So, we don't drop topology_mutex across ndi calls. 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate static dev_info_t * 1337c478bd9Sstevel@tonic-gate s1394_create_devinfo(s1394_hal_t *hal, s1394_node_t *node, uint32_t *unit_dir, 1347c478bd9Sstevel@tonic-gate int nunit) 1357c478bd9Sstevel@tonic-gate { 1367c478bd9Sstevel@tonic-gate dev_info_t *hal_dip; 1377c478bd9Sstevel@tonic-gate uint32_t *root_dir; 1387c478bd9Sstevel@tonic-gate dev_info_t *target_dip; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate int root_dir_len; 1417c478bd9Sstevel@tonic-gate int result, i, j, spec_id, sw_version; 1427c478bd9Sstevel@tonic-gate int mod_ven, mod_hw, mod_spec, mod_sw; 1437c478bd9Sstevel@tonic-gate int node_ven, node_hw, node_spec, node_sw; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /*LINTED type is unused*/ 1467c478bd9Sstevel@tonic-gate uint32_t type, key, value; 1477c478bd9Sstevel@tonic-gate uint32_t unit_spec_id, unit_sw_version; 1487c478bd9Sstevel@tonic-gate uint32_t node_spec_id, node_sw_version; 1497c478bd9Sstevel@tonic-gate uint32_t node_vendor_id, node_hw_version; 1507c478bd9Sstevel@tonic-gate uint32_t module_spec_id, module_sw_version; 1517c478bd9Sstevel@tonic-gate uint32_t module_vendor_id, module_hw_version; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate char *fmt = "firewire%06x,%06x"; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate char *buf[5], data[5][24]; 1567c478bd9Sstevel@tonic-gate uint32_t reg[6]; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate TNF_PROBE_2_DEBUG(s1394_create_devinfo_enter, 1617c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_uint, guid_hi, 1627c478bd9Sstevel@tonic-gate node->node_guid_hi, tnf_uint, guid_lo, node->node_guid_lo); 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate hal_dip = hal->halinfo.dip; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* Allocate and init a new device node instance. */ 167*fa9e4066Sahrens result = ndi_devi_alloc(hal_dip, "unit", (pnode_t)DEVI_SID_NODEID, 1687c478bd9Sstevel@tonic-gate &target_dip); 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate if (result != NDI_SUCCESS) { 1717c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Unable to create devinfo" 1727c478bd9Sstevel@tonic-gate " (node's GUID %08x%08x)", node->node_guid_hi, 1737c478bd9Sstevel@tonic-gate node->node_guid_lo); 1747c478bd9Sstevel@tonic-gate TNF_PROBE_2(s1394_create_devinfo_fail_alloc, 1757c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_uint, guid_hi, 1767c478bd9Sstevel@tonic-gate node->node_guid_hi, tnf_uint, guid_lo, node->node_guid_lo); 1777c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_create_devinfo_exit, 1787c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 1797c478bd9Sstevel@tonic-gate return (NULL); 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* Add "hp-node" property */ 1837c478bd9Sstevel@tonic-gate result = ndi_prop_update_int(DDI_DEV_T_NONE, target_dip, "hp-node", 0); 1847c478bd9Sstevel@tonic-gate if (result != NDI_SUCCESS) { 1857c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Unable to add \"hp-node\" property" 1867c478bd9Sstevel@tonic-gate " (node's GUID %08x%08x)", node->node_guid_hi, 1877c478bd9Sstevel@tonic-gate node->node_guid_lo); 1887c478bd9Sstevel@tonic-gate #if defined(DEBUG) 1897c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!Error code %d", result); 1907c478bd9Sstevel@tonic-gate #endif 1917c478bd9Sstevel@tonic-gate TNF_PROBE_3(s1394_create_devinfo_hp_node, 1927c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_uint, guid_hi, 1937c478bd9Sstevel@tonic-gate node->node_guid_hi, tnf_uint, guid_lo, node->node_guid_lo, 1947c478bd9Sstevel@tonic-gate tnf_int, error, result); 1957c478bd9Sstevel@tonic-gate ndi_prop_remove_all(target_dip); 1967c478bd9Sstevel@tonic-gate (void) ndi_devi_free(target_dip); 1977c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_create_devinfo_exit, 1987c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 1997c478bd9Sstevel@tonic-gate return (NULL); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate spec_id = sw_version = mod_ven = mod_hw = mod_spec = mod_sw = 2037c478bd9Sstevel@tonic-gate node_ven = node_hw = node_spec = node_sw = 0; 2047c478bd9Sstevel@tonic-gate unit_sw_version = node_sw_version = node_hw_version = 2057c478bd9Sstevel@tonic-gate module_sw_version = module_hw_version = 0; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate root_dir = CFGROM_ROOT_DIR(node->cfgrom); 2097c478bd9Sstevel@tonic-gate root_dir_len = CFGROM_DIR_LEN(root_dir); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate for (i = 0; i < root_dir_len; i++) { 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[i + 1], type, key, value); 2147c478bd9Sstevel@tonic-gate switch (key) { 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate case IEEE1212_MODULE_VENDOR_ID: 2177c478bd9Sstevel@tonic-gate module_vendor_id = value; 2187c478bd9Sstevel@tonic-gate mod_ven++; 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate case IEEE1212_MODULE_HW_VERSION: 2217c478bd9Sstevel@tonic-gate module_hw_version = value; 2227c478bd9Sstevel@tonic-gate mod_hw++; 2237c478bd9Sstevel@tonic-gate break; 2247c478bd9Sstevel@tonic-gate case IEEE1212_MODULE_SPEC_ID: 2257c478bd9Sstevel@tonic-gate module_spec_id = value; 2267c478bd9Sstevel@tonic-gate mod_spec++; 2277c478bd9Sstevel@tonic-gate break; 2287c478bd9Sstevel@tonic-gate case IEEE1212_MODULE_SW_VERSION: 2297c478bd9Sstevel@tonic-gate module_sw_version = value; 2307c478bd9Sstevel@tonic-gate mod_sw++; 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate case IEEE1212_NODE_VENDOR_ID: 2337c478bd9Sstevel@tonic-gate node_vendor_id = value; 2347c478bd9Sstevel@tonic-gate node_ven++; 2357c478bd9Sstevel@tonic-gate break; 2367c478bd9Sstevel@tonic-gate case IEEE1212_NODE_UNIQUE_ID: { 2377c478bd9Sstevel@tonic-gate uint32_t *node_unique_leaf = 2387c478bd9Sstevel@tonic-gate &root_dir[i + 1] + value; 2397c478bd9Sstevel@tonic-gate node_vendor_id = (node_unique_leaf[1] >> 8); 2407c478bd9Sstevel@tonic-gate node_ven++; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate break; 2437c478bd9Sstevel@tonic-gate case IEEE1212_NODE_HW_VERSION: 2447c478bd9Sstevel@tonic-gate node_hw_version = value; 2457c478bd9Sstevel@tonic-gate node_hw++; 2467c478bd9Sstevel@tonic-gate break; 2477c478bd9Sstevel@tonic-gate case IEEE1212_NODE_SPEC_ID: 2487c478bd9Sstevel@tonic-gate node_spec_id = value; 2497c478bd9Sstevel@tonic-gate node_spec++; 2507c478bd9Sstevel@tonic-gate break; 2517c478bd9Sstevel@tonic-gate case IEEE1212_NODE_SW_VERSION: 2527c478bd9Sstevel@tonic-gate node_sw_version = value; 2537c478bd9Sstevel@tonic-gate node_sw++; 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate if (mod_ven && mod_hw && mod_spec && mod_sw && node_ven && 2587c478bd9Sstevel@tonic-gate node_hw && node_spec && node_sw) { 2597c478bd9Sstevel@tonic-gate break; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * Search for unit spec and version 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate for (i = 0; i < CFGROM_DIR_LEN(unit_dir); i++) { 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(unit_dir[i + 1], type, key, value); 2697c478bd9Sstevel@tonic-gate if (key == IEEE1212_UNIT_SPEC_ID) { 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate unit_spec_id = value; 2727c478bd9Sstevel@tonic-gate spec_id++; 2737c478bd9Sstevel@tonic-gate } else if (key == IEEE1212_UNIT_SW_VERSION) { 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate unit_sw_version = value; 2767c478bd9Sstevel@tonic-gate sw_version++; 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate if (spec_id && sw_version) 2797c478bd9Sstevel@tonic-gate break; 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate /* 2837c478bd9Sstevel@tonic-gate * Refer to IEEE1212 (pages 90-92) for information regarding various 2847c478bd9Sstevel@tonic-gate * id's. Module_Vendor_Id is required. Node_Vendor_Id is optional and 2857c478bd9Sstevel@tonic-gate * if not implemented, its assumed value is Module_Vendor_Id. 2867c478bd9Sstevel@tonic-gate * Module_Spec_Id is optional and if not implemented, its assumed value 2877c478bd9Sstevel@tonic-gate * is Module_Vendor_Id. Node_Spec_Id is optional, and if not 2887c478bd9Sstevel@tonic-gate * implemented, its assumed value is Node_Vendor_Id. Unit_Spec_Id is 2897c478bd9Sstevel@tonic-gate * optional, and if not implemented, its assumed value is 2907c478bd9Sstevel@tonic-gate * Node_Vendor_Id. 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate if (node_ven == 0) { 2937c478bd9Sstevel@tonic-gate node_vendor_id = module_vendor_id; 2947c478bd9Sstevel@tonic-gate node_ven++; 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate if (node_spec == 0) { 2987c478bd9Sstevel@tonic-gate node_spec_id = node_vendor_id; 2997c478bd9Sstevel@tonic-gate node_spec++; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate if (mod_spec == 0) { 3037c478bd9Sstevel@tonic-gate module_spec_id = module_vendor_id; 3047c478bd9Sstevel@tonic-gate mod_spec++; 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate if (spec_id == 0) { 3087c478bd9Sstevel@tonic-gate unit_spec_id = node_vendor_id; 3097c478bd9Sstevel@tonic-gate spec_id++; 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate i = 0; 3137c478bd9Sstevel@tonic-gate if (sw_version != 0) { 3147c478bd9Sstevel@tonic-gate buf[i] = data[i]; 3157c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, unit_spec_id, unit_sw_version); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate if (node_sw != 0) { 3187c478bd9Sstevel@tonic-gate buf[i] = data[i]; 3197c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, node_spec_id, node_sw_version); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate if (node_hw != 0) { 3227c478bd9Sstevel@tonic-gate buf[i] = data[i]; 3237c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, node_vendor_id, node_hw_version); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate if (mod_sw != 0) { 3267c478bd9Sstevel@tonic-gate buf[i] = data[i]; 3277c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, module_spec_id, 3287c478bd9Sstevel@tonic-gate module_sw_version); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate if (mod_hw != 0) { 3317c478bd9Sstevel@tonic-gate buf[i] = data[i]; 3327c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, module_vendor_id, 3337c478bd9Sstevel@tonic-gate module_hw_version); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate result = ndi_prop_update_string_array(DDI_DEV_T_NONE, target_dip, 3377c478bd9Sstevel@tonic-gate "compatible", (char **)&buf, i); 3387c478bd9Sstevel@tonic-gate if (result != NDI_SUCCESS) { 3397c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Unable to add \"compatible\" property" 3407c478bd9Sstevel@tonic-gate " (node's GUID %08x%08x)", node->node_guid_hi, 3417c478bd9Sstevel@tonic-gate node->node_guid_lo); 3427c478bd9Sstevel@tonic-gate #if defined(DEBUG) 3437c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!Error code %d; nelements %d", result, i); 3447c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) { 3457c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!buf[%d]: %s", j, buf[j]); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate #endif 3487c478bd9Sstevel@tonic-gate ndi_prop_remove_all(target_dip); 3497c478bd9Sstevel@tonic-gate (void) ndi_devi_free(target_dip); 3507c478bd9Sstevel@tonic-gate TNF_PROBE_4(s1394_create_devinfo_fail_compat, 3517c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_uint, guid_hi, 3527c478bd9Sstevel@tonic-gate node->node_guid_hi, tnf_uint, guid_lo, node->node_guid_lo, 3537c478bd9Sstevel@tonic-gate tnf_int, error, result, tnf_int, nelements, i); 3547c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_create_devinfo_exit, 3557c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 3567c478bd9Sstevel@tonic-gate return (NULL); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) { 3607c478bd9Sstevel@tonic-gate TNF_PROBE_2_DEBUG(s1394_create_devinfo_props, 3617c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", 3627c478bd9Sstevel@tonic-gate tnf_int, compat_index, j, 3637c478bd9Sstevel@tonic-gate tnf_string, compat_prop, buf[j]); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate /* GUID,ADDR */ 3677c478bd9Sstevel@tonic-gate reg[0] = node->node_guid_hi; 3687c478bd9Sstevel@tonic-gate reg[1] = node->node_guid_lo; 3697c478bd9Sstevel@tonic-gate s1394_cfgrom_parse_unit_dir(unit_dir, ®[2], ®[3], ®[4], 3707c478bd9Sstevel@tonic-gate ®[5]); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate reg[3] = nunit; 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate result = ndi_prop_update_int_array(DDI_DEV_T_NONE, target_dip, "reg", 3757c478bd9Sstevel@tonic-gate (int *)reg, 6); 3767c478bd9Sstevel@tonic-gate if (result != NDI_SUCCESS) { 3777c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Unable to add \"reg\" property"); 3787c478bd9Sstevel@tonic-gate #if defined(DEBUG) 3797c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!Error code %d", result); 3807c478bd9Sstevel@tonic-gate for (j = 0; j < 6; j++) { 3817c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!reg[%d]: 0x%08x", j, reg[j]); 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate #endif 3847c478bd9Sstevel@tonic-gate ndi_prop_remove_all(target_dip); 3857c478bd9Sstevel@tonic-gate (void) ndi_devi_free(target_dip); 3867c478bd9Sstevel@tonic-gate TNF_PROBE_3(s1394_create_devinfo_fail_reg, 3877c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_uint, guid_hi, 3887c478bd9Sstevel@tonic-gate node->node_guid_hi, tnf_uint, guid_lo, node->node_guid_lo, 3897c478bd9Sstevel@tonic-gate tnf_int, error, result); 3907c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_create_devinfo_exit, 3917c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 3927c478bd9Sstevel@tonic-gate return (NULL); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_create_devinfo_exit, 3967c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", 3977c478bd9Sstevel@tonic-gate tnf_opaque, target_dip, target_dip); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate return (target_dip); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * s1394_devi_find() 4047c478bd9Sstevel@tonic-gate * Searches all children of pdip for a match of name@caddr. Builds the 4057c478bd9Sstevel@tonic-gate * name and address of each child node by looking up the reg property on 4067c478bd9Sstevel@tonic-gate * the node and compares the built name@addr with the name@addr passed in. 4077c478bd9Sstevel@tonic-gate * Returns the child dip if a match is found, otherwise, returns NULL. 4087c478bd9Sstevel@tonic-gate * NOTE: 4097c478bd9Sstevel@tonic-gate * This routine is decidedly non-ddi. We had to use this one since 4107c478bd9Sstevel@tonic-gate * ndi_devi_find() can find only nodes that have valid addr field 4117c478bd9Sstevel@tonic-gate * set and that won't happen unless the node goes through INITCHILD 4127c478bd9Sstevel@tonic-gate * (at which time nx1394.c calls ddi_set_name_addr()). If, in future, 4137c478bd9Sstevel@tonic-gate * the ndi_devi_find() provides a way of looking up nodes using criteria 4147c478bd9Sstevel@tonic-gate * other than addr, we can get rid of this routine. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4177c478bd9Sstevel@tonic-gate dev_info_t * 4187c478bd9Sstevel@tonic-gate s1394_devi_find(dev_info_t *pdip, char *name, char *caddr) 4197c478bd9Sstevel@tonic-gate { 4207c478bd9Sstevel@tonic-gate int i, reglen; 4217c478bd9Sstevel@tonic-gate char addr[32]; 4227c478bd9Sstevel@tonic-gate uint32_t *regptr; 4237c478bd9Sstevel@tonic-gate dev_info_t *cdip = NULL; 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate ASSERT((name != NULL) && (caddr != NULL)); 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_devi_find_enter, S1394_TNF_SL_HOTPLUG_STACK, 4287c478bd9Sstevel@tonic-gate "", tnf_string, addr, caddr); 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate /* 4317c478bd9Sstevel@tonic-gate * for each child of this parent, find name and addr and match with 4327c478bd9Sstevel@tonic-gate * name and caddr passed in. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate for (cdip = (dev_info_t *)DEVI(pdip)->devi_child; cdip != NULL; 4357c478bd9Sstevel@tonic-gate cdip = (dev_info_t *)DEVI(cdip)->devi_sibling) { 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate i = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 4387c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "reg", (int **)®ptr, 4397c478bd9Sstevel@tonic-gate (uint_t *)®len); 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate if (i != DDI_PROP_SUCCESS) 4427c478bd9Sstevel@tonic-gate continue; 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * Construct addr from the reg property (addr is of the format 4467c478bd9Sstevel@tonic-gate * GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA], where GGGGGGGGGGGGGGGG is 4477c478bd9Sstevel@tonic-gate * the address and AAAAAAAAAAAA is the optional unit address) 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate if (regptr[2] != NULL || regptr[3] != NULL) { 4507c478bd9Sstevel@tonic-gate (void) sprintf(addr, "%08x%08x,%04x%08x", regptr[0], 4517c478bd9Sstevel@tonic-gate regptr[1], regptr[2], regptr[3]); 4527c478bd9Sstevel@tonic-gate } else { 4537c478bd9Sstevel@tonic-gate (void) sprintf(addr, "%08x%08x", regptr[0], regptr[1]); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate ddi_prop_free(regptr); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (strcmp(caddr, addr) == 0) { 4587c478bd9Sstevel@tonic-gate ASSERT(strcmp(ddi_node_name(cdip), name) == 0); 4597c478bd9Sstevel@tonic-gate break; 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate if (cdip == NULL) { 4647c478bd9Sstevel@tonic-gate TNF_PROBE_1(s1394_devi_find_no_match, 4657c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_string, addr, caddr); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_devi_find_exit, S1394_TNF_SL_HOTPLUG_STACK, ""); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate return (cdip); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate /* 4747c478bd9Sstevel@tonic-gate * s1394_update_devinfo_tree() 4757c478bd9Sstevel@tonic-gate * Parses the config rom for the passed in node and creates/updates devinfo's 4767c478bd9Sstevel@tonic-gate * for each unit directory found. If the devinfo corresponding to a unit 4777c478bd9Sstevel@tonic-gate * already exists, any insert event callbacks registered for that devinfo 4787c478bd9Sstevel@tonic-gate * are called (topology tree is unlocked and relocked around these 4797c478bd9Sstevel@tonic-gate * callbacks). Returns DDI_SUCCESS if everything went fine and DDI_FAILURE 4807c478bd9Sstevel@tonic-gate * if unable to reacquire the lock after callbacks (relock fails because of 4817c478bd9Sstevel@tonic-gate * an intervening bus reset or if the services layer kills the bus reset 4827c478bd9Sstevel@tonic-gate * thread). The node is marked as parsed before returning. 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate int 4857c478bd9Sstevel@tonic-gate s1394_update_devinfo_tree(s1394_hal_t *hal, s1394_node_t *node) 4867c478bd9Sstevel@tonic-gate { 4877c478bd9Sstevel@tonic-gate dev_info_t *tdip; 4887c478bd9Sstevel@tonic-gate int j, units, d, lockfail = 0; 4897c478bd9Sstevel@tonic-gate s1394_target_t *target, *t; 4907c478bd9Sstevel@tonic-gate uint32_t hi, lo, size_hi, size_lo, type, key, value; 4917c478bd9Sstevel@tonic-gate uint32_t *ptr, *root_dir, dir_len; 4927c478bd9Sstevel@tonic-gate t1394_localinfo_t linfo; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate uint32_t *unit_dir_ptrs[32]; 4957c478bd9Sstevel@tonic-gate dev_info_t *devinfo_ptrs[32]; 4967c478bd9Sstevel@tonic-gate uint32_t new_devinfo = 0; /* to keep track of new allocations */ 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate char caddr[32]; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate ASSERT(CFGROM_PARSED(node) == B_FALSE); 5037c478bd9Sstevel@tonic-gate ASSERT(node->cfgrom != NULL); 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate TNF_PROBE_2_DEBUG(s1394_update_devinfo_tree_enter, 5067c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_int, node_num, 5077c478bd9Sstevel@tonic-gate node->node_num, tnf_opaque, cfgrom, node->cfgrom); 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate /* scan through config rom looking for unit dirs */ 5107c478bd9Sstevel@tonic-gate root_dir = CFGROM_ROOT_DIR(node->cfgrom); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (node->cfgrom_valid_size < CFGROM_DIR_LEN(root_dir)) 5137c478bd9Sstevel@tonic-gate dir_len = node->cfgrom_valid_size; 5147c478bd9Sstevel@tonic-gate else 5157c478bd9Sstevel@tonic-gate dir_len = CFGROM_DIR_LEN(root_dir); 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[0], type, key, value); 5187c478bd9Sstevel@tonic-gate if (s1394_valid_dir(hal, node, key, root_dir) == B_FALSE) { 5197c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 5207c478bd9Sstevel@tonic-gate "!Bad root directory in config rom (node's GUID %08x%08x)", 5217c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_update_devinfo_tree_exit, 5247c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_string, msg, 5257c478bd9Sstevel@tonic-gate "bad directory"); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate SET_CFGROM_PARSED(node); 5287c478bd9Sstevel@tonic-gate CLEAR_CFGROM_GEN_CHANGED(node); /* if set */ 5297c478bd9Sstevel@tonic-gate CLEAR_CFGROM_NEW_ALLOC(node); 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate for (units = 0, j = 1; j <= dir_len; j++) { 5357c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[j], type, key, value); 5367c478bd9Sstevel@tonic-gate if (key == IEEE1212_UNIT_DIRECTORY && type == 5377c478bd9Sstevel@tonic-gate IEEE1212_DIRECTORY_TYPE) { 5387c478bd9Sstevel@tonic-gate ptr = &root_dir[j] + value; 5397c478bd9Sstevel@tonic-gate if (s1394_valid_dir(hal, node, key, ptr) == B_TRUE) { 5407c478bd9Sstevel@tonic-gate unit_dir_ptrs[units++] = ptr; 5417c478bd9Sstevel@tonic-gate } else { 5427c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Bad unit directory in config" 5437c478bd9Sstevel@tonic-gate " rom (node's GUID %08x%08x)", 5447c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo); 5457c478bd9Sstevel@tonic-gate TNF_PROBE_2(s1394_update_devinfo_tree_bad_dir, 5467c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_uint, 5477c478bd9Sstevel@tonic-gate guid_hi, node->node_guid_hi, tnf_uint, 5487c478bd9Sstevel@tonic-gate guid_lo, node->node_guid_lo); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate for (d = 0, j = 0; j < units; j++) { 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate s1394_cfgrom_parse_unit_dir(unit_dir_ptrs[j], 5567c478bd9Sstevel@tonic-gate &hi, &lo, &size_hi, &size_lo); 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate lo = j; 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate if (hi || lo) { 5617c478bd9Sstevel@tonic-gate (void) sprintf(caddr, "%08x%08x,%04x%08x", 5627c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo, hi, lo); 5637c478bd9Sstevel@tonic-gate } else { 5647c478bd9Sstevel@tonic-gate (void) sprintf(caddr, "%08x%08x", 5657c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate tdip = s1394_devi_find(hal->halinfo.dip, "unit", caddr); 5697c478bd9Sstevel@tonic-gate if (tdip != NULL) { 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_WRITER); 5727c478bd9Sstevel@tonic-gate target = s1394_target_from_dip_locked(hal, tdip); 5737c478bd9Sstevel@tonic-gate if (target != NULL) { 5747c478bd9Sstevel@tonic-gate target->target_sibling = NULL; 5757c478bd9Sstevel@tonic-gate target->on_node = node; 5767c478bd9Sstevel@tonic-gate target->target_state &= ~S1394_TARG_GONE; 5777c478bd9Sstevel@tonic-gate target->unit_dir = unit_dir_ptrs[j] - root_dir; 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate if ((t = node->target_list) != NULL) { 5807c478bd9Sstevel@tonic-gate ASSERT(t != target); 5817c478bd9Sstevel@tonic-gate while (t->target_sibling != NULL) { 5827c478bd9Sstevel@tonic-gate t = t->target_sibling; 5837c478bd9Sstevel@tonic-gate ASSERT(t != target); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate t->target_sibling = target; 5867c478bd9Sstevel@tonic-gate } else { 5877c478bd9Sstevel@tonic-gate node->target_list = target; 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate target->target_list = node->target_list; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate s1394_update_unit_dir_location(hal, tdip, 5957c478bd9Sstevel@tonic-gate unit_dir_ptrs[j] - root_dir); 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate } else { 5987c478bd9Sstevel@tonic-gate /* create devinfo for unit@caddr */ 5997c478bd9Sstevel@tonic-gate tdip = s1394_create_devinfo(hal, node, 6007c478bd9Sstevel@tonic-gate unit_dir_ptrs[j], j); 6017c478bd9Sstevel@tonic-gate if (tdip != NULL) { 6027c478bd9Sstevel@tonic-gate new_devinfo |= (1 << d); 6037c478bd9Sstevel@tonic-gate s1394_update_unit_dir_location(hal, tdip, 6047c478bd9Sstevel@tonic-gate unit_dir_ptrs[j] - root_dir); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate if (tdip != NULL) 6087c478bd9Sstevel@tonic-gate devinfo_ptrs[d++] = tdip; 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 6127c478bd9Sstevel@tonic-gate /* Online all valid units */ 6137c478bd9Sstevel@tonic-gate for (j = 0; j < d; j++) { 6147c478bd9Sstevel@tonic-gate if ((new_devinfo & (1 << j)) == 0) { 6157c478bd9Sstevel@tonic-gate linfo.bus_generation = hal->generation_count; 6167c478bd9Sstevel@tonic-gate linfo.local_nodeID = hal->node_id; 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate /* don't need to drop topology_tree_mutex across ndi calls */ 6197c478bd9Sstevel@tonic-gate (void) ndi_devi_online_async(devinfo_ptrs[j], 0); 6207c478bd9Sstevel@tonic-gate if ((new_devinfo & (1 << j)) == 0) { 6217c478bd9Sstevel@tonic-gate /* 6227c478bd9Sstevel@tonic-gate * send an insert event if this an existing devinfo. 6237c478bd9Sstevel@tonic-gate * drop and reacquire topology_tree_mutex across 6247c478bd9Sstevel@tonic-gate * the event calls 6257c478bd9Sstevel@tonic-gate */ 6267c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 6277c478bd9Sstevel@tonic-gate s1394_send_insert_event(hal, devinfo_ptrs[j], &linfo); 6287c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) { 6297c478bd9Sstevel@tonic-gate TNF_PROBE_4(s1394_update_devinfo_tree_lock_fail, 6307c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", 6317c478bd9Sstevel@tonic-gate tnf_int, node_num, node->node_num, 6327c478bd9Sstevel@tonic-gate tnf_opaque, cfgrom, node->cfgrom, 6337c478bd9Sstevel@tonic-gate tnf_int, unit, j, 6347c478bd9Sstevel@tonic-gate tnf_opaque, devinfo, devinfo_ptrs[j]); 6357c478bd9Sstevel@tonic-gate lockfail = 1; 6367c478bd9Sstevel@tonic-gate break; 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate if (lockfail) { 6427c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_update_devinfo_tree_exit, 6437c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, ""); 6447c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate SET_CFGROM_PARSED(node); 6487c478bd9Sstevel@tonic-gate CLEAR_CFGROM_GEN_CHANGED(node); /* if set */ 6497c478bd9Sstevel@tonic-gate CLEAR_CFGROM_NEW_ALLOC(node); 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_update_devinfo_tree_exit, 6527c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * s1394_offline_node() 6597c478bd9Sstevel@tonic-gate * Offlines a node. This involves marking all targets attached to the 6607c478bd9Sstevel@tonic-gate * node as gone, invoking any remove event callbacks and calling 6617c478bd9Sstevel@tonic-gate * ndi_devi_offline to mark the devinfo as OFFLINE (for each unit 6627c478bd9Sstevel@tonic-gate * directory on the node). The tree is unlocked and relocked around 6637c478bd9Sstevel@tonic-gate * the callbacks. If unable to relock the tree, DDI_FAILURE, else 6647c478bd9Sstevel@tonic-gate * returns DDI_SUCCESS. 6657c478bd9Sstevel@tonic-gate */ 6667c478bd9Sstevel@tonic-gate int 6677c478bd9Sstevel@tonic-gate s1394_offline_node(s1394_hal_t *hal, s1394_node_t *node) 6687c478bd9Sstevel@tonic-gate { 6697c478bd9Sstevel@tonic-gate s1394_target_t *t; 6707c478bd9Sstevel@tonic-gate dev_info_t *tdip; 6717c478bd9Sstevel@tonic-gate int j, d, units; 6727c478bd9Sstevel@tonic-gate uint32_t *unit_dir_ptrs[32]; 6737c478bd9Sstevel@tonic-gate dev_info_t *devinfo_ptrs[32]; 6747c478bd9Sstevel@tonic-gate t1394_localinfo_t linfo; 6757c478bd9Sstevel@tonic-gate uint_t node_num; 6767c478bd9Sstevel@tonic-gate uint32_t *ptr, *root_dir, dir_len; 6777c478bd9Sstevel@tonic-gate uint32_t hi, lo, size_hi, size_lo, type, key, value; 6787c478bd9Sstevel@tonic-gate char caddr[32]; 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate node_num = node->node_num; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_offline_node_enter, S1394_TNF_SL_HOTPLUG_STACK, 6837c478bd9Sstevel@tonic-gate "", tnf_uint, node_num, node_num); 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate d = 0; 6887c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_WRITER); 6897c478bd9Sstevel@tonic-gate t = node->target_list; 6907c478bd9Sstevel@tonic-gate while (t != NULL) { 6917c478bd9Sstevel@tonic-gate TNF_PROBE_2(s1394_process_old_tree_mark, 6927c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_int, node_num, node_num, 6937c478bd9Sstevel@tonic-gate tnf_opaque, target, t); 6947c478bd9Sstevel@tonic-gate t->target_state |= S1394_TARG_GONE; 6957c478bd9Sstevel@tonic-gate t->on_node = NULL; 6967c478bd9Sstevel@tonic-gate t = t->target_sibling; 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate /* scan through config rom looking for unit dirs */ 7017c478bd9Sstevel@tonic-gate root_dir = CFGROM_ROOT_DIR(node->cfgrom); 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate if (node->cfgrom_valid_size < CFGROM_DIR_LEN(root_dir)) 7047c478bd9Sstevel@tonic-gate dir_len = node->cfgrom_valid_size; 7057c478bd9Sstevel@tonic-gate else 7067c478bd9Sstevel@tonic-gate dir_len = CFGROM_DIR_LEN(root_dir); 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[0], type, key, value); 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate for (units = 0, j = 1; j <= dir_len; j++) { 7117c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[j], type, key, value); 7127c478bd9Sstevel@tonic-gate if (key == IEEE1212_UNIT_DIRECTORY && type == 7137c478bd9Sstevel@tonic-gate IEEE1212_DIRECTORY_TYPE) { 7147c478bd9Sstevel@tonic-gate ptr = &root_dir[j] + value; 7157c478bd9Sstevel@tonic-gate if (s1394_valid_dir(hal, node, key, ptr) == B_TRUE) { 7167c478bd9Sstevel@tonic-gate unit_dir_ptrs[units++] = ptr; 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate for (d = 0, j = 0; j < units; j++) { 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate s1394_cfgrom_parse_unit_dir(unit_dir_ptrs[j], 7247c478bd9Sstevel@tonic-gate &hi, &lo, &size_hi, &size_lo); 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate lo = j; 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate if (hi || lo) { 7297c478bd9Sstevel@tonic-gate (void) sprintf(caddr, "%08x%08x,%04x%08x", 7307c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo, hi, lo); 7317c478bd9Sstevel@tonic-gate } else { 7327c478bd9Sstevel@tonic-gate (void) sprintf(caddr, "%08x%08x", 7337c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate if ((tdip = s1394_devi_find(hal->halinfo.dip, "unit", caddr)) != 7377c478bd9Sstevel@tonic-gate NULL) 7387c478bd9Sstevel@tonic-gate devinfo_ptrs[d++] = tdip; 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate node->old_node = NULL; 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate linfo.bus_generation = hal->generation_count; 7447c478bd9Sstevel@tonic-gate linfo.local_nodeID = hal->node_id; 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate for (j = 0; j < d; j++) { 7477c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate TNF_PROBE_2(s1394_offline_node, 7507c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_int, node_num, node_num, 7517c478bd9Sstevel@tonic-gate tnf_opaque, devinfo, devinfo_ptrs[j]); 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate s1394_send_remove_event(hal, devinfo_ptrs[j], &linfo); 7547c478bd9Sstevel@tonic-gate (void) ndi_devi_offline(devinfo_ptrs[j], NDI_DEVI_REMOVE); 7557c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) { 7567c478bd9Sstevel@tonic-gate TNF_PROBE_2(s1394_offline_node, 7577c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_string, msg, 7587c478bd9Sstevel@tonic-gate "unlock to relock tree", tnf_uint, node_num, 7597c478bd9Sstevel@tonic-gate node_num); 7607c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_offline_node_exit, 7617c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 7627c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 7677c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_offline_node_exit, S1394_TNF_SL_HOTPLUG_STACK, 7687c478bd9Sstevel@tonic-gate ""); 7697c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* 7737c478bd9Sstevel@tonic-gate * s1394_process_topology_tree() 7747c478bd9Sstevel@tonic-gate * Walks the topology tree, processing each node. If node that has 7757c478bd9Sstevel@tonic-gate * already been parsed, updates the generation property on all devinfos 7767c478bd9Sstevel@tonic-gate * for the node. Also, if the node exists in both old & new trees, ASSERTS 7777c478bd9Sstevel@tonic-gate * that both point to the same config rom. If the node has valid config 7787c478bd9Sstevel@tonic-gate * rom but hasn't been parsed yet, calls s1394_update_devinfo_tree() 7797c478bd9Sstevel@tonic-gate * to parse and create devinfos for the node. Kicks off further config 7807c478bd9Sstevel@tonic-gate * rom reading if only the bus info block for the node is read. 7817c478bd9Sstevel@tonic-gate * Returns DDI_SUCCESS if everything went fine, else returns DDI_FAILURE 7827c478bd9Sstevel@tonic-gate * (for eg. unable to reacquire the tree lock etc). wait_for_cbs argument 7837c478bd9Sstevel@tonic-gate * tells the caller if some completions can be expected. wait_gen tells 7847c478bd9Sstevel@tonic-gate * the generation the commands were issued at. 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate int 7877c478bd9Sstevel@tonic-gate s1394_process_topology_tree(s1394_hal_t *hal, int *wait_for_cbs, 7887c478bd9Sstevel@tonic-gate uint_t *wait_gen) 7897c478bd9Sstevel@tonic-gate { 7907c478bd9Sstevel@tonic-gate int i; 7917c478bd9Sstevel@tonic-gate uint_t hal_node_num, number_of_nodes; 7927c478bd9Sstevel@tonic-gate s1394_node_t *node, *onode; 7937c478bd9Sstevel@tonic-gate s1394_status_t status; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_process_topology_tree_enter, 7987c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) { 8017c478bd9Sstevel@tonic-gate TNF_PROBE_0(s1394_process_topology_tree_lock_failed, 8027c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, ""); 8037c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_process_topology_tree_exit, 8047c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 8057c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate hal_node_num = IEEE1394_NODE_NUM(hal->node_id); 8097c478bd9Sstevel@tonic-gate hal->cfgroms_being_read = 0; 8107c478bd9Sstevel@tonic-gate number_of_nodes = hal->number_of_nodes; 8117c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 8127c478bd9Sstevel@tonic-gate 8137c478bd9Sstevel@tonic-gate for (i = 0; i < number_of_nodes; i++) { 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate if (i == hal_node_num) 8167c478bd9Sstevel@tonic-gate continue; 8177c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) { 8187c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate node = &hal->topology_tree[i]; 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate TNF_PROBE_4_DEBUG(s1394_process_topology_tree, 8237c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", 8247c478bd9Sstevel@tonic-gate tnf_int, node_num, i, 8257c478bd9Sstevel@tonic-gate tnf_int, parsed, CFGROM_PARSED(node), 8267c478bd9Sstevel@tonic-gate tnf_int, matched, NODE_MATCHED(node), 8277c478bd9Sstevel@tonic-gate tnf_int, visited, NODE_VISITED(node)); 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate if (LINK_ACTIVE(node) == B_FALSE) { 8307c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 8317c478bd9Sstevel@tonic-gate continue; 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate if (node->cfgrom == NULL) { 8347c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 8357c478bd9Sstevel@tonic-gate continue; 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate onode = node->old_node; 8397c478bd9Sstevel@tonic-gate 8407c478bd9Sstevel@tonic-gate if (onode != NULL && onode->cfgrom != NULL && node->cfgrom != 8417c478bd9Sstevel@tonic-gate NULL) { 8427c478bd9Sstevel@tonic-gate /* 8437c478bd9Sstevel@tonic-gate * onode->cfgrom != node->cfgrom should have been 8447c478bd9Sstevel@tonic-gate * handled by s1394_match_GUID()!!! 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate if (onode->cfgrom != node->cfgrom) 8477c478bd9Sstevel@tonic-gate TNF_PROBE_5(s1394_process_topology_tree_err, 8487c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", 8497c478bd9Sstevel@tonic-gate tnf_int, node_num, i, tnf_int, gen_changed, 8507c478bd9Sstevel@tonic-gate CFGROM_GEN_CHANGED(node), tnf_int, parsed, 8517c478bd9Sstevel@tonic-gate CFGROM_PARSED(node), tnf_opaque, old_cfgrom, 8527c478bd9Sstevel@tonic-gate onode->cfgrom, tnf_opaque, new_cfgrom, 8537c478bd9Sstevel@tonic-gate node->cfgrom); 8547c478bd9Sstevel@tonic-gate ASSERT(onode->cfgrom == node->cfgrom); 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate if (CFGROM_PARSED(node) == B_FALSE && CFGROM_ALL_READ(node) == 8587c478bd9Sstevel@tonic-gate B_TRUE) { 8597c478bd9Sstevel@tonic-gate ASSERT((node->cfgrom_size < 8607c478bd9Sstevel@tonic-gate IEEE1394_CONFIG_ROM_QUAD_SZ) || 8617c478bd9Sstevel@tonic-gate NODE_MATCHED(node) == B_TRUE); 8627c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_READER); 8637c478bd9Sstevel@tonic-gate ASSERT(node->target_list == NULL); 8647c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock); 8657c478bd9Sstevel@tonic-gate if (s1394_update_devinfo_tree(hal, node) == 8667c478bd9Sstevel@tonic-gate DDI_FAILURE) { 8677c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD( 8687c478bd9Sstevel@tonic-gate &hal->topology_tree_mutex)); 8697c478bd9Sstevel@tonic-gate TNF_PROBE_1(s1394_process_topology_tree, 8707c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_string, 8717c478bd9Sstevel@tonic-gate msg, "failure from update devinfo"); 8727c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG( 8737c478bd9Sstevel@tonic-gate s1394_process_topology_tree_exit, 8747c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 8757c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate } else if (CFGROM_PARSED(node) == B_FALSE && CFGROM_BIB_READ( 8787c478bd9Sstevel@tonic-gate node) == B_TRUE) { 8797c478bd9Sstevel@tonic-gate if (s1394_read_rest_of_cfgrom(hal, node, &status) != 8807c478bd9Sstevel@tonic-gate DDI_SUCCESS) { 8817c478bd9Sstevel@tonic-gate TNF_PROBE_1(s1394_process_topology_tree, 8827c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_string, 8837c478bd9Sstevel@tonic-gate msg, "failure reading rest of cfgrom"); 8847c478bd9Sstevel@tonic-gate if ((status & S1394_LOCK_FAILED) == 0) { 8857c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal-> 8867c478bd9Sstevel@tonic-gate topology_tree_mutex)); 8877c478bd9Sstevel@tonic-gate *wait_for_cbs = 0; 8887c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG( 8917c478bd9Sstevel@tonic-gate s1394_process_topology_tree_exit, 8927c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 8937c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 8947c478bd9Sstevel@tonic-gate } else { 8957c478bd9Sstevel@tonic-gate *wait_for_cbs = 1; 8967c478bd9Sstevel@tonic-gate *wait_gen = hal->br_cfgrom_read_gen; 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate /* 9047c478bd9Sstevel@tonic-gate * flag the tree as processed; if a single bus reset happens after 9057c478bd9Sstevel@tonic-gate * this, we will use tree matching. 9067c478bd9Sstevel@tonic-gate */ 9077c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) { 9087c478bd9Sstevel@tonic-gate TNF_PROBE_1(s1394_process_topology_tree, 9097c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_string, 9107c478bd9Sstevel@tonic-gate msg, "relock failed while marking tree processed"); 9117c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_process_topology_tree_exit, 9127c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 9137c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 9147c478bd9Sstevel@tonic-gate } 9157c478bd9Sstevel@tonic-gate hal->topology_tree_processed = B_TRUE; 9167c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_process_topology_tree_exit, 9197c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_int, hal_instance, 9207c478bd9Sstevel@tonic-gate ddi_get_instance(hal->halinfo.dip)); 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate /* 9267c478bd9Sstevel@tonic-gate * s1394_process_old_tree() 9277c478bd9Sstevel@tonic-gate * Walks through the old tree and offlines nodes that are removed. Nodes 9287c478bd9Sstevel@tonic-gate * with an active link in the old tree but link powered off in the current 9297c478bd9Sstevel@tonic-gate * generation are also offlined, as well as nodes with invalid config 9307c478bd9Sstevel@tonic-gate * rom in current generation. 9317c478bd9Sstevel@tonic-gate * The topology tree is locked/unlocked while walking through all the nodes; 9327c478bd9Sstevel@tonic-gate * if the locking fails at any stage, stops further walking and returns 9337c478bd9Sstevel@tonic-gate * DDI_FAILURE. Returns DDI_SUCCESS if everything went fine. 9347c478bd9Sstevel@tonic-gate */ 9357c478bd9Sstevel@tonic-gate int 9367c478bd9Sstevel@tonic-gate s1394_process_old_tree(s1394_hal_t *hal) 9377c478bd9Sstevel@tonic-gate { 9387c478bd9Sstevel@tonic-gate int i; 9397c478bd9Sstevel@tonic-gate uint_t hal_node_num_old, old_number_of_nodes; 9407c478bd9Sstevel@tonic-gate s1394_node_t *onode; 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_process_old_tree_enter, 9437c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate /* 9467c478bd9Sstevel@tonic-gate * NODE_MATCHED(onode) == 0 indicates this node doesn't exist 9477c478bd9Sstevel@tonic-gate * any more. 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) { 9527c478bd9Sstevel@tonic-gate TNF_PROBE_0(s1394_process_old_tree_lock_failed, 9537c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, ""); 9547c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_process_old_tree_exit, 9557c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 9567c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate hal_node_num_old = IEEE1394_NODE_NUM(hal->old_node_id); 9597c478bd9Sstevel@tonic-gate old_number_of_nodes = hal->old_number_of_nodes; 9607c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate for (i = 0; i < old_number_of_nodes; i++) { 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate if (i == hal_node_num_old) 9657c478bd9Sstevel@tonic-gate continue; 9667c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) { 9677c478bd9Sstevel@tonic-gate TNF_PROBE_2(s1394_process_old_tree, 9687c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_string, msg, 9697c478bd9Sstevel@tonic-gate "lock failed while processing node", tnf_uint, 9707c478bd9Sstevel@tonic-gate node_num, i); 9717c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_process_old_tree_exit, 9727c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 9737c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate onode = &hal->old_tree[i]; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate if (onode->cfgrom == NULL) { 9797c478bd9Sstevel@tonic-gate CLEAR_CFGROM_STATE(onode); 9807c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 9817c478bd9Sstevel@tonic-gate continue; 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_process_old_tree, 9857c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_opaque, 9867c478bd9Sstevel@tonic-gate cfgrom, onode->cfgrom); 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate TNF_PROBE_5_DEBUG(s1394_process_old_tree, 9897c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_int, 9907c478bd9Sstevel@tonic-gate node_num, i, tnf_int, parsed, CFGROM_PARSED(onode), tnf_int, 9917c478bd9Sstevel@tonic-gate matched, NODE_MATCHED(onode), tnf_int, visited, 9927c478bd9Sstevel@tonic-gate NODE_VISITED(onode), tnf_int, generation_changed, 9937c478bd9Sstevel@tonic-gate CFGROM_GEN_CHANGED(onode)); 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate /* 9967c478bd9Sstevel@tonic-gate * onode->cur_node == NULL iff we couldn't read cfgrom in the 9977c478bd9Sstevel@tonic-gate * current generation in non-tree matching case (and thus 9987c478bd9Sstevel@tonic-gate * match_GUIDs couldn't set cur_node). 9997c478bd9Sstevel@tonic-gate */ 10007c478bd9Sstevel@tonic-gate if (NODE_MATCHED(onode) == B_FALSE || (onode->cur_node == 10017c478bd9Sstevel@tonic-gate NULL || ((CFGROM_VALID(onode) == B_TRUE && 10027c478bd9Sstevel@tonic-gate CFGROM_VALID(onode->cur_node) == B_FALSE) || 10037c478bd9Sstevel@tonic-gate (LINK_ACTIVE(onode) == B_TRUE && LINK_ACTIVE(onode-> 10047c478bd9Sstevel@tonic-gate cur_node) == B_FALSE)))) { 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate if (onode->cur_node != NULL && CFGROM_VALID(onode) == 10077c478bd9Sstevel@tonic-gate B_TRUE && CFGROM_VALID(onode->cur_node) == B_FALSE) 10087c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG 10097c478bd9Sstevel@tonic-gate (s1394_process_old_tree_invalid_cfgrom, 10107c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", 10117c478bd9Sstevel@tonic-gate tnf_int, node_num, i); 10127c478bd9Sstevel@tonic-gate if (onode->cur_node != NULL && LINK_ACTIVE(onode) == 10137c478bd9Sstevel@tonic-gate B_TRUE && LINK_ACTIVE(onode->cur_node) == B_FALSE) 10147c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG 10157c478bd9Sstevel@tonic-gate (s1394_process_old_tree_link_off, 10167c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, 10177c478bd9Sstevel@tonic-gate "", tnf_int, node_num, i); 10187c478bd9Sstevel@tonic-gate if (s1394_offline_node(hal, onode) != DDI_SUCCESS) { 10197c478bd9Sstevel@tonic-gate TNF_PROBE_2(s1394_process_old_tree, 10207c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_ERROR, "", tnf_string, 10217c478bd9Sstevel@tonic-gate msg, "failure from offline node", tnf_uint, 10227c478bd9Sstevel@tonic-gate node_num, i); 10237c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_process_old_tree_exit, 10247c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 10257c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate s1394_free_cfgrom(hal, onode, S1394_FREE_CFGROM_OLD); 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal); 10317c478bd9Sstevel@tonic-gate } 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex)); 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_process_old_tree_exit, 10367c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate /* 10427c478bd9Sstevel@tonic-gate * s1394_update_unit_dir_location() 10437c478bd9Sstevel@tonic-gate * Updates the unit-dir-offset property on the devinfo. 10447c478bd9Sstevel@tonic-gate * NOTE: ndi_prop_update_int() is interrupt callable (and thus won't block); 10457c478bd9Sstevel@tonic-gate * so, the caller doesn't drop topology_tree_mutex when calling this routine. 10467c478bd9Sstevel@tonic-gate */ 10477c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 10487c478bd9Sstevel@tonic-gate static void 10497c478bd9Sstevel@tonic-gate s1394_update_unit_dir_location(s1394_hal_t *hal, dev_info_t *tdip, 10507c478bd9Sstevel@tonic-gate uint_t offset) 10517c478bd9Sstevel@tonic-gate { 10527c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 10537c478bd9Sstevel@tonic-gate ASSERT(tdip != NULL); 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_update_unit_dir_location_enter, 10567c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_uint, offset, offset); 10577c478bd9Sstevel@tonic-gate (void) ndi_prop_update_int(DDI_DEV_T_NONE, tdip, "unit-dir-offset", 10587c478bd9Sstevel@tonic-gate offset); 10597c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_update_unit_dir_location_exit, 10607c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate /* 10647c478bd9Sstevel@tonic-gate * s1394_add_target_to_node() 10657c478bd9Sstevel@tonic-gate * adds target to the list of targets hanging off the node. Figures out 10667c478bd9Sstevel@tonic-gate * the node by searching the topology tree for the GUID corresponding 10677c478bd9Sstevel@tonic-gate * to the target. Points on_node field of target structure at the node. 10687c478bd9Sstevel@tonic-gate */ 10697c478bd9Sstevel@tonic-gate void 10707c478bd9Sstevel@tonic-gate s1394_add_target_to_node(s1394_target_t *target) 10717c478bd9Sstevel@tonic-gate { 10727c478bd9Sstevel@tonic-gate s1394_target_t *t; 10737c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 10747c478bd9Sstevel@tonic-gate uint32_t guid_hi; 10757c478bd9Sstevel@tonic-gate uint32_t guid_lo; 10767c478bd9Sstevel@tonic-gate int i; 10777c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 10787c478bd9Sstevel@tonic-gate char *ptr; 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_add_target_to_node_enter, 10817c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate hal = target->on_hal; 10847c478bd9Sstevel@tonic-gate ASSERT(hal != NULL); 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate /* Topology tree must be locked when it gets here! */ 10877c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate /* target_list_rwlock should be held in write mode */ 10907c478bd9Sstevel@tonic-gate ASSERT(rw_read_locked(&target->on_hal->target_list_rwlock) == 0); 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate if ((ptr = ddi_get_name_addr(target->target_dip)) == NULL) { 10937c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_add_target_to_node_exit_no_name, 10947c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 10957c478bd9Sstevel@tonic-gate return; 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate (void) sprintf(name, ptr); 10997c478bd9Sstevel@tonic-gate /* Drop the ,<ADDR> part, if present */ 11007c478bd9Sstevel@tonic-gate if ((ptr = strchr(name, ',')) != NULL) 11017c478bd9Sstevel@tonic-gate *ptr = '\0'; 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate ptr = name; 11047c478bd9Sstevel@tonic-gate guid_hi = s1394_stoi(ptr, 8, 16); 11057c478bd9Sstevel@tonic-gate guid_lo = s1394_stoi(ptr + 8, 8, 16); 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate /* Search the HAL's node list for this GUID */ 11087c478bd9Sstevel@tonic-gate for (i = 0; i < hal->number_of_nodes; i++) { 11097c478bd9Sstevel@tonic-gate if (CFGROM_VALID(&hal->topology_tree[i]) == B_TRUE) { 11107c478bd9Sstevel@tonic-gate ASSERT(hal->topology_tree[i].cfgrom != NULL); 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate if ((hal->topology_tree[i].node_guid_hi == guid_hi) && 11137c478bd9Sstevel@tonic-gate (hal->topology_tree[i].node_guid_lo == guid_lo)) { 11147c478bd9Sstevel@tonic-gate target->on_node = &hal->topology_tree[i]; 11157c478bd9Sstevel@tonic-gate if ((t = hal->topology_tree[i].target_list) != 11167c478bd9Sstevel@tonic-gate NULL) { 11177c478bd9Sstevel@tonic-gate ASSERT(t != target); 11187c478bd9Sstevel@tonic-gate while (t->target_sibling != NULL) { 11197c478bd9Sstevel@tonic-gate t = t->target_sibling; 11207c478bd9Sstevel@tonic-gate ASSERT(t != target); 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate t->target_sibling = target; 11237c478bd9Sstevel@tonic-gate } else { 11247c478bd9Sstevel@tonic-gate hal->topology_tree[i].target_list = 11257c478bd9Sstevel@tonic-gate target; 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate /* 11297c478bd9Sstevel@tonic-gate * update target_list in all targets on the 11307c478bd9Sstevel@tonic-gate * node 11317c478bd9Sstevel@tonic-gate */ 11327c478bd9Sstevel@tonic-gate t = hal->topology_tree[i].target_list; 11337c478bd9Sstevel@tonic-gate while (t != NULL) { 11347c478bd9Sstevel@tonic-gate t->target_list = 11357c478bd9Sstevel@tonic-gate hal->topology_tree[i].target_list; 11367c478bd9Sstevel@tonic-gate t = t->target_sibling; 11377c478bd9Sstevel@tonic-gate } 11387c478bd9Sstevel@tonic-gate break; 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate } 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_add_target_to_node_exit, 11447c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate /* 11487c478bd9Sstevel@tonic-gate * s1394_remove_target_from_node() 11497c478bd9Sstevel@tonic-gate * Removes target from the corresponding node's target_list. 11507c478bd9Sstevel@tonic-gate */ 11517c478bd9Sstevel@tonic-gate void 11527c478bd9Sstevel@tonic-gate s1394_remove_target_from_node(s1394_target_t *target) 11537c478bd9Sstevel@tonic-gate { 11547c478bd9Sstevel@tonic-gate s1394_target_t *t, *t1; 11557c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_remove_target_from_node_enter, 11587c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate hal = target->on_hal; 11617c478bd9Sstevel@tonic-gate ASSERT(hal != NULL); 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate /* Topology tree must be locked when it gets here! */ 11647c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex)); 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate /* target_list_rwlock should be held in write mode */ 11677c478bd9Sstevel@tonic-gate ASSERT(rw_read_locked(&target->on_hal->target_list_rwlock) == 0); 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate if (target->on_node == NULL) { 11707c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(s1394_remove_target_from_node_NULL, 11717c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", 11727c478bd9Sstevel@tonic-gate tnf_uint, target_state, target->target_state); 11737c478bd9Sstevel@tonic-gate } 11747c478bd9Sstevel@tonic-gate 11757c478bd9Sstevel@tonic-gate t = target->target_list; 11767c478bd9Sstevel@tonic-gate t1 = NULL; 11777c478bd9Sstevel@tonic-gate while (t != NULL) { 11787c478bd9Sstevel@tonic-gate if (t == target) { 11797c478bd9Sstevel@tonic-gate if (t1 == NULL) { 11807c478bd9Sstevel@tonic-gate target->target_list = t->target_sibling; 11817c478bd9Sstevel@tonic-gate } else { 11827c478bd9Sstevel@tonic-gate t1->target_sibling = t->target_sibling; 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate break; 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate t1 = t; 11877c478bd9Sstevel@tonic-gate t = t->target_sibling; 11887c478bd9Sstevel@tonic-gate } 11897c478bd9Sstevel@tonic-gate /* Update the target_list pointer in all the targets */ 11907c478bd9Sstevel@tonic-gate if (target->on_node != NULL) 11917c478bd9Sstevel@tonic-gate target->on_node->target_list = target->target_list; 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate t = t1 = target->target_list; 11947c478bd9Sstevel@tonic-gate while (t != NULL) { 11957c478bd9Sstevel@tonic-gate t->target_list = t1; 11967c478bd9Sstevel@tonic-gate t = t->target_sibling; 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate target->on_node = NULL; 12007c478bd9Sstevel@tonic-gate target->target_sibling = NULL; 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(s1394_remove_target_from_node_exit, 12037c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, ""); 12047c478bd9Sstevel@tonic-gate } 1205