⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dm9k_io.c

📁 ARP协议,含ARP
💻 C
字号:

#include "dm9k.h"

#define DM9K_TBUF_START             0x0000
#define DM9K_TBUF_END               0x0C00
#define DM9K_TBUF_SIZE              DM9K_TBUF_END

#define DM9K_RBUF_START             0x0C00
#define DM9K_RBUF_END               0x4000

#define DM9K_MSG_FLAG               0x01
#define DM9K_CHKSUM_SIZE            4
#define DM9K_MSGHEAD_SIZE           4

#define DM9K_RX_NORMAL              0x01
#define DM9K_RX_MIS                 0x02
#define DM9K_RX_DIS_CRC             0x10
#define DM9K_RX_DIS_LONG            0x20

#define DM9K_RX_DISALBE             0x00

#define DM9K_PHY_ENABLE             0x00
#define DM9K_PHY_DISABLE            0x01

#define DM9K_10M_MASK               0x80
#define DM9K_LINK_ACT_MASK          0x40

#define RS_RF                       0x80
#define RS_MF                       0x40
#define RS_LCS                      0x20
#define RS_RWTO                     0x10
#define RS_PLE                      0x08
#define RS_AE                       0x04
#define RS_CE                       0x02
#define RS_FOE                      0x01

#define DM9K_INC_RX_ADDR(l) { \
    start_addr += (l); \
    if (start_addr >= DM9K_RBUF_END) { \
        start_addr -= (DM9K_RBUF_END - DM9K_RBUF_START); \
    } \
    dm9k_write_word (MRRL, start_addr); \
}

struct _dm9k_msg_head {
    uc flag;
    uc status;
    us len;
};

struct _dm9k_msg_head dm9k_msg_head;

void dm9k_read_PAR(void)
{	
	uc mactemp[MAC_ADDR_LEN];
	uc i;
	for(i=0;i<MAC_ADDR_LEN;i++)
	{
		mactemp[i]=dm9k_read(PAR+i);
	}
		for(i=0;i<MAC_ADDR_LEN;i++)
	{
		put_hex(mactemp[i]);
	}

}

void dm9k_init_mac_address (void) {
    uc mac[MAC_ADDR_LEN];
    uc i;

    cfg_get_mac_addr (mac);
    for (i=0; i<6; i++) {
        dm9k_write (PAR + i, mac[i]);
    }
	
}

//本机MAC或广播MAC
bool dm9k_rx_mac (uc *mac) {
    uc i;

    if (0xFF == mac[0]) {
        for (i=0; i<MAC_ADDR_LEN; i++) {
            if (0xFF != mac[i]) {
                return false;
            }
        }
        return true;
    }

    return cfg_cmp_mac_addr (mac);
}

void dm9k_init_multicast_table (void) {
    uc i;

    for (i=0; i<DM9K_MULTICAST_BYTE_NUM; i++) {
        dm9k_write (MAR + i, 0x00);
    }

    //允许0xFFFFFF及同HASH的广播包通过
    dm9k_write (MAR + DM9K_MULTICAST_BYTE_NUM - 1, 0x80);
}

void dm9k_enable_phy (void) {
    dm9k_write (GPR, DM9K_PHY_ENABLE);
}

void dm9k_disable_phy (void) {
    dm9k_write (GPR, DM9K_PHY_DISABLE);
}

void dm9k_enable_rx_normal (void) {
    dm9k_write (RCR, DM9K_RX_NORMAL);
}

void dm9k_enable_rx_mis (void) {
    dm9k_write (RCR, DM9K_RX_NORMAL | DM9K_RX_MIS);
}

void dm9k_disable_rx (void) {
    dm9k_write (RCR, DM9K_RX_DISALBE);
}

void dm9k_set_tx_single (void) {
    dm9k_write (TCR2, 0x90); //at same time, LED MODE 1
}

void dm9k_set_tx_double (void) {
    dm9k_write (TCR2, 0x80); //at same time, LED MODE 1
}

void dm9k_enable_chksum (void) {
    dm9k_write (TCSCR, 0xFF);
}

void dm9k_disable_chksum (void) {
    dm9k_write (TCSCR, 0x00);
}

bool dm9k_tx_idle (void) {
    uc r;

    r = dm9k_read (TCR);
    if (0 != (r & 0x01)) {
        return false;
    }

    return true;
}

//DM9000控制寄存器的读写
void dm9k_write (uc addr, uc data) {
    cli ();
    DM9K_ADDR_PORT = addr;
    DM9K_DATA_PORT = data;
    sei ();
}

uc dm9k_read (uc addr) {
    uc data;

    cli ();
    DM9K_ADDR_PORT = addr;
    data = DM9K_DATA_PORT;
    sei ();

    return data;
}

void dm9k_write_word (uc addr, us data) {
    cli ();
    DM9K_ADDR_PORT = addr;
    DM9K_DATA_PORT = (uc)(data & 0x00FF);
    DM9K_ADDR_PORT = addr + 1;
    DM9K_DATA_PORT = (uc)(data >> 8);
    sei ();
}

us dm9k_read_word (uc addr) {
    us data;

    cli ();
    DM9K_ADDR_PORT = addr+1;
    data = DM9K_DATA_PORT;
    data <<= 8;

    DM9K_ADDR_PORT = addr;
    data += DM9K_DATA_PORT;
    sei ();

    return data;
}

//DM9000接口MII对PHY控制寄存器的读写
void dm9k_phy_wait_op (void) {
    uc r;

    do {
        r = dm9k_read (EPCR);
    } while (r & DM9K_PHY_OPERATING);
}

void dm9k_phy_write (uc addr, us data) {
    dm9k_write (EPAR, DM9K_PHY_AD | addr);

    dm9k_write_word (EPDRL, data);
    dm9k_write (EPCR, DM9K_PHY_WRITE);

    //等待操作结束
    dm9k_phy_wait_op ();

    dm9k_write (EPCR, DM9K_PHY_OP);
}

us dm9k_phy_read (uc addr) {
    us data;

    dm9k_write (EPAR, DM9K_PHY_AD | addr);
    dm9k_write (EPCR, DM9K_PHY_READ);

    //等待操作结束
    dm9k_phy_wait_op ();

    data = dm9k_read_word (EPDRL);
    dm9k_write (EPCR, DM9K_PHY_OP);

    return data;
}

//DM9000内存数据区读写
void dm9k_ram_read (uc *data, us len) {
    cli ();
    DM9K_ADDR_PORT = MRCMDX; //dummy read
    DM9K_DATA_PORT;
    DM9K_ADDR_PORT = MRCMD;

    len++;
    while (--len) {
        *data++ = DM9K_DATA_PORT;
    }
    sei ();
}

void dm9k_ram_write (uc *data, us len) {
    cli ();
    DM9K_ADDR_PORT = MRCMDX; //dummy read
    DM9K_DATA_PORT;
    DM9K_ADDR_PORT = MRCMD;

    len++;
    while (--len) {
        DM9K_DATA_PORT = *data++;
    }
    sei ();
}

void dm9k_msg_read (struct _mem_block *p) {
    uc *data;
    us rl;

    cli ();

    DM9K_ADDR_PORT = MRCMDX; //dummy read
    DM9K_DATA_PORT;
    DM9K_ADDR_PORT = MRCMD;

    while (NULL != p) {
        rl = p->len + 1;
        data = p->content;
        while (--rl) {
            *data++ = DM9K_DATA_PORT;
        }
        p = p->pnext;
    }

    DM9K_DATA_PORT; //pass checksum
    DM9K_DATA_PORT;
    DM9K_DATA_PORT;
    DM9K_DATA_PORT;

    sei ();
}

//>>>         addr2    addr1->>>>
//***---------.........**********
//read out one packet
bool dm9k_read_packet(struct _mem_block **ppm, us *plen) {
    struct _mem_block *p;
    us start_addr, end_addr;
	//put_char(0x67);
    *ppm = NULL;
    *plen = 0;

    //判断是否有数据可读
    start_addr = dm9k_read_word (MRRL);
    end_addr = dm9k_read_word (RWPAL);
    if (end_addr == start_addr) {
		//put_char(0x68);
        return false;
		
    }
	
    //从当前位置读出DM9K消息头
    dm9k_ram_read ((uc*)&dm9k_msg_head, sizeof (struct _dm9k_msg_head));

    if ((DM9K_MSG_FLAG != dm9k_msg_head.flag) ||
        (dm9k_msg_head.len <= DM9K_CHKSUM_SIZE)
       ){
        //标志错,长度错,丢弃所有后续消息,跟随当前位置
        dm9k_write_word (MRRL, end_addr);
        return false;
    }

    p = make_list_msg (dm9k_msg_head.len - DM9K_CHKSUM_SIZE);
    if (NULL == p) {
        //无内存资源,转到下一条消息
        DM9K_INC_RX_ADDR (DM9K_MSGHEAD_SIZE + dm9k_msg_head.len);
        return true;
    }

    *ppm = p;
    *plen = dm9k_msg_head.len - DM9K_CHKSUM_SIZE;
    dm9k_msg_read (p);
     
    return true;
}
  /*
void dm9k_fill_tx_ram_long_frame (struct _mem_block *pm, us correct) {
  union _usc addr;
    uc *data;
    uc len;

    cli ();
    DM9K_READ_WORD (TRPAL, addr);
    if (addr.n < correct) {
        addr.n += DM9K_TBUF_SIZE;
    }
    addr.n -= correct;
    DM9K_WRITE_WORD (MWRL, addr);

    len = ETH_UDP_HEAD_SIZE + 1;
    data = pm->content;

    DM9K_ADDR_PORT = MWCMD;
    while (--len) {
        DM9K_DATA_PORT = *data++;
    }
    sei ();
}

void dm9k_fill_tx_ram (struct _mem_block *pm) {
    struct _mem_block *p;
    us last_addr, len, wl;
    uc *data;
    uc n, i;

    last_addr = dm9k_read_word (TRPAL);
    if (last_addr < DM9K_CHKSUM_SIZE) {
        last_addr += DM9K_TBUF_SIZE;
    }
    last_addr -= 4;
    dm9k_write_word (MWRL, last_addr);

    len = get_msg_len (pm);
    n = (uc)(DM9K_TBUF_SIZE / len);

    cli ();
    DM9K_ADDR_PORT = MWCMD;
    for (i=0; i<n; i++) {
        for (p=pm; NULL!=p; p=p->pnext) {
            wl = p->len + 1;
            data = p->content;
            while (--wl) {
                DM9K_DATA_PORT = *data++;
            }
        }
    }
    sei ();
}
*/
void dm9k_write_packet (struct _mem_block *p) {
    us len, wl;
    uc *data;

    if (0 == p->len) {
        return;
    }
    len = 0;
	//**print_msg(0x69,p);
    cli ();

    DM9K_ADDR_PORT = MWCMD;

    while (NULL != p) {
        wl = p->len + 1;
        data = p->content;
        while (--wl) {
            DM9K_DATA_PORT = *data++;
        }

        len += p->len;
        p = p->pnext;
    }

    sei ();
	
    dm9k_write_word (TXPLL, len); //设置长度
    dm9k_write (TCR, 0x01); //启动发送
	
}

uc dm9k_get_link_speed (void) {
    uc r, rp, duplex;

    r = dm9k_read (NSR);

    if (0 == (r & DM9K_LINK_ACT_MASK)) {
        return ETH_OPEN;
    }

    rp = (uc)(dm9k_phy_read (17) >> 12);
    if (rp & 0x01) {
        duplex = ETH_HALF_DUPLEX;
    } else if (rp & 0x02) {
        duplex = ETH_FULL_DUPLEX;
    } else if (rp & 0x04) {
        duplex = ETH_HALF_DUPLEX;
    } else {
        duplex = ETH_FULL_DUPLEX;
    }
    duplex <<= 4;

    if (r & DM9K_10M_MASK) {
        return (duplex | ETH_10M);
    }

    return (duplex | ETH_100M);
}

bool dm9k_link_up (void) {
    uc r;

    r = dm9k_get_link_speed ();
    if (ETH_OPEN == (r & 0x0F)) {
        return false;
    }

    return true;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -