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 2006 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 * CMU-CH nexus utility routines: 30 * property and config routines for attach() 31 * reg/intr/range/assigned-address property routines for bus_map() 32 * init_child() 33 * fault handling 34 * debug functions 35 */ 36 37 #include <sys/types.h> 38 #include <sys/kmem.h> 39 #include <sys/async.h> 40 #include <sys/sysmacros.h> 41 #include <sys/sunddi.h> 42 #include <sys/sunndi.h> 43 #include <sys/fm/protocol.h> 44 #include <sys/fm/io/pci.h> 45 #include <sys/fm/util.h> 46 #include <sys/ddi_impldefs.h> 47 #include <sys/pcicmu/pcicmu.h> 48 #include <sys/promif.h> 49 50 /*LINTLIBRARY*/ 51 52 /* 53 * get_pcmu_properties 54 * 55 * This function is called from the attach routine to get the key 56 * properties of the pci nodes. 57 * 58 * used by: pcmu_attach() 59 * 60 * return value: DDI_FAILURE on failure 61 */ 62 int 63 get_pcmu_properties(pcmu_t *pcmu_p, dev_info_t *dip) 64 { 65 int i; 66 67 /* 68 * Get the device's port id. 69 */ 70 if ((pcmu_p->pcmu_id = (uint32_t)pcmu_get_portid(dip)) == -1u) { 71 cmn_err(CE_WARN, "%s%d: no portid property\n", 72 ddi_driver_name(dip), ddi_get_instance(dip)); 73 return (DDI_FAILURE); 74 } 75 76 /* 77 * Get the bus-ranges property. 78 */ 79 i = sizeof (pcmu_p->pcmu_bus_range); 80 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 81 "bus-range", (caddr_t)&pcmu_p->pcmu_bus_range, &i) != DDI_SUCCESS) { 82 cmn_err(CE_WARN, "%s%d: no bus-range property\n", 83 ddi_driver_name(dip), ddi_get_instance(dip)); 84 return (DDI_FAILURE); 85 } 86 PCMU_DBG2(PCMU_DBG_ATTACH, dip, 87 "get_pcmu_properties: bus-range (%x,%x)\n", 88 pcmu_p->pcmu_bus_range.lo, pcmu_p->pcmu_bus_range.hi); 89 90 /* 91 * Get the ranges property. 92 */ 93 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges", 94 (caddr_t)&pcmu_p->pcmu_ranges, &pcmu_p->pcmu_ranges_length) != 95 DDI_SUCCESS) { 96 cmn_err(CE_WARN, "%s%d: no ranges property\n", 97 ddi_driver_name(dip), ddi_get_instance(dip)); 98 return (DDI_FAILURE); 99 } 100 pcmu_fix_ranges(pcmu_p->pcmu_ranges, 101 pcmu_p->pcmu_ranges_length / sizeof (pcmu_ranges_t)); 102 103 /* 104 * Determine the number upa slot interrupts. 105 */ 106 pcmu_p->pcmu_numproxy = pcmu_get_numproxy(pcmu_p->pcmu_dip); 107 PCMU_DBG1(PCMU_DBG_ATTACH, dip, "get_pcmu_properties: numproxy=%d\n", 108 pcmu_p->pcmu_numproxy); 109 return (DDI_SUCCESS); 110 } 111 112 /* 113 * free_pcmu_properties: 114 * 115 * This routine frees the memory used to cache the 116 * "ranges" properties of the pci bus device node. 117 * 118 * used by: pcmu_detach() 119 * 120 * return value: none 121 */ 122 void 123 free_pcmu_properties(pcmu_t *pcmu_p) 124 { 125 kmem_free(pcmu_p->pcmu_ranges, pcmu_p->pcmu_ranges_length); 126 } 127 128 /* 129 * pcmu_reloc_reg 130 * 131 * If the "reg" entry (*pcmu_rp) is relocatable, lookup "assigned-addresses" 132 * property to fetch corresponding relocated address. 133 * 134 * used by: pcmu_map() 135 * 136 * return value: 137 * 138 * DDI_SUCCESS - on success 139 * DDI_ME_INVAL - regspec is invalid 140 */ 141 int 142 pcmu_reloc_reg(dev_info_t *dip, dev_info_t *rdip, pcmu_t *pcmu_p, 143 pci_regspec_t *rp) 144 { 145 int assign_len, assign_entries, i; 146 pci_regspec_t *assign_p; 147 register uint32_t phys_hi = rp->pci_phys_hi; 148 register uint32_t mask = PCI_REG_ADDR_M | PCI_CONF_ADDR_MASK; 149 register uint32_t phys_addr = phys_hi & mask; 150 151 PCMU_DBG5(PCMU_DBG_MAP | PCMU_DBG_CONT, dip, 152 "\tpcmu_reloc_reg fr: %x.%x.%x %x.%x\n", 153 rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low, 154 rp->pci_size_hi, rp->pci_size_low); 155 156 if ((phys_hi & PCI_RELOCAT_B) || !(phys_hi & PCI_ADDR_MASK)) { 157 return (DDI_SUCCESS); 158 } 159 160 /* phys_mid must be 0 regardless space type. XXX-64 bit mem space */ 161 if (rp->pci_phys_mid != 0 || rp->pci_size_hi != 0) { 162 PCMU_DBG0(PCMU_DBG_MAP | PCMU_DBG_CONT, pcmu_p->pcmu_dip, 163 "phys_mid or size_hi not 0\n"); 164 return (DDI_ME_INVAL); 165 } 166 167 if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, 168 "assigned-addresses", (caddr_t)&assign_p, &assign_len)) { 169 return (DDI_ME_INVAL); 170 } 171 172 assign_entries = assign_len / sizeof (pci_regspec_t); 173 for (i = 0; i < assign_entries; i++, assign_p++) { 174 if ((assign_p->pci_phys_hi & mask) == phys_addr) { 175 rp->pci_phys_low += assign_p->pci_phys_low; 176 break; 177 } 178 } 179 kmem_free(assign_p - i, assign_len); 180 PCMU_DBG5(PCMU_DBG_MAP | PCMU_DBG_CONT, dip, 181 "\tpcmu_reloc_reg to: %x.%x.%x %x.%x\n", 182 rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low, 183 rp->pci_size_hi, rp->pci_size_low); 184 return (i < assign_entries ? DDI_SUCCESS : DDI_ME_INVAL); 185 } 186 187 /* 188 * use "ranges" to translate relocated pci regspec into parent space 189 */ 190 int 191 pcmu_xlate_reg(pcmu_t *pcmu_p, pci_regspec_t *pcmu_rp, struct regspec *new_rp) 192 { 193 int n; 194 pcmu_ranges_t *rng_p = pcmu_p->pcmu_ranges; 195 int rng_n = pcmu_p->pcmu_ranges_length / sizeof (pcmu_ranges_t); 196 197 uint32_t space_type = PCI_REG_ADDR_G(pcmu_rp->pci_phys_hi); 198 uint32_t reg_end, reg_begin = pcmu_rp->pci_phys_low; 199 uint32_t sz = pcmu_rp->pci_size_low; 200 201 uint32_t rng_begin, rng_end; 202 203 if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) { 204 if (reg_begin > PCI_CONF_HDR_SIZE) { 205 return (DDI_ME_INVAL); 206 } 207 sz = sz ? MIN(sz, PCI_CONF_HDR_SIZE) : PCI_CONF_HDR_SIZE; 208 reg_begin += pcmu_rp->pci_phys_hi; 209 } 210 reg_end = reg_begin + sz - 1; 211 212 for (n = 0; n < rng_n; n++, rng_p++) { 213 if (space_type != PCI_REG_ADDR_G(rng_p->child_high)) { 214 continue; /* not the same space type */ 215 } 216 217 rng_begin = rng_p->child_low; 218 if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) { 219 rng_begin += rng_p->child_high; 220 } 221 rng_end = rng_begin + rng_p->size_low - 1; 222 if (reg_begin >= rng_begin && reg_end <= rng_end) { 223 break; 224 } 225 } 226 if (n >= rng_n) { 227 return (DDI_ME_REGSPEC_RANGE); 228 } 229 230 new_rp->regspec_addr = reg_begin - rng_begin + rng_p->parent_low; 231 new_rp->regspec_bustype = rng_p->parent_high; 232 new_rp->regspec_size = sz; 233 PCMU_DBG4(PCMU_DBG_MAP | PCMU_DBG_CONT, pcmu_p->pcmu_dip, 234 "\tpcmu_xlate_reg: entry %d new_rp %x.%x %x\n", 235 n, new_rp->regspec_bustype, new_rp->regspec_addr, sz); 236 return (DDI_SUCCESS); 237 } 238 239 240 /* 241 * pcmu_report_dev 242 * 243 * This function is called from our control ops routine on a 244 * DDI_CTLOPS_REPORTDEV request. 245 * 246 * The display format is 247 * 248 * <name><inst> at <pname><pinst> device <dev> function <func> 249 * 250 * where 251 * 252 * <name> this device's name property 253 * <inst> this device's instance number 254 * <name> parent device's name property 255 * <inst> parent device's instance number 256 * <dev> this device's device number 257 * <func> this device's function number 258 */ 259 int 260 pcmu_report_dev(dev_info_t *dip) 261 { 262 if (dip == (dev_info_t *)0) { 263 return (DDI_FAILURE); 264 } 265 cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n", ddi_node_name(dip), 266 ddi_get_name_addr(dip), ddi_driver_name(dip), 267 ddi_get_instance(dip)); 268 return (DDI_SUCCESS); 269 } 270 271 /* 272 * name_child 273 * 274 * This function is called from pcmu_init_child to name a node. It is 275 * also passed as a callback for node merging functions. 276 * 277 * return value: DDI_SUCCESS, DDI_FAILURE 278 */ 279 static int 280 name_child(dev_info_t *child, char *name, int namelen) 281 { 282 pci_regspec_t *pcmu_rp; 283 int reglen; 284 uint_t func; 285 char **unit_addr; 286 uint_t n; 287 288 /* 289 * Set the address portion of the node name based on 290 * unit-address property, if it exists. 291 * The interpretation of the unit-address is DD[,F] 292 * where DD is the device id and F is the function. 293 */ 294 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, 295 DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) == 296 DDI_PROP_SUCCESS) { 297 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { 298 cmn_err(CE_WARN, "unit-address property in %s.conf" 299 " not well-formed", ddi_driver_name(child)); 300 ddi_prop_free(unit_addr); 301 return (DDI_FAILURE); 302 } 303 (void) snprintf(name, namelen, "%s", *unit_addr); 304 ddi_prop_free(unit_addr); 305 return (DDI_SUCCESS); 306 } 307 308 /* 309 * The unit-address property is does not exist. Set the address 310 * portion of the node name based on the function and device number. 311 */ 312 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 313 "reg", (int **)&pcmu_rp, (uint_t *)®len) == DDI_SUCCESS) { 314 if (((reglen * sizeof (int)) % sizeof (pci_regspec_t)) != 0) { 315 cmn_err(CE_WARN, "reg property not well-formed"); 316 return (DDI_FAILURE); 317 } 318 319 func = PCI_REG_FUNC_G(pcmu_rp[0].pci_phys_hi); 320 if (func != 0) { 321 (void) snprintf(name, namelen, "%x,%x", 322 PCI_REG_DEV_G(pcmu_rp[0].pci_phys_hi), func); 323 } else { 324 (void) snprintf(name, namelen, "%x", 325 PCI_REG_DEV_G(pcmu_rp[0].pci_phys_hi)); 326 } 327 ddi_prop_free(pcmu_rp); 328 return (DDI_SUCCESS); 329 } 330 cmn_err(CE_WARN, "cannot name pci child '%s'", ddi_node_name(child)); 331 return (DDI_FAILURE); 332 } 333 334 int 335 pcmu_uninit_child(pcmu_t *pcmu_p, dev_info_t *child) 336 { 337 PCMU_DBG2(PCMU_DBG_CTLOPS, pcmu_p->pcmu_dip, 338 "DDI_CTLOPS_UNINITCHILD: arg=%s%d\n", 339 ddi_driver_name(child), ddi_get_instance(child)); 340 341 ddi_set_name_addr(child, NULL); 342 ddi_remove_minor_node(child, NULL); 343 impl_rem_dev_props(child); 344 345 PCMU_DBG0(PCMU_DBG_PWR, ddi_get_parent(child), "\n\n"); 346 return (DDI_SUCCESS); 347 } 348 349 /* 350 * pcmu_init_child 351 * 352 * This function is called from our control ops routine on a 353 * DDI_CTLOPS_INITCHILD request. It builds and sets the device's 354 * parent private data area. 355 * 356 * used by: pcmu_ctlops() 357 * 358 * return value: none 359 */ 360 int 361 pcmu_init_child(pcmu_t *pcmu_p, dev_info_t *child) 362 { 363 char name[10]; 364 ddi_acc_handle_t config_handle; 365 uint8_t bcr; 366 uint8_t header_type; 367 368 if (name_child(child, name, 10) != DDI_SUCCESS) 369 return (DDI_FAILURE); 370 ddi_set_name_addr(child, name); 371 372 PCMU_DBG2(PCMU_DBG_PWR, ddi_get_parent(child), 373 "INITCHILD: config regs setup for %s@%s\n", 374 ddi_node_name(child), ddi_get_name_addr(child)); 375 376 /* 377 * Map the child configuration space to for initialization. 378 * We assume the obp will do the following in the devices 379 * config space: 380 * 381 * Set the latency-timer register to values appropriate 382 * for the devices on the bus (based on other devices 383 * MIN_GNT and MAX_LAT registers. 384 * 385 * Set the fast back-to-back enable bit in the command 386 * register if it's supported and all devices on the bus 387 * have the capability. 388 * 389 */ 390 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) { 391 ddi_set_name_addr(child, NULL); 392 return (DDI_FAILURE); 393 } 394 395 /* 396 * Determine the configuration header type. 397 */ 398 header_type = pci_config_get8(config_handle, PCI_CONF_HEADER); 399 PCMU_DBG2(PCMU_DBG_INIT_CLD, pcmu_p->pcmu_dip, "%s: header_type=%x\n", 400 ddi_driver_name(child), header_type); 401 402 /* 403 * If the device has a bus control register then program it 404 * based on the settings in the command register. 405 */ 406 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) { 407 bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL); 408 if (pcmu_command_default & PCI_COMM_PARITY_DETECT) 409 bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE; 410 if (pcmu_command_default & PCI_COMM_SERR_ENABLE) 411 bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE; 412 bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE; 413 pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr); 414 } 415 416 pci_config_teardown(&config_handle); 417 return (DDI_SUCCESS); 418 } 419 420 /* 421 * pcmu_get_reg_set_size 422 * 423 * Given a dev info pointer to a pci child and a register number, this 424 * routine returns the size element of that reg set property. 425 * 426 * used by: pcmu_ctlops() - DDI_CTLOPS_REGSIZE 427 * 428 * return value: size of reg set on success, zero on error 429 */ 430 off_t 431 pcmu_get_reg_set_size(dev_info_t *child, int rnumber) 432 { 433 pci_regspec_t *pcmu_rp; 434 off_t size; 435 int i; 436 437 if (rnumber < 0) { 438 return (0); 439 } 440 441 /* 442 * Get the reg property for the device. 443 */ 444 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg", 445 (caddr_t)&pcmu_rp, &i) != DDI_SUCCESS) { 446 return (0); 447 } 448 449 if (rnumber >= (i / (int)sizeof (pci_regspec_t))) { 450 kmem_free(pcmu_rp, i); 451 return (0); 452 } 453 454 size = pcmu_rp[rnumber].pci_size_low | 455 ((uint64_t)pcmu_rp[rnumber].pci_size_hi << 32); 456 kmem_free(pcmu_rp, i); 457 return (size); 458 } 459 460 461 /* 462 * pcmu_get_nreg_set 463 * 464 * Given a dev info pointer to a pci child, this routine returns the 465 * number of sets in its "reg" property. 466 * 467 * used by: pcmu_ctlops() - DDI_CTLOPS_NREGS 468 * 469 * return value: # of reg sets on success, zero on error 470 */ 471 uint_t 472 pcmu_get_nreg_set(dev_info_t *child) 473 { 474 pci_regspec_t *pcmu_rp; 475 int i, n; 476 477 /* 478 * Get the reg property for the device. 479 */ 480 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg", 481 (caddr_t)&pcmu_rp, &i) != DDI_SUCCESS) { 482 return (0); 483 } 484 n = i / (int)sizeof (pci_regspec_t); 485 kmem_free(pcmu_rp, i); 486 return (n); 487 } 488 489 int 490 pcmu_cfg_report(dev_info_t *dip, ddi_fm_error_t *derr, 491 pcmu_errstate_t *pcmu_err_p, int caller, uint32_t prierr) 492 { 493 int fatal = 0; 494 int nonfatal = 0; 495 int i; 496 pcmu_t *pcmu_p; 497 int instance = ddi_get_instance(dip); 498 499 ASSERT(dip); 500 501 pcmu_p = get_pcmu_soft_state(instance); 502 503 derr->fme_ena = derr->fme_ena ? derr->fme_ena : 504 fm_ena_generate(0, FM_ENA_FMT1); 505 506 for (i = 0; pci_err_tbl[i].err_class != NULL; i++) { 507 if (pcmu_err_p->pcmu_cfg_stat & pci_err_tbl[i].reg_bit) { 508 char buf[FM_MAX_CLASS]; 509 char *aux_msg = NULL; 510 511 switch (pci_err_tbl[i].reg_bit) { 512 case PCI_STAT_R_MAST_AB: 513 aux_msg = "Recieved Master Abort"; 514 /* LINTED fallthrough on case statement */ 515 case PCI_STAT_R_TARG_AB: 516 if (aux_msg != NULL) 517 aux_msg = "Recieved Target Abort"; 518 if (prierr) { 519 /* 520 * piow case are already handled in 521 * pcmu_pbm_afsr_report() 522 */ 523 break; 524 } 525 if (caller != PCI_TRAP_CALL) { 526 /* 527 * if we haven't come from trap handler 528 * we won't have an address 529 */ 530 fatal++; 531 } 532 break; 533 default: 534 /* 535 * dpe on dma write or ta on dma 536 */ 537 nonfatal++; 538 break; 539 } 540 (void) snprintf(buf, FM_MAX_CLASS, "%s %s: %s %s", 541 (pcmu_p->pcmu_pcbm_p)->pcbm_nameinst_str, 542 (pcmu_p->pcmu_pcbm_p)->pcbm_nameaddr_str, 543 "PCI config space:", aux_msg); 544 cmn_err(CE_WARN, "%s %s=0x%p", buf, 545 "pbm-csr", (pcmu_p->pcmu_pcbm_p)->pcbm_ctrl_reg); 546 } 547 } 548 549 if (fatal) 550 return (DDI_FM_FATAL); 551 else if (nonfatal) 552 return (DDI_FM_NONFATAL); 553 554 return (DDI_FM_OK); 555 } 556 557 void 558 pcmu_child_cfg_save(dev_info_t *dip) 559 { 560 dev_info_t *cdip; 561 int ret = DDI_SUCCESS; 562 563 /* 564 * Save the state of the configuration headers of child 565 * nodes. 566 */ 567 568 for (cdip = ddi_get_child(dip); cdip != NULL; 569 cdip = ddi_get_next_sibling(cdip)) { 570 571 /* 572 * Not interested in children who are not already 573 * init'ed. They will be set up in pcmu_init_child(). 574 */ 575 if (i_ddi_node_state(cdip) < DS_INITIALIZED) { 576 PCMU_DBG2(PCMU_DBG_DETACH, dip, "DDI_SUSPEND: skipping " 577 "%s%d not in CF1\n", ddi_driver_name(cdip), 578 ddi_get_instance(cdip)); 579 580 continue; 581 } 582 583 /* 584 * Only save config registers if not already saved by child. 585 */ 586 if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 587 SAVED_CONFIG_REGS) == 1) { 588 589 continue; 590 } 591 592 /* 593 * The nexus needs to save config registers. Create a property 594 * so it knows to restore on resume. 595 */ 596 ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, 597 "nexus-saved-config-regs"); 598 599 if (ret != DDI_PROP_SUCCESS) { 600 cmn_err(CE_WARN, "%s%d can't update prop %s", 601 ddi_driver_name(cdip), ddi_get_instance(cdip), 602 "nexus-saved-config-regs"); 603 } 604 605 (void) pci_save_config_regs(cdip); 606 } 607 } 608 609 void 610 pcmu_child_cfg_restore(dev_info_t *dip) 611 { 612 dev_info_t *cdip; 613 614 /* 615 * Restore config registers for children that did not save 616 * their own registers. Children pwr states are UNKNOWN after 617 * a resume since it is possible for the PM framework to call 618 * resume without an actual power cycle. (ie if suspend fails). 619 */ 620 for (cdip = ddi_get_child(dip); cdip != NULL; 621 cdip = ddi_get_next_sibling(cdip)) { 622 623 /* 624 * Not interested in children who are not already 625 * init'ed. They will be set up by pcmu_init_child(). 626 */ 627 if (i_ddi_node_state(cdip) < DS_INITIALIZED) { 628 PCMU_DBG2(PCMU_DBG_DETACH, dip, 629 "DDI_RESUME: skipping %s%d not in CF1\n", 630 ddi_driver_name(cdip), ddi_get_instance(cdip)); 631 continue; 632 } 633 634 /* 635 * Only restore config registers if saved by nexus. 636 */ 637 if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 638 "nexus-saved-config-regs") == 1) { 639 (void) pci_restore_config_regs(cdip); 640 641 PCMU_DBG2(PCMU_DBG_PWR, dip, 642 "DDI_RESUME: nexus restoring %s%d config regs\n", 643 ddi_driver_name(cdip), ddi_get_instance(cdip)); 644 645 if (ndi_prop_remove(DDI_DEV_T_NONE, cdip, 646 "nexus-saved-config-regs") != DDI_PROP_SUCCESS) { 647 cmn_err(CE_WARN, "%s%d can't remove prop %s", 648 ddi_driver_name(cdip), 649 ddi_get_instance(cdip), 650 "nexus-saved-config-regs"); 651 } 652 } 653 } 654 } 655 656 #ifdef DEBUG 657 extern uint64_t pcmu_debug_flags; 658 659 pcmu_dflag_to_str_t pcmu_dflag_strings [] = { 660 {PCMU_DBG_ATTACH, "pcmu_attach"}, 661 {PCMU_DBG_DETACH, "pcmu_detach"}, 662 {PCMU_DBG_MAP, "pcmu_map"}, 663 {PCMU_DBG_A_INTX, "pcmu_add_intx"}, 664 {PCMU_DBG_R_INTX, "pcmu_rem_intx"}, 665 {PCMU_DBG_INIT_CLD, "pcmu_init_child"}, 666 {PCMU_DBG_CTLOPS, "pcmu_ctlops"}, 667 {PCMU_DBG_INTR, "pcmu_intr_wrapper"}, 668 {PCMU_DBG_ERR_INTR, "pcmu_pbm_error_intr"}, 669 {PCMU_DBG_BUS_FAULT, "pcmu_fault"}, 670 {PCMU_DBG_IB, "pcmu_ib"}, 671 {PCMU_DBG_CB, "pcmu_cb"}, 672 {PCMU_DBG_PBM, "pcmu_pbm"}, 673 {PCMU_DBG_OPEN, "pcmu_open"}, 674 {PCMU_DBG_CLOSE, "pcmu_close"}, 675 {PCMU_DBG_IOCTL, "pcmu_ioctl"}, 676 {PCMU_DBG_PWR, "pcmu_pwr"} 677 }; 678 679 void 680 pcmu_debug(uint64_t flag, dev_info_t *dip, char *fmt, 681 uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5) 682 { 683 char *s = "pcmu unknown"; 684 uint_t cont = 0; 685 int i; 686 int no_rec = (sizeof (pcmu_dflag_strings) / 687 sizeof (pcmu_dflag_to_str_t)); 688 689 if (flag & PCMU_DBG_CONT) { 690 flag &= ~PCMU_DBG_CONT; 691 cont = 1; 692 } 693 if ((pcmu_debug_flags & flag) == flag) { 694 for (i = 0; i < no_rec; i++) { 695 if (pcmu_dflag_strings[i].flag == flag) { 696 s = pcmu_dflag_strings[i].string; 697 break; 698 } 699 } 700 if (s && cont == 0) { 701 prom_printf("%s(%d): %s: ", ddi_driver_name(dip), 702 ddi_get_instance(dip), s); 703 } 704 prom_printf(fmt, a1, a2, a3, a4, a5); 705 } 706 } 707 #endif 708