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_SIDDEV: 1111 return (DDI_SUCCESS); 1112 1113 case DDI_CTLOPS_REGSIZE: 1114 case DDI_CTLOPS_NREGS: 1115 if (rdip == (dev_info_t *)0) 1116 return (DDI_FAILURE); 1117 1118 *(int *)result = 0; 1119 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, 1120 DDI_PROP_DONTPASS, "reg", (int **)&drv_regp, 1121 ®len) != DDI_PROP_SUCCESS) { 1122 return (DDI_FAILURE); 1123 } 1124 1125 totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t); 1126 if (ctlop == DDI_CTLOPS_NREGS) 1127 *(int *)result = totreg; 1128 else if (ctlop == DDI_CTLOPS_REGSIZE) { 1129 rn = *(int *)arg; 1130 if (rn >= totreg) { 1131 ddi_prop_free(drv_regp); 1132 return (DDI_FAILURE); 1133 } 1134 *(off_t *)result = drv_regp[rn].pci_size_low; 1135 } 1136 ddi_prop_free(drv_regp); 1137 1138 return (DDI_SUCCESS); 1139 1140 case DDI_CTLOPS_POWER: { 1141 power_req_t *reqp = (power_req_t *)arg; 1142 /* 1143 * We currently understand reporting of PCI_PM_IDLESPEED 1144 * capability. Everything else is passed up. 1145 */ 1146 if ((reqp->request_type == PMR_REPORT_PMCAP) && 1147 (reqp->req.report_pmcap_req.cap == PCI_PM_IDLESPEED)) { 1148 1149 return (DDI_SUCCESS); 1150 } 1151 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 1152 } 1153 1154 default: 1155 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 1156 } 1157 1158 /* NOTREACHED */ 1159 1160 } 1161 1162 /* 1163 * Assign the address portion of the node name 1164 */ 1165 static int 1166 pci_name_child(dev_info_t *child, char *name, int namelen) 1167 { 1168 pci_regspec_t *pci_rp; 1169 char **unit_addr; 1170 int dev, func, length; 1171 uint_t n; 1172 1173 if (ndi_dev_is_persistent_node(child) == 0) { 1174 /* 1175 * For .conf node, use "unit-address" property 1176 */ 1177 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, 1178 DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) != 1179 DDI_PROP_SUCCESS) { 1180 cmn_err(CE_WARN, 1181 "cannot find unit-address in %s.conf", 1182 ddi_get_name(child)); 1183 return (DDI_FAILURE); 1184 } 1185 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { 1186 cmn_err(CE_WARN, "unit-address property in %s.conf" 1187 " not well-formed", ddi_get_name(child)); 1188 ddi_prop_free(unit_addr); 1189 return (DDI_FAILURE); 1190 } 1191 (void) snprintf(name, namelen, "%s", *unit_addr); 1192 ddi_prop_free(unit_addr); 1193 return (DDI_SUCCESS); 1194 } 1195 1196 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, 1197 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, 1198 (uint_t *)&length) != DDI_PROP_SUCCESS) { 1199 cmn_err(CE_WARN, "cannot find reg property in %s", 1200 ddi_get_name(child)); 1201 return (DDI_FAILURE); 1202 } 1203 1204 /* copy the device identifications */ 1205 dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 1206 func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 1207 1208 /* 1209 * free the memory allocated by ddi_prop_lookup_int_array 1210 */ 1211 ddi_prop_free(pci_rp); 1212 1213 if (func != 0) { 1214 (void) snprintf(name, namelen, "%x,%x", dev, func); 1215 } else { 1216 (void) snprintf(name, namelen, "%x", dev); 1217 } 1218 1219 return (DDI_SUCCESS); 1220 } 1221 1222 static int 1223 pci_initchild(dev_info_t *child) 1224 { 1225 struct ddi_parent_private_data *pdptr; 1226 char name[80]; 1227 ddi_acc_handle_t config_handle; 1228 ushort_t command_preserve, command; 1229 1230 if (pci_name_child(child, name, 80) != DDI_SUCCESS) { 1231 return (DDI_FAILURE); 1232 } 1233 ddi_set_name_addr(child, name); 1234 1235 /* 1236 * Pseudo nodes indicate a prototype node with per-instance 1237 * properties to be merged into the real h/w device node. 1238 * The interpretation of the unit-address is DD[,F] 1239 * where DD is the device id and F is the function. 1240 */ 1241 if (ndi_dev_is_persistent_node(child) == 0) { 1242 extern int pci_allow_pseudo_children; 1243 1244 ddi_set_parent_data(child, NULL); 1245 1246 /* 1247 * Try to merge the properties from this prototype 1248 * node into real h/w nodes. 1249 */ 1250 if (ndi_merge_node(child, pci_name_child) == DDI_SUCCESS) { 1251 /* 1252 * Merged ok - return failure to remove the node. 1253 */ 1254 ddi_set_name_addr(child, NULL); 1255 return (DDI_FAILURE); 1256 } 1257 1258 /* workaround for ddivs to run under PCI */ 1259 if (pci_allow_pseudo_children) { 1260 /* 1261 * If the "interrupts" property doesn't exist, 1262 * this must be the ddivs no-intr case, and it returns 1263 * DDI_SUCCESS instead of DDI_FAILURE. 1264 */ 1265 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, 1266 DDI_PROP_DONTPASS, "interrupts", -1) == -1) 1267 return (DDI_SUCCESS); 1268 /* 1269 * Create the ddi_parent_private_data for a pseudo 1270 * child. 1271 */ 1272 pdptr = (struct ddi_parent_private_data *)kmem_zalloc( 1273 (sizeof (struct ddi_parent_private_data) + 1274 sizeof (struct intrspec)), KM_SLEEP); 1275 pdptr->par_intr = (struct intrspec *)(pdptr + 1); 1276 pdptr->par_nintr = 1; 1277 ddi_set_parent_data(child, pdptr); 1278 return (DDI_SUCCESS); 1279 } 1280 1281 /* 1282 * The child was not merged into a h/w node, 1283 * but there's not much we can do with it other 1284 * than return failure to cause the node to be removed. 1285 */ 1286 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged", 1287 ddi_get_name(child), ddi_get_name_addr(child), 1288 ddi_get_name(child)); 1289 ddi_set_name_addr(child, NULL); 1290 return (DDI_NOT_WELL_FORMED); 1291 } 1292 1293 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 1294 "interrupts", -1) != -1) { 1295 pdptr = (struct ddi_parent_private_data *) 1296 kmem_zalloc((sizeof (struct ddi_parent_private_data) + 1297 sizeof (struct intrspec)), KM_SLEEP); 1298 pdptr->par_intr = (struct intrspec *)(pdptr + 1); 1299 pdptr->par_nintr = 1; 1300 ddi_set_parent_data(child, pdptr); 1301 } else 1302 ddi_set_parent_data(child, NULL); 1303 1304 /* 1305 * initialize command register 1306 */ 1307 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) 1308 return (DDI_FAILURE); 1309 1310 /* 1311 * Support for the "command-preserve" property. 1312 */ 1313 command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child, 1314 DDI_PROP_DONTPASS, 1315 "command-preserve", 0); 1316 command = pci_config_get16(config_handle, PCI_CONF_COMM); 1317 command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB); 1318 command |= (pci_command_default & ~command_preserve); 1319 pci_config_put16(config_handle, PCI_CONF_COMM, command); 1320 1321 pci_config_teardown(&config_handle); 1322 return (DDI_SUCCESS); 1323 } 1324 1325 static int 1326 pci_removechild(dev_info_t *dip) 1327 { 1328 struct ddi_parent_private_data *pdptr; 1329 1330 if ((pdptr = ddi_get_parent_data(dip)) != NULL) { 1331 kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec))); 1332 ddi_set_parent_data(dip, NULL); 1333 } 1334 ddi_set_name_addr(dip, NULL); 1335 1336 /* 1337 * Strip the node to properly convert it back to prototype form 1338 */ 1339 ddi_remove_minor_node(dip, NULL); 1340 1341 impl_rem_dev_props(dip); 1342 1343 return (DDI_SUCCESS); 1344 } 1345 1346 1347 /* 1348 * These are the get and put functions to be shared with drivers. The 1349 * mutex locking is done inside the functions referenced, rather than 1350 * here, and is thus shared across PCI child drivers and any other 1351 * consumers of PCI config space (such as the ACPI subsystem). 1352 * 1353 * The configuration space addresses come in as pointers. This is fine on 1354 * a 32-bit system, where the VM space and configuration space are the same 1355 * size. It's not such a good idea on a 64-bit system, where memory 1356 * addresses are twice as large as configuration space addresses. At some 1357 * point in the call tree we need to take a stand and say "you are 32-bit 1358 * from this time forth", and this seems like a nice self-contained place. 1359 */ 1360 1361 static uint8_t 1362 pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr) 1363 { 1364 pci_acc_cfblk_t *cfp; 1365 uint8_t rval; 1366 int reg; 1367 1368 ASSERT64(((uintptr_t)addr >> 32) == 0); 1369 1370 reg = (int)(uintptr_t)addr; 1371 1372 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1373 1374 rval = (*pci_getb_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum, 1375 reg); 1376 1377 return (rval); 1378 } 1379 1380 static void 1381 pci_config_rep_rd8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, 1382 uint8_t *dev_addr, size_t repcount, uint_t flags) 1383 { 1384 uint8_t *h, *d; 1385 1386 h = host_addr; 1387 d = dev_addr; 1388 1389 if (flags == DDI_DEV_AUTOINCR) 1390 for (; repcount; repcount--) 1391 *h++ = pci_config_rd8(hdlp, d++); 1392 else 1393 for (; repcount; repcount--) 1394 *h++ = pci_config_rd8(hdlp, d); 1395 } 1396 1397 static uint16_t 1398 pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr) 1399 { 1400 pci_acc_cfblk_t *cfp; 1401 uint16_t rval; 1402 int reg; 1403 1404 ASSERT64(((uintptr_t)addr >> 32) == 0); 1405 1406 reg = (int)(uintptr_t)addr; 1407 1408 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1409 1410 rval = (*pci_getw_func)(cfp->c_busnum, cfp->c_devnum, cfp->c_funcnum, 1411 reg); 1412 1413 return (rval); 1414 } 1415 1416 static void 1417 pci_config_rep_rd16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 1418 uint16_t *dev_addr, size_t repcount, uint_t flags) 1419 { 1420 uint16_t *h, *d; 1421 1422 h = host_addr; 1423 d = dev_addr; 1424 1425 if (flags == DDI_DEV_AUTOINCR) 1426 for (; repcount; repcount--) 1427 *h++ = pci_config_rd16(hdlp, d++); 1428 else 1429 for (; repcount; repcount--) 1430 *h++ = pci_config_rd16(hdlp, d); 1431 } 1432 1433 static uint32_t 1434 pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr) 1435 { 1436 pci_acc_cfblk_t *cfp; 1437 uint32_t rval; 1438 int reg; 1439 1440 ASSERT64(((uintptr_t)addr >> 32) == 0); 1441 1442 reg = (int)(uintptr_t)addr; 1443 1444 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1445 1446 rval = (*pci_getl_func)(cfp->c_busnum, cfp->c_devnum, 1447 cfp->c_funcnum, reg); 1448 1449 return (rval); 1450 } 1451 1452 static void 1453 pci_config_rep_rd32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 1454 uint32_t *dev_addr, size_t repcount, uint_t flags) 1455 { 1456 uint32_t *h, *d; 1457 1458 h = host_addr; 1459 d = dev_addr; 1460 1461 if (flags == DDI_DEV_AUTOINCR) 1462 for (; repcount; repcount--) 1463 *h++ = pci_config_rd32(hdlp, d++); 1464 else 1465 for (; repcount; repcount--) 1466 *h++ = pci_config_rd32(hdlp, d); 1467 } 1468 1469 1470 static void 1471 pci_config_wr8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value) 1472 { 1473 pci_acc_cfblk_t *cfp; 1474 int reg; 1475 1476 ASSERT64(((uintptr_t)addr >> 32) == 0); 1477 1478 reg = (int)(uintptr_t)addr; 1479 1480 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1481 1482 (*pci_putb_func)(cfp->c_busnum, cfp->c_devnum, 1483 cfp->c_funcnum, reg, value); 1484 } 1485 1486 static void 1487 pci_config_rep_wr8(ddi_acc_impl_t *hdlp, uint8_t *host_addr, 1488 uint8_t *dev_addr, size_t repcount, uint_t flags) 1489 { 1490 uint8_t *h, *d; 1491 1492 h = host_addr; 1493 d = dev_addr; 1494 1495 if (flags == DDI_DEV_AUTOINCR) 1496 for (; repcount; repcount--) 1497 pci_config_wr8(hdlp, d++, *h++); 1498 else 1499 for (; repcount; repcount--) 1500 pci_config_wr8(hdlp, d, *h++); 1501 } 1502 1503 static void 1504 pci_config_wr16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) 1505 { 1506 pci_acc_cfblk_t *cfp; 1507 int reg; 1508 1509 ASSERT64(((uintptr_t)addr >> 32) == 0); 1510 1511 reg = (int)(uintptr_t)addr; 1512 1513 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1514 1515 (*pci_putw_func)(cfp->c_busnum, cfp->c_devnum, 1516 cfp->c_funcnum, reg, value); 1517 } 1518 1519 static void 1520 pci_config_rep_wr16(ddi_acc_impl_t *hdlp, uint16_t *host_addr, 1521 uint16_t *dev_addr, size_t repcount, uint_t flags) 1522 { 1523 uint16_t *h, *d; 1524 1525 h = host_addr; 1526 d = dev_addr; 1527 1528 if (flags == DDI_DEV_AUTOINCR) 1529 for (; repcount; repcount--) 1530 pci_config_wr16(hdlp, d++, *h++); 1531 else 1532 for (; repcount; repcount--) 1533 pci_config_wr16(hdlp, d, *h++); 1534 } 1535 1536 static void 1537 pci_config_wr32(ddi_acc_impl_t *hdlp, uint32_t *addr, uint32_t value) 1538 { 1539 pci_acc_cfblk_t *cfp; 1540 int reg; 1541 1542 ASSERT64(((uintptr_t)addr >> 32) == 0); 1543 1544 reg = (int)(uintptr_t)addr; 1545 1546 cfp = (pci_acc_cfblk_t *)&hdlp->ahi_common.ah_bus_private; 1547 1548 (*pci_putl_func)(cfp->c_busnum, cfp->c_devnum, 1549 cfp->c_funcnum, reg, value); 1550 } 1551 1552 static void 1553 pci_config_rep_wr32(ddi_acc_impl_t *hdlp, uint32_t *host_addr, 1554 uint32_t *dev_addr, size_t repcount, uint_t flags) 1555 { 1556 uint32_t *h, *d; 1557 1558 h = host_addr; 1559 d = dev_addr; 1560 1561 if (flags == DDI_DEV_AUTOINCR) 1562 for (; repcount; repcount--) 1563 pci_config_wr32(hdlp, d++, *h++); 1564 else 1565 for (; repcount; repcount--) 1566 pci_config_wr32(hdlp, d, *h++); 1567 } 1568 1569 static uint64_t 1570 pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr) 1571 { 1572 uint32_t lw_val; 1573 uint32_t hi_val; 1574 uint32_t *dp; 1575 uint64_t val; 1576 1577 dp = (uint32_t *)addr; 1578 lw_val = pci_config_rd32(hdlp, dp); 1579 dp++; 1580 hi_val = pci_config_rd32(hdlp, dp); 1581 val = ((uint64_t)hi_val << 32) | lw_val; 1582 return (val); 1583 } 1584 1585 static void 1586 pci_config_wr64(ddi_acc_impl_t *hdlp, uint64_t *addr, uint64_t value) 1587 { 1588 uint32_t lw_val; 1589 uint32_t hi_val; 1590 uint32_t *dp; 1591 1592 dp = (uint32_t *)addr; 1593 lw_val = (uint32_t)(value & 0xffffffff); 1594 hi_val = (uint32_t)(value >> 32); 1595 pci_config_wr32(hdlp, dp, lw_val); 1596 dp++; 1597 pci_config_wr32(hdlp, dp, hi_val); 1598 } 1599 1600 static void 1601 pci_config_rep_rd64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 1602 uint64_t *dev_addr, size_t repcount, uint_t flags) 1603 { 1604 if (flags == DDI_DEV_AUTOINCR) { 1605 for (; repcount; repcount--) 1606 *host_addr++ = pci_config_rd64(hdlp, dev_addr++); 1607 } else { 1608 for (; repcount; repcount--) 1609 *host_addr++ = pci_config_rd64(hdlp, dev_addr); 1610 } 1611 } 1612 1613 static void 1614 pci_config_rep_wr64(ddi_acc_impl_t *hdlp, uint64_t *host_addr, 1615 uint64_t *dev_addr, size_t repcount, uint_t flags) 1616 { 1617 if (flags == DDI_DEV_AUTOINCR) { 1618 for (; repcount; repcount--) 1619 pci_config_wr64(hdlp, host_addr++, *dev_addr++); 1620 } else { 1621 for (; repcount; repcount--) 1622 pci_config_wr64(hdlp, host_addr++, *dev_addr); 1623 } 1624 } 1625 1626 /* 1627 * When retrofitting this module for pci_tools, functions such as open, close, 1628 * and ioctl are now pulled into this module. Before this, the functions in 1629 * the pcihp module were referenced directly. Now they are called or 1630 * referenced through the pcihp cb_ops structure from functions in this module. 1631 */ 1632 1633 static int 1634 pci_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1635 { 1636 return ((pcihp_cb_ops.cb_open)(devp, flags, otyp, credp)); 1637 } 1638 1639 static int 1640 pci_close(dev_t dev, int flags, int otyp, cred_t *credp) 1641 { 1642 return ((pcihp_cb_ops.cb_close)(dev, flags, otyp, credp)); 1643 } 1644 1645 static int 1646 pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 1647 int *rvalp) 1648 { 1649 int rv = ENOTTY; 1650 1651 minor_t minor = getminor(dev); 1652 1653 switch (PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(minor)) { 1654 case PCI_TOOL_REG_MINOR_NUM: 1655 1656 switch (cmd) { 1657 case PCITOOL_DEVICE_SET_REG: 1658 case PCITOOL_DEVICE_GET_REG: 1659 1660 /* Require full privileges. */ 1661 if (secpolicy_kmdb(credp)) 1662 rv = EPERM; 1663 else 1664 rv = pcitool_dev_reg_ops( 1665 dev, (void *)arg, cmd, mode); 1666 break; 1667 1668 case PCITOOL_NEXUS_SET_REG: 1669 case PCITOOL_NEXUS_GET_REG: 1670 1671 /* Require full privileges. */ 1672 if (secpolicy_kmdb(credp)) 1673 rv = EPERM; 1674 else 1675 rv = pcitool_bus_reg_ops( 1676 dev, (void *)arg, cmd, mode); 1677 break; 1678 } 1679 break; 1680 1681 case PCI_TOOL_INTR_MINOR_NUM: 1682 1683 switch (cmd) { 1684 case PCITOOL_DEVICE_SET_INTR: 1685 1686 /* Require PRIV_SYS_RES_CONFIG, same as psradm */ 1687 if (secpolicy_ponline(credp)) { 1688 rv = EPERM; 1689 break; 1690 } 1691 1692 /*FALLTHRU*/ 1693 /* These require no special privileges. */ 1694 case PCITOOL_DEVICE_GET_INTR: 1695 case PCITOOL_DEVICE_NUM_INTR: 1696 rv = pcitool_intr_admn(dev, (void *)arg, cmd, mode); 1697 break; 1698 } 1699 break; 1700 1701 /* 1702 * All non-PCItool ioctls go through here, including: 1703 * devctl ioctls with minor number PCIHP_DEVCTL_MINOR and 1704 * those for attachment points with where minor number is the 1705 * device number. 1706 */ 1707 default: 1708 rv = (pcihp_cb_ops.cb_ioctl)(dev, cmd, arg, mode, 1709 credp, rvalp); 1710 break; 1711 } 1712 1713 return (rv); 1714 } 1715 1716 static int 1717 pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1718 int flags, char *name, caddr_t valuep, int *lengthp) 1719 { 1720 return ((pcihp_cb_ops.cb_prop_op)(dev, dip, prop_op, flags, 1721 name, valuep, lengthp)); 1722 } 1723 1724 static int 1725 pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 1726 { 1727 return (pcihp_info(dip, cmd, arg, result)); 1728 } 1729