zoukankan      html  css  js  c++  java
  • 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 !
    ");
            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;  // 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;
    }
  • 相关阅读:
    第27篇-虚拟机字节码指令之操作数栈管理指令
    第26篇-虚拟机对象操作指令之putstatic
    第25篇-虚拟机对象操作指令之getfield
    第24篇-虚拟机对象操作指令之getstatic
    第23篇-虚拟机字节码指令之类型转换
    第22篇-虚拟机字节码之运算指令
    第20篇-加载与存储指令之ldc与_fast_aldc指令(2)
    第19篇-加载与存储指令(1)
    第18章-x86指令集之常用指令
    第17章-x86-64寄存器
  • 原文地址:https://www.cnblogs.com/chd-zhangbo/p/5306081.html
Copyright © 2011-2022 走看看