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