📄 f91mac.c
字号:
}
//reading from the AMD 79C874 PHY registers.
UINT16 ReadPhyReg(UINT16 phy_reg, UINT16* data)
{
// read the creg
EMAC_RGAD = phy_reg;
EMAC_MIIMGT |= RSTAT;
// wait for mii done
while(EMAC_MIISTAT & MGTBUSY);
*data = (EMAC_PRSD_L + ((UINT16)EMAC_PRSD_H<<8));
return EMACDEV_ERR_SUCCESS;
}
void EmacReset( void )
{
EMAC_IEN = 0;
// Reset all pemac blocks
EMAC_RST = SRST | HRTFN | HRRFN | HRTMC | HRRMC | HRMGT;
}
void EmacEnableIrq( void )
{
// enable the tx and rx interrupts
EMAC_IEN = RXDONEIEN | TXDONEIEN;
}
void EmacDisableIrq( void )
{
// Disable the tx and rx interrupts
EMAC_IEN = 0;
}
RZK_TIMERHANDLE_t emacTimerHdl ;
DDF_STATUS_t EthInitFunc(INT8 * ieeeaddr, void (*rxnotify)(void))
{
//
// ieeeaddr is pointer to a char array containing 6 bytes of
// EMAC Station Address
//
UINT16 i;
UINT16 temp;
INT status ;
/*
* Save the interrupt callback addresses
*/
rxnotifyfunc = rxnotify;
if( rxnotifyfunc == 0 )
{
return (ILLEGAL_CALLBACKS);
}
/*
* Ensure internal EMAC Ram is enabled. Calculate memory base address and clear it.
*/
pInternalSramBase = (INT8 *)((((UINT32)RAM_ADDR_U) << 16) + (INT8*)EMAC_RAM_OFFSET);
RAM_CTL |= ERAM_EN;
memset( (INT8*)pInternalSramBase,0, EMAC_RAM_SIZE );
EmacReset();
// CRCErrors = RuntErrors = ExcessLengthErrors = RxMissCount = TxColCount = 0;
polynomial = 0x04c11db7UL;
// setup the emac station address
for (i = 0; i < 6; i++)
{
EmacStad(i) = *(ieeeaddr+i);
}
// check by reading back station address
for (i = 0; i < 6; i++)
{
if (EmacStad(i) != *(ieeeaddr+i))
return(EMACDEV_ERR_PEMAC_NOT_FOUND);
}
// disable EMAC interrupts
EMAC_IEN = 0;
// clear interrupt status flags
EMAC_ISTAT = 0xff;
// setup buffer size
if( F91_emac_config.bufSize > BUF32 )
{
bufSize = BUF32;
}
else
{
bufSize = F91_emac_config.bufSize;
}
bufSizeShift = 8 - bufSize;
EMAC_BUFSZ = bufSize << 6;
bufMask = 0xFFFF << bufSizeShift;
bufSize = 1 << bufSizeShift;
// kprintf( "Using packet buffer size %x, Mask %x, Shift %x\n", bufSize, bufMask, bufSizeShift );
// set pause frame control timeout value
EMAC_TPTV_L = 0x14;
EMAC_TPTV_H = 0x00;
/*
* Ensure there is enough room in the Tx buffer for at least 1
* full sized ethernet frame + one extra emac packet buffer.
*/
temp = (MAXDATASIZE + HEADERSIZE + sizeof(DESC_TBL_t) + (bufSize<<1) -1) & bufMask;
if( ((F91_emac_config.txBufSize & bufMask) >= temp)
&& ((F91_emac_config.txBufSize & bufMask) <= EMAC_RAM_SIZE) )
{
temp = F91_emac_config.txBufSize & bufMask;
}
if( F91_emac_config.txBufSize != temp )
{
/*kprintf( "Adjusted F91 Tx buffer size to %u\n", temp )*/;
}
// init descriptor tables boundry pointers
tlbp = (DESC_TBL_t*)(pInternalSramBase);
bp = (DESC_TBL_t*)(pInternalSramBase + temp);
rhbp = (DESC_TBL_t*)(pInternalSramBase + EMAC_RAM_SIZE);
//kprintf( "TLBP %x, BP %x, RHBP %x\n", tlbp, bp, rhbp );
// load Emac i/o regs from pointers
EMAC_TLBP_L = ((UINT32) tlbp);
EMAC_TLBP_H = ((UINT32) tlbp) >> 8;
EMAC_BP_L = ((UINT32) bp);
EMAC_BP_H = ((UINT32) bp) >> 8;
EMAC_BP_U = ((UINT32) bp) >> 16;
EMAC_RHBP_L = ((UINT32) rhbp);
EMAC_RHBP_H = ((UINT32) rhbp) >> 8;
//TOT notes
//TRP => Transmit Read pointer, EMAC controller reads next pkt ot TX from here
//TWP => Transmit Write pointer, Apliication write next pkt ot TX to here
//RWP => received write pointer, EMAC controller write next pkt RXed here
//RRP => received read pointer, Apliication reads next pkt from here
// setup s/w pointers to ring buffers
twp = trp = tlbp;
rwp = rrp = bp;
// write rrp into i/o reg rrp
EMAC_RRP_L = ((UINT32) rrp);
EMAC_RRP_H = ((UINT32) rrp) >> 8;
// host owns first buffer
twp->stat = 0x0000;
// set polling timer for minimum timeout period
EMAC_PTMR = 1;
// disable EMAC test modes
EMAC_TEST = 0;
// enable padding, crc generation, full duplex mode
// EMAC_CFG1 = PADEN | CRCEN | FULLD;
// set the late collision byte at byte 56
EMAC_CFG2 = 56;
// set max # collisions = 15
EMAC_CFG3 = 15;
// Enable the EMAC receiver
EMAC_CFG4 = RXEN;
// Init the Address Filter
EMAC_AFR = BROADCAST;
#ifdef MULTICAST
EMAC_AFR |= QMULTICAST;
#endif
// set the max # bytes per packet to 1536
EMAC_MAXF_L = 0x00;
EMAC_MAXF_H = 0x06;
// take EMAC out of reset
EMAC_RST = 0;
// Initialize the PHY AMD 79C874
// set mmiimgt mdc clock rate
EMAC_MIIMGT = CLKDIV20;
g_MacSem = RZKCreateSemaphore((RZK_NAME_t*)"g_MacSem",1,RECV_ORDER_PRIORITY);
if(g_MacSem == NULL)
printf("\nEmac Semaphore creation error");
status = phyInit() ;
if( status != EMACDEV_ERR_SUCCESS)
{
if(status == EMACDEV_ERR_PEMAC_PHYINIT_FAILED)
{
/* Added for initializing the link if cable has been pulled out during initialization */ // Against CR No 4401
emacConnChkThdHdl = RZKCreateThreadEnhanced((RZK_NAME_t*)"EMACcon",
(RZK_PTR_t)emacConnThd,
( FNP_THREAD_ENTRY* )NULL,
512,
2,
2,
RZK_THREAD_PREEMPTION|RZK_THREAD_AUTOSTART,
0 ) ;
if( emacConnChkThdHdl == NULL )
{
return EMACDEV_ERR_RESOURCE_NOT_CREATED ;
}
}
else
{
#ifdef net_reset
wdt_init(WDT_18OUT);
#endif
// SetPDState(2,0);
printf(" EMAC Initialization error\n") ;
return EMACDEV_ERR_PEMAC_PHYINIT_FAILED ;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//clear interrupt status register
EMAC_ISTAT = 0xff;
// Check access to EMAC shared ram
// don't overwrite tx status descriptor
for (i=10; i<18; i++)
pInternalSramBase[i] = i;
for (i=10; i<18; i++)
{
if( pInternalSramBase[i] != i )
return (EMACDEV_ERR_PEMAC_SMEM_FAIL);
}
/*
* Create the Interrupt Task
*/
/* Create Interrupt thread */
emacInterruptThdHdl = RZKCreateThreadEnhanced((RZK_NAME_t*)"EMACIT",
(RZK_PTR_t)F91EmacTask,
( FNP_THREAD_ENTRY* )NULL,
EMAC_THD_STACK_SIZE,
EMAC_TASK_PRIO,
2,
RZK_THREAD_INTERRUPT|RZK_THREAD_PREEMPTION,
0 ) ;
if( emacInterruptThdHdl == NULL )
{
return EMACDEV_ERR_RESOURCE_NOT_CREATED ;
}
// setup EMAC interrupts
RZKInstallInterruptHandler( (RZK_FNP_ISR)emacisr, IV_ERX) ;
RZKInstallInterruptHandler( (RZK_FNP_ISR)emacisr, IV_ETX) ;
RZKInstallInterruptHandler( (RZK_FNP_ISR)emacisr, IV_ESYS) ;
// enable the tx and rx interrupts
EMAC_IEN = RXDONEIEN | TXDONEIEN;
// EMAC_IEN = RXDONEIEN | TXDONEIEN | RXOVRRUNIEN; // When system interrupt handler added
return (EMACDEV_ERR_PEMAC_INIT_DONE);
}
/*
* 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.
*/
INT8 MulticastHash(INT8 *ether_addr)
{
INT8 bitnum, current_octet;
INT8 i;
crc = -1;
for(i=5; i >= 0; i--) {
current_octet = *ether_addr++;
for (bitnum = 0; bitnum < 8; bitnum++, current_octet >>= 1)
crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? polynomial : 0);
}
return ((UINT32) crc) >> 26;
}
void EthMAddFunc
(
INT8 * pAddr
)
{
INT8 bitnum;
INT8 i;
INT8 data;
INT8 MAR;
RZK_STATE_t stat ;
// kprintf( "Add multicast addr %02x:%02x:%02x:%02x:%02x:%02x\n",
// pAddr[0],
// pAddr[1],
// pAddr[2],
// pAddr[3],
// pAddr[4],
// pAddr[5] );
bitnum = MulticastHash(pAddr);
stat = RZKDisablePreemption();
//not sure about TS generating proper code here. Use temporary variables.
MAR = bitnum/8;
data = EmacHtbl(MAR);
data |= (1 << (bitnum%8));
EmacHtbl(MAR) = data;
data = 0;
for(i=0; i < 8; i++)
{
data |= EmacHtbl(i);
}
//if any bit set, enable multicast
if(data)
{
EMAC_AFR |= QMULTICAST;
}
RZKRestorePreemption(stat);
}
/*
* Remove given address from the list supported in HW.
*/
void EthMDelFunc
(
INT8 * pAddr
)
{
INT8 bitnum;
INT8 i;
INT8 data;
INT8 MAR;
RZK_STATE_t stat ;
// kprintf( "Delete multicast addr %02x:%02x:%02x:%02x:%02x:%02x\n",
// pAddr[0],
// pAddr[1],
// pAddr[2],
// pAddr[3],
// pAddr[4],
// pAddr[5] );
bitnum = MulticastHash(pAddr);
stat = RZKDisablePreemption();
MAR = bitnum/8;
data = ~(1 << (bitnum%8));
data &= EmacHtbl(MAR);
EmacHtbl(MAR) = data;
data = 0;
for(i=0; i < 8; i++)
{
data |= EmacHtbl(i);
}
//if no bit is set, disable multicast
if(!data)
{
EMAC_AFR &= ~(QMULTICAST);
}
RZKRestorePreemption(stat);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -