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

📄 skge.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);	#endif /* 0 */#endif /* USE_TX_COMPLETE */	/* IRQ is processed - Enable IRQs again*/	SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);	return;} /* SkGeIsrOnePort *//**************************************************************************** * *	SkGeOpen - handle start of initialized adapter * * Description: *	This function starts the initialized adapter. *	The board level variable is set and the adapter is *	brought to full functionality. *	The device flags are set for operation. *	Do all necessary level 2 initialization, enable interrupts and *	give start command to RLMT. * * Returns: *	0 on success *	!= 0 on error */static int SkGeOpen(struct net_device	*dev){SK_AC		*pAC;		/* pointer to adapter context struct */unsigned int	Flags;		/* for spin lock */int		i;SK_EVPARA	EvPara;		/* an event parameter union */	pAC = (SK_AC*) dev->priv;		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,		("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));	if (pAC->BoardLevel == 0) {		/* level 1 init common modules here */		if (SkGeInit(pAC, pAC->IoBase, 1) != 0) {			printk("%s: HWInit(1) failed\n", pAC->dev->name);			return (-1);		}		SkI2cInit	(pAC, pAC->IoBase, 1);		SkEventInit	(pAC, pAC->IoBase, 1);		SkPnmiInit	(pAC, pAC->IoBase, 1);		SkAddrInit	(pAC, pAC->IoBase, 1);		SkRlmtInit	(pAC, pAC->IoBase, 1);		SkTimerInit	(pAC, pAC->IoBase, 1);		pAC->BoardLevel = 1;	}			/* level 2 init modules here */	SkGeInit	(pAC, pAC->IoBase, 2);	SkI2cInit	(pAC, pAC->IoBase, 2);	SkEventInit	(pAC, pAC->IoBase, 2);	SkPnmiInit	(pAC, pAC->IoBase, 2);	SkAddrInit	(pAC, pAC->IoBase, 2);	SkRlmtInit	(pAC, pAC->IoBase, 2);	SkTimerInit	(pAC, pAC->IoBase, 2);	pAC->BoardLevel = 2;		for (i=0; i<pAC->GIni.GIMacsFound; i++) {		// Enable transmit descriptor polling.		SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);		FillRxRing(pAC, &pAC->RxPort[i]);	}	SkGeYellowLED(pAC, pAC->IoBase, 1);#ifdef USE_INT_MOD// moderate only TX complete interrupts (these are not time critical)#define IRQ_MOD_MASK (IRQ_EOF_AS_TX1 | IRQ_EOF_AS_TX2)	{		unsigned long ModBase;		ModBase = 53125000 / INTS_PER_SEC;		SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);		SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK);		SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);	}#endif	/* enable Interrupts */	SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);	SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);	spin_lock_irqsave(&pAC->SlowPathLock, Flags);	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);	if (pAC->RlmtMode != 0) {		EvPara.Para32[0] = pAC->RlmtMode;		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,			EvPara);	}	SkEventDispatcher(pAC, pAC->IoBase);	spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);		MOD_INC_USE_COUNT;		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,		("SkGeOpen suceeded\n"));	return (0);} /* SkGeOpen *//**************************************************************************** * *	SkGeClose - Stop initialized adapter * * Description: *	Close initialized adapter. * * Returns: *	0 - on success *	error code - on error */static int SkGeClose(struct net_device	*dev){SK_AC		*pAC;unsigned int	Flags;		/* for spin lock */int		i;SK_EVPARA	EvPara;	netif_stop_queue(dev);	pAC = (SK_AC*) dev->priv;		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,		("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));	/* 	 * Clear multicast table, promiscuous mode ....	 */	SkAddrMcClear(pAC, pAC->IoBase, pAC->ActivePort, 0);	SkAddrPromiscuousChange(pAC, pAC->IoBase, pAC->ActivePort,		SK_PROM_MODE_NONE);	spin_lock_irqsave(&pAC->SlowPathLock, Flags);	/* disable interrupts */	SK_OUT32(pAC->IoBase, B0_IMSK, 0);	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);	SkEventDispatcher(pAC, pAC->IoBase);	SK_OUT32(pAC->IoBase, B0_IMSK, 0);	/* stop the hardware */	SkGeDeInit(pAC, pAC->IoBase);	pAC->BoardLevel = 0;		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);	for (i=0; i<pAC->GIni.GIMacsFound; i++) {		/* clear all descriptor rings */		ReceiveIrq(pAC, &pAC->RxPort[i]);		ClearRxRing(pAC, &pAC->RxPort[i]);		ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);	}	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,		("SkGeClose: done "));	MOD_DEC_USE_COUNT;		return (0);} /* SkGeClose *//***************************************************************************** * * 	SkGeXmit - Linux frame transmit function * * Description: *	The system calls this function to send frames onto the wire. *	It puts the frame in the tx descriptor ring. If the ring is *	full then, the 'tbusy' flag is set. * * Returns: *	0, if everything is ok *	!=0, on error * WARNING: returning 1 in 'tbusy' case caused system crashes (double *	allocated skb's) !!! */static int SkGeXmit(struct sk_buff *skb, struct net_device *dev){SK_AC		*pAC;int		Rc;	/* return code of XmitFrame */		pAC = (SK_AC*) dev->priv;	Rc = XmitFrame(pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb);	/* Transmitter out of resources? */	if (Rc <= 0)		netif_stop_queue(dev);	/* If not taken, give buffer ownership back to the	 * queueing layer.	 */	if (Rc < 0)		return (1);	dev->trans_start = jiffies;	return (0);} /* SkGeXmit */	/***************************************************************************** * * 	XmitFrame - fill one socket buffer into the transmit ring * * Description: *	This function puts a message into the transmit descriptor ring *	if there is a descriptors left. *	Linux skb's consist of only one continuous buffer. *	The first step locks the ring. It is held locked *	all time to avoid problems with SWITCH_../PORT_RESET. *	Then the descriptoris allocated. *	The second part is linking the buffer to the descriptor. *	At the very last, the Control field of the descriptor *	is made valid for the BMU and a start TX command is given *	if necessary. * * Returns: *	> 0 - on succes: the number of bytes in the message *	= 0 - on resource shortage: this frame sent or dropped, now *        the ring is full ( -> set tbusy) *	< 0 - on failure: other problems ( -> return failure to upper layers) */static int XmitFrame(SK_AC 		*pAC,		/* pointer to adapter context */TX_PORT		*pTxPort,	/* pointer to struct of port to send to */struct sk_buff	*pMessage)	/* pointer to send-message */{TXD		*pTxd;		/* the rxd to fill */unsigned int	Flags;SK_U64		PhysAddr;int		BytesSend;	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,		("X"));	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);	if (pTxPort->TxdRingFree == 0) {		/* no enough free descriptors in ring at the moment */		FreeTxDescriptors(pAC, pTxPort);		if (pTxPort->TxdRingFree == 0) {			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);			SK_PNMI_CNT_NO_TX_BUF(pAC);			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_TX_PROGRESS,				("XmitFrame failed\n"));			/* this message can not be sent now */			return (-1);		}	}	/* advance head counter behind descriptor needed for this frame */	pTxd = pTxPort->pTxdRingHead;	pTxPort->pTxdRingHead = pTxd->pNextTxd;	pTxPort->TxdRingFree--;	/* the needed descriptor is reserved now */		/* 	 * everything allocated ok, so add buffer to descriptor	 */#ifdef SK_DUMP_TX	DumpMsg(pMessage, "XmitFrame");#endif	/* set up descriptor and CONTROL dword */	PhysAddr = (SK_U64) pci_map_single(&pAC->PciDev,					   pMessage->data,					   pMessage->len,					   PCI_DMA_TODEVICE);	pTxd->VDataLow = (SK_U32)  (PhysAddr & 0xffffffff);	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);	pTxd->pMBuf = pMessage;	pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_STF |		TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE |#ifdef USE_TX_COMPLETE		TX_CTRL_EOF | TX_CTRL_EOF_IRQ | pMessage->len;#else		TX_CTRL_EOF | pMessage->len;#endif		if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) {		/* previous descriptor already done, so give tx start cmd */		/* StartTx(pAC, pTxPort->HwAddr); */		SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START);	}	pTxPort->pTxdRingPrev = pTxd;			BytesSend = pMessage->len;	/* after releasing the lock, the skb may be immidiately freed */	if (pTxPort->TxdRingFree != 0) {		spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);		return (BytesSend);	}	else {		/* ring full: set tbusy on return */		spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);		return (0);	}} /* XmitFrame *//***************************************************************************** * * 	FreeTxDescriptors - release descriptors from the descriptor ring * * Description: *	This function releases descriptors from a transmit ring if they *	have been sent by the BMU. *	If a descriptors is sent, it can be freed and the message can *	be freed, too. *	The SOFTWARE controllable bit is used to prevent running around a *	completely free ring for ever. If this bit is no set in the *	frame (by XmitFrame), this frame has never been sent or is *	already freed. *	The Tx descriptor ring lock must be held while calling this function !!! * * Returns: *	none */static void FreeTxDescriptors(SK_AC	*pAC,		/* pointer to the adapter context */TX_PORT	*pTxPort)	/* pointer to destination port structure */{TXD	*pTxd;		/* pointer to the checked descriptor */TXD	*pNewTail;	/* pointer to 'end' of the ring */SK_U32	Control;	/* TBControl field of descriptor */SK_U64	PhysAddr;	/* address of DMA mapping */	pNewTail = pTxPort->pTxdRingTail;	pTxd = pNewTail;		/* 	 * loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame	 * or TX_CTRL_OWN_BMU bit set in any frame	 */	while (1) {		Control = pTxd->TBControl;		if ((Control & TX_CTRL_SOFTWARE) == 0) {			/* 			 * software controllable bit is set in first			 * fragment when given to BMU. Not set means that			 * this fragment was never sent or is already 			 * freed ( -> ring completely free now).			 */			pTxPort->pTxdRingTail = pTxd;			netif_start_queue(pAC->dev);			return;		}		if (Control & TX_CTRL_OWN_BMU) {			pTxPort->pTxdRingTail = pTxd;			if (pTxPort->TxdRingFree > 0) {				netif_start_queue(pAC->dev);			}			return;		}				/* release the DMA mapping */		PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;		PhysAddr |= (SK_U64) pTxd->VDataLow;		pci_unmap_single(&pAC->PciDev, PhysAddr,				 pTxd->pMBuf->len,				 PCI_DMA_TODEVICE);		/* free message */		DEV_KFREE_SKB_ANY(pTxd->pMBuf);		pTxPort->TxdRingFree++;		pTxd->TBControl &= ~TX_CTRL_SOFTWARE;		pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */	} /* while(forever) */} /* FreeTxDescriptors *//***************************************************************************** * * 	FillRxRing - fill the receive ring with valid descriptors * * Description: *	This function fills the receive ring descriptors with data *	segments and makes them valid for the BMU. *	The active ring is filled completely, if possible. *	The non-active ring is filled only partial to save memory. * * Description of rx ring structure: *	head - points to the descriptor which will be used next by the BMU *	tail - points to the next descriptor to give to the BMU *	 * Returns:	N/A */static void FillRxRing(SK_AC		*pAC,		/* pointer to the adapter context */RX_PORT		*pRxPort)	/* ptr to port struct for which the ring				   should be filled */{unsigned int	Flags;	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);	while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {		if(!FillRxDescriptor(pAC, pRxPort))			break;	}	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);} /* FillRxRing *//***************************************************************************** * * 	FillRxDescriptor - fill one buffer into the receive ring * * Description: *	The function allocates a new receive buffer and *	puts it into the next descriptor. * * Returns: *	SK_TRUE - a buffer was added to the ring *	SK_FALSE - a buffer could not be added */static SK_BOOL FillRxDescriptor(SK_AC		*pAC,		/* pointer to the adapter context struct */RX_PORT		*pRxPort)	/* ptr to port struct of ring to fill */{struct sk_buff	*pMsgBlock;	/* pointer to a new message block */RXD		*pRxd;		/* the rxd to fill */SK_U16		Length;		/* data fragment length */SK_U64		PhysAddr;	/* physical address of a rx buffer */	pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);	if (pMsgBlock == NULL) {		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,			SK_DBGCAT_DRV_ENTRY,			("%s: Allocation of rx buffer failed !\n",			pAC->dev->name));		SK_PNMI_CNT_NO_RX_BUF(pAC);		return(SK_FALSE);	}	skb_reserve(pMsgBlock, 2); /* to align IP frames */	/* skb allocated ok, so add buffer */	pRxd = pRxPort->pRxdRingTail;	pRxPort->pRxdRingTail = pRxd->pNextRxd;

⌨️ 快捷键说明

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