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

📄 forcedeth.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
	writel(0, base + NvRegTransmitterControl);	writel(0, base + NvRegReceiverControl);	writel(0, base + NvRegAdapterControl);	/* 2) initialize descriptor rings */	oom = nv_init_ring(dev);	writel(0, base + NvRegLinkSpeed);	writel(0, base + NvRegUnknownTransmitterReg);	nv_txrx_reset(dev);	writel(0, base + NvRegUnknownSetupReg6);	np->in_shutdown = 0;	/* 3) set mac address */	{		u32 mac[2];		mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +				(dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);		mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);		writel(mac[0], base + NvRegMacAddrA);		writel(mac[1], base + NvRegMacAddrB);	}	/* 4) give hw rings */	writel((u32) np->ring_addr, base + NvRegRxRingPhysAddr);	writel((u32) (np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);	writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),		base + NvRegRingSizes);	/* 5) continue setup */	np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;	np->duplex = 0;	writel(np->linkspeed, base + NvRegLinkSpeed);	writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);	writel(np->desc_ver, base + NvRegTxRxControl);	pci_push(base);	writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);	reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,			NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,			KERN_INFO "open: SetupReg5, Bit 31 remained off\n");	writel(0, base + NvRegUnknownSetupReg4);	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);	writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);	/* 6) continue setup */	writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);	writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);	writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);	writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig);	writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus);	get_random_bytes(&i, sizeof(i));	writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed);	writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1);	writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2);	writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval);	writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);	writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING,			base + NvRegAdapterControl);	writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed);	writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);	writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);	i = readl(base + NvRegPowerState);	if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0)		writel(NVREG_POWERSTATE_POWEREDUP|i, base + NvRegPowerState);	pci_push(base);	udelay(10);	writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState);	writel(0, base + NvRegIrqMask);	pci_push(base);	writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);	pci_push(base);	ret = request_irq(dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev);	if (ret)		goto out_drain;	/* ask for interrupts */	writel(np->irqmask, base + NvRegIrqMask);	spin_lock_irq(&np->lock);	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);	writel(0, base + NvRegMulticastAddrB);	writel(0, base + NvRegMulticastMaskA);	writel(0, base + NvRegMulticastMaskB);	writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);	/* One manual link speed update: Interrupts are enabled, future link	 * speed changes cause interrupts and are handled by nv_link_irq().	 */	{		u32 miistat;		miistat = readl(base + NvRegMIIStatus);		writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);		dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat);	}	ret = nv_update_linkspeed(dev);	nv_start_rx(dev);	nv_start_tx(dev);	netif_start_queue(dev);	if (ret) {		netif_carrier_on(dev);	} else {		printk("%s: no link during initialization.\n", dev->name);		netif_carrier_off(dev);	}	if (oom)		mod_timer(&np->oom_kick, jiffies + OOM_REFILL);	spin_unlock_irq(&np->lock);	return 0;out_drain:	drain_ring(dev);	return ret;}static int nv_close(struct net_device *dev){	struct fe_priv *np = get_nvpriv(dev);	u8 *base;	spin_lock_irq(&np->lock);	np->in_shutdown = 1;	spin_unlock_irq(&np->lock);	synchronize_irq(dev->irq);	del_timer_sync(&np->oom_kick);	del_timer_sync(&np->nic_poll);	netif_stop_queue(dev);	spin_lock_irq(&np->lock);	nv_stop_tx(dev);	nv_stop_rx(dev);	base = get_hwbase(dev);	/* disable interrupts on the nic or we will lock up */	writel(0, base + NvRegIrqMask);	pci_push(base);	dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);	spin_unlock_irq(&np->lock);	free_irq(dev->irq, dev);	drain_ring(dev);	if (np->wolenabled)		nv_start_rx(dev);	/* FIXME: power down nic */	return 0;}static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id){	struct net_device *dev;	struct fe_priv *np;	unsigned long addr;	u8 *base;	int err, i;	dev = alloc_etherdev(sizeof(struct fe_priv));	err = -ENOMEM;	if (!dev)		goto out;	np = get_nvpriv(dev);	np->pci_dev = pci_dev;	spin_lock_init(&np->lock);	SET_MODULE_OWNER(dev);	SET_NETDEV_DEV(dev, &pci_dev->dev);	init_timer(&np->oom_kick);	np->oom_kick.data = (unsigned long) dev;	np->oom_kick.function = &nv_do_rx_refill;	/* timer handler */	init_timer(&np->nic_poll);	np->nic_poll.data = (unsigned long) dev;	np->nic_poll.function = &nv_do_nic_poll;	/* timer handler */	err = pci_enable_device(pci_dev);	if (err) {		printk(KERN_INFO "forcedeth: pci_enable_dev failed (%d) for device %s\n",				err, pci_name(pci_dev));		goto out_free;	}	pci_set_master(pci_dev);	err = pci_request_regions(pci_dev, DRV_NAME);	if (err < 0)		goto out_disable;	err = -EINVAL;	addr = 0;	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {		dprintk(KERN_DEBUG "%s: resource %d start %p len %ld flags 0x%08lx.\n",				pci_name(pci_dev), i, (void*)pci_resource_start(pci_dev, i),				pci_resource_len(pci_dev, i),				pci_resource_flags(pci_dev, i));		if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM &&				pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) {			addr = pci_resource_start(pci_dev, i);			break;		}	}	if (i == DEVICE_COUNT_RESOURCE) {		printk(KERN_INFO "forcedeth: Couldn't find register window for device %s.\n",					pci_name(pci_dev));		goto out_relreg;	}	/* handle different descriptor versions */	if (pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_1 ||		pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_2 ||		pci_dev->device == PCI_DEVICE_ID_NVIDIA_NVENET_3)		np->desc_ver = DESC_VER_1;	else		np->desc_ver = DESC_VER_2;	err = -ENOMEM;	dev->base_addr = (unsigned long) ioremap(addr, NV_PCI_REGSZ);	if (!dev->base_addr)		goto out_relreg;	dev->irq = pci_dev->irq;	np->rx_ring = pci_alloc_consistent(pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),						&np->ring_addr);	if (!np->rx_ring)		goto out_unmap;	np->tx_ring = &np->rx_ring[RX_RING];	dev->open = nv_open;	dev->stop = nv_close;	dev->hard_start_xmit = nv_start_xmit;	dev->get_stats = nv_get_stats;	dev->change_mtu = nv_change_mtu;	dev->set_multicast_list = nv_set_multicast;	dev->do_ioctl = nv_ioctl;	dev->tx_timeout = nv_tx_timeout;	dev->watchdog_timeo = NV_WATCHDOG_TIMEO;	pci_set_drvdata(pci_dev, dev);	/* read the mac address */	base = get_hwbase(dev);	np->orig_mac[0] = readl(base + NvRegMacAddrA);	np->orig_mac[1] = readl(base + NvRegMacAddrB);	dev->dev_addr[0] = (np->orig_mac[1] >>  8) & 0xff;	dev->dev_addr[1] = (np->orig_mac[1] >>  0) & 0xff;	dev->dev_addr[2] = (np->orig_mac[0] >> 24) & 0xff;	dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;	dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;	dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;	if (!is_valid_ether_addr(dev->dev_addr)) {		/*		 * Bad mac address. At least one bios sets the mac address		 * to 01:23:45:67:89:ab		 */		printk(KERN_ERR "%s: Invalid Mac address detected: %02x:%02x:%02x:%02x:%02x:%02x\n",			pci_name(pci_dev),			dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],			dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);		printk(KERN_ERR "Please complain to your hardware vendor. Switching to a random MAC.\n");		dev->dev_addr[0] = 0x00;		dev->dev_addr[1] = 0x00;		dev->dev_addr[2] = 0x6c;		get_random_bytes(&dev->dev_addr[3], 3);	}	dprintk(KERN_DEBUG "%s: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", pci_name(pci_dev),			dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],			dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);	/* disable WOL */	writel(0, base + NvRegWakeUpFlags);	np->wolenabled = 0;	if (np->desc_ver == DESC_VER_1) {		np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;		if (id->driver_data & DEV_NEED_LASTPACKET1)			np->tx_flags |= NV_TX_LASTPACKET1;	} else {		np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;		if (id->driver_data & DEV_NEED_LASTPACKET1)			np->tx_flags |= NV_TX2_LASTPACKET1;	}	if (id->driver_data & DEV_IRQMASK_1)		np->irqmask = NVREG_IRQMASK_WANTED_1;	if (id->driver_data & DEV_IRQMASK_2)		np->irqmask = NVREG_IRQMASK_WANTED_2;	if (id->driver_data & DEV_NEED_TIMERIRQ)		np->irqmask |= NVREG_IRQ_TIMER;	if (id->driver_data & DEV_NEED_LINKTIMER) {		dprintk(KERN_INFO "%s: link timer on.\n", pci_name(pci_dev));		np->need_linktimer = 1;		np->link_timeout = jiffies + LINK_TIMEOUT;	} else {		dprintk(KERN_INFO "%s: link timer off.\n", pci_name(pci_dev));		np->need_linktimer = 0;	}	/* find a suitable phy */	for (i = 1; i < 32; i++) {		int id1, id2;		spin_lock_irq(&np->lock);		id1 = mii_rw(dev, i, MII_PHYSID1, MII_READ);		spin_unlock_irq(&np->lock);		if (id1 < 0 || id1 == 0xffff)			continue;		spin_lock_irq(&np->lock);		id2 = mii_rw(dev, i, MII_PHYSID2, MII_READ);		spin_unlock_irq(&np->lock);		if (id2 < 0 || id2 == 0xffff)			continue;		id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;		id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;		dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n",				pci_name(pci_dev), id1, id2, i);		np->phyaddr = i;		np->phy_oui = id1 | id2;		break;	}	if (i == 32) {		/* PHY in isolate mode? No phy attached and user wants to		 * test loopback? Very odd, but can be correct.		 */		printk(KERN_INFO "%s: open: Could not find a valid PHY.\n",				pci_name(pci_dev));	}	if (i != 32) {		/* reset it */		phy_init(dev);	}	err = register_netdev(dev);	if (err) {		printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);		goto out_freering;	}	printk(KERN_INFO "%s: forcedeth.c: subsystem: %05x:%04x bound to %s\n",			dev->name, pci_dev->subsystem_vendor, pci_dev->subsystem_device,			pci_name(pci_dev));	return 0;out_freering:	pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),				np->rx_ring, np->ring_addr);	pci_set_drvdata(pci_dev, NULL);out_unmap:	iounmap(get_hwbase(dev));out_relreg:	pci_release_regions(pci_dev);out_disable:	pci_disable_device(pci_dev);out_free:	free_netdev(dev);out:	return err;}static void __devexit nv_remove(struct pci_dev *pci_dev){	struct net_device *dev = pci_get_drvdata(pci_dev);	struct fe_priv *np = get_nvpriv(dev);	u8 *base = get_hwbase(dev);	unregister_netdev(dev);	/* special op: write back the misordered MAC address - otherwise	 * the next nv_probe would see a wrong address.	 */	writel(np->orig_mac[0], base + NvRegMacAddrA);	writel(np->orig_mac[1], base + NvRegMacAddrB);	/* free all structures */	pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring, np->ring_addr);	iounmap(get_hwbase(dev));	pci_release_regions(pci_dev);	pci_disable_device(pci_dev);	free_netdev(dev);	pci_set_drvdata(pci_dev, NULL);}static struct pci_device_id pci_tbl[] = {	{	/* nForce Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_1,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,	},	{	/* nForce2 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_2,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,	},	{	/* nForce3 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_3,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,	},	{	/* nForce3 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_4,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,	},	{	/* nForce3 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_5,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,	},	{	/* nForce3 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_6,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,	},	{	/* nForce3 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_7,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,	},	{	/* CK804 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_8,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,	},	{	/* CK804 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_9,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,	},	{	/* MCP04 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_10,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,	},	{	/* MCP04 Ethernet Controller */		.vendor = PCI_VENDOR_ID_NVIDIA,		.device = PCI_DEVICE_ID_NVIDIA_NVENET_11,		.subvendor = PCI_ANY_ID,		.subdevice = PCI_ANY_ID,		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,	},	{0,},};static struct pci_driver driver = {	.name = "forcedeth",	.id_table = pci_tbl,	.probe = nv_probe,	.remove = __devexit_p(nv_remove),};static int __init init_nic(void){	printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION);	return pci_module_init(&driver);}static void __exit exit_nic(void){	pci_unregister_driver(&driver);}module_param(max_interrupt_work, int, 0);MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt");MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");MODULE_LICENSE("GPL");MODULE_DEVICE_TABLE(pci, pci_tbl);module_init(init_nic);module_exit(exit_nic);

⌨️ 快捷键说明

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