Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include        <u.h>
#include        <libc.h>
#include        <ip.h>

static  short   endian  = 1;
static  uchar*  aendian = (uchar*)&endian;
#define LITTLE  *aendian

ushort
ptclbsum(uchar *addr, int len)
{
        ulong losum, hisum, mdsum, x;
        ulong t1, t2;

        losum = 0;
        hisum = 0;
        mdsum = 0;

        x = 0;
        if((uintptr)addr & 1) {
                if(len) {
                        hisum += addr[0];
                        len--;
                        addr++;
                }
                x = 1;
        }
        while(len >= 16) {
                t1 = *(ushort*)(addr+0);
                t2 = *(ushort*)(addr+2);        mdsum += t1;
                t1 = *(ushort*)(addr+4);        mdsum += t2;
                t2 = *(ushort*)(addr+6);        mdsum += t1;
                t1 = *(ushort*)(addr+8);        mdsum += t2;
                t2 = *(ushort*)(addr+10);       mdsum += t1;
                t1 = *(ushort*)(addr+12);       mdsum += t2;
                t2 = *(ushort*)(addr+14);       mdsum += t1;
                mdsum += t2;
                len -= 16;
                addr += 16;
        }
        while(len >= 2) {
                mdsum += *(ushort*)addr;
                len -= 2;
                addr += 2;
        }
        if(x) {
                if(len)
                        losum += addr[0];
                if(LITTLE)
                        losum += mdsum;
                else
                        hisum += mdsum;
        } else {
                if(len)
                        hisum += addr[0];
                if(LITTLE)
                        hisum += mdsum;
                else
                        losum += mdsum;
        }

        losum += hisum >> 8;
        losum += (hisum & 0xff) << 8;
        while(hisum = losum>>16)
                losum = hisum + (losum & 0xffff);

        return losum & 0xffff;
}