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