📄 if_5120.c
字号:
ifp->FreePktList = Pkt; ifp->FreePktCnt++; if (++idx == ifp->NumTxDescL) idx = 0; if (++LoopCnt > ifp->NumTxDescL) break; } ifp->TxIdxL_Tail = idx; ifp->TxL_PktCnt += LoopCnt; // Try to send the packets in the transmitting queue. if (ifp->TxL_QueueHead != NULL) SendPacketsL(NULL);}/**********************************************************************************//* SendPacketsL: *//* Send a low priority packet and try to transmit all the packet in the low *//* priority transmitting queue. *//**********************************************************************************/void SendPacketsL(PDRV_PACKET_DESC Pkt){ UINT32 Idx, IdxNext, reg; UINT32 TxCnt = 0; TX_DESC_T *TxDesc; UINT8 *buf; char str[] = "XXXXXXXXXXXX"; char protocol[] = "XXXX"; if (ifp->TxL_QueueHead != NULL) //The txL Queue has already some packet, send them first.. { ENQUEUE_TX_PACKET_AT_TAIL(ifp->TxL_QueueHead, ifp->TxL_QueueTail, Pkt); DEQUEUE_TX_PACKET(ifp->TxL_QueueHead, ifp->TxL_QueueTail, Pkt); } Idx = IdxNext = ifp->TxIdxL_Head; // try to transmit queued packets. while (Pkt != NULL) { // Check if the Tx queue is full. There is always one descriptor kept empty for queue full detection. if ((++IdxNext) >= ifp->NumTxDescL) IdxNext = 0; if (IdxNext == ifp->TxIdxL_Tail) { ifp->TxL_FullCnt++; break; } TxDesc = &ifp->HwTxDescL[Idx]; // If there is any free Tx DESC if (TxDesc->buf1cntl & OWN_BIT) break; // Transmit the packet ifp->DrvTxDescL[Idx].Pkt = Pkt; if (ifp->CtrlFlag & PKT_SOFTWARE_CRC) Pkt->PktLen += ETH_CRC_LEN; if (Pkt->PktLen <= Pkt->buf1len) { TxDesc->buf2cntl = 0; TxDesc->buflen = Pkt->PktLen; } else { TxDesc->buflen = Pkt->buf1len; TxDesc->buf2cntl = BUF2_EN | ((UINT32) (Pkt->Buf + Pkt->buf2off) & BUF_ADDR_MASK); } Pkt->Dst = (ADM5120_SW_REG(PHY_st_REG) & PORT_LINK_MASK) << 8; buf = Pkt->Buf + Pkt->buf2off; TxDesc->pktcntl = (Pkt->PktLen << PKT_LEN_SHIFT) | Pkt->Dst; TxDesc->buf1cntl = (TxDesc->buf1cntl & END_OF_RING) | OWN_BIT | ((UINT32) (Pkt->Buf + Pkt->buf1off) & BUF_ADDR_MASK); Idx = IdxNext; if (++TxCnt >= ifp->NumTxDescL) Pkt = NULL; else DEQUEUE_TX_PACKET(ifp->TxL_QueueHead, ifp->TxL_QueueTail, Pkt); } ifp->TxIdxL_Head = Idx; // Start the transmitting machine.// if(TxCnt > 0) ADM5106B_SW_REG(Send_trig_REG) = SEND_TRIG_LOW; ADM5120_SW_REG(Send_trig_REG) = SEND_TRIG_LOW; // Requeue the last packet if it was not transmitted. ENQUEUE_TX_PACKET_AT_FRONT(ifp->TxL_QueueHead, ifp->TxL_QueueTail, Pkt);}/*void ProcessLinkInt(PAM5120CONTEXT ifp){ UINT32 link_change, link_status; int i=0; buart_print("+P"); link_status = ADM5120_SW_REG(PHY_st_REG) & PORT_LINK_MASK; // Flip PORT_MII_LINK_DOWN bit. link_status ^= PORT_MII_LINKFAIL; link_change = link_status ^ ifp->link_status; ifp->link_status = link_status; while(link_change) { if(link_change & 0x1) { buart_put(i+0x30); if(link_status & (1 << i)) buart_put('u'); else buart_put('d'); } link_change>>=1; i++; } }*//**********************************************************************************//* Make Packet Align: *//**********************************************************************************/inline void SetPktAlign(PDRV_PACKET_DESC Pkt){ UINT32 buf2off; // Set buffer1 offset if (ifp->Buf1Off == BUF1_OFFSET_RAND) { // Buffer1 offset random Pkt->buf1off = rand() & BUF1_OFFSET_MAX; } else Pkt->buf1off = ifp->Buf1Off; if (ifp->CtrlFlag & SW_TWOBUF_PER_DESC) { // Two buffer per descriptor // Set Buffer1 length if (ifp->Buf1Len == BUF1_LEN_RAND) Pkt->buf1len = BUF1_LEN_MIN + (rand() & BUF1_LEN_RAND_MAX); else Pkt->buf1len = ifp->Buf1Len; // Set buffer 2 offset buf2off = (Pkt->buf1off + Pkt->buf1len + BUF_GUARD_BAND) & ~(ADM5120_CACHE_LINE_SIZE - 1); if (ifp->Buf2Off == BUF2_OFFSET_RAND) Pkt->buf2off = buf2off + (rand() & BUF2_OFFSET_MAX); else Pkt->buf2off = buf2off + ifp->Buf2Off; // Set buffer 2 length Pkt->buf2len = PKT_BUFFER_SIZE - Pkt->buf2off; } else { // One buffer per descriptor Pkt->buf1len = PKT_BUFFER_SIZE - Pkt->buf1off; Pkt->buf2len = Pkt->buf2off = 0; }}/********** Exported Functions ****************************************************//**********************************************************************************//* if5120_init: *//**********************************************************************************/int if5120_init(void){ int i, eth_num; static int init = 0; UINT32 reg1, reg2; UINT8 MacAddr[6]; // install exception handler install_exception(); // Init irq sys_irq_init(); // Per port PHY reset and enable auto-negotiation. ADM5120_SW_REG(PHY_cntl2_REG) |= SW_PHY_AN_MASK | SW_PHY_NORMAL_MASK; //Enable MII AN monitor via MDIO.(Dumb Mode) ADM5120_SW_REG(Port_conf2_REG) |= SW_GMII_AN_EN; // Allocate the driver context ifp = (PAM5120CONTEXT) MemAlloc(sizeof(AM5120CONTEXT), TRUE); if (ifp == NULL) return -1; // Disable Switch Interrupts ADM5120_SW_REG(SW_Int_mask_REG) = 0xFFFFFFF; // Set Phy control values ADM5120_SW_REG(PHY_cntl4_REG) = PHY_VOLT23 | PHY_ROMCODE_25; if (DrvAllocateResource() != 0) buart_print("\n\rSwitch allocate resource error."); // Hw initialization starts here // Initialize the ifp Desc ADM5120_SW_REG(Send_HBaddr_REG) = (UINT32) ifp->HwTxDescH; ADM5120_SW_REG(Send_LBaddr_REG) = (UINT32) ifp->HwTxDescL; ADM5120_SW_REG(Recv_HBaddr_REG) = (UINT32) ifp->HwRxDescH; ADM5120_SW_REG(Recv_LBaddr_REG) = (UINT32) ifp->HwRxDescL; if (ifp->CtrlFlag & PKT_SOFTWARE_CRC) ADM5120_SW_REG(CPUp_conf_REG) = CPU_PORT_DEFAULT; else ADM5120_SW_REG(CPUp_conf_REG) = CPU_PORT_DEFAULT | SW_PADING_CRC; // Daniel fix // Disable all port, enable MC, BP and FC ADM5120_SW_REG(Port_conf0_REG) = SW_DISABLE_PORT_MASK | SW_EN_MC_MASK | SW_EN_BP_MASK | SW_EN_FC_MASK; // Init VLAN group Regs, VLAN_GI & VLAN_GII reg1 = PORT_ALL; reg2 = PORT_NONE; ADM5120_SW_REG(VLAN_G1_REG) = reg1; ADM5120_SW_REG(VLAN_G2_REG) = reg2; if (!(ADM5120_SW_REG(Global_St_REG) & ALLMEM_TEST_DONE)) { buart_print("\n\rWaiting for switch memory test..."); while (!(ADM5120_SW_REG(Global_St_REG) & ALLMEM_TEST_DONE)); buart_print("\n\rSwitch memory test done!!\r\n"); for (i = 0; i < 2000; i++); } // Program Vlan0 Mac address bsp_GetMacBase(MacAddr, ð_num); ProgramMac(VLAN0, MacAddr); // Clear all interrupt status bit if any one was set reg1 = ADM5120_SW_REG(SW_Int_st_REG); ADM5120_SW_REG(SW_Int_st_REG) = reg1; // Connect Interrupt irqConnect(INT_LVL_SWITCH, IRQ_INT_MODE, (IRQ_HANDLER) Am5120Isr, 0, 0); IrqEnable(INT_LVL_SWITCH); // Enable CPU port reg1 = ADM5120_SW_REG(CPUp_conf_REG) & (~SW_CPU_PORT_DISABLE); ADM5120_SW_REG(CPUp_conf_REG) = reg1; // Enable VLAN0 port reg1 = ADM5120_SW_REG(Port_conf0_REG) & (~PORT_DISABLE_MASK); ADM5120_SW_REG(Port_conf0_REG) = reg1; // Clear Watchdog 1 counter reg1 = ADM5120_SW_REG(Watchdog1_REG); ADM5120_SW_REG(Watchdog1_REG) = (5 << WATCHDOG_TIMER_SET_SHIFT); ifp->IntMask = AM5120_INT_MASK; ifp->link_status = 0; // Enable switch interrupts ADM5120_SW_REG(SW_Int_mask_REG) = ~ifp->IntMask; return 0;}/**********************************************************************************//* Shutdown Switch: *//**********************************************************************************/void if5120shutdown(void){ int i, s; s = mips_int_lock(); ADM5120_SW_REG(Port_conf0_REG) |= SW_DISABLE_PORT_MASK; ADM5120_SW_REG(CPUp_conf_REG) |= SW_CPU_PORT_DISABLE; mips_int_unlock(s); for (i = 0; i < 1000000; i++);}/**********************************************************************************//* Turn On Switch: *//**********************************************************************************/void if5120turnon(void){ int i, s; UINT32 reg; s = mips_int_lock(); // Re-enable ports reg = ADM5120_SW_REG(Port_conf0_REG) & ~SW_DISABLE_PORT_MASK; ADM5120_SW_REG(Port_conf0_REG) = reg; // Re-enable CPU port reg = ADM5120_SW_REG(CPUp_conf_REG) & ~SW_CPU_PORT_DISABLE; ADM5120_SW_REG(CPUp_conf_REG) = reg; mips_int_unlock(s); for (i = 0; i < 1000000; i++);}/**********************************************************************************//* Am5120_GetFreePkt: *//**********************************************************************************/PDRV_PACKET_DESC Am5120_GetFreePkt(void){ PDRV_PACKET_DESC Pkt = NULL; int s; s = mips_int_lock(); if (ifp->FreePktList != NULL) { Pkt = ifp->FreePktList; ifp->FreePktList = Pkt->Next; ifp->FreePktCnt--; Pkt->Next = NULL; } mips_int_unlock(s); return Pkt;}void Am5120_RefreePkt(PDRV_PACKET_DESC Pkt){ int irq_state; irq_state = mips_int_lock(); Pkt->Next = ifp->FreePktList; ifp->FreePktList = Pkt; ifp->FreePktCnt++; mips_int_unlock(irq_state);}/***** Switch Interrupt Handler ******************************************************//**********************************************************************************//* ProcessAm5120Pkt: *//**********************************************************************************/void Am5120Isr(int intLev){ UINT32 IntReg, IntMask, reg; int LoopCnt = 0, RxFull = 0; // Disable Switch Interrupts ADM5120_SW_REG(SW_Int_mask_REG) = 0xFFFFFFF; // Clear watchdot timer 1// reg = ADM5120_SW_REG(Watchdog1_REG); // Ack all interrupts IntReg = ADM5120_SW_REG(SW_Int_st_REG); ADM5120_SW_REG(SW_Int_st_REG) = IntReg; IntReg = ifp->IntStatus | (IntReg & AM5120_INT_MASK); while (IntReg && LoopCnt < MAX_INT_LOOP_CNT) {// if(IntReg & GLOBAL_QUE_FULL_INT) ifp->DropFlag = TRUE; //buart_put('I'); if (IntReg & LINK_INT); //ProcessLinkInt(ifp); if (IntReg & TX_H_INT); //ProcessTxHInt(ifp); if (IntReg & TX_L_INT) ProcessTxLInt(); if (IntReg & RX_H_INT) { if (ProcessRxHInt() != 0) RxFull |= RX_H_FULL_INT; } if (IntReg & RX_L_INT) { if (ProcessRxLInt() != 0) RxFull |= RX_L_FULL_INT; }// if(IntReg & MUST_DROP_INT) buart_put('d'); IntReg = ADM5120_SW_REG(SW_Int_st_REG); // Acknowledge the interrupts ADM5120_SW_REG(SW_Int_st_REG) = IntReg; IntReg &= AM5120_INT_MASK; LoopCnt++; } // Record unhandled interrupts ifp->IntStatus = IntReg | RxFull; // If the rx H/L descriptor is still full, mask its interrupt temporarily. // If it is not masked, the interrupt will be asserted immediately after // the switch's IRQ being re-enabled. This will block the system from doing // anything other than servicing the switch's ISR/DSR routine. However, the // ISR/DSR is waiting the system to return some of its buffers for receiving. // A dead lock situation is entered. IntMask = ~ifp->IntMask | RxFull; // Enable switch interrupts ADM5120_SW_REG(SW_Int_mask_REG) = IntMask; ifp->IntCnt++;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -