xref: /plan9/sys/src/libip/ptclbsum.c (revision 73e742d79f6b0cfc24f3b01d7ade790955db63c2)
19a747e4fSDavid du Colombier #include	<u.h>
29a747e4fSDavid du Colombier #include	<libc.h>
39a747e4fSDavid du Colombier #include	<ip.h>
49a747e4fSDavid du Colombier 
59a747e4fSDavid du Colombier static	short	endian	= 1;
69a747e4fSDavid du Colombier static	uchar*	aendian	= (uchar*)&endian;
79a747e4fSDavid du Colombier #define	LITTLE	*aendian
89a747e4fSDavid du Colombier 
99a747e4fSDavid du Colombier ushort
ptclbsum(uchar * addr,int len)109a747e4fSDavid du Colombier ptclbsum(uchar *addr, int len)
119a747e4fSDavid du Colombier {
129a747e4fSDavid du Colombier 	ulong losum, hisum, mdsum, x;
139a747e4fSDavid du Colombier 	ulong t1, t2;
149a747e4fSDavid du Colombier 
159a747e4fSDavid du Colombier 	losum = 0;
169a747e4fSDavid du Colombier 	hisum = 0;
179a747e4fSDavid du Colombier 	mdsum = 0;
189a747e4fSDavid du Colombier 
199a747e4fSDavid du Colombier 	x = 0;
20*73e742d7SDavid du Colombier 	if((uintptr)addr & 1) {
219a747e4fSDavid du Colombier 		if(len) {
229a747e4fSDavid du Colombier 			hisum += addr[0];
239a747e4fSDavid du Colombier 			len--;
249a747e4fSDavid du Colombier 			addr++;
259a747e4fSDavid du Colombier 		}
269a747e4fSDavid du Colombier 		x = 1;
279a747e4fSDavid du Colombier 	}
289a747e4fSDavid du Colombier 	while(len >= 16) {
299a747e4fSDavid du Colombier 		t1 = *(ushort*)(addr+0);
309a747e4fSDavid du Colombier 		t2 = *(ushort*)(addr+2);	mdsum += t1;
319a747e4fSDavid du Colombier 		t1 = *(ushort*)(addr+4);	mdsum += t2;
329a747e4fSDavid du Colombier 		t2 = *(ushort*)(addr+6);	mdsum += t1;
339a747e4fSDavid du Colombier 		t1 = *(ushort*)(addr+8);	mdsum += t2;
349a747e4fSDavid du Colombier 		t2 = *(ushort*)(addr+10);	mdsum += t1;
359a747e4fSDavid du Colombier 		t1 = *(ushort*)(addr+12);	mdsum += t2;
369a747e4fSDavid du Colombier 		t2 = *(ushort*)(addr+14);	mdsum += t1;
379a747e4fSDavid du Colombier 		mdsum += t2;
389a747e4fSDavid du Colombier 		len -= 16;
399a747e4fSDavid du Colombier 		addr += 16;
409a747e4fSDavid du Colombier 	}
419a747e4fSDavid du Colombier 	while(len >= 2) {
429a747e4fSDavid du Colombier 		mdsum += *(ushort*)addr;
439a747e4fSDavid du Colombier 		len -= 2;
449a747e4fSDavid du Colombier 		addr += 2;
459a747e4fSDavid du Colombier 	}
469a747e4fSDavid du Colombier 	if(x) {
479a747e4fSDavid du Colombier 		if(len)
489a747e4fSDavid du Colombier 			losum += addr[0];
499a747e4fSDavid du Colombier 		if(LITTLE)
509a747e4fSDavid du Colombier 			losum += mdsum;
519a747e4fSDavid du Colombier 		else
529a747e4fSDavid du Colombier 			hisum += mdsum;
539a747e4fSDavid du Colombier 	} else {
549a747e4fSDavid du Colombier 		if(len)
559a747e4fSDavid du Colombier 			hisum += addr[0];
569a747e4fSDavid du Colombier 		if(LITTLE)
579a747e4fSDavid du Colombier 			hisum += mdsum;
589a747e4fSDavid du Colombier 		else
599a747e4fSDavid du Colombier 			losum += mdsum;
609a747e4fSDavid du Colombier 	}
619a747e4fSDavid du Colombier 
629a747e4fSDavid du Colombier 	losum += hisum >> 8;
639a747e4fSDavid du Colombier 	losum += (hisum & 0xff) << 8;
649a747e4fSDavid du Colombier 	while(hisum = losum>>16)
659a747e4fSDavid du Colombier 		losum = hisum + (losum & 0xffff);
669a747e4fSDavid du Colombier 
679a747e4fSDavid du Colombier 	return losum & 0xffff;
689a747e4fSDavid du Colombier }
69