#include <linux/kernel.h>
|
#include <linux/module.h>
|
#include <linux/errno.h>
|
#include <linux/delay.h>
|
#include <linux/string.h>
|
#include <linux/slab.h>
|
#include <asm/uaccess.h>
|
#include <linux/uaccess.h>
|
#include <linux/fs.h>
|
#include <linux/file.h>
|
#include <asm/io.h>
|
|
#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 <asm/io.h>
|
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<MDIO_DELAY;i++);
|
|
//set MDIO to 1
|
//set MDC to 1
|
ip1811_gpio_set(GPIO_MDIO_OFFSET,1);
|
ip1811_gpio_set(GPIO_MDC_OFFSET,1);
|
|
for(i=0;i<MDIO_DELAY;i++);
|
}
|
|
void mdio_0(void){
|
|
int i;
|
//set MDIO to 0
|
//set MDC to 0
|
ip1811_gpio_set(GPIO_MDIO_OFFSET,0);
|
ip1811_gpio_set(GPIO_MDC_OFFSET,0);
|
|
for(i=0;i<MDIO_DELAY;i++);
|
|
//set MDIO to 0
|
//set MDC to 1
|
ip1811_gpio_set(GPIO_MDIO_OFFSET,0);
|
ip1811_gpio_set(GPIO_MDC_OFFSET,1);
|
|
for(i=0;i<MDIO_DELAY;i++);
|
}
|
|
void mdio_z(void){
|
|
int i;
|
//set MDC to 0
|
ip1811_gpio_set(GPIO_MDC_OFFSET,0);
|
|
for(i=0;i<MDIO_DELAY;i++);
|
//set MDC to 1
|
ip1811_gpio_set(GPIO_MDC_OFFSET,1);
|
|
for(i=0;i<MDIO_DELAY;i++);
|
}
|
|
void mdio_start(void){
|
mdio_0();
|
mdio_1();
|
}
|
|
void mdio_rw(int rw){
|
if(rw==MDIO_RD){
|
mdio_1();
|
mdio_0();
|
}else{
|
mdio_0();
|
mdio_1();
|
}
|
}
|
void mdio_set_MDC_MDIO_direction(unsigned char mdc, unsigned char mdio)//0:input, 1:output for mdc/mdio values
|
{
|
if(mdc) ;
|
if(mdio)
|
ip1811_gpio_direction_out(GPIO_MDIO_OFFSET,0);
|
else
|
ip1811_gpio_direction_in(GPIO_MDIO_OFFSET);
|
}
|
void ic_mdio_wr(unsigned short pa, unsigned short ra, unsigned short va){
|
int i=0;
|
unsigned short data=0;
|
|
//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 direction to output
|
//set MDIO direction to output
|
mdio_set_MDC_MDIO_direction(1,1);
|
|
for(i=0;i<32;i++)
|
mdio_1();
|
mdio_start();
|
mdio_rw(MDIO_WR);
|
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_1();
|
mdio_0();
|
for(i=0;i<16;i++){
|
data=va<<i;
|
data=data>>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<MDIO_DELAY;i++);
|
//get MDIO value
|
regBit=ip1811_gpio_get(GPIO_MDIO_OFFSET);
|
if(regBit==0)
|
{
|
data|=0;
|
debug[15-j]=0;
|
}
|
else
|
{
|
data|=1;
|
debug[15-j]=1;
|
}
|
if(j<15)
|
data=data<<1;
|
//MDC set to 1
|
ip1811_gpio_set(GPIO_MDC_OFFSET,1);
|
|
for(i=0;i<MDIO_DELAY;i++);
|
}
|
//MDC set to 0
|
ip1811_gpio_set(GPIO_MDC_OFFSET,0);
|
|
for(i=0;i<MDIO_DELAY;i++);
|
//MDC set to 1
|
ip1811_gpio_set(GPIO_MDC_OFFSET,1);
|
|
for(i=0;i<MDIO_DELAY;i++);
|
|
return data;
|
}
|
#else//#ifndef ACCESS_REG_BY_MDIO
|
void ic_mdio_wr(unsigned short pa, unsigned short ra, unsigned short va){
|
void __iomem *base;
|
unsigned long val;
|
struct ip218_smictrl0 *smic0;
|
|
FUNC_MSG_IN;
|
|
val = 0;
|
smic0 = (struct ip218_smictrl0 *)&val;
|
smic0 -> 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);
|
u16dat |= (val&mask)<<offset;
|
Write_Reg(reg, u16dat);
|
|
FUNC_MSG_OUT;
|
}
|
|
static u16 _ReadRegBits(u8 page, u16 reg, u8 offset, u8 len)
|
{
|
u16 mask = 0;
|
u16 u16dat;
|
u16 val;
|
|
FUNC_MSG_IN;
|
|
IP2Page(page);
|
mask = (0x1 << len) - 1;
|
u16dat = Read_Reg(reg);
|
val = (u16dat>>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 (method<OP_SNIFFER1_METHOD_DISABLE || method>OP_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;i<MAX_PHY_NUM;i++){
|
if((i%8)==0){
|
cmd=Read_Reg(P9REG_PTP_PORT_TIMESTAMP0+(i/8));
|
}
|
|
if((pts->portmap&(0x01<<i))!=0){
|
if(pts->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;i<MAX_PHY_NUM;i++){
|
if((i%8)==0)
|
cmd=Read_Reg(P9REG_PTP_PORT_TIMESTAMP0+(i/8));
|
|
if(pts->in_out){
|
//egress
|
if((cmd&(0x01<<(1+(2*(i%8)))))!=0)
|
pts->portmap|=(0x01<<i);
|
}
|
else{
|
//ingress
|
if((cmd&(0x01<<(2*(i%8))))!=0)
|
pts->portmap|=(0x01<<i);
|
}
|
}
|
|
return 0;
|
}
|
|
int setPTPTimestampClear(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;i<MAX_PHY_NUM;i++){
|
if((pts->portmap&(0x01<<i))!=0){
|
if(pts->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<MAX_PHY_NUM; i++)
|
{
|
if(!((pm>>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<MAX_PHY_NUM; i++)
|
{
|
_WriteRegBits(7, P7REG_QINQ_P_DATA+i, 12, 1, ((member>>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<MAX_PHY_NUM; i++)
|
{
|
u16dat = Read_Reg(P7REG_QINQ_P_DATA+i);
|
*u32dat |= ((u16dat>>12)&0x1)<<i;
|
}
|
}
|
EXPORT_SYMBOL(switchdGetVlanQinQPKeep);
|
int getVlanQinQPKeep(void *cdata, int len)
|
{
|
u32 member=0;
|
|
FUNC_MSG_IN;
|
if (sizeof(struct PortMemberSetting) != len)
|
return -EINVAL;
|
|
switchdGetVlanQinQPKeep(&member);
|
|
((struct PortMemberSetting *)cdata) ->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<MAX_PHY_NUM; i++)
|
{
|
_WriteRegBits(2, P2REG_VLANGROUP+2*i, 12, 1, (member>>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<MAX_PHY_NUM; i++)
|
{
|
u16dat = Read_Reg(P2REG_VLANGROUP+2*i);
|
*u32dat |= ((u16dat>>12)&0x1)<<i;
|
}
|
}
|
EXPORT_SYMBOL(switchdGetVlanPortForce);
|
int getVlanPortForce(void *cdata, int len)
|
{
|
u32 member=0;
|
|
FUNC_MSG_IN;
|
if (sizeof(struct PortMemberSetting) != len)
|
return -EINVAL;
|
|
switchdGetVlanPortForce(&member);
|
|
((struct PortMemberSetting *)cdata) ->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<<type;
|
regdata &= ~rule_t;
|
regdata |= rule<<type;
|
ip1811drv_dbg("type : %d\n", type);
|
ip1811drv_dbg("rule : %x\n", rule);
|
ip1811drv_dbg("Write IGMPPktForward_0 : %x\n",regdata);
|
Write_Reg(P1REG_IGMPPKTFWD_0, regdata);
|
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;
|
regdata |=rule<<(type-1);
|
ip1811drv_dbg("type : %d\n", type);
|
ip1811drv_dbg("rule : %x\n", rule);
|
ip1811drv_dbg("Write IGMPPktForward_1 : %x\n", regdata);
|
Write_Reg(P1REG_IGMPPKTFWD_1, regdata);
|
break;
|
default:
|
ip1811drv_dbg("Option can't find.\n");
|
return -EINVAL;
|
break;
|
}
|
return 0;
|
}
|
EXPORT_SYMBOL(switchdSetIGMPPktForward);
|
|
int setIGMPPktForward(void *cdata, int len)
|
{
|
int ret;
|
struct IgmpPacketRule *igmp;
|
unsigned int pkt_type;
|
unsigned int pkt_rule;
|
|
FUNC_MSG_IN;
|
ip1811drv_dbg("In setIGMPPktForward.\n");
|
if (sizeof(struct IgmpPacketRule) != len) {
|
ip1811drv_err("length error!\n");
|
return -EINVAL;
|
}
|
igmp = (struct IgmpPacketRule *)cdata;
|
pkt_type = igmp ->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;
|
regdata &= rule_t;
|
*rule_p = regdata>>(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)<<set;
|
tmpbuf[ptr] |= tmpvalue;
|
ip1811drv_dbg("Result:\nbuf[%d] | %x = %x\n", ptr, tmpvalue, tmpbuf[ptr]);
|
if(len>(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<set; i++){
|
mask <<= 1;
|
mask |= 0x01;
|
}
|
tmpvalue = tmpbuf[ptr]&mask;
|
value = tmpvalue;
|
if((len-set)>=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; i++){
|
mask <<= 1;
|
mask |= 0x01;
|
}
|
tmpvalue = tmpbuf[ptr]&mask;
|
value = tmpvalue>>(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])<<i;
|
}
|
|
ip1811drv_dbg("tb_calc_index() index = %02u\n", index);
|
return index;
|
}
|
|
int switchdSetIGMPMctTable(int index, struct mt_rule *mt_data)
|
{
|
u16 regdata[6] = {0};
|
u16 i, tmpvalue;
|
|
memset(regdata, 0, 11);
|
ip1811drv_dbg("driver:index: %x\n", index);
|
ip1811drv_dbg("driver:group: %x : %x : %x : %x\n", mt_data->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<<i;
|
}
|
ip1811drv_dbg("%x\n", mask);
|
mt_data->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<MAX_PHY_NUM; j++) {
|
for(i=0; i<NUM_MIB_COUNTER_RX; i++) {
|
//statistic counter read , read clear rx counter
|
Write_Reg(POREG_MIBCOUN_CMD, 0xC000|(u16)i|((u16)j<<5));
|
/* need to check does trigger bit has been put down */
|
while((Read_Reg(POREG_MIBCOUN_CMD) >> 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<NUM_MIB_COUNTER_TX; i++) {
|
//statistic counter read , read clear tx counter
|
Write_Reg(POREG_MIBCOUN_CMD,0xC400|(u16)i|((u16)j<<5));
|
/* need to check does trigger bit has been put down */
|
while((Read_Reg(POREG_MIBCOUN_CMD) >> 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<NUM_MIB_COUNTER_RX; i++) {
|
//statistic counter read , read clear rx counter
|
Write_Reg(POREG_MIBCOUN_CMD, 0xC000|(u16)i|((u16)port<<5));
|
/* need to check does trigger bit has been put down */
|
while((Read_Reg(POREG_MIBCOUN_CMD) >> 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<NUM_MIB_COUNTER_TX; i++) {
|
//statistic counter read , read clear tx counter
|
Write_Reg(POREG_MIBCOUN_CMD, 0xC400|(u16)i|((u16)port<<5));
|
/* need to check does trigger bit has been put down */
|
while((Read_Reg(POREG_MIBCOUN_CMD) >> 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(mode<OP_QOS_MODE_FIFO || mode>OP_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(mode<OP_QOS_METHOD_WRR || mode>OP_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(queue<OP_QOS_NUM_Q0 || queue>OP_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(queue<OP_QOS_NUM_Q0 || queue>OP_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(queue<OP_QOS_NUM_Q0 || queue>OP_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(mode<OP_QOS_UNIT_64KBS || mode>OP_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("<DBG_DR_ACL> 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; i<num; i++) {
|
m |= BIT(i);
|
}
|
|
for(i=0; i<4; i++) {
|
t = (unsigned long)m_acl ->used_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("<DBG_DR_ACL> 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("<DBG_SWD_ACL> 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("<DBG_SWD_ACL> 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; i<mr->num_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("<DBG_DR_ACL> aclCleanTable()\n");
|
|
if(rule_index == 128) {
|
ip1811drv_dbg("<DBG_DR_ACL> aclCleanTable() 111111\n");
|
if(list_empty(&m_acl ->rule_list)) {
|
ip1811drv_dbg("<DBG_DR_ACL> aclCleanTable() 222222\n");
|
return 0;
|
}
|
|
list_for_each_entry_safe(mr, nmr, &m_acl ->rule_list, rule_entry)
|
{
|
for(i=0; i<mr->num_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("<DBG_SWD_ACL> 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; i<mr->num_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("<DBG_DR_ACL> 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; j<index_move_range; j++) {
|
acl_write_table_move(block_move_from, index_move_from+j, block_move_to, index_move_to+j);
|
}
|
|
// modify entry info
|
list_for_each_entry(mr, &m_acl ->rule_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("<DBG_DR_ACL> 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)
|
{}
|