第二季-专题18-网卡搭建新通道

专题18-网卡搭建新通道

第1课-网卡基本工作原理

  1. 网络模型

(1)     OSI七层模型

OSI(Open SystemInterconnection),开放式系统互联参考模型。它把网络协议从逻辑上分为了7层。通过七个层次使不同的系统网络之间实现可靠的通讯。

 

 

(2)     Linux四层模型

OSI参考模型的过于庞大、复杂招致了许多批评。与此对照,由技术人员自己开发的TCP/IP协议栈获得了更为广泛的应用。

 

  1. 网卡硬件模型

 

(1)     硬件总体架构

 

网卡的实质就是MAC通过MII接口控制PHY的过程。

(2)     MAC

MAC主要负责数据帧的构建、数据差错检查、传送控制等。

 

(3)     PHY

PHY是物理接口收发器,属于物理层,当它收到MAC过来的数据时,它会去加上校验码,然后按照物理层的规则进行数据编码,再发送到传输介质上。接收过程则相反

 

(4)     MII接口

MII:媒体独立接口, “媒体独立”表明MAC一定情况下,任何类型的PHY设备都可以正常工作。

 

  1. DM9000工作特性

(1)     片选

(2)     对外接口

 

第2课-DM9000驱动程序设计

#include "dm9000.h"

 

#define DM_ADD (*((volatile unsigned short *)0x20000300))

#define DM_DAT (*((volatile unsigned short *)0x20000304))

 

#define GPFCON    (*(volatile unsigned *)0x56000050) //Port F control

#define EXTINT0   (*(volatile unsigned *)0x56000088) //External interrupt control register 0

#define EINTMASK  (*(volatile unsigned *)0x560000a4) //External interrupt mask

#define SRCPND     (*(volatile unsigned *)0x4a000000) //Interrupt request status

#define INTPND     (*(volatile unsigned *)0x4a000010) //Interrupt request status

#define INTMSK     (*(volatile unsigned *)0x4a000008) //Interrupt mask control

#define EINTPEND  (*(volatile unsigned *)0x560000a8) //External interrupt pending

 

#define BWSCON    (*(volatile unsigned *)0x48000000) //Bus width & wait status

#define BANKCON4  (*(volatile unsigned *)0x48000014) //BANK4 control

 

 

typedef unsigned int u32;

typedef unsigned short u16;

typedef unsigned char u8;

 

 

u8 mac_addr[6] = {9,8,7,6,5,4};

u8 buffer[1000];

 

void cs_init()

{

    BWSCON = BWSCON & (~(0x3<<16));

    BWSCON = BWSCON |(0x1<<16);

    BANKCON4 = (0x0<<13)|(0x0<<11)|(0x7<<8)|(0x1<<6)|(0x0<<4)|(0x0<<2)|(0x0<<0);

}

 

void int_init()

{

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

}

 

void dm9000_reg_write(u16 reg,u16 data)

{

    DM_ADD = reg;

    DM_DAT = data;  

}

 

u8 dm9000_reg_read(u16 reg)

{

    DM_ADD = reg;

    return DM_DAT;  

}

 

void dm9000_reset()

{

    dm9000_reg_write(DM9000_GPCR, GPCR_GPIO0_OUT);

    dm9000_reg_write(DM9000_GPR, 0);  

   

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

    dm9000_reg_write(DM9000_NCR, 0);

}

 

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 ! ");

        return ;

    } else {

        printf("dm9000 is not found ! ");

        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 strange! 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地址*/

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

        dm9000_reg_write(DM9000_PAR+i, mac_addr[i]);

   

    /*激活DM9000*/

    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_DAT = 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_DAT;

   

    /*读取包数据*/

    if(len<PTK_MAX_LEN)

    {

       for(i=0;i<len;i+=2)

       {

           tmp = DM_DAT;

           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;

}

第3课-ARP协议实现

  1. ARP协议介绍

在计算机网络中,数据发送的过程,就是一个把数据按照各层协议层层封装的过程。在这个过程中,最终要使用的协议通常是以太网协议(数据链路层协议)。

(1)     以太网通讯格式

目的MAC地址:接收者的物理地址源

MAC地址:发送者的物理地址

类型:标明高层的数据使用的协议类型

数据:高层的数据

CRC:校验码

 

(2)     ARP协议功能

在以太网络中,每台计算机的唯一身份标示是MAC地址(物理层的地址),两台计算机要进行通讯,也必须知道对方的MAC地址,但是用户通常只知道对方的IP地址,这个时候,就可以利用ARP(地址解析协议)来向局域网中的所有计算机发送ARP请求包,收到请求包且满足条件的计算机将回复ARP应答包,告知其MAC地址。所以ARP协议是一种利用IP地址或者MAC地址的协议。

(3)     ARP通讯格式

 

ARP包分为请求包和应答包,通过OP字段来区别。

  1. 编程实现ARP
原文地址:https://www.cnblogs.com/free-1122/p/11452226.html