免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2176 | 回复: 0
打印 上一主题 下一主题

八.以太网组播地址过滤寄存器的计算 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-18 20:43 |只看该作者 |倒序浏览

               
转自zcx3000的专栏~~~~http://blog.csdn.net/zcx3000/
最近把AX88796的datasheet看了一下,又看到了zcx3000关于RTL8019的一系列文章,转过来参考一下~~~~~~
终于找到关于RTL8019AS里的 MAR0-MAR7的计算的程序,源程序是80x86的汇编,我把它转换成了在keil c51里的程序,以便可以在51单片机里使用。
跟组播地址有关的寄存器:


为8个寄存器,提供对组播地址的过滤。跟crc的逻辑有关。MAR0-7 全部设置为0xff时,将接收所有的组播数据包,将MAR0-7 全部设置为0x00时,将不接收所有组播地址的数据包。在windows98里,该值被设置为:
MAR0=0x00;
MAR1=0x41;
MAR2=0x00;
MAR3=0x80;
MAR4=0x00;
MAR5=0x00;
MAR6=0x00;
MAR7=0x00;


用户在嵌入式的应用当中,可以设置为全部0xff,也可以对特定的组播地址(比如你用在网络电台广播)进行计算,生成一个你需要的过滤参数。建议该过滤的算法不写在单片机里,最好是先算好,存储在单片机里,用的时候直接调用,以节省单片机的程序空间。

这8个寄存器的值是根据组播地址数组的值生成的,提供对组播地址的过滤,过滤掉一些不属于自己接收组播数据包。
以下是在80x86 里的汇编程序:
[color="#ff33cc"]点击这里打开

;注解: laogu  
http://www.laogu.com
;这是一段在80x86里的汇编源程序,用来生成多播地址过滤的 MAR0-MAR7(以太网卡里的多播地址过滤寄存器)
;多播也叫组播。程序调用的时候 将组播地址列表的地址传递到ds:si ,
;列表相当于c语言里的二维数组 unsigned char multicast_addresses[ax][6];
;   因为每个地址的长度为6,总共有ax个组播地址。
; ds:si 相当于c语言里的指针 unsigned char *multicast_addresses ;
;将地址总数传递到ax,字节数(=地址总数*6)传递到 cx里(在这个程序里,没有用到cx传递的值)

;程序运算的结果放在mcast_list_bits里,相当于c语言里的unsigned char mcast_list_bits[8];
;程序里的di相当于c语言里的指针 unsigned char *mcast_list_bits;
;mcast_list_bits[8]对应于地址过滤寄存器MAR[8],即MAR0---MAR7
;函数 set_hw_multi ; Set the multicast mask bits in chip是将mcast_list_bits[8]写入到MAR0--MAR7
;的一个函数调用,这里没有写。
    public   set_multicast_list
set_multicast_list:
;enter with ds:si ->list of multicast addresses, ax = number of addresses,
;  cx = number of bytes.
;入口调用: 将list of multicast addresses 组播地址列表(可以有多个组播地址)的地址放在
;ds:si  指针里。ax为多播地址的个数。cx为字节数
;return nc if we set all of them, or cy,dh=error if we didn't.
;设置成功返回c=0,失败c=1(c就是cy,cpu标志位)
    assume ds:code
    mov   cx,ax       ;keep a count of addresses in cx.
           ;cx=多播地址的个数
    mov   di,offset mcast_list_bits ;di=64位的多播地址crc
    xor   ax,ax
    mov   [di+0],ax
    mov   [di+2],ax
    mov   [di+4],ax
    mov   [di+6],ax   ;将多播地址8个字节的crc全部设置为0
    jcxz  set_mcl_2   ;cx=0 跳到set_mc1_2,将多播地址crc设置为全部0
set_mcl_1:
    call  add_mc_bits  ;调用crc计算
    loop  set_mcl_1
set_mcl_2:
    call    set_hw_multi ; Set the multicast mask bits in chip
                            ;将mcast_list_bits[8]  8个字节分别写入到MAR0--MAR7
                            ;mcast_list_bits[0]对应于MAR0   .
    clc
    ret
;=================
add_mc_bits:  开始计算
;entry:   ds:si -> multicast address, di-> sixty-four bit multicast filter.
;preserve cx, di, increment si by EADDR_LEN
    push  cx ;保存cx,就是保存多播地址的个数
    mov   cx,EADDR_LEN  ;EADDR_LEN就是以太网地址的长度=6
    mov   dx,0ffffh         ; this is msw.
    mov   bx,0ffffh         ; set 32 bit number
add_mcb_1:
    lodsb  ;将一个字节的数(地址为si指向的数)装到AL里,同时使si地址+1
    call  upd_crc        ; update crc
    loop  add_mcb_1      ; and loop.
;=============
  ifdef MULTICRC_REVERSE  ;ifdef 到endif这段函数是产生CRC过滤的反顺序码的,
                          ;例如 0000001 反顺序就是 1000000
                          ;就是高位和低位反过来。
                          ;程序的执行将dh里的数反顺序排列
                          ;这段程序应该是没有使用,也就是说我们用的是正顺序码。而不是反顺序码。
    mov   cl,8
add_mcb_2:
    shl   dh,1    ;逻辑左移1位,高位进c,地位补0
    rcr   dl,1       ;带进位的循环右移,c进高位,低位进c
    loop  add_mcb_2
    mov   dh,dl
  endif
;====================
    mov   al,dh       ; get ms 8 bits,
    rol   al,1     ;循环左移,高位进c和低位,
    rol   al,1
    rol   al,1        ; put 3 bits at bottom
    and   al,7
    mov   bl,al       ; save in bl
    xor   bh,bh       ; make bx into an index to the byte.
    mov   al,dh       ; get ms 8 bits,
    ror   al,1         ;循环右移,低位进c和高位
    ror   al,1        ; but at bottom
    and   al,7
    mov   cl,al       ; save in cl
    mov   al,1
    shl   al,cl       ; set the correct bit,
   
                     ;逻辑左移1位,高位进c,地位补0
    or [bx+di],al
    pop   cx
    ret
;
;   dx is high,
;   bx is low.
;   al is data
;======================
upd_crc:
    push  cx
    mov   cx,8     ; do 8 bits;cx=次数
    mov   ah,0
upd_crc1:
    shl   bx,1     ; shift bx  ;bx在最开始时被设置为0xffff
                   ;逻辑左移1位,高位进c,地位补0
    rcl   dx,1     ; through dx;dx最开始被设置为0xffff
               ;带进位循环左移,高位进c,c进低位
    rcl   ah,1     ; carry is at bottom of ah
                ;带进位循环左移,高位进c,c进低位
    xor   ah,al    ; xor with lsb of data
              ;逻辑异或,结果放在左边的ah里,相同为0,不同为1
    rcr   ah,1     ; and put in carry bit
              ;带进位的循环右移,c进高位,低位进c
    jnc   upd_crc2
;
;   autodin is x^32+x^26+x^23x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1
;
    xor   dx,0000010011000001b
    xor   bx,0001110110110110b + 1   ;plus one for end-around carry.
upd_crc2:
    shr   al,1     ; shift the data
      ; 循环右移,高位补0,低位进c
    loop  upd_crc1
    pop   cx
    ret
以下是在keil c51里的c语言程序,为斑竹所写
[color="#ff33cc"]点击这里打开

//作者laogu  
http://www.laogu.com
//程序的功能是根据多播地址multicast_address[6]的值,计算出MAR0-MAR7,就是multicast_filter[8];
//本程序指计算一个多播地址。如果有多个多播地址,将每个多播地址生成的multicast_filter[8]相或就可以了,
//例如根据多播地址 01:00:5e:00:00:01生成的 value1=multicast_filter[8];
//根据多播地址     01:00:5e:00:00:02生成的 value2=multicast_filter[8];
//那么对这两个多播地址生成的multicast_filter[8]=value1  |  value2 ;将两个值相或
//很容易从这里得到如果要接收所有多播地址的数据包,MAR0--MAR7必须设置为0xff,就是说
//multicast_filter[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
#define al ax_value.bytes.low
#define bl bx_value.bytes.low
#define cl cx_value.bytes.low
#define ah ax_value.bytes.high
#define bh bx_value.bytes.high
#define dh dx_value.bytes.high
#define ax ax_value.word
#define bx bx_value.word
#define cx cx_value.word
#define dx dx_value.word
#define shl_bx if((bx&0x8000)!=0){cf=1;}else{cf=0;};bx=bx>1;
#define rcl_dx if((dx&0x8000)!=0){cf_temp=1;}else{cf_temp=0;};dx=dx>1;if(cf){ah=ah+0x80;};cf=cf_temp;
#define rol_al if((al&0x80)!=0){cf=1;}else{cf=0;};al=al>1;if(cf){al=al+0x80;};
union u {unsigned int word;
         struct{unsigned char high;unsigned char low;}bytes;//字节顺序为高位在前的2byte结构
   };
union u ax_value;
union u bx_value;
union u cx_value;
union u dx_value;
bit cf;
bit cf_temp;
unsigned char multicast_address[6]={0x01,0x00,0x5e,0x00,0x00,0x00};
//unsigned char multicast_address[6]={0x00,0x00,0x00,0x5e,0x00,0x01};  //只计算一个多播地址
//unsigned char multicast_address[6]={0x01,0x80,0xc2,0x00,0x00,0x00};
unsigned char multicast_filter[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
                                      //结果放在这里,就是MAR0--MAR7的值
//;;0x41,0x00,0x00,0x80,0x00,0x00,0x00,0x00;
void up_crc(unsigned char al_byte)
{
al=al_byte;
ah=0;
for (cx=0;cxshr_al;
}

}
void add_mc_bits()
{
unsigned char i;
bx=0xffff;
dx=0xffff;
for(i=0;i}
cl=8;
al=dh;
rol_al;
rol_al;
rol_al;
al=al&0x07;
bl=al;
bh=bh^bh;
al=dh;
ror_al;
ror_al;
al=al&0x07;
cl=al;
al=1;
for(i=0;i<cl;i++)
{
shl_al;
}
multicast_filter[bx]=multicast_filter[bx] | al;
}
main()
{
add_mc_bits(); //计算多播地址的MAR0-MAR7.
while(1);
}

               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/84137/showart_1867716.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP