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

📄 ether-smc91x.c

📁 pxa270 NOR FLASH驱动代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	// Return to idle state	// Set clock to low, data to low, and output tristated	SMC_SET_MII( mii_reg );	msleep(1);	// Restore original bank select	SMC_SELECT_BANK( oldBank );	// Recover input data	phydata = 0;	for (i = 0; i < 16; ++i) {		phydata <<= 1;		if (bits[input_idx++] & MII_MDI)			phydata |= 0x0001;	}	DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",		__FUNCTION__, phyaddr, phyreg, phydata);	PRINT_MII_STREAM(bits, sizeof(bits));	return phydata;}/*------------------------------------------------------------ . Writes a register to the MII Management serial interface .-------------------------------------------------------------*/static voidsmc_write_phy_register( unsigned long ioaddr, int phyaddr,			int phyreg, int phydata ){	int oldBank;	int i, mask, mii_reg;	u8 bits[65];	int clk_idx = 0;	// 32 consecutive ones on MDO to establish sync	for (i = 0; i < 32; ++i)		bits[clk_idx++] = MII_MDOE | MII_MDO;	// Start code <01>	bits[clk_idx++] = MII_MDOE;	bits[clk_idx++] = MII_MDOE | MII_MDO;	// Write command <01>	bits[clk_idx++] = MII_MDOE;	bits[clk_idx++] = MII_MDOE | MII_MDO;	// Output the PHY address, msb first	mask = 0x10;	for (i = 0; i < 5; ++i) {		if (phyaddr & mask)			bits[clk_idx++] = MII_MDOE | MII_MDO;		else			bits[clk_idx++] = MII_MDOE;		// Shift to next lowest bit		mask >>= 1;	}	// Output the phy register number, msb first	mask = 0x10;	for (i = 0; i < 5; ++i) {		if (phyreg & mask)			bits[clk_idx++] = MII_MDOE | MII_MDO;		else			bits[clk_idx++] = 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++] = MII_MDOE | MII_MDO;		else			bits[clk_idx++] = MII_MDOE;		// Shift to next lowest bit		mask >>= 1;	}	// Final clock bit (tristate)	bits[clk_idx++] = 0;	// Save the current bank	oldBank = SMC_CURRENT_BANK();	// Select bank 3	SMC_SELECT_BANK( 3 );	// Get the current MII register value	mii_reg = SMC_GET_MII();	// Turn off all MII Interface bits	mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);	// Clock all cycles	for (i = 0; i < sizeof bits; ++i) {		// Clock Low - output data		SMC_SET_MII( mii_reg | bits[i] );		msleep(1);		// Clock Hi - input data		SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );		msleep(1);		bits[i] |= SMC_GET_MII() & MII_MDI;	}	// Return to idle state	// Set clock to low, data to low, and output tristated	SMC_SET_MII( mii_reg );	msleep(1);	// Restore original bank select	SMC_SELECT_BANK( oldBank );	DBG(3, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",		__FUNCTION__, phyaddr, phyreg, phydata);	PRINT_MII_STREAM(bits, sizeof(bits));}/*------------------------------------------------------------ . Finds and reports the PHY address .-------------------------------------------------------------*/static int smc_detect_phy(u32 ioaddr, u32 *pphyaddr){	int phy_id1, phy_id2;	int phyaddr;	int found = 0;	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);	// Scan all 32 PHY addresses if necessary	for (phyaddr = 0; phyaddr < 32; ++phyaddr) {		// Read the PHY identifiers		phy_id1 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG);		phy_id2 = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG);		DBG(3, "%s: phy_id1=0x%x, phy_id2=0x%x\n",			CARDNAME, phy_id1, phy_id2);		// Make sure it is a valid identifier		if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) &&		    (phy_id1 > 0x0000) && (phy_id1 < 0xffff)) {			if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000)) {				// Save the PHY's address				*pphyaddr = phyaddr;				found = 1;				break;			}		}	}	if (!found) {		DBG(1, "%s: No PHY found\n", CARDNAME);		return(0);	}	// Set the PHY type	if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) ) {		DBG(1, "%s: PHY=LAN83C183 (LAN91C111 Internal)\n", CARDNAME);	}	if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) ) {		DBG(1, "%s: PHY=LAN83C180\n", CARDNAME);	}	return 1;}/*------------------------------------------------------------ . Configures the specified PHY through the MII management interface . using Autonegotiation. . Calls smc_phy_fixed() if the user has requested a certain config. .-------------------------------------------------------------*/static voidsmc_phy_configure(u32 ioaddr){	int timeout;	int phyaddr;	int my_phy_caps; // My PHY capabilities	int my_ad_caps; // My Advertised capabilities	int status;	int failed = 0;	int rpc_cur_mode = RPC_DEFAULT;	DBG(3, "%s:smc_program_phy()\n", CARDNAME);	// Set the blocking flag	//lp->autoneg_active = 1;	// Find the address and type of our phy	if (!smc_detect_phy(ioaddr, (u32 *)&phyaddr))		goto smc_phy_configure_exit;	// Reset the PHY, setting all other bits to zero	smc_write_phy_register(ioaddr, 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 (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG)		    & PHY_CNTL_RST))			// reset complete			break;		msleep(500); // wait 500 millisecs	}	if (timeout < 1) {		printf("%s: PHY reset timed out\n", CARDNAME);		goto smc_phy_configure_exit;	}	// Read PHY Register 18, Status Output	//lp->lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);	// Enable PHY Interrupts (for register 18)	// Interrupts listed here are disabled	smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG,		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 );	SMC_SET_RPC( rpc_cur_mode );	// Copy our capabilities from PHY_STAT_REG to PHY_AD_REG	my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);	my_ad_caps  = PHY_AD_CSMA; // I am CSMA capable	if (my_phy_caps & PHY_STAT_CAP_T4)		my_ad_caps |= PHY_AD_T4;	if (my_phy_caps & PHY_STAT_CAP_TXF)		my_ad_caps |= PHY_AD_TX_FDX;	if (my_phy_caps & PHY_STAT_CAP_TXH)		my_ad_caps |= PHY_AD_TX_HDX;	if (my_phy_caps & PHY_STAT_CAP_TF)		my_ad_caps |= PHY_AD_10_FDX;	if (my_phy_caps & PHY_STAT_CAP_TH)		my_ad_caps |= PHY_AD_10_HDX;	// Disable capabilities not selected by our user	//if (lp->ctl_rspeed != 100)	//	my_ad_caps &= ~(PHY_AD_T4|PHY_AD_TX_FDX|PHY_AD_TX_HDX);	//if (!lp->ctl_rfduplx)	//	my_ad_caps &= ~(PHY_AD_TX_FDX|PHY_AD_10_FDX);	// Update our Auto-Neg Advertisement Register	smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps);	// Read the register back.  Without this, it appears that when	// auto-negotiation is restarted, sometimes it isn't ready and	// the link does not come up.	status = smc_read_phy_register(ioaddr, phyaddr, PHY_AD_REG);	DBG(2, "%s: phy caps=%x\n", CARDNAME, my_phy_caps);	DBG(2, "%s: phy advertised caps=%x\n", CARDNAME, my_ad_caps);	// Restart auto-negotiation process in order to advertise my caps	smc_write_phy_register( ioaddr, 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 = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);		if (status & PHY_STAT_ANEG_ACK)			// auto-negotiate complete			break;		msleep(500); // wait 500 millisecs		// Restart auto-negotiation if remote fault		if (status & PHY_STAT_REM_FLT) {			DBG(1, "%s: PHY remote fault detected\n", CARDNAME);			// Restart auto-negotiation			DBG(1, "%s: PHY restarting auto-negotiation\n",				CARDNAME);			smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,				PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST |				PHY_CNTL_SPEED | PHY_CNTL_DPLX);		}	}	if (timeout < 1) {		DBG(1, "%s: PHY auto-negotiate timed out\n", CARDNAME);		failed = 1;	}	// Fail if we detected an auto-negotiate remote fault	if (status & PHY_STAT_REM_FLT) {		DBG(1, "%s: PHY remote fault detected\n", CARDNAME);		failed = 1;	}	// Re-Configure the Receive/Phy Control register	SMC_SET_RPC( rpc_cur_mode );smc_phy_configure_exit:	// Exit auto-negotiation	return;}/*---------------------------------------------------------------------- . Function: smc_probe( unsigned long ioaddr ) . . Purpose: .	Tests to see if a given ioaddr points to an SMC91x chip. .	Returns a 0 on success . . Algorithm: .	(1) see if the high byte of BANK_SELECT is 0x33 . 	(2) compare the ioaddr with the base register's address .	(3) see if I recognize the chip ID in the appropriate register . .--------------------------------------------------------------------- *//*--------------------------------------------------------------- . Here I do typical initialization tasks. . . o  Initialize the structure if needed . o  print out my vanity message if not done so already . o  print out what type of hardware is detected . o  print out the ethernet address . o  find the IRQ . o  set up my private data . o  configure the dev structure with my subroutines . o  actually GRAB the irq. . o  GRAB the region .-----------------------------------------------------------------*/static int smc_probe(u32 ioaddr){	unsigned int val;	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);	/* First, see if the high byte is 0x33 */	val = SMC_CURRENT_BANK();	DBG(2, "%s: bank signature probe returned 0x%04x\n", CARDNAME, val);	if ( (val & 0xFF00) != 0x3300 )		return -1;	/* The above MIGHT indicate a device, but I need to write to further 	 	test this.  */	SMC_SELECT_BANK(0);	val = SMC_CURRENT_BANK();	if ( (val & 0xFF00 ) != 0x3300 ) 		return -1;	/* Get the MAC address */	SMC_SELECT_BANK( 1 );	SMC_GET_MAC_ADDR(hwaddress);	/* now, reset the chip, and put it into a known state */	smc_reset( ioaddr );	return 0;}static int smc_hw_reset(u32 ioaddr){#if defined(LUBBOCK)	{		volatile int *attaddr = (int*)(ioaddr + 1<<25);		long flags;		/* first reset, then enable the device. Sequence is critical */		attaddr[ECOR] |= ECOR_RESET;		msleep(1);		attaddr[ECOR] &= ~ECOR_RESET;		attaddr[ECOR] |= ECOR_ENABLE;		/* force 16-bit mode */		attaddr[ECSR] &= ~ECSR_IOIS8;		msleep(1);	}#endif	return 0;}/********************************************************************** * ethernet driver interfaces */static int smc_init(u32 ioaddr){	int err=0;	u8  version;	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);	err = smc_hw_reset(ioaddr);	if (err)		return err;	err = smc_probe(ioaddr);	if (err) 		return err;	SMC_SELECT_BANK(3);	version = SMC_GET_REV() & 0xff;	/* reset the hardware */	smc_reset(ioaddr);	smc_enable(ioaddr);	SMC_SELECT_BANK( 1 );	hwaddress[0] = 0x00;	hwaddress[1] = 0x80;	hwaddress[2] = 0x48;	hwaddress[3] = 0x12;	hwaddress[4] = 0x34;	hwaddress[5] = 0x56;	SMC_SET_MAC_ADDR(hwaddress);	smc_chip_base = ioaddr;	if (version > 0x70) 		smc_phy_configure(ioaddr);	return err;}static int readether( u8 *buf, int size ){	int ret = 0;	u8  status, mask = 0xff;	u16 saved_bank;	u32 ioaddr = smc_chip_base;	if ( !smc_chip_base ) 		return -EINVAL;	saved_bank = SMC_CURRENT_BANK();	SMC_SELECT_BANK(2);	mask = SMC_GET_INT_MASK();	/* clear all interrupts */	SMC_SET_INT_MASK(0);	/* read the status flag, and mask it */	status = SMC_GET_INT() & mask;	if (!status) {		ret = 0;	} 	else if ( status & IM_RCV_INT ) { 		ret = smc_rcv( smc_chip_base, buf, size );	}	SMC_SET_INT_MASK(mask);	SMC_SELECT_BANK(saved_bank);	return ret;}static int writeether( u8 *buf, int size ){	if ( !smc_chip_base )		return -EINVAL;	memcpy( buf+6, hwaddress, 6 );	return smc_send( smc_chip_base, buf, size);}static int get_ethaddr( u8 dev_addr[6] ){	u32 ioaddr = smc_chip_base;	if (!ioaddr) return -EINVAL;	SMC_GET_MAC_ADDR(dev_addr);	return 0;}static int set_ethaddr( u8 dev_addr[6] ){	u32 ioaddr = smc_chip_base;	if (!ioaddr) return -EINVAL;	SMC_SET_MAC_ADDR(dev_addr);	return 0;}/********************************************************************** * export ethernet driver  */ether_driver_t smc91x_ether_driver = {	smc_init,	readether,	writeether,	set_ethaddr,	get_ethaddr,	SMC_BASE,};int board_eth_init(void){	if(smc_init(smc91x_ether_driver.base)) {		puts("initialize ethernet card fail!\n");		return -1;	}	puts("initialize ethernet card OK!\n");	return 0;}int board_eth_lnk_stat(void){	return 0;}int board_eth_send(unsigned char *data, unsigned int len){	return writeether(data, len);}int board_eth_rcv(unsigned char *data, unsigned int *len){	int ret;		ret = readether(data, 1532);	if(ret>0) {		*len = ret;		return 0;	}	return -1;}int board_eth_get_addr(unsigned char *addr){	memcpy(addr, hwaddress, 6);	return 0;}void smc91x_read(void){	ether_driver_t *pEthDrv;	int ret;	u8 data[2000];	pEthDrv = &smc91x_ether_driver;	while(1) {		ret = pEthDrv->rcv(data, sizeof(data));		if(ret) {			printf("read result = %d\n", ret);			if(ret>0 && ret<=60) {				int i;								for(i=0; i<ret; i++)					printf("%02x%c", data[i], ((i+1)%16)?',':'\n');				putchar('\n');			}		}	}}

⌨️ 快捷键说明

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