主要就是在上篇文章 中的驱动程序里增加一个read函数。
另外在open函数里的iow(0x05, DIS_LONG|DIS_CRC|RXEN); 改为iow(0x05, DIS_LONG|DIS_CRC|RXEN|PRMMC);
其中PRMMC是一个宏:#define PRMMC 1<<1
增加的read函数如下:
//读取UDP报文 static ssize_t dm9k_read(struct file* filp, char __user* buf, size_t size, loff_t* ppos) { int i; u8 flag; u16 maclen; u16 datalen; u16 data; char* macbuf=NULL; //3条不使用返回值的读命令(伪读取命令): //读F0H MRCMDX(不带有地址增量寄存器的内存数据预取读命令): //网卡开始把自身SRAM数据预取到内部数据缓冲区 //读(F4H, F5H) MRRH, MRRL(内存数据读地址寄存器) ior(0xf0); ior(0xf4); ior(0xf5); //再次读F0H MRCMDX,返回当前报文FLAG //判断: FLAG为0则结束,函数返回0(代表没有要读取的报文) flag=ior(0xf0); if( flag==1) { printk(KERN_ALERT"flag=1"); //向io_addr写入0xF2,代表寄存器MRCMD(带有地址增量寄存器的内存数据读命令) //从io_data读取一个16位数据,是Status //从io_data读取一个16位数据,是Len(实际的报文长度) //以16位模式,从io_data循环读取数据,直至读取总长度为RxLen //函数结束,返回RxLen writeb(0xf2, io_addr); readw(io_data); maclen=readw(io_data);//mac报文的数据长度 printk(KERN_ALERT"maclen=%d/n", maclen); //确保maclen的值为偶数 if( maclen%2!=0 ) { maclen+=1; } macbuf=(char*)kmalloc(maclen, GFP_KERNEL); if( macbuf==NULL ) { printk(KERN_ALERT"kmalloc error!/n"); return -1; } memset(macbuf, 0, maclen); for( i=0 ; i<maclen ; i+=2 ) { data=readw(io_data); *(unsigned short*)(macbuf+i)=data; } struct ethernet_hdr* mac=(struct ethernet_hdr*)macbuf; printk(KERN_ALERT"mac->protocol=%x/n",ntohs( mac->protocol)); if( mac->protocol!=htons(0x0800) ) { printk(KERN_ALERT"No IP protocol!/n"); kfree(macbuf); return -1; } printk(KERN_ALERT"src_mac"); for( i=0 ; i<6 ; i++ ) { printk(KERN_ALERT":%02x", mac->src_mac[i]); } printk(KERN_ALERT"/n"); struct ip_hdr* ip=(struct ip_hdr*)(macbuf+IP_START); printk(KERN_ALERT"ip->protocol=%d/n", ip->protocol); if( ip->protocol!=17 ) { printk(KERN_ALERT"No UDP protocol!/n"); kfree(macbuf); return -1; } datalen=ntohs(ip->len)-sizeof(struct ip_hdr)-sizeof(struct udp_hdr); printk(KERN_ALERT"datalen=%d/n", datalen); copy_to_user(buf, macbuf+DATA_START, datalen ); printk(KERN_ALERT"copy_to_user complete!/n"); kfree(macbuf); return datalen; } else { printk(KERN_ALERT"flag=0"); return 0; } }
ARM上的接收程序为:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <string.h> #include <sys/ioctl.h> #define DEVICE_DM9K "/dev/dm9k" int main(int argc, char *argv[]) { int fd; int ret; char buf[1024]={0}; fd=open(DEVICE_DM9K, O_RDWR); if( fd<0 ) { perror("cannot open device!"); exit(1); } memset(buf, 0, 1024); ret=read(fd, buf, 1024); if( ret<0 ) { printf("read error!/n"); } else { printf("%s/n",buf); } close(fd); return 0; }
PC上的发送程序为:
#include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <netinet/ip.h> #include <string.h> #define DESTIP "192.168.0.88" #define DESTPORT 3000 int main(int argc, char *argv[]) { int sd = socket(AF_INET,SOCK_DGRAM,0); if(-1 == sd) { perror("socket"); return sd; } struct sockaddr_in destaddr; destaddr.sin_family = AF_INET; destaddr.sin_port = htons(DESTPORT); int ret = inet_pton(AF_INET,DESTIP,&(destaddr.sin_addr.s_addr)); if(ret < 0) { perror("inet_pton"); return ret; } ret = sendto(sd,argv[1],strlen(argv[1]),0,(struct sockaddr *)&destaddr,sizeof(struct sockaddr_in)); if(ret < 0) { perror("sendto"); return ret; } return 0; }