免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3527 | 回复: 3
打印 上一主题 下一主题

[硬件及驱动] 访问PCI配置空间,不理解宏PCI_CONF1_ADDRESS的实现 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-08-28 11:24 |只看该作者 |倒序浏览
hi,大家好:
     最近学习linux内核代码,当看到文件/arch/x86/pci/Direct.c时,对里面的部分代码感到困惑:

  1. /*
  2. * Functions for accessing PCI base (first 256 bytes) and extended
  3. * (4096 bytes per PCI function) configuration space with type 1
  4. * accesses.
  5. */

  6. #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
  7.         (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
  8.         | (devfn << 8) | (reg & 0xFC))

  9. int pci_conf1_read(unsigned int seg, unsigned int bus,
  10.                           unsigned int devfn, int reg, int len, u32 *value)
  11. {
  12.         unsigned long flags;

  13.         if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
  14.                 *value = -1;
  15.                 return -EINVAL;
  16.         }

  17.         spin_lock_irqsave(&pci_config_lock, flags);

  18.         outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);

  19.         switch (len) {
  20.         case 1:
  21.                 *value = inb(0xCFC + (reg & 3));
  22.                 break;
  23.         case 2:
  24.                 *value = inw(0xCFC + (reg & 2));
  25.                 break;
  26.         case 4:
  27.                 *value = inl(0xCFC);
  28.                 break;
  29.         }

  30.         spin_unlock_irqrestore(&pci_config_lock, flags);

  31.         return 0;
  32. }

  33. int pci_conf1_write(unsigned int seg, unsigned int bus,
  34.                            unsigned int devfn, int reg, int len, u32 value)
  35. {
  36.         unsigned long flags;

  37.         if ((bus > 255) || (devfn > 255) || (reg > 4095))
  38.                 return -EINVAL;

  39.         spin_lock_irqsave(&pci_config_lock, flags);

  40.         outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);

  41.         switch (len) {
  42.         case 1:
  43.                 outb((u8)value, 0xCFC + (reg & 3));
  44.                 break;
  45.         case 2:
  46.                 outw((u16)value, 0xCFC + (reg & 2));
  47.                 break;
  48.         case 4:
  49.                 outl((u32)value, 0xCFC);
  50.                 break;
  51.         }

  52.         spin_unlock_irqrestore(&pci_config_lock, flags);

  53.         return 0;
  54. }
复制代码
内核版本为2.6.18。大家知道,如果使用IO端口CF8/CFC访问PCI配置空间的时候,只能访问配置空间的前256字节,如果要访问大于256字节的空间,必须使用ECAM(Enhanced Configuration Access Mechanism)机制,关于这点,在PCI规范里有提到,在PCI[1].Express.Base.Specification.v1.0中第313页中有如下文字:
The extended PCI Express region can only be accessed by using the enhanced PCI Express configuration access mechanism

     上面说的extended PCI Express region指的就是256字节以上的空间。
     但是上面的代码中的注释说可以访问前256字节和所有的4096字节,我感到不解。上面代码中的宏PCI_CONF1_ADDRESS:
  1. #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
  2.         (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
  3.         | (devfn << 8) | (reg & 0xFC))
复制代码
如果此时访问前256字节,那么((reg & 0xF00) << 16)就为0,此时就生产了一个地址用来访问配置空间,这种方式很好理解,PCI规范里说的很清楚。但是如果访问的字节偏移大于256字节,那么((reg & 0xF00) << 16)就不为0,这种(生成地址的)方式不管是在PCI规范里还是在书里都没见到过。哪位大侠指教指教,谢谢!

论坛徽章:
0
2 [报告]
发表于 2012-08-28 16:31 |只看该作者
通过CF8/CFC I/O端口只能读256byte, 如果要读4096需要通过MMIO方式。估计注释是错误的。
http://www.ilinuxkernel.com/file ... press_Kernel_RW.htm

论坛徽章:
0
3 [报告]
发表于 2012-08-28 17:29 |只看该作者
     谢谢你的回复。
     你说的是对的,我没说清楚,如果使用增强访问配置机制访问大于256字节的空间的时候,实际使用的是MMIO的方式,不能通过IO端口。所以我对我贴出的这段代码和里面的注释感到很奇怪。但是内核里面的东西应该是非常严谨的,似乎不应该有这样的明显的错误,也许是我理解不够深入吧。而且不光是注释里那样说说而已,函数的实现跟注释也是一致的:

  1. if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
  2.                 *value = -1;
  3.                 return -EINVAL;
  4.         }
复制代码
很明显,代码的意思是reg可以大于256。
     

论坛徽章:
0
4 [报告]
发表于 2012-08-30 09:44 |只看该作者
不要迷信,kernel里面有大把的bug存在。这个边界检查是个小问题,只要输入的reg参数不会超过255就不会出问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP