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