pci.c (d4476ccb) | pci.c (70025d76) |
---|---|
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 * --- 17 unchanged lines hidden (view full) --- 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> | 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 * --- 17 unchanged lines hidden (view full) --- 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> | 34#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> | 35#include <sys/pci.h> 36#include <sys/pci_impl.h> |
42#include <sys/ddi.h> 43#include <sys/sunddi.h> | 37#include <sys/sysmacros.h> |
44#include <sys/sunndi.h> 45#include <sys/hotplug/pci/pcihp.h> 46#include <sys/pci_cfgspace.h> | 38#include <sys/sunndi.h> 39#include <sys/hotplug/pci/pcihp.h> 40#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" | 41#include <io/pci/pci_common.h> 42#include <io/pci/pci_tools_ext.h> 43#include <io/pci/pci_var.h> |
54 55/* Save minimal state. */ 56void *pci_statep; 57 58/* 59 * Bus Operation functions 60 */ 61static int pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *, 62 off_t, off_t, caddr_t *); 63static int pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, 64 void *, void *); 65static int pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t, 66 ddi_intr_handle_impl_t *, void *); | 44 45/* Save minimal state. */ 46void *pci_statep; 47 48/* 49 * Bus Operation functions 50 */ 51static int pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *, 52 off_t, off_t, caddr_t *); 53static int pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, 54 void *, void *); 55static int pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t, 56 ddi_intr_handle_impl_t *, void *); |
67static int pci_get_priority(dev_info_t *, int, int *); 68static int pci_get_nintrs(dev_info_t *, int, int *); 69static int pci_enable_intr(dev_info_t *, dev_info_t *, 70 ddi_intr_handle_impl_t *, uint32_t); 71static void pci_disable_intr(dev_info_t *, dev_info_t *, 72 ddi_intr_handle_impl_t *, uint32_t); | |
73 | 57 |
74/* Extern decalrations */ 75extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *, 76 psm_intr_op_t, int *); 77 | |
78struct 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, --- 16 unchanged lines hidden (view full) --- 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 | 58struct bus_ops pci_bus_ops = { 59 BUSO_REV, 60 pci_bus_map, 61 NULL, 62 NULL, 63 NULL, 64 i_ddi_map_fault, 65 ddi_dma_map, --- 16 unchanged lines hidden (view full) --- 82 NULL, /* (*bus_fm_init)(); */ 83 NULL, /* (*bus_fm_fini)(); */ 84 NULL, /* (*bus_fm_access_enter)(); */ 85 NULL, /* (*bus_fm_access_exit)(); */ 86 NULL, /* (*bus_power)(); */ 87 pci_intr_ops /* (*bus_intr_op)(); */ 88}; 89 |
110static int pci_open(dev_t *devp, int flags, int otyp, cred_t *credp); 111static int pci_close(dev_t dev, int flags, int otyp, cred_t *credp); 112static int pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 113 int *rvalp); 114static 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 */ | 90/* 91 * One goal here is to leverage off of the pcihp.c source without making 92 * changes to it. Call into it's cb_ops directly if needed, piggybacking 93 * anything else needed by the pci_tools.c module. Only pci_tools and pcihp 94 * will be opening PCI nexus driver file descriptors. 95 */ |
96static int pci_open(dev_t *, int, int, cred_t *); 97static int pci_close(dev_t, int, int, cred_t *); 98static int pci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 99static int pci_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *, 100 caddr_t, int *); 101static int pci_info(dev_info_t *, ddi_info_cmd_t, void *, void **); |
|
123 124struct 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 */ --- 9 unchanged lines hidden (view full) --- 140 CB_REV, /* rev */ 141 nodev, /* int (*cb_aread)() */ 142 nodev /* int (*cb_awrite)() */ 143}; 144 145/* 146 * Device Node Operation functions 147 */ | 102 103struct cb_ops pci_cb_ops = { 104 pci_open, /* open */ 105 pci_close, /* close */ 106 nodev, /* strategy */ 107 nodev, /* print */ 108 nodev, /* dump */ 109 nodev, /* read */ --- 9 unchanged lines hidden (view full) --- 119 CB_REV, /* rev */ 120 nodev, /* int (*cb_aread)() */ 121 nodev /* int (*cb_awrite)() */ 122}; 123 124/* 125 * Device Node Operation functions 126 */ |
148static int pci_info(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, 149 void **result); | |
150static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 151static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 152 153struct dev_ops pci_ops = { 154 DEVO_REV, /* devo_rev */ 155 0, /* refcnt */ 156 pci_info, /* info */ 157 nulldev, /* identify */ --- 15 unchanged lines hidden (view full) --- 173 174/* 175 * Internal routines in support of particular pci_ctlops. 176 */ 177static int pci_removechild(dev_info_t *child); 178static int pci_initchild(dev_info_t *child); 179 180/* | 127static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 128static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 129 130struct dev_ops pci_ops = { 131 DEVO_REV, /* devo_rev */ 132 0, /* refcnt */ 133 pci_info, /* info */ 134 nulldev, /* identify */ --- 15 unchanged lines hidden (view full) --- 150 151/* 152 * Internal routines in support of particular pci_ctlops. 153 */ 154static int pci_removechild(dev_info_t *child); 155static int pci_initchild(dev_info_t *child); 156 157/* |
181 * Miscellaneous internal functions 182 */ 183static 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 */ 189static uint8_t pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr); 190static uint16_t pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr); 191static uint32_t pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr); 192static uint64_t pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr); 193 --- 143 unchanged lines hidden (view full) --- 337 (void) pcihp_uninit(devi); 338 339 ddi_soft_state_free(pci_statep, DIP_TO_MINOR(devi)); 340 341 return (DDI_SUCCESS); 342} 343 344static int | 158 * These are the access routines. The pci_bus_map sets the handle 159 * to point to these. 160 */ 161static uint8_t pci_config_rd8(ddi_acc_impl_t *hdlp, uint8_t *addr); 162static uint16_t pci_config_rd16(ddi_acc_impl_t *hdlp, uint16_t *addr); 163static uint32_t pci_config_rd32(ddi_acc_impl_t *hdlp, uint32_t *addr); 164static uint64_t pci_config_rd64(ddi_acc_impl_t *hdlp, uint64_t *addr); 165 --- 143 unchanged lines hidden (view full) --- 309 (void) pcihp_uninit(devi); 310 311 ddi_soft_state_free(pci_statep, DIP_TO_MINOR(devi)); 312 313 return (DDI_SUCCESS); 314} 315 316static int |
345pci_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 389static int | |
390pci_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; | 317pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 318 off_t offset, off_t len, caddr_t *vaddrp) 319{ 320 struct regspec reg; 321 ddi_map_req_t mr; 322 ddi_acc_hdl_t *hp; 323 ddi_acc_impl_t *ap; 324 pci_regspec_t pci_reg; 325 pci_regspec_t *pci_rp; 326 int rnumber; 327 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; | 328 pci_acc_cfblk_t *cfp; 329 int space; 330 331 332 mr = *mp; /* Get private copy of request */ 333 mp = &mr; 334 335 /* 336 * check for register number 337 */ 338 switch (mp->map_type) { 339 case DDI_MT_REGSPEC: 340 pci_reg = *(pci_regspec_t *)(mp->map_obj.rp); 341 pci_rp = &pci_reg; |
416 if (pci_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS) | 342 if (pci_common_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 */ | 343 return (DDI_FAILURE); 344 break; 345 case DDI_MT_RNUMBER: 346 rnumber = mp->map_obj.rnumber; 347 /* 348 * get ALL "reg" properties for dip, select the one of 349 * of interest. In x86, "assigned-addresses" property 350 * is identical to the "reg" property, so there is no 351 * need to cross check the two to determine the physical 352 * address of the registers. 353 * This routine still performs some validity checks to 354 * make sure that everything is okay. 355 */ |
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) { | 356 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip, 357 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, 358 (uint_t *)&length) != DDI_PROP_SUCCESS) |
434 return (DDI_FAILURE); | 359 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); --- 5 unchanged lines hidden (view full) --- 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; | 360 361 /* 362 * validate the register number. 363 */ 364 length /= (sizeof (pci_regspec_t) / sizeof (int)); 365 if (rnumber >= length) { 366 ddi_prop_free(pci_rp); 367 return (DDI_FAILURE); --- 5 unchanged lines hidden (view full) --- 373 pci_reg = pci_rp[rnumber]; 374 375 /* 376 * free the memory allocated by ddi_prop_lookup_int_array 377 */ 378 ddi_prop_free(pci_rp); 379 380 pci_rp = &pci_reg; |
457 if (pci_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS) | 381 if (pci_common_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; --- 51 unchanged lines hidden (view full) --- 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 | 382 return (DDI_FAILURE); 383 mp->map_type = DDI_MT_REGSPEC; 384 break; 385 default: 386 return (DDI_ME_INVAL); 387 } 388 389 space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M; --- 51 unchanged lines hidden (view full) --- 441 * check for config space 442 * On x86, CONFIG is not mapped via MMU and there is 443 * no endian-ness issues. Set the attr field in the handle to 444 * indicate that the common routines to call the nexus driver. 445 */ 446 if (space == PCI_ADDR_CONFIG) { 447 hp = (ddi_acc_hdl_t *)mp->map_handlep; 448 |
525 if (hp == NULL) { 526 /* Can't map config space without a handle */ | 449 /* Can't map config space without a handle */ 450 if (hp == NULL) |
527 return (DDI_FAILURE); | 451 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 /* --- 82 unchanged lines hidden (view full) --- 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 | 452 453 ap = (ddi_acc_impl_t *)hp->ah_platform_private; 454 455 /* endian-ness check */ 456 if (hp->ah_acc.devacc_attr_endian_flags == DDI_STRUCTURE_BE_ACC) 457 return (DDI_FAILURE); 458 459 /* --- 82 unchanged lines hidden (view full) --- 542 reg.regspec_addr = pci_rp->pci_phys_low; 543 reg.regspec_size = pci_rp->pci_size_low; 544 545 mp->map_obj.rp = ® 546 return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp)); 547} 548 549 |
627/* 628 * pci_get_priority: 629 * Figure out the priority of the device 630 */ 631static int 632pci_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 */ 653static int 654pci_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 */ 679static int 680pci_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 1033static int 1034pci_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 1064static void 1065pci_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*/ 1086static int 1087pci_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; --- 63 unchanged lines hidden (view full) --- 1156 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 1157 } 1158 1159 /* NOTREACHED */ 1160 1161} 1162 1163/* | 550/*ARGSUSED*/ 551static int 552pci_ctlops(dev_info_t *dip, dev_info_t *rdip, 553 ddi_ctl_enum_t ctlop, void *arg, void *result) 554{ 555 pci_regspec_t *drv_regp; 556 uint_t reglen; 557 int rn; --- 63 unchanged lines hidden (view full) --- 621 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 622 } 623 624 /* NOTREACHED */ 625 626} 627 628/* |
1164 * Assign the address portion of the node name | 629 * pci_intr_ops |
1165 */ 1166static int | 630 */ 631static int |
1167pci_name_child(dev_info_t *child, char *name, int namelen) | 632pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op, 633 ddi_intr_handle_impl_t *hdlp, void *result) |
1168{ | 634{ |
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); | 635 return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result)); |
1221} 1222 | 636} 637 |
638 |
|
1223static int 1224pci_initchild(dev_info_t *child) 1225{ | 639static int 640pci_initchild(dev_info_t *child) 641{ |
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 | 642 char name[80]; 643 ddi_acc_handle_t config_handle; 644 ushort_t command_preserve, command; 645 |
1231 if (pci_name_child(child, name, 80) != DDI_SUCCESS) { | 646 if (pci_common_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 */ | 647 return (DDI_FAILURE); 648 } 649 ddi_set_name_addr(child, name); 650 651 /* 652 * Pseudo nodes indicate a prototype node with per-instance 653 * properties to be merged into the real h/w device node. 654 * The interpretation of the unit-address is DD[,F] 655 * where DD is the device id and F is the function. 656 */ 657 if (ndi_dev_is_persistent_node(child) == 0) { 658 extern int pci_allow_pseudo_children; 659 660 ddi_set_parent_data(child, NULL); 661 662 /* 663 * Try to merge the properties from this prototype 664 * node into real h/w nodes. 665 */ |
1251 if (ndi_merge_node(child, pci_name_child) == DDI_SUCCESS) { | 666 if (ndi_merge_node(child, pci_common_name_child) == 667 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 */ --- 5 unchanged lines hidden (view full) --- 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 */ | 668 /* 669 * Merged ok - return failure to remove the node. 670 */ 671 ddi_set_name_addr(child, NULL); 672 return (DDI_FAILURE); 673 } 674 675 /* workaround for ddivs to run under PCI */ --- 5 unchanged lines hidden (view full) --- 681 */ 682 if (ddi_prop_get_int(DDI_DEV_T_ANY, child, 683 DDI_PROP_DONTPASS, "interrupts", -1) == -1) 684 return (DDI_SUCCESS); 685 /* 686 * Create the ddi_parent_private_data for a pseudo 687 * child. 688 */ |
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); | 689 pci_common_set_parent_private_data(child); |
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, | 690 return (DDI_SUCCESS); 691 } 692 693 /* 694 * The child was not merged into a h/w node, 695 * but there's not much we can do with it other 696 * than return failure to cause the node to be removed. 697 */ 698 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged", 699 ddi_get_name(child), ddi_get_name_addr(child), 700 ddi_get_name(child)); 701 ddi_set_name_addr(child, NULL); 702 return (DDI_NOT_WELL_FORMED); 703 } 704 705 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 | 706 "interrupts", -1) != -1) 707 pci_common_set_parent_private_data(child); 708 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 --- 308 unchanged lines hidden (view full) --- 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 | 709 ddi_set_parent_data(child, NULL); 710 711 /* 712 * initialize command register 713 */ 714 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) 715 return (DDI_FAILURE); 716 --- 308 unchanged lines hidden (view full) --- 1025 for (; repcount; repcount--) 1026 pci_config_wr64(hdlp, host_addr++, *dev_addr++); 1027 } else { 1028 for (; repcount; repcount--) 1029 pci_config_wr64(hdlp, host_addr++, *dev_addr); 1030 } 1031} 1032 |
1033 |
|
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 1634static int 1635pci_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1636{ | 1034/* 1035 * When retrofitting this module for pci_tools, functions such as open, close, 1036 * and ioctl are now pulled into this module. Before this, the functions in 1037 * the pcihp module were referenced directly. Now they are called or 1038 * referenced through the pcihp cb_ops structure from functions in this module. 1039 */ 1040 1041static int 1042pci_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1043{ |
1637 return ((pcihp_cb_ops.cb_open)(devp, flags, otyp, credp)); | 1044 return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp)); |
1638} 1639 1640static int 1641pci_close(dev_t dev, int flags, int otyp, cred_t *credp) 1642{ | 1045} 1046 1047static int 1048pci_close(dev_t dev, int flags, int otyp, cred_t *credp) 1049{ |
1643 return ((pcihp_cb_ops.cb_close)(dev, flags, otyp, credp)); | 1050 return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp)); |
1644} 1645 1646static int | 1051} 1052 1053static int |
1647pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 1648 int *rvalp) | 1054pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 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); | 1055{ 1056 minor_t minor = getminor(dev); 1057 int instance = PCIHP_AP_MINOR_NUM_TO_INSTANCE(minor); 1058 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 | 1059 |
1656 switch (PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(minor)) { 1657 case PCI_TOOL_REG_MINOR_NUM: | 1060 if (pci_p == NULL) 1061 return (ENXIO); |
1658 | 1062 |
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); | 1063 return (pci_common_ioctl(pci_p->pci_dip, 1064 dev, cmd, arg, mode, credp, rvalp)); |
1717} 1718 | 1065} 1066 |
1067 |
|
1719static int 1720pci_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{ | 1068static int 1069pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1070 int flags, char *name, caddr_t valuep, int *lengthp) 1071{ |
1723 return ((pcihp_cb_ops.cb_prop_op)(dev, dip, prop_op, flags, | 1072 return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags, |
1724 name, valuep, lengthp)); 1725} 1726 1727static int 1728pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 1729{ 1730 return (pcihp_info(dip, cmd, arg, result)); 1731} | 1073 name, valuep, lengthp)); 1074} 1075 1076static int 1077pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 1078{ 1079 return (pcihp_info(dip, cmd, arg, result)); 1080} |