diff options
author | root <root@(null).(none)> | 2009-05-03 17:20:00 +0200 |
---|---|---|
committer | root <root@(null).(none)> | 2009-05-03 17:20:00 +0200 |
commit | e0faf22f31c48fb27b43c1825897d26e58feafc4 (patch) | |
tree | 65a09372b31e08a3a865bd0a88cd2718bafcd643 /pfinet.old/linux-src/arch/alpha |
This is my initial working version.
There is a bug in boot in this version: subhurd sometimes cannot boot.
Diffstat (limited to 'pfinet.old/linux-src/arch/alpha')
-rw-r--r-- | pfinet.old/linux-src/arch/alpha/CVS/Entries | 1 | ||||
-rw-r--r-- | pfinet.old/linux-src/arch/alpha/CVS/Repository | 1 | ||||
-rw-r--r-- | pfinet.old/linux-src/arch/alpha/CVS/Root | 1 | ||||
-rw-r--r-- | pfinet.old/linux-src/arch/alpha/lib/CVS/Entries | 3 | ||||
-rw-r--r-- | pfinet.old/linux-src/arch/alpha/lib/CVS/Repository | 1 | ||||
-rw-r--r-- | pfinet.old/linux-src/arch/alpha/lib/CVS/Root | 1 | ||||
-rw-r--r-- | pfinet.old/linux-src/arch/alpha/lib/checksum.c | 169 | ||||
-rw-r--r-- | pfinet.old/linux-src/arch/alpha/lib/csum_partial_copy.c | 384 |
8 files changed, 561 insertions, 0 deletions
diff --git a/pfinet.old/linux-src/arch/alpha/CVS/Entries b/pfinet.old/linux-src/arch/alpha/CVS/Entries new file mode 100644 index 00000000..7b214dc9 --- /dev/null +++ b/pfinet.old/linux-src/arch/alpha/CVS/Entries @@ -0,0 +1 @@ +D/lib//// diff --git a/pfinet.old/linux-src/arch/alpha/CVS/Repository b/pfinet.old/linux-src/arch/alpha/CVS/Repository new file mode 100644 index 00000000..cef2e087 --- /dev/null +++ b/pfinet.old/linux-src/arch/alpha/CVS/Repository @@ -0,0 +1 @@ +hurd/pfinet/linux-src/arch/alpha diff --git a/pfinet.old/linux-src/arch/alpha/CVS/Root b/pfinet.old/linux-src/arch/alpha/CVS/Root new file mode 100644 index 00000000..55403097 --- /dev/null +++ b/pfinet.old/linux-src/arch/alpha/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.savannah.gnu.org:/sources/hurd diff --git a/pfinet.old/linux-src/arch/alpha/lib/CVS/Entries b/pfinet.old/linux-src/arch/alpha/lib/CVS/Entries new file mode 100644 index 00000000..65920e32 --- /dev/null +++ b/pfinet.old/linux-src/arch/alpha/lib/CVS/Entries @@ -0,0 +1,3 @@ +/checksum.c/1.1.1.1/Fri Feb 4 03:21:18 2000/-ko/ +/csum_partial_copy.c/1.1/Wed May 29 08:34:41 2002// +D diff --git a/pfinet.old/linux-src/arch/alpha/lib/CVS/Repository b/pfinet.old/linux-src/arch/alpha/lib/CVS/Repository new file mode 100644 index 00000000..ddde2872 --- /dev/null +++ b/pfinet.old/linux-src/arch/alpha/lib/CVS/Repository @@ -0,0 +1 @@ +hurd/pfinet/linux-src/arch/alpha/lib diff --git a/pfinet.old/linux-src/arch/alpha/lib/CVS/Root b/pfinet.old/linux-src/arch/alpha/lib/CVS/Root new file mode 100644 index 00000000..55403097 --- /dev/null +++ b/pfinet.old/linux-src/arch/alpha/lib/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.savannah.gnu.org:/sources/hurd diff --git a/pfinet.old/linux-src/arch/alpha/lib/checksum.c b/pfinet.old/linux-src/arch/alpha/lib/checksum.c new file mode 100644 index 00000000..5165279f --- /dev/null +++ b/pfinet.old/linux-src/arch/alpha/lib/checksum.c @@ -0,0 +1,169 @@ +/* + * arch/alpha/lib/checksum.c + * + * This file contains network checksum routines that are better done + * in an architecture-specific manner due to speed.. + */ + +#include <linux/string.h> + +#include <asm/byteorder.h> + +static inline unsigned short from64to16(unsigned long x) +{ + /* add up 32-bit words for 33 bits */ + x = (x & 0xffffffff) + (x >> 32); + /* add up 16-bit and 17-bit words for 17+c bits */ + x = (x & 0xffff) + (x >> 16); + /* add up 16-bit and 2-bit for 16+c bit */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented. + */ +unsigned short int csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + return ~from64to16(saddr + daddr + sum + + ((unsigned long) ntohs(len) << 16) + + ((unsigned long) proto << 8)); +} + +unsigned int csum_tcpudp_nofold(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + unsigned long result; + + result = (saddr + daddr + sum + + ((unsigned long) ntohs(len) << 16) + + ((unsigned long) proto << 8)); + + /* Fold down to 32-bits so we don't loose in the typedef-less + network stack. */ + /* 64 to 33 */ + result = (result & 0xffffffff) + (result >> 32); + /* 33 to 32 */ + result = (result & 0xffffffff) + (result >> 32); + return result; +} + +/* + * Do a 64-bit checksum on an arbitrary memory area.. + * + * This isn't a great routine, but it's not _horrible_ either. The + * inner loop could be unrolled a bit further, and there are better + * ways to do the carry, but this is reasonable. + */ +static inline unsigned long do_csum(const unsigned char * buff, int len) +{ + int odd, count; + unsigned long result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = *buff << 8; + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + if (4 & (unsigned long) buff) { + result += *(unsigned int *) buff; + count--; + len -= 4; + buff += 4; + } + count >>= 1; /* nr of 64-bit words.. */ + if (count) { + unsigned long carry = 0; + do { + unsigned long w = *(unsigned long *) buff; + count--; + buff += 8; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffffffff) + (result >> 32); + } + if (len & 4) { + result += *(unsigned int *) buff; + buff += 4; + } + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += *buff; + result = from64to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + */ +unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) +{ + return ~do_csum(iph,ihl*4); +} + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) +{ + unsigned long result = do_csum(buff, len); + + /* add in old sum, and carry.. */ + result += sum; + /* 32+c bits -> 32 bits */ + result = (result & 0xffffffff) + (result >> 32); + return result; +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +unsigned short ip_compute_csum(unsigned char * buff, int len) +{ + return ~from64to16(do_csum(buff,len)); +} diff --git a/pfinet.old/linux-src/arch/alpha/lib/csum_partial_copy.c b/pfinet.old/linux-src/arch/alpha/lib/csum_partial_copy.c new file mode 100644 index 00000000..71308133 --- /dev/null +++ b/pfinet.old/linux-src/arch/alpha/lib/csum_partial_copy.c @@ -0,0 +1,384 @@ +/* + * csum_partial_copy - do IP checksumming and copy + * + * (C) Copyright 1996 Linus Torvalds + * + * Don't look at this too closely - you'll go mad. The things + * we do for performance.. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include <asm/uaccess.h> + + +#define ldq_u(x,y) \ +__asm__ __volatile__("ldq_u %0,%1":"=r" (x):"m" (*(const unsigned long *)(y))) + +#define stq_u(x,y) \ +__asm__ __volatile__("stq_u %1,%0":"=m" (*(unsigned long *)(y)):"r" (x)) + +#define extql(x,y,z) \ +__asm__ __volatile__("extql %1,%2,%0":"=r" (z):"r" (x),"r" (y)) + +#define extqh(x,y,z) \ +__asm__ __volatile__("extqh %1,%2,%0":"=r" (z):"r" (x),"r" (y)) + +#define mskql(x,y,z) \ +__asm__ __volatile__("mskql %1,%2,%0":"=r" (z):"r" (x),"r" (y)) + +#define mskqh(x,y,z) \ +__asm__ __volatile__("mskqh %1,%2,%0":"=r" (z):"r" (x),"r" (y)) + +#define insql(x,y,z) \ +__asm__ __volatile__("insql %1,%2,%0":"=r" (z):"r" (x),"r" (y)) + +#define insqh(x,y,z) \ +__asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y)) + + +#define __get_user_u(x,ptr) \ +({ \ + long __guu_err; \ + __asm__ __volatile__( \ + "1: ldq_u %0,%2\n" \ + "2:\n" \ + ".section __ex_table,\"a\"\n" \ + " .gprel32 1b\n" \ + " lda %0,2b-1b(%1)\n" \ + ".previous" \ + : "=r"(x), "=r"(__guu_err) \ + : "m"(__m(ptr)), "1"(0)); \ + __guu_err; \ +}) + +#define __put_user_u(x,ptr) \ +({ \ + long __puu_err; \ + __asm__ __volatile__( \ + "1: stq_u %2,%1\n" \ + "2:\n" \ + ".section __ex_table,\"a\"\n" \ + " .gprel32 1b" \ + " lda $31,2b-1b(%0)\n" \ + ".previous" \ + : "=r"(__puu_err) \ + : "m"(__m(addr)), "rJ"(x), "0"(0)); \ + __puu_err; \ +}) + + +/* + * Ok. This isn't fun, but this is the EASY case. + */ +static inline unsigned long +csum_partial_cfu_aligned(const unsigned long *src, unsigned long *dst, + long len, unsigned long checksum, + int *errp) +{ + unsigned long carry = 0; + int err = 0; + + while (len >= 0) { + unsigned long word; + err |= __get_user(word, src); + checksum += carry; + src++; + checksum += word; + len -= 8; + carry = checksum < word; + *dst = word; + dst++; + } + len += 8; + checksum += carry; + if (len) { + unsigned long word, tmp; + err |= __get_user(word, src); + tmp = *dst; + mskql(word, len, word); + checksum += word; + mskqh(tmp, len, tmp); + carry = checksum < word; + *dst = word | tmp; + checksum += carry; + } + if (err) *errp = err; + return checksum; +} + +/* + * This is even less fun, but this is still reasonably + * easy. + */ +static inline unsigned long +csum_partial_cfu_dest_aligned(const unsigned long *src, unsigned long *dst, + unsigned long soff, + long len, unsigned long checksum, + int *errp) +{ + unsigned long first; + unsigned long word, carry; + unsigned long lastsrc = 7+len+(unsigned long)src; + int err = 0; + + err |= __get_user_u(first,src); + carry = 0; + while (len >= 0) { + unsigned long second; + + err |= __get_user_u(second, src+1); + extql(first, soff, word); + len -= 8; + src++; + extqh(second, soff, first); + checksum += carry; + word |= first; + first = second; + checksum += word; + *dst = word; + dst++; + carry = checksum < word; + } + len += 8; + checksum += carry; + if (len) { + unsigned long tmp; + unsigned long second; + err |= __get_user_u(second, lastsrc); + tmp = *dst; + extql(first, soff, word); + extqh(second, soff, first); + word |= first; + mskql(word, len, word); + checksum += word; + mskqh(tmp, len, tmp); + carry = checksum < word; + *dst = word | tmp; + checksum += carry; + } + if (err) *errp = err; + return checksum; +} + +/* + * This is slightly less fun than the above.. + */ +static inline unsigned long +csum_partial_cfu_src_aligned(const unsigned long *src, unsigned long *dst, + unsigned long doff, + long len, unsigned long checksum, + unsigned long partial_dest, + int *errp) +{ + unsigned long carry = 0; + unsigned long word; + int err = 0; + + mskql(partial_dest, doff, partial_dest); + while (len >= 0) { + unsigned long second_dest; + err |= __get_user(word, src); + len -= 8; + insql(word, doff, second_dest); + checksum += carry; + stq_u(partial_dest | second_dest, dst); + src++; + checksum += word; + insqh(word, doff, partial_dest); + carry = checksum < word; + dst++; + } + len += doff; + checksum += carry; + if (len >= 0) { + unsigned long second_dest; + err |= __get_user(word, src); + mskql(word, len-doff, word); + checksum += word; + insql(word, doff, second_dest); + stq_u(partial_dest | second_dest, dst); + carry = checksum < word; + if (len) { + ldq_u(second_dest, dst+1); + insqh(word, doff, partial_dest); + mskqh(second_dest, len, second_dest); + stq_u(partial_dest | second_dest, dst+1); + } + checksum += carry; + } else if (len & 7) { + unsigned long second_dest; + err |= __get_user(word, src); + ldq_u(second_dest, dst); + mskql(word, len-doff, word); + checksum += word; + mskqh(second_dest, len, second_dest); + carry = checksum < word; + insql(word, doff, word); + stq_u(partial_dest | word | second_dest, dst); + checksum += carry; + } + if (err) *errp = err; + return checksum; +} + +/* + * This is so totally un-fun that it's frightening. Don't + * look at this too closely, you'll go blind. + */ +static inline unsigned long +csum_partial_cfu_unaligned(const unsigned long * src, unsigned long * dst, + unsigned long soff, unsigned long doff, + long len, unsigned long checksum, + unsigned long partial_dest, + int *errp) +{ + unsigned long carry = 0; + unsigned long first; + unsigned long lastsrc; + int err = 0; + + err |= __get_user_u(first, src); + lastsrc = 7+len+(unsigned long)src; + mskql(partial_dest, doff, partial_dest); + while (len >= 0) { + unsigned long second, word; + unsigned long second_dest; + + err |= __get_user_u(second, src+1); + extql(first, soff, word); + checksum += carry; + len -= 8; + extqh(second, soff, first); + src++; + word |= first; + first = second; + insql(word, doff, second_dest); + checksum += word; + stq_u(partial_dest | second_dest, dst); + carry = checksum < word; + insqh(word, doff, partial_dest); + dst++; + } + len += doff; + checksum += carry; + if (len >= 0) { + unsigned long second, word; + unsigned long second_dest; + + err |= __get_user_u(second, lastsrc); + extql(first, soff, word); + extqh(second, soff, first); + word |= first; + first = second; + mskql(word, len-doff, word); + checksum += word; + insql(word, doff, second_dest); + carry = checksum < word; + stq_u(partial_dest | second_dest, dst); + if (len) { + ldq_u(second_dest, dst+1); + insqh(word, doff, partial_dest); + mskqh(second_dest, len, second_dest); + stq_u(partial_dest | second_dest, dst+1); + } + checksum += carry; + } else if (len & 7) { + unsigned long second, word; + unsigned long second_dest; + + err |= __get_user_u(second, lastsrc); + extql(first, soff, word); + extqh(second, soff, first); + word |= first; + ldq_u(second_dest, dst); + mskql(word, len-doff, word); + checksum += word; + mskqh(second_dest, len, second_dest); + carry = checksum < word; + insql(word, doff, word); + stq_u(partial_dest | word | second_dest, dst); + checksum += carry; + } + if (err) *errp = err; + return checksum; +} + +static unsigned int +do_csum_partial_copy_from_user(const char *src, char *dst, int len, + unsigned int sum, int *errp) +{ + unsigned long checksum = (unsigned) sum; + unsigned long soff = 7 & (unsigned long) src; + unsigned long doff = 7 & (unsigned long) dst; + + if (len) { + if (!doff) { + if (!soff) + checksum = csum_partial_cfu_aligned( + (const unsigned long *) src, + (unsigned long *) dst, + len-8, checksum, errp); + else + checksum = csum_partial_cfu_dest_aligned( + (const unsigned long *) src, + (unsigned long *) dst, + soff, len-8, checksum, errp); + } else { + unsigned long partial_dest; + ldq_u(partial_dest, dst); + if (!soff) + checksum = csum_partial_cfu_src_aligned( + (const unsigned long *) src, + (unsigned long *) dst, + doff, len-8, checksum, + partial_dest, errp); + else + checksum = csum_partial_cfu_unaligned( + (const unsigned long *) src, + (unsigned long *) dst, + soff, doff, len-8, checksum, + partial_dest, errp); + } + /* 64 -> 33 bits */ + checksum = (checksum & 0xffffffff) + (checksum >> 32); + /* 33 -> < 32 bits */ + checksum = (checksum & 0xffff) + (checksum >> 16); + /* 32 -> 16 bits */ + checksum = (checksum & 0xffff) + (checksum >> 16); + checksum = (checksum & 0xffff) + (checksum >> 16); + } + return checksum; +} + +unsigned int +csum_partial_copy_from_user(const char *src, char *dst, int len, + unsigned int sum, int *errp) +{ + if (!access_ok(src, len, VERIFY_READ)) { + *errp = -EFAULT; + memset(dst, 0, len); + return sum; + } + + return do_csum_partial_copy_from_user(src, dst, len, sum, errp); +} + +unsigned int +csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum) +{ + return do_csum_partial_copy_from_user(src, dst, len, sum, NULL); +} + +unsigned int +csum_partial_copy (const char *src, char *dst, int len, unsigned int sum) +{ + unsigned int ret; + int error = 0; + + ret = do_csum_partial_copy_from_user(src, dst, len, sum, &error); + if (error) + printk("csum_partial_copy_old(): tell mingo to convert me!\n"); + + return ret; +} |