搜索
bottom↓
回复: 71

dm9000ae 100m以太网模块调试step by step

[复制链接]

出0入0汤圆

发表于 2007-5-21 17:25:11 | 显示全部楼层 |阅读模式
电路板已经焊接完成!!!

现在开始修改初始化函数,并读取芯片的id!!!





现在可以调试出来芯片的id号了!!



其中vid 厂商号 0x0a46

pid 芯片号 9000代表dm9000系列!!!



明天开始将图片开始上传!!!

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2007-5-21 18:58:02 | 显示全部楼层
期待中,我做了一个DM9008AE的板子,什么都不好使。

出0入0汤圆

 楼主| 发表于 2007-5-24 11:45:05 | 显示全部楼层
pcb第一版本正面





pcb第一版本反面







测试的mega32板



测试中的模块

出0入0汤圆

 楼主| 发表于 2007-5-24 11:48:35 | 显示全部楼层
测试情况汇报

现在可以

1.dm9000初始化

2.可以开始以中断方式进行网络数据包的读操作

3.写操作马上就要开始!!!



下面是网络抓包软件和包通过串口的对比















出0入0汤圆

 楼主| 发表于 2007-5-24 11:50:52 | 显示全部楼层
测试的main.c(部分)



//'****************************************************************************

void main(void)

{

unsigned int h=0;

unsigned int h1=0;

unsigned char i=0;

unsigned char B1=0;

u16_t vid,pid;

u8_t  vid0,vid1;

u8_t  pid0,pid1;

CLI();

Mcu_init();

uint0=0;

// WY_Showregs();

GICR=0X40;//Enable Int0

MCUCR=0X03;//int0 rising edge

//SREG|=0X80; //20050910

h=0X55;



//第一个历程首先初始化dm9000ae芯片,然后读写其芯片id

//1.初始化dm9000ae

/*printf("Now reset dm9000ae!
");

ResetPort_H;

ResetPort_L;

Delayxms(1000);

ResetPort_H;

*/

printf("Now begin init dm9000ae!
");

          

if(InitDM9000()==0)printf("dm9000ae init ok!
");

else printf("dm9000ae init error!
");



//2.读芯片id



vid0=read_nicreg(DM9000_VID);

vid1=read_nicreg(DM9000_VID+1);

vid=vid1;

vid=vid<<8;

vid+=vid0;



//if(vid != DM9000_VendID)

printf("vid=%x
",vid);



pid0=read_nicreg(DM9000_PID);

pid1=read_nicreg(DM9000_PID+1);

pid=pid1;

pid=pid<<8;

pid+=pid0;



//if(pid != DM9000_ProdID)

printf("pid=%x
",pid);



pid0=read_nicreg(DM9000_CHIPR);

printf("chipr=%x
",pid0);



pid0=read_nicdata();

printf("read_nicdata=%x
",pid0);



//发现没有连接

//打印出9:02:49> reg[0]= 0 reg[1]= 80 reg[2]= 0 reg[3]= 0 reg[4]= 0 reg[5]= 31 reg[6]= 0 reg[7]= 0

//reg[1]= 80 这个不对,没有LINKOK???

//检查原因

set_nicreg(DM9000_MRCMDX1);



//3.读写寄存器

for(i=0;i<=0x7;i++)printf("reg[%x]= %x ",i,read_nicreg(i));

printf("
");

for(i=8;i<=0x0f;i++)printf("reg[%x]= %x ",i,read_nicreg(i));

printf("
");

/*

for(i=10;i<=0x17;i++)printf("reg[%x]= %x ",i,read_nicreg(i));

printf("
");

for(i=18;i<=0x1f;i++)printf("reg[%x]= %x ",i,read_nicreg(i));

printf("
");



for(i=0x22;i<=0x29;i++)printf("reg[%x]= %x ",i,read_nicreg(i));

printf("
");

for(i=0x2a;i<=0x32;i++)printf("reg[%x]= %x ",i,read_nicreg(i));

printf("
");



for(i=0xf0;i<=0xfe;i++)printf("reg[%x]= %x ",i,read_nicreg(i));



printf("reg[0xff]= %x ",read_nicreg(0xff));

printf("
");

*/

uip_len=0;

//4.读网络接收包

pack_in=0;

SREG|=0X80; //20050910

while(1)

  {

  Delayxms(1);

    // Loops here until either a packet has been received or

    // TX_EventPending (half a sec) to scan for anything to send or

    // ARP_EventPending (10 secs) to send an ARP packet

       

        if(pack_in)

        {

        SREG&=0X7f; //20050910

        printf("now test uip !");

        pack_in=0;       

        write_nicreg(DM9000_ISR,read_nicreg(DM9000_ISR));

    uip_len = DM9000_receive();

        if(uip_len!=0)

        {

        printf("uip_len=%x
",uip_len);

        /*

        printf("source mac =
");

        for(i=0;i<6;i++)printf(" %x ",uip_buf);

        printf("
");

        */

        printf("source mac =%x,%x,%x,%x,%x,%x
",

        uip_buf[0],uip_buf[1],uip_buf[2],uip_buf[3],uip_buf[4],uip_buf[5]);

        //uip_buf[1]出问题=0 应该是0xff

       

        //for(i=0;i<6;i++)

        printf("destin mac =%x,%x,%x,%x,%x,%x
",

        uip_buf[6],uip_buf[7],uip_buf[8],uip_buf[9],uip_buf[0x0a],uip_buf[0x0b]);

       

        for(i=0x0c;i<uip_len;i++)printf("uip_buf[%x]= %x ",i,uip_buf);

        printf("
");

       

        }

        else printf("uip_len=0
");

        }

    SREG|=0X80; //20050910

        //printf("uip_buf=%x,%x,%x,%x,%x,%x
",uip_buf[0],uip_buf[1],uip_buf[2],uip_buf[3],uip_buf[4],uip_buf[5]);

}





/*

while(1)

{



  }

*/                       

                       



       

          

}



//'*******************************************************************************



#pragma interrupt_handler dm9000ae_interrupt:2

//'( Routine to handle an interrupt on the RTL8019AS

//'

void dm9000ae_interrupt(void)

{

//最后,不要忘记在重新使能中断之前通过对GIFR 寄存器的相应中断标志位INTF2 写'1’

//使其清零。

     

        //        GIFR|=0X40;       

                //wait for a good packet

printf("int0!
");               

printf("nsr-int=%x
",read_nicreg(DM9000_ISR));

if(read_nicreg(DM9000_ISR)&0x01)pack_in=1;

else write_nicreg(DM9000_ISR,0xff);



}

出0入0汤圆

 楼主| 发表于 2007-5-28 10:52:40 | 显示全部楼层
现在修改原厂的驱动程序,实现了一个中断多个数据报的接收





现在可以接收广播包和普通包!!



问题提出:



现在只能接收arp数据包和udp包,icmp tcp 包还没有接收到,原因待查!!!

出0入0汤圆

 楼主| 发表于 2007-5-31 15:24:36 | 显示全部楼层
做了个arp_reply

已经成功











出0入0汤圆

 楼主| 发表于 2007-5-31 15:33:36 | 显示全部楼层
程序中的ip和mac设置







出0入0汤圆

 楼主| 发表于 2007-6-1 08:44:25 | 显示全部楼层
pc 上的显示

出0入0汤圆

 楼主| 发表于 2007-6-1 15:37:56 | 显示全部楼层
修改程序现在可以接收到arp/icmp/udp数据报了



出0入0汤圆

发表于 2007-6-27 20:04:34 | 显示全部楼层
咋很久都没有消息了呢?

我的dm9008已经可以ping了

出0入0汤圆

发表于 2007-7-8 16:46:15 | 显示全部楼层
93C46可以不用吗?

出0入0汤圆

 楼主| 发表于 2007-7-20 10:20:19 | 显示全部楼层
93C46可以不用吗? --y

出0入0汤圆

发表于 2007-7-21 15:41:14 | 显示全部楼层
可以不用,但是有两个引脚挺有用

出0入0汤圆

发表于 2008-2-16 13:57:49 | 显示全部楼层
我也打算使用DM9008AE芯片,不知道是否有现成的uip下的驱动。

出0入0汤圆

发表于 2008-2-16 14:10:21 | 显示全部楼层
这个芯片  430单片机 有 源码。IAR的

这个芯片 没 8019 便宜。

我有块 dm9000 + mega128 的板,是2003年一个兼职的博士弄的, 还有个8019+mega128的,没兴趣弄了!

出0入0汤圆

 楼主| 发表于 2008-3-5 09:26:52 | 显示全部楼层
Linux下DM9000网卡驱动实验〈一〉
1.1        硬件系统介绍
1.1.1          网络驱动程序的特点    网络驱动程序是介于硬件和内核之间传送数据包,不是面向流的设备,不能象/dev/tty1那样简单的映射到文件系统的节点上。Linux调用这些接口的方式是给他们分配一个独立的名字(如eth0)。这样的名字在文件系统中并没有对应项。内核和网络设备驱动程序之间的通信与字符设备驱动程序和快设备驱动程序与内核间的通信是完全不同的。内核不再调用read/write,它调用与数据包传送相关的函数。

1.1.2          DM9000以太网芯片介绍网络控制器选用DAVICOM公司的DM9000快速以太网控制处理器,合成了MAC, PHY, MMU。该处理器配备有标准10M/100M自适应,16K大容量的FIFO,4路多功能GPIO,掉电,全双工工作等功能。物理层支持以太网接口协议。由于数据有时是以猝发形式收到的,因此,DM9000还集成有接收缓冲区,以便在接收到数据时能把数据放到这个缓冲区中,然后由数据链路层直接从该缓冲区里取走数据。链路层通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡,它们一起处理与电缆的物理接口细节数据,它的缓冲区可用来暂时存储要发送或接收的帧。

网络控制器包括MAC和PHY两个部分,其中MAC层控制器作为逻辑控制。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

1.1.3          2410与DM9000的硬件连接DM9000的模块示意图




接口电路图:


1.2        网卡驱动实验步骤
1.2.1          步骤一:编写简单的网络设备驱动程序  以下是一个网络驱动程序完整源码,这仅仅只是一个可编译,加载和卸载的驱动程序,不能完成任何实际的工作。不过,可把它当作模板,网络设备的驱动程序就从这个模板上添加而成。并且,针对每一个驱动程序的接口,都做了介绍和编程指导。


程序清单 1&#8209;0&#8209;1 简单的网络程序模板 test_net.c

/*********************************************************************************


*


*     net_test.c                a simple net device driver sample


*


*


*********************************************************************************


*/





#ifndef __KERNEL__


     #define  __KERNEL__


#endif




#ifndef MODULE


     #define MODULE


#endif




#define __NO_VERSION__




#include


#include


#include


#include




#include


#include


#include


#include


#include






static int test_init(struct net_device *dev);


static int test_open(struct net_device *dev);


static int test_release(struct net_device *dev);


static int test_config(struct net_device *dev, struct ifmap *map);


static int test_tx(struct sk_buff *skb, struct net_device *dev);




int  test_init_module(void);


void test_cleanup(void);






#define DEVICE_NAME "test" //内核模块名称




module_init(test_init_module);


module_exit(test_cleanup);




//定义结构体变量并初始化必须的成员


static struct net_device  net_test =


{


     init:test_init,


};




static int test_init(struct net_device *dev)


{


     ether_setup(dev);//初始化结构体变量中与硬件无关的成员


     strcpy(dev->name,"eth0");


     


     dev->open              =test_open;


     dev->stop              =test_release;


     dev->set_config                  =test_config;


     dev->hard_start_xmit             =test_tx;


     dev->flags                  &=~(IFF_BROADCAST|IFF_LOOPBACK|IFF_MULTICAST);


//设置驱动中感兴趣的成员...


     SET_MODULE_OWNER(dev);//设置owner成员




     return 0;


}


//当网络设备驱动程序不能自动识别硬件配置时,系统管理员会使用配制工具将正确的硬件配置传递给


//驱动程序。实际上就是调用驱动程序的set_config()方法。


static int test_config(struct net_device *dev, struct ifmap *map)


{


     return 0;


}




static int test_tx(struct sk_buff *skb, struct net_device *dev)


{


     return 0;


}




static int test_open(struct net_device *dev)


{


     MOD_INC_USE_COUNT;




    netif_start_queue(dev);//第一次调用open()方法必须调用




     return 0;


}




static int test_release(struct net_device *dev)


{


netif_stop_queue(dev);//最后一次调用stop()方法必须调用




MOD_DEC_USE_COUNT;




return 0;


}




int  test_init_module(void)


{


     int result = 0;


     //初始化模块自身(包括请求一些资源)


     result = register_netdev(&net_test);//注册网络设备驱动程序


     if(result < 0)


     {


         printk(KERN_ERR DEVICE_NAME":error % i registering device \"%s\"\n", result , net_test.name);


         return result;


     }




     printk(KERN_ERR DEVICE_NAME ":init OK\n");




     return 0;


}




void test_cleanup(void)


{


     unregister_netdev(&net_test); //卸载驱动程序


}




//////////////////////////////////////////////////////////////



1.2.2          步骤二:在Linux平台上编译和运行简单的网络设备驱动程序编译驱动程序需要编写Makefile文件,与其他驱动的Makefile类似。

#   Makefile for net_test.c


#                              a simple net device driver


#                                  Aka   2006.08


OBJS = net_test.o


SRC  = net_test.c




CC           =  /usr/local/arm/2.95.3/bin/arm-linux-gcc  


LD           =  /usr/local/arm/2.95.3/bin/arm-linux-ld




#INCLUDE = -I/HHARM2410-R3/kernel/include/linux -I/HHARM2410-R3/kernel/include


INCLUDE = -I/9200E/arm-kernel/linux-2.4.19-rmk7/include




CFLAGS = -D__KERNEL__  -DMODULE -O2 -Wall -Wstrict-prototypes -Wno-trigraphs -Wmissing-prototypes




All: $(OBJS)




%.o:%.c


         $(CC) $(CFLAGS) $(INCLUDE) -c $^ -o $@




.PHONY: clean


clean:


         -rm -f *.o


distclean:


         @make clean


         rm -f tags *~


编译,测试驱动文件net_test.o,要把这个文件下载到HHARM2410的开发平台上,需要建立好主机与开发板的连接和开发环境。参考附录一建立开发环境。



在主机上编译驱动程序,在源文件目下输入

[localhost]# make


生成驱动文件模块test_net.o

通过网络或者NFS,把驱动文件net_test.o传到开发板的系统中。

加载驱动模块如下

[localhost]# insmod test_net.o


卸载驱动模块如下:


[localhost]# rmmod test_net.o

出0入0汤圆

 楼主| 发表于 2008-3-5 09:27:22 | 显示全部楼层
Linux下DM9000网卡驱动实验〈二〉
1.1.1          步骤三:网络驱动程序的数据结构和抽象接口首先熟悉以下重要的数据结构,然后对照DM9000的驱动程序,察看具体数据结构的用法。

保存网络设备信息的结构体net_device

net_device结构存储了网络设备的操作方法和其他信息。其定义如下面的清单。仅仅列出了部分常用的成员,对于普通的网络设备驱动程序已足够。想详细了解的结构体参考LDD(Linux Device Driver)或内核源码/include/linux/netdevice.h


程序清单 0&#8209;2

struct net_device


{


     char               name[IFNAMSIZ];


     unsigned short     flags;   /* interface flags (a la BSD)    */


     unsigned long      base_addr;    /* device I/O address  */


     unsigned int       irq;     /* device IRQ number   */


     unsigned char      dev_addr[MAX_ADDR_LEN]; /* hw address */


     unsigned char      addr_len; /* hardware address length  */


     unsigned long      trans_start;  /* Time (in jiffies) of last Tx  */


     unsigned long      last_rx; /* Time of last Rx */


     int                watchdog_timeo;


     void               *priv;   /* pointer to private data  */


     struct module      *owner;  /* open/release and usage marking */




     int                    (*init)(struct net_device *dev);


     int                    (*open)(struct net_device *dev);


     int                    (*stop)(struct net_device *dev);


     int                    (*set_config)(struct net_device *dev, struct ifmap *map);


     int                    (*hard_start_xmit) (struct sk_buff *skb,struct net_device *dev);


     int                    (*set_mac_address)(struct net_device *dev,  void *addr);


     //..............


};






网卡实现的抽象接口

init(),open(),stop(),set_config()方法在模板中已经清楚地介绍了,这里重点讲解hard_start_xmit()方法。当内核需要发送一个数据包时,他调用hard_start_xmit()方法将数据放到一个输出队列。数据包包含在一个套接字缓冲区结构体(struct sk_buff)变量中。对于驱动程序来说,sk_buff只是一个数据包,不用关心里面复杂的结构成员。


程序清单 0&#8209;3

static int test_tx(struct sk_buff * skb , struct net_device * dev)


{


int len;




netif_stop_queue(dev);    //让内核暂停调用hard_start_xmit()方法


len = skb->len < ETH_ZLEN ? ETH_ZLEN :skb->len;


//把len个数据写入网络设备硬件缓冲区并启动发送;


dev->trans_start = jiffies;  //记录时间


dev_kfree_skb(skb);


//等待数据发送完毕


netif_wake_queue(dev);




return 0;


}




static int test_set_mac_address(struct net_device * dev, void *addr)


{


struct socketaddr   * mac_addr;




mac_addr = addr;


if(netif_running(dev))


{


    Return –EBUSY;


}


memcpy(dev->dev_addr , mac_addr->sa_data , dev->addr_len);


//改变mac地址,与具体硬件相关。


return 0;


}

















数据接收与中断服务程序

一般网络驱动程序不对发送数据进行缓存,而是直接使用硬件的发送功能把数据发送出去。接收数据则通过硬件中断来通知的。在中断处理程序中,把硬件帧信息填入一个sk_buff结构中,然后调用netif_rx()传递给上层处理。当然,在使用中断之前,需要向系统注册中断处理程序。



下面是中断服务程序的写法:

static void net_irq_handle(int irq, void * dev_id, struct pt_regs * regs)


{


struct net_device * dev;


struct sk_buff    *skb;


unsigned int     length;


u8            * dec;




dev = (struct net_device *)dev_id;


if(发送成功)


{


    清除发送中断标志;


   netif_wake_queue(dev);


}


if(接收成功)


{


    清除接受中断标志;


  length = 数据包长度;


    skb = dev_alloc_skb(length + 2);


    if(!skb)


{


    return;


}


    skb_reserve(skb, 2);


dec = skb->data;


//把数据包(length长度)读到dec指向的内存中;


skb->dev = dev;


skb->protocol = eth_type_trans(skb, dev);


skb->ip_summed = CHECKSUM_UNNECESSARY;


netif_rx(skb);


dev->last_rx = jiffies;


}




if(出错)


   错误处理




清除中断源;


}

出0入0汤圆

 楼主| 发表于 2008-3-5 09:28:22 | 显示全部楼层
Linux下DM9000网卡驱动实验〈三〉
1.1.1          步骤四:分析DM9000的网卡驱动程序驱动程序共包含三个文件dm9000x.c ,dm9000.c 和dm9000.h,都存放在drivers/net/目录下,其中dm9000x.c 主要包括以下函数:





底层硬件操作函数:这些函数与硬件相关,与驱动程序编写相关不大。  

void            outb(unsigned char value, unsigned long addr)


void            outw(unsigned short value, unsigned long addr)


unsigned char     inb(unsigned long addr)


unsigned short    inw(unsigned long addr)






u8 ior(board_info_t *db, int reg)   // Read a byte from I/O port


void iow(board_info_t *db, int reg, u8 value) //   Write a byte to I/O port











驱动程序的函数接口,

int init_module(void) ; //加载设备驱动程序


void cleanup_module(void) //卸载设备驱动程序






static void dmfe_init_dm9000(struct DEVICE *dev) /* Initilize DM910X board */


dmfe_probe(struct DEVICE *dev); //初始化net_device 结构体


static int dmfe_open(struct DEVICE *dev)


static int dmfe_stop(struct DEVICE *dev)


static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev) //发送一个数据包


static void dmfe_packet_receive(struct DEVICE *dev, board_info_t *db) //接收数据包,被中断调用











其中int init_module(void)函数调用了dmfe_probe(struct DEVICE *dev)来初始化net_device结构体

if(strcmp(dev->name,"eth0")==0)


         if(strcmp(dev->name,"eth1")==0)


         if(strcmp(dev->name,"eth3")==0)


                  


         outb(DM9000_VID_L, iobase);


         id_val = inb(iobase + 4);


         outb(DM9000_VID_H, iobase);


         id_val |= inb(iobase + 4) << 8;


         outb(DM9000_PID_L, iobase);


         id_val |= inb(iobase + 4) << 16;


         outb(DM9000_PID_H, iobase);


         id_val |= inb(iobase + 4) << 24;






         if (id_val == DM9000_ID) {


             printk("HHTech DM9000 %s I/O: %x,VID: %x,MAC: ", dev->name,iobase, id_val);


             dm9000_count++;


             /* Init network device */


             dev = init_etherdev(dev, 0);






         /* Allocated board information structure */


       irqline = 3;

         db = (void *)(kmalloc(sizeof(*db), GFP_KERNEL|GFP_DMA));


         memset(db, 0, sizeof(*db));


         dev->priv = db;   /* link device and board info */


         db->next_dev = dmfe_root_dev;


         dmfe_root_dev = dev;


         db->ioaddr = iobase;


         db->io_data = iobase + 4;






         /* driver system function */


         dev->base_addr = iobase;


         //dev->irq = 68; //INT4 166;//irqline;


         dev->open = &dmfe_open;


         dev->hard_start_xmit = &dmfe_start_xmit;


         dev->stop = &dmfe_stop;


         dev->get_stats = &dmfe_get_stats;


         dev->set_multicast_list = &dm9000_hash_table;


         dev->do_ioctl = &dmfe_do_ioctl;











在dmfe_open(struct DEVICE *dev)中,申请了中断处理程序,然后调用了

dmfe_init_dm9000(dev);初始化DM9000芯片。

static int dmfe_open(struct DEVICE *dev)


{      


if(request_irq(dev->irq, &dmfe_interrupt,SA_INTERRUPT/*SA_SHIRQ*/,


"DM9000 device",dev))


                   return -EAGAIN;


/* Initilize DM910X board */


       dmfe_init_dm9000(dev);






netif_wake_queue(dev);         //add by simon 2001.9.4 for kernel 2.4


MOD_INC_USE_COUNT;


}






Stop()方法停止网络驱动程序:

static int dmfe_stop(struct DEVICE *dev)


{


netif_stop_queue(dev);  //add by simon 2001.9.4 for kernel 2.4






         /* free interrupt */


         free_irq(dev->irq, dev);






         /* RESET devie */


         phy_write(db, 0x00, 0x8000);        /* PHY RESET */


         iow(db, 0x1f, 0x01);     /* Power-Down PHY */


         iow(db, 0xff, 0x80);      /* Disable all interrupt */


         iow(db, 0x05, 0x00);    /* Disable RX */






         MOD_DEC_USE_COUNT;


return 0;


}


发送数据接口,对照前面的简单的驱动框架。

static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev)


{


netif_stop_queue(dev); //add by simon 2001.9.4 for kernel 2.4






         /* Disable all interrupt */


         iow(db, 0xff, 0x80);






         /* Move data to DM9000 TX RAM */


         data_ptr = (char *)skb->data;


         outb(0xf8, db->ioaddr);


         tmplen = (skb->len + 1) / 2;


         /* Word mode*/


         for (i = 0; i < tmplen; i++)


                      outw(((u16 *)data_ptr), db->io_data);


         


         /* TX control: First packet immediately send, second packet queue */


         if (db->tx_pkt_cnt == 0) {


                   /* First Packet */


                   db->tx_pkt_cnt++;






                   /* Set TX length to DM9000 */


                   iow(db, 0xfc, skb->len & 0xff);


                   iow(db, 0xfd, (skb->len >> 8) & 0xff);






                   /* Issue TX polling command */


                   iow(db, 0x2, 0x1);        /* Cleared after TX complete */






                   dev->trans_start = jiffies;      /* saved the time stamp */


         } else {


                   /* Second packet */


                   db->tx_pkt_cnt++;


                   db->queue_pkt_len = skb->len;


         }





         /* free this SKB */


         dev_kfree_skb(skb);






       /* Re-enable resource check */


         if (db->tx_pkt_cnt == 1)


         netif_wake_queue(dev);   //add by simon 2001.9.4 for kernel 2.4


                  


         /* Re-enable interrupt mask */


         iow(db, 0xff, 0x83);






         return 0;


}






中断处理程序,用来接收数据

static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)


{      


         db = (board_info_t *)dev->priv;


         spin_lock(&db->lock); // add by simon 2001.9.4 for kernel 2.4






         /* Save previous register address */


         reg_save = inb(db->ioaddr);






         /* Disable all interrupt */


         iow(db, 0xff, 0x80);






         /* Got DM9000 interrupt status */


         int_status = ior(db, 0xfe);               /* Got ISR */


         iow(db, 0xfe, int_status);                /* Clear ISR status */


         //printk("I%x ", int_status);






         /* Received the coming packet */


         if (int_status & 1)


                   dmfe_packet_receive(dev, db);


                  


         /* Trnasmit Interrupt check */


         if (int_status & 2) {


                   tx_status = ior(db, 0x01);      /* Got TX status */


                   if (tx_status & 0xc) {


                            /* One packet sent complete */


                            db->tx_pkt_cnt--;


                            dev->trans_start = 0;


                            db->stats.tx_packets++;






                            /* Queue packet check & send */


                            if (db->tx_pkt_cnt > 0) {


                                     iow(db, 0xfc, db->queue_pkt_len & 0xff);


                                     iow(db, 0xfd, (db->queue_pkt_len >> 8) & 0xff);


                                     iow(db, 0x2, 0x1);


                                     dev->trans_start = jiffies;


                            }






                            //dev->tbusy = 0;         /* Active upper layer, send again */


                            //mark above by simon 2001.9.4 for kernel 2.4


                            netif_wake_queue(dev);


                            //mark_bh(NET_BH); //mark by simon 2001.9.4


                   }


         }





         /* Re-enable interrupt mask */


         iow(db, 0xff, 0x83);






         /* Restore previous register address */


         outb(reg_save, db->ioaddr);






1.1.2          步骤五:调试运行DM9000网卡驱动程序在内核的DM9000驱动代码中,直接增加调试和打印信息,然后重新编译内核,下载到开发板上,察看调试信息。内核中的打印输出语句用printk()。

把内核中的DM9000的网络驱动程序/drivers/net/dm9000x.c中的注释掉的printk语句打开。详细见dm9000x.c文件。





第一步,打印网络的配置信息,与ifconfig显示的信息比较。

1, 在/kernel/drivers/net/dm9000x.c中,注释掉的printk有效。主要是在dmfe_probe(struct DEVICE *dev)函数中的打印信息.

2, 然后再/kernel目录下编译内核,make zImage

3, 通过TFTP下载刚编译的内核镜像zImage到开发板中

tftp 30008000 zImage

tftp 30800000 ramdisk.image.gz

go 30008000






4,观察系统启动时有网络驱动程序打印出来的信息。进入系统后用ifconfig察看网络信息。





第二步:观察中断调用,数据接收的情况

1, 在/kernel/drivers/net/dm9000x.c中,使宏定义有效

//#undef DM9000_DEBUG   


#define DM9000_DEBUG


主要是在

static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)


static void dmfe_packet_receive(struct DEVICE *dev, board_info_t *db)


中的打印信息, 注释掉的printk有效.

2, 然后再/kernel目录下编译内核,make zImage

3, 通过TFTP下载刚编译的内核镜像zImage到开发板中

tftp 30008000 zImage

tftp 30800000 ramdisk.image.gz

go 30008000

4,观察系统启动时有网络驱动程序打印出来的信息。进入系统后挂载NFS系统(如果还没有挂载NFS),可以看到打印出网络中断和数据接收的信息。





第二步:用户层调用网络socket接口。

1,  因为操作系统封装了网络设备驱动程序,用户层只能通过socket接口使用网络。 HHARM2410-STUDY\modules.TestApp\ethernet-performance-test提供了测试网络流量的测试程序,使用了socket接口。

2,  分别编译HHARM2410-STUDY\modules.TestApp\ethernet-performance-test\run-on-board和HHARM2410-STUDY\modules.TestApp\ethernet-performance-test\run-on-LINUX-PC

3,开发板用网线(对接线)同PC机相连;


PC机上编译好eth-perf-pc/中的程序,生成server可执行程序,运行


./server


在minicom下执行客户端程序(开发板上)


./client 192.168.2.111 –t 1 –p 1


其中192.168.2.111为PC机的IP,-t表示time,-p表示package。

4,如果这时候没有注释掉网络驱动程序dm9000的中断和接收数据的打印信息,屏幕会频繁的提示产生中断和接收到数据。

还可以用

[localhost]# cat /prop/interrupts


察看中断使用情况,可以看到网络驱动程序使用中断号,和使用次数。

出0入0汤圆

 楼主| 发表于 2008-3-5 09:32:18 | 显示全部楼层
/*
* dm9000 Ethernet
*/

#ifndef _DM9000X_H_
#define _DM9000X_H_

#define DM9000_ID                0x90000A46

/* although the registers are 16 bit, they are 32-bit aligned.
*/

#define DM9000_NCR             0x00
#define DM9000_NSR             0x01
#define DM9000_TCR             0x02
#define DM9000_TSR1            0x03
#define DM9000_TSR2            0x04
#define DM9000_RCR             0x05
#define DM9000_RSR             0x06
#define DM9000_ROCR            0x07
#define DM9000_BPTR            0x08
#define DM9000_FCTR            0x09
#define DM9000_FCR             0x0A
#define DM9000_EPCR            0x0B
#define DM9000_EPAR            0x0C
#define DM9000_EPDRL           0x0D
#define DM9000_EPDRH           0x0E
#define DM9000_WCR             0x0F

#define DM9000_PAR             0x10
#define DM9000_MAR             0x16

#define DM9000_GPCR               0x1e
#define DM9000_GPR             0x1f
#define DM9000_TRPAL           0x22
#define DM9000_TRPAH           0x23
#define DM9000_RWPAL           0x24
#define DM9000_RWPAH           0x25

#define DM9000_VIDL            0x28
#define DM9000_VIDH            0x29
#define DM9000_PIDL            0x2A
#define DM9000_PIDH            0x2B

#define DM9000_CHIPR           0x2C
#define DM9000_SMCR            0x2F

#define DM9000_MRCMDX          0xF0
#define DM9000_MRCMD           0xF2
#define DM9000_MRRL            0xF4
#define DM9000_MRRH            0xF5
#define DM9000_MWCMDX          0xF6
#define DM9000_MWCMD           0xF8
#define DM9000_MWRL            0xFA
#define DM9000_MWRH            0xFB
#define DM9000_TXPLL           0xFC
#define DM9000_TXPLH           0xFD
#define DM9000_ISR             0xFE
#define DM9000_IMR             0xFF

#define NCR_EXT_PHY         (1<<7)
#define NCR_WAKEEN          (1<<6)
#define NCR_FCOL            (1<<4)
#define NCR_FDX             (1<<3)
#define NCR_LBK             (3<<1)
#define NCR_RST                    (1<<0)

#define NSR_SPEED           (1<<7)
#define NSR_LINKST          (1<<6)
#define NSR_WAKEST          (1<<5)
#define NSR_TX2END          (1<<3)
#define NSR_TX1END          (1<<2)
#define NSR_RXOV            (1<<1)

#define TCR_TJDIS           (1<<6)
#define TCR_EXCECM          (1<<5)
#define TCR_PAD_DIS2        (1<<4)
#define TCR_CRC_DIS2        (1<<3)
#define TCR_PAD_DIS1        (1<<2)
#define TCR_CRC_DIS1        (1<<1)
#define TCR_TXREQ           (1<<0)

#define TSR_TJTO            (1<<7)
#define TSR_LC              (1<<6)
#define TSR_NC              (1<<5)
#define TSR_LCOL            (1<<4)
#define TSR_COL             (1<<3)
#define TSR_EC              (1<<2)

#define RCR_WTDIS           (1<<6)
#define RCR_DIS_LONG        (1<<5)
#define RCR_DIS_CRC         (1<<4)
#define RCR_ALL                    (1<<3)
#define RCR_RUNT            (1<<2)
#define RCR_PRMSC           (1<<1)
#define RCR_RXEN            (1<<0)

#define RSR_RF              (1<<7)
#define RSR_MF              (1<<6)
#define RSR_LCS             (1<<5)
#define RSR_RWTO            (1<<4)
#define RSR_PLE             (1<<3)
#define RSR_AE              (1<<2)
#define RSR_CE              (1<<1)
#define RSR_FOE             (1<<0)

#define FCTR_HWOT(ot)        (( ot & 0xf ) << 4 )
#define FCTR_LWOT(ot)        ( ot & 0xf )

#define IMR_PAR             (1<<7)
#define IMR_ROOM            (1<<3)
#define IMR_ROM             (1<<2)
#define IMR_PTM             (1<<1)
#define IMR_PRM             (1<<0)

#define ISR_ROOS            (1<<3)
#define ISR_ROS             (1<<2)
#define ISR_PTS             (1<<1)
#define ISR_PRS             (1<<0)
#define ISR_CLR_STATUS      (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)

#define EPCR_REEP           (1<<5)
#define EPCR_WEP            (1<<4)
#define EPCR_EPOS           (1<<3)
#define EPCR_ERPRR          (1<<2)
#define EPCR_ERPRW          (1<<1)
#define EPCR_ERRE           (1<<0)

#define GPCR_GEP_CNTL       (1<<0)

#define DM9000_PKT_RDY                0x01        /* Packet ready to receive */
#define DM9000_PKT_MAX                1536        /* Received packet max size */

#endif /* _DM9000X_H_ */

出0入0汤圆

 楼主| 发表于 2008-3-5 09:32:40 | 显示全部楼层
/*
*   dm9000.c: Version 1.2 03/18/2003
*
*         A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
*         Copyright (C) 1997  Sten Wang
*
*         This program is free software; you can redistribute it and/or
*         modify it under the terms of the GNU General Public License
*         as published by the Free Software Foundation; either version 2
*         of the License, or (at your option) any later version.
*
*         This program is distributed in the hope that it will be useful,
*         but WITHOUT ANY WARRANTY; without even the implied warranty of
*         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*         GNU General Public License for more details.
*
*   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
*
* V0.11        06/20/2001        REG_0A bit3=1, default enable BP with DA match
*         06/22/2001         Support DM9801 progrmming
*                           E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
*                          E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
*                                      R17 = (R17 & 0xfff0) | NF + 3
*                          E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
*                                      R17 = (R17 & 0xfff0) | NF
*
* v1.00                       modify by simon 2001.9.5
*                         change for kernel 2.4.x
*
* v1.1   11/09/2001              fix force mode bug
*
* v1.2   03/18/2003       Weilun Huang <weilun_huang@davicom.com.tw>:
*                         Fixed phy reset.
*                         Added tx/rx 32 bit mode.
*                         Cleaned up for kernel merge.
*
*        03/03/2004    Sascha Hauer <s.hauer@pengutronix.de>
*                      Port to 2.6 kernel
*
*          24-Sep-2004   Ben Dooks <ben@simtec.co.uk>
*                        Cleanup of code to remove ifdefs
*                        Allowed platform device data to influence access width
*                        Reformatting areas of code
*
*        17-Mar-2005   Sascha Hauer <s.hauer@pengutronix.de>
*                      * removed 2.4 style module parameters
*                      * removed removed unused stat counter and fixed
*                        net_device_stats
*                      * introduced tx_timeout function
*                      * reworked locking
*
*          01-Jul-2005   Ben Dooks <ben@simtec.co.uk>
*                        * fixed spinlock call without pointer
*                        * ensure spinlock is initialised
*/

#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/dm9000.h>
#include <linux/delay.h>
#include <linux/platform_device.h>

#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/io.h>

#include "dm9000.h"

/* Board/System/Debug information/definition ---------------- */

#define DM9000_PHY                0x40        /* PHY address 0x01 */

#define TRUE                        1
#define FALSE                        0

#define CARDNAME "dm9000"
#define PFX CARDNAME ": "

#define DM9000_TIMER_WUT  jiffies+(HZ*2)        /* timer wakeup time : 2 second */

#define DM9000_DEBUG 0

#if DM9000_DEBUG > 2
#define PRINTK3(args...)  printk(CARDNAME ": " args)
#else
#define PRINTK3(args...)  do { } while(0)
#endif

#if DM9000_DEBUG > 1
#define PRINTK2(args...)  printk(CARDNAME ": " args)
#else
#define PRINTK2(args...)  do { } while(0)
#endif

#if DM9000_DEBUG > 0
#define PRINTK1(args...)  printk(CARDNAME ": " args)
#define PRINTK(args...)   printk(CARDNAME ": " args)
#else
#define PRINTK1(args...)  do { } while(0)
#define PRINTK(args...)   printk(KERN_DEBUG args)
#endif

/*
* Transmit timeout, default 5 seconds.
*/
static int watchdog = 5000;
module_param(watchdog, int, 0400);
MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");

/* Structure/enum declaration ------------------------------- */
typedef struct board_info {

        void __iomem *io_addr;        /* Register I/O base address */
        void __iomem *io_data;        /* Data I/O address */
        u16 irq;                /* IRQ */

        u16 tx_pkt_cnt;
        u16 queue_pkt_len;
        u16 queue_start_addr;
        u16 dbug_cnt;
        u8 io_mode;                /* 0:word, 2:byte */
        u8 phy_addr;

        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 resource        *addr_res;   /* resources found */
        struct resource *data_res;
        struct resource        *addr_req;   /* resources requested */
        struct resource *data_req;
        struct resource *irq_res;

        struct timer_list timer;
        struct net_device_stats stats;
        unsigned char srom[128];
        spinlock_t lock;

        struct mii_if_info mii;
        u32 msg_enable;
} board_info_t;

/* function declaration ------------------------------------- */
static int dm9000_probe(struct platform_device *);
static int dm9000_open(struct net_device *);
static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
static int dm9000_stop(struct net_device *);


static void dm9000_timer(unsigned long);
static void dm9000_init_dm9000(struct net_device *);

static struct net_device_stats *dm9000_get_stats(struct net_device *);

static irqreturn_t dm9000_interrupt(int, void *);

static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);
static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
                           int value);
static u16 read_srom_word(board_info_t *, int);
static void dm9000_rx(struct net_device *);
static void dm9000_hash_table(struct net_device *);

//#define DM9000_PROGRAM_EEPROM
#ifdef DM9000_PROGRAM_EEPROM
static void program_eeprom(board_info_t * db);
#endif
/* DM9000 network board routine ---------------------------- */

static void
dm9000_reset(board_info_t * db)
{
        PRINTK1("dm9000x: resetting\n");
        /* 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 u8
ior(board_info_t * db, int reg)
{
        writeb(reg, db->io_addr);
        return readb(db->io_data);
}

/*
*   Write a byte to I/O port
*/

static void
iow(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 */

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
*/

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 2:
                db->dumpblk = dm9000_dumpblk_16bit;
                db->outblk  = dm9000_outblk_16bit;
                db->inblk   = dm9000_inblk_16bit;
                break;

        case 3:
                printk(KERN_ERR PFX ": 3 byte IO, falling back to 16bit\n");
                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;
        }
}


/* Our watchdog timed out. Called by the networking layer */
static void dm9000_timeout(struct net_device *dev)
{
        board_info_t *db = (board_info_t *) dev->priv;
        u8 reg_save;
        unsigned long flags;

        /* Save previous register address */
        reg_save = readb(db->io_addr);
        spin_lock_irqsave(&db->lock,flags);

        netif_stop_queue(dev);
        dm9000_reset(db);
        dm9000_init_dm9000(dev);
        /* We can accept TX packets again */
        dev->trans_start = jiffies;
        netif_wake_queue(dev);

        /* Restore previous register address */
        writeb(reg_save, db->io_addr);
        spin_unlock_irqrestore(&db->lock,flags);
}

#ifdef CONFIG_NET_POLL_CONTROLLER
/*
*Used by netconsole
*/
static void dm9000_poll_controller(struct net_device *dev)
{
        disable_irq(dev->irq);
        dm9000_interrupt(dev->irq,dev);
        enable_irq(dev->irq);
}
#endif

/* dm9000_release_board
*
* release a board, and any mapped resources
*/

static void
dm9000_release_board(struct platform_device *pdev, struct board_info *db)
{
        if (db->data_res == NULL) {
                if (db->addr_res != NULL)
                        release_mem_region((unsigned long)db->io_addr, 4);
                return;
        }

        /* unmap our resources */

        iounmap(db->io_addr);
        iounmap(db->io_data);

        /* release the resources */

        if (db->data_req != NULL) {
                release_resource(db->data_req);
                kfree(db->data_req);
        }

        if (db->addr_req != NULL) {
                release_resource(db->addr_req);
                kfree(db->addr_req);
        }
}

#define res_size(_r) (((_r)->end - (_r)->start) + 1)

/*
* Search DM9000 board, allocate space and register it
*/
static int
dm9000_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;
        unsigned long base;
        int ret = 0;
        int iosize;
        int i;
        u32 id_val;

        /* Init network device */
        ndev = alloc_etherdev(sizeof (struct board_info));
        if (!ndev) {
                printk("%s: could not allocate device.\n", CARDNAME);
                return -ENOMEM;
        }

        SET_MODULE_OWNER(ndev);
        SET_NETDEV_DEV(ndev, &pdev->dev);

        PRINTK2("dm9000_probe()");

        /* setup board info structure */
        db = (struct board_info *) ndev->priv;
        memset(db, 0, sizeof (*db));

        spin_lock_init(&db->lock);

        if (pdev->num_resources < 2) {
                ret = -ENODEV;
                goto out;
        } else if (pdev->num_resources == 2) {
                base = pdev->resource[0].start;

                if (!request_mem_region(base, 4, ndev->name)) {
                        ret = -EBUSY;
                        goto out;
                }

                ndev->base_addr = base;
                ndev->irq = pdev->resource[1].start;
                db->io_addr = (void __iomem *)base;
                db->io_data = (void __iomem *)(base + 4);

        } else {
                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) {
                        printk(KERN_ERR PFX "insufficient resources\n");
                        ret = -ENOENT;
                        goto out;
                }

                i = res_size(db->addr_res);
                db->addr_req = request_mem_region(db->addr_res->start, i,
                                                  pdev->name);

                if (db->addr_req == NULL) {
                        printk(KERN_ERR PFX "cannot claim address reg area\n");
                        ret = -EIO;
                        goto out;
                }

                db->io_addr = ioremap(db->addr_res->start, i);

                if (db->io_addr == NULL) {
                        printk(KERN_ERR "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) {
                        printk(KERN_ERR PFX "cannot claim data reg area\n");
                        ret = -EIO;
                        goto out;
                }

                db->io_data = ioremap(db->data_res->start, iosize);

                if (db->io_data == NULL) {
                        printk(KERN_ERR "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;
        }

        dm9000_reset(db);

        /* try two times, DM9000 sometimes gets the first read wrong */
        for (i = 0; i < 2; 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;
                printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val);
        }

        if (id_val != DM9000_ID) {
                printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val);
                goto release;
        }

        /* 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->get_stats                 = &dm9000_get_stats;
        ndev->set_multicast_list = &dm9000_hash_table;
#ifdef CONFIG_NET_POLL_CONTROLLER
        ndev->poll_controller         = &dm9000_poll_controller;
#endif

#ifdef DM9000_PROGRAM_EEPROM
        program_eeprom(db);
#endif
        db->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;

        /* Read SROM content */
        for (i = 0; i < 64; i++)
                ((u16 *) db->srom) = read_srom_word(db, i);

        /* Set Node Address */
        for (i = 0; i < 6; i++)
                ndev->dev_addr = db->srom;

        if (!is_valid_ether_addr(ndev->dev_addr)) {
                /* try reading from mac */

                for (i = 0; i < 6; i++)
                        ndev->dev_addr = ior(db, i+DM9000_PAR);
        }

        if (!is_valid_ether_addr(ndev->dev_addr))
                printk("%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("%s: dm9000 at %p,%p IRQ %d MAC: ",
                       ndev->name,  db->io_addr, db->io_data, ndev->irq);
                for (i = 0; i < 5; i++)
                        printk("%02x:", ndev->dev_addr);
                printk("%02x\n", ndev->dev_addr[5]);
        }
        return 0;

release:
out:
        printk("%s: not found (%d).\n", CARDNAME, ret);

        dm9000_release_board(pdev, db);
        kfree(ndev);

        return ret;
}

/*
*  Open the interface.
*  The interface is opened whenever "ifconfig" actives it.
*/
static int
dm9000_open(struct net_device *dev)
{
        board_info_t *db = (board_info_t *) dev->priv;

        PRINTK2("entering dm9000_open\n");

        if (request_irq(dev->irq, &dm9000_interrupt, IRQF_SHARED, dev->name, dev))
                return -EAGAIN;

        /* Initialize DM9000 board */
        dm9000_reset(db);
        dm9000_init_dm9000(dev);

        /* Init driver variable */
        db->dbug_cnt = 0;

        /* set and active a timer process */
        init_timer(&db->timer);
        db->timer.expires  = DM9000_TIMER_WUT;
        db->timer.data     = (unsigned long) dev;
        db->timer.function = &dm9000_timer;
        add_timer(&db->timer);

        mii_check_media(&db->mii, netif_msg_link(db), 1);
        netif_start_queue(dev);

        return 0;
}

/*
* Initilize dm9000 board
*/
static void
dm9000_init_dm9000(struct net_device *dev)
{
        board_info_t *db = (board_info_t *) dev->priv;

        PRINTK1("entering %s\n",__FUNCTION__);

        /* I/O mode */
        db->io_mode = ior(db, DM9000_ISR) >> 6;        /* ISR bit7:6 keeps I/O mode */

        /* GPIO0 on pre-activate PHY */
        iow(db, DM9000_GPR, 0);        /* REG_1F bit0 activate phyxcer */
        iow(db, DM9000_GPCR, GPCR_GEP_CNTL);        /* Let GPIO0 output */
        iow(db, DM9000_GPR, 0);        /* Enable PHY */

        /* Program operating register */
        iow(db, DM9000_TCR, 0);                /* TX Polling clear */
        iow(db, DM9000_BPTR, 0x3f);        /* Less 3Kb, 200us */
        iow(db, DM9000_FCR, 0xff);        /* Flow Control */
        iow(db, DM9000_SMCR, 0);        /* Special Mode */
        /* clear TX status */
        iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
        iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */

        /* Set address filter table */
        dm9000_hash_table(dev);

        /* Activate DM9000 */
        iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
        /* Enable TX/RX interrupt mask */
        iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);

        /* Init Driver variable */
        db->tx_pkt_cnt = 0;
        db->queue_pkt_len = 0;
        dev->trans_start = 0;
}

/*
*  Hardware start transmission.
*  Send a packet to media from the upper layer.
*/
static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
        board_info_t *db = (board_info_t *) dev->priv;

        PRINTK3("dm9000_start_xmit\n");

        if (db->tx_pkt_cnt > 1)
                return 1;

        netif_stop_queue(dev);

        /* Disable all interrupts */
        iow(db, DM9000_IMR, IMR_PAR);

        /* Move data to DM9000 TX RAM */
        writeb(DM9000_MWCMD, db->io_addr);

        (db->outblk)(db->io_data, skb->data, skb->len);
        db->stats.tx_bytes += skb->len;

        /* TX control: First packet immediately send, second packet queue */
        if (db->tx_pkt_cnt == 0) {

                /* First Packet */
                db->tx_pkt_cnt++;

                /* Set TX length to DM9000 */
                iow(db, DM9000_TXPLL, skb->len & 0xff);
                iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff);

                /* 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->tx_pkt_cnt++;
                db->queue_pkt_len = skb->len;
        }

        /* free this SKB */
        dev_kfree_skb(skb);

        /* Re-enable resource check */
        if (db->tx_pkt_cnt == 1)
                netif_wake_queue(dev);

        /* Re-enable interrupt */
        iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);

        return 0;
}

static void
dm9000_shutdown(struct net_device *dev)
{
        board_info_t *db = (board_info_t *) dev->priv;

        /* RESET device */
        dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);        /* PHY RESET */
        iow(db, DM9000_GPR, 0x01);        /* Power-Down PHY */
        iow(db, DM9000_IMR, IMR_PAR);        /* Disable all interrupt */
        iow(db, DM9000_RCR, 0x00);        /* Disable RX */
}

/*
* Stop the interface.
* The interface is stopped when it is brought.
*/
static int
dm9000_stop(struct net_device *ndev)
{
        board_info_t *db = (board_info_t *) ndev->priv;

        PRINTK1("entering %s\n",__FUNCTION__);

        /* deleted timer */
        del_timer(&db->timer);

        netif_stop_queue(ndev);
        netif_carrier_off(ndev);

        /* free interrupt */
        free_irq(ndev->irq, ndev);

        dm9000_shutdown(ndev);

        return 0;
}

/*
* DM9000 interrupt handler
* receive the packet to upper layer, free the transmitted packet
*/

static void
dm9000_tx_done(struct net_device *dev, board_info_t * db)
{
        int tx_status = ior(db, DM9000_NSR);        /* Got TX status */

        if (tx_status & (NSR_TX2END | NSR_TX1END)) {
                /* One packet sent complete */
                db->tx_pkt_cnt--;
                db->stats.tx_packets++;

                /* Queue packet check & send */
                if (db->tx_pkt_cnt > 0) {
                        iow(db, DM9000_TXPLL, db->queue_pkt_len & 0xff);
                        iow(db, DM9000_TXPLH, (db->queue_pkt_len >> 8) & 0xff);
                        iow(db, DM9000_TCR, TCR_TXREQ);
                        dev->trans_start = jiffies;
                }
                netif_wake_queue(dev);
        }
}

static irqreturn_t
dm9000_interrupt(int irq, void *dev_id)
{
        struct net_device *dev = dev_id;
        board_info_t *db;
        int int_status;
        u8 reg_save;

        PRINTK3("entering %s\n",__FUNCTION__);

        if (!dev) {
                PRINTK1("dm9000_interrupt() without DEVICE arg\n");
                return IRQ_HANDLED;
        }

        /* A real interrupt coming */
        db = (board_info_t *) dev->priv;
        spin_lock(&db->lock);

        /* 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 */

        /* 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);

        /* Re-enable interrupt mask */
        iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);

        /* Restore previous register address */
        writeb(reg_save, db->io_addr);

        spin_unlock(&db->lock);

        return IRQ_HANDLED;
}

/*
*  Get statistics from driver.
*/
static struct net_device_stats *
dm9000_get_stats(struct net_device *dev)
{
        board_info_t *db = (board_info_t *) dev->priv;
        return &db->stats;
}


/*
*  A periodic timer routine
*  Dynamic media sense, allocated Rx buffer...
*/
static void
dm9000_timer(unsigned long data)
{
        struct net_device *dev = (struct net_device *) data;
        board_info_t *db = (board_info_t *) dev->priv;

        PRINTK3("dm9000_timer()\n");

        mii_check_media(&db->mii, netif_msg_link(db), 0);

        /* Set timer again */
        db->timer.expires = DM9000_TIMER_WUT;
        add_timer(&db->timer);
}

struct dm9000_rxhdr {
        u16        RxStatus;
        u16        RxLen;
} __attribute__((__packed__));

/*
*  Received a packet and pass to upper layer
*/
static void
dm9000_rx(struct net_device *dev)
{
        board_info_t *db = (board_info_t *) dev->priv;
        struct dm9000_rxhdr rxhdr;
        struct sk_buff *skb;
        u8 rxbyte, *rdptr;
        int 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) {
                        printk("status check failed: %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 = rxhdr.RxLen;

                /* Packet Status check */
                if (RxLen < 0x40) {
                        GoodPacket = FALSE;
                        PRINTK1("Bad Packet received (runt)\n");
                }

                if (RxLen > DM9000_PKT_MAX) {
                        PRINTK1("RST: RX Len:%x\n", RxLen);
                }

                if (rxhdr.RxStatus & 0xbf00) {
                        GoodPacket = FALSE;
                        if (rxhdr.RxStatus & 0x100) {
                                PRINTK1("fifo error\n");
                                db->stats.rx_fifo_errors++;
                        }
                        if (rxhdr.RxStatus & 0x200) {
                                PRINTK1("crc error\n");
                                db->stats.rx_crc_errors++;
                        }
                        if (rxhdr.RxStatus & 0x8000) {
                                PRINTK1("length error\n");
                                db->stats.rx_length_errors++;
                        }
                }

                /* Move data from DM9000 */
                if (GoodPacket
                    && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
                        skb->dev = dev;
                        skb_reserve(skb, 2);
                        rdptr = (u8 *) skb_put(skb, RxLen - 4);

                        /* Read received packet from RX SRAM */

                        (db->inblk)(db->io_data, rdptr, RxLen);
                        db->stats.rx_bytes += RxLen;

                        /* Pass to upper layer */
                        skb->protocol = eth_type_trans(skb, dev);
                        netif_rx(skb);
                        db->stats.rx_packets++;

                } else {
                        /* need to dump the packet's data */

                        (db->dumpblk)(db->io_data, RxLen);
                }
        } while (rxbyte == DM9000_PKT_RDY);
}

/*
*  Read a word data from SROM
*/
static u16
read_srom_word(board_info_t * db, int offset)
{
        iow(db, DM9000_EPAR, offset);
        iow(db, DM9000_EPCR, EPCR_ERPRR);
        mdelay(8);                /* according to the datasheet 200us should be enough,
                                   but it doesn't work */
        iow(db, DM9000_EPCR, 0x0);
        return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH) << 8));
}

#ifdef DM9000_PROGRAM_EEPROM
/*
* Write a word data to SROM
*/
static void
write_srom_word(board_info_t * db, int offset, u16 val)
{
        iow(db, DM9000_EPAR, offset);
        iow(db, DM9000_EPDRH, ((val >> 8) & 0xff));
        iow(db, DM9000_EPDRL, (val & 0xff));
        iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
        mdelay(8);                /* same (敏感词0373) */
        iow(db, DM9000_EPCR, 0);
}

/*
* Only for development:
* Here we write static data to the eeprom in case
* we don't have valid content on a new board
*/
static void
program_eeprom(board_info_t * db)
{
        u16 eeprom[] = { 0x0c00, 0x007f, 0x1300,        /* MAC Address */
                0x0000,                /* Autoload: accept nothing */
                0x0a46, 0x9000,        /* Vendor / Product ID */
                0x0000,                /* pin control */
                0x0000,
        };                        /* Wake-up mode control */
        int i;
        for (i = 0; i < 8; i++)
                write_srom_word(db, i, eeprom);
}
#endif


/*
*  Calculate the CRC valude of the Rx packet
*  flag = 1 : return the reverse CRC (for the received packet CRC)
*         0 : return the normal CRC (for Hash Table index)
*/

static unsigned long
cal_CRC(unsigned char *Data, unsigned int Len, u8 flag)
{

       u32 crc = ether_crc_le(Len, Data);

       if (flag)
               return ~crc;

       return crc;
}

/*
*  Set DM9000 multicast address
*/
static void
dm9000_hash_table(struct net_device *dev)
{
        board_info_t *db = (board_info_t *) dev->priv;
        struct dev_mc_list *mcptr = dev->mc_list;
        int mc_cnt = dev->mc_count;
        u32 hash_val;
        u16 i, oft, hash_table[4];
        unsigned long flags;

        PRINTK2("dm9000_hash_table()\n");

        spin_lock_irqsave(&db->lock,flags);

        for (i = 0, oft = 0x10; i < 6; i++, oft++)
                iow(db, oft, dev->dev_addr);

        /* Clear Hash Table */
        for (i = 0; i < 4; i++)
                hash_table = 0x0;

        /* broadcast address */
        hash_table[3] = 0x8000;

        /* the multicast address in Hash Table : 64 bits */
        for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
                hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
                hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
        }

        /* Write the hash table to MAC MD table */
        for (i = 0, oft = 0x16; i < 4; i++) {
                iow(db, oft++, hash_table & 0xff);
                iow(db, oft++, (hash_table >> 8) & 0xff);
        }

        spin_unlock_irqrestore(&db->lock,flags);
}


/*
*   Read a word from phyxcer
*/
static int
dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
{
        board_info_t *db = (board_info_t *) dev->priv;
        unsigned long flags;
        unsigned int reg_save;
        int ret;

        spin_lock_irqsave(&db->lock,flags);

        /* Save previous register address */
        reg_save = readb(db->io_addr);

        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9000_EPAR, DM9000_PHY | reg);

        iow(db, DM9000_EPCR, 0xc);        /* Issue phyxcer read command */
        udelay(100);                /* Wait read complete */
        iow(db, DM9000_EPCR, 0x0);        /* Clear phyxcer read command */

        /* The read data keeps on REG_0D & REG_0E */
        ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);

        /* restore the previous address */
        writeb(reg_save, db->io_addr);

        spin_unlock_irqrestore(&db->lock,flags);

        return ret;
}

/*
*   Write a word to phyxcer
*/
static void
dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
{
        board_info_t *db = (board_info_t *) dev->priv;
        unsigned long flags;
        unsigned long reg_save;

        spin_lock_irqsave(&db->lock,flags);

        /* Save previous register address */
        reg_save = readb(db->io_addr);

        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9000_EPAR, DM9000_PHY | reg);

        /* Fill the written data into REG_0D & REG_0E */
        iow(db, DM9000_EPDRL, (value & 0xff));
        iow(db, DM9000_EPDRH, ((value >> 8) & 0xff));

        iow(db, DM9000_EPCR, 0xa);        /* Issue phyxcer write command */
        udelay(500);                /* Wait write complete */
        iow(db, DM9000_EPCR, 0x0);        /* Clear phyxcer write command */

        /* restore the previous address */
        writeb(reg_save, db->io_addr);

        spin_unlock_irqrestore(&db->lock,flags);
}

static int
dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
{
        struct net_device *ndev = platform_get_drvdata(dev);

        if (ndev) {
                if (netif_running(ndev)) {
                        netif_device_detach(ndev);
                        dm9000_shutdown(ndev);
                }
        }
        return 0;
}

static int
dm9000_drv_resume(struct platform_device *dev)
{
        struct net_device *ndev = platform_get_drvdata(dev);
        board_info_t *db = (board_info_t *) ndev->priv;

        if (ndev) {

                if (netif_running(ndev)) {
                        dm9000_reset(db);
                        dm9000_init_dm9000(ndev);

                        netif_device_attach(ndev);
                }
        }
        return 0;
}

static int
dm9000_drv_remove(struct platform_device *pdev)
{
        struct net_device *ndev = platform_get_drvdata(pdev);

        platform_set_drvdata(pdev, NULL);

        unregister_netdev(ndev);
        dm9000_release_board(pdev, (board_info_t *) ndev->priv);
        kfree(ndev);                /* free device structure */

        PRINTK1("clean_module() exit\n");

        return 0;
}

static struct platform_driver dm9000_driver = {
        .driver        = {
                .name    = "dm9000",
                .owner         = THIS_MODULE,
        },
        .probe   = dm9000_probe,
        .remove  = dm9000_drv_remove,
        .suspend = dm9000_drv_suspend,
        .resume  = dm9000_drv_resume,
};

static int __init
dm9000_init(void)
{
        printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);

        return platform_driver_register(&dm9000_driver);        /* search board and register */
}

static void __exit
dm9000_cleanup(void)
{
        platform_driver_unregister(&dm9000_driver);
}

module_init(dm9000_init);
module_exit(dm9000_cleanup);

MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
MODULE_DESCRIPTION("Davicom DM9000 network driver");
MODULE_LICENSE("GPL");

出0入0汤圆

发表于 2008-3-6 10:51:41 | 显示全部楼层
谢谢楼主.我刚刚准备学习avr和pc机以太网通信.
能不能开个专题,讲讲以太网开发的基本知识.

出0入0汤圆

发表于 2008-3-6 21:01:02 | 显示全部楼层
不知道DM9008AE和DM9000AE软硬件是否兼容,我只知道他们一个是10M,一个是100M,但是都是48PIN,上次费了好多时间才在源码??网站上面下载了DM9000A的。C和。H文件,好像基于WINCE?。由于最近项目紧所以先用了RTL8019,不过有空要研究DM了,听说DM9008AE价格在10元左右,做些小应用应该很有性价比。

出0入0汤圆

发表于 2010-1-9 17:02:02 | 显示全部楼层
您好,我是爱欣文科技的江练锋。
您提的DM芯片的问题,我可以帮助你解答。
关于DM9000AEP,DM9161AEP,数据手册,驱动,请联系我!
我们是DM芯片国内的总代理商,有强大的技术支持。
我的联系方式:axwjiang@163.com   15827601937

出0入0汤圆

发表于 2010-1-11 15:55:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-1-11 16:20:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-1-28 10:13:06 | 显示全部楼层
mk

出0入0汤圆

发表于 2010-2-24 17:59:30 | 显示全部楼层
DM9008AEP和DM9000AEP,都是48ping。

在硬件上,是可以兼容的,但驱动和软件上需要改动。

如果有相关技术问题,可以联系我。邮件:cooke_jiang@axwdragon.com 江练锋

出0入0汤圆

发表于 2010-2-24 20:47:11 | 显示全部楼层
好帖收藏

出0入0汤圆

发表于 2010-4-5 19:15:39 | 显示全部楼层
就ping一下而已

出0入0汤圆

发表于 2010-4-5 20:56:20 | 显示全部楼层
把uboot带的dm9000a驱动抽出来移植一下就行。这芯片的操作过程官方应用笔记写得不详细,有uboot驱动参考就好办了。另外需要利用dm9000a的两个发送缓冲区的话还得自己想想

出0入0汤圆

发表于 2010-8-11 09:53:48 | 显示全部楼层
纯mark一下

出0入0汤圆

发表于 2010-8-11 15:57:03 | 显示全部楼层
这年头牛人还真多啊!!

出0入0汤圆

发表于 2010-8-25 20:56:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-1 15:06:46 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-1 15:44:07 | 显示全部楼层
记号~~

出0入0汤圆

发表于 2010-9-6 15:07:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-22 20:26:01 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-4-15 12:14:21 | 显示全部楼层
mark dm9000

出0入0汤圆

发表于 2011-4-15 13:16:04 | 显示全部楼层
mark~

出0入0汤圆

发表于 2011-4-15 21:59:57 | 显示全部楼层
以后会用到DM9000的
记号

出0入0汤圆

发表于 2011-4-16 09:47:37 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-4-16 11:03:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-22 15:44:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-22 16:02:22 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-26 17:10:45 | 显示全部楼层
好贴,mark

出0入0汤圆

发表于 2011-5-26 17:12:45 | 显示全部楼层
好贴,mark

出0入0汤圆

发表于 2011-6-22 23:32:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-22 23:51:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-1 16:15:54 | 显示全部楼层
标记看看

出0入0汤圆

发表于 2011-9-1 17:28:55 | 显示全部楼层
好多代码,顶!

出0入0汤圆

发表于 2011-9-9 11:11:48 | 显示全部楼层
mark

出0入8汤圆

发表于 2011-9-9 11:42:15 | 显示全部楼层
记号记号~

出0入0汤圆

发表于 2011-9-12 16:18:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-28 14:50:56 | 显示全部楼层
谢楼主分享

出0入0汤圆

发表于 2011-12-6 21:21:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-7 01:52:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-7 10:31:48 | 显示全部楼层
马克

出0入0汤圆

发表于 2012-2-5 19:06:45 | 显示全部楼层
楼主好人,mark

出0入0汤圆

发表于 2012-3-28 20:29:53 | 显示全部楼层
强帖 !先顶后学

出0入0汤圆

发表于 2012-12-15 10:58:08 | 显示全部楼层
学习

出0入0汤圆

发表于 2013-4-15 23:33:37 | 显示全部楼层
好东西~正在打算玩DM9000A,打算用STM32控制~MARK一下~

出0入0汤圆

发表于 2013-8-30 09:23:20 | 显示全部楼层
你好,有幸看到您的DM9000A的文章,有些问题想请教下。。。。。

请看 http://www.amobbs.com/thread-5549018-1-1.html 这个

出0入0汤圆

发表于 2013-8-30 09:42:18 | 显示全部楼层
有问题请教,请看:请教DM9000A读写寄存器问题
http://www.amobbs.com/thread-5549018-1-1.html

出0入0汤圆

发表于 2013-9-13 15:03:17 | 显示全部楼层
zhxlx 发表于 2007-7-21 15:41
可以不用,但是有两个引脚挺有用

请问个问题,我这板子上21脚接个10K上拉,用在8BIT,但是读取0XFE寄存器的BIT7位是0,用表测管脚电位是0 不知道问题所在。。。。

出0入0汤圆

发表于 2013-9-28 19:33:40 | 显示全部楼层
好,先记下

出0入0汤圆

发表于 2013-10-8 14:25:57 | 显示全部楼层
您好  请问您  如果我将DM9000初始化成32为数据总线  那么地址总线也变成32位了吗?还是地址总线不变?

出0入0汤圆

发表于 2013-10-21 11:19:14 | 显示全部楼层
请问DM9000 MRCMD寄存器中的数据包不包括以太网帧最后的CRC校验?

出0入0汤圆

发表于 2013-11-13 07:14:28 | 显示全部楼层
研究学习用台系芯片可以,但真正做产品,推荐用micrel ksz8851snl  ,SPI 接口,线路简单,接口稳定性好。或者选用SMSC LAN9221之类的。
在稳定性及可用性方面比台系芯片强很多。并且相应的软件资源更丰富.

做出来的产品  4KV 静电干扰测试,台系芯片抗静电性能与美系芯片性能比较?
不插网线,系统加电启动完成后,再插网线,看是否能正常连接,反复插拔网线,看看哪一家芯片每次都可以正常连接 ?

工控产品选美系的绝对是节约成本,减少系统维护成本。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-18 20:36

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表