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

📄 ethernet_smsc91c111.c

📁 Intrisyc 公司的PXA255-bootloader,源码易懂
💻 C
📖 第 1 页 / 共 3 页
字号:
	// Don't overwrite the buffer	// Don't bother writing the message for an off-by-one truncation	// because it's probably due to us ignoring the odd byte bit.	if (data_count-1 > *data_size)	{			DEBUG_2("%s: Data truncated: %d>%d\r\n", __FUNCTION__,			data_count, *data_size);		data_count = *data_size;		// Throw out truncated packet	        return 0;	}        *data_size = data_count;	/*	 * Handle the buffer alignment cases (32,16,8)	 * Try to read the largest words as we can	 * in as tight a loop as possible.	 */        // Read the last 0..3 bytes of data one byte at a time        leftovers = data_count % 4;        data_count -= leftovers;	if (((unsigned int)data % 4) == 0)	{		// Buffer area is long word aligned		data32 = (unsigned int *)data;		// Convert count into long words		data_count /= 4;	        // Read as many whole words as we can	        for(    pointer_offset=0;	        	pointer_offset < data_count;	        	++pointer_offset)	        {			data32[pointer_offset] = REG32(OFFSET_DR);		}		// Convert pointer_offset into byte offset		pointer_offset *= 4;	}	else if (((unsigned int)data % 4) == 2)	{		// Buffer area is short word aligned		data16 = (unsigned short *)data;		// Convert count into short words		data_count /= 2;	        // Read as many short words as we can	        for(    pointer_offset=0;	        	pointer_offset < data_count;	        	pointer_offset += 2)	        {			_temp32 = REG32(OFFSET_DR);			data16[pointer_offset] = (_temp32) & 0xFFFF;			data16[pointer_offset +1] = (_temp32 >> 16) & 0xFFFF;		}		// Convert pointer_offset into byte offset		pointer_offset *= 2;	}	else	{		// Buffer is byte aligned	        // Read as many short words as we can	        for(    pointer_offset=0;	        	pointer_offset < data_count;	        	pointer_offset += 4)	        {			_temp32 = REG32(OFFSET_DR);			data[pointer_offset] = _temp32 & 0xFF;			data[pointer_offset + 1] = (_temp32 >> 8) & 0xFF;			data[pointer_offset + 2] = (_temp32 >> 16) & 0xFF;			data[pointer_offset + 3] = (_temp32 >> 24) & 0xFF;		}	}        // Read the remaining bytes and store as many as requested        if (leftovers)        {            _temp32 = REG32(OFFSET_DR);            for (i=0;leftovers--;i++)            {                    data[pointer_offset + i] = (_temp32 >> (i*8)) & 0xFF;            }        }		return 1;} // End of read_mmu_datastatic int release_rx_packet (void){	unsigned short _temp;	int counter;	counter=MAX_MMUCR_COUNTER;	SETUP_BANK(BANK_MMUCR);	do 	{			READ_REG16(OFFSET_MMUCR, _temp);	} while ((_temp & BIT_MMUCR_BUSY) && --counter);	if (!counter)	{		ERROR ("MMU busy\r\n");	}		WRITE_REG16(OFFSET_MMUCR, OPCODE_MMUCR_REM_REL);	do 	{		READ_REG16(OFFSET_MMUCR, _temp);	} while (_temp & BIT_MMUCR_BUSY);	return 1;} // End of release_rx_packet/* * We must release the tx packet passed to us from the MMU.  If we do not * do this, then the memory will fill up. */static int release_tx_packet (unsigned char packet_number){	unsigned short _temp;	SETUP_BANK (BANK_PNR);	WRITE_REG8(OFFSET_PNR,packet_number);        SETUP_BANK (BANK_MMUCR);        do        {                READ_REG16 (OFFSET_MMUCR, _temp);        } while (_temp & BIT_MMUCR_BUSY);                WRITE_REG16 (OFFSET_MMUCR, OPCODE_MMUCR_REL_SPEC);		return 1;		} // End of release_tx_packetstatic int allocate_tx (unsigned char *packet_number){	unsigned int counter;	unsigned short _temp;	unsigned char _temp8;	int retry=0;    // disable retries for now	SETUP_BANK(BANK_MIR);	/*	 * We will wait till there is some available memory before	 * asking for some.	 */	counter = MAX_TRY;	do	{		READ_REG16(OFFSET_MIR, _temp);	} while (((_temp >> 8) == 0) && --counter);	/* 	 * For the Case of entering the if condition below...	 * 	 * Ok, we can't use the SMSC cause all of its memory is used up.	 * This can be one of 2 cases.	 *	 * 1.  We have Received Frames there.  This does us no good as	 * we are single threaded.	 *	 * 2.  We have Transmitted Frames there.	 *	 * 3. Both 1 & 2	 *	 * Number 2 is bad, because we should only really ever have one tx	 * packet in the buffer (we wait for its compeletion).  It should not	 * happen.	 *	 * Number 1 can be fixed by removing packets by either reading them	 * and releasing them, releasing them individually, or flushing them	 * all.	 */	if (!counter)	{		DEBUG_2("%s: Out of MMU Memory; flushing buffers\r\n", __FUNCTION__);                flush_ethernet ();		//return 0;	}allocate:	/*	 * Wait for MMU to become available	 */	SETUP_BANK(BANK_MMUCR);        counter = MAX_TRY;	do	{		READ_REG16(OFFSET_MMUCR, _temp);	} while (_temp & BIT_MMUCR_BUSY && --counter);	if (!counter)	{		ERROR ("MMU busy\r\n");	}	/*	 * Give the ALLOCATE TX PACKET command to the MMU	 */	WRITE_REG16(OFFSET_MMUCR, OPCODE_MMUCR_ALLOC_TX);	SETUP_BANK(BANK_ISR);	counter=MAX_TRY;	do	{		READ_REG8(OFFSET_ISR, _temp8);	} while	(!(_temp8 & BIT_ISR_ALLOC_INT) && --counter);	if (!counter)	{		DEBUG_2("%s: Allocation Timeout\r\n", __FUNCTION__);		if (!retry++)		{			goto allocate;		}		return 0;	}	/*	 * If the below fails lets try to flush the ethernet in one last	 * try to make a go of this.	 */	SETUP_BANK(BANK_ARR);	READ_REG8(OFFSET_ARR, _temp8);	if (_temp8 & BIT_ARR_FAILED)	{		if (!retry++)		{		        // We probably got flooded with received packets		        // at this point, using up all the buffers.                        DEBUG_2("%s: Allocation failed; flushing buffers\r\n",                               __FUNCTION__);			flush_ethernet ();			goto allocate;		}		return 0;	}		*packet_number &= _temp8 & MASK_ARR_PACKET_NUM;		return 1;} // End of allocate_tx/* * This function will do the bit-banging neccessary to do the MII transfers * to the PHY itself.  Below is a description of how it works. * * The sequence for the Management Interface is  * IDLE->START->OPCODE->PHY_ADDR->REG_ADDR->TA->DATA * * IDLE is 32 1's over the MDIO (via MI_IDLE) * START is 01b over the MDIO (via MI_START)  * OPCODE is 01b or 10b over the MDIO (via MI_WRITE / MI_READ) * PHY_ADDR is always 00000b (Internal) * REG_ADDR is reg (5 lower bits). * TA is Turnaround time (don't care for write) * DATA is data. * * reg and data both should be clocked out MSB first (Ie. Bit 15 / 4) */static int write_phy_register (unsigned char reg, unsigned short data){	int i;	SETUP_BANK(BANK_MI);		/* 	 * Lets do the IDLE	 */	mi_idle();			/*	 * Lets do that START condition	 */	mi_start ();	/*	 * Lets tell it we are doing a write	 */	mi_write_op ();	/*	 * Lets tell it the PHY ADDRESS	 */	mi_phy_addr (PHY_INT_ADDR);	/*	 * Lets tell it the PHY REG	 */	mi_phy_addr (reg);	/*	 * Here's The TurnAround time.  This is here so that if the	 * PHY has to switch from Tx or Rx it has time to do so..	 */	mi_ta ();		for (i=15;i>=0;i--)	{		WRITE_REG16(OFFSET_MI,((data >> i) & 0x1) | MI_MDOE);		udelay (MI_CLK_DELAY);		WRITE_REG16(OFFSET_MI,((data >> i) & 0x1) | MI_MDOE | MI_MDCLK);		udelay (MI_CLK_DELAY);	}			return 1;} // End of write_phy_register/* * This does the bit-banging for the MII to the PHY * * The sequence for the Management Interface is  * IDLE->START->OPCODE->PHY_ADDR->REG_ADDR->TA->DATA * * IDLE is 32 1's over the MDIO (via MI_IDLE) * START is 01b over the MDIO (via MI_START)  * OPCODE is 01b or 10b over the MDIO (via MI_WRITE / MI_READ) * PHY_ADDR is always 00000b (Internal) * REG_ADDR is reg (5 lower bits). * TA is Turnaround time (don't care for write) * DATA is data. * * reg and data both should be clocked out MSB first (Ie. Bit 15 / 4) */static int read_phy_register (unsigned char reg, unsigned short *data){	int i;	unsigned short _temp;	SETUP_BANK(BANK_MI);		/* 	 * Lets do the IDLE	 */	mi_idle ();			/*	 * Lets do that START condition	 */	mi_start ();	/*	 * Lets tell it we are doing a write	 */	mi_read_op ();	/*	 * Lets tell it the PHY ADDRESS	 */	mi_phy_addr (PHY_INT_ADDR);	/*	 * Lets tell it the PHY REG	 */	mi_phy_addr(reg);	/*	 * Heres The TurnAround time.  This is here so that if the	 * PHY has to switch from Tx or Rx it has time to do so..	 */	mi_ta ();	/*	 * Read the Data in from the PHY	 */		for (i=15,*data=0;i>=0;i--)	{		WRITE_REG16(OFFSET_MI, 0);		udelay (MI_CLK_DELAY);		READ_REG16(OFFSET_MIR, _temp);		*data |= ((((_temp >> 1) & 0x1) << i));		WRITE_REG16(OFFSET_MI, MI_MDCLK);		udelay (MI_CLK_DELAY);	}			return 1;} // End of read_phy_register/* * This function may be used to print out the Ethernet Packets.  It does * the appropriate byte swapping to make it easier for reading (by humans). * static int print_data (unsigned char *data, unsigned short size){	int i=0,x=0,leftovers;	unsigned int data32=0;	DEBUG("print_data: Printing %x bytes\r\n", size);	for (i=0;i<(size - 3);i+=4)	{		if ((i % 24)==0)		{			itc_printf("\r\n\t");		}				data32 = data[i]	<< 24;		data32 |= data[i+1] 	<< 16;		data32 |= data[i+2] 	<< 8;		data32 |= data[i+3];		itc_printf("%x ", data32);	}	if (i < (size))	{		leftovers = size - i;		for (data32=0,x=leftovers - 1;x >=0;i++,x--)		{			data32 |= data[i] << (8*x);		}		itc_printf("%x (%i bytes valid)", data32, leftovers);	}	itc_printf("\r\n");	return 1;}*/int rx_ethernet_off (void){	/*	 * Disable Receive	 */	SETUP_BANK(BANK_RCR);	REG16(OFFSET_RCR) &= ~(BIT_RCR_RXEN);	return 1;}int flush_ethernet (void){	unsigned short _temp;	int counter;	/*	 * Reset MMU	 *	 * This will flush all of Memory (both tx and rx).	 */	SETUP_BANK (BANK_MMUCR);        counter = MAX_TRY;	do 	{		READ_REG16(OFFSET_MMUCR, _temp);	} while (_temp & BIT_MMUCR_BUSY && --counter);	if (!counter)	{		ERROR ("MMU busy\r\n");	}		WRITE_REG16(OFFSET_MMUCR, OPCODE_MMUCR_RESET);	do 	{		READ_REG16(OFFSET_MMUCR, _temp);	} while (_temp & BIT_MMUCR_BUSY && --counter);	//SETUP_BANK(OFFSET_MIR);	return 1;}int rx_ethernet_on (void){	SETUP_BANK(BANK_RCR);	REG16(OFFSET_RCR) |= BIT_RCR_RXEN;	return 1;}

⌨️ 快捷键说明

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