summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2008-05-10 20:06:28 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2008-05-10 20:06:28 +0000
commitba4e3222839204021e000d34b676712b9aa14b24 (patch)
tree0c03cc82f4b06da1e609511ccbcac0c0bff64170 /sys/arch
parentf0b7557aa0bd4ef68437345a996cf2cc749c70db (diff)
First stab at a bootloader for the Thecus N1200.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/socppc/stand/Makefile5
-rw-r--r--sys/arch/socppc/stand/boot/Makefile53
-rw-r--r--sys/arch/socppc/stand/boot/clock.c55
-rw-r--r--sys/arch/socppc/stand/boot/conf.c69
-rw-r--r--sys/arch/socppc/stand/boot/dev_socppc.c115
-rw-r--r--sys/arch/socppc/stand/boot/devopen.c129
-rw-r--r--sys/arch/socppc/stand/boot/exec.c63
-rw-r--r--sys/arch/socppc/stand/boot/libsa.h42
-rw-r--r--sys/arch/socppc/stand/boot/machdep.c62
-rw-r--r--sys/arch/socppc/stand/boot/ns16550.c137
-rw-r--r--sys/arch/socppc/stand/boot/pciide.c77
-rw-r--r--sys/arch/socppc/stand/boot/start.S13
-rw-r--r--sys/arch/socppc/stand/boot/time.c8
-rw-r--r--sys/arch/socppc/stand/boot/wd.c322
-rw-r--r--sys/arch/socppc/stand/boot/wdc.c383
-rw-r--r--sys/arch/socppc/stand/boot/wdvar.h134
16 files changed, 1667 insertions, 0 deletions
diff --git a/sys/arch/socppc/stand/Makefile b/sys/arch/socppc/stand/Makefile
new file mode 100644
index 00000000000..981d45cb811
--- /dev/null
+++ b/sys/arch/socppc/stand/Makefile
@@ -0,0 +1,5 @@
+# $OpenBSD: Makefile,v 1.1 2008/05/10 20:06:26 kettenis Exp $
+
+SUBDIR=boot
+
+.include <bsd.subdir.mk>
diff --git a/sys/arch/socppc/stand/boot/Makefile b/sys/arch/socppc/stand/boot/Makefile
new file mode 100644
index 00000000000..59e16d31598
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/Makefile
@@ -0,0 +1,53 @@
+# $OpenBSD: Makefile,v 1.1 2008/05/10 20:06:26 kettenis Exp $
+
+NOMAN=
+
+.if ${MACHINE} == "socppc"
+PROG= boot
+S= ${.CURDIR}/../../../..
+
+.PATH: ${S}/stand/boot
+.PATH: ${S}/lib/libsa
+
+CPPFLAGS+= -D_STANDALONE
+CPPFLAGS+= -nostdinc -I../.. -I. -I${.CURDIR} -I${S}
+CPPFLAGS+= -DCONADDR=0xe0004500UL -DCONSPEED=115200
+CPPFLAGS+= -DNS16550_FREQ=266000000
+
+COPTS+= -ffreestanding -fno-stack-protector -ffixed-r29
+
+SRCS= start.S
+SRCS+= boot.c cmd.c vars.c
+SRCS+= conf.c devopen.c exec.c machdep.c dev_socppc.c time.c
+SRCS+= clock.c ns16550.c wd.c wdc.c pciide.c
+SRCS+= ctime.c strtol.c
+
+.PATH: ${S}/lib/libkern/arch/powerpc ${S}/lib/libkern
+#SRCS+= divsi3.S divdi3.c moddi3.c qdivrem.c strlcpy.c strlen.c ashrdi3.c
+SRCS+= strlcpy.c strlen.c ashrdi3.c
+
+### find out what to use for libsa
+SA_AS= library
+SAREL=
+USE_LOADFILE= yes
+.include "${S}/lib/libsa/Makefile.inc"
+LIBSA= ${SALIB}
+
+LDFLAGS= -Ttext 0x100000
+
+${PROG}: ${OBJS} ${LIBSA}
+ ${LD} ${LDFLAGS} -o boot ${OBJS} ${LIBSA} ${LIBSA}
+
+.if !make(obj)
+.BEGIN:
+ @([ -h machine ] || ln -s ${.CURDIR}/../../../${MACHINE}/include machine)
+ @([ -h powerpc ] || ln -s ${.CURDIR}/../../../powerpc/include powerpc)
+.NOPATH: machine powerpc
+CLEANFILES+= machine powerpc
+.endif
+
+.else
+NOPROG=
+.endif
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/socppc/stand/boot/clock.c b/sys/arch/socppc/stand/boot/clock.c
new file mode 100644
index 00000000000..10ea5229735
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/clock.c
@@ -0,0 +1,55 @@
+/* $OpenBSD: clock.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+/* $NetBSD: clock.c,v 1.1 2003/06/25 17:24:22 cdi Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Manuel Bouyer.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/types.h>
+
+#include "libsa.h"
+
+#define DELAY_CALIBRATE 1000
+
+void
+delay(int ms)
+{
+ /*
+ * XXX need *real* clock calibration.
+ */
+ volatile register int N = ms * DELAY_CALIBRATE;
+ for (; --N;)
+ ;
+}
diff --git a/sys/arch/socppc/stand/boot/conf.c b/sys/arch/socppc/stand/boot/conf.c
new file mode 100644
index 00000000000..648986179c4
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/conf.c
@@ -0,0 +1,69 @@
+/* $OpenBSD: conf.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+/* $NetBSD: conf.c,v 1.4 2005/12/11 12:17:06 christos Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The 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. 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.
+ *
+ * @(#)conf.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+
+#include <dev/cons.h>
+
+#include "libsa.h"
+#include <lib/libsa/ufs.h>
+
+const char version[] = "0.1";
+int debug = 0;
+
+/*
+ * Device configuration
+ */
+struct devsw devsw[] = {
+ { "wd", wdstrategy, wdopen, wdclose, noioctl },
+};
+int ndevs = NENTS(devsw);
+
+/*
+ * Filesystem configuration
+ */
+struct fs_ops file_system[] = {
+ { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek,
+ ufs_stat, ufs_readdir }
+};
+int nfsys = NENTS(file_system);
+
+/*
+ * Console configuration
+ */
+struct consdev constab[] = {
+ { com_probe, com_init, com_getc, com_putc },
+ { NULL }
+};
+struct consdev *cn_tab;
diff --git a/sys/arch/socppc/stand/boot/dev_socppc.c b/sys/arch/socppc/stand/boot/dev_socppc.c
new file mode 100644
index 00000000000..9fa311e57f7
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/dev_socppc.c
@@ -0,0 +1,115 @@
+/* $OpenBSD: dev_socppc.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <dev/cons.h>
+
+#include "libsa.h"
+
+const char cdevs[][4] = {
+ "cn", "", "", "", "", "", "", "",
+ "", "", "", "", "com"
+};
+const int ncdevs = NENTS(cdevs);
+
+void
+devboot(dev_t dev, char *p)
+{
+ strlcpy(p, "wd0a", 5);
+}
+
+int
+cnspeed(dev_t dev, int sp)
+{
+ return CONSPEED;
+}
+
+int pch_pos;
+
+void
+putchar(c)
+ int c;
+{
+ switch(c) {
+ case '\177': /* DEL erases */
+ cnputc('\b');
+ cnputc(' ');
+ case '\b':
+ cnputc('\b');
+ if (pch_pos)
+ pch_pos--;
+ break;
+ case '\t':
+ do
+ cnputc(' ');
+ while(++pch_pos % 8);
+ break;
+ case '\n':
+ case '\r':
+ cnputc(c);
+ pch_pos=0;
+ break;
+ default:
+ cnputc(c);
+ pch_pos++;
+ break;
+ }
+}
+
+int
+getchar()
+{
+ int c = cngetc();
+
+ if (c == '\r')
+ c = '\n';
+
+ if ((c < ' ' && c != '\n') || c == '\177')
+ return(c);
+
+ putchar(c);
+
+ return(c);
+}
+
+char ttyname_buf[8];
+
+char *
+ttyname(int fd)
+{
+ snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d",
+ cdevs[major(cn_tab->cn_dev)], minor(cn_tab->cn_dev));
+
+ return ttyname_buf;
+}
+
+dev_t
+ttydev(char *name)
+{
+ int i, unit = -1;
+ char *no = name + strlen(name) - 1;
+
+ while (no >= name && *no >= '0' && *no <= '9')
+ unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0';
+ if (no < name || unit < 0)
+ return NODEV;
+ for (i = 0; i < ncdevs; i++)
+ if (strncmp(name, cdevs[i], no - name + 1) == 0)
+ return (makedev(i, unit));
+ return NODEV;
+}
diff --git a/sys/arch/socppc/stand/boot/devopen.c b/sys/arch/socppc/stand/boot/devopen.c
new file mode 100644
index 00000000000..717427c3ee5
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/devopen.c
@@ -0,0 +1,129 @@
+/* $OpenBSD: devopen.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+/* $NetBSD: devopen.c,v 1.1 2003/06/25 17:24:22 cdi Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Rolf Grossmann.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 "libsa.h"
+
+#define MAXDEVNAME 16
+
+/*
+ * Parse a device spec.
+ *
+ * [A-Za-z]*[0-9]*[A-Za-z]:file
+ * dev uint part
+ */
+int
+devparse(const char *fname, int *dev, int *unit, int *part, const char **file)
+{
+ const char *s;
+
+ *unit = 0; /* default to wd0a */
+ *part = 0;
+ *dev = 0;
+
+ s = strchr(fname, ':');
+ if (s != NULL) {
+ int devlen;
+ int i, u, p;
+ struct devsw *dp;
+ char devname[MAXDEVNAME];
+
+ devlen = s - fname;
+ if (devlen > MAXDEVNAME)
+ return (EINVAL);
+
+ /* extract device name */
+ for (i = 0; isalpha(fname[i]) && (i < devlen); i++)
+ devname[i] = fname[i];
+ devname[i] = 0;
+
+ if (!isdigit(fname[i]))
+ return (EUNIT);
+
+ /* device number */
+ for (u = 0; isdigit(fname[i]) && (i < devlen); i++)
+ u = u * 10 + (fname[i] - '0');
+
+ if (!isalpha(fname[i]))
+ return (EPART);
+
+ /* partition number */
+ if (i < devlen)
+ p = fname[i++] - 'a';
+
+ if (i != devlen)
+ return (ENXIO);
+
+ /* check device name */
+ for (dp = devsw, i = 0; i < ndevs; dp++, i++) {
+ if (dp->dv_name && !strcmp(devname, dp->dv_name))
+ break;
+ }
+
+ if (i >= ndevs)
+ return (ENXIO);
+
+ *unit = u;
+ *part = p;
+ *dev = i;
+ fname = ++s;
+ }
+
+ *file = fname;
+
+ return (0);
+}
+
+int
+devopen(struct open_file *f, const char *fname, char **file)
+{
+ struct devsw *dp;
+ int dev, unit, part, error;
+
+ error = devparse(fname, &dev, &unit, &part, (const char **)file);
+ if (error)
+ return (error);
+
+ dp = &devsw[dev];
+ if ((void *)dp->dv_open == (void *)nodev)
+ return (ENXIO);
+
+ f->f_dev = dp;
+
+ return (*dp->dv_open)(f, unit, part);
+}
diff --git a/sys/arch/socppc/stand/boot/exec.c b/sys/arch/socppc/stand/boot/exec.c
new file mode 100644
index 00000000000..ab79ebc341e
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/exec.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: exec.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2006 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+
+#include <lib/libsa/loadfile.h>
+
+#ifdef BOOT_ELF
+#include <sys/exec_elf.h>
+#endif
+
+#include <sys/reboot.h>
+#include <stand/boot/cmd.h>
+#include <machine/bootconfig.h>
+
+typedef void (*startfuncp)(void) __attribute__ ((noreturn));
+
+void
+run_loadfile(u_long *marks, int howto)
+{
+ char *cp;
+
+ cp = (char *)0x00200000 - MAX_BOOT_STRING - 1;
+
+#define BOOT_STRING_MAGIC 0x4f425344
+
+ *(int *)cp = BOOT_STRING_MAGIC;
+
+ cp += sizeof(int);
+ snprintf(cp, MAX_BOOT_STRING, "%s:%s -", cmd.bootdev, cmd.image);
+
+ while (*cp != '\0')
+ cp++;
+ if (howto & RB_ASKNAME)
+ *cp++ = 'a';
+ if (howto & RB_CONFIG)
+ *cp++ = 'c';
+ if (howto & RB_KDB)
+ *cp++ = 'd';
+ if (howto & RB_SINGLE)
+ *cp++ = 's';
+
+ *cp = '\0';
+
+ (*(startfuncp)(marks[MARK_ENTRY]))();
+
+ /* NOTREACHED */
+}
diff --git a/sys/arch/socppc/stand/boot/libsa.h b/sys/arch/socppc/stand/boot/libsa.h
new file mode 100644
index 00000000000..eabb1700485
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/libsa.h
@@ -0,0 +1,42 @@
+/* $OpenBSD: libsa.h,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <lib/libsa/stand.h>
+
+#define DEFAULT_KERNEL_ADDRESS 0
+
+#ifdef DEBUG
+#define DPRINTF(x) printf x;
+#else
+#define DPRINTF(x)
+#endif
+
+/*
+ * com
+ */
+void com_probe(struct consdev *);
+void com_init(struct consdev *);
+int com_getc(dev_t);
+void com_putc(dev_t, int);
+
+/*
+ * wd
+ */
+int wdstrategy(void *, int, daddr_t, size_t, void *, size_t *);
+int wdopen(struct open_file *, ...);
+int wdclose(struct open_file *);
diff --git a/sys/arch/socppc/stand/boot/machdep.c b/sys/arch/socppc/stand/boot/machdep.c
new file mode 100644
index 00000000000..f54cea14f9c
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/machdep.c
@@ -0,0 +1,62 @@
+/* $OpenBSD: machdep.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include "libsa.h"
+
+#define RPR 0xe0000918
+#define RPR_RSTE 0x52535445
+#define RCR 0xe000091c
+#define RCR_SWSR 0x00000001
+#define RCR_SWHR 0x00000002
+
+void
+machdep(void)
+{
+ cninit();
+
+{
+ extern u_int32_t wdc_base_addr;
+ wdc_base_addr = 0xe2000000;
+}
+
+}
+
+int
+main(void)
+{
+ extern char __bss_start[], _end[];
+ bzero(__bss_start, _end-__bss_start);
+
+ boot(0);
+ return 0;
+}
+
+void
+_rtt(void)
+{
+ uint32_t v;
+
+ *((volatile uint32_t *)(RPR)) = RPR_RSTE;
+ __asm __volatile("eieio");
+ *((volatile uint32_t *)(RCR)) = RCR_SWHR;
+
+ printf("RESET FAILED\n");
+ for (;;) ;
+}
diff --git a/sys/arch/socppc/stand/boot/ns16550.c b/sys/arch/socppc/stand/boot/ns16550.c
new file mode 100644
index 00000000000..3da8ac78308
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/ns16550.c
@@ -0,0 +1,137 @@
+/* $OpenBSD: ns16550.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+/* $NetBSD: ns16550.c,v 1.3 2005/12/24 20:07:03 perry Exp $ */
+
+/*
+ * Copyright (c) 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * 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 for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+/*
+ * This file provides console I/O routines for boards that use
+ * 16550-compatible UARTs.
+ */
+
+#include <sys/types.h>
+
+#include <dev/cons.h>
+#include <dev/ic/comreg.h>
+
+#include "libsa.h"
+
+#define INB(x) *((volatile uint8_t *) (CONADDR + (x)))
+#define OUTB(x, v) *((volatile uint8_t *) (CONADDR + (x))) = (v)
+
+#define ISSET(t,f) ((t) & (f))
+
+#ifndef NS16550_FREQ
+#define NS16550_FREQ COM_FREQ
+#endif
+
+static int
+comspeed(int speed)
+{
+#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
+
+ int x, err;
+
+ if (speed <= 0)
+ return (-1);
+ x = divrnd((NS16550_FREQ / 16), speed);
+ if (x <= 0)
+ return (-1);
+ err = divrnd((((quad_t)NS16550_FREQ) / 16) * 1000, speed * x) - 1000;
+ if (err < 0)
+ err = -err;
+ if (err > COM_TOLERANCE)
+ return (-1);
+ return (x);
+#undef divrnd
+}
+
+void
+com_probe(struct consdev *cn)
+{
+ cn->cn_pri = CN_LOWPRI;
+ cn->cn_dev = makedev(12, 0);
+}
+
+void
+com_init(struct consdev *cn)
+{
+ int rate;
+
+ OUTB(com_cfcr, LCR_DLAB);
+ rate = comspeed(CONSPEED);
+ OUTB(com_dlbl, rate);
+ OUTB(com_dlbh, rate >> 8);
+ OUTB(com_cfcr, LCR_8BITS);
+ OUTB(com_mcr, MCR_DTR | MCR_RTS);
+ OUTB(com_fifo,
+ FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
+ OUTB(com_ier, 0);
+}
+
+int
+com_getc(dev_t dev)
+{
+ uint8_t stat;
+
+ if (dev & 0x80)
+ return ISSET(stat = INB(com_lsr), LSR_RXRDY);
+
+ while (!ISSET(stat = INB(com_lsr), LSR_RXRDY))
+ /* spin */ ;
+ return (INB(com_data));
+}
+
+void
+com_putc(dev_t dev, int c)
+{
+ uint8_t stat;
+ int timo;
+
+ /* Wait for any pending transmission to finish. */
+ timo = 50000;
+ while (!ISSET(stat = INB(com_lsr), LSR_TXRDY) && --timo)
+ /* spin */ ;
+
+ OUTB(com_data, c);
+
+ /* Wait for this transmission to complete. */
+ timo = 1500000;
+ while (!ISSET(stat = INB(com_lsr), LSR_TXRDY) && --timo)
+ /* spin */ ;
+
+ /* Clear any interrupts generated by this transmission. */
+ (void) INB(com_iir);
+}
diff --git a/sys/arch/socppc/stand/boot/pciide.c b/sys/arch/socppc/stand/boot/pciide.c
new file mode 100644
index 00000000000..14535c8b1c3
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/pciide.c
@@ -0,0 +1,77 @@
+/* $OpenBSD: pciide.c,v 1.1 2008/05/10 20:06:27 kettenis Exp $ */
+/* $NetBSD: pciide.c,v 1.5 2005/12/11 12:17:06 christos Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/types.h>
+
+#include "libsa.h"
+#include "wdvar.h"
+
+u_int32_t wdc_base_addr = 0;
+
+int
+pciide_init(struct wdc_channel *chp, u_int chan)
+{
+ u_int32_t cmdreg, ctlreg;
+ int i;
+
+ /*
+ * two channels per chip, one drive per channel
+ */
+ if (chan >= PCIIDE_NUM_CHANNELS || wdc_base_addr == 0)
+ return (ENXIO);
+ chp->ndrives = 1;
+
+ DPRINTF(("[pciide] channel: %d\n", chan));
+
+ /*
+ * XXX map?
+ */
+ cmdreg = wdc_base_addr + chan * 0x10;
+ ctlreg = wdc_base_addr+0x8 + chan * 0x10;
+
+ /* set up cmd regsiters */
+ chp->c_cmdbase = (u_int8_t *)cmdreg;
+ chp->c_data = (u_int16_t *)(cmdreg + wd_data);
+ for (i = 0; i < WDC_NPORTS; i++)
+ chp->c_cmdreg[i] = chp->c_cmdbase + i;
+ /* set up shadow registers */
+ chp->c_cmdreg[wd_status] = chp->c_cmdreg[wd_command];
+ chp->c_cmdreg[wd_features] = chp->c_cmdreg[wd_precomp];
+ /* set up ctl registers */
+ chp->c_ctlbase = (u_int8_t *)ctlreg;
+
+ return (0);
+}
diff --git a/sys/arch/socppc/stand/boot/start.S b/sys/arch/socppc/stand/boot/start.S
new file mode 100644
index 00000000000..74d8e795052
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/start.S
@@ -0,0 +1,13 @@
+#include <machine/asm.h>
+
+#define STACKSIZE 8192
+
+ENTRY(_start)
+ lis %r1, stack@ha
+ addi %r1, %r1, stack@l
+ addi %r1, %r1, STACKSIZE
+
+ b _C_LABEL(main)
+
+ .data
+.lcomm stack,STACKSIZE,8
diff --git a/sys/arch/socppc/stand/boot/time.c b/sys/arch/socppc/stand/boot/time.c
new file mode 100644
index 00000000000..b4def65f22b
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/time.c
@@ -0,0 +1,8 @@
+#include <sys/types.h>
+
+#include "libsa.h"
+
+time_t
+getsecs(void)
+{
+}
diff --git a/sys/arch/socppc/stand/boot/wd.c b/sys/arch/socppc/stand/boot/wd.c
new file mode 100644
index 00000000000..8ab80b0519e
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/wd.c
@@ -0,0 +1,322 @@
+/* $OpenBSD: wd.c,v 1.1 2008/05/10 20:06:27 kettenis Exp $ */
+/* $NetBSD: wd.c,v 1.5 2005/12/11 12:17:06 christos Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Manuel Bouyer.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/types.h>
+#include <sys/stdint.h>
+
+#include <machine/param.h>
+
+#include "libsa.h"
+#include "wdvar.h"
+
+void wdprobe(void);
+int wd_get_params(struct wd_softc *wd);
+int wdgetdisklabel(struct wd_softc *wd);
+void wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp);
+
+struct wd_softc wd_devs[NUNITS];
+int wd_ndevs = -1;
+
+void
+wdprobe(void)
+{
+ struct wd_softc *wd = wd_devs;
+ u_int chan, drive, unit = 0;
+
+ for (chan = 0; chan < PCIIDE_NUM_CHANNELS; chan++) {
+ if (wdc_init(wd, chan) != 0)
+ continue;
+ for (drive = 0; drive < wd->sc_channel.ndrives; drive++) {
+ wd->sc_unit = unit;
+ wd->sc_drive = drive;
+
+ if (wd_get_params(wd) != 0)
+ continue;
+
+ DPRINTF(("wd%d: channel %d drive %d\n",
+ unit, chan, drive));
+ unit++;
+ wd++;
+ }
+ }
+
+ wd_ndevs = unit;
+}
+
+/*
+ * Get drive parameters through 'device identify' command.
+ */
+int
+wd_get_params(wd)
+ struct wd_softc *wd;
+{
+ int error;
+ unsigned char buf[DEV_BSIZE];
+
+ if ((error = wdc_exec_identify(wd, buf)) != 0)
+ return (error);
+
+#if BYTE_ORDER == BIG_ENDIAN
+ /*
+ * All the fields in the params structure are 16-bit integers
+ * except for the ID strings which are char strings. The
+ * 16-bit integers are currently in memory in little-endian,
+ * regardless of architecture. So, they need to be swapped on
+ * big-endian architectures before they are accessed through
+ * the ataparams structure.
+ *
+ * The swaps below avoid touching the char strings.
+ */
+ swap16_multi((u_int16_t *)buf, 10);
+ swap16_multi((u_int16_t *)buf + 20, 3);
+ swap16_multi((u_int16_t *)buf + 47, DEV_BSIZE / 2 - 47);
+#endif
+
+ wd->sc_params = *(struct ataparams *)buf;
+
+ /* 48-bit LBA addressing */
+ if ((wd->sc_params.atap_cmd2_en & ATAPI_CMD2_48AD) != 0) {
+ DPRINTF(("Drive supports LBA48.\n"));
+#if defined(_ENABLE_LBA48)
+ wd->sc_flags |= WDF_LBA48;
+#endif
+ }
+
+ /* Prior to ATA-4, LBA was optional. */
+ if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) {
+ DPRINTF(("Drive supports LBA.\n"));
+ wd->sc_flags |= WDF_LBA;
+ }
+
+ return (0);
+}
+
+/*
+ * Initialize disk label to the default value.
+ */
+void
+wdgetdefaultlabel(wd, lp)
+ struct wd_softc *wd;
+ struct disklabel *lp;
+{
+ memset(lp, 0, sizeof(struct disklabel));
+
+ lp->d_secsize = DEV_BSIZE;
+ lp->d_ntracks = wd->sc_params.atap_heads;
+ lp->d_nsectors = wd->sc_params.atap_sectors;
+ lp->d_ncylinders = wd->sc_params.atap_cylinders;
+ lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+
+ if (strcmp(wd->sc_params.atap_model, "ST506") == 0)
+ lp->d_type = DTYPE_ST506;
+ else
+ lp->d_type = DTYPE_ESDI;
+
+ strncpy(lp->d_typename, wd->sc_params.atap_model, 16);
+ strncpy(lp->d_packname, "fictitious", 16);
+ if (wd->sc_capacity > UINT32_MAX)
+ lp->d_secperunit = UINT32_MAX;
+ else
+ lp->d_secperunit = wd->sc_capacity;
+ lp->d_rpm = 3600;
+ lp->d_interleave = 1;
+ lp->d_flags = 0;
+
+ lp->d_partitions[RAW_PART].p_offset = 0;
+ lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
+ lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
+ lp->d_npartitions = MAXPARTITIONS; /* RAW_PART + 1 ??? */
+
+ lp->d_magic = DISKMAGIC;
+ lp->d_magic2 = DISKMAGIC;
+ lp->d_checksum = dkcksum(lp);
+}
+
+/*
+ * Read disk label from the device.
+ */
+int
+wdgetdisklabel(wd)
+ struct wd_softc *wd;
+{
+ char *msg;
+ int sector;
+ size_t rsize;
+ struct disklabel *lp;
+ unsigned char buf[DEV_BSIZE];
+ u_int16_t sig;
+
+ wdgetdefaultlabel(wd, &wd->sc_label);
+
+ /*
+ * Find OpenBSD Partition in DOS partition table.
+ */
+ sector = 0;
+ if (wdstrategy(wd, F_READ, DOSBBSECTOR, DEV_BSIZE, buf, &rsize))
+ return EOFFSET;
+
+ sig = letoh16(*(u_int16_t *)&buf[DOSMBR_SIGNATURE_OFF]);
+ if (sig == DOSMBR_SIGNATURE) {
+ int i;
+ struct dos_partition *dp = (struct dos_partition *)buf;
+
+ /*
+ * Lookup OpenBSD slice. If there is none, go ahead
+ * and try to read the disklabel off sector #0.
+ */
+
+ memcpy(dp, &buf[DOSPARTOFF], NDOSPART * sizeof(*dp));
+ for (i = 0; i < NDOSPART; i++) {
+ if (dp[i].dp_typ == DOSPTYP_OPENBSD) {
+ sector = letoh32(dp[i].dp_start);
+ break;
+ }
+ }
+ }
+
+ if (wdstrategy(wd, F_READ, sector + LABELSECTOR, DEV_BSIZE,
+ buf, &rsize))
+ return EOFFSET;
+
+ if ((msg = getdisklabel(buf + LABELOFFSET, &wd->sc_label)))
+ printf("wd%d: getdisklabel: %s\n", wd->sc_unit, msg);
+
+ lp = &wd->sc_label;
+
+ /* check partition */
+ if ((wd->sc_part >= lp->d_npartitions) ||
+ (lp->d_partitions[wd->sc_part].p_fstype == FS_UNUSED)) {
+ DPRINTF(("illegal partition\n"));
+ return (EPART);
+ }
+
+ DPRINTF(("label info: d_secsize %d, d_nsectors %d, d_ncylinders %d,"
+ "d_ntracks %d, d_secpercyl %d\n",
+ wd->sc_label.d_secsize,
+ wd->sc_label.d_nsectors,
+ wd->sc_label.d_ncylinders,
+ wd->sc_label.d_ntracks,
+ wd->sc_label.d_secpercyl));
+
+ return (0);
+}
+
+/*
+ * Open device (read drive parameters and disklabel)
+ */
+int
+wdopen(struct open_file *f, ...)
+{
+ int error;
+ va_list ap;
+ u_int unit, part, drive;
+ struct wd_softc *wd;
+
+ va_start(ap, f);
+ unit = va_arg(ap, u_int);
+ part = va_arg(ap, u_int);
+ va_end(ap);
+
+ DPRINTF(("wdopen: wd%d%c\n", unit, 'a' + part));
+
+ if (unit < 0 || unit >= NUNITS)
+ return (ENXIO);
+
+ if (wd_ndevs == -1)
+ wdprobe();
+
+ if (unit >= wd_ndevs)
+ return (ENXIO);
+
+ wd = &wd_devs[unit];
+ wd->sc_part = part;
+
+ if ((error = wdgetdisklabel(wd)) != 0)
+ return (error);
+
+ f->f_devdata = wd;
+ return (0);
+}
+
+/*
+ * Close device.
+ */
+int
+wdclose(struct open_file *f)
+{
+ return 0;
+}
+
+/*
+ * Read some data.
+ */
+int
+wdstrategy(f, rw, dblk, size, buf, rsize)
+ void *f;
+ int rw;
+ daddr_t dblk;
+ size_t size;
+ void *buf;
+ size_t *rsize;
+{
+ int i, nsect;
+ daddr_t blkno;
+ struct wd_softc *wd = f;
+
+ if (size == 0)
+ return (0);
+
+ if (rw != F_READ)
+ return EOPNOTSUPP;
+
+ nsect = howmany(size, wd->sc_label.d_secsize);
+ blkno = dblk + wd->sc_label.d_partitions[wd->sc_part].p_offset;
+
+ for (i = 0; i < nsect; i++, blkno++) {
+ int error;
+
+ if ((error = wdc_exec_read(wd, WDCC_READ, blkno, buf)) != 0)
+ return (error);
+
+ buf += wd->sc_label.d_secsize;
+ }
+
+ *rsize = size;
+ return (0);
+}
diff --git a/sys/arch/socppc/stand/boot/wdc.c b/sys/arch/socppc/stand/boot/wdc.c
new file mode 100644
index 00000000000..e2885c91462
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/wdc.c
@@ -0,0 +1,383 @@
+/* $OpenBSD: wdc.c,v 1.1 2008/05/10 20:06:27 kettenis Exp $ */
+/* $NetBSD: wdc.c,v 1.7 2005/12/11 12:17:06 christos Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Manuel Bouyer.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/types.h>
+#include <machine/param.h>
+
+#include "libsa.h"
+#include "wdvar.h"
+
+#define WDCDELAY 100
+#define WDCNDELAY_RST 31000 * 10
+
+static int wdcprobe(struct wdc_channel *chp);
+static int wdc_wait_for_ready(struct wdc_channel *chp);
+static int wdc_read_block(struct wd_softc *sc, struct wdc_command *wd_c);
+static int __wdcwait_reset(struct wdc_channel *chp, int drv_mask);
+
+/*
+ * Reset the controller.
+ */
+static int
+__wdcwait_reset(chp, drv_mask)
+ struct wdc_channel *chp;
+ int drv_mask;
+{
+ int timeout;
+ u_int8_t st0, st1;
+
+ /* wait for BSY to deassert */
+ for (timeout = 0; timeout < WDCNDELAY_RST; timeout++) {
+ WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM); /* master */
+ delay(10);
+ st0 = WDC_READ_REG(chp, wd_status);
+ WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM | 0x10); /* slave */
+ delay(10);
+ st1 = WDC_READ_REG(chp, wd_status);
+
+ if ((drv_mask & 0x01) == 0) {
+ /* no master */
+ if ((drv_mask & 0x02) != 0 && (st1 & WDCS_BSY) == 0) {
+ /* No master, slave is ready, it's done */
+ goto end;
+ }
+ } else if ((drv_mask & 0x02) == 0) {
+ /* no slave */
+ if ((drv_mask & 0x01) != 0 && (st0 & WDCS_BSY) == 0) {
+ /* No slave, master is ready, it's done */
+ goto end;
+ }
+ } else {
+ /* Wait for both master and slave to be ready */
+ if ((st0 & WDCS_BSY) == 0 && (st1 & WDCS_BSY) == 0) {
+ goto end;
+ }
+ }
+
+ delay(WDCDELAY);
+ }
+
+ /* Reset timed out. Maybe it's because drv_mask was not right */
+ if (st0 & WDCS_BSY)
+ drv_mask &= ~0x01;
+ if (st1 & WDCS_BSY)
+ drv_mask &= ~0x02;
+
+end:
+ return (drv_mask);
+}
+
+/* Test to see controller with at last one attached drive is there.
+ * Returns a bit for each possible drive found (0x01 for drive 0,
+ * 0x02 for drive 1).
+ * Logic:
+ * - If a status register is at 0xff, assume there is no drive here
+ * (ISA has pull-up resistors). Similarly if the status register has
+ * the value we last wrote to the bus (for IDE interfaces without pullups).
+ * If no drive at all -> return.
+ * - reset the controller, wait for it to complete (may take up to 31s !).
+ * If timeout -> return.
+ */
+static int
+wdcprobe(chp)
+ struct wdc_channel *chp;
+{
+ u_int8_t st0, st1, sc, sn, cl, ch;
+ u_int8_t ret_value = 0x03;
+ u_int8_t drive;
+ int found;
+
+ /*
+ * Sanity check to see if the wdc channel responds at all.
+ */
+ WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM);
+ delay(10);
+ st0 = WDC_READ_REG(chp, wd_status);
+ WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM | 0x10);
+ delay(10);
+ st1 = WDC_READ_REG(chp, wd_status);
+
+ if (st0 == 0xff || st0 == WDSD_IBM)
+ ret_value &= ~0x01;
+ if (st1 == 0xff || st1 == (WDSD_IBM | 0x10))
+ ret_value &= ~0x02;
+ if (ret_value == 0)
+ return (ENXIO);
+
+ /* assert SRST, wait for reset to complete */
+ WDC_WRITE_REG(chp, wd_sdh, WDSD_IBM);
+ delay(10);
+ WDC_WRITE_CTLREG(chp, wd_aux_ctlr, WDCTL_RST | WDCTL_IDS);
+ delay(1000);
+ WDC_WRITE_CTLREG(chp, wd_aux_ctlr, WDCTL_IDS);
+ delay(1000);
+ (void) WDC_READ_REG(chp, wd_error);
+ WDC_WRITE_CTLREG(chp, wd_aux_ctlr, WDCTL_4BIT);
+ delay(10);
+
+ ret_value = __wdcwait_reset(chp, ret_value);
+
+ /* if reset failed, there's nothing here */
+ if (ret_value == 0)
+ return (ENXIO);
+
+ /*
+ * Test presence of drives. First test register signatures looking for
+ * ATAPI devices. If it's not an ATAPI and reset said there may be
+ * something here assume it's ATA or OLD. Ghost will be killed later in
+ * attach routine.
+ */
+ found = 0;
+ for (drive = 0; drive < 2; drive++) {
+ if ((ret_value & (0x01 << drive)) == 0)
+ continue;
+ return (0);
+ }
+ return (ENXIO);
+}
+
+/*
+ * Initialize the device.
+ */
+int
+wdc_init(sc, unit)
+ struct wd_softc *sc;
+ u_int unit;
+{
+ if (pciide_init(&sc->sc_channel, unit) != 0)
+ return (ENXIO);
+ if (wdcprobe(&sc->sc_channel) != 0)
+ return (ENXIO);
+ return (0);
+}
+
+/*
+ * Wait until the device is ready.
+ */
+int
+wdc_wait_for_ready(chp)
+ struct wdc_channel *chp;
+{
+ u_int timeout;
+ for (timeout = WDC_TIMEOUT; timeout > 0; --timeout) {
+ if ((WDC_READ_REG(chp, wd_status) & (WDCS_BSY | WDCS_DRDY))
+ == WDCS_DRDY)
+ return (0);
+ }
+ return (ENXIO);
+}
+
+/*
+ * Read one block off the device.
+ */
+int
+wdc_read_block(sc, wd_c)
+ struct wd_softc *sc;
+ struct wdc_command *wd_c;
+{
+ int i;
+ struct wdc_channel *chp = &sc->sc_channel;
+ u_int16_t *ptr = (u_int16_t*)wd_c->data;
+
+ if (ptr == NULL)
+ return (0);
+
+ for (i = wd_c->bcount; i > 0; i -= sizeof(u_int16_t))
+ *ptr++ = WDC_READ_DATA(chp);
+
+ return (0);
+}
+
+/*
+ * Send a command to the device (CHS and LBA addressing).
+ */
+int
+wdccommand(wd, wd_c)
+ struct wd_softc *wd;
+ struct wdc_command *wd_c;
+{
+ u_int8_t err;
+ struct wdc_channel *chp = &wd->sc_channel;
+
+#if 0
+ DPRINTF(("wdccommand(%d, %d, %d, %d, %d, %d, %d)\n",
+ wd_c->drive, wd_c->r_command, wd_c->r_cyl,
+ wd_c->r_head, wd_c->r_sector, wd_c->bcount,
+ wd_c->r_precomp));
+#endif
+
+ WDC_WRITE_REG(chp, wd_precomp, wd_c->r_precomp);
+ WDC_WRITE_REG(chp, wd_seccnt, wd_c->r_count);
+ WDC_WRITE_REG(chp, wd_sector, wd_c->r_sector);
+ WDC_WRITE_REG(chp, wd_cyl_lo, wd_c->r_cyl);
+ WDC_WRITE_REG(chp, wd_cyl_hi, wd_c->r_cyl >> 8);
+ WDC_WRITE_REG(chp, wd_sdh,
+ WDSD_IBM | (wd_c->drive << 4) | wd_c->r_head);
+ WDC_WRITE_REG(chp, wd_command, wd_c->r_command);
+
+ if (wdc_wait_for_ready(chp) != 0)
+ return (ENXIO);
+
+ if (WDC_READ_REG(chp, wd_status) & WDCS_ERR) {
+ DPRINTF(("wd%d: error %x\n", wd->sc_unit,
+ WDC_READ_REG(chp, wd_error)));
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+/*
+ * Send a command to the device (LBA48 addressing).
+ */
+int
+wdccommandext(wd, wd_c)
+ struct wd_softc *wd;
+ struct wdc_command *wd_c;
+{
+ u_int8_t err;
+ struct wdc_channel *chp = &wd->sc_channel;
+
+ /* Select drive, head, and addressing mode. */
+ WDC_WRITE_REG(chp, wd_sdh, (wd_c->drive << 4) | WDSD_LBA);
+
+ /* previous */
+ WDC_WRITE_REG(chp, wd_features, 0);
+ WDC_WRITE_REG(chp, wd_seccnt, wd_c->r_count >> 8);
+ WDC_WRITE_REG(chp, wd_lba_hi, wd_c->r_blkno >> 40);
+ WDC_WRITE_REG(chp, wd_lba_mi, wd_c->r_blkno >> 32);
+ WDC_WRITE_REG(chp, wd_lba_lo, wd_c->r_blkno >> 24);
+
+ /* current */
+ WDC_WRITE_REG(chp, wd_features, 0);
+ WDC_WRITE_REG(chp, wd_seccnt, wd_c->r_count);
+ WDC_WRITE_REG(chp, wd_lba_hi, wd_c->r_blkno >> 16);
+ WDC_WRITE_REG(chp, wd_lba_mi, wd_c->r_blkno >> 8);
+ WDC_WRITE_REG(chp, wd_lba_lo, wd_c->r_blkno);
+
+ /* Send command. */
+ WDC_WRITE_REG(chp, wd_command, wd_c->r_command);
+
+ if (wdc_wait_for_ready(chp) != 0)
+ return (ENXIO);
+
+ if (WDC_READ_REG(chp, wd_status) & WDCS_ERR) {
+ DPRINTF(("wd%d: error %x\n", wd->sc_unit,
+ WDC_READ_REG(chp, wd_error)));
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+/*
+ * Issue 'device identify' command.
+ */
+int
+wdc_exec_identify(wd, data)
+ struct wd_softc *wd;
+ void *data;
+{
+ int error;
+ struct wdc_command wd_c;
+
+ memset(&wd_c, 0, sizeof(wd_c));
+
+ wd_c.drive = wd->sc_drive;
+ wd_c.r_command = WDCC_IDENTIFY;
+ wd_c.bcount = DEV_BSIZE;
+ wd_c.data = data;
+
+ if ((error = wdccommand(wd, &wd_c)) != 0)
+ return (error);
+
+ return wdc_read_block(wd, &wd_c);
+}
+
+/*
+ * Issue 'read' command.
+ */
+int
+wdc_exec_read(wd, cmd, blkno, data)
+ struct wd_softc *wd;
+ u_int8_t cmd;
+ daddr_t blkno;
+ void *data;
+{
+ int error;
+ struct wdc_command wd_c;
+
+ memset(&wd_c, 0, sizeof(wd_c));
+
+ if (wd->sc_flags & WDF_LBA48) {
+ /* LBA48 */
+ wd_c.r_blkno = blkno;
+ } else if (wd->sc_flags & WDF_LBA) {
+ /* LBA */
+ wd_c.r_sector = (blkno >> 0) & 0xff;
+ wd_c.r_cyl = (blkno >> 8) & 0xffff;
+ wd_c.r_head = (blkno >> 24) & 0x0f;
+ wd_c.r_head |= WDSD_LBA;
+ } else {
+ /* LHS */
+ wd_c.r_sector = blkno % wd->sc_label.d_nsectors;
+ wd_c.r_sector++; /* Sectors begin with 1, not 0. */
+ blkno /= wd->sc_label.d_nsectors;
+ wd_c.r_head = blkno % wd->sc_label.d_ntracks;
+ blkno /= wd->sc_label.d_ntracks;
+ wd_c.r_cyl = blkno;
+ wd_c.r_head |= WDSD_CHS;
+ }
+
+ wd_c.data = data;
+ wd_c.r_count = 1;
+ wd_c.drive = wd->sc_drive;
+ wd_c.r_command = cmd;
+ wd_c.bcount = wd->sc_label.d_secsize;
+
+ if (wd->sc_flags & WDF_LBA48)
+ error = wdccommandext(wd, &wd_c);
+ else
+ error = wdccommand(wd, &wd_c);
+
+ if (error != 0)
+ return (error);
+
+ return wdc_read_block(wd, &wd_c);
+}
diff --git a/sys/arch/socppc/stand/boot/wdvar.h b/sys/arch/socppc/stand/boot/wdvar.h
new file mode 100644
index 00000000000..ae33a7d8829
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/wdvar.h
@@ -0,0 +1,134 @@
+/* $OpenBSD: wdvar.h,v 1.1 2008/05/10 20:06:27 kettenis Exp $ */
+/* $NetBSD: wdvar.h,v 1.6 2005/12/11 12:17:06 christos Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * Copyright (c) 2001 Dynarc AB, Sweden. All rights reserved.
+ *
+ * This code is derived from software written by Anders Magnusson,
+ * ragge@ludd.luth.se
+ *
+ * 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. 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.
+ */
+
+#ifndef _STAND_WDVAR_H
+#define _STAND_WDVAR_H
+
+#include <sys/disklabel.h>
+
+#include <dev/ic/wdcreg.h>
+#include <dev/ata/atareg.h>
+#include <dev/pci/pciidereg.h>
+
+/*
+ * WD1003 / ATA Disk Controller register definitions.
+ */
+
+/* offsets of registers in the 'regular' register region */
+#define wd_data 0 /* data register (R/W - 16 bits) */
+#define wd_error 1 /* error register (R) */
+#define wd_precomp 1 /* write precompensation (W) */
+#define wd_seccnt 2 /* sector count (R/W) */
+#define wd_ireason 2 /* interrupt reason (R/W) (for atapi) */
+#define wd_sector 3 /* first sector number (R/W) */
+#define wd_cyl_lo 4 /* cylinder address, low byte (R/W) */
+#define wd_cyl_hi 5 /* cylinder address, high byte (R/W) */
+#define wd_sdh 6 /* sector size/drive/head (R/W) */
+#define wd_command 7 /* command register (W) */
+#define wd_lba_lo 3 /* lba address, low byte (RW) */
+#define wd_lba_mi 4 /* lba address, middle byte (RW) */
+#define wd_lba_hi 5 /* lba address, high byte (RW) */
+
+/* "shadow" registers; these may or may not overlap regular registers */
+#define wd_status 8 /* immediate status (R) */
+#define wd_features 9 /* features (W) */
+
+/* offsets of registers in the auxiliary register region */
+#define wd_aux_altsts 0 /* alternate fixed disk status (R) */
+#define wd_aux_ctlr 0 /* fixed disk controller control (W) */
+#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */
+#define WDCTL_RST 0x04 /* reset the controller */
+#define WDCTL_IDS 0x02 /* disable controller interrupts */
+
+#define WDC_TIMEOUT 2000000
+#define PCIIDE_CHANNEL_NDEV 2
+#define NUNITS (PCIIDE_CHANNEL_NDEV * PCIIDE_NUM_CHANNELS)
+#define WDC_NPORTS 8 /* XXX */
+#define WDC_NSHADOWREG 2 /* XXX */
+
+struct wdc_channel {
+ volatile u_int8_t *c_cmdbase;
+ volatile u_int8_t *c_ctlbase;
+ volatile u_int8_t *c_cmdreg[WDC_NPORTS + WDC_NSHADOWREG];
+ volatile u_int16_t *c_data;
+
+ u_int8_t ndrives;
+};
+
+#define WDC_READ_REG(chp, reg) *(chp)->c_cmdreg[(reg)]
+#define WDC_WRITE_REG(chp, reg, val) *(chp)->c_cmdreg[(reg)] = (val)
+#define WDC_READ_CTLREG(chp, reg) (chp)->c_ctlbase[(reg)]
+#define WDC_WRITE_CTLREG(chp, reg, val) (chp)->c_ctlbase[(reg)] = (val)
+#define WDC_READ_DATA(chp) *(chp)->c_data
+
+struct wd_softc {
+#define WDF_LBA 0x0001
+#define WDF_LBA48 0x0002
+ u_int16_t sc_flags;
+
+ u_int sc_part;
+ u_int sc_unit;
+
+ u_int64_t sc_capacity;
+
+ struct ataparams sc_params;
+ struct disklabel sc_label;
+ struct wdc_channel sc_channel;
+ u_int sc_drive;
+};
+
+struct wdc_command {
+ u_int8_t drive; /* drive id */
+
+ u_int8_t r_command; /* Parameters to upload to registers */
+ u_int8_t r_head;
+ u_int16_t r_cyl;
+ u_int8_t r_sector;
+ u_int8_t r_count;
+ u_int8_t r_precomp;
+
+ u_int16_t bcount;
+ void *data;
+
+ u_int64_t r_blkno;
+};
+
+int wdc_init (struct wd_softc*, u_int);
+int wdccommand (struct wd_softc*, struct wdc_command*);
+int wdccommandext (struct wd_softc*, struct wdc_command*);
+int wdc_exec_read (struct wd_softc*, u_int8_t, daddr_t, void*);
+int wdc_exec_identify (struct wd_softc*, void*);
+
+int pciide_init (struct wdc_channel*, u_int);
+
+#endif /* _STAND_WDVAR_H */