11c42de6dSgd78059 /* 21c42de6dSgd78059 * CDDL HEADER START 31c42de6dSgd78059 * 41c42de6dSgd78059 * The contents of this file are subject to the terms of the 51c42de6dSgd78059 * Common Development and Distribution License (the "License"). 61c42de6dSgd78059 * You may not use this file except in compliance with the License. 71c42de6dSgd78059 * 81c42de6dSgd78059 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91c42de6dSgd78059 * or http://www.opensolaris.org/os/licensing. 101c42de6dSgd78059 * See the License for the specific language governing permissions 111c42de6dSgd78059 * and limitations under the License. 121c42de6dSgd78059 * 131c42de6dSgd78059 * When distributing Covered Code, include this CDDL HEADER in each 141c42de6dSgd78059 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151c42de6dSgd78059 * If applicable, add the following below this CDDL HEADER, with the 161c42de6dSgd78059 * fields enclosed by brackets "[]" replaced with your own identifying 171c42de6dSgd78059 * information: Portions Copyright [yyyy] [name of copyright owner] 181c42de6dSgd78059 * 191c42de6dSgd78059 * CDDL HEADER END 201c42de6dSgd78059 */ 211c42de6dSgd78059 /* 22*88294e09SRichard Bean * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 231c42de6dSgd78059 * Use is subject to license terms. 241c42de6dSgd78059 */ 251c42de6dSgd78059 261c42de6dSgd78059 /* 271c42de6dSgd78059 * Safari Configurator (gptwocfg) 281c42de6dSgd78059 * 291c42de6dSgd78059 */ 301c42de6dSgd78059 311c42de6dSgd78059 #include <sys/types.h> 321c42de6dSgd78059 #include <sys/cred.h> 331c42de6dSgd78059 #include <sys/mman.h> 341c42de6dSgd78059 #include <sys/kmem.h> 351c42de6dSgd78059 #include <sys/conf.h> 361c42de6dSgd78059 #include <sys/cmn_err.h> 371c42de6dSgd78059 #include <sys/ddi.h> 381c42de6dSgd78059 #include <sys/sunddi.h> 391c42de6dSgd78059 #include <sys/sunndi.h> 401c42de6dSgd78059 #include <sys/modctl.h> 411c42de6dSgd78059 #include <sys/stat.h> 421c42de6dSgd78059 #include <sys/param.h> 431c42de6dSgd78059 #include <sys/autoconf.h> 441c42de6dSgd78059 #include <sys/ksynch.h> 451c42de6dSgd78059 #include <sys/promif.h> 461c42de6dSgd78059 #include <sys/ndi_impldefs.h> 471c42de6dSgd78059 #include <sys/ddi_impldefs.h> 481c42de6dSgd78059 #include <sys/gp2cfg.h> 491c42de6dSgd78059 #include <sys/machsystm.h> 501c42de6dSgd78059 #include <sys/platform_module.h> 511c42de6dSgd78059 #pragma weak starcat_dr_name 521c42de6dSgd78059 531c42de6dSgd78059 #ifdef DEBUG 541c42de6dSgd78059 int gptwocfg_debug = 0; 551c42de6dSgd78059 561c42de6dSgd78059 static void debug(char *, uintptr_t, uintptr_t, 571c42de6dSgd78059 uintptr_t, uintptr_t, uintptr_t); 581c42de6dSgd78059 591c42de6dSgd78059 #define GPTWO_DEBUG0(level, flag, s) if (gptwocfg_debug >= level) \ 601c42de6dSgd78059 cmn_err(flag, s) 611c42de6dSgd78059 #define GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwocfg_debug >= level) \ 621c42de6dSgd78059 debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0); 631c42de6dSgd78059 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwocfg_debug >= level) \ 641c42de6dSgd78059 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0); 651c42de6dSgd78059 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \ 661c42de6dSgd78059 if (gptwocfg_debug >= level) \ 671c42de6dSgd78059 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0); 681c42de6dSgd78059 #else 691c42de6dSgd78059 #define GPTWO_DEBUG0(level, flag, s) 701c42de6dSgd78059 #define GPTWO_DEBUG1(level, flag, fmt, a1) 711c42de6dSgd78059 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) 721c42de6dSgd78059 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) 731c42de6dSgd78059 #endif 741c42de6dSgd78059 751c42de6dSgd78059 kmutex_t gptwo_handle_list_lock; 761c42de6dSgd78059 gptwocfg_handle_list_t *gptwocfg_handle_list; 771c42de6dSgd78059 781c42de6dSgd78059 static kmutex_t gptwo_config_list_lock; 791c42de6dSgd78059 static gptwocfg_config_t *gptwo_config_list; 801c42de6dSgd78059 811c42de6dSgd78059 static gptwo_new_nodes_t * 821c42de6dSgd78059 gptwocfg_get_obp_created_nodes(dev_info_t *, uint_t); 831c42de6dSgd78059 841c42de6dSgd78059 void (*gptwocfg_unclaim_address)(uint_t); 851c42de6dSgd78059 861c42de6dSgd78059 extern caddr_t efcode_vaddr; 871c42de6dSgd78059 extern int efcode_size; 881c42de6dSgd78059 891c42de6dSgd78059 #define GPTWO_NUMBER_OF_DEVICE_TYPES 6 901c42de6dSgd78059 911c42de6dSgd78059 static kmutex_t gptwocfg_ops_table_lock; 921c42de6dSgd78059 gptwocfg_ops_t *gptwocfg_ops_table[GPTWO_NUMBER_OF_DEVICE_TYPES]; 931c42de6dSgd78059 941c42de6dSgd78059 /* 951c42de6dSgd78059 * Module linkage information for the kernel. 961c42de6dSgd78059 */ 971c42de6dSgd78059 981c42de6dSgd78059 extern struct mod_ops mod_miscops; 991c42de6dSgd78059 1001c42de6dSgd78059 static struct modlmisc modlmisc = { 1011c42de6dSgd78059 &mod_miscops, /* Type of module */ 102*88294e09SRichard Bean "gptwo configurator", 1031c42de6dSgd78059 }; 1041c42de6dSgd78059 1051c42de6dSgd78059 static struct modlinkage modlinkage = { 1061c42de6dSgd78059 MODREV_1, (void *)&modlmisc, NULL 1071c42de6dSgd78059 }; 1081c42de6dSgd78059 1091c42de6dSgd78059 int 1101c42de6dSgd78059 _init(void) 1111c42de6dSgd78059 { 1121c42de6dSgd78059 unsigned int i; 1131c42de6dSgd78059 1141c42de6dSgd78059 GPTWO_DEBUG0(1, CE_WARN, "gptwocfg (Safari Configurator) " 1151c42de6dSgd78059 "has been loaded\n"); 1161c42de6dSgd78059 1171c42de6dSgd78059 mutex_init(&gptwo_config_list_lock, NULL, MUTEX_DRIVER, NULL); 1181c42de6dSgd78059 mutex_init(&gptwocfg_ops_table_lock, NULL, MUTEX_DRIVER, NULL); 1191c42de6dSgd78059 gptwo_config_list = NULL; 1201c42de6dSgd78059 1211c42de6dSgd78059 mutex_init(&gptwo_handle_list_lock, NULL, MUTEX_DRIVER, NULL); 1221c42de6dSgd78059 gptwocfg_handle_list = NULL; 1231c42de6dSgd78059 1241c42de6dSgd78059 for (i = 0; i < GPTWO_NUMBER_OF_DEVICE_TYPES; i++) 1251c42de6dSgd78059 gptwocfg_ops_table[i] = NULL; 1261c42de6dSgd78059 1271c42de6dSgd78059 return (mod_install(&modlinkage)); 1281c42de6dSgd78059 } 1291c42de6dSgd78059 1301c42de6dSgd78059 int 1311c42de6dSgd78059 _fini(void) 1321c42de6dSgd78059 { 1331c42de6dSgd78059 int error; 1341c42de6dSgd78059 1351c42de6dSgd78059 error = mod_remove(&modlinkage); 1361c42de6dSgd78059 if (error != 0) { 1371c42de6dSgd78059 return (error); 1381c42de6dSgd78059 } 1391c42de6dSgd78059 mutex_destroy(&gptwo_config_list_lock); 1401c42de6dSgd78059 mutex_destroy(&gptwocfg_ops_table_lock); 1411c42de6dSgd78059 mutex_destroy(&gptwo_handle_list_lock); 1421c42de6dSgd78059 1431c42de6dSgd78059 return (0); 1441c42de6dSgd78059 } 1451c42de6dSgd78059 1461c42de6dSgd78059 int 1471c42de6dSgd78059 _info(modinfop) 1481c42de6dSgd78059 struct modinfo *modinfop; 1491c42de6dSgd78059 { 1501c42de6dSgd78059 return (mod_info(&modlinkage, modinfop)); 1511c42de6dSgd78059 } 1521c42de6dSgd78059 1531c42de6dSgd78059 gptwo_new_nodes_t * 1541c42de6dSgd78059 gptwocfg_allocate_node_list(int number_of_nodes) 1551c42de6dSgd78059 { 1561c42de6dSgd78059 gptwo_new_nodes_t *gptwo_new_nodes; 1571c42de6dSgd78059 int size; 1581c42de6dSgd78059 1591c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_allocate_node_list- %d nodes", 1601c42de6dSgd78059 number_of_nodes); 1611c42de6dSgd78059 1621c42de6dSgd78059 size = sizeof (gptwo_new_nodes_t) + 1631c42de6dSgd78059 ((number_of_nodes -1) * sizeof (dev_info_t *)); 1641c42de6dSgd78059 1651c42de6dSgd78059 gptwo_new_nodes = kmem_zalloc(size, KM_SLEEP); 1661c42de6dSgd78059 1671c42de6dSgd78059 gptwo_new_nodes->gptwo_number_of_nodes = number_of_nodes; 1681c42de6dSgd78059 gptwo_new_nodes->gptwo_version = GP2_VERSION; 1691c42de6dSgd78059 1701c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_allocate_node_list- returned %p\n", 1711c42de6dSgd78059 gptwo_new_nodes); 1721c42de6dSgd78059 1731c42de6dSgd78059 return (gptwo_new_nodes); 1741c42de6dSgd78059 } 1751c42de6dSgd78059 1761c42de6dSgd78059 void 1771c42de6dSgd78059 gptwocfg_free_node_list(gptwo_new_nodes_t *gptwo_new_nodes) 1781c42de6dSgd78059 { 1791c42de6dSgd78059 int size; 1801c42de6dSgd78059 1811c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_free_node_list- %p %d nodes", 1821c42de6dSgd78059 gptwo_new_nodes, gptwo_new_nodes->gptwo_number_of_nodes); 1831c42de6dSgd78059 1841c42de6dSgd78059 size = sizeof (gptwo_new_nodes_t) + 1851c42de6dSgd78059 ((gptwo_new_nodes->gptwo_number_of_nodes - 1) * 1861c42de6dSgd78059 sizeof (dev_info_t *)); 1871c42de6dSgd78059 1881c42de6dSgd78059 kmem_free(gptwo_new_nodes, size); 1891c42de6dSgd78059 } 1901c42de6dSgd78059 1911c42de6dSgd78059 void 1921c42de6dSgd78059 gptwocfg_register_ops(uint_t type, gptwo_cfgfunc_t *cfg_func, 1931c42de6dSgd78059 gptwo_uncfgfunc_t *uncfg_func) 1941c42de6dSgd78059 { 1951c42de6dSgd78059 /* KM_SLEEP guarantees success */ 1961c42de6dSgd78059 gptwocfg_ops_t *ops = kmem_zalloc(sizeof (gptwocfg_ops_t), KM_SLEEP); 1971c42de6dSgd78059 1981c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_register_ops: type=%x ops=%lx\n", 1991c42de6dSgd78059 type, ops); 2001c42de6dSgd78059 ASSERT(type < GPTWO_NUMBER_OF_DEVICE_TYPES); 2011c42de6dSgd78059 ops->gptwocfg_type = type; 2021c42de6dSgd78059 ops->gptwocfg_version = GPTWOCFG_OPS_VERSION; 2031c42de6dSgd78059 ops->gptwocfg_configure = cfg_func; 2041c42de6dSgd78059 ops->gptwocfg_unconfigure = uncfg_func; 2051c42de6dSgd78059 2061c42de6dSgd78059 mutex_enter(&gptwocfg_ops_table_lock); 2071c42de6dSgd78059 gptwocfg_ops_table[type] = ops; 2081c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 2091c42de6dSgd78059 } 2101c42de6dSgd78059 2111c42de6dSgd78059 2121c42de6dSgd78059 2131c42de6dSgd78059 void 2141c42de6dSgd78059 gptwocfg_unregister_ops(uint_t type) 2151c42de6dSgd78059 { 2161c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unregister_ops: type=%x\n", type); 2171c42de6dSgd78059 2181c42de6dSgd78059 ASSERT(type < GPTWO_NUMBER_OF_DEVICE_TYPES); 2191c42de6dSgd78059 2201c42de6dSgd78059 mutex_enter(&gptwocfg_ops_table_lock); 2211c42de6dSgd78059 kmem_free(gptwocfg_ops_table[type], sizeof (gptwocfg_ops_t)); 2221c42de6dSgd78059 gptwocfg_ops_table[type] = NULL; 2231c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 2241c42de6dSgd78059 } 2251c42de6dSgd78059 2261c42de6dSgd78059 gptwocfg_cookie_t 2271c42de6dSgd78059 gptwocfg_configure(dev_info_t *ap, spcd_t *pcd, gptwo_aid_t id) 2281c42de6dSgd78059 { 2291c42de6dSgd78059 gptwo_new_nodes_t *new_nodes = NULL; 2301c42de6dSgd78059 gptwocfg_config_t *config; 2311c42de6dSgd78059 gptwocfg_ops_t *ops; 2321c42de6dSgd78059 2331c42de6dSgd78059 GPTWO_DEBUG3(1, CE_CONT, "gptwocfg_configure: ap=0x%p pcd=%p id=%x\n", 2341c42de6dSgd78059 ap, pcd, id); 2351c42de6dSgd78059 2361c42de6dSgd78059 /* 2371c42de6dSgd78059 * Look to see if the port is already configured. 2381c42de6dSgd78059 */ 2391c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 2401c42de6dSgd78059 config = gptwo_config_list; 2411c42de6dSgd78059 while (config != NULL) { 2421c42de6dSgd78059 if (&starcat_dr_name) { 2431c42de6dSgd78059 if (starcat_dr_name(ddi_node_name(ap)) < 0) { 2441c42de6dSgd78059 config = config->gptwo_next; 2451c42de6dSgd78059 continue; 2461c42de6dSgd78059 } 2471c42de6dSgd78059 } 2481c42de6dSgd78059 if (config->gptwo_portid == id) { 2491c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: gptwocfg_configure: " 2501c42de6dSgd78059 "0x%x Port already configured\n", id); 2511c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 2521c42de6dSgd78059 return (NULL); 2531c42de6dSgd78059 } 2541c42de6dSgd78059 config = config->gptwo_next; 2551c42de6dSgd78059 } 2561c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 2571c42de6dSgd78059 2581c42de6dSgd78059 if (pcd == NULL) { 2591c42de6dSgd78059 GPTWO_DEBUG0(1, CE_CONT, "gptwocfg_configure: pcd=NULL\n"); 2601c42de6dSgd78059 return (NULL); 2611c42de6dSgd78059 } 2621c42de6dSgd78059 2631c42de6dSgd78059 if ((pcd->spcd_magic != PCD_MAGIC) || 2641c42de6dSgd78059 (pcd->spcd_version != PCD_VERSION)) { 2651c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: Invalid Port " 2661c42de6dSgd78059 "Configuration Descriptor\n"); 2671c42de6dSgd78059 return (NULL); 2681c42de6dSgd78059 } 2691c42de6dSgd78059 2701c42de6dSgd78059 if (pcd->spcd_ptype >= GPTWO_NUMBER_OF_DEVICE_TYPES) { 2711c42de6dSgd78059 cmn_err(CE_WARN, 2721c42de6dSgd78059 "gptwocfg: Invalid device type %x", pcd->spcd_ptype); 2731c42de6dSgd78059 return (NULL); 2741c42de6dSgd78059 } 2751c42de6dSgd78059 2761c42de6dSgd78059 if (pcd->spcd_prsv != SPCD_RSV_PASS) { 2771c42de6dSgd78059 cmn_err(CE_WARN, 2781c42de6dSgd78059 "gptwocfg: Agent at ID %x has not passed test(s)\n", id); 2791c42de6dSgd78059 return (NULL); 2801c42de6dSgd78059 } 2811c42de6dSgd78059 2821c42de6dSgd78059 mutex_enter(&gptwocfg_ops_table_lock); 2831c42de6dSgd78059 2841c42de6dSgd78059 ops = gptwocfg_ops_table[pcd->spcd_ptype]; 2851c42de6dSgd78059 2861c42de6dSgd78059 if (ops == NULL) { 2871c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: Ops for type %x have not been " 2881c42de6dSgd78059 "registered\n", pcd->spcd_ptype); 2891c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 2901c42de6dSgd78059 return (NULL); 2911c42de6dSgd78059 } 2921c42de6dSgd78059 2931c42de6dSgd78059 if (ops->gptwocfg_configure == NULL) { 2941c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: no configure routine registered " 2951c42de6dSgd78059 "for sfaari type %x\n", pcd->spcd_ptype); 2961c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 2971c42de6dSgd78059 return (NULL); 2981c42de6dSgd78059 } 2991c42de6dSgd78059 3001c42de6dSgd78059 new_nodes = ops->gptwocfg_configure(ap, pcd, id); 3011c42de6dSgd78059 3021c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 3031c42de6dSgd78059 3041c42de6dSgd78059 if (new_nodes != NULL) { 3051c42de6dSgd78059 config = kmem_zalloc(sizeof (gptwocfg_config_t), KM_SLEEP); 3061c42de6dSgd78059 config->gptwo_version = GP2_VERSION; 3071c42de6dSgd78059 config->gptwo_ap = ap; 3081c42de6dSgd78059 config->gptwo_portid = id; 3091c42de6dSgd78059 config->gptwo_nodes = new_nodes; 3101c42de6dSgd78059 config->gptwo_ops = ops; 3111c42de6dSgd78059 3121c42de6dSgd78059 /* 3131c42de6dSgd78059 * put config on config list 3141c42de6dSgd78059 */ 3151c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 3161c42de6dSgd78059 config->gptwo_next = gptwo_config_list; 3171c42de6dSgd78059 gptwo_config_list = config; 3181c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 3191c42de6dSgd78059 } else { 3201c42de6dSgd78059 config = NULL; 3211c42de6dSgd78059 } 3221c42de6dSgd78059 3231c42de6dSgd78059 return ((gptwocfg_cookie_t)config); 3241c42de6dSgd78059 } 3251c42de6dSgd78059 3261c42de6dSgd78059 gptwocfg_cookie_t 3271c42de6dSgd78059 gptwocfg_unconfigure(dev_info_t *ap, gptwo_aid_t id) 3281c42de6dSgd78059 { 3291c42de6dSgd78059 int i, circ; 3301c42de6dSgd78059 int failure = 0; 3311c42de6dSgd78059 dev_info_t *saf_dip; 3321c42de6dSgd78059 gptwocfg_config_t *config, *temp; 3331c42de6dSgd78059 gptwo_new_nodes_t *obp_nodes; 3341c42de6dSgd78059 gptwocfg_ops_t *ops; 3351c42de6dSgd78059 3361c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_unconfigure: ap=0x%p id=0x%lx\n", 3371c42de6dSgd78059 ap, id); 3381c42de6dSgd78059 3391c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 3401c42de6dSgd78059 config = gptwo_config_list; 3411c42de6dSgd78059 while (config != NULL) { 3421c42de6dSgd78059 if (config->gptwo_portid == id) { 3431c42de6dSgd78059 break; 3441c42de6dSgd78059 } 3451c42de6dSgd78059 config = config->gptwo_next; 3461c42de6dSgd78059 } 3471c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 3481c42de6dSgd78059 3491c42de6dSgd78059 if (config == NULL) { 3501c42de6dSgd78059 /* 3511c42de6dSgd78059 * There is no config structure associated with this agent id 3521c42de6dSgd78059 * so it was probably built by firmware at start of day. We 3531c42de6dSgd78059 * need to create a config structure before we can continue. 3541c42de6dSgd78059 */ 3551c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure: id=0x%lx " 3561c42de6dSgd78059 "No config structure - Need to build one\n", id); 3571c42de6dSgd78059 3581c42de6dSgd78059 obp_nodes = gptwocfg_get_obp_created_nodes(ap, id); 3591c42de6dSgd78059 3601c42de6dSgd78059 if (obp_nodes != NULL) { 3611c42de6dSgd78059 config = kmem_zalloc(sizeof (gptwocfg_config_t), 3621c42de6dSgd78059 KM_SLEEP); 3631c42de6dSgd78059 config->gptwo_version = GP2_VERSION; 3641c42de6dSgd78059 config->gptwo_ap = ap; 3651c42de6dSgd78059 config->gptwo_portid = id; 3661c42de6dSgd78059 config->gptwo_nodes = obp_nodes; 3671c42de6dSgd78059 3681c42de6dSgd78059 /* 3691c42de6dSgd78059 * put config on config list 3701c42de6dSgd78059 */ 3711c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 3721c42de6dSgd78059 config->gptwo_next = gptwo_config_list; 3731c42de6dSgd78059 gptwo_config_list = config; 3741c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 3751c42de6dSgd78059 } else { 3761c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: gptwocfg_unconfigure: " 3771c42de6dSgd78059 "No OBP created nodes for ap=0x%lx agent id=0x%x", 3781c42de6dSgd78059 (long)ap, id); 3791c42de6dSgd78059 return (NULL); 3801c42de6dSgd78059 } 3811c42de6dSgd78059 } 3821c42de6dSgd78059 3831c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure config=0x%lx\n", 3841c42de6dSgd78059 config); 3851c42de6dSgd78059 3861c42de6dSgd78059 ops = config->gptwo_ops; 3871c42de6dSgd78059 3881c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure: ops=%lx\n", ops); 3891c42de6dSgd78059 3901c42de6dSgd78059 ndi_devi_enter(ap, &circ); 3911c42de6dSgd78059 3921c42de6dSgd78059 for (i = 0; i < config->gptwo_nodes->gptwo_number_of_nodes; i++) { 3931c42de6dSgd78059 dev_info_t *fdip = NULL; 3941c42de6dSgd78059 3951c42de6dSgd78059 saf_dip = config->gptwo_nodes->gptwo_nodes[i]; 3961c42de6dSgd78059 3971c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure saf_dip=0x%lx\n", 3981c42de6dSgd78059 saf_dip); 3991c42de6dSgd78059 4001c42de6dSgd78059 if (saf_dip == NULL) { 4011c42de6dSgd78059 GPTWO_DEBUG0(1, CE_CONT, "gptwocfg_unconfigure: " 4021c42de6dSgd78059 "skipping NULLL saf device\n"); 4031c42de6dSgd78059 4041c42de6dSgd78059 continue; 4051c42de6dSgd78059 } 4061c42de6dSgd78059 4071c42de6dSgd78059 config->gptwo_nodes->gptwo_nodes[i] = NULL; 4081c42de6dSgd78059 4091c42de6dSgd78059 if (ops) { 4101c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_configure " 4111c42de6dSgd78059 "ops->gptwocfg_configure=%lx\n", 4121c42de6dSgd78059 ops->gptwocfg_configure); 4131c42de6dSgd78059 4141c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure " 4151c42de6dSgd78059 "ops->gptwocfg_unconfigure=%lx\n", 4161c42de6dSgd78059 ops->gptwocfg_unconfigure); 4171c42de6dSgd78059 4181c42de6dSgd78059 if (ops->gptwocfg_unconfigure != NULL) { 4191c42de6dSgd78059 config->gptwo_nodes->gptwo_nodes[i] = 4201c42de6dSgd78059 ops->gptwocfg_unconfigure(saf_dip); 4211c42de6dSgd78059 4221c42de6dSgd78059 } 4231c42de6dSgd78059 } 4241c42de6dSgd78059 4251c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "e_ddi_branch_destroy <%s>\n", 4261c42de6dSgd78059 ddi_get_name(saf_dip)); 4271c42de6dSgd78059 4281c42de6dSgd78059 ASSERT(e_ddi_branch_held(saf_dip)); 4291c42de6dSgd78059 4301c42de6dSgd78059 /* 4311c42de6dSgd78059 * Don't hold parent busy when calling 4321c42de6dSgd78059 * e_ddi_branch_unconfigure/destroy/referenced() 4331c42de6dSgd78059 */ 4341c42de6dSgd78059 ndi_devi_exit(ap, circ); 4351c42de6dSgd78059 if (e_ddi_branch_destroy(saf_dip, &fdip, 0)) { 4361c42de6dSgd78059 char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 4371c42de6dSgd78059 4381c42de6dSgd78059 /* 4391c42de6dSgd78059 * If non-NULL, fdip is held and must be released. 4401c42de6dSgd78059 */ 4411c42de6dSgd78059 if (fdip != NULL) { 4421c42de6dSgd78059 (void) ddi_pathname(fdip, path); 4431c42de6dSgd78059 ddi_release_devi(fdip); 4441c42de6dSgd78059 } else { 4451c42de6dSgd78059 (void) ddi_pathname(saf_dip, path); 4461c42de6dSgd78059 } 4471c42de6dSgd78059 4481c42de6dSgd78059 cmn_err(CE_WARN, "saf node removal failed: %s (%p)", 4491c42de6dSgd78059 path, fdip ? (void *)fdip : (void *)saf_dip); 4501c42de6dSgd78059 4511c42de6dSgd78059 kmem_free(path, MAXPATHLEN); 4521c42de6dSgd78059 4531c42de6dSgd78059 config->gptwo_nodes->gptwo_nodes[i] = saf_dip; 4541c42de6dSgd78059 failure = 1; 4551c42de6dSgd78059 } 4561c42de6dSgd78059 ndi_devi_enter(ap, &circ); 4571c42de6dSgd78059 } 4581c42de6dSgd78059 4591c42de6dSgd78059 ndi_devi_exit(ap, circ); 4601c42de6dSgd78059 4611c42de6dSgd78059 if (!failure) { 4621c42de6dSgd78059 gptwocfg_free_node_list(config->gptwo_nodes); 4631c42de6dSgd78059 4641c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 4651c42de6dSgd78059 if (gptwo_config_list == config) { 4661c42de6dSgd78059 gptwo_config_list = config->gptwo_next; 4671c42de6dSgd78059 } else { 4681c42de6dSgd78059 temp = gptwo_config_list; 4691c42de6dSgd78059 while (temp->gptwo_next != config) { 4701c42de6dSgd78059 temp = temp->gptwo_next; 4711c42de6dSgd78059 } 4721c42de6dSgd78059 temp->gptwo_next = config->gptwo_next; 4731c42de6dSgd78059 } 4741c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 4751c42de6dSgd78059 4761c42de6dSgd78059 kmem_free(config, sizeof (gptwocfg_config_t)); 4771c42de6dSgd78059 config = NULL; 4781c42de6dSgd78059 } 4791c42de6dSgd78059 4801c42de6dSgd78059 return (config); 4811c42de6dSgd78059 } 4821c42de6dSgd78059 4831c42de6dSgd78059 int 4841c42de6dSgd78059 gptwocfg_next_node(gptwocfg_cookie_t c, dev_info_t *previous, dev_info_t **next) 4851c42de6dSgd78059 { 4861c42de6dSgd78059 gptwocfg_config_t *cookie; 4871c42de6dSgd78059 int i, j; 4881c42de6dSgd78059 4891c42de6dSgd78059 GPTWO_DEBUG3(1, CE_WARN, "gptwocfg_next_node" 4901c42de6dSgd78059 "(c=0x%lx, previous=0x%lx, next=0x%lx)\n", c, previous, next); 4911c42de6dSgd78059 4921c42de6dSgd78059 cookie = (gptwocfg_config_t *)c; 4931c42de6dSgd78059 4941c42de6dSgd78059 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes; i++) { 4951c42de6dSgd78059 GPTWO_DEBUG1(1, CE_WARN, "0x%lx\n", 4961c42de6dSgd78059 cookie->gptwo_nodes->gptwo_nodes[i]); 4971c42de6dSgd78059 } 4981c42de6dSgd78059 4991c42de6dSgd78059 if (previous == NULL) { 5001c42de6dSgd78059 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes; 5011c42de6dSgd78059 i++) { 5021c42de6dSgd78059 if (cookie->gptwo_nodes->gptwo_nodes[i]) { 5031c42de6dSgd78059 *next = cookie->gptwo_nodes->gptwo_nodes[i]; 5041c42de6dSgd78059 GPTWO_DEBUG1(1, CE_WARN, "returned 0x%lx\n", 5051c42de6dSgd78059 *next); 5061c42de6dSgd78059 return (1); 5071c42de6dSgd78059 } 5081c42de6dSgd78059 } 5091c42de6dSgd78059 return (0); 5101c42de6dSgd78059 } 5111c42de6dSgd78059 5121c42de6dSgd78059 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes; i++) { 5131c42de6dSgd78059 if (cookie->gptwo_nodes->gptwo_nodes[i] == previous) { 5141c42de6dSgd78059 for (j = i + 1; 5151c42de6dSgd78059 j < cookie->gptwo_nodes->gptwo_number_of_nodes; 5161c42de6dSgd78059 j++) { 5171c42de6dSgd78059 if (cookie->gptwo_nodes->gptwo_nodes[j]) { 5181c42de6dSgd78059 *next = 5191c42de6dSgd78059 cookie->gptwo_nodes->gptwo_nodes[j]; 5201c42de6dSgd78059 GPTWO_DEBUG1(1, CE_WARN, 5211c42de6dSgd78059 "returned 0x%lx\n", *next); 5221c42de6dSgd78059 return (1); 5231c42de6dSgd78059 } 5241c42de6dSgd78059 } 5251c42de6dSgd78059 *next = NULL; 5261c42de6dSgd78059 GPTWO_DEBUG1(1, CE_WARN, "returned 0x%lx\n", 5271c42de6dSgd78059 *next); 5281c42de6dSgd78059 return (1); 5291c42de6dSgd78059 } 5301c42de6dSgd78059 } 5311c42de6dSgd78059 5321c42de6dSgd78059 /* 5331c42de6dSgd78059 * previous is probably an invalid dev_info. 5341c42de6dSgd78059 */ 5351c42de6dSgd78059 return (0); 5361c42de6dSgd78059 } 5371c42de6dSgd78059 5381c42de6dSgd78059 static gptwo_new_nodes_t * 5391c42de6dSgd78059 gptwocfg_get_obp_created_nodes(dev_info_t *ap, uint_t id) 5401c42de6dSgd78059 { 5411c42de6dSgd78059 gptwo_new_nodes_t *obp_nodes; 5421c42de6dSgd78059 dev_info_t *saf_dev; 5431c42de6dSgd78059 int i = 0, nodes = 0; 5441c42de6dSgd78059 int circular_count; 5451c42de6dSgd78059 5461c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_get_obp_created_nodes - ap=0x%lx " 5471c42de6dSgd78059 "id=0x%x\n", ap, id); 5481c42de6dSgd78059 5491c42de6dSgd78059 ndi_devi_enter(ap, &circular_count); 5501c42de6dSgd78059 5511c42de6dSgd78059 /* 5521c42de6dSgd78059 * First go through all the children of the attachment point 5531c42de6dSgd78059 * to count matching safari agent ids 5541c42de6dSgd78059 */ 5551c42de6dSgd78059 saf_dev = ddi_get_child(ap); 5561c42de6dSgd78059 while (saf_dev != NULL) { 5571c42de6dSgd78059 if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, DDI_PROP_DONTPASS, 5581c42de6dSgd78059 "portid", -1) == id) { 5591c42de6dSgd78059 if (&starcat_dr_name) { 5601c42de6dSgd78059 if (starcat_dr_name(ddi_node_name(saf_dev)) 5611c42de6dSgd78059 < 0) { 5621c42de6dSgd78059 saf_dev = ddi_get_next_sibling(saf_dev); 5631c42de6dSgd78059 continue; 5641c42de6dSgd78059 } 5651c42de6dSgd78059 } 5661c42de6dSgd78059 nodes++; 5671c42de6dSgd78059 } 5681c42de6dSgd78059 saf_dev = ddi_get_next_sibling(saf_dev); 5691c42de6dSgd78059 } 5701c42de6dSgd78059 5711c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_obp_created_nodes - %d nodes " 5721c42de6dSgd78059 "found\n", nodes); 5731c42de6dSgd78059 5741c42de6dSgd78059 obp_nodes = gptwocfg_allocate_node_list(nodes); 5751c42de6dSgd78059 5761c42de6dSgd78059 /* 5771c42de6dSgd78059 * Then fill in the nodes structure. 5781c42de6dSgd78059 */ 5791c42de6dSgd78059 saf_dev = ddi_get_child(ap); 5801c42de6dSgd78059 while ((saf_dev != NULL) && (i < nodes)) { 5811c42de6dSgd78059 if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, DDI_PROP_DONTPASS, 5821c42de6dSgd78059 "portid", -1) == id) { 5831c42de6dSgd78059 if (&starcat_dr_name) { 5841c42de6dSgd78059 if (starcat_dr_name(ddi_node_name(saf_dev)) 5851c42de6dSgd78059 < 0) { 5861c42de6dSgd78059 saf_dev = ddi_get_next_sibling(saf_dev); 5871c42de6dSgd78059 continue; 5881c42de6dSgd78059 } 5891c42de6dSgd78059 } 5901c42de6dSgd78059 /* 5911c42de6dSgd78059 * Branch rooted at this dip must have been 5921c42de6dSgd78059 * held by the DR driver. 5931c42de6dSgd78059 */ 5941c42de6dSgd78059 ASSERT(e_ddi_branch_held(saf_dev)); 5951c42de6dSgd78059 obp_nodes->gptwo_nodes[i++] = saf_dev; 5961c42de6dSgd78059 } 5971c42de6dSgd78059 saf_dev = ddi_get_next_sibling(saf_dev); 5981c42de6dSgd78059 } 5991c42de6dSgd78059 6001c42de6dSgd78059 ndi_devi_exit(ap, circular_count); 6011c42de6dSgd78059 6021c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_obp_created_nodes - " 6031c42de6dSgd78059 "Returning 0x%lx\n", obp_nodes); 6041c42de6dSgd78059 6051c42de6dSgd78059 return (obp_nodes); 6061c42de6dSgd78059 } 6071c42de6dSgd78059 6081c42de6dSgd78059 void 6091c42de6dSgd78059 gptwocfg_save_handle(dev_info_t *dip, fco_handle_t fco_handle) 6101c42de6dSgd78059 { 6111c42de6dSgd78059 gptwocfg_handle_list_t *h; 6121c42de6dSgd78059 6131c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_save_handle - " 6141c42de6dSgd78059 "dip=%lx fco_handle=%lx\n", dip, fco_handle); 6151c42de6dSgd78059 6161c42de6dSgd78059 h = kmem_zalloc(sizeof (gptwocfg_handle_list_t), KM_SLEEP); 6171c42de6dSgd78059 6181c42de6dSgd78059 mutex_enter(&gptwo_handle_list_lock); 6191c42de6dSgd78059 6201c42de6dSgd78059 h->next = gptwocfg_handle_list; 6211c42de6dSgd78059 h->dip = dip; 6221c42de6dSgd78059 h->fco_handle = fco_handle; 6231c42de6dSgd78059 gptwocfg_handle_list = h; 6241c42de6dSgd78059 6251c42de6dSgd78059 mutex_exit(&gptwo_handle_list_lock); 6261c42de6dSgd78059 } 6271c42de6dSgd78059 6281c42de6dSgd78059 fco_handle_t 6291c42de6dSgd78059 gptwocfg_get_handle(dev_info_t *dip) 6301c42de6dSgd78059 { 6311c42de6dSgd78059 gptwocfg_handle_list_t *h, *last; 6321c42de6dSgd78059 fco_handle_t fco_handle; 6331c42de6dSgd78059 6341c42de6dSgd78059 mutex_enter(&gptwo_handle_list_lock); 6351c42de6dSgd78059 6361c42de6dSgd78059 h = last = gptwocfg_handle_list; 6371c42de6dSgd78059 6381c42de6dSgd78059 while (h != NULL) { 6391c42de6dSgd78059 if (h->dip == dip) { 6401c42de6dSgd78059 if (h == gptwocfg_handle_list) 6411c42de6dSgd78059 gptwocfg_handle_list = h->next; 6421c42de6dSgd78059 else 6431c42de6dSgd78059 last->next = h->next; 6441c42de6dSgd78059 6451c42de6dSgd78059 mutex_exit(&gptwo_handle_list_lock); 6461c42de6dSgd78059 6471c42de6dSgd78059 fco_handle = h->fco_handle; 6481c42de6dSgd78059 6491c42de6dSgd78059 kmem_free(h, sizeof (gptwocfg_handle_list_t)); 6501c42de6dSgd78059 6511c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_get_handle - " 6521c42de6dSgd78059 "dip=%lx fco_handle=%lx\n", dip, fco_handle); 6531c42de6dSgd78059 6541c42de6dSgd78059 return (fco_handle); 6551c42de6dSgd78059 } 6561c42de6dSgd78059 last = h; 6571c42de6dSgd78059 h = h->next; 6581c42de6dSgd78059 } 6591c42de6dSgd78059 6601c42de6dSgd78059 mutex_exit(&gptwo_handle_list_lock); 6611c42de6dSgd78059 6621c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_handle - dip=%lx NO HANDLE\n", 6631c42de6dSgd78059 dip); 6641c42de6dSgd78059 6651c42de6dSgd78059 return (0); 6661c42de6dSgd78059 } 6671c42de6dSgd78059 6681c42de6dSgd78059 void 6691c42de6dSgd78059 gptwocfg_devi_attach_to_parent(dev_info_t *dip) 6701c42de6dSgd78059 { 6711c42de6dSgd78059 (void) i_ndi_config_node(dip, DS_LINKED, 0); 6721c42de6dSgd78059 } 6731c42de6dSgd78059 6741c42de6dSgd78059 #ifdef DEBUG 6751c42de6dSgd78059 static void 6761c42de6dSgd78059 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3, 6771c42de6dSgd78059 uintptr_t a4, uintptr_t a5) 6781c42de6dSgd78059 { 6791c42de6dSgd78059 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5); 6801c42de6dSgd78059 } 6811c42de6dSgd78059 #endif 682