#include #include #include #include #include #include #include #include #include #include #include #include "ip1811.h" #include "ip1811reg.h" #include "ip1811ds.h" #include "ip1811op.h" #include "ip1811fdat.h" #include "ip218.h" #define MII_OP_READ 0 #define MII_OP_WRITE 1 //#define TEST_REG //#define IP1811DEBUG //#define IP1811DRV_REG_DEBUG #ifdef IP1811DRV_REG_DEBUG #define ip1811drv_dbg(fmt, ...) printk(KERN_DEBUG "<%s:%d>" fmt, __func__, __LINE__, ##__VA_ARGS__) #else #define ip1811drv_dbg(...) #endif//IP1811DRV_REG_DEBUG #define IP1811DRV_REG_ERROR #ifdef IP1811DRV_REG_ERROR #define ip1811drv_err(fmt, ...) printk(KERN_ERR "<%s:%d>" fmt, __func__, __LINE__, ##__VA_ARGS__) #else #define ip1811drv_err(...) #endif//IP1811DRV_REG_ERROR #define FUNC_MSG_IN ip1811drv_dbg("IN \n") #define FUNC_MSG_OUT ip1811drv_dbg("OUT\n") extern u8 CPU_IF_SPEED_NORMAL; #ifdef TEST_REG u16 RegList[16][256]; u8 pg; #endif//TEST_REG #define ip1811delay() (udelay(100)) /*============= misc. driver functions ===================*/ //#define ACCESS_REG_BY_MDIO #ifdef ACCESS_REG_BY_MDIO //-------------- p1811 project GPIO MDIO Function --------------------- #define MDIO_DELAY 0 #define MDIO_RD 0 #define MDIO_WR 1 #define GPIO_MDIO_OFFSET 10 #define GPIO_MDC_OFFSET 11 #include static DEFINE_MUTEX(ip1811_gpio_lock); #define IP1811_GPIO_BASE 0xBD700000 #define IP1811_GPIO_OUTPUT_VALUE_2_OFFSET 0x003C #define IP1811_GPIO_OUTPUT_ENABLE_2_OFFSET 0x0040 #define IP1811_GPIO_INPUT_VALUE_2_OFFSET 0x0038 #define IP1811_GPIO_SET_VALUE_1 0x1 #define IP1811_GPIO_SET_VALUE_0 0x0 static int ip1811_gpio_get(unsigned offset) { void __iomem *base; u32 val; mutex_lock(&ip1811_gpio_lock); base = IP1811_GPIO_BASE + IP1811_GPIO_INPUT_VALUE_2_OFFSET; val = readl(base); val = ((val & BIT(offset))>>offset); mutex_unlock(&ip1811_gpio_lock); return val; } static void ip1811_gpio_set(unsigned offset,int value) { void __iomem *base; u32 val; mutex_lock(&ip1811_gpio_lock); base = IP1811_GPIO_BASE + IP1811_GPIO_OUTPUT_VALUE_2_OFFSET; val = readl(base); val = (value == IP1811_GPIO_SET_VALUE_1) ? (val | BIT(offset)) : (val & ~((BIT(offset)))); writel(val, base); mutex_unlock(&ip1811_gpio_lock); return; } static int ip1811_gpio_direction_out(unsigned offset,int value) { void __iomem *base; u32 val; mutex_lock(&ip1811_gpio_lock); base = IP1811_GPIO_BASE + IP1811_GPIO_OUTPUT_ENABLE_2_OFFSET; val = readl(base); val |= BIT(offset); writel(val, base); mutex_unlock(&ip1811_gpio_lock); return 0; } static int ip1811_gpio_direction_in( unsigned offset) { void __iomem *base; u32 val; mutex_lock(&ip1811_gpio_lock); base = IP1811_GPIO_BASE + IP1811_GPIO_OUTPUT_ENABLE_2_OFFSET; val = readl(base); val &= ~(BIT(offset)); writel(val, base); mutex_unlock(&ip1811_gpio_lock); return val; } void mdio_1(void){ int i; //set MDIO to 1 //set MDC to 0 ip1811_gpio_set(GPIO_MDIO_OFFSET,1); ip1811_gpio_set(GPIO_MDC_OFFSET,0); for(i=0;i>(5-1-i))%2) mdio_1(); else mdio_0(); } for(i=0;i<5;i++){ if((ra>>(5-1-i))%2) mdio_1(); else mdio_0(); } mdio_1(); mdio_0(); for(i=0;i<16;i++){ data=va<>15; if(data==1) mdio_1(); else mdio_0(); } } unsigned short ic_mdio_rd(unsigned short pa, unsigned short ra){ int i=0,j=0; unsigned short data=0; int regBit; unsigned char debug[16]; //set MDC/MDIO pins to GPIO mode ip1811_gpio_direction_out(GPIO_MDC_OFFSET,0); ip1811_gpio_direction_out(GPIO_MDIO_OFFSET,0); //set MDC/MDIO PIN direction //mdio_set_MDC_MDIO_dir(); //MDC direction set to output //MDIO direction set to output mdio_set_MDC_MDIO_direction(1,1); for(i=0;i<32;i++) mdio_1(); mdio_start(); mdio_rw(MDIO_RD); for(i=0;i<5;i++){ if((pa>>(5-1-i))%2) mdio_1(); else mdio_0(); } for(i=0;i<5;i++){ if((ra>>(5-1-i))%2) mdio_1(); else mdio_0(); } mdio_z(); //MDIO DIR set to input mdio_set_MDC_MDIO_direction(1,0); mdio_0(); for(j=0;j<16;j++){ //MDC set to 0 ip1811_gpio_set(GPIO_MDC_OFFSET,0); for(i=0;i phy = pa; smic0 -> reg = ra; smic0 -> wr_data = va; smic0 -> rdwr = 1;//1: write cycle smic0 -> en = 1; base = (void __iomem *)(IP218_MAC_BASE + IP218_MAC_SMICTRL0); ip1811drv_dbg("write [%p]=%08lX\n", base, val); writel(val, base); // wait for writing process done do{ val = readl(base); }while(smic0 -> en); FUNC_MSG_OUT; } unsigned short ic_mdio_rd(unsigned short pa, unsigned short ra){ void __iomem *base; unsigned long val; unsigned short ret; struct ip218_smictrl0 *smic0; struct ip218_smictrl1 *smic1; FUNC_MSG_IN; val = 0; smic0 = (struct ip218_smictrl0 *)&val; smic0 -> phy = pa; smic0 -> reg = ra; smic0 -> rdwr = 0;//0: read cycle smic0 -> en = 1; base = (void __iomem *)(IP218_MAC_BASE + IP218_MAC_SMICTRL0); ip1811drv_dbg("write [%p]=%08lX\n", base, val); writel(val, base); // wait for writing process done do{ val = readl(base); }while(smic0 -> en); // read data from register base = (void __iomem *)(IP218_MAC_BASE + IP218_MAC_SMICTRL1); val = readl(base); smic1 = (struct ip218_smictrl1 *)&val; ret = smic1 -> rd_data; ip1811drv_dbg("read [%p]=%08lX\n", base, val); FUNC_MSG_OUT; return ret; } #endif//ACCESS_REG_BY_MDIO void Write_Reg(u8 regaddr, u16 value) { u16 tmp = CPU_IF_SPEED_NORMAL ? regaddr : (u16)regaddr << 2; #ifdef TEST_REG ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, regaddr, RegList[pg][regaddr]); RegList[pg][regaddr]=value; #else ic_mdio_wr(((tmp)>>5)&0x1f,(tmp)&0x1f,value); #endif//TEST_REG #ifdef TEST_REG ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, regaddr, RegList[pg][regaddr]); #endif//TEST_REG ip1811drv_dbg("write [%02X]=%04x\n", regaddr, value); } u16 Read_Reg(u8 regaddr) { u16 u16d; u16 tmp = CPU_IF_SPEED_NORMAL ? regaddr : (u16)regaddr << 2; #ifdef TEST_REG u16d = RegList[pg][regaddr]; #else u16d=ic_mdio_rd(((tmp)>>5)&0x1f,(tmp)&0x1f); #endif//TEST_REG #ifdef TEST_REG ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, regaddr, RegList[pg][regaddr]); #endif//TEST_REG ip1811drv_dbg("read [%02X]=%04x\n", regaddr, u16d); return u16d; } void _Write_Reg(u8 regaddr, u16 value) { u16 tmp = CPU_IF_SPEED_NORMAL ? regaddr : (u16)regaddr << 2; ic_mdio_wr(((tmp)>>5)&0x1f,(tmp)&0x1f,value); ip1811drv_dbg("write [%02X]=%04x\n", regaddr, value); } u16 _Read_Reg(u8 regaddr) { u16 u16d; u16 tmp = CPU_IF_SPEED_NORMAL ? regaddr : (u16)regaddr << 2; u16d=ic_mdio_rd(((tmp)>>5)&0x1f,(tmp)&0x1f); ip1811drv_dbg("read [%02X]=%04x\n", regaddr, u16d); return u16d; } u16 Read_Reg_0_With_1s(void) { u16 u16d; u16 tmp = CPU_IF_SPEED_NORMAL ? 0x300 : 0x3; u16d = ic_mdio_rd(((tmp)>>5)&0x1f,(tmp)&0x1f); ip1811drv_dbg("read [%04X]=%04x\n", tmp, u16d); return u16d; } void IP2Page(u8 page) // Change page to pagenum { u16 tmp = CPU_IF_SPEED_NORMAL ? REG_Page : (u16)REG_Page << 2; #ifdef TEST_REG pg = page; #else ic_mdio_wr(((tmp)>>5)&0x1f,(tmp)&0x1f,page); #endif//TEST_REG ip1811drv_dbg("set to page[%02u]\n", page); } void _IP2Page(u8 page) // Change page to pagenum { u16 tmp = CPU_IF_SPEED_NORMAL ? REG_Page : (u16)REG_Page << 2; ic_mdio_wr(((tmp)>>5)&0x1f,(tmp)&0x1f,page); ip1811drv_dbg("set to page[%02u]\n", page); } /*============= sub. driver functions ==================*/ static void _WriteRegBits(u8 page, u16 reg, u8 offset, u8 len, u16 val) { u16 mask = 0; u16 u16dat; FUNC_MSG_IN; IP2Page(page); mask = (0x1 << len) - 1; u16dat = Read_Reg(reg); u16dat &= ~(mask<>offset)&mask; FUNC_MSG_OUT; return val; } #if 0 u16 _read_mii_register(u8 phy, u8 page, u8 reg) { u8 option = MII_OP_READ; u16 u16dat = 0; IP2Page(3); // change phy page Write_Reg(P3REG_PHYACCESS_DATA, page); u16dat = (phy & 0x1f); //PHY u16dat |= (0x14 & 0x1f ) << 5; //MII Reg u16dat |= (MII_OP_WRITE & 0x1 )<< 14;//Read or Write u16dat |= 0x1 << 15;//Trigger & Write Write_Reg(P3REG_PHYACCESS_CMD, u16dat); while(_ReadRegBits(3, P3REG_PHYACCESS_CMD, 15, 1)); udelay(5000); // phy read command u16dat = 0; u16dat = (phy & 0x1f); //PHY u16dat |= (reg & 0x1f ) << 5;//MII Reg u16dat |= (option & 0x1 )<< 14;//Read or Write u16dat |= 0x1 << 15;//Trigger & Write Write_Reg(P3REG_PHYACCESS_CMD, u16dat); while(_ReadRegBits(3, P3REG_PHYACCESS_CMD, 15, 1)); udelay(5000); return Read_Reg(P3REG_PHYACCESS_DATA); } u16 _write_mii_register(u8 phy, u8 page, u8 reg, u16 val, u8 all) { u8 option = MII_OP_WRITE; u16 u16dat = 0; u8 count = 0; IP2Page(3); // change phy page do { Write_Reg(P3REG_PHYACCESS_DATA, page); u16dat = ((phy+(count*8)) & 0x1f); //PHY u16dat |= (0x14 & 0x1f ) << 5; //MII Reg u16dat |= (MII_OP_WRITE & 0x1 )<< 14;//Read or Write u16dat |= 0x1 << 15;//Trigger & Write Write_Reg(P3REG_PHYACCESS_CMD, u16dat); while(_ReadRegBits(3, P3REG_PHYACCESS_CMD, 15, 1)); udelay(5000); count = count + 1; }while(all&&(count<3)); // phy write command Write_Reg(P3REG_PHYACCESS_DATA, val); u16dat = 0; u16dat = (phy & 0x1f); //PHY u16dat |= (reg & 0x1f ) << 5; //MII Reg u16dat |= (all & 0x1) << 10; // write to all 24 phy u16dat |= (option & 0x1 )<< 14;//Read or Write u16dat |= 0x1 << 15;//Trigger & Write Write_Reg(P3REG_PHYACCESS_CMD, u16dat); while(_ReadRegBits(3, P3REG_PHYACCESS_CMD, 15, 1)); if(all) udelay(30000); else udelay(5000); return 0; } int get_mii_reg(void *cdata, int len) { u8 phy, page, reg; u16 u16dat; if (sizeof(struct PhySetting) != len) return -EINVAL; phy = ((struct PhySetting *)cdata) ->phy; page = ((struct PhySetting *)cdata) ->page; reg = ((struct PhySetting *)cdata) ->reg; if (phy >= 0x20) return -EINVAL; if (page >= 0x20) return -EINVAL; if (reg >= 0x20) return -EINVAL; u16dat = _read_mii_register(phy, page, reg); ((struct PhySetting *)cdata) ->val = (unsigned short)u16dat; return 0; } int set_mii_reg(void *cdata, int len) { u8 phy, page, reg, all; u16 val; u16 u16dat; if (sizeof(struct PhySetting) != len) return -EINVAL; phy = ((struct PhySetting *)cdata) ->phy; page = ((struct PhySetting *)cdata) ->page; reg = ((struct PhySetting *)cdata) ->reg; val = ((struct PhySetting *)cdata) ->val; all = ((struct PhySetting *)cdata) ->all; // if the command is set 24 phy,bit=1 if (phy >= 0x20) return -EINVAL; if (page >= 0x20) return -EINVAL; if (reg >= 0x20) return -EINVAL; if (all >= 2) return -EINVAL; u16dat = _write_mii_register(phy, page, reg, val, all); return 0; } #endif static int _setGeneralEnable(void *cdata, int len, u8 page, u16 reg, u8 offset) { int gdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } gdata = ((struct GeneralSetting *)cdata) ->gdata; if( gdata != OP_FUNC_ENABLE && gdata != OP_FUNC_DISABLE ){ ip1811drv_err("Error: gdata=%X\n", gdata); return -EINVAL; } ip1811drv_dbg("cdata ->gdata=%d\n", gdata); _WriteRegBits(page, reg, offset, 1, gdata); FUNC_MSG_OUT; return 0; } static int _getGeneralEnable(void *cdata, int len, u8 page, u16 reg, u8 offset) { FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ((struct GeneralSetting *)cdata) ->gdata = _ReadRegBits(page, reg, offset, 1); ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); FUNC_MSG_OUT; return 0; } static int _setPortmapMask(void *cdata, int len, u8 page, u8 reg) { unsigned long pm; int pd; u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } pm = ((struct PortmapSetting *)cdata) ->portmap; pd = ((struct PortmapSetting *)cdata) ->pmdata; if (pm & ~0x1FFFFFFF){ ip1811drv_err("Error: portmap=%08lX\n", pm); return -EINVAL; } if (pd & ~0x1FFFFFFF){ ip1811drv_err("Error: pmdata=%X\n", pd); return -EINVAL; } ip1811drv_dbg("portmap=0x%08lX\n", pm); ip1811drv_dbg("portdata=0x%08X\n", pd); IP2Page(page); u32dat = (u32)Read_Reg(reg+1)<<16 | (u32)Read_Reg(reg); u32dat &= ~pm; u32dat |= pm & pd; Write_Reg(reg, (u16)(u32dat & 0xFFFF)); Write_Reg(reg+1, (u16)(u32dat >> 16)); FUNC_MSG_OUT; return 0; } static int _getPortmapMask(void *cdata, int len, u8 page, u8 reg) { unsigned long pm; u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } pm = ((struct PortmapSetting *)cdata) ->portmap; if (pm & ~0x1FFFFFFF){ ip1811drv_err("Error: portmap=%08lX\n", pm); return -EINVAL; } IP2Page(page); u32dat = (u32)Read_Reg(reg+1)<<16 | (u32)Read_Reg(reg); ((struct PortmapSetting *)cdata) ->pmdata = u32dat & pm; ip1811drv_dbg("cdata ->portmap=0x%08lX\n", ((struct PortmapSetting *)cdata) ->portmap); ip1811drv_dbg("cdata ->pmdata=0x%08X\n", ((struct PortmapSetting *)cdata) ->pmdata); FUNC_MSG_OUT; return 0; } static int _setPortmap(void *cdata, int len, u8 page, u8 reg) { unsigned long pm; int pd; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } pm = ((struct PortmapSetting *)cdata) ->portmap; pd = ((struct PortmapSetting *)cdata) ->pmdata; if (pm & ~0xFFF) { ip1811drv_err("Error: portmap=%08lX\n", pm); return -EINVAL; } if ((pd != OP_FUNC_ENABLE) && (pd != OP_FUNC_DISABLE)) { ip1811drv_err("Error: pd=%X\n", pd); return -EINVAL; } ip1811drv_dbg("portmap=0x%08lX\n", pm); ip1811drv_dbg("portdata=0x%X\n", pd); IP2Page(page); u16dat = Read_Reg(reg); #ifdef COMBINED_PORT if ((pm >> 9) & 0x1) pm |= (u16)(1 << 10); #endif if (pd == OP_FUNC_ENABLE) u16dat |= (u16)pm; else//OP_FUNC_DISABLE u16dat &= ~(u16)pm; Write_Reg(reg, (u16dat & 0xFFF)); FUNC_MSG_OUT; return 0; } static int _getPortmap(void *cdata, int len, u8 page, u8 reg) { unsigned long pm; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } pm = ((struct PortmapSetting *)cdata) ->portmap; if (pm & ~0xFFF){ ip1811drv_err("Error: portmap=%08lX\n", pm); return -EINVAL; } IP2Page(page); u16dat = Read_Reg(reg); u16dat &= (u16)pm; ((struct PortmapSetting *)cdata) ->pmdata = u16dat; ip1811drv_dbg("cdata ->pmdata=0x%08X\n", ((struct PortmapSetting *)cdata) ->pmdata); FUNC_MSG_OUT; return 0; } //------------------------------------------------ //common_smi int switchdSetPortAN(int port, int an) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(an==OP_FUNC_DISABLE || an==OP_FUNC_ENABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("an=%d\n", an); IP2Page(3); u16dat = Read_Reg(P3REG_AN); if (an == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (an == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_AN, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortAN); int setPortAN(void *cdata, int len) { int port, an; ip1811drv_dbg("ip1811: +setPortAN...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; an = ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortAN(port, an) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortAN...\n"); return 0; } int switchdGetPortAN(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = _ReadRegBits(3, P3REG_PORTSTS0 + port/2,6+(port&0x1)*8 , 1); ip1811drv_dbg("an=0x%x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetPortAN); int getPortAN(void *cdata, int len) { int port, an; ip1811drv_dbg("ip1811: +getPortAN...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortAN(port, &an) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = an; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortAN...\n"); return 0; } int switchdSetPortSpeed(int port, int speed) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(speed==OP_SMI_SPEED_10 || speed==OP_SMI_SPEED_100 || (speed==OP_SMI_SPEED_1000 && port>=8)) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("speed=%d\n", speed); IP2Page(3); if (speed == OP_SMI_SPEED_1000) { u16dat = Read_Reg(P3REG_SPG); u16dat |= (u16)(1 << (port-8)); #ifdef COMBINED_PORT if (port==9) u16dat |= (u16)(1 << (port+1-8)); #endif Write_Reg(P3REG_SPG, u16dat); } else { if (port >= 8) { u16dat = Read_Reg(P3REG_SPG); u16dat &= (u16)~(1 << (port-8)); #ifdef COMBINED_PORT if (port==9) u16dat &= (u16)~(1 << (port+1-8)); #endif Write_Reg(P3REG_SPG, u16dat); } u16dat = (u16)( Read_Reg(P3REG_SP) ); if (speed == OP_SMI_SPEED_100) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (speed == OP_SMI_SPEED_100) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_SP, u16dat & 0xFFFF); } return 0; } EXPORT_SYMBOL(switchdSetPortSpeed); int setPortSpeed(void *cdata, int len) { int port, speed; ip1811drv_dbg("ip1811: +setPortSpeed...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; speed= ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortSpeed(port, speed) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortSpeed...\n"); return 0; } int switchdGetPortSpeed(int port, int *ptrInt) { int speed; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif speed = (int) _ReadRegBits(3, P3REG_PORTSTS0 + port/2,1+(port&0x1)*8 , 2); ip1811drv_dbg("speed=0x%x\n", speed); if (speed & 0x2) *ptrInt = OP_SMI_SPEED_1000; else{ if (speed & 0x1) *ptrInt = OP_SMI_SPEED_100; else *ptrInt = OP_SMI_SPEED_10; } return 0; } EXPORT_SYMBOL(switchdGetPortSpeed); int getPortSpeed(void *cdata, int len) { int port, speed; ip1811drv_dbg("ip1811: +getPortSpeed...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortSpeed(port, &speed) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = speed; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortSpeed...\n"); return 0; } int switchdSetPortDuplex(int port, int dup) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(dup==OP_SMI_DUPLEX_HALF || dup==OP_SMI_DUPLEX_FULL) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("dup=%d\n", dup); IP2Page(3); u16dat = Read_Reg(P3REG_DUPLEX); if (dup == OP_SMI_DUPLEX_FULL) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (dup == OP_SMI_DUPLEX_FULL) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_DUPLEX, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortDuplex); int setPortDuplex(void *cdata, int len) { int port, dup; ip1811drv_dbg("ip1811: +setPortDuplex...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; dup =((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortDuplex(port, dup) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortDuplex...\n"); return 0; } int switchdGetPortDuplex(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (int) _ReadRegBits(3, P3REG_PORTSTS0 + port/2,(3+(port&0x1)*8), 1); ip1811drv_dbg("dup=0x%x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetPortDuplex); int getPortDuplex(void *cdata, int len) { int port, dup; ip1811drv_dbg("ip1811: +getPortDuplex...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortDuplex(port, &dup) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = dup; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortDuplex...\n"); return 0; } int switchdSetPortPause(int port, int ps) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(ps==OP_FUNC_ENABLE || ps==OP_FUNC_DISABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("ps=%d\n", ps); IP2Page(3); u16dat = Read_Reg(P3REG_PAUSE); if (ps == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (ps == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_PAUSE, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortPause); int setPortPause(void *cdata, int len) { int port, ps; ip1811drv_dbg("ip1811: +setPortPause...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; ps = ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortPause(port, ps) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortPause...\n"); return 0; } int switchdGetPortPause(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (int) _ReadRegBits(3, P3REG_PORTSTS0 + port/2,4+(port&0x1)*8 , 1); ip1811drv_dbg("ps=0x%x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetPortPause); int getPortPause(void *cdata, int len) { int port, ps; ip1811drv_dbg("ip1811: +getPortPause...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortPause(port, &ps) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = ps; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortPause...\n"); return 0; } int switchdSetPortAsymPause(int port, int aps) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(aps==OP_FUNC_ENABLE || aps==OP_FUNC_DISABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("aps=%d\n", aps); IP2Page(3); u16dat = Read_Reg(P3REG_ASPAUSE); if (aps == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (aps == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_ASPAUSE, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortAsymPause); int setPortAsymPause(void *cdata, int len) { int port, aps; ip1811drv_dbg("ip1811: +setPortAsymPause...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; aps =((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortAsymPause(port, aps) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortAsymPause...\n"); return 0; } int switchdGetPortAsymPause(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (int) _ReadRegBits(3, P3REG_PORTSTS0 + port/2,5+(port&0x1)*8 , 1); ip1811drv_dbg("aps=0x%x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetPortAsymPause); int getPortAsymPause(void *cdata, int len) { int port, aps; ip1811drv_dbg("ip1811: +getPortAsymPause...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortAsymPause(port, &aps) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = aps; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortAsymPause...\n"); return 0; } int switchdSetPortLinkStatus(struct LinkStatusSetting *avg) { int port, sp, dup, ps, asym, an; u16 u16dat; port= avg->port; sp = avg->speed; dup = avg->duplex; ps = avg->pause; asym= avg->asym; an = avg->an; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(sp==OP_SMI_SPEED_10 || sp==OP_SMI_SPEED_100 || (sp==OP_SMI_SPEED_1000 && port>8)) ) return -EINVAL; if ( !(dup==OP_SMI_DUPLEX_HALF || dup==OP_SMI_DUPLEX_FULL) ) return -EINVAL; if ( !(ps==OP_FUNC_DISABLE || ps==OP_FUNC_ENABLE) ) return -EINVAL; if ( !(asym==OP_FUNC_DISABLE || asym==OP_FUNC_ENABLE) ) return -EINVAL; if ( !(an==OP_FUNC_DISABLE || an==OP_FUNC_ENABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("sp=%d dup=%d ps=%d asym=%d an=%d\n", sp, dup, ps, asym, an); IP2Page(3); if (sp == OP_SMI_SPEED_1000) { u16dat = Read_Reg(P3REG_SPG); u16dat |= (u16)(1 << (port-8)); #ifdef COMBINED_PORT if (port==9){ u16dat |= (u16)(1 << (port+1-8)); } #endif Write_Reg(P3REG_SPG, u16dat); } else { if (port >= 8) { u16dat = Read_Reg(P3REG_SPG); u16dat &= (u16)~(1 << (port-8)); #ifdef COMBINED_PORT if (port==9){ u16dat &= (u16)~(1 << (port+1-8)); } #endif Write_Reg(P3REG_SPG, u16dat); } u16dat = Read_Reg(P3REG_SP); if (sp == OP_SMI_SPEED_100) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (sp == OP_SMI_SPEED_100) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_SP, u16dat & 0xFFFF); } u16dat = Read_Reg(P3REG_DUPLEX); if (dup == OP_SMI_DUPLEX_FULL) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (dup == OP_SMI_DUPLEX_FULL) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_DUPLEX, u16dat & 0xFFFF); u16dat = Read_Reg(P3REG_PAUSE); if (ps == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (ps == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_PAUSE, u16dat & 0xFFFF); u16dat = Read_Reg(P3REG_ASPAUSE); if (asym == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (asym == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_ASPAUSE, u16dat & 0xFFFF); u16dat = Read_Reg(P3REG_AN); if (an == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (an == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_AN, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortLinkStatus); int setPortLinkStatus(void *cdata, int len) { int port, sp, dup, ps, asym, an; u16 u16dat; struct LinkStatusSetting *avg = (struct LinkStatusSetting *)cdata; ip1811drv_dbg("ip1811: +setPortLinkStatus...\n"); if (sizeof(struct LinkStatusSetting) != len) return -EINVAL; if(switchdSetPortLinkStatus(avg) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortLinkStatus...\n"); return 0; } int switchdGetPortLinkStatus(struct LinkStatusSetting *cdata) { int port, link, sp, dup, ps, asym, an, fiber; u8 u8dat; u16 u16dat; port = ((struct LinkStatusSetting *)cdata) ->port; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif IP2Page(3); u8dat = P3REG_PORTSTS0 + port/2; u16dat = Read_Reg(u8dat); ip1811drv_dbg("u16dat=0x%04x\n", u16dat); link=(int)( ( u16dat >> (0+(port&0x1)*8) ) & 0x1 ); sp = (int)( ( u16dat >> (1+(port&0x1)*8) ) & 0x3 ); if (sp & 0x2) sp = OP_SMI_SPEED_1000; else { if (sp & 0x1) sp = OP_SMI_SPEED_100; else sp = OP_SMI_SPEED_10; } dup =(int)( ( u16dat >> (3+(port&0x1)*8) ) & 0x1 ); ps = (int)( ( u16dat >> (4+(port&0x1)*8) ) & 0x1 ); asym=(int)( ( u16dat >> (5+(port&0x1)*8) ) & 0x1 ); an = (int)( ( u16dat >> (6+(port&0x1)*8) ) & 0x1 ); fiber = (int)( ( u16dat >> (7+(port&0x1)*8) ) & 0x1 ); ip1811drv_dbg("link=0x%x sp=%d dup=0x%x ps=0x%x asym=0x%x an=0x%x fiber=0x%x\n", link, sp, dup, ps, asym, an, fiber); ((struct LinkStatusSetting *)cdata) ->link = link; ((struct LinkStatusSetting *)cdata) ->speed = sp; ((struct LinkStatusSetting *)cdata) ->duplex = dup; ((struct LinkStatusSetting *)cdata) ->pause = ps; ((struct LinkStatusSetting *)cdata) ->asym = asym; ((struct LinkStatusSetting *)cdata) ->an = an; ((struct LinkStatusSetting *)cdata) ->fiber = fiber; ip1811drv_dbg("cdata ->link=%d\n", ((struct LinkStatusSetting *)cdata) ->link); ip1811drv_dbg("cdata ->speed=%d\n", ((struct LinkStatusSetting *)cdata) ->speed); ip1811drv_dbg("cdata ->duplex=%d\n", ((struct LinkStatusSetting *)cdata) ->duplex); ip1811drv_dbg("cdata ->pause=%d\n", ((struct LinkStatusSetting *)cdata) ->pause); ip1811drv_dbg("cdata ->asym=%d\n", ((struct LinkStatusSetting *)cdata) ->asym); ip1811drv_dbg("cdata ->an=%d\n", ((struct LinkStatusSetting *)cdata) ->an); ip1811drv_dbg("cdata ->fiber=%d\n", ((struct LinkStatusSetting *)cdata) ->fiber); return 0; } EXPORT_SYMBOL(switchdGetPortLinkStatus); int getPortLinkStatus(void *cdata, int len) { struct LinkStatusSetting *avg = (struct LinkStatusSetting *)cdata; ip1811drv_dbg("ip1811: +getPortLinkStatus...\n"); if (sizeof(struct LinkStatusSetting) != len) return -EINVAL; if(switchdGetPortLinkStatus(avg) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -getPortLinkStatus...\n"); return 0; } int switchdSetPortBackpressure(int port, int bp) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(bp==OP_FUNC_ENABLE || bp==OP_FUNC_DISABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("bp=%d\n", bp); IP2Page(3); u16dat = Read_Reg(P3REG_BPRESS); if (bp == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (bp == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_BPRESS, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortBackpressure); int setPortBackpressure(void *cdata, int len) { int port, bp; ip1811drv_dbg("ip1811: +setPortBackpressure...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; bp = ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortBackpressure(port, bp) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortBackpressure...\n"); return 0; } int switchdGetPortBackpressure(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (int)_ReadRegBits(3, P3REG_BPRESS + port/16, port%16, 1); ip1811drv_dbg("bp=0x%x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetPortBackpressure); int getPortBackpressure(void *cdata, int len) { int port, bp; ip1811drv_dbg("ip1811: +getPortBackpressure...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortBackpressure(port, &bp) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = bp; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortBackpressure...\n"); return 0; } int switchdSetPortPowerDown(int port, int pd) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(pd==OP_FUNC_ENABLE || pd==OP_FUNC_DISABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("pd=%d\n", pd); IP2Page(3); u16dat = Read_Reg(P3REG_POWERDOWN); if (pd == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); Write_Reg(P3REG_POWERDOWN, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortPowerDown); int setPortPowerDown(void *cdata, int len) { int port, pd; ip1811drv_dbg("ip1811: +setPortPowerDown...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; pd = ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortPowerDown(port, pd) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortPowerDown...\n"); return 0; } int switchdGetPortPowerDown(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); *ptrInt = (int)_ReadRegBits(3, P3REG_POWERDOWN + port/16, port%16, 1); ip1811drv_dbg("pd=0x%x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetPortPowerDown); int getPortPowerDown(void *cdata, int len) { int port, pd; ip1811drv_dbg("ip1811: +getPortPowerDown...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortPowerDown(port, &pd) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = pd; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortPowerDown...\n"); return 0; } int switchdSetPortForceLink(int port, int fl) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(fl==OP_FUNC_ENABLE || fl==OP_FUNC_DISABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("fl=%d\n", fl); IP2Page(3); u16dat = Read_Reg(P3REG_FORCELINK); if (fl == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (fl == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_FORCELINK, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortForceLink); int setPortForceLink(void *cdata, int len) { int port, fl; ip1811drv_dbg("ip1811: +setPortForceLink...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; fl = ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortForceLink(port, fl) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortForceLink...\n"); return 0; } int switchdGetPortForceLink(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (int)_ReadRegBits(3, P3REG_FORCELINK + port/16, port%16, 1); ip1811drv_dbg("fl=0x%x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetPortForceLink); int getPortForceLink(void *cdata, int len) { int port, fl; ip1811drv_dbg("ip1811: +getPortForceLink...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortForceLink(port, &fl) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = fl; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortForceLink...\n"); return 0; } int switchdSetPortUniDirection(int port, int uni) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(uni==OP_FUNC_ENABLE || uni==OP_FUNC_DISABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("uni=%d\n", uni); IP2Page(3); u16dat = Read_Reg(P3REG_UNIDIRECT); if (uni == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port); else u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (uni == OP_FUNC_ENABLE) u16dat |= (u16)(1 << port+1); else u16dat &= (u16)~(1 << port+1); } #endif Write_Reg(P3REG_UNIDIRECT, u16dat & 0xFFFF); return 0; } EXPORT_SYMBOL(switchdSetPortUniDirection); int setPortUniDirection(void *cdata, int len) { int port, uni; ip1811drv_dbg("ip1811: +setPortUniDirection...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; uni =((struct ByPortSetting *)cdata) ->pdata; if(switchdSetPortUniDirection(port, uni) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setPortUniDirection...\n"); return 0; } int switchdGetPortUniDirection(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (int)_ReadRegBits(3, P3REG_UNIDIRECT + port/16, (port-1)%16, 1); ip1811drv_dbg("uni=0x%x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetPortUniDirection); int getPortUniDirection(void *cdata, int len) { int port, uni; ip1811drv_dbg("ip1811: +getPortUniDirection...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetPortUniDirection(port, &uni) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = uni; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getPortUniDirection...\n"); return 0; } //------------------------------------------------ //common_cap int switchdSetL2CapAct(int ptcl, int act) { u32 u32dat, mask; if (ptcl < OP_CAP_PTCL_BPDU || ptcl > OP_CAP_PTCL_GRP3) return -EINVAL; if (act!=OP_CAP_ACT_FORWARD && act!=OP_CAP_ACT_TO_CPU && act!=OP_CAP_ACT_DROP) return -EINVAL; ip1811drv_dbg("ptcl=%d\n", ptcl); ip1811drv_dbg("act=%d\n", act); IP2Page(0); u32dat = ( Read_Reg(P0REG_L2FRAMEGETCTRL1) << 16 | Read_Reg(P0REG_L2FRAMEGETCTRL) ); mask = (u32)~(0x3 << (ptcl*2)); u32dat &= mask; u32dat |= (u32)(act << (ptcl*2)); Write_Reg(P0REG_L2FRAMEGETCTRL, (u16)(u32dat & 0xFFFF)); Write_Reg(P0REG_L2FRAMEGETCTRL1, (u16)(u32dat >> 16)); return 0; } EXPORT_SYMBOL(switchdSetL2CapAct); int setL2CapAct(void *cdata, int len) { int ptcl, act; ip1811drv_dbg("ip1811: +setL2CapAct...\n"); if (sizeof(struct CapActSetting) != len) return -EINVAL; ptcl= ((struct CapActSetting *)cdata) ->protocol; act = ((struct CapActSetting *)cdata) ->act; if(switchdSetL2CapAct(ptcl, act) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setL2CapAct...\n"); return 0; } int switchdSetCapInBand(int gdata) { if( gdata != OP_CAP_ACT_TO_CPU && gdata != OP_CAP_ACT_DROP ){ ip1811drv_err("Error: gdata=%X\n", gdata); return -EINVAL; } ip1811drv_dbg("cdata ->gdata=%d\n", gdata); _WriteRegBits(0, P0REG_MACBEHAVIOR, 6, 1, (gdata==OP_CAP_ACT_TO_CPU?0x1:0x0)); return 0; } EXPORT_SYMBOL(switchdSetCapInBand); int setCapInBand(void *cdata, int len) { int gdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } gdata = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetCapInBand(gdata) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdSetCapSwitchMac(unsigned char * mac) { int i; u16 u16dat; for(i=0; i<6; i++) ip1811drv_dbg("cdata ->mac[%d]=%X\n", i, mac[i]); IP2Page(0); for(i=0; i<3; i++){ u16dat = ((((u16)mac[i*2])&0xFF)<<8) | (((u16)mac[i*2+1])&0xFF); Write_Reg(P0REG_MACADDRESS+(2-i), u16dat); } } EXPORT_SYMBOL(switchdSetCapSwitchMac); int setCapSwitchMac(void *cdata, int len) { char mac[6]; FUNC_MSG_IN; if (sizeof(struct MACSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } memcpy(mac, ((struct MACSetting *)cdata) ->mac, 6); switchdSetCapSwitchMac(mac); FUNC_MSG_OUT; return 0; } int switchdSetCapIpv6TcpUdpEnable(int enable) { if(enable!=OP_FUNC_ENABLE && enable!=OP_FUNC_DISABLE) { ip1811drv_err("Error: enable=%X\n", enable); return -EINVAL; } ip1811drv_dbg("enable=%d\n", enable); _WriteRegBits(0, P0REG_IPV6RLTCFG, 0, 1, enable); return 0; } EXPORT_SYMBOL(switchdSetCapIpv6TcpUdpEnable); int setCapIpv6TcpUdpEnable(void *cdata, int len) { int ret, en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } en = ((struct GeneralSetting *)cdata) ->gdata; ret = switchdSetCapIpv6TcpUdpEnable(en); FUNC_MSG_OUT; return ret; } //------------------------------------------------ //common_lut int switchdSetSMACLearning(int port, int en) { u32 u32dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if ( !(en==OP_FUNC_DISABLE || en==OP_FUNC_ENABLE) ) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("en=%d\n", en); IP2Page(1); u32dat = (u32)Read_Reg(P1REG_SRCLEARN_ENABLE); if (en == OP_FUNC_ENABLE) u32dat |= (u32)(1 << port); else u32dat &= (u32)~(1 << port); #ifdef COMBINED_PORT if (port==9){ if (en == OP_FUNC_ENABLE) u32dat |= (u32)(1 << port+1); else u32dat &= (u32)~(1 << port+1); } #endif Write_Reg(P1REG_SRCLEARN_ENABLE, (u32dat & 0xFFF)); return 0; } EXPORT_SYMBOL(switchdSetSMACLearning); int setSMACLearning(void *cdata, int len) { int port, en; ip1811drv_dbg("ip1811: +setSMACLearning...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port=((struct ByPortSetting *)cdata) ->port; en = ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetSMACLearning(port, en) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setSMACLearning...\n"); return 0; } int switchdGetSMACLearning(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (int)_ReadRegBits(1, P1REG_SRCLEARN_ENABLE, port, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetSMACLearning); int getSMACLearning(void *cdata, int len) { int port, en; ip1811drv_dbg("ip1811: +getSMACLearning...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetSMACLearning(port, &en) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = en; ip1811drv_dbg("ip1811: -getSMACLearning...\n"); return 0; } int switchdSetLutPortFlush(unsigned long pm, int en) { u16 u16dat; if (pm & 0xF000) return -EINVAL; if ( en != OP_LUT_FLUSH_DYNAMIC_ONLY && en != OP_LUT_FLUSH_STATIC_ONLY && en != OP_LUT_FLUSH_ALL ) return -EINVAL; ip1811drv_dbg("pm=0x%04x\n", (u16)pm); ip1811drv_dbg("en=%d\n", en); /* start to flush LUT */ IP2Page(1); u16dat = 0x80; if (en == OP_LUT_FLUSH_ALL) u16dat |= (u16)0x40; // flush static entries Write_Reg(P1REG_PORTFLUSH, (u16)(pm & 0x0FFF)); Write_Reg(P1REG_LUTFLUSH_CFG, u16dat); udelay(10000);//flush LUT needs waiting at least 4 ms return 0; } EXPORT_SYMBOL(switchdSetLutPortFlush); int setLutPortFlush(void *cdata, int len) { unsigned long pm; int en; ip1811drv_dbg("ip1811: +setLutPortFlush...\n"); if (sizeof(struct PortmapSetting) != len) return -EINVAL; pm = ((struct PortmapSetting *)cdata) ->portmap; en = ((struct PortmapSetting *)cdata) ->pmdata; if(switchdSetLutPortFlush(pm, en) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setLutPortFlush...\n"); return 0; } int switchdSetLutAgingTime(int time) { if (time > 18000) return -EINVAL; ip1811drv_dbg("time=%d\n", time); _WriteRegBits(1, P1REG_LUTAGINGTIME, 0, 15, (u16)(time*1000/AGING_TIME_UNIT)); return 0; } EXPORT_SYMBOL(switchdSetLutAgingTime); int setLutAgingTime(void *cdata, int len) { int time; ip1811drv_dbg("ip1811: +setLutAgingTime...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; time = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetLutAgingTime(time) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setLutAgingTime...\n"); return 0; } void switchdGetLutAgingTime(int *ptrInt) { *ptrInt = ((int)_ReadRegBits(1, P1REG_LUTAGINGTIME, 0, 15))*AGING_TIME_UNIT/1000; } EXPORT_SYMBOL(switchdGetLutAgingTime); int getLutAgingTime(void *cdata, int len) { int time; ip1811drv_dbg("ip1811: +getLutAgingTime...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; switchdGetLutAgingTime(&time); ((struct GeneralSetting *)cdata) ->gdata = time; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getLutAgingTime...\n"); return 0; } int switchdSetLutAgingTimeEnable(int en) { if ( !(en==OP_FUNC_DISABLE || en==OP_FUNC_ENABLE) ) return -EINVAL; ip1811drv_dbg("en=%d\n", en); _WriteRegBits(1, P1REG_LUTAGINGTIME, 15, 1, (en==OP_FUNC_ENABLE)?0:1); return 0; } EXPORT_SYMBOL(switchdSetLutAgingTimeEnable); int setLutAgingTimeEnable(void *cdata, int len) { int en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; en = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetLutAgingTimeEnable(en) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetLutLearningNullSA(int en) { if ( !(en==OP_FUNC_DISABLE || en==OP_FUNC_ENABLE) ) return -EINVAL; ip1811drv_dbg("en=%d\n", en); _WriteRegBits(1, P1REG_SRCLEARNCFG, 1, 1, en); return 0; } EXPORT_SYMBOL(switchdSetLutLearningNullSA); int setLutLearningNullSA(void *cdata, int len) { int en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; en = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetLutLearningNullSA(en) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetLutHashingAlgorithm(int hash) { if ( !(hash==OP_HASH_DIRECT || hash==OP_HASH_CRC) ) return -EINVAL; ip1811drv_dbg("hash=%d\n", hash); _WriteRegBits(1, P1REG_SRCLEARNCFG, 2, 1, (hash==OP_HASH_CRC)?0:1); return 0; } EXPORT_SYMBOL(switchdSetLutHashingAlgorithm); int setLutHashingAlgorithm(void *cdata, int len) { int hash; ip1811drv_dbg("ip1811: +setLutHashingAlgorithm...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; hash = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetLutHashingAlgorithm(hash) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setLutHashingAlgorithm...\n"); return 0; } int switchdSetLutBindingEnable(int en) { if ( !(en==OP_FUNC_DISABLE || en==OP_FUNC_ENABLE) ) return -EINVAL; ip1811drv_dbg("en=%d\n", en); _WriteRegBits(1, P1REG_SRCLEARNCFG, 5, 1, (en==OP_FUNC_ENABLE)?1:0); return 0; } EXPORT_SYMBOL(switchdSetLutBindingEnable); int setLutBindingEnable(void *cdata, int len) { int en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; en = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetLutBindingEnable(en) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetLutBindingEnable(int *ptrInt) { *ptrInt = (int)(_ReadRegBits(1, P1REG_SRCLEARNCFG, 5, 1)?OP_FUNC_ENABLE:OP_FUNC_DISABLE); } EXPORT_SYMBOL(switchdGetLutBindingEnable); int getLutBindingEnable(void *cdata, int len) { int en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; switchdGetLutBindingEnable(&en); ((struct GeneralSetting *)cdata) ->gdata = en; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); FUNC_MSG_OUT; return 0; } //------------------------------------------------ //common_sniffer int switchdSetSnifferSrc(unsigned long pm) { if (pm & 0xFFFFF000) return -EINVAL; ip1811drv_dbg("pm=0x%08x\n",(unsigned long)pm); IP2Page(1); Write_Reg(P1REG_SNIFSRC, (u16)(pm & 0xFFF)); return 0; } EXPORT_SYMBOL(switchdSetSnifferSrc); int setSnifferSrc(void *cdata, int len) { unsigned long pm; ip1811drv_dbg("ip1811: +setSnifferSrc...\n"); if (sizeof(struct PortMemberSetting) != len) return -EINVAL; pm = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetSnifferSrc(pm) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setSnifferSrc...\n"); return 0; } int switchdGetSnifferSrc(u16 *u16dat) { IP2Page(1); *u16dat = (u16)Read_Reg(P1REG_SNIFSRC); ip1811drv_dbg("cdata ->pdata=%d\n", *u16dat); return 0; } EXPORT_SYMBOL(switchdGetSnifferSrc); int getSnifferSrc(void *cdata, int len) { u16 u16dat; ip1811drv_dbg("ip1811: +getSnifferSrc...\n"); if (sizeof(struct PortMemberSetting) != len) return -EINVAL; if(switchdGetSnifferSrc(&u16dat) != 0) return -EINVAL; ((struct PortMemberSetting *)cdata) ->member = (u16dat & 0xFFF); ip1811drv_dbg("cdata ->gdata=0x%08x\n",(unsigned int)((struct PortMemberSetting *)cdata) ->member); ip1811drv_dbg("ip1811: -getSnifferSrc...\n"); return 0; } int switchdSetSnifferDestGrp1(unsigned long pm) { u32 u32dat; if (pm & 0xFFFFF000) return -EINVAL; ip1811drv_dbg("pm=0x%08x\n", (unsigned int)pm); IP2Page(1); u32dat = (u32)Read_Reg(P1REG_SNIFDEST); u32dat = ((u32dat & 0xFFFFF000) | pm); Write_Reg(P1REG_SNIFDEST, (u16)(u32dat & 0xFFF)); return 0; } EXPORT_SYMBOL(switchdSetSnifferDestGrp1); int setSnifferDestGrp1(void *cdata, int len) { unsigned long pm; ip1811drv_dbg("ip1811: +setSnifferDestGrp1...\n"); if (sizeof(struct PortMemberSetting) != len) return -EINVAL; pm = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetSnifferDestGrp1(pm) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setSnifferDestGrp1...\n"); return 0; } int switchdGetSnifferDestGrp1(u16 *u16dat) { IP2Page(1); *u16dat = (u16)Read_Reg(P1REG_SNIFDEST); ip1811drv_dbg("cdata ->pdata=%d\n", *u16dat); return 0; } EXPORT_SYMBOL(switchdGetSnifferDestGrp1); int getSnifferDestGrp1(void *cdata, int len) { u16 u16dat; ip1811drv_dbg("ip1811: +getSnifferDestGrp1...\n"); if (sizeof(struct PortMemberSetting) != len) return -EINVAL; if(switchdGetSnifferDestGrp1(&u16dat) != 0) return -EINVAL; ((struct PortMemberSetting *)cdata) ->member = (u16dat & 0xFFF); ip1811drv_dbg("cdata ->gdata=0x%08x\n", (unsigned int)((struct PortMemberSetting *)cdata) ->member); ip1811drv_dbg("ip1811: -getSnifferDestGrp1...\n"); return 0; } int switchdSetS1Method(int method) { if (methodOP_SNIFFER1_METHOD_BOTHDIR) return -EINVAL; ip1811drv_dbg("method=%d\n", method); _WriteRegBits(1, P1REG_SNIFCFG, 0, 2, method); return 0; } EXPORT_SYMBOL(switchdSetS1Method); int setS1Method(void *cdata, int len) { int method; ip1811drv_dbg("ip1811: +setS1Method...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; method = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetS1Method(method) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setS1Method...\n"); return 0; } int switchdGetS1Method(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 0, 2); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetS1Method); int getS1Method(void *cdata, int len) { int method; ip1811drv_dbg("ip1811: +getS1Method...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetS1Method(&method) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = method; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getS1Method...\n"); return 0; } //------------------------------------------------ //common_storm int switchdSetStormFunc(int storm, int porten) { u8 u8dat=0; if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF && storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP) return -EINVAL; if (porten<0 || (porten&0xFFFFF000)) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); ip1811drv_dbg("porten=0x%08x\n", (unsigned int)porten); IP2Page(1); switch (storm){ case OP_STORM_BCST: u8dat = P1REG_BSTORMEN; break; case OP_STORM_MCST: u8dat = P1REG_MSTORMEN; break; case OP_STORM_DLF: u8dat = P1REG_DLFSTORMEN; break; case OP_STORM_ARP: u8dat = P1REG_ARPSTORMEN; break; case OP_STORM_ICMP: u8dat = P1REG_ICMPSTORMEN; break; } Write_Reg(u8dat, (u16)(porten & 0xFFFF)); return 0; } EXPORT_SYMBOL(switchdSetStormFunc); int setStormFunc(void *cdata, int len) { u8 storm; long porten; ip1811drv_dbg("ip1811: +setStormFunc...\n"); if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; porten= ((struct StormGeneralSetting *)cdata) ->sdata; if(switchdSetStormFunc(storm, porten) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setStormFunc...\n"); return 0; } int switchdGetStormFunc(int storm, u32 *u32dat) { u8 u8dat=0; if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF && storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); IP2Page(1); switch (storm){ case OP_STORM_BCST: u8dat = P1REG_BSTORMEN; break; case OP_STORM_MCST: u8dat = P1REG_MSTORMEN; break; case OP_STORM_DLF: u8dat = P1REG_DLFSTORMEN; break; case OP_STORM_ARP: u8dat = P1REG_ARPSTORMEN; break; case OP_STORM_ICMP: u8dat = P1REG_ICMPSTORMEN; break; } *u32dat = (u32)Read_Reg(u8dat); ip1811drv_dbg("cdata ->sdata=0x%08x\n", *u32dat); return 0; } EXPORT_SYMBOL(switchdGetStormFunc); int getStormFunc(void *cdata, int len) { u8 storm; u32 u32dat; ip1811drv_dbg("ip1811: +getStormFunc...\n"); if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; if(switchdGetStormFunc(storm, &u32dat) != 0) return -EINVAL; ((struct StormGeneralSetting *)cdata) ->sdata = (long)u32dat; ip1811drv_dbg("ip1811: -getStormFunc...\n"); return 0; } int switchdSetStormThreshold(u8 storm, long threshold) { u8 u8dat=0; if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF && storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP) return -EINVAL; if (threshold<0 || threshold>0xFF) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); ip1811drv_dbg("threshold=0x%08x\n", (unsigned int)threshold); switch (storm) { case OP_STORM_BCST: case OP_STORM_MCST: case OP_STORM_DLF: u8dat = P1REG_BSTORMTHRESH; break; case OP_STORM_ARP: u8dat = P1REG_ARPSTORMCFG; break; case OP_STORM_ICMP: u8dat = P1REG_ICMPSTORMCFG; break; } _WriteRegBits(1, u8dat, 0, 8, (u16)threshold); return 0; } EXPORT_SYMBOL(switchdSetStormThreshold); int setStormThreshold(void *cdata, int len) { u8 storm; long threshold; ip1811drv_dbg("ip1811: +setStormThreshold...\n"); if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; threshold = ((struct StormGeneralSetting *)cdata) ->sdata; if(switchdSetStormThreshold(storm, threshold) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setStormThreshold...\n"); return 0; } int switchdGetStormThreshold(u8 storm, long *ptrLong) { u8 u8dat=0; if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF && storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); switch (storm) { case OP_STORM_BCST: case OP_STORM_MCST: case OP_STORM_DLF: u8dat = P1REG_BSTORMTHRESH; break; case OP_STORM_ARP: u8dat = P1REG_ARPSTORMCFG; break; case OP_STORM_ICMP: u8dat = P1REG_ICMPSTORMCFG; break; } *ptrLong = (long)_ReadRegBits(1, u8dat, 0, 8); return 0; } EXPORT_SYMBOL(switchdGetStormThreshold); int getStormThreshold(void *cdata, int len) { u8 storm; long threshold; ip1811drv_dbg("ip1811: +getStormThreshold...\n"); if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; if(switchdGetStormThreshold(storm, &threshold) != 0) return -EINVAL; ((struct StormGeneralSetting *)cdata) ->sdata = threshold; ip1811drv_dbg("cdata ->sdata=0x%08x\n", (unsigned int)((struct StormGeneralSetting *)cdata) ->sdata); ip1811drv_dbg("ip1811: -getStormThreshold...\n"); return 0; } int switchdSetStormCntrClrPeriod(u8 storm, long period) { u8 reg=0; if ( storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF && storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP) return -EINVAL; if (period<0 || period>3) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); ip1811drv_dbg("period=0x%X\n", (unsigned int)period); switch (storm) { case OP_STORM_BCST: case OP_STORM_MCST: case OP_STORM_DLF: reg = P1REG_BSTORMTHRESH; break; case OP_STORM_ARP: reg = P1REG_ARPSTORMCFG; break; case OP_STORM_ICMP: reg = P1REG_ICMPSTORMCFG; break; } ip1811drv_dbg("cdata ->sdata=0x%X\n", (s16)period); _WriteRegBits(1, reg, 8, 2, period); return 0; } EXPORT_SYMBOL(switchdSetStormCntrClrPeriod); int setStormCntrClrPeriod(void *cdata, int len) { u8 storm; long period; FUNC_MSG_IN; if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; period = ((struct StormGeneralSetting *)cdata) ->sdata; if(switchdSetStormCntrClrPeriod(storm, period) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdGetStormCntrClrPeriod(u8 storm, long *ptrInt) { u8 reg =0; if ( storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF && storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); switch (storm) { case OP_STORM_BCST: case OP_STORM_MCST: case OP_STORM_DLF: reg = P1REG_BSTORMTHRESH; break; case OP_STORM_ARP: reg = P1REG_ARPSTORMCFG; break; case OP_STORM_ICMP: reg = P1REG_ICMPSTORMCFG; break; } *ptrInt = _ReadRegBits(1, reg, 8, 2); ip1811drv_dbg("cdata ->sdata=0x%X\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetStormCntrClrPeriod); int getStormCntrClrPeriod(void *cdata, int len) { u8 storm; long period=0; FUNC_MSG_IN; ip1811drv_dbg("ip1811: +getStormCntrClrPeriod...\n"); if (sizeof(struct StormGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } storm = ((struct StormGeneralSetting *)cdata) ->storm; if(switchdGetStormCntrClrPeriod(storm, &period) != 0) return -EINVAL; ((struct StormGeneralSetting *)cdata) ->sdata = period; ip1811drv_dbg("ip1811: -getStormCntrClrPeriod...\n"); FUNC_MSG_OUT; return 0; } int switchdSetStormBlockFrm2Cpu(int storm, int en) { u8 u8dat=0; if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_ARP) return -EINVAL; if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); ip1811drv_dbg("en=0x%08x\n", (unsigned int)en); switch (storm) { case OP_STORM_BCST: case OP_STORM_MCST: u8dat = P1REG_BSTORMTHRESH; break; case OP_STORM_ARP: u8dat = P1REG_ARPSTORMCFG; break; } _WriteRegBits(1, u8dat, 10, 1, en); return 0; } EXPORT_SYMBOL(switchdSetStormBlockFrm2Cpu); int setStormBlockFrm2Cpu(void *cdata, int len) { u8 storm = 0; long en; ip1811drv_dbg("ip1811: +setStormBlockFrm2Cpu...\n"); if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; en = ((struct StormGeneralSetting *)cdata) ->sdata; if(switchdSetStormBlockFrm2Cpu(storm, en) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setStormBlockFrm2Cpu...\n"); return 0; } int switchdGetStormBlockFrm2Cpu(u8 storm, int *ptrInt) { u8 u8dat=0; if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_ARP) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); switch (storm) { case OP_STORM_BCST: case OP_STORM_MCST: u8dat = P1REG_BSTORMTHRESH; break; case OP_STORM_ARP: u8dat = P1REG_ARPSTORMCFG; break; } *ptrInt = (int)_ReadRegBits(1, u8dat, 10, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetStormBlockFrm2Cpu); int getStormBlockFrm2Cpu(void *cdata, int len) { u8 storm; int en; ip1811drv_dbg("ip1811: +getStormBlockFrm2Cpu...\n"); if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; if(switchdGetStormBlockFrm2Cpu(storm, &en) != 0) return -EINVAL; ((struct StormGeneralSetting *)cdata) ->sdata = en; ip1811drv_dbg("cdata ->sdata=0x%08x\n", (unsigned int)((struct StormGeneralSetting *)cdata) ->sdata); ip1811drv_dbg("ip1811: -getStormBlockFrm2Cpu...\n"); return 0; } int switchdSetStormDropInterrupt(u8 storm, int en) { if (storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP) return -EINVAL; if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); ip1811drv_dbg("en=0x%08x\n", en); switch (storm) { case OP_STORM_ARP: _WriteRegBits(1, P1REG_ARPSTORMCFG, 11, 1, (en == OP_FUNC_DISABLE)?0:1); break; case OP_STORM_ICMP: _WriteRegBits(1, P1REG_ICMPSTORMCFG, 10, 1, (en == OP_FUNC_DISABLE)?0:1); break; } return 0; } EXPORT_SYMBOL(switchdSetStormDropInterrupt); int setStormDropInterrupt(void *cdata, int len) { u8 storm; int en; ip1811drv_dbg("ip1811: +setStormDropInterrupt...\n"); if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; en = ((struct StormGeneralSetting *)cdata) ->sdata; if(switchdSetStormDropInterrupt(storm, en) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setStormDropInterrupt...\n"); return 0; } int switchdGetStormDropInterrupt(u8 storm, int *ptrInt) { if (storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP) return -EINVAL; ip1811drv_dbg("storm=0x%02X\n", storm); switch (storm) { case OP_STORM_ARP: *ptrInt = (int)_ReadRegBits(1, P1REG_ARPSTORMCFG, 11, 1); break; case OP_STORM_ICMP: *ptrInt = (int)_ReadRegBits(1, P1REG_ICMPSTORMCFG, 10, 1); break; } ip1811drv_dbg("cdata ->sdata=0x%08x\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetStormDropInterrupt); int getStormDropInterrupt(void *cdata, int len) { u8 storm; int en; ip1811drv_dbg("ip1811: +getStormDropInterrupt...\n"); if (sizeof(struct StormGeneralSetting) != len) return -EINVAL; storm = ((struct StormGeneralSetting *)cdata) ->storm; if(switchdGetStormDropInterrupt(storm, &en) != 0) return -EINVAL; ((struct StormGeneralSetting *)cdata) ->sdata = en; ip1811drv_dbg("ip1811: -getStormDropInterrupt...\n"); return 0; } //------------------------------------------------ //common_loop_detect int switchdSetLdFunc(unsigned int pm, int en) { u16 u16dat; if (pm & 0xF000) return -EINVAL; ip1811drv_dbg("pm=0x%08x\n", pm); ip1811drv_dbg("en=%d\n", en); _WriteRegBits(1, P1REG_MISCCFG, 11, 1, en); IP2Page(0); u16dat = Read_Reg(P0REG_LDEN); u16dat = ((u16dat & 0xF000) | pm); Write_Reg(P0REG_LDEN, u16dat); return 0; } EXPORT_SYMBOL(switchdSetLdFunc); int setLdFunc(void *cdata, int len) { unsigned long pm; int en, ret; u32 u32dat; ip1811drv_dbg("ip1811: +setLdFunc...\n"); if (sizeof(struct PortmapSetting) != len) { ret = -EINVAL; goto out_setLdFunc; } pm = ((struct PortmapSetting *)cdata) ->portmap; en = ((struct PortmapSetting *)cdata) ->pmdata; ret = switchdSetLdFunc(pm, en); out_setLdFunc: ip1811drv_dbg("ip1811: -setLdFunc...\n"); return ret; } int switchdGetLdFunc(unsigned long *portmap, int *pmdata) { u16 u16dat; IP2Page(1); u16dat = Read_Reg(P1REG_MISCCFG); if(u16dat & 0x0800) *pmdata = OP_FUNC_ENABLE; else *pmdata = OP_FUNC_DISABLE; IP2Page(0); u16dat = Read_Reg(P0REG_LDEN); *portmap = (u16dat & 0xFFF); return 0; } EXPORT_SYMBOL(switchdGetLdFunc); int getLdFunc(void *cdata, int len) { int ret; int pmdata; unsigned long portmap; ip1811drv_dbg("ip1811: +getLdFunc...\n"); if (sizeof(struct PortmapSetting) != len) { ret = -EINVAL; goto out_getLdFunc; } ret = switchdGetLdFunc(&portmap, &pmdata); ((struct PortmapSetting *)cdata) ->portmap = portmap; ((struct PortmapSetting *)cdata) ->pmdata = pmdata; ip1811drv_dbg("cdata ->portmap=0x%08x\n", ((struct PortmapSetting *)cdata) ->portmap); ip1811drv_dbg("cdata ->pmdata=%d\n", ((struct PortmapSetting *)cdata) ->pmdata); out_getLdFunc: ip1811drv_dbg("ip1811: -getLdFunc...\n"); return ret; } int switchdSetLdTimeUnit(int time_unit) { if (time_unit!=OP_LD_TIME_UNIT_500MS && time_unit!=OP_LD_TIME_UNIT_10S) return -EINVAL; ip1811drv_dbg("tunit=%d\n", time_unit); _WriteRegBits(0, P0REG_LDCONFIG, 0, 1, time_unit); return 0; } EXPORT_SYMBOL(switchdSetLdTimeUnit); int setLdTimeUnit(void *cdata, int len) { int tunit, ret; ip1811drv_dbg("ip1811: +setLdTimeUnit...\n"); if (sizeof(struct GeneralSetting) != len) { ret = -EINVAL; goto out_setLdTimeUnit; } tunit = ((struct GeneralSetting *)cdata) ->gdata; ret = switchdSetLdTimeUnit(tunit); out_setLdTimeUnit: ip1811drv_dbg("ip1811: -setLdTimeUnit...\n"); return ret; } int switchdGetLdTimeUnit(int *time_unit_get) { *time_unit_get = (int)_ReadRegBits(0, P0REG_LDCONFIG, 0, 1); return 0; } EXPORT_SYMBOL(switchdGetLdTimeUnit); int getLdTimeUnit(void *cdata, int len) { int val, ret; ip1811drv_dbg("ip1811: +getLdTimeUnit...\n"); if (sizeof(struct GeneralSetting) != len) { ret = -EINVAL; } ret = switchdGetLdTimeUnit(&val); ((struct GeneralSetting *)cdata) ->gdata = val; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); out_getLdTimeUnit: ip1811drv_dbg("ip1811: -getLdTimeUnit...\n"); return ret; } int switchdSetLdPktSendTimer(int timer) { if (timer < 0 || timer > 0xFF) return -EINVAL; ip1811drv_dbg("timer=%d\n", timer); _WriteRegBits(0, P0REG_LDTIMER, 0, 8, timer); return 0; } EXPORT_SYMBOL(switchdSetLdPktSendTimer); int setLdPktSendTimer(void *cdata, int len) { int timer, ret; ip1811drv_dbg("ip1811: +setLdPktSendTimer...\n"); if (sizeof(struct GeneralSetting) != len) { ret = -EINVAL; goto out_setLdPktSendTimer; } timer = ((struct GeneralSetting *)cdata) ->gdata; ret = switchdSetLdPktSendTimer(timer); out_setLdPktSendTimer: ip1811drv_dbg("ip1811: -setLdPktSendTimer...\n"); return ret; } int switchdGetLdPktSendTimer(int *send_timer_get) { *send_timer_get = (int)_ReadRegBits(0, P0REG_LDTIMER, 0, 8); return 0; } EXPORT_SYMBOL(switchdGetLdPktSendTimer); int getLdPktSendTimer(void *cdata, int len) { int val, ret; ip1811drv_dbg("ip1811: +getLdPktSendTimer...\n"); if (sizeof(struct GeneralSetting) != len) { ret = -EINVAL; goto out_getLdPktSendTimer; } ret = switchdGetLdPktSendTimer(&val); ((struct GeneralSetting *)cdata) ->gdata = val; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); out_getLdPktSendTimer: ip1811drv_dbg("ip1811: -getLdPktSendTimer...\n"); return ret; } int switchdSetLdBlockReleaseTimer(int timer) { if (timer < 0 || timer > 0xFF) return -EINVAL; ip1811drv_dbg("timer=%d\n", timer); _WriteRegBits(0, P0REG_LDTIMER, 8, 8, timer); return 0; } EXPORT_SYMBOL(switchdSetLdBlockReleaseTimer); int setLdBlockReleaseTimer(void *cdata, int len) { int timer, ret; ip1811drv_dbg("ip1811: +setLdBlockReleaseTimer...\n"); if (sizeof(struct GeneralSetting) != len) { ret = -EINVAL; goto out_setLdBlockReleaseTimer; } timer = ((struct GeneralSetting *)cdata) ->gdata; ret = switchdSetLdBlockReleaseTimer(timer); out_setLdBlockReleaseTimer: ip1811drv_dbg("ip1811: -setLdBlockReleaseTimer...\n"); return ret; } int switchdGetLdBlockReleaseTimer(int *release_timer_get) { *release_timer_get = (int)_ReadRegBits(0, P0REG_LDTIMER, 8, 8); return 0; } EXPORT_SYMBOL(switchdGetLdBlockReleaseTimer); int getLdBlockReleaseTimer(void *cdata, int len) { int val, ret; ip1811drv_dbg("ip1811: +getLdBlockReleaseTimer...\n"); if (sizeof(struct GeneralSetting) != len) { ret = -EINVAL; goto out_getLdBlockReleaseTimer; } ret = switchdGetLdBlockReleaseTimer(&val); ((struct GeneralSetting *)cdata) ->gdata = val; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); out_getLdBlockReleaseTimer: ip1811drv_dbg("ip1811: -getLdBlockReleaseTimer...\n"); return ret; } int switchdGetLdStatus(unsigned long *status) { IP2Page(0); *status = Read_Reg(P0REG_LDSTATUS); return 0; } EXPORT_SYMBOL(switchdGetLdStatus); int getLdStatus(void *cdata, int len) { unsigned long val; int ret; ip1811drv_dbg("ip1811: +getLdStatus...\n"); if (sizeof(struct PortMemberSetting) != len) { ret = -EINVAL; goto out_getLdStatus; } ret = switchdGetLdStatus(&val); ((struct PortMemberSetting *)cdata) ->member = val; ip1811drv_dbg("cdata ->member=%08lX\n", ((struct PortMemberSetting *)cdata) ->member); out_getLdStatus: ip1811drv_dbg("ip1811: -getLdStatus...\n"); return ret; } //ip1811_loop_detect int switchdSetLdDMAC(unsigned char *mac) { int i; u16 u16dat; IP2Page(0); for (i=0; i<3; i++) { u16dat = (u16)( (mac[i*2] << 8) | mac[i*2+1] ); Write_Reg(P0REG_LDDA0+2-i, u16dat); } return 0; } EXPORT_SYMBOL(switchdSetLdDMAC); int setLdDMAC(void *cdata, int len) { int i, ret; u8 da[6]; ip1811drv_dbg("ip1811: +setLdDMAC...\n"); if (sizeof(struct LDDASetting) != len) { ret = -EINVAL; goto out_setLdDMAC; } ip1811drv_dbg("da=["); for (i=0; i<6; i++) { da[i] = ((struct LDDASetting *)cdata) ->da[i]; ip1811drv_dbg("0x%02X, ", da[i]); } ip1811drv_dbg("]\n"); ret = switchdSetLdDMAC(da); out_setLdDMAC: ip1811drv_dbg("ip1811: -setLdDMAC...\n"); return 0; } int switchdSetLdSubType(int stype) { IP2Page(0); Write_Reg(P0REG_LDSUBTYPE, (u16)stype); return 0; } EXPORT_SYMBOL(switchdSetLdSubType); int setLdSubType(void *cdata, int len) { int stype, ret; ip1811drv_dbg("ip1811: +setLdSubType...\n"); if (sizeof(struct GeneralSetting) != len) { ret = -EINVAL; goto out_setLdSubType; } stype = ((struct GeneralSetting *)cdata) ->gdata; if (stype<0 && stype>0xFFFF) { ret = -EINVAL; goto out_setLdSubType; } ip1811drv_dbg("stype=%d\n", stype); ret = switchdSetLdSubType(stype); out_setLdSubType: ip1811drv_dbg("ip1811: -setLdSubType...\n"); return 0; } //------------------------------------------------ //common_stag int switchdSetCpuPortLink(int clink) { if (clink!=OP_CPU_PORT_NORMAL && clink!=OP_CPU_PORT_CPU) return -EINVAL; ip1811drv_dbg("clink=%d\n", clink); return 0; } EXPORT_SYMBOL(switchdSetCpuPortLink); int setCpuPortLink(void *cdata, int len) { int clink; ip1811drv_dbg("ip1811: +setCpuPortLink...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; clink = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetCpuPortLink(clink) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setCpuPortLink...\n"); return 0; } int switchdSetSTagFunc(int en) { if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("en=%d\n", en); if(en == OP_FUNC_ENABLE){ _WriteRegBits(0xE, PEREG_CPUMODE, 0, 2 , 0x3); }else{ _WriteRegBits(0xE, PEREG_CPUMODE, 0, 2 , 0x0); } return 0; } EXPORT_SYMBOL(switchdSetSTagFunc); int setSTagFunc(void *cdata, int len) { int en; ip1811drv_dbg("ip1811: +setSTagFunc...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; en = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetSTagFunc(en) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setSTagFunc...\n"); return 0; } void switchdGetSTagTypeLen(unsigned short *ptrLength, unsigned short *ptrType) { IP2Page(0xE); *ptrType= Read_Reg(PEREG_SPTAG); *ptrLength = 0; ip1811drv_dbg("cdata ->length=%d\n", *ptrLength); ip1811drv_dbg("cdata ->type=0x%08x\n", *ptrType); } EXPORT_SYMBOL(switchdGetSTagTypeLen); int getSTagTypeLen(void *cdata, int len) { unsigned short type, length; ip1811drv_dbg("ip1811: +getSTagTypeLen...\n"); if (sizeof(struct STagTypeLenSetting) != len) return -EINVAL; switchdGetSTagTypeLen(&length, &type); ((struct STagTypeLenSetting *)cdata) ->length = (unsigned int)length; ((struct STagTypeLenSetting *)cdata) ->type = (unsigned int)type; ip1811drv_dbg("ip1811: -getSTagTypeLen...\n"); return 0; } //------------ PTP functions:common Start ----------------------- int setPTPEnable(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 0); FUNC_MSG_OUT; return ret; } int getPTPEnable(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 0); FUNC_MSG_OUT; return ret; } int setPTPDA011B19000000(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 1); FUNC_MSG_OUT; return ret; } int getPTPDA011B19000000(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 1); FUNC_MSG_OUT; return ret; } int setPTPDA0180C200000E(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 2); FUNC_MSG_OUT; return ret; } int getPTPDA0180C200000E(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 2); FUNC_MSG_OUT; return ret; } int setPTPUdpDP(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 3); FUNC_MSG_OUT; return ret; } int getPTPUdpDP(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 3); FUNC_MSG_OUT; return ret; } int setPTPUdpSP(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 4); FUNC_MSG_OUT; return ret; } int getPTPUdpSP(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 4); FUNC_MSG_OUT; return ret; } int setPTPToCPU(void *cdata, int len) { int gdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gdata = ((struct GeneralSetting *)cdata) ->gdata; if( gdata != OP_CAP_ACT_TO_CPU && gdata != OP_CAP_ACT_FORWARD ) { ip1811drv_err("Error: gdata=%X\n", gdata); return -EINVAL; } ip1811drv_dbg("cdata ->gdata=%d\n", gdata); _WriteRegBits(0, P0REG_PTPCFG, 5, 1, gdata==OP_CAP_ACT_TO_CPU?0x0:0x1); FUNC_MSG_OUT; return 0; } int getPTPToCPU(void *cdata, int len) { int gdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gdata = (_ReadRegBits(0, P0REG_PTPCFG, 5, 1)==0x0?OP_CAP_ACT_TO_CPU:OP_CAP_ACT_FORWARD); ((struct GeneralSetting *)cdata) ->gdata = gdata; ip1811drv_dbg("cdata ->gdata=%d\n", gdata); FUNC_MSG_OUT; return 0; } int setPTPSpecialTag(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0x07, P7REG_TXDMA, 5); FUNC_MSG_OUT; return ret; } int getPTPSpecialTag(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0x07, P7REG_TXDMA, 5); FUNC_MSG_OUT; return ret; } int setPTPClockReset(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CLOCK_RESET, 0); FUNC_MSG_OUT; return ret; } int getPTPTimeStamp(void *cdata, int len){ unsigned int cmd=0, port=0; struct PTPReadSetting* ps=(struct PTPReadSetting*)cdata; if(sizeof(struct PTPReadSetting) != len) return -EINVAL; cmd=ps->addr; cmd|=(ps->in_out)<<4; port = ps->port; #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif cmd|=(port)<<5; cmd|=0x8000; IP2Page(0x09); Write_Reg(P9REG_PTP_TIMESTAMP_READ, (u16)cmd); while((Read_Reg(P9REG_PTP_TIMESTAMP_READ) >> 15)&0x1); ps->second=Read_Reg(P9REG_PTP_TIMEDATA_SEC2); ps->second<<=16; ps->second=Read_Reg(P9REG_PTP_TIMEDATA_SEC1); ps->second<<=16; ps->second|=Read_Reg(P9REG_PTP_TIMEDATA_SEC0); ps->nanosecond=Read_Reg(P9REG_PTP_TIMEDATA_NANOSEC1); ps->nanosecond<<=16; ps->nanosecond|=Read_Reg(P9REG_PTP_TIMEDATA_NANOSEC0); return 0; } int setPTPClockEnable(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 0); FUNC_MSG_OUT; return ret; } int getPTPClockEnable(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 0); FUNC_MSG_OUT; return ret; } int setPTPOverwriteEnable(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 1); FUNC_MSG_OUT; return ret; } int getPTPOverwriteEnable(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 1); FUNC_MSG_OUT; return ret; } int setPTPProgrammable(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 2); FUNC_MSG_OUT; return ret; } int getPTPProgrammable(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 2); FUNC_MSG_OUT; return ret; } int setPTPProgrammableOut(void *cdata, int len){ int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 9); FUNC_MSG_OUT; return ret; } int setPTPTimestampEnable(void *cdata, int len){ unsigned int cmd=0, i=0; struct PTPPortTSSetting* pts=(struct PTPPortTSSetting*)cdata; if(sizeof(struct PTPPortTSSetting)!=len) return -EINVAL; IP2Page(0x09); for(i=0;iportmap&(0x01<pmdata==OP_FUNC_ENABLE){ if(pts->in_out){ //egress cmd|=0x01<<(1+(2*(i%8))); } else{ //ingress cmd|=0x01<<(2*(i%8)); } } else{ if(pts->in_out){ //egress cmd&=~(0x01<<(1+(2*(i%8)))); } else{ //ingress cmd&=~(0x01<<(2*(i%8))); } } } if((i%8)==7){ Write_Reg(P9REG_PTP_PORT_TIMESTAMP0+(i/8), (u16)cmd); } } Write_Reg(P9REG_PTP_PORT_TIMESTAMP0+(i/8), (u16)cmd); return 0; } int getPTPTimestampEnable(void *cdata, int len){ unsigned int cmd=0, i=0; struct PTPPortTSSetting* pts=(struct PTPPortTSSetting*)cdata; if(sizeof(struct PTPPortTSSetting)!=len) return -EINVAL; pts->pmdata=OP_FUNC_ENABLE; pts->portmap=0; IP2Page(0x09); for(i=0;iin_out){ //egress if((cmd&(0x01<<(1+(2*(i%8)))))!=0) pts->portmap|=(0x01<portmap|=(0x01<portmap&(0x01<in_out){ //egress cmd|=0x01<<(1+(2*(i%8))); } else{ //ingress cmd|=0x01<<(2*(i%8)); } } if((i%8)==7 && cmd!=0){ Write_Reg(P9REG_PTP_TIMESTAMP_CLEAR0+(i/8), (u16)cmd); cmd=0; } } if(cmd){ Write_Reg(P9REG_PTP_TIMESTAMP_CLEAR0+(i/8), (u16)cmd); } return 0; } int setPTPTimeData(void *cdata, int len){ struct PTPTimeSetting* ts=(struct PTPTimeSetting*)cdata; if(sizeof(struct PTPTimeSetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_TIMEDATA_SEC0, (u16)(ts->second&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_SEC1, (u16)((ts->second>>16)&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_SEC2, (u16)((ts->second>>32)&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC0, (u16)(ts->nanosecond&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC1, (u16)((ts->nanosecond>>16)&0x3FFF)); Write_Reg(P9REG_PTP_CLOCK_CONTROL, 0x03); return 0; } int getPTPTimeData(void *cdata, int len){ struct PTPTimeSetting* ts=(struct PTPTimeSetting*)cdata; if(sizeof(struct PTPTimeSetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_TIMESTAMP_READ, 0); Write_Reg(P9REG_PTP_CLOCK_CONTROL, 0x01); ts->second=Read_Reg(P9REG_PTP_TIMEDATA_SEC2); ts->second<<=16; ts->second=Read_Reg(P9REG_PTP_TIMEDATA_SEC1); ts->second<<=16; ts->second|=Read_Reg(P9REG_PTP_TIMEDATA_SEC0); ts->nanosecond=Read_Reg(P9REG_PTP_TIMEDATA_NANOSEC1); ts->nanosecond<<=16; ts->nanosecond|=Read_Reg(P9REG_PTP_TIMEDATA_NANOSEC0); return 0; } int addPTPTimeData(void *cdata, int len){ struct PTPTimeSetting* ts=(struct PTPTimeSetting*)cdata; if(sizeof(struct PTPTimeSetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_TIMEDATA_SEC0, (u16)(ts->second&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_SEC1, (u16)((ts->second>>16)&0xFFFF)); // Write_Reg(P9REG_PTP_TIMEDATA_SEC2, (u16)((ts->second>>32)&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC0, (u16)(ts->nanosecond&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC1, (u16)((ts->nanosecond>>16)&0x3FFF)); Write_Reg(P9REG_PTP_CLOCK_CONTROL, 0x05); return 0; } int subPTPTimeData(void *cdata, int len){ struct PTPTimeSetting* ts=(struct PTPTimeSetting*)cdata; if(sizeof(struct PTPTimeSetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_TIMEDATA_SEC0, (u16)(ts->second&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_SEC1, (u16)((ts->second>>16)&0xFFFF)); // Write_Reg(P9REG_PTP_TIMEDATA_SEC2, (u16)((ts->second>>32)&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC0, (u16)(ts->nanosecond&0xFFFF)); Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC1, (u16)((ts->nanosecond>>16)&0x3FFF)); Write_Reg(P9REG_PTP_CLOCK_CONTROL, 0x07); return 0; } int setPTPFrequencyAdd(void *cdata, int len){ struct PTPFrequencySetting* fs=(struct PTPFrequencySetting*)cdata; if(sizeof(struct PTPFrequencySetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_FREQUENCY_ADD0, (u16)(fs->frequency&0xFFFF)); Write_Reg(P9REG_PTP_FREQUENCY_ADD1, (u16)((fs->frequency>>16)&0xFFFF)); return 0; } int getPTPFrequencyAdd(void *cdata, int len){ struct PTPFrequencySetting* fs=(struct PTPFrequencySetting*)cdata; if(sizeof(struct PTPFrequencySetting)!=len) return -EINVAL; IP2Page(0x09); fs->frequency=Read_Reg(P9REG_PTP_FREQUENCY_ADD1); fs->frequency<<=16; fs->frequency|=Read_Reg(P9REG_PTP_FREQUENCY_ADD0); return 0; } int setPTPClockPeriod(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_CLOCK_PERIOD, (u16)(((struct GeneralSetting*)cdata)->gdata)&0xFFFF); return 0; } int getPTPClockPeriod(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); ((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_CLOCK_PERIOD); return 0; } int setPTPProgrammableConfig(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_PROGRAMMABLE_OUTPUT, (u16)(((struct GeneralSetting*)cdata)->gdata)&0xFFFF); return 0; } int setPTPDurationFrequencyCompensation(void *cdata, int len){ struct PTPFrequencySetting* fs=(struct PTPFrequencySetting*)cdata; if(sizeof(struct PTPFrequencySetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION0, (u16)(fs->frequency&0xFFFF)); Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION1, (u16)((fs->frequency>>16)&0x3FF)); Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION2, (u16)(fs->clockcycle&0xFFFF)); Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION3, (u16)((fs->clockcycle>>16)&0x3FF)); if(fs->type==1){ //add Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x03); } else{ //sub Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x07); } //Wait a period of time ndelay(fs->period_time); Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x0); return 0; } int setPTPAlwaysFrequencyCompensation(void *cdata, int len){ struct PTPFrequencyPPMSetting* fps=(struct PTPFrequencyPPMSetting*)cdata; if(sizeof(struct PTPFrequencyPPMSetting)!=len) return -EINVAL; IP2Page(0x09); Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION0, (u16)(fps->ppm_l)); Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION1, (u16)(fps->ppm_h)); if(fps->type==1){ //add Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x01); } else{ //Sub Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x05); } return 0; } int getPTPIngressLatency10(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); ((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_INGRESS_LATENCY_10TP); return 0; } int getPTPIngressLatency100(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); ((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_INGRESS_LATENCY_100TP); return 0; } int getPTPIngressLatencyFiber(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); ((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_INGRESS_LATENCY_FIBER); return 0; } int getPTPEgressLatency10(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); ((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_EGRESS_LATENCY_10TP); return 0; } int getPTPEgressLatency100(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); ((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_EGRESS_LATENCY_100TP); return 0; } int getPTPEgressLatencyFiber(void *cdata, int len){ if(sizeof(struct GeneralSetting)!=len) return -EINVAL; IP2Page(0x09); ((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_EGRESS_LATENCY_FIBER); return 0; } //------------ PTP functions:common end ----------------------- int switchdConfigCpuPort(int portid) { ip1811drv_dbg("portid=%d\n", portid); if (portid < 0 || portid >= 12) return -EINVAL; IP2Page(1); Write_Reg(P1REG_CONFIG_CPUPORT, (portid + 1) | 0x20); return 0; } EXPORT_SYMBOL(switchdConfigCpuPort); int configCpuPort(void *cdata, int len) { int portid; ip1811drv_dbg("ip1811: +configCpuPort...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; portid = ((struct GeneralSetting *)cdata) ->gdata; if(switchdConfigCpuPort(portid) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -configCpuPort...\n"); return 0; } int switchdGetCpuPort(int *ptrVal) { *ptrVal = Read_Reg(P1REG_CONFIG_CPUPORT); ip1811drv_dbg("portid=%d\n", *ptrVal); return 0; } EXPORT_SYMBOL(switchdGetCpuPort); int getCpuPort(void *cdata, int len) { int portid; ip1811drv_dbg("ip1811: +getCpuPort...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetCpuPort(&portid) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = portid; ip1811drv_dbg("ip1811: -getCpuPort...\n"); return 0; } //------------------------------------------------ //common_misc int switchdSet8021xFunc(int en, unsigned long pm) { unsigned long reg16; if (pm & 0xF0000000) return -EINVAL; if (en != OP_FUNC_ENABLE && en != OP_FUNC_DISABLE) return -EINVAL; IP2Page(0); if(en == OP_FUNC_ENABLE) { reg16 = Read_Reg(P0REG_PORTLOCKEN); Write_Reg(P0REG_PORTLOCKEN, (u16)(reg16 | pm)); } else {//OP_FUNC_DISABLE reg16 = Read_Reg(P0REG_PORTLOCKEN); Write_Reg(P0REG_PORTLOCKEN, (u16)(reg16 & ~pm)); } return 0; } EXPORT_SYMBOL(switchdSet8021xFunc); int set8021xFunc(void *cdata, int len) { unsigned long pm; int en, ret; ip1811drv_dbg("ip1811: +set8021xFunc...\n"); if (sizeof(struct PortmapSetting) != len) return -EINVAL; pm = ((struct PortmapSetting *)cdata) ->portmap; en = ((struct PortmapSetting *)cdata) ->pmdata; ip1811drv_dbg("pm=0x%08x\n", (unsigned int)pm); ip1811drv_dbg("en=%d\n", en); ret = switchdSet8021xFunc(en, pm); ip1811drv_dbg("ip1811: -set8021xFunc...\n"); return ret; } int switchdGet8021xFunc(int *gdata_p) { IP2Page(0); *gdata_p = (int)Read_Reg(P0REG_PORTLOCKEN); return 0; } EXPORT_SYMBOL(switchdGet8021xFunc); int get8021xFunc(void *cdata, int len) { int val, ret; ip1811drv_dbg("ip1811: +get8021xFunc...\n"); if (sizeof(struct PortmapSetting) != len) return -EINVAL; ret = switchdGet8021xFunc(&val); ((struct PortmapSetting *)cdata) ->portmap = (val & ALL_PHY_PORTS_LIST); ((struct PortmapSetting *)cdata) ->pmdata = val?OP_FUNC_ENABLE:OP_FUNC_DISABLE; ip1811drv_dbg("cdata ->portmap=0x%08x\n", (unsigned int)((struct PortmapSetting *)cdata) ->portmap); ip1811drv_dbg("cdata ->pmdata=%d\n", ((struct PortmapSetting *)cdata) ->pmdata); ip1811drv_dbg("ip1811: -get8021xFunc...\n"); return ret; } int switchdSetReg(u8 page, u8 reg, u16 val) { if (page > 0xE) return -EINVAL; ip1811drv_dbg("page=0x%x\n", page); ip1811drv_dbg("reg=0x%02X\n", reg); ip1811drv_dbg("val=0x%04x\n", val); _IP2Page(page); // ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, P2REG_VLANCFG, // RegList[pg][P2REG_VLANCFG]); _Write_Reg(reg, val); // ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, P2REG_VLANCFG, // RegList[pg][P2REG_VLANCFG]); ip1811drv_dbg("ip1811: -setReg...\n"); return 0; } EXPORT_SYMBOL(switchdSetReg); int setReg(void *cdata, int len) { u8 page, reg; u16 val; ip1811drv_dbg("ip1811: +setReg...\n"); if (sizeof(struct RegSetting) != len) return -EINVAL; page= ((struct RegSetting *)cdata) ->page; reg = ((struct RegSetting *)cdata) ->reg; val = ((struct RegSetting *)cdata) ->val; if(switchdSetReg(page, reg, val) != 0) return -EINVAL; return 0; } int switchdGetReg(u8 page, u8 reg, u16 *ptrVal) { if (page > 0xE) return -EINVAL; ip1811drv_dbg("page=0x%x\n", page); printk("page=0x%x\n", page); ip1811drv_dbg("reg=0x%02X\n", reg); printk("reg=0x%02X\n", reg); _IP2Page(page); // ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, P2REG_VLANCFG, // RegList[pg][P2REG_VLANCFG]); *ptrVal= _Read_Reg(reg); ip1811drv_dbg("u16dat=0x%04x\n", *ptrVal); printk("u16dat=0x%04x\n", *ptrVal); // ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, P2REG_VLANCFG, // RegList[pg][P2REG_VLANCFG]); ip1811drv_dbg("cdata ->val=0x%04x\n", *ptrVal); ip1811drv_dbg("ip1811: -getReg...\n"); return 0; } EXPORT_SYMBOL(switchdGetReg); int getReg(void *cdata, int len) { u8 page, reg; u16 u16dat; printk("ip1811: +getReg...\n"); ip1811drv_dbg("ip1811: +getReg...\n"); if (sizeof(struct RegSetting) != len) return -EINVAL; page= ((struct RegSetting *)cdata) ->page; reg = ((struct RegSetting *)cdata) ->reg; if(switchdGetReg(page, reg, &u16dat) != 0) return -EINVAL; ((struct RegSetting *)cdata) ->val = (unsigned short)u16dat; return 0; } void switchdGetCPUReg(unsigned long reg, int * ptrVal) { volatile unsigned int *p; p = (unsigned int *)(reg); *ptrVal = *p; ip1811drv_dbg("reg=%lX\n", reg); ip1811drv_dbg("get val=%X\n", *ptrVal); } EXPORT_SYMBOL(switchdGetCPUReg); int getCPUReg(void *cdata, int len) { unsigned long reg; int val; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } reg = ((struct PortmapSetting *)cdata) ->portmap; switchdGetCPUReg(reg, &val); ((struct PortmapSetting *)cdata) ->pmdata = val; ip1811delay(); FUNC_MSG_OUT; return 0; } void switchdSetCPUReg(unsigned long reg, int val) { volatile unsigned int *p; p = (unsigned int *)(reg); *p = val; ip1811drv_dbg("reg=%lX\n", reg); ip1811drv_dbg("set val=%X\n", val); } EXPORT_SYMBOL(switchdSetCPUReg); int setCPUReg(void *cdata, int len) { unsigned long reg; int val; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } reg = ((struct PortmapSetting *)cdata) ->portmap; val = ((struct PortmapSetting *)cdata) ->pmdata; switchdSetCPUReg(reg, val); ip1811delay(); FUNC_MSG_OUT; return 0; } int switchdSetSwitchRestart(int en) { if(en!=OP_FUNC_ENABLE){ ip1811drv_err("Error: en=%d\n", en); return -EINVAL; } ip1811drv_dbg("reset the switch of IP1811, all parameters are maintained\n"); _WriteRegBits(0xE, PEREG_SW_RESET, 0, 1, en); return 0; } EXPORT_SYMBOL(switchdSetSwitchRestart); int setSwitchRestart(void *cdata, int len) { int en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } en = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetSwitchRestart(en) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetSwitchReset(int en) { if(en!=OP_FUNC_ENABLE){ ip1811drv_err("Error: en=%d\n", en); return -EINVAL; } ip1811drv_dbg("reset the switch of IP1811, all parameters are reset to default\n"); _WriteRegBits(0xE, PEREG_SW_RESET, 4, 1, en); return 0; } EXPORT_SYMBOL(switchdSetSwitchReset); int setSwitchReset(void *cdata, int len) { int en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } en = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetSwitchReset(en) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdSetCpuIfSpeed(int type) { CPU_IF_SPEED_NORMAL = type; printk("\nip1811: set CPU I/F speed to %s\n",CPU_IF_SPEED_NORMAL?"Normal":"High"); } EXPORT_SYMBOL(switchdSetCpuIfSpeed); int setCpuIfSpeed(void *cdata, int len) { int type; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } switchdSetCpuIfSpeed(type); FUNC_MSG_OUT; return 0; } //------------ CoS functions:common ----------------------------- int setCosTcpUdpUserDefine(void *cdata, int len) { unsigned int ptcl; int act; FUNC_MSG_IN; if (sizeof(struct CapActSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ptcl = ((struct CapActSetting *)cdata) ->protocol; act = ((struct CapActSetting *)cdata) ->act; if( ptcl >= OP_TCPUDP_USER_TOTALNUM) { ip1811drv_err("Error: protocol=%X\n", ptcl); return -EINVAL; } if( act < 0x0 || act > 0xFFFF ) { ip1811drv_err("Error: act=%X\n", act); return -EINVAL; } ip1811drv_dbg("cdata ->ptcl=%X\n", ptcl); ip1811drv_dbg("cdata ->act=%X\n", act); IP2Page(0); Write_Reg(P0REG_TCPUDPUSERDEF + ptcl, (u16)act); FUNC_MSG_OUT; return 0; } int getCosTcpUdpUserDefine(void *cdata, int len) { unsigned int ptcl; int act; FUNC_MSG_IN; if (sizeof(struct CapActSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ptcl = ((struct CapActSetting *)cdata) ->protocol; if( ptcl >= OP_TCPUDP_USER_TOTALNUM) { ip1811drv_err("Error: protocol=%X\n", ptcl); return -EINVAL; } IP2Page(0); act = Read_Reg(P0REG_TCPUDPUSERDEF + ptcl); ((struct CapActSetting *)cdata) ->act = act; ip1811drv_dbg("cdata ->protocol=%X\n", ((struct CapActSetting *)cdata) ->protocol); ip1811drv_dbg("cdata ->act=%X\n", ((struct CapActSetting *)cdata) ->act); FUNC_MSG_OUT; return 0; } int setCosTcpUdpQueue(void *cdata, int len) { unsigned int ptcl; int act; FUNC_MSG_IN; if (sizeof(struct CapActSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ptcl = ((struct CapActSetting *)cdata) ->protocol; act = ((struct CapActSetting *)cdata) ->act; if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM) { ip1811drv_err("Error: protocol=%X\n", ptcl); return -EINVAL; } if( act < OP_TCPUDP_ACT_Q0 || act > OP_TCPUDP_ACT_ALL_PORT || act == 0x8) { ip1811drv_err("Error: act=%X\n", act); return -EINVAL; } ip1811drv_dbg("cdata ->ptcl=%X\n", ptcl); ip1811drv_dbg("cdata ->act=%X\n", act); _WriteRegBits(0, P0REG_TCPUDPPRICFG + ptcl/4, (ptcl%4)*4, 4, act); FUNC_MSG_OUT; return 0; } int getCosTcpUdpQueue(void *cdata, int len) { unsigned int ptcl; int act; FUNC_MSG_IN; if (sizeof(struct CapActSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ptcl = ((struct CapActSetting *)cdata) ->protocol; if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM) { ip1811drv_err("Error: protocol=%X\n", ptcl); return -EINVAL; } act = _ReadRegBits(0, P0REG_TCPUDPPRICFG + (ptcl/4), (ptcl%4)*4, 4); ((struct CapActSetting *)cdata) ->act = act; ip1811drv_dbg("cdata ->protocol=%X\n", ((struct CapActSetting *)cdata) ->protocol); ip1811drv_dbg("cdata ->act=%X\n", ((struct CapActSetting *)cdata) ->act); FUNC_MSG_OUT; return 0; } int setCosTcpUdpEnable(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 0, P0REG_TCPUDFUNCEN); FUNC_MSG_OUT; return ret; } int getCosTcpUdpEnable(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmapMask(cdata, len, 0, P0REG_TCPUDFUNCEN); FUNC_MSG_OUT; return ret; } int setCosTcpEnable(void *cdata, int len) { unsigned int ptcl; int act; FUNC_MSG_IN; if (sizeof(struct CapActSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ptcl = ((struct CapActSetting *)cdata) ->protocol; act = ((struct CapActSetting *)cdata) ->act; if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM) { ip1811drv_err("Error: protocol=%X\n", ptcl); return -EINVAL; } if( act != OP_FUNC_ENABLE && act != OP_FUNC_DISABLE) { ip1811drv_err("Error: act=%X\n", act); return -EINVAL; } ip1811drv_dbg("cdata ->ptcl=%X\n", ptcl); ip1811drv_dbg("cdata ->act=%X\n", act); /* check L3 TCP action */ if(_ReadRegBits(0, P0REG_L3FRAMEGETCTRL, 2, 2) == OP_CAP_ACT_DROP) { ip1811drv_err("Error: L3 TCP action is drop\n"); return -EINVAL; } /* set register */ _WriteRegBits(0, P0REG_TCPCHECKEN + (ptcl/16), (ptcl%16), 1, act); FUNC_MSG_OUT; return 0; } int getCosTcpEnable(void *cdata, int len) { unsigned int ptcl; int act; FUNC_MSG_IN; if (sizeof(struct CapActSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ptcl = ((struct CapActSetting *)cdata) ->protocol; if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM) { ip1811drv_err("Error: protocol=%X\n", ptcl); return -EINVAL; } act = _ReadRegBits(0, P0REG_TCPCHECKEN + (ptcl/16), (ptcl%16), 1); ((struct CapActSetting *)cdata) ->act = act; ip1811drv_dbg("cdata ->protocol=%X\n", ((struct CapActSetting *)cdata) ->protocol); ip1811drv_dbg("cdata ->act=%X\n", ((struct CapActSetting *)cdata) ->act); FUNC_MSG_OUT; return 0; } int setCosUdpEnable(void *cdata, int len) { unsigned int ptcl; int act; FUNC_MSG_IN; if (sizeof(struct CapActSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ptcl = ((struct CapActSetting *)cdata) ->protocol; act = ((struct CapActSetting *)cdata) ->act; if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM) { ip1811drv_err("Error: protocol=%X\n", ptcl); return -EINVAL; } if( act != OP_FUNC_ENABLE && act != OP_FUNC_DISABLE) { ip1811drv_err("Error: act=%X\n", act); return -EINVAL; } ip1811drv_dbg("cdata ->ptcl=%X\n", ptcl); ip1811drv_dbg("cdata ->act=%X\n", act); /* check L3 UDP action */ if(_ReadRegBits(0, P0REG_L3FRAMEGETCTRL, 4, 2) == OP_CAP_ACT_DROP) { ip1811drv_err("Error: L3 UDP action is drop\n"); return -EINVAL; } /* set register */ _WriteRegBits(0, (P0REG_UDPCHECKEN + ptcl/16), (ptcl%16), 1, act); FUNC_MSG_OUT; return 0; } int getCosUdpEnable(void *cdata, int len) { unsigned int ptcl; int act; FUNC_MSG_IN; if (sizeof(struct CapActSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ptcl = ((struct CapActSetting *)cdata) ->protocol; if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM) { ip1811drv_err("Error: protocol=%X\n", ptcl); return -EINVAL; } act = _ReadRegBits(0, (P0REG_UDPCHECKEN + ptcl/16), (ptcl%16), 1); ((struct CapActSetting *)cdata) ->act = act; ip1811drv_dbg("cdata ->protocol=%X\n", ((struct CapActSetting *)cdata) ->protocol); ip1811drv_dbg("cdata ->act=%X\n", ((struct CapActSetting *)cdata) ->act); FUNC_MSG_OUT; return 0; } int setCosTcpFlagDropNull(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0, P0REG_TCPFLGCFGGLB, 0); FUNC_MSG_OUT; return ret; } int getCosTcpFlagDropNull(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0, P0REG_TCPFLGCFGGLB, 0); FUNC_MSG_OUT; return ret; } int setCosTcpFlagDropAllset(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0, P0REG_TCPFLGCFGGLB, 1); FUNC_MSG_OUT; return ret; } int getCosTcpFlagDropAllset(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0, P0REG_TCPFLGCFGGLB, 1); FUNC_MSG_OUT; return ret; } int setCosTcpFlag(void *cdata, int len) { unsigned int index; int fdata; FUNC_MSG_IN; if (sizeof(struct TcpFlagSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } index = ((struct TcpFlagSetting *)cdata) ->index; if( index > OP_TCPFLAG_FLAG3 ) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } fdata = ((struct TcpFlagSetting *)cdata) ->fdata; if( fdata < 0x0 || fdata > 0xFF ) { ip1811drv_err("Error: flag=%X\n", fdata); return -EINVAL; } ip1811drv_dbg("cdata ->index=%X\n", index); ip1811drv_dbg("cdata ->fdata=%X\n", fdata); _WriteRegBits(0, P0REG_TCPFLGCFG0 + index, 0, 8, fdata); FUNC_MSG_OUT; return 0; } int getCosTcpFlag(void *cdata, int len) { unsigned int index; int fdata; FUNC_MSG_IN; if (sizeof(struct TcpFlagSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } index = ((struct TcpFlagSetting *)cdata) ->index; if( index > OP_TCPFLAG_FLAG3 ) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } fdata = _ReadRegBits(0, P0REG_TCPFLGCFG0 + index, 0, 8); ((struct TcpFlagSetting *)cdata) ->index = fdata; ip1811drv_dbg("cdata ->index=%X\n", index); ip1811drv_dbg("cdata ->fdata=%X\n", fdata); FUNC_MSG_OUT; return 0; } int setCosTcpFlagAct(void *cdata, int len) { unsigned int index; int fdata; FUNC_MSG_IN; if (sizeof(struct TcpFlagSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } index = ((struct TcpFlagSetting *)cdata) ->index; if( index > OP_TCPFLAG_FLAG3 ) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } fdata = ((struct TcpFlagSetting *)cdata) ->fdata; if( fdata < OP_TCPFLAG_ACT_NONE || fdata > OP_TCPFLAG_ACT_DROP ) { ip1811drv_err("Error: act=%X\n", fdata); return -EINVAL; } ip1811drv_dbg("cdata ->index=%X\n", index); ip1811drv_dbg("cdata ->fdata=%X\n", fdata); IP2Page(0); /* check L3 TCP action */ if(_ReadRegBits(0, P0REG_L3FRAMEGETCTRL, 2, 2) == OP_CAP_ACT_DROP) { ip1811drv_err("Error: L3 TCP action is drop\n"); return -EINVAL; } /* set register */ _WriteRegBits(0, P0REG_TCPFLGCFG0 + index, 12, 2, fdata); FUNC_MSG_OUT; return 0; } int getCosTcpFlagAct(void *cdata, int len) { unsigned int index; int fdata; FUNC_MSG_IN; if (sizeof(struct TcpFlagSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } index = ((struct TcpFlagSetting *)cdata) ->index; if( index > OP_TCPFLAG_FLAG3 ) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } fdata = _ReadRegBits(0, P0REG_TCPFLGCFG0 + index, 12, 2); ((struct TcpFlagSetting *)cdata) ->fdata = fdata; ip1811drv_dbg("cdata ->index=%X\n", index); ip1811drv_dbg("cdata ->fdata=%X\n", fdata); FUNC_MSG_OUT; return 0; } int setCosTcpFlagPort(void *cdata, int len) { unsigned int index; int fdata; FUNC_MSG_IN; if (sizeof(struct TcpFlagSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } index = ((struct TcpFlagSetting *)cdata) ->index; if( index > OP_TCPFLAG_FLAG3 ) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } fdata = ((struct TcpFlagSetting *)cdata) ->fdata; if( fdata & ~0xFFF ) { ip1811drv_err("Error: portmap=%X\n", fdata); return -EINVAL; } ip1811drv_dbg("cdata ->index=%X\n", index); ip1811drv_dbg("cdata ->fdata=%X\n", fdata); IP2Page(0); Write_Reg(P0REG_TCPFLGPORTEN+index*2, fdata&0xFFF); FUNC_MSG_OUT; return 0; } int getCosTcpFlagPort(void *cdata, int len) { unsigned int index; int fdata; FUNC_MSG_IN; if (sizeof(struct TcpFlagSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } index = ((struct TcpFlagSetting *)cdata) ->index; if( index > OP_TCPFLAG_FLAG3 ) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } IP2Page(0); fdata = Read_Reg(P0REG_TCPFLGPORTEN+index*2); ((struct TcpFlagSetting *)cdata) ->fdata = fdata; ip1811drv_dbg("cdata ->index=%X\n", index); ip1811drv_dbg("cdata ->fdata=%X\n", fdata); FUNC_MSG_OUT; return 0; } //------------ CoS functions:common end ------------------------ //------------------------------------------------ //common_stp int switchdSetMstpFunc(int en) { if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("en=%d\n", en); _WriteRegBits(2, P2REG_VLANCFG, 6, 1, en); //MSTP enable _WriteRegBits(2, P2REG_VLANCFG, 2, 1, en); //IVL return 0; } EXPORT_SYMBOL(switchdSetMstpFunc); int setMstpFunc(void *cdata, int len) { int en; ip1811drv_dbg("ip1811: +setMstpFunc...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; en = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetMstpFunc(en) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setMstpFunc...\n"); return 0; } int switchdGetMstpFunc(int *ptrInt) { *ptrInt = (int)_ReadRegBits(2, P2REG_VLANCFG, 6, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetMstpFunc); int getMstpFunc(void *cdata, int len) { int en; ip1811drv_dbg("ip1811: +getMstpFunc...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetMstpFunc(&en) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = en; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getMstpFunc...\n"); return 0; } //common_lacp int switchdSetTrunkHashMthd(int mthd) { if (mthd < OP_TRUNK_HASH_METHOD_PORT_ID || mthd > OP_TRUNK_HASH_METHOD_SP) return -EINVAL; ip1811drv_dbg("mthd=%d\n", mthd); _WriteRegBits(1, P1REG_TRUNKCFG, 0, 3, mthd); return 0; } EXPORT_SYMBOL(switchdSetTrunkHashMthd); int setTrunkHashMthd(void *cdata, int len) { int mthd; ip1811drv_dbg("ip1811: +setTrunkHashMthd...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; mthd = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetTrunkHashMthd(mthd) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setTrunkHashMthd...\n"); return 0; } int switchdGetTrunkHashMthd(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_TRUNKCFG, 0, 3); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetTrunkHashMthd); int getTrunkHashMthd(void *cdata, int len) { int mthd; ip1811drv_dbg("ip1811: +getTrunkHashMthd...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetTrunkHashMthd(&mthd) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = mthd; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getTrunkHashMthd...\n"); return 0; } int switchdSetTrunkMbr(unsigned long pmask, unsigned long state) { unsigned long u32dat; if ((pmask & 0xFFFFF000) || !pmask) return -EINVAL; if ((state & 0xFFFFF000) || (state & ~pmask)) return -EINVAL; ip1811drv_dbg("pmask=0x%08X\n", pmask); ip1811drv_dbg("state=0x%08X\n", state); IP2Page(1); u32dat= (unsigned long)( Read_Reg(P1REG_TRUNKGRP) ); pmask = (unsigned long)( pmask&0xFFF ); state = (unsigned long)( state&0xFFF ); u32dat &= (~pmask); u32dat |= state; #ifdef COMBINED_PORT u32dat |= 0x600; #endif Write_Reg(P1REG_TRUNKGRP, (u32dat & 0xFFF)); return 0; } EXPORT_SYMBOL(switchdSetTrunkMbr); int setTrunkMbr(void *cdata, int len) { unsigned long pmask, state, u32dat; ip1811drv_dbg("ip1811: +setTrunkMbr...\n"); if (sizeof(struct TrunkMemberSetting) != len) return -EINVAL; pmask = ((struct TrunkMemberSetting *)cdata) ->portmask; state = ((struct TrunkMemberSetting *)cdata) ->tstate; if(switchdSetTrunkMbr(pmask, state) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setTrunkMbr...\n"); return 0; } int switchdGetTrunkMbr(unsigned long pmask, unsigned long *ptrInt) { if ((pmask & 0xFFFFF000) || !pmask) return -EINVAL; ip1811drv_dbg("pmask=0x%08X\n", pmask); IP2Page(1); *ptrInt = (unsigned long)( (Read_Reg(P1REG_TRUNKGRP) & 0xFFF) & pmask ); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetTrunkMbr); int getTrunkMbr(void *cdata, int len) { unsigned long pmask, u32dat; ip1811drv_dbg("ip1811: +getTrunkMbr...\n"); if (sizeof(struct TrunkMemberSetting) != len) return -EINVAL; pmask = ((struct TrunkMemberSetting *)cdata) ->portmask; if(switchdGetTrunkMbr(pmask, &u32dat) != 0) return -EINVAL; ((struct TrunkMemberSetting *)cdata) ->tstate = u32dat; ip1811drv_dbg("cdata ->tstate=0x%08x\n", (unsigned int)((struct TrunkMemberSetting *)cdata) ->tstate); ip1811drv_dbg("ip1811: -getTrunkMbr...\n"); return 0; } int switchdSetCpuNCareTrunkAndVlan(int en) { if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("en=%d\n", en); _WriteRegBits(1, P1REG_TRUNKCFG, 4, 1, en); return 0; } EXPORT_SYMBOL(switchdSetCpuNCareTrunkAndVlan); int setCpuNCareTrunkAndVlan(void *cdata, int len) { int en; ip1811drv_dbg("ip1811: +setCpuNCareTrunkAndVlan...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; en = ((struct GeneralSetting *)cdata) ->gdata; switchdSetCpuNCareTrunkAndVlan(en); ip1811drv_dbg("ip1811: -setCpuNCareTrunkAndVlan...\n"); return 0; } int switchdGetCpuNCareTrunkAndVlan(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_TRUNKCFG, 4, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetCpuNCareTrunkAndVlan); int getCpuNCareTrunkAndVlan(void *cdata, int len) { int en; ip1811drv_dbg("ip1811: +getCpuNCareTrunkAndVlan...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetCpuNCareTrunkAndVlan(&en) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = en; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getCpuNCareTrunkAndVlan...\n"); return 0; } //------------------------------------------------ //common_vlan int switchdSetVlanEgressFrame(int mode) { if (mode > 0x7 ) { ip1811drv_err("Error: mode=%X\n", mode); return -EINVAL; } ip1811drv_dbg("mode=0x%08x\n", mode); _WriteRegBits(2, P2REG_VLAN_EGRESS_CFG1, 0, 3, mode); return 0; } EXPORT_SYMBOL(switchdSetVlanEgressFrame); int setVlanEgressFrame(void *cdata, int len) { u16 mode; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; mode = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetVlanEgressFrame(mode) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanEgressFrame(int *ptrInt) { *ptrInt = (int)_ReadRegBits(2,P2REG_VLAN_EGRESS_CFG1, 0, 3); } EXPORT_SYMBOL(switchdGetVlanEgressFrame); int getVlanEgressFrame(void *cdata, int len) { int ftype; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; switchdGetVlanEgressFrame(&ftype); ((struct GeneralSetting *)cdata) ->gdata = ftype; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); FUNC_MSG_OUT; return 0; } int switchdSetVlanTagging(int mode) { if ((mode != OP_VLAN_TAGGING_BY_PORT) && (mode != OP_VLAN_TAGGING_BY_VID)) { ip1811drv_err("Error: mode=%X\n", mode); return -EINVAL; } ip1811drv_dbg("mode=0x%08x\n", mode); _WriteRegBits(2, P2REG_VLANCFG, 3, 1, mode); return 0; } EXPORT_SYMBOL(switchdSetVlanTagging); int setVlanTagging(void *cdata, int len) { u16 mode; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; mode = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetVlanTagging(mode) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanType(int mode) { if ((mode != OP_VLAN_TYPE_TAG) && (mode != OP_VLAN_TYPE_GROUP)) { ip1811drv_err("Error: mode=%X\n", mode); return -EINVAL; } ip1811drv_dbg("mode=0x%08x\n", mode); /* set vlan type: port/tag base */ _WriteRegBits(2, P2REG_VLANCFG, 1, 1, mode); /* set vlan protocol base */ _WriteRegBits(2, P2REG_VLANCFG, 0, 1, mode); return 0; } EXPORT_SYMBOL(switchdSetVlanType); int setVlanType(void *cdata, int len) { u16 mode; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; mode = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetVlanType(mode) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanGroup(unsigned long pm, int option) { u32 u32dat; int i; if (pm & ~(0x0FFF)) { ip1811drv_err("Error: portmap=%08lX\n", pm); return -EINVAL; } if (option & ~0x1) { ip1811drv_err("Error: option=%X\n", option); return -EINVAL; } ip1811drv_dbg("pm=0x%08lx\n", pm); ip1811drv_dbg("option=%x\n", option); IP2Page(2); for(i=0;i>i)&0x1)) continue; u32dat = (u32)Read_Reg(P2REG_VLANGROUP+2*i); if(option) u32dat |= pm; else u32dat &= ~pm; Write_Reg(P2REG_VLANGROUP+2*i, (u16)(u32dat & 0xFFFF)); //Write_Reg(P2REG_VLANGROUP+1+2*i, (u16)(u32dat >> 16)); } return 0; } EXPORT_SYMBOL(switchdSetVlanGroup); int setVlanGroup(void *cdata, int len) { unsigned long pm; int option; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len) return -EINVAL; pm = ((struct PortmapSetting *)cdata) ->portmap; option = ((struct PortmapSetting *)cdata) ->pmdata; if(switchdSetVlanGroup(pm, option) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanQinQPType(int type) { if (type&(~0xFFFF)) { ip1811drv_err("Error: type=%d\n", type); return -EINVAL; } ip1811drv_dbg("type=0x%08x\n", type); IP2Page(7); Write_Reg(P7REG_QINQEGTYPELEN, type); return 0; } EXPORT_SYMBOL(switchdSetVlanQinQPType); int setVlanQinQPType(void *cdata, int len) { int type; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; type = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetVlanQinQPType(type) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanQinQPAddtag(int member) { if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(7); Write_Reg(P7REG_QINQ_ADDTAG, (u16)(member & 0xFFFF)); //Write_Reg(P7REG_QINQ_ADDTAG+1, (u16)(member >> 16)); return 0; } EXPORT_SYMBOL(switchdSetVlanQinQPAddtag); int setVlanQinQPAddtag(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanQinQPAddtag(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanQinQPAddtag(u32 *u32dat) { IP2Page(7); *u32dat = (u32)Read_Reg(P7REG_QINQ_ADDTAG); } EXPORT_SYMBOL(switchdGetVlanQinQPAddtag); int getVlanQinQPAddtag(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanQinQPAddtag(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanQinQPRmvtag(int member) { if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(7); Write_Reg(P7REG_QINQ_RMVTAG, (u16)(member & 0xFFFF)); //Write_Reg(P7REG_QINQ_RMVTAG+1, (u16)(member >> 16)); return 0; } EXPORT_SYMBOL(switchdSetVlanQinQPRmvtag); int setVlanQinQPRmvtag(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanQinQPRmvtag(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanQinQPRmvtag(u32 *u32dat) { IP2Page(7); *u32dat = (u32)Read_Reg(P7REG_QINQ_RMVTAG); } EXPORT_SYMBOL(switchdGetVlanQinQPRmvtag); int getVlanQinQPRmvtag(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanQinQPRmvtag(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanQinQPRxdet(int member) { if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(7); Write_Reg(P7REG_QINQ_DET_RX, (u16)(member & 0xFFFF)); //Write_Reg(P7REG_QINQ_DET_RX+1, (u16)(member >> 16)); return 0; } EXPORT_SYMBOL(switchdSetVlanQinQPRxdet); int setVlanQinQPRxdet(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanQinQPRxdet(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanQinQPRxdet(u32 *u32dat) { IP2Page(7); *u32dat = (u32)Read_Reg(P7REG_QINQ_DET_RX); } EXPORT_SYMBOL(switchdGetVlanQinQPRxdet); int getVlanQinQPRxdet(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanQinQPRxdet(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanQinQPKeep(int member) { int i; if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); for(i=0; i>i)&0x1)); } return 0; } EXPORT_SYMBOL(switchdSetVlanQinQPKeep); int setVlanQinQPKeep(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanQinQPKeep(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanQinQPKeep(u32 *u32dat) { int i; u16 u16dat; IP2Page(7); for(i=0; i>12)&0x1)<member = member; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanQinQPIndex(int port, int index) { if (port < 0 || port >= MAX_PHY_NUM) { ip1811drv_err("Error: port=%X\n", port); return -EINVAL; } if (index < 0 || index > 15) { ip1811drv_err("Error: pmdata=%X\n", index); return -EINVAL; } ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("index=%d\n", index); //index |= (0x0001 << 8); _WriteRegBits(7, P7REG_QINQ_P_DATA+port, 0, 4, index); #ifdef COMBINED_PORT if (port==9) _WriteRegBits(7, P7REG_QINQ_P_DATA+port+1, 0, 4, index); #endif return 0; } EXPORT_SYMBOL(switchdSetVlanQinQPIndex); int setVlanQinQPIndex(void *cdata, int len) { int port, index; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; index= ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetVlanQinQPIndex(port, index) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdGetVlanQinQPIndex(int port, int *index) { if (port < 0 || port >= MAX_PHY_NUM) { ip1811drv_err("Error: port=%X\n", port); return -EINVAL; } #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *index= _ReadRegBits(7,P7REG_QINQ_P_DATA+port, 0, 4); return 0; } EXPORT_SYMBOL(switchdGetVlanQinQPIndex); int getVlanQinQPIndex(void *cdata, int len) { int port; int index; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetVlanQinQPIndex(port, &index) != 0) return -EINVAL; ((struct ByPortSetting *)cdata) ->pdata = index; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); FUNC_MSG_OUT; return 0; } int switchdSetVlanQinQIndex(int index, int value) { if (index<0 || index>15) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } if (value & (~0xFFFF)) { ip1811drv_err("Error: data=%x\n", value); return -EINVAL; } ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("value=0x%x\n", value); IP2Page(7); Write_Reg(P7REG_QINQ_DATA+index, (u16)value); return 0; } EXPORT_SYMBOL(switchdSetVlanQinQIndex); int setVlanQinQIndex(void *cdata, int len) { int type, data, ret; struct VlanSetting *vs = (struct VlanSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct VlanSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } type = vs ->vtype; data = vs ->vdata; ret = switchdSetVlanQinQIndex(type, data); FUNC_MSG_OUT; return ret; } int switchdSetVlanQinQStagSelectMethod(int port, int method) { if (port<0 || port>=MAX_PHY_NUM) { ip1811drv_err("Error: port=%X\n", port); return -EINVAL; } ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("method=%d\n", method); _WriteRegBits(7, P7REG_QINQ_P_DATA+port, 8, 4, method); #ifdef COMBINED_PORT if (port==9) _WriteRegBits(7, P7REG_QINQ_P_DATA+port+1, 8, 4, method); #endif return 0; } EXPORT_SYMBOL(switchdSetVlanQinQStagSelectMethod); int setVlanQinQStagSelectMethod(void *cdata, int len) { int port, method, ret; struct ByPortSetting *bps = (struct ByPortSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } port = bps ->port; method = bps ->pdata; ret = switchdSetVlanQinQStagSelectMethod(port, method) ; FUNC_MSG_OUT; return ret; } int switchdSetVlanPortAddtag(int member) { if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(2); Write_Reg(P2REG_VLAN_ADDTAG, (u16)(member & 0xFFFF)); //Write_Reg(P2REG_VLAN_ADDTAG+1, (u16)(member >> 16)); return 0; } EXPORT_SYMBOL(switchdSetVlanPortAddtag); int setVlanPortAddtag(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanPortAddtag(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanPortAddtag(u32 *u32dat) { IP2Page(2); *u32dat = (u32)Read_Reg(P2REG_VLAN_ADDTAG); } EXPORT_SYMBOL(switchdGetVlanPortAddtag); int getVlanPortAddtag(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanPortAddtag(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanPortRmvtag(int member) { if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(2); Write_Reg(P2REG_VLAN_RMVTAG, (u16)(member & 0xFFFF)); //Write_Reg(P2REG_VLAN_RMVTAG+1, (u16)(member >> 16)); return 0; } EXPORT_SYMBOL(switchdSetVlanPortRmvtag); int setVlanPortRmvtag(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanPortRmvtag(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanPortRmvtag(u32 *u32dat) { IP2Page(2); *u32dat = (u32)Read_Reg(P2REG_VLAN_RMVTAG); } EXPORT_SYMBOL(switchdGetVlanPortRmvtag); int getVlanPortRmvtag(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanPortRmvtag(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanPortForce(int member) { int i; if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); for(i=0; i>i)&0x1); } return 0; } EXPORT_SYMBOL(switchdSetVlanPortForce); int setVlanPortForce(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanPortForce(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanPortForce(u32 *u32dat) { u16 u16dat; int i; IP2Page(2); for(i=0; i>12)&0x1)<member = member; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanPortUplink(int member) { //u16 u16dat; if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(2); Write_Reg(P2REG_VLAN_UPLINK, (u16)((member & 0xFFFF) | 0x1000)); //u16dat = (u16)(member >> 16); //u16dat |= (u16)0x1<<13; //enable uplink //_WriteRegBits(2, P2REG_VLAN_UPLINK+1, 0, 14, u16dat); return 0; } EXPORT_SYMBOL(switchdSetVlanPortUplink); int setVlanPortUplink(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanPortUplink(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanPortUplink(u32 *u32dat) { IP2Page(2); *u32dat = (u32)Read_Reg(P2REG_VLAN_UPLINK); *u32dat &= 0x0FFF; } EXPORT_SYMBOL(switchdGetVlanPortUplink); int getVlanPortUplink(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanPortUplink(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanPortExclusive(int member) { if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(2); Write_Reg(P2REG_VLAN_EXCLUSIVE, (u16)(member & 0xFFFF)); //Write_Reg(P2REG_VLAN_EXCLUSIVE+1, (u16)(member >> 16)); return 0; } EXPORT_SYMBOL(switchdSetVlanPortExclusive); int setVlanPortExclusive(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanPortExclusive(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanPortExclusive(u32 *u32dat) { IP2Page(2); *u32dat = (u32)Read_Reg(P2REG_VLAN_EXCLUSIVE); } EXPORT_SYMBOL(switchdGetVlanPortExclusive); int getVlanPortExclusive(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanPortExclusive(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanPortEgress(int member) { if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(2); Write_Reg(P2REG_VLAN_EGRESS_CFG, (u16)(member & 0xFFFF)); //_WriteRegBits(2, P2REG_VLAN_EGRESS_CFG+1, 0, 13, (u16)(member >> 16)); return 0; } EXPORT_SYMBOL(switchdSetVlanPortEgress); int setVlanPortEgress(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanPortEgress(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanPortEgress(u32 *u32dat) { IP2Page(2); *u32dat = (u32)Read_Reg(P2REG_VLAN_EGRESS_CFG); //u32dat &= 0x1FFFFFFF; } EXPORT_SYMBOL(switchdGetVlanPortEgress); int getVlanPortEgress(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanPortEgress(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanPortIngressFrame(int port, int pdata) { if (port < 0 || port >= MAX_PHY_NUM) { ip1811drv_err("Error: port=%d\n", port); return -EINVAL; } if (pdata < 0 || pdata > 0x3) { ip1811drv_err("Error: pdata=0x%X\n", pdata); return -EINVAL; } ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("pdata=0x%X\n", pdata); _WriteRegBits(2, P2REG_VLAN_INGRESS_FRAME_0, port, 1, (pdata&0x1)); _WriteRegBits(2, P2REG_VLAN_INGRESS_FRAME_1, port, 1, ((pdata>>1)&0x1)); #ifdef COMBINED_PORT if (port==9){ _WriteRegBits(2, P2REG_VLAN_INGRESS_FRAME_0, port+1, 1, (pdata&0x1)); _WriteRegBits(2, P2REG_VLAN_INGRESS_FRAME_1, port+1, 1, ((pdata>>1)&0x1)); } #endif return 0; } EXPORT_SYMBOL(switchdSetVlanPortIngressFrame); int setVlanPortIngressFrame(void *cdata, int len) { int port, pdata; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; pdata = ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetVlanPortIngressFrame(port, pdata) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanPortIngressCheck(int member) { if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%08X\n", member); return -EINVAL; } ip1811drv_dbg("member=0x%08x\n", member); IP2Page(2); Write_Reg(P2REG_VLAN_INGRESS_CHK, (u16)(member & 0xFFFF)); //Write_Reg(P2REG_VLAN_INGRESS_CHK+1, (u16)(member >> 16)); return 0; } EXPORT_SYMBOL(switchdSetVlanPortIngressCheck); int setVlanPortIngressCheck(void *cdata, int len) { int member; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; member = ((struct PortMemberSetting *)cdata) ->member; if(switchdSetVlanPortIngressCheck(member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetVlanPortIngressCheck(u32 *u32dat) { IP2Page(2); *u32dat = (u32)Read_Reg(P2REG_VLAN_INGRESS_CHK); } EXPORT_SYMBOL(switchdGetVlanPortIngressCheck); int getVlanPortIngressCheck(void *cdata, int len) { u32 u32dat; FUNC_MSG_IN; if (sizeof(struct PortMemberSetting) != len) return -EINVAL; switchdGetVlanPortIngressCheck(&u32dat); ((struct PortMemberSetting *)cdata) ->member = (int)u32dat; ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member); FUNC_MSG_OUT; return 0; } int switchdSetVlanPortVid(int port, int pvid) { if (port < 0 || port >= MAX_PHY_NUM) { ip1811drv_err("Error: port=%X\n", port); return -EINVAL; } if (pvid < 0 || pvid >= MAX_PVID_NUM) { ip1811drv_err("Error: pmdata=%X\n", pvid); return -EINVAL; } ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("pvid=%d\n", pvid); _WriteRegBits(2, P2REG_VLAN_PVIDCFG+port, 0, 12, pvid); #ifdef COMBINED_PORT if (port==9) _WriteRegBits(2, P2REG_VLAN_PVIDCFG+port+1, 0, 12, pvid); #endif return 0; } EXPORT_SYMBOL(switchdSetVlanPortVid); int setVlanPortVid(void *cdata, int len) { int port, pvid; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; pvid= ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetVlanPortVid(port, pvid) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanProtocolMode(int index, int mode) { if (index < 0 || index >= MAX_PRO_VLAN_ENTRY_NUM) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } if( (mode!=OP_VLAN_PROTOCOL_INVALID) && (mode!=OP_VLAN_PROTOCOL_ETHER) && (mode!=OP_VLAN_PROTOCOL_LLC) && (mode!=OP_VLAN_PROTOCOL_1042) ) { ip1811drv_err("Error: mode=%X\n", mode); return -EINVAL; } ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("mode=%d\n", mode); _WriteRegBits(2, P2REG_VLAN_PROCOTOL_CFG+1+index*2, 12, 2, mode); return 0; } EXPORT_SYMBOL(switchdSetVlanProtocolMode); int setVlanProtocolMode(void *cdata, int len) { int index, mode; FUNC_MSG_IN; if (sizeof(struct VlanSetting) != len) return -EINVAL; index = (((struct VlanSetting *)cdata) ->vtype) - 1; mode= ((struct VlanSetting *)cdata) ->vdata; if(switchdSetVlanProtocolMode(index, mode) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanProtocolVid(int index, int vid) { if (index < 0 || index >= MAX_PRO_VLAN_ENTRY_NUM) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } if( (vid < 0) || (vid>=MAX_PVID_NUM) ) { ip1811drv_err("Error: vid=%X\n", vid); return -EINVAL; } ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("vid=%d\n", vid); _WriteRegBits(2, P2REG_VLAN_PROCOTOL_CFG+1+index*2, 0, 12, vid); return 0; } EXPORT_SYMBOL(switchdSetVlanProtocolVid); int setVlanProtocolVid(void *cdata, int len) { int index, vid; FUNC_MSG_IN; if (sizeof(struct VlanSetting) != len) return -EINVAL; index = (((struct VlanSetting *)cdata) ->vtype) - 1; vid= ((struct VlanSetting *)cdata) ->vdata; if(switchdSetVlanProtocolVid(index, vid) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanProtocolType(int index, int type) { if (index < 0 || index >= MAX_PRO_VLAN_ENTRY_NUM) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } if (type & (~0xFFFF)) { ip1811drv_err("Error: type=%X\n", type); return -EINVAL; } ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("type=%d\n", type); IP2Page(2); Write_Reg(P2REG_VLAN_PROCOTOL_CFG+index*2, (u16)type); return 0; } EXPORT_SYMBOL(switchdSetVlanProtocolType); int setVlanProtocolType(void *cdata, int len) { int index, type; FUNC_MSG_IN; if (sizeof(struct VlanSetting) != len) return -EINVAL; index = (((struct VlanSetting *)cdata) ->vtype) - 1; type= ((struct VlanSetting *)cdata) ->vdata; if(switchdSetVlanProtocolType(index, type) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanProtocolClear(int index) { if (index < 0 || index >= MAX_PRO_VLAN_ENTRY_NUM) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } ip1811drv_dbg("index=0x%08x\n", index); IP2Page(2); Write_Reg(P2REG_VLAN_PROCOTOL_CFG+index*2, 0 ); Write_Reg(P2REG_VLAN_PROCOTOL_CFG+index*2+1, 0 ); return 0; } EXPORT_SYMBOL(switchdSetVlanProtocolClear); int setVlanProtocolClear(void *cdata, int len) { int index; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; index = (((struct GeneralSetting *)cdata) ->gdata) - 1; if(switchdSetVlanProtocolClear(index) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanMACBased(int mode) { if (mode!=OP_FUNC_DISABLE && mode!=OP_FUNC_ENABLE){ ip1811drv_err("Error: mode=%X\n", mode); return -EINVAL; } ip1811drv_dbg("mode=0x%08x\n", mode); _WriteRegBits(2, P2REG_VLANCFG, 11, 1, mode); return 0; } EXPORT_SYMBOL(switchdSetVlanMACBased); int setVlanMACBased(void *cdata, int len) { int mode; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; mode = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetVlanMACBased(mode) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanMACBasedtableconfig(unsigned int index, unsigned int data) { if (index < 0 || index >= MAX_FID_NUM) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } if (data & (~0x1FFF)) { ip1811drv_err("Error: data=%X\n", data); return -EINVAL; } ip1811drv_dbg("index=%d data=0x%08x\n", index, data); IP2Page(2); Write_Reg(P2REG_VLAN_MACBASED_ENTRY_0+index, (u16)data); return 0; } EXPORT_SYMBOL(switchdSetVlanMACBasedtableconfig); int setVlanMACBasedtableconfig(void *cdata, int len) { unsigned int index, data; FUNC_MSG_IN; if (sizeof(struct MACVlanSetting) != len) return -EINVAL; index = ((struct MACVlanSetting *)cdata) ->index; data = ((struct MACVlanSetting *)cdata) ->mvdata; if(switchdSetVlanMACBasedtableconfig(index, data) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdGetVlanMACBasedtableconfig(unsigned int index, unsigned int *data) { if (index < 0 || index >= MAX_FID_NUM) { ip1811drv_err("Error: index=%X\n", index); return -EINVAL; } ip1811drv_dbg("index=%d\n", index); IP2Page(2); *data = (unsigned int)Read_Reg(P2REG_VLAN_MACBASED_ENTRY_0+index); return 0; } EXPORT_SYMBOL(switchdGetVlanMACBasedtableconfig); int getVlanMACBasedtableconfig(void *cdata, int len) { unsigned int index, data; FUNC_MSG_IN; if (sizeof(struct MACVlanSetting) != len) return -EINVAL; index = ((struct MACVlanSetting *)cdata) ->index; if(switchdGetVlanMACBasedtableconfig(index, &data) != 0) return -EINVAL; ((struct MACVlanSetting *)cdata) ->mvdata = data; ip1811drv_dbg("cdata ->mvdata=%d\n", ((struct MACVlanSetting *)cdata) ->mvdata); FUNC_MSG_OUT; return 0; } int switchdSetVlanMACBasedunknown(unsigned int data) { if (data & (~0x1FFF)) { ip1811drv_err("Error: data=%X\n", data); return -EINVAL; } ip1811drv_dbg("data=0x%08x\n", data); IP2Page(2); Write_Reg(P2REG_VLAN_MACBASED_UNKNOWN, (u16)data); return 0; } EXPORT_SYMBOL(switchdSetVlanMACBasedunknown); int setVlanMACBasedunknown(void *cdata, int len) { unsigned int data; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; data = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetVlanMACBasedunknown(data) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } //ip1811_vlan int switchdSetVlanEntryMember(int vid, int member) { u16 u16dat; if (vid < 0 || vid >= MAX_PVID_NUM) { ip1811drv_err("Error: vid=%X\n", vid); return -EINVAL; } if (member & ~(0x0FFF)) { ip1811drv_err("Error: member=%X\n", member); return -EINVAL; } ip1811drv_dbg("vid=%d\n", vid); ip1811drv_dbg("member=%d\n", member); IP2Page(2); /* read data from VLAN table */ u16dat = 0x8000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); /* set entry memeber */ u16dat = Read_Reg(P2REG_VLANDAT0); u16dat &= ~0xFFF; u16dat |= (u16)member&0x0FFF; Write_Reg(P2REG_VLANDAT0, u16dat); u16dat = Read_Reg(P2REG_VLANDAT0+1); Write_Reg(P2REG_VLANDAT0+1, u16dat); u16dat = Read_Reg(P2REG_VLANDAT0+2); Write_Reg(P2REG_VLANDAT0+2, u16dat); /* set valid bit to 1 */ u16dat = (u16)0x1; Write_Reg(P2REG_VLANDAT0+3, u16dat); /* Write data to VLAN table */ u16dat = 0xC000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); return 0; } EXPORT_SYMBOL(switchdSetVlanEntryMember); int setVlanEntryMember(void *cdata, int len) { int vid, member; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len) return -EINVAL; vid = ((struct PortmapSetting *)cdata) ->pmdata; member= ((struct PortmapSetting *)cdata) ->portmap; if(switchdSetVlanEntryMember(vid, member) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanEntryAddtag(int vid, int addtag) { u16 u16dat; if (vid < 0 || vid >= MAX_PVID_NUM) { ip1811drv_err("Error: vid=%X\n", vid); return -EINVAL; } if (addtag & ~(0x0FFF)) { ip1811drv_err("Error: addtag=%X\n", addtag); return -EINVAL; } ip1811drv_dbg("vid=%d\n", vid); ip1811drv_dbg("addtag=%d\n", addtag); IP2Page(2); /* read data from VLAN table */ u16dat = 0x8000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); /* set entry addtag */ u16dat = Read_Reg(P2REG_VLANDAT0); u16dat &= ~0xF000; u16dat |= (u16)(addtag&0xF)<<12; Write_Reg(P2REG_VLANDAT0, u16dat); u16dat = Read_Reg(P2REG_VLANDAT0+1); u16dat &= ~0x00FF; u16dat |= (u16)(addtag>>4)&0x00FF; Write_Reg(P2REG_VLANDAT0+1, u16dat); u16dat = Read_Reg(P2REG_VLANDAT0+2); Write_Reg(P2REG_VLANDAT0+2, u16dat); /* set valid bit to 1 */ u16dat = (u16)0x1; Write_Reg(P2REG_VLANDAT0+3, u16dat); /* Write data to VLAN table */ u16dat = 0xC000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); return 0; } EXPORT_SYMBOL(switchdSetVlanEntryAddtag); int setVlanEntryAddtag(void *cdata, int len) { int vid, addtag; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len) return -EINVAL; vid = ((struct PortmapSetting *)cdata) ->pmdata; addtag= ((struct PortmapSetting *)cdata) ->portmap; if(switchdSetVlanEntryAddtag(vid, addtag) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanEntryRmvtag(int vid, int rmvtag) { u16 u16dat; if (vid < 0 || vid >= MAX_PVID_NUM) { ip1811drv_err("Error: vid=%X\n", vid); return -EINVAL; } if (rmvtag & ~(0x0FFF)) { ip1811drv_err("Error: rmvtag=%X\n", rmvtag); return -EINVAL; } ip1811drv_dbg("vid=%d\n", vid); ip1811drv_dbg("rmvtag=%d\n", rmvtag); IP2Page(2); /* read data from VLAN table */ u16dat = 0x8000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); u16dat = Read_Reg(P2REG_VLANDAT0); Write_Reg(P2REG_VLANDAT0, u16dat); /* set entry rmvtag */ u16dat = Read_Reg(P2REG_VLANDAT0+1); u16dat &= ~0xFF00; u16dat |= (u16)(rmvtag&0xFF)<<8; Write_Reg(P2REG_VLANDAT0+1, u16dat); u16dat = Read_Reg(P2REG_VLANDAT0+2); u16dat &= ~0xF; u16dat |= (u16)(rmvtag>>8)&0xF; Write_Reg(P2REG_VLANDAT0+2, u16dat); /* set valid bit to 1 */ u16dat = (u16)0x1; Write_Reg(P2REG_VLANDAT0+3, u16dat); /* Write data to VLAN table */ u16dat = 0xC000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); return 0; } EXPORT_SYMBOL(switchdSetVlanEntryRmvtag); int setVlanEntryRmvtag(void *cdata, int len) { int vid, rmvtag; FUNC_MSG_IN; if (sizeof(struct PortmapSetting) != len) return -EINVAL; vid = ((struct PortmapSetting *)cdata) ->pmdata; rmvtag= ((struct PortmapSetting *)cdata) ->portmap; if(switchdSetVlanEntryRmvtag(vid, rmvtag) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanEntryPriority(int vid, int priority) { u16 u16dat; if (vid < 0 || vid >= MAX_PVID_NUM) { ip1811drv_err("Error: vid=%X\n", vid); return -EINVAL; } if (priority & ~(0xF)) { ip1811drv_err("Error: priority=%X\n", priority); return -EINVAL; } ip1811drv_dbg("vid=%d\n", vid); ip1811drv_dbg("priority=%d\n", priority); IP2Page(2); /* read data from VLAN table */ u16dat = 0x8000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); u16dat = Read_Reg(P2REG_VLANDAT0); Write_Reg(P2REG_VLANDAT0, u16dat); u16dat = Read_Reg(P2REG_VLANDAT0+1); Write_Reg(P2REG_VLANDAT0+1, u16dat); /* set entry priority */ u16dat = Read_Reg(P2REG_VLANDAT0+2); u16dat &= ~0x00F0; u16dat |= (u16)(priority&0xF)<<4; Write_Reg(P2REG_VLANDAT0+2, u16dat); /* set valid bit to 1 */ u16dat = (u16)0x1; Write_Reg(P2REG_VLANDAT0+3, u16dat); /* Write data to VLAN table */ u16dat = 0xC000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); return 0; } EXPORT_SYMBOL(switchdSetVlanEntryPriority); int setVlanEntryPriority(void *cdata, int len) { int vid, priority; FUNC_MSG_IN; if (sizeof(struct VlanSetting) != len) return -EINVAL; vid = ((struct VlanSetting *)cdata) ->vtype; priority= ((struct VlanSetting *)cdata) ->vdata; if(switchdSetVlanEntryPriority(vid, priority) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetVlanEntryFid(int vid, int fid) { u16 u16dat; if (vid < 0 || vid >= MAX_PVID_NUM) { ip1811drv_err("Error: vid=%X\n", vid); return -EINVAL; } if (fid & ~(0xF)) { ip1811drv_err("Error: fid=%X\n", fid); return -EINVAL; } ip1811drv_dbg("vid=%d\n", vid); ip1811drv_dbg("fid=%d\n", fid); IP2Page(2); /* read data from VLAN table */ u16dat = 0x8000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); u16dat = Read_Reg(P2REG_VLANDAT0); Write_Reg(P2REG_VLANDAT0, u16dat); u16dat = Read_Reg(P2REG_VLANDAT0+1); Write_Reg(P2REG_VLANDAT0+1, u16dat); /* set entry fid */ u16dat = Read_Reg(P2REG_VLANDAT0+2); u16dat &= ~0xFF00; u16dat |= (u16)(fid&0xF)<<8; u16dat |= (u16)(fid&0xF)<<12; Write_Reg(P2REG_VLANDAT0+2, u16dat); /* set valid bit to 1 */ u16dat = (u16)0x1; Write_Reg(P2REG_VLANDAT0+3, u16dat); /* Write data to VLAN table */ u16dat = 0xC000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); return 0; } EXPORT_SYMBOL(switchdSetVlanEntryFid); int setVlanEntryFid(void *cdata, int len) { int vid, fid; FUNC_MSG_IN; if (sizeof(struct VlanSetting) != len) return -EINVAL; vid = ((struct VlanSetting *)cdata) ->vtype; fid= ((struct VlanSetting *)cdata) ->vdata; if(switchdSetVlanEntryFid(vid, fid) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdGetVlanEntryFid(int vid, int *ptrFid) { u16 u16dat; if (vid < 0 || vid >= MAX_PVID_NUM){ ip1811drv_err("Error: vtype=%X\n", vid); return -EINVAL; } ip1811drv_dbg("vid=%d\n", vid); IP2Page(2); /* read data from VLAN table */ u16dat = 0x8000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); /* get entry fid */ u16dat = Read_Reg(P2REG_VLANDAT0+2); *ptrFid = (int)(u16dat>>8)&0xF; return 0; } EXPORT_SYMBOL(switchdGetVlanEntryFid); int getVlanEntryFid(void *cdata, int len) { int vid, fid=0; FUNC_MSG_IN; if (sizeof(struct VlanSetting) != len) return -EINVAL; vid = ((struct VlanSetting *)cdata) ->vtype; if(switchdGetVlanEntryFid(vid, &fid) != 0) return -EINVAL; ((struct VlanSetting *)cdata) ->vdata = fid; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct VlanSetting *)cdata) ->vdata); FUNC_MSG_OUT; return 0; } int switchdSetVlanEntryClear(int vid) { u16 u16dat; int i; if (vid < 0 || vid >= MAX_PVID_NUM) { ip1811drv_err("Error: vid=%X\n", vid); return -EINVAL; } ip1811drv_dbg("vid=%d\n", vid); IP2Page(2); /* clear entry data */ for(i=0; i<4; i++) Write_Reg(P2REG_VLANDAT0+i, 0 ); /* Write data from VLAN table */ u16dat = 0xC000 | vid; Write_Reg(P2REG_VLANCMD, u16dat); /* wait for command ack */ while(Read_Reg(P2REG_VLANCMD)&0x8000); return 0; } EXPORT_SYMBOL(switchdSetVlanEntryClear); int setVlanEntryClear(void *cdata, int len) { int vid; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; vid = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetVlanEntryClear(vid) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } //------------------------------------------------ //ip1811_lut int switchdSetLutUnknownSARule(int rule) { if ( !( rule==OP_LUT_UNKNOWN_SA_DROP || rule==OP_LUT_UNKNOWN_SA_FWD_2_CPU || rule==OP_LUT_UNKNOWN_SA_FWD) ) return -EINVAL; ip1811drv_dbg("rule=%d\n", rule); _WriteRegBits(1, P1REG_SRCLEARNCFG, 3, 2, rule); return 0; } EXPORT_SYMBOL(switchdSetLutUnknownSARule); int setLutUnknownSARule(void *cdata, int len) { int rule; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; rule = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetLutUnknownSARule(rule) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdSetLutEntry(struct IP1811LUTSetting *luts) { int i; unsigned char f_notMatch = 0; u16 u16dat, index; u8 block; int temp_offset = -1; struct IP1811LUTSetting tmp_luts; if( luts ->action!=OP_ENTRY_CREATE && luts ->action!=OP_ENTRY_CONFIG && luts ->action!=OP_ENTRY_DELETE && luts ->action!=OP_ENTRY_CREATE_REG) { ip1811drv_err("action error:%d\n", luts ->action); return -EINVAL; } if( luts ->action == OP_ENTRY_CREATE || luts ->action == OP_ENTRY_CONFIG) { if(luts ->entry.fid > 15) { ip1811drv_err("fid error:%d\n", luts ->entry.fid); return -EINVAL; } if(luts ->entry.srcport > 31) { ip1811drv_err("srcport error:%d\n", luts ->entry.srcport); return -EINVAL; } if(luts ->entry.aging > 15) { ip1811drv_err("aging error:%d\n", luts ->entry.aging); return -EINVAL; } if(luts ->entry.priority > 15) { ip1811drv_err("priority error:%d\n", luts ->entry.priority); return -EINVAL; } if(luts ->entry.cfg > OP_LUT_CFG_MVT) { ip1811drv_err("cfg error:%d\n", luts ->entry.cfg); return -EINVAL; } } /* initialize retval value */ luts ->retval = 0; /* calculate hash value */ index = 0;//LUT_hash(luts ->entry.mac, luts ->entry.fid); ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("MAC=\n"); for(i=0; i<6; i++) ip1811drv_dbg("[%02X]\n", luts ->entry.mac[i]); ip1811drv_dbg("fid=%d\n", luts ->entry.fid); ip1811drv_dbg("srcport=%d\n", luts ->entry.srcport); ip1811drv_dbg("aging=%d\n", luts ->entry.aging); ip1811drv_dbg("priority=%d\n", luts ->entry.priority); ip1811drv_dbg("drop=%d\n", luts ->entry.flag.drop); ip1811drv_dbg("snif=%d\n", luts ->entry.flag.snif); ip1811drv_dbg("sflow=%d\n", luts ->entry.flag.sflow); ip1811drv_dbg("cfg=%d\n", luts ->entry.cfg); IP2Page(1); if(luts ->action==OP_ENTRY_CREATE_REG) { ip1811drv_dbg("OP_ENTRY_CREATE_REG\n"); for(i=0; i<5; i++) Write_Reg(P1REG_LUTDATA_0+i, luts ->data[i] ); Write_Reg(P1REG_LUTDATA_0+5, luts ->data[5]|0x0800 ); //hw_calc u16dat = 0; u16dat |= (u16)0x3<<14; //set write command & command trigger Write_Reg(P1REG_LUTCFG, u16dat ); /* need to check does trigger bit has been pull up */ while(!(Read_Reg(P1REG_LUTCFG)&0x8000)); return 0; } /* search the index of target entry */ /* cause use hw_calc bit can't get entry index */ // if((luts ->action==OP_ENTRY_CONFIG) || (luts ->action==OP_ENTRY_DELETE)) { memset(&tmp_luts, 0, sizeof(struct IP1811LUTSetting)); /* search all entries */ tmp_luts.action = OP_LUT_STATE_ALL; tmp_luts.tarports = ALL_PHY_PORTS_LIST; while(1) { /* try to get a valid MAC entry */ tmp_luts.retval = 0; getLutValidEntry(&tmp_luts, sizeof(struct IP1811LUTSetting)); if(tmp_luts.retval != OP_ENTRY_EXISTS) break; /* get a valid static entry */ /* check MAC address & FID */ f_notMatch = 0; for(i=0; i<6; i++) { if(luts ->entry.mac[i] != tmp_luts.entry.mac[i]) { f_notMatch = 1; break; } } if(luts ->entry.fid != tmp_luts.entry.fid) f_notMatch = 1; if(!f_notMatch){ /* if match, record the index */ temp_offset = tmp_luts.index; break; } /* search next valid entry */ tmp_luts.index++; } } if(luts ->action==OP_ENTRY_CREATE) { ip1811drv_dbg("OP_ENTRY_CREATE\n"); if(tmp_luts.entry.aging == 0xf) { ip1811drv_dbg("target entry has existed!!\n"); luts ->retval = OP_ENTRY_EXISTS; return 0; } for(i=0; i<3; i++) { u16dat = (u16)(luts ->entry.mac[4 - i*2])<<8 | (u16)(luts ->entry.mac[5 - i*2]); Write_Reg(P1REG_LUTDATA_0+i, u16dat ); } u16dat = 0; u16dat = luts ->entry.fid; u16dat |= (u16)luts ->entry.srcport<<4; u16dat |= (u16)0x0f<<9; //set aging to static u16dat |= (u16)((luts ->entry.priority & 0x7)<<13); Write_Reg(P1REG_LUTDATA_3, u16dat ); u16dat = (u16)((luts ->entry.priority >> 3)&0x1); u16dat |= (u16)luts ->entry.flag.sflow<<1; u16dat |= (u16)luts ->entry.flag.snif<<2; u16dat |= (u16)luts ->entry.flag.drop<<3; if (luts ->entry.cfg < OP_LUT_CFG_TRAN) u16dat |= (u16)((luts ->entry.cfg & 0x3)<<4); else { u16dat |= (u16)0x0020; // cfg[1] = 1 if (luts ->entry.cfg == OP_LUT_CFG_MVT) u16dat |= (u16)0x0008; // drop = 1 } Write_Reg(P1REG_LUTDATA_4, u16dat ); u16dat = 0x01<<11;//hw_calc Write_Reg(P1REG_LUTDATA_5, u16dat ); u16dat = 0; //set index u16dat |= (u16)0x3<<14; //set write command & command trigger Write_Reg(P1REG_LUTCFG, u16dat ); /* need to check does trigger bit has been pull up */ while(!(Read_Reg(P1REG_LUTCFG)&0x8000)); } else if(luts ->action==OP_ENTRY_CONFIG) { ip1811drv_dbg("OP_ENTRY_CONFIG\n"); /* if MAC or FID isn't match, we should abort this configuration */ if(f_notMatch) { ip1811drv_dbg("MAC or FID not match!!\n"); luts ->retval = OP_ENTRY_NOT_MATCH; return 0; } for (i=0; i < 3; i++) Write_Reg(P1REG_LUTDATA_0+i, tmp_luts.data[i]); u16dat = luts ->entry.fid; u16dat |= (u16)luts ->entry.srcport<<4; u16dat |= (u16)0x0f<<9; //set aging to static u16dat |= (u16)((luts ->entry.priority & 0x7)<<13); Write_Reg(P1REG_LUTDATA_3, u16dat ); u16dat = (u16)((luts ->entry.priority >> 3)&0x1); u16dat |= (u16)luts ->entry.flag.sflow<<1; u16dat |= (u16)luts ->entry.flag.snif<<2; if (luts ->entry.cfg < OP_LUT_CFG_TRAN) { u16dat |= (u16)luts ->entry.flag.drop<<3; u16dat |= (u16)((luts ->entry.cfg & 0x3)<<4); } else { u16dat |= (u16)0x0020; // cfg[1] = 1 if (luts ->entry.cfg == OP_LUT_CFG_MVT) u16dat |= (u16)0x0008; // drop = 1 } Write_Reg(P1REG_LUTDATA_4, u16dat ); u16dat = 0x01<<11;//hw_calc Write_Reg(P1REG_LUTDATA_5, u16dat ); u16dat = 0; //set index u16dat |= (u16)0x3<<14; //set write command & command trigger Write_Reg(P1REG_LUTCFG, u16dat ); /* need to check does trigger bit has been pull up */ while(!(Read_Reg(P1REG_LUTCFG)&0x8000)); } else if(luts ->action==OP_ENTRY_DELETE) { ip1811drv_dbg("OP_ENTRY_DELETE\n"); if(f_notMatch) { ip1811drv_dbg("MAC or FID not match!!\n"); luts ->retval = OP_ENTRY_NOT_MATCH; return 0; } if(tmp_luts.entry.aging != 0xf) { /* only static entry can be deleted */ ip1811drv_dbg("not static entry!!\n"); luts ->retval = OP_ENTRY_NOT_FOUND; return 0; } for (i=0; i < 3; i++) Write_Reg(P1REG_LUTDATA_0+i, tmp_luts.data[i]); u16dat = 0x0; //set aging to invalid Write_Reg(P1REG_LUTDATA_3, u16dat ); u16dat = 0x01<<11;//hw_calc Write_Reg(P1REG_LUTDATA_5, u16dat ); u16dat = 0; //set index u16dat |= (u16)0x3<<14; //set write command & command trigger Write_Reg(P1REG_LUTCFG, u16dat ); /* need to check does trigger bit has been pull up */ while(!(Read_Reg(P1REG_LUTCFG)&0x8000)); } return 0; } EXPORT_SYMBOL(switchdSetLutEntry); int setLutEntry(void *cdata, const int len) { struct IP1811LUTSetting *luts; FUNC_MSG_IN; /* check cdata length */ if (sizeof(struct IP1811LUTSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } luts = (struct IP1811LUTSetting *)cdata; if(switchdSetLutEntry(luts) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } u8 getLutCfgFromReg(u16 reg) { if (reg & 0x0020) // cfg[1] = 1 { if (reg & 0x8) // drop = 1 return (u8)OP_LUT_CFG_MVT; else return (u8)OP_LUT_CFG_TRAN; } else // cfg[1] = 0 return (u8)((reg >> 4) & 0x1); } int switchdGetLutEntry(struct IP1811LUTSetting *luts) { int i; bool f_notMatch = 0; u16 u16dat, lutdat_3, lutdat_4; int val_aging; u8 op_cfg; /* check index range */ if(luts ->index >= MAX_LUT_ENTRY_NUM){ ip1811drv_err("Error: index=%d\n", luts ->index); return -EINVAL; } /* set to register page 1 */ IP2Page(1); /* check command action */ if(luts ->action == OP_ENTRY_GET_BY_INFO){ if(luts ->entry.fid >= MAX_FID_NUM){ ip1811drv_err("Error: fid=%d\n", luts ->entry.fid); return -EINVAL; } /* copy mac to register from cdata */ for(i=0; i<3; i++){ u16dat = (u16)(luts ->entry.mac[4 - i*2])<<8 | (u16)(luts ->entry.mac[5 - i*2]); Write_Reg(P1REG_LUTDATA_0 + i, u16dat ); } /* set fid to register from cdata */ Write_Reg(P1REG_LUTDATA_3, luts ->entry.fid ); /* setup table address access method by HW */ Write_Reg(P1REG_LUTDATA_5, 0x0800 ); } else if(luts ->action == OP_ENTRY_GET_BY_INDEX){ /* setup table address access method by CPU */ Write_Reg(P1REG_LUTDATA_5, 0 ); } else{ ip1811drv_err("Error: action=%d\n", luts ->action); return -EINVAL; } /* initialize return value */ luts ->retval = 0; u16dat = luts ->index; //set index u16dat |= (u16)0x2<<14; //set read command & command trigger Write_Reg(P1REG_LUTCFG, u16dat ); /* check does trigger bit has been pull up */ while(!(Read_Reg(P1REG_LUTCFG)&0x8000)); /* catch aging time to check entry state */ lutdat_3 = Read_Reg(P1REG_LUTDATA_3); lutdat_4 = Read_Reg(P1REG_LUTDATA_4); val_aging = (lutdat_3 >> 9) & 0x0F; if(val_aging == 0x0){ luts ->retval = OP_ENTRY_NOT_FOUND; return 0; } /* get lut cfg */ op_cfg = getLutCfgFromReg(lutdat_4); if(luts ->action == OP_ENTRY_GET_BY_INFO){ /* if action is get by entry info, check if register value is same with input data */ /* catch MAC address */ for(i=0; i<3; i++){ u16dat = Read_Reg(P1REG_LUTDATA_0 + i); if( luts ->entry.mac[5 - i*2] != (u8)(u16dat&0xFF) ) f_notMatch = 1; if( luts ->entry.mac[4 - i*2] != (u8)((u16dat>>8)&0xFF) ) f_notMatch = 1; } /* check whether fid is matched to input cdata */ if( luts ->entry.fid != (lutdat_3 & 0x000f)) f_notMatch = 1; /* check whether cfg is matched to input cdata */ if( luts ->entry.cfg != op_cfg) f_notMatch = 1; if(val_aging == 0xf){//static entry if(f_notMatch){ ip1811drv_err("Error: MAC or FID is not match\n"); luts ->retval = OP_ENTRY_NOT_MATCH; return 0; } else luts ->retval = OP_ENTRY_EXISTS; } else{//dynamic entry if(f_notMatch){ ip1811drv_err("Error: MAC or FID is not match\n"); luts ->retval = OP_ENTRY_NOT_MATCH; return 0; } else luts ->retval = OP_ENTRY_EXISTS_DYNAMIC; } } else{//if(luts ->action == OP_ENTRY_GET_BY_INDEX) if( ((lutdat_3 >> 9) & 0x000F ) == 0x000F ) luts ->retval = OP_ENTRY_EXISTS; else luts ->retval = OP_ENTRY_EXISTS_DYNAMIC; /* if action is get by entry index, copy the register value into output data */ /* catch MAC address */ for(i=0; i<3; i++){ u16dat = Read_Reg(P1REG_LUTDATA_0 + i); luts ->entry.mac[5 - i*2] = (u8)(u16dat&0xFF); luts ->entry.mac[4 - i*2] = (u8)((u16dat>>8)&0xFF); } lutdat_3 = Read_Reg(P1REG_LUTDATA_3); luts ->entry.fid = lutdat_3 & 0x000F; } luts ->entry.priority = ((lutdat_4 & 0x0001) << 3) | ((lutdat_3>>13) & 0x0007); if (op_cfg < OP_LUT_CFG_TRAN) luts ->entry.flag.drop = (lutdat_4>>3) & 0x0001; else luts ->entry.flag.drop = 0; luts ->entry.flag.sflow = (lutdat_4>>1) & 0x0001; luts ->entry.flag.snif = (lutdat_4>>2) & 0x0001; luts ->entry.srcport = (lutdat_3>>4) & 0x001F; luts ->entry.aging = val_aging; luts ->entry.cfg = op_cfg; ip1811drv_dbg("cdata ->MAC="); for(i=0; i<6; i++) ip1811drv_dbg("[%02X]", luts ->entry.mac[i]); ip1811drv_dbg("\ncdata ->fid=%d\n", luts ->entry.fid); ip1811drv_dbg("cdata ->srcport=%d\n", luts ->entry.srcport); ip1811drv_dbg("cdata ->aging=%d\n", luts ->entry.aging); ip1811drv_dbg("cdata ->priority=%d\n", luts ->entry.priority); ip1811drv_dbg("cdata ->drop=%d\n", luts ->entry.flag.drop); ip1811drv_dbg("cdata ->snif=%d\n", luts ->entry.flag.snif); ip1811drv_dbg("cdata ->sflow=%d\n", luts ->entry.flag.sflow); ip1811drv_dbg("cdata ->cfg=%d\n", luts ->entry.cfg); return 0; } EXPORT_SYMBOL(switchdGetLutEntry); int getLutEntry(void *cdata, const int len) { struct IP1811LUTSetting *luts; FUNC_MSG_IN; /* check cdata length */ if (sizeof(struct IP1811LUTSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } luts = (struct IP1811LUTSetting *)cdata; if(switchdGetLutEntry(luts) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdGetLutValidEntry(struct IP1811LUTSetting *luts) { int i, retrytimes=25; u16 u16dat, lutdat[6]; unsigned short index; unsigned char block; int temp_offset; u16 hashvid; /* check index range */ if(luts ->index >= MAX_LUT_ENTRY_NUM) { ip1811drv_err("Error: index=%d\n", luts ->index); return -EINVAL; } index = luts ->index; ip1811drv_dbg("action=%d\n", luts ->action); /* set to register page 1 */ IP2Page(1); /* setup table address access method by CPU */ Write_Reg(P1REG_LUTDATA_5, 0 ); /* initialize return value */ luts ->retval = 0; u16dat = index; //set index u16dat |= (u16)0x2000; //sequential search for valid entry u16dat |= (u16)0x2<<14; //set read command & command trigger Write_Reg(P1REG_LUTCFG, u16dat ); while (1) { memset(lutdat, 0, sizeof(lutdat)); /* check does trigger bit has been pull up */ for (i=0; i < retrytimes; i++) { udelay(100); u16dat = Read_Reg(P1REG_LUTCFG); if (u16dat & 0x8000) break; } if (i == retrytimes) goto out_switchdGetLutValidEntry; /* read out all registers of lut data */ for (i=0; i < 6; i++) lutdat[i] = Read_Reg(P1REG_LUTDATA_0+i); /* check if there is any entry data */ if (lutdat[0]==0 && lutdat[1]==0 && lutdat[2]==0){ /* no data in lut table */ goto out_switchdGetLutValidEntry; } /* check if there is no more new data */ if (!(u16dat & 0x2000)){ /* lut table has been scanned to the end */ goto out_switchdGetLutValidEntry; } /* catch aging time to check entry state */ if((lutdat[3] &0x1e00) == 0x0){ /* invalid entry */ continue; } if( ((lutdat[3] >> 9) & 0xf) == 0xf && !(luts ->action & OP_LUT_STATE_STATIC) ) { /* action don't need static entry */ continue; } if( ((lutdat[3] >> 9) & 0xf) != 0xf && !(luts ->action & OP_LUT_STATE_DYNAMIC) ) { /* action don't need dynamic entry */ continue; } /* check whether source port bigger than CPU port num */ if((((lutdat[3]>>4) & 0x001f) + 1) > MAX_PHY_NUM) continue; /* check whether this entry is in target portlist */ if(!((1UL << ((lutdat[3]>>4) & 0x001f))&luts ->tarports)) continue; break; } /* if find a valid entry, copy the register value into output data */ /* catch MAC address */ for(i=0; i<6; i++) { luts ->data[i] = lutdat[i]; if (i < 3) { luts ->entry.mac[5 - i*2] = (u8)(lutdat[i]&0xFF); luts ->entry.mac[4 - i*2] = (u8)((lutdat[i]>>8)&0xFF); } } luts ->entry.fid = lutdat[3] & 0x000f; luts ->entry.srcport = (lutdat[3]>>4) & 0x001f; luts ->entry.aging = (lutdat[3]>>9) & 0x000f; luts ->entry.priority = (lutdat[3]>>13) & 0x0007; luts ->entry.priority |= ((lutdat[4] & 0x0001) << 3); luts ->entry.flag.sflow = (lutdat[4]>>1) & 0x0001; luts ->entry.flag.snif = (lutdat[4]>>2) & 0x0001; luts -> entry.cfg = getLutCfgFromReg(lutdat[4]); if (luts -> entry.cfg < OP_LUT_CFG_TRAN) luts ->entry.flag.drop = (lutdat[4]>>3) & 0x0001; else luts ->entry.flag.drop = 0; luts ->retval = OP_ENTRY_EXISTS; ip1811drv_dbg("=====================================\n"); ip1811drv_dbg("index=%d\n", luts ->index); ip1811drv_dbg("retval=%lX\n", luts ->retval); ip1811drv_dbg("MAC="); for(i=0; i<6; i++) ip1811drv_dbg("[%02X]", luts ->entry.mac[i]); ip1811drv_dbg("\nfid=%d\n", luts ->entry.fid); ip1811drv_dbg("srcport=%d\n", luts ->entry.srcport); ip1811drv_dbg("aging=%d\n", luts ->entry.aging); ip1811drv_dbg("priority=%d\n", luts ->entry.priority); ip1811drv_dbg("drop=%d\n", luts ->entry.flag.drop); ip1811drv_dbg("snif=%d\n", luts ->entry.flag.snif); ip1811drv_dbg("sflow=%d\n", luts ->entry.flag.sflow); ip1811drv_dbg("cfg=%d\n", luts ->entry.cfg); out_switchdGetLutValidEntry: return 0; } EXPORT_SYMBOL(switchdGetLutValidEntry); int getLutValidEntry(void *cdata, const int len) { struct IP1811LUTSetting *luts; FUNC_MSG_IN; /* check cdata length */ if (sizeof(struct IP1811LUTSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } luts = (struct IP1811LUTSetting *)cdata; if(switchdGetLutValidEntry(luts) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } //------------------------------------------------ //ip1811_igmp int switchdSetIGMPSnooping(int enable) { switch(enable) { case OP_FUNC_ENABLE: ip1811drv_dbg("Enable IGMP\n"); break; case OP_FUNC_DISABLE: ip1811drv_dbg("Disable IGMP\n"); break; default: ip1811drv_dbg("Option can't find\n"); return -EINVAL; } ip1811drv_dbg("Set IGMPSNOP: %x\n", enable); _WriteRegBits(1, P1REG_IGMPSNOP, 0, 1, enable); return 0; } EXPORT_SYMBOL(switchdSetIGMPSnooping); int setIGMPSnooping(void *cdata, int len) { int ret, func_en; struct GeneralSetting *igmp; FUNC_MSG_IN; ip1811drv_dbg("In setIGMPSnoopin.\n"); if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct GeneralSetting *)cdata; func_en = igmp ->gdata; ret = switchdSetIGMPSnooping(func_en); FUNC_MSG_OUT; return ret; } int switchdGetIGMPSnooping(int *gdata_p) { *gdata_p = (int)_ReadRegBits(1, P1REG_IGMPSNOP, 0, 1)?OP_FUNC_ENABLE:OP_FUNC_DISABLE; ip1811drv_dbg("IGMP %s",(*gdata_p==OP_FUNC_ENABLE)?"ENABLE":"DISABLE"); return 0; } EXPORT_SYMBOL(switchdGetIGMPSnooping); int getIGMPSnooping(void *cdata, int len) { int ret; struct GeneralSetting *igmp; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPSnoopin.\n"); if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct GeneralSetting *)cdata; ret = switchdGetIGMPSnooping(&(igmp ->gdata)) FUNC_MSG_OUT; return ret; } int switchdSetIGMPMctByCPU(int enable) { switch(enable) { case OP_FUNC_ENABLE: ip1811drv_dbg("Enable MCT By CPU\n"); break; case OP_FUNC_DISABLE: ip1811drv_dbg("Disable MCT By CPU\n"); break; default: ip1811drv_dbg("Option can't find\n"); return -EINVAL; } ip1811drv_dbg("Set MCT By CPU: %x\n", enable); _WriteRegBits(1, P1REG_IGMPSNOP, 1, 1, enable); return 0; } EXPORT_SYMBOL(switchdSetIGMPMctByCPU); int setIGMPMctByCPU(void *cdata, int len) { int ret, func_en; struct GeneralSetting *igmp; FUNC_MSG_IN; ip1811drv_dbg("In setIGMPMctByCPU.\n"); if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct GeneralSetting *)cdata; func_en = igmp ->gdata; ret = switchdSetIGMPMctByCPU(func_en); FUNC_MSG_OUT; return ret; } int switchdGetIGMPMctByCPU(int *gdata_p) { *gdata_p = (int)_ReadRegBits(1, P1REG_IGMPSNOP, 1, 1)?OP_FUNC_ENABLE:OP_FUNC_DISABLE; ip1811drv_dbg("IGMPMctByCPU %s",(*gdata_p==OP_FUNC_ENABLE)?"ENABLE":"DISABLE"); return 0; } EXPORT_SYMBOL(switchdGetIGMPMctByCPU); int getIGMPMctByCPU(void *cdata, int len) { int ret; struct GeneralSetting *igmp; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPMctByCPU.\n"); if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct GeneralSetting *)cdata; ret = switchdGetIGMPMctByCPU(&(igmp ->gdata)); FUNC_MSG_OUT; return ret; } int switchdSetIGMPRltByCPU(int enable) { switch(enable) { case OP_FUNC_ENABLE: ip1811drv_dbg("Enable router list by CPU\n"); break; case OP_FUNC_DISABLE: ip1811drv_dbg("Disable router list by CPU\n"); break; default: ip1811drv_dbg("Option can't find\n"); return -EINVAL; } ip1811drv_dbg("Set router list by CPU: %x\n", enable); _WriteRegBits(1, P1REG_IGMPSNOP, 5, 1, enable); return 0; } EXPORT_SYMBOL(switchdSetIGMPRltByCPU); int setIGMPRltByCPU(void *cdata, int len) { int ret, func_en; struct GeneralSetting *igmp; FUNC_MSG_IN; ip1811drv_dbg("In setIGMPRltByCPU.\n"); if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct GeneralSetting *)cdata; func_en = igmp ->gdata; ret = switchdSetIGMPRltByCPU(func_en); FUNC_MSG_OUT; return 0; } int switchdGetIGMPRltByCPU(int *gdata_p) { *gdata_p = (int)_ReadRegBits(1, P1REG_IGMPSNOP, 5, 1)?OP_FUNC_ENABLE:OP_FUNC_DISABLE; ip1811drv_dbg("IGMPRltByCPU %s",(*gdata_p==OP_FUNC_ENABLE)?"ENABLE":"DISABLE"); return 0; } EXPORT_SYMBOL(switchdGetIGMPRltByCPU); int getIGMPRltByCPU(void *cdata, int len) { int ret; struct GeneralSetting *igmp; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPRltByCPU.\n"); if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct GeneralSetting *)cdata; ret = switchdGetIGMPRltByCPU(&(igmp ->gdata)); FUNC_MSG_OUT; return 0; } int switchdSetIGMPPktForward(unsigned int type, unsigned int rule) { u16 regdata; u16 rule_t; IP2Page(1); switch(type){ case OP_IGMP_PACKET_QUERY: case OP_IGMP_PACKET_LEAVE: case OP_IGMP_PACKET_UN_REG_DATA: case OP_IGMP_PACKET_UN_DEFINED: if(rule >= OP_IGMP_RULE_GROUP_MEM){ ip1811drv_dbg("Select Type can't support Rule 'OP_IGMP_RULE_GROUP_MEM'.\n"); return -EINVAL; } regdata = Read_Reg(P1REG_IGMPPKTFWD_0); ip1811drv_dbg("Read IGMPPktForward_0 : %x\n", regdata); rule_t = 0x000F<packet_type; pkt_rule = igmp ->rule; ret = switchdSetIGMPPktForward(pkt_type, pkt_rule); FUNC_MSG_OUT; return ret; } int switchdGetIGMPPktForward(unsigned int type, int *rule_p) { u16 regdata; u16 rule_t; IP2Page(1); switch(type){ case OP_IGMP_PACKET_QUERY: case OP_IGMP_PACKET_LEAVE: case OP_IGMP_PACKET_UN_REG_DATA: case OP_IGMP_PACKET_UN_DEFINED: regdata = Read_Reg(P1REG_IGMPPKTFWD_0); ip1811drv_dbg("Read IGMPPktForward_0 : %x\n", regdata); rule_t = 0x000F<>(type); ip1811drv_dbg("type : %d\n", type); ip1811drv_dbg("Get rule : %x\n", *rule_p); break; case OP_IGMP_PACKET_REPORT: case OP_IGMP_PACKET_GROUP_SPECIFIC_QUERY: case OP_IGMP_PACKET_REG_DATA: regdata = Read_Reg(P1REG_IGMPPKTFWD_1); ip1811drv_dbg("Read IGMPPktForward_1 : %x\n", regdata); rule_t = 0x001F<<(type-1); regdata &= rule_t; *rule_p = regdata>>(type-1); ip1811drv_dbg("type : %d\n", type); ip1811drv_dbg("Get rule : %x\n", *rule_p); break; default: ip1811drv_dbg("Option can't find.\n"); return -EINVAL; break; } return 0; } EXPORT_SYMBOL(switchdGetIGMPPktForward); int getIGMPPktForward(void *cdata, int len) { unsigned int pkt_type; struct IgmpPacketRule *igmp; int ret; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPPktForward.\n"); if (sizeof(struct IgmpPacketRule) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct IgmpPacketRule *)cdata; pkt_type = igmp ->packet_type; ret = switchdGetIGMPPktForward(pkt_type, &(igmp ->rule)); FUNC_MSG_OUT; return ret; } int switchdSetIGMPRlt(unsigned int map, unsigned int tstate) { u16 regdata; u16 i, mask; IP2Page(1); regdata = Read_Reg(P1REG_ROUTLIST); ip1811drv_dbg("Read [12-01] : %x\n", regdata); mask = 0x01; for(i=0; i<12;i++){ if((map&mask)!=0) { if((tstate&mask)!=0) regdata |= mask; else regdata &= ~mask; } mask <<= 1; } ip1811drv_dbg("Write new [12-01] : %x\n", regdata); Write_Reg(P1REG_ROUTLIST, regdata); return 0; } EXPORT_SYMBOL(switchdSetIGMPRlt); int setIGMPRlt(void *cdata, int len) { u16 map, value; struct IgmpRouterListSetting *igmp; int ret; FUNC_MSG_IN; ip1811drv_dbg("In setIGMPRlt.\n"); if (sizeof(struct IgmpRouterListSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct IgmpRouterListSetting *)cdata; map = 0xFFF&(igmp ->portmask); value = 0xFFF&(igmp ->tstate); ip1811drv_dbg("map [12-01] : %x\n", map); ip1811drv_dbg("val [12-01] : %x\n", value); ret = switchdSetIGMPRlt(map, value); FUNC_MSG_OUT; return ret; } int switchdGetIGMPRlt(unsigned int map, int *value_p) { u16 regdata, value, i, mask; IP2Page(1); regdata = Read_Reg(P1REG_ROUTLIST); ip1811drv_dbg("Read [12-01] : %x\n", regdata&0xFFF); mask = 0x01; for(i=0; i<12; i++) { if((map&mask)!=0){ if((regdata&mask)!=0) value |= mask; else value &= ~mask; } mask <<= 1; } *value_p = value; ip1811drv_dbg("Return value : %lx\n", *value_p); return 0; } EXPORT_SYMBOL(switchdGetIGMPRlt); int getIGMPRlt(void *cdata, int len) { u16 map, value, i, mask; struct IgmpRouterListSetting *igmp; int ret; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPRlt.\n"); if (sizeof(struct IgmpRouterListSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct IgmpRouterListSetting *)cdata; map = 0xFFF&(igmp ->portmask); ip1811drv_dbg("map [12-01] : %x\n", map); ret = switchdGetIGMPRlt(map, &(igmp ->tstate)); FUNC_MSG_OUT; return ret; } int switchdSetIGMPHashMethod(int hash_method) { if (!(hash_method==OP_HASH_DIRECT || hash_method==OP_HASH_CRC)) return -EINVAL; ip1811drv_dbg("Set Hash Method: %s\n", (hash_method==OP_HASH_DIRECT)?"DIRECT":"CRC"); _WriteRegBits(1, P1REG_IGMPSNOP, 6, 1,(hash_method==OP_HASH_DIRECT)?1:0); return 0; } EXPORT_SYMBOL(switchdSetIGMPHashMethod); int setIGMPHashMethod(void *cdata, int len) { int hash, ret; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) return -EINVAL; hash = ((struct GeneralSetting *)cdata) ->gdata; ret = switchdSetIGMPHashMethod(hash); FUNC_MSG_OUT; return ret; } int switchdGetIGMPHashMethod(int *gdata_p) { *gdata_p = (int)_ReadRegBits(1, P1REG_IGMPSNOP, 6, 1)?OP_HASH_DIRECT:OP_HASH_CRC; ip1811drv_dbg("HASH METHOD %s",(*gdata_p==OP_HASH_DIRECT)?"DIRECT":"CRC"); return 0; } EXPORT_SYMBOL(switchdGetIGMPHashMethod); int getIGMPHashMethod(void *cdata, int len) { int ret; struct GeneralSetting *igmp; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPHashMethod.\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; igmp = (struct GeneralSetting *)cdata; ret = switchdGetIGMPHashMethod(&(igmp ->gdata)); FUNC_MSG_OUT; return ret; } int switchdSetIGMPMldRule(int forwarding) { ip1811drv_dbg("set ICMPv6 MLD forwarding: %x\n", forwarding); _WriteRegBits(0, P0REG_IPV6RLTFWD, 8, 2, forwarding); return 0; } EXPORT_SYMBOL(switchdSetIGMPMldRule); int setIGMPMldRule(void *cdata, int len) { struct GeneralSetting *igmp; int ret, forward; FUNC_MSG_IN; ip1811drv_dbg("In setIGMPMldRule.\n"); if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct GeneralSetting *)cdata; forward = igmp ->gdata; ret = switchdSetIGMPMldRule(forward); FUNC_MSG_OUT; return ret; } int switchdGetIGMPMldRule(int *gdata_p) { *gdata_p = (int)_ReadRegBits(0, P0REG_IPV6RLTFWD, 8, 2); ip1811drv_dbg("get ICMPv6 MLD forwarding: %x\n", *gdata_p); return 0; } EXPORT_SYMBOL(switchdGetIGMPMldRule); int getIGMPMldRule(void *cdata, int len) { struct GeneralSetting *igmp; int ret; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPMldRule.\n"); if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct GeneralSetting *)cdata; ret = switchdGetIGMPMldRule(&(igmp ->gdata)); FUNC_MSG_OUT; return ret; } void makeTable(u16 *tmpbuf, u16 offset, u32 value, u8 len) { u16 ptr, set, tmpvalue; ptr = offset/16; set = offset%16; ip1811drv_dbg("\n\nMakeTable:\noffset : %d\nvalue : %x\nlen : %d\n", offset, value, len); ip1811drv_dbg("\nbuf[%d]=%x buf[%d]=%x\n", ptr, tmpbuf[ptr], ptr+1, tmpbuf[ptr+1]); tmpvalue = (0xFFFF&value)<(16-set)) { len -= (16-set); tmpvalue = 0xFFFF&(value>>(16-set)); tmpbuf[ptr+1] |= tmpvalue; ip1811drv_dbg("buf[%d] | %x = %x\n", ptr+1, tmpvalue, tmpbuf[ptr+1]); if(len>16){ tmpvalue = 0xFFFF&(value>>(32-set)); tmpbuf[ptr+2] |= tmpvalue; ip1811drv_dbg("buf[%d] | %x = %x\n", ptr+2, tmpvalue, tmpbuf[ptr+2]); } } } u32 getTable(u16 *tmpbuf, u16 offset, u8 len) { u32 value; u16 ptr, set, tmpvalue, i, mask; u16 debug; ip1811drv_dbg("getTable:\n"); ip1811drv_dbg("offset = %d, len = %d", offset, len); debug = offset/16; ip1811drv_dbg("tmpbuf[%d] offset value:\n", debug); for(i=0; i<3; i++) ip1811drv_dbg("%04x ", tmpbuf[debug+i]); ptr = (offset+len)/16; set = (offset+len)%16; if(len>=set){ mask = 0; for(i=0; i=16) { value <<= 16; value |= tmpbuf[ptr-1]; if((len-set-16)>0){ value <<= (len-set-16); value |= tmpbuf[ptr-2]>>(16-(len-set-16)); } } else { if(len!=set) { value <<= (len-set); value |= tmpbuf[ptr-1]>>(16-(len-set)); } } } else { mask = 0; for(i=0; i>(set-len); } ip1811drv_dbg("return %x\n",value); return value; } /* ipv: 4: IPv4 * 6: IPv6 * addr: IP address * method: 1: Direct * 0: CRC * */ u8 tb_calc_index(u8 ipv, void *addr, u8 method) { u8 index = 0; u8 *u8_addr = (u8*)addr; // Direct if(method) { if(ipv == 4) { index = u8_addr[3]; } else if(ipv == 6) { index = u8_addr[15]; } } else { // CRC int i; bool crc[8], d[32]; bool c[8] = {1,1,1,1,1,1,1,1}; // init data if(ipv == 4) { for(i=0; i<32; i++) d[i] = (bool)((u8_addr[i/8] >> (7-(i%8))) & 0x1); } else if(ipv == 6) { for(i=0; i<32; i++) d[i] = (bool)((u8_addr[12+(i/8)] >> (7-(i%8))) & 0x1); } // calculate crc crc[0] = d[31] ^ d[30] ^ d[28] ^ d[23] ^ d[21] ^ d[19] ^ d[18] ^ d[16] ^ d[14] ^ d[12] ^ d[8] ^ d[7] ^ d[6] ^ d[0] ^ c[4] ^ c[6] ^ c[7]; crc[1] = d[30] ^ d[29] ^ d[28] ^ d[24] ^ d[23] ^ d[22] ^ d[21] ^ d[20] ^ d[18] ^ d[17] ^ d[16] ^ d[15] ^ d[14] ^ d[13] ^ d[12] ^ d[9] ^ d[6] ^ d[1] ^ d[0] ^ c[0] ^ c[4] ^ c[5] ^ c[6]; crc[2] = d[29] ^ d[28] ^ d[25] ^ d[24] ^ d[22] ^ d[17] ^ d[15] ^ d[13] ^ d[12] ^ d[10] ^ d[8] ^ d[6]^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[4] ^ c[5]; crc[3] = d[30] ^ d[29] ^ d[26] ^ d[25] ^ d[23] ^ d[18] ^ d[16] ^ d[14] ^ d[13] ^ d[11] ^ d[9] ^ d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[5] ^ c[6]; crc[4] = d[31] ^ d[30] ^ d[27] ^ d[26] ^ d[24] ^ d[19] ^ d[17] ^ d[15] ^ d[14] ^ d[12] ^ d[10] ^ d[8] ^ d[4] ^ d[3] ^ d[2] ^ c[0] ^ c[2] ^ c[3] ^ c[6] ^ c[7]; crc[5] = d[31] ^ d[28] ^ d[27] ^ d[25] ^ d[20] ^ d[18] ^ d[16] ^ d[15] ^ d[13] ^ d[11] ^ d[9] ^ d[5] ^ d[4] ^ d[3] ^ c[1] ^ c[3] ^ c[4] ^ c[7]; crc[6] = d[29] ^ d[28] ^ d[26] ^ d[21] ^ d[19] ^ d[17] ^ d[16] ^ d[14] ^ d[12] ^ d[10] ^ d[6] ^ d[5] ^ d[4] ^ c[2] ^ c[4] ^ c[5]; crc[7] = d[30] ^ d[29] ^ d[27] ^ d[22] ^ d[20] ^ d[18] ^ d[17] ^ d[15] ^ d[13] ^ d[11] ^ d[7] ^ d[6] ^ d[5] ^ c[3] ^ c[5] ^ c[6]; // get index for(i=0; i<8; i++) index |= ((u8)crc[i])<group[0], mt_data->group[1], mt_data->group[2], mt_data->group[3]); ip1811drv_dbg("driver:Set FID: %x\n", mt_data->fid); ip1811drv_dbg("driver:Set age port:: %lx\n", mt_data->port_mem); ip1811drv_dbg("driver:Set SIP: %x\n", mt_data->slt_index); ip1811drv_dbg("driver:Set flag: %x\n", mt_data->flag); //set Group regdata[0] = (mt_data->group[2] << 8) | mt_data->group[3]; regdata[1] = (mt_data->group[0] << 8) | mt_data->group[1]; //set FID makeTable(regdata, 32, mt_data->fid, 4); //set Aging Member for(i=0; i<12; i++) { if(mt_data->port_mem & BIT(i)) { makeTable(regdata, 36+i, 0x1, 1); makeTable(regdata, 36+i+12, 0x1, 1); makeTable(regdata, 36+i+24, 0x1, 1); } } //set Pri makeTable(regdata, 72, mt_data->pri, 4); //set SIP makeTable(regdata, 76, mt_data->slt_index, 5); //set ver and CPU makeTable(regdata, 81, mt_data->flag, 2); IP2Page(1); ip1811drv_dbg("driver:Write Mct Table Data:\n"); for(i=0; i<6; i++) { ip1811drv_dbg("%04x ", regdata[i]); Write_Reg(P1REG_MEM_MCT_TABLE_0+i, regdata[i]); } ip1811drv_dbg("\n"); tmpvalue = index; tmpvalue |= 0xC000; ip1811drv_dbg("\ndirver:Start Write [%04x]", tmpvalue); Write_Reg(P1REG_MEM_MCT_COMMAND, tmpvalue); tmpvalue = Read_Reg(P1REG_MEM_MCT_COMMAND); while((tmpvalue&0x8000)!=0) tmpvalue = Read_Reg(P1REG_MEM_MCT_COMMAND); return 0; } EXPORT_SYMBOL(switchdSetIGMPMctTable); int setIGMPMctTable(void *cdata, int len){ int ret, index; struct MtRuleSetting *igmp; struct mt_rule *mt; FUNC_MSG_IN; ip1811drv_dbg("In setIGMPMctTable.\n"); if (sizeof(struct MtRuleSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct MtRuleSetting *)cdata; index = igmp ->index; mt = &(igmp ->mt_data); ret = switchdSetIGMPMctTable(index, mt); FUNC_MSG_OUT; return 0; } int switchdGetIGMPMctTable(int index, struct mt_rule *mt_data) { u16 regdata[6] = {0}; u16 i, j, tmpvalue; u32 mask; tmpvalue = index; tmpvalue |= 0x8000; IP2Page(1); Write_Reg(P1REG_MEM_MCT_COMMAND, tmpvalue); ip1811drv_dbg("driver:start read: %x\n", tmpvalue); tmpvalue = Read_Reg(P1REG_MEM_MCT_COMMAND); while((tmpvalue&0x8000)!=0) tmpvalue = Read_Reg(P1REG_MEM_MCT_COMMAND); ip1811drv_dbg("driver:index: %x\n", index); ip1811drv_dbg("driver:Read Table Data:\n"); for(i=0; i<6; i++) { regdata[i] = Read_Reg(P1REG_MEM_MCT_TABLE_0+i); ip1811drv_dbg("%04x ", regdata[i]); } ip1811drv_dbg("\nRead Group:\n"); for(i=0; i<4; i++) { mt_data->group[i] = getTable(regdata, (0+(8*i)), 8); ip1811drv_dbg("%x ", mt_data->group[i]); } ip1811drv_dbg("\nRead FID:\n"); mt_data->fid = getTable(regdata, 32, 4); ip1811drv_dbg("%x\n",mt_data->fid); ip1811drv_dbg("Read Aging:\n"); mask = 0; for(i=0; i<12; i++){ int val = 0; for(j=0; j<3; j++) { if(getTable(regdata, (36+i+(12*j)), 1)!=0 ) val++; } if(val) mask |= 0x01<port_mem = mask; ip1811drv_dbg("Read Priority:\n"); mt_data->pri = getTable(regdata, 72, 4); ip1811drv_dbg("%x\n",mt_data->pri); ip1811drv_dbg("Read SLT index:\n"); mt_data->slt_index = getTable(regdata, 76, 5); ip1811drv_dbg("%x\n",mt_data->slt_index); ip1811drv_dbg("Read flag:\n"); mt_data->flag = getTable(regdata, 81, 2); ip1811drv_dbg("%x\n",mt_data->flag); printk(KERN_ERR "\nGroup:"); for(i=0;i<4;i++) printk(KERN_ERR " %d", mt_data->group[i]); printk(KERN_ERR "\nFID: %x", mt_data->fid); printk(KERN_ERR "\nPort member: %lx", (unsigned long)mt_data->port_mem); printk(KERN_ERR "\nPriority: %d", (mt_data->pri&0x07)); printk(KERN_ERR "\nSLT index: %x", mt_data->slt_index); printk(KERN_ERR "\nFlag: %x\n", mt_data->flag); return 0; } EXPORT_SYMBOL(switchdGetIGMPMctTable); int getIGMPMctTable(void *cdata, int len){ int ret, index; struct MtRuleSetting *igmp; struct mt_rule *mt; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPMctTable.\n"); if (sizeof(struct MtRuleSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct MtRuleSetting *)cdata; index = igmp ->index; mt = &(igmp ->mt_data); ret = switchdGetIGMPMctTable(index, mt); FUNC_MSG_OUT; return ret; } int switchdSetIGMPSltTable(int index, struct slt_rule *slt_data) { u16 regdata[19] = {0}; u16 i, j, tmpvalue; if(slt_data->type == OP_IGMP_SLT_IPV4) { //set IP for(i=0; i<6; i++){ regdata[i*2] = (slt_data->data.ipv4.ip[i][2] << 8) | slt_data->data.ipv4.ip[i][3]; regdata[i*2+1] = (slt_data->data.ipv4.ip[i][0] << 8) | slt_data->data.ipv4.ip[i][1]; } //set User Define for(i=0; i<6; i++) makeTable(regdata, (192+(12*i)), slt_data->data.ipv4.used_port[i], 12); }else{ //set IP for(i=0; i<2; i++){ for(j=0; j<8; j++) makeTable(regdata, ((128*i)+(16*j)), slt_data->data.ipv6.ip[i][7-j], 16); } //set User Define for(i=0; i<2 ;i++) makeTable(regdata, (256+(12*i)), slt_data->data.ipv6.used_port[i], 12); } ip1811drv_dbg("SLT Table Data:"); IP2Page(1); for(i=0; i<19; i++) { if((i%16)==0) ip1811drv_dbg("\n"); ip1811drv_dbg("%04x ", regdata[i]); Write_Reg(P1REG_MEM_SLT_TABLE_0+i, regdata[i]); } tmpvalue = index; tmpvalue |= 0xC000; ip1811drv_dbg("\ndirver:Start Write [%04x]", tmpvalue); Write_Reg(P1REG_MEM_SLT_COMMAND, tmpvalue); return 0; } EXPORT_SYMBOL(switchdSetIGMPSltTable); int setIGMPSltTable(void *cdata, int len){ int ret, index; struct SltRuleSetting *igmp; struct slt_rule *slt; FUNC_MSG_IN; ip1811drv_dbg("In setIGMPSltTable.\n"); if (sizeof(struct SltRuleSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct SltRuleSetting *)cdata; index = igmp ->index; slt = &(igmp ->slt_data); ret = switchdSetIGMPSltTable(index, slt); FUNC_MSG_OUT; return ret; } int switchdGetIGMPSltTable(int index, struct slt_rule *slt_data) { u16 regdata[19] = {0}; u16 i, j, tmpvalue; tmpvalue = index; tmpvalue |= 0x8000; IP2Page(1); Write_Reg(P1REG_MEM_SLT_COMMAND, tmpvalue); tmpvalue = Read_Reg(P1REG_MEM_SLT_COMMAND); while( (tmpvalue&0x8000)!=0 ) tmpvalue = Read_Reg(P1REG_MEM_SLT_COMMAND); ip1811drv_dbg("Read SLT Table:"); for(i=0; i<19; i++) { regdata[i] = Read_Reg(P1REG_MEM_SLT_TABLE_0+i); if(i%16==0) ip1811drv_dbg("\n"); ip1811drv_dbg("%04x ", regdata[i]); } if(slt_data->type == OP_IGMP_SLT_IPV4){ ip1811drv_dbg("Read IPv4:\n"); printk(KERN_ERR "\nRead IPv4:"); for(i=0; i<6; i++) { printk(KERN_ERR "\n"); for(j=0; j<4; j++) { slt_data->data.ipv4.ip[i][j] = getTable(regdata, ((32*i)+(8*j)), 8 ); printk(KERN_ERR " %d", slt_data->data.ipv4.ip[i][j]); } } ip1811drv_dbg("Read Used Define:\n"); printk(KERN_ERR "\nUsed Define:\n"); for(i=0; i<6; i++) { slt_data->data.ipv4.used_port[i] = getTable(regdata, (192+(12*i)), 12); printk(KERN_ERR " %04lx", (unsigned long)slt_data->data.ipv4.used_port[i]); } }else{ ip1811drv_dbg("Read IPv6:\n"); printk(KERN_ERR "\nRead IPv6:"); for(i=0; i<2; i++) { printk(KERN_ERR "\n"); for(j=0; j<8; j++) { slt_data->data.ipv6.ip[i][j] = getTable(regdata, ((128*i)+(16*j)), 16); printk(KERN_ERR " %04x", slt_data->data.ipv6.ip[i][j]); } } ip1811drv_dbg("Read Used Define:\n"); printk(KERN_ERR "\nUsed Define:\n"); for(i=0; i<2;i++) { slt_data->data.ipv6.used_port[i] = getTable(regdata, (256+(12*i)), 12); printk(KERN_ERR " %04lx", (unsigned long)slt_data->data.ipv6.used_port[i]); } } printk(KERN_ERR "\n"); return 0; } EXPORT_SYMBOL(switchdGetIGMPSltTable); int getIGMPSltTable(void *cdata, int len){ int ret, index; struct SltRuleSetting *igmp; struct slt_rule *slt; FUNC_MSG_IN; ip1811drv_dbg("In getIGMPSltTable.\n"); if (sizeof(struct SltRuleSetting) != len) { ip1811drv_err("length error!\n"); return -EINVAL; } igmp = (struct SltRuleSetting *)cdata; index = igmp ->index; slt = &(igmp ->slt_data); ret = switchdGetIGMPSltTable(index, slt); FUNC_MSG_OUT; return 0; } //------------------------------------------------ //ip1811_sniffer int switchdSetS1PktModify(int modify) { if (modify!=OP_SNIFFER1_PKT_MODIFY && modify!=OP_SNIFFER1_PKT_KEEP) return -EINVAL; ip1811drv_dbg("modify=%d\n", modify); _WriteRegBits(1, P1REG_SNIFCFG, 2, 1, modify); return 0; } EXPORT_SYMBOL(switchdSetS1PktModify); int setS1PktModify(void *cdata, int len) { int modify; ip1811drv_dbg("ip1811: +setS1PktModify...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; modify = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetS1PktModify(modify) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setS1PktModify...\n"); return 0; } int switchdGetS1PktModify(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 2, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetS1PktModify); int getS1PktModify(void *cdata, int len) { int modify; ip1811drv_dbg("ip1811: +getS1PktModify...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetS1PktModify(&modify) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = modify; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getS1PktModify...\n"); return 0; } int switchdSetS1TM4CpuSTag(int modify) { if (modify!=OP_SNIFFER1_TAG_KEEP && modify!=OP_SNIFFER1_TAG_MODIFY) return -EINVAL; ip1811drv_dbg("modify=%d\n", modify); _WriteRegBits(1, P1REG_SNIFCFG, 5, 1, modify); return 0; } EXPORT_SYMBOL(switchdSetS1TM4CpuSTag); int setS1TM4CpuSTag(void *cdata, int len) { int modify; ip1811drv_dbg("ip1811: +setS1TM4CpuSTag...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; modify = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetS1TM4CpuSTag(modify) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setS1TM4CpuSTag...\n"); return 0; } int switchdGetS1TM4CpuSTag(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 5, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetS1TM4CpuSTag); int getS1TM4CpuSTag(void *cdata, int len) { int modify; ip1811drv_dbg("ip1811: +getS1TM4CpuSTag...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetS1TM4CpuSTag(&modify) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = modify; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getS1TM4CpuSTag...\n"); return 0; } int switchdSetS1TM4Acl2Cpu(int modify) { if (modify!=OP_SNIFFER1_TAG_KEEP && modify!=OP_SNIFFER1_TAG_MODIFY) return -EINVAL; ip1811drv_dbg("modify=%d\n", modify); _WriteRegBits(1, P1REG_SNIFCFG, 6, 1, modify); return 0; } EXPORT_SYMBOL(switchdSetS1TM4Acl2Cpu); int setS1TM4Acl2Cpu(void *cdata, int len) { int modify; ip1811drv_dbg("ip1811: +setS1TM4Acl2Cpu...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; modify = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetS1TM4Acl2Cpu(modify) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setS1TM4Acl2Cpu...\n"); return 0; } int switchdGetS1TM4Acl2Cpu(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 6, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetS1TM4Acl2Cpu); int getS1TM4Acl2Cpu(void *cdata, int len) { int modify; ip1811drv_dbg("ip1811: +getS1TM4Acl2Cpu...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetS1TM4Acl2Cpu(&modify) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = modify; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getS1TM4Acl2Cpu...\n"); return 0; } int switchdSetS1TM4Pkt2MPort(int modify) { if (modify!=OP_SNIFFER1_TAG_KEEP && modify!=OP_SNIFFER1_TAG_MODIFY) return -EINVAL; ip1811drv_dbg("modify=%d\n", modify); _WriteRegBits(1, P1REG_SNIFCFG, 7, 1, modify); return 0; } EXPORT_SYMBOL(switchdSetS1TM4Pkt2MPort); int setS1TM4Pkt2MPort(void *cdata, int len) { int modify; ip1811drv_dbg("ip1811: +setS1TM4Pkt2MPort...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; modify = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetS1TM4Pkt2MPort(modify) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setS1TM4Pkt2MPort...\n"); return 0; } int switchdGetS1TM4Pkt2MPort(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 7, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetS1TM4Pkt2MPort); int getS1TM4Pkt2MPort(void *cdata, int len) { int modify; ip1811drv_dbg("ip1811: +getS1TM4Pkt2MPort...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetS1TM4Pkt2MPort(&modify) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = modify; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getS1TM4Pkt2MPort...\n"); return 0; } int switchdSetS2LTT4Grp1(int ltt) { if (ltt!=OP_SNIFFER2_LUT_TRIGGER_TARGET_DA && ltt!=OP_SNIFFER2_LUT_TRIGGER_TARGET_SA) return -EINVAL; ip1811drv_dbg("ltt=%d\n", ltt); _WriteRegBits(1, P1REG_SNIFCFG, 3, 1, ltt); return 0; } EXPORT_SYMBOL(switchdSetS2LTT4Grp1); int setS2LTT4Grp1(void *cdata, int len) { int ltt; ip1811drv_dbg("ip1811: +setS2LTT4Grp1...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; ltt = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetS2LTT4Grp1(ltt) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setS2LTT4Grp1...\n"); return 0; } int switchdGetS2LTT4Grp1(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 3, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetS2LTT4Grp1); int getS2LTT4Grp1(void *cdata, int len) { int ltt; ip1811drv_dbg("ip1811: +getS2LTT4Grp1...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetS2LTT4Grp1(<t) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = ltt; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getS2LTT4Grp1...\n"); return 0; } //------------------------------------------------ //ip1811_storm int switchdSetMStormNBlockIpPkt(int nb) { if (nb!=OP_FUNC_DISABLE && nb!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("nb=%d\n", nb); _WriteRegBits(1, P1REG_BSTORMTHRESH, 11, 1, nb); return 0; } EXPORT_SYMBOL(switchdSetMStormNBlockIpPkt); int setMStormNBlockIpPkt(void *cdata, int len) { int nb; ip1811drv_dbg("ip1811: +setMStormNBlockIpPkt...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; nb = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetMStormNBlockIpPkt(nb) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setMStormNBlockIpPkt...\n"); return 0; } int switchdGetMStormNBlockIpPkt(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_BSTORMTHRESH, 11, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetMStormNBlockIpPkt); int getMStormNBlockIpPkt(void *cdata, int len) { int nb; ip1811drv_dbg("ip1811: +getMStormNBlockIpPkt...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetMStormNBlockIpPkt(&nb) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = nb; ip1811drv_dbg("ip1811: -getMStormNBlockIpPkt...\n"); return 0; } int switchdSetMStormIgnr01005EXXXXXX(int ignr) { if (ignr!=OP_FUNC_DISABLE && ignr!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("ignr=%d\n", ignr); _WriteRegBits(1, P1REG_BSTORMTHRESH, 12, 1, ignr); return 0; } EXPORT_SYMBOL(switchdSetMStormIgnr01005EXXXXXX); int setMStormIgnr01005EXXXXXX(void *cdata, int len) { int ignr; ip1811drv_dbg("ip1811: +setMStormIgnr01005EXXXXXX...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; ignr = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetMStormIgnr01005EXXXXXX(ignr) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setMStormIgnr01005EXXXXXX...\n"); return 0; } int switchdGetMStormIgnr01005EXXXXXX(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_BSTORMTHRESH, 12, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetMStormIgnr01005EXXXXXX); int getMStormIgnr01005EXXXXXX(void *cdata, int len) { int en=0; ip1811drv_dbg("ip1811: +getMStormIgnr01005EXXXXXX...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetMStormIgnr01005EXXXXXX(&en) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = en; ip1811drv_dbg("ip1811: -getMStormIgnr01005EXXXXXX...\n"); return 0; } //ip1811_stp int switchdSetBpduCapMode(int bcmode) { if (bcmode!=OP_BPDU_CMODE_GLOBAL && bcmode!=OP_BPDU_CMODE_BY_PORT) return -EINVAL; ip1811drv_dbg("bcmode=%d\n", bcmode); _WriteRegBits(0, P0REG_MACBEHAVIOR, 10, 1, bcmode); return 0; } EXPORT_SYMBOL(switchdSetBpduCapMode); int setBpduCapMode(void *cdata, int len) { int bcmode; ip1811drv_dbg("ip1811: +setBpduCapMode...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; bcmode = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetBpduCapMode(bcmode) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setBpduCapMode...\n"); return 0; } int switchdGetBpduCapMode(int *ptrInt) { *ptrInt = (int)_ReadRegBits(0, P0REG_MACBEHAVIOR, 10, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetBpduCapMode); int getBpduCapMode(void *cdata, int len) { int bcmode; ip1811drv_dbg("ip1811: +getBpduCapMode...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetBpduCapMode(&bcmode) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = bcmode; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getBpduCapMode...\n"); return 0; } int switchdSetBpduPortAct(int port, int state) { u16 u16dat; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if (state!=OP_CAP_ACT_FORWARD && state!=OP_CAP_ACT_TO_CPU && state!=OP_CAP_ACT_DROP) return -EINVAL; ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("state=%d\n", state); IP2Page(0); u16dat = Read_Reg(P0REG_BPDUPORTCAPCFG); u16dat |= (u16)((state&0x1) << (port)); #ifdef COMBINED_PORT if (port==9) u16dat |= (u16)((state&0x1) << (port+1)); #endif Write_Reg(P0REG_BPDUPORTCAPCFG, u16dat); u16dat = Read_Reg(P0REG_BPDUPORTCAPCFG+2); u16dat |= (u16)(((state>>1)&0x1) << (port)); #ifdef COMBINED_PORT if (port==9) u16dat |= (u16)(((state>>1)&0x1) << (port+1)); #endif Write_Reg(P0REG_BPDUPORTCAPCFG+2, u16dat); return 0; } EXPORT_SYMBOL(switchdSetBpduPortAct); int setBpduPortAct(void *cdata, int len) { int port, state; ip1811drv_dbg("ip1811: +setBpduPortAct...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; state= ((struct ByPortSetting *)cdata) ->pdata; if(switchdSetBpduPortAct(port, state) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setBpduPortAct...\n"); return 0; } int switchdGetBpduPortAct(int port, int *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (int)(_ReadRegBits(0, P0REG_BPDUPORTCAPCFG+2, port, 1) | _ReadRegBits(0, P0REG_BPDUPORTCAPCFG, port, 1)); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetBpduPortAct); int getBpduPortAct(void *cdata, int len) { int port, state; ip1811drv_dbg("ip1811: +getBpduPortAct...\n"); if (sizeof(struct ByPortSetting) != len) return -EINVAL; port = ((struct ByPortSetting *)cdata) ->port; if(switchdGetBpduPortAct(port, &state) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = state; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); ip1811drv_dbg("ip1811: -getBpduPortAct...\n"); return 0; } int switchdSetStpPortState(int fid, int port, int state) { u16 u16dat=0; if (fid < 1 || fid > 16) return -EINVAL; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if (state < OP_STP_STATE_DISCARD || state > OP_STP_STATE_FORWARD) return -EINVAL; ip1811drv_dbg("fid=%d\n", fid); ip1811drv_dbg("port=%d\n", port); ip1811drv_dbg("state=%d\n", state); fid--; IP2Page(2); Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0x8010 | fid)); u16dat = Read_Reg(P2REG_SPANTREE_PORTDTA); switch(state){ case OP_STP_STATE_DISCARD: case OP_STP_STATE_BLOCK: u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9) u16dat &= (u16)~(1 << port+1); #endif break; case OP_STP_STATE_LEARN: case OP_STP_STATE_FORWARD: u16dat |= (u16)(1 << port); #ifdef COMBINED_PORT if (port==9) u16dat |= (u16)(1 << port+1); #endif break; } Write_Reg(P2REG_SPANTREE_PORTDTA, u16dat & 0xFFFF); Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0xC010 | fid)); Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0x8000 | fid)); u16dat = Read_Reg(P2REG_SPANTREE_PORTDTA); switch(state){ case OP_STP_STATE_DISCARD: case OP_STP_STATE_LEARN: u16dat &= (u16)~(1 << port); #ifdef COMBINED_PORT if (port==9) u16dat &= (u16)~(1 << port+1); #endif break; case OP_STP_STATE_BLOCK: case OP_STP_STATE_FORWARD: u16dat |= (u16)(1 << port); #ifdef COMBINED_PORT if (port==9) u16dat |= (u16)(1 << port+1); #endif break; } Write_Reg(P2REG_SPANTREE_PORTDTA, u16dat & 0xFFFF); Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0xC000 | fid)); return 0; } EXPORT_SYMBOL(switchdSetStpPortState); int setStpPortState(void *cdata, int len) { int fid, port, state; ip1811drv_dbg("ip1811: +setStpPortState...\n"); if (sizeof(struct StpByFPSetting) != len) return -EINVAL; fid = ((struct StpByFPSetting *)cdata) ->fid; port= ((struct StpByFPSetting *)cdata) ->port; state=((struct StpByFPSetting *)cdata) ->pstate; if(switchdSetStpPortState(fid, port, state) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setStpPortState...\n"); return 0; } int switchdGetStpPortState(int fid, int port, int *ptrInt) { int state; u16 u16dat=0; if (fid < 1 || fid > 16) return -EINVAL; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; ip1811drv_dbg("fid=%d\n", fid); ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif fid--; IP2Page(2); Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0x8010 | fid)); u16dat = Read_Reg(P2REG_SPANTREE_PORTDTA); state = ((u16dat>>port)&0x1)<<1; Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0x8000 | fid)); u16dat = Read_Reg(P2REG_SPANTREE_PORTDTA); state |= ((u16dat>>port)&0x1); *ptrInt = state; ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetStpPortState); int getStpPortState(void *cdata, int len) { int fid, port, state; ip1811drv_dbg("ip1811: +getStpPortState...\n"); if (sizeof(struct StpByFPSetting) != len) return -EINVAL; fid = ((struct StpByFPSetting *)cdata) ->fid; port= ((struct StpByFPSetting *)cdata) ->port; if(switchdGetStpPortState(fid, port, &state) != 0) return -EINVAL; ((struct StpByFPSetting *)cdata) ->pstate = state; ip1811drv_dbg("cdata ->pstate=%d\n", ((struct StpByFPSetting *)cdata) ->pstate); ip1811drv_dbg("ip1811: -getStpPortState...\n"); return 0; } //ip1811_lacp int switchdSetTrunkHashMthdSeq(int en) { if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("en=%d\n", en); _WriteRegBits(1, P1REG_TRUNKCFG, 3, 1, en); return 0; } EXPORT_SYMBOL(switchdSetTrunkHashMthdSeq); int setTrunkHashMthdSeq(void *cdata, int len) { int en; ip1811drv_dbg("ip1811: +setTrunkHashMthdSeq...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; en = ((struct GeneralSetting *)cdata) ->gdata; if(switchdSetTrunkHashMthdSeq(en) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setTrunkHashMthdSeq...\n"); return 0; } int switchdGetTrunkHashMthdSeq(int *ptrInt) { *ptrInt = (int)_ReadRegBits(1, P1REG_TRUNKCFG, 3, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetTrunkHashMthdSeq); int getTrunkHashMthdSeq(void *cdata, int len) { int en; ip1811drv_dbg("ip1811: +getTrunkHashMthdSeq...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; if(switchdGetTrunkHashMthdSeq(&en) != 0) return -EINVAL; ((struct GeneralSetting *)cdata) ->gdata = en; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getTrunkHashMthdSeq...\n"); return 0; } int switchdSetTrunkGrpCombine(int grps, int en) { if (grps < OP_TRUNK_COMBINE_G1_G2 || grps > OP_TRUNK_COMBINE_G3_G4) return -EINVAL; if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE) return -EINVAL; ip1811drv_dbg("grps=%d\n", grps); ip1811drv_dbg("en=%d\n", en); _WriteRegBits(1, P1REG_TRUNKCFG, grps, 1, en); return 0; } EXPORT_SYMBOL(switchdSetTrunkGrpCombine); int setTrunkGrpCombine(void *cdata, int len) { int grps, en; ip1811drv_dbg("ip1811: +setTrunkGrpCombine...\n"); if (sizeof(struct TrunkCombineSetting) != len) return -EINVAL; grps=((struct TrunkCombineSetting *)cdata) ->tgrps; en = ((struct TrunkCombineSetting *)cdata) ->cen; if(switchdSetTrunkGrpCombine(grps, en) != 0) return -EINVAL; ip1811drv_dbg("ip1811: -setTrunkGrpCombine...\n"); return 0; } int switchdGetTrunkGrpCombine(int grps, int *ptrInt) { if (grps < OP_TRUNK_COMBINE_G1_G2 || grps > OP_TRUNK_COMBINE_G3_G4) return -EINVAL; ip1811drv_dbg("grps=%d\n", grps); *ptrInt = (int)_ReadRegBits(1, P1REG_TRUNKCFG, grps, 1); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetTrunkGrpCombine); int getTrunkGrpCombine(void *cdata, int len) { int grps, en; ip1811drv_dbg("ip1811: +getTrunkGrpCombine...\n"); if (sizeof(struct TrunkCombineSetting) != len) return -EINVAL; grps=((struct TrunkCombineSetting *)cdata) ->tgrps; if(switchdGetTrunkGrpCombine(grps, &en) != 0) return -EINVAL; ((struct TrunkCombineSetting *)cdata) ->cen = en; ip1811drv_dbg("cdata ->cen=%d\n", ((struct TrunkCombineSetting *)cdata) ->cen); ip1811drv_dbg("ip1811: -getTrunkGrpCombine...\n"); return 0; } //------------ MIB Counter functions:ip1811 --------------------- int switchdSetMibCounterEnable(int en) { if( en!=OP_FUNC_ENABLE && en!=OP_FUNC_DISABLE ){ ip1811drv_err("Error: en=%X\n", en); return -EINVAL; } _WriteRegBits(0, P0REG_MACBEHAVIOR, 9, 1, en); return 0; } EXPORT_SYMBOL(switchdSetMibCounterEnable); int setMibCounterEnable(void *cdata, int len) { int ret, en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } en = ((struct GeneralSetting *)cdata) ->gdata; ip1811drv_dbg("cdata ->gdata=%d\n", en); ret = switchdSetMibCounterEnable(en); FUNC_MSG_OUT; return ret; } int switchdGetMibCounterEnable(int *gdata_p) { *gdata_p = _ReadRegBits(0, P0REG_MACBEHAVIOR, 9, 1); return 0; } EXPORT_SYMBOL(switchdGetMibCounterEnable); int getMibCounterEnable(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ret = switchdGetMibCounterEnable(&(gs ->gdata)); FUNC_MSG_OUT; return ret; } int switchdGetMibCounterAll(void *uptr) { int i, j, ret=0; struct MIBCounterEntry_all *dptr; dptr = kmalloc(sizeof(struct MIBCounterEntry_all), GFP_KERNEL); if (!dptr) { ret = -ENOMEM; goto out_mib_counter_all; } IP2Page(0); for(j=0; j> 15)&0x1); dptr ->entry[j].RX_counter[i] = (u32)Read_Reg(POREG_MIBCOUN_DATA_L); dptr ->entry[j].RX_counter[i] |= ((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16); } for(i=0; i> 15)&0x1); dptr ->entry[j].TX_counter[i] = (u32)Read_Reg(POREG_MIBCOUN_DATA_L); dptr ->entry[j].TX_counter[i] |= ((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16); } } if (copy_to_user(uptr, dptr, sizeof(struct MIBCounterEntry_all))) { ret = -EFAULT; goto out_mib_counter_all; } out_mib_counter_all: if(dptr){ kfree(dptr); } return (ret < 0) ? ret : 0; } EXPORT_SYMBOL(switchdGetMibCounterAll); int getMibCounterAll(void *cdata, int len) { int ret; void *uptr; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } uptr = (void *)(((struct GeneralSetting *)cdata) ->gdata); ret = switchdGetMibCounterAll(uptr); FUNC_MSG_OUT; return ret; } int switchdGetMibCounterByPort(void *uptr, int port) { int i, ret; struct MIBCounterEntry *dptr; dptr = kmalloc(sizeof(struct MIBCounterEntry), GFP_KERNEL); if (!dptr) { ret = -ENOMEM; goto out_mib_counter; } IP2Page(0); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif for(i=0; i> 15)&0x1); dptr ->RX_counter[i] = (u32)(((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16)|Read_Reg(POREG_MIBCOUN_DATA_L)); } for(i=0; i> 15)&0x1); dptr ->TX_counter[i] = (u32)(((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16)|Read_Reg(POREG_MIBCOUN_DATA_L)); } if (copy_to_user(uptr, dptr, sizeof(struct MIBCounterEntry))) { ret = -EFAULT; goto out_mib_counter; } out_mib_counter: if(dptr) { kfree(dptr); } return (ret < 0) ? ret : 0; } EXPORT_SYMBOL(switchdGetMibCounterByPort); int getMibCounterByPort(void *cdata, int len) { int port, ret; void *uptr; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } uptr = (void *)(((struct ByPortSetting *)cdata) ->pdata); port = ((struct ByPortSetting *)cdata) ->port; ret = switchdGetMibCounterByPort(uptr, port); FUNC_MSG_OUT; return ret; } int switchdGetMibCounterByItem(int port, int is_tx, int idx, unsigned long *cnt) { IP2Page(0); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif //statistic counter read , read clear rx counter Write_Reg(POREG_MIBCOUN_CMD, (is_tx?0xC400:0xC000)|(u16)idx|((u16)port<<5)); /* need to check does trigger bit has been put down */ while((Read_Reg(POREG_MIBCOUN_CMD) >> 15)&0x1); *cnt = (u32)(((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16)|Read_Reg(POREG_MIBCOUN_DATA_L)); return 0; } EXPORT_SYMBOL(switchdGetMibCounterByItem); int getMibCounterByItem(void *cdata, int len) { int port, dir, idx, ret; unsigned long mibcnt; struct MIBCounterData *mcd = (struct MIBCounterData *)cdata; FUNC_MSG_IN; if (sizeof(struct MIBCounterData) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } port = mcd ->port; dir = mcd ->dir; idx = mcd ->idx; ret = switchdGetMibCounterByItem(port, dir, idx, &mibcnt); mcd ->counter = mibcnt; FUNC_MSG_OUT; return ret; } //------------ MIB Counter functions:ip1811 end------------------ //------------ QOS functions:ip1811 ----------------------------- int setQOSAgingFunction(void *cdata, int len) { int port,aging; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } port=((struct ByPortSetting *)cdata) ->port; aging =((struct ByPortSetting *)cdata) ->pdata; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if (aging < 0 || aging > 0xff) return -EINVAL; _WriteRegBits(8, P8REG_QOSPORTAGINGEN0+(port/2), (port%2)*8, 8, aging); #ifdef COMBINED_PORT if (port==9){ _WriteRegBits(8, P8REG_QOSPORTAGINGEN0+((port+1)/2), ((port+1)%2)*8, 8, aging); } #endif FUNC_MSG_OUT; return 0; } int getQOSAgingFunction(void *cdata, int len) { int port; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } port=((struct ByPortSetting *)cdata) ->port; if (port < 0 || port >= MAX_PHY_NUM) return -EINVAL; #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif ((struct ByPortSetting *)cdata) ->pdata=(u32)_ReadRegBits(8,P8REG_QOSPORTAGINGEN0+(port/2),(port%2)*8,8); FUNC_MSG_OUT; ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata); return 0; } int setQOSAgingTime(void *cdata, int len) { int aging; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } aging = ((struct GeneralSetting *)cdata) ->gdata; if (aging < 0 || aging > 0xff) return -EINVAL; _WriteRegBits(8, P8REG_QOSAGINGTIME, 0, 8, aging); FUNC_MSG_OUT; return 0; } int getQOSAgingTime(void *cdata, int len) { FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } ((struct GeneralSetting *)cdata) ->gdata = (u16)_ReadRegBits(8, P8REG_QOSAGINGTIME, 0, 8); FUNC_MSG_OUT; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); return 0; } int setQOSFastAging(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 8, P8REG_QOSAGINGTIME, 8); FUNC_MSG_OUT; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); return ret; } int getQOSFastAging(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 8, P8REG_QOSAGINGTIME, 8); FUNC_MSG_OUT; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); return ret; } int setCOSIGMP(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 0, P0REG_COSIGMPBASEPRIEN); FUNC_MSG_OUT; return ret; } int getCOSIGMP(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 0, P0REG_COSIGMPBASEPRIEN); FUNC_MSG_OUT; return ret; } int setCOSMACAddress(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 0, P0REG_COSMACBASEPRIEN); FUNC_MSG_OUT; return ret; } int getCOSMACAddress(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 0, P0REG_COSMACBASEPRIEN); FUNC_MSG_OUT; return ret; } int setCOSVID(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 0, P0REG_COSVIDBASEPRIEN); FUNC_MSG_OUT; return ret; } int getCOSVID(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 0, P0REG_COSVIDBASEPRIEN); FUNC_MSG_OUT; return ret; } int setCOSTCPUDPPort(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 0, P0REG_COSTCPUDPBASEPRIEN); FUNC_MSG_OUT; return ret; } int getCOSTCPUDPPort(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 0, P0REG_COSTCPUDPBASEPRIEN); FUNC_MSG_OUT; return ret; } int setCOSDSCP(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 0, P0REG_COSDSCPBASEPRIEN); FUNC_MSG_OUT; return ret; } int getCOSDSCP(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 0, P0REG_COSDSCPBASEPRIEN); FUNC_MSG_OUT; return ret; } int setCOS8021P(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 0, P0REG_COS8021PBASEPRIEN); FUNC_MSG_OUT; return ret; } int getCOS8021P(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 0, P0REG_COS8021PBASEPRIEN); FUNC_MSG_OUT; return ret; } int setCOSPhsicalPort(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 0, P0REG_COSPORTBASEPRIEN); FUNC_MSG_OUT; return ret; } int getCOSPhsicalPort(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 0, P0REG_COSPORTBASEPRIEN); FUNC_MSG_OUT; return ret; } int setCOSPortQueue(void *cdata, int len) { int port; u8 queue; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } port = ((struct ByPortSetting *)cdata) ->port; queue = ((struct ByPortSetting *)cdata) ->pdata; if ((port < 0) || (port >= MAX_PHY_NUM)) { ip1811drv_err("Error: port=%d\n", port); return -EINVAL; } if(queue>7) { ip1811drv_err("Error: queue=%d\n", queue); return -EINVAL; } _WriteRegBits(0, P0REG_COSPORTBASEQUEUE0+(port/5), (port%5)*3, 3, queue); #ifdef COMBINED_PORT if (port==9) _WriteRegBits(0, P0REG_COSPORTBASEQUEUE0+((port+1)/5), ((port+1)%5)*3, 3, queue); #endif FUNC_MSG_OUT; return 0; } int getCOSPortQueue(void *cdata, int len) { int port; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } port = ((struct ByPortSetting *)cdata) ->port; if ((port < 0) || (port >= MAX_PHY_NUM)) { ip1811drv_err("Error: port=%d\n", port); return -EINVAL; } #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif ((struct ByPortSetting *)cdata) ->pdata = (u16)_ReadRegBits(0, P0REG_COSPORTBASEQUEUE0+(port/5), (port%5)*3, 3); ip1811drv_dbg("cdata ->pdata=0x%04X\n", ((struct ByPortSetting *)cdata) ->pdata); FUNC_MSG_OUT; return 0; } int setCOS8021PEdtion(void *cdata, int len) { int gdata; u16 regdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gdata = ((struct GeneralSetting *)cdata) ->gdata; if( gdata != OP_QOS_8021PEDTION_2005 && gdata != OP_QOS_8021PEDTION_2005_EX && gdata != OP_QOS_8021PEDTION_EARLY ) { ip1811drv_err("Error: gdata=%X\n", gdata); return -EINVAL; } ip1811drv_dbg("cdata ->gdata=%d\n", gdata); IP2Page(0); regdata = Read_Reg(P0REG_COS8021PBASEPRIEN); regdata &= (u16)~0x6000; switch(gdata) { case OP_QOS_8021PEDTION_2005: break; case OP_QOS_8021PEDTION_2005_EX: regdata |= 0x4000; break; case OP_QOS_8021PEDTION_EARLY: regdata |= 0x2000; break; } Write_Reg(P0REG_COS8021PBASEPRIEN,regdata); FUNC_MSG_OUT; return 0; } int getCOS8021PEdtion(void *cdata, int len) { u16 u16dat; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } u16dat =_ReadRegBits(0, P0REG_COS8021PBASEPRIEN, 13, 2); if(u16dat&0x1) { ((struct GeneralSetting *)cdata) ->gdata = OP_QOS_8021PEDTION_EARLY; } else { if(u16dat&0x2) { ((struct GeneralSetting *)cdata) ->gdata = OP_QOS_8021PEDTION_2005_EX; } else { ((struct GeneralSetting *)cdata) ->gdata = OP_QOS_8021PEDTION_2005; } } ip1811drv_dbg("cdata ->gdata=0x%08x\n", ((struct GeneralSetting *)cdata) ->gdata); FUNC_MSG_OUT; return 0; } int setCOSDSCPBaseDSCP(void *cdata, int len) { u8 entryno,value,queue; FUNC_MSG_IN; if (sizeof(struct qos_dscp_setting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } entryno = ((struct qos_dscp_setting *)cdata) ->dscpentry; value = ((struct qos_dscp_setting *)cdata) ->dscpvalue; queue = ((struct qos_dscp_setting *)cdata) ->dscpqueue; if(entryno<1 || entryno>8) { ip1811drv_err("Error: entryno=%d\n", entryno); return -EINVAL; } if(value & ~0x3f) { ip1811drv_err("Error: value=%X\n", value); return -EINVAL; } if(queue>7) { ip1811drv_err("Error: queue=%d\n", queue); return -EINVAL; } entryno-=1; _WriteRegBits(0, P0REG_COSDSCPVALUE0+(entryno/2), (entryno%2)*6, 6, value); _WriteRegBits(0, P0REG_COSDSCPPRISETTING0+(entryno/5), (entryno%5)*3, 3, queue); FUNC_MSG_OUT; return 0; } int getCOSDSCPBaseDSCP(void *cdata, int len) { u8 entryno; FUNC_MSG_IN; if (sizeof(struct qos_dscp_setting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } entryno = ((struct qos_dscp_setting *)cdata) ->dscpentry; if(entryno>7) { ip1811drv_err("Error: entryno=%d\n", entryno); return -EINVAL; } ((struct qos_dscp_setting *)cdata) ->dscpvalue = (u16)_ReadRegBits(0, P0REG_COSDSCPVALUE0+(entryno/2), (entryno%2)*5, 6); ((struct qos_dscp_setting *)cdata) ->dscpqueue = (u16)_ReadRegBits(0, P0REG_COSDSCPPRISETTING0+(entryno/5), (entryno%5)*3, 3); ip1811drv_dbg("cdata ->dscpvalue=0x%04X\n", ((struct qos_dscp_setting *)cdata) ->dscpvalue); ip1811drv_dbg("cdata ->dscpqueue=0x%04X\n", ((struct qos_dscp_setting *)cdata) ->dscpqueue); FUNC_MSG_OUT; return 0; } int setCOSDSCPBaseNoMatchAction(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0, P0REG_COSDSCPPRISETTING1, 9); FUNC_MSG_OUT; return ret; } int getCOSDSCPBaseNoMatchAction(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0, P0REG_COSDSCPPRISETTING1, 9); FUNC_MSG_OUT; return ret; } int setQOSmodeGroupMember(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 8, P8REG_QOSGROUPSEL); FUNC_MSG_OUT; return ret; } int getQOSmodeGroupMember(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 8, P8REG_QOSGROUPSEL); FUNC_MSG_OUT; return ret; } int setQOSGroupBEn(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 8, P8REG_QOSMODESELGROUP2, 9); FUNC_MSG_OUT; return ret; } int getQOSGroupBEn(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 8, P8REG_QOSMODESELGROUP2, 9); FUNC_MSG_OUT; return ret; } int setQOSMode(void *cdata, int len) { int gpnum,mode; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; mode = ((struct qos_modesettings *)cdata) ->modesettings; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } if(modeOP_QOS_MODE_SP8) { ip1811drv_err("Error: mode=%d\n", mode); return -EINVAL; } _WriteRegBits(8, (gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2, 0, 3, mode); FUNC_MSG_OUT; return 0; } int getQOSMode(void *cdata, int len) { int gpnum; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } ((struct qos_modesettings *)cdata) ->modesettings= (int)_ReadRegBits(8,(gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2, 0, 3); ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum); ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings); FUNC_MSG_OUT; return 0; } int setQOSMethod(void *cdata, int len) { int gpnum,mode; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; mode = ((struct qos_modesettings *)cdata) ->modesettings; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } if(modeOP_QOS_METHOD_TWRR) { ip1811drv_err("Error: mode=%d\n", mode); return -EINVAL; } IP2Page(8); u16dat = Read_Reg((gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2); u16dat &= 0xFF9F; switch(mode) { case OP_QOS_METHOD_WRR: break; case OP_QOS_METHOD_BW: u16dat |= ((u16)0x1<<5); break; case OP_QOS_METHOD_WFQ: u16dat |= ((u16)0x2<<5); break; case OP_QOS_METHOD_TWRR: u16dat |= ((u16)0x3<<5); break; } Write_Reg((gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2,u16dat); if(mode==OP_QOS_METHOD_BW) Write_Reg(P8REG_QOSMODESELGROUP1,Read_Reg(P8REG_QOSMODESELGROUP1)|0x8000);//stop & hold pkt else Write_Reg(P8REG_QOSMODESELGROUP1,Read_Reg(P8REG_QOSMODESELGROUP1)&0x7FFF); ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum); ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings); FUNC_MSG_OUT; return 0; } int getQOSMethod(void *cdata, int len) { int gpnum; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } u16dat = _ReadRegBits(8, (gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2, 5, 3); ((struct qos_modesettings *)cdata) ->modesettings = u16dat; ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum); ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings); FUNC_MSG_OUT; return 0; } int setQOSWeight(void *cdata, int len) { int gpnum,mode,queue; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; queue = ((struct qos_modesettings *)cdata) ->queuenum; mode = ((struct qos_modesettings *)cdata) ->modesettings; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } if(queueOP_QOS_NUM_Q7) { ip1811drv_err("Error: queue=%d\n", queue); return -EINVAL; } if(mode & ~(int)0xff) { ip1811drv_err("Error: mode=%d\n", mode); return -EINVAL; } _WriteRegBits(8, (gpnum==OP_QOS_GROUP1)?(P8REG_QOSGP1_WEIGHT0+(queue/2)):(P8REG_QOSGP2_WEIGHT0+(queue/2)), (queue%2)*8, 8, mode); FUNC_MSG_OUT; return 0; } int getQOSWeight(void *cdata, int len) { int gpnum,queue; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; queue = ((struct qos_modesettings *)cdata) ->queuenum; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } u16dat = _ReadRegBits(8,(gpnum==OP_QOS_GROUP1)?(P8REG_QOSGP1_WEIGHT0+(queue/2)):(P8REG_QOSGP2_WEIGHT0+(queue/2)), ((queue%2)*8), 8); ((struct qos_modesettings *)cdata) ->modesettings=(int)u16dat; ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum); ip1811drv_dbg("cdata ->queuenum=0x%04X\n", ((struct qos_modesettings *)cdata) ->queuenum); ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings); FUNC_MSG_OUT; return 0; } int setQOSMaxBandwidth(void *cdata, int len) { int gpnum,mode,queue; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; queue = ((struct qos_modesettings *)cdata) ->queuenum; mode = ((struct qos_modesettings *)cdata) ->modesettings; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } if(queueOP_QOS_NUM_Q7) { ip1811drv_err("Error: queue=%d\n", queue); return -EINVAL; } if(mode & ~(int)0xff) { ip1811drv_err("Error: mode=%d\n", mode); return -EINVAL; } _WriteRegBits(8, (gpnum==OP_QOS_GROUP1)?(P8REG_QOSGP1_MAXBDWT0+(queue/2)):(P8REG_QOSGP2_MAXBDWT0+(queue/2)), (queue%2)*8, 8, mode); FUNC_MSG_OUT; return 0; } int getQOSMaxBandwidth(void *cdata, int len) { int gpnum,queue; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; queue = ((struct qos_modesettings *)cdata) ->queuenum; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } if(queueOP_QOS_NUM_Q7) { ip1811drv_err("Error: queue=%d\n", queue); return -EINVAL; } u16dat = _ReadRegBits(8, (gpnum==OP_QOS_GROUP1)?(P8REG_QOSGP1_MAXBDWT0+(queue/2)):(P8REG_QOSGP2_MAXBDWT0+(queue/2)), ((queue%2)*8), 8); ((struct qos_modesettings *)cdata) ->modesettings=(int)u16dat; ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum); ip1811drv_dbg("cdata ->queuenum=0x%04X\n", ((struct qos_modesettings *)cdata) ->queuenum); ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings); FUNC_MSG_OUT; return 0; } int setQOSUnit(void *cdata, int len) { int gpnum,mode; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; mode = ((struct qos_modesettings *)cdata) ->modesettings; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } if(modeOP_QOS_UNIT_4MBS) { ip1811drv_err("Error: mode=%d\n", mode); return -EINVAL; } _WriteRegBits(8, (gpnum==OP_QOS_GROUP1)?(P8REG_QOSMODESELGROUP1):(P8REG_QOSMODESELGROUP2), 3, 2, mode); FUNC_MSG_OUT; return 0; } int getQOSUnit(void *cdata, int len) { int gpnum; FUNC_MSG_IN; if (sizeof(struct qos_modesettings) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } gpnum = ((struct qos_modesettings *)cdata) ->groupnum; if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2) { ip1811drv_err("Error: gpnum=%d\n", gpnum); return -EINVAL; } ((struct qos_modesettings *)cdata) ->modesettings= (int)_ReadRegBits(8,(gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2, 3, 2); ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum); ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings); FUNC_MSG_OUT; return 0; } int setQOSRatioValue0Def(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 8, P8REG_QOSMODESELGROUP1, 15); FUNC_MSG_OUT; return ret; } int getQOSRatioValue0Def(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 8, P8REG_QOSMODESELGROUP1, 15); FUNC_MSG_OUT; return ret; } int setQOSSBMDBM(void *cdata, int len) { int port,mode; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } port = ((struct ByPortSetting *)cdata) ->port; mode = ((struct ByPortSetting *)cdata) ->pdata; if(port < 0 || port >= MAX_PHY_NUM) return -EINVAL; if(mode!=OP_QOS_QBASE_DBM && mode!=OP_QOS_QBASE_SBM) { ip1811drv_err("Error: mode=%d\n", mode); return -EINVAL; } ip1811drv_dbg(" port=%d\n", port); ip1811drv_dbg(" mode=%d\n", mode); IP2Page(8); // set all queue(per port) to same mode u16dat=Read_Reg(P8REG_QOS_SBMDBMSEL0+(port/2)); u16dat&=((port%2)?0x00FF:0xFF00); if(mode==OP_QOS_QBASE_SBM) { u16dat|=((port%2)?0xFF00:0x00FF); } Write_Reg(P8REG_QOS_SBMDBMSEL0+(port/2),u16dat); #ifdef COMBINED_PORT if (port==9){ u16dat=Read_Reg(P8REG_QOS_SBMDBMSEL0+((port+1)/2)); u16dat&=(((port+1)%2)?0x00FF:0xFF00); if(mode==OP_QOS_QBASE_SBM) { u16dat|=(((port+1)%2)?0xFF00:0x00FF); } Write_Reg(P8REG_QOS_SBMDBMSEL0+((port+1)/2),u16dat); } #endif FUNC_MSG_OUT; return 0; } int getQOSSBMDBM(void *cdata, int len) { int port; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct ByPortSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } port = ((struct ByPortSetting *)cdata) ->port; if(port<0 || port>=MAX_PHY_NUM) return -EINVAL; IP2Page(8); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif u16dat=Read_Reg(P8REG_QOS_SBMDBMSEL0+(port/2)); u16dat>>=((port%2)*8); if(u16dat&0xff) { ((struct ByPortSetting *)cdata) ->pdata=OP_QOS_QBASE_SBM; } else { ((struct ByPortSetting *)cdata) ->pdata=OP_QOS_QBASE_DBM; } ip1811drv_dbg("cdata ->port=0x%d\n", ((struct ByPortSetting *)cdata) ->port); ip1811drv_dbg("cdata ->pdata=0x%d\n", ((struct ByPortSetting *)cdata) ->pdata); FUNC_MSG_OUT; return 0; } int setQOSDBMEn(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setPortmap(cdata, len, 8, P8REG_QOSQUEUEDBMEN); FUNC_MSG_IN; return ret; } int getQOSDBMEn(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getPortmap(cdata, len, 8, P8REG_QOSQUEUEDBMEN); FUNC_MSG_IN; return ret; } int setQOSRemap(void *cdata, int len) { int port; u8 queue,remap; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct qos_remap) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } port = ((struct qos_remap *)cdata) ->port; queue = ((struct qos_remap *)cdata) ->queue; remap = ((struct qos_remap *)cdata) ->remap; if(port<0 || port>=MAX_PHY_NUM) return -EINVAL; if(queue>OP_QOS_REMAP_TX_Q7) { ip1811drv_err("Error: queue=%d\n", queue); return -EINVAL; } if(remap>7) { ip1811drv_err("Error: remap=%d\n", remap); return -EINVAL; } ip1811drv_dbg("cdata ->port=0x%d\n", ((struct qos_remap *)cdata) ->port); ip1811drv_dbg("cdata ->queue=0x%d\n", ((struct qos_remap *)cdata) ->queue); ip1811drv_dbg("cdata ->remap=0x%d\n", ((struct qos_remap *)cdata) ->remap); if(queue<=OP_QOS_REMAP_RX_Q7)//RX { if ((queue/5) == 0) { IP2Page(6); u16dat = Read_Reg(P6REG_QOS_REMAP_RX0+(port*2)+1); } _WriteRegBits(6, P6REG_QOS_REMAP_RX0+(port*2)+(queue/5), (queue%5)*3, 3, remap); if ((queue/5) == 0) { IP2Page(6); Write_Reg(P6REG_QOS_REMAP_RX0+(port*2)+1, u16dat); } #ifdef COMBINED_PORT if (port==9) { if ((queue/5) == 0) { IP2Page(6); u16dat = Read_Reg(P6REG_QOS_REMAP_RX0+((port+1)*2)+1); } _WriteRegBits(6, P6REG_QOS_REMAP_RX0+((port+1)*2)+(queue/5), (queue%5)*3, 3, remap); if ((queue/5) == 0) { IP2Page(6); Write_Reg(P6REG_QOS_REMAP_RX0+((port+1)*2)+1, u16dat); } } #endif } else//TX { queue-=8; if (port == 0) { _WriteRegBits(8, P8REG_QOS_REMAP_TX0+(port*2)+(queue/5), (queue%5)*3, 3, remap); } else if (port == 1) { if (queue / 5) _WriteRegBits(8, P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)+1, (queue%5)*3, 3, remap); else _WriteRegBits(8, P8REG_QOS_REMAP_TX0+(port*2)+(queue/5), (queue%5)*3, 3, remap); } else { _WriteRegBits(8, P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)+1, (queue%5)*3, 3, remap); #ifdef COMBINED_PORT if (port==9) _WriteRegBits(8, P8REG_QOS_REMAP_TX0+((port+1)*2)+(queue/5)+1, (queue%5)*3, 3, remap); #endif } } FUNC_MSG_OUT; return 0; } int getQOSRemap(void *cdata, int len) { int port; u8 queue; u16 u16dat; FUNC_MSG_IN; if (sizeof(struct qos_remap) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } port = ((struct qos_remap *)cdata) ->port; queue = ((struct qos_remap *)cdata) ->queue; if(port<0 || port>=MAX_PHY_NUM) return -EINVAL; if(queue>OP_QOS_REMAP_TX_Q7) { ip1811drv_err("Error: queue=%d\n", queue); return -EINVAL; } ip1811drv_dbg("cdata ->port=0x%d\n", ((struct qos_remap *)cdata) ->port); ip1811drv_dbg("cdata ->queue=0x%d\n", ((struct qos_remap *)cdata) ->queue); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif if(queue<=OP_QOS_REMAP_RX_Q7)//RX { IP2Page(6); u16dat = Read_Reg(P6REG_QOS_REMAP_RX0+(port*2)+(queue/5)); } else//TX { queue-=8; IP2Page(8); if (port == 0) { u16dat = Read_Reg(P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)); } else if (port == 1) { if (queue / 5) u16dat = Read_Reg(P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)+1); else u16dat = Read_Reg(P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)); } else { u16dat = Read_Reg(P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)+1); } } ((struct qos_remap *)cdata) ->remap = (u8)((u16dat>>((queue%5)*3))&0x7); ip1811drv_dbg("cdata ->remap=0x%d\n", ((struct qos_remap *)cdata) ->remap); FUNC_MSG_OUT; return 0; } //------------ QOS functions:ip1811 end-------------------------- //------------ ACL functions:common ---------------------------- struct acl_man *m_acl; // acl golbal manage variable int acl_write_table_0010(int block, int index, int link, struct acl_rule *r); int acl_write_table_0100(int block, int index, int link, struct acl_rule *r); int acl_write_table_0101(int block, int index, int link, struct acl_rule *r); int acl_write_table_0110(int block, int index, int link, struct acl_rule *r); int acl_write_table_0111(int block, int index, int link, struct acl_rule *r); int acl_write_table_1x00(int block, int index, int link, struct acl_rule *r); int acl_write_table_1x01(int block, int index, int link, struct acl_rule *r); int acl_write_table_1x10(int block, int index, int link, struct acl_rule *r); int acl_write_table_1x11(int block, int index, int link, struct acl_rule *r); int (*acl_write_table_rule[])(int block, int index, int link, struct acl_rule *r) = { NULL, acl_write_table_0010, NULL, acl_write_table_0100, acl_write_table_0101, acl_write_table_0110, acl_write_table_0111, acl_write_table_1x00, acl_write_table_1x01, acl_write_table_1x10, acl_write_table_1x11 }; int acl_write_table_drop(int block, int index, int is_link, struct acl_rule *r); int acl_write_table_a1(int block, int index, int is_link, struct acl_rule *r); int acl_write_table_a2(int block, int index, int is_link, struct acl_rule *r); int acl_write_table_a3(int block, int index, int is_link, struct acl_rule *r); int (*acl_write_table_act[])(int block, int index, int is_link, struct acl_rule *r) = { acl_write_table_drop, acl_write_table_a1, acl_write_table_a2, acl_write_table_a3 }; int set_rule_index_remap(void); void acl_init(void) { int i; ip1811drv_dbg(" acl_init()\n"); m_acl = kmalloc(sizeof(struct acl_man), GFP_KERNEL); if(m_acl == NULL) { ip1811drv_err("Error: acl_init() acl_man malloc failed.\n"); return; } INIT_LIST_HEAD(&m_acl ->rule_list); m_acl ->num_used_rules = 0; m_acl ->num_used_entries = 0; for(i=0; i<4; i++) { m_acl ->used_entry_mask[i] = 0; } } int acl_find_index(int num, int *block, int *index, int find_idx_blockn, int find_idx_rvs) { int i=0, j=0; unsigned char m = 0; unsigned long t = 0; for(i=0; iused_entry_mask[(find_idx_blockn+i)%4]; if(find_idx_rvs) { // find index in reverse for(j=15; j>=0; j--) { if((16-j) < num) // empty entry is not enough, find next block break; if(!((t>>j) & m)) { *block = (i+find_idx_blockn)%4; *index = j; return 0; } } } else { for(j=0; j<16; j++) { if((16-j) < num) // empty entry is not enough, find next block break; if(!((t>>j) & m)) { *block = (i+find_idx_blockn)%4; *index = j; return 0; } } } } return -ENOMEM; } int acl_clean_table_rule(int block, int index) { IP2Page(1); Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0); Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_clean_table_act(int block, int index) { IP2Page(1); Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0); Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0); // act Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|index|(block<<5)); return 0; } int acl_clean_table(int block, int index) { acl_clean_table_rule(block, index); acl_clean_table_act(block, index); return 0; } int acl_write_table_0010(int block, int index, int link, struct acl_rule *r) { u16 tmp=0; IP2Page(1); /* Set user define location D3 and D4 */ if(r->location1) Write_Reg(P1REG_ACL_PATTEM_LOCATION_D3, r->location1); if(r->location2) Write_Reg(P1REG_ACL_PATTEM_LOCATION_D4, r->location2); /* E1 ~ E8 */ Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->usr0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, r->mask0); Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->usr1); Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->mask1); Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->usr2); Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->mask2); Write_Reg(P1REG_ACL_TABLE_DATA_E7, r->usr3); Write_Reg(P1REG_ACL_TABLE_DATA_E8, r->mask3); //E9 if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp=ACL_SELECT_MODE_0010<<6; if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_0100(int block, int index, int link, struct acl_rule *r) { u16 tmp = 0; IP2Page(1); //E1 & E2 if(r->rule_valid & ACL_RULE_VALID_SIP) { Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->sip4_addr&0xFFFF); Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->sip4_addr>>16)&0xFFFF); tmp |= ((u16)(r->sip_mask&0xF)<<7); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); tmp |= (0xF<<7); // any sip } //E3 & E4 if(r->rule_valid & ACL_RULE_VALID_DP_R) { Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->dp_lo); Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->dp_hi); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); tmp |= BIT(5); } //E5 & E6 if(r->rule_valid & ACL_RULE_VALID_SP_R) { Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->sp_lo); Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->sp_hi); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); tmp |= BIT(6); } //E7 if(r->rule_valid & ACL_RULE_VALID_VLAN) { if(r->rule_valid & ACL_RULE_VALID_COS) { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000)); } } else { tmp |= (0x3<<11); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000); } //E8 tmp |= (0x3<<13); Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0x8000); //E9 if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } if(r->rule_rvs & ACL_RULE_RVS_SIP) { tmp |= 0x8000; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp = ((ACL_SELECT_MODE_0100<<6) | (link<<4)); if(r->rule_rvs & ACL_RULE_RVS_DP_R) { tmp |= 0x1; } if(r->rule_rvs & ACL_RULE_RVS_SP_R) { tmp |= 0x2; } if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) { tmp |= 0x4; } if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_0101(int block, int index, int link, struct acl_rule *r) { u16 tmp = 0; IP2Page(1); //E1 & E2 if(r->rule_valid & ACL_RULE_VALID_DIP) { Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->dip4_addr&0xFFFF); Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->dip4_addr>>16)&0xFFFF); tmp |= ((u16)(r->dip_mask&0xF)<<7); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); tmp |= (0xF<<7); // any dip } //E3 & E4 if(r->rule_valid & ACL_RULE_VALID_DP_R) { Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->dp_lo); Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->dp_hi); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); tmp |= BIT(5); } //E5 & E6 if(r->rule_valid & ACL_RULE_VALID_SP_R) { Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->sp_lo); Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->sp_hi); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); tmp |= BIT(6); } //E7 if(r->rule_valid & ACL_RULE_VALID_VLAN) { if(r->rule_valid & ACL_RULE_VALID_COS) { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000)); } } else { tmp |= (0x3<<11); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000); } //E8 tmp |= (0x3<<13); Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0x8000); //E9 if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } if(r->rule_rvs & ACL_RULE_RVS_DIP) { tmp |= 0x8000; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp = ((ACL_SELECT_MODE_0101<<6) | (link<<4)); if(r->rule_rvs & ACL_RULE_RVS_DP_R) { tmp |= 0x1; } if(r->rule_rvs & ACL_RULE_RVS_SP_R) { tmp |= 0x2; } if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) { tmp |= 0x4; } if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_0110(int block, int index, int link, struct acl_rule *r) { u16 tmp = 0; IP2Page(1); //E1 ~ E8 Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->sip6_addr16[7]); Write_Reg(P1REG_ACL_TABLE_DATA_E2, r->sip6_addr16[6]); Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->sip6_addr16[5]); Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->sip6_addr16[4]); Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->sip6_addr16[3]); Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->sip6_addr16[2]); Write_Reg(P1REG_ACL_TABLE_DATA_E7, r->sip6_addr16[1]); Write_Reg(P1REG_ACL_TABLE_DATA_E8, r->sip6_addr16[0]); //E9 tmp |= ((u16)(r->sip_mask&0x3FF)<<5); if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp = ((ACL_SELECT_MODE_0110<<6) | (link<<4)); if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_0111(int block, int index, int link, struct acl_rule *r) { u16 tmp = 0; IP2Page(1); //E1 ~ E8 Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->dip6_addr16[7]); Write_Reg(P1REG_ACL_TABLE_DATA_E2, r->dip6_addr16[6]); Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->dip6_addr16[5]); Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->dip6_addr16[4]); Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->dip6_addr16[3]); Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->dip6_addr16[2]); Write_Reg(P1REG_ACL_TABLE_DATA_E7, r->dip6_addr16[1]); Write_Reg(P1REG_ACL_TABLE_DATA_E8, r->dip6_addr16[0]); //E9 tmp |= ((u16)(r->dip_mask&0x3FF)<<5); if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp = ((ACL_SELECT_MODE_0111<<6) | (link<<4)); if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_1x00(int block, int index, int link, struct acl_rule *r) { u16 tmp=0, tmp2=0; IP2Page(1); //E1 & E2 if(r->rule_valid & ACL_RULE_VALID_SIP) { Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->sip4_addr&0xFFFF); Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->sip4_addr>>16)&0xFFFF); tmp |= ((u16)(r->sip_mask&0xF)<<7); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); tmp |= (0xF<<7); // any sip } //E3 if(r->rule_valid & ACL_RULE_VALID_ETH_TYPE) { Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->eth_type); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); tmp |= BIT(5); } //E4 ~ E6 if(r->rule_valid & ACL_RULE_VALID_SMAC) { Write_Reg(P1REG_ACL_TABLE_DATA_E4, ((u16)(r->smac[4]&0xFF)<<8) | ((u16)(r->smac[5]&0xFF))); Write_Reg(P1REG_ACL_TABLE_DATA_E5, ((u16)(r->smac[2]&0xFF)<<8) | ((u16)(r->smac[3]&0xFF))); Write_Reg(P1REG_ACL_TABLE_DATA_E6, ((u16)(r->smac[0]&0xFF)<<8) | ((u16)(r->smac[1]&0xFF))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); tmp |= (0x1<<6); // any smac } //E7 if(r->rule_valid & ACL_RULE_VALID_VLAN) { if(r->rule_valid & ACL_RULE_VALID_COS) { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000)); } } else { tmp |= (0x3<<11); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000); } //E8 // ip_proto if(r->rule_valid & ACL_RULE_VALID_IP_PROT) { tmp2 |= ((u16)r->ip_prot&0xFF); } else { tmp |= BIT(13); // any ip_prot } // dscp if(r->rule_valid & ACL_RULE_VALID_DSCP) { tmp2 |= ((u16)(r->r_dscp&0x3F)<<10); } else { tmp |= BIT(14); } Write_Reg(P1REG_ACL_TABLE_DATA_E8, tmp2); //E9 if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } if(r->rule_rvs & ACL_RULE_RVS_SIP) { tmp |= 0x8000; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp = ((ACL_SELECT_MODE_1x00<<6) | (link<<4)); if(r->rule_rvs & ACL_RULE_RVS_ETH_TYPE) { tmp |= 0x1; } if(r->rule_rvs & ACL_RULE_RVS_SMAC) { tmp |= 0x2; } if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) { tmp |= 0x4; } if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_1x01(int block, int index, int link, struct acl_rule *r) { u16 tmp=0, tmp2=0; IP2Page(1); //E1 & E2 if(r->rule_valid & ACL_RULE_VALID_DIP) { Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->dip4_addr&0xFFFF); Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->dip4_addr>>16)&0xFFFF); tmp |= ((u16)(r->dip_mask&0xF)<<7); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); tmp |= (0xF<<7); // any dip } //E3 if(r->rule_valid & ACL_RULE_VALID_ETH_TYPE) { Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->eth_type); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); tmp |= BIT(5); } //E4 ~ E6 if(r->rule_valid & ACL_RULE_VALID_SMAC) { Write_Reg(P1REG_ACL_TABLE_DATA_E4, ((u16)(r->smac[4]&0xFF)<<8) | ((u16)(r->smac[5]&0xFF))); Write_Reg(P1REG_ACL_TABLE_DATA_E5, ((u16)(r->smac[2]&0xFF)<<8) | ((u16)(r->smac[3]&0xFF))); Write_Reg(P1REG_ACL_TABLE_DATA_E6, ((u16)(r->smac[0]&0xFF)<<8) | ((u16)(r->smac[1]&0xFF))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); tmp |= (0x1<<6); // any smac } //E7 if(r->rule_valid & ACL_RULE_VALID_VLAN) { if(r->rule_valid & ACL_RULE_VALID_COS) { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000)); } } else { tmp |= (0x3<<11); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000); } //E8 // ip_proto if(r->rule_valid & ACL_RULE_VALID_IP_PROT) { tmp2 |= ((u16)r->ip_prot&0xFF); } else { tmp |= BIT(13); // any ip_prot } // dscp if(r->rule_valid & ACL_RULE_VALID_DSCP) { tmp2 |= ((u16)(r->r_dscp&0x3F)<<10); } else { tmp |= BIT(14); } Write_Reg(P1REG_ACL_TABLE_DATA_E8, tmp2); //E9 if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } if(r->rule_rvs & ACL_RULE_RVS_DIP) { tmp |= 0x8000; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp = ((ACL_SELECT_MODE_1x01<<6) | (link<<4)); if(r->rule_rvs & ACL_RULE_RVS_ETH_TYPE) { tmp |= 0x1; } if(r->rule_rvs & ACL_RULE_RVS_SMAC) { tmp |= 0x2; } if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) { tmp |= 0x4; } if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_1x10(int block, int index, int link, struct acl_rule *r) { u16 tmp=0, tmp2=0; IP2Page(1); //E1 & E2 if(r->rule_valid & ACL_RULE_VALID_SIP) { Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->sip4_addr&0xFFFF); Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->sip4_addr>>16)&0xFFFF); tmp |= ((u16)(r->sip_mask&0xF)<<7); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); tmp |= (0xF<<7); // any sip } //E3 if(r->rule_valid & ACL_RULE_VALID_ETH_TYPE) { Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->eth_type); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); tmp |= BIT(5); } //E4 ~ E6 if(r->rule_valid & ACL_RULE_VALID_DMAC) { Write_Reg(P1REG_ACL_TABLE_DATA_E4, ((u16)(r->dmac[4]&0xFF)<<8) | ((u16)(r->dmac[5]&0xFF))); Write_Reg(P1REG_ACL_TABLE_DATA_E5, ((u16)(r->dmac[2]&0xFF)<<8) | ((u16)(r->dmac[3]&0xFF))); Write_Reg(P1REG_ACL_TABLE_DATA_E6, ((u16)(r->dmac[0]&0xFF)<<8) | ((u16)(r->dmac[1]&0xFF))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); tmp |= (0x1<<6); // any dmac } //E7 if(r->rule_valid & ACL_RULE_VALID_VLAN) { if(r->rule_valid & ACL_RULE_VALID_COS) { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000)); } } else { tmp |= (0x3<<11); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000); } //E8 // ip_proto if(r->rule_valid & ACL_RULE_VALID_IP_PROT) { tmp2 |= ((u16)r->ip_prot&0xFF); } else { tmp |= BIT(13); // any ip_prot } // dscp if(r->rule_valid & ACL_RULE_VALID_DSCP) { tmp2 |= ((u16)(r->r_dscp&0x3F)<<10); } else { tmp |= BIT(14); } Write_Reg(P1REG_ACL_TABLE_DATA_E8, tmp2); //E9 if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } if(r->rule_rvs & ACL_RULE_RVS_SIP) { tmp |= 0x8000; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp = ((ACL_SELECT_MODE_1x10<<6) | (link<<4)); if(r->rule_rvs & ACL_RULE_RVS_ETH_TYPE) { tmp |= 0x1; } if(r->rule_rvs & ACL_RULE_RVS_DMAC) { tmp |= 0x2; } if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) { tmp |= 0x4; } if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_1x11(int block, int index, int link, struct acl_rule *r) { u16 tmp=0, tmp2=0; IP2Page(1); //E1 & E2 if(r->rule_valid & ACL_RULE_VALID_DIP) { Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->dip4_addr&0xFFFF); Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->dip4_addr>>16)&0xFFFF); tmp |= ((u16)(r->dip_mask&0xF)<<7); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); tmp |= (0xF<<7); // any dip } //E3 if(r->rule_valid & ACL_RULE_VALID_ETH_TYPE) { Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->eth_type); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); tmp |= BIT(5); } //E4 ~ E6 if(r->rule_valid & ACL_RULE_VALID_DMAC) { Write_Reg(P1REG_ACL_TABLE_DATA_E4, ((u16)(r->dmac[4]&0xFF)<<8) | ((u16)(r->dmac[5]&0xFF))); Write_Reg(P1REG_ACL_TABLE_DATA_E5, ((u16)(r->dmac[2]&0xFF)<<8) | ((u16)(r->dmac[3]&0xFF))); Write_Reg(P1REG_ACL_TABLE_DATA_E6, ((u16)(r->dmac[0]&0xFF)<<8) | ((u16)(r->dmac[1]&0xFF))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); tmp |= (0x1<<6); // any dmac } //E7 if(r->rule_valid & ACL_RULE_VALID_VLAN) { if(r->rule_valid & ACL_RULE_VALID_COS) { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12))); } else { Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000)); } } else { tmp |= (0x3<<11); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000); } //E8 // ip_proto if(r->rule_valid & ACL_RULE_VALID_IP_PROT) { tmp2 |= ((u16)r->ip_prot&0xFF); } else { tmp |= BIT(13); // any ip_prot } // dscp if(r->rule_valid & ACL_RULE_VALID_DSCP) { tmp2 |= ((u16)(r->r_dscp&0x3F)<<10); } else { tmp |= BIT(14); } Write_Reg(P1REG_ACL_TABLE_DATA_E8, tmp2); //E9 if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) { tmp |= r->ingress_port+1; } if(r->rule_rvs & ACL_RULE_RVS_DIP) { tmp |= 0x8000; } Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp); //EA tmp = ((ACL_SELECT_MODE_1x11<<6) | (link<<4)); if(r->rule_rvs & ACL_RULE_RVS_ETH_TYPE) { tmp |= 0x1; } if(r->rule_rvs & ACL_RULE_RVS_DMAC) { tmp |= 0x2; } if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) { tmp |= 0x4; } if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) { tmp |= 0x8; } Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int acl_write_table_drop(int block, int index, int is_link, struct acl_rule *r) { u16 tmp = 0; IP2Page(1); //E1 tmp = 0x1F; Write_Reg(P1REG_ACL_TABLE_DATA_E1, tmp); Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0); if(is_link) { tmp = ((ACL_SELECT_MODE_0001<<6) | (ACL_LINK_TYPE_11<<4)); Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); } else { Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|index|(block<<5)); } return 0; } int acl_write_table_a1(int block, int index, int is_link, struct acl_rule *r) { u16 tmp = 0; u16 tmp2 = 0; IP2Page(1); //E1 if(r->act_valid & ACL_ACT_VALID_REDIR) { tmp |= ((r->redir)&0x1F); } if(r->act_valid & ACL_ACT_VALID_CTAG) { tmp |= ((r->ctag&0x7F)<<5); } if(r->act_valid & ACL_ACT_VALID_STAG) { tmp |= ((r->stag&0xF)<<12); } Write_Reg(P1REG_ACL_TABLE_DATA_E1, tmp); //E2 tmp = 0; if(r->act_valid & ACL_ACT_VALID_STAG) { tmp |= ((r->stag&0x70)>>4); } if(r->act_valid & ACL_ACT_VALID_PRI) { tmp |= ((BIT(3)|(r->pri&0x7))<<3); } if(r->act_valid & ACL_ACT_VALID_DSCP) { tmp |= ((BIT(3)|(r->a_dscp&0x7))<<7); } if(r->act_valid & ACL_ACT_VALID_BW) { if(is_link) tmp2 |= ((BIT(2)|(r->bw&0x3))<<4); else tmp |= ((BIT(2)|(r->bw&0x3))<<11); } if(r->act_valid & ACL_ACT_VALID_SNIFFER) { if(is_link) tmp |= BIT(15); else tmp |= BIT(14); } Write_Reg(P1REG_ACL_TABLE_DATA_E2, tmp); Write_Reg(P1REG_ACL_TABLE_DATA_E3, tmp2); Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0); if(is_link) { tmp = ((ACL_SELECT_MODE_0001<<6) | (ACL_LINK_TYPE_11<<4)); Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); } else { Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|index|(block<<5)); } return 0; } int acl_write_table_a2(int block, int index, int is_link, struct acl_rule *r) { u16 tmp = 0; u16 tmp2 = 0; IP2Page(1); //E1 if(r->act_valid & ACL_ACT_VALID_REDIR) { tmp |= ((r->redir)&0x1F); } if(r->act_valid & ACL_ACT_VALID_CTAG) { tmp |= ((r->ctag&0x7F)<<5); } if(r->act_valid & ACL_ACT_VALID_STAG) { tmp |= ((r->stag&0xF)<<12); } Write_Reg(P1REG_ACL_TABLE_DATA_E1, tmp); //E2 tmp = 0; if(r->act_valid & ACL_ACT_VALID_STAG) { tmp |= ((r->stag&0x70)>>4); } if(r->act_valid & ACL_ACT_VALID_PRI) { tmp |= ((BIT(3)|(r->pri&0x7))<<3); } if(r->act_valid & ACL_ACT_VALID_STORM) { if(is_link) tmp2 |= (BIT(r->storm-1)<<1); else tmp |= (BIT(r->storm-1)<<7); } if(r->act_valid & ACL_ACT_VALID_CPU) { if(is_link) tmp2 |= BIT(0); else tmp |= BIT(10); } if(r->act_valid & ACL_ACT_VALID_MIB_COUNTER) { tmp |= ((BIT(1)|((r->mib_counter-1)&0x1))<<11); } if(r->act_valid & ACL_ACT_VALID_PTP) { tmp |= BIT(13); } if(r->act_valid & ACL_ACT_VALID_SFLOW) { tmp |= BIT(14); } tmp |= BIT(15); Write_Reg(P1REG_ACL_TABLE_DATA_E2, tmp); Write_Reg(P1REG_ACL_TABLE_DATA_E3, tmp2); Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0); Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0); if(is_link) { tmp = ((ACL_SELECT_MODE_0001<<6) | (ACL_LINK_TYPE_11<<4)); Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); } else { Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|index|(block<<5)); } return 0; } int acl_write_table_a3(int block, int index, int is_link, struct acl_rule *r) { u16 tmp = 0; IP2Page(1); //E1 if(r->act_valid & ACL_ACT_VALID_REDIR) { tmp |= ((r->redir)&0x1F); } if(r->act_valid & ACL_ACT_VALID_CTAG) { tmp |= ((r->ctag&0x7F)<<5); } if(r->act_valid & ACL_ACT_VALID_STAG) { tmp |= ((r->stag&0xF)<<12); } Write_Reg(P1REG_ACL_TABLE_DATA_E1, tmp); //E2 tmp = 0; if(r->act_valid & ACL_ACT_VALID_STAG) { tmp |= ((r->stag&0x70)>>4); } if(r->act_valid & ACL_ACT_VALID_PRI) { tmp |= ((BIT(3)|(r->pri&0x7))<<3); } if(r->act_valid & ACL_ACT_VALID_DSCP) { tmp |= ((BIT(3)|(r->a_dscp&0x7))<<7); } if(r->act_valid & ACL_ACT_VALID_MIB_COUNTER) { tmp |= ((BIT(1)|(r->mib_counter&0x1))<<11); } if(r->act_valid & ACL_ACT_VALID_PTP) { tmp |= BIT(13); } if(r->act_valid & ACL_ACT_VALID_SFLOW) { tmp |= BIT(14); } if(r->act_valid & ACL_ACT_VALID_SNIFFER) { tmp |= BIT(15); } Write_Reg(P1REG_ACL_TABLE_DATA_E2, tmp); //E3 tmp = 0; if(r->act_valid & ACL_ACT_VALID_CPU) { tmp |= BIT(0); } if(r->act_valid & ACL_ACT_VALID_STORM) { tmp |= (BIT(r->storm-1)<<1); } if(r->act_valid & ACL_ACT_VALID_BW) { tmp |= ((BIT(2)|(r->bw&0x3))<<4); } Write_Reg(P1REG_ACL_TABLE_DATA_E3, tmp); //E4 Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0); //E5 Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0); //E6 Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0); //E7 Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0); //E8 Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0); //E9 Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0); //EA Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0); tmp = ((ACL_SELECT_MODE_0001<<6) | (ACL_LINK_TYPE_11<<4)); Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp); Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5)); return 0; } int switchdSetAclRule(struct AclRuleSetting *ars) { struct acl_rule *r = &ars ->rule; unsigned long rule_v = r->rule_valid; int s_mode = 0, s_num = 0, flag = 0, i = 0, block = 0, index = 0, link = 0; struct acl_man_rule *mr; int ret = 0; int find_idx_blockn; int find_idx_rvs; ip1811drv_dbg(" switchdSetAclRule(): ars ->rule_index = %i\n", ars ->rule_index); // check index list_for_each_entry(mr, &m_acl ->rule_list, rule_entry) { if(mr->rule_index == ars ->rule_index) { if((mr->func_used) & (ars->func_used)) { for(i = mr->start_index; i<(mr->start_index+mr->num_entries); i++) { block = mr->start_block; index = i&0xF; acl_clean_table(block, index); m_acl ->used_entry_mask[block] &= ~BIT(i&0xF); m_acl ->num_used_entries--; } m_acl ->num_used_rules--; flag = 1; break; } } } if(!flag) { mr = NULL; } if(rule_v==0) { ars->rule_index_res=0; ars->reserved=0; m_acl->num_used_rules++; if(mr!=NULL) { list_del(&mr->rule_entry); kfree(mr); } return 0; } // selection logic if((rule_v & ACL_RULE_VALID_SIP6) || (rule_v & ACL_RULE_VALID_DIP6)) { if(rule_v & ACL_RULE_VALID_SIP6) { // 0110 s_mode |= ACL_SELECT_MODE_BIT_0110; s_num += 1; } if(rule_v & ACL_RULE_VALID_DIP6) { // 0111 s_mode |= ACL_SELECT_MODE_BIT_0111; s_num += 1; } if((rule_v & ACL_RULE_VALID_SP_R) || (rule_v & ACL_RULE_VALID_DP_R)) { // 0101 s_mode |= ACL_SELECT_MODE_BIT_0101; s_num += 1; } goto out_select_logic; } else if(rule_v & ACL_RULE_VALID_USERDEF_OFFSET) { //0010 s_mode=ACL_SELECT_MODE_BIT_0010; s_num=1; goto out_select_logic; } if((rule_v & ACL_RULE_VALID_SP_R) || (rule_v & ACL_RULE_VALID_DP_R)) { if(rule_v & ACL_RULE_VALID_DIP) { // 0101 s_mode |= ACL_SELECT_MODE_BIT_0101; s_num += 1; if( (rule_v & ACL_RULE_VALID_SIP) || (rule_v & ACL_RULE_VALID_DMAC) || (rule_v & ACL_RULE_VALID_SMAC) || (rule_v & ACL_RULE_VALID_ETH_TYPE) || (rule_v & ACL_RULE_VALID_DSCP) || (rule_v & ACL_RULE_VALID_IP_PROT) ) { if(rule_v & ACL_RULE_VALID_DMAC) { // 1x10 s_mode |= ACL_SELECT_MODE_BIT_1x10; s_num += 1; if(rule_v & ACL_RULE_VALID_SMAC) { // 1x00 s_mode |= ACL_SELECT_MODE_BIT_1x00; s_num += 1; } } else { // 1x00 s_mode |= ACL_SELECT_MODE_BIT_1x00; s_num += 1; } } } else { // 0100 s_mode |= ACL_SELECT_MODE_BIT_0100; s_num += 1; if( (rule_v & ACL_RULE_VALID_DMAC) || (rule_v & ACL_RULE_VALID_SMAC) || (rule_v & ACL_RULE_VALID_ETH_TYPE) || (rule_v & ACL_RULE_VALID_DSCP) || (rule_v & ACL_RULE_VALID_IP_PROT) ) { if(rule_v & ACL_RULE_VALID_DMAC) { // 1x10 s_mode |= ACL_SELECT_MODE_BIT_1x10; s_num += 1; if(rule_v & ACL_RULE_VALID_SMAC) { // 1x00 s_mode |= ACL_SELECT_MODE_BIT_1x00; s_num += 1; } } else { // 1x00 s_mode |= ACL_SELECT_MODE_BIT_1x00; s_num += 1; } } } } else { if(rule_v & ACL_RULE_VALID_DIP) { if(rule_v & ACL_RULE_VALID_DMAC) { // 1x11 s_mode |= ACL_SELECT_MODE_BIT_1x11; s_num += 1; if((rule_v & ACL_RULE_VALID_SMAC) || (rule_v & ACL_RULE_VALID_SIP)) { // 1x00 s_mode |= ACL_SELECT_MODE_BIT_1x00; s_num += 1; } } else { // 1x01 s_mode |= ACL_SELECT_MODE_BIT_1x01; s_num += 1; if(rule_v & ACL_RULE_VALID_SIP) { // 1x00 s_mode |= ACL_SELECT_MODE_BIT_1x00; s_num += 1; } } } else { if(rule_v & ACL_RULE_VALID_DMAC) { // 1x10 s_mode |= ACL_SELECT_MODE_BIT_1x10; s_num += 1; if(rule_v & ACL_RULE_VALID_SMAC) { // 1x00 s_mode |= ACL_SELECT_MODE_BIT_1x00; s_num += 1; } } else { // 1x00 s_mode |= ACL_SELECT_MODE_BIT_1x00; s_num += 1; } } } out_select_logic: ip1811drv_dbg(" s_mode = %02x, s_num = %i\n", s_mode, s_num); if((r->act_type==ACL_ACT_TYPE_3) || (s_num>=2)) { s_num++; } find_idx_blockn = ars->find_index_blockn; find_idx_rvs = ars->find_index_rvs; ret = acl_find_index(s_num, &block, &index, find_idx_blockn, find_idx_rvs); if(ret < 0) { // if acl_find_index return <0, remap acl rule index and find index again set_rule_index_remap(); ret = acl_find_index(s_num, &block, &index, find_idx_blockn, find_idx_rvs); } if(ret < 0) { if(mr != NULL) { list_del(&mr->rule_entry); kfree(mr); } ars ->rule_index_res = -2; ars ->reserved = s_num; return 0; //return -ENOMEM; } ip1811drv_dbg(" block, index = %i, %i\n", block, index); ars->find_index_blockn = block; if(mr == NULL) { mr = kmalloc(sizeof(struct acl_man_rule), GFP_KERNEL); if(mr == NULL) { ip1811drv_err("Error: switchdSetAclRule() acl_man_rule malloc failed.\n"); return -ENOMEM; } list_add_tail(&mr->rule_entry, &m_acl ->rule_list); } mr->start_block = block; mr->start_index = index; mr->num_entries = s_num; mr->rule_index = ars ->rule_index; mr->func_used = ars ->func_used; if(s_num == 1) { link = ACL_LINK_TYPE_00; // write rule table for(i=2; i<12; i++) { if(s_mode & BIT(i)) { acl_write_table_rule[i-1](block, index, link, r); s_num--; break; } } // write action table acl_write_table_act[r->act_type](block, index, s_num, r); } else { link = ACL_LINK_TYPE_01; // write rule table for(i=2; i<12; i++) { if(s_mode & BIT(i)) { acl_write_table_rule[i-1](block, index, link, r); index++; s_num--; if(s_num == 1) { break; } else { link = ACL_LINK_TYPE_10; } } } // write action table //acl_write_table_act[r->act_type](block, index, s_num, r); acl_write_table_act[3](block, index, s_num, r); } for(i=0; inum_entries; i++) { m_acl ->used_entry_mask[mr->start_block] |= BIT((i+mr->start_index)&0xF); m_acl ->num_used_entries++; } m_acl ->num_used_rules++; ars ->rule_index_res = 0; ars ->reserved = mr->num_entries; return 0; } EXPORT_SYMBOL(switchdSetAclRule); int setAclRule(void *cdata, int len) { int ret; struct AclRuleSetting *ars = (struct AclRuleSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct AclRuleSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ret = switchdSetAclRule(ars); FUNC_MSG_OUT; return ret; } int getAclRule(void *cdata, int len) { return 0; } int switchdAclCleanTable(int rule_index, int func_used) { int i = 0; struct acl_man_rule *mr, *nmr; int block, index; if ((rule_index<1 || rule_index>64) && (rule_index!=128)) { ip1811drv_err("Error: rule index=%d\n", rule_index); return -EINVAL; } ip1811drv_dbg(" aclCleanTable()\n"); if(rule_index == 128) { ip1811drv_dbg(" aclCleanTable() 111111\n"); if(list_empty(&m_acl ->rule_list)) { ip1811drv_dbg(" aclCleanTable() 222222\n"); return 0; } list_for_each_entry_safe(mr, nmr, &m_acl ->rule_list, rule_entry) { for(i=0; inum_entries; i++) { block = mr->start_block; index = mr->start_index; acl_clean_table(block, index+i); m_acl ->used_entry_mask[block] &= ~BIT((index+i)&0xF); m_acl ->num_used_entries--; } m_acl ->num_used_rules--; list_del(&mr->rule_entry); kfree(mr); } INIT_LIST_HEAD(&m_acl ->rule_list); if((m_acl ->num_used_rules!=0) || (m_acl ->num_used_entries!=0)) ip1811drv_err(" aclCleanTable something error!\n"); } else { list_for_each_entry(mr, &m_acl ->rule_list, rule_entry) { if(mr->rule_index == rule_index) { if((mr->func_used) & func_used) { for(i=0; inum_entries; i++) { block = mr->start_block; index = mr->start_index; acl_clean_table(block, index+i); m_acl ->used_entry_mask[block] &= ~BIT((index+i)&0xF); m_acl ->num_used_entries--; } m_acl ->num_used_rules--; list_del(&mr->rule_entry); kfree(mr); break; } } } } return 0; } EXPORT_SYMBOL(switchdAclCleanTable); int aclCleanTable(void *cdata, int len) { int ret, rule_index, func_used; struct AclTableCleanSetting *atcs = (struct AclTableCleanSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct AclTableCleanSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } rule_index = atcs ->rule_idx; func_used = atcs ->func_used; ret = switchdAclCleanTable(rule_index, func_used); FUNC_MSG_OUT; return ret; } int switchdSetAclFunctionEn(int enable) { if ((enable!=OP_FUNC_ENABLE) && (enable!=OP_FUNC_DISABLE)) { ip1811drv_err("Error: value=%d\n", enable); return -EINVAL; } _WriteRegBits(1, P1REG_MISCCFG, 0, 1, enable); return 0; } EXPORT_SYMBOL(switchdSetAclFunctionEn); int setAclFunctionEn(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; int func_en; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } func_en = gs ->gdata; ret = switchdSetAclFunctionEn(func_en); FUNC_MSG_OUT; return ret; } int switchdGetAclFunctionEn(int *gdata_p) { *gdata_p = _ReadRegBits(1, P1REG_MISCCFG, 0, 1); return 0; } EXPORT_SYMBOL(switchdGetAclFunctionEn); int getAclFunctionEn(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ret = switchdGetAclFunctionEn(&(gs ->gdata)); FUNC_MSG_OUT; return ret; } int switchdSetAclEtherAfterTag(int is_after_tag) { if ((is_after_tag!=OP_FUNC_ENABLE) && (is_after_tag!=OP_FUNC_DISABLE)) { ip1811drv_err("Error: value=%d\n", is_after_tag); return -EINVAL; } _WriteRegBits(1, P1REG_MISCCFG, 1, 1, is_after_tag); return 0; } EXPORT_SYMBOL(switchdSetAclEtherAfterTag); int setAclEtherAfterTag(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; int loca_v; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } loca_v = gs ->gdata; ret = switchdSetAclEtherAfterTag(loca_v); FUNC_MSG_OUT; return ret; } int switchdGetAclEtherAfterTag(int *gdata_p) { *gdata_p = _ReadRegBits(1, P1REG_MISCCFG, 1, 1); return 0; } EXPORT_SYMBOL(switchdGetAclEtherAfterTag); int getAclEtherAfterTag(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ret = switchdGetAclEtherAfterTag(&(gs ->gdata)); FUNC_MSG_OUT; return ret; } int switchdGetAclUsedRules(int *gdata_p) { *gdata_p = m_acl ->num_used_rules; return 0; } EXPORT_SYMBOL(switchdGetAclUsedRules); int getAclUsedRules(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ret = switchdGetAclUsedRules(&(gs ->gdata)); FUNC_MSG_OUT; return ret; } int switchdGetAclUsedEntries(int *gdata_p) { *gdata_p = m_acl ->num_used_entries; return 0; } EXPORT_SYMBOL(switchdGetAclUsedEntries); int getAclUsedEntries(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ret = switchdGetAclUsedEntries(&(gs ->gdata)); FUNC_MSG_OUT; return ret; } int switchdGetAclUsedEntryMask(unsigned short *gmask_p) { memcpy(gmask_p, m_acl->used_entry_mask, 4*sizeof(unsigned short)); return 0; } EXPORT_SYMBOL(switchdGetAclUsedEntryMask); int getAclUsedEntryMask(void *cdata, int len) { int ret; struct AclEntryMaskGetting *aemg = (struct AclEntryMaskGetting *)cdata; FUNC_MSG_IN; if (sizeof(struct AclEntryMaskGetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ret = switchdGetAclUsedEntryMask(aemg ->mask); FUNC_MSG_OUT; return ret; } int switchdSetAclBW(int index, int in_rate) { u16 rate = 0; if (index<0 || index>3) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } if (in_rate<0 || in_rate>2540) { ip1811drv_err("Error: rate=%d\n", in_rate); return -EINVAL; } if(in_rate > 163) { rate |= BIT(7); rate |= (in_rate*100/2000); if(in_rate*100%2000) rate++; } else { rate = (in_rate*100/128); if(in_rate*100%128) rate++; } ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("value=0x%x\n", rate); // set 4 block _WriteRegBits(1, P1REG_ACL_BW_01+(index/2)+0, 8*(index%2), 8, rate); _WriteRegBits(1, P1REG_ACL_BW_01+(index/2)+2, 8*(index%2), 8, rate); _WriteRegBits(1, P1REG_ACL_BW_01+(index/2)+4, 8*(index%2), 8, rate); _WriteRegBits(1, P1REG_ACL_BW_01+(index/2)+6, 8*(index%2), 8, rate); return 0; } EXPORT_SYMBOL(switchdSetAclBW); int setAclBW(void *cdata, int len) { int ret; struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata; int bw_index; int bw_v; FUNC_MSG_IN; if (sizeof(struct AclGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } bw_index = ags ->index; bw_v = ags ->data; ret = switchdSetAclBW(bw_index, bw_v); FUNC_MSG_OUT; return ret; } int switchdGetAclBW(int index, int *gdata_p) { u16 tmp = 0; u32 c_rate; if (index<0 || index>3) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } tmp = _ReadRegBits(1, P1REG_ACL_BW_01+(index/2), (8*(index%2)), 8); if(tmp&BIT(7)) { c_rate = (tmp&(0x7F))*2000; } else { c_rate = (tmp&(0x7F))*128; } *gdata_p = c_rate/100; return 0; } EXPORT_SYMBOL(switchdGetAclBW); int getAclBW(void *cdata, int len) { int ret; struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata; int bw_index; FUNC_MSG_IN; if (sizeof(struct AclGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } bw_index = ags ->index; ret = switchdGetAclBW(bw_index, &(ags ->data)); ip1811drv_dbg("cdata ->data=%d\n", ags ->data); FUNC_MSG_OUT; return ret; } int switchdSetAclDscp(int index, int value) { if (index<0 || index>7) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } if (value & (~0x3F)) { ip1811drv_err("Error: value=%x\n", value); return -EINVAL; } ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("value=0x%x\n", value); _WriteRegBits(7, P7REG_DSCP_REMARKING_01+(index/2), 8*(index%2), 8, value); return 0; } EXPORT_SYMBOL(switchdSetAclDscp); int setAclDscp(void *cdata, int len) { int ret; struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata; int dscp_index; int dscp_v; FUNC_MSG_IN; if (sizeof(struct AclGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } dscp_index = ags ->index; dscp_v = ags ->data; ret = switchdSetAclDscp(dscp_index, dscp_v); FUNC_MSG_OUT; return ret; } int switchdGetAclDscp(int index, int *gdata_p) { if (index<0 || index>7) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } *gdata_p = _ReadRegBits(7, P7REG_DSCP_REMARKING_01+(index/2), (8*(index%2)), 8); return 0; } EXPORT_SYMBOL(switchdGetAclDscp); int getAclDscp(void *cdata, int len) { int ret; struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata; int dscp_index; FUNC_MSG_IN; if (sizeof(struct AclGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } dscp_index = ags ->index; ret = switchdGetAclDscp(dscp_index, &(ags ->data)); ip1811drv_dbg("cdata ->data=%d\n", ags ->data); FUNC_MSG_OUT; return ret; } int switchdSetAclVidRemark(int index, int value) { if (index<0 || index>15) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } if (value & (~0x7FFF)) { ip1811drv_err("Error: value=%x\n", value); return -EINVAL; } ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("value=0x%x\n", value); _WriteRegBits(2, P2REG_ACL_VID_REMARK_00+index, 0, 15, value); return 0; } EXPORT_SYMBOL(switchdSetAclVidRemark); int setAclVidRemark(void *cdata, int len) { int ret; struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata; int vid_index; int vid_v; FUNC_MSG_IN; if (sizeof(struct AclGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } vid_index = ags ->index; vid_v = ags ->data; ret = switchdSetAclVidRemark(vid_index, vid_v); FUNC_MSG_OUT; return ret; } int switchdGetAclVidRemark(int index, int *gdata_p) { if (index<0 || index>15) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } *gdata_p = _ReadRegBits(2, P2REG_ACL_VID_REMARK_00+index, 0, 15); return 0; } EXPORT_SYMBOL(switchdGetAclVidRemark); int getAclVidRemark(void *cdata, int len) { int ret; struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata; int vid_index; FUNC_MSG_IN; if (sizeof(struct AclGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } vid_index = ags ->index; ret = switchdGetAclVidRemark(vid_index, &(ags ->data)); ip1811drv_dbg("cdata ->data=%d\n", ags ->data); FUNC_MSG_OUT; return ret; } int acl_write_table_move(int from_block, int from_index, int to_block, int to_index) { int i; u16 u16array[10]; u16 u16dat; IP2Page(1); // rule Write_Reg(P1REG_ACL_TABLE_ACCESS, 0x8000|from_index|((from_block&0x3)<<5)); for(i=0; i<10; i++) { u16dat = Read_Reg(P1REG_ACL_TABLE_DATA_E1+i); u16array[i] = u16dat; } acl_clean_table_rule(from_block, from_index); for(i=0; i<10; i++) { Write_Reg(P1REG_ACL_TABLE_DATA_E1+i, u16array[i]); } Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|to_index|((to_block&0x3)<<5)); // act Write_Reg(P1REG_ACL_TABLE_ACCESS, 0x8100|from_index|((from_block&0x3)<<5)); for(i=0; i<10; i++) { u16dat = Read_Reg(P1REG_ACL_TABLE_DATA_E1+i); u16array[i] = u16dat; } acl_clean_table_act(from_block, from_index); for(i=0; i<10; i++) { Write_Reg(P1REG_ACL_TABLE_DATA_E1+i, u16array[i]); } Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|to_index|((to_block&0x3)<<5)); m_acl ->used_entry_mask[to_block] |= BIT(to_index); m_acl ->used_entry_mask[from_block] &= ~BIT(from_index); return 0; } int set_rule_index_remap(void) { int i, j; int index_move_to; int block_move_to; int index_move_from; int block_move_from; int index_move_range; struct acl_man_rule *mr; ip1811drv_dbg(" set_rule_index_remap()\n"); for(i=0; i<64; i++) { if(m_acl ->used_entry_mask[i>>4] & BIT(i%16)) { // entry i rule exist } else { // entry i rule not exist int no_entry = 1; block_move_to = (i>>4)&0x3; index_move_to = i&0xF; block_move_from = 3; index_move_from = 16; index_move_range= 0; // scan closest entry list_for_each_entry(mr, &m_acl ->rule_list, rule_entry) { if(mr->func_used != ACL_RULE_FUNC_USED_SNOOP) { if((16*mr->start_block+mr->start_index)>i) { if(((16*mr->start_block+mr->start_index)<(block_move_from*16+index_move_from)) && (mr->num_entries<=(16-index_move_to))) { block_move_from = mr->start_block; index_move_from = mr->start_index; index_move_range = mr->num_entries; no_entry = 0; } } } } if(no_entry) continue; // move exist entry to empty rule index for(j=0; jrule_list, rule_entry) { if((mr->start_block==block_move_from) && (mr->start_index==index_move_from)) { mr->start_block = block_move_to; mr->start_index = index_move_to; } } // assign i to be link entry end i += (index_move_range-1); } ip1811drv_dbg(" set_rule_index_remap(): entry from block(%d)/index(%d) to block(%d)/index(%d)\n", block_move_from, index_move_from, block_move_to, index_move_to); } return 0; } int switchdSetAclStormPeriod(int period) { if (period& (~0x3)) { ip1811drv_err("Error: period=0x%x\n", period); return -EINVAL; } ip1811drv_dbg("clear period=0x%x\n", period); _WriteRegBits(1, P1REG_MISCCFG, 4, 2, period); return 0; } EXPORT_SYMBOL(switchdSetAclStormPeriod); int setAclStormPeriod(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; int period; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } period = gs ->gdata; ret = switchdSetAclStormPeriod(period); FUNC_MSG_OUT; return ret; } int switchdGetAclStormPeriod(int *gdata_p) { *gdata_p = _ReadRegBits(1, P1REG_MISCCFG, 4, 2); return 0; } EXPORT_SYMBOL(switchdGetAclStormPeriod); int getAclStormPeriod(void *cdata, int len) { int ret; struct GeneralSetting *gs = (struct GeneralSetting *)cdata; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } ret = switchdGetAclStormPeriod(&(gs ->gdata)); ip1811drv_dbg("cdata ->gdata=%d\n", gs ->gdata); FUNC_MSG_OUT; return ret; } int switchdSetAclStorm(int index, int value) { if (index<0 || index>2) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } if (value & (~0xFFFF)) { ip1811drv_err("Error: value=%x\n", value); return -EINVAL; } _WriteRegBits(1, P1REG_MISCCFG, 13, 1, 1); ip1811drv_dbg("index=%d\n", index); ip1811drv_dbg("value=0x%x\n", value); _WriteRegBits(1, P1REG_ACL_STORM_0+index, 0, 16, value); _WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0); return 0; } EXPORT_SYMBOL(switchdSetAclStorm); int setAclStorm(void *cdata, int len) { int ret; struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata; int storm_index; int storm_v; FUNC_MSG_IN; if (sizeof(struct AclGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } storm_index = ags ->index; storm_v = ags ->data; ret = switchdSetAclStorm(storm_index, storm_v); FUNC_MSG_OUT; return ret; } int switchdGetAclStorm(int index, int *gdata_p) { if (index<0 || index>2) { ip1811drv_err("Error: index=%d\n", index); return -EINVAL; } _WriteRegBits(1, P1REG_MISCCFG, 13, 1, 1); *gdata_p = _ReadRegBits(1, P1REG_ACL_STORM_0+index, 0, 16); _WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0); return 0; } EXPORT_SYMBOL(switchdGetAclStorm); int getAclStorm(void *cdata, int len) { int ret; struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata; int storm_index; FUNC_MSG_IN; if (sizeof(struct AclGeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } storm_index = ags ->index; ret = switchdGetAclStorm(storm_index, &(ags ->data)); ip1811drv_dbg("cdata ->data=%d\n", ags ->data); FUNC_MSG_OUT; return ret; } //------------ ACL functions:common end ----------------------- //------------------------------------------------ //common_bandwidth int switchdSetBandwidthIngressRate(int port, unsigned long rate) { if (port < 0 || port >= MAX_PHY_NUM) { ip1811drv_err("Error: port=%d\n", port); return -EINVAL; } if (rate > MAX_GIGA_SPEED) { ip1811drv_err("Error: pdata=0x%08X\n", (u16)rate); return -EINVAL; } IP2Page(0); if (rate == 0 || rate == MAX_GIGA_SPEED || (port < MAX_PHY_TP_NUM && rate >= MAX_TP_SPEED)) { Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,0); } else if(rate > 0 && rate < MAX_GIGA_SPEED) { if(port < MAX_PHY_TP_NUM && rate >= (MAX_TP_SPEED/RATE_SCALE_UNIT)*RATE_SCALE_UNIT) { Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,0); } else if(rate >= (MAX_GIGA_SPEED/RATE_SCALE_UNIT)*RATE_SCALE_UNIT) { Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,0); #ifdef COMBINED_PORT if (port==9) Write_Reg(P0REG_INGRESS_RATE_CTRL0+port+1,0); #endif } else { if(rate%RATE_SCALE_UNIT) { Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,rate/RATE_SCALE_UNIT+1); #ifdef COMBINED_PORT if (port==9) Write_Reg(P0REG_INGRESS_RATE_CTRL0+port+1,rate/RATE_SCALE_UNIT+1); #endif } else { Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,rate/RATE_SCALE_UNIT); #ifdef COMBINED_PORT if (port==9) Write_Reg(P0REG_INGRESS_RATE_CTRL0+port+1,rate/RATE_SCALE_UNIT); #endif } } } return 0; } EXPORT_SYMBOL(switchdSetBandwidthIngressRate); int setBandwidthIngressRate(void *cdata, int len) { int port; //1-28 unsigned long rate; FUNC_MSG_IN; if (sizeof(struct ByPortSetting32) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } port = ((struct ByPortSetting32 *)cdata)->port; rate = ((struct ByPortSetting32 *)cdata)->pdata; if(switchdSetBandwidthIngressRate(port, rate) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdGetBandwidthIngressRate(int port, unsigned long *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM){ ip1811drv_err("Error: port=%d\n", port); return -EINVAL; } ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (unsigned long)(_ReadRegBits(0, P0REG_INGRESS_RATE_CTRL0+port, 0, 14)*64000); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetBandwidthIngressRate); int getBandwidthIngressRate(void *cdata, int len) { int port; unsigned long rate; FUNC_MSG_IN; if (sizeof(struct ByPortSetting32) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } port = ((struct ByPortSetting32 *)cdata)->port; if(switchdGetBandwidthIngressRate(port, &rate) != 0) return -EINVAL; ((struct ByPortSetting32 *)cdata)->pdata = rate; ip1811drv_dbg("cdata->port=%d\n", ((struct ByPortSetting32 *)cdata)->port); ip1811drv_dbg("cdata->pdata=0x%08X\n", (u16)((struct ByPortSetting32 *)cdata)->pdata); FUNC_MSG_OUT; return 0; } int switchdSetBandwidthEgressRate(int port, unsigned long rate) { if (port < 0 || port >= MAX_PHY_NUM) { ip1811drv_err("Error: port=%d\n", port); return -EINVAL; } if (rate > MAX_GIGA_SPEED) { ip1811drv_err("Error: pdata=0x%08X\n", (u16)rate); return -EINVAL; } IP2Page(8); if (rate == 0 || rate == MAX_GIGA_SPEED || (port < MAX_PHY_TP_NUM && rate >= MAX_TP_SPEED)) { Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,0); } else if(rate > 0 && rate < MAX_GIGA_SPEED) { if(port < MAX_PHY_TP_NUM && rate >= (MAX_TP_SPEED/RATE_SCALE_UNIT)*RATE_SCALE_UNIT) { Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,0); } else if(rate >= (MAX_GIGA_SPEED/RATE_SCALE_UNIT)*RATE_SCALE_UNIT) { Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,0); #ifdef COMBINED_PORT if (port==9) Write_Reg(P8REG_EGRESS_RATE_CTRL0+port+1,0); #endif } else { if(rate%RATE_SCALE_UNIT) { Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,rate/RATE_SCALE_UNIT+1); #ifdef COMBINED_PORT if (port==9) Write_Reg(P8REG_EGRESS_RATE_CTRL0+port+1,rate/RATE_SCALE_UNIT+1); #endif } else { Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,rate/RATE_SCALE_UNIT); #ifdef COMBINED_PORT if (port==9) Write_Reg(P8REG_EGRESS_RATE_CTRL0+port+1,rate/RATE_SCALE_UNIT+1); #endif } } } return 0; } EXPORT_SYMBOL(switchdSetBandwidthEgressRate); int setBandwidthEgressRate(void *cdata, int len) { int port; unsigned long rate; FUNC_MSG_IN; if (sizeof(struct ByPortSetting32) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } port = ((struct ByPortSetting32 *)cdata)->port; rate = ((struct ByPortSetting32 *)cdata)->pdata; if(switchdSetBandwidthEgressRate(port, rate) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdGetBandwidthEgressRate(int port, unsigned long *ptrInt) { if (port < 0 || port >= MAX_PHY_NUM){ ip1811drv_err("Error: port=%d\n", port); return -EINVAL; } ip1811drv_dbg("port=%d\n", port); #ifdef COMBINED_PORT if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link port++; #endif *ptrInt = (unsigned long)(_ReadRegBits(8, P8REG_EGRESS_RATE_CTRL0+port, 0, 14)*64000); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetBandwidthEgressRate); int getBandwidthEgressRate(void *cdata, int len) { int port; unsigned long rate; FUNC_MSG_IN; if (sizeof(struct ByPortSetting32) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } port = ((struct ByPortSetting32 *)cdata)->port; if(switchdGetBandwidthEgressRate(port, &rate) != 0) return -EINVAL; ((struct ByPortSetting32 *)cdata)->pdata = rate; ip1811drv_dbg("cdata->port=%d\n", ((struct ByPortSetting32 *)cdata)->port); ip1811drv_dbg("cdata->pdata=0x%08X\n", (u16)((struct ByPortSetting32 *)cdata)->pdata); FUNC_MSG_OUT; return 0; } int switchdSetBandwidthEgressPeriod(int period) { if (period < 0 || period > 7){ ip1811drv_err("Error: gdata=%d\n", period); return -EINVAL; } _WriteRegBits(8, P8REG_OUT_QUEUE_PARAM, 4, 3, period); return 0; } EXPORT_SYMBOL(switchdSetBandwidthEgressPeriod); int setBandwidthEgressPeriod(void *cdata, int len) { int period; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len) { ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } period = ((struct GeneralSetting *)cdata)->gdata; if(switchdSetBandwidthEgressPeriod(period) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } int switchdGetBandwidthEgressPeriod(int *ptrInt) { *ptrInt = (int)_ReadRegBits(8,P8REG_OUT_QUEUE_PARAM,4,3); ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt); return 0; } EXPORT_SYMBOL(switchdGetBandwidthEgressPeriod); int getBandwidthEgressPeriod(void *cdata, int len) { int period=0; FUNC_MSG_IN; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } if(switchdGetBandwidthEgressPeriod(&period) != 0) return -EINVAL; ((struct GeneralSetting *)cdata)->gdata = period; ip1811drv_dbg("cdata->gdata=0x%08X\n", ((struct GeneralSetting *)cdata)->gdata); FUNC_MSG_OUT; return 0; } //------------ EEPROM functions:common start ----------------- #define CMD_EEPROM_READ 0x8000 #define CMD_EEPROM_WRITE 0xC000 #define EEPROM_BIT_COMPLETE 0x8000 #define REG_RETRY_COUNT 200 u8 EE_Type = OP_EE_TYPE_Unknow; u8 EE_Data [OP_EEPROM_LEN_24C32] = {0x0}; u8 EE_Flag [OP_EEPROM_LEN_24C32] = {0x0}; u8 getEepromType(void) { unsigned short val, i; IP2Page(0xE); Write_Reg(PEREG_EEPROM_CMD+1, (unsigned short)(Read_Reg(PEREG_EEPROM_CMD+1)&0xFF00)); IP2Page(0xE); Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_READ + 0x1)); IP2Page(0xE); val = Read_Reg(PEREG_EEPROM_CMD); for(i = 0 ; 0 == (val&EEPROM_BIT_COMPLETE) && i < REG_RETRY_COUNT ; i++) { IP2Page(0xE); val = Read_Reg(PEREG_EEPROM_CMD); } if(i == REG_RETRY_COUNT) { ip1811drv_err("Error: get EEPROM type REG_RETRY_COUNT reached\n"); return -EINVAL; } IP2Page(0xE); val = Read_Reg(PEREG_EEPROM_DATA) & 0xFF; udelay(5000); if(val == 0x0B) return OP_EE_TYPE_C16; else if(val == 0x0D) return OP_EE_TYPE_C32; else return OP_EE_TYPE_Unknow; } // EEPROM READ/WRITE int setEepromByte(void *cdata, int len) { unsigned short addr2write, i, val; unsigned char val2write; FUNC_MSG_IN; if (sizeof(struct EepromSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } if(EE_Type==OP_EE_TYPE_Unknow) { EE_Type = getEepromType(); if(EE_Type==OP_EE_TYPE_Unknow) { ip1811drv_err("Error: setEEPROM get type failed\n"); return -EINVAL; } ip1811drv_dbg("set EEPROM type->%X\n", EE_Type); } addr2write = ((struct EepromSetting *)cdata)->addr; val2write = ((struct EepromSetting *)cdata)->value; if (addr2write > (EE_Type?OP_EEPROM_LEN_24C32:OP_EEPROM_LEN_24C16)) { ip1811drv_err("Error: addr=0x%04X\n", addr2write); return -EINVAL; } ip1811drv_dbg("type %X set addr:%04X , value:%02X\n", EE_Type, addr2write, val2write); // update eeprom hardware IP2Page(0xE); Write_Reg(PEREG_EEPROM_DATA, val2write); IP2Page(0xE); if(EE_Type==OP_EE_TYPE_C16) { Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_WRITE + addr2write)); } else { Write_Reg(PEREG_EEPROM_CMD+1, (unsigned short)((Read_Reg(PEREG_EEPROM_CMD+1)&0xFF00)|((addr2write>>8)&0xFF))); IP2Page(0xE); Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_WRITE + (addr2write&0xFF))); } IP2Page(0xE); val = Read_Reg(PEREG_EEPROM_CMD); for(i = 0 ; 0 == (val&EEPROM_BIT_COMPLETE) && i < REG_RETRY_COUNT ; i++) { IP2Page(0xE); val = Read_Reg(PEREG_EEPROM_CMD); } if(i == REG_RETRY_COUNT) { ip1811drv_err("Error: set EEPROM REG_RETRY_COUNT reached %04X\n", addr2write); return -EINVAL; } // udelay(5000); // update eeprom driver mem EE_Flag[addr2write] = 0x1; EE_Data[addr2write] = val2write; ip1811drv_dbg("EE set done\n"); FUNC_MSG_OUT; return 0; } int getEepromByte(void *cdata, int len) { unsigned short addr2read, i, val; unsigned char val2return; FUNC_MSG_IN; if (sizeof(struct EepromSetting) != len) { ip1811drv_err("Error: length=%d\n", len); return -EINVAL; } if(EE_Type==OP_EE_TYPE_Unknow) { EE_Type = getEepromType(); if(EE_Type==OP_EE_TYPE_Unknow) { ip1811drv_err("Error: getEEPROM get type failed\n"); return -EINVAL; } ip1811drv_dbg("set EEPROM type->%X\n", EE_Type); } addr2read = ((struct EepromSetting *)cdata)->addr; if (addr2read > (EE_Type?OP_EEPROM_LEN_24C32:OP_EEPROM_LEN_24C16)) { ip1811drv_err("Error: addr=0x%04X\n", addr2read); return -EINVAL; } ip1811drv_dbg("type %X get addr:%04X\n", EE_Type, addr2read); if(EE_Flag[addr2read]==0x1) // return driver value { val2return = EE_Data[addr2read]; } else // update driver memory { IP2Page(0xE); if(EE_Type==OP_EE_TYPE_C16) { Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_READ + addr2read)); } else { Write_Reg(PEREG_EEPROM_CMD+1, (unsigned short)((Read_Reg(PEREG_EEPROM_CMD+1)&0xFF00)|((addr2read>>8)&0xFF))); IP2Page(0xE); Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_READ + (addr2read & 0xFF))); } IP2Page(0xE); val = Read_Reg(PEREG_EEPROM_CMD); for(i = 0 ; 0 == (val&EEPROM_BIT_COMPLETE) && i < REG_RETRY_COUNT ; i++) { IP2Page(0xE); val = Read_Reg(PEREG_EEPROM_CMD); } if(i == REG_RETRY_COUNT) { ip1811drv_err("Error: get EEPROM REG_RETRY_COUNT reached %04X\n", addr2read); return -EINVAL; } IP2Page(0xE); val2return = Read_Reg(PEREG_EEPROM_DATA) & 0xFF; EE_Flag[addr2read] = 0x1; EE_Data[addr2read] = val2return; // udelay(5000); } ((struct EepromSetting *)cdata)->value = val2return; ip1811drv_dbg("EE get done and value:%04X\n", val2return); FUNC_MSG_OUT; return 0; } //------------ EEPROM functions:common end ----------------- //------------ HSR functions:common Start ----------------------- int setHSREnable(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _setGeneralEnable(cdata, len, 0x02, P2REG_HSR_REG_SETTING_1, 0); FUNC_MSG_OUT; return ret; } int getHSREnable(void *cdata, int len) { int ret; FUNC_MSG_IN; ret = _getGeneralEnable(cdata, len, 0x02, P2REG_HSR_REG_SETTING_1, 0); FUNC_MSG_OUT; return ret; } int switchdSetHSRMode(int mode) { if( mode != OP_HSR_MANDATORY && mode != OP_HSR_UNICAST ){ ip1811drv_err("Error: mode=%X\n", mode); return -EINVAL; } ip1811drv_dbg("cdata ->mode=%d\n", mode); if(mode==OP_HSR_MANDATORY){ _WriteRegBits(2, P2REG_HSR_REG_SETTING_1, 10, 2, 0x3); _WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 8, 1, 0x1); _WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 11, 1, 0x1); _WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 0, 2, 0x0); _WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0x1); IP2Page(0x1); Write_Reg(P1REG_LUTAGINGTIME, 0x0003); _WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0x0); } else if(mode==OP_HSR_UNICAST){ _WriteRegBits(2, P2REG_HSR_REG_SETTING_1, 10, 2, 0x3); _WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 8, 1, 0x1); _WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 11, 1, 0x1); _WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 0, 2, 0x3); _WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0x1); IP2Page(0x1); Write_Reg(P1REG_LUTAGINGTIME, 0x00A3); _WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0x0); } return 0; } EXPORT_SYMBOL(switchdSetHSRMode); int setHSRMode(void *cdata, int len) { int gdata; if (sizeof(struct GeneralSetting) != len){ ip1811drv_err("Error: lengtn=%d\n", len); return -EINVAL; } gdata = ((struct GeneralSetting *)cdata) ->gdata; FUNC_MSG_IN; if(switchdSetHSRMode(gdata) != 0) return -EINVAL; FUNC_MSG_OUT; return 0; } void switchdGetHSRMode(int *ptrInt) { int val; val=(int)_ReadRegBits(2, P2REG_HSR_REG_SETTING_2, 0, 2); if(val==0x3) *ptrInt = OP_HSR_MANDATORY; else if(val==0x0) *ptrInt = OP_HSR_UNICAST; } EXPORT_SYMBOL(switchdGetHSRMode); int getHSRMode(void *cdata, int len) { int ret; ip1811drv_dbg("ip1811: +getHSRMode...\n"); if (sizeof(struct GeneralSetting) != len) return -EINVAL; FUNC_MSG_IN; switchdGetHSRMode(&ret); FUNC_MSG_OUT; ((struct GeneralSetting *)cdata) ->gdata = ret; ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata); ip1811drv_dbg("ip1811: -getHSRMode...\n"); return 0; } //------------ HSR functions:common end ----------------------- void noFunc(void) {}