前面有文章分析了网卡也是属于类内存总线的设备,类内存总线的设备有地址总线和数据总线,先来看下DM9000的管脚:
从上面可以看出DM9000的地址总线就一根,它不像CS8900那样地址总线和数据总线都齐全。而这里只有一根地址线(CMD),16跟数据线,所以可以确定位宽为16位,而地址线为什么只有一根,这是DM9000决定的,看手册可以知道CPU总线只访问它的两个地址,CMD管脚为0时,数据线送的是DM9000的寄存器地址,CMD管脚为1时,数据线上送的是16位的寄存器数据,所以对DM9000的操作至少需要两步:先写地址,再写(读)数据。他不像其他类内存总线那样直接把数据写到地址传输一次就可以了,而他要传输两次,因为他的总线地址就退化成了类似于NAND的ALE信号,就是地址和数据的区分信号了,而不是DM9000里面操作的寄存器地址。
上面的片选信号为:nLAN_CS,链接到S3C2440的CS4,对应BANK4,所以基地址为0X20000000,网上很多人讨论为什么有的开发板基地址设置为0X20000300,这个是没有任何作用的,之前分析了,DM9000对于CPU的地址线只认识一根线,只要这根线对应的CPU传送的地址的对应位匹配就可以了,上面接到LADDR2,也就是说:
传寄存器地址的时候操作的总线地址满足:
以基地址起头(0x20000000),偏移基地址LADDR2为0(低四位:0000),也就是写的时候总线地址为:0x20000000
传寄存器数据的时候操作的总线地址满足:
以基地址起头,偏移基地址LADDR2为1 (低四位:0100),也就是写的时候总线地址为:0x20000004
所以首先满足总线地址在BANK4里面(这样CS4才能自动选中),其次满足最后四位为0(传送寄存器地址)或4(传送数据)就可以了,满足这两个条件地址随便设。
所以上面0x20000300这个多出的300H没任何意义,他满足上面条件,你设置为0x20000400,0x20000320,0x23456780这些地址都没任何影响。
上面分析知道了基地址,位宽,再简要说下中断引脚:
这里的IRQ_LAN接的是S3C2440的ENT7,用的外部中断7,这个中断用于接收数据时触发的,中断服务函数处理接收数据,向协议层上报接收数据。这个中断号要和驱动里面的对应起来。
DM9000移植的要点:
1 基地址(看CS接口)
2 CPU的寄存器设置:位宽,时序等设置
3 设置中断号(看中断接口)
原文链接:https://blog.csdn.net/wangshuchangfrank/article/details/22588179?utm_source=blogxgwz7
上面的内容是转载的,下面补充本人理解的:
基地址的设置并不一定要0x2000 0000,只要满足在一定范围内,让片选使能;然后LADDR2为0则表示data线上传输的是地址,LADDR2为1表示data线上传输的是数据
主控芯片上面发出的地址,只不过决定了DM9000是否被片选,且ADDR2决定了是传输地址还是数据,仅此而已,而访问DM9000上某个寄存器所需的地址,是在数据线上传输的!!!!!!
在DM9000的厂家驱动程序里面,我们可以看到
outb(DM9KS_VID_L, iobase); /* DM9000C的索引寄存器(cmd引脚为0) */ 这里其实就是写 DM9KS_VID_L (0x28)这个值给DM9000,告诉他是地址(通过把ADDR2拉低的方式)id_val = inb(iobase + 4); /* 读DM9000C的数据寄存器(cmd引脚为1) */ 这里就是读取数据了(iobase + 4 表示传输的是数据),读出来到 id_val 这在第二个视频第二分钟的时候有讲到outb(DM9KS_VID_H, iobase);id_val |= inb(iobase + 4) << 8;outb(DM9KS_PID_L, iobase);id_val |= inb(iobase + 4) << 16;outb(DM9KS_PID_H, iobase);id_val |= inb(iobase + 4) << 24;
读DM9000上的寄存器的步骤如下:
把要读取的寄存器地址写到“索引寄存器”里面,然后再读数据寄存器。(怎么分辨操作的是索引寄存器还是数据寄存器呢?通过ADDR2的状态来决定)
CMD引脚一般都是接到主控的ADDR2引脚,包括DM9000的厂家程序也是默认如此,所以我们才不用改,如果我们不是把CMD接到ADDR2,而是ADDR1,那 iobase +4 就得改成 iobase + 2 了,但一般没有硬件工程师这么干,而是参照芯片厂家给出的参考电路图去设计的,所以大多数的开发板也都把主控的ADDR2接到DM9000的CMD引脚。