#include <ccblkfn.h>
#include <cdefBF533.h>
#include <DM9000.h>
#include <sysreg.h>
#include <Header.h>
#include <UDP.h>
#define true 1
#define false 0
#define MAX_PACK_LEN 0x200
//typedef int bool;
//typedef int bool;
uchar clientEther[6] = {0x00, 0x5e, 0xf6, 0x34, 0xd8, 0x3d};
ulong clientIP = 0x3400a8c0;
uchar PktBuf[608];
enum DM9000_PHY_mode {
DM9000_10MHD = 0,
DM9000_100MHD = 1,
DM9000_10MFD = 4,
DM9000_100MFD = 5,
DM9000_AUTO = 8,
DM9000_1M_HPNA = 0x10
};
int media_mode = DM9000_AUTO;
#define DM9000_outb(d,r) ( *(volatile uchar *)r = d )
#define DM9000_outw(d,r) ( *(volatile ushort *)r = d )
#define DM9000_inb(r) (*(volatile uchar *)r)
#define DM9000_inw(r) (*(volatile ushort *)r)
void MemCpy(void *dest, void *src, int cnt)
{
char *s1 = dest, *s2 = src, *endptr = (char *)dest+cnt;
while(s1 < endptr)
*s1++ = *s2++;
return;
}
void RxPacketHandle(uchar *rxPktBuf, int len)
{
ETH_HEADER *et = (ETH_HEADER *)rxPktBuf;
IP_HEADER *ip = (IP_HEADER *)(rxPktBuf + 14);
ARP_HEADER *arp = (ARP_HEADER *)(rxPktBuf + 14);
ICMP_HEADER *icmp = (ICMP_HEADER *)(rxPktBuf + 34);
ushort prot;
ushort pklen;
prot = SWAP16(et->et_protlen);
switch(prot)
{
case 0x806:
MemCpy(&rxPktBuf[0], (char*)et->et_src, 6);
MemCpy(&rxPktBuf[6], (char*)clientEther, 6);
*(short *)(&rxPktBuf[12]) = SWAP16(0x806);
*(short *)(&rxPktBuf[14]) = SWAP16(0x0001);
*(short *)(&rxPktBuf[16]) = SWAP16(0x800);
rxPktBuf[18] = 0x06;
rxPktBuf[19] = 0x04;
*(short *)(&rxPktBuf[20]) = SWAP16(0x0002);
MemCpy(&(rxPktBuf[32]), &(rxPktBuf[22]), 6);
MemCpy(&(rxPktBuf[38]), &(rxPktBuf[28]), 4);
MemCpy(&(rxPktBuf[22]), clientEther, 6);
MemCpy(&(rxPktBuf[28]), &(clientIP), 4);
EthTx(rxPktBuf, 42);
break;
case 0x800:
pklen = SWAP16(ip->ip_len);
if((pklen<=20)||(pklen>MAX_PACK_LEN))
return;
pklen-=20;
icmp->icmp_op=0;
icmp->icmp_chksum=0;
icmp->icmp_chksum=~IPChksum((char *)icmp, pklen/2);
MemCpy((char *)&(ip->ip_dest), (char *)&(ip->ip_src), 4);
MemCpy((char *)&(ip->ip_src), (char *)&clientIP, 4);
ip->ip_chksum = 0;
ip->ip_ttl = 0x40;
ip->ip_chksum = ~IPChksum((char *)ip, 10);
MemCpy(&rxPktBuf[0], (char *)et->et_src, 6);
MemCpy(&rxPktBuf[6], (char *)clientEther, 6);
TxPacket(rxPktBuf, 34+pklen);
break;
default:
break;
}
return;
}
unsigned IPChksum(char *ptr, int len){
ulong xsum;
xsum = 0;
while (len-- > 0)
xsum += *((ushort *)ptr)++;
xsum = (xsum & 0xffff) + (xsum >> 16);
xsum = (xsum & 0xffff) + (xsum >> 16);
return xsum & 0xffff;
} // IPChksum.
void MemSet(void *dest, char c, int len)
{
char *s = dest;
char *limit = (char *)dest + len;
while(s<limit)*s++ = c;
}
int dm9000_probe(void)
{
int i;
ulong id_val;
for(i = 0; i < 3; i ++)
{
id_val = DM9000_ior(DM9000_VIDL);
id_val |= DM9000_ior(DM9000_VIDH) << 8;
id_val |= DM9000_ior(DM9000_PIDL) << 16;
id_val |= DM9000_ior(DM9000_PIDH) << 24;
if (id_val == DM9000_ID)
{
return 1;
}
}
return 0;
}
// Set PHY operationg mode
void set_PHY_mode(void)
{
ushort phy_reg4 = 0x01e1, phy_reg0 = 0x1000;
if (!(media_mode & DM9000_AUTO)) {
switch (media_mode) {
case DM9000_10MHD:
phy_reg4 = 0x21;
phy_reg0 = 0x0000;
break;
case DM9000_10MFD:
phy_reg4 = 0x41;
phy_reg0 = 0x1100;
break;
case DM9000_100MHD:
phy_reg4 = 0x81;
phy_reg0 = 0x2000;
break;
case DM9000_100MFD:
phy_reg4 = 0x101;
phy_reg0 = 0x3100;
break;
}
phy_write(4, phy_reg4); // Set PHY media mode
phy_write(0, phy_reg0); // Tmp
}
DM9000_iow(DM9000_GPCR, 0x01); // Let GPIO0 output
DM9000_iow(DM9000_GPR, 0x00); // Enable PHY
}
// General Purpose dm9000 reset routine
void dm9000_reset(void)
{
DM9000_iow(DM9000_NCR, NCR_RST);
delay(100000); // delay 1ms
}
// Initilize dm9000 board
bool EthInit()
{
int i,oft, lnk;
ulong id_val;
MemSet((char *)0x20100300, 0x0, 2); // Test Code
dm9000_reset();
if(dm9000_probe() == 1)
{
DM9000_iow(DM9000_GPR, 0x00); // REG_1F bit0 activate phyxcer
set_PHY_mode();
DM9000_iow(DM9000_NCR, 0x0); // only intern phy supported by now
DM9000_iow(DM9000_TCR, 0); // TX Polling clear
DM9000_iow(DM9000_SMCR, 0); // Special Mode
DM9000_iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); // clear TX status
DM9000_iow(DM9000_ISR, 0x0f); // Clear interrupt status
for (i = 0, oft = 0x10; i < 6; i++, oft++)
{
DM9000_iow(oft, clientEther[i]);
}
for (i = 0, oft = 0x16; i < 8; i++, oft++)
{
DM9000_iow(oft, 0xff);
}
DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); // RX enable
DM9000_iow(DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM); /* Enable TX/RX interrupt mask */
//while ((phy_read(1) & 0x20));
delay(100000); // delay 1ms
return 1;
}
return 0;
}
uchar DM9000_ior(int reg)
{
DM9000_outb(reg, DM9000_IO);
delay(100);
return DM9000_inb(DM9000_DATA);
}
// Write a byte to I/O port
void DM9000_iow(int reg, uchar value)
{
DM9000_outb(reg, DM9000_IO);
delay(100);
DM9000_outb(value, DM9000_DATA);
}
// Read a word from phyxcer
ushort phy_read(int reg)
{
ushort val;
// Fill the phyxcer register into REG_0C
DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
DM9000_iow(DM9000_EPCR, 0xc); // Issue phyxcer read command
delay(10000); // Wait read complete
DM9000_iow(DM9000_EPCR, 0x0); // Clear phyxcer read command
val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
// The read data keeps on REG_0D & REG_0E
//DM9000_DBG("phy_read(%d): %d\n", reg, val);
return val;
}
// Write a word to phyxcer
void phy_write(int reg, ushort value)
{
// Fill the phyxcer register into REG_0C
DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
// Fill the written data into REG_0D & REG_0E
DM9000_iow(DM9000_EPDRL, (value & 0xff));
DM9000_iow(DM9000_EPDRH, ((value >> 8) & 0xff));
DM9000_iow(DM9000_EPCR, 0xa); // Issue phyxcer write command
delay(50000); // Wait write complete
DM9000_iow(DM9000_EPCR, 0x0); // Clear phyxcer write command
}
int EthTx(uchar *packet, int length)
{
uchar *data_ptr;
ulong tmplen, i;
int tmo;
// Move data to DM9000 TX RAM
//while(DM9000_ior(DM9000_TCR) & TCR_TXREQ); //发送完成
data_ptr = (uchar *) packet;
DM9000_outb(DM9000_MWCMD, DM9000_IO);
tmplen = (length + 1) / 2;
for (i = 0; i < tmplen; i++)
{
DM9000_outw(((ushort *) data_ptr)[i], DM9000_DATA);
}
// Set TX length to DM9000
DM9000_iow(DM9000_TXPLL, length & 0xff);
DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);
// Issue TX polling command
DM9000_iow(DM9000_TCR, TCR_TXREQ);
return 1;
}
// Received a packet and pass to upper layer
bool EthRx()
{
uchar rxbyte;
uchar *rxPktBuf = PktBuf;
ushort IntStatus, RxStatus, RxLen = 0;
ulong tmplen, i;
IntStatus = DM9000_ior(DM9000_ISR); /* Got ISR */
DM9000_iow(DM9000_ISR, (uchar)IntStatus); /* Clear ISR status */
DM9000_ior(DM9000_MRCMDX); // Dummy read
rxbyte = DM9000_inb(DM9000_DATA); // Got most updated data
if (rxbyte == 0)
return 0;
// Status check: this byte must be 0 or 1
if (rxbyte > 1)
{
delay(100);
DM9000_iow(DM9000_RCR, 0x00); // Stop Device
}
// A packet ready now & Get status/length
DM9000_outb(