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