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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * PCI nexus utility routines: 31 * property and config routines for attach() 32 * reg/intr/range/assigned-address property routines for bus_map() 33 * init_child() 34 * fault handling 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/pci/pci_obj.h> 48 49 /*LINTLIBRARY*/ 50 51 /* 52 * get_pci_properties 53 * 54 * This function is called from the attach routine to get the key 55 * properties of the pci nodes. 56 * 57 * used by: pci_attach() 58 * 59 * return value: DDI_FAILURE on failure 60 */ 61 int 62 get_pci_properties(pci_t *pci_p, dev_info_t *dip) 63 { 64 int i; 65 66 /* 67 * Get the device's port id. 68 */ 69 if ((pci_p->pci_id = (uint32_t)pci_get_portid(dip)) == -1u) { 70 cmn_err(CE_WARN, "%s%d: no portid property\n", 71 ddi_driver_name(dip), ddi_get_instance(dip)); 72 return (DDI_FAILURE); 73 } 74 75 /* 76 * Get the bus-ranges property. 77 */ 78 i = sizeof (pci_p->pci_bus_range); 79 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 80 "bus-range", (caddr_t)&pci_p->pci_bus_range, &i) != DDI_SUCCESS) { 81 cmn_err(CE_WARN, "%s%d: no bus-range property\n", 82 ddi_driver_name(dip), ddi_get_instance(dip)); 83 return (DDI_FAILURE); 84 } 85 DEBUG2(DBG_ATTACH, dip, "get_pci_properties: bus-range (%x,%x)\n", 86 pci_p->pci_bus_range.lo, pci_p->pci_bus_range.hi); 87 88 /* 89 * disable streaming cache if necessary, this must be done 90 * before PBM is configured. 91 */ 92 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 93 "no-streaming-cache")) { 94 pci_stream_buf_enable = 0; 95 pci_stream_buf_exists = 0; 96 } 97 98 /* 99 * Get the ranges property. 100 */ 101 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges", 102 (caddr_t)&pci_p->pci_ranges, &pci_p->pci_ranges_length) != 103 DDI_SUCCESS) { 104 105 cmn_err(CE_WARN, "%s%d: no ranges property\n", 106 ddi_driver_name(dip), ddi_get_instance(dip)); 107 return (DDI_FAILURE); 108 } 109 pci_fix_ranges(pci_p->pci_ranges, 110 pci_p->pci_ranges_length / sizeof (pci_ranges_t)); 111 112 /* 113 * Determine the number upa slot interrupts. 114 */ 115 pci_p->pci_numproxy = pci_get_numproxy(pci_p->pci_dip); 116 DEBUG1(DBG_ATTACH, dip, "get_pci_properties: numproxy=%d\n", 117 pci_p->pci_numproxy); 118 119 pci_p->pci_thermal_interrupt = 120 ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 121 "thermal-interrupt", -1); 122 DEBUG1(DBG_ATTACH, dip, "get_pci_properties: thermal_interrupt=%d\n", 123 pci_p->pci_thermal_interrupt); 124 return (DDI_SUCCESS); 125 } 126 127 /* 128 * free_pci_properties: 129 * 130 * This routine frees the memory used to cache the 131 * "ranges" properties of the pci bus device node. 132 * 133 * used by: pci_detach() 134 * 135 * return value: none 136 */ 137 void 138 free_pci_properties(pci_t *pci_p) 139 { 140 kmem_free(pci_p->pci_ranges, pci_p->pci_ranges_length); 141 } 142 143 /* 144 * pci_reloc_reg 145 * 146 * If the "reg" entry (*pci_rp) is relocatable, lookup "assigned-addresses" 147 * property to fetch corresponding relocated address. 148 * 149 * used by: pci_map() 150 * 151 * return value: 152 * 153 * DDI_SUCCESS - on success 154 * DDI_ME_INVAL - regspec is invalid 155 */ 156 int 157 pci_reloc_reg(dev_info_t *dip, dev_info_t *rdip, pci_t *pci_p, 158 pci_regspec_t *rp) 159 { 160 int assign_len, assign_entries, i; 161 pci_regspec_t *assign_p; 162 register uint32_t phys_hi = rp->pci_phys_hi; 163 register uint32_t mask = PCI_REG_ADDR_M | PCI_CONF_ADDR_MASK; 164 register uint32_t phys_addr = phys_hi & mask; 165 166 DEBUG5(DBG_MAP | DBG_CONT, dip, "\tpci_reloc_reg fr: %x.%x.%x %x.%x\n", 167 rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low, 168 rp->pci_size_hi, rp->pci_size_low); 169 170 if ((phys_hi & PCI_RELOCAT_B) || !(phys_hi & PCI_ADDR_MASK)) 171 return (DDI_SUCCESS); 172 173 if (pci_p->hotplug_capable == B_FALSE) { /* validate bus # */ 174 uint32_t bus = PCI_REG_BUS_G(phys_hi); 175 if (bus < pci_p->pci_bus_range.lo || 176 bus > pci_p->pci_bus_range.hi) { 177 DEBUG1(DBG_MAP | DBG_CONT, dip, "bad bus# (%x)\n", bus); 178 return (DDI_ME_INVAL); 179 } 180 } 181 182 /* phys_mid must be 0 regardless space type. */ 183 if (rp->pci_phys_mid != 0 || rp->pci_size_hi != 0) { 184 DEBUG0(DBG_MAP | DBG_CONT, pci_p->pci_dip, 185 "phys_mid or size_hi not 0\n"); 186 return (DDI_ME_INVAL); 187 } 188 189 if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, 190 "assigned-addresses", (caddr_t)&assign_p, &assign_len)) 191 return (DDI_ME_INVAL); 192 193 assign_entries = assign_len / sizeof (pci_regspec_t); 194 for (i = 0; i < assign_entries; i++, assign_p++) { 195 if ((assign_p->pci_phys_hi & mask) == phys_addr) { 196 rp->pci_phys_low += assign_p->pci_phys_low; 197 break; 198 } 199 } 200 kmem_free(assign_p - i, assign_len); 201 DEBUG5(DBG_MAP | DBG_CONT, dip, "\tpci_reloc_reg to: %x.%x.%x %x.%x\n", 202 rp->pci_phys_hi, rp->pci_phys_mid, rp->pci_phys_low, 203 rp->pci_size_hi, rp->pci_size_low); 204 return (i < assign_entries ? DDI_SUCCESS : DDI_ME_INVAL); 205 } 206 207 /* 208 * use "ranges" to translate relocated pci regspec into parent space 209 */ 210 int 211 pci_xlate_reg(pci_t *pci_p, pci_regspec_t *pci_rp, struct regspec *new_rp) 212 { 213 int n; 214 pci_ranges_t *rng_p = pci_p->pci_ranges; 215 int rng_n = pci_p->pci_ranges_length / sizeof (pci_ranges_t); 216 217 uint32_t space_type = PCI_REG_ADDR_G(pci_rp->pci_phys_hi); 218 uint32_t reg_end, reg_begin = pci_rp->pci_phys_low; 219 uint32_t sz = pci_rp->pci_size_low; 220 221 uint32_t rng_begin, rng_end; 222 223 if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) { 224 if (reg_begin > PCI_CONF_HDR_SIZE) 225 return (DDI_ME_INVAL); 226 sz = sz ? MIN(sz, PCI_CONF_HDR_SIZE) : PCI_CONF_HDR_SIZE; 227 reg_begin += pci_rp->pci_phys_hi; 228 } 229 reg_end = reg_begin + sz - 1; 230 231 for (n = 0; n < rng_n; n++, rng_p++) { 232 if (space_type != PCI_REG_ADDR_G(rng_p->child_high)) 233 continue; /* not the same space type */ 234 235 rng_begin = rng_p->child_low; 236 if (space_type == PCI_REG_ADDR_G(PCI_ADDR_CONFIG)) 237 rng_begin += rng_p->child_high; 238 239 rng_end = rng_begin + rng_p->size_low - 1; 240 if (reg_begin >= rng_begin && reg_end <= rng_end) 241 break; 242 } 243 if (n >= rng_n) 244 return (DDI_ME_REGSPEC_RANGE); 245 246 new_rp->regspec_addr = reg_begin - rng_begin + rng_p->parent_low; 247 new_rp->regspec_bustype = rng_p->parent_high; 248 new_rp->regspec_size = sz; 249 DEBUG4(DBG_MAP | DBG_CONT, pci_p->pci_dip, 250 "\tpci_xlate_reg: entry %d new_rp %x.%x %x\n", 251 n, new_rp->regspec_bustype, new_rp->regspec_addr, sz); 252 253 return (DDI_SUCCESS); 254 } 255 256 257 /* 258 * report_dev 259 * 260 * This function is called from our control ops routine on a 261 * DDI_CTLOPS_REPORTDEV request. 262 * 263 * The display format is 264 * 265 * <name><inst> at <pname><pinst> device <dev> function <func> 266 * 267 * where 268 * 269 * <name> this device's name property 270 * <inst> this device's instance number 271 * <name> parent device's name property 272 * <inst> parent device's instance number 273 * <dev> this device's device number 274 * <func> this device's function number 275 */ 276 int 277 report_dev(dev_info_t *dip) 278 { 279 if (dip == (dev_info_t *)0) 280 return (DDI_FAILURE); 281 cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n", 282 ddi_node_name(dip), ddi_get_name_addr(dip), 283 ddi_driver_name(dip), 284 ddi_get_instance(dip)); 285 return (DDI_SUCCESS); 286 } 287 288 289 /* 290 * reg property for pcimem nodes that covers the entire address 291 * space for the node: config, io, or memory. 292 */ 293 pci_regspec_t pci_pcimem_reg[3] = 294 { 295 {PCI_ADDR_CONFIG, 0, 0, 0, 0x800000 }, 296 {(uint_t)(PCI_ADDR_IO|PCI_RELOCAT_B), 0, 0, 0, PCI_IO_SIZE }, 297 {(uint_t)(PCI_ADDR_MEM32|PCI_RELOCAT_B), 0, 0, 0, PCI_MEM_SIZE } 298 }; 299 300 /* 301 * name_child 302 * 303 * This function is called from init_child to name a node. It is 304 * also passed as a callback for node merging functions. 305 * 306 * return value: DDI_SUCCESS, DDI_FAILURE 307 */ 308 static int 309 name_child(dev_info_t *child, char *name, int namelen) 310 { 311 pci_regspec_t *pci_rp; 312 int reglen; 313 uint_t func; 314 char **unit_addr; 315 uint_t n; 316 317 /* 318 * Set the address portion of the node name based on 319 * unit-address property, if it exists. 320 * The interpretation of the unit-address is DD[,F] 321 * where DD is the device id and F is the function. 322 */ 323 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, 324 DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) == 325 DDI_PROP_SUCCESS) { 326 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { 327 cmn_err(CE_WARN, "unit-address property in %s.conf" 328 " not well-formed", ddi_driver_name(child)); 329 ddi_prop_free(unit_addr); 330 return (DDI_FAILURE); 331 } 332 (void) snprintf(name, namelen, "%s", *unit_addr); 333 ddi_prop_free(unit_addr); 334 return (DDI_SUCCESS); 335 } 336 337 /* 338 * The unit-address property is does not exist. Set the address 339 * portion of the node name based on the function and device number. 340 */ 341 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 342 "reg", (int **)&pci_rp, (uint_t *)®len) == DDI_SUCCESS) { 343 if (((reglen * sizeof (int)) % sizeof (pci_regspec_t)) != 0) { 344 cmn_err(CE_WARN, "reg property not well-formed"); 345 return (DDI_FAILURE); 346 } 347 348 func = PCI_REG_FUNC_G(pci_rp[0].pci_phys_hi); 349 if (func != 0) 350 (void) snprintf(name, namelen, "%x,%x", 351 PCI_REG_DEV_G(pci_rp[0].pci_phys_hi), func); 352 else 353 (void) snprintf(name, namelen, "%x", 354 PCI_REG_DEV_G(pci_rp[0].pci_phys_hi)); 355 ddi_prop_free(pci_rp); 356 return (DDI_SUCCESS); 357 } 358 359 cmn_err(CE_WARN, "cannot name pci child '%s'", ddi_node_name(child)); 360 return (DDI_FAILURE); 361 } 362 363 int 364 uninit_child(pci_t *pci_p, dev_info_t *child) 365 { 366 DEBUG2(DBG_CTLOPS, pci_p->pci_dip, 367 "DDI_CTLOPS_UNINITCHILD: arg=%s%d\n", 368 ddi_driver_name(child), ddi_get_instance(child)); 369 370 371 (void) pm_uninit_child(child); 372 373 ddi_set_name_addr(child, NULL); 374 ddi_remove_minor_node(child, NULL); 375 impl_rem_dev_props(child); 376 377 DEBUG0(DBG_PWR, ddi_get_parent(child), "\n\n"); 378 379 /* 380 * Handle chip specific post-uninit-child tasks. 381 */ 382 pci_post_uninit_child(pci_p); 383 384 return (DDI_SUCCESS); 385 } 386 387 /* 388 * init_child 389 * 390 * This function is called from our control ops routine on a 391 * DDI_CTLOPS_INITCHILD request. It builds and sets the device's 392 * parent private data area. 393 * 394 * used by: pci_ctlops() 395 * 396 * return value: none 397 */ 398 int 399 init_child(pci_t *pci_p, dev_info_t *child) 400 { 401 pci_regspec_t *pci_rp; 402 char name[10]; 403 ddi_acc_handle_t config_handle; 404 uint16_t command_preserve, command; 405 uint8_t bcr; 406 uint8_t header_type, min_gnt; 407 uint16_t latency_timer; 408 uint_t n; 409 int i, no_config; 410 411 /* 412 * The following is a special case for pcimem nodes. 413 * For these nodes we create a reg property with a 414 * single entry that covers the entire address space 415 * for the node (config, io or memory). 416 */ 417 if (strcmp(ddi_driver_name(child), "pcimem") == 0) { 418 (void) ddi_prop_create(DDI_DEV_T_NONE, child, 419 DDI_PROP_CANSLEEP, "reg", (caddr_t)pci_pcimem_reg, 420 sizeof (pci_pcimem_reg)); 421 ddi_set_name_addr(child, "0"); 422 ddi_set_parent_data(child, NULL); 423 return (DDI_SUCCESS); 424 } 425 426 /* 427 * Check whether the node has config space or is a hard decode 428 * node (possibly created by a driver.conf file). 429 */ 430 no_config = ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 431 "no-config", 0); 432 433 /* 434 * Pseudo nodes indicate a prototype node with per-instance 435 * properties to be merged into the real h/w device node. 436 * However, do not merge if the no-config property is set 437 * (see PSARC 2000/088). 438 */ 439 if ((ndi_dev_is_persistent_node(child) == 0) && (no_config == 0)) { 440 extern int pci_allow_pseudo_children; 441 442 if (ddi_getlongprop(DDI_DEV_T_ANY, child, 443 DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp, &i) == 444 DDI_SUCCESS) { 445 cmn_err(CE_WARN, "cannot merge prototype from %s.conf", 446 ddi_driver_name(child)); 447 kmem_free(pci_rp, i); 448 return (DDI_NOT_WELL_FORMED); 449 } 450 /* 451 * Name the child 452 */ 453 if (name_child(child, name, 10) != DDI_SUCCESS) 454 return (DDI_FAILURE); 455 456 ddi_set_name_addr(child, name); 457 ddi_set_parent_data(child, NULL); 458 459 /* 460 * Try to merge the properties from this prototype 461 * node into real h/w nodes. 462 */ 463 if (ndi_merge_node(child, name_child) == DDI_SUCCESS) { 464 /* 465 * Merged ok - return failure to remove the node. 466 */ 467 ddi_set_name_addr(child, NULL); 468 return (DDI_FAILURE); 469 } 470 471 /* workaround for ddivs to run under PCI */ 472 if (pci_allow_pseudo_children) 473 return (DDI_SUCCESS); 474 475 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged", 476 ddi_driver_name(child), ddi_get_name_addr(child), 477 ddi_driver_name(child)); 478 ddi_set_name_addr(child, NULL); 479 return (DDI_NOT_WELL_FORMED); 480 } 481 482 if (name_child(child, name, 10) != DDI_SUCCESS) 483 return (DDI_FAILURE); 484 ddi_set_name_addr(child, name); 485 486 if (no_config != 0) { 487 /* 488 * There is no config space so there's nothing more to do. 489 */ 490 return (DDI_SUCCESS); 491 } 492 493 if (pm_init_child(child) != DDI_SUCCESS) 494 return (DDI_FAILURE); 495 496 497 /* 498 * If configuration registers were previously saved by 499 * child (before it went to D3), then let the child do the 500 * restore to set up the config regs as it'll first need to 501 * power the device out of D3. 502 */ 503 if (ddi_prop_exists(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 504 "config-regs-saved-by-child") == 1) { 505 DEBUG0(DBG_PWR, child, 506 "INITCHILD: config regs to be restored by child\n"); 507 508 return (DDI_SUCCESS); 509 } 510 511 DEBUG2(DBG_PWR, ddi_get_parent(child), 512 "INITCHILD: config regs setup for %s@%s\n", 513 ddi_node_name(child), ddi_get_name_addr(child)); 514 515 /* 516 * Map the child configuration space to for initialization. 517 * We assume the obp will do the following in the devices 518 * config space: 519 * 520 * Set the latency-timer register to values appropriate 521 * for the devices on the bus (based on other devices 522 * MIN_GNT and MAX_LAT registers. 523 * 524 * Set the fast back-to-back enable bit in the command 525 * register if it's supported and all devices on the bus 526 * have the capability. 527 * 528 */ 529 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) { 530 (void) pm_uninit_child(child); 531 ddi_set_name_addr(child, NULL); 532 533 return (DDI_FAILURE); 534 } 535 536 /* 537 * Determine the configuration header type. 538 */ 539 header_type = pci_config_get8(config_handle, PCI_CONF_HEADER); 540 DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: header_type=%x\n", 541 ddi_driver_name(child), header_type); 542 543 /* 544 * Support for "command-preserve" property. Note that we 545 * add PCI_COMM_BACK2BACK_ENAB to the bits to be preserved 546 * since the obp will set this if the device supports and 547 * all targets on the same bus support it. Since psycho 548 * doesn't support PCI_COMM_BACK2BACK_ENAB, it will never 549 * be set. This is just here in case future revs do support 550 * PCI_COMM_BACK2BACK_ENAB. 551 */ 552 command_preserve = 553 ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 554 "command-preserve", 0); 555 DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: command-preserve=%x\n", 556 ddi_driver_name(child), command_preserve); 557 command = pci_config_get16(config_handle, PCI_CONF_COMM); 558 command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB); 559 command |= (pci_command_default & ~command_preserve); 560 pci_config_put16(config_handle, PCI_CONF_COMM, command); 561 command = pci_config_get16(config_handle, PCI_CONF_COMM); 562 DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: command=%x\n", 563 ddi_driver_name(child), 564 pci_config_get16(config_handle, PCI_CONF_COMM)); 565 566 /* 567 * If the device has a bus control register then program it 568 * based on the settings in the command register. 569 */ 570 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) { 571 bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL); 572 if (pci_command_default & PCI_COMM_PARITY_DETECT) 573 bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE; 574 if (pci_command_default & PCI_COMM_SERR_ENABLE) 575 bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE; 576 bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE; 577 pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr); 578 } 579 580 /* 581 * Initialize cache-line-size configuration register if needed. 582 */ 583 if (pci_set_cache_line_size_register && 584 ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 585 "cache-line-size", 0) == 0) { 586 587 pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ, 588 PCI_CACHE_LINE_SIZE); 589 n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ); 590 if (n != 0) 591 (void) ndi_prop_update_int(DDI_DEV_T_NONE, child, 592 "cache-line-size", n); 593 } 594 595 /* 596 * Initialize latency timer registers if needed. 597 */ 598 if (pci_set_latency_timer_register && 599 ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 600 "latency-timer", 0) == 0) { 601 602 latency_timer = pci_latency_timer; 603 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) { 604 pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER, 605 latency_timer); 606 } else { 607 min_gnt = pci_config_get8(config_handle, 608 PCI_CONF_MIN_G); 609 DEBUG2(DBG_INIT_CLD, pci_p->pci_dip, "%s: min_gnt=%x\n", 610 ddi_driver_name(child), min_gnt); 611 if (min_gnt != 0) { 612 switch (pci_p->pci_pbm_p->pbm_speed) { 613 case PBM_SPEED_33MHZ: 614 latency_timer = min_gnt * 8; 615 break; 616 case PBM_SPEED_66MHZ: 617 latency_timer = min_gnt * 4; 618 break; 619 } 620 } 621 } 622 latency_timer = MIN(latency_timer, 0xff); 623 pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER, 624 latency_timer); 625 n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER); 626 if (n != 0) 627 (void) ndi_prop_update_int(DDI_DEV_T_NONE, child, 628 "latency-timer", n); 629 } 630 631 pci_config_teardown(&config_handle); 632 633 /* 634 * Handle chip specific init-child tasks. 635 */ 636 pci_post_init_child(pci_p, child); 637 638 return (DDI_SUCCESS); 639 } 640 641 /* 642 * get_nreg_set 643 * 644 * Given a dev info pointer to a pci child, this routine returns the 645 * number of sets in its "reg" property. 646 * 647 * used by: pci_ctlops() - DDI_CTLOPS_NREGS 648 * 649 * return value: # of reg sets on success, zero on error 650 */ 651 uint_t 652 get_nreg_set(dev_info_t *child) 653 { 654 pci_regspec_t *pci_rp; 655 int i, n; 656 657 /* 658 * Get the reg property for the device. 659 */ 660 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg", 661 (caddr_t)&pci_rp, &i) != DDI_SUCCESS) 662 return (0); 663 664 n = i / (int)sizeof (pci_regspec_t); 665 kmem_free(pci_rp, i); 666 return (n); 667 } 668 669 670 /* 671 * get_nintr 672 * 673 * Given a dev info pointer to a pci child, this routine returns the 674 * number of items in its "interrupts" property. 675 * 676 * used by: pci_ctlops() - DDI_CTLOPS_NREGS 677 * 678 * return value: # of interrupts on success, zero on error 679 */ 680 uint_t 681 get_nintr(dev_info_t *child) 682 { 683 int *pci_ip; 684 int i, n; 685 686 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 687 "interrupts", (caddr_t)&pci_ip, &i) != DDI_SUCCESS) 688 return (0); 689 690 n = i / (int)sizeof (uint_t); 691 kmem_free(pci_ip, i); 692 return (n); 693 } 694 695 uint64_t 696 pci_get_cfg_pabase(pci_t *pci_p) 697 { 698 int i; 699 pci_ranges_t *rangep = pci_p->pci_ranges; 700 int nrange = pci_p->pci_ranges_length / sizeof (pci_ranges_t); 701 uint32_t cfg_space_type = PCI_REG_ADDR_G(PCI_ADDR_CONFIG); 702 703 ASSERT(cfg_space_type == 0); 704 705 for (i = 0; i < nrange; i++, rangep++) { 706 if (PCI_REG_ADDR_G(rangep->child_high) == cfg_space_type) 707 break; 708 } 709 710 if (i >= nrange) 711 cmn_err(CE_PANIC, "no cfg space in pci(%x) ranges prop.\n", 712 (void *)pci_p); 713 714 return (((uint64_t)rangep->parent_high << 32) | rangep->parent_low); 715 } 716 717 int 718 pci_cfg_report(dev_info_t *dip, ddi_fm_error_t *derr, pci_errstate_t *pci_err_p, 719 int caller, uint32_t prierr) 720 { 721 int fatal = 0; 722 int nonfatal = 0; 723 int i; 724 pci_target_err_t tgt_err; 725 726 ASSERT(dip); 727 728 derr->fme_ena = derr->fme_ena ? derr->fme_ena : 729 fm_ena_generate(0, FM_ENA_FMT1); 730 731 for (i = 0; pci_err_tbl[i].err_class != NULL; i++) { 732 if (pci_err_p->pci_cfg_stat & pci_err_tbl[i].reg_bit) { 733 char buf[FM_MAX_CLASS]; 734 735 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", 736 PCI_ERROR_SUBCLASS, 737 pci_err_tbl[i].err_class); 738 ddi_fm_ereport_post(dip, buf, derr->fme_ena, 739 DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0, 740 PCI_CONFIG_STATUS, DATA_TYPE_UINT16, 741 pci_err_p->pci_cfg_stat, 742 PCI_CONFIG_COMMAND, DATA_TYPE_UINT16, 743 pci_err_p->pci_cfg_comm, 744 PCI_PA, DATA_TYPE_UINT64, 745 pci_err_p->pci_pa, 746 NULL); 747 748 switch (pci_err_tbl[i].reg_bit) { 749 case PCI_STAT_S_SYSERR: 750 /* 751 * address parity error on dma - treat as fatal 752 */ 753 fatal++; 754 break; 755 case PCI_STAT_R_MAST_AB: 756 case PCI_STAT_R_TARG_AB: 757 case PCI_STAT_S_PERROR: 758 if (prierr) { 759 /* 760 * piow case are already handled in 761 * pbm_afsr_report() 762 */ 763 break; 764 } 765 if (caller != PCI_TRAP_CALL) { 766 /* 767 * if we haven't come from trap handler 768 * we won't have an address 769 */ 770 fatal++; 771 break; 772 } 773 774 /* 775 * queue target ereport - use return from 776 * pci_lookup_handle() to determine if sync 777 * or async 778 */ 779 tgt_err.tgt_err_ena = derr->fme_ena; 780 tgt_err.tgt_err_class = 781 pci_err_tbl[i].terr_class; 782 tgt_err.tgt_bridge_type = PCI_ERROR_SUBCLASS; 783 tgt_err.tgt_err_addr = 784 (uint64_t)derr->fme_bus_specific; 785 nonfatal++; 786 errorq_dispatch(pci_target_queue, 787 (void *)&tgt_err, 788 sizeof (pci_target_err_t), 789 ERRORQ_ASYNC); 790 break; 791 default: 792 /* 793 * dpe on dma write or ta on dma 794 */ 795 nonfatal++; 796 break; 797 } 798 } 799 } 800 801 if (fatal) 802 return (DDI_FM_FATAL); 803 else if (nonfatal) 804 return (DDI_FM_NONFATAL); 805 806 return (DDI_FM_OK); 807 } 808 809 void 810 pci_child_cfg_save(dev_info_t *dip) 811 { 812 dev_info_t *cdip; 813 int ret = DDI_SUCCESS; 814 815 /* 816 * Save the state of the configuration headers of child 817 * nodes. 818 */ 819 820 for (cdip = ddi_get_child(dip); cdip != NULL; 821 cdip = ddi_get_next_sibling(cdip)) { 822 823 /* 824 * Not interested in children who are not already 825 * init'ed. They will be set up in init_child(). 826 */ 827 if (i_ddi_node_state(cdip) < DS_INITIALIZED) { 828 DEBUG2(DBG_DETACH, dip, "DDI_SUSPEND: skipping " 829 "%s%d not in CF1\n", ddi_driver_name(cdip), 830 ddi_get_instance(cdip)); 831 832 continue; 833 } 834 835 /* 836 * Only save config registers if not already saved by child. 837 */ 838 if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 839 SAVED_CONFIG_REGS) == 1) { 840 841 continue; 842 } 843 844 /* 845 * The nexus needs to save config registers. Create a property 846 * so it knows to restore on resume. 847 */ 848 ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, 849 "nexus-saved-config-regs"); 850 851 if (ret != DDI_PROP_SUCCESS) { 852 cmn_err(CE_WARN, "%s%d can't update prop %s", 853 ddi_driver_name(cdip), ddi_get_instance(cdip), 854 "nexus-saved-config-regs"); 855 } 856 857 (void) pci_save_config_regs(cdip); 858 } 859 } 860 861 void 862 pci_child_cfg_restore(dev_info_t *dip) 863 { 864 dev_info_t *cdip; 865 866 /* 867 * Restore config registers for children that did not save 868 * their own registers. Children pwr states are UNKNOWN after 869 * a resume since it is possible for the PM framework to call 870 * resume without an actual power cycle. (ie if suspend fails). 871 */ 872 for (cdip = ddi_get_child(dip); cdip != NULL; 873 cdip = ddi_get_next_sibling(cdip)) { 874 875 /* 876 * Not interested in children who are not already 877 * init'ed. They will be set up by init_child(). 878 */ 879 if (i_ddi_node_state(cdip) < DS_INITIALIZED) { 880 DEBUG2(DBG_DETACH, dip, 881 "DDI_RESUME: skipping %s%d not in CF1\n", 882 ddi_driver_name(cdip), ddi_get_instance(cdip)); 883 continue; 884 } 885 886 /* 887 * Only restore config registers if saved by nexus. 888 */ 889 if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 890 "nexus-saved-config-regs") == 1) { 891 (void) pci_restore_config_regs(cdip); 892 893 DEBUG2(DBG_PWR, dip, 894 "DDI_RESUME: nexus restoring %s%d config regs\n", 895 ddi_driver_name(cdip), ddi_get_instance(cdip)); 896 897 if (ndi_prop_remove(DDI_DEV_T_NONE, cdip, 898 "nexus-saved-config-regs") != DDI_PROP_SUCCESS) { 899 cmn_err(CE_WARN, "%s%d can't remove prop %s", 900 ddi_driver_name(cdip), 901 ddi_get_instance(cdip), 902 "nexus-saved-config-regs"); 903 } 904 } 905 } 906 } 907