📄 if_5120.c
字号:
/*****************************************************************************;; (C) Unpublished Work of ADMtek Incorporated. All Rights Reserved.;; THIS WORK IS AN UNPUBLISHED WORK AND CONTAINS CONFIDENTIAL,; PROPRIETARY AND TRADESECRET INFORMATION OF ADMTEK INCORPORATED.; ACCESS TO THIS WORK IS RESTRICTED TO (I) ADMTEK EMPLOYEES WHO HAVE A; NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF THEIR ASSIGNMENTS; AND (II) ENTITIES OTHER THAN ADMTEK WHO HAVE ENTERED INTO APPROPRIATE; LICENSE AGREEMENTS. NO PART OF THIS WORK MAY BE USED, PRACTICED,; PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,; ABBRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF ADMTEK.; ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD; SUBJECT THE PERPERTRATOR TO CRIMINAL AND CIVIL LIABILITY.;;------------------------------------------------------------------------------;; Project : ADM5120; Creator : David Weng; File : if_5120.c; Abstract: ;;Modification History:; ;;*****************************************************************************/#include <ctype.h>#include <adm5120.h>#include <irqlib.h>#include <mips4kc.h>#include <cachelib.h>#include <memlib.h>#include <if_5120.h>/********************************************************************//***************************************************************************************//***************************************************************************************//***************************************************************************************//******************** Some Constants *****************/#define NUM_TX_H_DESC 0 // Number of the Transmitting descriptors of high priority#define NUM_TX_L_DESC 16 // Number of the Transmitting descriptors of low priority#define NUM_RX_H_DESC 0 // Number of the Receiving descriptors of high priority#define NUM_RX_L_DESC 32 // Number of the Receiving descriptors of low priority#define NUM_FREE_PKT 48 // Number of the Free packets#define MAX_INT_LOOP_CNT 1#define PKT_BUFFER_SIZE 1792 // Size of the packet buffer. // This number should be a multiply of CACHE_LINE_SIZE.#define PKT_BUFFER_ALIGN (ADM5120_CACHE_LINE_SIZE - 1)#define DEF_CTRL_FLAG (PKT_HARDWARE_CRC | SW_ONEBUF_PER_DESC)#define DEF_BUF1_OFFSET 0#define DEF_BUF1_LEN BUF1_LEN_FULL#define DEF_BUF2_OFFSET 0/********************** Macros *********************/#define ENQUEUE_TX_PACKET_AT_TAIL(_h, _t, _Pkt) { \ if((_Pkt) != NULL) { \ if((_t) == NULL) (_h) = (_t) = (_Pkt); \ else { \ (_t)->Next = (_Pkt); \ (_t) = (_Pkt); \ } \ (_Pkt)->Next = NULL; \ } \ }#define ENQUEUE_TX_PACKET_AT_FRONT(_h, _t, _Pkt) { \ if(_Pkt != NULL) \ { \ (_Pkt)->Next = (_h); \ if((_h) == NULL) (_h) = (_t) = (_Pkt); \ else { \ (_h) = (_Pkt); \ } \ } \ }#define DEQUEUE_TX_PACKET(_h, _t, _Pkt) { \ (_Pkt) = (_h); \ if((_h) != NULL) \ { \ if((_h) == (_t)) (_h) = (_t) = NULL; \ else (_h) = (_Pkt)->Next; \ (_Pkt)->Next = NULL; \ } \ }/*********************** Local Funcitons Prototypes ***********************/static int DrvAllocateResource(void);int ProgramMac(int vlan, UINT8 * Mac);static int ProcessRxHInt(void);static int ProcessRxLInt(void);static void ProcessTxLInt(void);void SendPacketsL(PDRV_PACKET_DESC Pkt);inline void SetPktAlign(PDRV_PACKET_DESC Pkt);static void Am5120Isr(int intLev);extern void panic(void);#ifdef DBG_OUT_SUPPORTextern void DbgUartPutStr(const char *);extern void DbgUartPutChar(char);#else#define DbgUartPutStr#define DbgUartPutChar#endifstatic PAM5120CONTEXT ifp;/*********************** Local Funcitons ******************************************//**********************************************************************************//* DrvAllocateResource: *//**********************************************************************************/static int DrvAllocateResource(void){ unsigned int i, PktIdx, TotalPktRequired; UINT8 *Buf; UINT32 memsz, membk; PDRV_PACKET_DESC Pkt; if (ifp == NULL) return -1; ifp->NumRxDescH = NUM_RX_H_DESC; ifp->NumRxDescL = NUM_RX_L_DESC; ifp->NumTxDescH = NUM_TX_H_DESC; ifp->NumTxDescL = NUM_TX_L_DESC; ifp->NumFreePkt = NUM_FREE_PKT; ifp->CtrlFlag = DEF_CTRL_FLAG; ifp->Buf1Off = DEF_BUF1_OFFSET; ifp->Buf1Len = DEF_BUF1_LEN; ifp->Buf2Off = DEF_BUF2_OFFSET; // Allocate HwTxDesc/HwRxDesc memsz = sizeof(TX_DESC_T) * (ifp->NumTxDescH + ifp->NumTxDescL) + TX_DESC_ALIGN; if ((membk = (UINT32) SharedMemAlloc(memsz, TRUE)) == 0) return -1; if (membk & (TX_DESC_ALIGN - 1)) ifp->HwTxDescH = (TX_DESC_T *) ((membk + TX_DESC_ALIGN - 1) & ~(TX_DESC_ALIGN - 1)); else ifp->HwTxDescH = (TX_DESC_T *) membk; ifp->HwTxDescL = &ifp->HwTxDescH[ifp->NumTxDescH]; memsz = sizeof(RX_DESC_T) * (ifp->NumRxDescH + ifp->NumRxDescL) + RX_DESC_ALIGN; if ((membk = (UINT32) SharedMemAlloc(memsz, TRUE)) == 0) return -1; if (membk & (RX_DESC_ALIGN - 1)) ifp->HwRxDescH = (RX_DESC_T *) ((membk + RX_DESC_ALIGN - 1) & ~(RX_DESC_ALIGN - 1)); else ifp->HwRxDescH = (RX_DESC_T *) membk; ifp->HwRxDescL = &ifp->HwRxDescH[ifp->NumRxDescH]; // Allocate DrvTxDesc/DrvRxDesc ifp->DrvTxDescH = MemAlloc(sizeof(DRV_TX_DESC) * ifp->NumTxDescH, FALSE); ifp->DrvTxDescL = MemAlloc(sizeof(DRV_TX_DESC) * ifp->NumTxDescL, FALSE); ifp->DrvRxDescH = MemAlloc(sizeof(DRV_RX_DESC) * ifp->NumRxDescH, FALSE); ifp->DrvRxDescL = MemAlloc(sizeof(DRV_RX_DESC) * ifp->NumRxDescL, FALSE); TotalPktRequired = ifp->NumRxDescH + ifp->NumRxDescL + ifp->NumFreePkt; // Allocate Packet pool ifp->PktPool = MemAlloc(sizeof(DRV_PACKET_DESC) * TotalPktRequired, FALSE); // Allocate Buffer pool ifp->BufPool = MemAlloc(PKT_BUFFER_SIZE * TotalPktRequired + PKT_BUFFER_ALIGN, FALSE); // Align to PKT_BUFFER_ALIGN boundry if ((UINT32) ifp->BufPool & PKT_BUFFER_ALIGN) ifp->BufPool = (UINT8 *) (((UINT32) ifp->BufPool + PKT_BUFFER_ALIGN) & (~PKT_BUFFER_ALIGN)); // Initialize Packet Descriptors for (Buf = ifp->BufPool, i = 0; i < TotalPktRequired; i++) { Pkt = &ifp->PktPool[i]; Pkt->Next = NULL; Pkt->Buf = Buf; SetPktAlign(Pkt); Buf += PKT_BUFFER_SIZE; } // Initialize the TxDescH for (i = 0; i < ifp->NumTxDescH; i++) { //ifp->HwTxDescH[i].buf1ctnt = 0; //ifp->HwTxDescH[i].buf2cntl = 0; //ifp->HwTxDescH[i].buflen = 0; //ifp->HwTxDescH[i].pktcntl = 0; ifp->DrvTxDescH[i].Pkt = NULL; } ifp->HwTxDescH[--i].buf1cntl |= END_OF_RING; // Initialize the TxDescL for (i = 0; i < ifp->NumTxDescL; i++) { //ifp->HwTxDescL[i].buf1ctnt = 0; //ifp->HwTxDescL[i].buf2cntl = 0; //ifp->HwTxDescL[i].buflen = 0; //ifp->HwTxDescL[i].pktcntl = 0; ifp->DrvTxDescL[i].Pkt = NULL; } ifp->HwTxDescL[--i].buf1cntl |= END_OF_RING; // Initialize the RxDescH for (i = 0, PktIdx = 0; i < ifp->NumRxDescH; i++) { Pkt = ifp->DrvRxDescH[i].Pkt = &ifp->PktPool[PktIdx++]; if (Pkt->buf2len != 0) { ifp->HwRxDescH[i].buf2cntl = BUF2_EN | ((UINT32) (Pkt->Buf + Pkt->buf2off) & BUF_ADDR_MASK); } else ifp->HwRxDescH[i].buf2cntl = 0; ifp->HwRxDescH[i].buflen = Pkt->buf1len; ifp->HwRxDescH[i].buf1cntl = OWN_BIT | ((UINT32) (Pkt->Buf + Pkt->buf1off) & BUF_ADDR_MASK); } ifp->HwRxDescH[--i].buf1cntl |= END_OF_RING; // Initialize the RxDescL for (i = 0; i < ifp->NumRxDescL; i++) { Pkt = ifp->DrvRxDescL[i].Pkt = &ifp->PktPool[PktIdx++]; if (Pkt->buf2len != 0) { ifp->HwRxDescL[i].buf2cntl = BUF2_EN | ((UINT32) (Pkt->Buf + Pkt->buf2off) & BUF_ADDR_MASK); } else ifp->HwRxDescL[i].buf2cntl = 0; ifp->HwRxDescL[i].buflen = Pkt->buf1len; ifp->HwRxDescL[i].buf1cntl = OWN_BIT | ((UINT32) (Pkt->Buf + Pkt->buf1off) & BUF_ADDR_MASK); } ifp->HwRxDescL[--i].buf1cntl |= END_OF_RING; // Initialize FreePktList ifp->FreePktList = &ifp->PktPool[PktIdx]; for (; PktIdx < TotalPktRequired - 1; PktIdx++) { ifp->PktPool[PktIdx].Next = &ifp->PktPool[PktIdx + 1]; } ifp->FreePktCnt = ifp->NumFreePkt; // Initialize Rx/Tx Indices ifp->RxIdxH = ifp->RxIdxL = 0; ifp->TxIdxH_Head = ifp->TxIdxH_Tail = ifp->TxIdxL_Head = ifp->TxIdxL_Tail = 0; // Initialize the Tx queues ifp->TxH_QueueHead = ifp->TxH_QueueTail = ifp->TxL_QueueHead = ifp->TxL_QueueTail = NULL; return 0;}/**********************************************************************************//* ProgramMac: *//**********************************************************************************/int ProgramMac(int vlan, UINT8 * Mac){ UINT32 Reg0, Reg1; if (vlan < 0 || vlan > 6) return -1; Reg0 = (((UINT32) Mac[1] << 24) + ((UINT32) Mac[0] << 16)) | (vlan << SW_MAC_VLANID_SHIFT) | SW_MAC_AGE_VALID | SW_MAC_WRITE | SW_MAC_VLANID_EN; Reg1 = ((UINT32) Mac[5] << 24) + ((UINT32) Mac[4] << 16) + ((UINT32) Mac[3] << 8) + Mac[2]; ADM5120_SW_REG(MAC_wt1_REG) = Reg1; ADM5120_SW_REG(MAC_wt0_REG) = Reg0; while (!(ADM5120_SW_REG(MAC_wt0_REG) & SW_MAC_WRITE_DONE)); return 0;}/**********************************************************************************//* ProcessRxHInt: *//**********************************************************************************/static int ProcessRxHInt(void){ buart_print("\n\rNot support High priority receive and send!!"); return FALSE;}/**********************************************************************************//* ProcessRxLInt: *//**********************************************************************************/static int ProcessRxLInt(void){ UINT32 LoopCnt = 0, idx, RxStatus; PDRV_PACKET_DESC Pkt, FreePkt; RX_DESC_T *RxDesc; PORT_STAT *pstat; idx = ifp->RxIdxL; RxDesc = &ifp->HwRxDescL[idx]; while (!(RxDesc->buf1cntl & OWN_BIT)) { if (ifp->FreePktList == NULL) { ifp->RxIdxL = idx; ifp->RxL_PktCnt += LoopCnt; return TRUE; } // Store the received packet Pkt = ifp->DrvRxDescL[idx].Pkt; if ((RxStatus = RxDesc->status) == 0) { // Reuse the Pkt buffer RxDesc->status = 0; RxDesc->buf1cntl = RxDesc->buf1cntl | OWN_BIT; if (++idx >= ifp->NumRxDescL) idx = 0; RxDesc = &ifp->HwRxDescL[idx]; continue; } Pkt->SrcPort = (RxStatus & SRC_PORT_MASK) >> SRC_PORT_SHIFT; Pkt->PktLen = ((RxStatus & PKT_LEN_MASK) >> PKT_LEN_SHIFT) - ETH_CRC_LEN; Pkt->flag = RxStatus & RX_PKT_FLAG_MASK; // Get another free packet for the receive descriptor FreePkt = ifp->DrvRxDescL[idx].Pkt = ifp->FreePktList; ifp->FreePktList = FreePkt->Next; ifp->FreePktCnt--; FreePkt->Next = NULL; // Set the descriptor and release it to switch RxDesc->status = 0; if (FreePkt->buf2len != 0) { RxDesc->buf2cntl = BUF2_EN | (((UINT32) FreePkt->Buf + FreePkt->buf2off) & BUF_ADDR_MASK); } else RxDesc->buf2cntl = 0; RxDesc->buflen = FreePkt->buf1len; RxDesc->buf1cntl = (RxDesc->buf1cntl & END_OF_RING) | OWN_BIT | (((UINT32) FreePkt->Buf + FreePkt->buf1off) & BUF_ADDR_MASK); if (Pkt->PktLen <= Pkt->buf1len) { dcache_invalidate_block(Pkt->Buf + Pkt->buf1off, Pkt->PktLen); } else { dcache_invalidate_block(Pkt->Buf + Pkt->buf1off, Pkt->buf1len); dcache_invalidate_block(Pkt->Buf + Pkt->buf2off, Pkt->PktLen - Pkt->buf1len); } // Collect statistic information pstat = &ifp->portstat[Pkt->SrcPort]; if (Pkt->flag & RX_FRAME_BC) { ifp->RxL_BCCnt++; ++pstat->RxBCPkt; } else if (Pkt->flag & RX_FRAME_MC) { ifp->RxL_MCCnt++; ++pstat->RxMCPkt; } else { ifp->RxL_UCCnt++; ++pstat->RxUCPkt; } pstat->RxPktCnt++; pstat->RxBytes += Pkt->PktLen; IndicateRxPacketL(Pkt); if (++idx >= ifp->NumRxDescL) idx = 0; if (++LoopCnt > ifp->NumRxDescL) break; RxDesc = &ifp->HwRxDescL[idx]; } ifp->RxIdxL = idx; ifp->RxL_PktCnt += LoopCnt; return FALSE;}/**********************************************************************************//* ProcessTxLInt: *//**********************************************************************************/static void ProcessTxLInt(void){ UINT32 LoopCnt = 0, idx; PDRV_PACKET_DESC Pkt; idx = ifp->TxIdxL_Tail; while (!(ifp->HwTxDescL[idx].buf1cntl & OWN_BIT) && (idx != ifp->TxIdxL_Head)) { Pkt = ifp->DrvTxDescL[idx].Pkt; ifp->DrvTxDescL[idx].Pkt = NULL; // Return the Packet to the Free Packet List SetPktAlign(Pkt); Pkt->Next = ifp->FreePktList;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -