DM9000网卡的基本工作原理

时间:2021-12-17 15:09:27

DM9000网卡的基本工作原理

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

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

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

 

DM9000网卡部分函数实现:

/*
//实验步骤
//初始化dm900
//数据包发送
//数据包接收    

*/

#include "dm9000.h"
#include "arp.h"

#define DM_ADD (*((volatile unsigned short *)0x18000000))
#define DM_DAT (*((volatile unsigned short *)0x18000004))

/*Register*/
#define MEM_SYS_CFG    (*(volatile unsigned *)0x7E00F120)

#define SROM_BW        (*(volatile unsigned *)0x70000000)
#define SROM_BC1    (*(volatile unsigned *)0x70000008)

#define GPNCON        (*(volatile unsigned *)0x7F008830) /* 中断相关寄存器 */
#define EINT0CON0    (*(volatile unsigned *)0x7F008900) 
#define EINT0MASK    (*(volatile unsigned *)0x7F008920)
#define EINT0PEND    (*(volatile unsigned *)0x7F008924)
#define VIC0INTENABLE    (*(volatile unsigned *)0x71200010)
#define EINT7_VECTADDR    (*(volatile unsigned *)0x71200104)
#define VIC0ADDRESS    *((volatile unsigned int *)0x71200f00)   
#define VIC1ADDRESS    *((volatile unsigned int *)0x71300f00)


u8 *buffer = &arpbuf;

u8 host_mac_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
u8 mac_addr[6] = {9,8,7,6,5,4};
u8 ip_addr[4] = {192,168,1,113};
u8 host_ip_addr[4] = {192,168,1,101};
u16 packet_len;


void cs_init()
{
//    MEM_SYS_CFG
    SROM_BW &= (~(1<<4));                                //设置位宽度
    SROM_BW |= (1<<4);
    SROM_BC1 = (0x0<<28)|(0x0<<24)|(0x7<<16)|(0x0<<12)|(0x0<<8)|(0x0<<4)|(0x0<<0);    //设置时序    参考uboot  ok6410的网卡片选位于bank1                                                                                                                
}

void int_init()                                                  //中断初始化
{
    GPNCON &= (~(0x3<<14));
    GPNCON |= (0x2<<14);

//    EINT0PEND &= (~(0x1<<7));
//    EINT0PEND |= (0x1<<7);
}

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 !\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 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;  // MWCMD是DM9000内部SRAM的DMA指针,根据处理器模式,写后自动增加
   
    for(i=0;i<length;i+=2)
    {
        DM_DAT = data[i] | (data[i+1]<<8);   //低8  高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);
    
//    printf("dm9000_tx");
}

#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;
        }
    }
    
    return len;
}