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

📄 dmfe.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
		send_filter_frame(dev, dev->mc_count); 	/* DM9102/DM9102A */	spin_unlock_irqrestore(&db->lock, flags);}static void netdev_get_drvinfo(struct net_device *dev,			       struct ethtool_drvinfo *info){	struct dmfe_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 struct ethtool_ops netdev_ethtool_ops = {	.get_drvinfo		= netdev_get_drvinfo,};/* *	A periodic timer routine *	Dynamic media sense, allocate Rx buffer... */static void dmfe_timer(unsigned long data){	u32 tmp_cr8;	unsigned char tmp_cr12;	struct DEVICE *dev = (struct DEVICE *) data;	struct dmfe_board_info *db = netdev_priv(dev); 	unsigned long flags;	DMFE_DBUG(0, "dmfe_timer()", 0);	spin_lock_irqsave(&db->lock, flags);	/* Media mode process when Link OK before enter this route */	if (db->first_in_callback == 0) {		db->first_in_callback = 1;		if (db->chip_type && (db->chip_id==PCI_DM9102_ID)) {			db->cr6_data &= ~0x40000;			update_cr6(db->cr6_data, db->ioaddr);			phy_write(db->ioaddr, db->phy_addr, 0, 0x1000, db->chip_id);			db->cr6_data |= 0x40000;			update_cr6(db->cr6_data, db->ioaddr);			db->timer.expires = DMFE_TIMER_WUT + HZ * 2;			add_timer(&db->timer);			spin_unlock_irqrestore(&db->lock, flags);			return;		}	}	/* Operating Mode Check */	if ( (db->dm910x_chk_mode & 0x1) &&		(db->stats.rx_packets > MAX_CHECK_PACKET) )		db->dm910x_chk_mode = 0x4;	/* Dynamic reset DM910X : 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 + DMFE_TX_KICK) ) {		outl(0x1, dev->base_addr + DCR1);   /* Tx polling again */		/* TX Timeout */		if ( time_after(jiffies, dev->trans_start + DMFE_TX_TIMEOUT) ) {			db->reset_TXtimeout++;			db->wait_reset = 1;			printk(KERN_WARNING "%s: Tx timeout - resetting\n",			       dev->name);		}	}	if (db->wait_reset) {		DMFE_DBUG(0, "Dynamic Reset device", db->tx_packet_cnt);		db->reset_count++;		dmfe_dynamic_reset(dev);		db->first_in_callback = 0;		db->timer.expires = DMFE_TIMER_WUT;		add_timer(&db->timer);		spin_unlock_irqrestore(&db->lock, flags);		return;	}	/* Link status check, Dynamic media type change */	if (db->chip_id == PCI_DM9132_ID)		tmp_cr12 = inb(db->ioaddr + DCR9 + 3);	/* DM9132 */	else		tmp_cr12 = inb(db->ioaddr + DCR12);	/* DM9102/DM9102A */	if ( ((db->chip_id == PCI_DM9102_ID) &&		(db->chip_revision == 0x02000030)) ||		((db->chip_id == PCI_DM9132_ID) &&		(db->chip_revision == 0x02000010)) ) {		/* DM9102A Chip */		if (tmp_cr12 & 2)			tmp_cr12 = 0x0;		/* Link failed */		else			tmp_cr12 = 0x3;	/* Link OK */	}	if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {		/* Link Failed */		DMFE_DBUG(0, "Link Failed", tmp_cr12);		db->link_failed = 1;		/* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */		/* AUTO or force 1M Homerun/Longrun don't need */		if ( !(db->media_mode & 0x38) )			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 & DMFE_AUTO) {			/* 10/100M link failed, used 1M Home-Net */			db->cr6_data|=0x00040000;	/* bit18=1, MII */			db->cr6_data&=~0x00000200;	/* bit9=0, HD mode */			update_cr6(db->cr6_data, db->ioaddr);		}	} else		if ((tmp_cr12 & 0x3) && db->link_failed) {			DMFE_DBUG(0, "Link link OK", tmp_cr12);			db->link_failed = 0;			/* Auto Sense Speed */			if ( (db->media_mode & DMFE_AUTO) &&				dmfe_sense_speed(db) )				db->link_failed = 1;			dmfe_process_mode(db);			/* SHOW_MEDIA_TYPE(db->op_mode); */		}	/* HPNA remote command check */	if (db->HPNA_command & 0xf00) {		db->HPNA_timer--;		if (!db->HPNA_timer)			dmfe_HPNA_remote_cmd_chk(db);	}	/* Timer active again */	db->timer.expires = DMFE_TIMER_WUT;	add_timer(&db->timer);	spin_unlock_irqrestore(&db->lock, flags);}/* *	Dynamic reset the DM910X board *	Stop DM910X board *	Free Tx/Rx allocated memory *	Reset DM910X board *	Re-initilize DM910X board */static void dmfe_dynamic_reset(struct DEVICE *dev){	struct dmfe_board_info *db = netdev_priv(dev);	DMFE_DBUG(0, "dmfe_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 */	dmfe_free_rxbuffer(db);	/* system variable init */	db->tx_packet_cnt = 0;	db->tx_queue_cnt = 0;	db->rx_avail_cnt = 0;	db->link_failed = 1;	db->wait_reset = 0;	/* Re-initilize DM910X board */	dmfe_init_dm910x(dev);	/* Restart upper layer interface */	netif_wake_queue(dev);}/* *	free all allocated rx buffer */static void dmfe_free_rxbuffer(struct dmfe_board_info * db){	DMFE_DBUG(0, "dmfe_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 dmfe_reuse_skb(struct dmfe_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->data, 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		DMFE_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 dmfe_descriptor_init(struct dmfe_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;	DMFE_DBUG(0, "dmfe_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 DM910X , then written value and start */static void update_cr6(u32 cr6_data, unsigned long ioaddr){	u32 cr6_tmp;	cr6_tmp = cr6_data & ~0x2002;           /* stop Tx/Rx */	outl(cr6_tmp, ioaddr + DCR6);	udelay(5);	outl(cr6_data, ioaddr + DCR6);	udelay(5);}/* *	Send a setup frame for DM9132 *	This setup frame initilize DM910X address filter mode*/static void dm9132_id_table(struct DEVICE *dev, int mc_cnt){	struct dev_mc_list *mcptr;	u16 * addrptr;	unsigned long ioaddr = dev->base_addr+0xc0;		/* ID Table */	u32 hash_val;	u16 i, hash_table[4];	DMFE_DBUG(0, "dm9132_id_table()", 0);	/* Node address */	addrptr = (u16 *) dev->dev_addr;	outw(addrptr[0], ioaddr);	ioaddr += 4;	outw(addrptr[1], ioaddr);	ioaddr += 4;	outw(addrptr[2], ioaddr);	ioaddr += 4;	/* Clear Hash Table */	for (i = 0; i < 4; i++)		hash_table[i] = 0x0;	/* broadcast address */	hash_table[3] = 0x8000;	/* the multicast address in Hash Table : 64 bits */	for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {		hash_val = cal_CRC( (char *) mcptr->dmi_addr, 6, 0) & 0x3f;		hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);	}	/* Write the hash table to MAC MD table */	for (i = 0; i < 4; i++, ioaddr += 4)		outw(hash_table[i], ioaddr);}/* *	Send a setup frame for DM9102/DM9102A *	This setup frame initilize DM910X address filter mode */static void send_filter_frame(struct DEVICE *dev, int mc_cnt){	struct dmfe_board_info *db = netdev_priv(dev);	struct dev_mc_list *mcptr;	struct tx_desc *txptr;	u16 * addrptr;	u32 * suptr;	int i;	DMFE_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 */	if (!db->tx_packet_cnt) {		/* Resource Empty */		db->tx_packet_cnt++;		txptr->tdes0 = cpu_to_le32(0x80000000);		update_cr6(db->cr6_data | 0x2000, dev->base_addr);		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling */		update_cr6(db->cr6_data, dev->base_addr);		dev->trans_start = jiffies;	} else		db->tx_queue_cnt++;	/* Put in TX queue */}/* *	Allocate rx buffer, *	As possible as allocate maxiumn Rx buffer */static void allocate_rx_buffer(struct dmfe_board_info *db){	struct rx_desc *rxptr;	struct sk_buff *skb;	rxptr = db->rx_insert_ptr;	while(db->rx_avail_cnt < RX_DESC_CNT) {		if ( ( skb = dev_alloc_skb(RX_ALLOC_SIZE) ) == NULL )			break;		rxptr->rx_skb_ptr = skb; /* FIXME (?) */		rxptr->rdes2 = cpu_to_le32( pci_map_single(db->pdev, skb->data, RX_ALLOC_SIZE, PCI_DMA_FROMDEVICE) );		wmb();		rxptr->rdes0 = cpu_to_le32(0x80000000);		rxptr = rxptr->next_rx_desc;		db->rx_avail_cnt++;	}	db->rx_insert_ptr = rxptr;}/* *	Read one word data from the serial ROM */static u16 read_srom_word(long ioaddr, int offset){	int i;	u16 srom_data = 0;	long cr9_ioaddr = ioaddr + DCR9;	outl(CR9_SROM_READ, cr9_ioaddr);	outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);	/* Send the Read Command 110b */	SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);	SROM_CLK_WRITE(SROM_DATA_1, cr9_ioaddr);	SROM_CLK_WRITE(SROM_DATA_0, cr9_ioaddr);	/* Send the offset */	for (i = 5; i >= 0; i--) {		srom_data = (offset & (1 << i)) ? SROM_DATA_1 : SROM_DATA_0;		SROM_CLK_WRITE(srom_data, cr9_ioaddr);	}	outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);	for (i = 16; i > 0; i--) {		outl(CR9_SROM_READ | CR9_SRCS | CR9_SRCLK, cr9_ioaddr);		udelay(5);		srom_data = (srom_data << 1) | ((inl(cr9_ioaddr) & CR9_CRDOUT) ? 1 : 0);		outl(CR9_SROM_READ | CR9_SRCS, cr9_ioaddr);		udelay(5);	}	outl(CR9_SROM_READ, cr9_ioaddr);	return srom_data;}/* *	Auto sense the media mode */static u8 dmfe_sense_speed(struct dmfe_board_info * db){	u8 ErrFlag = 0;	u16 phy_mode;	/* CR6 bit18=0, select 10/100M */	update_cr6( (db->cr6_data & ~0x40000), db->ioaddr);	phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);	phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);	if ( (phy_mode & 0x24) == 0x24 ) {		if (db->chip_id == PCI_DM9132_ID)	/* DM9132 */			phy_mode = phy_read(db->ioaddr, db->phy_addr, 7, db->chip_id) & 0xf000;		else 				/* DM9102/DM9102A */			phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000;		/* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */		switch (phy_mode) {		case 0x1000: db->op_mode = DMFE_10MHF; break;		case 0x2000: db->op_mode = DMFE_10MFD; break;		case 0x4000: db->op_mode = DMFE_100MHF; break;		case 0x8000: db->op_mode = DMFE_100MFD; break;		default: db->op_mode = DMFE_10MHF;			ErrFlag = 1;			break;		}	} else {		db->op_mode = DMFE_10MHF;		DMFE_DBUG(0, "Link Failed :", phy_mode);

⌨️ 快捷键说明

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