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

📄 sis900.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
 err_out_unregister: 	unregister_netdev(net_dev); err_unmap_rx:	pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,		sis_priv->rx_ring_dma); err_unmap_tx:	pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring,		sis_priv->tx_ring_dma); err_out_cleardev: 	pci_set_drvdata(pci_dev, NULL);	pci_release_regions(pci_dev); err_out:	kfree(net_dev);	return ret;}/** *	sis900_mii_probe: - Probe MII PHY for sis900 *	@net_dev: the net device to probe for *	 *	Search for total of 32 possible mii phy addresses. *	Identify and set current phy if found one, *	return error if it failed to found. */static int __init sis900_mii_probe (struct net_device * net_dev){	struct sis900_private * sis_priv = net_dev->priv;	u16 poll_bit = MII_STAT_LINK, status = 0;	unsigned int timeout = jiffies + 5 * HZ;	int phy_addr;	u8 revision;	sis_priv->mii = NULL;	/* search for total of 32 possible mii phy addresses */	for (phy_addr = 0; phy_addr < 32; phy_addr++) {			struct mii_phy * mii_phy = NULL;		u16 mii_status;		int i;		mii_phy = NULL;		for(i = 0; i < 2; i++)			mii_status = mdio_read(net_dev, phy_addr, MII_STATUS);		if (mii_status == 0xffff || mii_status == 0x0000)			/* the mii is not accessable, try next one */			continue;				if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) == NULL) {			printk(KERN_INFO "Cannot allocate mem for struct mii_phy\n");			return 0;		}				mii_phy->phy_id0 = mdio_read(net_dev, phy_addr, MII_PHY_ID0);		mii_phy->phy_id1 = mdio_read(net_dev, phy_addr, MII_PHY_ID1);				mii_phy->phy_addr = phy_addr;		mii_phy->status = mii_status;		mii_phy->next = sis_priv->mii;		sis_priv->mii = mii_phy;		sis_priv->first_mii = mii_phy;		for (i = 0; mii_chip_table[i].phy_id1; i++)			if ((mii_phy->phy_id0 == mii_chip_table[i].phy_id0 ) &&			    ((mii_phy->phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){				mii_phy->phy_types = mii_chip_table[i].phy_types;				if (mii_chip_table[i].phy_types == MIX)					mii_phy->phy_types =						(mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;				printk(KERN_INFO "%s: %s transceiver found at address %d.\n",				       net_dev->name, mii_chip_table[i].name, phy_addr);				break;			}					if( !mii_chip_table[i].phy_id1 )			printk(KERN_INFO "%s: Unknown PHY transceiver found at address %d.\n",			       net_dev->name, phy_addr);				}		if (sis_priv->mii == NULL) {		printk(KERN_INFO "%s: No MII transceivers found!\n",		       net_dev->name);		return 0;	}	/* select default PHY for mac */	sis_priv->mii = NULL;	sis900_default_phy( net_dev );	/* Reset phy if default phy is internal sis900 */        if ((sis_priv->mii->phy_id0 == 0x001D) &&	    ((sis_priv->mii->phy_id1&0xFFF0) == 0x8000))        	status = sis900_reset_phy(net_dev, sis_priv->cur_phy);                /* workaround for ICS1893 PHY */        if ((sis_priv->mii->phy_id0 == 0x0015) &&            ((sis_priv->mii->phy_id1&0xFFF0) == 0xF440))            	mdio_write(net_dev, sis_priv->cur_phy, 0x0018, 0xD200);	if(status & MII_STAT_LINK){		while (poll_bit) {			current->state = TASK_INTERRUPTIBLE;			schedule_timeout(0);			poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit);			if (jiffies >= timeout) {				printk(KERN_WARNING "%s: reset phy and link down now\n", net_dev->name);				return -ETIME;			}		}	}	pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);	if (revision == SIS630E_900_REV) {		/* SiS 630E has some bugs on default value of PHY registers */		mdio_write(net_dev, sis_priv->cur_phy, MII_ANADV, 0x05e1);		mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG1, 0x22);		mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG2, 0xff00);		mdio_write(net_dev, sis_priv->cur_phy, MII_MASK, 0xffc0);		//mdio_write(net_dev, sis_priv->cur_phy, MII_CONTROL, 0x1000);		}	if (sis_priv->mii->status & MII_STAT_LINK)		netif_carrier_on(net_dev);	else		netif_carrier_off(net_dev);	return 1;}/** *	sis900_default_phy: - Select default PHY for sis900 mac. *	@net_dev: the net device to probe for * *	Select first detected PHY with link as default. *	If no one is link on, select PHY whose types is HOME as default. *	If HOME doesn't exist, select LAN. */static u16 sis900_default_phy(struct net_device * net_dev){	struct sis900_private * sis_priv = net_dev->priv; 	struct mii_phy *phy = NULL, *phy_home = NULL, *default_phy = NULL;	u16 status;        for( phy=sis_priv->first_mii; phy; phy=phy->next ){		status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);		status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);		/* Link ON & Not select deafalut PHY */		 if ( (status & MII_STAT_LINK) && !(default_phy) )		 	default_phy = phy;		 else{			status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL);			mdio_write(net_dev, phy->phy_addr, MII_CONTROL,				status | MII_CNTL_AUTO | MII_CNTL_ISOLATE);			if( phy->phy_types == HOME )				phy_home = phy;		 }	}	if( (!default_phy) && phy_home )		default_phy = phy_home;	else if(!default_phy)		default_phy = sis_priv->first_mii;	if( sis_priv->mii != default_phy ){		sis_priv->mii = default_phy;		sis_priv->cur_phy = default_phy->phy_addr;		printk(KERN_INFO "%s: Using transceiver found at address %d as default\n", net_dev->name,sis_priv->cur_phy);	}		status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);	status &= (~MII_CNTL_ISOLATE);	mdio_write(net_dev, sis_priv->cur_phy, MII_CONTROL, status);		status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);	status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS);	return status;	}/** * 	sis900_set_capability: - set the media capability of network adapter. *	@net_dev : the net device to probe for *	@phy : default PHY * *	Set the media capability of network adapter according to *	mii status register. It's necessary before auto-negotiate. */ static void sis900_set_capability( struct net_device *net_dev , struct mii_phy *phy ){	u16 cap;	u16 status;		status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);	status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);		cap = MII_NWAY_CSMA_CD |		((phy->status & MII_STAT_CAN_TX_FDX)? MII_NWAY_TX_FDX:0) |		((phy->status & MII_STAT_CAN_TX)    ? MII_NWAY_TX:0) |		((phy->status & MII_STAT_CAN_T_FDX) ? MII_NWAY_T_FDX:0)|		((phy->status & MII_STAT_CAN_T)     ? MII_NWAY_T:0);	mdio_write(net_dev, phy->phy_addr, MII_ANADV, cap);}/* Delay between EEPROM clock transitions. */#define eeprom_delay()  inl(ee_addr)/** *	read_eeprom: - Read Serial EEPROM *	@ioaddr: base i/o address *	@location: the EEPROM location to read * *	Read Serial EEPROM through EEPROM Access Register. *	Note that location is in word (16 bits) unit */static u16 read_eeprom(long ioaddr, int location){	int i;	u16 retval = 0;	long ee_addr = ioaddr + mear;	u32 read_cmd = location | EEread;	outl(0, ee_addr);	eeprom_delay();	outl(EECLK, ee_addr);	eeprom_delay();	/* Shift the read command (9) bits out. */	for (i = 8; i >= 0; i--) {		u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;		outl(dataval, ee_addr);		eeprom_delay();		outl(dataval | EECLK, ee_addr);		eeprom_delay();	}	outb(EECS, ee_addr);	eeprom_delay();	/* read the 16-bits data in */	for (i = 16; i > 0; i--) {		outl(EECS, ee_addr);		eeprom_delay();		outl(EECS | EECLK, ee_addr);		eeprom_delay();		retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);		eeprom_delay();	}	/* Terminate the EEPROM access. */	outl(0, ee_addr);	eeprom_delay();	outl(EECLK, ee_addr);	return (retval);}/* Read and write the MII management registers using software-generated   serial MDIO protocol. Note that the command bits and data bits are   send out seperately */#define mdio_delay()    inl(mdio_addr)static void mdio_idle(long mdio_addr){	outl(MDIO | MDDIR, mdio_addr);	mdio_delay();	outl(MDIO | MDDIR | MDC, mdio_addr);}/* Syncronize the MII management interface by shifting 32 one bits out. */static void mdio_reset(long mdio_addr){	int i;	for (i = 31; i >= 0; i--) {		outl(MDDIR | MDIO, mdio_addr);		mdio_delay();		outl(MDDIR | MDIO | MDC, mdio_addr);		mdio_delay();	}	return;}/** *	mdio_read: - read MII PHY register *	@net_dev: the net device to read *	@phy_id: the phy address to read *	@location: the phy regiester id to read * *	Read MII registers through MDIO and MDC *	using MDIO management frame structure and protocol(defined by ISO/IEC). *	Please see SiS7014 or ICS spec */static u16 mdio_read(struct net_device *net_dev, int phy_id, int location){	long mdio_addr = net_dev->base_addr + mear;	int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);	u16 retval = 0;	int i;	mdio_reset(mdio_addr);	mdio_idle(mdio_addr);	for (i = 15; i >= 0; i--) {		int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;		outl(dataval, mdio_addr);		mdio_delay();		outl(dataval | MDC, mdio_addr);		mdio_delay();	}	/* Read the 16 data bits. */	for (i = 16; i > 0; i--) {		outl(0, mdio_addr);		mdio_delay();		retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);		outl(MDC, mdio_addr);		mdio_delay();	}	outl(0x00, mdio_addr);	return retval;}/** *	mdio_write: - write MII PHY register *	@net_dev: the net device to write *	@phy_id: the phy address to write *	@location: the phy regiester id to write *	@value: the register value to write with * *	Write MII registers with @value through MDIO and MDC *	using MDIO management frame structure and protocol(defined by ISO/IEC) *	please see SiS7014 or ICS spec */static void mdio_write(struct net_device *net_dev, int phy_id, int location, int value){	long mdio_addr = net_dev->base_addr + mear;	int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);	int i;	mdio_reset(mdio_addr);	mdio_idle(mdio_addr);	/* Shift the command bits out. */	for (i = 15; i >= 0; i--) {		int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;		outb(dataval, mdio_addr);		mdio_delay();		outb(dataval | MDC, mdio_addr);		mdio_delay();	}	mdio_delay();	/* Shift the value bits out. */	for (i = 15; i >= 0; i--) {		int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;		outl(dataval, mdio_addr);		mdio_delay();		outl(dataval | MDC, mdio_addr);		mdio_delay();	}	mdio_delay();	/* Clear out extra bits. */	for (i = 2; i > 0; i--) {		outb(0, mdio_addr);		mdio_delay();		outb(MDC, mdio_addr);		mdio_delay();	}	outl(0x00, mdio_addr);	return;}/** *	sis900_reset_phy: - reset sis900 mii phy. *	@net_dev: the net device to write *	@phy_addr: default phy address * *	Some specific phy can't work properly without reset. *	This function will be called during initialization and *	link status change from ON to DOWN. */static u16 sis900_reset_phy(struct net_device *net_dev, int phy_addr){	int i = 0;	u16 status;	while (i++ < 2)		status = mdio_read(net_dev, phy_addr, MII_STATUS);	mdio_write( net_dev, phy_addr, MII_CONTROL, MII_CNTL_RESET );		return status;}/** *	sis900_open: - open sis900 device *	@net_dev: the net device to open * *	Do some initialization and start net interface. *	enable interrupts and set sis900 timer. */static intsis900_open(struct net_device *net_dev){	struct sis900_private *sis_priv = net_dev->priv;	long ioaddr = net_dev->base_addr;	u8 revision;	int ret;	/* Soft reset the chip. */	sis900_reset(net_dev);	/* Equalizer workaround Rule */	pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);	sis630_set_eq(net_dev, revision);	ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev);	if (ret)		return ret;	sis900_init_rxfilter(net_dev);

⌨️ 快捷键说明

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