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