1*1c42de6dSgd78059 /* 2*1c42de6dSgd78059 * CDDL HEADER START 3*1c42de6dSgd78059 * 4*1c42de6dSgd78059 * The contents of this file are subject to the terms of the 5*1c42de6dSgd78059 * Common Development and Distribution License (the "License"). 6*1c42de6dSgd78059 * You may not use this file except in compliance with the License. 7*1c42de6dSgd78059 * 8*1c42de6dSgd78059 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1c42de6dSgd78059 * or http://www.opensolaris.org/os/licensing. 10*1c42de6dSgd78059 * See the License for the specific language governing permissions 11*1c42de6dSgd78059 * and limitations under the License. 12*1c42de6dSgd78059 * 13*1c42de6dSgd78059 * When distributing Covered Code, include this CDDL HEADER in each 14*1c42de6dSgd78059 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1c42de6dSgd78059 * If applicable, add the following below this CDDL HEADER, with the 16*1c42de6dSgd78059 * fields enclosed by brackets "[]" replaced with your own identifying 17*1c42de6dSgd78059 * information: Portions Copyright [yyyy] [name of copyright owner] 18*1c42de6dSgd78059 * 19*1c42de6dSgd78059 * CDDL HEADER END 20*1c42de6dSgd78059 */ 21*1c42de6dSgd78059 /* 22*1c42de6dSgd78059 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 23*1c42de6dSgd78059 * Use is subject to license terms. 24*1c42de6dSgd78059 */ 25*1c42de6dSgd78059 26*1c42de6dSgd78059 #pragma ident "%Z%%M% %I% %E% SMI" 27*1c42de6dSgd78059 28*1c42de6dSgd78059 /* 29*1c42de6dSgd78059 * Safari Configurator (gptwocfg) 30*1c42de6dSgd78059 * 31*1c42de6dSgd78059 */ 32*1c42de6dSgd78059 33*1c42de6dSgd78059 #include <sys/types.h> 34*1c42de6dSgd78059 #include <sys/cred.h> 35*1c42de6dSgd78059 #include <sys/mman.h> 36*1c42de6dSgd78059 #include <sys/kmem.h> 37*1c42de6dSgd78059 #include <sys/conf.h> 38*1c42de6dSgd78059 #include <sys/cmn_err.h> 39*1c42de6dSgd78059 #include <sys/ddi.h> 40*1c42de6dSgd78059 #include <sys/sunddi.h> 41*1c42de6dSgd78059 #include <sys/sunndi.h> 42*1c42de6dSgd78059 #include <sys/modctl.h> 43*1c42de6dSgd78059 #include <sys/stat.h> 44*1c42de6dSgd78059 #include <sys/param.h> 45*1c42de6dSgd78059 #include <sys/autoconf.h> 46*1c42de6dSgd78059 #include <sys/ksynch.h> 47*1c42de6dSgd78059 #include <sys/promif.h> 48*1c42de6dSgd78059 #include <sys/ndi_impldefs.h> 49*1c42de6dSgd78059 #include <sys/ddi_impldefs.h> 50*1c42de6dSgd78059 #include <sys/gp2cfg.h> 51*1c42de6dSgd78059 #include <sys/machsystm.h> 52*1c42de6dSgd78059 #include <sys/platform_module.h> 53*1c42de6dSgd78059 #pragma weak starcat_dr_name 54*1c42de6dSgd78059 55*1c42de6dSgd78059 #ifdef DEBUG 56*1c42de6dSgd78059 int gptwocfg_debug = 0; 57*1c42de6dSgd78059 58*1c42de6dSgd78059 static void debug(char *, uintptr_t, uintptr_t, 59*1c42de6dSgd78059 uintptr_t, uintptr_t, uintptr_t); 60*1c42de6dSgd78059 61*1c42de6dSgd78059 #define GPTWO_DEBUG0(level, flag, s) if (gptwocfg_debug >= level) \ 62*1c42de6dSgd78059 cmn_err(flag, s) 63*1c42de6dSgd78059 #define GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwocfg_debug >= level) \ 64*1c42de6dSgd78059 debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0); 65*1c42de6dSgd78059 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwocfg_debug >= level) \ 66*1c42de6dSgd78059 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0); 67*1c42de6dSgd78059 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \ 68*1c42de6dSgd78059 if (gptwocfg_debug >= level) \ 69*1c42de6dSgd78059 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0); 70*1c42de6dSgd78059 #else 71*1c42de6dSgd78059 #define GPTWO_DEBUG0(level, flag, s) 72*1c42de6dSgd78059 #define GPTWO_DEBUG1(level, flag, fmt, a1) 73*1c42de6dSgd78059 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) 74*1c42de6dSgd78059 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) 75*1c42de6dSgd78059 #endif 76*1c42de6dSgd78059 77*1c42de6dSgd78059 kmutex_t gptwo_handle_list_lock; 78*1c42de6dSgd78059 gptwocfg_handle_list_t *gptwocfg_handle_list; 79*1c42de6dSgd78059 80*1c42de6dSgd78059 static kmutex_t gptwo_config_list_lock; 81*1c42de6dSgd78059 static gptwocfg_config_t *gptwo_config_list; 82*1c42de6dSgd78059 83*1c42de6dSgd78059 static gptwo_new_nodes_t * 84*1c42de6dSgd78059 gptwocfg_get_obp_created_nodes(dev_info_t *, uint_t); 85*1c42de6dSgd78059 86*1c42de6dSgd78059 void (*gptwocfg_unclaim_address)(uint_t); 87*1c42de6dSgd78059 88*1c42de6dSgd78059 extern caddr_t efcode_vaddr; 89*1c42de6dSgd78059 extern int efcode_size; 90*1c42de6dSgd78059 91*1c42de6dSgd78059 #define GPTWO_NUMBER_OF_DEVICE_TYPES 6 92*1c42de6dSgd78059 93*1c42de6dSgd78059 static kmutex_t gptwocfg_ops_table_lock; 94*1c42de6dSgd78059 gptwocfg_ops_t *gptwocfg_ops_table[GPTWO_NUMBER_OF_DEVICE_TYPES]; 95*1c42de6dSgd78059 96*1c42de6dSgd78059 /* 97*1c42de6dSgd78059 * Module linkage information for the kernel. 98*1c42de6dSgd78059 */ 99*1c42de6dSgd78059 100*1c42de6dSgd78059 extern struct mod_ops mod_miscops; 101*1c42de6dSgd78059 102*1c42de6dSgd78059 static struct modlmisc modlmisc = { 103*1c42de6dSgd78059 &mod_miscops, /* Type of module */ 104*1c42de6dSgd78059 "gptwo configurator %I%", 105*1c42de6dSgd78059 }; 106*1c42de6dSgd78059 107*1c42de6dSgd78059 static struct modlinkage modlinkage = { 108*1c42de6dSgd78059 MODREV_1, (void *)&modlmisc, NULL 109*1c42de6dSgd78059 }; 110*1c42de6dSgd78059 111*1c42de6dSgd78059 int 112*1c42de6dSgd78059 _init(void) 113*1c42de6dSgd78059 { 114*1c42de6dSgd78059 unsigned int i; 115*1c42de6dSgd78059 116*1c42de6dSgd78059 GPTWO_DEBUG0(1, CE_WARN, "gptwocfg (Safari Configurator) " 117*1c42de6dSgd78059 "has been loaded\n"); 118*1c42de6dSgd78059 119*1c42de6dSgd78059 mutex_init(&gptwo_config_list_lock, NULL, MUTEX_DRIVER, NULL); 120*1c42de6dSgd78059 mutex_init(&gptwocfg_ops_table_lock, NULL, MUTEX_DRIVER, NULL); 121*1c42de6dSgd78059 gptwo_config_list = NULL; 122*1c42de6dSgd78059 123*1c42de6dSgd78059 mutex_init(&gptwo_handle_list_lock, NULL, MUTEX_DRIVER, NULL); 124*1c42de6dSgd78059 gptwocfg_handle_list = NULL; 125*1c42de6dSgd78059 126*1c42de6dSgd78059 for (i = 0; i < GPTWO_NUMBER_OF_DEVICE_TYPES; i++) 127*1c42de6dSgd78059 gptwocfg_ops_table[i] = NULL; 128*1c42de6dSgd78059 129*1c42de6dSgd78059 return (mod_install(&modlinkage)); 130*1c42de6dSgd78059 } 131*1c42de6dSgd78059 132*1c42de6dSgd78059 int 133*1c42de6dSgd78059 _fini(void) 134*1c42de6dSgd78059 { 135*1c42de6dSgd78059 int error; 136*1c42de6dSgd78059 137*1c42de6dSgd78059 error = mod_remove(&modlinkage); 138*1c42de6dSgd78059 if (error != 0) { 139*1c42de6dSgd78059 return (error); 140*1c42de6dSgd78059 } 141*1c42de6dSgd78059 mutex_destroy(&gptwo_config_list_lock); 142*1c42de6dSgd78059 mutex_destroy(&gptwocfg_ops_table_lock); 143*1c42de6dSgd78059 mutex_destroy(&gptwo_handle_list_lock); 144*1c42de6dSgd78059 145*1c42de6dSgd78059 return (0); 146*1c42de6dSgd78059 } 147*1c42de6dSgd78059 148*1c42de6dSgd78059 int 149*1c42de6dSgd78059 _info(modinfop) 150*1c42de6dSgd78059 struct modinfo *modinfop; 151*1c42de6dSgd78059 { 152*1c42de6dSgd78059 return (mod_info(&modlinkage, modinfop)); 153*1c42de6dSgd78059 } 154*1c42de6dSgd78059 155*1c42de6dSgd78059 gptwo_new_nodes_t * 156*1c42de6dSgd78059 gptwocfg_allocate_node_list(int number_of_nodes) 157*1c42de6dSgd78059 { 158*1c42de6dSgd78059 gptwo_new_nodes_t *gptwo_new_nodes; 159*1c42de6dSgd78059 int size; 160*1c42de6dSgd78059 161*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_allocate_node_list- %d nodes", 162*1c42de6dSgd78059 number_of_nodes); 163*1c42de6dSgd78059 164*1c42de6dSgd78059 size = sizeof (gptwo_new_nodes_t) + 165*1c42de6dSgd78059 ((number_of_nodes -1) * sizeof (dev_info_t *)); 166*1c42de6dSgd78059 167*1c42de6dSgd78059 gptwo_new_nodes = kmem_zalloc(size, KM_SLEEP); 168*1c42de6dSgd78059 169*1c42de6dSgd78059 gptwo_new_nodes->gptwo_number_of_nodes = number_of_nodes; 170*1c42de6dSgd78059 gptwo_new_nodes->gptwo_version = GP2_VERSION; 171*1c42de6dSgd78059 172*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_allocate_node_list- returned %p\n", 173*1c42de6dSgd78059 gptwo_new_nodes); 174*1c42de6dSgd78059 175*1c42de6dSgd78059 return (gptwo_new_nodes); 176*1c42de6dSgd78059 } 177*1c42de6dSgd78059 178*1c42de6dSgd78059 void 179*1c42de6dSgd78059 gptwocfg_free_node_list(gptwo_new_nodes_t *gptwo_new_nodes) 180*1c42de6dSgd78059 { 181*1c42de6dSgd78059 int size; 182*1c42de6dSgd78059 183*1c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_free_node_list- %p %d nodes", 184*1c42de6dSgd78059 gptwo_new_nodes, gptwo_new_nodes->gptwo_number_of_nodes); 185*1c42de6dSgd78059 186*1c42de6dSgd78059 size = sizeof (gptwo_new_nodes_t) + 187*1c42de6dSgd78059 ((gptwo_new_nodes->gptwo_number_of_nodes - 1) * 188*1c42de6dSgd78059 sizeof (dev_info_t *)); 189*1c42de6dSgd78059 190*1c42de6dSgd78059 kmem_free(gptwo_new_nodes, size); 191*1c42de6dSgd78059 } 192*1c42de6dSgd78059 193*1c42de6dSgd78059 void 194*1c42de6dSgd78059 gptwocfg_register_ops(uint_t type, gptwo_cfgfunc_t *cfg_func, 195*1c42de6dSgd78059 gptwo_uncfgfunc_t *uncfg_func) 196*1c42de6dSgd78059 { 197*1c42de6dSgd78059 /* KM_SLEEP guarantees success */ 198*1c42de6dSgd78059 gptwocfg_ops_t *ops = kmem_zalloc(sizeof (gptwocfg_ops_t), KM_SLEEP); 199*1c42de6dSgd78059 200*1c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_register_ops: type=%x ops=%lx\n", 201*1c42de6dSgd78059 type, ops); 202*1c42de6dSgd78059 ASSERT(type < GPTWO_NUMBER_OF_DEVICE_TYPES); 203*1c42de6dSgd78059 ops->gptwocfg_type = type; 204*1c42de6dSgd78059 ops->gptwocfg_version = GPTWOCFG_OPS_VERSION; 205*1c42de6dSgd78059 ops->gptwocfg_configure = cfg_func; 206*1c42de6dSgd78059 ops->gptwocfg_unconfigure = uncfg_func; 207*1c42de6dSgd78059 208*1c42de6dSgd78059 mutex_enter(&gptwocfg_ops_table_lock); 209*1c42de6dSgd78059 gptwocfg_ops_table[type] = ops; 210*1c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 211*1c42de6dSgd78059 } 212*1c42de6dSgd78059 213*1c42de6dSgd78059 214*1c42de6dSgd78059 215*1c42de6dSgd78059 void 216*1c42de6dSgd78059 gptwocfg_unregister_ops(uint_t type) 217*1c42de6dSgd78059 { 218*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unregister_ops: type=%x\n", type); 219*1c42de6dSgd78059 220*1c42de6dSgd78059 ASSERT(type < GPTWO_NUMBER_OF_DEVICE_TYPES); 221*1c42de6dSgd78059 222*1c42de6dSgd78059 mutex_enter(&gptwocfg_ops_table_lock); 223*1c42de6dSgd78059 kmem_free(gptwocfg_ops_table[type], sizeof (gptwocfg_ops_t)); 224*1c42de6dSgd78059 gptwocfg_ops_table[type] = NULL; 225*1c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 226*1c42de6dSgd78059 } 227*1c42de6dSgd78059 228*1c42de6dSgd78059 gptwocfg_cookie_t 229*1c42de6dSgd78059 gptwocfg_configure(dev_info_t *ap, spcd_t *pcd, gptwo_aid_t id) 230*1c42de6dSgd78059 { 231*1c42de6dSgd78059 gptwo_new_nodes_t *new_nodes = NULL; 232*1c42de6dSgd78059 gptwocfg_config_t *config; 233*1c42de6dSgd78059 gptwocfg_ops_t *ops; 234*1c42de6dSgd78059 235*1c42de6dSgd78059 GPTWO_DEBUG3(1, CE_CONT, "gptwocfg_configure: ap=0x%p pcd=%p id=%x\n", 236*1c42de6dSgd78059 ap, pcd, id); 237*1c42de6dSgd78059 238*1c42de6dSgd78059 /* 239*1c42de6dSgd78059 * Look to see if the port is already configured. 240*1c42de6dSgd78059 */ 241*1c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 242*1c42de6dSgd78059 config = gptwo_config_list; 243*1c42de6dSgd78059 while (config != NULL) { 244*1c42de6dSgd78059 if (&starcat_dr_name) { 245*1c42de6dSgd78059 if (starcat_dr_name(ddi_node_name(ap)) < 0) { 246*1c42de6dSgd78059 config = config->gptwo_next; 247*1c42de6dSgd78059 continue; 248*1c42de6dSgd78059 } 249*1c42de6dSgd78059 } 250*1c42de6dSgd78059 if (config->gptwo_portid == id) { 251*1c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: gptwocfg_configure: " 252*1c42de6dSgd78059 "0x%x Port already configured\n", id); 253*1c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 254*1c42de6dSgd78059 return (NULL); 255*1c42de6dSgd78059 } 256*1c42de6dSgd78059 config = config->gptwo_next; 257*1c42de6dSgd78059 } 258*1c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 259*1c42de6dSgd78059 260*1c42de6dSgd78059 if (pcd == NULL) { 261*1c42de6dSgd78059 GPTWO_DEBUG0(1, CE_CONT, "gptwocfg_configure: pcd=NULL\n"); 262*1c42de6dSgd78059 return (NULL); 263*1c42de6dSgd78059 } 264*1c42de6dSgd78059 265*1c42de6dSgd78059 if ((pcd->spcd_magic != PCD_MAGIC) || 266*1c42de6dSgd78059 (pcd->spcd_version != PCD_VERSION)) { 267*1c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: Invalid Port " 268*1c42de6dSgd78059 "Configuration Descriptor\n"); 269*1c42de6dSgd78059 return (NULL); 270*1c42de6dSgd78059 } 271*1c42de6dSgd78059 272*1c42de6dSgd78059 if (pcd->spcd_ptype >= GPTWO_NUMBER_OF_DEVICE_TYPES) { 273*1c42de6dSgd78059 cmn_err(CE_WARN, 274*1c42de6dSgd78059 "gptwocfg: Invalid device type %x", pcd->spcd_ptype); 275*1c42de6dSgd78059 return (NULL); 276*1c42de6dSgd78059 } 277*1c42de6dSgd78059 278*1c42de6dSgd78059 if (pcd->spcd_prsv != SPCD_RSV_PASS) { 279*1c42de6dSgd78059 cmn_err(CE_WARN, 280*1c42de6dSgd78059 "gptwocfg: Agent at ID %x has not passed test(s)\n", id); 281*1c42de6dSgd78059 return (NULL); 282*1c42de6dSgd78059 } 283*1c42de6dSgd78059 284*1c42de6dSgd78059 mutex_enter(&gptwocfg_ops_table_lock); 285*1c42de6dSgd78059 286*1c42de6dSgd78059 ops = gptwocfg_ops_table[pcd->spcd_ptype]; 287*1c42de6dSgd78059 288*1c42de6dSgd78059 if (ops == NULL) { 289*1c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: Ops for type %x have not been " 290*1c42de6dSgd78059 "registered\n", pcd->spcd_ptype); 291*1c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 292*1c42de6dSgd78059 return (NULL); 293*1c42de6dSgd78059 } 294*1c42de6dSgd78059 295*1c42de6dSgd78059 if (ops->gptwocfg_configure == NULL) { 296*1c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: no configure routine registered " 297*1c42de6dSgd78059 "for sfaari type %x\n", pcd->spcd_ptype); 298*1c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 299*1c42de6dSgd78059 return (NULL); 300*1c42de6dSgd78059 } 301*1c42de6dSgd78059 302*1c42de6dSgd78059 new_nodes = ops->gptwocfg_configure(ap, pcd, id); 303*1c42de6dSgd78059 304*1c42de6dSgd78059 mutex_exit(&gptwocfg_ops_table_lock); 305*1c42de6dSgd78059 306*1c42de6dSgd78059 if (new_nodes != NULL) { 307*1c42de6dSgd78059 config = kmem_zalloc(sizeof (gptwocfg_config_t), KM_SLEEP); 308*1c42de6dSgd78059 config->gptwo_version = GP2_VERSION; 309*1c42de6dSgd78059 config->gptwo_ap = ap; 310*1c42de6dSgd78059 config->gptwo_portid = id; 311*1c42de6dSgd78059 config->gptwo_nodes = new_nodes; 312*1c42de6dSgd78059 config->gptwo_ops = ops; 313*1c42de6dSgd78059 314*1c42de6dSgd78059 /* 315*1c42de6dSgd78059 * put config on config list 316*1c42de6dSgd78059 */ 317*1c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 318*1c42de6dSgd78059 config->gptwo_next = gptwo_config_list; 319*1c42de6dSgd78059 gptwo_config_list = config; 320*1c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 321*1c42de6dSgd78059 } else { 322*1c42de6dSgd78059 config = NULL; 323*1c42de6dSgd78059 } 324*1c42de6dSgd78059 325*1c42de6dSgd78059 return ((gptwocfg_cookie_t)config); 326*1c42de6dSgd78059 } 327*1c42de6dSgd78059 328*1c42de6dSgd78059 gptwocfg_cookie_t 329*1c42de6dSgd78059 gptwocfg_unconfigure(dev_info_t *ap, gptwo_aid_t id) 330*1c42de6dSgd78059 { 331*1c42de6dSgd78059 int i, circ; 332*1c42de6dSgd78059 int failure = 0; 333*1c42de6dSgd78059 dev_info_t *saf_dip; 334*1c42de6dSgd78059 gptwocfg_config_t *config, *temp; 335*1c42de6dSgd78059 gptwo_new_nodes_t *obp_nodes; 336*1c42de6dSgd78059 gptwocfg_ops_t *ops; 337*1c42de6dSgd78059 338*1c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_unconfigure: ap=0x%p id=0x%lx\n", 339*1c42de6dSgd78059 ap, id); 340*1c42de6dSgd78059 341*1c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 342*1c42de6dSgd78059 config = gptwo_config_list; 343*1c42de6dSgd78059 while (config != NULL) { 344*1c42de6dSgd78059 if (config->gptwo_portid == id) { 345*1c42de6dSgd78059 break; 346*1c42de6dSgd78059 } 347*1c42de6dSgd78059 config = config->gptwo_next; 348*1c42de6dSgd78059 } 349*1c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 350*1c42de6dSgd78059 351*1c42de6dSgd78059 if (config == NULL) { 352*1c42de6dSgd78059 /* 353*1c42de6dSgd78059 * There is no config structure associated with this agent id 354*1c42de6dSgd78059 * so it was probably built by firmware at start of day. We 355*1c42de6dSgd78059 * need to create a config structure before we can continue. 356*1c42de6dSgd78059 */ 357*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure: id=0x%lx " 358*1c42de6dSgd78059 "No config structure - Need to build one\n", id); 359*1c42de6dSgd78059 360*1c42de6dSgd78059 obp_nodes = gptwocfg_get_obp_created_nodes(ap, id); 361*1c42de6dSgd78059 362*1c42de6dSgd78059 if (obp_nodes != NULL) { 363*1c42de6dSgd78059 config = kmem_zalloc(sizeof (gptwocfg_config_t), 364*1c42de6dSgd78059 KM_SLEEP); 365*1c42de6dSgd78059 config->gptwo_version = GP2_VERSION; 366*1c42de6dSgd78059 config->gptwo_ap = ap; 367*1c42de6dSgd78059 config->gptwo_portid = id; 368*1c42de6dSgd78059 config->gptwo_nodes = obp_nodes; 369*1c42de6dSgd78059 370*1c42de6dSgd78059 /* 371*1c42de6dSgd78059 * put config on config list 372*1c42de6dSgd78059 */ 373*1c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 374*1c42de6dSgd78059 config->gptwo_next = gptwo_config_list; 375*1c42de6dSgd78059 gptwo_config_list = config; 376*1c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 377*1c42de6dSgd78059 } else { 378*1c42de6dSgd78059 cmn_err(CE_WARN, "gptwocfg: gptwocfg_unconfigure: " 379*1c42de6dSgd78059 "No OBP created nodes for ap=0x%lx agent id=0x%x", 380*1c42de6dSgd78059 (long)ap, id); 381*1c42de6dSgd78059 return (NULL); 382*1c42de6dSgd78059 } 383*1c42de6dSgd78059 } 384*1c42de6dSgd78059 385*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure config=0x%lx\n", 386*1c42de6dSgd78059 config); 387*1c42de6dSgd78059 388*1c42de6dSgd78059 ops = config->gptwo_ops; 389*1c42de6dSgd78059 390*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure: ops=%lx\n", ops); 391*1c42de6dSgd78059 392*1c42de6dSgd78059 ndi_devi_enter(ap, &circ); 393*1c42de6dSgd78059 394*1c42de6dSgd78059 for (i = 0; i < config->gptwo_nodes->gptwo_number_of_nodes; i++) { 395*1c42de6dSgd78059 dev_info_t *fdip = NULL; 396*1c42de6dSgd78059 397*1c42de6dSgd78059 saf_dip = config->gptwo_nodes->gptwo_nodes[i]; 398*1c42de6dSgd78059 399*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure saf_dip=0x%lx\n", 400*1c42de6dSgd78059 saf_dip); 401*1c42de6dSgd78059 402*1c42de6dSgd78059 if (saf_dip == NULL) { 403*1c42de6dSgd78059 GPTWO_DEBUG0(1, CE_CONT, "gptwocfg_unconfigure: " 404*1c42de6dSgd78059 "skipping NULLL saf device\n"); 405*1c42de6dSgd78059 406*1c42de6dSgd78059 continue; 407*1c42de6dSgd78059 } 408*1c42de6dSgd78059 409*1c42de6dSgd78059 config->gptwo_nodes->gptwo_nodes[i] = NULL; 410*1c42de6dSgd78059 411*1c42de6dSgd78059 if (ops) { 412*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_configure " 413*1c42de6dSgd78059 "ops->gptwocfg_configure=%lx\n", 414*1c42de6dSgd78059 ops->gptwocfg_configure); 415*1c42de6dSgd78059 416*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure " 417*1c42de6dSgd78059 "ops->gptwocfg_unconfigure=%lx\n", 418*1c42de6dSgd78059 ops->gptwocfg_unconfigure); 419*1c42de6dSgd78059 420*1c42de6dSgd78059 if (ops->gptwocfg_unconfigure != NULL) { 421*1c42de6dSgd78059 config->gptwo_nodes->gptwo_nodes[i] = 422*1c42de6dSgd78059 ops->gptwocfg_unconfigure(saf_dip); 423*1c42de6dSgd78059 424*1c42de6dSgd78059 } 425*1c42de6dSgd78059 } 426*1c42de6dSgd78059 427*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "e_ddi_branch_destroy <%s>\n", 428*1c42de6dSgd78059 ddi_get_name(saf_dip)); 429*1c42de6dSgd78059 430*1c42de6dSgd78059 ASSERT(e_ddi_branch_held(saf_dip)); 431*1c42de6dSgd78059 432*1c42de6dSgd78059 /* 433*1c42de6dSgd78059 * Don't hold parent busy when calling 434*1c42de6dSgd78059 * e_ddi_branch_unconfigure/destroy/referenced() 435*1c42de6dSgd78059 */ 436*1c42de6dSgd78059 ndi_devi_exit(ap, circ); 437*1c42de6dSgd78059 if (e_ddi_branch_destroy(saf_dip, &fdip, 0)) { 438*1c42de6dSgd78059 char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 439*1c42de6dSgd78059 440*1c42de6dSgd78059 /* 441*1c42de6dSgd78059 * If non-NULL, fdip is held and must be released. 442*1c42de6dSgd78059 */ 443*1c42de6dSgd78059 if (fdip != NULL) { 444*1c42de6dSgd78059 (void) ddi_pathname(fdip, path); 445*1c42de6dSgd78059 ddi_release_devi(fdip); 446*1c42de6dSgd78059 } else { 447*1c42de6dSgd78059 (void) ddi_pathname(saf_dip, path); 448*1c42de6dSgd78059 } 449*1c42de6dSgd78059 450*1c42de6dSgd78059 cmn_err(CE_WARN, "saf node removal failed: %s (%p)", 451*1c42de6dSgd78059 path, fdip ? (void *)fdip : (void *)saf_dip); 452*1c42de6dSgd78059 453*1c42de6dSgd78059 kmem_free(path, MAXPATHLEN); 454*1c42de6dSgd78059 455*1c42de6dSgd78059 config->gptwo_nodes->gptwo_nodes[i] = saf_dip; 456*1c42de6dSgd78059 failure = 1; 457*1c42de6dSgd78059 } 458*1c42de6dSgd78059 ndi_devi_enter(ap, &circ); 459*1c42de6dSgd78059 } 460*1c42de6dSgd78059 461*1c42de6dSgd78059 ndi_devi_exit(ap, circ); 462*1c42de6dSgd78059 463*1c42de6dSgd78059 if (!failure) { 464*1c42de6dSgd78059 gptwocfg_free_node_list(config->gptwo_nodes); 465*1c42de6dSgd78059 466*1c42de6dSgd78059 mutex_enter(&gptwo_config_list_lock); 467*1c42de6dSgd78059 if (gptwo_config_list == config) { 468*1c42de6dSgd78059 gptwo_config_list = config->gptwo_next; 469*1c42de6dSgd78059 } else { 470*1c42de6dSgd78059 temp = gptwo_config_list; 471*1c42de6dSgd78059 while (temp->gptwo_next != config) { 472*1c42de6dSgd78059 temp = temp->gptwo_next; 473*1c42de6dSgd78059 } 474*1c42de6dSgd78059 temp->gptwo_next = config->gptwo_next; 475*1c42de6dSgd78059 } 476*1c42de6dSgd78059 mutex_exit(&gptwo_config_list_lock); 477*1c42de6dSgd78059 478*1c42de6dSgd78059 kmem_free(config, sizeof (gptwocfg_config_t)); 479*1c42de6dSgd78059 config = NULL; 480*1c42de6dSgd78059 } 481*1c42de6dSgd78059 482*1c42de6dSgd78059 return (config); 483*1c42de6dSgd78059 } 484*1c42de6dSgd78059 485*1c42de6dSgd78059 int 486*1c42de6dSgd78059 gptwocfg_next_node(gptwocfg_cookie_t c, dev_info_t *previous, dev_info_t **next) 487*1c42de6dSgd78059 { 488*1c42de6dSgd78059 gptwocfg_config_t *cookie; 489*1c42de6dSgd78059 int i, j; 490*1c42de6dSgd78059 491*1c42de6dSgd78059 GPTWO_DEBUG3(1, CE_WARN, "gptwocfg_next_node" 492*1c42de6dSgd78059 "(c=0x%lx, previous=0x%lx, next=0x%lx)\n", c, previous, next); 493*1c42de6dSgd78059 494*1c42de6dSgd78059 cookie = (gptwocfg_config_t *)c; 495*1c42de6dSgd78059 496*1c42de6dSgd78059 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes; i++) { 497*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_WARN, "0x%lx\n", 498*1c42de6dSgd78059 cookie->gptwo_nodes->gptwo_nodes[i]); 499*1c42de6dSgd78059 } 500*1c42de6dSgd78059 501*1c42de6dSgd78059 if (previous == NULL) { 502*1c42de6dSgd78059 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes; 503*1c42de6dSgd78059 i++) { 504*1c42de6dSgd78059 if (cookie->gptwo_nodes->gptwo_nodes[i]) { 505*1c42de6dSgd78059 *next = cookie->gptwo_nodes->gptwo_nodes[i]; 506*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_WARN, "returned 0x%lx\n", 507*1c42de6dSgd78059 *next); 508*1c42de6dSgd78059 return (1); 509*1c42de6dSgd78059 } 510*1c42de6dSgd78059 } 511*1c42de6dSgd78059 return (0); 512*1c42de6dSgd78059 } 513*1c42de6dSgd78059 514*1c42de6dSgd78059 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes; i++) { 515*1c42de6dSgd78059 if (cookie->gptwo_nodes->gptwo_nodes[i] == previous) { 516*1c42de6dSgd78059 for (j = i + 1; 517*1c42de6dSgd78059 j < cookie->gptwo_nodes->gptwo_number_of_nodes; 518*1c42de6dSgd78059 j++) { 519*1c42de6dSgd78059 if (cookie->gptwo_nodes->gptwo_nodes[j]) { 520*1c42de6dSgd78059 *next = 521*1c42de6dSgd78059 cookie->gptwo_nodes->gptwo_nodes[j]; 522*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_WARN, 523*1c42de6dSgd78059 "returned 0x%lx\n", *next); 524*1c42de6dSgd78059 return (1); 525*1c42de6dSgd78059 } 526*1c42de6dSgd78059 } 527*1c42de6dSgd78059 *next = NULL; 528*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_WARN, "returned 0x%lx\n", 529*1c42de6dSgd78059 *next); 530*1c42de6dSgd78059 return (1); 531*1c42de6dSgd78059 } 532*1c42de6dSgd78059 } 533*1c42de6dSgd78059 534*1c42de6dSgd78059 /* 535*1c42de6dSgd78059 * previous is probably an invalid dev_info. 536*1c42de6dSgd78059 */ 537*1c42de6dSgd78059 return (0); 538*1c42de6dSgd78059 } 539*1c42de6dSgd78059 540*1c42de6dSgd78059 static gptwo_new_nodes_t * 541*1c42de6dSgd78059 gptwocfg_get_obp_created_nodes(dev_info_t *ap, uint_t id) 542*1c42de6dSgd78059 { 543*1c42de6dSgd78059 gptwo_new_nodes_t *obp_nodes; 544*1c42de6dSgd78059 dev_info_t *saf_dev; 545*1c42de6dSgd78059 int i = 0, nodes = 0; 546*1c42de6dSgd78059 int circular_count; 547*1c42de6dSgd78059 548*1c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_get_obp_created_nodes - ap=0x%lx " 549*1c42de6dSgd78059 "id=0x%x\n", ap, id); 550*1c42de6dSgd78059 551*1c42de6dSgd78059 ndi_devi_enter(ap, &circular_count); 552*1c42de6dSgd78059 553*1c42de6dSgd78059 /* 554*1c42de6dSgd78059 * First go through all the children of the attachment point 555*1c42de6dSgd78059 * to count matching safari agent ids 556*1c42de6dSgd78059 */ 557*1c42de6dSgd78059 saf_dev = ddi_get_child(ap); 558*1c42de6dSgd78059 while (saf_dev != NULL) { 559*1c42de6dSgd78059 if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, DDI_PROP_DONTPASS, 560*1c42de6dSgd78059 "portid", -1) == id) { 561*1c42de6dSgd78059 if (&starcat_dr_name) { 562*1c42de6dSgd78059 if (starcat_dr_name(ddi_node_name(saf_dev)) 563*1c42de6dSgd78059 < 0) { 564*1c42de6dSgd78059 saf_dev = ddi_get_next_sibling(saf_dev); 565*1c42de6dSgd78059 continue; 566*1c42de6dSgd78059 } 567*1c42de6dSgd78059 } 568*1c42de6dSgd78059 nodes++; 569*1c42de6dSgd78059 } 570*1c42de6dSgd78059 saf_dev = ddi_get_next_sibling(saf_dev); 571*1c42de6dSgd78059 } 572*1c42de6dSgd78059 573*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_obp_created_nodes - %d nodes " 574*1c42de6dSgd78059 "found\n", nodes); 575*1c42de6dSgd78059 576*1c42de6dSgd78059 obp_nodes = gptwocfg_allocate_node_list(nodes); 577*1c42de6dSgd78059 578*1c42de6dSgd78059 /* 579*1c42de6dSgd78059 * Then fill in the nodes structure. 580*1c42de6dSgd78059 */ 581*1c42de6dSgd78059 saf_dev = ddi_get_child(ap); 582*1c42de6dSgd78059 while ((saf_dev != NULL) && (i < nodes)) { 583*1c42de6dSgd78059 if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, DDI_PROP_DONTPASS, 584*1c42de6dSgd78059 "portid", -1) == id) { 585*1c42de6dSgd78059 if (&starcat_dr_name) { 586*1c42de6dSgd78059 if (starcat_dr_name(ddi_node_name(saf_dev)) 587*1c42de6dSgd78059 < 0) { 588*1c42de6dSgd78059 saf_dev = ddi_get_next_sibling(saf_dev); 589*1c42de6dSgd78059 continue; 590*1c42de6dSgd78059 } 591*1c42de6dSgd78059 } 592*1c42de6dSgd78059 /* 593*1c42de6dSgd78059 * Branch rooted at this dip must have been 594*1c42de6dSgd78059 * held by the DR driver. 595*1c42de6dSgd78059 */ 596*1c42de6dSgd78059 ASSERT(e_ddi_branch_held(saf_dev)); 597*1c42de6dSgd78059 obp_nodes->gptwo_nodes[i++] = saf_dev; 598*1c42de6dSgd78059 } 599*1c42de6dSgd78059 saf_dev = ddi_get_next_sibling(saf_dev); 600*1c42de6dSgd78059 } 601*1c42de6dSgd78059 602*1c42de6dSgd78059 ndi_devi_exit(ap, circular_count); 603*1c42de6dSgd78059 604*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_obp_created_nodes - " 605*1c42de6dSgd78059 "Returning 0x%lx\n", obp_nodes); 606*1c42de6dSgd78059 607*1c42de6dSgd78059 return (obp_nodes); 608*1c42de6dSgd78059 } 609*1c42de6dSgd78059 610*1c42de6dSgd78059 void 611*1c42de6dSgd78059 gptwocfg_save_handle(dev_info_t *dip, fco_handle_t fco_handle) 612*1c42de6dSgd78059 { 613*1c42de6dSgd78059 gptwocfg_handle_list_t *h; 614*1c42de6dSgd78059 615*1c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_save_handle - " 616*1c42de6dSgd78059 "dip=%lx fco_handle=%lx\n", dip, fco_handle); 617*1c42de6dSgd78059 618*1c42de6dSgd78059 h = kmem_zalloc(sizeof (gptwocfg_handle_list_t), KM_SLEEP); 619*1c42de6dSgd78059 620*1c42de6dSgd78059 mutex_enter(&gptwo_handle_list_lock); 621*1c42de6dSgd78059 622*1c42de6dSgd78059 h->next = gptwocfg_handle_list; 623*1c42de6dSgd78059 h->dip = dip; 624*1c42de6dSgd78059 h->fco_handle = fco_handle; 625*1c42de6dSgd78059 gptwocfg_handle_list = h; 626*1c42de6dSgd78059 627*1c42de6dSgd78059 mutex_exit(&gptwo_handle_list_lock); 628*1c42de6dSgd78059 } 629*1c42de6dSgd78059 630*1c42de6dSgd78059 fco_handle_t 631*1c42de6dSgd78059 gptwocfg_get_handle(dev_info_t *dip) 632*1c42de6dSgd78059 { 633*1c42de6dSgd78059 gptwocfg_handle_list_t *h, *last; 634*1c42de6dSgd78059 fco_handle_t fco_handle; 635*1c42de6dSgd78059 636*1c42de6dSgd78059 mutex_enter(&gptwo_handle_list_lock); 637*1c42de6dSgd78059 638*1c42de6dSgd78059 h = last = gptwocfg_handle_list; 639*1c42de6dSgd78059 640*1c42de6dSgd78059 while (h != NULL) { 641*1c42de6dSgd78059 if (h->dip == dip) { 642*1c42de6dSgd78059 if (h == gptwocfg_handle_list) 643*1c42de6dSgd78059 gptwocfg_handle_list = h->next; 644*1c42de6dSgd78059 else 645*1c42de6dSgd78059 last->next = h->next; 646*1c42de6dSgd78059 647*1c42de6dSgd78059 mutex_exit(&gptwo_handle_list_lock); 648*1c42de6dSgd78059 649*1c42de6dSgd78059 fco_handle = h->fco_handle; 650*1c42de6dSgd78059 651*1c42de6dSgd78059 kmem_free(h, sizeof (gptwocfg_handle_list_t)); 652*1c42de6dSgd78059 653*1c42de6dSgd78059 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_get_handle - " 654*1c42de6dSgd78059 "dip=%lx fco_handle=%lx\n", dip, fco_handle); 655*1c42de6dSgd78059 656*1c42de6dSgd78059 return (fco_handle); 657*1c42de6dSgd78059 } 658*1c42de6dSgd78059 last = h; 659*1c42de6dSgd78059 h = h->next; 660*1c42de6dSgd78059 } 661*1c42de6dSgd78059 662*1c42de6dSgd78059 mutex_exit(&gptwo_handle_list_lock); 663*1c42de6dSgd78059 664*1c42de6dSgd78059 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_handle - dip=%lx NO HANDLE\n", 665*1c42de6dSgd78059 dip); 666*1c42de6dSgd78059 667*1c42de6dSgd78059 return (0); 668*1c42de6dSgd78059 } 669*1c42de6dSgd78059 670*1c42de6dSgd78059 void 671*1c42de6dSgd78059 gptwocfg_devi_attach_to_parent(dev_info_t *dip) 672*1c42de6dSgd78059 { 673*1c42de6dSgd78059 (void) i_ndi_config_node(dip, DS_LINKED, 0); 674*1c42de6dSgd78059 } 675*1c42de6dSgd78059 676*1c42de6dSgd78059 #ifdef DEBUG 677*1c42de6dSgd78059 static void 678*1c42de6dSgd78059 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3, 679*1c42de6dSgd78059 uintptr_t a4, uintptr_t a5) 680*1c42de6dSgd78059 { 681*1c42de6dSgd78059 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5); 682*1c42de6dSgd78059 } 683*1c42de6dSgd78059 #endif 684