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