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

📄 uli526x.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
{	struct uli526x_board_info *db = dev->priv;	unsigned long flags;	ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);	spin_lock_irqsave(&db->lock, flags);	if (dev->flags & IFF_PROMISC) {		ULI526X_DBUG(0, "Enable PROM Mode", 0);		db->cr6_data |= CR6_PM | CR6_PBF;		update_cr6(db->cr6_data, db->ioaddr);		spin_unlock_irqrestore(&db->lock, flags);		return;	}	if (dev->flags & IFF_ALLMULTI || dev->mc_count > ULI5261_MAX_MULTICAST) {		ULI526X_DBUG(0, "Pass all multicast address", dev->mc_count);		db->cr6_data &= ~(CR6_PM | CR6_PBF);		db->cr6_data |= CR6_PAM;		spin_unlock_irqrestore(&db->lock, flags);		return;	}	ULI526X_DBUG(0, "Set multicast address", dev->mc_count);	send_filter_frame(dev, dev->mc_count); 	/* M5261/M5263 */	spin_unlock_irqrestore(&db->lock, flags);}static voidULi_ethtool_gset(struct uli526x_board_info *db, struct ethtool_cmd *ecmd){	ecmd->supported = (SUPPORTED_10baseT_Half |	                   SUPPORTED_10baseT_Full |	                   SUPPORTED_100baseT_Half |	                   SUPPORTED_100baseT_Full |	                   SUPPORTED_Autoneg |	                   SUPPORTED_MII);			ecmd->advertising = (ADVERTISED_10baseT_Half |	                   ADVERTISED_10baseT_Full |	                   ADVERTISED_100baseT_Half |	                   ADVERTISED_100baseT_Full |	                   ADVERTISED_Autoneg |	                   ADVERTISED_MII);	ecmd->port = PORT_MII;	ecmd->phy_address = db->phy_addr;	ecmd->transceiver = XCVR_EXTERNAL;			ecmd->speed = 10;	ecmd->duplex = DUPLEX_HALF;		if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)	{		ecmd->speed = 100;               	}	if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)	{		ecmd->duplex = DUPLEX_FULL;	}	if(db->link_failed)	{		ecmd->speed = -1;		ecmd->duplex = -1;		}		if (db->media_mode & ULI526X_AUTO)	{			ecmd->autoneg = AUTONEG_ENABLE;	}}static void netdev_get_drvinfo(struct net_device *dev,			       struct ethtool_drvinfo *info){	struct uli526x_board_info *np = netdev_priv(dev);	strcpy(info->driver, DRV_NAME);	strcpy(info->version, DRV_VERSION);	if (np->pdev)		strcpy(info->bus_info, pci_name(np->pdev));	else		sprintf(info->bus_info, "EISA 0x%lx %d",			dev->base_addr, dev->irq);}static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {	struct uli526x_board_info *np = netdev_priv(dev);		ULi_ethtool_gset(np, cmd);		return 0;}static u32 netdev_get_link(struct net_device *dev) {	struct uli526x_board_info *np = netdev_priv(dev);			if(np->link_failed)		return 0;	else		return 1;}static void uli526x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	wol->supported = WAKE_PHY | WAKE_MAGIC;	wol->wolopts = 0;}static struct ethtool_ops netdev_ethtool_ops = {	.get_drvinfo		= netdev_get_drvinfo,	.get_settings		= netdev_get_settings,	.get_link		= netdev_get_link,	.get_wol		= uli526x_get_wol,};/* *	A periodic timer routine *	Dynamic media sense, allocate Rx buffer... */static void uli526x_timer(unsigned long data){	u32 tmp_cr8;	unsigned char tmp_cr12=0;	struct net_device *dev = (struct net_device *) data;	struct uli526x_board_info *db = netdev_priv(dev); 	unsigned long flags;	u8 TmpSpeed=10;		//ULI526X_DBUG(0, "uli526x_timer()", 0);	spin_lock_irqsave(&db->lock, flags);		/* Dynamic reset ULI526X : system error or transmit time-out */	tmp_cr8 = inl(db->ioaddr + DCR8);	if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {		db->reset_cr8++;		db->wait_reset = 1;	}	db->interval_rx_cnt = 0;	/* TX polling kick monitor */	if ( db->tx_packet_cnt &&	     time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) {		outl(0x1, dev->base_addr + DCR1);   // Tx polling again 		// TX Timeout 		if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) {			db->reset_TXtimeout++;			db->wait_reset = 1;			printk( "%s: Tx timeout - resetting\n",			       dev->name);		}	}	if (db->wait_reset) {		ULI526X_DBUG(0, "Dynamic Reset device", db->tx_packet_cnt);		db->reset_count++;		uli526x_dynamic_reset(dev);		db->timer.expires = ULI526X_TIMER_WUT;		add_timer(&db->timer);		spin_unlock_irqrestore(&db->lock, flags);		return;	}	/* Link status check, Dynamic media type change */	if((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)!=0)		tmp_cr12 = 3;	if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {		/* Link Failed */		ULI526X_DBUG(0, "Link Failed", tmp_cr12);		netif_carrier_off(dev);		printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name);		db->link_failed = 1;		/* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */		/* AUTO don't need */		if ( !(db->media_mode & 0x8) )			phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);		/* AUTO mode, if INT phyxcer link failed, select EXT device */		if (db->media_mode & ULI526X_AUTO) {			db->cr6_data&=~0x00000200;	/* bit9=0, HD mode */			update_cr6(db->cr6_data, db->ioaddr);		}	} else		if ((tmp_cr12 & 0x3) && db->link_failed) {			ULI526X_DBUG(0, "Link link OK", tmp_cr12);			db->link_failed = 0;			/* Auto Sense Speed */			if ( (db->media_mode & ULI526X_AUTO) &&				uli526x_sense_speed(db) )				db->link_failed = 1;			uli526x_process_mode(db);						if(db->link_failed==0)			{				if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)				{					TmpSpeed = 100;				}				if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)				{					printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Full duplex\n",dev->name,TmpSpeed);				}				else				{					printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Half duplex\n",dev->name,TmpSpeed);				}				netif_carrier_on(dev);			}			/* SHOW_MEDIA_TYPE(db->op_mode); */		}		else if(!(tmp_cr12 & 0x3) && db->link_failed)		{			if(db->init==1)			{				printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name);				netif_carrier_off(dev);			}		}		db->init=0;	/* Timer active again */	db->timer.expires = ULI526X_TIMER_WUT;	add_timer(&db->timer);	spin_unlock_irqrestore(&db->lock, flags);}/* *	Dynamic reset the ULI526X board *	Stop ULI526X board *	Free Tx/Rx allocated memory *	Reset ULI526X board *	Re-initialize ULI526X board */static void uli526x_dynamic_reset(struct net_device *dev){	struct uli526x_board_info *db = netdev_priv(dev);	ULI526X_DBUG(0, "uli526x_dynamic_reset()", 0);	/* Sopt MAC controller */	db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);	/* Disable Tx/Rx */	update_cr6(db->cr6_data, dev->base_addr);	outl(0, dev->base_addr + DCR7);		/* Disable Interrupt */	outl(inl(dev->base_addr + DCR5), dev->base_addr + DCR5);	/* Disable upper layer interface */	netif_stop_queue(dev);	/* Free Rx Allocate buffer */	uli526x_free_rxbuffer(db);	/* system variable init */	db->tx_packet_cnt = 0;	db->rx_avail_cnt = 0;	db->link_failed = 1;	db->init=1;	db->wait_reset = 0;	/* Re-initialize ULI526X board */	uli526x_init(dev);	/* Restart upper layer interface */	netif_wake_queue(dev);}/* *	free all allocated rx buffer */static void uli526x_free_rxbuffer(struct uli526x_board_info * db){	ULI526X_DBUG(0, "uli526x_free_rxbuffer()", 0);	/* free allocated rx buffer */	while (db->rx_avail_cnt) {		dev_kfree_skb(db->rx_ready_ptr->rx_skb_ptr);		db->rx_ready_ptr = db->rx_ready_ptr->next_rx_desc;		db->rx_avail_cnt--;	}}/* *	Reuse the SK buffer */static void uli526x_reuse_skb(struct uli526x_board_info *db, struct sk_buff * skb){	struct rx_desc *rxptr = db->rx_insert_ptr;	if (!(rxptr->rdes0 & cpu_to_le32(0x80000000))) {		rxptr->rx_skb_ptr = skb;		rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->tail, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );		wmb();		rxptr->rdes0 = cpu_to_le32(0x80000000);		db->rx_avail_cnt++;		db->rx_insert_ptr = rxptr->next_rx_desc;	} else		ULI526X_DBUG(0, "SK Buffer reuse method error", db->rx_avail_cnt);}/* *	Initialize transmit/Receive descriptor *	Using Chain structure, and allocate Tx/Rx buffer */static void uli526x_descriptor_init(struct uli526x_board_info *db, unsigned long ioaddr){	struct tx_desc *tmp_tx;	struct rx_desc *tmp_rx;	unsigned char *tmp_buf;	dma_addr_t tmp_tx_dma, tmp_rx_dma;	dma_addr_t tmp_buf_dma;	int i;	ULI526X_DBUG(0, "uli526x_descriptor_init()", 0);	/* tx descriptor start pointer */	db->tx_insert_ptr = db->first_tx_desc;	db->tx_remove_ptr = db->first_tx_desc;	outl(db->first_tx_desc_dma, ioaddr + DCR4);     /* TX DESC address */	/* rx descriptor start pointer */	db->first_rx_desc = (void *)db->first_tx_desc + sizeof(struct tx_desc) * TX_DESC_CNT;	db->first_rx_desc_dma =  db->first_tx_desc_dma + sizeof(struct tx_desc) * TX_DESC_CNT;	db->rx_insert_ptr = db->first_rx_desc;	db->rx_ready_ptr = db->first_rx_desc;	outl(db->first_rx_desc_dma, ioaddr + DCR3);	/* RX DESC address */	/* Init Transmit chain */	tmp_buf = db->buf_pool_start;	tmp_buf_dma = db->buf_pool_dma_start;	tmp_tx_dma = db->first_tx_desc_dma;	for (tmp_tx = db->first_tx_desc, i = 0; i < TX_DESC_CNT; i++, tmp_tx++) {		tmp_tx->tx_buf_ptr = tmp_buf;		tmp_tx->tdes0 = cpu_to_le32(0);		tmp_tx->tdes1 = cpu_to_le32(0x81000000);	/* IC, chain */		tmp_tx->tdes2 = cpu_to_le32(tmp_buf_dma);		tmp_tx_dma += sizeof(struct tx_desc);		tmp_tx->tdes3 = cpu_to_le32(tmp_tx_dma);		tmp_tx->next_tx_desc = tmp_tx + 1;		tmp_buf = tmp_buf + TX_BUF_ALLOC;		tmp_buf_dma = tmp_buf_dma + TX_BUF_ALLOC;	}	(--tmp_tx)->tdes3 = cpu_to_le32(db->first_tx_desc_dma);	tmp_tx->next_tx_desc = db->first_tx_desc;	 /* Init Receive descriptor chain */	tmp_rx_dma=db->first_rx_desc_dma;	for (tmp_rx = db->first_rx_desc, i = 0; i < RX_DESC_CNT; i++, tmp_rx++) {		tmp_rx->rdes0 = cpu_to_le32(0);		tmp_rx->rdes1 = cpu_to_le32(0x01000600);		tmp_rx_dma += sizeof(struct rx_desc);		tmp_rx->rdes3 = cpu_to_le32(tmp_rx_dma);		tmp_rx->next_rx_desc = tmp_rx + 1;	}	(--tmp_rx)->rdes3 = cpu_to_le32(db->first_rx_desc_dma);	tmp_rx->next_rx_desc = db->first_rx_desc;	/* pre-allocate Rx buffer */	allocate_rx_buffer(db);}/* *	Update CR6 value *	Firstly stop ULI526X, then written value and start */static void update_cr6(u32 cr6_data, unsigned long ioaddr){	outl(cr6_data, ioaddr + DCR6);	udelay(5);}/* *	Send a setup frame for M5261/M5263 *	This setup frame initialize ULI526X address filter mode */static void send_filter_frame(struct net_device *dev, int mc_cnt){	struct uli526x_board_info *db = netdev_priv(dev);	struct dev_mc_list *mcptr;	struct tx_desc *txptr;	u16 * addrptr;	u32 * suptr;	int i;	ULI526X_DBUG(0, "send_filter_frame()", 0);	txptr = db->tx_insert_ptr;	suptr = (u32 *) txptr->tx_buf_ptr;	/* Node address */	addrptr = (u16 *) dev->dev_addr;	*suptr++ = addrptr[0];	*suptr++ = addrptr[1];	*suptr++ = addrptr[2];	/* broadcast address */	*suptr++ = 0xffff;	*suptr++ = 0xffff;	*suptr++ = 0xffff;	/* fit the multicast address */	for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {		addrptr = (u16 *) mcptr->dmi_addr;		*suptr++ = addrptr[0];		*suptr++ = addrptr[1];		*suptr++ = addrptr[2];	}	for (; i<14; i++) {		*suptr++ = 0xffff;		*suptr++ = 0xffff;		*suptr++ = 0xffff;	}	/* prepare the setup frame */	db->tx_insert_ptr = txptr->next_tx_desc;	txptr->tdes1 = cpu_to_le32(0x890000c0);	/* Resource Check and Send the setup packet */

⌨️ 快捷键说明

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