亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? mvswitch.c

?? 交換機芯片vlan配置
?? C
字號:
	 	/*	 * Marvell 88E6060 switch driver	 * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org>	 *	 * This program is free software; you can redistribute  it and/or modify it	 * under  the terms of the GNU General Public License v2 as published by the	 * Free Software Foundation	 */	#include <linux/kernel.h>	#include <linux/string.h>	#include <linux/errno.h>	#include <linux/unistd.h>	#include <linux/slab.h>	#include <linux/interrupt.h>	#include <linux/init.h>	#include <linux/delay.h>	#include <linux/netdevice.h>	#include <linux/etherdevice.h>	#include <linux/skbuff.h>	#include <linux/spinlock.h>	#include <linux/mm.h>	#include <linux/module.h>	#include <linux/mii.h>	#include <linux/ethtool.h>	#include <linux/phy.h>	#include <linux/if_vlan.h>		#include <asm/io.h>	#include <asm/irq.h>	#include <asm/uaccess.h>	#include "mvswitch.h"		/* Undefine this to use trailer mode instead.	 * I don't know if header mode works with all chips */	#define HEADER_MODE     1		MODULE_DESCRIPTION("Marvell 88E6060 Switch driver");	MODULE_AUTHOR("Felix Fietkau");	MODULE_LICENSE("GPL");		struct mvswitch_priv {	        /* the driver's tx function */	        int (*hardstart)(struct sk_buff *skb, struct net_device *dev);	        struct vlan_group *grp;	        u8 vlans[16];	};		#define to_mvsw(_phy) ((struct mvswitch_priv *) (_phy)->priv)		static inline u16	r16(struct phy_device *phydev, int addr, int reg)	{	        return phydev->bus->read(phydev->bus, addr, reg);	}		static inline void	w16(struct phy_device *phydev, int addr, int reg, u16 val)	{	        phydev->bus->write(phydev->bus, addr, reg, val);	}			static int	mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)	{	        struct mvswitch_priv *priv;	        char *buf = NULL;	        u16 vid;		        priv = dev->phy_ptr;	        if (unlikely(!priv))	                goto error;		        if (unlikely(skb->len < 16))	                goto error;		#ifdef HEADER_MODE	        if (__vlan_hwaccel_get_tag(skb, &vid))	                goto error;		        if (skb_cloned(skb) || (skb->len <= 62) || (skb_headroom(skb) < MV_HEADER_SIZE)) {	                if (pskb_expand_head(skb, MV_HEADER_SIZE, (skb->len < 62 ? 62 - skb->len : 0), GFP_ATOMIC))	                        goto error_expand;	                if (skb->len < 62)	                        skb->len = 62;	        }	        buf = skb_push(skb, MV_HEADER_SIZE);	#else	        if (__vlan_get_tag(skb, &vid))	                goto error;		        if (unlikely((vid > 15 || !priv->vlans[vid])))	                goto error;		        if (skb->len <= 64) {	                if (pskb_expand_head(skb, 0, 64 + MV_TRAILER_SIZE - skb->len, GFP_ATOMIC))	                        goto error_expand;		                buf = skb->data + 64;	                skb->len = 64 + MV_TRAILER_SIZE;	        } else {	                if (skb_cloned(skb) || unlikely(skb_tailroom(skb) < 4)) {	                        if (pskb_expand_head(skb, 0, 4, GFP_ATOMIC))	                                goto error_expand;	                }	                buf = skb_put(skb, 4);	        }		        /* move the ethernet header 4 bytes forward, overwriting the vlan tag */	        memmove(skb->data + 4, skb->data, 12);	        skb->data += 4;	        skb->len -= 4;	        skb->mac_header += 4;	#endif		        if (!buf)	                goto error;			#ifdef HEADER_MODE	        /* prepend the tag */	        *((__be16 *) buf) = cpu_to_be16(	                ((vid << MV_HEADER_VLAN_S) & MV_HEADER_VLAN_M) |	                ((priv->vlans[vid] << MV_HEADER_PORTS_S) & MV_HEADER_PORTS_M)	        );	#else	        /* append the tag */	        *((__be32 *) buf) = cpu_to_be32((	                (MV_TRAILER_OVERRIDE << MV_TRAILER_FLAGS_S) |	                ((priv->vlans[vid] & MV_TRAILER_PORTS_M) << MV_TRAILER_PORTS_S)	        ));	#endif		        return priv->hardstart(skb, dev);		error_expand:	        if (net_ratelimit())	                printk("%s: failed to expand/update skb for the switch\n", dev->name);		error:	        /* any errors? drop the packet! */	        dev_kfree_skb_any(skb);	        return 0;	}		static int	mvswitch_mangle_rx(struct sk_buff *skb, int napi)	{	        struct mvswitch_priv *priv;	        struct net_device *dev;	        int vlan = -1;	        unsigned char *buf;	        int i;		        dev = skb->dev;	        if (!dev)	                goto error;		        priv = dev->phy_ptr;	        if (!priv)	                goto error;		        if (!priv->grp)	                goto error;		#ifdef HEADER_MODE	        buf = skb->data;	        skb_pull(skb, MV_HEADER_SIZE);	#else	        buf = skb->data + skb->len - MV_TRAILER_SIZE;	        if (buf[0] != 0x80)	                goto error;	#endif		        /* look for the vlan matching the incoming port */	        for (i = 0; i < ARRAY_SIZE(priv->vlans); i++) {	                if ((1 << buf[1]) & priv->vlans[i])	                        vlan = i;	        }		        if (vlan == -1)	                goto error;		        skb->protocol = eth_type_trans(skb, skb->dev);		        if (napi)	                return vlan_hwaccel_receive_skb(skb, priv->grp, vlan);	        else	                return vlan_hwaccel_rx(skb, priv->grp, vlan);		error:	        /* no vlan? eat the packet! */	        dev_kfree_skb_any(skb);	        return 0;	}			static int	mvswitch_netif_rx(struct sk_buff *skb)	{	        return mvswitch_mangle_rx(skb, 0);	}		static int	mvswitch_netif_receive_skb(struct sk_buff *skb)	{	        return mvswitch_mangle_rx(skb, 1);	}			static void	mvswitch_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)	{	        struct mvswitch_priv *priv = dev->phy_ptr;	        priv->grp = grp;	}			static int	mvswitch_wait_mask(struct phy_device *pdev, int addr, int reg, u16 mask, u16 val)	{	        int i = 100;	        u16 r;		        do {	                r = r16(pdev, addr, reg) & mask;	                if (r == val)	                        return 0;	        } while(--i > 0);	        return -ETIMEDOUT;	}		static int	mvswitch_config_init(struct phy_device *pdev)	{	        struct mvswitch_priv *priv = to_mvsw(pdev);	        struct net_device *dev = pdev->attached_dev;	        u8 vlmap = 0;	        int i;		        if (!dev)	                return -EINVAL;		        printk("%s: Marvell 88E6060 PHY driver attached.\n", dev->name);	        pdev->supported = ADVERTISED_100baseT_Full;	        pdev->advertising = ADVERTISED_100baseT_Full;	        dev->phy_ptr = priv;	        dev->irq = PHY_POLL;		        /* initialize default vlans */	        for (i = 0; i < MV_PORTS; i++)	                priv->vlans[(i == MV_WANPORT ? 1 : 0)] |= (1 << i);		        /* before entering reset, disable all ports */	        for (i = 0; i < MV_PORTS; i++)	                w16(pdev, MV_PORTREG(CONTROL, i), 0x00);		        msleep(2); /* wait for the status change to settle in */		        /* put the ATU in reset */	        w16(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET);		        i = mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_CTRL), MV_ATUCTL_RESET, 0);	        if (i < 0) {	                printk("%s: Timeout waiting for the switch to reset.\n", dev->name);	                return i;	        }		        /* set the ATU flags */	        w16(pdev, MV_SWITCHREG(ATU_CTRL),	                MV_ATUCTL_NO_LEARN |	                MV_ATUCTL_ATU_1K |	                MV_ATUCTL_AGETIME(MV_ATUCTL_AGETIME_MIN) /* minimum without disabling ageing */	        );		        /* initialize the cpu port */	        w16(pdev, MV_PORTREG(CONTROL, MV_CPUPORT),	#ifdef HEADER_MODE	                MV_PORTCTRL_HEADER |	#else	                MV_PORTCTRL_RXTR |	                MV_PORTCTRL_TXTR |	#endif	                MV_PORTCTRL_ENABLED	        );	        /* wait for the phy change to settle in */	        msleep(2);	        for (i = 0; i < MV_PORTS; i++) {	                u8 pvid = 0;	                int j;		                vlmap = 0;		                /* look for the matching vlan */	                for (j = 0; j < ARRAY_SIZE(priv->vlans); j++) {	                        if (priv->vlans[j] & (1 << i)) {	                                vlmap = priv->vlans[j];	                                pvid = j;	                        }	                }	                /* leave port unconfigured if it's not part of a vlan */	                if (!vlmap)	                        continue;		                /* add the cpu port to the allowed destinations list */	                vlmap |= (1 << MV_CPUPORT);		                /* take port out of its own vlan destination map */	                vlmap &= ~(1 << i);		                /* apply vlan settings */	                w16(pdev, MV_PORTREG(VLANMAP, i),	                        MV_PORTVLAN_PORTS(vlmap) |	                        MV_PORTVLAN_ID(i)	                );		                /* re-enable port */	                w16(pdev, MV_PORTREG(CONTROL, i),	                        MV_PORTCTRL_ENABLED	                );	        }		        w16(pdev, MV_PORTREG(VLANMAP, MV_CPUPORT),	                MV_PORTVLAN_ID(MV_CPUPORT)	        );		        /* set the port association vector */	        for (i = 0; i <= MV_PORTS; i++) {	                w16(pdev, MV_PORTREG(ASSOC, i),	                        MV_PORTASSOC_PORTS(1 << i)	                );	        }		        /* init switch control */	        w16(pdev, MV_SWITCHREG(CTRL),	                MV_SWITCHCTL_MSIZE |	                MV_SWITCHCTL_DROP	        );		        /* hook into the tx function */	        priv->hardstart = dev->hard_start_xmit;	        pdev->netif_receive_skb = mvswitch_netif_receive_skb;	        pdev->netif_rx = mvswitch_netif_rx;	        dev->hard_start_xmit = mvswitch_mangle_tx;	        dev->vlan_rx_register = mvswitch_vlan_rx_register;	#ifdef HEADER_MODE	        dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;	#else	        dev->features |= NETIF_F_HW_VLAN_RX;	#endif		        return 0;	}		static int	mvswitch_read_status(struct phy_device *pdev)	{	        pdev->speed = SPEED_100;	        pdev->duplex = DUPLEX_FULL;	        pdev->state = PHY_UP;		        /* XXX ugly workaround: we can't force the switch	         * to gracefully handle hosts moving from one port to another,	         * so we have to regularly clear the ATU database */		        /* wait for the ATU to become available */	        mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0);		        /* flush the ATU */	        w16(pdev, MV_SWITCHREG(ATU_OP),	                MV_ATUOP_INPROGRESS |	                MV_ATUOP_FLUSH_ALL	        );		        /* wait for operation to complete */	        mvswitch_wait_mask(pdev, MV_SWITCHREG(ATU_OP), MV_ATUOP_INPROGRESS, 0);		        return 0;	}		static int	mvswitch_config_aneg(struct phy_device *phydev)	{	        return 0;	}		static void	mvswitch_remove(struct phy_device *pdev)	{	        struct mvswitch_priv *priv = to_mvsw(pdev);	        struct net_device *dev = pdev->attached_dev;		        /* restore old xmit handler */	        if (priv->hardstart && dev)	                dev->hard_start_xmit = priv->hardstart;	        dev->vlan_rx_register = NULL;	        dev->vlan_rx_kill_vid = NULL;	        dev->phy_ptr = NULL;	        dev->features &= ~NETIF_F_HW_VLAN_RX;	        kfree(priv);	}		static bool	mvswitch_detect(struct mii_bus *bus, int addr)	{	        u16 reg;	        int i;		        /* we attach to phy id 31 to make sure that the late probe works */	        if (addr != 31)	                return false;		        /* look for the switch on the bus */	        reg = bus->read(bus, MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK;	        if (reg != MV_IDENT_VALUE)	                return false;		        /*	         * Now that we've established that the switch actually exists, let's0	         * get rid of the competition :)	         */	        for (i = 0; i < 31; i++) {	                if (!bus->phy_map[i])	                        continue;		                device_unregister(&bus->phy_map[i]->dev);	                kfree(bus->phy_map[i]);	                bus->phy_map[i] = NULL;	        }		        return true;	}		static int	mvswitch_probe(struct phy_device *pdev)	{	        struct mvswitch_priv *priv;		        priv = kzalloc(sizeof(struct mvswitch_priv), GFP_KERNEL);	        if (priv == NULL)	                return -ENOMEM;		        pdev->priv = priv;		        return 0;	}			static struct phy_driver mvswitch_driver = {	        .name           = "Marvell 88E6060",        .features       = PHY_BASIC_FEATURES,	        .detect         = &mvswitch_detect,	        .probe          = &mvswitch_probe,	        .remove         = &mvswitch_remove,	        .config_init    = &mvswitch_config_init,	        .config_aneg    = &mvswitch_config_aneg,	        .read_status    = &mvswitch_read_status,	        .driver         = { .owner = THIS_MODULE,},	};		static int __init	mvswitch_init(void)	{	        return phy_driver_register(&mvswitch_driver);	}		static void __exit	mvswitch_exit(void)	{	        phy_driver_unregister(&mvswitch_driver);	}		module_init(mvswitch_init);	module_exit(mvswitch_exit);

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
色综合一个色综合| 日韩成人免费电影| 成人午夜视频网站| 欧美激情一区二区三区不卡| 成人福利视频在线看| 亚洲视频一区在线观看| 91蝌蚪porny| 亚洲成人av电影| 欧美电影免费观看完整版| 国产精品一区二区在线观看不卡| 国产婷婷色一区二区三区| 97久久精品人人爽人人爽蜜臀| 中文字幕一区二区三区av| 在线观看视频一区二区欧美日韩 | 精品嫩草影院久久| 国产成人综合亚洲网站| 亚洲欧美一区二区三区久本道91| 欧美视频自拍偷拍| 国产一区二区中文字幕| 亚洲美腿欧美偷拍| 精品免费一区二区三区| 色综合欧美在线视频区| 在线视频国产一区| 一色屋精品亚洲香蕉网站| 麻豆成人免费电影| 国产午夜精品理论片a级大结局| www.久久久久久久久| 午夜精品一区二区三区免费视频| 精品少妇一区二区三区在线视频| 成人在线视频一区| 亚洲v精品v日韩v欧美v专区| 精品国内二区三区| 在线欧美日韩国产| 国产精品正在播放| 亚洲成人av中文| 中文字幕一区日韩精品欧美| 欧美一区二区精品久久911| 成人av在线网站| 免费精品视频在线| 亚洲卡通动漫在线| 26uuu色噜噜精品一区二区| 欧洲一区二区av| 高清不卡一区二区| 免费看日韩精品| 亚洲v精品v日韩v欧美v专区| 国产精品毛片久久久久久久| 欧美xxxx在线观看| 欧美肥妇free| 欧美性猛交xxxxxx富婆| 成人app网站| 国产精一区二区三区| 日韩国产在线一| 亚洲专区一二三| 亚洲丝袜自拍清纯另类| 国产欧美日韩在线视频| 欧美不卡一区二区三区四区| 欧美欧美欧美欧美| 91黄视频在线观看| 97aⅴ精品视频一二三区| 国产在线精品一区二区夜色| 日韩av中文在线观看| 亚洲专区一二三| 亚洲精品福利视频网站| 中文字幕一区二区三区不卡在线| 国产欧美日韩在线视频| 国产偷国产偷精品高清尤物 | 日韩久久精品一区| 欧美蜜桃一区二区三区| 欧美性猛片xxxx免费看久爱| 在线免费观看日本一区| 在线视频欧美精品| 欧美系列日韩一区| 欧美精品久久99久久在免费线| 欧美三级视频在线观看| 欧亚洲嫩模精品一区三区| 色菇凉天天综合网| 欧美日韩午夜在线视频| 欧美日韩中文字幕一区二区| 欧美撒尿777hd撒尿| 欧美日本不卡视频| 欧美另类z0zxhd电影| 欧美人xxxx| 日韩一区二区三区免费观看| 欧美日韩精品免费观看视频| 欧美美女网站色| 日韩欧美一级二级三级| 久久久久久久精| 日本一区二区不卡视频| 一区二区在线观看免费| 亚洲午夜在线电影| 天堂蜜桃一区二区三区| 捆绑调教一区二区三区| 国产制服丝袜一区| 99久久精品国产网站| 91高清视频免费看| 91精品国产全国免费观看| www一区二区| 亚洲欧洲韩国日本视频| 亚洲大片免费看| 日韩精品久久久久久| 国产一区二区视频在线| 91丨porny丨国产| 91精品国产免费久久综合| 精品国产一区二区三区久久久蜜月 | 久久久一区二区三区捆绑**| 国产精品女主播在线观看| 一区二区三区精品在线观看| 日韩精品一二三区| 福利91精品一区二区三区| 日本韩国精品在线| 欧美va亚洲va国产综合| 亚洲人精品一区| 美女在线观看视频一区二区| 国产成a人无v码亚洲福利| 在线免费一区三区| 久久女同精品一区二区| 亚洲欧美日韩国产另类专区| 日韩电影一区二区三区四区| 国产成人精品免费| 欧美日韩国产经典色站一区二区三区 | 欧美亚洲综合一区| 久久综合久久鬼色中文字| 亚洲日本韩国一区| 老司机午夜精品99久久| 99久久久久久99| 精品少妇一区二区三区免费观看| 亚洲欧洲国产日韩| 国产真实乱对白精彩久久| 欧美色图片你懂的| 欧美国产日韩精品免费观看| 婷婷丁香激情综合| 色综合久久天天| 久久久精品黄色| 日韩在线卡一卡二| 色综合久久综合网| 亚洲国产岛国毛片在线| 欧美aaa在线| 欧美三级电影在线观看| 成人欧美一区二区三区白人 | 亚洲自拍都市欧美小说| 国产成人av电影在线观看| 91精品国产入口在线| 亚洲第一福利一区| 日本韩国欧美在线| 中文字幕亚洲电影| 粉嫩av一区二区三区粉嫩 | 欧美日韩国产片| 1024国产精品| 高清国产一区二区三区| 欧美精品一区二| 美女视频一区二区| 欧美狂野另类xxxxoooo| 亚洲精品视频一区| 93久久精品日日躁夜夜躁欧美| 亚洲精品在线观看视频| 美美哒免费高清在线观看视频一区二区| 色老汉一区二区三区| 成人欧美一区二区三区| 波多野结衣中文一区| 国产精品嫩草影院av蜜臀| 国内一区二区视频| 日韩欧美国产高清| 免费成人美女在线观看.| 欧美老年两性高潮| 日韩国产欧美在线视频| 69堂国产成人免费视频| 天天做天天摸天天爽国产一区 | 精品国产伦一区二区三区免费 | 国产乱码精品一区二区三区忘忧草 | 狠狠久久亚洲欧美| 精品播放一区二区| 国产乱一区二区| 中文一区二区完整视频在线观看| 国产激情一区二区三区| 国产午夜精品美女毛片视频| www.欧美亚洲| 亚洲精品成人少妇| 欧美日韩一二三| 免费观看成人av| 久久免费视频一区| 菠萝蜜视频在线观看一区| 亚洲欧美区自拍先锋| 欧美日韩美女一区二区| 日韩国产欧美视频| 久久久夜色精品亚洲| 大胆亚洲人体视频| 亚洲综合色视频| 日韩欧美电影一区| 成人免费观看视频| 一区二区三区av电影| 91精品国产91热久久久做人人| 麻豆91精品视频| 国产精品无遮挡| 欧日韩精品视频| 精品一区二区三区视频在线观看| 国产女同互慰高潮91漫画| 91小视频免费观看| 免费黄网站欧美| 综合欧美亚洲日本| 欧美一区二区在线免费播放 |