diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 10:44:53 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 10:44:53 +0000 |
commit | 49235ceee0c25492d4ca35194d7c72838a9ec284 (patch) | |
tree | 14f77677934d4f4cb9baa428691ace792fd0deed /sys/arch/mvme68k/stand/sboot | |
parent | c9328c850e70436131e06a34f73c14cc230c18f9 (diff) |
mvme68k port by me. some parts by dale rahn.
Diffstat (limited to 'sys/arch/mvme68k/stand/sboot')
-rw-r--r-- | sys/arch/mvme68k/stand/sboot/XBUG.S | 72 | ||||
-rw-r--r-- | sys/arch/mvme68k/stand/sboot/XSRT0.S | 42 | ||||
-rw-r--r-- | sys/arch/mvme68k/stand/sboot/if_le.c | 327 | ||||
-rw-r--r-- | sys/arch/mvme68k/stand/sboot/oc_cksum.S | 187 | ||||
-rw-r--r-- | sys/arch/mvme68k/stand/sboot/srec.c | 155 |
5 files changed, 783 insertions, 0 deletions
diff --git a/sys/arch/mvme68k/stand/sboot/XBUG.S b/sys/arch/mvme68k/stand/sboot/XBUG.S new file mode 100644 index 00000000000..8b1e52f76a6 --- /dev/null +++ b/sys/arch/mvme68k/stand/sboot/XBUG.S @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1995 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed Theo de Raadt + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Theo sez: I wrote a bootrom for the MVME147 *years* ago. To write + * this ROM I copied a few chunks from the old bootrom, like this piece: + * + * "watch this, the moto bastard struck here, shouldn't have hired people + * from intel I tried to tell them... + * "BOOT" + * offset from baseaddr to entry point. + * offset from baseaddr to first word after checksum + * garbage + * checksum made with CS command + * No need to change any of this unless you try to take our names out + * of there. Ie. don't touch." + */ + + .text +bootlabel: .ascii "BOOT" + .long bootstart-0xffa00000 | for rom install + .long bootlabelend - bootlabel + .asciz "VME147 rboot Copyright (c) 1995 Theo de Raadt" + .align 2 +bootstart: jmp bssclr + .word 0x229c | XXX bitching cksum! +bootlabelend: + .word 0 + + | clear bss and the kernel location +bssclr: movl #_edata,a0 + movl #_end - _edata,d0 +1: clrb a0@+ + subql #1,d0 + bpl 1b + + | rip the data segment from ROM into ram.. + movl #_etext,a2 | start of data + movl #0x4000,a1 | shovel address + movl #_edata - _etext,d0 +1: movb a2@+,a1@+ + subql #1,d0 + bpl 1b + + bra start diff --git a/sys/arch/mvme68k/stand/sboot/XSRT0.S b/sys/arch/mvme68k/stand/sboot/XSRT0.S new file mode 100644 index 00000000000..5d14a09a7c0 --- /dev/null +++ b/sys/arch/mvme68k/stand/sboot/XSRT0.S @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1995 Charles D. Cranor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles D. Cranor. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + | start at 0x4000, load at 0xa000, stack at 0x9ff0. + .text + .globl start +start: movb #0,_reboot + jra Ldoit +restart: movb #1,_reboot | fall through + +Ldoit: movl #0x00006ff0,sp + jsr _main + + .globl ___main +___main: rts diff --git a/sys/arch/mvme68k/stand/sboot/if_le.c b/sys/arch/mvme68k/stand/sboot/if_le.c new file mode 100644 index 00000000000..2f75f839d8c --- /dev/null +++ b/sys/arch/mvme68k/stand/sboot/if_le.c @@ -0,0 +1,327 @@ +/* $NetBSD: le_poll.c,v 1.3 1994/10/26 09:11:48 cgd Exp $ */ + +/* + * Copyright (c) 1993 Adam Glass + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Glass. + * 4. The name of the Author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include "sboot.h" +#include "if_lereg.h" + +struct { + struct lereg1 *sc_r1; /* LANCE registers */ + struct lereg2 *sc_r2; /* RAM */ + int next_rmd; + int next_tmd; +} le_softc; + +void +le_error(str, ler1) + char *str; + struct lereg1 *ler1; +{ + /* ler1->ler1_rap = LE_CSRO done in caller */ + if (ler1->ler1_rdp & LE_C0_BABL) { + printf("le0: been babbling, found by '%s'\n", str); + callrom(); + } + if (ler1->ler1_rdp & LE_C0_CERR) { + ler1->ler1_rdp = LE_C0_CERR; + } + if (ler1->ler1_rdp & LE_C0_MISS) { + ler1->ler1_rdp = LE_C0_MISS; + } + if (ler1->ler1_rdp & LE_C0_MERR) { + printf("le0: memory error in '%s'\n", str); + callrom(); + } +} + +void +le_reset(myea) + u_char *myea; +{ + struct lereg1 *ler1 = le_softc.sc_r1; + struct lereg2 *ler2 = le_softc.sc_r2; + unsigned int a; + int timo = 100000, stat, i; + + ler1->ler1_rap = LE_CSR0; + ler1->ler1_rdp = LE_C0_STOP; /* do nothing until we are finished */ + + bzero(ler2, sizeof(*ler2)); + + ler2->ler2_mode = LE_MODE_NORMAL; + ler2->ler2_padr[0] = myea[1]; + ler2->ler2_padr[1] = myea[0]; + ler2->ler2_padr[2] = myea[3]; + ler2->ler2_padr[3] = myea[2]; + ler2->ler2_padr[4] = myea[5]; + ler2->ler2_padr[5] = myea[4]; + + + ler2->ler2_ladrf0 = 0; + ler2->ler2_ladrf1 = 0; + + a = (u_int) ler2->ler2_rmd; + ler2->ler2_rlen = LE_RLEN | (a >> 16); + ler2->ler2_rdra = a & LE_ADDR_LOW_MASK; + + a = (u_int) ler2->ler2_tmd; + ler2->ler2_tlen = LE_TLEN | (a >> 16); + ler2->ler2_tdra = a & LE_ADDR_LOW_MASK; + + ler1->ler1_rap = LE_CSR1; + a = (u_int) ler2; + ler1->ler1_rdp = a & LE_ADDR_LOW_MASK; + ler1->ler1_rap = LE_CSR2; + ler1->ler1_rdp = a >> 16; + + for (i = 0; i < LERBUF; i++) { + a = (u_int) & ler2->ler2_rbuf[i]; + ler2->ler2_rmd[i].rmd0 = a & LE_ADDR_LOW_MASK; + ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN; + ler2->ler2_rmd[i].rmd1_hadr = a >> 16; + ler2->ler2_rmd[i].rmd2 = -LEMTU; + ler2->ler2_rmd[i].rmd3 = 0; + } + for (i = 0; i < LETBUF; i++) { + a = (u_int) & ler2->ler2_tbuf[i]; + ler2->ler2_tmd[i].tmd0 = a & LE_ADDR_LOW_MASK; + ler2->ler2_tmd[i].tmd1_bits = 0; + ler2->ler2_tmd[i].tmd1_hadr = a >> 16; + ler2->ler2_tmd[i].tmd2 = 0; + ler2->ler2_tmd[i].tmd3 = 0; + } + + ler1->ler1_rap = LE_CSR3; + ler1->ler1_rdp = LE_C3_BSWP; + + ler1->ler1_rap = LE_CSR0; + ler1->ler1_rdp = LE_C0_INIT; + do { + if (--timo == 0) { + printf("le0: init timeout, stat = 0x%x\n", stat); + break; + } + stat = ler1->ler1_rdp; + } while ((stat & LE_C0_IDON) == 0); + + ler1->ler1_rdp = LE_C0_IDON; + le_softc.next_rmd = 0; + le_softc.next_tmd = 0; + ler1->ler1_rap = LE_CSR0; + ler1->ler1_rdp = LE_C0_STRT; +} + +int +le_poll(pkt, len) + void *pkt; + int len; +{ + struct lereg1 *ler1 = le_softc.sc_r1; + struct lereg2 *ler2 = le_softc.sc_r2; + unsigned int a; + int length; + struct lermd *rmd; + + ler1->ler1_rap = LE_CSR0; + if ((ler1->ler1_rdp & LE_C0_RINT) != 0) + ler1->ler1_rdp = LE_C0_RINT; + rmd = &ler2->ler2_rmd[le_softc.next_rmd]; + if (rmd->rmd1_bits & LE_R1_OWN) { + return (0); + } + if (ler1->ler1_rdp & LE_C0_ERR) + le_error("le_poll", ler1); + if (rmd->rmd1_bits & LE_R1_ERR) { + printf("le0_poll: rmd status 0x%x\n", rmd->rmd1_bits); + length = 0; + goto cleanup; + } + if ((rmd->rmd1_bits & (LE_R1_STP | LE_R1_ENP)) != (LE_R1_STP | LE_R1_ENP)) { + printf("le_poll: chained packet\n"); + callrom(); + } + length = rmd->rmd3; + if (length >= LEMTU) { + length = 0; + printf("csr0 when bad things happen: %x\n", ler1->ler1_rdp); + callrom(); + goto cleanup; + } + if (!length) + goto cleanup; + length -= 4; + if (length > 0) + bcopy((char *) &ler2->ler2_rbuf[le_softc.next_rmd], pkt, length); + +cleanup: + a = (u_int) & ler2->ler2_rbuf[le_softc.next_rmd]; + rmd->rmd0 = a & LE_ADDR_LOW_MASK; + rmd->rmd1_hadr = a >> 16; + rmd->rmd2 = -LEMTU; + le_softc.next_rmd = + (le_softc.next_rmd == (LERBUF - 1)) ? 0 : (le_softc.next_rmd + 1); + rmd->rmd1_bits = LE_R1_OWN; + return length; +} + +int +le_put(pkt, len) + u_char *pkt; + size_t len; +{ + struct lereg1 *ler1 = le_softc.sc_r1; + struct lereg2 *ler2 = le_softc.sc_r2; + struct letmd *tmd; + int timo = 100000, stat, i; + unsigned int a; + + ler1->ler1_rap = LE_CSR0; + if (ler1->ler1_rdp & LE_C0_ERR) + le_error("le_put(way before xmit)", ler1); + tmd = &ler2->ler2_tmd[le_softc.next_tmd]; + while (tmd->tmd1_bits & LE_T1_OWN) { + printf("le0: output buffer busy\n"); + } + bcopy(pkt, (char *) ler2->ler2_tbuf[le_softc.next_tmd], len); + if (len < 64) + tmd->tmd2 = -64; + else + tmd->tmd2 = -len; + tmd->tmd3 = 0; + if (ler1->ler1_rdp & LE_C0_ERR) + le_error("le_put(before xmit)", ler1); + tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP | LE_T1_OWN; + a = (u_int) & ler2->ler2_tbuf[le_softc.next_tmd]; + tmd->tmd0 = a & LE_ADDR_LOW_MASK; + tmd->tmd1_hadr = a >> 16; + ler1->ler1_rdp = LE_C0_TDMD; + if (ler1->ler1_rdp & LE_C0_ERR) + le_error("le_put(after xmit)", ler1); + do { + if (--timo == 0) { + printf("le0: transmit timeout, stat = 0x%x\n", + stat); + if (ler1->ler1_rdp & LE_C0_ERR) + le_error("le_put(timeout)", ler1); + break; + } + stat = ler1->ler1_rdp; + } while ((stat & LE_C0_TINT) == 0); + ler1->ler1_rdp = LE_C0_TINT; + if (ler1->ler1_rdp & LE_C0_ERR) { + if ((ler1->ler1_rdp & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR)) != + LE_C0_CERR) + printf("le_put: xmit error, buf %d\n", le_softc.next_tmd); + le_error("le_put(xmit error)", ler1); + } + le_softc.next_tmd = 0; +/* (le_softc.next_tmd == (LETBUF - 1)) ? 0 : le_softc.next_tmd + 1;*/ + if (tmd->tmd1_bits & LE_T1_ERR) { + printf("le0: transmit error, error = 0x%x\n", + tmd->tmd3); + return -1; + } + return len; +} + +int +le_get(pkt, len, timeout) + u_char *pkt; + size_t len; + u_long timeout; +{ + int cc; + int now, then; + int stopat = time() + timeout; + then = 0; + + cc = 0; + while ((now = time()) < stopat && !cc) { + cc = le_poll(pkt, len); + if (then != now) { +#ifdef LE_DEBUG + printf("%d \r", stopat - now); +#endif + then = now; + } + if (cc && (pkt[0] != myea[0] || pkt[1] != myea[1] || + pkt[2] != myea[2] || pkt[3] != myea[3] || + pkt[4] != myea[4] || pkt[5] != myea[5])) { + cc = 0; /* ignore broadcast / multicast */ +#ifdef LE_DEBUG + printf("reject (%d sec left)\n", stopat - now); +#endif + } + } +#ifdef LE_DEBUG + printf("\n"); +#endif + return cc; +} + +void +le_init() +{ + caddr_t addr; + int *ea = (int *) LANCE_ADDR; + u_long *eram = (u_long *) ERAM_ADDR; + u_long e = *ea; + if ((e & 0x2fffff00) == 0x2fffff00) { + printf("ERROR: ethernet address not set! Use LSAD.\n"); + callrom(); + } + myea[0] = 0x08; + myea[1] = 0x00; + myea[2] = 0x3e; + e = e >> 8; + myea[5] = e & 0xff; + e = e >> 8; + myea[4] = e & 0xff; + e = e >> 8; + myea[3] = e; + printf("le0: ethernet address: %x:%x:%x:%x:%x:%x\n", + myea[0], myea[1], myea[2], myea[3], myea[4], myea[5]); + bzero(&le_softc, sizeof(le_softc)); + le_softc.sc_r1 = (struct lereg1 *) LANCE_REG_ADDR; + le_softc.sc_r2 = (struct lereg2 *) (*eram - (1024 * 1024)); + le_reset(myea); +} + +void +le_end() +{ + struct lereg1 *ler1 = le_softc.sc_r1; + + ler1->ler1_rap = LE_CSR0; + ler1->ler1_rdp = LE_C0_STOP; +} diff --git a/sys/arch/mvme68k/stand/sboot/oc_cksum.S b/sys/arch/mvme68k/stand/sboot/oc_cksum.S new file mode 100644 index 00000000000..2c9d6a63a24 --- /dev/null +++ b/sys/arch/mvme68k/stand/sboot/oc_cksum.S @@ -0,0 +1,187 @@ +| $NetBSD: oc_cksum.s,v 1.4 1994/10/26 07:51:13 cgd Exp $ + +| Copyright (c) 1988 Regents of the University of California. +| All rights reserved. +| +| Redistribution and use in source and binary forms, with or without +| modification, are permitted provided that the following conditions +| are met: +| 1. Redistributions of source code must retain the above copyright +| notice, this list of conditions and the following disclaimer. +| 2. Redistributions in binary form must reproduce the above copyright +| notice, this list of conditions and the following disclaimer in the +| documentation and/or other materials provided with the distribution. +| 3. All advertising materials mentioning features or use of this software +| must display the following acknowledgement: +| This product includes software developed by the University of +| California, Berkeley and its contributors. +| 4. Neither the name of the University nor the names of its contributors +| may be used to endorse or promote products derived from this software +| without specific prior written permission. +| +| THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +| OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +| SUCH DAMAGE. +| +| @(#)oc_cksum.s 7.2 (Berkeley) 11/3/90 +| +| +| oc_cksum: ones complement 16 bit checksum for MC68020. +| +| oc_cksum (buffer, count, strtval) +| +| Do a 16 bit ones complement sum of 'count' bytes from 'buffer'. +| 'strtval' is the starting value of the sum (usually zero). +| +| It simplifies life in in_cksum if strtval can be >= 2^16. +| This routine will work as long as strtval is < 2^31. +| +| Performance +| ----------- +| This routine is intended for MC 68020s but should also work +| for 68030s. It (deliberately) does not worry about the alignment +| of the buffer so will only work on a 68010 if the buffer is +| aligned on an even address. (Also, a routine written to use +| 68010 "loop mode" would almost certainly be faster than this +| code on a 68010). +| +| We do not worry about alignment because this routine is frequently +| called with small counts: 20 bytes for IP header checksums and 40 +| bytes for TCP ack checksums. For these small counts, testing for +| bad alignment adds ~10% to the per-call cost. Since, by the nature +| of the kernel allocator, the data we are called with is almost +| always longword aligned, there is no benefit to this added cost +| and we are better off letting the loop take a big performance hit +| in the rare cases where we are handed an unaligned buffer. +| +| Loop unrolling constants of 2, 4, 8, 16, 32 and 64 times were +| tested on random data on four different types of processors (see +| list below -- 64 was the largest unrolling because anything more +| overflows the 68020 Icache). On all the processors, the +| throughput asymptote was located between 8 and 16 (closer to 8). +| However, 16 was substantially better than 8 for small counts. +| (It is clear why this happens for a count of 40: unroll-8 pays a +| loop branch cost and unroll-16 does not. But the tests also showed +| that 16 was better than 8 for a count of 20. It is not obvious to +| me why.) So, since 16 was good for both large and small counts, +| the loop below is unrolled 16 times. +| +| The processors tested and their average time to checksum 1024 bytes +| of random data were: +| Sun 3/50 (15MHz) 190 us/KB +| Sun 3/180 (16.6MHz) 175 us/KB +| Sun 3/60 (20MHz) 134 us/KB +| Sun 3/280 (25MHz) 95 us/KB +| +| The cost of calling this routine was typically 10% of the per- +| kilobyte cost. E.g., checksumming zero bytes on a 3/60 cost 9us +| and each additional byte cost 125ns. With the high fixed cost, +| it would clearly be a gain to "inline" this routine -- the +| subroutine call adds 400% overhead to an IP header checksum. +| However, in absolute terms, inlining would only gain 10us per +| packet -- a 1% effect for a 1ms ethernet packet. This is not +| enough gain to be worth the effort. + +#include <machine/asm.h> + + .text + + .text; .even; .globl _oc_cksum; _oc_cksum: + movl sp@(4),a0 | get buffer ptr + movl sp@(8),d1 | get byte count + movl sp@(12),d0 | get starting value + movl d2,sp@- | free a reg + + | test for possible 1, 2 or 3 bytes of excess at end + | of buffer. The usual case is no excess (the usual + | case is header checksums) so we give that the faster + | 'not taken' leg of the compare. (We do the excess + | first because we are about the trash the low order + | bits of the count in d1.) + + btst #0,d1 + jne L5 | if one or three bytes excess + btst #1,d1 + jne L7 | if two bytes excess +L1: + movl d1,d2 + lsrl #6,d1 | make cnt into # of 64 byte chunks + andl #0x3c,d2 | then find fractions of a chunk + negl d2 + andb #0xf,cc | clear X + jmp pc@(L3-.-2:b,d2) +L2: + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 + movl a0@+,d2 + addxl d2,d0 +L3: + dbra d1,L2 | (NB- dbra does not affect X) + + movl d0,d1 | fold 32 bit sum to 16 bits + swap d1 | (NB- swap does not affect X) + addxw d1,d0 + jcc L4 + addw #1,d0 +L4: + andl #0xffff,d0 + movl sp@+,d2 + rts + +L5: | deal with 1 or 3 excess bytes at the end of the buffer. + btst #1,d1 + jeq L6 | if 1 excess + + | 3 bytes excess + clrl d2 + movw a0@(-3,d1:l),d2 | add in last full word then drop + addl d2,d0 | through to pick up last byte + +L6: | 1 byte excess + clrl d2 + movb a0@(-1,d1:l),d2 + lsll #8,d2 + addl d2,d0 + jra L1 + +L7: | 2 bytes excess + clrl d2 + movw a0@(-2,d1:l),d2 + addl d2,d0 + jra L1 diff --git a/sys/arch/mvme68k/stand/sboot/srec.c b/sys/arch/mvme68k/stand/sboot/srec.c new file mode 100644 index 00000000000..59ff4368995 --- /dev/null +++ b/sys/arch/mvme68k/stand/sboot/srec.c @@ -0,0 +1,155 @@ +/* + * convert binary file to Srecord format + * XXX srec generates improper checksums for 4-byte dumps + */ +#include <stdio.h> +#include <ctype.h> + +int get32(); +void put32(); +void sput(); +void put(); +int checksum(); + +int mask; +int size; + +main(argc, argv) + int argc; + char *argv[]; +{ + char buf[32]; + int cc; + int base; + int addr; + char *name; + + if (argc != 4) { + fprintf(stderr, "usage: %s {size} {hex_addr} {name}\n", argv[0]); + fprintf(stderr, "Size = 2, 3, or 4 byte address\n"); + exit(1); + } + sscanf(argv[1], "%x", &size); + mask = (1 << (size * 8)) - 1; + if (!mask) + mask = (-1); + sscanf(argv[2], "%x", &base); + name = argv[3]; + + if (size == 2) + printf("S0%02X%04X", 2 + strlen(name) + 1, 0); + if (size == 3) + printf("S0%02X%06X", 3 + strlen(name) + 1, 0); + if (size == 4) + printf("S0%02X%08X", 4 + strlen(name) + 1, 0); + sput(name); + printf("%02X\n", checksum(0, name, strlen(name), size)); + + addr = base; + for (;;) { + cc = get32(buf); + if (cc > 0) { + put32(cc, addr, buf, size, mask); + addr += cc; + } else + break; + } + + buf[0] = base >> 8; + buf[1] = base; + printf("S%d%02X", 11 - size, 2 + 1); + switch (size) { + case 2: + printf("%04X", base & mask); + break; + case 3: + printf("%06X", base & mask); + break; + case 4: + printf("%08X", base & mask); + break; + } + + /* + * kludge -> don't know why you have to add the +1 = works + * for size =3 at least + */ + printf("%02X\n", checksum(base, (char *) 0, 0, size) + 1); + exit (0); +} + +int +get32(buf) + char buf[]; +{ + char *cp = buf; + int i; + int c; + + for (i = 0; i < 32; ++i) { + if ((c = getchar()) != EOF) + *cp++ = c; + else + break; + } + return (cp - buf); +} + +void +put32(len, addr, buf, size, mask) + int len; + int addr; + char buf[]; + int size, mask; +{ + char *cp = buf; + int i; + + if (size == 2) + printf("S1%02X%04X", 2 + len + 1, addr & mask); + if (size == 3) + printf("S2%02X%06X", 3 + len + 1, addr & mask); + if (size == 4) + printf("S3%02X%08X", 4 + len + 1, addr & mask); + for (i = 0; i < len; ++i) + put(*cp++); + printf("%02X\n", checksum(addr, buf, len, size)); +} + +void +sput(s) + char *s; +{ + while (*s != '\0') + put(*s++); +} + +void +put(c) + int c; +{ + printf("%02X", c & 0xff); +} + +int +checksum(addr, buf, len, size) + int addr; + char buf[]; + int len; + int size; +{ + char *cp = buf; + int sum = 0xff - 1 - size - (len & 0xff); + int i; + + if (size == 4) + sum -= (addr >> 24) & 0xff; + if (size >= 3) + sum -= (addr >> 16) & 0xff; + sum -= (addr >> 8) & 0xff; + sum -= addr & 0xff; + for (i = 0; i < len; ++i) { + sum -= *cp++ & 0xff; + } + return (sum & 0xff); +} |