免费注册 查看新帖 |

Chinaunix

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

PCI映射内存读写求助 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-07 12:56 |显示全部楼层 |倒序浏览
自己做的板子,linux2.6.20,host mpc8313,pci device dm642,dm642外接64MB的SDRAM。

Base 0: 4M-byte prefetchable maps to all of DSP memory with the DSP page register (DSPP).

驱动里,我用pci_resource_start获得base0的物理地址,ioremap到虚拟地址mmio上。

在read和write函数里,我使用ioread(mmio + offset)和iowrite(mmio + offset)来读写内存。

按照我的理解,4MB的开窗范围,那么offset的范围是0—3fffff,超过这个范围的话,就要挪动窗的位置,即重新设置DSPP的值,64MB的外设内存,DSPP的范围就是0—F。

现在的情况是:
1、offset的范围是0— 47ffff 的时候,都可以正常读写。
2、DSPP为0时,可以正常读写。DSPP设置其余值时候,读出的数据全高。

请问我对于的读写理解是不是有问题,正确的是怎么样的呢?谢谢。

论坛徽章:
0
2 [报告]
发表于 2008-11-07 15:33 |显示全部楼层
应该没有限制。

DSPP register (bits 9−0) Current PCI address (bits 21−0)
sdram的物理地址是0x80000000,映射后是0xc9080000。

比如,我要读写0xc9080000这个地址,即设置DSPP为0x324,ioread32(0xc9080000)读出来全高。

请问上面的Current PCI address 是不是ioread里面的参数的低22位?

论坛徽章:
0
3 [报告]
发表于 2008-11-07 16:01 |显示全部楼层
DSPP设置sdram开窗的位置。我映射的内存大小只有4MB,实际的sdram有64MB,就需要DSPP。

PCI Base Slave Address = DSPP register (bits 9-0) Current PCI address (bits 21-0),这里的PCI Base Slave Address是物理地址?

DSPP bits 9-0 是根据要访问的物理地址得到的,那么我理解Current PCI address (bits 21-0)也应该是一个物理地址。

可是,ioread的参数应该是一个映射后的虚拟地址,即Current PCI address不是ioread的参数。

那么Current PCI address 是在哪里定义的呢,或者说以什么形式出现的呢?

我这样理解对么?谢谢。

ps,我对io端口、io内存这类定义理解的比较模糊,我的理解是,sdram属于io内存,所以对sdram的访问是通过ioread来完成的。不知道对不对。

论坛徽章:
0
4 [报告]
发表于 2008-11-07 16:13 |显示全部楼层
谢谢版主,你这么解释内存的话,我现在的问题就集中在从哪里获取Current PCI address了。

论坛徽章:
0
5 [报告]
发表于 2008-11-07 18:47 |显示全部楼层
问题解决了。

Current PCI address是cpu自动从虚拟地址转换得到的。

论坛徽章:
0
6 [报告]
发表于 2008-11-13 14:38 |显示全部楼层
原帖由 dreamice 于 2008-11-7 21:26 发表



恭喜,恭喜
建议你写个总结跟在这个帖子后面,分享一下你的经验,包括如何解决的,以及相关技术知识,这样有助于你巩固经验,又有利于他人学习借鉴,呵呵。


我这段时间忙完之后就写。

论坛徽章:
0
7 [报告]
发表于 2008-12-11 15:30 |显示全部楼层
好不容易可以歇两天了,简单写了点自己的感受。

关于设备的驱动步骤等通用性的东西就不啰嗦了,我认为步骤最好的参考是内核的说明文档《Documentation/pci.txt》,实现的参考就是LDD3了。这里就说针对DM642这个PCI设备说一下其特殊性,资料来源于TI的SPRU581C。

第一,IO memory,IO port,简单的说,一个是memory,一个是port。前者先映射再通过readX、writeX(早期版本)或ioreadX、iowriteX(近期版本)访问,后者直接使用inX、outX访问,后者也可以ioport_map为memory被访问。针对不同架构的处理器,两者的处理略有不同,这里不细述了。

第二,host、agent,master、slave。这是采用DMA方式时候遇到的概念,host和agent是固定的,master和slave区分谁是数据传输的发起者。

PCI驱动最重要的就是PCI Registers的设置,对于DM642,有Configuration Registers(只能被host访问)、I/O Registers(只能被host访问)、Memory-Mapped Registers(能被host和dsp本身访问)。

1、Configuration Registers:它里面的Base Address需要特别注意,其余的一般的话都用不到。
DM642的Base Address有三种:4M-byte prefetchable、8M-byte nonprefetchable和4 words I/O。
(1)4M-byte prefetchable的作用:DM642有4GB的寻址空间,需要使用开窗的方式来完成内存映射,4M-byte prefetchable就提供窗内的映射地址信息。通过pci_resource_X系列函数得到该IO区域的信息,ioremap后就可以直接被主机访问了。
(2)8M-byte nonprefetchable,没用到。
(3)4 words I/O,它在pci_resource_X后需要ioport_map,才能被当作内存来访问。

2、I/O Registers:可以通过8M-byte nonprefetchable或4 words I/O访问,我选择了后者。它的DSPP就是完成开窗位置的寄存器。

3、Memory-Mapped Registers,master传输时候用到的寄存器。

到目前为止,主机通过PCI访问DM642内存的准备工作已经完成,接下来就是Memory Map到需要访问的地址上。
PCI Base Slave Address Generation = DSPP register (bits 9-0) + Current PCI address (bits 21-0),共32位地址。
这里需要处理的都是物理地址,问题就出在了Current PCI address这里,从哪里得到这个地址呢,没有相关的寄存器。因为CPU执行内存读写函数时候,会自动把虚拟地址转换为物理地址,那么Current PCI address就是由CPU自己来完成的。我只需要在ioreadX和iowriteX里给出Current PCI virtual address,CPU自己会转换为Current PCI address,就可以得到PCI Base Slave Address。

至此,主机读写DM642内存已经可以顺利进行。

评分

参与人数 1可用积分 +12 收起 理由
dreamice + 12 我很赞同,总结得很好!

查看全部评分

论坛徽章:
0
8 [报告]
发表于 2008-12-11 15:50 |显示全部楼层
斑竹过奖了,我只是新手,第一次写驱动,还有太多东西要学习。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP