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