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