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

📄 lan91c111.c

📁 Coldfire MCF5282 DBug bootloader
💻 C
📖 第 1 页 / 共 2 页
字号:
	for(index=0 ; index < pNbuf->length; index +=2)
	{
		*(uint16*)&ethframe->data[index] = LAN91C111_DATA;
	}

	/* Get control byte and odd byte if there is one */
	lastword = LAN91C111_DATA;
	
	if(lastword & 0x0020)
	{
		/* write last byte */
		ethframe->data[index] = (uint8)((lastword & 0xFF00)>>8);
		/* increase length by 1*/
		pNbuf->length++;
	}

	/* Issue "Remove and Release" command */
	while (LAN91C111_MMCR & LAN91C111_MMCR_BUSY);
	LAN91C111_MMCR = LAN91C111_MMCR_RELEASE;

	/* Call the appropriate handler */
	nif_protocol_handler(nif,ethframe->type,pNbuf);

	/* free the buffer */
	nif->rx_free(pNbuf);

	/* Return to ISR */
	return;
}

/********************************************************************/
int
lan91c111_handler (void * applefritter, NIF *nif)
{
	uint16 intstatus, oldIMR, oldBank, oldPTR;
	vuint32 intdone;

	intdone = FALSE;

	/* Save off Bank Select register */
	oldBank = LAN91C111_BSR;

	/* switch to Bank 2 */
	SMC_SELECT_BANK(2);

	/* Save off Address Pointer register */
	oldPTR = LAN91C111_PTR;

	/* read the interrupt mask register */
	oldIMR = LAN91C111_IMR;

	/* disable all interrupts */
	LAN91C111_IMR = 0;

	while(!intdone)
	{
		/* switch to Bank 2 */
		SMC_SELECT_BANK(2);

		/* read in interrupt status register */
		intstatus = (LAN91C111_ISR&0xFF00);

		if(LAN91C111_ISR_RCV_INT &intstatus)		
		{
			lan91c111_receive(applefritter, nif);
			++nif->f_rx;

		}
		else if(LAN91C111_ISR_TX_INT &intstatus)		
		{
			/* Acknowledge TXINTR */
			LAN91C111_ISR = LAN91C111_ISR_TX_INT;
			++nif->f_tx;
		}
		else if(LAN91C111_ISR_RX_OVRN_INT &intstatus)	
		{
			/* Acknowledge interrupt */
			LAN91C111_ISR = LAN91C111_ISR_RX_OVRN_INT;
		}

		else
			intdone = TRUE;

	} /* while(!intdone) */
	
	/* Make sure I am in Bank 2 */
	SMC_SELECT_BANK(2);
	
	/* Check to see if FIFO is emtpy */
	if(LAN91C111_PTR & LAN91C111_PTR_NOT_EMPTY)
	{
		return FALSE;
	}

	/* Restore Address Pointer register */
	LAN91C111_PTR = oldPTR; 

	
	/* Restore the interrupt mask register */
	LAN91C111_IMR = oldIMR;

	/* Restore Bank Select register */
	LAN91C111_BSR = oldBank;

	return TRUE;
}
/********************************************************************
 * Shutdown phy
 ********************************************************************/
static void lan91c111_phy_shutdown(void)
{
	unsigned int timeout;
	unsigned int j;

	// Reset the PHY, setting all other bits to zero
	lan91c111_write_phy_reg(PHYADDR, PHY_CNTL_REG, PHY_CNTL_RST);

	// Wait for the reset to complete, or time out
	timeout = 6; // Wait up to 3 seconds
	while (timeout--)
		{
		if (!(lan91c111_read_phy_reg(PHYADDR, PHY_CNTL_REG) & PHY_CNTL_RST))
			{
			// reset complete
			break;
			}

		/* delay some time */
		for( j=0 ; j<100 ; j++);
		}

	if (timeout < 1)
		{
		printf("PHY reset timed out\n");
		return;
		}
}

/********************************************************************
 * Configures the specified PHY using Autonegotiation. Calls
 * smc_phy_fixed() if the user has requested a certain config.
 ********************************************************************/
static void lan91c111_phy_configure(void)
{
	unsigned int timeout;
	unsigned int j;
	uint16		 status;

	// Reset the PHY, setting all other bits to zero
	lan91c111_write_phy_reg(PHYADDR, PHY_CNTL_REG, PHY_CNTL_RST);

	// Wait for the reset to complete, or time out
	timeout = 6; // Wait up to 3 seconds
	while (timeout--)
		{
		if (!(lan91c111_read_phy_reg(PHYADDR, PHY_CNTL_REG) & PHY_CNTL_RST))
			{
			// reset complete
			break;
			}

		/* delay some time */
		for( j=0 ; j<100 ; j++);
		}

	if (timeout < 1)
		{
		printf("PHY reset timed out\n");
		return;
		}

	// Enable PHY Interrupts (for register 18)
	// Interrupts listed here are disabled
	lan91c111_write_phy_reg(PHYADDR, PHY_MASK_REG, PHY_INT_LNKFAIL
												|PHY_INT_INT
												|PHY_INT_LOSSSYNC
												|PHY_INT_CWRD
												|PHY_INT_SSD
												|PHY_INT_ESD	
												|PHY_INT_RPOL
												|PHY_INT_JAB	
												|PHY_INT_SPDDET
												|PHY_INT_DPLXDET);

	/* Configure the Receive/Phy Control register */
	SMC_SELECT_BANK(0);
	LAN91C111_RPC = LAN91C111_RPC_DEFAULT;


	// Update our Auto-Neg Advertisement Register
	lan91c111_write_phy_reg(PHYADDR, PHY_AD_REG, (PHY_AD_TX_FDX|PHY_AD_TX_HDX|PHY_AD_10_FDX|PHY_AD_10_HDX|PHY_AD_CSMA));		

	// Restart auto-negotiation process in order to advertise my caps
	lan91c111_write_phy_reg(PHYADDR, PHY_CNTL_REG,	PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST );
	
	// Wait for the auto-negotiation to complete.  This may take from
	// 2 to 3 seconds.
	// Wait for the reset to complete, or time out
	timeout = 20; // Wait up to 10 seconds
	while (timeout--)
	{
		status = lan91c111_read_phy_reg(PHYADDR, PHY_STAT_REG);
		if (status & PHY_STAT_ANEG_ACK)
		{
			// auto-negotiate complete
			break;
		}

		/* delay some time */
		for( j=0 ; j<10000 ; j++);

		// Restart auto-negotiation if remote fault
		if (status & PHY_STAT_REM_FLT)
		{
			// Restart auto-negotiation
			lan91c111_write_phy_reg(PHYADDR, PHY_CNTL_REG,
				PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST |
				PHY_CNTL_SPEED | PHY_CNTL_DPLX);
		}
	}
}

/********************************************************************
 * Writes a register to the MII Management serial interface
 ********************************************************************/
static void lan91c111_write_phy_reg(uint8 phyaddr, uint8 phyreg, uint16 phydata)
{
	uint16 oldBank;
	uint32 i,j;
	uint16 mask;
	uint16 mii_reg;
	uint16 bits[65];
	uint32 clk_idx = 0;

	// 32 consecutive ones on MDO to establish sync
	for (i = 0; i < 32; ++i)
		bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;

	// Start code <01>
	bits[clk_idx++] = LAN91C111_MII_MDOE;
	bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;

	// Write command <01>
	bits[clk_idx++] = LAN91C111_MII_MDOE;
	bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;

	// Output the PHY address, msb first
	mask = (uint8)0x10;
	for (i = 0; i < 5; ++i)
		{
		if (phyaddr & mask)
			bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
		else
			bits[clk_idx++] = LAN91C111_MII_MDOE;

		// Shift to next lowest bit
		mask >>= 1;
		}

	// Output the phy register number, msb first
	mask = (uint8)0x10;
	for (i = 0; i < 5; ++i)
		{
		if (phyreg & mask)
			bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
		else
			bits[clk_idx++] = LAN91C111_MII_MDOE;

		// Shift to next lowest bit
		mask >>= 1;
		}

	// Tristate and turnaround (2 bit times)
	bits[clk_idx++] = 0;
	bits[clk_idx++] = 0;

	// Write out 16 bits of data, msb first
	mask = 0x8000;
	for (i = 0; i < 16; ++i)
		{
		if (phydata & mask)
			bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
		else
			bits[clk_idx++] = LAN91C111_MII_MDOE;

		// Shift to next lowest bit
		mask >>= 1;
		}

	// Save the current bank
	oldBank = LAN91C111_BSR;

	// Select bank 3
	SMC_SELECT_BANK(3);

	// Get the current MII register value
	mii_reg = LAN91C111_MII;

	// Turn off all MII Interface bits
	mii_reg &= ~(LAN91C111_MII_MDOE|LAN91C111_MII_MCLK|LAN91C111_MII_MDI|LAN91C111_MII_MDO);

	// Clock all cycles
	for (i = 0; i < sizeof bits; ++i)
		{
		// Clock Low - output data
		LAN91C111_MII = (mii_reg | bits[i]);
		for(j=0 ; j<4000 ;j++);
		
		// Clock Hi - input data
		LAN91C111_MII = (mii_reg | bits[i] | LAN91C111_MII_MCLK);
		for(j=0 ; j<4000 ;j++);

		bits[i] |= 	(LAN91C111_MII & LAN91C111_MII_MDI);		
		}

	// Return to idle state
	// Set clock to low, data to low, and output tristated
	LAN91C111_MII = mii_reg;
	for(j=0 ; j<1000 ;j++);

	// Restore original bank select
//	SMC_SELECT_BANK(oldBank);
	LAN91C111_BSR = oldBank;

}

/********************************************************************
 * Reads a register from the MII Management serial interface
 ********************************************************************/
static uint16
lan91c111_read_phy_reg(uint8 phyaddr, uint8 phyreg)
{
	uint16 oldBank;
	uint32 i,j;
	uint8 mask;
	uint16 mii_reg;
	uint16 bits[64];
	uint32 clk_idx = 0;
	uint32 input_idx;
	uint16 phydata;

	// 32 consecutive ones on MDO to establish sync
	for (i = 0; i < 32; ++i)
		bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;

	// Start code <01>
	bits[clk_idx++] = LAN91C111_MII_MDOE;
	bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;

	// Read command <10>
	bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
	bits[clk_idx++] = LAN91C111_MII_MDOE;

	// Output the PHY address, msb first
	mask = (uint8)0x10;
	for (i = 0; i < 5; ++i)
		{
		if (phyaddr & mask)
			bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
		else
			bits[clk_idx++] = LAN91C111_MII_MDOE;

		// Shift to next lowest bit
		mask >>= 1;
		}

	// Output the phy register number, msb first
	mask = (uint8)0x10;
	for (i = 0; i < 5; ++i)
		{
		if (phyreg & mask)
			bits[clk_idx++] = LAN91C111_MII_MDOE | LAN91C111_MII_MDO;
		else
			bits[clk_idx++] = LAN91C111_MII_MDOE;

		// Shift to next lowest bit
		mask >>= 1;
		}

	// Tristate and turnaround (2 bit times)
	bits[clk_idx++] = 0;
	//bits[clk_idx++] = 0;

	// Input starts at this bit time
	input_idx = clk_idx;

	// Will input 16 bits
	for (i = 0; i < 16; ++i)
		bits[clk_idx++] = 0;

	// Final clock bit
	bits[clk_idx] = 0;

	// Save the current bank
	oldBank = LAN91C111_BSR;

	// Select bank 3
	SMC_SELECT_BANK(3);

	// Get the current MII register value
	mii_reg = LAN91C111_MII;

	// Turn off all MII Interface bits
	mii_reg &= ~(LAN91C111_MII_MDOE|LAN91C111_MII_MCLK|LAN91C111_MII_MDI|LAN91C111_MII_MDO);

	// Clock all 64 cycles
	for (i = 0; i < sizeof bits; ++i)
		{
		// Clock Low - output data
		LAN91C111_MII = ( mii_reg | bits[i] );
		for(j=0 ; j<4000 ;j++);

		// Clock Hi - input data
		LAN91C111_MII = ( mii_reg | bits[i] | LAN91C111_MII_MCLK );
		for(j=0 ; j<4000 ;j++)
		{}
		bits[i] |= (LAN91C111_MII & LAN91C111_MII_MDI);
		}

	// Return to idle state
	// Set clock to low, data to low, and output tristated
	LAN91C111_MII = mii_reg;
	for(j=0 ; j<1000 ;j++);

	// Restore original bank select
//	SMC_SELECT_BANK( oldBank );
	LAN91C111_BSR = oldBank;

	// Recover input data
	phydata = 0;
	for (i = 0; i < 16; ++i)
		{
		phydata <<= 1;

		if (bits[input_idx++] & LAN91C111_MII_MDI)
			phydata |= 0x0001;
		}

	return(phydata);	
}

/********************************************************************/

⌨️ 快捷键说明

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