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 /* 23 * Copyright 2007 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 * Host to PCI-Express local bus driver 31 */ 32 33 #include <sys/conf.h> 34 #include <sys/modctl.h> 35 #include <sys/pcie.h> 36 #include <sys/pci_impl.h> 37 #include <sys/sysmacros.h> 38 #include <sys/ddi_intr.h> 39 #include <sys/sunndi.h> 40 #include <sys/sunddi.h> 41 #include <sys/ddifm.h> 42 #include <sys/ndifm.h> 43 #include <sys/fm/util.h> 44 #include <sys/hotplug/pci/pcihp.h> 45 #include <io/pci/pci_common.h> 46 #include <io/pci/pci_tools_ext.h> 47 #include <io/pciex/pcie_error.h> 48 49 /* 50 * Bus Operation functions 51 */ 52 static int npe_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *, 53 off_t, off_t, caddr_t *); 54 static int npe_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, 55 void *, void *); 56 static int npe_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t, 57 ddi_intr_handle_impl_t *, void *); 58 static int npe_fm_init(dev_info_t *, dev_info_t *, int, 59 ddi_iblock_cookie_t *); 60 61 static int npe_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *); 62 63 struct bus_ops npe_bus_ops = { 64 BUSO_REV, 65 npe_bus_map, 66 NULL, 67 NULL, 68 NULL, 69 i_ddi_map_fault, 70 ddi_dma_map, 71 ddi_dma_allochdl, 72 ddi_dma_freehdl, 73 ddi_dma_bindhdl, 74 ddi_dma_unbindhdl, 75 ddi_dma_flush, 76 ddi_dma_win, 77 ddi_dma_mctl, 78 npe_ctlops, 79 ddi_bus_prop_op, 80 0, /* (*bus_get_eventcookie)(); */ 81 0, /* (*bus_add_eventcall)(); */ 82 0, /* (*bus_remove_eventcall)(); */ 83 0, /* (*bus_post_event)(); */ 84 0, /* (*bus_intr_ctl)(); */ 85 0, /* (*bus_config)(); */ 86 0, /* (*bus_unconfig)(); */ 87 npe_fm_init, /* (*bus_fm_init)(); */ 88 NULL, /* (*bus_fm_fini)(); */ 89 NULL, /* (*bus_fm_access_enter)(); */ 90 NULL, /* (*bus_fm_access_exit)(); */ 91 NULL, /* (*bus_power)(); */ 92 npe_intr_ops /* (*bus_intr_op)(); */ 93 }; 94 95 /* 96 * One goal here is to leverage off of the pcihp.c source without making 97 * changes to it. Call into it's cb_ops directly if needed, piggybacking 98 * anything else needed by the pci_tools.c module. Only pci_tools and pcihp 99 * will be using the PCI devctl node. 100 */ 101 static int npe_open(dev_t *, int, int, cred_t *); 102 static int npe_close(dev_t, int, int, cred_t *); 103 static int npe_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 104 static int npe_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *, 105 caddr_t, int *); 106 static int npe_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 107 108 struct cb_ops npe_cb_ops = { 109 npe_open, /* open */ 110 npe_close, /* close */ 111 nodev, /* strategy */ 112 nodev, /* print */ 113 nodev, /* dump */ 114 nodev, /* read */ 115 nodev, /* write */ 116 npe_ioctl, /* ioctl */ 117 nodev, /* devmap */ 118 nodev, /* mmap */ 119 nodev, /* segmap */ 120 nochpoll, /* poll */ 121 npe_prop_op, /* cb_prop_op */ 122 NULL, /* streamtab */ 123 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ 124 CB_REV, /* rev */ 125 nodev, /* int (*cb_aread)() */ 126 nodev /* int (*cb_awrite)() */ 127 }; 128 129 130 /* 131 * Device Node Operation functions 132 */ 133 static int npe_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 134 static int npe_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 135 136 struct dev_ops npe_ops = { 137 DEVO_REV, /* devo_rev */ 138 0, /* refcnt */ 139 npe_info, /* info */ 140 nulldev, /* identify */ 141 nulldev, /* probe */ 142 npe_attach, /* attach */ 143 npe_detach, /* detach */ 144 nulldev, /* reset */ 145 &npe_cb_ops, /* driver operations */ 146 &npe_bus_ops /* bus operations */ 147 }; 148 149 /* 150 * Internal routines in support of particular npe_ctlops. 151 */ 152 static int npe_removechild(dev_info_t *child); 153 static int npe_initchild(dev_info_t *child); 154 155 /* 156 * External support routine 157 */ 158 extern void npe_query_acpi_mcfg(dev_info_t *dip); 159 extern void npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl); 160 extern int npe_disable_empty_bridges_workaround(dev_info_t *child); 161 162 /* 163 * Module linkage information for the kernel. 164 */ 165 static struct modldrv modldrv = { 166 &mod_driverops, /* Type of module */ 167 "Host to PCIe nexus driver %I%", 168 &npe_ops, /* driver ops */ 169 }; 170 171 static struct modlinkage modlinkage = { 172 MODREV_1, 173 (void *)&modldrv, 174 NULL 175 }; 176 177 /* Save minimal state. */ 178 void *npe_statep; 179 180 181 int 182 _init(void) 183 { 184 int e; 185 186 /* 187 * Initialize per-pci bus soft state pointer. 188 */ 189 e = ddi_soft_state_init(&npe_statep, sizeof (pci_state_t), 1); 190 if (e != 0) 191 return (e); 192 193 if ((e = mod_install(&modlinkage)) != 0) 194 ddi_soft_state_fini(&npe_statep); 195 196 return (e); 197 } 198 199 200 int 201 _fini(void) 202 { 203 int rc; 204 205 rc = mod_remove(&modlinkage); 206 if (rc != 0) 207 return (rc); 208 209 ddi_soft_state_fini(&npe_statep); 210 return (rc); 211 } 212 213 214 int 215 _info(struct modinfo *modinfop) 216 { 217 return (mod_info(&modlinkage, modinfop)); 218 } 219 220 /*ARGSUSED*/ 221 static int 222 npe_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 223 { 224 /* 225 * Use the minor number as constructed by pcihp, as the index value to 226 * ddi_soft_state_zalloc. 227 */ 228 int instance = ddi_get_instance(devi); 229 pci_state_t *pcip = NULL; 230 231 if (cmd == DDI_RESUME) 232 return (DDI_SUCCESS); 233 234 if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", 235 "pciex") != DDI_PROP_SUCCESS) { 236 cmn_err(CE_WARN, "npe: 'device_type' prop create failed"); 237 } 238 239 if (ddi_soft_state_zalloc(npe_statep, instance) == DDI_SUCCESS) 240 pcip = ddi_get_soft_state(npe_statep, instance); 241 242 if (pcip == NULL) 243 return (DDI_FAILURE); 244 245 pcip->pci_dip = devi; 246 247 /* 248 * Initialize hotplug support on this bus. At minimum 249 * (for non hotplug bus) this would create ":devctl" minor 250 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls 251 * to this bus. 252 */ 253 if (pcihp_init(devi) != DDI_SUCCESS) { 254 cmn_err(CE_WARN, "npe: Failed to setup hotplug framework"); 255 ddi_soft_state_free(npe_statep, instance); 256 return (DDI_FAILURE); 257 } 258 259 /* Second arg: initialize for pci_express root nexus */ 260 if (pcitool_init(devi, B_TRUE) != DDI_SUCCESS) { 261 (void) pcihp_uninit(devi); 262 ddi_soft_state_free(npe_statep, instance); 263 return (DDI_FAILURE); 264 } 265 pcip->pci_fmcap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE | 266 DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE; 267 ddi_fm_init(devi, &pcip->pci_fmcap, &pcip->pci_fm_ibc); 268 269 if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) 270 ddi_fm_handler_register(devi, npe_fm_callback, NULL); 271 272 npe_query_acpi_mcfg(devi); 273 ddi_report_dev(devi); 274 return (DDI_SUCCESS); 275 276 } 277 278 279 /*ARGSUSED*/ 280 static int 281 npe_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 282 { 283 int instance = ddi_get_instance(devi); 284 pci_state_t *pcip; 285 286 pcip = ddi_get_soft_state(npe_statep, ddi_get_instance(devi)); 287 288 switch (cmd) { 289 case DDI_DETACH: 290 291 /* Uninitialize pcitool support. */ 292 pcitool_uninit(devi); 293 294 /* 295 * Uninitialize hotplug support on this bus. 296 */ 297 (void) pcihp_uninit(devi); 298 299 if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) 300 ddi_fm_handler_unregister(devi); 301 302 ddi_fm_fini(devi); 303 ddi_soft_state_free(npe_statep, instance); 304 return (DDI_SUCCESS); 305 306 case DDI_SUSPEND: 307 return (DDI_SUCCESS); 308 default: 309 return (DDI_FAILURE); 310 } 311 } 312 313 314 static int 315 npe_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 316 off_t offset, off_t len, caddr_t *vaddrp) 317 { 318 int rnumber; 319 int length; 320 int space; 321 ddi_acc_impl_t *ap; 322 ddi_acc_hdl_t *hp; 323 ddi_map_req_t mr; 324 pci_regspec_t pci_reg; 325 pci_regspec_t *pci_rp; 326 struct regspec reg; 327 pci_acc_cfblk_t *cfp; 328 int retval; 329 330 mr = *mp; /* Get private copy of request */ 331 mp = &mr; 332 333 /* 334 * check for register number 335 */ 336 switch (mp->map_type) { 337 case DDI_MT_REGSPEC: 338 pci_reg = *(pci_regspec_t *)(mp->map_obj.rp); 339 pci_rp = &pci_reg; 340 if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS) 341 return (DDI_FAILURE); 342 break; 343 case DDI_MT_RNUMBER: 344 rnumber = mp->map_obj.rnumber; 345 /* 346 * get ALL "reg" properties for dip, select the one of 347 * of interest. In x86, "assigned-addresses" property 348 * is identical to the "reg" property, so there is no 349 * need to cross check the two to determine the physical 350 * address of the registers. 351 * This routine still performs some validity checks to 352 * make sure that everything is okay. 353 */ 354 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, 355 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, 356 (uint_t *)&length) != DDI_PROP_SUCCESS) 357 return (DDI_FAILURE); 358 359 /* 360 * validate the register number. 361 */ 362 length /= (sizeof (pci_regspec_t) / sizeof (int)); 363 if (rnumber >= length) { 364 ddi_prop_free(pci_rp); 365 return (DDI_FAILURE); 366 } 367 368 /* 369 * copy the required entry. 370 */ 371 pci_reg = pci_rp[rnumber]; 372 373 /* 374 * free the memory allocated by ddi_prop_lookup_int_array 375 */ 376 ddi_prop_free(pci_rp); 377 378 pci_rp = &pci_reg; 379 if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS) 380 return (DDI_FAILURE); 381 mp->map_type = DDI_MT_REGSPEC; 382 break; 383 default: 384 return (DDI_ME_INVAL); 385 } 386 387 space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M; 388 389 /* 390 * check for unmap and unlock of address space 391 */ 392 if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) { 393 switch (space) { 394 case PCI_ADDR_IO: 395 reg.regspec_bustype = 1; 396 break; 397 398 case PCI_ADDR_CONFIG: 399 /* 400 * Check for AMD's northbridges 401 * AND 402 * for any PCI device. 403 * 404 * This is a workaround fix for 405 * AMD-8132's inability to handle MMCFG 406 * accesses on Galaxy's PE servers 407 * AND 408 * to disable MMCFG for any PCI device. 409 * 410 * If a device is *not* found to have PCIe 411 * capability, then assume it is a PCI device. 412 */ 413 414 if (is_amd_northbridge(rdip) == 0 || 415 (ddi_prop_get_int(DDI_DEV_T_ANY, rdip, 416 DDI_PROP_DONTPASS, "pcie-capid-pointer", 417 PCI_CAP_NEXT_PTR_NULL) == PCI_CAP_NEXT_PTR_NULL)) { 418 if (DDI_FM_ACC_ERR_CAP(ddi_fm_capable(rdip)) && 419 mp->map_handlep->ah_acc.devacc_attr_access 420 != DDI_DEFAULT_ACC) { 421 ndi_fmc_remove(rdip, ACC_HANDLE, 422 (void *)mp->map_handlep); 423 } 424 return (DDI_SUCCESS); 425 } 426 427 428 /* FALLTHROUGH */ 429 case PCI_ADDR_MEM64: 430 /* 431 * MEM64 requires special treatment on map, to check 432 * that the device is below 4G. On unmap, however, 433 * we can assume that everything is OK... the map 434 * must have succeeded. 435 */ 436 /* FALLTHROUGH */ 437 case PCI_ADDR_MEM32: 438 reg.regspec_bustype = 0; 439 break; 440 441 default: 442 return (DDI_FAILURE); 443 } 444 445 /* 446 * Adjust offset and length 447 * A non-zero length means override the one in the regspec. 448 */ 449 pci_rp->pci_phys_low += (uint_t)offset; 450 if (len != 0) 451 pci_rp->pci_size_low = len; 452 453 reg.regspec_addr = pci_rp->pci_phys_low; 454 reg.regspec_size = pci_rp->pci_size_low; 455 456 mp->map_obj.rp = ® 457 retval = ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp); 458 if (DDI_FM_ACC_ERR_CAP(ddi_fm_capable(rdip)) && 459 mp->map_handlep->ah_acc.devacc_attr_access != 460 DDI_DEFAULT_ACC) { 461 ndi_fmc_remove(rdip, ACC_HANDLE, 462 (void *)mp->map_handlep); 463 } 464 return (retval); 465 466 } 467 468 /* check for user mapping request - not legal for Config */ 469 if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) { 470 cmn_err(CE_NOTE, "npe: Config mapping request from user\n"); 471 return (DDI_FAILURE); 472 } 473 474 475 /* 476 * Note that pci_fm_acc_setup() is called to serve two purposes 477 * i) enable legacy PCI I/O style config space access 478 * ii) register with FMA 479 */ 480 if (space == PCI_ADDR_CONFIG) { 481 /* Can't map config space without a handle */ 482 hp = (ddi_acc_hdl_t *)mp->map_handlep; 483 if (hp == NULL) 484 return (DDI_FAILURE); 485 486 /* record the device address for future reference */ 487 cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private; 488 cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi); 489 cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 490 cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 491 492 *vaddrp = (caddr_t)offset; 493 494 /* 495 * Check for AMD's northbridges, pci devices and 496 * devices underneath a pci bridge. This is to setup 497 * I/O based config space access. 498 */ 499 if (is_amd_northbridge(rdip) == 0 || 500 (ddi_prop_get_int(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, 501 "pcie-capid-pointer", PCI_CAP_NEXT_PTR_NULL) == 502 PCI_CAP_NEXT_PTR_NULL)) { 503 int ret; 504 505 if ((ret = pci_fm_acc_setup(hp, offset, len)) == 506 DDI_SUCCESS) { 507 if (DDI_FM_ACC_ERR_CAP(ddi_fm_capable(rdip)) && 508 mp->map_handlep->ah_acc.devacc_attr_access 509 != DDI_DEFAULT_ACC) { 510 ndi_fmc_insert(rdip, ACC_HANDLE, 511 (void *)mp->map_handlep, NULL); 512 } 513 } 514 return (ret); 515 } 516 517 pci_rp->pci_phys_low = ddi_prop_get_int64(DDI_DEV_T_ANY, 518 rdip, 0, "ecfga-base-address", 0); 519 520 pci_rp->pci_phys_low += ((cfp->c_busnum << 20) | 521 (cfp->c_devnum) << 15 | (cfp->c_funcnum << 12)); 522 523 pci_rp->pci_size_low = PCIE_CONF_HDR_SIZE; 524 } 525 526 length = pci_rp->pci_size_low; 527 528 /* 529 * range check 530 */ 531 if ((offset >= length) || (len > length) || (offset + len > length)) 532 return (DDI_FAILURE); 533 534 /* 535 * Adjust offset and length 536 * A non-zero length means override the one in the regspec. 537 */ 538 pci_rp->pci_phys_low += (uint_t)offset; 539 if (len != 0) 540 pci_rp->pci_size_low = len; 541 542 /* 543 * convert the pci regsec into the generic regspec used by the 544 * parent root nexus driver. 545 */ 546 switch (space) { 547 case PCI_ADDR_IO: 548 reg.regspec_bustype = 1; 549 break; 550 case PCI_ADDR_CONFIG: 551 case PCI_ADDR_MEM64: 552 /* 553 * We can't handle 64-bit devices that are mapped above 554 * 4G or that are larger than 4G. 555 */ 556 if (pci_rp->pci_phys_mid != 0 || pci_rp->pci_size_hi != 0) 557 return (DDI_FAILURE); 558 /* 559 * Other than that, we can treat them as 32-bit mappings 560 */ 561 /* FALLTHROUGH */ 562 case PCI_ADDR_MEM32: 563 reg.regspec_bustype = 0; 564 break; 565 default: 566 return (DDI_FAILURE); 567 } 568 569 reg.regspec_addr = pci_rp->pci_phys_low; 570 reg.regspec_size = pci_rp->pci_size_low; 571 572 mp->map_obj.rp = ® 573 retval = ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp); 574 if (retval == DDI_SUCCESS) { 575 /* 576 * For config space gets force use of cautious access routines. 577 * These will handle default and protected mode accesses too. 578 */ 579 if (space == PCI_ADDR_CONFIG) { 580 ap = (ddi_acc_impl_t *)mp->map_handlep; 581 ap->ahi_acc_attr &= ~DDI_ACCATTR_DIRECT; 582 ap->ahi_acc_attr |= DDI_ACCATTR_CONFIG_SPACE; 583 ap->ahi_get8 = i_ddi_caut_get8; 584 ap->ahi_get16 = i_ddi_caut_get16; 585 ap->ahi_get32 = i_ddi_caut_get32; 586 ap->ahi_get64 = i_ddi_caut_get64; 587 ap->ahi_rep_get8 = i_ddi_caut_rep_get8; 588 ap->ahi_rep_get16 = i_ddi_caut_rep_get16; 589 ap->ahi_rep_get32 = i_ddi_caut_rep_get32; 590 ap->ahi_rep_get64 = i_ddi_caut_rep_get64; 591 } 592 if (DDI_FM_ACC_ERR_CAP(ddi_fm_capable(rdip)) && 593 mp->map_handlep->ah_acc.devacc_attr_access != 594 DDI_DEFAULT_ACC) { 595 ndi_fmc_insert(rdip, ACC_HANDLE, 596 (void *)mp->map_handlep, NULL); 597 } 598 } 599 return (retval); 600 } 601 602 603 604 /*ARGSUSED*/ 605 static int 606 npe_ctlops(dev_info_t *dip, dev_info_t *rdip, 607 ddi_ctl_enum_t ctlop, void *arg, void *result) 608 { 609 int rn; 610 int totreg; 611 uint_t reglen; 612 pci_regspec_t *drv_regp; 613 struct attachspec *asp; 614 615 switch (ctlop) { 616 case DDI_CTLOPS_REPORTDEV: 617 if (rdip == (dev_info_t *)0) 618 return (DDI_FAILURE); 619 cmn_err(CE_CONT, "?PCI Express-device: %s@%s, %s%d\n", 620 ddi_node_name(rdip), ddi_get_name_addr(rdip), 621 ddi_driver_name(rdip), ddi_get_instance(rdip)); 622 return (DDI_SUCCESS); 623 624 case DDI_CTLOPS_INITCHILD: 625 return (npe_initchild((dev_info_t *)arg)); 626 627 case DDI_CTLOPS_UNINITCHILD: 628 return (npe_removechild((dev_info_t *)arg)); 629 630 case DDI_CTLOPS_SIDDEV: 631 return (DDI_SUCCESS); 632 633 case DDI_CTLOPS_REGSIZE: 634 case DDI_CTLOPS_NREGS: 635 if (rdip == (dev_info_t *)0) 636 return (DDI_FAILURE); 637 638 *(int *)result = 0; 639 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, 640 DDI_PROP_DONTPASS, "reg", (int **)&drv_regp, 641 ®len) != DDI_PROP_SUCCESS) { 642 return (DDI_FAILURE); 643 } 644 645 totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t); 646 if (ctlop == DDI_CTLOPS_NREGS) 647 *(int *)result = totreg; 648 else if (ctlop == DDI_CTLOPS_REGSIZE) { 649 rn = *(int *)arg; 650 if (rn >= totreg) { 651 ddi_prop_free(drv_regp); 652 return (DDI_FAILURE); 653 } 654 *(off_t *)result = drv_regp[rn].pci_size_low; 655 } 656 ddi_prop_free(drv_regp); 657 658 return (DDI_SUCCESS); 659 660 case DDI_CTLOPS_POWER: 661 { 662 power_req_t *reqp = (power_req_t *)arg; 663 /* 664 * We currently understand reporting of PCI_PM_IDLESPEED 665 * capability. Everything else is passed up. 666 */ 667 if ((reqp->request_type == PMR_REPORT_PMCAP) && 668 (reqp->req.report_pmcap_req.cap == PCI_PM_IDLESPEED)) 669 return (DDI_SUCCESS); 670 671 break; 672 } 673 674 case DDI_CTLOPS_PEEK: 675 case DDI_CTLOPS_POKE: 676 return (pci_common_peekpoke(dip, rdip, ctlop, arg, result)); 677 678 /* X86 systems support PME wakeup from suspended state */ 679 case DDI_CTLOPS_ATTACH: 680 asp = (struct attachspec *)arg; 681 /* only do this for immediate children */ 682 if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE && 683 ddi_get_parent(rdip) == dip) 684 if (pci_pre_resume(rdip) != DDI_SUCCESS) { 685 /* Not good, better stop now. */ 686 cmn_err(CE_PANIC, 687 "Couldn't pre-resume device %p", 688 (void *) dip); 689 /* NOTREACHED */ 690 } 691 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 692 693 case DDI_CTLOPS_DETACH: 694 asp = (struct attachspec *)arg; 695 /* only do this for immediate children */ 696 if (asp->cmd == DDI_SUSPEND && asp->when == DDI_POST && 697 ddi_get_parent(rdip) == dip) 698 if (pci_post_suspend(rdip) != DDI_SUCCESS) 699 return (DDI_FAILURE); 700 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 701 702 default: 703 break; 704 } 705 706 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 707 708 } 709 710 711 /* 712 * npe_intr_ops 713 */ 714 static int 715 npe_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op, 716 ddi_intr_handle_impl_t *hdlp, void *result) 717 { 718 return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result)); 719 } 720 721 722 static int 723 npe_initchild(dev_info_t *child) 724 { 725 char name[80]; 726 ddi_acc_handle_t cfg_hdl; 727 728 /* 729 * Do not bind drivers to empty bridges. 730 * Fail above, if the bridge is found to be hotplug capable 731 */ 732 if (npe_disable_empty_bridges_workaround(child) == 1) 733 return (DDI_FAILURE); 734 735 if (pci_common_name_child(child, name, 80) != DDI_SUCCESS) 736 return (DDI_FAILURE); 737 738 ddi_set_name_addr(child, name); 739 740 /* 741 * Pseudo nodes indicate a prototype node with per-instance 742 * properties to be merged into the real h/w device node. 743 * The interpretation of the unit-address is DD[,F] 744 * where DD is the device id and F is the function. 745 */ 746 if (ndi_dev_is_persistent_node(child) == 0) { 747 extern int pci_allow_pseudo_children; 748 749 ddi_set_parent_data(child, NULL); 750 751 /* 752 * Try to merge the properties from this prototype 753 * node into real h/w nodes. 754 */ 755 if (ndi_merge_node(child, pci_common_name_child) == 756 DDI_SUCCESS) { 757 /* 758 * Merged ok - return failure to remove the node. 759 */ 760 ddi_set_name_addr(child, NULL); 761 return (DDI_FAILURE); 762 } 763 764 /* workaround for DDIVS to run under PCI Express */ 765 if (pci_allow_pseudo_children) { 766 /* 767 * If the "interrupts" property doesn't exist, 768 * this must be the ddivs no-intr case, and it returns 769 * DDI_SUCCESS instead of DDI_FAILURE. 770 */ 771 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, 772 DDI_PROP_DONTPASS, "interrupts", -1) == -1) 773 return (DDI_SUCCESS); 774 /* 775 * Create the ddi_parent_private_data for a pseudo 776 * child. 777 */ 778 pci_common_set_parent_private_data(child); 779 return (DDI_SUCCESS); 780 } 781 782 /* 783 * The child was not merged into a h/w node, 784 * but there's not much we can do with it other 785 * than return failure to cause the node to be removed. 786 */ 787 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged", 788 ddi_get_name(child), ddi_get_name_addr(child), 789 ddi_get_name(child)); 790 ddi_set_name_addr(child, NULL); 791 return (DDI_NOT_WELL_FORMED); 792 } 793 794 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 795 "interrupts", -1) != -1) 796 pci_common_set_parent_private_data(child); 797 else 798 ddi_set_parent_data(child, NULL); 799 800 /* 801 * Enable AER next pointer being displayed and PCIe Error initilization 802 */ 803 if (pci_config_setup(child, &cfg_hdl) == DDI_SUCCESS) { 804 npe_ck804_fix_aer_ptr(cfg_hdl); 805 (void) pcie_error_enable(child, cfg_hdl); 806 pci_config_teardown(&cfg_hdl); 807 } 808 809 return (DDI_SUCCESS); 810 } 811 812 813 static int 814 npe_removechild(dev_info_t *dip) 815 { 816 ddi_acc_handle_t cfg_hdl; 817 struct ddi_parent_private_data *pdptr; 818 819 /* 820 * Do it way early. 821 * Otherwise ddi_map() call form pcie_error_fini crashes 822 */ 823 if (pci_config_setup(dip, &cfg_hdl) == DDI_SUCCESS) { 824 pcie_error_disable(dip, cfg_hdl); 825 pci_config_teardown(&cfg_hdl); 826 } 827 828 if ((pdptr = ddi_get_parent_data(dip)) != NULL) { 829 kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec))); 830 ddi_set_parent_data(dip, NULL); 831 } 832 ddi_set_name_addr(dip, NULL); 833 834 /* 835 * Strip the node to properly convert it back to prototype form 836 */ 837 ddi_remove_minor_node(dip, NULL); 838 839 ddi_prop_remove_all(dip); 840 841 return (DDI_SUCCESS); 842 } 843 844 845 /* 846 * When retrofitting this module for pci_tools, functions such as open, close, 847 * and ioctl are now pulled into this module. Before this, the functions in 848 * the pcihp module were referenced directly. Now they are called or 849 * referenced through the pcihp cb_ops structure from functions in this module. 850 */ 851 static int 852 npe_open(dev_t *devp, int flags, int otyp, cred_t *credp) 853 { 854 return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp)); 855 } 856 857 static int 858 npe_close(dev_t dev, int flags, int otyp, cred_t *credp) 859 { 860 return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp)); 861 } 862 863 static int 864 npe_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) 865 { 866 minor_t minor = getminor(dev); 867 int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor); 868 pci_state_t *pci_p = ddi_get_soft_state(npe_statep, instance); 869 dev_info_t *dip; 870 871 if (pci_p == NULL) 872 return (ENXIO); 873 874 dip = pci_p->pci_dip; 875 return (pci_common_ioctl(dip, dev, cmd, arg, mode, credp, rvalp)); 876 } 877 878 static int 879 npe_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 880 int flags, char *name, caddr_t valuep, int *lengthp) 881 { 882 return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags, 883 name, valuep, lengthp)); 884 } 885 886 static int 887 npe_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 888 { 889 return (pcihp_info(dip, cmd, arg, result)); 890 } 891 892 /*ARGSUSED*/ 893 static int 894 npe_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap, 895 ddi_iblock_cookie_t *ibc) 896 { 897 pci_state_t *pcip = ddi_get_soft_state(npe_statep, 898 ddi_get_instance(dip)); 899 900 ASSERT(ibc != NULL); 901 *ibc = pcip->pci_fm_ibc; 902 903 return (pcip->pci_fmcap); 904 } 905 906 /*ARGSUSED*/ 907 static int 908 npe_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *no_used) 909 { 910 return (ndi_fm_handler_dispatch(dip, NULL, derr)); 911 } 912