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

📄 skge.c

📁 linux嵌入式课程实践中的一个关于声卡驱动程序 。
💻 C
📖 第 1 页 / 共 5 页
字号:
	SetQueueSizes(pAC);	/* Print adapter specific string from vpd */	ProductStr(pAC);	printk("%s: %s\n", dev->name, pAC->DeviceStr);	/* Print configuration settings */	printk("      PrefPort:%c  RlmtMode:%s\n",		'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,		(pAC->RlmtMode==0)  ? "Check Link State" :		((pAC->RlmtMode==1) ? "Check Link State" : 		((pAC->RlmtMode==3) ? "Check Local Port" : 		((pAC->RlmtMode==7) ? "Check Segmentation" : 		((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));	SkGeYellowLED(pAC, pAC->IoBase, 1);	/*	 * Register the device here	 */	pAC->Next = sk98lin_root_dev;	sk98lin_root_dev = dev;	return (0);} /* SkGeBoardInit *//***************************************************************************** * * 	BoardAllocMem - allocate the memory for the descriptor rings * * Description: *	This function allocates the memory for all descriptor rings. *	Each ring is aligned for the desriptor alignment and no ring *	has a 4 GByte boundary in it (because the upper 32 bit must *	be constant for all descriptiors in one rings). * * Returns: *	SK_TRUE, if all memory could be allocated *	SK_FALSE, if not */static SK_BOOL BoardAllocMem(SK_AC	*pAC){caddr_t		pDescrMem;	/* pointer to descriptor memory area */size_t		AllocLength;	/* length of complete descriptor area */int		i;		/* loop counter */unsigned long	BusAddr;		/* rings plus one for alignment (do not cross 4 GB boundary) */	/* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */#if (BITS_PER_LONG == 32)	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;#else	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound		+ RX_RING_SIZE + 8;#endif	pDescrMem = pci_alloc_consistent(&pAC->PciDev, AllocLength,					 &pAC->pDescrMemDMA);	if (pDescrMem == NULL) {		return (SK_FALSE);	}	pAC->pDescrMem = pDescrMem;	/* Descriptors need 8 byte alignment, and this is ensured	 * by pci_alloc_consistent.	 */	BusAddr = (unsigned long) pAC->pDescrMemDMA;	for (i=0; i<pAC->GIni.GIMacsFound; i++) {		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,			("TX%d/A: pDescrMem: %lX,   PhysDescrMem: %lX\n",			i, (unsigned long) pDescrMem,			BusAddr));		pAC->TxPort[i][0].pTxDescrRing = pDescrMem;		pAC->TxPort[i][0].VTxDescrRing = BusAddr;		pDescrMem += TX_RING_SIZE;		BusAddr += TX_RING_SIZE;			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,			("RX%d: pDescrMem: %lX,   PhysDescrMem: %lX\n",			i, (unsigned long) pDescrMem,			(unsigned long)BusAddr));		pAC->RxPort[i].pRxDescrRing = pDescrMem;		pAC->RxPort[i].VRxDescrRing = BusAddr;		pDescrMem += RX_RING_SIZE;		BusAddr += RX_RING_SIZE;	} /* for */		return (SK_TRUE);} /* BoardAllocMem *//**************************************************************************** * *	BoardFreeMem - reverse of BoardAllocMem * * Description: *	Free all memory allocated in BoardAllocMem: adapter context, *	descriptor rings, locks. * * Returns:	N/A */static void BoardFreeMem(SK_AC		*pAC){size_t		AllocLength;	/* length of complete descriptor area */	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,		("BoardFreeMem\n"));#if (BITS_PER_LONG == 32)	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;#else	AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound		+ RX_RING_SIZE + 8;#endif	pci_free_consistent(&pAC->PciDev, AllocLength,			    pAC->pDescrMem, pAC->pDescrMemDMA);	pAC->pDescrMem = NULL;} /* BoardFreeMem *//***************************************************************************** * * 	BoardInitMem - initiate the descriptor rings * * Description: *	This function sets the descriptor rings up in memory. *	The adapter is initialized with the descriptor start addresses. * * Returns:	N/A */static void BoardInitMem(SK_AC	*pAC)	/* pointer to adapter context */{int	i;		/* loop counter */int	RxDescrSize;	/* the size of a rx descriptor rounded up to alignment*/int	TxDescrSize;	/* the size of a tx descriptor rounded up to alignment*/	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,		("BoardInitMem\n"));	RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;	pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;	TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;	pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;		for (i=0; i<pAC->GIni.GIMacsFound; i++) {		SetupRing(			pAC,			pAC->TxPort[i][0].pTxDescrRing,			pAC->TxPort[i][0].VTxDescrRing,			(RXD**)&pAC->TxPort[i][0].pTxdRingHead,			(RXD**)&pAC->TxPort[i][0].pTxdRingTail,			(RXD**)&pAC->TxPort[i][0].pTxdRingPrev,			&pAC->TxPort[i][0].TxdRingFree,			SK_TRUE);		SetupRing(			pAC,			pAC->RxPort[i].pRxDescrRing,			pAC->RxPort[i].VRxDescrRing,			&pAC->RxPort[i].pRxdRingHead,			&pAC->RxPort[i].pRxdRingTail,			&pAC->RxPort[i].pRxdRingPrev,			&pAC->RxPort[i].RxdRingFree,			SK_FALSE);	}} /* BoardInitMem *//***************************************************************************** * * 	SetupRing - create one descriptor ring * * Description: *	This function creates one descriptor ring in the given memory area. *	The head, tail and number of free descriptors in the ring are set. * * Returns: *	none */static void SetupRing(SK_AC		*pAC,void		*pMemArea,	/* a pointer to the memory area for the ring */uintptr_t	VMemArea,	/* the virtual bus address of the memory area */RXD		**ppRingHead,	/* address where the head should be written */RXD		**ppRingTail,	/* address where the tail should be written */RXD		**ppRingPrev,	/* address where the tail should be written */int		*pRingFree,	/* address where the # of free descr. goes */SK_BOOL		IsTx)		/* flag: is this a tx ring */{int	i;		/* loop counter */int	DescrSize;	/* the size of a descriptor rounded up to alignment*/int	DescrNum;	/* number of descriptors per ring */RXD	*pDescr;	/* pointer to a descriptor (receive or transmit) */RXD	*pNextDescr;	/* pointer to the next descriptor */RXD	*pPrevDescr;	/* pointer to the previous descriptor */uintptr_t VNextDescr;	/* the virtual bus address of the next descriptor */	if (IsTx == SK_TRUE) {		DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *			DESCR_ALIGN;		DescrNum = TX_RING_SIZE / DescrSize;	}	else {		DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *			DESCR_ALIGN;		DescrNum = RX_RING_SIZE / DescrSize;	}		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,		("Descriptor size: %d   Descriptor Number: %d\n",		DescrSize,DescrNum));		pDescr = (RXD*) pMemArea;	pPrevDescr = NULL;	pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);	VNextDescr = VMemArea + DescrSize;	for(i=0; i<DescrNum; i++) {		/* set the pointers right */		pDescr->VNextRxd = VNextDescr & 0xffffffffULL;		pDescr->pNextRxd = pNextDescr;		pDescr->TcpSumStarts = pAC->CsOfs;		/* advance on step */		pPrevDescr = pDescr;		pDescr = pNextDescr;		pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);		VNextDescr += DescrSize;	}	pPrevDescr->pNextRxd = (RXD*) pMemArea;	pPrevDescr->VNextRxd = VMemArea;	pDescr = (RXD*) pMemArea;	*ppRingHead = (RXD*) pMemArea;	*ppRingTail = *ppRingHead;	*ppRingPrev = pPrevDescr;	*pRingFree = DescrNum;} /* SetupRing *//***************************************************************************** * * 	PortReInitBmu - re-initiate the descriptor rings for one port * * Description: *	This function reinitializes the descriptor rings of one port *	in memory. The port must be stopped before. *	The HW is initialized with the descriptor start addresses. * * Returns: *	none */static void PortReInitBmu(SK_AC	*pAC,		/* pointer to adapter context */int	PortIndex)	/* index of the port for which to re-init */{	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,		("PortReInitBmu "));	/* set address of first descriptor of ring in BMU */	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+		TX_Q_CUR_DESCR_LOW,		(uint32_t)(((caddr_t)		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &		0xFFFFFFFF));	SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+		TX_Q_DESCR_HIGH,		(uint32_t)(((caddr_t)		(pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -		pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +		pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CUR_DESCR_LOW,		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -		pAC->RxPort[PortIndex].pRxDescrRing +		pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));	SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_DESCR_HIGH,		(uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -		pAC->RxPort[PortIndex].pRxDescrRing +		pAC->RxPort[PortIndex].VRxDescrRing) >> 32));} /* PortReInitBmu *//**************************************************************************** * *	SkGeIsr - handle adapter interrupts * * Description: *	The interrupt routine is called when the network adapter *	generates an interrupt. It may also be called if another device *	shares this interrupt vector with the driver. * * Returns: N/A * */static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs){struct net_device *dev = (struct net_device *)dev_id;DEV_NET		*pNet;SK_AC		*pAC;SK_U32		IntSrc;		/* interrupts source register contents */		pNet = (DEV_NET*) dev->priv;	pAC = pNet->pAC;		/*	 * Check and process if its our interrupt	 */	SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);	if (IntSrc == 0) {		return;	}	while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {#if 0 /* software irq currently not used */		if (IntSrc & IRQ_SW) {			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_INT_SRC,				("Software IRQ\n"));		}#endif		if (IntSrc & IRQ_EOF_RX1) {			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_INT_SRC,				("EOF RX1 IRQ\n"));			ReceiveIrq(pAC, &pAC->RxPort[0]);			SK_PNMI_CNT_RX_INTR(pAC,0);		}		if (IntSrc & IRQ_EOF_RX2) {			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_INT_SRC,				("EOF RX2 IRQ\n"));			ReceiveIrq(pAC, &pAC->RxPort[1]);			SK_PNMI_CNT_RX_INTR(pAC,1);		}#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */		if (IntSrc & IRQ_EOF_AS_TX1) {			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_INT_SRC,				("EOF AS TX1 IRQ\n"));			SK_PNMI_CNT_TX_INTR(pAC,0);			spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);			FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);			spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);		}		if (IntSrc & IRQ_EOF_AS_TX2) {			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_INT_SRC,				("EOF AS TX2 IRQ\n"));			SK_PNMI_CNT_TX_INTR(pAC,1);			spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);			FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);			spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);		}#if 0 /* only if sync. queues used */		if (IntSrc & IRQ_EOF_SY_TX1) {			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_INT_SRC,				("EOF SY TX1 IRQ\n"));			SK_PNMI_CNT_TX_INTR(pAC,0);			spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);			FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);			spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);			ClearTxIrq(pAC, 0, TX_PRIO_HIGH);		}		if (IntSrc & IRQ_EOF_SY_TX2) {			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_INT_SRC,				("EOF SY TX2 IRQ\n"));			SK_PNMI_CNT_TX_INTR(pAC,1);			spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);			FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);			spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);			ClearTxIrq(pAC, 1, TX_PRIO_HIGH);		}#endif /* 0 */#endif /* USE_TX_COMPLETE */		/* do all IO at once */		if (IntSrc & IRQ_EOF_RX1)			ClearAndStartRx(pAC, 0);		if (IntSrc & IRQ_EOF_RX2)			ClearAndStartRx(pAC, 1);#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */		if (IntSrc & IRQ_EOF_AS_TX1)			ClearTxIrq(pAC, 0, TX_PRIO_LOW);		if (IntSrc & IRQ_EOF_AS_TX2)			ClearTxIrq(pAC, 1, TX_PRIO_LOW);#endif		SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);	} /* while (IntSrc & IRQ_MASK != 0) */	if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,			("SPECIAL IRQ\n"));		pAC->CheckQueue = SK_FALSE;		spin_lock(&pAC->SlowPathLock);		if (IntSrc & SPECIAL_IRQS)			SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);		SkEventDispatcher(pAC, pAC->IoBase);		spin_unlock(&pAC->SlowPathLock);	}	/*	 * do it all again is case we cleared an interrupt that 	 * came in after handling the ring (OUTs may be delayed	 * in hardware buffers, but are through after IN)	 */	// ReceiveIrq(pAC, &pAC->RxPort[pAC->ActivePort]);	ReceiveIrq(pAC, &pAC->RxPort[0]);	ReceiveIrq(pAC, &pAC->RxPort[1]);	#if 0// #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */	spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);	FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);	spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);	spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);	FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);	spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);#if 0	/* only if sync. queues used */	spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);	FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);	spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);		spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);	FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);	spin_unlock(&pAC->TxPort[1][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;} /* SkGeIsr *//**************************************************************************** * *	SkGeIsrOnePort - handle adapter interrupts for single port adapter * * Description:

⌨️ 快捷键说明

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