📄 dm9k_io.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 + -