1*1708Sstevel /* 2*1708Sstevel * CDDL HEADER START 3*1708Sstevel * 4*1708Sstevel * The contents of this file are subject to the terms of the 5*1708Sstevel * Common Development and Distribution License (the "License"). 6*1708Sstevel * You may not use this file except in compliance with the License. 7*1708Sstevel * 8*1708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1708Sstevel * or http://www.opensolaris.org/os/licensing. 10*1708Sstevel * See the License for the specific language governing permissions 11*1708Sstevel * and limitations under the License. 12*1708Sstevel * 13*1708Sstevel * When distributing Covered Code, include this CDDL HEADER in each 14*1708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1708Sstevel * If applicable, add the following below this CDDL HEADER, with the 16*1708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 17*1708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 18*1708Sstevel * 19*1708Sstevel * CDDL HEADER END 20*1708Sstevel */ 21*1708Sstevel 22*1708Sstevel /* 23*1708Sstevel * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*1708Sstevel * Use is subject to license terms. 25*1708Sstevel */ 26*1708Sstevel 27*1708Sstevel #pragma ident "%Z%%M% %I% %E% SMI" 28*1708Sstevel 29*1708Sstevel /* 30*1708Sstevel * Schizo/PCI Functions to the Safari Configurator 31*1708Sstevel * 32*1708Sstevel */ 33*1708Sstevel 34*1708Sstevel #include <sys/types.h> 35*1708Sstevel #include <sys/cred.h> 36*1708Sstevel #include <sys/mman.h> 37*1708Sstevel #include <sys/kmem.h> 38*1708Sstevel #include <sys/conf.h> 39*1708Sstevel #include <sys/ddi.h> 40*1708Sstevel #include <sys/sunddi.h> 41*1708Sstevel #include <sys/sunndi.h> 42*1708Sstevel #include <sys/modctl.h> 43*1708Sstevel #include <sys/stat.h> 44*1708Sstevel #include <sys/param.h> 45*1708Sstevel #include <sys/autoconf.h> 46*1708Sstevel #include <sys/ksynch.h> 47*1708Sstevel #include <sys/promif.h> 48*1708Sstevel #include <sys/ndi_impldefs.h> 49*1708Sstevel #include <sys/ddi_impldefs.h> 50*1708Sstevel #include <sys/machsystm.h> 51*1708Sstevel #include <sys/gp2cfg.h> 52*1708Sstevel #include <sys/gptwo_pci.h> 53*1708Sstevel 54*1708Sstevel #ifdef DEBUG 55*1708Sstevel int gptwo_pci_debug = 0; 56*1708Sstevel 57*1708Sstevel static void debug(char *, uintptr_t, uintptr_t, 58*1708Sstevel uintptr_t, uintptr_t, uintptr_t); 59*1708Sstevel 60*1708Sstevel #define GPTWO_DEBUG0(level, flag, s) if (gptwo_pci_debug >= level) \ 61*1708Sstevel cmn_err(flag, s) 62*1708Sstevel #define GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwo_pci_debug >= level) \ 63*1708Sstevel debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0); 64*1708Sstevel #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwo_pci_debug >= level) \ 65*1708Sstevel debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0); 66*1708Sstevel #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \ 67*1708Sstevel if (gptwo_pci_debug >= level) \ 68*1708Sstevel debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0); 69*1708Sstevel #else 70*1708Sstevel #define GPTWO_DEBUG0(level, flag, s) 71*1708Sstevel #define GPTWO_DEBUG1(level, flag, fmt, a1) 72*1708Sstevel #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) 73*1708Sstevel #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) 74*1708Sstevel #endif 75*1708Sstevel 76*1708Sstevel void gptwocfg_devi_attach_to_parent(dev_info_t *); 77*1708Sstevel static char *gptwo_get_probe_string(spcd_t *, int); 78*1708Sstevel static void gptwo_find_nodes(dev_info_t *, int, gptwo_new_nodes_t *); 79*1708Sstevel 80*1708Sstevel extern caddr_t efcode_vaddr; 81*1708Sstevel extern int efcode_size; 82*1708Sstevel 83*1708Sstevel /* 84*1708Sstevel * Module linkage information for the kernel. 85*1708Sstevel */ 86*1708Sstevel 87*1708Sstevel extern struct mod_ops mod_miscops; 88*1708Sstevel 89*1708Sstevel static struct modlmisc modlmisc = { 90*1708Sstevel &mod_miscops, /* Type of module */ 91*1708Sstevel "gptwo->pci configurator %I%", 92*1708Sstevel }; 93*1708Sstevel 94*1708Sstevel static struct modlinkage modlinkage = { 95*1708Sstevel MODREV_1, (void *)&modlmisc, NULL 96*1708Sstevel }; 97*1708Sstevel 98*1708Sstevel int 99*1708Sstevel _init(void) 100*1708Sstevel { 101*1708Sstevel int err = 0; 102*1708Sstevel 103*1708Sstevel /* 104*1708Sstevel * Create a resource map for the contigous memory allocated 105*1708Sstevel * at start-of-day in startup.c 106*1708Sstevel */ 107*1708Sstevel if (ndi_ra_map_setup(ddi_root_node(), "gptwo-contigousmem") 108*1708Sstevel == NDI_FAILURE) { 109*1708Sstevel GPTWO_DEBUG0(1, CE_WARN, 110*1708Sstevel "Can not setup resource map - gptwo-contigousmem\n"); 111*1708Sstevel return (1); 112*1708Sstevel } 113*1708Sstevel 114*1708Sstevel /* 115*1708Sstevel * Put the allocated memory into the pool. 116*1708Sstevel */ 117*1708Sstevel (void) ndi_ra_free(ddi_root_node(), (uint64_t)efcode_vaddr, 118*1708Sstevel (uint64_t)efcode_size, "gptwo-contigousmem", 0); 119*1708Sstevel 120*1708Sstevel /* register devices with the configurator */ 121*1708Sstevel gptwocfg_register_ops(SAFPTYPE_sPCI, gptwo_configure_pci, 122*1708Sstevel gptwo_unconfigure_pci); 123*1708Sstevel gptwocfg_register_ops(SAFPTYPE_cPCI, gptwo_configure_pci, 124*1708Sstevel gptwo_unconfigure_pci); 125*1708Sstevel gptwocfg_register_ops(SAFPTYPE_PCIX, gptwo_configure_pci, 126*1708Sstevel gptwo_unconfigure_pci); 127*1708Sstevel 128*1708Sstevel if ((err = mod_install(&modlinkage)) != 0) { 129*1708Sstevel GPTWO_DEBUG1(1, CE_WARN, "gptwo_pci (PCI Functions) " 130*1708Sstevel "failed to load, error=%d\n", err); 131*1708Sstevel gptwocfg_unregister_ops(SAFPTYPE_sPCI); 132*1708Sstevel gptwocfg_unregister_ops(SAFPTYPE_cPCI); 133*1708Sstevel gptwocfg_unregister_ops(SAFPTYPE_PCIX); 134*1708Sstevel } else { 135*1708Sstevel GPTWO_DEBUG0(1, CE_WARN, "gptwo_pci (PCI Functions) " 136*1708Sstevel "has been loaded.\n"); 137*1708Sstevel } 138*1708Sstevel return (err); 139*1708Sstevel } 140*1708Sstevel 141*1708Sstevel int 142*1708Sstevel _fini(void) 143*1708Sstevel { 144*1708Sstevel gptwocfg_unregister_ops(SAFPTYPE_sPCI); 145*1708Sstevel gptwocfg_unregister_ops(SAFPTYPE_cPCI); 146*1708Sstevel gptwocfg_unregister_ops(SAFPTYPE_PCIX); 147*1708Sstevel return (mod_remove(&modlinkage)); 148*1708Sstevel } 149*1708Sstevel 150*1708Sstevel int 151*1708Sstevel _info(modinfop) 152*1708Sstevel struct modinfo *modinfop; 153*1708Sstevel { 154*1708Sstevel return (mod_info(&modlinkage, modinfop)); 155*1708Sstevel } 156*1708Sstevel 157*1708Sstevel /*ARGSUSED*/ 158*1708Sstevel static int 159*1708Sstevel set_name_prop(dev_info_t *dip, void *arg, uint_t flags) 160*1708Sstevel { 161*1708Sstevel if (ndi_prop_update_string(DDI_DEV_T_NONE, dip, 162*1708Sstevel "name", "pci") != DDI_SUCCESS) { 163*1708Sstevel return (DDI_WALK_ERROR); 164*1708Sstevel } 165*1708Sstevel 166*1708Sstevel return (DDI_WALK_TERMINATE); 167*1708Sstevel } 168*1708Sstevel 169*1708Sstevel /*ARGSUSED*/ 170*1708Sstevel static void 171*1708Sstevel get_new_child(dev_info_t *rdip, void *arg, uint_t flags) 172*1708Sstevel { 173*1708Sstevel dev_info_t **dipp = (dev_info_t **)arg; 174*1708Sstevel 175*1708Sstevel ASSERT(dipp && (*dipp == NULL)); 176*1708Sstevel 177*1708Sstevel *dipp = rdip; 178*1708Sstevel } 179*1708Sstevel 180*1708Sstevel gptwo_new_nodes_t * 181*1708Sstevel gptwo_configure_pci(dev_info_t *ap, spcd_t *pcd, uint_t id) 182*1708Sstevel { 183*1708Sstevel fco_handle_t fco_handle; 184*1708Sstevel int error, i, circ, freq; 185*1708Sstevel dev_info_t *new_child; 186*1708Sstevel char unit_address[64]; 187*1708Sstevel gptwo_new_nodes_t *new_nodes; 188*1708Sstevel char *probe_string; 189*1708Sstevel devi_branch_t b = {0}; 190*1708Sstevel 191*1708Sstevel GPTWO_DEBUG2(1, CE_CONT, "gptwo_configure_pci: id=%x pcd=%lx\n", 192*1708Sstevel id, pcd); 193*1708Sstevel 194*1708Sstevel new_nodes = gptwocfg_allocate_node_list(IOBUS_PER_PORT); 195*1708Sstevel 196*1708Sstevel i = IOBUS_PER_PORT; 197*1708Sstevel 198*1708Sstevel while (i) { 199*1708Sstevel i--; 200*1708Sstevel 201*1708Sstevel if (pcd->spcd_iobus_rsv[i] != SPCD_RSV_PASS) { 202*1708Sstevel 203*1708Sstevel cmn_err(CE_WARN, "gptwo_configure_pci: saf id=0x%x " 204*1708Sstevel "leaf %d - Can not be probed\n", id, i); 205*1708Sstevel 206*1708Sstevel continue; 207*1708Sstevel } 208*1708Sstevel 209*1708Sstevel /* 210*1708Sstevel * Ideally, fcode would be run from the "sid_branch_create" 211*1708Sstevel * callback (that is the primary purpose of that callback). 212*1708Sstevel * However, the fcode interpreter was written with the 213*1708Sstevel * assumption that the "new_child" was linked into the 214*1708Sstevel * device tree. The callback is invoked with the devinfo node 215*1708Sstevel * in the DS_PROTO state. More investigation is needed before 216*1708Sstevel * we can invoke the interpreter from the callback. For now, 217*1708Sstevel * we create the "new_child" in the BOUND state, invoke the 218*1708Sstevel * fcode interpreter and then rebind the dip to use any 219*1708Sstevel * compatible properties created by fcode. 220*1708Sstevel */ 221*1708Sstevel 222*1708Sstevel new_child = NULL; 223*1708Sstevel 224*1708Sstevel b.arg = &new_child; 225*1708Sstevel b.type = DEVI_BRANCH_SID; 226*1708Sstevel b.create.sid_branch_create = set_name_prop; 227*1708Sstevel b.devi_branch_callback = get_new_child; 228*1708Sstevel 229*1708Sstevel /* 230*1708Sstevel * Prevent any changes to new_child 231*1708Sstevel * until we have bound it to the correct driver. 232*1708Sstevel */ 233*1708Sstevel ndi_devi_enter(ap, &circ); 234*1708Sstevel if (e_ddi_branch_create(ap, &b, NULL, 0)) { 235*1708Sstevel ASSERT(new_child == NULL); 236*1708Sstevel 237*1708Sstevel if (new_nodes->gptwo_nodes[0] == NULL) { 238*1708Sstevel GPTWO_DEBUG0(1, CE_CONT, "gptwo_configure_pci: " 239*1708Sstevel "No nodes configured - " 240*1708Sstevel "removing new_nodes\n"); 241*1708Sstevel gptwocfg_free_node_list(new_nodes); 242*1708Sstevel new_nodes = NULL; 243*1708Sstevel } 244*1708Sstevel 245*1708Sstevel ndi_devi_exit(ap, circ); 246*1708Sstevel 247*1708Sstevel return (new_nodes); 248*1708Sstevel } 249*1708Sstevel 250*1708Sstevel /* 251*1708Sstevel * The platform DR interfaces created the dip in 252*1708Sstevel * bound state. Bring devinfo node down to linked 253*1708Sstevel * state and hold it there until compatible 254*1708Sstevel * properties are created. 255*1708Sstevel */ 256*1708Sstevel e_ddi_branch_rele(new_child); 257*1708Sstevel (void) i_ndi_unconfig_node(new_child, DS_LINKED, 0); 258*1708Sstevel ASSERT(i_ddi_node_state(new_child) == DS_LINKED); 259*1708Sstevel e_ddi_branch_hold(new_child); 260*1708Sstevel 261*1708Sstevel mutex_enter(&DEVI(new_child)->devi_lock); 262*1708Sstevel DEVI(new_child)->devi_flags |= DEVI_NO_BIND; 263*1708Sstevel mutex_exit(&DEVI(new_child)->devi_lock); 264*1708Sstevel 265*1708Sstevel /* 266*1708Sstevel * Drop the busy-hold on parent before calling 267*1708Sstevel * fcode_interpreter to prevent potential deadlocks 268*1708Sstevel */ 269*1708Sstevel ndi_devi_exit(ap, circ); 270*1708Sstevel 271*1708Sstevel (void) sprintf(unit_address, "%x", id); 272*1708Sstevel 273*1708Sstevel /* 274*1708Sstevel * Build the probe string from the PCD that will be passed 275*1708Sstevel * in to the interpreter as my-args. This will tell the 276*1708Sstevel * fcode what pci devices to probe after the pci node has 277*1708Sstevel * been probed. 278*1708Sstevel */ 279*1708Sstevel probe_string = gptwo_get_probe_string(pcd, i); 280*1708Sstevel 281*1708Sstevel GPTWO_DEBUG3(1, CE_CONT, "gptwo_configure_pci: args to " 282*1708Sstevel "interpreter ap=%lx new_child=%lx unit_address=%s\n", 283*1708Sstevel ap, new_child, unit_address); 284*1708Sstevel 285*1708Sstevel if (probe_string) 286*1708Sstevel GPTWO_DEBUG1(1, CE_CONT, "gptwo_configure_pci: " 287*1708Sstevel "probe string=%s\n", probe_string); 288*1708Sstevel 289*1708Sstevel fco_handle = gp2_fc_ops_alloc_handle(ap, new_child, NULL, NULL, 290*1708Sstevel unit_address, probe_string); 291*1708Sstevel 292*1708Sstevel GPTWO_DEBUG0(1, CE_CONT, 293*1708Sstevel "gptwocfg: Calling Fcode Interpeter...\n"); 294*1708Sstevel 295*1708Sstevel error = fcode_interpreter(ap, &gp2_fc_ops, fco_handle); 296*1708Sstevel 297*1708Sstevel GPTWO_DEBUG1(1, CE_CONT, 298*1708Sstevel "gptwo_configure_pci: fcode_interpreter " 299*1708Sstevel " returned %x\n", error); 300*1708Sstevel 301*1708Sstevel if (error) { 302*1708Sstevel cmn_err(CE_WARN, "gptwo_pci: Unable to probe pci leaf " 303*1708Sstevel "%s\n", unit_address); 304*1708Sstevel 305*1708Sstevel gp2_fc_ops_free_handle(fco_handle); 306*1708Sstevel 307*1708Sstevel (void) e_ddi_branch_destroy(new_child, NULL, 0); 308*1708Sstevel } else { 309*1708Sstevel gptwocfg_save_handle(new_child, fco_handle); 310*1708Sstevel 311*1708Sstevel /* 312*1708Sstevel * Compatible properties (if any) have been created, 313*1708Sstevel * so bind driver. 314*1708Sstevel */ 315*1708Sstevel ndi_devi_enter(ap, &circ); 316*1708Sstevel ASSERT(i_ddi_node_state(new_child) <= DS_LINKED); 317*1708Sstevel 318*1708Sstevel mutex_enter(&DEVI(new_child)->devi_lock); 319*1708Sstevel DEVI(new_child)->devi_flags &= ~DEVI_NO_BIND; 320*1708Sstevel mutex_exit(&DEVI(new_child)->devi_lock); 321*1708Sstevel 322*1708Sstevel ndi_devi_exit(ap, circ); 323*1708Sstevel 324*1708Sstevel if (ndi_devi_bind_driver(new_child, 0) != 325*1708Sstevel DDI_SUCCESS) { 326*1708Sstevel cmn_err(CE_WARN, "gptwo_pci: Unable to bind" 327*1708Sstevel " new pci child at dip=0x%p\n", 328*1708Sstevel new_child); 329*1708Sstevel } 330*1708Sstevel 331*1708Sstevel /* 332*1708Sstevel * If POST provided a frequency, the clock-frequency 333*1708Sstevel * property needs to be updated. 334*1708Sstevel */ 335*1708Sstevel if (pcd->spcd_afreq) { 336*1708Sstevel 337*1708Sstevel /* 338*1708Sstevel * The upper byte is for leaf B and the lower 339*1708Sstevel * byte is for leaf A. 340*1708Sstevel */ 341*1708Sstevel if (i) 342*1708Sstevel freq = pcd->spcd_afreq >> 8; 343*1708Sstevel else 344*1708Sstevel freq = pcd->spcd_afreq & 0x00ff; 345*1708Sstevel 346*1708Sstevel (void) ndi_prop_update_int(DDI_DEV_T_NONE, 347*1708Sstevel new_child, "clock-frequency", 348*1708Sstevel (freq * 1000 * 1000)); 349*1708Sstevel } 350*1708Sstevel } 351*1708Sstevel } 352*1708Sstevel 353*1708Sstevel gptwo_find_nodes(ap, id, new_nodes); 354*1708Sstevel 355*1708Sstevel if (new_nodes->gptwo_nodes[0] == NULL) { 356*1708Sstevel GPTWO_DEBUG0(1, CE_CONT, "gptwo_configure_pci: " 357*1708Sstevel "No nodes configured - removing new_nodes\n"); 358*1708Sstevel gptwocfg_free_node_list(new_nodes); 359*1708Sstevel new_nodes = NULL; 360*1708Sstevel } 361*1708Sstevel 362*1708Sstevel GPTWO_DEBUG1(1, CE_CONT, "gptwo_configure_pci: " 363*1708Sstevel "Returning new_nodes=%p\n", new_nodes); 364*1708Sstevel 365*1708Sstevel return (new_nodes); 366*1708Sstevel } 367*1708Sstevel 368*1708Sstevel dev_info_t * 369*1708Sstevel gptwo_unconfigure_pci(dev_info_t *dip) 370*1708Sstevel { 371*1708Sstevel fco_handle_t fco_handle; 372*1708Sstevel 373*1708Sstevel fco_handle = gptwocfg_get_handle(dip); 374*1708Sstevel 375*1708Sstevel if (fco_handle != NULL) { 376*1708Sstevel /* 377*1708Sstevel * If there is a handle, there may be resources 378*1708Sstevel * that need to be freed from when the 379*1708Sstevel * devices's fcode ran. 380*1708Sstevel */ 381*1708Sstevel GPTWO_DEBUG1(1, CE_CONT, "fco_handle=%lx\n", fco_handle); 382*1708Sstevel gp2_fc_ops_free_handle(fco_handle); 383*1708Sstevel } 384*1708Sstevel return (NULL); 385*1708Sstevel } 386*1708Sstevel 387*1708Sstevel static void 388*1708Sstevel gptwo_find_nodes(dev_info_t *ap, int id, gptwo_new_nodes_t *new_nodes) 389*1708Sstevel { 390*1708Sstevel dev_info_t *saf_dev; 391*1708Sstevel int found, j, circ; 392*1708Sstevel int i = 0; 393*1708Sstevel 394*1708Sstevel GPTWO_DEBUG1(1, CE_CONT, "gptwo_find_nodes - id=%x\n", id); 395*1708Sstevel 396*1708Sstevel /* 397*1708Sstevel * We are walking child list of ap, so hold it busy 398*1708Sstevel */ 399*1708Sstevel ndi_devi_enter(ap, &circ); 400*1708Sstevel 401*1708Sstevel saf_dev = ddi_get_child(ap); 402*1708Sstevel while (saf_dev != NULL) { 403*1708Sstevel if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, 404*1708Sstevel DDI_PROP_DONTPASS, "portid", -1) == id) { 405*1708Sstevel if (i < IOBUS_PER_PORT) { 406*1708Sstevel 407*1708Sstevel GPTWO_DEBUG2(1, CE_CONT, 408*1708Sstevel "gptwo_find_nodes - " 409*1708Sstevel "Found %d %p\n", i, saf_dev); 410*1708Sstevel 411*1708Sstevel found = 0; 412*1708Sstevel for (j = 0; j < IOBUS_PER_PORT; j++) { 413*1708Sstevel if (new_nodes->gptwo_nodes[j] == 414*1708Sstevel saf_dev) { 415*1708Sstevel found = 1; 416*1708Sstevel } 417*1708Sstevel } 418*1708Sstevel if (!found) { 419*1708Sstevel /* 420*1708Sstevel * Branch rooted at saf-dev was 421*1708Sstevel * held earlier. 422*1708Sstevel */ 423*1708Sstevel ASSERT(e_ddi_branch_held(saf_dev)); 424*1708Sstevel new_nodes->gptwo_nodes[i] = saf_dev; 425*1708Sstevel i++; 426*1708Sstevel } 427*1708Sstevel } else { 428*1708Sstevel GPTWO_DEBUG0(1, CE_CONT, 429*1708Sstevel "gptwo_find_nodes - " 430*1708Sstevel "No room in new_nodes\n"); 431*1708Sstevel } 432*1708Sstevel } 433*1708Sstevel saf_dev = ddi_get_next_sibling(saf_dev); 434*1708Sstevel } 435*1708Sstevel 436*1708Sstevel ndi_devi_exit(ap, circ); 437*1708Sstevel } 438*1708Sstevel 439*1708Sstevel static char * 440*1708Sstevel gptwo_get_probe_string(spcd_t *pcd, int bus_number) 441*1708Sstevel { 442*1708Sstevel int i, str_size; 443*1708Sstevel char temp[64]; 444*1708Sstevel char num[8]; 445*1708Sstevel char *probe; 446*1708Sstevel 447*1708Sstevel GPTWO_DEBUG2(1, CE_CONT, "gptwo_get_probe_string - %p %x\n", pcd, 448*1708Sstevel bus_number); 449*1708Sstevel 450*1708Sstevel temp[0] = NULL; 451*1708Sstevel 452*1708Sstevel for (i = 0; i < IOCARD_PER_BUS; i++) { 453*1708Sstevel 454*1708Sstevel GPTWO_DEBUG2(1, CE_CONT, "gptwo_get_probe_string - " 455*1708Sstevel "card status %x %x\n", 456*1708Sstevel i, pcd->spcd_iocard_rsv[bus_number][i]); 457*1708Sstevel 458*1708Sstevel if (pcd->spcd_iocard_rsv[bus_number][i] == SPCD_RSV_PASS) { 459*1708Sstevel numtos(i, num); 460*1708Sstevel if (temp[0] == NULL) 461*1708Sstevel (void) sprintf(temp, "%s", num); 462*1708Sstevel else 463*1708Sstevel (void) sprintf(temp, "%s,%s", temp, num); 464*1708Sstevel } 465*1708Sstevel } 466*1708Sstevel 467*1708Sstevel if (bus_number == 0) 468*1708Sstevel (void) sprintf(temp, "%sa", temp); /* Append a 'a' for leaf A */ 469*1708Sstevel else 470*1708Sstevel (void) sprintf(temp, "%sb", temp); /* Append a 'b' for leaf B */ 471*1708Sstevel 472*1708Sstevel str_size = strlen(temp); 473*1708Sstevel 474*1708Sstevel if (str_size == 0) 475*1708Sstevel return (NULL); 476*1708Sstevel 477*1708Sstevel probe = kmem_zalloc(str_size + 1, KM_SLEEP); 478*1708Sstevel 479*1708Sstevel (void) strcpy(probe, temp); 480*1708Sstevel 481*1708Sstevel GPTWO_DEBUG1(1, CE_CONT, "gptwo_get_probe_string - Returning %s\n", 482*1708Sstevel probe); 483*1708Sstevel 484*1708Sstevel return (probe); 485*1708Sstevel } 486*1708Sstevel 487*1708Sstevel #ifdef DEBUG 488*1708Sstevel static void 489*1708Sstevel debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3, 490*1708Sstevel uintptr_t a4, uintptr_t a5) 491*1708Sstevel { 492*1708Sstevel cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5); 493*1708Sstevel } 494*1708Sstevel #endif 495