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 /*
23fa9e4066Sahrens * 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 /*
287c478bd9Sstevel@tonic-gate * s1394_hotplug.c
297c478bd9Sstevel@tonic-gate * 1394 Services Layer Hotplug Routines
307c478bd9Sstevel@tonic-gate * This file contains routines that walk the old and topology
317c478bd9Sstevel@tonic-gate * trees, at bus reset time, creating devinfo's for new nodes and offlining
327c478bd9Sstevel@tonic-gate * nodes that are removed.
337c478bd9Sstevel@tonic-gate */
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate #include <sys/conf.h>
367c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
377c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
387c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
397c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
407c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
417c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
427c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
447c478bd9Sstevel@tonic-gate #include <sys/1394/t1394.h>
457c478bd9Sstevel@tonic-gate #include <sys/1394/s1394.h>
467c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
477c478bd9Sstevel@tonic-gate #include <sys/1394/ieee1394.h>
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate static void s1394_send_remove_event(s1394_hal_t *hal, dev_info_t *dip,
507c478bd9Sstevel@tonic-gate t1394_localinfo_t *localinfo);
517c478bd9Sstevel@tonic-gate static void s1394_send_insert_event(s1394_hal_t *hal, dev_info_t *dip,
527c478bd9Sstevel@tonic-gate t1394_localinfo_t *localinfo);
537c478bd9Sstevel@tonic-gate static dev_info_t *s1394_create_devinfo(s1394_hal_t *hal, s1394_node_t *node,
547c478bd9Sstevel@tonic-gate uint32_t *unit_dir, int nunit);
557c478bd9Sstevel@tonic-gate static void s1394_update_unit_dir_location(s1394_hal_t *hal, dev_info_t *tdip,
567c478bd9Sstevel@tonic-gate uint_t offset);
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate * s1394_send_remove_event()
607c478bd9Sstevel@tonic-gate * Invokes any "remove event" callback registered for dip. Passes
617c478bd9Sstevel@tonic-gate * t1394_localinfo_t as impl_data for the callback.
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate static void
s1394_send_remove_event(s1394_hal_t * hal,dev_info_t * dip,t1394_localinfo_t * localinfo)647c478bd9Sstevel@tonic-gate s1394_send_remove_event(s1394_hal_t *hal, dev_info_t *dip,
657c478bd9Sstevel@tonic-gate t1394_localinfo_t *localinfo)
667c478bd9Sstevel@tonic-gate {
677c478bd9Sstevel@tonic-gate char name[128];
687c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie;
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate (void) sprintf(name, "%s%d", ddi_driver_name(dip),
717c478bd9Sstevel@tonic-gate ddi_get_instance(dip));
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate if (ndi_event_retrieve_cookie(hal->hal_ndi_event_hdl, dip,
747c478bd9Sstevel@tonic-gate DDI_DEVI_REMOVE_EVENT, &cookie, NDI_EVENT_NOPASS)
757c478bd9Sstevel@tonic-gate == NDI_SUCCESS) {
767c478bd9Sstevel@tonic-gate (void) ndi_event_run_callbacks(hal->hal_ndi_event_hdl, dip,
777c478bd9Sstevel@tonic-gate cookie, localinfo);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate * s1394_send_insert_event()
837c478bd9Sstevel@tonic-gate * Invokes any "insert event" callback registered for dip. Passes
847c478bd9Sstevel@tonic-gate * t1394_localinfo_t as impl_data for the callback.
857c478bd9Sstevel@tonic-gate */
867c478bd9Sstevel@tonic-gate static void
s1394_send_insert_event(s1394_hal_t * hal,dev_info_t * dip,t1394_localinfo_t * localinfo)877c478bd9Sstevel@tonic-gate s1394_send_insert_event(s1394_hal_t *hal, dev_info_t *dip,
887c478bd9Sstevel@tonic-gate t1394_localinfo_t *localinfo)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate char name[128];
917c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie;
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate (void) sprintf(name, "%s%d", ddi_driver_name(dip),
947c478bd9Sstevel@tonic-gate ddi_get_instance(dip));
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate if (ndi_event_retrieve_cookie(hal->hal_ndi_event_hdl, dip,
977c478bd9Sstevel@tonic-gate DDI_DEVI_INSERT_EVENT, &cookie, NDI_EVENT_NOPASS) ==
987c478bd9Sstevel@tonic-gate NDI_SUCCESS)
997c478bd9Sstevel@tonic-gate (void) ndi_event_run_callbacks(hal->hal_ndi_event_hdl, dip,
1007c478bd9Sstevel@tonic-gate cookie, localinfo);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate * s1394_create_devinfo()
1057c478bd9Sstevel@tonic-gate * This routine creates a devinfo corresponding to the unit_dir passed in.
1067c478bd9Sstevel@tonic-gate * It adds "hp-node", "reg", "compatible" properties to the devinfo
1077c478bd9Sstevel@tonic-gate * (formats for "reg" and "compatible" properties are specified by 1275
1087c478bd9Sstevel@tonic-gate * binding for IEEE1394). If unable to create the devinfo and/or add the
1097c478bd9Sstevel@tonic-gate * the properties, returns NULL, otherwise, returns the devinfo created.
1107c478bd9Sstevel@tonic-gate *
1117c478bd9Sstevel@tonic-gate * NOTE: All ndi_* routines are interrupt callable (and thus won't sleep).
1127c478bd9Sstevel@tonic-gate * So, we don't drop topology_mutex across ndi calls.
1137c478bd9Sstevel@tonic-gate */
1147c478bd9Sstevel@tonic-gate static dev_info_t *
s1394_create_devinfo(s1394_hal_t * hal,s1394_node_t * node,uint32_t * unit_dir,int nunit)1157c478bd9Sstevel@tonic-gate s1394_create_devinfo(s1394_hal_t *hal, s1394_node_t *node, uint32_t *unit_dir,
1167c478bd9Sstevel@tonic-gate int nunit)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate dev_info_t *hal_dip;
1197c478bd9Sstevel@tonic-gate uint32_t *root_dir;
1207c478bd9Sstevel@tonic-gate dev_info_t *target_dip;
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate int root_dir_len;
1237c478bd9Sstevel@tonic-gate int result, i, j, spec_id, sw_version;
1247c478bd9Sstevel@tonic-gate int mod_ven, mod_hw, mod_spec, mod_sw;
1257c478bd9Sstevel@tonic-gate int node_ven, node_hw, node_spec, node_sw;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate /*LINTED type is unused*/
1287373b68aSToomas Soome uint32_t type __unused, key, value;
1297c478bd9Sstevel@tonic-gate uint32_t unit_spec_id, unit_sw_version;
1307c478bd9Sstevel@tonic-gate uint32_t node_spec_id, node_sw_version;
1317c478bd9Sstevel@tonic-gate uint32_t node_vendor_id, node_hw_version;
1327c478bd9Sstevel@tonic-gate uint32_t module_spec_id, module_sw_version;
1337c478bd9Sstevel@tonic-gate uint32_t module_vendor_id, module_hw_version;
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate char *fmt = "firewire%06x,%06x";
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate char *buf[5], data[5][24];
1387c478bd9Sstevel@tonic-gate uint32_t reg[6];
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate hal_dip = hal->halinfo.dip;
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate /* Allocate and init a new device node instance. */
145fa9e4066Sahrens result = ndi_devi_alloc(hal_dip, "unit", (pnode_t)DEVI_SID_NODEID,
1467c478bd9Sstevel@tonic-gate &target_dip);
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate if (result != NDI_SUCCESS) {
1497c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Unable to create devinfo"
1507c478bd9Sstevel@tonic-gate " (node's GUID %08x%08x)", node->node_guid_hi,
1517c478bd9Sstevel@tonic-gate node->node_guid_lo);
1527c478bd9Sstevel@tonic-gate return (NULL);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /* Add "hp-node" property */
1567c478bd9Sstevel@tonic-gate result = ndi_prop_update_int(DDI_DEV_T_NONE, target_dip, "hp-node", 0);
1577c478bd9Sstevel@tonic-gate if (result != NDI_SUCCESS) {
1587c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Unable to add \"hp-node\" property"
1597c478bd9Sstevel@tonic-gate " (node's GUID %08x%08x)", node->node_guid_hi,
1607c478bd9Sstevel@tonic-gate node->node_guid_lo);
1617c478bd9Sstevel@tonic-gate #if defined(DEBUG)
1627c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!Error code %d", result);
1637c478bd9Sstevel@tonic-gate #endif
1647c478bd9Sstevel@tonic-gate ndi_prop_remove_all(target_dip);
1657c478bd9Sstevel@tonic-gate (void) ndi_devi_free(target_dip);
1667c478bd9Sstevel@tonic-gate return (NULL);
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate spec_id = sw_version = mod_ven = mod_hw = mod_spec = mod_sw =
1707c478bd9Sstevel@tonic-gate node_ven = node_hw = node_spec = node_sw = 0;
1717c478bd9Sstevel@tonic-gate unit_sw_version = node_sw_version = node_hw_version =
1727c478bd9Sstevel@tonic-gate module_sw_version = module_hw_version = 0;
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate root_dir = CFGROM_ROOT_DIR(node->cfgrom);
1767c478bd9Sstevel@tonic-gate root_dir_len = CFGROM_DIR_LEN(root_dir);
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate for (i = 0; i < root_dir_len; i++) {
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[i + 1], type, key, value);
1817c478bd9Sstevel@tonic-gate switch (key) {
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate case IEEE1212_MODULE_VENDOR_ID:
1847c478bd9Sstevel@tonic-gate module_vendor_id = value;
1857c478bd9Sstevel@tonic-gate mod_ven++;
1867c478bd9Sstevel@tonic-gate break;
1877c478bd9Sstevel@tonic-gate case IEEE1212_MODULE_HW_VERSION:
1887c478bd9Sstevel@tonic-gate module_hw_version = value;
1897c478bd9Sstevel@tonic-gate mod_hw++;
1907c478bd9Sstevel@tonic-gate break;
1917c478bd9Sstevel@tonic-gate case IEEE1212_MODULE_SPEC_ID:
1927c478bd9Sstevel@tonic-gate module_spec_id = value;
1937c478bd9Sstevel@tonic-gate mod_spec++;
1947c478bd9Sstevel@tonic-gate break;
1957c478bd9Sstevel@tonic-gate case IEEE1212_MODULE_SW_VERSION:
1967c478bd9Sstevel@tonic-gate module_sw_version = value;
1977c478bd9Sstevel@tonic-gate mod_sw++;
1987c478bd9Sstevel@tonic-gate break;
1997c478bd9Sstevel@tonic-gate case IEEE1212_NODE_VENDOR_ID:
2007c478bd9Sstevel@tonic-gate node_vendor_id = value;
2017c478bd9Sstevel@tonic-gate node_ven++;
2027c478bd9Sstevel@tonic-gate break;
2037c478bd9Sstevel@tonic-gate case IEEE1212_NODE_UNIQUE_ID: {
2047c478bd9Sstevel@tonic-gate uint32_t *node_unique_leaf =
2057c478bd9Sstevel@tonic-gate &root_dir[i + 1] + value;
2067c478bd9Sstevel@tonic-gate node_vendor_id = (node_unique_leaf[1] >> 8);
2077c478bd9Sstevel@tonic-gate node_ven++;
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate break;
2107c478bd9Sstevel@tonic-gate case IEEE1212_NODE_HW_VERSION:
2117c478bd9Sstevel@tonic-gate node_hw_version = value;
2127c478bd9Sstevel@tonic-gate node_hw++;
2137c478bd9Sstevel@tonic-gate break;
2147c478bd9Sstevel@tonic-gate case IEEE1212_NODE_SPEC_ID:
2157c478bd9Sstevel@tonic-gate node_spec_id = value;
2167c478bd9Sstevel@tonic-gate node_spec++;
2177c478bd9Sstevel@tonic-gate break;
2187c478bd9Sstevel@tonic-gate case IEEE1212_NODE_SW_VERSION:
2197c478bd9Sstevel@tonic-gate node_sw_version = value;
2207c478bd9Sstevel@tonic-gate node_sw++;
2217c478bd9Sstevel@tonic-gate break;
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate if (mod_ven && mod_hw && mod_spec && mod_sw && node_ven &&
2257c478bd9Sstevel@tonic-gate node_hw && node_spec && node_sw) {
2267c478bd9Sstevel@tonic-gate break;
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate * Search for unit spec and version
2327c478bd9Sstevel@tonic-gate */
2337c478bd9Sstevel@tonic-gate for (i = 0; i < CFGROM_DIR_LEN(unit_dir); i++) {
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(unit_dir[i + 1], type, key, value);
2367c478bd9Sstevel@tonic-gate if (key == IEEE1212_UNIT_SPEC_ID) {
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate unit_spec_id = value;
2397c478bd9Sstevel@tonic-gate spec_id++;
2407c478bd9Sstevel@tonic-gate } else if (key == IEEE1212_UNIT_SW_VERSION) {
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate unit_sw_version = value;
2437c478bd9Sstevel@tonic-gate sw_version++;
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate if (spec_id && sw_version)
2467c478bd9Sstevel@tonic-gate break;
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * Refer to IEEE1212 (pages 90-92) for information regarding various
2517c478bd9Sstevel@tonic-gate * id's. Module_Vendor_Id is required. Node_Vendor_Id is optional and
2527c478bd9Sstevel@tonic-gate * if not implemented, its assumed value is Module_Vendor_Id.
2537c478bd9Sstevel@tonic-gate * Module_Spec_Id is optional and if not implemented, its assumed value
2547c478bd9Sstevel@tonic-gate * is Module_Vendor_Id. Node_Spec_Id is optional, and if not
2557c478bd9Sstevel@tonic-gate * implemented, its assumed value is Node_Vendor_Id. Unit_Spec_Id is
2567c478bd9Sstevel@tonic-gate * optional, and if not implemented, its assumed value is
2577c478bd9Sstevel@tonic-gate * Node_Vendor_Id.
2587c478bd9Sstevel@tonic-gate */
2597c478bd9Sstevel@tonic-gate if (node_ven == 0) {
2607c478bd9Sstevel@tonic-gate node_vendor_id = module_vendor_id;
2617c478bd9Sstevel@tonic-gate node_ven++;
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate if (node_spec == 0) {
2657c478bd9Sstevel@tonic-gate node_spec_id = node_vendor_id;
2667c478bd9Sstevel@tonic-gate node_spec++;
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate if (mod_spec == 0) {
2707c478bd9Sstevel@tonic-gate module_spec_id = module_vendor_id;
2717c478bd9Sstevel@tonic-gate mod_spec++;
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate if (spec_id == 0) {
2757c478bd9Sstevel@tonic-gate unit_spec_id = node_vendor_id;
2767c478bd9Sstevel@tonic-gate spec_id++;
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate i = 0;
2807c478bd9Sstevel@tonic-gate if (sw_version != 0) {
2817c478bd9Sstevel@tonic-gate buf[i] = data[i];
2827c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, unit_spec_id, unit_sw_version);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate if (node_sw != 0) {
2857c478bd9Sstevel@tonic-gate buf[i] = data[i];
2867c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, node_spec_id, node_sw_version);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate if (node_hw != 0) {
2897c478bd9Sstevel@tonic-gate buf[i] = data[i];
2907c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, node_vendor_id, node_hw_version);
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate if (mod_sw != 0) {
2937c478bd9Sstevel@tonic-gate buf[i] = data[i];
2947c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, module_spec_id,
2957c478bd9Sstevel@tonic-gate module_sw_version);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate if (mod_hw != 0) {
2987c478bd9Sstevel@tonic-gate buf[i] = data[i];
2997c478bd9Sstevel@tonic-gate (void) sprintf(data[i++], fmt, module_vendor_id,
3007c478bd9Sstevel@tonic-gate module_hw_version);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate result = ndi_prop_update_string_array(DDI_DEV_T_NONE, target_dip,
3047c478bd9Sstevel@tonic-gate "compatible", (char **)&buf, i);
3057c478bd9Sstevel@tonic-gate if (result != NDI_SUCCESS) {
3067c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Unable to add \"compatible\" property"
3077c478bd9Sstevel@tonic-gate " (node's GUID %08x%08x)", node->node_guid_hi,
3087c478bd9Sstevel@tonic-gate node->node_guid_lo);
3097c478bd9Sstevel@tonic-gate #if defined(DEBUG)
3107c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!Error code %d; nelements %d", result, i);
3117c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) {
3127c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!buf[%d]: %s", j, buf[j]);
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate #endif
3157c478bd9Sstevel@tonic-gate ndi_prop_remove_all(target_dip);
3167c478bd9Sstevel@tonic-gate (void) ndi_devi_free(target_dip);
3177c478bd9Sstevel@tonic-gate return (NULL);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate /* GUID,ADDR */
3217c478bd9Sstevel@tonic-gate reg[0] = node->node_guid_hi;
3227c478bd9Sstevel@tonic-gate reg[1] = node->node_guid_lo;
3237c478bd9Sstevel@tonic-gate s1394_cfgrom_parse_unit_dir(unit_dir, ®[2], ®[3], ®[4],
3247c478bd9Sstevel@tonic-gate ®[5]);
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate reg[3] = nunit;
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate result = ndi_prop_update_int_array(DDI_DEV_T_NONE, target_dip, "reg",
3297c478bd9Sstevel@tonic-gate (int *)reg, 6);
3307c478bd9Sstevel@tonic-gate if (result != NDI_SUCCESS) {
3317c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Unable to add \"reg\" property");
3327c478bd9Sstevel@tonic-gate #if defined(DEBUG)
3337c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!Error code %d", result);
3347c478bd9Sstevel@tonic-gate for (j = 0; j < 6; j++) {
3357c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!reg[%d]: 0x%08x", j, reg[j]);
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate #endif
3387c478bd9Sstevel@tonic-gate ndi_prop_remove_all(target_dip);
3397c478bd9Sstevel@tonic-gate (void) ndi_devi_free(target_dip);
3407c478bd9Sstevel@tonic-gate return (NULL);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate return (target_dip);
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate /*
3477c478bd9Sstevel@tonic-gate * s1394_devi_find()
3487c478bd9Sstevel@tonic-gate * Searches all children of pdip for a match of name@caddr. Builds the
3497c478bd9Sstevel@tonic-gate * name and address of each child node by looking up the reg property on
3507c478bd9Sstevel@tonic-gate * the node and compares the built name@addr with the name@addr passed in.
3517c478bd9Sstevel@tonic-gate * Returns the child dip if a match is found, otherwise, returns NULL.
3527c478bd9Sstevel@tonic-gate * NOTE:
3537c478bd9Sstevel@tonic-gate * This routine is decidedly non-ddi. We had to use this one since
3547c478bd9Sstevel@tonic-gate * ndi_devi_find() can find only nodes that have valid addr field
3557c478bd9Sstevel@tonic-gate * set and that won't happen unless the node goes through INITCHILD
3567c478bd9Sstevel@tonic-gate * (at which time nx1394.c calls ddi_set_name_addr()). If, in future,
3577c478bd9Sstevel@tonic-gate * the ndi_devi_find() provides a way of looking up nodes using criteria
3587c478bd9Sstevel@tonic-gate * other than addr, we can get rid of this routine.
3597c478bd9Sstevel@tonic-gate */
3607c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3617c478bd9Sstevel@tonic-gate dev_info_t *
s1394_devi_find(dev_info_t * pdip,char * name,char * caddr)3627c478bd9Sstevel@tonic-gate s1394_devi_find(dev_info_t *pdip, char *name, char *caddr)
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate int i, reglen;
3657c478bd9Sstevel@tonic-gate char addr[32];
3667c478bd9Sstevel@tonic-gate uint32_t *regptr;
3677c478bd9Sstevel@tonic-gate dev_info_t *cdip = NULL;
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate ASSERT((name != NULL) && (caddr != NULL));
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate /*
3727c478bd9Sstevel@tonic-gate * for each child of this parent, find name and addr and match with
3737c478bd9Sstevel@tonic-gate * name and caddr passed in.
3747c478bd9Sstevel@tonic-gate */
3757c478bd9Sstevel@tonic-gate for (cdip = (dev_info_t *)DEVI(pdip)->devi_child; cdip != NULL;
3767c478bd9Sstevel@tonic-gate cdip = (dev_info_t *)DEVI(cdip)->devi_sibling) {
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate i = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
3797c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "reg", (int **)®ptr,
3807c478bd9Sstevel@tonic-gate (uint_t *)®len);
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate if (i != DDI_PROP_SUCCESS)
3837c478bd9Sstevel@tonic-gate continue;
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate /*
3867c478bd9Sstevel@tonic-gate * Construct addr from the reg property (addr is of the format
3877c478bd9Sstevel@tonic-gate * GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA], where GGGGGGGGGGGGGGGG is
3887c478bd9Sstevel@tonic-gate * the address and AAAAAAAAAAAA is the optional unit address)
3897c478bd9Sstevel@tonic-gate */
390*1a182508SToomas Soome if (regptr[2] != 0 || regptr[3] != 0) {
3917c478bd9Sstevel@tonic-gate (void) sprintf(addr, "%08x%08x,%04x%08x", regptr[0],
3927c478bd9Sstevel@tonic-gate regptr[1], regptr[2], regptr[3]);
3937c478bd9Sstevel@tonic-gate } else {
3947c478bd9Sstevel@tonic-gate (void) sprintf(addr, "%08x%08x", regptr[0], regptr[1]);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate ddi_prop_free(regptr);
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate if (strcmp(caddr, addr) == 0) {
3997c478bd9Sstevel@tonic-gate ASSERT(strcmp(ddi_node_name(cdip), name) == 0);
4007c478bd9Sstevel@tonic-gate break;
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate return (cdip);
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate * s1394_update_devinfo_tree()
4097c478bd9Sstevel@tonic-gate * Parses the config rom for the passed in node and creates/updates devinfo's
4107c478bd9Sstevel@tonic-gate * for each unit directory found. If the devinfo corresponding to a unit
4117c478bd9Sstevel@tonic-gate * already exists, any insert event callbacks registered for that devinfo
4127c478bd9Sstevel@tonic-gate * are called (topology tree is unlocked and relocked around these
4137c478bd9Sstevel@tonic-gate * callbacks). Returns DDI_SUCCESS if everything went fine and DDI_FAILURE
4147c478bd9Sstevel@tonic-gate * if unable to reacquire the lock after callbacks (relock fails because of
4157c478bd9Sstevel@tonic-gate * an intervening bus reset or if the services layer kills the bus reset
4167c478bd9Sstevel@tonic-gate * thread). The node is marked as parsed before returning.
4177c478bd9Sstevel@tonic-gate */
4187c478bd9Sstevel@tonic-gate int
s1394_update_devinfo_tree(s1394_hal_t * hal,s1394_node_t * node)4197c478bd9Sstevel@tonic-gate s1394_update_devinfo_tree(s1394_hal_t *hal, s1394_node_t *node)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate dev_info_t *tdip;
4227c478bd9Sstevel@tonic-gate int j, units, d, lockfail = 0;
4237c478bd9Sstevel@tonic-gate s1394_target_t *target, *t;
4247c478bd9Sstevel@tonic-gate uint32_t hi, lo, size_hi, size_lo, type, key, value;
4257c478bd9Sstevel@tonic-gate uint32_t *ptr, *root_dir, dir_len;
4267c478bd9Sstevel@tonic-gate t1394_localinfo_t linfo;
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate uint32_t *unit_dir_ptrs[32];
4297c478bd9Sstevel@tonic-gate dev_info_t *devinfo_ptrs[32];
4307c478bd9Sstevel@tonic-gate uint32_t new_devinfo = 0; /* to keep track of new allocations */
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate char caddr[32];
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate ASSERT(CFGROM_PARSED(node) == B_FALSE);
4377c478bd9Sstevel@tonic-gate ASSERT(node->cfgrom != NULL);
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate /* scan through config rom looking for unit dirs */
4407c478bd9Sstevel@tonic-gate root_dir = CFGROM_ROOT_DIR(node->cfgrom);
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate if (node->cfgrom_valid_size < CFGROM_DIR_LEN(root_dir))
4437c478bd9Sstevel@tonic-gate dir_len = node->cfgrom_valid_size;
4447c478bd9Sstevel@tonic-gate else
4457c478bd9Sstevel@tonic-gate dir_len = CFGROM_DIR_LEN(root_dir);
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[0], type, key, value);
4487c478bd9Sstevel@tonic-gate if (s1394_valid_dir(hal, node, key, root_dir) == B_FALSE) {
4497c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
4507c478bd9Sstevel@tonic-gate "!Bad root directory in config rom (node's GUID %08x%08x)",
4517c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo);
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate SET_CFGROM_PARSED(node);
4547c478bd9Sstevel@tonic-gate CLEAR_CFGROM_GEN_CHANGED(node); /* if set */
4557c478bd9Sstevel@tonic-gate CLEAR_CFGROM_NEW_ALLOC(node);
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate for (units = 0, j = 1; j <= dir_len; j++) {
4617c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[j], type, key, value);
4627c478bd9Sstevel@tonic-gate if (key == IEEE1212_UNIT_DIRECTORY && type ==
4637c478bd9Sstevel@tonic-gate IEEE1212_DIRECTORY_TYPE) {
4647c478bd9Sstevel@tonic-gate ptr = &root_dir[j] + value;
4657c478bd9Sstevel@tonic-gate if (s1394_valid_dir(hal, node, key, ptr) == B_TRUE) {
4667c478bd9Sstevel@tonic-gate unit_dir_ptrs[units++] = ptr;
4677c478bd9Sstevel@tonic-gate } else {
4687c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!Bad unit directory in config"
4697c478bd9Sstevel@tonic-gate " rom (node's GUID %08x%08x)",
4707c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo);
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate for (d = 0, j = 0; j < units; j++) {
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate s1394_cfgrom_parse_unit_dir(unit_dir_ptrs[j],
4787c478bd9Sstevel@tonic-gate &hi, &lo, &size_hi, &size_lo);
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate lo = j;
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate if (hi || lo) {
4837c478bd9Sstevel@tonic-gate (void) sprintf(caddr, "%08x%08x,%04x%08x",
4847c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo, hi, lo);
4857c478bd9Sstevel@tonic-gate } else {
4867c478bd9Sstevel@tonic-gate (void) sprintf(caddr, "%08x%08x",
4877c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate tdip = s1394_devi_find(hal->halinfo.dip, "unit", caddr);
4917c478bd9Sstevel@tonic-gate if (tdip != NULL) {
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_WRITER);
4947c478bd9Sstevel@tonic-gate target = s1394_target_from_dip_locked(hal, tdip);
4957c478bd9Sstevel@tonic-gate if (target != NULL) {
4967c478bd9Sstevel@tonic-gate target->target_sibling = NULL;
4977c478bd9Sstevel@tonic-gate target->on_node = node;
4987c478bd9Sstevel@tonic-gate target->target_state &= ~S1394_TARG_GONE;
4997c478bd9Sstevel@tonic-gate target->unit_dir = unit_dir_ptrs[j] - root_dir;
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate if ((t = node->target_list) != NULL) {
5027c478bd9Sstevel@tonic-gate ASSERT(t != target);
5037c478bd9Sstevel@tonic-gate while (t->target_sibling != NULL) {
5047c478bd9Sstevel@tonic-gate t = t->target_sibling;
5057c478bd9Sstevel@tonic-gate ASSERT(t != target);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate t->target_sibling = target;
5087c478bd9Sstevel@tonic-gate } else {
5097c478bd9Sstevel@tonic-gate node->target_list = target;
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate target->target_list = node->target_list;
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock);
5157c478bd9Sstevel@tonic-gate
5167c478bd9Sstevel@tonic-gate s1394_update_unit_dir_location(hal, tdip,
5177c478bd9Sstevel@tonic-gate unit_dir_ptrs[j] - root_dir);
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate } else {
5207c478bd9Sstevel@tonic-gate /* create devinfo for unit@caddr */
5217c478bd9Sstevel@tonic-gate tdip = s1394_create_devinfo(hal, node,
5227c478bd9Sstevel@tonic-gate unit_dir_ptrs[j], j);
5237c478bd9Sstevel@tonic-gate if (tdip != NULL) {
5247c478bd9Sstevel@tonic-gate new_devinfo |= (1 << d);
5257c478bd9Sstevel@tonic-gate s1394_update_unit_dir_location(hal, tdip,
5267c478bd9Sstevel@tonic-gate unit_dir_ptrs[j] - root_dir);
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate if (tdip != NULL)
5307c478bd9Sstevel@tonic-gate devinfo_ptrs[d++] = tdip;
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
5347c478bd9Sstevel@tonic-gate /* Online all valid units */
5357c478bd9Sstevel@tonic-gate for (j = 0; j < d; j++) {
5367c478bd9Sstevel@tonic-gate if ((new_devinfo & (1 << j)) == 0) {
5377c478bd9Sstevel@tonic-gate linfo.bus_generation = hal->generation_count;
5387c478bd9Sstevel@tonic-gate linfo.local_nodeID = hal->node_id;
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate /* don't need to drop topology_tree_mutex across ndi calls */
5417c478bd9Sstevel@tonic-gate (void) ndi_devi_online_async(devinfo_ptrs[j], 0);
5427c478bd9Sstevel@tonic-gate if ((new_devinfo & (1 << j)) == 0) {
5437c478bd9Sstevel@tonic-gate /*
5447c478bd9Sstevel@tonic-gate * send an insert event if this an existing devinfo.
5457c478bd9Sstevel@tonic-gate * drop and reacquire topology_tree_mutex across
5467c478bd9Sstevel@tonic-gate * the event calls
5477c478bd9Sstevel@tonic-gate */
5487c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
5497c478bd9Sstevel@tonic-gate s1394_send_insert_event(hal, devinfo_ptrs[j], &linfo);
5507c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) {
5517c478bd9Sstevel@tonic-gate lockfail = 1;
5527c478bd9Sstevel@tonic-gate break;
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate }
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate if (lockfail) {
5587c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
5597c478bd9Sstevel@tonic-gate }
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate SET_CFGROM_PARSED(node);
5627c478bd9Sstevel@tonic-gate CLEAR_CFGROM_GEN_CHANGED(node); /* if set */
5637c478bd9Sstevel@tonic-gate CLEAR_CFGROM_NEW_ALLOC(node);
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate /*
5697c478bd9Sstevel@tonic-gate * s1394_offline_node()
5707c478bd9Sstevel@tonic-gate * Offlines a node. This involves marking all targets attached to the
5717c478bd9Sstevel@tonic-gate * node as gone, invoking any remove event callbacks and calling
5727c478bd9Sstevel@tonic-gate * ndi_devi_offline to mark the devinfo as OFFLINE (for each unit
5737c478bd9Sstevel@tonic-gate * directory on the node). The tree is unlocked and relocked around
5747c478bd9Sstevel@tonic-gate * the callbacks. If unable to relock the tree, DDI_FAILURE, else
5757c478bd9Sstevel@tonic-gate * returns DDI_SUCCESS.
5767c478bd9Sstevel@tonic-gate */
5777c478bd9Sstevel@tonic-gate int
s1394_offline_node(s1394_hal_t * hal,s1394_node_t * node)5787c478bd9Sstevel@tonic-gate s1394_offline_node(s1394_hal_t *hal, s1394_node_t *node)
5797c478bd9Sstevel@tonic-gate {
5807c478bd9Sstevel@tonic-gate s1394_target_t *t;
5817c478bd9Sstevel@tonic-gate dev_info_t *tdip;
5827c478bd9Sstevel@tonic-gate int j, d, units;
5837c478bd9Sstevel@tonic-gate uint32_t *unit_dir_ptrs[32];
5847c478bd9Sstevel@tonic-gate dev_info_t *devinfo_ptrs[32];
5857c478bd9Sstevel@tonic-gate t1394_localinfo_t linfo;
5867c478bd9Sstevel@tonic-gate uint32_t *ptr, *root_dir, dir_len;
5877c478bd9Sstevel@tonic-gate uint32_t hi, lo, size_hi, size_lo, type, key, value;
5887c478bd9Sstevel@tonic-gate char caddr[32];
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate d = 0;
5937c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_WRITER);
5947c478bd9Sstevel@tonic-gate t = node->target_list;
5957c478bd9Sstevel@tonic-gate while (t != NULL) {
5967c478bd9Sstevel@tonic-gate t->target_state |= S1394_TARG_GONE;
5977c478bd9Sstevel@tonic-gate t->on_node = NULL;
5987c478bd9Sstevel@tonic-gate t = t->target_sibling;
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock);
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate /* scan through config rom looking for unit dirs */
6037c478bd9Sstevel@tonic-gate root_dir = CFGROM_ROOT_DIR(node->cfgrom);
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate if (node->cfgrom_valid_size < CFGROM_DIR_LEN(root_dir))
6067c478bd9Sstevel@tonic-gate dir_len = node->cfgrom_valid_size;
6077c478bd9Sstevel@tonic-gate else
6087c478bd9Sstevel@tonic-gate dir_len = CFGROM_DIR_LEN(root_dir);
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[0], type, key, value);
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate for (units = 0, j = 1; j <= dir_len; j++) {
6137c478bd9Sstevel@tonic-gate CFGROM_TYPE_KEY_VALUE(root_dir[j], type, key, value);
6147c478bd9Sstevel@tonic-gate if (key == IEEE1212_UNIT_DIRECTORY && type ==
6157c478bd9Sstevel@tonic-gate IEEE1212_DIRECTORY_TYPE) {
6167c478bd9Sstevel@tonic-gate ptr = &root_dir[j] + value;
6177c478bd9Sstevel@tonic-gate if (s1394_valid_dir(hal, node, key, ptr) == B_TRUE) {
6187c478bd9Sstevel@tonic-gate unit_dir_ptrs[units++] = ptr;
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate }
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate for (d = 0, j = 0; j < units; j++) {
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate s1394_cfgrom_parse_unit_dir(unit_dir_ptrs[j],
6267c478bd9Sstevel@tonic-gate &hi, &lo, &size_hi, &size_lo);
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate lo = j;
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate if (hi || lo) {
6317c478bd9Sstevel@tonic-gate (void) sprintf(caddr, "%08x%08x,%04x%08x",
6327c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo, hi, lo);
6337c478bd9Sstevel@tonic-gate } else {
6347c478bd9Sstevel@tonic-gate (void) sprintf(caddr, "%08x%08x",
6357c478bd9Sstevel@tonic-gate node->node_guid_hi, node->node_guid_lo);
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate
6387c478bd9Sstevel@tonic-gate if ((tdip = s1394_devi_find(hal->halinfo.dip, "unit", caddr)) !=
6397c478bd9Sstevel@tonic-gate NULL)
6407c478bd9Sstevel@tonic-gate devinfo_ptrs[d++] = tdip;
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate node->old_node = NULL;
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate linfo.bus_generation = hal->generation_count;
6467c478bd9Sstevel@tonic-gate linfo.local_nodeID = hal->node_id;
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate for (j = 0; j < d; j++) {
6497c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate s1394_send_remove_event(hal, devinfo_ptrs[j], &linfo);
6527c478bd9Sstevel@tonic-gate (void) ndi_devi_offline(devinfo_ptrs[j], NDI_DEVI_REMOVE);
6537c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) {
6547c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
6597c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
6607c478bd9Sstevel@tonic-gate }
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate /*
6637c478bd9Sstevel@tonic-gate * s1394_process_topology_tree()
6647c478bd9Sstevel@tonic-gate * Walks the topology tree, processing each node. If node that has
6657c478bd9Sstevel@tonic-gate * already been parsed, updates the generation property on all devinfos
6667c478bd9Sstevel@tonic-gate * for the node. Also, if the node exists in both old & new trees, ASSERTS
6677c478bd9Sstevel@tonic-gate * that both point to the same config rom. If the node has valid config
6687c478bd9Sstevel@tonic-gate * rom but hasn't been parsed yet, calls s1394_update_devinfo_tree()
6697c478bd9Sstevel@tonic-gate * to parse and create devinfos for the node. Kicks off further config
6707c478bd9Sstevel@tonic-gate * rom reading if only the bus info block for the node is read.
6717c478bd9Sstevel@tonic-gate * Returns DDI_SUCCESS if everything went fine, else returns DDI_FAILURE
6727c478bd9Sstevel@tonic-gate * (for eg. unable to reacquire the tree lock etc). wait_for_cbs argument
6737c478bd9Sstevel@tonic-gate * tells the caller if some completions can be expected. wait_gen tells
6747c478bd9Sstevel@tonic-gate * the generation the commands were issued at.
6757c478bd9Sstevel@tonic-gate */
6767c478bd9Sstevel@tonic-gate int
s1394_process_topology_tree(s1394_hal_t * hal,int * wait_for_cbs,uint_t * wait_gen)6777c478bd9Sstevel@tonic-gate s1394_process_topology_tree(s1394_hal_t *hal, int *wait_for_cbs,
6787c478bd9Sstevel@tonic-gate uint_t *wait_gen)
6797c478bd9Sstevel@tonic-gate {
6807c478bd9Sstevel@tonic-gate int i;
6817c478bd9Sstevel@tonic-gate uint_t hal_node_num, number_of_nodes;
6827c478bd9Sstevel@tonic-gate s1394_node_t *node, *onode;
6837c478bd9Sstevel@tonic-gate s1394_status_t status;
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) {
6887c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
6897c478bd9Sstevel@tonic-gate }
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
6927c478bd9Sstevel@tonic-gate hal->cfgroms_being_read = 0;
6937c478bd9Sstevel@tonic-gate number_of_nodes = hal->number_of_nodes;
6947c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate for (i = 0; i < number_of_nodes; i++) {
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate if (i == hal_node_num)
6997c478bd9Sstevel@tonic-gate continue;
7007c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) {
7017c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate node = &hal->topology_tree[i];
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate if (LINK_ACTIVE(node) == B_FALSE) {
7067c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
7077c478bd9Sstevel@tonic-gate continue;
7087c478bd9Sstevel@tonic-gate }
7097c478bd9Sstevel@tonic-gate if (node->cfgrom == NULL) {
7107c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
7117c478bd9Sstevel@tonic-gate continue;
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate onode = node->old_node;
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate if (onode != NULL && onode->cfgrom != NULL && node->cfgrom !=
7177c478bd9Sstevel@tonic-gate NULL) {
7187c478bd9Sstevel@tonic-gate /*
7197c478bd9Sstevel@tonic-gate * onode->cfgrom != node->cfgrom should have been
7207c478bd9Sstevel@tonic-gate * handled by s1394_match_GUID()!!!
7217c478bd9Sstevel@tonic-gate */
7227c478bd9Sstevel@tonic-gate ASSERT(onode->cfgrom == node->cfgrom);
7237c478bd9Sstevel@tonic-gate }
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate if (CFGROM_PARSED(node) == B_FALSE && CFGROM_ALL_READ(node) ==
7267c478bd9Sstevel@tonic-gate B_TRUE) {
7277c478bd9Sstevel@tonic-gate ASSERT((node->cfgrom_size <
7287c478bd9Sstevel@tonic-gate IEEE1394_CONFIG_ROM_QUAD_SZ) ||
7297c478bd9Sstevel@tonic-gate NODE_MATCHED(node) == B_TRUE);
7307c478bd9Sstevel@tonic-gate rw_enter(&hal->target_list_rwlock, RW_READER);
7317c478bd9Sstevel@tonic-gate ASSERT(node->target_list == NULL);
7327c478bd9Sstevel@tonic-gate rw_exit(&hal->target_list_rwlock);
7337c478bd9Sstevel@tonic-gate if (s1394_update_devinfo_tree(hal, node) ==
7347c478bd9Sstevel@tonic-gate DDI_FAILURE) {
7357c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(
7367c478bd9Sstevel@tonic-gate &hal->topology_tree_mutex));
7377c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate } else if (CFGROM_PARSED(node) == B_FALSE && CFGROM_BIB_READ(
7407c478bd9Sstevel@tonic-gate node) == B_TRUE) {
7417c478bd9Sstevel@tonic-gate if (s1394_read_rest_of_cfgrom(hal, node, &status) !=
7427c478bd9Sstevel@tonic-gate DDI_SUCCESS) {
7437c478bd9Sstevel@tonic-gate if ((status & S1394_LOCK_FAILED) == 0) {
7447c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->
7457c478bd9Sstevel@tonic-gate topology_tree_mutex));
7467c478bd9Sstevel@tonic-gate *wait_for_cbs = 0;
7477c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
7507c478bd9Sstevel@tonic-gate } else {
7517c478bd9Sstevel@tonic-gate *wait_for_cbs = 1;
7527c478bd9Sstevel@tonic-gate *wait_gen = hal->br_cfgrom_read_gen;
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate /*
7607c478bd9Sstevel@tonic-gate * flag the tree as processed; if a single bus reset happens after
7617c478bd9Sstevel@tonic-gate * this, we will use tree matching.
7627c478bd9Sstevel@tonic-gate */
7637c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) {
7647c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate hal->topology_tree_processed = B_TRUE;
7677c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
7707c478bd9Sstevel@tonic-gate }
7717c478bd9Sstevel@tonic-gate
7727c478bd9Sstevel@tonic-gate /*
7737c478bd9Sstevel@tonic-gate * s1394_process_old_tree()
7747c478bd9Sstevel@tonic-gate * Walks through the old tree and offlines nodes that are removed. Nodes
7757c478bd9Sstevel@tonic-gate * with an active link in the old tree but link powered off in the current
7767c478bd9Sstevel@tonic-gate * generation are also offlined, as well as nodes with invalid config
7777c478bd9Sstevel@tonic-gate * rom in current generation.
7787c478bd9Sstevel@tonic-gate * The topology tree is locked/unlocked while walking through all the nodes;
7797c478bd9Sstevel@tonic-gate * if the locking fails at any stage, stops further walking and returns
7807c478bd9Sstevel@tonic-gate * DDI_FAILURE. Returns DDI_SUCCESS if everything went fine.
7817c478bd9Sstevel@tonic-gate */
7827c478bd9Sstevel@tonic-gate int
s1394_process_old_tree(s1394_hal_t * hal)7837c478bd9Sstevel@tonic-gate s1394_process_old_tree(s1394_hal_t *hal)
7847c478bd9Sstevel@tonic-gate {
7857c478bd9Sstevel@tonic-gate int i;
7867c478bd9Sstevel@tonic-gate uint_t hal_node_num_old, old_number_of_nodes;
7877c478bd9Sstevel@tonic-gate s1394_node_t *onode;
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate /*
7907c478bd9Sstevel@tonic-gate * NODE_MATCHED(onode) == 0 indicates this node doesn't exist
7917c478bd9Sstevel@tonic-gate * any more.
7927c478bd9Sstevel@tonic-gate */
7937c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
7947c478bd9Sstevel@tonic-gate
7957c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) {
7967c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate hal_node_num_old = IEEE1394_NODE_NUM(hal->old_node_id);
7997c478bd9Sstevel@tonic-gate old_number_of_nodes = hal->old_number_of_nodes;
8007c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate for (i = 0; i < old_number_of_nodes; i++) {
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate if (i == hal_node_num_old)
8057c478bd9Sstevel@tonic-gate continue;
8067c478bd9Sstevel@tonic-gate if (s1394_lock_tree(hal) != DDI_SUCCESS) {
8077c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate onode = &hal->old_tree[i];
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate if (onode->cfgrom == NULL) {
8137c478bd9Sstevel@tonic-gate CLEAR_CFGROM_STATE(onode);
8147c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
8157c478bd9Sstevel@tonic-gate continue;
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate * onode->cur_node == NULL iff we couldn't read cfgrom in the
8207c478bd9Sstevel@tonic-gate * current generation in non-tree matching case (and thus
8217c478bd9Sstevel@tonic-gate * match_GUIDs couldn't set cur_node).
8227c478bd9Sstevel@tonic-gate */
8237c478bd9Sstevel@tonic-gate if (NODE_MATCHED(onode) == B_FALSE || (onode->cur_node ==
8247c478bd9Sstevel@tonic-gate NULL || ((CFGROM_VALID(onode) == B_TRUE &&
8257c478bd9Sstevel@tonic-gate CFGROM_VALID(onode->cur_node) == B_FALSE) ||
8267c478bd9Sstevel@tonic-gate (LINK_ACTIVE(onode) == B_TRUE && LINK_ACTIVE(onode->
8277c478bd9Sstevel@tonic-gate cur_node) == B_FALSE)))) {
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate if (s1394_offline_node(hal, onode) != DDI_SUCCESS) {
8307c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
8317c478bd9Sstevel@tonic-gate }
8327c478bd9Sstevel@tonic-gate s1394_free_cfgrom(hal, onode, S1394_FREE_CFGROM_OLD);
8337c478bd9Sstevel@tonic-gate }
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate s1394_unlock_tree(hal);
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate
8387c478bd9Sstevel@tonic-gate ASSERT(MUTEX_NOT_HELD(&hal->topology_tree_mutex));
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
8417c478bd9Sstevel@tonic-gate }
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate /*
8447c478bd9Sstevel@tonic-gate * s1394_update_unit_dir_location()
8457c478bd9Sstevel@tonic-gate * Updates the unit-dir-offset property on the devinfo.
8467c478bd9Sstevel@tonic-gate * NOTE: ndi_prop_update_int() is interrupt callable (and thus won't block);
8477c478bd9Sstevel@tonic-gate * so, the caller doesn't drop topology_tree_mutex when calling this routine.
8487c478bd9Sstevel@tonic-gate */
8497c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8507c478bd9Sstevel@tonic-gate static void
s1394_update_unit_dir_location(s1394_hal_t * hal,dev_info_t * tdip,uint_t offset)8517c478bd9Sstevel@tonic-gate s1394_update_unit_dir_location(s1394_hal_t *hal, dev_info_t *tdip,
8527c478bd9Sstevel@tonic-gate uint_t offset)
8537c478bd9Sstevel@tonic-gate {
8547c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
8557c478bd9Sstevel@tonic-gate ASSERT(tdip != NULL);
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate (void) ndi_prop_update_int(DDI_DEV_T_NONE, tdip, "unit-dir-offset",
8587c478bd9Sstevel@tonic-gate offset);
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate /*
8627c478bd9Sstevel@tonic-gate * s1394_add_target_to_node()
8637c478bd9Sstevel@tonic-gate * adds target to the list of targets hanging off the node. Figures out
8647c478bd9Sstevel@tonic-gate * the node by searching the topology tree for the GUID corresponding
8657c478bd9Sstevel@tonic-gate * to the target. Points on_node field of target structure at the node.
8667c478bd9Sstevel@tonic-gate */
8677c478bd9Sstevel@tonic-gate void
s1394_add_target_to_node(s1394_target_t * target)8687c478bd9Sstevel@tonic-gate s1394_add_target_to_node(s1394_target_t *target)
8697c478bd9Sstevel@tonic-gate {
8707c478bd9Sstevel@tonic-gate s1394_target_t *t;
8717c478bd9Sstevel@tonic-gate s1394_hal_t *hal;
8727c478bd9Sstevel@tonic-gate uint32_t guid_hi;
8737c478bd9Sstevel@tonic-gate uint32_t guid_lo;
8747c478bd9Sstevel@tonic-gate int i;
8757c478bd9Sstevel@tonic-gate char name[MAXNAMELEN];
8767c478bd9Sstevel@tonic-gate char *ptr;
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate hal = target->on_hal;
8797c478bd9Sstevel@tonic-gate ASSERT(hal != NULL);
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate /* Topology tree must be locked when it gets here! */
8827c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate /* target_list_rwlock should be held in write mode */
8857c478bd9Sstevel@tonic-gate ASSERT(rw_read_locked(&target->on_hal->target_list_rwlock) == 0);
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate if ((ptr = ddi_get_name_addr(target->target_dip)) == NULL) {
8887c478bd9Sstevel@tonic-gate return;
8897c478bd9Sstevel@tonic-gate }
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate (void) sprintf(name, ptr);
8927c478bd9Sstevel@tonic-gate /* Drop the ,<ADDR> part, if present */
8937c478bd9Sstevel@tonic-gate if ((ptr = strchr(name, ',')) != NULL)
8947c478bd9Sstevel@tonic-gate *ptr = '\0';
8957c478bd9Sstevel@tonic-gate
8967c478bd9Sstevel@tonic-gate ptr = name;
8977c478bd9Sstevel@tonic-gate guid_hi = s1394_stoi(ptr, 8, 16);
8987c478bd9Sstevel@tonic-gate guid_lo = s1394_stoi(ptr + 8, 8, 16);
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate /* Search the HAL's node list for this GUID */
9017c478bd9Sstevel@tonic-gate for (i = 0; i < hal->number_of_nodes; i++) {
9027c478bd9Sstevel@tonic-gate if (CFGROM_VALID(&hal->topology_tree[i]) == B_TRUE) {
9037c478bd9Sstevel@tonic-gate ASSERT(hal->topology_tree[i].cfgrom != NULL);
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate if ((hal->topology_tree[i].node_guid_hi == guid_hi) &&
9067c478bd9Sstevel@tonic-gate (hal->topology_tree[i].node_guid_lo == guid_lo)) {
9077c478bd9Sstevel@tonic-gate target->on_node = &hal->topology_tree[i];
9087c478bd9Sstevel@tonic-gate if ((t = hal->topology_tree[i].target_list) !=
9097c478bd9Sstevel@tonic-gate NULL) {
9107c478bd9Sstevel@tonic-gate ASSERT(t != target);
9117c478bd9Sstevel@tonic-gate while (t->target_sibling != NULL) {
9127c478bd9Sstevel@tonic-gate t = t->target_sibling;
9137c478bd9Sstevel@tonic-gate ASSERT(t != target);
9147c478bd9Sstevel@tonic-gate }
9157c478bd9Sstevel@tonic-gate t->target_sibling = target;
9167c478bd9Sstevel@tonic-gate } else {
9177c478bd9Sstevel@tonic-gate hal->topology_tree[i].target_list =
9187c478bd9Sstevel@tonic-gate target;
9197c478bd9Sstevel@tonic-gate }
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate /*
9227c478bd9Sstevel@tonic-gate * update target_list in all targets on the
9237c478bd9Sstevel@tonic-gate * node
9247c478bd9Sstevel@tonic-gate */
9257c478bd9Sstevel@tonic-gate t = hal->topology_tree[i].target_list;
9267c478bd9Sstevel@tonic-gate while (t != NULL) {
9277c478bd9Sstevel@tonic-gate t->target_list =
9287c478bd9Sstevel@tonic-gate hal->topology_tree[i].target_list;
9297c478bd9Sstevel@tonic-gate t = t->target_sibling;
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate break;
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate }
9347c478bd9Sstevel@tonic-gate }
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate /*
9387c478bd9Sstevel@tonic-gate * s1394_remove_target_from_node()
9397c478bd9Sstevel@tonic-gate * Removes target from the corresponding node's target_list.
9407c478bd9Sstevel@tonic-gate */
9417c478bd9Sstevel@tonic-gate void
s1394_remove_target_from_node(s1394_target_t * target)9427c478bd9Sstevel@tonic-gate s1394_remove_target_from_node(s1394_target_t *target)
9437c478bd9Sstevel@tonic-gate {
9447c478bd9Sstevel@tonic-gate s1394_target_t *t, *t1;
9457c478bd9Sstevel@tonic-gate s1394_hal_t *hal;
9467c478bd9Sstevel@tonic-gate
9477c478bd9Sstevel@tonic-gate hal = target->on_hal;
9487c478bd9Sstevel@tonic-gate ASSERT(hal != NULL);
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate /* Topology tree must be locked when it gets here! */
9517c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate /* target_list_rwlock should be held in write mode */
9547c478bd9Sstevel@tonic-gate ASSERT(rw_read_locked(&target->on_hal->target_list_rwlock) == 0);
9557c478bd9Sstevel@tonic-gate
9567c478bd9Sstevel@tonic-gate t = target->target_list;
9577c478bd9Sstevel@tonic-gate t1 = NULL;
9587c478bd9Sstevel@tonic-gate while (t != NULL) {
9597c478bd9Sstevel@tonic-gate if (t == target) {
9607c478bd9Sstevel@tonic-gate if (t1 == NULL) {
9617c478bd9Sstevel@tonic-gate target->target_list = t->target_sibling;
9627c478bd9Sstevel@tonic-gate } else {
9637c478bd9Sstevel@tonic-gate t1->target_sibling = t->target_sibling;
9647c478bd9Sstevel@tonic-gate }
9657c478bd9Sstevel@tonic-gate break;
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate t1 = t;
9687c478bd9Sstevel@tonic-gate t = t->target_sibling;
9697c478bd9Sstevel@tonic-gate }
9707c478bd9Sstevel@tonic-gate /* Update the target_list pointer in all the targets */
9717c478bd9Sstevel@tonic-gate if (target->on_node != NULL)
9727c478bd9Sstevel@tonic-gate target->on_node->target_list = target->target_list;
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate t = t1 = target->target_list;
9757c478bd9Sstevel@tonic-gate while (t != NULL) {
9767c478bd9Sstevel@tonic-gate t->target_list = t1;
9777c478bd9Sstevel@tonic-gate t = t->target_sibling;
9787c478bd9Sstevel@tonic-gate }
9797c478bd9Sstevel@tonic-gate
9807c478bd9Sstevel@tonic-gate target->on_node = NULL;
9817c478bd9Sstevel@tonic-gate target->target_sibling = NULL;
9827c478bd9Sstevel@tonic-gate }
983