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

📄 skfddi.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/************************ * *	mac_drv_get_desc_mem * *	This function is called by the hardware dependent module. *	It allocates the memory for the RxD and TxD descriptors. * *	This memory must be non-cached, non-movable and non-swappable. *	This memory should start at a physical page boundary. * Args *	smc - A pointer to the SMT context struct. * *	size - Size of memory in bytes to allocate. * Out *	!= 0	A pointer to the virtual address of the allocated memory. *	== 0	Allocation error. * ************************/void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size){	char *virt;	PRINTK(KERN_INFO "mac_drv_get_desc_mem\n");	// Descriptor memory must be aligned on 16-byte boundary.	virt = mac_drv_get_space(smc, size);	size = (u_int) (16 - (((unsigned long) virt) & 15UL));	size = size % 16;	PRINTK("Allocate %u bytes alignment gap ", size);	PRINTK("for descriptor memory.\n");	if (!mac_drv_get_space(smc, size)) {		printk("fddi: Unable to align descriptor memory.\n");		return (NULL);	}	return (virt + size);}				// mac_drv_get_desc_mem/************************ * *	mac_drv_virt2phys * *	Get the physical address of a given virtual address. * Args *	smc - A pointer to the SMT context struct. * *	virt - A (virtual) pointer into our 'shared' memory area. * Out *	Physical address of the given virtual address. * ************************/unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt){	return (smc->os.SharedMemDMA +		((char *) virt - (char *)smc->os.SharedMemAddr));}				// mac_drv_virt2phys/************************ * *	dma_master * *	The HWM calls this function, when the driver leads through a DMA *	transfer. If the OS-specific module must prepare the system hardware *	for the DMA transfer, it should do it in this function. * *	The hardware module calls this dma_master if it wants to send an SMT *	frame.  This means that the virt address passed in here is part of *      the 'shared' memory area. * Args *	smc - A pointer to the SMT context struct. * *	virt - The virtual address of the data. * *	len - The length in bytes of the data. * *	flag - Indicates the transmit direction and the buffer type: *		DMA_RD	(0x01)	system RAM ==> adapter buffer memory *		DMA_WR	(0x02)	adapter buffer memory ==> system RAM *		SMT_BUF (0x80)	SMT buffer * *	>> NOTE: SMT_BUF and DMA_RD are always set for PCI. << * Out *	Returns the pyhsical address for the DMA transfer. * ************************/u_long dma_master(struct s_smc * smc, void *virt, int len, int flag){	return (smc->os.SharedMemDMA +		((char *) virt - (char *)smc->os.SharedMemAddr));}				// dma_master/************************ * *	dma_complete * *	The hardware module calls this routine when it has completed a DMA *	transfer. If the operating system dependent module has set up the DMA *	channel via dma_master() (e.g. Windows NT or AIX) it should clean up *	the DMA channel. * Args *	smc - A pointer to the SMT context struct. * *	descr - A pointer to a TxD or RxD, respectively. * *	flag - Indicates the DMA transfer direction / SMT buffer: *		DMA_RD	(0x01)	system RAM ==> adapter buffer memory *		DMA_WR	(0x02)	adapter buffer memory ==> system RAM *		SMT_BUF (0x80)	SMT buffer (managed by HWM) * Out *	Nothing. * ************************/void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag){	/* For TX buffers, there are two cases.  If it is an SMT transmit	 * buffer, there is nothing to do since we use consistent memory	 * for the 'shared' memory area.  The other case is for normal	 * transmit packets given to us by the networking stack, and in	 * that case we cleanup the PCI DMA mapping in mac_drv_tx_complete	 * below.	 *	 * For RX buffers, we have to unmap dynamic PCI DMA mappings here	 * because the hardware module is about to potentially look at	 * the contents of the buffer.  If we did not call the PCI DMA	 * unmap first, the hardware module could read inconsistent data.	 */	if (flag & DMA_WR) {		skfddi_priv *bp = &smc->os;		volatile struct s_smt_fp_rxd *r = &descr->r;		/* If SKB is NULL, we used the local buffer. */		if (r->rxd_os.skb && r->rxd_os.dma_addr) {			int MaxFrameSize = bp->MaxFrameSize;			pci_unmap_single(&bp->pdev, r->rxd_os.dma_addr,					 MaxFrameSize, PCI_DMA_FROMDEVICE);			r->rxd_os.dma_addr = 0;		}	}}				// dma_complete/************************ * *	mac_drv_tx_complete * *	Transmit of a packet is complete. Release the tx staging buffer. * * Args *	smc - A pointer to the SMT context struct. * *	txd - A pointer to the last TxD which is used by the frame. * Out *	Returns nothing. * ************************/void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd){	struct sk_buff *skb;	PRINTK(KERN_INFO "entering mac_drv_tx_complete\n");	// Check if this TxD points to a skb	if (!(skb = txd->txd_os.skb)) {		PRINTK("TXD with no skb assigned.\n");		return;	}	txd->txd_os.skb = NULL;	// release the DMA mapping	pci_unmap_single(&smc->os.pdev, txd->txd_os.dma_addr,			 skb->len, PCI_DMA_TODEVICE);	txd->txd_os.dma_addr = 0;	smc->os.MacStat.gen.tx_packets++;	// Count transmitted packets.	smc->os.MacStat.gen.tx_bytes+=skb->len;	// Count bytes	// free the skb	dev_kfree_skb_irq(skb);	PRINTK(KERN_INFO "leaving mac_drv_tx_complete\n");}				// mac_drv_tx_complete/************************ * * dump packets to logfile * ************************/#ifdef DUMPPACKETSvoid dump_data(unsigned char *Data, int length){	int i, j;	unsigned char s[255], sh[10];	if (length > 64) {		length = 64;	}	printk(KERN_INFO "---Packet start---\n");	for (i = 0, j = 0; i < length / 8; i++, j += 8)		printk(KERN_INFO "%02x %02x %02x %02x %02x %02x %02x %02x\n",		       Data[j + 0], Data[j + 1], Data[j + 2], Data[j + 3],		       Data[j + 4], Data[j + 5], Data[j + 6], Data[j + 7]);	strcpy(s, "");	for (i = 0; i < length % 8; i++) {		sprintf(sh, "%02x ", Data[j + i]);		strcat(s, sh);	}	printk(KERN_INFO "%s\n", s);	printk(KERN_INFO "------------------\n");}				// dump_data#else#define dump_data(data,len)#endif				// DUMPPACKETS/************************ * *	mac_drv_rx_complete * *	The hardware module calls this function if an LLC frame is received *	in a receive buffer. Also the SMT, NSA, and directed beacon frames *	from the network will be passed to the LLC layer by this function *	if passing is enabled. * *	mac_drv_rx_complete forwards the frame to the LLC layer if it should *	be received. It also fills the RxD ring with new receive buffers if *	some can be queued. * Args *	smc - A pointer to the SMT context struct. * *	rxd - A pointer to the first RxD which is used by the receive frame. * *	frag_count - Count of RxDs used by the received frame. * *	len - Frame length. * Out *	Nothing. * ************************/void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,			 int frag_count, int len){	skfddi_priv *bp = &smc->os;	struct sk_buff *skb;	unsigned char *virt, *cp;	unsigned short ri;	u_int RifLength;	PRINTK(KERN_INFO "entering mac_drv_rx_complete (len=%d)\n", len);	if (frag_count != 1) {	// This is not allowed to happen.		printk("fddi: Multi-fragment receive!\n");		goto RequeueRxd;	// Re-use the given RXD(s).	}	skb = rxd->rxd_os.skb;	if (!skb) {		PRINTK(KERN_INFO "No skb in rxd\n");		smc->os.MacStat.gen.rx_errors++;		goto RequeueRxd;	}	virt = skb->data;	// The DMA mapping was released in dma_complete above.	dump_data(skb->data, len);	/*	 * FDDI Frame format:	 * +-------+-------+-------+------------+--------+------------+	 * | FC[1] | DA[6] | SA[6] | RIF[0..18] | LLC[3] | Data[0..n] |	 * +-------+-------+-------+------------+--------+------------+	 *	 * FC = Frame Control	 * DA = Destination Address	 * SA = Source Address	 * RIF = Routing Information Field	 * LLC = Logical Link Control	 */	// Remove Routing Information Field (RIF), if present.	if ((virt[1 + 6] & FDDI_RII) == 0)		RifLength = 0;	else {		int n;// goos: RIF removal has still to be tested		PRINTK(KERN_INFO "RIF found\n");		// Get RIF length from Routing Control (RC) field.		cp = virt + FDDI_MAC_HDR_LEN;	// Point behind MAC header.		ri = ntohs(*((unsigned short *) cp));		RifLength = ri & FDDI_RCF_LEN_MASK;		if (len < (int) (FDDI_MAC_HDR_LEN + RifLength)) {			printk("fddi: Invalid RIF.\n");			goto RequeueRxd;	// Discard the frame.		}		virt[1 + 6] &= ~FDDI_RII;	// Clear RII bit.		// regions overlap		virt = cp + RifLength;		for (n = FDDI_MAC_HDR_LEN; n; n--)			*--virt = *--cp;		// adjust sbd->data pointer		skb_pull(skb, RifLength);		len -= RifLength;		RifLength = 0;	}	// Count statistics.	smc->os.MacStat.gen.rx_packets++;	// Count indicated receive						// packets.	smc->os.MacStat.gen.rx_bytes+=len;	// Count bytes.	// virt points to header again	if (virt[1] & 0x01) {	// Check group (multicast) bit.		smc->os.MacStat.gen.multicast++;	}	// deliver frame to system	rxd->rxd_os.skb = NULL;	skb_trim(skb, len);	skb->protocol = fddi_type_trans(skb, bp->dev);	skb->dev = bp->dev;	/* pass up device pointer */	netif_rx(skb);	bp->dev->last_rx = jiffies;	HWM_RX_CHECK(smc, RX_LOW_WATERMARK);	return;      RequeueRxd:	PRINTK(KERN_INFO "Rx: re-queue RXD.\n");	mac_drv_requeue_rxd(smc, rxd, frag_count);	smc->os.MacStat.gen.rx_errors++;	// Count receive packets						// not indicated.}				// mac_drv_rx_complete/************************ * *	mac_drv_requeue_rxd * *	The hardware module calls this function to request the OS-specific *	module to queue the receive buffer(s) represented by the pointer *	to the RxD and the frag_count into the receive queue again. This *	buffer was filled with an invalid frame or an SMT frame. * Args *	smc - A pointer to the SMT context struct. * *	rxd - A pointer to the first RxD which is used by the receive frame. * *	frag_count - Count of RxDs used by the received frame. * Out *	Nothing. * ************************/void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,			 int frag_count){	volatile struct s_smt_fp_rxd *next_rxd;	volatile struct s_smt_fp_rxd *src_rxd;	struct sk_buff *skb;	int MaxFrameSize;	unsigned char *v_addr;	dma_addr_t b_addr;	if (frag_count != 1)	// This is not allowed to happen.		printk("fddi: Multi-fragment requeue!\n");	MaxFrameSize = smc->os.MaxFrameSize;	src_rxd = rxd;	for (; frag_count > 0; frag_count--) {		next_rxd = src_rxd->rxd_next;		rxd = HWM_GET_CURR_RXD(smc);		skb = src_rxd->rxd_os.skb;		if (skb == NULL) {	// this should not happen			PRINTK("Requeue with no skb in rxd!\n");			skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC);			if (skb) {				// we got a skb				rxd->rxd_os.skb = skb;				skb_reserve(skb, 3);				skb_put(skb, MaxFrameSize);				v_addr = skb->data;				b_addr = pci_map_single(&smc->os.pdev,							v_addr,							MaxFrameSize,							PCI_DMA_FROMDEVICE);				rxd->rxd_os.dma_addr = b_addr;			} else {				// no skb available, use local buffer				PRINTK("Queueing invalid buffer!\n");				rxd->rxd_os.skb = NULL;				v_addr = smc->os.LocalRxBuffer;				b_addr = smc->os.LocalRxBufferDMA;			}		} else {			// we use skb from old rxd			rxd->rxd_os.skb = skb;			v_addr = skb->data;			b_addr = pci_map_single(&smc->os.pdev,						v_addr,						MaxFrameSize,						PCI_DMA_FROMDEVICE);			rxd->rxd_os.dma_addr = b_addr;		}		hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize,			    FIRST_FRAG | LAST_FRAG);		src_rxd = next_rxd;	}}				// mac_drv_requeue_rxd/************************ * *	mac_drv_fill_rxd * *	The hardware module calls this function at initialization time *	to fill the RxD ring with receive buffers. It is also called by *	mac_drv_rx_complete if rx_free is large enough to queue some new *	receive buffers into the RxD ring. mac_drv_fill_rxd queues new *	receive buffers as long as enough RxDs and receive buffers are *	available. * Args *	smc - A pointer to the SMT context struct. * Out *	Nothing. * ************************/void mac_drv_fill_rxd(struct s_smc *smc){	int MaxFrameSize;	unsigned char *v_addr;	unsigned long b_addr;	struct sk_buff *skb;	volatile struct s_smt_fp_rxd *rxd;

⌨️ 快捷键说明

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