summaryrefslogtreecommitdiff
path: root/sys/arch/mvme68k/stand/sboot
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 10:44:53 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 10:44:53 +0000
commit49235ceee0c25492d4ca35194d7c72838a9ec284 (patch)
tree14f77677934d4f4cb9baa428691ace792fd0deed /sys/arch/mvme68k/stand/sboot
parentc9328c850e70436131e06a34f73c14cc230c18f9 (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.S72
-rw-r--r--sys/arch/mvme68k/stand/sboot/XSRT0.S42
-rw-r--r--sys/arch/mvme68k/stand/sboot/if_le.c327
-rw-r--r--sys/arch/mvme68k/stand/sboot/oc_cksum.S187
-rw-r--r--sys/arch/mvme68k/stand/sboot/srec.c155
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);
+}