生成pci设备树的简单实现

来源:互联网 发布:地下城网络中断啥毛病 编辑:程序博客网 时间:2024/05/22 03:16

2015-09-16

系统的所有pci设备记录在/sys/bus/pci/devices目录下面:


而如果pci地址下连接有其他子设备的话,可以在对应的目录下找到其他的pci地址:


可以看到0000:00:11.0下连接有0000:02:00.0, 0000:02:01.0, 0000:02:02.0, 0000:02:03.0四个设备。

所以,通过分析/sys/bus/pci/devices目录结构,就可以简单生成pci设备的树形结构。

具体过程如下:

1.读取所有的pci地址(/sys/bus/pci/devices)


承载pci信息的结构体定义如下:

/*****************************/typedef struct _pci_data {   char caPCIAddr[ NAMELEN ];   char caPCIClassId[ NAMELEN ];   char caPCIClassDesc[ NAMELEN ];   char caPCIDomain[ NAMELEN ];   char caPCIBus[ NAMELEN ];   char caPCISlot[ NAMELEN ];   char caPCIFunction[ NAMELEN ];   char caPCIProductId[ NAMELEN ];   char caPCIVendorId[ NAMELEN ];} st_pci_data; typedef struct _pci_node{   st_pci_data data;   struct _pci_node *next;   struct _pci_node *children;} st_pci_node;/****************************/intget_all_pci_devices( st_pci_node **stppPCIs ){    DIR *fpDir = NULL;    struct dirent *stpEntry = NULL;    st_pci_node *stpCur = NULL;    if( ( fpDir = opendir( CPCIPATH ) ) == NULL )    {        fprintf( stderr, "[%s:%d]opendir error: %s\n", _FL_, strerror( errno ) );    return -1;    }    while( ( stpEntry = readdir( fpDir ) ) != NULL )    {        st_pci_node *stpPCITmp = NULL;        /* filter the '.' and '..' */        if( strcmp( stpEntry->d_name, "." ) == 0 ||        strcmp( stpEntry->d_name, ".." ) == 0 )        continue;        /* allocate a new pci node */    stpPCITmp = malloc( sizeof( st_pci_node ) );    if( stpPCITmp == NULL )    {        fprintf( stderr, "[%s:%d]malloc error: %s\n", _FL_, strerror( errno ) );        return -1;    }        /* init the pci node */    init_pci_node( stpPCITmp );        /*     ** fill the pci node     **     pci address(domain:bus:slot.function)    **     pci domain bus slot function    */    strcpy( stpPCITmp->data.caPCIAddr, stpEntry->d_name );        split_pci_addr( stpPCITmp->data.caPCIAddr, stpPCITmp->data.caPCIDomain,         stpPCITmp->data.caPCIBus, stpPCITmp->data.caPCISlot, stpPCITmp->data.caPCIFunction );     get_pci_vendor_id( stpPCITmp->data.caPCIAddr, stpPCITmp->data.caPCIVendorId );    get_pci_product_id( stpPCITmp->data.caPCIAddr, stpPCITmp->data.caPCIProductId );    get_pci_class_id( stpPCITmp->data.caPCIAddr, stpPCITmp->data.caPCIClassId );    get_pci_class_desc( stpPCITmp->data.caPCIClassId, stpPCITmp->data.caPCIClassDesc );        if( stpCur == NULL )        *stppPCIs = stpPCITmp;    else        stpCur->next = stpPCITmp;        stpCur = stpPCITmp;    }    return 0;}

2.再分别读取单个pci地址下的目录节点,和步骤1下的pci地址比较,将找到的pci地址,作为当前pci地址的子节点


intgenerate_pci_tree( st_pci_node **stppPCIs ){    st_pci_node *stpCur = *stppPCIs;    st_pci_node *stpPre = NULL;    st_pci_node *stpAim = NULL;    char        caPath[ NAMELEN ] = { 0 };    while( stpCur != NULL )    {        DIR *fpDir = NULL;    struct dirent *stpEntry = NULL;        strcpy( caPath, CPCIPATH );    strcat( caPath, stpCur->data.caPCIAddr );                if( ( fpDir = opendir( caPath ) ) == NULL )    {        fprintf( stderr, "[%s:%d]opendir error: %s\n", _FL_, strerror( errno ) );        return -1;    }        while( ( stpEntry = readdir( fpDir ) ) != NULL )    {        if( search_pci_node( *stppPCIs, stpEntry->d_name, &stpPre, &stpAim ) )        {            if( *stppPCIs == stpAim )                    *stppPCIs = ( *stppPCIs )->next;    /* first node is the child of current node */        else            stpPre->next = stpAim->next;                stpAim->next = stpCur->children;        stpCur->children = stpAim;        }    }    closedir( fpDir );        if( stpCur->children != NULL )        generate_pci_tree( &( stpCur->children ) );        stpCur = stpCur->next;    }    return 0;}

3.将生成的pci树输出到xml文件

intprint_pci_xml_file( char *cpXmlFileName, st_pci_node *stpPCIs ){    xmlDocPtr    pXmlDoc      = NULL;    xmlNodePtr   pXmlRootNode = NULL;    xmlChar      *pXmlString  = NULL;    int          iSize      = 0;    xmlKeepBlanksDefault( 0 );    pXmlDoc      = xmlNewDoc( BAD_CAST "1.0" );    pXmlRootNode = xmlNewNode( NULL, BAD_CAST "pci" );    xmlDocSetRootElement( pXmlDoc, pXmlRootNode );    print_pci_xml_node( pXmlRootNode, stpPCIs );    xmlSaveFormatFile( cpXmlFileName, pXmlDoc, 1 );    xmlDocDumpFormatMemoryEnc( pXmlDoc, &pXmlString, &iSize, "UTF-8", 1 );    xmlFree( pXmlString );    xmlFreeDoc( pXmlDoc );    xmlMemoryDump();    return 0;}intprint_pci_xml_node( xmlNodePtr pXmlParent, st_pci_node *stpPCIs ){    while( stpPCIs != NULL )    {        xmlNodePtr xmlCurPtr = xmlNewNode( NULL, BAD_CAST stpPCIs->data.caPCIClassDesc );    xmlAddChild( pXmlParent, xmlCurPtr );        xmlSetProp( xmlCurPtr, BAD_CAST "ven_id", BAD_CAST ( stpPCIs->data.caPCIVendorId ) );    xmlSetProp( xmlCurPtr, BAD_CAST "dev_id", BAD_CAST ( stpPCIs->data.caPCIProductId ) );    xmlSetProp( xmlCurPtr, BAD_CAST "addr", BAD_CAST ( stpPCIs->data.caPCIAddr ) );        if( stpPCIs->children != NULL )        print_pci_xml_node( xmlCurPtr, stpPCIs->children );            stpPCIs = stpPCIs->next;    }    return 0;}

4.运行结果如下:


5.源代码

http://download.csdn.net/detail/qq123386926/9112375

0 0