pcitools in OpenSolaris, a good pci debug tool

pci_tools (i86pc/io/pci/pci_tools.c) in Solaris kernel define some function level infrastructure for the kernel code to achieve the following goal:

pci device register operation
=============================
pci_tools support configure space, memory, ROM and io space for both pci and pci express device. Function pcitool_dev_reg_ops() dispatch the operations to the following functions.

1. access the pci express extended configure space (above 256 bytes till 4k), the protype of this function is

static int pcitool_pciex_cfg_access(dev_info_t *dip, pcitool_reg_t *prg,
    boolean_t write_flag)

where pcitool_reg_t is a common struct describes the access attribute of the access. It is definded as

/*
 * Data stucture to read and write to pci device registers.
 * This is the argument to the following ioctls:
 *      PCITOOL_DEVICE_SET/GET_REG
 *      PCITOOL_NEXUS_SET/GET_REG
 */
typedef struct pcitool_reg {
        uint16_t        user_version;   /* Userland program version - to krnl */
        uint16_t        drvr_version;   /* Driver version - from kernel */
        uint8_t         bus_no;         /* pci bus - to kernel */
        uint8_t         dev_no;         /* pci dev - to kernel */
        uint8_t         func_no;        /* pci function - to kernel */
        uint8_t         barnum;         /* bank (DEVCTL_NEXUS_SET/GET_REG) or */
                                        /*   BAR from pcitools_bar_t */
                                        /*   (DEVCTL_DEVICE_SET/GET_REG) */
                                        /*   to kernel */
        uint64_t        offset;         /* to kernel */
        uint32_t        acc_attr;       /* access attributes - to kernel */
        uint32_t        padding1;       /* 8-byte align next uint64_t for X86 */
        uint64_t        data;           /* to/from kernel, 64-bit alignment */
        uint32_t        status;         /* from kernel */
        uint32_t        padding2;       /* 8-byte align next uint64_t for X86 */
        uint64_t        phys_addr;      /* from kernel, 64-bit alignment */
} pcitool_reg_t;

2. access the pci configure space header (below 256 bytes), the protype of this function is

static int pcitool_cfg_access(dev_info_t *dip, pcitool_reg_t *prg,
    boolean_t write_flag);

3. access io space, the protype of this function is

static int pcitool_io_access(dev_info_t *dip, pcitool_reg_t *prg,
    boolean_t write_flag);

4. access memory mapped space, the protype of this function is

static int pcitool_mem_access(dev_info_t *dip, pcitool_reg_t *prg,
     uint64_t virt_addr, boolean_t write_flag);

5. map and unmap memory mapped address space of a pci device, the functions are defined as

static uint64_t pcitool_map(uint64_t phys_addr, size_t size, size_t *num_pages);
static void pcitool_unmap(uint64_t virt_addr, size_t num_pages);

interrupt CPU binding requests and queries
==========================================

This functionality is handled by pcitool_intr_admn(), which also dispatch the request to the following functions.

Note: This functionality is under construction at least in build 90. So we leave it empty here.

initialize of pci_tools
=======================

Kernel component which wants to utilize pci_tools should call pcitool_init() first.

  96 pcitool_init(dev_info_t *dip, boolean_t is_pciex)
  97 {
  98         int instance = ddi_get_instance(dip);
  99
 100         /* Create pcitool nodes for register access and interrupt routing. */
 101
 102         if (ddi_create_minor_node(dip, PCI_MINOR_REG, S_IFCHR,
 103             PCIHP_AP_MINOR_NUM(instance, PCI_TOOL_REG_MINOR_NUM),
 104             DDI_NT_REGACC, 0) != DDI_SUCCESS) {
 105                 return (DDI_FAILURE);
 106         }
 107
 108         if (ddi_create_minor_node(dip, PCI_MINOR_INTR, S_IFCHR,
 109             PCIHP_AP_MINOR_NUM(instance, PCI_TOOL_INTR_MINOR_NUM),
 110             DDI_NT_INTRCTL, 0) != DDI_SUCCESS) {
 111                 ddi_remove_minor_node(dip, PCI_MINOR_REG);
 112                 return (DDI_FAILURE);
 113         }
 114
 115         if (is_pciex)
 116                 max_cfg_size = PCIE_CONF_HDR_SIZE;
 117
 118         return (DDI_SUCCESS);
 119 }

This function create two minor node for the pass-in dip, one for reg access and another for intr access. max_cfg_size if determined by whether it is a native pci express device (lagcy pci express device has no extened configure space).

pci_tools interface to user-land
================================

pcitool_init() is called during attachment of pci and pci express root nexus. In i86pc/io/pciex/npe.c,

        /* Second arg: initialize for pci_express root nexus */
        if (pcitool_init(devi, B_TRUE) != DDI_SUCCESS) {
                (void) pcihp_uninit(devi);
                ddi_soft_state_free(npe_statep, instance);
                return (DDI_FAILURE);
        }

user land application can issue ioctl() against the pci or pci express root nexus for pci_tool operations. In i86pc/io/pci/pci_common.c,

 857         switch (PCIHP_AP_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
 858         case PCI_TOOL_REG_MINOR_NUM:
 859
 860                 switch (cmd) {
 861                 case PCITOOL_DEVICE_SET_REG:
 862                 case PCITOOL_DEVICE_GET_REG:
 863
 864                         /* Require full privileges. */
 865                         if (secpolicy_kmdb(credp))
 866                                 rv = EPERM;
 867                         else
 868                                 rv = pcitool_dev_reg_ops(dip, (void *)arg,
 869                                     cmd, mode);
 870                         break;
 871
 872                 case PCITOOL_NEXUS_SET_REG:
 873                 case PCITOOL_NEXUS_GET_REG:
 874
 875                         /* Require full privileges. */
 876                         if (secpolicy_kmdb(credp))
 877                                 rv = EPERM;
 878                         else
 879                                 rv = pcitool_bus_reg_ops(dip, (void *)arg,
 880                                     cmd, mode);
 881                         break;
 882                 }
 883                 break;
 884
 885         case PCI_TOOL_INTR_MINOR_NUM:
 886
 887                 switch (cmd) {
 888                 case PCITOOL_DEVICE_SET_INTR:
 889
 890                         /* Require PRIV_SYS_RES_CONFIG, same as psradm */
 891                         if (secpolicy_ponline(credp)) {
 892                                 rv = EPERM;
 893                                 break;
 894                         }
 895
 896                 /*FALLTHRU*/
 897                 /* These require no special privileges. */
 898                 case PCITOOL_DEVICE_GET_INTR:
 899                 case PCITOOL_SYSTEM_INTR_INFO:
 900                         rv = pcitool_intr_admn(dip, (void *)arg, cmd, mode);
 901                         break;
 902                 }
 903                 break;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值