⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_5120.c

📁 Boot code for ADM5120 with serial console for Edimax router.
💻 C
📖 第 1 页 / 共 2 页
字号:
		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, &eth_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 + -