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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Host to PCI local bus driver 31 */ 32 33 #include <sys/conf.h> 34 #include <sys/kmem.h> 35 #include <sys/debug.h> 36 #include <sys/modctl.h> 37 #include <sys/autoconf.h> 38 #include <sys/ddi_impldefs.h> 39 #include <sys/ddi_subrdefs.h> 40 #include <sys/pci.h> 41 #include <sys/pci_impl.h> 42 #include <sys/ddi.h> 43 #include <sys/sunddi.h> 44 #include <sys/sunndi.h> 45 #include <sys/hotplug/pci/pcihp.h> 46 #include <sys/pci_cfgspace.h> 47 #include <sys/avintr.h> 48 #include <sys/psm.h> 49 #include <sys/pci_intr_lib.h> 50 #include <sys/policy.h> 51 #include <sys/pci_tools.h> 52 #include <sys/pci_tools_var.h> 53 #include "pci_var.h" 54 55 /* Save minimal state. */ 56 void *pci_statep; 57 58 /* 59 * Bus Operation functions 60 */ 61 static int pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *, 62 off_t, off_t, caddr_t *); 63 static int pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, 64 void *, void *); 65 static int pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t, 66 ddi_intr_handle_impl_t *, void *); 67 static int pci_get_priority(dev_info_t *, int, int *); 68 static int pci_get_nintrs(dev_info_t *, int, int *); 69 static int pci_enable_intr(dev_info_t *, dev_info_t *, 70 ddi_intr_handle_impl_t *, uint32_t); 71 static void pci_disable_intr(dev_info_t *, dev_info_t *, 72 ddi_intr_handle_impl_t *, uint32_t); 73 74 /* Extern decalrations */ 75 extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *, 76 psm_intr_op_t, int *); 77 78 struct bus_ops pci_bus_ops = { 79 BUSO_REV, 80 pci_bus_map, 81 NULL, 82 NULL, 83 NULL, 84 i_ddi_map_fault, 85 ddi_dma_map, 86 ddi_dma_allochdl, 87 ddi_dma_freehdl, 88 ddi_dma_bindhdl, 89 ddi_dma_unbindhdl, 90 ddi_dma_flush, 91 ddi_dma_win, 92 ddi_dma_mctl, 93 pci_ctlops, 94 ddi_bus_prop_op, 95 0, /* (*bus_get_eventcookie)(); */ 96 0, /* (*bus_add_eventcall)(); */ 97 0, /* (*bus_remove_eventcall)(); */ 98 0, /* (*bus_post_event)(); */ 99 0, /* (*bus_intr_ctl)(); */ 100 0, /* (*bus_config)(); */ 101 0, /* (*bus_unconfig)(); */ 102 NULL, /* (*bus_fm_init)(); */ 103 NULL, /* (*bus_fm_fini)(); */ 104 NULL, /* (*bus_fm_access_enter)(); */ 105 NULL, /* (*bus_fm_access_exit)(); */ 106 NULL, /* (*bus_power)(); */ 107 pci_intr_ops /* (*bus_intr_op)(); */ 108 }; 109 110 static int pci_open(dev_t *devp, int flags, int otyp, cred_t *credp); 111 static int pci_close(dev_t dev, int flags, int otyp, cred_t *credp); 112 static int pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 113 int *rvalp); 114 static int pci_prop_op(dev_t dev, dev_info_t *devi, ddi_prop_op_t prop_op, 115 int flags, char *name, caddr_t valuep, int *lengthp); 116 117 /* 118 * One goal here is to leverage off of the pcihp.c source without making 119 * changes to it. Call into it's cb_ops directly if needed, piggybacking 120 * anything else needed by the pci_tools.c module. Only pci_tools and pcihp 121 * will be opening PCI nexus driver file descriptors. 122 */ 123 124 struct cb_ops pci_cb_ops = { 125 pci_open, /* open */ 126 pci_close, /* close */ 127 nodev, /* strategy */ 128 nodev, /* print */ 129 nodev, /* dump */ 130 nodev, /* read */ 131 nodev, /* write */ 132 pci_ioctl, /* ioctl */ 133 nodev, /* devmap */ 134 nodev, /* mmap */ 135 nodev, /* segmap */ 136 nochpoll, /* poll */ 137 pci_prop_op, /* cb_prop_op */ 138 NULL, /* streamtab */ 139 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ 140 CB_REV, /* rev */ 141 nodev, /* int (*cb_aread)() */ 142 nodev /* int (*cb_awrite)() */ 143 }; 144 145 /* 146 * Device Node Operation functions 147 */ 148 static int pci_info(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, 149 void **result); 150 static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 151 static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 152 153 struct dev_ops pci_ops = { 154 DEVO_REV, /* devo_rev */ 155 0, /* refcnt */ 156 pci_info, /* info */ 157 nulldev, /* identify */ 158 nulldev, /* probe */ 159 pci_attach, /* attach */ 160 pci_detach, /* detach */ 161 nulldev, /* reset */ 162 &pci_cb_ops, /* driver operations */ 163 &pci_bus_ops /* bus operations */ 164 }; 165 166 /* 167 * Internal routines in support of particular pci_ctlops. 168 */ 169 static int pci_removechild(dev_info_t *child); 170 static int pci_initchild(dev_info_t *child); 171 172 /* 173 * Miscellaneous internal functions 174 */ 175 static int pci_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp); 176 177 /* 178 * These are the access routines. The pci_bus_map sets the handle 179 * to point to these. 180 */ 181 static uint8_t pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr); 182 static uint16_t pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr); 183 static uint32_t pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr); 184 static uint64_t pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr); 185 186 static void pci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr, 187 uint8_t value); 188 static void pci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr, 189 uint16_t value); 190 static void pci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr, 191 uint32_t value); 192 static void pci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr, 193 uint64_t value); 194 195 static void pci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, 196 uint8_t *dev_addr, size_t repcount, uint_t flags); 197 static void pci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 198 uint16_t *dev_addr, size_t repcount, uint_t flags); 199 static void pci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 200 uint32_t *dev_addr, size_t repcount, uint_t flags); 201 static void pci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 202 uint64_t *dev_addr, size_t repcount, uint_t flags); 203 204 static void pci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, 205 uint8_t *dev_addr, size_t repcount, uint_t flags); 206 static void pci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 207 uint16_t *dev_addr, size_t repcount, uint_t flags); 208 static void pci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 209 uint32_t *dev_addr, size_t repcount, uint_t flags); 210 static void pci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 211 uint64_t *dev_addr, size_t repcount, uint_t flags); 212 213 /* 214 * Module linkage information for the kernel. 215 */ 216 217 static struct modldrv modldrv = { 218 &mod_driverops, /* Type of module */ 219 "host to PCI nexus driver %I%", 220 &pci_ops, /* driver ops */ 221 }; 222 223 static struct modlinkage modlinkage = { 224 MODREV_1, 225 (void *)&modldrv, 226 NULL 227 }; 228 229 int 230 _init(void) 231 { 232 int e; 233 234 /* 235 * Initialize per-pci bus soft state pointer. 236 */ 237 e = ddi_soft_state_init(&pci_statep, sizeof (pci_state_t), 1); 238 if (e != 0) 239 return (e); 240 241 if ((e = mod_install(&modlinkage)) != 0) 242 ddi_soft_state_fini(&pci_statep); 243 244 return (e); 245 } 246 247 int 248 _fini(void) 249 { 250 int rc; 251 252 rc = mod_remove(&modlinkage); 253 if (rc != 0) 254 return (rc); 255 256 ddi_soft_state_fini(&pci_statep); 257 258 return (rc); 259 } 260 261 int 262 _info(struct modinfo *modinfop) 263 { 264 return (mod_info(&modlinkage, modinfop)); 265 } 266 267 /*ARGSUSED*/ 268 static int 269 pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 270 { 271 /* 272 * Use the minor number as constructed by pcihp, as the index value to 273 * ddi_soft_state_zalloc. 274 */ 275 int instance = ddi_get_instance(devi); 276 pci_state_t *pcip = NULL; 277 278 if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci") 279 != DDI_PROP_SUCCESS) { 280 cmn_err(CE_WARN, "pci: 'device_type' prop create failed"); 281 } 282 283 if (ddi_soft_state_zalloc(pci_statep, instance) == DDI_SUCCESS) { 284 pcip = ddi_get_soft_state(pci_statep, instance); 285 } 286 287 if (pcip == NULL) { 288 goto bad_soft_state; 289 } 290 291 pcip->pci_dip = devi; 292 293 /* 294 * Initialize hotplug support on this bus. At minimum 295 * (for non hotplug bus) this would create ":devctl" minor 296 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls 297 * to this bus. 298 */ 299 if (pcihp_init(devi) != DDI_SUCCESS) { 300 cmn_err(CE_WARN, "pci: Failed to setup hotplug framework"); 301 goto bad_pcihp_init; 302 } 303 304 if (pcitool_init(devi) != DDI_SUCCESS) { 305 goto bad_pcitool_init; 306 } 307 308 ddi_report_dev(devi); 309 310 return (DDI_SUCCESS); 311 312 bad_pcitool_init: 313 (void) pcihp_uninit(devi); 314 bad_pcihp_init: 315 ddi_soft_state_free(pci_statep, instance); 316 bad_soft_state: 317 return (DDI_FAILURE); 318 } 319 320 /*ARGSUSED*/ 321 static int 322 pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 323 { 324 /* Uninitialize pcitool support. */ 325 pcitool_uninit(devi); 326 327 /* Uninitialize hotplug support on this bus. */ 328 (void) pcihp_uninit(devi); 329 330 ddi_soft_state_free(pci_statep, DIP_TO_MINOR(devi)); 331 332 return (DDI_SUCCESS); 333 } 334 335 static int 336 pci_get_reg_prop(dev_info_t *dip, pci_regspec_t *pci_rp) 337 { 338 pci_regspec_t *assigned_addr; 339 int assigned_addr_len; 340 uint_t phys_hi; 341 int i; 342 int rc; 343 int number; 344 345 phys_hi = pci_rp->pci_phys_hi; 346 if (((phys_hi & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG) || 347 (phys_hi & PCI_RELOCAT_B)) 348 return (DDI_SUCCESS); 349 350 /* 351 * the "reg" property specifies relocatable, get and interpret the 352 * "assigned-addresses" property. 353 */ 354 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 355 DDI_PROP_DONTPASS, "assigned-addresses", 356 (int **)&assigned_addr, (uint_t *)&assigned_addr_len); 357 if (rc != DDI_PROP_SUCCESS) 358 return (DDI_FAILURE); 359 360 /* 361 * Scan the "assigned-addresses" for one that matches the specified 362 * "reg" property entry. 363 */ 364 phys_hi &= PCI_CONF_ADDR_MASK; 365 number = assigned_addr_len / (sizeof (pci_regspec_t) / sizeof (int)); 366 for (i = 0; i < number; i++) { 367 if ((assigned_addr[i].pci_phys_hi & PCI_CONF_ADDR_MASK) == 368 phys_hi) { 369 pci_rp->pci_phys_mid = assigned_addr[i].pci_phys_mid; 370 pci_rp->pci_phys_low = assigned_addr[i].pci_phys_low; 371 ddi_prop_free(assigned_addr); 372 return (DDI_SUCCESS); 373 } 374 } 375 376 ddi_prop_free(assigned_addr); 377 return (DDI_FAILURE); 378 } 379 380 static int 381 pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 382 off_t offset, off_t len, caddr_t *vaddrp) 383 { 384 struct regspec reg; 385 ddi_map_req_t mr; 386 ddi_acc_hdl_t *hp; 387 ddi_acc_impl_t *ap; 388 pci_regspec_t pci_reg; 389 pci_regspec_t *pci_rp; 390 int rnumber; 391 int length; 392 int rc; 393 pci_acc_cfblk_t *cfp; 394 int space; 395 396 397 mr = *mp; /* Get private copy of request */ 398 mp = &mr; 399 400 /* 401 * check for register number 402 */ 403 switch (mp->map_type) { 404 case DDI_MT_REGSPEC: 405 pci_reg = *(pci_regspec_t *)(mp->map_obj.rp); 406 pci_rp = &pci_reg; 407 if (pci_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS) 408 return (DDI_FAILURE); 409 break; 410 case DDI_MT_RNUMBER: 411 rnumber = mp->map_obj.rnumber; 412 /* 413 * get ALL "reg" properties for dip, select the one of 414 * of interest. In x86, "assigned-addresses" property 415 * is identical to the "reg" property, so there is no 416 * need to cross check the two to determine the physical 417 * address of the registers. 418 * This routine still performs some validity checks to 419 * make sure that everything is okay. 420 */ 421 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, 422 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, 423 (uint_t *)&length); 424 if (rc != DDI_PROP_SUCCESS) { 425 return (DDI_FAILURE); 426 } 427 428 /* 429 * validate the register number. 430 */ 431 length /= (sizeof (pci_regspec_t) / sizeof (int)); 432 if (rnumber >= length) { 433 ddi_prop_free(pci_rp); 434 return (DDI_FAILURE); 435 } 436 437 /* 438 * copy the required entry. 439 */ 440 pci_reg = pci_rp[rnumber]; 441 442 /* 443 * free the memory allocated by ddi_prop_lookup_int_array 444 */ 445 ddi_prop_free(pci_rp); 446 447 pci_rp = &pci_reg; 448 if (pci_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS) 449 return (DDI_FAILURE); 450 mp->map_type = DDI_MT_REGSPEC; 451 break; 452 default: 453 return (DDI_ME_INVAL); 454 } 455 456 space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M; 457 458 /* 459 * check for unmap and unlock of address space 460 */ 461 if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) { 462 /* 463 * Adjust offset and length 464 * A non-zero length means override the one in the regspec. 465 */ 466 pci_rp->pci_phys_low += (uint_t)offset; 467 if (len != 0) 468 pci_rp->pci_size_low = len; 469 470 switch (space) { 471 case PCI_ADDR_CONFIG: 472 /* No work required on unmap of Config space */ 473 return (DDI_SUCCESS); 474 475 case PCI_ADDR_IO: 476 reg.regspec_bustype = 1; 477 break; 478 479 case PCI_ADDR_MEM64: 480 /* 481 * MEM64 requires special treatment on map, to check 482 * that the device is below 4G. On unmap, however, 483 * we can assume that everything is OK... the map 484 * must have succeeded. 485 */ 486 /* FALLTHROUGH */ 487 case PCI_ADDR_MEM32: 488 reg.regspec_bustype = 0; 489 break; 490 491 default: 492 return (DDI_FAILURE); 493 } 494 reg.regspec_addr = pci_rp->pci_phys_low; 495 reg.regspec_size = pci_rp->pci_size_low; 496 497 mp->map_obj.rp = ® 498 return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp)); 499 500 } 501 502 /* check for user mapping request - not legal for Config */ 503 if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) { 504 return (DDI_FAILURE); 505 } 506 507 /* 508 * check for config space 509 * On x86, CONFIG is not mapped via MMU and there is 510 * no endian-ness issues. Set the attr field in the handle to 511 * indicate that the common routines to call the nexus driver. 512 */ 513 if (space == PCI_ADDR_CONFIG) { 514 hp = (ddi_acc_hdl_t *)mp->map_handlep; 515 516 if (hp == NULL) { 517 /* Can't map config space without a handle */ 518 return (DDI_FAILURE); 519 } 520 521 ap = (ddi_acc_impl_t *)hp->ah_platform_private; 522 523 /* endian-ness check */ 524 if (hp->ah_acc.devacc_attr_endian_flags == DDI_STRUCTURE_BE_ACC) 525 return (DDI_FAILURE); 526 527 /* 528 * range check 529 */ 530 if ((offset >= 256) || (len > 256) || (offset + len > 256)) 531 return (DDI_FAILURE); 532 *vaddrp = (caddr_t)offset; 533 534 ap->ahi_acc_attr |= DDI_ACCATTR_CONFIG_SPACE; 535 ap->ahi_put8 = pci_config_wr8; 536 ap->ahi_get8 = pci_config_rd8; 537 ap->ahi_put64 = pci_config_wr64; 538 ap->ahi_get64 = pci_config_rd64; 539 ap->ahi_rep_put8 = pci_config_rep_wr8; 540 ap->ahi_rep_get8 = pci_config_rep_rd8; 541 ap->ahi_rep_put64 = pci_config_rep_wr64; 542 ap->ahi_rep_get64 = pci_config_rep_rd64; 543 ap->ahi_get16 = pci_config_rd16; 544 ap->ahi_get32 = pci_config_rd32; 545 ap->ahi_put16 = pci_config_wr16; 546 ap->ahi_put32 = pci_config_wr32; 547 ap->ahi_rep_get16 = pci_config_rep_rd16; 548 ap->ahi_rep_get32 = pci_config_rep_rd32; 549 ap->ahi_rep_put16 = pci_config_rep_wr16; 550 ap->ahi_rep_put32 = pci_config_rep_wr32; 551 552 /* Initialize to default check/notify functions */ 553 ap->ahi_fault_check = i_ddi_acc_fault_check; 554 ap->ahi_fault_notify = i_ddi_acc_fault_notify; 555 ap->ahi_fault = 0; 556 impl_acc_err_init(hp); 557 558 /* record the device address for future reference */ 559 cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private; 560 cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi); 561 cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 562 cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 563 564 return (DDI_SUCCESS); 565 } 566 567 /* 568 * range check 569 */ 570 if ((offset >= pci_rp->pci_size_low) || 571 (len > pci_rp->pci_size_low) || 572 (offset + len > pci_rp->pci_size_low)) { 573 return (DDI_FAILURE); 574 } 575 576 /* 577 * Adjust offset and length 578 * A non-zero length means override the one in the regspec. 579 */ 580 pci_rp->pci_phys_low += (uint_t)offset; 581 if (len != 0) 582 pci_rp->pci_size_low = len; 583 584 /* 585 * convert the pci regsec into the generic regspec used by the 586 * parent root nexus driver. 587 */ 588 switch (space) { 589 case PCI_ADDR_IO: 590 reg.regspec_bustype = 1; 591 break; 592 case PCI_ADDR_MEM64: 593 /* 594 * We can't handle 64-bit devices that are mapped above 595 * 4G or that are larger than 4G. 596 */ 597 if (pci_rp->pci_phys_mid != 0 || 598 pci_rp->pci_size_hi != 0) 599 return (DDI_FAILURE); 600 /* 601 * Other than that, we can treat them as 32-bit mappings 602 */ 603 /* FALLTHROUGH */ 604 case PCI_ADDR_MEM32: 605 reg.regspec_bustype = 0; 606 break; 607 default: 608 return (DDI_FAILURE); 609 } 610 reg.regspec_addr = pci_rp->pci_phys_low; 611 reg.regspec_size = pci_rp->pci_size_low; 612 613 mp->map_obj.rp = ® 614 return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp)); 615 } 616 617 618 /* 619 * pci_get_priority: 620 * Figure out the priority of the device 621 */ 622 static int 623 pci_get_priority(dev_info_t *dip, int inum, int *pri) 624 { 625 struct intrspec *ispec; 626 627 DDI_INTR_NEXDBG((CE_CONT, "pci_get_priority: dip = 0x%p\n", 628 (void *)dip)); 629 630 if ((ispec = (struct intrspec *)pci_intx_get_ispec(dip, dip, inum)) == 631 NULL) 632 return (DDI_FAILURE); 633 634 *pri = ispec->intrspec_pri; 635 636 return (DDI_SUCCESS); 637 } 638 639 640 /* 641 * pci_get_nintrs: 642 * Figure out how many interrupts the device supports 643 */ 644 static int 645 pci_get_nintrs(dev_info_t *dip, int type, int *nintrs) 646 { 647 int ret; 648 649 *nintrs = 0; 650 651 if (DDI_INTR_IS_MSI_OR_MSIX(type)) 652 ret = pci_msi_get_nintrs(dip, type, nintrs); 653 else { 654 ret = DDI_FAILURE; 655 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 656 "interrupts", -1) != -1) { 657 *nintrs = 1; 658 ret = DDI_SUCCESS; 659 } 660 } 661 662 return (ret); 663 } 664 665 666 /* 667 * pci_intr_ops: bus_intr_op() function for interrupt support 668 */ 669 /* ARGSUSED */ 670 static int 671 pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op, 672 ddi_intr_handle_impl_t *hdlp, void *result) 673 { 674 int priority = 0; 675 int psm_status = 0; 676 int pci_status = 0; 677 int pci_rval, psm_rval = PSM_FAILURE; 678 int types = 0; 679 int i, j; 680 int behavior; 681 ddi_intrspec_t isp; 682 struct intrspec *ispec; 683 ddi_intr_handle_impl_t tmp_hdl; 684 ddi_intr_msix_t *msix_p; 685 686 DDI_INTR_NEXDBG((CE_CONT, 687 "pci_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n", 688 (void *)pdip, (void *)rdip, intr_op, (void *)hdlp)); 689 690 /* Process the request */ 691 switch (intr_op) { 692 case DDI_INTROP_SUPPORTED_TYPES: 693 /* Fixed supported by default */ 694 *(int *)result = DDI_INTR_TYPE_FIXED; 695 696 /* Figure out if MSI or MSI-X is supported? */ 697 if (pci_msi_get_supported_type(rdip, &types) != DDI_SUCCESS) 698 return (DDI_SUCCESS); 699 700 if (psm_intr_ops != NULL) { 701 /* MSI or MSI-X is supported, OR it in */ 702 *(int *)result |= types; 703 704 tmp_hdl.ih_type = *(int *)result; 705 (void) (*psm_intr_ops)(rdip, &tmp_hdl, 706 PSM_INTR_OP_CHECK_MSI, result); 707 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: rdip: 0x%p " 708 "supported types: 0x%x\n", (void *)rdip, 709 *(int *)result)); 710 } 711 break; 712 case DDI_INTROP_NINTRS: 713 if (pci_get_nintrs(rdip, hdlp->ih_type, result) != DDI_SUCCESS) 714 return (DDI_FAILURE); 715 break; 716 case DDI_INTROP_ALLOC: 717 /* 718 * MSI or MSIX (figure out number of vectors available) 719 * FIXED interrupts: just return available interrupts 720 */ 721 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) && 722 (psm_intr_ops != NULL) && 723 (pci_get_priority(rdip, hdlp->ih_inum, 724 &priority) == DDI_SUCCESS)) { 725 hdlp->ih_pri = priority; 726 behavior = hdlp->ih_scratch2; 727 (void) (*psm_intr_ops)(rdip, hdlp, 728 PSM_INTR_OP_ALLOC_VECTORS, result); 729 730 /* verify behavior flag and take appropriate action */ 731 if ((behavior == DDI_INTR_ALLOC_STRICT) && 732 (*(int *)result < hdlp->ih_scratch1)) { 733 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: " 734 "behavior %x, couldn't get enough intrs\n", 735 behavior)); 736 hdlp->ih_scratch1 = *(int *)result; 737 (void) (*psm_intr_ops)(rdip, hdlp, 738 PSM_INTR_OP_FREE_VECTORS, NULL); 739 return (DDI_EAGAIN); 740 } 741 742 if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) { 743 if (!(msix_p = i_ddi_get_msix(hdlp->ih_dip))) { 744 msix_p = pci_msix_init(hdlp->ih_dip); 745 if (msix_p) 746 i_ddi_set_msix(hdlp->ih_dip, 747 msix_p); 748 } 749 msix_p->msix_intrs_in_use += *(int *)result; 750 } 751 752 } else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) { 753 /* Figure out if this device supports MASKING */ 754 pci_rval = pci_intx_get_cap(rdip, &pci_status); 755 if (pci_rval == DDI_SUCCESS && pci_status) 756 hdlp->ih_cap |= pci_status; 757 *(int *)result = 1; /* DDI_INTR_TYPE_FIXED */ 758 } else 759 return (DDI_FAILURE); 760 break; 761 case DDI_INTROP_FREE: 762 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) && 763 (psm_intr_ops != NULL)) { 764 (void) (*psm_intr_ops)(rdip, hdlp, 765 PSM_INTR_OP_FREE_VECTORS, NULL); 766 767 if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) { 768 msix_p = i_ddi_get_msix(hdlp->ih_dip); 769 if (msix_p && 770 --msix_p->msix_intrs_in_use == 0) { 771 pci_msix_fini(msix_p); 772 i_ddi_set_msix(hdlp->ih_dip, NULL); 773 } 774 } 775 } 776 break; 777 case DDI_INTROP_GETPRI: 778 if (pci_get_priority(rdip, hdlp->ih_inum, &priority) != 779 DDI_SUCCESS) /* Get the priority */ 780 return (DDI_FAILURE); 781 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: priority = 0x%x\n", 782 priority)); 783 *(int *)result = priority; 784 break; 785 case DDI_INTROP_SETPRI: 786 /* Validate the interrupt priority passed */ 787 if (*(int *)result > LOCK_LEVEL) 788 return (DDI_FAILURE); 789 790 /* Ensure that PSM is all initialized */ 791 if (psm_intr_ops == NULL) 792 return (DDI_FAILURE); 793 794 /* Change the priority */ 795 if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_PRI, result) == 796 PSM_FAILURE) 797 return (DDI_FAILURE); 798 799 /* update ispec */ 800 isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum); 801 ispec = (struct intrspec *)isp; 802 ispec->intrspec_pri = *(int *)result; 803 break; 804 case DDI_INTROP_ADDISR: 805 /* update ispec */ 806 isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum); 807 ispec = (struct intrspec *)isp; 808 ispec->intrspec_func = hdlp->ih_cb_func; 809 break; 810 case DDI_INTROP_REMISR: 811 /* Get the interrupt structure pointer */ 812 isp = pci_intx_get_ispec(pdip, rdip, (int)hdlp->ih_inum); 813 ispec = (struct intrspec *)isp; 814 ispec->intrspec_func = (uint_t (*)()) 0; 815 break; 816 case DDI_INTROP_GETCAP: 817 /* 818 * First check the config space and/or 819 * MSI capability register(s) 820 */ 821 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) 822 pci_rval = pci_msi_get_cap(rdip, hdlp->ih_type, 823 &pci_status); 824 else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) 825 pci_rval = pci_intx_get_cap(rdip, &pci_status); 826 827 /* next check with pcplusmp */ 828 if (psm_intr_ops != NULL) 829 psm_rval = (*psm_intr_ops)(rdip, hdlp, 830 PSM_INTR_OP_GET_CAP, &psm_status); 831 832 DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned psm_rval = %x, " 833 "psm_status = %x, pci_rval = %x, pci_status = %x\n", 834 psm_rval, psm_status, pci_rval, pci_status)); 835 836 if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) { 837 *(int *)result = 0; 838 return (DDI_FAILURE); 839 } 840 841 if (psm_rval == PSM_SUCCESS) 842 *(int *)result = psm_status; 843 844 if (pci_rval == DDI_SUCCESS) 845 *(int *)result |= pci_status; 846 847 DDI_INTR_NEXDBG((CE_CONT, "pci: GETCAP returned = %x\n", 848 *(int *)result)); 849 break; 850 case DDI_INTROP_SETCAP: 851 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: SETCAP cap=0x%x\n", 852 *(int *)result)); 853 if (psm_intr_ops == NULL) 854 return (DDI_FAILURE); 855 856 if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result)) { 857 DDI_INTR_NEXDBG((CE_CONT, "GETCAP: psm_intr_ops" 858 " returned failure\n")); 859 return (DDI_FAILURE); 860 } 861 break; 862 case DDI_INTROP_ENABLE: 863 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: ENABLE\n")); 864 if (psm_intr_ops == NULL) 865 return (DDI_FAILURE); 866 867 if (pci_enable_intr(pdip, rdip, hdlp, hdlp->ih_inum) != 868 DDI_SUCCESS) 869 return (DDI_FAILURE); 870 871 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: ENABLE vector=0x%x\n", 872 hdlp->ih_vector)); 873 break; 874 case DDI_INTROP_DISABLE: 875 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: DISABLE\n")); 876 if (psm_intr_ops == NULL) 877 return (DDI_FAILURE); 878 879 pci_disable_intr(pdip, rdip, hdlp, hdlp->ih_inum); 880 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: DISABLE vector = %x\n", 881 hdlp->ih_vector)); 882 break; 883 case DDI_INTROP_BLOCKENABLE: 884 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKENABLE\n")); 885 if (hdlp->ih_type != DDI_INTR_TYPE_MSI) { 886 DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: not MSI\n")); 887 return (DDI_FAILURE); 888 } 889 890 /* Check if psm_intr_ops is NULL? */ 891 if (psm_intr_ops == NULL) 892 return (DDI_FAILURE); 893 894 for (i = 0; i < hdlp->ih_scratch1; i++) { 895 if (pci_enable_intr(pdip, rdip, hdlp, 896 hdlp->ih_inum + i) != DDI_SUCCESS) { 897 DDI_INTR_NEXDBG((CE_CONT, "BLOCKENABLE: " 898 "pci_enable_intr failed for %d\n", i)); 899 for (j = 0; j < i; j++) 900 pci_disable_intr(pdip, rdip, hdlp, 901 hdlp->ih_inum + j); 902 return (DDI_FAILURE); 903 } 904 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKENABLE " 905 "inum %x done\n", hdlp->ih_inum + i)); 906 } 907 break; 908 case DDI_INTROP_BLOCKDISABLE: 909 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKDISABLE\n")); 910 if (hdlp->ih_type != DDI_INTR_TYPE_MSI) { 911 DDI_INTR_NEXDBG((CE_CONT, "BLOCKDISABLE: not MSI\n")); 912 return (DDI_FAILURE); 913 } 914 915 /* Check if psm_intr_ops is present */ 916 if (psm_intr_ops == NULL) 917 return (DDI_FAILURE); 918 919 for (i = 0; i < hdlp->ih_scratch1; i++) { 920 pci_disable_intr(pdip, rdip, hdlp, hdlp->ih_inum + i); 921 DDI_INTR_NEXDBG((CE_CONT, "pci_intr_ops: BLOCKDISABLE " 922 "inum %x done\n", hdlp->ih_inum + i)); 923 } 924 break; 925 case DDI_INTROP_SETMASK: 926 case DDI_INTROP_CLRMASK: 927 /* 928 * First handle in the config space 929 */ 930 if (intr_op == DDI_INTROP_SETMASK) { 931 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) 932 pci_status = pci_msi_set_mask(rdip, 933 hdlp->ih_type, hdlp->ih_inum); 934 else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) 935 pci_status = pci_intx_set_mask(rdip); 936 } else { 937 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) 938 pci_status = pci_msi_clr_mask(rdip, 939 hdlp->ih_type, hdlp->ih_inum); 940 else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) 941 pci_status = pci_intx_clr_mask(rdip); 942 } 943 944 /* For MSI/X; no need to check with pcplusmp */ 945 if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) 946 return (pci_status); 947 948 /* For fixed interrupts only: handle config space first */ 949 if (hdlp->ih_type == DDI_INTR_TYPE_FIXED && 950 pci_status == DDI_SUCCESS) 951 break; 952 953 /* For fixed interrupts only: confer with pcplusmp next */ 954 if (psm_intr_ops != NULL) { 955 /* If interrupt is shared; do nothing */ 956 psm_rval = (*psm_intr_ops)(rdip, hdlp, 957 PSM_INTR_OP_GET_SHARED, &psm_status); 958 959 if (psm_rval == PSM_FAILURE || psm_status == 1) 960 return (pci_status); 961 962 /* Now, pcplusmp should try to set/clear the mask */ 963 if (intr_op == DDI_INTROP_SETMASK) 964 psm_rval = (*psm_intr_ops)(rdip, hdlp, 965 PSM_INTR_OP_SET_MASK, NULL); 966 else 967 psm_rval = (*psm_intr_ops)(rdip, hdlp, 968 PSM_INTR_OP_CLEAR_MASK, NULL); 969 } 970 return ((psm_rval == PSM_FAILURE) ? DDI_FAILURE : DDI_SUCCESS); 971 case DDI_INTROP_GETPENDING: 972 /* 973 * First check the config space and/or 974 * MSI capability register(s) 975 */ 976 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) 977 pci_rval = pci_msi_get_pending(rdip, hdlp->ih_type, 978 hdlp->ih_inum, &pci_status); 979 else if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) 980 pci_rval = pci_intx_get_pending(rdip, &pci_status); 981 982 /* On failure; next try with pcplusmp */ 983 if (pci_rval != DDI_SUCCESS && psm_intr_ops != NULL) 984 psm_rval = (*psm_intr_ops)(rdip, hdlp, 985 PSM_INTR_OP_GET_PENDING, &psm_status); 986 987 DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned " 988 "psm_rval = %x, psm_status = %x, pci_rval = %x, " 989 "pci_status = %x\n", psm_rval, psm_status, pci_rval, 990 pci_status)); 991 if (psm_rval == PSM_FAILURE && pci_rval == DDI_FAILURE) { 992 *(int *)result = 0; 993 return (DDI_FAILURE); 994 } 995 996 if (psm_rval != PSM_FAILURE) 997 *(int *)result = psm_status; 998 else if (pci_rval != DDI_FAILURE) 999 *(int *)result = pci_status; 1000 DDI_INTR_NEXDBG((CE_CONT, "pci: GETPENDING returned = %x\n", 1001 *(int *)result)); 1002 break; 1003 case DDI_INTROP_NAVAIL: 1004 if ((psm_intr_ops != NULL) && (pci_get_priority(rdip, 1005 hdlp->ih_inum, &priority) == DDI_SUCCESS)) { 1006 /* Priority in the handle not initialized yet */ 1007 hdlp->ih_pri = priority; 1008 (void) (*psm_intr_ops)(rdip, hdlp, 1009 PSM_INTR_OP_NAVAIL_VECTORS, result); 1010 } else { 1011 *(int *)result = 1; 1012 } 1013 DDI_INTR_NEXDBG((CE_CONT, "pci: NAVAIL returned = %x\n", 1014 *(int *)result)); 1015 break; 1016 default: 1017 return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result)); 1018 } 1019 1020 return (DDI_SUCCESS); 1021 } 1022 1023 1024 static int 1025 pci_enable_intr(dev_info_t *pdip, dev_info_t *rdip, 1026 ddi_intr_handle_impl_t *hdlp, uint32_t inum) 1027 { 1028 int vector; 1029 struct intrspec *ispec; 1030 1031 DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: hdlp %p inum %x\n", 1032 (void *)hdlp, inum)); 1033 1034 /* Translate the interrupt if needed */ 1035 ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum); 1036 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) 1037 ispec->intrspec_vec = inum; 1038 hdlp->ih_private = (void *)ispec; 1039 1040 /* translate the interrupt if needed */ 1041 (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &vector); 1042 DDI_INTR_NEXDBG((CE_CONT, "pci_enable_intr: priority=%x vector=%x\n", 1043 hdlp->ih_pri, vector)); 1044 1045 /* Add the interrupt handler */ 1046 if (!add_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, 1047 DEVI(rdip)->devi_name, vector, hdlp->ih_cb_arg1, 1048 hdlp->ih_cb_arg2, rdip)) 1049 return (DDI_FAILURE); 1050 1051 return (DDI_SUCCESS); 1052 } 1053 1054 1055 static void 1056 pci_disable_intr(dev_info_t *pdip, dev_info_t *rdip, 1057 ddi_intr_handle_impl_t *hdlp, uint32_t inum) 1058 { 1059 int vector; 1060 struct intrspec *ispec; 1061 1062 DDI_INTR_NEXDBG((CE_CONT, "pci_disable_intr: \n")); 1063 ispec = (struct intrspec *)pci_intx_get_ispec(pdip, rdip, (int)inum); 1064 if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type)) 1065 ispec->intrspec_vec = inum; 1066 hdlp->ih_private = (void *)ispec; 1067 1068 /* translate the interrupt if needed */ 1069 (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &vector); 1070 1071 /* Disable the interrupt handler */ 1072 rem_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, vector); 1073 } 1074 1075 1076 /*ARGSUSED*/ 1077 static int 1078 pci_ctlops(dev_info_t *dip, dev_info_t *rdip, 1079 ddi_ctl_enum_t ctlop, void *arg, void *result) 1080 { 1081 pci_regspec_t *drv_regp; 1082 uint_t reglen; 1083 int rn; 1084 int totreg; 1085 1086 switch (ctlop) { 1087 case DDI_CTLOPS_REPORTDEV: 1088 if (rdip == (dev_info_t *)0) 1089 return (DDI_FAILURE); 1090 cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n", 1091 ddi_node_name(rdip), ddi_get_name_addr(rdip), 1092 ddi_driver_name(rdip), 1093 ddi_get_instance(rdip)); 1094 return (DDI_SUCCESS); 1095 1096 case DDI_CTLOPS_INITCHILD: 1097 return (pci_initchild((dev_info_t *)arg)); 1098 1099 case DDI_CTLOPS_UNINITCHILD: 1100 return (pci_removechild((dev_info_t *)arg)); 1101 1102 case DDI_CTLOPS_NINTRS: 1103 if (ddi_get_parent_data(rdip)) 1104 *(int *)result = 1; 1105 else 1106 *(int *)result = 0; 1107 return (DDI_SUCCESS); 1108 1109 case DDI_CTLOPS_XLATE_INTRS: 1110 return (DDI_SUCCESS); 1111 1112 case DDI_CTLOPS_SIDDEV: 1113 return (DDI_SUCCESS); 1114 1115 case DDI_CTLOPS_REGSIZE: 1116 case DDI_CTLOPS_NREGS: 1117 if (rdip == (dev_info_t *)0) 1118 return (DDI_FAILURE); 1119 1120 *(int *)result = 0; 1121 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, 1122 DDI_PROP_DONTPASS, "reg", (int **)&drv_regp, 1123 ®len) != DDI_PROP_SUCCESS) { 1124 return (DDI_FAILURE); 1125 } 1126 1127 totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t); 1128 if (ctlop == DDI_CTLOPS_NREGS) 1129 *(int *)result = totreg; 1130 else if (ctlop == DDI_CTLOPS_REGSIZE) { 1131 rn = *(int *)arg; 1132 if (rn >= totreg) { 1133 ddi_prop_free(drv_regp); 1134 return (DDI_FAILURE); 1135 } 1136 *(off_t *)result = drv_regp[rn].pci_size_low; 1137 } 1138 ddi_prop_free(drv_regp); 1139 1140 return (DDI_SUCCESS); 1141 1142 case DDI_CTLOPS_POWER: { 1143 power_req_t *reqp = (power_req_t *)arg; 1144 /* 1145 * We currently understand reporting of PCI_PM_IDLESPEED 1146 * capability. Everything else is passed up. 1147 */ 1148 if ((reqp->request_type == PMR_REPORT_PMCAP) && 1149 (reqp->req.report_pmcap_req.cap == PCI_PM_IDLESPEED)) { 1150 1151 return (DDI_SUCCESS); 1152 } 1153 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 1154 } 1155 1156 default: 1157 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 1158 } 1159 1160 /* NOTREACHED */ 1161 1162 } 1163 1164 /* 1165 * Assign the address portion of the node name 1166 */ 1167 static int 1168 pci_name_child(dev_info_t *child, char *name, int namelen) 1169 { 1170 pci_regspec_t *pci_rp; 1171 char **unit_addr; 1172 int dev, func, length; 1173 uint_t n; 1174 1175 if (ndi_dev_is_persistent_node(child) == 0) { 1176 /* 1177 * For .conf node, use "unit-address" property 1178 */ 1179 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, 1180 DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) != 1181 DDI_PROP_SUCCESS) { 1182 cmn_err(CE_WARN, 1183 "cannot find unit-address in %s.conf", 1184 ddi_get_name(child)); 1185 return (DDI_FAILURE); 1186 } 1187 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { 1188 cmn_err(CE_WARN, "unit-address property in %s.conf" 1189 " not well-formed", ddi_get_name(child)); 1190 ddi_prop_free(unit_addr); 1191 return (DDI_FAILURE); 1192 } 1193 (void) snprintf(name, namelen, "%s", *unit_addr); 1194 ddi_prop_free(unit_addr); 1195 return (DDI_SUCCESS); 1196 } 1197 1198 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, 1199 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, 1200 (uint_t *)&length) != DDI_PROP_SUCCESS) { 1201 cmn_err(CE_WARN, "cannot find reg property in %s", 1202 ddi_get_name(child)); 1203 return (DDI_FAILURE); 1204 } 1205 1206 /* copy the device identifications */ 1207 dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 1208 func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 1209 1210 /* 1211 * free the memory allocated by ddi_prop_lookup_int_array 1212 */ 1213 ddi_prop_free(pci_rp); 1214 1215 if (func != 0) { 1216 (void) snprintf(name, namelen, "%x,%x", dev, func); 1217 } else { 1218 (void) snprintf(name, namelen, "%x", dev); 1219 } 1220 1221 return (DDI_SUCCESS); 1222 } 1223 1224 static int 1225 pci_initchild(dev_info_t *child) 1226 { 1227 struct ddi_parent_private_data *pdptr; 1228 char name[80]; 1229 1230 if (pci_name_child(child, name, 80) != DDI_SUCCESS) { 1231 return (DDI_FAILURE); 1232 } 1233 ddi_set_name_addr(child, name); 1234 1235 /* 1236 * Pseudo nodes indicate a prototype node with per-instance 1237 * properties to be merged into the real h/w device node. 1238 * The interpretation of the unit-address is DD[,F] 1239 * where DD is the device id and F is the function. 1240 */ 1241 if (ndi_dev_is_persistent_node(child) == 0) { 1242 extern int pci_allow_pseudo_children; 1243 1244 ddi_set_parent_data(child, NULL); 1245 1246 /* 1247 * Try to merge the properties from this prototype 1248 * node into real h/w nodes. 1249 */ 1250 if (ndi_merge_node(child, pci_name_child) == DDI_SUCCESS) { 1251 /* 1252 * Merged ok - return failure to remove the node. 1253 */ 1254 ddi_set_name_addr(child, NULL); 1255 return (DDI_FAILURE); 1256 } 1257 1258 /* workaround for ddivs to run under PCI */ 1259 if (pci_allow_pseudo_children) { 1260 /* 1261 * If the "interrupts" property doesn't exist, 1262 * this must be the ddivs no-intr case, and it returns 1263 * DDI_SUCCESS instead of DDI_FAILURE. 1264 */ 1265 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, 1266 DDI_PROP_DONTPASS, "interrupts", -1) == -1) 1267 return (DDI_SUCCESS); 1268 /* 1269 * Create the ddi_parent_private_data for a pseudo 1270 * child. 1271 */ 1272 pdptr = (struct ddi_parent_private_data *)kmem_zalloc( 1273 (sizeof (struct ddi_parent_private_data) + 1274 sizeof (struct intrspec)), KM_SLEEP); 1275 pdptr->par_intr = (struct intrspec *)(pdptr + 1); 1276 pdptr->par_nintr = 1; 1277 ddi_set_parent_data(child, pdptr); 1278 return (DDI_SUCCESS); 1279 } 1280 1281 /* 1282 * The child was not merged into a h/w node, 1283 * but there's not much we can do with it other 1284 * than return failure to cause the node to be removed. 1285 */ 1286 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged", 1287 ddi_get_name(child), ddi_get_name_addr(child), 1288 ddi_get_name(child)); 1289 ddi_set_name_addr(child, NULL); 1290 return (DDI_NOT_WELL_FORMED); 1291 } 1292 1293 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 1294 "interrupts", -1) != -1) { 1295 pdptr = (struct ddi_parent_private_data *) 1296 kmem_zalloc((sizeof (struct ddi_parent_private_data) + 1297 sizeof (struct intrspec)), KM_SLEEP); 1298 pdptr->par_intr = (struct intrspec *)(pdptr + 1); 1299 pdptr->par_nintr = 1; 1300 ddi_set_parent_data(child, pdptr); 1301 } else 1302 ddi_set_parent_data(child, NULL); 1303 1304 return (DDI_SUCCESS); 1305 } 1306 1307 static int 1308 pci_removechild(dev_info_t *dip) 1309 { 1310 struct ddi_parent_private_data *pdptr; 1311 1312 if ((pdptr = ddi_get_parent_data(dip)) != NULL) { 1313 kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec))); 1314 ddi_set_parent_data(dip, NULL); 1315 } 1316 ddi_set_name_addr(dip, NULL); 1317 1318 /* 1319 * Strip the node to properly convert it back to prototype form 1320 */ 1321 ddi_remove_minor_node(dip, NULL); 1322 1323 impl_rem_dev_props(dip); 1324 1325 return (DDI_SUCCESS); 1326 } 1327 1328 1329 /* 1330 * These are the get and put functions to be shared with drivers. The 1331 * mutex locking is done inside the functions referenced, rather than 1332 * here, and is thus shared across PCI child drivers and any other 1333 * consumers of PCI config space (such as the ACPI subsystem). 1334 * 1335 * The configuration space addresses come in as pointers. This is fine on 1336 * a 32-bit system, where the VM space and configuration space are the same 1337 * size. It's not such a good idea on a 64-bit system, where memory 1338 * addresses are twice as large as configuration space addresses. At some 1339 * point in the call tree we need to take a stand and say "you are 32-bit 1340 * from this time forth", and this seems like a nice self-contained place. 1341 */ 1342 1343 static uint8_t 1344 pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr) 1345 { 1346 pci_acc_cfblk_t *cfp; 1347 uint8_t rval; 1348 int reg; 1349 1350 ASSERT64(((uintptr_t)addr >> 32) == 0); 1351 1352 reg = (int)(uintptr_t)addr; 1353 1354 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1355 1356 rval = (*pci_getb_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum, 1357 reg); 1358 1359 return (rval); 1360 } 1361 1362 static void 1363 pci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, 1364 uint8_t *dev_addr, size_t repcount, uint_t flags) 1365 { 1366 uint8_t *h, *d; 1367 1368 h = host_addr; 1369 d = dev_addr; 1370 1371 if (flags == DDI_DEV_AUTOINCR) 1372 for (; repcount; repcount--) 1373 *h++ = pci_config_rd8(hdlp, d++); 1374 else 1375 for (; repcount; repcount--) 1376 *h++ = pci_config_rd8(hdlp, d); 1377 } 1378 1379 static uint16_t 1380 pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr) 1381 { 1382 pci_acc_cfblk_t *cfp; 1383 uint16_t rval; 1384 int reg; 1385 1386 ASSERT64(((uintptr_t)addr >> 32) == 0); 1387 1388 reg = (int)(uintptr_t)addr; 1389 1390 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1391 1392 rval = (*pci_getw_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum, 1393 reg); 1394 1395 return (rval); 1396 } 1397 1398 static void 1399 pci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 1400 uint16_t *dev_addr, size_t repcount, uint_t flags) 1401 { 1402 uint16_t *h, *d; 1403 1404 h = host_addr; 1405 d = dev_addr; 1406 1407 if (flags == DDI_DEV_AUTOINCR) 1408 for (; repcount; repcount--) 1409 *h++ = pci_config_rd16(hdlp, d++); 1410 else 1411 for (; repcount; repcount--) 1412 *h++ = pci_config_rd16(hdlp, d); 1413 } 1414 1415 static uint32_t 1416 pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr) 1417 { 1418 pci_acc_cfblk_t *cfp; 1419 uint32_t rval; 1420 int reg; 1421 1422 ASSERT64(((uintptr_t)addr >> 32) == 0); 1423 1424 reg = (int)(uintptr_t)addr; 1425 1426 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1427 1428 rval = (*pci_getl_func)(cfp->c_busnum, cfp->c_devnum, 1429 cfp->c_funcnum, reg); 1430 1431 return (rval); 1432 } 1433 1434 static void 1435 pci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 1436 uint32_t *dev_addr, size_t repcount, uint_t flags) 1437 { 1438 uint32_t *h, *d; 1439 1440 h = host_addr; 1441 d = dev_addr; 1442 1443 if (flags == DDI_DEV_AUTOINCR) 1444 for (; repcount; repcount--) 1445 *h++ = pci_config_rd32(hdlp, d++); 1446 else 1447 for (; repcount; repcount--) 1448 *h++ = pci_config_rd32(hdlp, d); 1449 } 1450 1451 1452 static void 1453 pci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value) 1454 { 1455 pci_acc_cfblk_t *cfp; 1456 int reg; 1457 1458 ASSERT64(((uintptr_t)addr >> 32) == 0); 1459 1460 reg = (int)(uintptr_t)addr; 1461 1462 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1463 1464 (*pci_putb_func)(cfp->c_busnum, cfp->c_devnum, 1465 cfp->c_funcnum, reg, value); 1466 } 1467 1468 static void 1469 pci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, 1470 uint8_t *dev_addr, size_t repcount, uint_t flags) 1471 { 1472 uint8_t *h, *d; 1473 1474 h = host_addr; 1475 d = dev_addr; 1476 1477 if (flags == DDI_DEV_AUTOINCR) 1478 for (; repcount; repcount--) 1479 pci_config_wr8(hdlp, d++, *h++); 1480 else 1481 for (; repcount; repcount--) 1482 pci_config_wr8(hdlp, d, *h++); 1483 } 1484 1485 static void 1486 pci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) 1487 { 1488 pci_acc_cfblk_t *cfp; 1489 int reg; 1490 1491 ASSERT64(((uintptr_t)addr >> 32) == 0); 1492 1493 reg = (int)(uintptr_t)addr; 1494 1495 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1496 1497 (*pci_putw_func)(cfp->c_busnum, cfp->c_devnum, 1498 cfp->c_funcnum, reg, value); 1499 } 1500 1501 static void 1502 pci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 1503 uint16_t *dev_addr, size_t repcount, uint_t flags) 1504 { 1505 uint16_t *h, *d; 1506 1507 h = host_addr; 1508 d = dev_addr; 1509 1510 if (flags == DDI_DEV_AUTOINCR) 1511 for (; repcount; repcount--) 1512 pci_config_wr16(hdlp, d++, *h++); 1513 else 1514 for (; repcount; repcount--) 1515 pci_config_wr16(hdlp, d, *h++); 1516 } 1517 1518 static void 1519 pci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) 1520 { 1521 pci_acc_cfblk_t *cfp; 1522 int reg; 1523 1524 ASSERT64(((uintptr_t)addr >> 32) == 0); 1525 1526 reg = (int)(uintptr_t)addr; 1527 1528 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1529 1530 (*pci_putl_func)(cfp->c_busnum, cfp->c_devnum, 1531 cfp->c_funcnum, reg, value); 1532 } 1533 1534 static void 1535 pci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 1536 uint32_t *dev_addr, size_t repcount, uint_t flags) 1537 { 1538 uint32_t *h, *d; 1539 1540 h = host_addr; 1541 d = dev_addr; 1542 1543 if (flags == DDI_DEV_AUTOINCR) 1544 for (; repcount; repcount--) 1545 pci_config_wr32(hdlp, d++, *h++); 1546 else 1547 for (; repcount; repcount--) 1548 pci_config_wr32(hdlp, d, *h++); 1549 } 1550 1551 static uint64_t 1552 pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr) 1553 { 1554 uint32_t lw_val; 1555 uint32_t hi_val; 1556 uint32_t *dp; 1557 uint64_t val; 1558 1559 dp = (uint32_t *)addr; 1560 lw_val = pci_config_rd32(hdlp, dp); 1561 dp++; 1562 hi_val = pci_config_rd32(hdlp, dp); 1563 val = ((uint64_t)hi_val << 32) | lw_val; 1564 return (val); 1565 } 1566 1567 static void 1568 pci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) 1569 { 1570 uint32_t lw_val; 1571 uint32_t hi_val; 1572 uint32_t *dp; 1573 1574 dp = (uint32_t *)addr; 1575 lw_val = (uint32_t)(value & 0xffffffff); 1576 hi_val = (uint32_t)(value >> 32); 1577 pci_config_wr32(hdlp, dp, lw_val); 1578 dp++; 1579 pci_config_wr32(hdlp, dp, hi_val); 1580 } 1581 1582 static void 1583 pci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 1584 uint64_t *dev_addr, size_t repcount, uint_t flags) 1585 { 1586 if (flags == DDI_DEV_AUTOINCR) { 1587 for (; repcount; repcount--) 1588 *host_addr++ = pci_config_rd64(hdlp, dev_addr++); 1589 } else { 1590 for (; repcount; repcount--) 1591 *host_addr++ = pci_config_rd64(hdlp, dev_addr); 1592 } 1593 } 1594 1595 static void 1596 pci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 1597 uint64_t *dev_addr, size_t repcount, uint_t flags) 1598 { 1599 if (flags == DDI_DEV_AUTOINCR) { 1600 for (; repcount; repcount--) 1601 pci_config_wr64(hdlp, host_addr++, *dev_addr++); 1602 } else { 1603 for (; repcount; repcount--) 1604 pci_config_wr64(hdlp, host_addr++, *dev_addr); 1605 } 1606 } 1607 1608 /* 1609 * When retrofitting this module for pci_tools, functions such as open, close, 1610 * and ioctl are now pulled into this module. Before this, the functions in 1611 * the pcihp module were referenced directly. Now they are called or 1612 * referenced through the pcihp cb_ops structure from functions in this module. 1613 */ 1614 1615 static int 1616 pci_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1617 { 1618 return ((pcihp_cb_ops.cb_open)(devp, flags, otyp, credp)); 1619 } 1620 1621 static int 1622 pci_close(dev_t dev, int flags, int otyp, cred_t *credp) 1623 { 1624 return ((pcihp_cb_ops.cb_close)(dev, flags, otyp, credp)); 1625 } 1626 1627 static int 1628 pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 1629 int *rvalp) 1630 { 1631 int rv = ENOTTY; 1632 1633 minor_t minor = getminor(dev); 1634 1635 switch (PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(minor)) { 1636 case PCIHP_DEVCTL_MINOR: 1637 if (IS_DEVCTL(cmd)) 1638 rv = (pcihp_cb_ops.cb_ioctl)(dev, cmd, arg, mode, 1639 credp, rvalp); 1640 break; 1641 1642 case PCI_TOOL_REG_MINOR_NUM: 1643 1644 switch (cmd) { 1645 case PCITOOL_DEVICE_SET_REG: 1646 case PCITOOL_DEVICE_GET_REG: 1647 1648 /* Require full privileges. */ 1649 if (secpolicy_kmdb(credp)) 1650 rv = EPERM; 1651 else 1652 rv = pcitool_dev_reg_ops( 1653 dev, (void *)arg, cmd, mode); 1654 break; 1655 1656 case PCITOOL_NEXUS_SET_REG: 1657 case PCITOOL_NEXUS_GET_REG: 1658 1659 /* Require full privileges. */ 1660 if (secpolicy_kmdb(credp)) 1661 rv = EPERM; 1662 else 1663 rv = pcitool_bus_reg_ops( 1664 dev, (void *)arg, cmd, mode); 1665 break; 1666 } 1667 break; 1668 1669 case PCI_TOOL_INTR_MINOR_NUM: 1670 1671 switch (cmd) { 1672 case PCITOOL_DEVICE_SET_INTR: 1673 1674 /* Require PRIV_SYS_RES_CONFIG, same as psradm */ 1675 if (secpolicy_ponline(credp)) { 1676 rv = EPERM; 1677 break; 1678 } 1679 1680 /*FALLTHRU*/ 1681 /* These require no special privileges. */ 1682 case PCITOOL_DEVICE_GET_INTR: 1683 case PCITOOL_DEVICE_NUM_INTR: 1684 rv = pcitool_intr_admn(dev, (void *)arg, cmd, mode); 1685 break; 1686 } 1687 break; 1688 1689 default: 1690 break; 1691 } 1692 1693 return (rv); 1694 } 1695 1696 static int 1697 pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1698 int flags, char *name, caddr_t valuep, int *lengthp) 1699 { 1700 return ((pcihp_cb_ops.cb_prop_op)(dev, dip, prop_op, flags, 1701 name, valuep, lengthp)); 1702 } 1703 1704 static int 1705 pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 1706 { 1707 return (pcihp_info(dip, cmd, arg, result)); 1708 } 1709