#include <asm/uaccess.h> #include <linux/capability.h> #include <linux/module.h> #include <linux/mm.h> #include <linux/in.h> #include <linux/init.h> #include <linux/if.h> #include <linux/if_ether.h> #include "ptm_mii_sw_wanif.h" #ifdef USE_PTM_MII_WANIF #include "ptm_rtl8685.h" #if 1 #define PTMMSG(format, args...) if(pt_wan_dbg) printk("%s:%d> " format, __FUNCTION__, __LINE__, ##args) #else #define PTMMSG(format, args...) while(0){} #endif typedef struct _ptm_mii_wanif_sw_ { struct _ptm_mii_wanif_sw_ *next; unsigned char name[IFNAMSIZ]; unsigned char addr[ETH_ALEN]; unsigned short svid; unsigned short cvid; unsigned char tag:4; unsigned char isbridge:4; unsigned char path; unsigned char qid[8]; } ptm_mii_wanif_sw; static ptm_mii_wanif_sw *pwaniflist=NULL; static int pt_wan_dbg=0; /*hw api*******************************************************************/ static void ptm_mii_cleanall_hw_wanif(void) { int i; rtl8685_WANtbl_t w; PTMMSG("\n"); memset( &w, 0, sizeof(w) ); for(i=0;i<PTM_MAX_INTF;i++) { rtl8685_setWanTable(i, &w ); } } static void ptm_mii_update_hw_wanif(int idx, ptm_mii_wanif_sw *n) { rtl8685_WANtbl_t w; PTMMSG("\n"); memset( &w, 0, sizeof(w) ); w.Valid=1; w.SVlanID=n->svid; w.CVlanID=n->cvid; if(n->isbridge==0) memcpy( w.MAC, n->addr, ETH_ALEN ); strncpy(w.ifname, n->name, IFNAMSIZ); rtl8685_setWanTable(idx, &w ); } static void ptm_mii_update_hw_qmap(int idx, ptm_mii_wanif_sw *n) { int max_qid=8; int qid; PTMMSG("\n"); for(qid=0; qid<max_qid; qid++) { unsigned char qval; qval= ((n->path&0x1)<<2)|(n->qid[qid]&0x3); rtl8685_set_QMap(idx,qid,qval); } } static void ptm_mii_update_hw(void) { int idx=0; ptm_mii_wanif_sw *c=pwaniflist; PTMMSG("\n"); //set all invalid ptm_mii_cleanall_hw_wanif(); while(c) { ptm_mii_update_hw_wanif(idx, c); ptm_mii_update_hw_qmap(idx, c); c=c->next; idx++; } } /*end hw api***************************************************************/ static int ptm_mii_gen_tag(ptm_mii_wanif_sw *n) { int ret=-1; PTMMSG("\n"); if(n) { ret=0; if(n->svid) ret+=4; if(n->cvid) ret+=2; if(n->isbridge==0) ret+=1; } return ret; } static void ptm_mii_dump_wanif_node(ptm_mii_wanif_sw *c) { PTMMSG("c=0x%08x\n", (unsigned int)c); if(c) { printk( "name=%s, tag=%u, isbridge=%u\n", c->name, c->tag, c->isbridge); printk( "\t svid=%u, cvid=%u, mac=%02x%02x%02x%02x%02x%02x\n", c->svid, c->cvid, c->addr[0],c->addr[1], c->addr[2],c->addr[3],c->addr[4],c->addr[5]); printk( "\t path=%u, qid=%u%u%u%u%u%u%u%u\n", c->path, c->qid[0], c->qid[1], c->qid[2], c->qid[3], c->qid[4], c->qid[5], c->qid[6], c->qid[7]); } } static void ptm_mii_dump_wanif(void) { ptm_mii_wanif_sw *c=pwaniflist; PTMMSG("enter: c=0x%08x\n", (unsigned int)c); while(c) { ptm_mii_dump_wanif_node(c); c=c->next; } } static int ptm_mii_get_wanif_num(void) { ptm_mii_wanif_sw *c=pwaniflist; int idx=0; PTMMSG("enter: c=0x%08x\n", (unsigned int)c); while(c) { idx++; c=c->next; } return idx; } static int ptm_mii_insert_wanif(ptm_mii_wanif_sw *n) { ptm_mii_wanif_sw **p=&pwaniflist; ptm_mii_wanif_sw *c=pwaniflist; PTMMSG("enter: n=0x%08x\n", (unsigned int)n); if(n==NULL) return -1; PTMMSG("p=0x%08x, c=0x%08x\n", (unsigned int)p, (unsigned int)c); PTMMSG("n->name=%s, n->tag=%u\n", n->name, n->tag); //check duplicate while( c ) { PTMMSG("c->name=%s, c->tag=%u\n", c->name, c->tag); if( c->tag>=n->tag ) { p=&c->next; c=c->next; PTMMSG("p=0x%08x, c=0x%08x\n", (unsigned int)p, (unsigned int)c); }else break; } n->next=c; *p=n; ptm_mii_update_hw(); if(pt_wan_dbg) ptm_mii_dump_wanif(); return 0; } static ptm_mii_wanif_sw *ptm_mii_get_wanif(unsigned char *name, int *idx) { ptm_mii_wanif_sw *c=pwaniflist; int i=0; PTMMSG("enter: name=%s\n", name?name:(unsigned char*)"" ); if(name==NULL) return NULL; if(idx) *idx=-1; PTMMSG("c=0x%08x\n", (unsigned int)c); while( c ) { PTMMSG("c->name=%s\n", c->name); if( strncmp(c->name,name,IFNAMSIZ) ) { c=c->next; PTMMSG("c=0x%08x\n", (unsigned int)c); }else{ PTMMSG("match, c=0x%08x\n", (unsigned int)c); if(idx) *idx=i; break; } i++; } return c; } static ptm_mii_wanif_sw *ptm_mii_remove_wanif(unsigned char *name) { ptm_mii_wanif_sw **p=&pwaniflist; ptm_mii_wanif_sw *c=pwaniflist; PTMMSG("enter: name=%s\n", name?name:(unsigned char*)"" ); if(name==NULL) return NULL; PTMMSG("p=0x%08x, c=0x%08x\n", (unsigned int)p, (unsigned int)c); while( c ) { PTMMSG("c->name=%s\n", c->name); if( strncmp(c->name,name,IFNAMSIZ) ) { p=&c->next; c=c->next; PTMMSG("p=0x%08x, c=0x%08x\n", (unsigned int)p, (unsigned int)c); }else{ *p=c->next; c->next=NULL; PTMMSG("match, p=0x%08x, c=0x%08x\n", (unsigned int)p, (unsigned int)c); break; } } if(pt_wan_dbg) ptm_mii_dump_wanif(); return c; } static int ptm_mii_delete_wanif(unsigned char *name) { ptm_mii_wanif_sw *c; c=ptm_mii_remove_wanif(name); if(c) { PTMMSG( "free node=0x%08x\n", (unsigned int)c ); kfree(c); ptm_mii_update_hw(); return 0; } return -1; } static void ptm_mii_debug(char *name, unsigned char path, unsigned char *qid) { //start from 200 switch(path) { case 200: pt_wan_dbg=0; printk( "pt_wan_dbg disabled\n"); break; case 201: pt_wan_dbg=1; printk( "pt_wan_dbg enabled\n"); break; case 202: { int num; num=ptm_mii_get_wanif_num(); printk( "total ptm mii wan interface = %d\n", num ); ptm_mii_dump_wanif(); printk( "\n" ); } break; default: break; } } /*smux-related api***************************************************************/ int ptm_mii_update_qmap(char *name, unsigned char path, unsigned char *qid) { unsigned long flags; int ret=-1; ptm_mii_wanif_sw *n; int idx; PTMMSG("name=%s, path=%u\n", name?name:"", path); if(qid) PTMMSG("qid=%u%u%u%u%u%u%u%u\n", qid[0],qid[1],qid[2],qid[3],qid[4],qid[5],qid[6],qid[7]); if( (name==NULL) || (qid==NULL) ) return ret; //for debug if(path>=200) { ptm_mii_debug( name, path, qid ); return 0; } local_irq_save(flags); n=ptm_mii_get_wanif(name, &idx); if(n) { n->path=path?1:0; memcpy( n->qid, qid, sizeof(n->qid)); ptm_mii_update_hw_qmap(idx, n); ret=0; } local_irq_restore(flags); return ret; } int ptm_mii_update_wanif_macaddr(char *name, unsigned char *addr) { unsigned long flags; int ret=-1; ptm_mii_wanif_sw *n; int idx; PTMMSG("name=%s\n", name?name:""); if(addr) PTMMSG("addr=%02x%02x%02x%02x%02x%02x\n", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]); if( (name==NULL) || (addr==NULL) ) return ret; local_irq_save(flags); n=ptm_mii_get_wanif(name, &idx); if(n) { if( (!n->isbridge)&& (!addr[0])&&(!addr[1])&&(!addr[2])&& (!addr[3])&&(!addr[4])&&(!addr[5]) ) { printk( "%s: error (not bridge but macaddr=0)\n", __FUNCTION__ ); }else{ memcpy( n->addr, addr, ETH_ALEN); if(!n->isbridge) ptm_mii_update_hw_wanif(idx, n); ret=0; } } local_irq_restore(flags); return ret; } int ptm_mii_register_wanif(char *name, unsigned char *addr, int svid, int cvid, int isbridge) { unsigned long flags; int ret=-1; ptm_mii_wanif_sw *n; PTMMSG("name=%s, isbridge=%d, svid=%d, cvid=%d, addr=0x%08x\n", name?name:"", isbridge, svid, cvid, (unsigned int)addr); if(addr) PTMMSG("addr=%02x%02x%02x%02x%02x%02x\n", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]); if( (name==NULL) || (addr==NULL) ) return ret; if(ptm_mii_get_wanif_num()>=PTM_MAX_INTF) { printk( "%s: error (exceed the ptm wanif num, %d)\n", __FUNCTION__, PTM_MAX_INTF ); return ret; } if( (!isbridge)&& (!addr[0])&&(!addr[1])&&(!addr[2])&& (!addr[3])&&(!addr[4])&&(!addr[5]) ) { printk( "%s: error (not bridge but macaddr=0)\n", __FUNCTION__ ); return ret; } n=(ptm_mii_wanif_sw *)kmalloc(sizeof(ptm_mii_wanif_sw) , GFP_KERNEL); if(n==NULL) return ret; PTMMSG("new node=0x%08x\n", (unsigned int)n); memset( n, 0, sizeof(ptm_mii_wanif_sw) ); strncpy( n->name, name, IFNAMSIZ ); memcpy( n->addr, addr, ETH_ALEN); if(svid<0) svid=0; n->svid=(unsigned short)svid&0xfff; if(cvid<0) cvid=0; n->cvid=(unsigned short)cvid&0xfff; n->isbridge=isbridge?1:0; n->path=1; //fast n->tag=ptm_mii_gen_tag(n); local_irq_save(flags); ret=ptm_mii_insert_wanif(n); local_irq_restore(flags); if(ret<0) { PTMMSG( "free node=0x%08x\n", (unsigned int)n ); kfree(n); } return ret; } int ptm_mii_unregister_wanif(char *name) { unsigned long flags; int ret=-1; PTMMSG( "enter, name=%s\n", name?name:"" ); if(name==NULL) return ret; local_irq_save(flags); ret=ptm_mii_delete_wanif(name); local_irq_restore(flags); return ret; } /*end smux-related api***************************************************************/ #if 0 int ptm_mii_main(void) //int main(void) { int i=0; unsigned char testmac1[6]={0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; //unsigned char testmac1[6]={0, 0, 0, 0, 0, 0}; unsigned char testmac2[6]={0x00, 0x11, 0x22, 0x33, 0x44, 0x66}; unsigned char testmac3[6]={0x00, 0x11, 0x22, 0x33, 0x44, 0x77}; unsigned char testmac4[6]={0x00, 0x11, 0x22, 0x33, 0x44, 0x44}; unsigned char testmac5[6]={0x11, 0x22, 0x33, 0x44, 0x77, 0x88}; unsigned char qid[8]={ 0,0,1,1,2,2,3,3 }; PTMMSG( "%d=================================\n", i++ ); ptm_mii_register_wanif( "ptm0", testmac1, 100, 100, 0 ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_register_wanif( "ptm1", testmac2, 0, 0, 1 ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_register_wanif( "ptm2", testmac3, 0,0, 0 ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_register_wanif( "ptm3", testmac4, 200,200, 1 ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_dump_wanif(); ptm_mii_update_qmap( "ptm3", 1, qid ); ptm_mii_dump_wanif(); PTMMSG( "%d=================================\n", i++ ); ptm_mii_update_wanif_macaddr( "ptm2", testmac4 ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_unregister_wanif( "ptm99" ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_unregister_wanif( "ptm1" ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_unregister_wanif( "ptm0" ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_unregister_wanif( "ptm2" ); PTMMSG( "%d=================================\n", i++ ); ptm_mii_unregister_wanif( "ptm3" ); PTMMSG( "%d=================================\n", i++ ); return 0; } #endif #endif /*USE_PTM_MII_WANIF*/