DM9000驱动解析
- 格式:pdf
- 大小:2.99 MB
- 文档页数:28


下面我们来介绍一下TQ2440开发板上的另一个芯片—DM9000。
DM9000寄存器功能详细介绍总体看来DM9000是一个全集成、功能强、性价比高的快速以太网MAC层控制器。
它带有一个通用处理器接口、EEPROM接口、10/100 PHY和16KB的SRAM (其中13KB用来接收FIFO,3KB用来发送FIFO)。
电源模块采用的是单一电源,可以分别兼容3.3V和5V的IO接口电平。
DM9000支持MII(Media Independent Interface 介质无关)接口,可以连接到HPNA(Home Phone-line Networking Alliance)即家用电话网络联盟的设备上。
如果按照字面意思来理解,介质无关就是接口和介质没有关系。
在这里介质特指是指网络介质,也就是信号传输的媒介,如光纤、光缆、同轴电缆、各类双绞线等等。
介质无关接口作用是将不同类型的PHY与相同网络控制器(MAC)相连接。
MAC可以用同样的硬件接口与任意一个PHY相连接。
当然与之对应的是介质相关接口,用于PHY和传输介质的相连。
意味着对于不同的介质,相应的接口标准是不同的,故称之为“介质相关”。
DM9000以太网驱动器,内置一系列可被访问的控制状态寄存器。
这些字节对对齐的寄存器,在硬件或者软件复位时需要设置成初始值。
DM9000支持各类接口访问内部内部存储器,故而可以支持不同类型的处理器。
DM9000的物理层的协议接口支持使用10兆以下的第3类、4类、5类非屏蔽双绞线和100兆的第5类非屏蔽双绞线。
DM9000是一个集成度很高、功耗很低的高速网络控制器,用于各类开发板中。
它可以直接连接CPU部分,支持10M或100M的的快速以太网连接。
在DM9000内自带4K双字节的SRAM,其中13KB用来接收,另外3KB用来发送。
它支持8各类CPU,还有IEEE 802.3x全双工流量控制。
在整个流程中DM9000的操作很简单,故而用户可以轻易的移植系统里的端口驱动程序。
OK6410、2.6.36内核移植,dm9000 驱动移植,详细!分类:嵌入式学习Linux学习2012-04-27 00:54 3004人阅读评论(7) 收藏举报interfaceccompressionresourcesstructtable还是先来吐槽:本来我是在上一个星期的周末已经把Linux2.6.34.11 的驱动已经成功的移植到,OK6410 的开发板上的,并且能够启动主机上的NFS 根文件系统,可是我在周一的时候,开始学习LCD 的驱动程序,在修改内核文件的时候,有几处错误修改,将原来自己做的2.6.34.11 的内核源码搞的乱七八糟的,在这里还是自己在修改内核的时候没有提注重注释,并且没有记录下来自己的操作步骤,以至于我没办法,恢复2.6.34 的内核,所以也就只能重新先开始最基础的内核移植了。
这次我选择的是2.6.36.2 的内核,谁知到一开始移植就出现一大堆问题。
在这里我不得不说,飞凌开发人员对内核修改的代码,管理真的是太扯了,自己在注销任何一个设备是没有一点点注释,就把这个设备原有的线性地址分配给其它设备了,让我让我们这些菜鸟干看着一大堆的报错信息顶个什么用,真的是伤不起。
好了不乱扯了,现在开始记录。
我的开发环境是:VMware Ubuntu 10.10 。
OK6410 A版256M+2G 的开发板。
主机系统:XP。
Uboot:飞凌提供的Uboot。
参考内核:飞凌提供的Forlinx 的2.6.36.2 内核操作步骤以下./ 均代表你的内核根目录1、修改./Makefile191 ARCH ?=arm // 指定cpu类型,arm后面不要有空格,要不然编译是会提醒ARCH 不能为一个目录192 CROSS_COMPILE ?=/usr/local/arm/4.2.2-eabi/usr/bin/arm-linux- // 指定交叉编译器的路径,按照你自己的进行指定路径2、先来说说nand flash 的驱动涉及到的文件:MTD 通用nand flash 驱动程序位置:./drivers/mtd/nand/.nand_base.cNAND Flash 的platform 设备信息: ./drivers/mtd/nand/s3c_nand.c有了上面的依赖驱动依赖程序、接下来修改./arch/arm/mach-s3c64xx/mach-smdk6410.c 1) nandflash 驱动,修改方法加载头文件[cpp]view plaincopyprint?1.#include <linux/mtd/mtd.h>2.#include <linux/mtd/partitions.h>3.#include <plat/nand.h> //这些头文件放在./arch/arm/plat-samsung/include/ 下面添加nand 结构体[cpp]view plaincopyprint?1.// add by acanoe first2.extern void s3c64xx_reserve_bootmem(void); //add by acanoe3.4.5.struct mtd_partition ok6410_nand_part[] = {6. {7. .name = "Bootloader",8. .offset = 0,9. .size = (1 * SZ_1M),10. .mask_flags = MTD_CAP_NANDFLASH,11. },12. {13. .name = "Kernel",14. .offset = (1 * SZ_1M),15. .size = (5*SZ_1M) ,16. .mask_flags = MTD_CAP_NANDFLASH,17. },18. {19. .name = "User",20. .offset = (6 * SZ_1M),21. .size = (120*SZ_1M) ,22. },23. {24. .name = "File System",25. .offset = MTDPART_OFS_APPEND,26. .size = MTDPART_SIZ_FULL,27. }28.};29.30.31.static struct s3c2410_nand_set ok6410_nand_sets[] = {32. [0] = {33. .name = "nand",34. .nr_chips = 1,35. .nr_partitions = ARRAY_SIZE(ok6410_nand_part),36. .partitions = ok6410_nand_part,37. },38.};39.40.41.static struct s3c2410_platform_nand ok6410_nand_info = {42. .tacls = 25,43. .twrph0 = 55,44. .twrph1 = 40,45. .nr_sets = ARRAY_SIZE(ok6410_nand_sets),46. .sets = ok6410_nand_sets,47.};48.//add by acanoe first修改 smdk6410_devices[] __initdata = {对照这个结构体将那些进行修改,注意 by acanoe 的语句为修改重点。
DM9000网卡驱动笔记网卡芯片为DM9000,ARM开发板用的是S3C6410,PC机装的是RED HAT ENTERPRISE LINUX 5.5.网卡接入soc上并没有接入到专门的驱动ic上,而是接入到了SROM的控制器上,所以需要配置的寄存器就需要配置SROM的寄存器。
S3C6410支持6页的SROM,DM9000的片选连接到了SROM控制的bank1,地址线连接的是addr2,也就是以后地址线上发出去的数据,第2位为0,数据为地址,第2位为1,数据为数据(这比较难理解)。
根据这样的地址数据的读写,操作DM9000中的寄存器,配置好网卡芯片,arm端封装一个arp请求包,在PC机上用tcpdump命令看能不能接收到如果能接受,网卡配置就算比较成功了附上源码:#include "up.h"#define INDEX (0x18000000)#define DATA (0x18000004)int (*printf)(char *, ...) = 0x57e11d4c;void (*udelay)(int ) = 0x57e00a98;struct ethhdr{unsigned char dest[6];unsigned char source[6];unsigned short type;};struct arphdr{unsigned short hw_type;unsigned short pro_type;unsigned char hw_len;unsigned char pro_len;unsigned short op;unsigned char src_mac[6];unsigned char src_ip[4];unsigned char dest_mac[6];unsigned char dest_ip[4];};void write_dm9000(unsigned char reg, unsigned short val); unsigned short read_dm9000(unsigned char reg);void init_dm9000();void send_data(unsigned char *buff, int len);int create_arp(unsigned char *buff);void *memset(void *s, int c, int len);unsigned short htons(unsigned short);int main(){/*set XM0bank1*/SROM_BW = (1 << 4);SROM_BC1 = (4 << 4) | (5 << 16);unsigned char buff[1024] = {0};int len = create_arp(buff);init_dm9000();send_data(buff, len);return 0;}void write_dm9000(unsigned char reg, unsigned short val) {*(unsigned char *)INDEX = reg;*(unsigned short *)DATA = val;}unsigned short read_dm9000(unsigned char reg) {*(unsigned char *)INDEX = reg;unsigned char c = *(unsigned char *)DATA;return c;}void init_dm9000(){//application notes//step 1: p22write_dm9000(0x1f, 0x00);//step 2:write_dm9000(0x00, 0x01);udelay(10);write_dm9000(0x00, 0x00);//step 3:write_dm9000(0x00, (1 << 3));//step 4:write_dm9000(0xff, 0xff);//step 5://step 6:write_dm9000(0x10, 0x11);write_dm9000(0x11, 0x22);write_dm9000(0x12, 0x33);write_dm9000(0x13, 0x44);write_dm9000(0x14, 0x55);write_dm9000(0x15, 0x66);//step 7://step 8:write_dm9000(0x01, (1 << 2) | (1 << 3) | (1 << 5));write_dm9000(0xfe, 0x3f);printf("3\n");//step 9://step 10:write_dm9000(0xff, 0xff);//step 11:write_dm9000(0x05, 0x01);//step 12:}void send_data(unsigned char *buff, int len){//p28://step 1:unsigned char c = read_dm9000(0xfe);if(c >> 7)printf("8 bit mode\n");elseprintf("16 bit mode\n");//step 2*(unsigned char*)INDEX = 0xf8;int tmp = (len + 1) >> 1;int i = 0;for(i=0; i<tmp; i++){*(unsigned short *)DATA = ((unsigned short*)buff)[i];}//step 3write_dm9000(0xfd, (len >> 8) & 0xff);write_dm9000(0xfc, len & 0xff);//step 4write_dm9000(0x02, 0x01);}int create_arp(unsigned char *buff){int len = 0;struct ethhdr *eth = (struct ethhdr *)buff;eth->dest[0] = 0xff;eth->dest[1] = 0xff;eth->dest[2] = 0xff;eth->dest[3] = 0xff;eth->dest[4] = 0xff;eth->dest[5] = 0xff;eth->source[0] = 0x11;eth->source[1] = 0x22;eth->source[2] = 0x33;eth->source[3] = 0x44;eth->source[4] = 0x55;eth->source[5] = 0x66;eth->type = htons(0x0806);struct arphdr *arp = (struct arphdr *)(buff + sizeof(struct ethhdr));arp->hw_type = htons(1);arp->pro_type = htons(0x0800); arp->hw_len = 6;arp->pro_len = 4;arp->op = htons(1);arp->src_mac[0] = 0x11;arp->src_mac[1] = 0x22;arp->src_mac[2] = 0x33;arp->src_mac[3] = 0x44;arp->src_mac[4] = 0x55;arp->src_mac[5] = 0x66;arp->src_ip[0] = 192;arp->src_ip[1] = 168;arp->src_ip[2] = 1;arp->src_ip[3] = 2;arp->dest_mac[0] = 0xff;arp->dest_mac[1] = 0xff;arp->dest_mac[2] = 0xff;arp->dest_mac[3] = 0xff;arp->dest_mac[4] = 0xff;arp->dest_mac[5] = 0xff;arp->dest_ip[0] = 192;arp->dest_ip[1] = 168;arp->dest_ip[2] = 1;arp->dest_ip[3] = 1;len = sizeof(struct ethhdr) + sizeof(struct arphdr);return len;}void *memset(void *s, int c, int len){int i = 0;for(i=0; i<len; i++)((unsigned char *)s)[i] = c;}unsigned short htons(unsigned short data){unsigned short ret = 0;ret = ((data >> 8) & 0xff) | ((data << 8) & 0xff00);return ret;。
9.功能描述9.1主机接口主机接口是ISA总线兼容模式,有8个IO口基址,分别是300H、310H、320H、330H、340H、350H、360H、370H。
IO基址由设置引脚决定或者由EEPROM重载。
主机接口只有两个寻址口(addressing port),一个是索引口(index Port),另一个是数据口(data port)。
CMD=0时是索引口,CMD=1时是数据口。
索引口的内容是数据口的寄存器地址。
在读写任何寄存器之前,必须通过索引口保存这些寄存器的地址。
9.2直接数据存取控制DM9000提供了DMA功能、简化了内部存储器的存取。
在初始化了内部存储器的起始地址、发送了一个虚拟的读写指令将当前数据加载到内部数据缓冲区后,读写指令寄存器就可以读写内部指令寄存器的指定位置了。
存储器地址将按照当前运行模式(如8位模式、16位模式、32位模式)递增,而且下一个存储器地址的数据将自动被加载到数据缓冲区。
注意,第一次读取的一连串数据(即虚拟读写指令)必须忽略,因为这些数据是上一次读写指令的内容。
内部存储器空间是16K字节。
开始的3K字节用作包传输的数据缓冲区。
接下来的13K 字节用作接收包的缓冲区。
所以在写存储器操作时,当IMR的第七位置一时,如果存储器地址增量到达传输缓冲区的末尾(3K)时将强置为0。
类似的,在读存储器操作时,当IMR 的第七位置一时,如果存储器地址增量到达接收缓冲区的末尾(16K)时将强置为0x0C00。
9.3数据包传输有两个传输包,依次是INDEX I和INDEX II,可以被同时保存到发送SRAM中。
发送控制寄存器(02H)控制着冗余校验码和便签(pads)的插入。
传输包的状态被分别记录在发送状态寄存器I(03H)和发送状态寄存器II(04H)中。
传输的起始地址是00H,软件复位或者硬件复位后,当前包是INDEX I。
首先使用DMA 口写数据到TX SRAM,然后写字节数到的字节数寄存器,即发送包长度寄存器(0FCH/0FDH)。