libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:3506回复:45

谈谈ISA的DMA传输,8237的设置问题

楼主#
更多 发布于:2003-05-27 09:11
我的ISA板子上有一映射的内存,想通过DMA方式把数据从这个映射内存传输到主板的内存子中,我的DMAC是主板上的8237,不知道我的8237的控制寄存器(命令寄存器)是设置成:存储器到存储器的传输还是设置成I/O到存储器的传输?请大虾指教!!!
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-05-27 23:23
看你的内存是映射在I/O空间,还是存储器空间。不过,我只用过I/O到存储器的传输,这种传输可在ISA总线DMA周期中查到。
虾米
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-05-28 08:17
我是映射到存储器空间的,这种情况下,是不是只能用通道0和1来传输数据,是这样吗?
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-05-28 14:27
是这样的,并且内存到内存的传输是不推荐的,因为速度慢得多。
虾米
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-05-28 14:56
我的板子上有两个映射的内存,都需要DMA传输,那么必须竞争使用通道0和1了!那么写驱动程序的时候怎么处理,是申请通道0还是1呢?
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-05-28 21:08
通道0和1都是8位数据传输,但好象成功的机会较少,你可以看一下《PC技术内幕》这本书,上面对DMA的存储器到存储器传输不是很赞成。
虾米
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-05-29 12:49
DMA的板卡上的映射内存到主板内存的数据传输必须使用通道1和0?我认为使用别的通道也是可以的吧?比如通道5,为什么就不可以呢?
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-05-29 13:29
  8237的4个通道中只有通道0和1是可以支持RAM到RAM的传输,因为RAM到RAM的传输要用到8237内部的临时寄存器,而临时寄存器只有1个。
  在设为RAM到RAM的传输时,通道0存放源地址,通道1存放目的地址和传送字节数。由通道0的软件请求启动传送,数据从源RAM到8237的临时寄存器,再由8237的临时寄存器到目的RAM。而且8237的临时寄存器是8位的,不是16位的。
  在AT及以后的PC机中使用了2片8237,8237之间采用级联。硬件电路已将DRQ0-DRQ3设计为8位,将DRQ5-DRQ7设计为16位,DRQ4用于级联,考虑到8237的临时寄存器是8位的,所以只能用DRQ0和DRQ1来实现RAM到RAM的传输。
  由于PC机之间的兼容性,部分PC机可能没有实现8237的数据和存储器的数据的连通关系。而且,如果存储器是DRAM的话,实现存储器和8237的数据交换还可能影响DRAM的刷新,导致系统故障。所以不赞成使用RAM到RAM的DAM传输。
  而IO和RAM之间DMA时,数据是在IO和RAM之间交换的,不通过8237的临时寄存器,所以可以是16位的。
虾米
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2003-06-02 19:48
 8237的4个通道中只有通道0和1是可以支持RAM到RAM的传输,因为RAM到RAM的传输要用到8237内部的临时寄存器,而临时寄存器只有1个。
  在设为RAM到RAM的传输时,通道0存放源地址,通道1存放目的地址和传送字节数。由通道0的软件请求启动传送,数据从源RAM到8237的临时寄存器,再由8237的临时寄存器到目的RAM。而且8237的临时寄存器是8位的,不是16位的。
  在AT及以后的PC机中使用了2片8237,8237之间采用级联。硬件电路已将DRQ0-DRQ3设计为8位,将DRQ5-DRQ7设计为16位,DRQ4用于级联,考虑到8237的临时寄存器是8位的,所以只能用DRQ0和DRQ1来实现RAM到RAM的传输。
  由于PC机之间的兼容性,部分PC机可能没有实现8237的数据和存储器的数据的连通关系。而且,如果存储器是DRAM的话,实现存储器和8237的数据交换还可能影响DRAM的刷新,导致系统故障。所以不赞成使用RAM到RAM的DAM传输。
  而IO和RAM之间DMA时,数据是在IO和RAM之间交换的,不通过8237的临时寄存器,所以可以是16位的。
 


感谢楼上大哥的热心回答,我看了关于8237的资料,确实是你说的这种情况,你回答的非常出色!

我想解决这个问题的方式有两个,一个是把双口RAM的寻址方式改成I/O寻址,这样就可以使用 通道5的DMA传输了。另一个方法是把双口RAM改成FIFO,同样也使用通道5来进行DMA传输,这样就不存在多个地址的问题,因为FIFO只有一个口地址。但我以前的传输条件:双口RAM半满的时候发DMA请求在用FIFO的情况下,应怎样处理?也就是怎样进行这种情况下的DMA块传输?请大虾指点迷津!
真的很感激你的回答!
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2003-06-02 21:14
不用客气,你的问题也促使我将ISA的DMA操作理解地更全面。

可以使用FIFO的半满信号触发中断;在中断的服务程序中设置DMA的内存起始地址和传输字节数(可设为FIFO的半满字节数),并有效DRQ5;在TC和/DACK5同时有效时清除中断和DRQ5。在中断的服务程序中设置信号量,即可通知用户程序处理有效的数据块。如果使用可编程逻辑的话,关键的部分如下:
S:  DFF;
S.CLK = HALF(半满信号);
S.D = VCC;
DRQ5 = S.Q;
IRQn = S.Q;
S.CLRN = !(TC & !DACK5);

如果FIFO发生上溢,则说明DMA的速度没有FIFO填充的速度快,不过这种情况应该不会发生吧?!
虾米
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2003-06-03 08:29
不用客气,你的问题也促使我将ISA的DMA操作理解地更全面。

可以使用FIFO的半满信号触发中断;在中断的服务程序中设置DMA的内存起始地址和传输字节数(可设为FIFO的半满字节数),并有效DRQ5;在TC和/DACK5同时有效时清除中断和DRQ5。在中断的服务程序中设置信号量,即可通知用户程序处理有效的数据块。如果使用可编程逻辑的话,关键的部分如下:
S:  DFF;
S.CLK = HALF(半满信号);
S.D = VCC;
DRQ5 = S.Q;
IRQn = S.Q;
S.CLRN = !(TC & !DACK5);

如果FIFO发生上溢,则说明DMA的速度没有FIFO填充的速度快,不过这种情况应该不会发生吧?!


能详细地说说吗?是不是硬件上要有一定的口地址让我来写这些参数,可是FIFO片子上没有这些口地址啊?有些糊涂!!!


我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2003-06-03 10:19
还有一个问题就是FIFO片子上没有地址线,那就是不用译码。那么在驱动中我怎么申请这个资源?是属于I/O呢?还是属于MEMORY?还是不用申请?
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2003-06-03 12:55
S是一个D触发器;
S.CLK是触发器的时钟端;
HALF是FIFO的半满信号;
S.D是触发器的数据输入端;
S.Q是触发器的数据输出端;
S.CLRN是触发器的异步清零端;
DRQ5是ISA总线信号,为DMA请求;
IRQn是你选择的ISA总线IRQ信号;
TC是ISA总线信号,为任一DMA通道全部数据传送结束信号;
DACK5是ISA总线信号,为DMA应答。
与S有关的设计全部是硬件电路或可编程逻辑,所以DMA请求和中断请求都是硬件触发和硬件清除的。需要软件设置的主要是PC机的DMA页面寄存器、相应DMA通道的地址和计数寄存器,以及开放中断和DMA通道。DMA页面寄存器、8237和8259的地址在PC机上是固定的、开放的,你要自己先找一下资料,不然我还不一定说的清楚。

FIFO应该映射到I/O空间,用DACK5来做DMA时FIFO的片选信号,用AEN(ISA总线信号,为0表示正常读写,为1表示由CPU以外的控制器来接管ISA总线)来区分DMA读写和正常的读写,读写使用IOR和IOW(也是ISA总线信号)。
虾米
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2003-06-03 16:28
谢谢你的回答!

你做过WIN2000下的系统DMA的驱动吗?用DDK或DS都可以的,我在启动DMA这里卡住了,所有的资料都说,告诉设备开始请求DMA服务,也就是给设备发送合适的命令来启动DMA传输,但我感觉DMA请求来自外设的DREQ,我怎么控制这根信号?还有,8237的内部寄存器我不能碰,DDK的函数封装了底层的东西,我不能读或写它的寄存器,是这样吧?我该怎么办?问了很多人,都不知道怎么办!
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2003-06-03 19:38
我没有做过这方面的驱动,但我很想继续和你探讨这方面的问题,并随时提供可能的帮助。我从事的主要是硬件设计和板级调试,不太注意软件的使用。但我和很多驱动开发人员接触过,我能理解你的难题。

(1)你要找到初始化DMA传输物理地址和计数的函数,驱动开发软件肯定会提供这些函数。
(2)你要找到将DMA传输物理地址和软件缓冲区对应的函数,因为DMA使用的是真实物理地址,而不是虚拟地址。
(3)把你能找到的DMA方面的函数的说明发到论坛上,我可以帮你分析一下操作流程。

关于“告诉设备开始请求DMA服务”的说法,我提供的设计不需要对设备进行操作,硬件会自动提出DRQ5。但8237是否会处理DRQ5,还需要看DRQ5的屏蔽位,对屏蔽位的操作详见8237的手册,这个操作也应已被驱动开发软件封装在函数内。你要找找了。
虾米
ljfhch
驱动牛犊
驱动牛犊
  • 注册日期2003-06-03
  • 最后登录2003-07-28
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2003-06-03 21:40
这么快就得到了你的回复,真的是很感激!
你说的很对,DDK封装了很多的对8237的内部寄存器的设置,所以我感觉我不能直接读写它的内部寄存器。你说的使能DREQ,一点不错,是要设置8237的屏蔽寄存器,我看了8237的这部分资料,可以同时设置4个通道的,也可以分别设置每个通道的,我感觉,这个功能;也被DDK的函数给封装了,但我找不到这个函数。麻烦你问一下你那些做过驱动的同事,做过WIN2000,下的NT试或WDM试的系统DMA驱动的人(我见过好多做过WIN98下的系统DMA驱动的,是VXD的驱动和2000下的差别很大,没有值得借鉴的),我是不是要自己去设置屏蔽寄存器来使能DREQ有效,还是我不能设置它,要通过操作设备来使DREQ有效?
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2003-06-03 22:01
不好意思,刚才用别人的帐户留的言!

这么快就得到了你的回复,真的是很感激!
你说的很对,DDK封装了很多的对8237的内部寄存器的设置,所以我感觉我不能直接读写它的内部寄存器。你说的使能DREQ,一点不错,是要设置8237的屏蔽寄存器,我看了8237的这部分资料,可以同时设置4个通道的,也可以分别设置每个通道的,我感觉,这个功能;也被DDK的函数给封装了,但我找不到这个函数。麻烦你问一下你那些做过驱动的同事,做过WIN2000,下的NT试或WDM试的系统DMA驱动的人(我见过好多做过WIN98下的系统DMA驱动的,是VXD的驱动和2000下的差别很大,没有值得借鉴的),我是不是要自己去设置屏蔽寄存器来使能DREQ有效,还是我不能设置它,要通过操作设备来使DREQ有效?
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2003-06-03 23:36
给我作过DMA驱动的人已经跳了。
我觉得还是要找到设置8237的屏蔽寄存器的函数,我没有这方面的代码样例,你可以把相关的函数说明发出来,我可以帮忙区分一下。
虾米
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2003-06-04 09:28
相关函数:IoMapTransfer,只是说了得到内存描述符(MDL)的物理地址和长度(传输长度),对于系统DMA设备(例如ISA的8237控制的设备)利用这个函数可以得到这两项,并且完成编程硬件的功能,我理解就是这个函数执行的结果,相当于用汇编函数往该通道的地址和记数寄存器写入地址和记数值,但写屏蔽寄存器,我没看到哪个函数有这种功能。还有,在驱动入口点中的适配器对象中定义的DEVICE_DESCRIPTION中的DEMANDMODE是TRUE,还是FALSE,我理解是要设置模式寄存器。自动初始化是TRUE,还是 FALSE是设置控制寄存器。其他的没看出怎么设置那些寄存器。
不知道你同事原来做的是什么系统下的什么类型的DMA,是系统的还是总线主的?
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
我是游虾儿
驱动牛犊
驱动牛犊
  • 注册日期2003-05-05
  • 最后登录2004-03-04
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2003-06-04 11:57
我同事原来做的是NT下系统8237提供的DMA,不是类似PCI总线主控的方式。

如果只有IoMapTransfer这一个函数和DMA有关,且IoMapTransfer能识别DMA通道指定的话,我认为该函数已经进行了开放相应通道屏蔽位的操作。也就是说,该函数一被调用,8237就会立刻响应该通道的DMA请求。

根据我给你的设计,我认为DEVICE_DESCRIPTION中的DEMANDMODE可设为FALSE,因为硬件是在FIFO半满时发起DMA请求的,在块传输字节不超过FIFO的一半时8237不用理会DRQ5是否始终有效。如果你想开两个缓冲,轮流存放数据/处理数据,就让自动初始化是FALSE,且在每次中断时都调用IoMapTransfer函数,以便更新内存的物理地址及再次开放相应通道屏蔽位。

在我提供的设计中有一个限制,就是DMA的速度一定要比FIFO的填充速度块,否则DMA结束时FIFO的半满信号可能还没从有效变成无效,这会导致下一次DMA请求和中断请求不能产生。
虾米
上一页
游客

返回顶部