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

📄 i82559.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 2 页
字号:
		printf("i82559 CBL Configure Command Timed Out\n");
		return CBL_CMD_CFG_TIMEOUT;	
	}
	return 0;
}

//--------------------------------------------------------------------------
// i82559_send()
//
// This function tells the i82559 to send the tx buffer pointed to by tx_buf
//
vulong i82559_send(uchar *txbuf, vulong length)
{
	vulong i, timeout;
	vushort temp16;
	vuchar *from_p, *to_p;

	if (i82559_found == 0) return 0;

	// build the header
	WR_SM16(i82559_tfd_base + CBL_STAT, 0);
	WR_SM16(i82559_tfd_base + CBL_CMD, (CBL_CMD_TX | CBL_CMD_EL));
	WR_SM32(i82559_tfd_base + CBL_LINK, (i82559_tfd_base & 0x0fffffff));
	WR_SM32(i82559_tfd_base + CBL_TxCB_TBD, 0xffffffff);
	WR_SM16(i82559_tfd_base + CBL_TxCB_CNT, (length | CBL_TxCB_CNT_EOF));
	WR_SM8(i82559_tfd_base + CBL_TxCB_THRESH, 16);
	WR_SM8(i82559_tfd_base + CBL_TxCB_TBD_NUM, 0);

	from_p = txbuf;
	to_p = (vuchar *)(i82559_tfd_base + CBL_TxCB_DATA);

	// copy the data into the shared memory area
	for (i = 0; i < length; i++){
		WR_SM8(to_p++, *from_p++);
	}

	// wait for the CU to be idle
	i82559_wait_for_cu_cmd();

	// issue the command to the i82559
	WR_SM32(i82559_scb + SCB_PTR, (i82559_tfd_base & 0x0fffffff));
	WR_SM16(i82559_scb + SCB_CMD, SCB_CU_START | SCB_IM_M);

	// wait for the CU to be idle
	i82559_wait_for_cu_cmd();

	// Now check the CBL Status word
    timeout = 10000;
	while(timeout){
		// delay before each check
		udelay(10);
		RD_SM16(i82559_cbl + CBL_STAT, temp16);
		if (temp16 & CBL_STAT_C){
			if (temp16 & CBL_STAT_OK){
				return 0;
			}
			else {
				return CBL_CMD_TX_ERR;
			}
		}
   		timeout--;
    }
	if (timeout == 0){
		return CBL_CMD_TX_TIMEOUT;	
	}
	return 0;
}

//--------------------------------------------------------------------------
// i82559_rx_get()
//
// This function checks the list of rx buffers to see if any of them are
// ready to be received.  If so, it copies the first ready buffer to
// pktbuf.  It then resumes the RU if it was suspended and returns the
// packet length.  This function also acts to start the receiver when
// called for the first time.
//
vushort i82559_rx_get(vuchar *pktbuf)
{
	vulong i, x, rfd;
	vushort temp16, rx_cmd, length;
	vuchar *from_p, *to_p;

	if (i82559_found == 0) return 0;

	rfd = i82559_rfd_base;

	// scan the rx list looking for ready buffers
	for (i = 0; i < RBUFCNT; i++){
		RD_SM16(rfd + RFD_STAT, temp16);
		// check the OK and Complete bits first
		if(temp16 & (RFD_STAT_C | RFD_STAT_OK)){
			// get the size 
			RD_SM16(rfd + RFD_CNT, length);
			// check the data valid flag
			if (length & RFD_CNT_EOF){
				length = length & RFD_CNT_MASK;
				// copy the data into pktbuf
				from_p = (vuchar *)(rfd + RFD_DATA);
				to_p = (vuchar *)(pktbuf);
				for(x = 0; x < length; x++){
					RD_SM8(from_p++, *to_p++);
				}
				// fixup this rfd for re-use
				WR_SM16(rfd + RFD_STAT, 0);
				WR_SM16(rfd + RFD_CNT, 0);
				break;
			}
		}
		rfd = rfd + RBUFSIZE;
		length = 0;
	}
	// Check the state of the RU before we leave
	RD_SM16(i82559_scb + SCB_STAT, temp16);
	temp16 = (temp16 & SCB_STAT_RU_MASK) >> SCB_STAT_RU_SHIFT;

	// Issue an RU command appropriate to the state.
	switch(temp16) {
		case RUS_IDLE: rx_cmd = (SCB_RU_START | SCB_IM_M); break;
		case RUS_SUSP: rx_cmd = (SCB_RU_RESUME | SCB_IM_M); break;
		case RUS_NORES: rx_cmd = (SCB_RU_START | SCB_IM_M); break;
		case RUS_SUSP_NO_RBD: rx_cmd = (SCB_RU_RESUME_RBD | SCB_IM_M); break;
		case RUS_NO_RES_NO_RBD: rx_cmd = (SCB_RU_RESUME_RBD | SCB_IM_M); break;
		case RUS_READY_NO_RBD: rx_cmd = (SCB_RU_START | SCB_IM_M); break;
		default: rx_cmd = (SCB_RU_NOP | SCB_IM_M);
	}
	// make sure the RU is ready to receive a command
	i82559_wait_for_ru_cmd();

	// issue the command
	WR_SM32(i82559_scb + SCB_PTR, (i82559_rfd_base & 0x0fffffff));
	WR_SM16(i82559_scb + SCB_CMD, rx_cmd);
	return length;
}
					   	
//--------------------------------------------------------------------------
// i82559_rx_init()
//
// This function builds/rebuilds the rx buffer list, then enables the i82559
// for receive
//
void i82559_rx_init()
{
	vulong i, rfd;

	rfd = i82559_rfd_base;

	for (i = 0; i < RBUFCNT - 1; i++){
		WR_SM16(rfd + RFD_CMD, 0); 
		WR_SM16(rfd + RFD_STAT, 0); 
		WR_SM32(rfd + RFD_LINK, ((rfd + RBUFSIZE) & 0x0fffffff)); 
		WR_SM16(rfd + RFD_CNT, 0); 
		WR_SM16(rfd + RFD_SIZE, RBUFSIZE); 
		rfd = rfd + RBUFSIZE;
	}
	// mark the last one as End Of List
	WR_SM16(rfd + RFD_CMD, RFD_CMD_EL); 
	WR_SM16(rfd + RFD_STAT, 0); 
	WR_SM32(rfd + RFD_LINK, ((rfd + RBUFSIZE) & 0x0fffffff)); 
	WR_SM16(rfd + RFD_CNT, 0); 
	WR_SM16(rfd + RFD_SIZE, RBUFSIZE); 
}

//--------------------------------------------------------------------------
// i82559_wait_for_cu_cmd()
//
// This function polls the SCB Status word waiting for the CU
// command to be accepted, then for the CU status to go idle
//
vulong i82559_wait_for_cu_cmd(void)
{
	vulong timeout;
	vushort temp16;

    timeout = 10000;
	while(timeout){
		// delay before each check
		udelay(10);
		RD_SM16(i82559_scb + SCB_CMD, temp16);
		temp16 = temp16 & SCB_CMD_CU_MASK;
    	if(temp16 == 0) break; 
   		timeout--;
    }
	if(timeout == 0){
		// Issue a selective reset to the i82559 and check again
		WR_SM32(i82559_scb + SCB_PORT, SCB_PORT_SEL_RST);
		udelay(10);
  	    timeout = 10000;
		while(timeout){
			// delay before each check
			udelay(10);
			RD_SM16(i82559_scb + SCB_CMD, temp16);
			temp16 = temp16 & SCB_CMD_CU_MASK;
	    	if(temp16 == 0) break; 
	   		timeout--;
	    }
		if (timeout == 0){
			return CU_CMD_TIMEOUT;	
		}
	}

	if(timeout == 0){
		// Issue a selective reset to the i82559 and check again
		WR_SM32(i82559_scb + SCB_PORT, SCB_PORT_SEL_RST);
		udelay(10);
  	    timeout = 10000;
		while(timeout){
			// delay before each check
			udelay(10);
			RD_SM16(i82559_scb + SCB_CMD, temp16);
			temp16 = temp16 & SCB_CMD_CU_MASK;
	    	if(temp16 == 0) break; 
	   		timeout--;
	    }
		if (timeout == 0){
			return CU_STAT_TIMEOUT;	
		}
	}

	return 0;
}

//--------------------------------------------------------------------------
// i82559_wait_for_ru_cmd()
//
// This function polls the SCB Status word waiting for the RU
// command to be accepted
//
vulong i82559_wait_for_ru_cmd(void)
{
	vulong timeout;
	vushort temp16;

    timeout = 100000;
	while(timeout){
		// delay before each check
		udelay(10);
		RD_SM16(i82559_scb + SCB_CMD, temp16);
		temp16 = temp16 & SCB_CMD_RU_MASK;
    	if(temp16 == 0) break; 
   		timeout--;
    }
	if (timeout == 0){
		return RU_CMD_TIMEOUT;	
	}

	return 0;
}

//--------------------------------------------------------------------------
// i82559_reset()
//
// This function issues a selective reset, then a full reset to the i82559.
// It then clears the CU and RU base pointers
//
void i82559_reset()
{

//	if (i82559_found == 0) return;

	// First issue a selective reset to the i82559 to force the i82559
	// off the pci bus
	WR_SM32(i82559_scb + SCB_PORT, SCB_PORT_SEL_RST);
	udelay(10);
  
    // Do hard reset now that the controller is off the PCI bus.
	WR_SM32(i82559_scb + SCB_PORT, SCB_PORT_RST);
    udelay(10);

	// zero the base addresses in the Command Unit and the Receive Unit.  
	WR_SM32(i82559_scb + SCB_PTR, 0x00000000);
	WR_SM16(i82559_scb + SCB_CMD, SCB_CU_BASE_ADD | SCB_IM_M);
	udelay(10);

	// wait for the RU to be ready
	i82559_wait_for_ru_cmd();

	WR_SM32(i82559_scb + SCB_PTR, 0x00000000);
	WR_SM16(i82559_scb + SCB_CMD, SCB_RU_BASE_ADD | SCB_IM_M);
	udelay(10);

}


#endif // INCLUDE_ETHERNET

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -