/*--------------------------------------------------------------------
|
/*--------------------------------------------------------------------
|
* TITLE: Plasma Ethernet MAC
|
* TITLE: Plasma Ethernet MAC
|
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
* AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
* DATE CREATED: 1/12/08
|
* DATE CREATED: 1/12/08
|
* FILENAME: ethernet.c
|
* FILENAME: ethernet.c
|
* PROJECT: Plasma CPU core
|
* PROJECT: Plasma CPU core
|
* COPYRIGHT: Software placed into the public domain by the author.
|
* COPYRIGHT: Software placed into the public domain by the author.
|
* Software 'as is' without warranty. Author liable for nothing.
|
* Software 'as is' without warranty. Author liable for nothing.
|
* DESCRIPTION:
|
* DESCRIPTION:
|
* Ethernet MAC implementation.
|
* Ethernet MAC implementation.
|
* Data is received from the Ethernet PHY four bits at a time.
|
* Data is received from the Ethernet PHY four bits at a time.
|
* After 32-bits are received they are written to 0x13ff0000 + N.
|
* After 32-bits are received they are written to 0x13ff0000 + N.
|
* The data is received LSB first for each byte which requires the
|
* The data is received LSB first for each byte which requires the
|
* nibbles to be swapped.
|
* nibbles to be swapped.
|
* Transmit data is read from 0x13fe0000. Write length/4+1 to
|
* Transmit data is read from 0x13fe0000. Write length/4+1 to
|
* ETHERNET_REG to start transfer.
|
* ETHERNET_REG to start transfer.
|
*--------------------------------------------------------------------*/
|
*--------------------------------------------------------------------*/
|
#include "plasma.h"
|
#include "plasma.h"
|
#include "rtos.h"
|
#include "rtos.h"
|
#include "tcpip.h"
|
#include "tcpip.h"
|
|
|
#define POLYNOMIAL 0x04C11DB7 //CRC bit 33 is truncated
|
#define POLYNOMIAL 0x04C11DB7 //CRC bit 33 is truncated
|
#define TOPBIT (1<<31)
|
#define TOPBIT (1<<31)
|
#define BYTE_EMPTY 0xde //Data copied into receive buffer
|
#define BYTE_EMPTY 0xde //Data copied into receive buffer
|
#define COUNT_EMPTY 16 //Count to decide there isn't data
|
#define COUNT_EMPTY 16 //Count to decide there isn't data
|
#define INDEX_MASK 0xffff //Size of receive buffer
|
#define INDEX_MASK 0xffff //Size of receive buffer
|
|
|
static unsigned char gDestMac[]={0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
static unsigned char gDestMac[]={0x5d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
static unsigned int CrcTable[256];
|
static unsigned int CrcTable[256];
|
static unsigned char reflect[256];
|
static unsigned char reflect[256];
|
static unsigned char reflectNibble[256];
|
static unsigned char reflectNibble[256];
|
static OS_Semaphore_t *SemEthernet, *SemEthTransmit;
|
static OS_Semaphore_t *SemEthernet, *SemEthTransmit;
|
static int gIndex; //byte index into 0x13ff0000 receive buffer
|
static int gIndex; //byte index into 0x13ff0000 receive buffer
|
static int gCrcChecked;
|
static int gCrcChecked;
|
|
|
|
|
//Read received data from 0x13ff0000. Data starts with 0x5d+MACaddress.
|
//Read received data from 0x13ff0000. Data starts with 0x5d+MACaddress.
|
//Data is being received while processing the data. Therefore,
|
//Data is being received while processing the data. Therefore,
|
//all errors require waiting and then re-processing the data
|
//all errors require waiting and then re-processing the data
|
//to see if the error is fixed by receiving the rest of the packet.
|
//to see if the error is fixed by receiving the rest of the packet.
|
int EthernetReceive(unsigned char *buffer, int length)
|
int EthernetReceive(unsigned char *buffer, int length)
|
{
|
{
|
int count;
|
int count;
|
int start, i, j, shift, offset, index, emptyCount;
|
int start, i, j, shift, offset, index, emptyCount;
|
int byte, byteNext;
|
int byte, byteNext;
|
unsigned long crc;
|
unsigned long crc;
|
int byteCrc;
|
int byteCrc;
|
volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
|
volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
|
int packetExpected;
|
int packetExpected;
|
|
|
//Find the start of a frame
|
//Find the start of a frame
|
packetExpected = MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_RECEIVE;
|
packetExpected = MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_RECEIVE;
|
MemoryRead(ETHERNET_REG); //clear receive interrupt
|
MemoryRead(ETHERNET_REG); //clear receive interrupt
|
emptyCount = 0;
|
emptyCount = 0;
|
|
|
//Find dest MAC address
|
//Find dest MAC address
|
for(offset = 0; offset <= INDEX_MASK; ++offset)
|
for(offset = 0; offset <= INDEX_MASK; ++offset)
|
{
|
{
|
index = (gIndex + offset) & INDEX_MASK;
|
index = (gIndex + offset) & INDEX_MASK;
|
byte = buf[index];
|
byte = buf[index];
|
if(byte == 0x5d) //bit pattern 01011101
|
if(byte == 0x5d) //bit pattern 01011101
|
{
|
{
|
for(i = 1; i < sizeof(gDestMac); ++i)
|
for(i = 1; i < sizeof(gDestMac); ++i)
|
{
|
{
|
j = (index + i) & INDEX_MASK;
|
j = (index + i) & INDEX_MASK;
|
byte = buf[j];
|
byte = buf[j];
|
if(byte != 0xff && byte != gDestMac[i])
|
if(byte != 0xff && byte != gDestMac[i])
|
break;
|
break;
|
}
|
}
|
if(i == sizeof(gDestMac))
|
if(i == sizeof(gDestMac))
|
break; //found dest MAC
|
break; //found dest MAC
|
emptyCount = 0;
|
emptyCount = 0;
|
}
|
}
|
else if(byte == BYTE_EMPTY)
|
else if(byte == BYTE_EMPTY)
|
{
|
{
|
if(packetExpected == 0 && ++emptyCount >= 4)
|
if(packetExpected == 0 && ++emptyCount >= 4)
|
return 0;
|
return 0;
|
}
|
}
|
else
|
else
|
emptyCount = 0;
|
emptyCount = 0;
|
}
|
}
|
if(offset > INDEX_MASK)
|
if(offset > INDEX_MASK)
|
return 0;
|
return 0;
|
while(gIndex != index)
|
while(gIndex != index)
|
{
|
{
|
buf[gIndex] = BYTE_EMPTY;
|
buf[gIndex] = BYTE_EMPTY;
|
gIndex = (gIndex + 1) & INDEX_MASK;
|
gIndex = (gIndex + 1) & INDEX_MASK;
|
}
|
}
|
|
|
//Found start of frame. Now find end of frame and check CRC.
|
//Found start of frame. Now find end of frame and check CRC.
|
start = gIndex;
|
start = gIndex;
|
gIndex = (gIndex + 1) & INDEX_MASK; //skip 0x5d byte
|
gIndex = (gIndex + 1) & INDEX_MASK; //skip 0x5d byte
|
crc = 0xffffffff;
|
crc = 0xffffffff;
|
for(count = 0; count < length; )
|
for(count = 0; count < length; )
|
{
|
{
|
byte = buf[gIndex];
|
byte = buf[gIndex];
|
gIndex = (gIndex + 1) & INDEX_MASK;
|
gIndex = (gIndex + 1) & INDEX_MASK;
|
|
|
byte = ((byte << 4) & 0xf0) | (byte >> 4); //swap nibbles
|
byte = ((byte << 4) & 0xf0) | (byte >> 4); //swap nibbles
|
buffer[count++] = (unsigned char)byte;
|
buffer[count++] = (unsigned char)byte;
|
byte = reflect[byte] ^ (crc >> 24); //calculate CRC32
|
byte = reflect[byte] ^ (crc >> 24); //calculate CRC32
|
crc = CrcTable[byte] ^ (crc << 8);
|
crc = CrcTable[byte] ^ (crc << 8);
|
if(count >= 40)
|
if(count >= 40)
|
{
|
{
|
//Check if CRC matches to detect end of frame
|
//Check if CRC matches to detect end of frame
|
byteCrc = reflectNibble[crc >> 24];
|
byteCrc = reflectNibble[crc >> 24];
|
byteNext = buf[gIndex];
|
byteNext = buf[gIndex];
|
if(byteCrc == byteNext)
|
if(byteCrc == byteNext)
|
{
|
{
|
for(i = 1; i < 4; ++i)
|
for(i = 1; i < 4; ++i)
|
{
|
{
|
shift = 24 - (i << 3);
|
shift = 24 - (i << 3);
|
byteCrc = reflectNibble[(crc >> shift) & 0xff];
|
byteCrc = reflectNibble[(crc >> shift) & 0xff];
|
byteNext = buf[(gIndex + i) & 0xffff];
|
byteNext = buf[(gIndex + i) & 0xffff];
|
if(byteCrc != byteNext)
|
if(byteCrc != byteNext)
|
{
|
{
|
//printf("nope %d %d 0x%x 0x%x\n", count, i, byteCrc, byteNext);
|
//printf("nope %d %d 0x%x 0x%x\n", count, i, byteCrc, byteNext);
|
i = 99;
|
i = 99;
|
}
|
}
|
}
|
}
|
if(i == 4)
|
if(i == 4)
|
{
|
{
|
//Found end of frame -- set used bytes to BYTE_EMPTY
|
//Found end of frame -- set used bytes to BYTE_EMPTY
|
//printf("Found it! %d\n", count);
|
//printf("Found it! %d\n", count);
|
gIndex = (gIndex + 4) & INDEX_MASK;
|
gIndex = (gIndex + 4) & INDEX_MASK;
|
for(i = 0; i < count+5; ++i)
|
for(i = 0; i < count+5; ++i)
|
buf[(start + i) & INDEX_MASK] = BYTE_EMPTY;
|
buf[(start + i) & INDEX_MASK] = BYTE_EMPTY;
|
while(gIndex & 3)
|
while(gIndex & 3)
|
{
|
{
|
buf[gIndex] = BYTE_EMPTY;
|
buf[gIndex] = BYTE_EMPTY;
|
gIndex = (gIndex + 1) & INDEX_MASK;
|
gIndex = (gIndex + 1) & INDEX_MASK;
|
}
|
}
|
gCrcChecked = 0;
|
gCrcChecked = 0;
|
return count;
|
return count;
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
gIndex = start;
|
gIndex = start;
|
if(++gCrcChecked > 0) //if the CPU speed is > 25MHz, change to 1
|
if(++gCrcChecked > 0) //if the CPU speed is > 25MHz, change to 1
|
{
|
{
|
buf[gIndex] = BYTE_EMPTY;
|
buf[gIndex] = BYTE_EMPTY;
|
gIndex = (gIndex + 1) & INDEX_MASK;
|
gIndex = (gIndex + 1) & INDEX_MASK;
|
}
|
}
|
return -1;
|
return -1;
|
}
|
}
|
|
|
|
|
//Copy transmit data to 0x13fe0000 with preamble and CRC32
|
//Copy transmit data to 0x13fe0000 with preamble and CRC32
|
void EthernetTransmit(unsigned char *buffer, int length)
|
void EthernetTransmit(unsigned char *buffer, int length)
|
{
|
{
|
int i, byte, shift;
|
int i, byte, shift;
|
unsigned long crc;
|
unsigned long crc;
|
volatile unsigned char *buf = (unsigned char*)ETHERNET_TRANSMIT;
|
volatile unsigned char *buf = (unsigned char*)ETHERNET_TRANSMIT;
|
|
|
OS_SemaphorePend(SemEthTransmit, OS_WAIT_FOREVER);
|
OS_SemaphorePend(SemEthTransmit, OS_WAIT_FOREVER);
|
|
|
//Wait for previous transfer to complete
|
//Wait for previous transfer to complete
|
for(i = 0; i < 10000; ++i)
|
for(i = 0; i < 10000; ++i)
|
{
|
{
|
if(MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_TRANSMIT)
|
if(MemoryRead(IRQ_STATUS) & IRQ_ETHERNET_TRANSMIT)
|
break;
|
break;
|
}
|
}
|
|
|
Led(2, 2);
|
Led(2, 2);
|
while(length < 60 || (length & 3) != 0)
|
while(length < 60 || (length & 3) != 0)
|
buffer[length++] = 0;
|
buffer[length++] = 0;
|
|
|
//Start of Ethernet frame
|
//Start of Ethernet frame
|
for(i = 0; i < 7; ++i)
|
for(i = 0; i < 7; ++i)
|
buf[i] = 0x55;
|
buf[i] = 0x55;
|
buf[7] = 0x5d;
|
buf[7] = 0x5d;
|
|
|
//Calculate CRC32
|
//Calculate CRC32
|
crc = 0xffffffff;
|
crc = 0xffffffff;
|
for(i = 0; i < length; ++i)
|
for(i = 0; i < length; ++i)
|
{
|
{
|
byte = buffer[i];
|
byte = buffer[i];
|
buf[i + 8] = (unsigned char)((byte << 4) | (byte >> 4)); //swap nibbles
|
buf[i + 8] = (unsigned char)((byte << 4) | (byte >> 4)); //swap nibbles
|
byte = reflect[byte] ^ (crc >> 24); //calculate CRC32
|
byte = reflect[byte] ^ (crc >> 24); //calculate CRC32
|
crc = CrcTable[byte] ^ (crc << 8);
|
crc = CrcTable[byte] ^ (crc << 8);
|
}
|
}
|
|
|
//Output CRC32
|
//Output CRC32
|
for(i = 0; i < 4; ++i)
|
for(i = 0; i < 4; ++i)
|
{
|
{
|
shift = 24 - (i << 3);
|
shift = 24 - (i << 3);
|
byte = reflectNibble[(crc >> shift) & 0xff];
|
byte = reflectNibble[(crc >> shift) & 0xff];
|
buf[length + 8 + i] = (unsigned char)byte;
|
buf[length + 8 + i] = (unsigned char)byte;
|
}
|
}
|
|
|
//Start transfer
|
//Start transfer
|
length = (length + 12 + 4) >> 2;
|
length = (length + 12 + 4) >> 2;
|
MemoryWrite(ETHERNET_REG, length);
|
MemoryWrite(ETHERNET_REG, length);
|
Led(2, 0);
|
Led(2, 0);
|
|
|
OS_SemaphorePost(SemEthTransmit);
|
OS_SemaphorePost(SemEthTransmit);
|
}
|
}
|
|
|
|
|
void EthernetThread(void *arg)
|
void EthernetThread(void *arg)
|
{
|
{
|
int length;
|
int length;
|
int rc;
|
int rc;
|
unsigned int ticks, ticksLast=0;
|
unsigned int ticks, ticksLast=0;
|
IPFrame *ethFrame=NULL;
|
IPFrame *ethFrame=NULL;
|
(void)arg;
|
(void)arg;
|
|
|
for(;;)
|
for(;;)
|
{
|
{
|
OS_InterruptMaskSet(IRQ_ETHERNET_RECEIVE); //enable interrupt
|
OS_InterruptMaskSet(IRQ_ETHERNET_RECEIVE); //enable interrupt
|
OS_SemaphorePend(SemEthernet, 50); //wait for interrupt
|
OS_SemaphorePend(SemEthernet, 50); //wait for interrupt
|
|
|
//Process all received packets
|
//Process all received packets
|
for(;;)
|
for(;;)
|
{
|
{
|
if(ethFrame == NULL)
|
if(ethFrame == NULL)
|
ethFrame = IPFrameGet(FRAME_COUNT_RCV);
|
ethFrame = IPFrameGet(FRAME_COUNT_RCV);
|
if(ethFrame == NULL)
|
if(ethFrame == NULL)
|
break;
|
break;
|
length = EthernetReceive(ethFrame->packet, PACKET_SIZE);
|
length = EthernetReceive(ethFrame->packet, PACKET_SIZE);
|
if(length == 0)
|
if(length == 0)
|
break; //no packet found
|
break; //no packet found
|
if(length < 0)
|
if(length < 0)
|
continue; //CRC didn't match; process next packet
|
continue; //CRC didn't match; process next packet
|
Led(1, 1);
|
Led(1, 1);
|
rc = IPProcessEthernetPacket(ethFrame, length);
|
rc = IPProcessEthernetPacket(ethFrame, length);
|
Led(1, 0);
|
Led(1, 0);
|
if(rc)
|
if(rc)
|
ethFrame = NULL;
|
ethFrame = NULL;
|
}
|
}
|
|
|
ticks = OS_ThreadTime();
|
ticks = OS_ThreadTime();
|
if(ticks - ticksLast >= 50)
|
if(ticks - ticksLast >= 50)
|
{
|
{
|
IPTick();
|
IPTick();
|
ticksLast = ticks;
|
ticksLast = ticks;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
void EthernetIsr(void *arg)
|
void EthernetIsr(void *arg)
|
{
|
{
|
(void)arg;
|
(void)arg;
|
OS_InterruptMaskClear(IRQ_ETHERNET_RECEIVE);
|
OS_InterruptMaskClear(IRQ_ETHERNET_RECEIVE);
|
OS_SemaphorePost(SemEthernet);
|
OS_SemaphorePost(SemEthernet);
|
}
|
}
|
|
|
|
|
/******************* CRC32 calculations **********************
|
/******************* CRC32 calculations **********************
|
* The CRC32 code is modified from Michale Barr's article in
|
* The CRC32 code is modified from Michael Barr's article in
|
* Embedded Systems Programming January 2000.
|
* Embedded Systems Programming January 2000.
|
* A CRC is really modulo-2 binary division. Substraction means XOR. */
|
* A CRC is really modulo-2 binary division. Substraction means XOR. */
|
static unsigned int Reflect(unsigned int value, int bits)
|
static unsigned int Reflect(unsigned int value, int bits)
|
{
|
{
|
unsigned int num=0;
|
unsigned int num=0;
|
int i;
|
int i;
|
for(i = 0; i < bits; ++i)
|
for(i = 0; i < bits; ++i)
|
{
|
{
|
num = (num << 1) | (value & 1);
|
num = (num << 1) | (value & 1);
|
value >>= 1;
|
value >>= 1;
|
}
|
}
|
return num;
|
return num;
|
}
|
}
|
|
|
|
|
static void CrcInit(void)
|
static void CrcInit(void)
|
{
|
{
|
unsigned int remainder;
|
unsigned int remainder;
|
int dividend, bit, i;
|
int dividend, bit, i;
|
|
|
//Compute the remainder of each possible dividend
|
//Compute the remainder of each possible dividend
|
for(dividend = 0; dividend < 256; ++dividend)
|
for(dividend = 0; dividend < 256; ++dividend)
|
{
|
{
|
//Start with the dividend followed by zeros
|
//Start with the dividend followed by zeros
|
remainder = dividend << 24;
|
remainder = dividend << 24;
|
//Perform modulo-2 division, a bit at a time
|
//Perform modulo-2 division, a bit at a time
|
for(bit = 8; bit > 0; --bit)
|
for(bit = 8; bit > 0; --bit)
|
{
|
{
|
//Try to divide the current data bit
|
//Try to divide the current data bit
|
if(remainder & TOPBIT)
|
if(remainder & TOPBIT)
|
remainder = (remainder << 1) ^ POLYNOMIAL;
|
remainder = (remainder << 1) ^ POLYNOMIAL;
|
else
|
else
|
remainder = remainder << 1;
|
remainder = remainder << 1;
|
}
|
}
|
CrcTable[dividend] = remainder;
|
CrcTable[dividend] = remainder;
|
}
|
}
|
for(i = 0; i < 256; ++i)
|
for(i = 0; i < 256; ++i)
|
{
|
{
|
reflect[i] = (unsigned char)Reflect(i, 8);
|
reflect[i] = (unsigned char)Reflect(i, 8);
|
reflectNibble[i] = (unsigned char)((Reflect((i >> 4) ^ 0xf, 4) << 4) |
|
reflectNibble[i] = (unsigned char)((Reflect((i >> 4) ^ 0xf, 4) << 4) |
|
Reflect(i ^ 0xf, 4));
|
Reflect(i ^ 0xf, 4));
|
}
|
}
|
}
|
}
|
|
|
|
|
static void SpinWait(int clocks)
|
static void SpinWait(int clocks)
|
{
|
{
|
int value = *(volatile int*)COUNTER_REG + clocks;
|
int value = *(volatile int*)COUNTER_REG + clocks;
|
while(*(volatile int*)COUNTER_REG - value < 0)
|
while(*(volatile int*)COUNTER_REG - value < 0)
|
;
|
;
|
}
|
}
|
|
|
|
|
//Use the Ethernet MDIO bus to configure the Ethernet PHY
|
//Use the Ethernet MDIO bus to configure the Ethernet PHY
|
static int EthernetConfigure(int index, int value)
|
static int EthernetConfigure(int index, int value)
|
{
|
{
|
unsigned int data;
|
unsigned int data;
|
int i, bit, rc=0;
|
int i, bit, rc=0;
|
|
|
//Format of SMI data: 0101 A4:A0 R4:R0 00 D15:D0
|
//Format of SMI data: 0101 A4:A0 R4:R0 00 D15:D0
|
if(value <= 0xffff)
|
if(value <= 0xffff)
|
data = 0x5f800000; //write
|
data = 0x5f800000; //write
|
else
|
else
|
data = 0x6f800000; //read
|
data = 0x6f800000; //read
|
data |= index << 18 | value;
|
data |= index << 18 | value;
|
|
|
MemoryWrite(GPIO0_SET, ETHERNET_MDIO | ETHERNET_MDIO_WE | ETHERNET_MDC);
|
MemoryWrite(GPIO0_SET, ETHERNET_MDIO | ETHERNET_MDIO_WE | ETHERNET_MDC);
|
for(i = 0; i < 34; ++i)
|
for(i = 0; i < 34; ++i)
|
{
|
{
|
MemoryWrite(GPIO0_SET, ETHERNET_MDC); //clock high
|
MemoryWrite(GPIO0_SET, ETHERNET_MDC); //clock high
|
SpinWait(10);
|
SpinWait(10);
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDC); //clock low
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDC); //clock low
|
SpinWait(10);
|
SpinWait(10);
|
}
|
}
|
for(i = 31; i >= 0; --i)
|
for(i = 31; i >= 0; --i)
|
{
|
{
|
bit = (data >> i) & 1;
|
bit = (data >> i) & 1;
|
if(bit)
|
if(bit)
|
MemoryWrite(GPIO0_SET, ETHERNET_MDIO);
|
MemoryWrite(GPIO0_SET, ETHERNET_MDIO);
|
else
|
else
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO);
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO);
|
SpinWait(10);
|
SpinWait(10);
|
MemoryWrite(GPIO0_SET, ETHERNET_MDC); //clock high
|
MemoryWrite(GPIO0_SET, ETHERNET_MDC); //clock high
|
SpinWait(10);
|
SpinWait(10);
|
rc = rc << 1 | ((MemoryRead(GPIOA_IN) >> 13) & 1);
|
rc = rc << 1 | ((MemoryRead(GPIOA_IN) >> 13) & 1);
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDC); //clock low
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDC); //clock low
|
SpinWait(10);
|
SpinWait(10);
|
if(value > 0xffff && i == 17)
|
if(value > 0xffff && i == 17)
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO_WE);
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO_WE);
|
}
|
}
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO | ETHERNET_MDIO_WE | ETHERNET_MDC);
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_MDIO | ETHERNET_MDIO_WE | ETHERNET_MDC);
|
return (rc >> 1) & 0xffff;
|
return (rc >> 1) & 0xffff;
|
}
|
}
|
|
|
|
|
void EthernetInit(unsigned char MacAddress[6])
|
void EthernetInit(unsigned char MacAddress[6])
|
{
|
{
|
int i, value;
|
int i, value;
|
volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
|
volatile unsigned char *buf = (unsigned char*)ETHERNET_RECEIVE;
|
|
|
CrcInit();
|
CrcInit();
|
if(MacAddress)
|
if(MacAddress)
|
{
|
{
|
for(i = 0; i < 6; ++i)
|
for(i = 0; i < 6; ++i)
|
{
|
{
|
value = MacAddress[i];
|
value = MacAddress[i];
|
gDestMac[i+1] = (unsigned char)((value >> 4) | (value << 4));
|
gDestMac[i+1] = (unsigned char)((value >> 4) | (value << 4));
|
}
|
}
|
}
|
}
|
|
|
EthernetConfigure(4, 0x0061); //advertise 10Base-T full duplex
|
EthernetConfigure(4, 0x0061); //advertise 10Base-T full duplex
|
EthernetConfigure(0, 0x1300); //start auto negotiation
|
EthernetConfigure(0, 0x1300); //start auto negotiation
|
#if 0
|
#if 0
|
OS_ThreadSleep(100);
|
OS_ThreadSleep(100);
|
printf("reg4=0x%x (0x61)\n", EthernetConfigure(4, 0x10000));
|
printf("reg4=0x%x (0x61)\n", EthernetConfigure(4, 0x10000));
|
printf("reg0=0x%x (0x1100)\n", EthernetConfigure(0, 0x10000));
|
printf("reg0=0x%x (0x1100)\n", EthernetConfigure(0, 0x10000));
|
printf("reg1=status=0x%x (0x7809)\n", EthernetConfigure(1, 0x10000));
|
printf("reg1=status=0x%x (0x7809)\n", EthernetConfigure(1, 0x10000));
|
printf("reg5=partner=0x%x (0x01e1)\n", EthernetConfigure(5, 0x10000));
|
printf("reg5=partner=0x%x (0x01e1)\n", EthernetConfigure(5, 0x10000));
|
#endif
|
#endif
|
|
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_ENABLE);
|
MemoryWrite(GPIO0_CLEAR, ETHERNET_ENABLE);
|
|
|
//Clear receive buffer
|
//Clear receive buffer
|
for(i = 0; i <= INDEX_MASK; ++i)
|
for(i = 0; i <= INDEX_MASK; ++i)
|
buf[i] = BYTE_EMPTY;
|
buf[i] = BYTE_EMPTY;
|
|
|
if(SemEthernet == NULL)
|
if(SemEthernet == NULL)
|
{
|
{
|
SemEthernet = OS_SemaphoreCreate("eth", 0);
|
SemEthernet = OS_SemaphoreCreate("eth", 0);
|
SemEthTransmit = OS_SemaphoreCreate("ethT", 1);
|
SemEthTransmit = OS_SemaphoreCreate("ethT", 1);
|
OS_ThreadCreate("eth", EthernetThread, NULL, 240, 0);
|
OS_ThreadCreate("eth", EthernetThread, NULL, 240, 0);
|
}
|
}
|
|
|
//Setup interrupts for receiving data
|
//Setup interrupts for receiving data
|
OS_InterruptRegister(IRQ_ETHERNET_RECEIVE, EthernetIsr);
|
OS_InterruptRegister(IRQ_ETHERNET_RECEIVE, EthernetIsr);
|
|
|
//Start receive DMA
|
//Start receive DMA
|
MemoryWrite(GPIO0_SET, ETHERNET_ENABLE);
|
MemoryWrite(GPIO0_SET, ETHERNET_ENABLE);
|
}
|
}
|
|
|