免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: liuaiping0205
打印 上一主题 下一主题

[硬件及驱动] 如何遍历PCI设备 [复制链接]

论坛徽章:
0
11
发表于 2013-05-09 22:08
回复 7# xs3c

这个代码现在我写出来了,谢谢!


  1. /*
  2.         下面是我写的代码,目前知道的就这么多了
  3.         操作系统:Redhat 6.2
  4.         参考网址:http://wiki.osdev.org/PCI#Base_Address_Registers     维基百科对pci的详细介绍,看代码时可以一起看看,很有参考意义

  5.         下面是测试代码:
  6.         若你想看某个pci设备的配置信息,通过命令:lspci得到详细信息,比如下面是我的其中一个信息:
  7.         00:1b.0 Audio device: Intel Corporation 82801H (ICH8 Family) HD Audio Controller (rev 02)
  8.         那么我如何知道这个声卡设备的厂商ID和设备ID呢?
  9.         可以查看下面两个文件:
  10.         #cat  /sys/bus/pci/devices/0000\:00\:1b.0/device        //设备ID文件
  11.         0x284b
  12.         #cat  /sys/bus/pci/devices/0000\:00\:1b.0/vendor                  //厂商ID文件
  13.         0x8066

  14. */
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <sys/io.h>

  19. typedef unsigned long DWORD;
  20. typedef unsigned char BYTE;
  21. typedef unsigned int WORD;
  22. typedef unsigned short HALF;
  23. /* 计算pci空间地址基址 */       
  24. #define MK_PDI(bus, device, func) (WORD)((bus&PCI_BUS_MAX)<<PCI_BUS_SHIFT | (device&PCI_DEVICE_MAX)<<PCI_DEVICE_SHIFT      | (func&PCI_FUNC_MAX))
  25. #define MK_PCICONFIADDR(bus, device, func) (DWORD)(0x80000000L | (DWORD)MK_PDI(bus,device,func)<<8)
  26. /* PCI配置空间寄存器 */
  27. #define VENDOR_ID 0x8086                //要查找的产商ID     
  28. #define DEVICE_ID 0x284b                //要查找的设备ID

  29. /* 这两个寄存器是关键 */
  30. #define PCI_CONFIG_ADDRESS      0xCF8 //地址寄存器
  31. #define PCI_CONFIG_DATA         0xCFC //数据寄存器

  32. #define PCI_BUS_SHIFT                8
  33. #define PCI_DEVICE_SHIFT    3

  34. #define PCI_BUS_MAX                        255                //最多256个总线 255=(0xff)
  35. #define PCI_DEVICE_MAX                31                //每个总线上面最多可以接32个设备 21=(0x1f)
  36. #define PCI_FUNC_MAX                7                //每个设备最多有8个功能号 7=(0x7)
  37. #define PCI_FUNCTION_MASK        0x0007

  38. void
  39. grub_traverse_pci (unsigned int vendor_id, unsigned int device_id)
  40. {
  41.         int flag = 0;
  42.         unsigned long indentify_id;
  43.         unsigned char bus, device, func;        //总线号、设备号、功能号这3个确定唯一的一个PCI设备
  44.         unsigned int busAddr, busData;                //pci配置空间地址、数据
  45.         indentify_id = (device_id << 16) | vendor_id;  //由配置空间中可知,device_id是高16位,vendor_id是低16位
  46.         printf ("indentify_id =%x\n", indentify_id);
  47.         /* 用3层循环遍历pci设备 */
  48.         for (bus = 0; bus <= PCI_BUS_MAX ; bus++)
  49.         {
  50.                 for (device = 0; device <= PCI_DEVICE_MAX; device++)
  51.                 {
  52.                         for (func = 0; func <= PCI_FUNC_MAX; func++)
  53.                         {
  54.                                 busAddr = MK_PCICONFIADDR (bus, device, func); //计算配置空间的基址地址
  55. //                                busAddr = (0x80000000L |bus << 16  |  device << 11  |  func <<  8); //这种方法和上面方法是一个意思,
  56.                                 /* 使用内嵌汇编来代替outl函数 */                               
  57. //                                __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr), "Nd" (PCI_CONFIG_ADDRESS));
  58.                                 outl (busAddr, PCI_CONFIG_ADDRESS); //向配置空间的地址寄存器0xcf8写入地址
  59.                                 __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA));
  60. //                                busData = inl (PCI_CONFIG_DATA); //读取数据
  61. //                                printf ("###  %x, %x\n",(HALF)busData, busData);
  62.                                 /* 假如busData=0x284b8086,那么(unsigned short)busData=8086 */                               
  63.                                 if ((unsigned short) busData != 0xffff) //只需比较它的2个字节,通过产商ID和ffff比较来判断这个设备是否存在
  64.                                 {
  65. //                                                printf ("%x %x %x %x %x\n", bus, device, func, busAddr, busData);       
  66. //#if 0
  67.                                         if (indentify_id == busData) //查找Vendor ID和Device ID分别是8086和284b的设备
  68.                                         {
  69.                                                 printf ("bus=%x,device=%x,func=%x,busAddr=%x,busData=%x\n", bus, device, func, busAddr, busData);       
  70.                                                 flag = 1;        //找到设备后就退出
  71.                                                 break;
  72.                                         }
  73. //#endif                                       
  74.                                 }
  75.                         }
  76.                         if (flag)
  77.                                 break;
  78.                 }
  79.                 if (flag)
  80.                         break;
  81.         }
  82.         /* 找到设备后读取它的配置空间信息 */
  83.         if (flag)
  84.         {
  85. //                printf ("VendorID=%x, DeviceID=%x\n", (unsigned short)busData, busData >> 16);        //将busData右移得到设备ID

  86.                 /* 获得Command部分,可以通过设置它的bit0、bit1和bit2这3位为1,bit0\bit1可以达到函数pci_enable_device的功能,就是为了开启io和内存映射,bit2是达到函数pci_set_master()的功能,让设备能够成为.. */
  87.                 /* 内嵌汇编 */
  88.                 __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr | 0x4), "Nd" (PCI_CONFIG_ADDRESS));
  89. //                outl (busAddr | 0x4, PCI_CONFIG_ADDRESS); //向配置空间的地址寄存器0xcf8写入地址           (这行代码和上面代码一个意思)
  90.                 __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA));
  91. //                busData = inl (PCI_CONFIG_DATA); //读取数据
  92.                 printf ("Command=%x\n", (unsigned short)busData); //得到command部分
  93.                 __asm__ __volatile__ ("outl %0,%w1": :"a" (busData | 0x00000007), "Nd" (PCI_CONFIG_DATA));
  94. //                outl (busData | 0x00000007, PCI_CONFIG_DATA); //将最低的3位置1
  95.                        
  96.                 /* Test:查看是否写的正确 */
  97.                 __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA));
  98. //                busData = inl (PCI_CONFIG_DATA); //读取数据
  99.                 printf ("Command=%x\n", (unsigned short)busData); //得到command部分


  100.                 /* 获得class code 和subclass、ProgIF、Reversion ID*/               
  101.                 __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr | 0x8), "Nd" (PCI_CONFIG_ADDRESS));
  102. //                outl (busAddr | 0x8, PCI_CONFIG_ADDRESS); //向配置空间的地址寄存器0xcf8写入地址
  103.                 __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA));
  104. //                busData = inl (PCI_CONFIG_DATA); //读取数据
  105.                 printf ("Class code=%x,Subclass=%x, progif=%x, Reversion ID=%x\n",(busData & 0xff000000) >> 24, (busData & 0x00ff0000) >> 16,(busData & 0xff00) >> 8 ,(BYTE)busData);

  106.                 /* 获得基址 */
  107.                 int i;
  108. //                char *buf = (char *) malloc (20);
  109.                 char buf[20];
  110.                 memset (buf,'0', 20);
  111.                 unsigned int base;
  112.                 unsigned int BarAddr[6];
  113.                 unsigned int bar_bak;
  114.                 unsigned int bar_len = 0;
  115.                 for (i = 0; i < 6; i++)
  116.                 {
  117.                         base = 0x10;
  118.                         base += i*4;
  119. //                        printf ("base=%x\n", base);
  120.                         __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr | base), "Nd" (PCI_CONFIG_ADDRESS));
  121. //                        outl (busAddr | base, PCI_CONFIG_ADDRESS); //想配置空间的地址寄存器0xcf8写入地址

  122.                         __asm__ __volatile__ ("inl %w1,%0":"=a" (BarAddr[i]):"Nd" (PCI_CONFIG_DATA));
  123. //                        BarAddr[i] = inl (PCI_CONFIG_DATA); //读取数据
  124.                         if (BarAddr[i] & 0x00000001) //假如最低位为1,说明这个地址是给IO空间的
  125.                                 printf ("IO address,BarAddr[%d]=%x\n", i, BarAddr[i] & 0xfffffffc);

  126.                         else
  127.                                 printf ("Memory address,BarAddr[%d]=%x\n", i, BarAddr[i] & 0xfffffff0);

  128.                         /* 获得需要的空间大小 */
  129.                         bar_bak = BarAddr[i]; //注意这里一定要保存原来的值
  130.                         printf ("bar_bak=%x\n", bar_bak);
  131.                         __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr | base), "Nd" (PCI_CONFIG_ADDRESS));
  132. //                        outl (busAddr | base, PCI_CONFIG_ADDRESS); //要操作的寄存器地址
  133.                         __asm__ __volatile__ ("outl %0,%w1": :"a" (0xffffffff), "Nd" (PCI_CONFIG_DATA)); //向这个Bar全部写1
  134. //                        outl (0xffffffff, PCI_CONFIG_DATA); //写入0xffffffff
  135.                         __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA)); //再读出它的值
  136.                         bar_len = ~(busData) + 1; //取返+1
  137.                         printf ("bar_len=%x\n", bar_len);
  138. //                        bar_len = ~(inl (PCI_CONFIG_DATA)) + 1; //再读出寄存器值取返,加1
  139.                         __asm__ __volatile__ ("outl %0,%w1": :"a" (bar_bak), "Nd" (PCI_CONFIG_DATA));
  140. //                        outl (bar_bak, PCI_CONFIG_DATA); //最后将原来值写回去

  141.                         /* Test:查看是不是写进去的再读出来和之前的是否一样--最后结果说明是对的 */
  142. #if 0                               
  143.                                 outl (busAddr | base, PCI_CONFIG_ADDRESS);
  144.                                 printf ("### %x\n", inl (PCI_CONFIG_DATA));
  145. #endif
  146.                 }
  147. #if 0
  148.                 /* 查看HeadType段 */
  149.                 outl (busAddr | 0x0c, PCI_CONFIG_ADDRESS); //想配置空间的地址寄存器0xcf8写入地址
  150.                 busData = inl (PCI_CONFIG_DATA); //读取数据
  151.                 printf ("Header Type=%x\n",(busData & 0x00ff0000) >> 16 );
  152. #endif

  153.         }
  154. }


  155. int
  156. main ()
  157. {
  158.         iopl (3); //设置IO端口权限
  159.         grub_traverse_pci (VENDOR_ID, DEVICE_ID);
  160.                
  161.         return 0;
  162. }
复制代码

论坛徽章:
0
12
发表于 2013-05-09 22:10
回复 1# liuaiping0205


  1. /*
  2.         下面是我写的代码,目前知道的就这么多了
  3.         操作系统:Redhat 6.2
  4.         参考网址:http://wiki.osdev.org/PCI#Base_Address_Registers     维基百科对pci的详细介绍,看代码时可以一起看看,很有参考意义

  5.         下面是测试代码:
  6.         若你想看某个pci设备的配置信息,通过命令:lspci得到详细信息,比如下面是我的其中一个信息:
  7.         00:1b.0 Audio device: Intel Corporation 82801H (ICH8 Family) HD Audio Controller (rev 02)
  8.         那么我如何知道这个声卡设备的厂商ID和设备ID呢?
  9.         可以查看下面两个文件:
  10.         #cat  /sys/bus/pci/devices/0000\:00\:1b.0/device        //设备ID文件
  11.         0x284b
  12.         #cat  /sys/bus/pci/devices/0000\:00\:1b.0/vendor                  //厂商ID文件
  13.         0x8066

  14. */
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <sys/io.h>

  19. typedef unsigned long DWORD;
  20. typedef unsigned char BYTE;
  21. typedef unsigned int WORD;
  22. typedef unsigned short HALF;
  23. /* 计算pci空间地址基址 */       
  24. #define MK_PDI(bus, device, func) (WORD)((bus&PCI_BUS_MAX)<<PCI_BUS_SHIFT | (device&PCI_DEVICE_MAX)<<PCI_DEVICE_SHIFT      | (func&PCI_FUNC_MAX))
  25. #define MK_PCICONFIADDR(bus, device, func) (DWORD)(0x80000000L | (DWORD)MK_PDI(bus,device,func)<<8)
  26. /* PCI配置空间寄存器 */
  27. #define VENDOR_ID 0x8086                //要查找的产商ID     
  28. #define DEVICE_ID 0x284b                //要查找的设备ID

  29. /* 这两个寄存器是关键 */
  30. #define PCI_CONFIG_ADDRESS      0xCF8 //地址寄存器
  31. #define PCI_CONFIG_DATA         0xCFC //数据寄存器

  32. #define PCI_BUS_SHIFT                8
  33. #define PCI_DEVICE_SHIFT    3

  34. #define PCI_BUS_MAX                        255                //最多256个总线 255=(0xff)
  35. #define PCI_DEVICE_MAX                31                //每个总线上面最多可以接32个设备 21=(0x1f)
  36. #define PCI_FUNC_MAX                7                //每个设备最多有8个功能号 7=(0x7)
  37. #define PCI_FUNCTION_MASK        0x0007

  38. void
  39. grub_traverse_pci (unsigned int vendor_id, unsigned int device_id)
  40. {
  41.         int flag = 0;
  42.         unsigned long indentify_id;
  43.         unsigned char bus, device, func;        //总线号、设备号、功能号这3个确定唯一的一个PCI设备
  44.         unsigned int busAddr, busData;                //pci配置空间地址、数据
  45.         indentify_id = (device_id << 16) | vendor_id;  //由配置空间中可知,device_id是高16位,vendor_id是低16位
  46.         printf ("indentify_id =%x\n", indentify_id);
  47.         /* 用3层循环遍历pci设备 */
  48.         for (bus = 0; bus <= PCI_BUS_MAX ; bus++)
  49.         {
  50.                 for (device = 0; device <= PCI_DEVICE_MAX; device++)
  51.                 {
  52.                         for (func = 0; func <= PCI_FUNC_MAX; func++)
  53.                         {
  54.                                 busAddr = MK_PCICONFIADDR (bus, device, func); //计算配置空间的基址地址
  55. //                                busAddr = (0x80000000L |bus << 16  |  device << 11  |  func <<  8); //这种方法和上面方法是一个意思,
  56.                                 /* 使用内嵌汇编来代替outl函数 */                               
  57. //                                __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr), "Nd" (PCI_CONFIG_ADDRESS));
  58.                                 outl (busAddr, PCI_CONFIG_ADDRESS); //向配置空间的地址寄存器0xcf8写入地址
  59.                                 __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA));
  60. //                                busData = inl (PCI_CONFIG_DATA); //读取数据
  61. //                                printf ("###  %x, %x\n",(HALF)busData, busData);
  62.                                 /* 假如busData=0x284b8086,那么(unsigned short)busData=8086 */                               
  63.                                 if ((unsigned short) busData != 0xffff) //只需比较它的2个字节,通过产商ID和ffff比较来判断这个设备是否存在
  64.                                 {
  65. //                                                printf ("%x %x %x %x %x\n", bus, device, func, busAddr, busData);       
  66. //#if 0
  67.                                         if (indentify_id == busData) //查找Vendor ID和Device ID分别是8086和284b的设备
  68.                                         {
  69.                                                 printf ("bus=%x,device=%x,func=%x,busAddr=%x,busData=%x\n", bus, device, func, busAddr, busData);       
  70.                                                 flag = 1;        //找到设备后就退出
  71.                                                 break;
  72.                                         }
  73. //#endif                                       
  74.                                 }
  75.                         }
  76.                         if (flag)
  77.                                 break;
  78.                 }
  79.                 if (flag)
  80.                         break;
  81.         }
  82.         /* 找到设备后读取它的配置空间信息 */
  83.         if (flag)
  84.         {
  85. //                printf ("VendorID=%x, DeviceID=%x\n", (unsigned short)busData, busData >> 16);        //将busData右移得到设备ID

  86.                 /* 获得Command部分,可以通过设置它的bit0、bit1和bit2这3位为1,bit0\bit1可以达到函数pci_enable_device的功能,就是为了开启io和内存映射,bit2是达到函数pci_set_master()的功能,让设备能够成为.. */
  87.                 /* 内嵌汇编 */
  88.                 __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr | 0x4), "Nd" (PCI_CONFIG_ADDRESS));
  89. //                outl (busAddr | 0x4, PCI_CONFIG_ADDRESS); //向配置空间的地址寄存器0xcf8写入地址           (这行代码和上面代码一个意思)
  90.                 __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA));
  91. //                busData = inl (PCI_CONFIG_DATA); //读取数据
  92.                 printf ("Command=%x\n", (unsigned short)busData); //得到command部分
  93.                 __asm__ __volatile__ ("outl %0,%w1": :"a" (busData | 0x00000007), "Nd" (PCI_CONFIG_DATA));
  94. //                outl (busData | 0x00000007, PCI_CONFIG_DATA); //将最低的3位置1
  95.                        
  96.                 /* Test:查看是否写的正确 */
  97.                 __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA));
  98. //                busData = inl (PCI_CONFIG_DATA); //读取数据
  99.                 printf ("Command=%x\n", (unsigned short)busData); //得到command部分


  100.                 /* 获得class code 和subclass、ProgIF、Reversion ID*/               
  101.                 __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr | 0x8), "Nd" (PCI_CONFIG_ADDRESS));
  102. //                outl (busAddr | 0x8, PCI_CONFIG_ADDRESS); //向配置空间的地址寄存器0xcf8写入地址
  103.                 __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA));
  104. //                busData = inl (PCI_CONFIG_DATA); //读取数据
  105.                 printf ("Class code=%x,Subclass=%x, progif=%x, Reversion ID=%x\n",(busData & 0xff000000) >> 24, (busData & 0x00ff0000) >> 16,(busData & 0xff00) >> 8 ,(BYTE)busData);

  106.                 /* 获得基址 */
  107.                 int i;
  108. //                char *buf = (char *) malloc (20);
  109.                 char buf[20];
  110.                 memset (buf,'0', 20);
  111.                 unsigned int base;
  112.                 unsigned int BarAddr[6];
  113.                 unsigned int bar_bak;
  114.                 unsigned int bar_len = 0;
  115.                 for (i = 0; i < 6; i++)
  116.                 {
  117.                         base = 0x10;
  118.                         base += i*4;
  119. //                        printf ("base=%x\n", base);
  120.                         __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr | base), "Nd" (PCI_CONFIG_ADDRESS));
  121. //                        outl (busAddr | base, PCI_CONFIG_ADDRESS); //想配置空间的地址寄存器0xcf8写入地址

  122.                         __asm__ __volatile__ ("inl %w1,%0":"=a" (BarAddr[i]):"Nd" (PCI_CONFIG_DATA));
  123. //                        BarAddr[i] = inl (PCI_CONFIG_DATA); //读取数据
  124.                         if (BarAddr[i] & 0x00000001) //假如最低位为1,说明这个地址是给IO空间的
  125.                                 printf ("IO address,BarAddr[%d]=%x\n", i, BarAddr[i] & 0xfffffffc);

  126.                         else
  127.                                 printf ("Memory address,BarAddr[%d]=%x\n", i, BarAddr[i] & 0xfffffff0);

  128.                         /* 获得需要的空间大小 */
  129.                         bar_bak = BarAddr[i]; //注意这里一定要保存原来的值
  130.                         printf ("bar_bak=%x\n", bar_bak);
  131.                         __asm__ __volatile__ ("outl %0,%w1": :"a" (busAddr | base), "Nd" (PCI_CONFIG_ADDRESS));
  132. //                        outl (busAddr | base, PCI_CONFIG_ADDRESS); //要操作的寄存器地址
  133.                         __asm__ __volatile__ ("outl %0,%w1": :"a" (0xffffffff), "Nd" (PCI_CONFIG_DATA)); //向这个Bar全部写1
  134. //                        outl (0xffffffff, PCI_CONFIG_DATA); //写入0xffffffff
  135.                         __asm__ __volatile__ ("inl %w1,%0":"=a" (busData):"Nd" (PCI_CONFIG_DATA)); //再读出它的值
  136.                         bar_len = ~(busData) + 1; //取返+1
  137.                         printf ("bar_len=%x\n", bar_len);
  138. //                        bar_len = ~(inl (PCI_CONFIG_DATA)) + 1; //再读出寄存器值取返,加1
  139.                         __asm__ __volatile__ ("outl %0,%w1": :"a" (bar_bak), "Nd" (PCI_CONFIG_DATA));
  140. //                        outl (bar_bak, PCI_CONFIG_DATA); //最后将原来值写回去

  141.                         /* Test:查看是不是写进去的再读出来和之前的是否一样--最后结果说明是对的 */
  142. #if 0                               
  143.                                 outl (busAddr | base, PCI_CONFIG_ADDRESS);
  144.                                 printf ("### %x\n", inl (PCI_CONFIG_DATA));
  145. #endif
  146.                 }
  147. #if 0
  148.                 /* 查看HeadType段 */
  149.                 outl (busAddr | 0x0c, PCI_CONFIG_ADDRESS); //想配置空间的地址寄存器0xcf8写入地址
  150.                 busData = inl (PCI_CONFIG_DATA); //读取数据
  151.                 printf ("Header Type=%x\n",(busData & 0x00ff0000) >> 16 );
  152. #endif

  153.         }
  154. }


  155. int
  156. main ()
  157. {
  158.         iopl (3); //设置IO端口权限
  159.         grub_traverse_pci (VENDOR_ID, DEVICE_ID);
  160.                
  161.         return 0;
  162. }
复制代码

论坛徽章:
0
13
发表于 2013-05-09 22:11
回复 2# 瀚海书香

谢谢,代码我写出来了。


   

论坛徽章:
0
14 [报告]
发表于 2013-05-09 22:12 |只看该作者
回复 6# lenky0401

谢谢,代码我已经贴出来了。


   

论坛徽章:
0
15 [报告]
发表于 2013-05-09 22:13 |只看该作者
回复 10# smalloc

谢谢,代码我写出来,贴出来了。

   

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
16 [报告]
发表于 2013-05-09 22:16 |只看该作者

赞~~~~~~~

论坛徽章:
0
17 [报告]
发表于 2013-05-09 22:20 |只看该作者
回复 16# chishanmingshen


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP