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

📄 fealnx.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
	static int printed_version;	if (!printed_version++)		printk (version);#endif		card_idx++;	sprintf(boardname, "fealnx%d", card_idx);		option = card_idx < MAX_UNITS ? options[card_idx] : 0;	i = pci_enable_device(pdev);	if (i) return i;	pci_set_master(pdev);	#ifdef USE_IO_OPS	ioaddr = pci_resource_len(pdev, 0);#else	ioaddr = pci_resource_len(pdev, 1);#endif	if (ioaddr < MIN_REGION_SIZE) {		printk(KERN_ERR "%s: region size %ld too small, aborting\n",		       boardname, ioaddr);		return -ENODEV;	}	i = pci_request_regions(pdev, boardname);	if (i) return i;		irq = pdev->irq;#ifdef USE_IO_OPS	ioaddr = pci_resource_start(pdev, 0);#else	ioaddr = (long) ioremap(pci_resource_start(pdev, 1),				pci_resource_len(pdev, 1));	if (!ioaddr) {		err = -ENOMEM;		goto err_out_res;	}#endif		dev = alloc_etherdev(sizeof(struct netdev_private));	if (!dev) {		err = -ENOMEM;		goto err_out_unmap;	}	SET_MODULE_OWNER(dev);	/* read ethernet id */	for (i = 0; i < 6; ++i)		dev->dev_addr[i] = readb(ioaddr + PAR0 + i);	/* Reset the chip to erase previous misconfiguration. */	writel(0x00000001, ioaddr + BCR);	dev->base_addr = ioaddr;	dev->irq = irq;	/* Make certain the descriptor lists are aligned. */	np = dev->priv;	spin_lock_init(&np->lock);	np->pci_dev = pdev;	np->flags = skel_netdrv_tbl[chip_id].flags;	pci_set_drvdata(pdev, dev);	np->mii.dev = dev;	np->mii.mdio_read = mdio_read;	np->mii.mdio_write = mdio_write;	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);	if (!ring_space) {		err = -ENOMEM;		goto err_out_free_dev;	}	np->rx_ring = (struct fealnx_desc *)ring_space;	np->rx_ring_dma = ring_dma;	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);	if (!ring_space) {		err = -ENOMEM;		goto err_out_free_rx;	}	np->tx_ring = (struct fealnx_desc *)ring_space;	np->tx_ring_dma = ring_dma;	/* find the connected MII xcvrs */	if (np->flags == HAS_MII_XCVR) {		int phy, phy_idx = 0;		for (phy = 1; phy < 32 && phy_idx < 4; phy++) {			int mii_status = mdio_read(dev, phy, 1);			if (mii_status != 0xffff && mii_status != 0x0000) {				np->phys[phy_idx++] = phy;				printk(KERN_INFO				       "%s: MII PHY found at address %d, status "				       "0x%4.4x.\n", dev->name, phy, mii_status);				/* get phy type */				{					unsigned int data;					data = mdio_read(dev, np->phys[0], 2);					if (data == SeeqPHYID0)						np->PHYType = SeeqPHY;					else if (data == AhdocPHYID0)						np->PHYType = AhdocPHY;					else if (data == MarvellPHYID0)						np->PHYType = MarvellPHY;					else if (data == MysonPHYID0)						np->PHYType = Myson981;					else if (data == LevelOnePHYID0)						np->PHYType = LevelOnePHY;					else						np->PHYType = OtherPHY;				}			}		}		np->mii_cnt = phy_idx;		if (phy_idx == 0) {			printk(KERN_WARNING "%s: MII PHY not found -- this device may "			       "not operate correctly.\n", dev->name);		}	} else {		np->phys[0] = 32;/* 89/6/23 add, (begin) */		/* get phy type */		if (readl(dev->base_addr + PHYIDENTIFIER) == MysonPHYID)			np->PHYType = MysonPHY;		else			np->PHYType = OtherPHY;	}	np->mii.phy_id = np->phys[0];	if (dev->mem_start)		option = dev->mem_start;	/* The lower four bits are the media type. */	if (option > 0) {		if (option & 0x200)			np->mii.full_duplex = 1;		np->default_port = option & 15;	}	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)		np->mii.full_duplex = full_duplex[card_idx];	if (np->mii.full_duplex) {		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);/* 89/6/13 add, (begin) *///      if (np->PHYType==MarvellPHY)		if ((np->PHYType == MarvellPHY) || (np->PHYType == LevelOnePHY)) {			unsigned int data;			data = mdio_read(dev, np->phys[0], 9);			data = (data & 0xfcff) | 0x0200;			mdio_write(dev, np->phys[0], 9, data);		}/* 89/6/13 add, (end) */		if (np->flags == HAS_MII_XCVR)			mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);		else			writel(ADVERTISE_FULL, dev->base_addr + ANARANLPAR);		np->mii.duplex_lock = 1;	}	/* The chip-specific entries in the device structure. */	dev->open = &netdev_open;	dev->hard_start_xmit = &start_tx;	dev->stop = &netdev_close;	dev->get_stats = &get_stats;	dev->set_multicast_list = &set_rx_mode;	dev->do_ioctl = &mii_ioctl;	dev->tx_timeout = tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;		err = register_netdev(dev);	if (err)		goto err_out_free_tx;	printk(KERN_INFO "%s: %s at 0x%lx, ",	       dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);	for (i = 0; i < 5; i++)		printk("%2.2x:", dev->dev_addr[i]);	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);	return 0;err_out_free_tx:	pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);err_out_free_rx:	pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);err_out_free_dev:	kfree(dev);err_out_unmap:#ifndef USE_IO_OPS	iounmap((void *)ioaddr);err_out_res:#endif	pci_release_regions(pdev);	return err;}static void __devexit fealnx_remove_one(struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	if (dev) {		struct netdev_private *np = dev->priv;		pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring,			np->tx_ring_dma);		pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,			np->rx_ring_dma);		unregister_netdev(dev);#ifndef USE_IO_OPS		iounmap((void *)dev->base_addr);#endif		kfree(dev);		pci_release_regions(pdev);		pci_set_drvdata(pdev, NULL);	} else		printk(KERN_ERR "fealnx: remove for unknown device\n");}unsigned int m80x_read_tick(void)/* function: Reads the Timer tick count register which decrements by 2 from  *//*           65536 to 0 every 1/36.414 of a second. Each 2 decrements of the *//*           count represents 838 nsec's.                                    *//* input   : none.                                                           *//* output  : none.                                                           */{	unsigned char tmp;	int value;	writeb((char) 0x06, 0x43);	// Command 8254 to latch T0's count	// now read the count.	tmp = (unsigned char) readb(0x40);	value = ((int) tmp) << 8;	tmp = (unsigned char) readb(0x40);	value |= (((int) tmp) & 0xff);	return (value);}void m80x_delay(unsigned int interval)/* function: to wait for a specified time.                                   *//* input   : interval ... the specified time.                                *//* output  : none.                                                           */{	unsigned int interval1, interval2, i = 0;	interval1 = m80x_read_tick();	// get initial value	do {		interval2 = m80x_read_tick();		if (interval1 < interval2)			interval1 = interval2;		++i;	} while (((interval1 - interval2) < (ushort) interval) && (i < 65535));}static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad){	ulong miir;	int i;	unsigned int mask, data;	/* enable MII output */	miir = (ulong) readl(miiport);	miir &= 0xfffffff0;	miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;	/* send 32 1's preamble */	for (i = 0; i < 32; i++) {		/* low MDC; MDO is already high (miir) */		miir &= ~MASK_MIIR_MII_MDC;		writel(miir, miiport);		/* high MDC */		miir |= MASK_MIIR_MII_MDC;		writel(miir, miiport);	}	/* calculate ST+OP+PHYAD+REGAD+TA */	data = opcode | (phyad << 7) | (regad << 2);	/* sent out */	mask = 0x8000;	while (mask) {		/* low MDC, prepare MDO */		miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);		if (mask & data)			miir |= MASK_MIIR_MII_MDO;		writel(miir, miiport);		/* high MDC */		miir |= MASK_MIIR_MII_MDC;		writel(miir, miiport);		m80x_delay(30);		/* next */		mask >>= 1;		if (mask == 0x2 && opcode == OP_READ)			miir &= ~MASK_MIIR_MII_WRITE;	}	return miir;}static int mdio_read(struct net_device *dev, int phyad, int regad){	long miiport = dev->base_addr + MANAGEMENT;	ulong miir;	unsigned int mask, data;	miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);	/* read data */	mask = 0x8000;	data = 0;	while (mask) {		/* low MDC */		miir &= ~MASK_MIIR_MII_MDC;		writel(miir, miiport);		/* read MDI */		miir = readl(miiport);		if (miir & MASK_MIIR_MII_MDI)			data |= mask;		/* high MDC, and wait */		miir |= MASK_MIIR_MII_MDC;		writel(miir, miiport);		m80x_delay((int) 30);		/* next */		mask >>= 1;	}	/* low MDC */	miir &= ~MASK_MIIR_MII_MDC;	writel(miir, miiport);	return data & 0xffff;}static void mdio_write(struct net_device *dev, int phyad, int regad, int data){	long miiport = dev->base_addr + MANAGEMENT;	ulong miir;	unsigned int mask;	miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);	/* write data */	mask = 0x8000;	while (mask) {		/* low MDC, prepare MDO */		miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);		if (mask & data)			miir |= MASK_MIIR_MII_MDO;		writel(miir, miiport);		/* high MDC */		miir |= MASK_MIIR_MII_MDC;		writel(miir, miiport);		/* next */		mask >>= 1;	}	/* low MDC */	miir &= ~MASK_MIIR_MII_MDC;	writel(miir, miiport);	return;}static int netdev_open(struct net_device *dev){	struct netdev_private *np = dev->priv;	long ioaddr = dev->base_addr;	writel(0x00000001, ioaddr + BCR);	/* Reset */	if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev))		return -EAGAIN;	init_ring(dev);	writel(np->rx_ring_dma, ioaddr + RXLBA);	writel(np->tx_ring_dma, ioaddr + TXLBA);	/* Initialize other registers. */	/* Configure the PCI bus bursts and FIFO thresholds.	   486: Set 8 longword burst.	   586: no burst limit.	   Burst length 5:3	   0 0 0   1	   0 0 1   4	   0 1 0   8	   0 1 1   16	   1 0 0   32	   1 0 1   64	   1 1 0   128	   1 1 1   256	   Wait the specified 50 PCI cycles after a reset by initializing	   Tx and Rx queues and the address filter list.	   FIXME (Ueimor): optimistic for alpha + posted writes ? */#if defined(__powerpc__) || defined(__sparc__)// 89/9/1 modify, //   np->bcrvalue=0x04 | 0x0x38;  /* big-endian, 256 burst length */	np->bcrvalue = 0x04 | 0x10;	/* big-endian, tx 8 burst length */	np->crvalue = 0xe00;	/* rx 128 burst length */#elif defined(__alpha__) || defined(__x86_64__)// 89/9/1 modify, //   np->bcrvalue=0x38;           /* little-endian, 256 burst length */	np->bcrvalue = 0x10;	/* little-endian, 8 burst length */	np->crvalue = 0xe00;	/* rx 128 burst length */#elif defined(__i386__)#if defined(MODULE)// 89/9/1 modify, //   np->bcrvalue=0x38;           /* little-endian, 256 burst length */	np->bcrvalue = 0x10;	/* little-endian, 8 burst length */	np->crvalue = 0xe00;	/* rx 128 burst length */#else	/* When not a module we can work around broken '486 PCI boards. */#define x86 boot_cpu_data.x86// 89/9/1 modify, //   np->bcrvalue=(x86 <= 4 ? 0x10 : 0x38);	np->bcrvalue = 0x10;	np->crvalue = (x86 <= 4 ? 0xa00 : 0xe00);	if (x86 <= 4)		printk(KERN_INFO "%s: This is a 386/486 PCI system, setting burst "		       "length to %x.\n", dev->name, (x86 <= 4 ? 0x10 : 0x38));#endif#else// 89/9/1 modify,//   np->bcrvalue=0x38;	np->bcrvalue = 0x10;	np->cralue = 0xe00;	/* rx 128 burst length */#warning Processor architecture undefined!#endif// 89/12/29 add,// 90/1/16 modify,//   np->imrvalue=FBE|TUNF|CNTOVF|RBU|TI|RI;	np->imrvalue = TUNF | CNTOVF | RBU | TI | RI;	if (np->pci_dev->device == 0x891) {		np->bcrvalue |= 0x200;	/* set PROG bit */		np->crvalue |= 0x02000000;	/* set enhanced bit */		np->imrvalue |= ETI;	}	writel(np->bcrvalue, ioaddr + BCR);	if (dev->if_port == 0)		dev->if_port = np->default_port;	writel(0, dev->base_addr + RXPDR);// 89/9/1 modify,//   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */	np->crvalue |= 0x00e40001;	/* tx store and forward, tx/rx enable */	np->mii.full_duplex = np->mii.duplex_lock;	getlinkstatus(dev);	if (np->linkok)		getlinktype(dev);	set_rx_mode(dev);	netif_start_queue(dev);	/* Clear and Enable interrupts by setting the interrupt mask. */	writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);	writel(np->imrvalue, ioaddr + IMR);	if (debug)		printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name);	/* Set the timer to check for link beat. */	init_timer(&np->timer);	np->timer.expires = RUN_AT(3 * HZ);	np->timer.data = (unsigned long) dev;	np->timer.function = &netdev_timer;	/* timer handler */	add_timer(&np->timer);	return 0;}static void getlinkstatus(struct net_device *dev)/* function: Routine will read MII Status Register to get link status.       */

⌨️ 快捷键说明

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