📄 dm9000.c
字号:
UINT16 DM9000_Initializtion(UINT8 *MAC_ADDR)
{
UINT8 get_status;
int i;
/*
1. To power on the internal PHY:
iow ( 0x1F, 0x00 ); to set GPR (REG. 1FH) Bit [0]: PHYPD = 0
The PHY is powered down at default. The power-up procedure will be needed to enable it by
writing iow "0" to PHYPD (GP0 = 0). Please refer to the ch.3.4 about setting the GPIO pins.
*/
iow(DM9KS_GPR, 0x00);
delay(100);
/*
2. To do a software reset for the DM9000A initial (see chapter 4.2):
i. iow ( 0x00, 0x01 ); to set NCR (REG. 00) RST Bit [0] = 1 for a period time 10 us.
ii. iow ( 0x00, 0x00 ); to clear NCR (REG. 00) RST Bit [0] = 0, or let it auto clear.
*/
iow(DM9KS_NCR, 0x03);
delay(100);
iow(DM9KS_NCR, 0x03);
delay(100);
/*
3. Program the NCR register. Choose normal mode by setting NCR (REG. 00) LBK Bit [2:1] =
00b. The system designer can choose the network operations such as the internal MAC/ PHY
loop-back mode, forced the external PHY Full/ half duplex mode or to force collisions, and the
wake-up events enable. Please refer to the datasheet chapter 6.1 about the NCR setting.
*/
get_status = ior(DM9KS_NCR);
iow(DM9KS_NCR, 0x00);
get_status = ior(DM9KS_NCR);
iow(DM9KS_TCR, 0); /* TX Polling clear */
/*
4. To set the IMR register (REG. FFH) Bit [7] = 1 to enable the Pointer Auto Return function,
which is the memory read/ write address pointer of the RX/ TX FIFO SRAM.
*/
get_status = ior(DM9KS_IMR);
iow(DM9KS_IMR, get_status | 0x80);
/*
5. Read the EEPROM data 3 words, for the individual Ethernet node address (if necessary).
*/
iow(DM9KS_ETCR, 0); /* Early transmit disable */
iow(DM9KS_TCCR, 0x07); /* TX UDP/TCP/IP checksum enable */
iow(DM9KS_RCSR, 0x03); /* Receive checksum enable & discard checksum error
packet */
iow(0x39, 0x00); /* INT Pin Polarity Control 0: INT active high */
/*
6. Write 6-byte Ethernet node address into the Physical Address Registers (REG. 10H~15H).
*/
iow(DM9KS_PA0, 0x00);
iow(DM9KS_PA1, 0x01);
iow(DM9KS_PA2, 0x02);
iow(DM9KS_PA3, 0x03);
iow(DM9KS_PA4, 0x04);
iow(DM9KS_PA5, 0x05);
for (i = 0; i < 6; i++)
my_hwaddr[i] = MAC_ADDR[i];
/*
7. Write Hash Table 8 bytes into the Multicast Address Registers (REG. 16H ~ REG. 1DH).
*/
iow(DM9KS_MA0, 0xFF);
iow(DM9KS_MA1, 0xFF);
iow(DM9KS_MA2, 0xFF);
iow(DM9KS_MA3, 0xFF);
iow(DM9KS_MA4, 0xFF);
iow(DM9KS_MA5, 0xFF);
iow(DM9KS_MA6, 0xFF);
iow(DM9KS_MA7, 0xFF);
/*
8. To clear TX & INTR status by R/W1 the NSR REG. 01 and ISR REG. FEH registers. The Bit
[2] TX1END, Bit [3] TX2END, and Bit [5] WAKEST will be cleared automatically by reading it
or writing "1" back. Please refer to the datasheet chapter 6.2 & 6.33 about setting NSR & ISR.
*/
get_status = ior(DM9KS_NSR);
iow(DM9KS_NSR, get_status);
get_status = ior(DM9KS_ISR);
iow(DM9KS_ISR, get_status);
/*
9. To handle the NIC interrupts or polling service routines.
*/
/*
10. Program the IMR register (REG. FFH) Bit [0]/ Bit [1] to enable the RX/ TX interrupt.
*/
iow(DM9KS_IMR, 0x81); // Enable RX interrupt mask
/*
11. Program the RCR register to enable RX. The RX function is enabled by setting the RXEN
Bit [0] = 1 in the RX control register, RCR REG. 05. Please refer to the datasheet ch.6.6 RCR.
*/
iow(DM9KS_RXCR, 0x31); /* RX enable */
/*
12. NIC is being activated and ready RX/ TX now.
*/
}
UINT8 send_frame(UCHAR *outbuf, UINT16 len)
{
UINT8 TX_request, TX_status;
UINT16 *eth, i, j, k, length, length_a;
//edit by fae
#if 1
UINT16 save_mwr, calc_mwr, check_mwr;
#endif
j = 0;
k = 0;
length = len;
//edit by fae
#if 0
TX_request = ior(DM9KS_TCR);
if (TX_request &1)
{
TX_status = ior(DM9KS_NSR);
while (!(TX_status &(4 | 8)))
{
TX_status = ior(DM9KS_NSR);
j++;
if (j > 10000)
break;
}
}
#else
while (ior(DM9KS_TCR) &0x01)
{
delay(5);
}
save_mwr = (ior(0xfb) << 8) | ior(0xfa);
calc_mwr = save_mwr + length;
if (length &0x01)
calc_mwr++;
if (calc_mwr > 0x0bff)
calc_mwr -= 0x0c00;
#endif
iow(DM9KS_IMR, 0x80); /* RX interrupt enable */
eth = (UINT16*)outbuf;
DM9000_INDEX = DM9KS_MWCMD;
if (Move_Fault_Flag == 1)
{
i = 0;
length_a = 58;
while (length_a)
{
if ((length_a % 2) == 1)
length_a += 1;
length_a -= 2;
DM9000_DATA = outbuf[i] | (outbuf[i + 1] << 8);
i += 2;
}
eth = (UINT16*)dm9k_pointer; // 0
move_eth_data(eth);
eth = (UINT16*)(dm9k_pointer+192); // 768=0+768
move_eth_data(eth);
eth = (UINT16*)(dm9k_pointer+384); // 19968=768+19200
move_eth_data(eth);
eth = (UINT16*)(dm9k_pointer+576); // 20736=19968+768
move_eth_data(eth);
eth = (UINT16*)(dm9k_pointer+768); // 39936=20736+19200
move_eth_data(eth);
eth = (UINT16*)(dm9k_pointer+960); // 40704=39936+768
move_eth_data(eth);
DM9000_DATA = outbuf[1210] | (outbuf[1211] << 8);
Move_Fault_Flag = 0;
}
else
{
i = 0;
while (length)
{
if ((length % 2) == 1)
length += 1;
length -= 2;
DM9000_DATA = outbuf[i] | (outbuf[i + 1] << 8);
i += 2;
}
}
iow(DM9KS_TXPLL, len &0xff);
iow(DM9KS_TXPLH, ((len >> 8) &0xff));
iow(DM9KS_TCR, 0x01);
TX_status = ior(0x01);
//edit by fae
#if 0
TX_status = ior(0x01);
while (!(TX_status &(4 | 8)))
{
TX_status = ior(0x01);
k++;
if (k > 10000)
break;
}
#else
check_mwr = (ior(0xfb) << 8) | ior(0xfa);
if (calc_mwr != check_mwr)
{
// print err info .....
iow(0xfb, (calc_mwr >> 8) &0xff);
iow(0xfa, calc_mwr &0xff);
}
#endif
iow(DM9KS_IMR, 0x81); /* RX interrupt enable */
return 0;
}
//------------------------------------------------------------------------
// This function gets an incoming Ethernet frame from the 8900.
// There may be more than 1 waiting but just allocate memory for
// one and read one in. Use the 8900 to queue incoming packets.
//------------------------------------------------------------------------
UINT8 rcve_frame(UINT16 RxEvent)
{
int i, j;
UINT16 rxlen, mydata, RX_length;
UINT8 *inbuf, DA[6], SA[6], MAC_Addr[6], RX_ready, INT_status, RX_status;
//edit by fae
#if 1
UINT16 save_mrr, calc_mrr, check_mrr;
#endif
inbuf = ETH_Rbuf;
// INT_status = ior(DM9KS_ISR); /* got DM9000A interrupt status in ISR REG. FEH */
// if (INT_status & 0x01)
// {
ior(DM9KS_MRCMDX);
save_mrr = (ior(0xf5) << 8) | ior(0xf4);
RX_ready = ior(DM9KS_MRCMDX);
if (RX_ready ==0x1)
{
do
{
DM9000_INDEX = DM9KS_MRCMD;
RX_status = DM9000_DATA;
RX_length = DM9000_DATA;
eth_len = RX_length;
//edit by fae
#if 0
if (RX_length > PKTSIZE_ALIGN)
return 0;
#else
calc_mrr = save_mrr + 4+RX_length;
if (RX_length &0x01)
calc_mrr++;
if (calc_mrr > 0x3fff)
calc_mrr -= 0x3400;
if (RX_length > PKTSIZE_ALIGN)
{
iow(0xf5, (calc_mrr >> 8) &0xff);
iow(0xf4, calc_mrr &0xff);
return 0;
}
#endif
j = 0;
for (i = 0; i < 3; i++)
{
mydata = DM9000_DATA;
DA[j] = mydata &0xff;
DA[j + 1] = mydata >> 8;
j += 2;
}
j = 0;
for (i = 0; i < 3; i++)
{
mydata = DM9000_DATA;
SA[j] = mydata &0xff;
SA[j + 1] = mydata >> 8;
j += 2;
}
for (i = 0; i < 6; i++)
*inbuf++ = DA[i];
for (i = 0; i < 6; i++)
*inbuf++ = SA[i];
for (i = (RX_length - 12) >> 1; i > 0; i--)
{
mydata = DM9000_DATA;
*inbuf++ = mydata &0xff;
*inbuf++ = mydata >> 8;
}
//edit by fae
#if 1
check_mrr = (ior(0xf5) << 8) | ior(0xf4);
if (calc_mrr != check_mrr)
{
// print err info .....
iow(0xf5, (calc_mrr >> 8) &0xff);
iow(0xf4, calc_mrr &0xff);
}
#endif
if((RX_length - 4) > 0)
TCT_Activate_HISR(ETH_HISR);
}while(ior(DM9KS_MRCMDX)==0x1);
//return (RX_length - 4); //减去校验和4个字节
}
else if(RX_ready != 0)
{
iow(DM9KS_RXCR, 0x30); /* RX enable */
iow(DM9KS_NCR, 0x03);
delay(100);
iow(DM9KS_NCR, 0x03);
delay(100);
iow(DM9KS_RXCR, 0x31); /* RX enable */
return (0);
}
// iow(DM9KS_ISR,0x01);/* clear the PR Bit [0] latched in ISR REG. FEH */
// }
}
void eth_send(UCHAR *outbuf, UCHAR *hwaddr)
{
ETH_HEADER eth;
UCHAR i, j, k;
// eth = (ETH_HEADER *)outbuf;
// Add 14 byte Ethernet header
//memcpy(eth.dest_hwaddr,hwaddr,6);
eth.dest_hwaddr[0] = hwaddr[0];
eth.dest_hwaddr[1] = hwaddr[1];
eth.dest_hwaddr[2] = hwaddr[2];
eth.dest_hwaddr[3] = hwaddr[3];
eth.dest_hwaddr[4] = hwaddr[4];
eth.dest_hwaddr[5] = hwaddr[5];
// DA
//memcpy(eth.source_hwaddr,my_hwaddr,6);
eth.source_hwaddr[0] = my_hwaddr[0];
eth.source_hwaddr[1] = my_hwaddr[1];
eth.source_hwaddr[2] = my_hwaddr[2];
eth.source_hwaddr[3] = my_hwaddr[3];
eth.source_hwaddr[4] = my_hwaddr[4];
eth.source_hwaddr[5] = my_hwaddr[5];
// SA
eth.frame_type = ETH_ptype;
// TYPE
i = 0;
for (j = 0; j < 6; j++)
outbuf[i++] = eth.dest_hwaddr[j];
for (j = 0; j < 6; j++)
outbuf[i++] = eth.source_hwaddr[j];
outbuf[i++] = eth.frame_type >> 8;
outbuf[i++] = eth.frame_type &0xff;
// We just added 14 bytes to length
send_frame(outbuf, (ETH_len + 14));
}
//------------------------------------------------------------------------
// This is the handler for incoming Ethernet frames
// This is designed to handle standard Ethernet (RFC 893) frames
// See "TCP/IP Illustrated, Volume 1" Sect 2.2
//------------------------------------------------------------------------
void ethuser_send(UCHAR *outbuf, UINT len, UCHAR nr)
{
TCP_HEADER tcp;
IP_HEADER ip;
ULONG sum;
UINT result;
// Fill in TCP segment header
// tcp = (TCP_HEADER *)(outbuf + 34);
// ip = (IP_HEADER *)(outbuf + 14);
tcp.source_port = APPL_PORT1;
tcp.dest_port = conxn[nr].port;
tcp.sequence = conxn[nr].my_sequence;
tcp.ack_number = conxn[nr].his_sequence;
// Header is always 20 bytes long
tcp.flags = 0x5000 | FLG_ACK | FLG_PSH;
//tcp.window=1024;
tcp.window = 8192;
tcp.checksum = 0;
tcp.urgent_ptr = 0;
outbuf[34] = tcp.source_port >> 8;
outbuf[35] = tcp.source_port &0xff;
outbuf[36] = tcp.dest_port >> 8;
outbuf[37] = tcp.dest_port &0xff;
outbuf[38] = tcp.sequence >> 24;
outbuf[39] = (tcp.sequence >> 16) &0xff;
outbuf[40] = (tcp.sequence >> 8) &0xff;
outbuf[41] = tcp.sequence &0xff;
outbuf[42] = tcp.ack_number >> 24;
outbuf[43] = (tcp.ack_number >> 16) &0xff;
outbuf[44] = (tcp.ack_number >> 8) &0xff;
outbuf[45] = tcp.ack_number &0xff;
outbuf[46] = tcp.flags >> 8;
outbuf[47] = tcp.flags &0xff;
outbuf[48] = tcp.window >> 8;
outbuf[49] = tcp.window &0xff;
outbuf[50] = tcp.checksum >> 8;
outbuf[51] = tcp.checksum &0xff;
outbuf[52] = tcp.urgent_ptr >> 8;
outbuf[53] = tcp.urgent_ptr &0xff;
// Compute checksum including 12 bytes of pseudoheader
// Must pre-fill 2 items in ip header to do this
ip.dest_ipaddr = conxn[nr].ipaddr;
ip.source_ipaddr = my_ipaddr;
outbuf[26] = ip.source_ipaddr >> 24;
outbuf[27] = (ip.source_ipaddr >> 16) &0xff;
outbuf[28] = (ip.source_ipaddr >> 8) &0xff;
outbuf[29] = ip.source_ipaddr &0xff;
outbuf[30] = ip.dest_ipaddr >> 24;
outbuf[31] = (ip.dest_ipaddr >> 16) &0xff;
outbuf[32] = (ip.dest_ipaddr >> 8) &0xff;
outbuf[33] = ip.dest_ipaddr &0xff;
// Sum source_ipaddr, dest_ipaddr, and entire TCP message
sum = (ULONG)cksum(outbuf + 26, 8+len);
// Add in the rest of pseudoheader which is
// protocol id and TCP segment length
sum += (ULONG)0x0006;
sum += (ULONG)len;
// In case there was a carry, add it back around
result = (UINT)(sum + (sum >> 16));
tcp.checksum = ~result;
outbuf[50] = tcp.checksum >> 8;
outbuf[51] = tcp.checksum &0xff;
IP_protocol = 6;
IP_len = len;
ip_send(outbuf, conxn[nr].ipaddr);
// (Re)start TCP retransmit timer
conxn[nr].timer = TCP_TIMEOUT;
}
UINT user_server_1(UCHAR *inbuf, UINT header_len, UCHAR nr, UCHAR resend)
{
UCHAR *tcp_data, i;
UINT16 len;
if (nr == NO_CONNECTION)
return 0;
if (!resend)
{
tcp_data = inbuf + 34+header_len;
//memcpy(conxn[nr].query,tcp_data,20);
for (i = 0; i < 20; i++)
conxn[nr].query[i] = tcp_data[i];
conxn[nr].old_sequence = conxn[nr].my_sequence;
}
// If this is a resend, set sequence number to what it was
// the last time we sent this
else
{
tcp_data = inbuf;
conxn[nr].my_sequence = conxn[nr].old_sequence;
}
len = user_server(inbuf, header_len, nr, resend);
//conxn[nr].my_sequence+=len;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -