linux 网络设备DM9000驱动分析

合集下载

DM9000网卡驱动分析

DM9000网卡驱动分析

DM9000网卡驱动分析#include <linux/module.h>#include <linux/ioport.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/init.h>#include <linux/skbuff.h>#include <linux/spinlock.h>#include <linux/crc32.h>#include <linux/mii.h>#include <linux/ethtool.h>#include <linux/dm9000.h>#include <linux/delay.h>#include <linux/platform_device.h>#include <linux/irq.h>#include <asm/delay.h>#include <asm/irq.h>#include <asm/io.h>#if defined(CONFIG_ARCH_S3C2410)#include <mach/regs-mem.h>#endif#include "dm9000.h"/* Board/System/Debug information/definition ---------------- *///在EEPROM或PHY地址寄存器中要选择内部PHY,那么7-6位强制为01#define DM9000_PHY 0x40 /* PHY address 0x01 */#define CARDNAME "dm9000"#define DRV_VERSION "1.31"/** Transmit timeout, default 5 seconds.*///传输超时时间设定,当传输超时时调用函数dm9000_timeout(struct net_device *dev) static int watchdog = 5000;module_param(watchdog, int, 0400);//在驱动程序加载时可以重新设定watchdog MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");/* DM9000 register address locking.** The DM9000 uses an address register to control where data written* to the data register goes. This means that the address register* must be preserved over interrupts or similar calls.** During interrupt and other critical calls, a spinlock is used to* protect the system, but the calls themselves save the address* in the address register in case they are interrupting another* access to the device.** For general accesses a lock is provided so that calls which are* allowed to sleep are serialised so that the address register does* not need to be saved. This lock also serves to serialise access* to the EEPROM and PHY access registers which are shared between* these two devices.*//* The driver supports the original DM9000E, and now the two newer* devices, DM9000A and DM9000B.*/enum dm9000_type {TYPE_DM9000E, /* original DM9000 */TYPE_DM9000A,TYPE_DM9000B};/* Structure/enum declaration ------------------------------- */typedef struct board_info {//cmd脚决定了数据数据口还是地址索引void __iomem *io_addr; /* Register I/O base address */void __iomem *io_data; /* Data I/O address */u16 irq; /* IRQ */u16 tx_pkt_cnt;//当前待传输的数据包的数量,最多两个//第二个数据包长度存于此处,第二个数据包写入网卡SRAM中后要释放skb u16 queue_pkt_len;u16 queue_start_addr;u16 dbug_cnt;u8 io_mode; /* 0:word, 2:byte */u8 phy_addr;u8 imr_all;//在probe()函数中有db->flags = pdata->flags;unsigned int flags;unsigned int in_suspend :1;int debug_level;enum dm9000_type type;void (*inblk)(void __iomem *port, void *data, int length);void (*outblk)(void __iomem *port, void *data, int length);void (*dumpblk)(void __iomem *port, int length);struct device *dev; /* parent device */struct resource *addr_res; /* resources found */struct resource *data_res;//物理地址struct resource *addr_req; /* resources requested */struct resource *data_req;//I/O映射后的虚拟地址struct resource *irq_res;struct mutex addr_lock; /* phy and eeprom access lock *///在probe函数中初始化,处理函数dm9000_poll_work,链路连接状态改变 struct delayed_work phy_poll;struct net_device *ndev;spinlock_t lock;struct mii_if_info mii;u32 msg_enable;//网络入口信息} board_info_t;/* debug code */#define dm9000_dbg(db, lev, msg...) do { \if ((lev) < CONFIG_DM9000_DEBUGLEVEL && \(lev) < db->debug_level) { \dev_dbg(db->dev, msg); \} \} while (0)static inline board_info_t *to_dm9000_board(struct net_device *dev){//存取私有数据指针专用函数return netdev_priv(dev);}/* DM9000 network board routine ---------------------------- */static voiddm9000_reset(board_info_t * db){dev_dbg(db->dev, "resetting device\n");//NCR(00H):网络控制寄存器/* RESET device */writeb(DM9000_NCR, db->io_addr);udelay(200);writeb(NCR_RST, db->io_data);udelay(200);}/** Read a byte from I/O port*/static u8ior(board_info_t * db, int reg){//对网卡寄存器进行操作要先写该寄存器的偏移地址writeb(reg, db->io_addr);return readb(db->io_data);}/** Write a byte to I/O port*/static voidiow(board_info_t * db, int reg, int value){writeb(reg, db->io_addr);writeb(value, db->io_data);}/* routines for sending block to chip */static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count) {writesb(reg, data, count);}static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count) {writesw(reg, data, (count+1) >> 1);}static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count) {writesl(reg, data, (count+3) >> 2);}/* input block from chip to memory */static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count) {readsb(reg, data, count);}static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count) {readsw(reg, data, (count+1) >> 1);}static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count) {readsl(reg, data, (count+3) >> 2);}/* dump block from chip to null *///读出没用的数据,为了改变网卡SRAM FIFO的数据指针,static void dm9000_dumpblk_8bit(void __iomem *reg, int count){int i;int tmp;for (i = 0; i < count; i++)tmp = readb(reg);}static void dm9000_dumpblk_16bit(void __iomem *reg, int count){int i;int tmp;count = (count + 1) >> 1;for (i = 0; i < count; i++)tmp = readw(reg);}static void dm9000_dumpblk_32bit(void __iomem *reg, int count){int i;int tmp;count = (count + 3) >> 2;for (i = 0; i < count; i++)tmp = readl(reg);}/* dm9000_set_io** select the specified set of io routines to use with the* device*///设定I/O线宽static void dm9000_set_io(struct board_info *db, int byte_width) {/* use the size of the data resource to work out what IO* routines we want to use*/switch (byte_width) {case 1:db->dumpblk = dm9000_dumpblk_8bit;db->outblk = dm9000_outblk_8bit;db->inblk = dm9000_inblk_8bit;break;case 3:dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n");case 2:db->dumpblk = dm9000_dumpblk_16bit;db->outblk = dm9000_outblk_16bit;db->inblk = dm9000_inblk_16bit;break;case 4:default:db->dumpblk = dm9000_dumpblk_32bit;db->outblk = dm9000_outblk_32bit;db->inblk = dm9000_inblk_32bit;break;}}/*延时调度。

DM9000驱动移植详解及问题点

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网卡驱动

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;。

成功移植U-BOOT之---- DM9000网卡驱动

成功移植U-BOOT之---- DM9000网卡驱动
保存退出
5、修改完成,开始编译
make TQ2440_config
make CROSS_COMPILE=arm-linux-
把编译后在顶层目录生成的 u-boot.bin 通过 SAMBA 拷出来,通过 JTAG 或 JLINK 烧到开发 板!
-------- -------------- -------
…… /*修改环境变量*/ #define CONFIG_ETHADDDR 00:01:02:03:04:05 #define CONFIG_NETMASK 255.255.255.0 #define CONFIG_IPADDR 192.168.0.61 #define CONFIG_SERVERIP 192.168.0.60
case 2: printf("10M case 4: printf("100M half duplex ");
break; case 8:
printf("100M full duplex "); break; default: printf("unknown: %d ", lnk); break; } p rintf("mo d e \n");
#endif
return 0; }
重新编译,再烧写,问题解除。
今天成功的在天嵌 TQ2440 的板子上完成了 U-BOOT -DM9000 网卡驱动的移植!
实验使用的是国嵌实验 4-2-4 修改过的源码(u-boot-basic.tar.gz) 废话不说,记笔记:
mkdir 4-2-4 cp u-boot-basic.tar.gz 4-2-4/ cd 4-2-4 tar zxvf u-boot-basic.tar.gz

dm9000

dm9000

1、先看芯片手册,弄懂dm9000基本工作原理和寄存器含义之后,再看代码2、看代码时用source insight,可以快速查看定义,代码的大致流程如下,其中标红的函数再仔细看看。

3、先把关于VxWorks驱动介绍的PPT做好,介绍大体框架,具体的程序不用着急着一步到位dm9000start()cpuForDM9000Init() →配置CPU,使用EINT7SYS_INT_CONNECT (pDrvCtrl, dm9000Int, (int)pDrvCtrl, &result); →注册中断处理函数dm9000IntintEnable (pDrvCtrl->ilevel); →使能该设备的中断/* Activate DM9000 */ →配置dm9000的0x05和0xff寄存器DM9000_OUT_CHAR( 0x05, DM9000_REG05 ); /* RX enable */DM9000_OUT_CHAR( 0xff, DM9000_REGFF );/* Enable TX/RX interrupt mask */dm9000Stop →→ dmfe_stop_dm9000( pDrvCtrl );→ cpuForDm9000disable();配置CPU,设置EINT7掩码→ SYS_INT_DISCONNECT (pDrvCtrl, dm9000Int, &result);注销中断函数dm9000Int→中断处理函数(详细分析。

)接收→netJobAdd ((FUNCPTR)dm9000HandleRcvInt, (int)pDrvCtrl, 0,0,0,0);→dm9000HandleRcvInt→dm9000Recv(详细分析。

vxworks网络数据结构MBlock)→dmfe_packet_receive发送→DM9000_OUT_CHAR( 0xfc, pDrvCtrl->queue_pkt_len & 0xff );→DM9000_OUT_CHAR( 0xfd, (pDrvCtrl->queue_pkt_len >> 8) & 0xff ); dm9000Send→intLock ()→dmfe_start_xmit( &skb, pDrvCtrl )→intUnLock ()dm9000PollStart →启动dm9000轮询模式dm9000PollRcv →轮询方式接收数据→ dmfe_packet_receive(详细分析。

移植调试dm9000网卡驱动(U-Boot)

移植调试dm9000网卡驱动(U-Boot)

这样就到了 DM9000A 的驱动部分代码。 DM9000A 的接收数据函数: eth_rx(void) { u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0]; u16 RxStatus, RxLen = 0; u32 tmplen, i;
// DM9000A 接收缓冲区中的数据格中格式是 4 字节的包头+真正的数据. // 其中 4 字节包头分别位为: rxbyte, status, count_low, count_hight // 说明如下: // rxbyte: 0-没有接收到数据, 1-有新的数据包 // status: 状态 // count_low, count_hight: 接收到的数据长度
/*******************************************************/ 包含两部分内容:配置说明和调试。
1 配置说明 Uboot 可以使用 RS232 和主机进行通讯,但其最大的波特率不过是 115200,1 秒最多只能 传送 11,520byte 的数据,如果说是传输 1.5M 的内核文件,计算下来将需要 133 秒,2 分钟的 时间,如果是传送 32M 的根文件系统文件,那么传输时间将是非常惊人的! 为了提高效率我们选用以太网传输,Uboot 本身也提供了网络的支持。 本系统中使用的网络芯片是 DM9000A,Uboot 的 driver 目录中包含了该芯片的驱动,文件 名为 dm9000x.c 和 dm9000x.h。要加入驱动的支持,必须在 config 文件中增加对 DM9000A
在这里#define CONFIG_DM9000_BASE 的定义最为重要。不同的板子只要修改这个参数即可。友善之臂的 SBC2440V4 上的 DM9000 在 BANK4 上所以定义为“0x20000300”。有 的板子是在 BANK1 上,就为“0x08000300”。

U-BOOT_DM9000驱动完全注释

U-BOOT_DM9000驱动完全注释

int eth_init(bd_t * bd);
//DM9000 网卡初始化
int eth_send(volatile void *, int);
//将来自上层的数据包发送到媒介上
int eth_rx(void);
//接收数据包并且发送到上层去
void eth_halt(void);
//关闭网卡
static int dm9000_probe(void);
{
u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000;
if (!(media_mode & DM9000_AUTO)) {
switch (media_mode) { case DM9000_10MHD:
//10M 半双工
phy_reg4 = 0x21;
//设置双工、半双工
return -1;
}
}
//*======================================================
==========
//函数名称:s e t_P HY_mod e
//函数功能:设置 PHY 芯片的操作模式 。若设置的是自动选择,则直接配置,若不是则可以选择
//
/* #define CONFIG_DM9000_DEBUG */ #define DM9000_DBG(fmt,args...) //*====================================================== ========== //DM9000 芯片的 PHY 层模式 //*====================================================== ========== enum DM9000_PHY_mode { DM9000_10MHD = 0, DM9000_100MHD =

DM9000调试血泪总结http...

DM9000调试血泪总结http...

DM9000调试血泪总结http...因为需要使用DM9000,因此就有了这条血泪之路。

话说那是一个月前,板子刚回来,感觉难度不大,因为此前搞过F4板子上的网络,对LWIP的移植和使用相对比较熟悉,所以花了3天的时间就把DM9000的驱动写好了,其实就是FSMC的配置,然后就是内部寄存器的读写,这个不难,驱动写完以后就是LWIP的移植,花了2个小时左右就移植成功了,成功以后开ping,ping成功,兴奋啊!但是在做webserver的时候发现网速很慢,而且很容易就会挂掉的!因此做了一次稳定性测试,就是连续的ping好几个小时,但是发现ping到0.5-2个小时的时候就会挂掉!!心碎啊,没办法,度娘,找各种DM9000在STM32上的程序,发现就那么几个,大多是就与RTT的DM9000例程修改的,就是在RTT例程的基础上修改一下IO口而已。

而RTT对LWIP做了修改,而且移植方法和常用的不同,因此就排除了RTT的例程。

但是将RTT的例程做了小修改,在我的板子上可以跑下去,这样可以确定板子硬件有没有问题!经过测试ping很稳定,时间基本小于1ms的。

这说明什么?说明我的代码有问题啊,初步怀疑是接收和发送函数有问题,接着又是各种度娘啊,还是没有什么用啊,当时那个心情啊!本以为很容易的一件事结果拖了好几个星期了!!心急啊,但是又有什么办法啊,面对庞大的UCOSII和LWIP协议栈,顿时慌了手脚啊,当时感觉那个无助啊,就像被抛弃到了一个荒岛一样!前两天再看其他参考例程的时候突然灵光一现,发现虽然其他代码都使用了DM9000的中断,但是却没有一个在DM9000的中断中接收数据,而是在中断中发送一个信号量(参考的代码都是带系统的),其他的任务接收该信号量,做任务同步,数据的接收在专门的接收任务中完成!!而我的数据接收是直接放在了DM9000的中断服务函数中,在进入中断的时候是要关闭中断的,这样有新的数据来时就会塞进MD9000的RX SRAM中,很容易导致overflow!接着就是死掉!昨天把数据的接收放到了一个任务中,中断里面也只是发送一个信号量,这样关中断时间就大大减小了,经过测试,ping好几个小时都没有挂掉,ping的时间基本也小于等于1ms。

DM9000 网口驱动器 调试说明

DM9000 网口驱动器 调试说明

10M/100M DM9000模块测试方法1.网络模块与红牛STM32连接安装DM9000模块与红牛板连接时,只要保证在红牛开发板液晶模块接口的排针位置,起与DM9000的VCC3.3V和GND相对应即可,关于DM9000模块的接口定义如下图:硬件连接如下图:2.电脑本地连接属性配置如果电脑只有一张网卡,那么直接用一根交叉的双绞线与电脑连接即可(注意网线必须是交叉的,即两端的水晶头收发的交叉的),然后在网上邻居中选择查看网络连接,出现的本地连接,右键选择属性下图:选择Internet协议(TCP/IP),双击进入配置本地连接的IP,如下图:如上图,本地连接的IP地址配置为192.168.2.10,点击子网掩码它自动生成,配置这个地址只要注意前面的192.168.2固定即可,后面数字取2-255都可以,因为STM32端得IP地址是192.168.2.30,两个IP地址要在同一个网段。

如果电脑是笔记本,那么有线网卡的配置和上面一样。

如果你是台式机,并有两张网卡,那么可以一张网卡上外网,一张网卡做实验连接STM32开发板,我的电脑就是两种网卡,关于双网卡的使用,配置稍微繁琐一点,如果有需要请联系我,我再教大家配置。

3.Putty的安装Putty的安装是为了STM32的RT Thread使用的,它通过串口与开发板连接,测试列程使用的是串口1,波特率115200。

打开Putty后,配置如下图:COM1是我电脑使用的串口号,这个需要根据大家各自的电脑串口号进行修改。

有关详细Putty和RT Thread finsh的入门使用方法,请见我发的帖子/bbs/bbs_content.jsp?bbs_sn=4593755&bbs_page_ no=1&search_mode=3&search_text=zidong404&bbs_id=9999。

如果硬件连接好以后,可以通过Putty看到刚开机时输出的DM9000ID 号,并提示Lwip 初始化成功,如果没有看到DM9000的ID号那么请仔细检查模块是否安装正确。

Linux内核移植步骤_添加DM9000网卡驱动(设备树)

Linux内核移植步骤_添加DM9000网卡驱动(设备树)

Linux内核移植步骤2015年05月13日星期三上午 11:05往设备树中添加网卡驱动:1、选平台,指定交叉编译工具链:(1)、在Makefile中指定:源码顶层目录下MakefileARCH ?= $(SUBARCH)CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)改为:ARCH ?= armCROSS_COMPILE ?=arm-linux-(2)、编译时指定:# make ARCH=arm CROSS_COMPILE=/opt/arm-linux-gcc-4.6.4/bin/arm-linux-2、导出缺省配置:(1)、直接把缺省配置文件改成”.config“:把“源码/arch/arm/configs”目录下的“xxxx_defconfig“(例如:”exynos_defconfig“)配置文件拷贝到源码顶层目录下,并改名为”.config“。

(2)、使用make生成缺省配置:# make exynos_defconfig#执行该命令后系统会在源码顶层目录下自动生成”.config“文件:# configuration written to .config3、往设备树文件中添加dm9000网卡驱动:(1)、参考与自己板子最接近的demo板的设备树文件生成自己的设备树文件(直接拷贝修改)。

设备树文件在”源码目录/arch/arm/boot/dts/exynos4412-fs4412.dts“(2)、在设备树文件中添加网卡设备驱动信息(参考网卡厂商提供的范例代码):示例代码在”Documentation/devicetree/bindings/net/davicom-dm9000.txt“,如下:Davicom DM9000 Fast Ethernet controllerRequired properties:- compatible = "davicom,dm9000";- reg : physical addresses and sizes of registers, must contain 2 entries:first entry : address register,second entry : data register.- interrupt-parent : interrupt controller to which the device is connected- interrupts : interrupt specifier specific to interrupt controllerOptional properties:- davicom,no-eeprom : Configuration EEPROM is not available- davicom,ext-phy : Use external PHYExample:ethernet@18000000 {compatible = "davicom,dm9000";reg = <0x18000000 0x2 0x18000004 0x2>;interrupt-parent = <&gpn>;interrupts = <7 4>;local-mac-address = [00 00 de ad be ef];davicom,no-eeprom;};修改并添加:ethernet@05000000 {compatible = "davicom,dm9000";reg = <0x05000000 0x2 0x05000004 0x2>;/*0x05000000为4412处理器的srom片选地址,详见手册*/interrupt-parent = <&gpx0>;/*继承父节点*/interrupts = <6 4>;/*gpx0节点中断中的第6个,4是标志*/local-mac-address = [00 00 de ad be ef];/*网卡地址*/davicom,no-eeprom;pinctrl@11000000 {...gpx0: gpx0 {gpio-controller;#gpio-cells = <2>;interrupt-controller;interrupt-parent = <&gic>;interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,/*中断<类型中断号中断标志>*/<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;#interrupt-cells = <2>;};...}4、修改设备树的Makefile文件:设备树的Makefile文件在”xxx/linux-3.19.1/arch/arm/boot/dts“目录下。

dm9000网卡驱动分析

dm9000网卡驱动分析

DM9000 驱动程序分析1. 模块注册static int __init dm9000_init(void){printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME,DRV_VERSION);return platform_driver_register(&dm9000_driver);}static struct platform_driver dm9000_driver = {.driver = {.name = "dm9000",.owner = THIS_MODULE,},.probe = dm9000_probe,.remove = __devexit_p(dm9000_drv_remove),.suspend = dm9000_drv_suspend,.resume = dm9000_drv_resume,};2. 驱动初始化static int __devinitdm9000_probe(struct platform_device *pdev){struct dm9000_plat_data *pdata = pdev->dev.platform_data;struct board_info *db; /* Point a board information structure */struct net_device *ndev;const unsigned char *mac_src;int ret = 0;int iosize;int i;u32 id_val;/* Init network device */ndev = alloc_etherdev(sizeof(struct board_info));if (!ndev) {dev_err(&pdev->dev, "could not allocate device.\n");return -ENOMEM;}SET_NETDEV_DEV(ndev, &pdev->dev);dev_dbg(&pdev->dev, "dm9000_probe()\n");/* setup board info structure */db = netdev_priv(ndev);memset(db, 0, sizeof(*db));db->dev = &pdev->dev;db->ndev = ndev;spin_lock_init(&db->lock);mutex_init(&db->addr_lock);INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);if (db->addr_res == NULL || db->data_res == NULL ||db->irq_res == NULL) {dev_err(db->dev, "insufficient resources\n");ret = -ENOENT;goto out;}iosize = res_size(db->addr_res);db->addr_req = request_mem_region(db->addr_res->start, iosize,pdev->name);if (db->addr_req == NULL) {dev_err(db->dev, "cannot claim address reg area\n");ret = -EIO;goto out;}db->io_addr = ioremap(db->addr_res->start, iosize);if (db->io_addr == NULL) {dev_err(db->dev, "failed to ioremap address reg\n");ret = -EINVAL;goto out;}iosize = res_size(db->data_res);db->data_req = request_mem_region(db->data_res->start, iosize,pdev->name);if (db->data_req == NULL) {dev_err(db->dev, "cannot claim data reg area\n");ret = -EIO;goto out;}db->io_data = ioremap(db->data_res->start, iosize);if (db->io_data == NULL) {dev_err(db->dev, "failed to ioremap data reg\n");ret = -EINVAL;goto out;}/* fill in parameters for net-dev structure */ndev->base_addr = (unsigned long)db->io_addr;ndev->irq = db->irq_res->start;/* ensure at least we have a default set of IO routines */dm9000_set_io(db, iosize);/* check to see if anything is being over-ridden */if (pdata != NULL) {/* check to see if the driver wants to over-ride the* default IO width */if (pdata->flags & DM9000_PLATF_8BITONLY)dm9000_set_io(db, 1);if (pdata->flags & DM9000_PLATF_16BITONLY)dm9000_set_io(db, 2);if (pdata->flags & DM9000_PLATF_32BITONLY)dm9000_set_io(db, 4);/* check to see if there are any IO routine* over-rides */if (pdata->inblk != NULL)db->inblk = pdata->inblk;if (pdata->outblk != NULL)db->outblk = pdata->outblk;if (pdata->dumpblk != NULL)db->dumpblk = pdata->dumpblk;db->flags = pdata->flags;}#ifdef CONFIG_DM9000_FORCE_SIMPLE_PHY_POLLdb->flags |= DM9000_PLATF_SIMPLE_PHY;#endifdm9000_reset(db);/* try multiple times, DM9000 sometimes gets the read wrong */for (i = 0; i < 8; i++) {id_val = ior(db, DM9000_VIDL);id_val |= (u32)ior(db, DM9000_VIDH) << 8;id_val |= (u32)ior(db, DM9000_PIDL) << 16;id_val |= (u32)ior(db, DM9000_PIDH) << 24;if (id_val == DM9000_ID)break;dev_err(db->dev, "read wrong id 0x%08x\n", id_val);}if (id_val != DM9000_ID) {dev_err(db->dev, "wrong id: 0x%08x\n", id_val);ret = -ENODEV;goto out;}/* Identify what type of DM9000 we are working on */id_val = ior(db, DM9000_CHIPR);dev_dbg(db->dev, "dm9000 revision 0x%02x\n", id_val);switch (id_val) {case CHIPR_DM9000A:db->type = TYPE_DM9000A;break;case CHIPR_DM9000B:db->type = TYPE_DM9000B;break;default:dev_dbg(db->dev, "ID %02x => defaulting to DM9000E\n", id_val);db->type = TYPE_DM9000E;}/* from this point we assume that we have found a DM9000 *//* driver system function */ether_setup(ndev);ndev->open = &dm9000_open;ndev->hard_start_xmit = &dm9000_start_xmit;ndev->tx_timeout = &dm9000_timeout;ndev->watchdog_timeo = msecs_to_jiffies(watchdog);ndev->stop = &dm9000_stop;ndev->set_multicast_list = &dm9000_hash_table;ndev->ethtool_ops = &dm9000_ethtool_ops;ndev->do_ioctl = &dm9000_ioctl;#ifdef CONFIG_NET_POLL_CONTROLLERndev->poll_controller = &dm9000_poll_controller;#endifdb->msg_enable = NETIF_MSG_LINK;db->mii.phy_id_mask = 0x1f;db->mii.reg_num_mask = 0x1f;db->mii.force_media = 0;db->mii.full_duplex = 0;db->mii.dev = ndev;db->mii.mdio_read = dm9000_phy_read;db->mii.mdio_write = dm9000_phy_write;mac_src = "eeprom";/* try reading the node address from the attached EEPROM */for (i = 0; i < 6; i += 2)dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) {mac_src = "platform data";memcpy(ndev->dev_addr, pdata->dev_addr, 6);}if (!is_valid_ether_addr(ndev->dev_addr)) {/* try reading from mac */mac_src = "chip";for (i = 0; i < 6; i++)ndev->dev_addr[i] = ior(db, i+DM9000_PAR);}if (!is_valid_ether_addr(ndev->dev_addr))dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please ""set using ifconfig\n", ndev->name);platform_set_drvdata(pdev, ndev);ret = register_netdev(ndev);if (ret == 0)printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",ndev->name, dm9000_type_to_char(db->type),db->io_addr, db->io_data, ndev->irq,ndev->dev_addr, mac_src);return 0;out:dev_err(db->dev, "not found (%d).\n", ret);dm9000_release_board(pdev, db);free_netdev(ndev);return ret;}3.打开网卡static int dm9000_open(struct net_device *dev){board_info_t *db = netdev_priv(dev);unsigned long irqflags = db->irq_res->flags &IRQF_TRIGGER_MASK;if (netif_msg_ifup(db))dev_dbg(db->dev, "enabling %s\n", dev->name);/* If there is no IRQ type specified, default to something that* may work, and tell the user that this is a problem */if (irqflags == IRQF_TRIGGER_NONE)dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");irqflags |= IRQF_SHARED;if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev))return -EAGAIN;/* Initialize DM9000 board */dm9000_reset(db);dm9000_init_dm9000(dev);/* Init driver variable */db->dbug_cnt = 0;mii_check_media(&db->mii, netif_msg_link(db), 1);netif_start_queue(dev);dm9000_schedule_poll(db);return 0;}4.数据发送static int dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) {unsigned long flags;board_info_t *db = netdev_priv(dev);dm9000_dbg(db, 3, "%s:\n", __func__);if (db->tx_pkt_cnt > 1)return 1;spin_lock_irqsave(&db->lock, flags);/* Move data to DM9000 TX RAM */writeb(DM9000_MWCMD, db->io_addr);(db->outblk)(db->io_data, skb->data, skb->len);dev->stats.tx_bytes += skb->len;db->tx_pkt_cnt++;/* TX control: First packet immediately send, second packet queue */ if (db->tx_pkt_cnt == 1) {/* Set TX length to DM9000 */iow(db, DM9000_TXPLL, skb->len);iow(db, DM9000_TXPLH, skb->len >> 8);/* Issue TX polling command */iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */dev->trans_start = jiffies; /* save the time stamp */ } else {/* Second packet */db->queue_pkt_len = skb->len;netif_stop_queue(dev);}spin_unlock_irqrestore(&db->lock, flags);/* free this SKB */dev_kfree_skb(skb);return 0;}5.数据接收static irqreturn_t dm9000_interrupt(int irq, void *dev_id){struct net_device *dev = dev_id;board_info_t *db = netdev_priv(dev);int int_status;unsigned long flags;u8 reg_save;dm9000_dbg(db, 3, "entering %s\n", __func__);/* A real interrupt coming *//* holders of db->lock must always block IRQs */spin_lock_irqsave(&db->lock, flags);/* Save previous register address */reg_save = readb(db->io_addr);/* Disable all interrupts */iow(db, DM9000_IMR, IMR_PAR);/* Got DM9000 interrupt status */int_status = ior(db, DM9000_ISR); /* Got ISR */iow(db, DM9000_ISR, int_status); /* Clear ISR status */if (netif_msg_intr(db))dev_dbg(db->dev, "interrupt status %02x\n", int_status);/* Received the coming packet */if (int_status & ISR_PRS)dm9000_rx(dev);/* Trnasmit Interrupt check */if (int_status & ISR_PTS)dm9000_tx_done(dev, db);if (db->type != TYPE_DM9000E) {if (int_status & ISR_LNKCHNG) {/* fire a link-change request */schedule_delayed_work(&db->phy_poll, 1);}}/* Re-enable interrupt mask */iow(db, DM9000_IMR, db->imr_all);/* Restore previous register address */writeb(reg_save, db->io_addr);spin_unlock_irqrestore(&db->lock, flags);return IRQ_HANDLED;}static voiddm9000_rx(struct net_device *dev){board_info_t *db = netdev_priv(dev);struct dm9000_rxhdr rxhdr;struct sk_buff *skb;u8 rxbyte, *rdptr;bool GoodPacket;int RxLen;/* Check packet ready or not */do {ior(db, DM9000_MRCMDX); /* Dummy read *//* Get most updated data */rxbyte = readb(db->io_data);/* Status check: this byte must be 0 or 1 */if (rxbyte > DM9000_PKT_RDY) {dev_warn(db->dev, "status check fail: %d\n", rxbyte);iow(db, DM9000_RCR, 0x00); /* Stop Device */iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */return;}if (rxbyte != DM9000_PKT_RDY)return;/* A packet ready now & Get status/length */GoodPacket = true;writeb(DM9000_MRCMD, db->io_addr);(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));RxLen = le16_to_cpu(rxhdr.RxLen);if (netif_msg_rx_status(db))dev_dbg(db->dev, "RX: status %02x,length %04x\n",rxhdr.RxStatus, RxLen);/* Packet Status check */if (RxLen < 0x40) {GoodPacket = false;if (netif_msg_rx_err(db))dev_dbg(db->dev, "RX: Bad Packet (runt)\n");}if (RxLen > DM9000_PKT_MAX) {dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);}/* rxhdr.RxStatus is identical to RSR register. */if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |RSR_PLE | RSR_RWTO |RSR_LCS | RSR_RF)) {GoodPacket = false;if (rxhdr.RxStatus & RSR_FOE) {if (netif_msg_rx_err(db))dev_dbg(db->dev, "fifo error\n");dev->stats.rx_fifo_errors++;}if (rxhdr.RxStatus & RSR_CE) {if (netif_msg_rx_err(db))dev_dbg(db->dev, "crc error\n");dev->stats.rx_crc_errors++;}if (rxhdr.RxStatus & RSR_RF) {if (netif_msg_rx_err(db))dev_dbg(db->dev, "length error\n");dev->stats.rx_length_errors++;}}/* Move data from DM9000 */if (GoodPacket&& ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {skb_reserve(skb, 2);rdptr = (u8 *) skb_put(skb, RxLen - 4);/* Read received packet from RX SRAM */(db->inblk)(db->io_data, rdptr, RxLen);dev->stats.rx_bytes += RxLen;/* Pass to upper layer */skb->protocol = eth_type_trans(skb, dev);netif_rx(skb);dev->stats.rx_packets++;} else {/* need to dump the packet's data */(db->dumpblk)(db->io_data, RxLen);}} while (rxbyte == DM9000_PKT_RDY);}。

DM9000网卡芯片详细调试过程

DM9000网卡芯片详细调试过程

DM9000网卡芯片详细调试过程1.硬件接入:将DM9000芯片与主控芯片相连接。

DM9000芯片需要与主控芯片通过SPI、I2C或8位数据总线相连接。

同时,还需要给DM9000芯片供电。

2.芯片驱动:需要编写相关的DM9000驱动程序,确保主控芯片可以与DM9000芯片进行通信。

驱动程序一般会提供一些API函数,可以通过调用这些函数来操作DM9000芯片。

3.软件配置:使用DM9000驱动程序进行软件配置,以设置一些基本参数,例如MAC地址、IP地址、子网掩码等。

这些参数在网络通信中是必须的。

4.连接网络:确保主控芯片与DM9000芯片所在的嵌入式系统已经连接到网络中,可以通过路由器进行连接。

5.测试通信:编写通信测试程序,利用DM9000芯片进行网络通信测试。

可以测试网卡是否可以正常接收和发送数据包。

通过打印调试信息,可以了解网络通信的过程和结果。

以上是DM9000网卡芯片的详细调试过程的基本步骤。

下面将更加详细地介绍每个步骤:1.硬件接入:根据DM9000芯片的硬件接口,将其与主控芯片连接。

DM9000芯片可以通过SPI、I2C或8位数据总线进行连接,具体的连接方式需根据系统需求进行选择。

同时,还需要正确连接DM9000芯片的供电引脚,确保芯片正常工作。

2.芯片驱动:编写DM9000驱动程序,确保主控芯片可以与DM9000芯片进行通信。

驱动程序一般需要提供一些API函数,例如初始化函数、发送数据函数和接收数据函数等。

这些API函数会通过SPI、I2C或8位数据总线来操作DM9000芯片,以完成相应的功能。

3.软件配置:在驱动程序中提供相应的函数,用于配置DM9000芯片的相关参数。

例如,设置MAC地址、IP地址和子网掩码等。

这些参数在网络通信中是必须的,可以通过调用驱动程序提供的函数进行配置。

4.连接网络:确保主控芯片与DM9000芯片所在的嵌入式系统已经连接到网络中,可以通过路由器进行连接。

【驱动】DM9000A网卡驱动框架源码分析

【驱动】DM9000A网卡驱动框架源码分析

【驱动】DM9000A⽹卡驱动框架源码分析Linux⽹络设备结构 ⾸先看⼀下Linux⽹络设备的结构,如下图:1. ⽹络协议接⼝层向⽹络层协议提供提供统⼀的数据包收发接⼝,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过netif_rx()函数接受数据。

这⼀层的存在使得上层协议独⽴于具体的设备。

2. ⽹络设备接⼝层向协议接⼝层提供统⼀的⽤于描述具体⽹络设备属性和操作的结构体net_device,该结构体是设备驱动功能层中各函数的容器。

实际上,⽹络设备接⼝层从宏观上规划了具体操作硬件的设备驱动功能层的结构。

3. 设备驱动功能层各函数是⽹络设备接⼝层net_device数据结构的具体成员,是驱使⽹络设备硬件完成相应动作的程序,他通过hard_start_xmit()函数启动发送操作,并通过⽹络设备上的中断触发接受操作。

4. ⽹络设备与媒介层是完成数据包发送和接受的物理实体,包括⽹络适配器和具体的传输媒介,⽹络适配器被驱动功能层中的函数物理上驱动。

对于Linux系统⽽⾔,⽹络设备和媒介都可以是虚拟的。

上⾯的结构还可以细分,如下图⽹络协议接⼝层 这⾥主要进⾏数据包的收发,使⽤函数原型为:dev_queue_xmit(struct sk_buff *skb);int netif_rx(struct sk_buff *skb); 这⾥使⽤了⼀个skb_buff结构体,定义于include/linux/skbuff.h中,它的含义为“套接字缓冲区”,⽤于在Linux⽹络⼦系统各层间传输数据。

它是⼀个双向链表,在⽼的内核中会有⼀个list域指向sk_buff_head也就是链表头,但是在linux2.6.30.4内核后已经不存在了,如下图:操作套接字缓冲区的函数1.分配struct sk_buff *alloc_skb(unsigned int len, int priority);struct sk_buff *dev_alloc_skb(unsigned int len); 分配⼀个缓冲区。

经典DM9000驱动详解

经典DM9000驱动详解

DM9000 驱动移植及源码简析(1)/whs08/blog/item/384fee175781f1094a90a7a5.html转自/User/lvembededsys/Article/6856_1.htm在成功移植Dm9000驱动到我的EIEVK-100(SMDK2440)开发板的前提下,本文从以下几个方面说明相关原理及过程:1.硬件情况2.Dm9000驱动移植详细过程3.Platform_device与platform_driver4.Dm9000驱动代码简要分析一. 硬件情况DM9000在电路板上的连接中与编程相关的如下:1)EECS拉高:16bit模式;2)EECK拉高,INT连接到2440 EINT7:INT脚为低时为有效中断信号,中断线为EINT73)cs连接到2440的nGCS2,CMD连接2440地址总线ADDR[2]:INDEX和DATA端口地址分别为0x1000_0000和0x1000_0004。

知道上面这些信息已经足够移植驱动了。

二. Dm9000驱动移植详细过程1.在内核编译配置选项中,driver-->net-->10/100M net-->DM9000 support 选项选中。

2.在arch/arm/mach-s3c2410/devs.c 中添加dm9000的platform_device。

/* Add Dm9000 platform_device beelike@ */#includestatic struct resource eievk_dm9000_resource[] = {[0]= {.start = 0x10000000, //this is based on EIEVK board.end = 0x10000003,.flags = IORESOURCE_MEM,},[1]={.start = 0x10000004,.end = 0x10000007,.flags = IORESOURCE_MEM,},[2]={.start = IRQ_EINT7,.end = IRQ_EINT7,.flags = IORESOURCE_IRQ,}};static struct dm9000_plat_data eievk_dm9000_platdata ={.flags = DM9000_PLATF_16BITONLY,//work in 16bit mode};struct platform_device eievk_dm9000_device = {.name = "dm9000",.id = -1,.num_resources = 3,.resource = eievk_dm9000_resource,.dev = {.platform_data = &eievk_dm9000_platdata,}};EXPORT_SYMBOL(eievk_dm9000_device);/*end add beelike@ */3.在arch/arm/mach-s3c2410/devs.h中声明平台设备eievk_dm9000_device :extern struct platform_device eievk_dm9000_device;4.在arm/arm/mach-s3c2410/mach-smdk2410.c中将eievk_dm9000_device添加到平台设备列表中:static struct platform_device *smdk2440_devices[] __initdata = {&s3c_device_usb,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c,&s3c_device_iis,&eievk_dm9000_device, //add dm9000 by beelike&s3c_device_nand,};5.OK,经过上述努力,Dm9000设备已经成功注册进入驱动核心。

基于嵌入式Linux的DM9000网络驱动设计

基于嵌入式Linux的DM9000网络驱动设计

基于嵌入式Linux的DM9000网络驱动设计高嵩;纪超;陈超波【期刊名称】《计算机与数字工程》【年(卷),期】2013(041)002【摘要】The device driver is an important part of Linux system, but also the link between hardware and application software, and network equipment is one of the important ways of communication between devices, so the design of network driver has important significance. Based on analysing of the Linux network driver architecture, using Linux2. 6. 32. 2 kernel on S3C2440 development board transplant write DM9000 card driver instance, the implementation principle of the embedded network driver programe is discussed and the framework structure of the program code is analysed in detail. Design of interface circuit and program finally achieve the purpose of driving, makes the DM9000 card to work properly, and can be applied to a variety of embedded equipment.%设备驱动是Linux 系统的重要组成部分,也是硬件和应用软件之间的纽带,而网络设备更是设备间通信的重要方式之一,所以设计网络驱动有着重要的意义.论文在分析Linux网络驱动程序体系结构的基础上,利用Linux2.6.32.2内核在S3C2440开发板上移植编写DM9000网卡驱动程序的实例,重点讨论了嵌入式网络驱动程序的实现原理,并详细分析了程序代码的框架结构.设计的网卡接口电路与程序最终实现了驱动的目的,使得DM9000网卡能够正常工作,并且可以应用到多种嵌入式设备当中.【总页数】3页(P304-306)【作者】高嵩;纪超;陈超波【作者单位】西安工业大学电子信息工程学院西安710032;西安工业大学电子信息工程学院西安710032;西安工业大学电子信息工程学院西安710032【正文语种】中文【中图分类】TP391.4【相关文献】1.嵌入式linux下DM9000网卡驱动的移植与实现 [J], 贺金平2.嵌入式Linux下基于SPI总线的网络设备驱动设计与实现 [J], 张晓雷;陈相宁;郭剑3.基于嵌入式Linux的DM9000的网络驱动 [J], 赵楠楠;刘敬伟;朱克研4.基于嵌入式Linux的platform驱动设计与应用 [J], 王晓君;王星;李玉莹5.基于嵌入式Linux的网络设备驱动设计与实现 [J], 管秋梅;胡仁杰因版权原因,仅展示原文概要,查看原文内容请购买。

基于嵌入式Linux的DM9000的网络驱动

基于嵌入式Linux的DM9000的网络驱动

基于嵌入式Linux的DM9000的网络驱动
赵楠楠;刘敬伟;朱克研
【期刊名称】《辽宁科技大学学报》
【年(卷),期】2014(037)003
【摘要】嵌入式网络技术正在快速发展,基于嵌入式的网络开发和应用成为当前研究热点.以嵌入式Linux为载体的DM9000网卡是通信领域应用较为广泛的硬件设备,因此开发DM9000网卡的驱动程序具有现实意义.本文基于嵌入式ARM和网络芯片DM9000对网络驱动程序进行研究,分析Linux网络驱动的实现原理,实现了基于嵌入式Linux的DM9000的网卡驱动程序开发,通过对应用程序服务器和客户端的设计,进一步分析网络驱动的工作原理,为更好地利用和改进网络驱动提供理论依据.
【总页数】4页(P265-268)
【作者】赵楠楠;刘敬伟;朱克研
【作者单位】辽宁科技大学电子与信息工程学院,辽宁鞍山 114051;辽宁科技大学电子与信息工程学院,辽宁鞍山 114051;中国三冶集团有限公司企业策划部,辽宁鞍山 110039
【正文语种】中文
【中图分类】TP316
【相关文献】
1.基于ARM和Linux的DM9000网络接口设计及驱动实现 [J], 袁安富;夏生凤
2.嵌入式Linux下基于SPI总线的网络设备驱动设计与实现 [J], 张晓雷;陈相宁;郭剑
3.基于嵌入式Linux的DM9000网络驱动设计 [J], 高嵩;纪超;陈超波
4.基于VxWorks
5.4的DM9000网络驱动移植 [J], 顾伟
5.基于嵌入式Linux的网络设备驱动设计与实现 [J], 管秋梅;胡仁杰
因版权原因,仅展示原文概要,查看原文内容请购买。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

说明1:本文分析基于内核源码版本为linux-2.6.31说明2:本文在理解了linux中总线、设备和驱动模型的基础上加以分析代码虽然Linux驱动程序应该是和具体的硬件平台分离的,但是为了更好的理解DM9000的驱动程序,这里还是结合一下Mini2440开发板,这样也可以更好的体会如何实现驱动和平台分离。

本文分成以下几个部分:一、Mini2440开发板上DM9000的电气连接和Mach-mini2440.c文件的关系。

二、两个重要的结构体介绍:sk_buff和net_device三、具体代码分析一、Mini2440开发板上DM9000的电气连接和Mach-mini2440.c文件的关系Mini2440开发板上DM9000与S3C2440的连接关系如下:其中片选信号AEN使用了nGCS4,所以网卡的内存区域在BANK4,也就是从地址0x20000000开始。

DM9000的TXD[2:0]作为 strap pin在电路图中是空接的,所以IO base是300H。

中断使用了EINT7。

这些内容在Mach文件中有如下体现:点击(此处)折叠或打开1.01.#define S3C2410_CS4 (0x20000000)2.02.#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)3.03.static struct resource mini2440_dm9k_resource[] __initdata ={4.04.[0]={5.05..start = MACH_MINI2440_DM9K_BASE,6.06..end= MACH_MINI2440_DM9K_BASE + 3,7.07..flags = IORESOURCE_MEM8.08.},9.09.[1]={10.10..start = MACH_MINI2440_DM9K_BASE + 4,11.11..end= MACH_MINI2440_DM9K_BASE + 7,12.12..flags = IORESOURCE_MEM13.13.},14.14.[2]={15.15..start = IRQ_EINT7,16.16..end= IRQ_EINT7,17.17..flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,18.18.}19.19.};另外在Mach文件中还定义了DM9000平台设备,设备名称为“dm9000”,设备资源就是上面定义的IO和中断资源。

代码清单如下:点击(此处)折叠或打开1.01.static struct dm9000_plat_data mini2440_dm9k_pdata __initdata ={2.02..flags =(DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),3.03.};4.04.5.05.static struct platform_device mini2440_device_eth __initdata ={ ="dm9000",7.07..id =-1,8.08..num_resources = ARRAY_SIZE(mini2440_dm9k_resource),9.09..resource = mini2440_dm9k_resource,10.10..dev ={11.11..platform_data =&mini2440_dm9k_pdata,12.12.},13.13.};这个DM9000平台设备作为众多平台设备中的一个在扳子初始化的时候就被添加到了总线上。

代码清单如下:点击(此处)折叠或打开1.01.MACHINE_START(MINI2440,"MINI2440")2.02./* Maintainer: Michel Pollet <buserror@>*/3.03..phys_io = S3C2410_PA_UART,4.04..io_pg_offst =(((u32)S3C24XX_VA_UART)>> 18)& 0xfffc,5.05..boot_params = S3C2410_SDRAM_PA + 0x100,6.06..map_io = mini2440_map_io,7.07..init_machine = mini2440_init,/*初始化函数*/8.08..init_irq = s3c24xx_init_irq,9.09..timer =&s3c24xx_timer,10.10.MACHINE_END点击(此处)折叠或打开1.01.static void __init mini2440_init(void)2.02.{3.03....4.04....5.05. platform_add_devices(mini2440_devices,ARRAY_SIZE(mini2440_devices));6.06.7.07....8.08....9.09.}点击(此处)折叠或打开1.01.static struct platform_device *mini2440_devices[] __initdata ={2.02.&s3c_device_usb,3.03.&s3c_device_wdt,4.04./*&s3c_device_adc,*//* ADC doesn't like living with touchscreen !*/5.05.&s3c_device_i2c0,6.06.&s3c_device_rtc,7.07.&s3c_device_usbgadget,8.08.&mini2440_device_eth,/*dm9000是众多平台设备中的一个*/9.09.&mini2440_led1,10.10.&mini2440_led2,11.11.&mini2440_led3,12.12.&mini2440_led4,13.13.&mini2440_button_device,14.14.&s3c_device_nand,15.15.&s3c_device_sdi,16.16.&s3c_device_iis,17.17.&mini2440_audio,18.18./*&s3c_device_timer[0],*//* buzzer pwm, no API for it */19.19./* remaining devices are optional */20.20.};二、两个重要的结构体简单介绍:sk_buff和net_device*sk_buff如果把网络传输看成是运送货物的话,那么sk_buff就是这个“货物”了,所有经手这个货物的人都要干点什么事儿,要么加个包装,要么印个戳儿等等。

收货的时候就要拆掉这些包装,得到我们需要的货物(payload data)。

没有货物你还运输什么呢?由此可见sk_buff的重要性了。

关于sk_buff的详细介绍和几个操作它的函数,参考:“linux内核 sk_buff的结构分析”/Linux/2011-07/39163.htm,写得非常明白了。

赞一个~*net_device又是一个庞大的结构体。

好吧,我承认我从来就没有看全过这个结构体。

它在内核中就是指代了一个网络设备。

驱动程序需要在探测的时候分配并初始化这个结构体,然后使用register_netdev来注册它,这样就可以把操作硬件的函数与内核挂接在一起。

三、具体代码的分析在顺序分析之前先看三个结构体变量和一个自定义的结构体。

* dm9000_driver变量。

是platform_driver结构体变量,其中包含了重要的:驱动的名字(用来match)和几个重要操作函数。

点击(此处)折叠或打开1.01.static struct platform_driver dm9000_driver ={2.02..driver ={ ="dm9000",4.04..owner = THIS_MODULE,5.05.},6.06..probe = dm9000_probe,7.07..remove = __devexit_p(dm9000_drv_remove),8.08..suspend = dm9000_drv_suspend,9.09..resume= dm9000_drv_resume,10.10.};* dm9000_netdev_ops变量。

是net_device_ops结构体变量,其中定义了操作net_device的重要函数,我们在驱动程序中根据需要的操作要填充这些函数。

代码清单如下:点击(此处)折叠或打开1.01.static const struct net_device_ops dm9000_netdev_ops ={2.02..ndo_open = dm9000_open,3.03..ndo_stop = dm9000_stop,4.04..ndo_start_xmit = dm9000_start_xmit,5.05..ndo_tx_timeout = dm9000_timeout,6.06..ndo_set_multicast_list = dm9000_hash_table,7.07..ndo_do_ioctl = dm9000_ioctl,8.08..ndo_change_mtu = eth_change_mtu,9.09..ndo_validate_addr = eth_validate_addr,10.10..ndo_set_mac_address = eth_mac_addr,11.11.#ifdef CONFIG_NET_POLL_CONTROLLER12.12..ndo_poll_controller = dm9000_poll_controller,13.13.#endif14.14.};* dm9000_ethtool_ops变量。

是ethtool_ops结构体变量,为了支持ethtool,其中的函数主要是用于查询和设置网卡参数(当然也有的驱动程序可能不支持ethtool)。

代码清单如下:点击(此处)折叠或打开1.01.static const struct ethtool_ops dm9000_ethtool_ops ={2.02..get_drvinfo = dm9000_get_drvinfo,3.03..get_settings = dm9000_get_settings,4.04..set_settings = dm9000_set_settings,5.05..get_msglevel = dm9000_get_msglevel,6.06..set_msglevel = dm9000_set_msglevel,7.07..nway_reset = dm9000_nway_reset,8.08..get_link = dm9000_get_link,9.09..get_eeprom_len = dm9000_get_eeprom_len,10.10..get_eeprom = dm9000_get_eeprom,11.11..set_eeprom = dm9000_set_eeprom,12.12.};* board_info结构体。

相关文档
最新文档