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

📄 1022.ethernet.patch

📁 sm86xx内核源包括补丁( GPL )的
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+	/* Reset the PHY */+	phy_cntl = BMCR_RESET;+	if (private->phy_loopback)+		phy_cntl |= BMCR_LOOPBACK;+	DBG_PRINT("%s: Reset PHY\n", __func__);+	mdio_write(dev, mii_if->phy_id, MII_BMCR, phy_cntl);+	/* Wait up to 5 seconds for the reset to complete */+	for (timeout = 10; timeout != 0; timeout--) {+		phy_cntl = mdio_read(dev, mii_if->phy_id, MII_BMCR);+		if (!(phy_cntl & BMCR_RESET))+			break;+		/* Wait 500 milliseconds */+		wait_ms(500);+	}+	if (timeout == 0) {+		DBG_PRINT("PHY reset timeout\n");+		goto out;+	}+	/* Read phy & advertising capabilities */+	DBG_PRINT("%s: set up caps\n", __func__);+	phy_caps = mdio_read(dev, mii_if->phy_id, MII_BMSR);+	ad_caps = ADVERTISE_CSMA;+	if (phy_caps & BMSR_100BASE4)+		ad_caps |= ADVERTISE_100BASE4;+	if (phy_caps & BMSR_100FULL)+		ad_caps |= ADVERTISE_100FULL;+	if (phy_caps & BMSR_100HALF)+		ad_caps |= ADVERTISE_100HALF;+	if (phy_caps & BMSR_10FULL)+		ad_caps |= ADVERTISE_10FULL;+	if (phy_caps & BMSR_10HALF)+		ad_caps |= ADVERTISE_10HALF;++	/* Update auto-negociation advertisement register */+	mdio_write(dev, mii_if->phy_id, MII_ADVERTISE, ad_caps);+	/* Read the register back. Some (buggy) PHY won't negociate properly+	 * if this is not done.+	 */+	status = mdio_read(dev, mii_if->phy_id, MII_ADVERTISE);+	timeout = 30;+	/* Restart auto-negociation with our new advertisement capabilities */+	DBG_PRINT("%s: start autonegociation\n", __func__);+ restart_autoneg:+	phy_cntl = BMCR_ANRESTART | BMCR_ANENABLE;+	if (private->phy_loopback)+		phy_cntl |= BMCR_LOOPBACK;+	mdio_write(dev, mii_if->phy_id, MII_BMCR, phy_cntl);+	/* Wait for the auto-negociation to complete.+	 * This can take up to 3 seconds.+	 */+	for (; timeout != 0; timeout--) {+		status = mdio_read(dev, mii_if->phy_id, MII_BMSR);+		if (status & BMSR_ANEGCOMPLETE)+			break;+		if (status & BMSR_RFAULT) {+            /* In case of remote fault, restart negociation */+			DBG_PRINT("%s: restart autonegociation\n", __func__);+			goto restart_autoneg;+		}+		wait_ms(100);+	}+	status = mdio_read(dev, mii_if->phy_id, MII_BMSR);+	if (!(status & BMSR_ANEGCOMPLETE))+		DBG_PRINT("Auto-negociation timeout\n");+	else if (status & BMSR_RFAULT)+		DBG_PRINT("Auto-negociation remote fault\n");+	else+		DBG_PRINT("Auto-negociation done\n");++	netdev_get_settings(dev, &cmd);+	dump_ethtool_cmd(&cmd);+ out:+	private->autoneg_active = 0;+	DBG_PRINT_INOUT_FUNC("END");+}++/* PHY detection */+/* XXX: to be moved into mii.c */+int phy_detect (struct net_device *dev, struct mii_if_info *mii_if)+{+	int phy_n;+	int mii_status, phy_id1, phy_id2;+	+	DBG_PRINT_INOUT_FUNC("START");+	mii_if->dev = dev;+	mii_if->mdio_read = mdio_read;+	mii_if->mdio_write = mdio_write;+	mii_if->phy_id_mask = 0x1f;+	mii_if->reg_num_mask = 0x1f;+	mii_if->phy_id = -1; /* No PHY found */+	for (phy_n = 0; phy_n < 32; phy_n++) {+		DBG_PRINT("%s: check PHY %d\n", __func__, phy_n);+		mii_status = mdio_read(dev, phy_n, MII_BMSR);+		phy_id1 = mdio_read(dev, phy_n, MII_PHYSID1);+		phy_id2 = mdio_read(dev, phy_n, MII_PHYSID2);+		/* PHY_ID1 is zero in some realtek PHYs */+		if (/*phy_id1 > 0 &&*/ phy_id1 < 0xFFFF && phy_id1 != 0x8000 &&+		    phy_id2 > 0 && phy_id2 < 0xFFFF && phy_id2 != 0x8000 &&+		    mii_status != 0xffff && mii_status != 0x0000) {+			mii_if->advertising = mdio_read(dev, phy_n, 4);+			mii_if->phy_id = phy_n;+			DBG_PRINT(KERN_INFO "%s: MII PHY found at address %d, status "+			       "0x%4.4x advertising %4.4x Link %4.4x.\n",+			       dev->name, phy_n, mii_status, mii_if->advertising,+			       mdio_read(dev, phy_n, 5));+			/* set IFF_RUNNING */+			if (mii_status & BMSR_LSTATUS) {+				DBG_PRINT("%s: netif_carrier_on\n", __func__);+				netif_carrier_on(dev);+			}+			else {+				DBG_PRINT("%s: netif_carrier_off\n", __func__);+				netif_carrier_off(dev);+			}+			break;+		}+	}+	if (phy_n == 32) {+		DBG_PRINT("failed to detect PHY\n");+		return -1;+	}+	+	DBG_PRINT_INOUT_FUNC("END");+	return phy_n;+}++/* Getting MAC address from local RAM */+static int get_mac_address(unsigned long *mac_lo, unsigned long *mac_hi)+{+	unsigned long cksum, lo, hi;+	const unsigned char marker = 'M';+	+	DBG_PRINT_INOUT_FUNC("START");+	lo = em86xx_read_reg(REG_BASE_cpu_block + LR_ETH_MAC_LO);+	hi = em86xx_read_reg(REG_BASE_cpu_block + LR_ETH_MAC_HI);++	if (((unsigned char)((hi >> 16) & 0xff)) != marker)+		return(1); /* Not valid MAC */+	cksum = ((lo & 0xff) + ((lo >> 8) & 0xff) + ((lo >> 16) & 0xff) + ((lo >> 24) & 0xff) + +		 (hi & 0xff) + ((hi >> 8) & 0xff)) & 0xff;+	if (((hi >> 24) & 0xff) != cksum)+		return(1); /* Not valid MAC */+	*mac_lo = lo;+	*mac_hi = hi & 0xffff;++	DBG_PRINT_INOUT_FUNC("END");+	return(0); /* Got valid MAC */+}++/* Get the device mac address */+static int em86xx_get_macaddr(unsigned char *addr)+{+	DBG_PRINT_INOUT_FUNC("START");+#if defined(CONFIG_TANGO2) && (defined(CONFIG_TANGO2_SIG_BLOCK) || defined(CONFIG_TANGO2_XENV))+	unsigned long hi, lo;+	if (get_mac_address(&lo, &hi) == 0) {+		*addr++ = (hi & 0x0000ff00) >> 8;+		*addr++ = (hi & 0x000000ff);+		*addr++ = (lo & 0xff000000) >> 24;+		*addr++ = (lo & 0x00ff0000) >> 16;+		*addr++ = (lo & 0x0000ff00) >> 8;+		*addr   = (lo & 0x000000ff);+	} else if (tango2_ethernet_getmac(addr) == 0) {+		*addr++ = (def_mac_hi & 0x0000ff00) >> 8;+		*addr++ = (def_mac_hi & 0x000000ff);+		*addr++ = (def_mac_lo & 0xff000000) >> 24;+		*addr++ = (def_mac_lo & 0x00ff0000) >> 16;+		*addr++ = (def_mac_lo & 0x0000ff00) >> 8;+		*addr   = (def_mac_lo & 0x000000ff);+	}+#else+#ifdef BOOTLOADER+	if(	mac_read(addr) == -1) {+		*addr++ = (def_mac_hi & 0x0000ff00) >> 8;+		*addr++ = (def_mac_hi & 0x000000ff);+		*addr++ = (def_mac_lo & 0xff000000) >> 24;+		*addr++ = (def_mac_lo & 0x00ff0000) >> 16;+		*addr++ = (def_mac_lo & 0x0000ff00) >> 8;+		*addr   = (def_mac_lo & 0x000000ff);+	}+#else+#ifdef CONFIG_SD_BOOTLOADER_INTEGRATION+	{+		unsigned long lo, hi;++		if (get_mac_address(&lo, &hi) == 0) {+			def_mac_hi = hi;+			def_mac_lo = lo;+		}+	}+#endif+	*addr++ = (def_mac_hi & 0x0000ff00) >> 8;+	*addr++ = (def_mac_hi & 0x000000ff);+	*addr++ = (def_mac_lo & 0xff000000) >> 24;+	*addr++ = (def_mac_lo & 0x00ff0000) >> 16;+	*addr++ = (def_mac_lo & 0x0000ff00) >> 8;+	*addr   = (def_mac_lo & 0x000000ff);+#endif /* BOOTLOADER */	+#endif /* CONFIG_TANGO2 && (CONFIG_TANGO2_SIG_BLOCK || CONFIG_TANGO2_XENV) */+	DBG_PRINT_INOUT_FUNC("END");+	return 0;+}++/* Setting up MAC address of ethernet PHY and device data */+static int em86xx_set_mac(struct net_device *dev)+{+	unsigned long hi_mac, low_mac;++	DBG_PRINT_INOUT_FUNC("START");+	/* Set up device mac address */+	if (em86xx_get_macaddr(dev->dev_addr))+		return(-EIO);++	if (!is_valid_ether_addr(dev->dev_addr))+		MSG_PRINT("%s: bogus mac address detected.\n", dev->name);++	hi_mac =  (dev->dev_addr[5] << 8)  | dev->dev_addr[4];+	low_mac = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | +		  (dev->dev_addr[1] << 8)  | dev->dev_addr[0];++	/* Set up MAC address */+	em86xx_write_reg(EM86XX_MACAHR_REG, hi_mac);+	em86xx_write_reg(EM86XX_MACALR_REG, low_mac);++	DBG_PRINT_INOUT_FUNC("END");+	return 0;+}++#ifndef BOOTLOADER+/* Setting customized mac address */+static int em86xx_eth_set_macaddr(struct net_device *dev, void *addr)+{+	unsigned long hi_mac, low_mac;++	DBG_PRINT_INOUT_FUNC("START");+	/* Check if given address is valid ethernet MAC address */+	if (!is_valid_ether_addr(addr))+		return(-EIO);++	/* Turn off IRQ and stop receive/transmit */+	em86xx_write_reg(EM86XX_CR_REG, 0);+	em86xx_write_reg(EM86XX_IER_REG, 0);++	netif_carrier_off(dev); /* Shutdown interface */++	/* Save the customize mac address */+	memcpy(dev->dev_addr, addr, 6);+	hi_mac  = (dev->dev_addr[5] << 8) | dev->dev_addr[4];+	low_mac = (dev->dev_addr[3] << 24)| (dev->dev_addr[2] << 16) | +		  (dev->dev_addr[1] << 8) | dev->dev_addr[0];++	def_mac_hi = hi_mac;+	def_mac_lo = low_mac;++	/* Set up MAC address */+	em86xx_write_reg(EM86XX_MACAHR_REG, hi_mac );+	em86xx_write_reg(EM86XX_MACALR_REG, low_mac );++	netif_carrier_off(dev);++	DBG_PRINT_INOUT_FUNC("END");+	return 0;+}+#endif /* BOOTLOADER */++/* RTL8201BL is a single-port PHY with an MII/SNI. The MAC layer device can +   control a maximum of 31 devices, configured with different PHY addresses+   (00001b to 11111b). We need to find out which PHY address is using in +   order to obtain the mode status after the auto-neotiation is completed.++   There is a module parameter phy_address to be used to override this probe,+   to set PHY address if one already knew it.+*/+static int em86xx_phy_probe(void)+{++        int phy_addr 	= 0;+	u16 phy_id 	= 0;+        u16 phy_status 	= 0;++	DBG_PRINT_INOUT_FUNC("START");+	if (phy_address < 0) {+		/* search for total of 31 possible mii phy addresses */+		for (phy_addr = 1; phy_addr < 32; phy_addr++) {+			phy_status = em86xx_mii_read(phy_addr,GEN_sts);++			if (phy_status != 0xffff && phy_status != 0x0000)+				break;+		}+	} else {+		phy_addr = phy_address;+		phy_status = em86xx_mii_read(phy_addr,GEN_sts);+	}+	phy_id =  em86xx_mii_read(phy_addr,GEN_id_lo);+	MSG_PRINT("Found PHY %04x at Addr = %d Status=0x%x\n", phy_id, phy_addr, phy_status);+ +	DBG_PRINT_INOUT_FUNC("END");+	return phy_addr;+}++/* Initialize the ethernet link status, mac, and flow control */+static int em86xx_link_config(struct net_device *dev)+{+	EM86XX_ETH_PRIV *private = (EM86XX_ETH_PRIV *)dev->priv;+	struct mii_if_info *mii = &(private->mii_if);+	unsigned long word = 0;++	DBG_PRINT_INOUT_FUNC("START");++	// Turn off IRQ and stop receive/transmit +	em86xx_write_reg(EM86XX_CR_REG, 0);+	em86xx_write_reg(EM86XX_IER_REG, 0);++	setup_phy(mii);++	/* set the descriptor base address */+	em86xx_write_reg(EM86XX_RLBAR_REG, PHYSADDR((u32)private->rxdsc) );+	em86xx_write_reg(EM86XX_TLBAR_REG, PHYSADDR((u32)private->txdsc));++	/* set bus mode: burst length = 32 | BLE | ~DBO */+	word = (32 << 8) /*| (1 << 7) | (1 << 20)*/ ;+	em86xx_write_reg(EM86XX_BMR_REG, word); ++	/* enable MAC flow ctrl */+	word = (1 << 1);+	em86xx_write_reg(EM86XX_FCR_REG, word); ++	/* configure MAC ctrller */+	word = ETH_MAC_FLAGS;+	word |= MacLoopbackOff; +        if (mii->full_duplex)+                word |= MacFullDuplex;+        else+                word &= ~MacFullDuplex;+	em86xx_write_reg(EM86XX_MACCR_REG, word);++	/* Turn on the IRQ and start receive/transmit */+	em86xx_write_reg(EM86XX_IER_REG, ETH_IRQ_FLAGS);+	em86xx_write_reg(EM86XX_CR_REG, ETH_RXTX_FLAGS); ++	netif_carrier_on(dev);++	DBG_PRINT_INOUT_FUNC("END");+	return 0;+}++/* Ethernet hardware initialization */+static int em86xx_eth_hw_init(struct net_device *dev)+{+	EM86XX_ETH_PRIV *private = (EM86XX_ETH_PRIV *)dev->priv;+	int rc;++	DBG_PRINT_INOUT_FUNC("START");++	/* Turn off IRQ and stop receive/transmit */+	em86xx_write_reg(EM86XX_CR_REG, 0);+	em86xx_write_reg(EM86XX_IER_REG, 0);++	/* reset dma engine*/+	em86xx_write_reg(EM86XX_BMR_REG, DmaResetOn);+	em86xx_write_reg(EM86XX_BMR_REG, DmaResetOff);++	if (em86xx_set_mac(dev))+		return(-EIO);++	/* stop MAC engine */+	em86xx_write_reg(EM86XX_CR_REG, 0x0); +#ifndef USE_HW_FILTERING+	/* set up multicast hash table to MCHTHR MCHTLR */+	/* set multicast hash table to accept all */+	em86xx_write_reg(EM86XX_MCHTHR_REG, 0xffffffff); +	em86xx_write_reg(EM86XX_MCHTLR_REG, 0xffffffff); +#else+	/* clear hash table */+        em86xx_write_reg( EM86XX_MCHTHR_REG, 0 );+        em86xx_write_reg( EM86XX_MCHTLR_REG, 0 );++	em86xx_eth_set_multicast_list(dev);+#endif++	/* resetting descriptors */+#ifdef BOOTLOADER+        if (em86xx_eth_reset_desc(dev, &private->reset_flag))+#else+        if (em86xx_eth_reset_desc(&em86xx_eth_dev, &private->reset_flag))+#endif+		return(-EIO);++	/* configure PHY and speed */+	rc = em86xx_link_config(dev);+	DBG_PRINT_INOUT_FUNC("END");+	return rc;+}++#ifndef BOOTLOADER+/* Monitor the status of link, re-do link initialization if necessary. */+#ifdef USE_KERNEL_TIMER+static void em86xx_eth_link_monitor(unsigned long dummy)+#else+static int em86xx_eth_link_monitor(void *dummy)+#endif+{+	struct net_device *dev = (struct net_device *)dummy;+	EM86XX_ETH_PRIV *private = (EM86XX_ETH_PRIV *)dev->priv;+        unsigned long flags;+        int link;+	int res;++	DBG_PRINT_INOUT_FUNC("START");++#ifndef USE_KERNEL_TIMER+	strcpy(current->comm, "em86xx_eth");+	daemonize();+	reparent_to_init();++	while (private->stop_thread == 0) {+#endif+		spin_lock_irqsave(&private->lock, flags);+		link = mii_link_ok(&private->mii_if);+		spin_unlock_irqrestore(&private->lock, flags);+		+		if (netif_carrier_ok(dev) && !link) {			+			MSG_PRINT("%s: detected link DOWN.\n", dev->name);+			netif_carrier_off(dev);+		}+		else if (!netif_carrier_ok(dev) && link) {+			MSG_PRINT("%s: detected link UP.\n", dev->name);+			res = em86xx_eth_hw_init(dev);+			netif_carrier_on(dev);+		}++#ifndef USE_KERNEL_TIMER+		set_current_state(TASK_UNINTERRUPTIBLE);+		schedule_timeout(HZ);+	}+#endif++#ifdef USE_KERNEL_TIMER+	/* Schedule for the next time */+	mod_timer(&private->eth_timer, jiffies + HZ); +	DBG_PRINT_INOUT_FUNC("END (with timer)");+#else+	DBG_PRINT_INOUT_FUNC("END (IRQ)");+	return(0);+#endif+}+#endif++/* Setting rx/tx descriptors */+static void em86xx_eth_setup_desc(struct net_device *dev)+{+	register int i;+	struct em86xx_desc *desc_ptr = NULL;+	unsigned long base_addr = 0;+	EM86XX_ETH_PRIV *private = (EM86XX_ETH_PRIV *)dev->priv;++	DBG_PRINT_INOUT_FUNC("START");+	/* Setup rx descriptor */+	desc_ptr = (struct em86xx_desc *)(private->rxdsc);+	for (i = 0; i < (private->num_rxdesc - 1); i++, desc_ptr++) {+		desc_ptr->desc3 = PHYSADDR((unsigned long)(desc_ptr + 1));+		desc_ptr->desc1 = (DescChain | R_BUF_SIZE);+  		desc_ptr->desc0 = DescOwnByDma; +	}+	desc_ptr->desc3 = PHYSADDR((unsigned long)(private->rxdsc));+	desc_ptr->desc1 = (DescChain | DescEndOfRing | R_BUF_SIZE);+	desc_ptr->desc0 = De

⌨️ 快捷键说明

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