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