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

📄 pmcmspeth.c

📁 175dswitch的驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			netif_carrier_on(dev);		}	}	/* reschedule the timer */	lp->link_timer.expires = jiffies + HZ / LINK_DELAY_DIV;	add_timer(&lp->link_timer);}/************************************************************************** * Reset the hardware and restore defaults.  Queues etc must be * cleared afterwards, although we don't change the pointers so they don't * need to be reallocated. */static void mspeth_mac_reset(struct net_device *dev){	struct mspeth_local *lp = (struct mspeth_local *) dev->priv;	struct mspeth_regs *tr = (struct mspeth_regs *) dev->base_addr;	int i;	/* software reset the MAC -- why do we have to do both?  But it seems to work better this	 * way so .....	 */	write_mspreg(MAC_Reset, &tr->MAC_Ctl);	/* hardware reset */	write_mspreg(MacRSTBases[lp->hwunit], RST_SET_REG);	mdelay(100);	write_mspreg(MacRSTBases[lp->hwunit], RST_CLR_REG);	/* Wait for the MAC to come out of reset */	for (i = 0; i < 10; i++) {		if ((read_mspreg(SYS_RST_REG) & MacRSTBases[lp->hwunit]) ==		    0)			break;		ndelay(100);	}	/* initialize registers to default value */	write_mspreg(0, &tr->MAC_Ctl);	write_mspreg(0, &tr->DMA_Ctl);	write_mspreg(0, &tr->TxThrsh);	write_mspreg(0, &tr->TxPollCtr);	write_mspreg(0, &tr->RxFragSize);	write_mspreg(0, &tr->Int_En);	write_mspreg(0, &tr->FDA_Bas);	write_mspreg(0, &tr->FDA_Lim);	write_mspreg(0xffffffff, &tr->Int_Src);	/* Write 1 to clear */	write_mspreg(0, &tr->ARC_Ctl);	write_mspreg(0, &tr->Tx_Ctl);	write_mspreg(0, &tr->Rx_Ctl);	write_mspreg(0, &tr->ARC_Ena);	(void) read_mspreg(&tr->Miss_Cnt);	/* Read to clear */}/************************************************************************** * initialize the hardware and start the DMA/MAC RX/TX.  The queues must * be setup before this is called. */static void mspeth_mac_init(struct net_device *dev){	struct mspeth_local *lp = (struct mspeth_local *) dev->priv;	struct mspeth_regs *tr = (struct mspeth_regs *) dev->base_addr;	int flags;	/* do not interrupt me while I'm configuring the MAC */	local_irq_save(flags);	/* load station address to ARC */	mspeth_set_arc_entry(tr, ARC_ENTRY_SOURCE, dev->dev_addr);	/* Enable ARC (broadcast and unicast) */	write_mspreg(ARC_Ena_Bit(ARC_ENTRY_SOURCE), &tr->ARC_Ena);	write_mspreg(ARC_CompEn | ARC_BroadAcc, &tr->ARC_Ctl);	/* configure DMA */	write_mspreg(DMA_CTL_CMD, &tr->DMA_Ctl);	/* configure the RX/TX mac */	write_mspreg(0, &tr->RxFragSize);	write_mspreg(TX_POLL_CNT, &tr->TxPollCtr);	write_mspreg(TX_THRESHOLD, &tr->TxThrsh);	/* zero and enable the interrupts */	lp->fatal_icnt = 0;	write_mspreg(INT_EN_CMD, &tr->Int_En);	/* set queues */	/* NOTE: This needs to be checked against the documentation:	 * How much does (RX_BUF_NUM-1) need to be shifted over.	 * Andrew thinks 5, used to be 4. */	/* hammtrev, 2005-11-25:	 * Using the formula used in the old brecis driver, which gives a	 * little bit less than (RX_BUF_NUM-1)<<5, allowing for more 	 * buffer descriptors attached to a frame descriptor.	 */	write_mspreg(lp->rxfd_base, &tr->FDA_Bas); 	write_mspreg((RX_BUF_NUM - 1) << 5, &tr->FDA_Lim); 	/*	 * Activation method:	 * First, enable the MAC Transmitter and the DMA Receive circuits.	 * Then enable the DMA Transmitter and the MAC Receive circuits.	 */	write_mspreg(lp->blfd_ptr, &tr->BLFrmPtr);	/* start DMA receiver */	write_mspreg(RX_CTL_CMD, &tr->Rx_Ctl);	/* start MAC receiver */	write_mspreg(lp->txfd_base, &tr->TxFrmPtr);	/* start the DMA transmitter */	write_mspreg(TX_CTL_CMD, &tr->Tx_Ctl);	/* start the MAC transmitter */	/* turn the interrupts back on */	local_irq_restore(flags);}/************************************************************************** * start the Address Recognition circuit.  It must be initialized with * address of the device (which can be changed in the PROM). */static voidmspeth_set_arc_entry(struct mspeth_regs *tr, int index,		     unsigned char *addr){	int arc_index = index * 6;	unsigned long arc_data;	unsigned long saved_addr;	saved_addr = read_mspreg(&tr->ARC_Adr);	if (mspeth_debug > 1) {		int i;		printk(KERN_DEBUG "%s: arc %d:", cardname, index);		for (i = 0; i < 6; i++)			printk(" %02x", addr[i]);		printk("\n");	}	if (index & 1) {		/* read modify write */		write_mspreg(arc_index - 2, &tr->ARC_Adr);		arc_data = read_mspreg(&tr->ARC_Data) & 0xffff0000;		arc_data |= addr[0] << 8 | addr[1];		write_mspreg(arc_data, &tr->ARC_Data);		/* write whole word */		write_mspreg(arc_index + 2, &tr->ARC_Adr);		arc_data =		    (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |		    addr[5];		write_mspreg(arc_data, &tr->ARC_Data);	} else {		/* write whole word */		write_mspreg(arc_index, &tr->ARC_Adr);		arc_data =		    (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) |		    addr[3];		write_mspreg(arc_data, &tr->ARC_Data);		/* read modify write */		write_mspreg(arc_index + 4, &tr->ARC_Adr);		arc_data = read_mspreg(&tr->ARC_Data) & 0x0000ffff;		arc_data |= addr[4] << 24 | (addr[5] << 16);		write_mspreg(arc_data, &tr->ARC_Data);	}	if (mspeth_debug > 2) {		int i;		for (i = arc_index / 4; i < arc_index / 4 + 2; i++) {			write_mspreg(i * 4, &tr->ARC_Adr);			printk("arc 0x%x: %08x\n",			       i * 4, read_mspreg(&tr->ARC_Data));		}	}	write_mspreg(saved_addr, &tr->ARC_Adr);}/************************************************************************** * Initialize the RX/TX queues and the free buffer list.  This routine * allocates memory and care must be taken to free the memory when it * is no longer required */static bool mspeth_queue_init(struct net_device *dev){	struct mspeth_local *lp = (struct mspeth_local *) dev->priv;	int i, size = 0;	u32 tmp_addr;	struct sk_buff *skb;	/* The queue structure allocates individual buffers large enough to hold an entire	 * packet.  There is no packing so each FD requires a single BD.  There is one	 * Q_Desc (an FD and a BD, 16-byte aligned) for each packet recieved and the same	 * for each packet to transmit.  The list of free buffers has one FD and an arbitrary number	 * of BDs following it (but even).  There is one BD for each RX buffer	 */	/* need to add some error checking here for reentry into this routine */	/* test for allocation requirements */	if (lp->FD_base == NULL) {		/* descriptors for the rx/tx buffers and the buffer list */		size =		    (RX_BUF_NUM + TX_BUF_NUM) * sizeof(struct Q_Desc) +		    sizeof(struct BL_Desc);		/* add enough margin to align to 16-byte boundary */		lp->FD_base = kmalloc(size + 15, GFP_KERNEL);		if (lp->FD_base == NULL) {			printk(KERN_ERR			       "Cannot allocate space for MSPETH descriptors!\n");			return false;		}		/* Move frame descriptors to uncached addresses. This prevents spurious IntBLEx interrupts. */		lp->FD_base = KSEG1ADDR(lp->FD_base);		memset(lp->FD_base, 0, size + 15);		if (mspeth_debug > 1)			printk(KERN_INFO "MSPETH (queue_init) %s:FD_base = %p\n", dev->name, lp->FD_base);	}	/* Align to a 16 byte boundary */	tmp_addr = (u32) (lp->FD_base+15) & ~15;	/* allocate the rx queue (aka free descriptor area) */	lp->rxfd_base = (struct Q_Desc *) tmp_addr;	lp->rxfd_curr = lp->rxfd_base;	tmp_addr += RX_BUF_NUM * sizeof(struct Q_Desc);	/* initialize the receive queue (these values are mostly overwritten by the MAC) */	for (i = 0; i < RX_BUF_NUM; i++) {		lp->rxfd_base[i].fd0.FDNext = 0x00000000;		lp->rxfd_base[i].fd0.FDSystem = 0x00000000;		lp->rxfd_base[i].fd0.FDStat = 0x00000000;		lp->rxfd_base[i].fd0.FDCtl = FD_CownsFD;		lp->rxfd_base[i].fd1.FDNext = 0x00000000;		lp->rxfd_base[i].fd1.FDSystem = 0x00000000;		lp->rxfd_base[i].fd1.FDStat = 0x00000000;		lp->rxfd_base[i].fd1.FDCtl = FD_CownsFD;	}	/* allocate the tx queue */	lp->txfd_base = (struct Q_Desc *) tmp_addr;	lp->tx_head = lp->tx_tail = 0;	tmp_addr += TX_BUF_NUM * sizeof(struct Q_Desc);	/* initialize the transmit queue */	for (i = 0; i < TX_BUF_NUM; i++) {		lp->txfd_base[i].fd.FDNext = (u32) (&lp->txfd_base[i + 1]);		lp->txfd_base[i].fd.FDSystem = 0x00000000;		lp->txfd_base[i].fd.FDStat = 0x00000000;		lp->txfd_base[i].fd.FDCtl = 0x00000000;	}	lp->txfd_base[TX_BUF_NUM - 1].fd.FDNext =	    (u32) (&lp->txfd_base[0]);	/* initialize the buffer list FD */	lp->blfd_ptr = (struct BL_Desc *) tmp_addr;	lp->blfd_ptr->fd.FDNext = (u32) lp->blfd_ptr;	lp->blfd_ptr->fd.FDCtl = (RX_BUF_NUM << 1 | FD_CownsFD);	/* allocate the array of sk_buff pointers */	if (lp->rx_skbp == NULL) {		lp->rx_skbp =		    (struct sk_buff **) kmalloc(((RX_BUF_NUM << 1) * sizeof(struct sk_buff *)),						GFP_KERNEL);		for (i = 0; i < RX_BUF_NUM << 1; i++)			lp->rx_skbp[i] = NULL;	}	/* allocate and initialize the actual sk_buffs proper */	for (i = 0; i < RX_BUF_NUM << 1; i++) {		/* free up old sk_buffs */		if (lp->rx_skbp[i] != NULL) {			dev_kfree_skb_any(lp->rx_skbp[i]);			lp->rx_skbp[i] = NULL;		}		/* allocate and align the skb */		skb = mspeth_alloc_skb(dev);		lp->rx_skbp[i] = skb;		/* initialize the buffer list entries		 * reserving 2 bytes in the skb results in a 16-byte aligned 		 * IP header, but also puts the skb->data at a 16-bit 		 * boundary.  The hardware requires a 32-bit aligned buffer.		 * So we round back two bytes and then instruct the hardware		 * to skip forward 2 bytes into the buffer.		 */		lp->blfd_ptr->bd[i].BuffData = (u32) skb->data & ~15;		lp->blfd_ptr->bd[i].BDCtl =		    (BD_CownsBD | (i << BD_RxBDID_SHIFT) |		     MSP_END_BUFSIZE);	}	/* configure the queue length and return */	atomic_set(&lp->tx_qspc, TX_BUF_NUM);	return true;}/************************************************************************** * Clear the queues of any outstanding packet.  This *will* cause packet * loss, so it's a recovery mechanism. */static void mspeth_clear_queues(struct net_device *dev){	struct mspeth_local *lp = (struct mspeth_local *) dev->priv;	int i;	struct sk_buff *skb;	if (lp->txfd_base != NULL) {		for (i = 0; i < TX_BUF_NUM; i++) {			if (lp->txfd_base[i].fd.FDSystem != 0x00000000) {				skb =				    (struct sk_buff *) lp->txfd_base[i].fd.				    FDSystem;				dev_kfree_skb_any(skb);			}			lp->txfd_base[i].fd.FDSystem = (0x00000000);		}	}	mspeth_queue_init(dev);}/************************************************************************** * converse of the mspeth_init_queues routine.  This frees all the memory * associated with the queues.  It must be called when closing the device.  */static void mspeth_free_queues(struct net_device *dev){	struct mspeth_local *lp = (struct mspeth_local *) dev->priv;	struct sk_buff *skb;	int i;	/* free up any TX buffers */	if (lp->txfd_base != NULL) {		for (i = 0; i < TX_BUF_NUM; i++) {			if (lp->txfd_base[i].fd.FDSystem != 0x00000000) {				skb =				    (struct sk_buff *) lp->txfd_base[i].fd.				    FDSystem;				dev_kfree_skb_any(skb);			}			lp->txfd_base[i].fd.FDSystem = 0x00000000;		}	}	/* free up the buffer list */	if (lp->rx_skbp != NULL) {		for (i = 0; i < RX_BUF_NUM << 1; i++) {			skb = lp->rx_skbp[i];			if (skb != NULL)				dev_kfree_skb_any(skb);		}		kfree(lp->rx_skbp);	}	/* free the descriptor area. Move FD_base back to KSEG0 before freeing it. */	if (lp->FD_base != NULL)		kfree(KSEG0ADDR(lp->FD_base));	/* nullify all the pointers and zero out the queue space */	lp->FD_base = NULL;	lp->rxfd_base = NULL;	lp->rxfd_curr = NULL;	lp->txfd_base = NULL;	lp->blfd_ptr = NULL;	lp->rx_skbp = NULL;	lp->tx_head = lp->tx_tail = 0;	atomic_set(&lp->tx_qspc, 0);}/************************************************************************** * Do a safe soft restart of the device.  This *will* cause packet loss, so * it's only used as a recovery mechanism */static void mspeth_soft_restart(struct net_device *dev){	int flags;	struct mspeth_local *lp = (struct mspeth_local *) dev->priv;	printk("MSPETH (soft_restart) %s: Soft device restart\n",	       dev->name);	netif_stop_queue(dev);	/* please don't interrupt me while I'm resetting everything */	local_irq_save(flags);	/* Try to restart the adaptor. */	mspeth_mac_reset(dev);	mspeth_clear_queues(dev);	mspeth_mac_init(dev);	//if (!(lp->option & MSP_OPT_SWITCH))		mspeth_phy_init(dev);	/* turn back on the interrupts */	local_irq_restore(flags);	/* and start up the queue!  We should be fixed .... */	dev->trans_start = jiffies;	netif_wake_queue(dev);}/************************************************************************** * Do a *hard* restart of the device.  This *will* cause packet loss, so * it's only used as a recovery mechanism */static void mspeth_hard_restart(struct net_device *dev){	int flags;	struct mspeth_local *lp = (struct mspeth_local *) dev->priv;	printk("MSPETH (hard_restart) %s: Hard device restart\n",	       dev->name);	netif_stop_queue(dev);	/* please don't interrupt me while I'm resetting everything */	local_irq_save(flags);	/* Try to restart the adaptor. */	mspeth_mac_reset(dev);	if (!(lp->option & MSP_OPT_SWITCH))		mspeth_phy_reset(dev);	mspeth_free_queues(dev);	mspeth_queue_init(dev);	mspeth_mac_init(dev);	//if (!(lp->option & MSP_OPT_SWITCH))		mspeth_phy_init(dev);	/* turn back on the interrupts */	local_irq_restore(flags);	/* and start up the queue!  We should be fixed .... */	dev->trans_start = jiffies;	netif_wake_queue(dev);}static void time_out(){	int i=0;//added by Shi ->		int j = 0;//added by Shi <-	//macTimer_on = 0;	//del_timer(&macTimer);	if(jiffies-stime>=TIME_OUT)	{		for(i=0;i<MAX_COUNT;i++)

⌨️ 快捷键说明

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