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

📄 gt96100eth.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
	// now route ethernet interrupts to GT Int0 (eth0 and eth1 will be	// sharing it).	// FIX! The kernel's irq code should do this	intMask = GT96100_READ(GT96100_INT0_HIGH_MASK);	intMask |= 1 << gp->port_num;	GT96100_WRITE(GT96100_INT0_HIGH_MASK, intMask);}static void disable_ether_irq(struct net_device *dev){	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;	u32 intMask;	// FIX! The kernel's irq code should do this	intMask = GT96100_READ(GT96100_INT0_HIGH_MASK);	intMask &= ~(1 << gp->port_num);	GT96100_WRITE(GT96100_INT0_HIGH_MASK, intMask);	GT96100ETH_WRITE(gp, GT96100_ETH_INT_MASK, 0);}/* * Probe for a GT96100 ethernet controller. */int __init gt96100_probe(struct net_device *dev){	unsigned int base_addr = dev ? dev->base_addr : 0;	int i;#ifndef CONFIG_MIPS_GT96100ETH	return -ENODEV;#endif	if (gt96100_debug > 2)		printk(KERN_INFO "%s: gt96100_probe\n", dev->name);	if (base_addr >= KSEG0)	/* Check a single specified location. */		return gt96100_probe1(dev, base_addr, dev->irq, 0);	else if (base_addr != 0)	/* Don't probe at all. */		return -ENXIO;//	for (i = 0; i<NUM_INTERFACES; i++) {	for (i = NUM_INTERFACES - 1; i >= 0; i--) {		int base_addr = gt96100_iflist[i].port;#if 0		if (check_region(base_addr, GT96100_ETH_IO_SIZE)) {			printk(KERN_ERR			       "%s: gt96100_probe: ioaddr 0x%lx taken?\n",			       dev->name, base_addr);			continue;		}#endif		if (gt96100_probe1		    (dev, base_addr, gt96100_iflist[i].irq, i) == 0)			return 0;	}	return -ENODEV;}static int __initgt96100_probe1(struct net_device *dev, long ioaddr, int irq, int port_num){	static unsigned version_printed = 0;	struct gt96100_private *gp = NULL;	int i, retval;	u32 cpuConfig;	// FIX! probe for GT96100 by reading a suitable register	if (gt96100_debug > 2)		printk(KERN_INFO "gt96100_probe1: ioaddr 0x%lx, irq %d\n",		       ioaddr, irq);	request_region(ioaddr, GT96100_ETH_IO_SIZE, "GT96100ETH");	cpuConfig = GT96100_READ(GT96100_CPU_INTERF_CONFIG);	if (cpuConfig & (1 << 12)) {		printk(KERN_ERR		       "gt96100_probe1: must be in Big Endian mode!\n");		retval = -ENODEV;		goto free_region;	}	if (gt96100_debug > 2)		printk(KERN_INFO		       "gt96100_probe1: chip in Big Endian mode - cool\n");	/* Allocate a new 'dev' if needed. */	if (dev == NULL)		dev = init_etherdev(0, sizeof(struct gt96100_private));	if (gt96100_debug && version_printed++ == 0)		printk(version);	if (irq < 0) {		printk(KERN_ERR		       "gt96100_probe1: irq unknown - probing not supported\n");		retval = -ENODEV;		goto free_region;	}	printk(KERN_INFO "%s: GT-96100 ethernet found at 0x%lx, irq %d\n",	       dev->name, ioaddr, irq);	/* private struct aligned and zeroed by init_etherdev */	/* Fill in the 'dev' fields. */	dev->base_addr = ioaddr;	dev->irq = irq;	memcpy(dev->dev_addr, gt96100_station_addr[port_num],	       sizeof(dev->dev_addr));	printk(KERN_INFO "%s: HW Address ", dev->name);	for (i = 0; i < sizeof(dev->dev_addr); i++) {		printk("%2.2x", dev->dev_addr[i]);		printk(i < 5 ? ":" : "\n");	}	/* Initialize our private structure. */	if (dev->priv == NULL) {		gp =		    (struct gt96100_private *) kmalloc(sizeof(*gp),						       GFP_KERNEL);		if (gp == NULL) {			retval = -ENOMEM;			goto free_region;		}		dev->priv = gp;	}	gp = dev->priv;	memset(gp, 0, sizeof(*gp));	// clear it	gp->port_num = port_num;	gp->io_size = GT96100_ETH_IO_SIZE;	gp->port_offset = port_num * GT96100_ETH_IO_SIZE;	gp->phy_addr = port_num + 1;	if (gt96100_debug > 2)		printk(KERN_INFO "%s: gt96100_probe1, port %d\n",		       dev->name, gp->port_num);	// Allocate Rx and Tx descriptor rings	if (gp->rx_ring == NULL) {		// All descriptors in ring must be 16-byte aligned		gp->rx_ring = dmaalloc(sizeof(gt96100_rd_t) * RX_RING_SIZE				       +				       sizeof(gt96100_td_t) * TX_RING_SIZE,				       &gp->rx_ring_dma);		if (gp->rx_ring == NULL) {			retval = -ENOMEM;			goto free_region;		}		gp->tx_ring =		    (gt96100_td_t *) (gp->rx_ring + RX_RING_SIZE);		gp->tx_ring_dma =		    gp->rx_ring_dma + sizeof(gt96100_rd_t) * RX_RING_SIZE;	}	if (gt96100_debug > 2)		printk(KERN_INFO		       "%s: gt96100_probe1, rx_ring=%p, tx_ring=%p\n",		       dev->name, gp->rx_ring, gp->tx_ring);	// Allocate Rx Hash Table	if (gp->hash_table == NULL) {		gp->hash_table = (char *) dmaalloc(RX_HASH_TABLE_SIZE,						   &gp->hash_table_dma);		if (gp->hash_table == NULL) {			dmafree(sizeof(gt96100_rd_t) * RX_RING_SIZE				+ sizeof(gt96100_td_t) * TX_RING_SIZE,				gp->rx_ring);			retval = -ENOMEM;			goto free_region;		}	}	if (gt96100_debug > 2)		printk(KERN_INFO "%s: gt96100_probe1, hash=%p\n",		       dev->name, gp->hash_table);	spin_lock_init(&gp->lock);	dev->open = gt96100_open;	dev->hard_start_xmit = gt96100_tx;	dev->stop = gt96100_close;	dev->get_stats = gt96100_get_stats;	//dev->do_ioctl = gt96100_ioctl;	dev->set_multicast_list = gt96100_set_rx_mode;	dev->tx_timeout = gt96100_tx_timeout;	dev->watchdog_timeo = GT96100ETH_TX_TIMEOUT;	/* Fill in the fields of the device structure with ethernet values. */	ether_setup(dev);	return 0;      free_region:	release_region(ioaddr, gp->io_size);	unregister_netdev(dev);	if (dev->priv != NULL)		kfree(dev->priv);	kfree(dev);	printk(KERN_ERR "%s: gt96100_probe1 failed.  Returns %d\n",	       dev->name, retval);	return retval;}static int gt96100_init(struct net_device *dev){	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;	unsigned long flags;	u32 phyAD, ciu;	int i;	if (gt96100_debug > 2)		printk("%s: gt96100_init: dev=%p\n", dev->name, dev);	// Stop and disable Port	hard_stop(dev);	spin_lock_irqsave(&gp->lock, flags);	// First things first, set-up hash table	memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE);	// clear it	gp->hash_mode = 0;	// Add a single entry to hash table - our ethernet address	gt96100_add_hash_entry(dev, dev->dev_addr);	// Set-up DMA ptr to hash table	GT96100ETH_WRITE(gp, GT96100_ETH_HASH_TBL_PTR, gp->hash_table_dma);	if (gt96100_debug > 2)		printk("%s: gt96100_init: Hash Tbl Ptr=%x\n", dev->name,		       GT96100ETH_READ(gp, GT96100_ETH_HASH_TBL_PTR));	// Setup Tx descriptor ring	for (i = 0; i < TX_RING_SIZE; i++) {		gp->tx_ring[i].cmdstat = 0;	// CPU owns		gp->tx_ring[i].byte_cnt = 0;		gp->tx_ring[i].buff_ptr = 0;		gp->tx_ring[i].next =		    cpu_to_dma32(gp->tx_ring_dma +				 sizeof(gt96100_td_t) * (i + 1));	}	/* Wrap the ring. */	gp->tx_ring[i - 1].next = cpu_to_dma32(gp->tx_ring_dma);	// setup only the lowest priority TxCDP reg	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR0,			 gp->tx_ring_dma);	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR1, 0);	if (gt96100_debug > 2)		printk("%s: gt96100_init: Curr Tx Desc Ptr0=%x\n",		       dev->name, GT96100ETH_READ(gp,						  GT96100_ETH_CURR_TX_DESC_PTR0));	// Setup Rx descriptor ring 	for (i = 0; i < RX_RING_SIZE; i++) {		dma_addr_t rx_buff_dma;		gp->rx_ring[i].next =		    cpu_to_dma32(gp->rx_ring_dma +				 sizeof(gt96100_rd_t) * (i + 1));		if (gp->rx_buff[i] == NULL)			gp->rx_buff[i] =			    dmaalloc(PKT_BUF_SZ, &rx_buff_dma);		else			rx_buff_dma = virt_to_phys(gp->rx_buff[i]);		if (gp->rx_buff[i] == NULL)			break;		gp->rx_ring[i].buff_ptr = cpu_to_dma32(rx_buff_dma);		gp->rx_ring[i].buff_cnt_sz =		    cpu_to_dma32(PKT_BUF_SZ << rdBuffSzBit);		// Give ownership to device, enable interrupt		gp->rx_ring[i].cmdstat =		    cpu_to_dma32((u32) (rxOwn | rxEI));	}	if (i != RX_RING_SIZE) {		int j;		for (j = 0; j < RX_RING_SIZE; j++) {			if (gp->rx_buff[j]) {				dmafree(PKT_BUF_SZ, gp->rx_buff[j]);				gp->rx_buff[j] = NULL;			}		}		printk(KERN_ERR "%s: Rx ring allocation failed.\n",		       dev->name);		spin_unlock_irqrestore(&gp->lock, flags);		return -ENOMEM;	}	/* Wrap the ring. */	gp->rx_ring[i - 1].next = cpu_to_dma32(gp->rx_ring_dma);	// Set our MII PHY device address	phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);	phyAD &= ~(0x1f << (gp->port_num * 5));	phyAD |= gp->phy_addr << (gp->port_num * 5);	GT96100_WRITE(GT96100_ETH_PHY_ADDR_REG, phyAD);	if (gt96100_debug > 2)		printk("%s: gt96100_init: PhyAD=%x\n", dev->name,		       GT96100_READ(GT96100_ETH_PHY_ADDR_REG));	// Clear all the RxFDP and RXCDP regs...	for (i = 0; i < 4; i++) {		GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0 + i * 4,				 0);		GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0 + i * 4,				 0);	}	// and setup only the lowest priority RxFDP and RxCDP regs	GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0,			 gp->rx_ring_dma);	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0,			 gp->rx_ring_dma);	if (gt96100_debug > 2)		printk("%s: gt96100_init: 1st/Curr Rx Desc Ptr0=%x/%x\n",		       dev->name, GT96100ETH_READ(gp,						  GT96100_ETH_1ST_RX_DESC_PTR0),		       GT96100ETH_READ(gp, GT96100_ETH_CURR_RX_DESC_PTR0));	// init Rx/Tx indeces and pkt counters	gp->rx_next_out = gp->tx_next_in = gp->tx_next_out = 0;	gp->tx_count = 0;	// setup DMA	// FIX! this should be done by Kernel setup code	ciu = GT96100_READ(GT96100_CIU_ARBITER_CONFIG);	ciu |= (0x0c << (gp->port_num * 2));	// set Ether DMA req priority to high	// FIX! setting the following bit causes the EV96100 board to hang!!!	//ciu |= (1 << (24+gp->port_num));   // pull Ethernet port out of Reset???	// FIX! endian mode???	ciu &= ~(1 << 31);	// set desc endianess to Big	GT96100_WRITE(GT96100_CIU_ARBITER_CONFIG, ciu);	if (gt96100_debug > 2)		printk("%s: gt96100_init: CIU Config=%x/%x\n", dev->name,		       ciu, GT96100_READ(GT96100_CIU_ARBITER_CONFIG));	// We want the Rx/Tx DMA to write/read data to/from memory in	// Big Endian mode. Also set DMA Burst Size to 8 64Bit words.	// FIX! endian mode???	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_CONFIG,			 //sdcrBLMR | sdcrBLMT |			 (0xf << sdcrRCBit) | sdcrRIFB | (3 << sdcrBSZBit));	if (gt96100_debug > 2)		printk("%s: gt96100_init: SDMA Config=%x\n", dev->name,		       GT96100ETH_READ(gp, GT96100_ETH_SDMA_CONFIG));	// start Rx DMA	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, sdcmrERD);	if (gt96100_debug > 2)		printk("%s: gt96100_init: SDMA Comm=%x\n", dev->name,		       GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM));	// enable interrupts	enable_ether_irq(dev);	/*	 * Disable all Type-of-Service queueing. All Rx packets will be	 * treated normally and will be sent to the lowest priority	 * queue.	 *	 * Disable flow-control for now. FIX! support flow control?	 */	// clear all the MIB ctr regs	// Enable reg clear on read. FIX! desc of this bit is inconsistent	// in the GT-96100A datasheet.	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,			 pcxrFCTL | pcxrFCTLen | pcxrFLP);	read_mib_counters(gp);	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,			 pcxrFCTL | pcxrFCTLen | pcxrFLP | pcxrMIBclrMode);	if (gt96100_debug > 2)		printk("%s: gt96100_init: Port Config Ext=%x\n", dev->name,		       GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG_EXT));	// enable this port (set hash size to 1/2K)	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG, pcrEN | pcrHS);	if (gt96100_debug > 2)		printk("%s: gt96100_init: Port Config=%x\n", dev->name,		       GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG));	// we should now be receiving frames	if (gt96100_debug > 2)		dump_MII(dev);	spin_unlock_irqrestore(&gp->lock, flags);	return 0;}static int gt96100_open(struct net_device *dev){	int retval;	MOD_INC_USE_COUNT;	if (gt96100_debug > 2)		printk("%s: gt96100_open: dev=%p\n", dev->name, dev);	if ((retval = request_irq(dev->irq, &gt96100_interrupt,				  SA_SHIRQ, dev->name, dev))) {		printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name,		       dev->irq);		MOD_DEC_USE_COUNT;		return retval;	}	// Initialize and startup the GT-96100 ethernet port	if ((retval = gt96100_init(dev))) {

⌨️ 快捷键说明

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