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