一、网卡工作基本原理
1.网络模型
1.1 OSI七层模型
OSI(Open System
Interconnection),开放式系统互联参考模型 。它把网络协议从逻辑上分为了7层。
通过七个层次使不同
的系统网络之间实现可靠的通讯。
1.2 Linux四层模型
OSI参考模型的过于
庞大、复杂招致了许多批评。与此对照,由技术人员自己开发的TCP/IP协议栈获得了更为广泛的应用。
2.网卡硬件结构
网卡的实质就是MAC通过MII接口控制PHY的过程
2.1 DM9000硬件结构
MAC属于数据链路层,PHY数据物理层
2.2 MAC
MAC主要负责
数据帧的构建、数据差错检
查、传送控制等。
2.3 PHY
PHY是物理接口收发器,属于物理层,当它收
到MAC过来的数据时,它会去加上校验码,然后按照物理层的规则进行数据编码,再发送到传输介质上。接收过程则相反
2.4 MII
MII:媒体独立接口, “媒体独立”表明MAC一
定情况下,任何类型的PHY设备都可以正常工作。
3.DM9000工作特性
3.1 编程接口
DM9000只有两种接口:INDEX接口(偏移接口)、数据接口(内容接口)
2440平台片选为什么是0x2开头的,DM9000连接的2440是CS4,而CS4是片选4(nGCS4),对应的基地址是0x20000000
为什么是300:打开DM9000芯片手册,300H是芯片的基地址。
为什么是4:DM9000传输数据是用SD0~SD15,cmd位来决定使用INDEX端口或者数据端口。
二、DM9000驱动程序设计
-
/*
-
* dm9000.c
-
*
-
* Created on: 2016-11-25
-
* Author: root
-
*/
-
#include "dm9000.h"
-
-
#define DM_ADD (*((volatile unsigned short *)0x20000300))
-
#define DM_DATA (*((volatile unsigned short *)0x20000304))
-
-
#define BWSCON (*(volatile unsigned long*) 0x48000000)
-
#define BANKCON4 (*(volatile unsigned long*) 0x48000014)
-
#define GPFCON (*(volatile unsigned long*) 0x56000050)
-
#define EXTINT0 (*(volatile unsigned long*) 0x56000088)
-
#define INTMSK (*(volatile unsigned long*) 0X4A000008)
-
#define EINTMASK (*(volatile unsigned long*) 0x560000A4)
-
#define SRCPND (*(volatile unsigned long*) 0X4A000000)
-
#define INTPND (*(volatile unsigned long*) 0X4A000010)
-
#define EINTPEND (*(volatile unsigned long*) 0x560000A8)
-
-
typedef unsigned char u8;
-
typedef unsigned short u16;
-
typedef unsigned int u32;
-
-
u8 mac_addr[6] = {9,8,7,6,5,4};
-
u8 buffer[1000];
-
-
void cs_init()
-
{
-
//设置bank4为16位长度
-
BWSCON = BWSCON & (~(0x3<<16));
-
BWSCON = BWSCON | (0x01<<16);
-
//设置时钟
-
BANKCON4 = (0x0<<13)|(0x0<<11)|(0x7<<8)|(0x1<<6)|(0x0<<4)|(0x0<<2)|(0x0<<0);
-
}
-
-
void int_init()
-
{
-
//配置GPF7为EINT7
-
GPFCON = GPFCON & (~(0X3)<<14);
-
GPFCON = GPFCON | ((0X2)<<14);
-
-
EXTINT0 = EXTINT0 & (~(0X7)<<28);
-
EXTINT0 = EXTINT0 | ((0X1)<<28);
-
-
INTMSK = INTMSK & (~(1<<4));
-
EINTMASK = EINTMASK & (~(0x1<<7));
-
-
SRCPND = (1<<4);
-
INTPND = (1<<4);
-
}
-
-
//dm9000寄存器读取函数
-
void dm9000_reg_write(u16 reg, u16 data)
-
{
-
DM_ADD = reg;
-
DM_DATA = data;
-
}
-
-
//dm9000寄存器写入函数
-
u8 dm9000_reg_read(u16 reg)
-
{
-
DM_ADD = reg;
-
return DM_DATA;
-
}
-
-
void dm9000_reset()
-
{
-
//设置成输出
-
dm9000_reg_write(DM9000_GPCR, GPCR_GPIO0_OUT);
-
//写0清零POWER_DOWN信号,使PHY使活动的
-
dm9000_reg_write(DM9000_GPR, 0);
-
//软件重启,MAC Internal loopback模式,重启
-
dm9000_reg_write(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
-
//重新复位(第二次)
-
dm9000_reg_write(DM9000_NCR, 0);
-
dm9000_reg_write(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
-
}
-
-
void dm9000_probe(void)
-
{
-
u32 id_val;
-
//读取供应商的值,并比较
-
id_val = dm9000_reg_read(DM9000_VIDL);
-
id_val |= dm9000_reg_read(DM9000_VIDH) << 8;
-
id_val |= dm9000_reg_read(DM9000_PIDL) << 16;
-
id_val |= dm9000_reg_read(DM9000_PIDH) << 24;
-
if (id_val == DM9000_ID) {
-
printf("dm9000 is found!\n");
-
return;
-
} else {
-
printf("dm9000 is not found!\n");
-
return;
-
}
-
}
-
-
void dm9000_init()
-
{
-
u32 i;
-
/*设置片选*/
-
cs_init();
-
-
/*中断初始化*/
-
int_init();
-
-
/*复位设备*/
-
dm9000_reset();
-
-
/*捕获dm9000*/
-
dm9000_probe();
-
-
/*MAC初始化*/
-
/* Program operating register, only internal phy supported */
-
dm9000_reg_write(DM9000_NCR, 0x0);
-
/* TX Polling clear */
-
dm9000_reg_write(DM9000_TCR, 0);
-
/* Less 3Kb, 200us */
-
dm9000_reg_write(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);
-
/* Flow Control : High/Low Water */
-
dm9000_reg_write(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
-
/* SH FIXME: This looks Flow Control */
-
dm9000_reg_write(DM9000_FCR, 0x0);
-
/* Special Mode */
-
dm9000_reg_write(DM9000_SMCR, 0);
-
/* clear TX status */
-
dm9000_reg_write(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
-
/* Clear interrupt status */
-
dm9000_reg_write(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);
-
-
/*填充MAC地址*/
-
/* fill device MAC address registers */
-
for (i = 0; i < 6; i++)
-
dm9000_reg_write(DM9000_PAR + i, mac_addr[i]);
-
/*多播地址
-
for (i = 0, oft = 0x16; i < 8; i++, oft++)
-
dm9000_reg_write(oft, 0xff);
-
*/
-
-
/*激活dm9000*/
-
/* Activate DM9000 */
-
/* RX enable */
-
dm9000_reg_write(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
-
/* Enable TX/RX interrupt mask */
-
dm9000_reg_write(DM9000_IMR, IMR_PAR);
-
}
-
-
void dm9000_tx(u8 *data,u32 length)
-
{
-
u32 i;
-
/*禁止中断*/
-
dm9000_reg_write(DM9000_IMR, 0x80);
-
/*写入发送数据的长度*/
-
dm9000_reg_write(DM9000_TXPLL, length & 0xff);
-
dm9000_reg_write(DM9000_TXPLH, (length >> 8) & 0xff);
-
/*写入待发送的数据*/
-
DM_ADD = DM9000_MWCMD;
-
for(i=0;i<length;i+=2)
-
{
-
DM_DATA = data[i] | (data[i+1]<<8);
-
}
-
/*启动发送*/
-
dm9000_reg_write(DM9000_TCR, TCR_TXREQ);
-
/*等待发送结束*/
-
while(1)
-
{
-
u8 status;
-
status = dm9000_reg_read(DM9000_TCR);
-
if((status & 0x01) == 0x00)
-
break;
-
}
-
/*清除发送状态*/
-
dm9000_reg_write(DM9000_NSR, 0x2c);
-
/*恢复中断使能*/
-
dm9000_reg_write(DM9000_IMR, 0x81);
-
}
-
-
#define PTK_MAX_LEN 1522
-
-
u32 dm9000_rx(u8 *data)
-
{
-
u8 status,len;
-
u16 tmp;
-
u32 i;
-
/*判断是否产生中断,且清除*/
-
if(dm9000_reg_read(DM9000_ISR) & 0x01)
-
dm9000_reg_write(DM9000_ISR, 0x01);
-
else
-
return 0;
-
/*空读*/
-
dm9000_reg_read(DM9000_MRCMDX);
-
/*读取状态,读取包长度*/
-
status = dm9000_reg_read(DM9000_MRCMD);
-
len = DM_DATA;
-
/*读取包的数据*/
-
if(len<PTK_MAX_LEN)
-
{
-
for(i=0;i<len;i+=2)
-
{
-
tmp = DM_DATA;
-
data[i] = tmp & 0x0ff;
-
data[i+1] = tmp>>8 & 0x0ff;
-
}
-
}
-
}
-
-
void int_issue()
-
{
-
u32 i;
-
i = dm9000_rx(buffer);
-
-
SRCPND = (1<<4);
-
INTPND = (1<<4);
-
EINTPEND |= 1<<7;
-
}
三、ARP协议实现
1.ARP协议介绍
1.1 以太网通讯
在计算机网络中,数据发送的过程,就是一个把数据按照各层
协议层层封装的过程。在这个过程中,最终要使用的协议通常是以太网协议(数据链路层协议)。
1.2 以太网包格式
目的MAC地址:接收者的物理地址
源MAC地址:发送者的物理地址
类型:标明高层的数据使用的协议类型
数据:高层的数据
CRC:校验码
1.3 ARP功能
在以太网络中,每台计算机的唯一身
份标示是MAC地址(物理层的地址),两台计算机要进行通讯,也必须知道对方的MAC地址,但是用户通常只知道对方的IP地址,这个时候,就可以利用ARP(地址解析协议)来向局域网中的所有计算机发送ARP请求包,收到请求包且满足条件的计算机将回复ARP应答包,告知其MAC地址。所以ARP协议是一种利用IP地址或者MAC地址的协议。
1.4 ARP格式
ARP包分为请求包和应答包,通过OP字段来区别。(网络层)
发送包(A->B):
以太网的头部:以太网目的地址、以太网源地址、帧类型。
硬件地址长度:就是MAC地址长度
发送端以太网地址、发送端IP地址:如果A发送给B,这里填写的应该是A的地址
目的以太网地址:应该填写的是全FFFFF,找的使所有的连接设备。
目的IP地址:应该是B的IP地址
应答包(B->A):
发送端以太网地址、发送端IP地址:
此时应该是B的地址
目的以太网地址:A的目的以太网地址(从发送包中获得)
目的IP地址:应该是A的IP地址
1.5 编写实现ARP
开发板做一台主机,PC做一台主机。
①开发板发送ARP请求包(pc),PC会往开发板回应答包。
②开发板提取PC中的MAC地址打印出来。
阅读(675) | 评论(0) | 转发(0) |