103831d35Sstevel /* 203831d35Sstevel * CDDL HEADER START 303831d35Sstevel * 403831d35Sstevel * The contents of this file are subject to the terms of the 503831d35Sstevel * Common Development and Distribution License (the "License"). 603831d35Sstevel * You may not use this file except in compliance with the License. 703831d35Sstevel * 803831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 903831d35Sstevel * or http://www.opensolaris.org/os/licensing. 1003831d35Sstevel * See the License for the specific language governing permissions 1103831d35Sstevel * and limitations under the License. 1203831d35Sstevel * 1303831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each 1403831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1503831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the 1603831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying 1703831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner] 1803831d35Sstevel * 1903831d35Sstevel * CDDL HEADER END 2003831d35Sstevel */ 2103831d35Sstevel 2203831d35Sstevel /* 23*07d06da5SSurya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2403831d35Sstevel * Use is subject to license terms. 2503831d35Sstevel */ 2603831d35Sstevel 2703831d35Sstevel /* 2803831d35Sstevel * Schizo/PCI Functions to the Safari Configurator 2903831d35Sstevel * 3003831d35Sstevel */ 3103831d35Sstevel 3203831d35Sstevel #include <sys/types.h> 3303831d35Sstevel #include <sys/cred.h> 3403831d35Sstevel #include <sys/mman.h> 3503831d35Sstevel #include <sys/kmem.h> 3603831d35Sstevel #include <sys/conf.h> 3703831d35Sstevel #include <sys/ddi.h> 3803831d35Sstevel #include <sys/sunddi.h> 3903831d35Sstevel #include <sys/sunndi.h> 4003831d35Sstevel #include <sys/modctl.h> 4103831d35Sstevel #include <sys/stat.h> 4203831d35Sstevel #include <sys/param.h> 4303831d35Sstevel #include <sys/autoconf.h> 4403831d35Sstevel #include <sys/ksynch.h> 4503831d35Sstevel #include <sys/promif.h> 4603831d35Sstevel #include <sys/ndi_impldefs.h> 4703831d35Sstevel #include <sys/ddi_impldefs.h> 4803831d35Sstevel #include <sys/machsystm.h> 4903831d35Sstevel #include <sys/gp2cfg.h> 5003831d35Sstevel #include <sys/gptwo_pci.h> 5103831d35Sstevel 5203831d35Sstevel #ifdef DEBUG 5303831d35Sstevel int gptwo_pci_debug = 0; 5403831d35Sstevel 5503831d35Sstevel static void debug(char *, uintptr_t, uintptr_t, 5603831d35Sstevel uintptr_t, uintptr_t, uintptr_t); 5703831d35Sstevel 5803831d35Sstevel #define GPTWO_DEBUG0(level, flag, s) if (gptwo_pci_debug >= level) \ 5903831d35Sstevel cmn_err(flag, s) 6003831d35Sstevel #define GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwo_pci_debug >= level) \ 6103831d35Sstevel debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0); 6203831d35Sstevel #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwo_pci_debug >= level) \ 6303831d35Sstevel debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0); 6403831d35Sstevel #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \ 6503831d35Sstevel if (gptwo_pci_debug >= level) \ 6603831d35Sstevel debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0); 6703831d35Sstevel #else 6803831d35Sstevel #define GPTWO_DEBUG0(level, flag, s) 6903831d35Sstevel #define GPTWO_DEBUG1(level, flag, fmt, a1) 7003831d35Sstevel #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) 7103831d35Sstevel #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) 7203831d35Sstevel #endif 7303831d35Sstevel 7403831d35Sstevel void gptwocfg_devi_attach_to_parent(dev_info_t *); 7503831d35Sstevel static char *gptwo_get_probe_string(spcd_t *, int); 7603831d35Sstevel static void gptwo_find_nodes(dev_info_t *, int, gptwo_new_nodes_t *); 7703831d35Sstevel 7803831d35Sstevel extern caddr_t efcode_vaddr; 7903831d35Sstevel extern int efcode_size; 8003831d35Sstevel 8103831d35Sstevel /* 8203831d35Sstevel * Module linkage information for the kernel. 8303831d35Sstevel */ 8403831d35Sstevel 8503831d35Sstevel extern struct mod_ops mod_miscops; 8603831d35Sstevel 8703831d35Sstevel static struct modlmisc modlmisc = { 8803831d35Sstevel &mod_miscops, /* Type of module */ 89f500b196SRichard Bean "gptwo->pci configurator", 9003831d35Sstevel }; 9103831d35Sstevel 9203831d35Sstevel static struct modlinkage modlinkage = { 9303831d35Sstevel MODREV_1, (void *)&modlmisc, NULL 9403831d35Sstevel }; 9503831d35Sstevel 9603831d35Sstevel int 9703831d35Sstevel _init(void) 9803831d35Sstevel { 9903831d35Sstevel int err = 0; 10003831d35Sstevel 10103831d35Sstevel /* 10203831d35Sstevel * Create a resource map for the contigous memory allocated 10303831d35Sstevel * at start-of-day in startup.c 10403831d35Sstevel */ 10503831d35Sstevel if (ndi_ra_map_setup(ddi_root_node(), "gptwo-contigousmem") 10603831d35Sstevel == NDI_FAILURE) { 10703831d35Sstevel GPTWO_DEBUG0(1, CE_WARN, 10803831d35Sstevel "Can not setup resource map - gptwo-contigousmem\n"); 10903831d35Sstevel return (1); 11003831d35Sstevel } 11103831d35Sstevel 11203831d35Sstevel /* 11303831d35Sstevel * Put the allocated memory into the pool. 11403831d35Sstevel */ 11503831d35Sstevel (void) ndi_ra_free(ddi_root_node(), (uint64_t)efcode_vaddr, 11603831d35Sstevel (uint64_t)efcode_size, "gptwo-contigousmem", 0); 11703831d35Sstevel 11803831d35Sstevel /* register devices with the configurator */ 11903831d35Sstevel gptwocfg_register_ops(SAFPTYPE_sPCI, gptwo_configure_pci, 12003831d35Sstevel gptwo_unconfigure_pci); 12103831d35Sstevel gptwocfg_register_ops(SAFPTYPE_cPCI, gptwo_configure_pci, 12203831d35Sstevel gptwo_unconfigure_pci); 12303831d35Sstevel gptwocfg_register_ops(SAFPTYPE_PCIX, gptwo_configure_pci, 12403831d35Sstevel gptwo_unconfigure_pci); 12503831d35Sstevel 12603831d35Sstevel if ((err = mod_install(&modlinkage)) != 0) { 12703831d35Sstevel GPTWO_DEBUG1(1, CE_WARN, "gptwo_pci (PCI Functions) " 12803831d35Sstevel "failed to load, error=%d\n", err); 12903831d35Sstevel gptwocfg_unregister_ops(SAFPTYPE_sPCI); 13003831d35Sstevel gptwocfg_unregister_ops(SAFPTYPE_cPCI); 13103831d35Sstevel gptwocfg_unregister_ops(SAFPTYPE_PCIX); 13203831d35Sstevel } else { 13303831d35Sstevel GPTWO_DEBUG0(1, CE_WARN, "gptwo_pci (PCI Functions) " 13403831d35Sstevel "has been loaded.\n"); 13503831d35Sstevel } 13603831d35Sstevel return (err); 13703831d35Sstevel } 13803831d35Sstevel 13903831d35Sstevel int 14003831d35Sstevel _fini(void) 14103831d35Sstevel { 14203831d35Sstevel gptwocfg_unregister_ops(SAFPTYPE_sPCI); 14303831d35Sstevel gptwocfg_unregister_ops(SAFPTYPE_cPCI); 14403831d35Sstevel gptwocfg_unregister_ops(SAFPTYPE_PCIX); 14503831d35Sstevel return (mod_remove(&modlinkage)); 14603831d35Sstevel } 14703831d35Sstevel 14803831d35Sstevel int 14903831d35Sstevel _info(modinfop) 15003831d35Sstevel struct modinfo *modinfop; 15103831d35Sstevel { 15203831d35Sstevel return (mod_info(&modlinkage, modinfop)); 15303831d35Sstevel } 15403831d35Sstevel 15503831d35Sstevel /*ARGSUSED*/ 15603831d35Sstevel static int 15703831d35Sstevel set_name_prop(dev_info_t *dip, void *arg, uint_t flags) 15803831d35Sstevel { 15903831d35Sstevel if (ndi_prop_update_string(DDI_DEV_T_NONE, dip, 16003831d35Sstevel "name", "pci") != DDI_SUCCESS) { 16103831d35Sstevel return (DDI_WALK_ERROR); 16203831d35Sstevel } 16303831d35Sstevel 16403831d35Sstevel return (DDI_WALK_TERMINATE); 16503831d35Sstevel } 16603831d35Sstevel 16703831d35Sstevel /*ARGSUSED*/ 16803831d35Sstevel static void 16903831d35Sstevel get_new_child(dev_info_t *rdip, void *arg, uint_t flags) 17003831d35Sstevel { 17103831d35Sstevel dev_info_t **dipp = (dev_info_t **)arg; 17203831d35Sstevel 17303831d35Sstevel ASSERT(dipp && (*dipp == NULL)); 17403831d35Sstevel 17503831d35Sstevel *dipp = rdip; 17603831d35Sstevel } 17703831d35Sstevel 17803831d35Sstevel gptwo_new_nodes_t * 17903831d35Sstevel gptwo_configure_pci(dev_info_t *ap, spcd_t *pcd, uint_t id) 18003831d35Sstevel { 18103831d35Sstevel fco_handle_t fco_handle; 18203831d35Sstevel int error, i, circ, freq; 18303831d35Sstevel dev_info_t *new_child; 18403831d35Sstevel char unit_address[64]; 18503831d35Sstevel gptwo_new_nodes_t *new_nodes; 18603831d35Sstevel char *probe_string; 18703831d35Sstevel devi_branch_t b = {0}; 18803831d35Sstevel 18903831d35Sstevel GPTWO_DEBUG2(1, CE_CONT, "gptwo_configure_pci: id=%x pcd=%lx\n", 19003831d35Sstevel id, pcd); 19103831d35Sstevel 19203831d35Sstevel new_nodes = gptwocfg_allocate_node_list(IOBUS_PER_PORT); 19303831d35Sstevel 19403831d35Sstevel i = IOBUS_PER_PORT; 19503831d35Sstevel 19603831d35Sstevel while (i) { 19703831d35Sstevel i--; 19803831d35Sstevel 19903831d35Sstevel if (pcd->spcd_iobus_rsv[i] != SPCD_RSV_PASS) { 20003831d35Sstevel 20103831d35Sstevel cmn_err(CE_WARN, "gptwo_configure_pci: saf id=0x%x " 20203831d35Sstevel "leaf %d - Can not be probed\n", id, i); 20303831d35Sstevel 20403831d35Sstevel continue; 20503831d35Sstevel } 20603831d35Sstevel 20703831d35Sstevel /* 20803831d35Sstevel * Ideally, fcode would be run from the "sid_branch_create" 20903831d35Sstevel * callback (that is the primary purpose of that callback). 21003831d35Sstevel * However, the fcode interpreter was written with the 21103831d35Sstevel * assumption that the "new_child" was linked into the 21203831d35Sstevel * device tree. The callback is invoked with the devinfo node 21303831d35Sstevel * in the DS_PROTO state. More investigation is needed before 21403831d35Sstevel * we can invoke the interpreter from the callback. For now, 21503831d35Sstevel * we create the "new_child" in the BOUND state, invoke the 21603831d35Sstevel * fcode interpreter and then rebind the dip to use any 21703831d35Sstevel * compatible properties created by fcode. 21803831d35Sstevel */ 21903831d35Sstevel 22003831d35Sstevel new_child = NULL; 22103831d35Sstevel 22203831d35Sstevel b.arg = &new_child; 22303831d35Sstevel b.type = DEVI_BRANCH_SID; 22403831d35Sstevel b.create.sid_branch_create = set_name_prop; 22503831d35Sstevel b.devi_branch_callback = get_new_child; 22603831d35Sstevel 22703831d35Sstevel /* 22803831d35Sstevel * Prevent any changes to new_child 22903831d35Sstevel * until we have bound it to the correct driver. 23003831d35Sstevel */ 23103831d35Sstevel ndi_devi_enter(ap, &circ); 23203831d35Sstevel if (e_ddi_branch_create(ap, &b, NULL, 0)) { 23303831d35Sstevel ASSERT(new_child == NULL); 23403831d35Sstevel 23503831d35Sstevel if (new_nodes->gptwo_nodes[0] == NULL) { 23603831d35Sstevel GPTWO_DEBUG0(1, CE_CONT, "gptwo_configure_pci: " 23703831d35Sstevel "No nodes configured - " 23803831d35Sstevel "removing new_nodes\n"); 23903831d35Sstevel gptwocfg_free_node_list(new_nodes); 24003831d35Sstevel new_nodes = NULL; 24103831d35Sstevel } 24203831d35Sstevel 24303831d35Sstevel ndi_devi_exit(ap, circ); 24403831d35Sstevel 24503831d35Sstevel return (new_nodes); 24603831d35Sstevel } 24703831d35Sstevel 24803831d35Sstevel /* 24903831d35Sstevel * The platform DR interfaces created the dip in 25003831d35Sstevel * bound state. Bring devinfo node down to linked 25103831d35Sstevel * state and hold it there until compatible 25203831d35Sstevel * properties are created. 25303831d35Sstevel */ 25403831d35Sstevel e_ddi_branch_rele(new_child); 25503831d35Sstevel (void) i_ndi_unconfig_node(new_child, DS_LINKED, 0); 25603831d35Sstevel ASSERT(i_ddi_node_state(new_child) == DS_LINKED); 25703831d35Sstevel e_ddi_branch_hold(new_child); 25803831d35Sstevel 25903831d35Sstevel mutex_enter(&DEVI(new_child)->devi_lock); 26003831d35Sstevel DEVI(new_child)->devi_flags |= DEVI_NO_BIND; 26103831d35Sstevel mutex_exit(&DEVI(new_child)->devi_lock); 26203831d35Sstevel 26303831d35Sstevel /* 26403831d35Sstevel * Drop the busy-hold on parent before calling 26503831d35Sstevel * fcode_interpreter to prevent potential deadlocks 26603831d35Sstevel */ 26703831d35Sstevel ndi_devi_exit(ap, circ); 26803831d35Sstevel 26903831d35Sstevel (void) sprintf(unit_address, "%x", id); 27003831d35Sstevel 27103831d35Sstevel /* 27203831d35Sstevel * Build the probe string from the PCD that will be passed 27303831d35Sstevel * in to the interpreter as my-args. This will tell the 27403831d35Sstevel * fcode what pci devices to probe after the pci node has 27503831d35Sstevel * been probed. 27603831d35Sstevel */ 27703831d35Sstevel probe_string = gptwo_get_probe_string(pcd, i); 27803831d35Sstevel 27903831d35Sstevel GPTWO_DEBUG3(1, CE_CONT, "gptwo_configure_pci: args to " 28003831d35Sstevel "interpreter ap=%lx new_child=%lx unit_address=%s\n", 28103831d35Sstevel ap, new_child, unit_address); 28203831d35Sstevel 28303831d35Sstevel if (probe_string) 28403831d35Sstevel GPTWO_DEBUG1(1, CE_CONT, "gptwo_configure_pci: " 28503831d35Sstevel "probe string=%s\n", probe_string); 28603831d35Sstevel 28703831d35Sstevel fco_handle = gp2_fc_ops_alloc_handle(ap, new_child, NULL, NULL, 28803831d35Sstevel unit_address, probe_string); 28903831d35Sstevel 29003831d35Sstevel GPTWO_DEBUG0(1, CE_CONT, 29103831d35Sstevel "gptwocfg: Calling Fcode Interpeter...\n"); 29203831d35Sstevel 29303831d35Sstevel error = fcode_interpreter(ap, &gp2_fc_ops, fco_handle); 29403831d35Sstevel 29503831d35Sstevel GPTWO_DEBUG1(1, CE_CONT, 29603831d35Sstevel "gptwo_configure_pci: fcode_interpreter " 29703831d35Sstevel " returned %x\n", error); 29803831d35Sstevel 29903831d35Sstevel if (error) { 30003831d35Sstevel cmn_err(CE_WARN, "gptwo_pci: Unable to probe pci leaf " 30103831d35Sstevel "%s\n", unit_address); 30203831d35Sstevel 30303831d35Sstevel gp2_fc_ops_free_handle(fco_handle); 30403831d35Sstevel 30503831d35Sstevel (void) e_ddi_branch_destroy(new_child, NULL, 0); 30603831d35Sstevel } else { 30703831d35Sstevel gptwocfg_save_handle(new_child, fco_handle); 30803831d35Sstevel 30903831d35Sstevel /* 31003831d35Sstevel * Compatible properties (if any) have been created, 31103831d35Sstevel * so bind driver. 31203831d35Sstevel */ 31303831d35Sstevel ndi_devi_enter(ap, &circ); 31403831d35Sstevel ASSERT(i_ddi_node_state(new_child) <= DS_LINKED); 31503831d35Sstevel 31603831d35Sstevel mutex_enter(&DEVI(new_child)->devi_lock); 31703831d35Sstevel DEVI(new_child)->devi_flags &= ~DEVI_NO_BIND; 31803831d35Sstevel mutex_exit(&DEVI(new_child)->devi_lock); 31903831d35Sstevel 32003831d35Sstevel ndi_devi_exit(ap, circ); 32103831d35Sstevel 32203831d35Sstevel if (ndi_devi_bind_driver(new_child, 0) != 32303831d35Sstevel DDI_SUCCESS) { 32403831d35Sstevel cmn_err(CE_WARN, "gptwo_pci: Unable to bind" 32503831d35Sstevel " new pci child at dip=0x%p\n", 326*07d06da5SSurya Prakki (void *)new_child); 32703831d35Sstevel } 32803831d35Sstevel 32903831d35Sstevel /* 33003831d35Sstevel * If POST provided a frequency, the clock-frequency 33103831d35Sstevel * property needs to be updated. 33203831d35Sstevel */ 33303831d35Sstevel if (pcd->spcd_afreq) { 33403831d35Sstevel 33503831d35Sstevel /* 33603831d35Sstevel * The upper byte is for leaf B and the lower 33703831d35Sstevel * byte is for leaf A. 33803831d35Sstevel */ 33903831d35Sstevel if (i) 34003831d35Sstevel freq = pcd->spcd_afreq >> 8; 34103831d35Sstevel else 34203831d35Sstevel freq = pcd->spcd_afreq & 0x00ff; 34303831d35Sstevel 34403831d35Sstevel (void) ndi_prop_update_int(DDI_DEV_T_NONE, 34503831d35Sstevel new_child, "clock-frequency", 34603831d35Sstevel (freq * 1000 * 1000)); 34703831d35Sstevel } 34803831d35Sstevel } 34903831d35Sstevel } 35003831d35Sstevel 35103831d35Sstevel gptwo_find_nodes(ap, id, new_nodes); 35203831d35Sstevel 35303831d35Sstevel if (new_nodes->gptwo_nodes[0] == NULL) { 35403831d35Sstevel GPTWO_DEBUG0(1, CE_CONT, "gptwo_configure_pci: " 35503831d35Sstevel "No nodes configured - removing new_nodes\n"); 35603831d35Sstevel gptwocfg_free_node_list(new_nodes); 35703831d35Sstevel new_nodes = NULL; 35803831d35Sstevel } 35903831d35Sstevel 36003831d35Sstevel GPTWO_DEBUG1(1, CE_CONT, "gptwo_configure_pci: " 36103831d35Sstevel "Returning new_nodes=%p\n", new_nodes); 36203831d35Sstevel 36303831d35Sstevel return (new_nodes); 36403831d35Sstevel } 36503831d35Sstevel 36603831d35Sstevel dev_info_t * 36703831d35Sstevel gptwo_unconfigure_pci(dev_info_t *dip) 36803831d35Sstevel { 36903831d35Sstevel fco_handle_t fco_handle; 37003831d35Sstevel 37103831d35Sstevel fco_handle = gptwocfg_get_handle(dip); 37203831d35Sstevel 37303831d35Sstevel if (fco_handle != NULL) { 37403831d35Sstevel /* 37503831d35Sstevel * If there is a handle, there may be resources 37603831d35Sstevel * that need to be freed from when the 37703831d35Sstevel * devices's fcode ran. 37803831d35Sstevel */ 37903831d35Sstevel GPTWO_DEBUG1(1, CE_CONT, "fco_handle=%lx\n", fco_handle); 38003831d35Sstevel gp2_fc_ops_free_handle(fco_handle); 38103831d35Sstevel } 38203831d35Sstevel return (NULL); 38303831d35Sstevel } 38403831d35Sstevel 38503831d35Sstevel static void 38603831d35Sstevel gptwo_find_nodes(dev_info_t *ap, int id, gptwo_new_nodes_t *new_nodes) 38703831d35Sstevel { 38803831d35Sstevel dev_info_t *saf_dev; 38903831d35Sstevel int found, j, circ; 39003831d35Sstevel int i = 0; 39103831d35Sstevel 39203831d35Sstevel GPTWO_DEBUG1(1, CE_CONT, "gptwo_find_nodes - id=%x\n", id); 39303831d35Sstevel 39403831d35Sstevel /* 39503831d35Sstevel * We are walking child list of ap, so hold it busy 39603831d35Sstevel */ 39703831d35Sstevel ndi_devi_enter(ap, &circ); 39803831d35Sstevel 39903831d35Sstevel saf_dev = ddi_get_child(ap); 40003831d35Sstevel while (saf_dev != NULL) { 40103831d35Sstevel if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, 40203831d35Sstevel DDI_PROP_DONTPASS, "portid", -1) == id) { 40303831d35Sstevel if (i < IOBUS_PER_PORT) { 40403831d35Sstevel 40503831d35Sstevel GPTWO_DEBUG2(1, CE_CONT, 40603831d35Sstevel "gptwo_find_nodes - " 40703831d35Sstevel "Found %d %p\n", i, saf_dev); 40803831d35Sstevel 40903831d35Sstevel found = 0; 41003831d35Sstevel for (j = 0; j < IOBUS_PER_PORT; j++) { 41103831d35Sstevel if (new_nodes->gptwo_nodes[j] == 41203831d35Sstevel saf_dev) { 41303831d35Sstevel found = 1; 41403831d35Sstevel } 41503831d35Sstevel } 41603831d35Sstevel if (!found) { 41703831d35Sstevel /* 41803831d35Sstevel * Branch rooted at saf-dev was 41903831d35Sstevel * held earlier. 42003831d35Sstevel */ 42103831d35Sstevel ASSERT(e_ddi_branch_held(saf_dev)); 42203831d35Sstevel new_nodes->gptwo_nodes[i] = saf_dev; 42303831d35Sstevel i++; 42403831d35Sstevel } 42503831d35Sstevel } else { 42603831d35Sstevel GPTWO_DEBUG0(1, CE_CONT, 42703831d35Sstevel "gptwo_find_nodes - " 42803831d35Sstevel "No room in new_nodes\n"); 42903831d35Sstevel } 43003831d35Sstevel } 43103831d35Sstevel saf_dev = ddi_get_next_sibling(saf_dev); 43203831d35Sstevel } 43303831d35Sstevel 43403831d35Sstevel ndi_devi_exit(ap, circ); 43503831d35Sstevel } 43603831d35Sstevel 43703831d35Sstevel static char * 43803831d35Sstevel gptwo_get_probe_string(spcd_t *pcd, int bus_number) 43903831d35Sstevel { 44003831d35Sstevel int i, str_size; 44103831d35Sstevel char temp[64]; 44203831d35Sstevel char num[8]; 44303831d35Sstevel char *probe; 44403831d35Sstevel 44503831d35Sstevel GPTWO_DEBUG2(1, CE_CONT, "gptwo_get_probe_string - %p %x\n", pcd, 44603831d35Sstevel bus_number); 44703831d35Sstevel 44803831d35Sstevel temp[0] = NULL; 44903831d35Sstevel 45003831d35Sstevel for (i = 0; i < IOCARD_PER_BUS; i++) { 45103831d35Sstevel 45203831d35Sstevel GPTWO_DEBUG2(1, CE_CONT, "gptwo_get_probe_string - " 45303831d35Sstevel "card status %x %x\n", 45403831d35Sstevel i, pcd->spcd_iocard_rsv[bus_number][i]); 45503831d35Sstevel 45603831d35Sstevel if (pcd->spcd_iocard_rsv[bus_number][i] == SPCD_RSV_PASS) { 45703831d35Sstevel numtos(i, num); 45803831d35Sstevel if (temp[0] == NULL) 45903831d35Sstevel (void) sprintf(temp, "%s", num); 46003831d35Sstevel else 46103831d35Sstevel (void) sprintf(temp, "%s,%s", temp, num); 46203831d35Sstevel } 46303831d35Sstevel } 46403831d35Sstevel 46503831d35Sstevel if (bus_number == 0) 46603831d35Sstevel (void) sprintf(temp, "%sa", temp); /* Append a 'a' for leaf A */ 46703831d35Sstevel else 46803831d35Sstevel (void) sprintf(temp, "%sb", temp); /* Append a 'b' for leaf B */ 46903831d35Sstevel 47003831d35Sstevel str_size = strlen(temp); 47103831d35Sstevel 47203831d35Sstevel if (str_size == 0) 47303831d35Sstevel return (NULL); 47403831d35Sstevel 47503831d35Sstevel probe = kmem_zalloc(str_size + 1, KM_SLEEP); 47603831d35Sstevel 47703831d35Sstevel (void) strcpy(probe, temp); 47803831d35Sstevel 47903831d35Sstevel GPTWO_DEBUG1(1, CE_CONT, "gptwo_get_probe_string - Returning %s\n", 48003831d35Sstevel probe); 48103831d35Sstevel 48203831d35Sstevel return (probe); 48303831d35Sstevel } 48403831d35Sstevel 48503831d35Sstevel #ifdef DEBUG 48603831d35Sstevel static void 48703831d35Sstevel debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3, 48803831d35Sstevel uintptr_t a4, uintptr_t a5) 48903831d35Sstevel { 49003831d35Sstevel cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5); 49103831d35Sstevel } 49203831d35Sstevel #endif 493