📄 cs8900.c
字号:
#ifdef PB_DEBUG
OrPortB( 0x10 );
#endif
pep = tx_pep_next;
RZKReleaseSemaphore(g_MacSem);
// RZKRestorePreemption(CritFlag);
nic_write( txbuffnext->length, (INT8*)&txbuffnext->dstAddr[0], p_emac_base );
status = pep->ethPktLen ; // CR6168 - MSS
}
else
{
RZKReleaseSemaphore(g_MacSem);
// RZKRestorePreemption(CritFlag);
}
}
else
{
status = PKTTOOBIG;
}
return( status );
}
/*----------------------------------------------------------------------------*/
UINT8 no_emac_rx_buffer;
void
ReceiveEthPkt
(
EMAC_FRAME_t * databuff
)
{
no_emac_rx_buffer = 0;
/*
* Rx Data Preceeded by Status (2 bytes) and Length (2 bytes)
* Note: The Status bytes must be read HiLo before reading the
* rest of the data (LoHi) since the CS8900 stores word data in the
* opposite endian of the network.
*
* Even though documentation from Cirrus suggests reading the
* packet length Hi first then Lo, doing this causes truncation of Rx data.
* Therefore we go against the spec and read data LoHi.
*/
databuff->flags = DATAPORTH0;
databuff->flags = (databuff->flags << 8) + DATAPORTL0;
databuff->length = DATAPORT0;
if( databuff->length )
{
nic_read( databuff->length, (INT8*)&databuff->dstAddr[0], p_emac_base );
}
else
{
printf( "Nothing to read!!!\n" );
}
#ifdef PERF_TRACE
kprintf( " M%x ", databuff->Length );
#endif
#if 0
if( (databuff->flags & 0x304) == 0x304 )
{
INT8 * ptr;
UINT16 i;
printf( "Rx Status Flags %x\n", databuff->flags );
printf( "Rx Length %x\n", databuff->length );
printf( "Hash = %x\n", MulticastHash( (INT8*)&databuff->dstAddr[0]) );
printf( "Rx Data: \n");
ptr = (INT8 *) &databuff->dstAddr[0];
for( i=0; i< databuff->length; i++ )
{
printf( " %x", ptr[i] & 0xFF );
}
printf( "\n" );
}
#endif
}
/*
* Internal function to calculate a multicast hash value for the receiver.
* For this device, a bit mask is used to coarsely filter possible
* multicast packets. The bit is calculated by using the CRC algorithm
* applied to the physical destination address, and then using the six
* most significant bits as the integer bit index in the eight-byte mask.
*/
static UINT32 crc_poly = 0x04C11DB7;
INT8
MulticastHash
(
INT8 * addr
)
{
INT8 HashIndex;
INT8 AddrByte;
UINT16 Byte;
UINT16 Bit;
INT32 CRC;
/*
* Compute CRC32 on the 6 byte DA
*/
CRC = 0xFFFFFFFF;
for( Byte=0; Byte<6; Byte++ )
{
AddrByte = *addr++;
for( Bit=0; Bit<8; Bit++, AddrByte>>=1 )
{
CRC = (CRC << 1) ^ ( ((CRC < 0) ^ (AddrByte & 1)) ? crc_poly : 0 );
}
}
/*
* Hash index is the bottom 6 bits of the CRC in reverse bit order.
*/
HashIndex = 0;
for( Bit=0, HashIndex=0; Bit<6; Bit++ )
{
HashIndex = (HashIndex << 1) + ((CRC >> Bit) & 1);
}
return( HashIndex );
}
/*
* Update the hash filter in HW to add another MC address.
*/
void EthMAddFunc
(
INT8 * pAddr
)
{
UINT16 data;
UINT16 bitnum;
UINT16 addr;
UINT16 saved_PktPage;
RZK_STATE_t CritFlag;
/*
kprintf( "Add %02x:%02x:%02x:%02x:%02x:%02x to MC Filter table\n",
pAddr[0],
pAddr[1],
pAddr[2],
pAddr[3],
pAddr[4],
pAddr[5] );
*/
bitnum = MulticastHash(pAddr);
// kprintf( "CRC mapping is %x\n", bitnum );
CritFlag = RZKDisablePreemption();
saved_PktPage = PKTPAGEPTR;
PKTPAGEPTR = LINECTL;
PKTPAGEDATA0 &= ~SerRxON;
addr = (LAFILTER + ((bitnum/16)*2));
bitnum = ( 1 << (bitnum%16) );
PKTPAGEPTR = addr;
data = PKTPAGEDATA0;
// kprintf( "Read %x from port %x\n", data, addr);
if( (data & bitnum) == 0 )
{
data |= bitnum;
b_mc_count++;
// kprintf( "Writing %x to %x\n", data, addr );
PKTPAGEDATA0 = data;
// kprintf( "MC count now %x\n", b_mc_count);
if( b_mc_count )
{
/*
* Enable Rx Multicast frames
*/
RxFilter |= MulticastA;
PKTPAGEPTR = RXCTL;
PKTPAGEDATA0 = (RxFilter | ADDR_RXCTL);
}
}
PKTPAGEPTR = LINECTL;
PKTPAGEDATA0 |= SerRxON;
PKTPAGEPTR = saved_PktPage;
RZKRestorePreemption(CritFlag);
}
/*
* Remove given address from the list supported in HW.
*/
void EthMDelFunc
(
INT8 * pAddr
)
{
UINT16 data;
UINT16 bitnum;
UINT16 addr;
UINT16 saved_PktPage;
RZK_STATE_t CritFlag;
/*
kprintf( "Remove %02x:%02x:%02x:%02x:%02x:%02x to MC Filter table\n",
pAddr[0],
pAddr[1],
pAddr[2],
pAddr[3],
pAddr[4],
pAddr[5] );
*/
bitnum = MulticastHash(pAddr);
// kprintf( "CRC mapping is %x\n", bitnum );
CritFlag = RZKDisablePreemption();
saved_PktPage = PKTPAGEPTR;
PKTPAGEPTR = LINECTL;
PKTPAGEDATA0 &= ~SerRxON;
addr = (LAFILTER + ((bitnum/16)*2));
bitnum = ( 1 << (bitnum%16) );
PKTPAGEPTR = addr;
data = PKTPAGEDATA0;
// kprintf( "Read %x from port %x\n", data, addr);
if( data & bitnum )
{
data &= ~bitnum;
b_mc_count--;
// kprintf( "Writing %x to %x\n", data, addr );
PKTPAGEDATA0 = data;
// kprintf( "MC count now %x\n", b_mc_count);
if( b_mc_count == 0 )
{
/*
* Disable Rx Multicast frames
*/
RxFilter &= ~MulticastA;
PKTPAGEPTR = RXCTL;
PKTPAGEDATA0 = (RxFilter | ADDR_RXCTL);
}
}
PKTPAGEPTR = LINECTL;
PKTPAGEDATA0 |= SerRxON;
PKTPAGEPTR = saved_PktPage;
RZKRestorePreemption(CritFlag);
}
UINT16 emac_save_count = 0;
void cs8900PollTask(void)
{
UINT32 my_emac_isr_count = 0;
UINTRMASK intmask ;
while( 1 )
{
RZKSuspendThread( RZKGetCurrentThread(), 100 ) ; //CR6167 - MSS
if( my_emac_isr_count == emac_isr_count )
{
/*
* CS8900A 8-bit interrupt patch:
* Simulate a call into the MAC ISR to re-enable interrupts.
*/
// emac_save_count++;
intmask = RZKDisableInterrupts();
emacisr();
RZKEnableInterrupts(intmask);
}
my_emac_isr_count = emac_isr_count;
}
}
extern UINT32 SysUpTime;
void CS8900IntTask( void )
{
UINT16 i;
ETH_PKT_t * pep;
RZK_STATE_t CritFlag;
// RZK_STATUS_t status ; // Commented during IAR Porting
UINTRMASK intmask1, intmask2 ;
intmask1 = RZKDisableInterrupts();
while( 1 )
{
i = ISQ;
while( i )
{
RZKEnableInterrupts(intmask1); //changed for debugging
emac_isr_count++;
#ifdef PERF_TRACE
kprintf( "ISQ=%x @ %x", i, SysUpTime );
#endif
switch (i & 0x3F) /* lower 6 bits give reg number causing INTR */
{
case 0x04: /* RXEVENT cause ID */
{
#if 0
if ((i & BIT_CRCError) && (CRCErrors != 0xFFFF))
CRCErrors++;
if ((i & BIT_Runt) && (RuntErrors != 0xFFFF))
RuntErrors++;
if ((i & BIT_Extradata) && (ExcessLengthErrors != 0xFFFF))
ExcessLengthErrors++;
#endif
if( i & BIT_RXOK )
{
RZKAcquireSemaphore(g_MacSem,MAX_INFINITE_SUSPEND);
// CritFlag = RZKDisablePreemption();
// b_rx_count++;
if (rxnotifyfunc != 0)
{
no_emac_rx_buffer = 1;
rxnotifyfunc();
/*
* Check if the ReceivePkt routine was called.
* If it was, no_emac_rx_buffer will be reset to 0.
* If it wasn't then the system is out of receive buffers.
*/
if(no_emac_rx_buffer)
{
volatile INT8 temp;
volatile INT8 temp2;
UINT16 Len;
temp = DATAPORTH0;
temp2 = DATAPORTL0;
Len = DATAPORT0;
// kprintf( "discarding packet, len is %u\n", Len );
if( Len )
{
nic_discard( Len, p_emac_base );
}
// b_rx_count--;
}
}
// RZKRestorePreemption(CritFlag);
RZKReleaseSemaphore(g_MacSem);
}
break;
}
case 0x08: /* TXEVENT cause ID */
{
RZKAcquireSemaphore(g_MacSem,MAX_INFINITE_SUSPEND);
// CritFlag = RZKDisablePreemption();
doing_tx = RZK_FALSE;
if( TransmitNextPkt() )
{
pep = tx_pep_next;
nic_write( txbuffnext->length, (INT8*)&txbuffnext->dstAddr[0], p_emac_base );
// RZKRestorePreemption(CritFlag);
}
#if 0
else
{
// RZKRestorePreemption(CritFlag);
RZKReleaseSemaphore(g_MacSem);
}
#endif
RZKReleaseSemaphore(g_MacSem);
break;
}
case 0x0C: /* BUF EVENT casue ID, space now available for earlier TxCMD request */
{
if (i & RDY4TX)
{
#ifdef PB_DEBUG
OrPortB( 0x04 );
#endif
pep = tx_pep_next;
nic_write( txbuffnext->length, (INT8*)&txbuffnext->dstAddr[0], p_emac_base );
#ifdef PB_DEBUG
AndPortB( 0xFB );
#endif
};
if( i & 0x400 )
{
// kprintf( "RxMiss %x\n", ++RxMissCount );
}
break;
}
case 0x10: /* RxMiss count overflow */
{
if (RxMissCount != 0xFFFF)
RxMissCount++; /* Saturating counter */
break;
}
case 0x12: /* TxCOL count overflow */
{
if (TxColCount != 0xFFFF)
TxColCount++; /* Saturating counter */
break;
}
default:
{
#if DEBUG
printf("Unexpected CS8900 Interrupt %x\n", i );
#endif
break;
}
}
/*
* Look for another interrupt
*/
intmask1 = RZKDisableInterrupts(); //changed for debugging
i = ISQ;
}
RZKEnableInterrupts(intmask1);
intmask2 = RZKDisableInterrupts();
/*
* Re-enable CS8900 interrupt generation
*/
PKTPAGEPTR = BUSCTL;
PKTPAGEDATA0 = ADDR_BUSCTL | ENABLE_IRQ;
RZKSuspendInterruptThread() ;
RZKEnableInterrupts(intmask2) ;
}
}
UINT8
IsEthernetConnected( void )
{
UINT16 Save, Data;
UINT8 Status = RZK_FALSE;
UINT8 CritFlag;
CritFlag = RZKDisablePreemption();
Save = PKTPAGEPTR;
PKTPAGEPTR = LINEST;
Data = PKTPAGEDATA0;
PKTPAGEPTR = Save;
RZKRestorePreemption( CritFlag );
/*
* Read the Line Status register to determine if the Link is OK.
*/
if( Data & CS8900_LINK_OK )
{
Status = RZK_TRUE;
}
return( Status );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -