📄 f91mac.c
字号:
/*
* Copyright 2001, Metro Link, Inc.
* All Rights Reserved
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Metro Link, Inc. and may
* contain proprietary, confidential and trade secret information of
* Metro Link, Inc. and/or its partners.
*
* The contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Metro Link, Inc.
*
*/
/*
* File : F91mac.c
*
* Description : Driver source file for ez80F91 ethernet controller
*
*
* Copyright 2004 ZiLOG Inc. ALL RIGHTS RESERVED.
*
* This file contains unpublished confidential and proprietary information
* of ZiLOG, Inc.
* NO PART OF THIS WORK MAY BE DUPLICATED, STORED, PUBLISHED OR DISCLOSED
* IN ANY FORM WITHOUT THE PRIOR WRITTEN CONSENT OF ZiLOG, INC.
* This is not a license and no use of any kind of this work is authorized
* in the absence of a written license granted by ZiLOG, Inc. in ZiLOG's
* sole discretion
*/
#include <stdio.h>
#include <string.h>
#include "ZSysgen.h"
#include "ZTypes.h"
#include "ZThread.h"
#include "ZTimer.h"
#include "ZMessageQ.h"
#include "ZInterrupt.h"
#include "ZDevice.h"
#include "ZSemaphore.h"
#include "_ez80.h"
#include "emacF91.h"
#include "EtherMgr.h"
#include "AMD79C874_phy.h"
#include "wdt.h" //gym add
#define ETH_PKT_ADD_LEN 6
extern void SetPDState(int bitindex,short int level);//gym add
extern void emacisr(void) ;
extern void* RZKMemcpy(void *, const void *, RZK_LENGTH_t) ;
extern INT phyInit(void) ;
extern UINT rxBlockTime ;
extern UINT8 EMAC_Task_Stack[] ;
extern UINT8 EMAC_TASK_PRIO ;
extern UINT EMAC_THD_STACK_SIZE ;
extern UINT16 EMAC_MQ_SIZE ;
extern UINT8 EMAC_Message_Buff[] ;
extern RZK_MESSAGEQHANDLE_t rxQueueHandle ; /* receive queue handle */
extern const F91_EMAC_CONF_t F91_emac_config ;
extern void emacConnThd(void) ;
QUEUE_REF_t txQueueReference = { (QUEUE_NODE_t*)NULL, (QUEUE_NODE_t*)NULL};
INT8 * pInternalSramBase; // 24-bit address of internal MAC SRAM
/*
* Pointers into EMAC shared memory for buffer management.
*/
DESC_TBL_t * twp; /* Transmit write pointer */
DESC_TBL_t * trp; /* Transmit read pointer */
DESC_TBL_t * rwp; /* Receive write pointer */
DESC_TBL_t * rrp; /* Receive read pointer */
DESC_TBL_t * tlbp; /* Transmit low boundary pointer */
DESC_TBL_t * bp; /* Boundary Pointer */
DESC_TBL_t * rhbp; /* Receive high boundary pointer */
UINT16 bufMask;
UINT16 bufSize;
UINT16 bufSizeShift;
UINT16 txBufsLeft; /* counts tx pkt buffers left */
UINT16 rxBufsLeft; /* counts rx pkt buffers left*/
static INT32 crc; /* For crc calculation */
static UINT32 polynomial;
/* Common to all drivers */
ETH_DEV_STRUCT_t emac[1];
void (* rxnotifyfunc)(void);
INT8 bRxCount = 0; /* Received packet count */
/* Error counters */
UINT16 crcErrors ;
UINT16 runtErrors ;
UINT16 excessLengthErrors ;
UINT16 rxMissCount ;
UINT16 txColCount ;
INT8 doingTx = RZK_FALSE; /* Transmit busy flag */
ETH_PKT_t* txPepNext;
QUEUE_NODE_t emacTxQueue;
/* These can be added to the device structure */
RZK_THREADHANDLE_t emacInterruptThdHdl ; /* emac interrupt thread handle */
RZK_THREADHANDLE_t emacConnChkThdHdl ;
//UINT8 EMAC_Conn_Stack[512] ;
RZK_SEMAPHOREHANDLE_t g_MacSem;
DDF_STATUS_t EthPktTransmit (ETH_PKT_t * pep )
{
DDF_STATUS_t status = pep->ethPktLen ;
if( pep->ethPktLen <= (MAX_DATA_SIZE + HEADER_SIZE) )
{
// status = EMACDEV_ERR_TX_WAITING;
// stat = RZKDisablePreemption();
RZKAcquireSemaphore(g_MacSem,MAX_INFINITE_SUSPEND);
PutToQueue(&txQueueReference, &pep->link) ;
TransmitNextPkt();
RZKReleaseSemaphore(g_MacSem);
// RZKRestorePreemption(stat);
}
else
{
status = EMACDEV_ERR_PKTTOOBIG ;
}
return( status );
}
void TransmitNextPkt ()
{
if( doingTx == RZK_FALSE )
{
txPepNext = (ETH_PKT_t*)GetFromQueue(&txQueueReference) ;
if( txPepNext )
{
doingTx = RZK_TRUE;
SendNow( (EMAC_FRAME_t *) &txPepNext->ethPktOrder );
}
}
}
void SendNow(EMAC_FRAME_t* databuff)
{
DESC_TBL_t * NextPkt;
UINT16 Len = databuff->length;
UINT16 WrapLen;
INT8 * pSrc;
INT8 * pDst;
/*
* Calculate the address of the emac packet buffer that will immediately
* follow the one about to transmitted. Before giving the current
* packet to the emac HW, set the ownership of the next packet buffer to
* Host Owns so the emac HW does not try to transmit the frame.
*
* Note: this implementation only sends 1 packet at a time and the the
* init routine has already verified that a max sized frame can fit in the
* emac Tx buffer. Therefore there is no need to track how many ehternet
* buffers remain.
*/
NextPkt = (DESC_TBL_t*) ((INT8*)twp + ((Len+bufSize-1+DATA_OS) & (bufMask)));
if( NextPkt >= bp )
{
NextPkt = (DESC_TBL_t*)((INT8*)tlbp + ((INT8*)NextPkt - (INT8*)bp));
}
NextPkt->stat = HOST_OWNS;
twp->np = NextPkt;
twp->pktsz = Len;
// asm("\tdi") ;
/*
* Copy packet data into the emac Tx buffer. Check to see if the data will
* wrap around the end of the transmit buffer.
*/
pSrc = (INT8*)&databuff->dstAddr[0];
pDst = (INT8*)twp+DATA_OS;
WrapLen = (INT8*)bp - pDst;
if( WrapLen >= Len )
{ // No wrap
RZKMemcpy( pDst, pSrc, Len );
}
else
{ // Wrap
RZKMemcpy( pDst, pSrc, WrapLen );
RZKMemcpy( tlbp, &pSrc[WrapLen], (Len-WrapLen) );
}
// asm("\tei") ;
/*
* Set the status to Emac owns so the HW will begin trnamitting the frame.
*/
twp->stat = EMAC_OWNS;
twp = NextPkt;
}
void EthTransmit(void)
{
DESC_TBL_t * HW_TRP;
// stat = RZKDisablePreemption();
RZKAcquireSemaphore(g_MacSem,MAX_INFINITE_SUSPEND);
EMAC_ISTAT = TXDONE;
/*
* Determine the location of HW Transmit Read Poiter
*/
HW_TRP = (DESC_TBL_t*)(pInternalSramBase + EMAC_TRP_L + ((UINT16)EMAC_TRP_H<<8));
/*
* Verify the current tx frame was sent
*/
if( trp->stat & TxAbort )
{
// Give the frame back to the MAC
trp = HW_TRP;
SendNow( (EMAC_FRAME_t *) &txPepNext->ethPktOrder );
}
else
{
trp = HW_TRP;
doingTx = RZK_FALSE;
TransmitNextPkt();
}
RZKReleaseSemaphore(g_MacSem);
// RZKRestorePreemption(stat);
}
//Receive Packet Processing
void ReceiveEthPkt(EMAC_FRAME_t * databuff)
{
UINT16 temp;
INT8* psrc;
INT8* pdst;
UINT16 txferSz;
txferSz = rrp->pktsz - CRCSIZE;
// set databuff->Flags from rx descriptor status
databuff->flags = rrp->stat;
databuff->length = txferSz;
// move the data from the rx ring buffers into system buffer
pdst = (INT8*)&databuff->dstAddr[0];
psrc = (INT8*)rrp+DATA_OS;
if (psrc+txferSz > (INT8*)rhbp)
{
temp = (INT8*)rhbp - psrc;
RZKMemcpy(pdst, psrc, temp);
RZKMemcpy(&pdst[temp], bp, txferSz-temp);
}
else
{
RZKMemcpy(pdst, psrc, txferSz);
}
}
//Receive Interrupt Processing
void EthReceive(void)
{
// struct ETH_DEV_STRUCT_t * ped=&(emac[0]);
// ETH_PKT_t * pep; // Commented during IAR Porting
// ETH_DEV_STRUCT_t *ped=&emac[0]; // Commented during IAR Porting
UINT16 temp;
// RZK_STATUS_t status ; // Commented during IAR Porting
if( rrp->np == ((DESC_TBL_t*)(pInternalSramBase + EMAC_RWP_L + ((UINT16)EMAC_RWP_H<<8))) )
{
EMAC_ISTAT = RXDONE;//rx_stat;
}
// update error/event counters
temp = rrp->stat;
if( temp & RxCrcError )
/*CRCErrors++*/;
if (rrp->pktsz < MINFRAMESIZE)
{
/*RuntErrors++;*/
temp &= ~RxOK;
}
if (rrp->pktsz > MAXFRAMESIZE)
{
/*ExcessLengthErrors++;*/
temp &= ~RxOK;
}
if( (rxnotifyfunc != 0) && (temp & RxOK) )
{
rxnotifyfunc();
}
if(temp & (UINT16)RxOVR)
{
// kprintf( "F91 emac Rx Overrun.\n" );
EMAC_ISTAT = RXOVRRUN;
}
// update rrp to next pkt
rrp = rrp->np;
// update rrp i/o reg - for h/w rx buffer counting
// must do this or we'll run outofbufs.
EmacRrp = (UINT32)rrp;
}
void F91EmacTask( void )
{
INT8 bIntStat;
UINTRMASK intmask ;
// KE_DisableMI();
while( 1 )
{
// KE_EnableMI();
bIntStat = EMAC_ISTAT & (RXDONE | RXOVRRUN | TXDONE);
while( bIntStat )
{
if( bIntStat & RXDONE )
{
EthReceive();
}
if( bIntStat & TXDONE )
{
EthTransmit();
}
bIntStat = EMAC_ISTAT & (RXDONE | RXOVRRUN | TXDONE);
}
intmask = RZKDisableInterrupts() ;
EMAC_IEN = RXDONEIEN | TXDONEIEN;
RZKSuspendInterruptThread() ;
RZKEnableInterrupts(intmask) ;
}
}
/***************************************************************************************************/
/* Accessory Functions */
//writing into the AMD 79C874 PHY registers.
UINT16 WritePhyReg(UINT16 phy_reg, UINT16 data)
{
// write the phy reg
EmacCtld= data;
EMAC_RGAD = phy_reg;
EMAC_MIIMGT |= LCTLD;
// wait for mii done
while(EMAC_MIISTAT & MGTBUSY);
return EMACDEV_ERR_SUCCESS ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -