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

📄 ucc_geth.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 2006-2007 Freescale Semicondutor, Inc. All rights reserved. * * Author: Shlomi Gridish <gridish@freescale.com> *	   Li Yang <leoli@freescale.com> * * Description: * QE UCC Gigabit Ethernet Driver * * This program is free software; you can redistribute  it and/or modify it * under  the terms of  the GNU General  Public License as published by the * Free Software Foundation;  either version 2 of the  License, or (at your * option) any later version. */#include <linux/kernel.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/stddef.h>#include <linux/interrupt.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/spinlock.h>#include <linux/mm.h>#include <linux/dma-mapping.h>#include <linux/fsl_devices.h>#include <linux/mii.h>#include <linux/phy.h>#include <linux/workqueue.h>#include <asm/of_platform.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/immap_qe.h>#include <asm/qe.h>#include <asm/ucc.h>#include <asm/ucc_fast.h>#include "ucc_geth.h"#include "ucc_geth_mii.h"#undef DEBUG#define ugeth_printk(level, format, arg...)  \        printk(level format "\n", ## arg)#define ugeth_dbg(format, arg...)            \        ugeth_printk(KERN_DEBUG , format , ## arg)#define ugeth_err(format, arg...)            \        ugeth_printk(KERN_ERR , format , ## arg)#define ugeth_info(format, arg...)           \        ugeth_printk(KERN_INFO , format , ## arg)#define ugeth_warn(format, arg...)           \        ugeth_printk(KERN_WARNING , format , ## arg)#ifdef UGETH_VERBOSE_DEBUG#define ugeth_vdbg ugeth_dbg#else#define ugeth_vdbg(fmt, args...) do { } while (0)#endif				/* UGETH_VERBOSE_DEBUG */#define UGETH_MSG_DEFAULT	(NETIF_MSG_IFUP << 1 ) - 1void uec_set_ethtool_ops(struct net_device *netdev);static DEFINE_SPINLOCK(ugeth_lock);static struct {	u32 msg_enable;} debug = { -1 };module_param_named(debug, debug.msg_enable, int, 0);MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 0xffff=all)");static struct ucc_geth_info ugeth_primary_info = {	.uf_info = {		    .bd_mem_part = MEM_PART_SYSTEM,		    .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES,		    .max_rx_buf_length = 1536,		    /* adjusted at startup if max-speed 1000 */		    .urfs = UCC_GETH_URFS_INIT,		    .urfet = UCC_GETH_URFET_INIT,		    .urfset = UCC_GETH_URFSET_INIT,		    .utfs = UCC_GETH_UTFS_INIT,		    .utfet = UCC_GETH_UTFET_INIT,		    .utftt = UCC_GETH_UTFTT_INIT,		    .ufpt = 256,		    .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET,		    .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,		    .tenc = UCC_FAST_TX_ENCODING_NRZ,		    .renc = UCC_FAST_RX_ENCODING_NRZ,		    .tcrc = UCC_FAST_16_BIT_CRC,		    .synl = UCC_FAST_SYNC_LEN_NOT_USED,		    },	.numQueuesTx = 1,	.numQueuesRx = 1,	.extendedFilteringChainPointer = ((uint32_t) NULL),	.typeorlen = 3072 /*1536 */ ,	.nonBackToBackIfgPart1 = 0x40,	.nonBackToBackIfgPart2 = 0x60,	.miminumInterFrameGapEnforcement = 0x50,	.backToBackInterFrameGap = 0x60,	.mblinterval = 128,	.nortsrbytetime = 5,	.fracsiz = 1,	.strictpriorityq = 0xff,	.altBebTruncation = 0xa,	.excessDefer = 1,	.maxRetransmission = 0xf,	.collisionWindow = 0x37,	.receiveFlowControl = 1,	.transmitFlowControl = 1,	.maxGroupAddrInHash = 4,	.maxIndAddrInHash = 4,	.prel = 7,	.maxFrameLength = 1518,	.minFrameLength = 64,	.maxD1Length = 1520,	.maxD2Length = 1520,	.vlantype = 0x8100,	.ecamptr = ((uint32_t) NULL),	.eventRegMask = UCCE_OTHER,	.pausePeriod = 0xf000,	.interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1},	.bdRingLenTx = {			TX_BD_RING_LEN,			TX_BD_RING_LEN,			TX_BD_RING_LEN,			TX_BD_RING_LEN,			TX_BD_RING_LEN,			TX_BD_RING_LEN,			TX_BD_RING_LEN,			TX_BD_RING_LEN},	.bdRingLenRx = {			RX_BD_RING_LEN,			RX_BD_RING_LEN,			RX_BD_RING_LEN,			RX_BD_RING_LEN,			RX_BD_RING_LEN,			RX_BD_RING_LEN,			RX_BD_RING_LEN,			RX_BD_RING_LEN},	.numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1,	.largestexternallookupkeysize =	    QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE,	.statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE |		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX |		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX,	.vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP,	.vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP,	.rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT,	.aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE,	.padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC,	.numThreadsTx = UCC_GETH_NUM_OF_THREADS_4,	.numThreadsRx = UCC_GETH_NUM_OF_THREADS_4,	.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,	.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,};static struct ucc_geth_info ugeth_info[8];#ifdef DEBUGstatic void mem_disp(u8 *addr, int size){	u8 *i;	int size16Aling = (size >> 4) << 4;	int size4Aling = (size >> 2) << 2;	int notAlign = 0;	if (size % 16)		notAlign = 1;	for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16)		printk("0x%08x: %08x %08x %08x %08x\r\n",		       (u32) i,		       *((u32 *) (i)),		       *((u32 *) (i + 4)),		       *((u32 *) (i + 8)), *((u32 *) (i + 12)));	if (notAlign == 1)		printk("0x%08x: ", (u32) i);	for (; (u32) i < (u32) addr + size4Aling; i += 4)		printk("%08x ", *((u32 *) (i)));	for (; (u32) i < (u32) addr + size; i++)		printk("%02x", *((u8 *) (i)));	if (notAlign == 1)		printk("\r\n");}#endif /* DEBUG */#ifdef CONFIG_UGETH_FILTERINGstatic void enqueue(struct list_head *node, struct list_head *lh){	unsigned long flags;	spin_lock_irqsave(&ugeth_lock, flags);	list_add_tail(node, lh);	spin_unlock_irqrestore(&ugeth_lock, flags);}#endif /* CONFIG_UGETH_FILTERING */static struct list_head *dequeue(struct list_head *lh){	unsigned long flags;	spin_lock_irqsave(&ugeth_lock, flags);	if (!list_empty(lh)) {		struct list_head *node = lh->next;		list_del(node);		spin_unlock_irqrestore(&ugeth_lock, flags);		return node;	} else {		spin_unlock_irqrestore(&ugeth_lock, flags);		return NULL;	}}static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, u8 *bd){	struct sk_buff *skb = NULL;	skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +				  UCC_GETH_RX_DATA_BUF_ALIGNMENT);	if (skb == NULL)		return NULL;	/* We need the data buffer to be aligned properly.  We will reserve	 * as many bytes as needed to align the data properly	 */	skb_reserve(skb,		    UCC_GETH_RX_DATA_BUF_ALIGNMENT -		    (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -					      1)));	skb->dev = ugeth->dev;	out_be32(&((struct qe_bd *)bd)->buf,		      dma_map_single(NULL,				     skb->data,				     ugeth->ug_info->uf_info.max_rx_buf_length +				     UCC_GETH_RX_DATA_BUF_ALIGNMENT,				     DMA_FROM_DEVICE));	out_be32((u32 *)bd, (R_E | R_I | (in_be32((u32 *)bd) & R_W)));	return skb;}static int rx_bd_buffer_set(struct ucc_geth_private *ugeth, u8 rxQ){	u8 *bd;	u32 bd_status;	struct sk_buff *skb;	int i;	bd = ugeth->p_rx_bd_ring[rxQ];	i = 0;	do {		bd_status = in_be32((u32*)bd);		skb = get_new_skb(ugeth, bd);		if (!skb)	/* If can not allocate data buffer,				abort. Cleanup will be elsewhere */			return -ENOMEM;		ugeth->rx_skbuff[rxQ][i] = skb;		/* advance the BD pointer */		bd += sizeof(struct qe_bd);		i++;	} while (!(bd_status & R_W));	return 0;}static int fill_init_enet_entries(struct ucc_geth_private *ugeth,				  volatile u32 *p_start,				  u8 num_entries,				  u32 thread_size,				  u32 thread_alignment,				  enum qe_risc_allocation risc,				  int skip_page_for_first_entry){	u32 init_enet_offset;	u8 i;	int snum;	for (i = 0; i < num_entries; i++) {		if ((snum = qe_get_snum()) < 0) {			if (netif_msg_ifup(ugeth))				ugeth_err("fill_init_enet_entries: Can not get SNUM.");			return snum;		}		if ((i == 0) && skip_page_for_first_entry)		/* First entry of Rx does not have page */			init_enet_offset = 0;		else {			init_enet_offset =			    qe_muram_alloc(thread_size, thread_alignment);			if (IS_ERR_VALUE(init_enet_offset)) {				if (netif_msg_ifup(ugeth))					ugeth_err("fill_init_enet_entries: Can not allocate DPRAM memory.");				qe_put_snum((u8) snum);				return -ENOMEM;			}		}		*(p_start++) =		    ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset		    | risc;	}	return 0;}static int return_init_enet_entries(struct ucc_geth_private *ugeth,				    volatile u32 *p_start,				    u8 num_entries,				    enum qe_risc_allocation risc,				    int skip_page_for_first_entry){	u32 init_enet_offset;	u8 i;	int snum;	for (i = 0; i < num_entries; i++) {		/* Check that this entry was actually valid --		needed in case failed in allocations */		if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {			snum =			    (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>			    ENET_INIT_PARAM_SNUM_SHIFT;			qe_put_snum((u8) snum);			if (!((i == 0) && skip_page_for_first_entry)) {			/* First entry of Rx does not have page */				init_enet_offset =				    (in_be32(p_start) &				     ENET_INIT_PARAM_PTR_MASK);				qe_muram_free(init_enet_offset);			}			*(p_start++) = 0;	/* Just for cosmetics */		}	}	return 0;}#ifdef DEBUGstatic int dump_init_enet_entries(struct ucc_geth_private *ugeth,				  volatile u32 *p_start,				  u8 num_entries,				  u32 thread_size,				  enum qe_risc_allocation risc,				  int skip_page_for_first_entry){	u32 init_enet_offset;	u8 i;	int snum;	for (i = 0; i < num_entries; i++) {		/* Check that this entry was actually valid --		needed in case failed in allocations */		if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {			snum =			    (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>			    ENET_INIT_PARAM_SNUM_SHIFT;			qe_put_snum((u8) snum);			if (!((i == 0) && skip_page_for_first_entry)) {			/* First entry of Rx does not have page */				init_enet_offset =				    (in_be32(p_start) &				     ENET_INIT_PARAM_PTR_MASK);				ugeth_info("Init enet entry %d:", i);				ugeth_info("Base address: 0x%08x",					   (u32)					   qe_muram_addr(init_enet_offset));				mem_disp(qe_muram_addr(init_enet_offset),					 thread_size);			}			p_start++;		}	}	return 0;}#endif#ifdef CONFIG_UGETH_FILTERINGstatic struct enet_addr_container *get_enet_addr_container(void){	struct enet_addr_container *enet_addr_cont;	/* allocate memory */	enet_addr_cont = kmalloc(sizeof(struct enet_addr_container), GFP_KERNEL);	if (!enet_addr_cont) {		ugeth_err("%s: No memory for enet_addr_container object.",			  __FUNCTION__);		return NULL;	}	return enet_addr_cont;}#endif /* CONFIG_UGETH_FILTERING */static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont){	kfree(enet_addr_cont);}static void set_mac_addr(__be16 __iomem *reg, u8 *mac){	out_be16(&reg[0], ((u16)mac[5] << 8) | mac[4]);	out_be16(&reg[1], ((u16)mac[3] << 8) | mac[2]);	out_be16(&reg[2], ((u16)mac[1] << 8) | mac[0]);}#ifdef CONFIG_UGETH_FILTERINGstatic int hw_add_addr_in_paddr(struct ucc_geth_private *ugeth,                                u8 *p_enet_addr, u8 paddr_num){	struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;

⌨️ 快捷键说明

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