📄 if_5120.c
字号:
}/************************************************//* SendPacketsL: *//* Send a low priority packet and try *//* to transmit all the packets 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 some packets ready so 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 mechanism... 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);}/****************************************************************//* NOTE: This entire routine was already commented out *//****************************************************************//*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 buffers per descriptor // Set Buffer 1 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; static int init = 0; UINT32 reg1, reg2; UINT8 MacAddr[8]; // was 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 // i.e. 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; // DE - note only 7 // Set PHY control values ADM5120_SW_REG(PHY_cntl4_REG) = PHY_VOLT23 | PHY_ROMCODE_25; if (DrvAllocateResource() != 0) buart_print("\r\nSwitch allocate resource error."); // Hardware 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("\r\nWaiting for switch memory test..."); while ( ! (ADM5120_SW_REG(Global_St_REG) & ALLMEM_TEST_DONE)) ; buart_print("\r\nSwitch memory test done!\r\n"); for (i = 0; i < 2000; i++) ; } // Program VLAN0 MAC address bsp_GetMAC(MacAddr); ProgramMac(VLAN0,MacAddr); // Clear all interrupt status bits if any were 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++) // 1 million ;}/****************************//* 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++) // 1 million ;}/****************************//* 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); // was already commented out // 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) {// These next 2 statements were already commented out// if(IntReg & GLOBAL_QUE_FULL_INT) ifp->DropFlag = TRUE;// buart_put('I'); if (IntReg & LINK_INT) //ProcessLinkInt(ifp); // already commented out ; if (IntReg & TX_H_INT) //ProcessTxHInt(ifp); // already commented out ; 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) // already commented out// buart_put('d'); // already commented out IntReg = ADM5120_SW_REG(SW_Int_st_REG); // Acknowledge 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 deadlock 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 + -