summaryrefslogtreecommitdiff
path: root/sys/arch/socppc
diff options
context:
space:
mode:
authorDariusz Swiderski <dms@cvs.openbsd.org>2009-09-07 21:16:58 +0000
committerDariusz Swiderski <dms@cvs.openbsd.org>2009-09-07 21:16:58 +0000
commit62e16fa714108af7898865c8a3d9d9b60e0a26b2 (patch)
tree8438cd556a3e7b813e0a84af07731f688141ffdf /sys/arch/socppc
parent4ce731d151c39a6e5c68c9ce6a1a24ee37d52622 (diff)
Bring support for booting RB600.
Imported FDT parsing code, implemented wdc_obio driver to support booting of CF cards. If FDT is available initialize console and wdc_obio accordingly and pass it later to the kernel. Unified the code with Thecus boot code, so that we can use one boot image. The whole boot code is now compiled with -msoft-float. Bump version while there. tested on Thecus by maja@ and kettenis@ tested on RB600 by dlg@ and me ok by kettenis@
Diffstat (limited to 'sys/arch/socppc')
-rw-r--r--sys/arch/socppc/stand/boot/Makefile6
-rw-r--r--sys/arch/socppc/stand/boot/conf.c4
-rw-r--r--sys/arch/socppc/stand/boot/exec.c5
-rw-r--r--sys/arch/socppc/stand/boot/fdt.c395
-rw-r--r--sys/arch/socppc/stand/boot/fdt.h60
-rw-r--r--sys/arch/socppc/stand/boot/machdep.c85
-rw-r--r--sys/arch/socppc/stand/boot/ns16550.c19
-rw-r--r--sys/arch/socppc/stand/boot/pciide.c43
-rw-r--r--sys/arch/socppc/stand/boot/start.S8
-rw-r--r--sys/arch/socppc/stand/boot/wdc.c8
-rw-r--r--sys/arch/socppc/stand/boot/wdc_obio.c99
-rw-r--r--sys/arch/socppc/stand/boot/wdvar.h16
12 files changed, 714 insertions, 34 deletions
diff --git a/sys/arch/socppc/stand/boot/Makefile b/sys/arch/socppc/stand/boot/Makefile
index da255a925ba..bea0f9c5cbd 100644
--- a/sys/arch/socppc/stand/boot/Makefile
+++ b/sys/arch/socppc/stand/boot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.5 2008/06/09 15:01:56 deraadt Exp $
+# $OpenBSD: Makefile,v 1.6 2009/09/07 21:16:57 dms Exp $
.include "${.CURDIR}/../Makefile.inc"
@@ -17,12 +17,12 @@ CPPFLAGS+= -nostdinc -I../.. -I. -I${.CURDIR} -I${S}
CPPFLAGS+= -DCONADDR=0xe0004500UL -DCONSPEED=115200
CPPFLAGS+= -DNS16550_FREQ=266000000
-COPTS+= -ffreestanding -fno-stack-protector -ffixed-r29
+COPTS+= -ffreestanding -fno-stack-protector -ffixed-r29 -msoft-float
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+= clock.c ns16550.c wd.c wdc.c pciide.c wdc_obio.c fdt.c
SRCS+= ctime.c strtol.c
.PATH: ${S}/lib/libkern/arch/powerpc ${S}/lib/libkern
diff --git a/sys/arch/socppc/stand/boot/conf.c b/sys/arch/socppc/stand/boot/conf.c
index 648986179c4..f8b4c740ccd 100644
--- a/sys/arch/socppc/stand/boot/conf.c
+++ b/sys/arch/socppc/stand/boot/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+/* $OpenBSD: conf.c,v 1.2 2009/09/07 21:16:57 dms Exp $ */
/* $NetBSD: conf.c,v 1.4 2005/12/11 12:17:06 christos Exp $ */
/*
@@ -39,7 +39,7 @@
#include "libsa.h"
#include <lib/libsa/ufs.h>
-const char version[] = "0.1";
+const char version[] = "0.2";
int debug = 0;
/*
diff --git a/sys/arch/socppc/stand/boot/exec.c b/sys/arch/socppc/stand/boot/exec.c
index d9b7c3ea961..ec941ba5cdb 100644
--- a/sys/arch/socppc/stand/boot/exec.c
+++ b/sys/arch/socppc/stand/boot/exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec.c,v 1.2 2008/05/11 19:58:24 kettenis Exp $ */
+/* $OpenBSD: exec.c,v 1.3 2009/09/07 21:16:57 dms Exp $ */
/*
* Copyright (c) 2006 Mark Kettenis
@@ -66,8 +66,9 @@ run_loadfile(u_long *marks, int howto)
l += sizeof(ssym);
bcopy(&esym, args + l, sizeof(esym));
l += sizeof(esym);
+ extern int fdtaddrsave;
- (*(startfuncp)(marks[MARK_ENTRY]))(0, 0, entry, args, l);
+ (*(startfuncp)(marks[MARK_ENTRY]))(fdtaddrsave, 0, entry, args, l);
/* NOTREACHED */
}
diff --git a/sys/arch/socppc/stand/boot/fdt.c b/sys/arch/socppc/stand/boot/fdt.c
new file mode 100644
index 00000000000..d6199205f2a
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/fdt.c
@@ -0,0 +1,395 @@
+/* $OpenBSD: fdt.c,v 1.1 2009/09/07 21:16:57 dms Exp $ */
+
+/*
+ * Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
+ *
+ * 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 <sys/param.h>
+//#include <sys/user.h>
+#include <machine/fdt.h>
+
+#include "libsa.h"
+
+
+unsigned int fdt_check_head(void *);
+char *fdt_get_str(u_int32_t);
+void *skip_property(u_int32_t *);
+void *skip_props(u_int32_t *);
+void *skip_node_name(u_int32_t *);
+void *fdt_find_node_recurse(void *node, char *name);
+#ifdef DEBUG
+void fdt_print_node_recurse(void *, int);
+#endif
+
+static int tree_inited = 0;
+static struct fdt tree;
+
+unsigned int
+fdt_check_head(void *fdt)
+{
+ struct fdt_head *fh;
+ u_int32_t *ptr;
+
+ fh = fdt;
+ ptr = (u_int32_t *)fdt;
+
+ if (fh->fh_magic != FDT_MAGIC)
+ return 0;
+
+ if (fh->fh_version > FDT_CODE_VERSION)
+ return 0;
+
+ if (*(ptr + (fh->fh_struct_off / 4)) != FDT_NODE_BEGIN)
+ return 0;
+
+ /* check for end signature on version 17 blob */
+ if ((fh->fh_version >= 17) & (*(ptr + fh->fh_struct_size) != FDT_END))
+ return 0;
+
+ return fh->fh_version;
+}
+
+/*
+ * Initializes internal structures of module.
+ * Has to be called once, preferably in machdep.c.
+ */
+int
+fdt_init(void *fdt)
+{
+ int version;
+
+ bzero(&tree, sizeof(struct fdt));
+ tree_inited = 0;
+
+ if (!fdt)
+ return 0;
+
+ if (!(version = fdt_check_head(fdt)))
+ return 0;
+
+ tree.header = (struct fdt_head *)fdt;
+ tree.tree = (char *)fdt + tree.header->fh_struct_off;
+ tree.strings = (char *)fdt + tree.header->fh_strings_off;
+ tree.memory = (char *)fdt + tree.header->fh_reserve_off;
+ tree.version = version;
+
+ if (version < 3) {
+ if ((tree.strings < tree.tree) && (tree.tree < tree.memory))
+ tree.strings_size = tree.tree - tree.strings;
+ else if ((tree.strings < tree.memory) && (tree.memory <
+ tree.tree))
+ tree.strings_size = tree.memory - tree.strings;
+ else if ((tree.strings < tree.tree) && (tree.memory <
+ tree.strings))
+ tree.strings_size = tree.tree - tree.strings;
+ else if ((tree.strings < tree.memory) && (tree.tree <
+ tree.strings))
+ tree.strings_size = tree.memory - tree.strings;
+ else
+ tree.strings_size = tree.header->fh_size -
+ (int)tree.strings;
+ } else
+ tree.strings_size = tree.header->fh_strings_size;
+
+ tree.strings_size = tree.header->fh_strings_size;
+ tree_inited = 1;
+
+ return version;
+}
+
+/*
+ * Retrieve string pointer from srtings table.
+ */
+char *
+fdt_get_str(u_int32_t num)
+{
+ if (num > tree.strings_size)
+ return NULL;
+ return (tree.strings) ? (tree.strings + num) : NULL;
+}
+
+/*
+ * Utility functions for skipping parts of tree.
+ */
+void *
+skip_property(u_int32_t *ptr)
+{
+ u_int32_t size;
+
+ size = *(ptr + 1);
+ /* move forward by magic + size + nameid + rounded up property size */
+ ptr += 3 + roundup(size, sizeof(u_int32_t)) / sizeof(u_int32_t);
+
+ return ptr;
+}
+
+void *
+skip_props(u_int32_t *ptr)
+{
+ while (*ptr == FDT_PROPERTY) {
+ ptr = skip_property(ptr);
+ }
+ return ptr;
+}
+
+void *
+skip_node_name(u_int32_t *ptr)
+{
+ /* skip name, aligned to 4 bytes, this is NULL term., so must add 1 */
+ return ptr + roundup(strlen((char *)ptr) + 1,
+ sizeof(u_int32_t)) / sizeof(u_int32_t);
+}
+
+/*
+ * Retrieves node property, the returned pointer is inside the fdt tree,
+ * so we should not modify content pointed by it directly.
+ */
+int
+fdt_node_property(void *node, char *name, char **out)
+{
+ u_int32_t *ptr;
+ u_int32_t nameid;
+ char *tmp;
+
+ if (!tree_inited)
+ return 0;
+
+ ptr = (u_int32_t *)node;
+
+ if (*ptr != FDT_NODE_BEGIN)
+ return 0;
+
+ ptr = skip_node_name(ptr + 1);
+
+ while (*ptr == FDT_PROPERTY) {
+ nameid = *(ptr + 2); /* id of name in strings table */
+ tmp = fdt_get_str(nameid);
+ if (!strcmp(name, tmp)) {
+ *out = (char *)(ptr + 3); /* begining of the value */
+ return *(ptr + 1); /* size of value */
+ }
+ ptr = skip_property(ptr);
+ }
+ return 0;
+}
+
+/*
+ * Retrieves next node, skipping all the children nodes of the pointed node
+ * if passed 0 wil return first node of the tree (root)
+ */
+void *
+fdt_next_node(void *node)
+{
+ u_int32_t *ptr;
+
+ if (!tree_inited)
+ return NULL;
+
+ ptr = node;
+
+ if (!node) {
+ ptr = tree.tree;
+ return (*ptr == FDT_NODE_BEGIN) ? ptr : NULL;
+ }
+
+ if (*ptr != FDT_NODE_BEGIN)
+ return NULL;
+
+ ptr++;
+
+ ptr = skip_node_name(ptr);
+ ptr = skip_props(ptr);
+
+ /* skip children */
+ while (*ptr == FDT_NODE_BEGIN)
+ ptr = fdt_next_node(ptr);
+
+ return (*ptr == FDT_NODE_END) ? (ptr + 1) : NULL;
+}
+
+/*
+ * Retrieves next node, skipping all the children nodes of the pointed node
+ */
+void *
+fdt_child_node(void *node)
+{
+ u_int32_t *ptr;
+
+ if (!tree_inited)
+ return NULL;
+
+ ptr = node;
+
+ if (*ptr != FDT_NODE_BEGIN)
+ return NULL;
+
+ ptr++;
+
+ ptr = skip_node_name(ptr);
+ ptr = skip_props(ptr);
+ /* check if there is a child node */
+ return (*ptr == FDT_NODE_BEGIN) ? (ptr) : NULL;
+}
+
+/*
+ * Retrieves node name.
+ */
+char *
+fdt_node_name(void *node)
+{
+ u_int32_t *ptr;
+
+ if (!tree_inited)
+ return NULL;
+
+ ptr = node;
+
+ if (*ptr != FDT_NODE_BEGIN)
+ return NULL;
+
+ return (char *)(ptr + 1);
+}
+
+void *
+fdt_find_node(char *name)
+{
+ void *node = fdt_next_node(0);
+ const char *p = name;
+
+ if (!tree_inited)
+ return NULL;
+
+ if (*p != '/')
+ return NULL;
+
+ while (*p) {
+ void *child;
+ const char *q;
+
+ while (*p == '/')
+ p++;
+ if (*p == 0)
+ return node;
+ q = strchr(p, '/');
+ if (q == NULL)
+ q = p + strlen(p);
+
+ for (child = fdt_child_node(node); child;
+ child = fdt_next_node(child)) {
+ if (strncmp(p, fdt_node_name(child), q - p) == 0) {
+ node = child;
+ break;
+ }
+ }
+
+ p = q;
+ }
+
+ return node;
+}
+
+#ifdef DEBUG
+/*
+ * Debug methods for printing whole tree, particular odes and properies
+ */
+void *
+fdt_print_property(void *node, int level)
+{
+ u_int32_t *ptr;
+ char *tmp, *value;
+ int cnt;
+ u_int32_t nameid, size;
+
+ ptr = (u_int32_t *)node;
+
+ if (!tree_inited)
+ return NULL;
+
+ if (*ptr != FDT_PROPERTY)
+ return ptr; /* should never happen */
+
+ /* extract property name_id and size */
+ size = *++ptr;
+ nameid = *++ptr;
+
+ for (cnt = 0; cnt < level; cnt++)
+ printf("\t");
+
+ tmp = fdt_get_str(nameid);
+ printf("\t%s : ", tmp ? tmp : "NO_NAME");
+
+ ptr++;
+ value = (char *)ptr;
+
+ if (!strcmp(tmp, "device_type") || !strcmp(tmp, "compatible") ||
+ !strcmp(tmp, "model") || !strcmp(tmp, "bootargs") ||
+ !strcmp(tmp, "linux,stdout-path")) {
+ printf("%s", value);
+ } else if (!strcmp(tmp, "clock-frequency") ||
+ !strcmp(tmp, "timebase-frequency")) {
+ printf("%d", *((unsigned int *)value));
+ } else {
+ for (cnt = 0; cnt < size; cnt++) {
+ if ((cnt % sizeof(u_int32_t)) == 0)
+ printf(" ");
+ printf("%x", value[cnt]);
+ }
+ }
+ ptr += roundup(size, sizeof(u_int32_t)) / sizeof(u_int32_t);
+ printf("\n");
+
+ return ptr;
+}
+
+void
+fdt_print_node(void *node, int level)
+{
+ u_int32_t *ptr;
+ int cnt;
+
+ ptr = (u_int32_t *)node;
+
+ if (*ptr != FDT_NODE_BEGIN)
+ return;
+
+ ptr++;
+
+ for (cnt = 0; cnt < level; cnt++)
+ printf("\t");
+ printf("%s :\n", fdt_node_name(node));
+ ptr = skip_node_name(ptr);
+
+ while (*ptr == FDT_PROPERTY)
+ ptr = fdt_print_property(ptr, level);
+}
+
+void
+fdt_print_node_recurse(void *node, int level)
+{
+ void *child;
+
+ fdt_print_node(node, level);
+ for (child = fdt_child_node(node); child; child = fdt_next_node(child))
+ fdt_print_node_recurse(child, level + 1);
+}
+
+void
+fdt_print_tree(void)
+{
+ fdt_print_node_recurse(fdt_next_node(0), 0);
+}
+#endif
diff --git a/sys/arch/socppc/stand/boot/fdt.h b/sys/arch/socppc/stand/boot/fdt.h
new file mode 100644
index 00000000000..1d0d93fb006
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/fdt.h
@@ -0,0 +1,60 @@
+/* $OpenBSD: fdt.h,v 1.1 2009/09/07 21:16:57 dms Exp $ */
+
+/*
+ * Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
+ *
+ * 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.
+ */
+
+struct fdt_head {
+ u_int32_t fh_magic;
+ u_int32_t fh_size;
+ u_int32_t fh_struct_off;
+ u_int32_t fh_strings_off;
+ u_int32_t fh_reserve_off;
+ u_int32_t fh_version;
+ u_int32_t fh_comp_ver; /* last compatible version */
+ u_int32_t fh_boot_cpu_id; /* fh_version >=2 */
+ u_int32_t fh_strings_size; /* fh_version >=3 */
+ u_int32_t fh_struct_size; /* fh_version >=17 */
+};
+
+struct fdt {
+ struct fdt_head *header;
+ void * tree;
+ void * strings;
+ void * memory;
+ int version;
+ int strings_size;
+};
+
+#define FDT_MAGIC 0xd00dfeed
+#define FDT_NODE_BEGIN 0x01
+#define FDT_NODE_END 0x02
+#define FDT_PROPERTY 0x03
+#define FDT_NOP 0x04
+#define FDT_END 0x09
+
+#define FDT_CODE_VERSION 0x11
+
+int fdt_init(void *);
+void *fdt_next_node(void *);
+void *fdt_child_node(void *);
+char *fdt_node_name(void *);
+void *fdt_find_node(char *);
+int fdt_node_property(void *, char *, char **);
+#ifdef DEBUG
+void *fdt_print_property(void *, int);
+void fdt_print_node(void *, int);
+void fdt_print_tree(void);
+#endif
diff --git a/sys/arch/socppc/stand/boot/machdep.c b/sys/arch/socppc/stand/boot/machdep.c
index f54cea14f9c..e75baca1147 100644
--- a/sys/arch/socppc/stand/boot/machdep.c
+++ b/sys/arch/socppc/stand/boot/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+/* $OpenBSD: machdep.c,v 1.2 2009/09/07 21:16:57 dms Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
@@ -19,6 +19,8 @@
#include <sys/types.h>
#include "libsa.h"
+#include "wdvar.h"
+#include "fdt.h"
#define RPR 0xe0000918
#define RPR_RSTE 0x52535445
@@ -26,14 +28,82 @@
#define RCR_SWSR 0x00000001
#define RCR_SWHR 0x00000002
+/* defines from pciide.c and wdc_obio.c */
+int pciide_init (struct wdc_channel*, u_int);
+int wdc_obio_init (struct wdc_channel*, u_int);
+
void
machdep(void)
{
- cninit();
+ char soc[32];
+ void *node;
+ char *tmp;
+ int len;
+
+ extern int consfreq;
+ extern uint8_t *consaddr;
+
+ /* set default values */
+ consfreq = NS16550_FREQ;
+ consaddr = (uint8_t *)CONADDR;
+
+ /* lookup FTD for informations about conole */
+ node = fdt_find_node("/chosen");
+ if (node) {
+ char *console;
+ fdt_node_property(node, "linux,stdout-path", &console);
+ node = fdt_find_node(console);
+ if (node) {
+ len = fdt_node_property(node, "clock-frequency", &tmp);
+ if (len == 4)
+ consfreq = *(int *)tmp;
+
+ len = fdt_node_property(node, "reg", &tmp);
+ if (len == 8)
+ consaddr = (uint8_t *)*(int *)tmp;
+ }
+ memcpy(soc, console, 32);
+ if (strchr(soc + 1, '/')!=0) {
+ /* we are on a soc */
+ *strchr(soc + 1, '/') = 0;
+ node = fdt_find_node(soc);
+ if (node) {
+ len = fdt_node_property(node, "reg", &tmp);
+ if (len == 8)
+ consaddr += *(int *)tmp;
+ }
+ }
+ }
+ cninit();
{
- extern u_int32_t wdc_base_addr;
- wdc_base_addr = 0xe2000000;
+ extern int (*controller_init)(struct wdc_channel *chp, u_int chan);
+ extern u_int32_t pciide_base_addr;
+ extern u_int32_t wdc_base_addr[];
+ int *addr;
+ int chnum;
+
+ /* Thecus defaults */
+ controller_init = pciide_init;
+ pciide_base_addr = 0xe2000000;
+
+ /* lookup the FDT, may have some CF there */
+ chnum = 0;
+ wdc_base_addr[0] = 0;
+ wdc_base_addr[1] = 0;
+ node = fdt_find_node("/");
+ for (node = fdt_child_node(node); node; node = fdt_next_node(node)) {
+ len = fdt_node_property(node, "device_type", &tmp);
+ if (len && (strcmp(tmp, "rb,cf") == 0) && (chnum < 2)) {
+ len = fdt_node_property(node, "reg", (char **)&addr);
+ if (len == 8) {
+ wdc_base_addr[chnum] = *addr;
+ chnum++;
+ }
+ }
+ }
+ if (chnum)
+ controller_init = wdc_obio_init;
}
}
@@ -44,6 +114,13 @@ main(void)
extern char __bss_start[], _end[];
bzero(__bss_start, _end-__bss_start);
+ /* initialize FDT if the blob is available */
+ extern int fdtaddrsave;
+ if (fdtaddrsave) {
+ if (fdt_init((void *)fdtaddrsave) == 0)
+ fdtaddrsave = 0; /* no usable blob there */
+ }
+
boot(0);
return 0;
}
diff --git a/sys/arch/socppc/stand/boot/ns16550.c b/sys/arch/socppc/stand/boot/ns16550.c
index 3da8ac78308..5345cccb878 100644
--- a/sys/arch/socppc/stand/boot/ns16550.c
+++ b/sys/arch/socppc/stand/boot/ns16550.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ns16550.c,v 1.1 2008/05/10 20:06:26 kettenis Exp $ */
+/* $OpenBSD: ns16550.c,v 1.2 2009/09/07 21:16:57 dms Exp $ */
/* $NetBSD: ns16550.c,v 1.3 2005/12/24 20:07:03 perry Exp $ */
/*
@@ -48,15 +48,14 @@
#include "libsa.h"
-#define INB(x) *((volatile uint8_t *) (CONADDR + (x)))
-#define OUTB(x, v) *((volatile uint8_t *) (CONADDR + (x))) = (v)
-
+uint8_t *consaddr;
+uint32_t consspeed;
+uint32_t consfreq;
+
+#define INB(x) *((volatile uint8_t *) (consaddr + (x)))
+#define OUTB(x, v) *((volatile uint8_t *) (consaddr + (x))) = (v)
#define ISSET(t,f) ((t) & (f))
-#ifndef NS16550_FREQ
-#define NS16550_FREQ COM_FREQ
-#endif
-
static int
comspeed(int speed)
{
@@ -66,10 +65,10 @@ comspeed(int speed)
if (speed <= 0)
return (-1);
- x = divrnd((NS16550_FREQ / 16), speed);
+ x = divrnd((consfreq / 16), speed);
if (x <= 0)
return (-1);
- err = divrnd((((quad_t)NS16550_FREQ) / 16) * 1000, speed * x) - 1000;
+ err = divrnd((((quad_t)consfreq) / 16) * 1000, speed * x) - 1000;
if (err < 0)
err = -err;
if (err > COM_TOLERANCE)
diff --git a/sys/arch/socppc/stand/boot/pciide.c b/sys/arch/socppc/stand/boot/pciide.c
index 7ed5bdfaf8d..7b3ffb7dda6 100644
--- a/sys/arch/socppc/stand/boot/pciide.c
+++ b/sys/arch/socppc/stand/boot/pciide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide.c,v 1.2 2008/06/26 05:42:13 ray Exp $ */
+/* $OpenBSD: pciide.c,v 1.3 2009/09/07 21:16:57 dms Exp $ */
/* $NetBSD: pciide.c,v 1.5 2005/12/11 12:17:06 christos Exp $ */
/*-
@@ -32,7 +32,12 @@
#include "libsa.h"
#include "wdvar.h"
-u_int32_t wdc_base_addr = 0;
+u_int8_t pciide_read_cmdreg(struct wdc_channel *, u_int8_t);
+void pciide_write_cmdreg(struct wdc_channel *, u_int8_t, u_int8_t);
+u_int8_t pciide_read_ctlreg(struct wdc_channel *, u_int8_t);
+void pciide_write_ctlreg(struct wdc_channel *, u_int8_t, u_int8_t);
+
+u_int32_t pciide_base_addr = 0;
int
pciide_init(struct wdc_channel *chp, u_int chan)
@@ -43,7 +48,7 @@ pciide_init(struct wdc_channel *chp, u_int chan)
/*
* two channels per chip, one drive per channel
*/
- if (chan >= PCIIDE_NUM_CHANNELS || wdc_base_addr == 0)
+ if (chan >= PCIIDE_NUM_CHANNELS || pciide_base_addr == 0)
return (ENXIO);
chp->ndrives = 1;
@@ -52,8 +57,8 @@ pciide_init(struct wdc_channel *chp, u_int chan)
/*
* XXX map?
*/
- cmdreg = wdc_base_addr + chan * 0x10;
- ctlreg = wdc_base_addr+0x8 + chan * 0x10;
+ cmdreg = pciide_base_addr + chan * 0x10;
+ ctlreg = pciide_base_addr+0x8 + chan * 0x10;
/* set up cmd regsiters */
chp->c_cmdbase = (u_int8_t *)cmdreg;
@@ -66,5 +71,33 @@ pciide_init(struct wdc_channel *chp, u_int chan)
/* set up ctl registers */
chp->c_ctlbase = (u_int8_t *)ctlreg;
+ chp->read_cmdreg = pciide_read_cmdreg;
+ chp->write_cmdreg = pciide_write_cmdreg;
+ chp->read_ctlreg = pciide_read_ctlreg;
+ chp->write_ctlreg = pciide_write_ctlreg;
return (0);
}
+
+u_int8_t
+pciide_read_cmdreg(struct wdc_channel *chp, u_int8_t reg)
+{
+ return *chp->c_cmdreg[reg];
+}
+
+void
+pciide_write_cmdreg(struct wdc_channel *chp, u_int8_t reg, u_int8_t val)
+{
+ *chp->c_cmdreg[reg] = val;
+}
+
+u_int8_t
+pciide_read_ctlreg(struct wdc_channel *chp, u_int8_t reg)
+{
+ return chp->c_ctlbase[reg];
+}
+
+void
+pciide_write_ctlreg(struct wdc_channel *chp, u_int8_t reg, u_int8_t val)
+{
+ chp->c_ctlbase[reg] = val;
+}
diff --git a/sys/arch/socppc/stand/boot/start.S b/sys/arch/socppc/stand/boot/start.S
index 74d8e795052..94b44424ae3 100644
--- a/sys/arch/socppc/stand/boot/start.S
+++ b/sys/arch/socppc/stand/boot/start.S
@@ -2,7 +2,15 @@
#define STACKSIZE 8192
+ .globl _C_LABEL(fdtaddrsave)
+ .type _C_LABEL(fdtaddrsave),@object
+ .data
+_C_LABEL(fdtaddrsave): .long 0
+
ENTRY(_start)
+ lis %r1, fdtaddrsave@ha
+ stw %r3, fdtaddrsave@l(%r1)
+
lis %r1, stack@ha
addi %r1, %r1, stack@l
addi %r1, %r1, STACKSIZE
diff --git a/sys/arch/socppc/stand/boot/wdc.c b/sys/arch/socppc/stand/boot/wdc.c
index 70acef280a7..28ac9ca8d8d 100644
--- a/sys/arch/socppc/stand/boot/wdc.c
+++ b/sys/arch/socppc/stand/boot/wdc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdc.c,v 1.2 2008/06/26 05:42:13 ray Exp $ */
+/* $OpenBSD: wdc.c,v 1.3 2009/09/07 21:16:57 dms Exp $ */
/* $NetBSD: wdc.c,v 1.7 2005/12/11 12:17:06 christos Exp $ */
/*-
@@ -44,6 +44,8 @@ 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);
+int (*controller_init)(struct wdc_channel *, u_int) = 0;
+
/*
* Reset the controller.
*/
@@ -173,7 +175,9 @@ wdc_init(sc, unit)
struct wd_softc *sc;
u_int unit;
{
- if (pciide_init(&sc->sc_channel, unit) != 0)
+ if (!controller_init)
+ return (ENXIO);
+ if ((*controller_init)(&sc->sc_channel, unit) != 0)
return (ENXIO);
if (wdcprobe(&sc->sc_channel) != 0)
return (ENXIO);
diff --git a/sys/arch/socppc/stand/boot/wdc_obio.c b/sys/arch/socppc/stand/boot/wdc_obio.c
new file mode 100644
index 00000000000..480e83731ab
--- /dev/null
+++ b/sys/arch/socppc/stand/boot/wdc_obio.c
@@ -0,0 +1,99 @@
+/* $OpenBSD: wdc_obio.c,v 1.1 2009/09/07 21:16:57 dms Exp $ */
+
+/*
+ * Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net>
+ *
+ * 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"
+#include "wdvar.h"
+
+#define WDC_OBIO_REG_OFFSET (8 << 17)
+#define WDC_OBIO_AUXREG_OFFSET (6 << 16)
+
+u_int8_t wdc_read_cmdreg(struct wdc_channel *, u_int8_t);
+void wdc_write_cmdreg(struct wdc_channel *, u_int8_t, u_int8_t);
+u_int8_t wdc_read_ctlreg(struct wdc_channel *, u_int8_t);
+void wdc_write_ctlreg(struct wdc_channel *, u_int8_t, u_int8_t);
+
+u_int32_t wdc_base_addr[2];
+
+int
+wdc_obio_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 >= 2 || !wdc_base_addr[chan])
+ return (ENXIO);
+ chp->ndrives = 1;
+
+ cmdreg = wdc_base_addr[chan] + WDC_OBIO_REG_OFFSET;
+ ctlreg = wdc_base_addr[chan] + WDC_OBIO_AUXREG_OFFSET;
+
+ /* 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<<16);
+ /* 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;
+
+ chp->read_cmdreg = wdc_read_cmdreg;
+ chp->write_cmdreg = wdc_write_cmdreg;
+ chp->read_ctlreg = wdc_read_ctlreg;
+ chp->write_ctlreg = wdc_write_ctlreg;
+
+ return (0);
+}
+
+u_int8_t
+wdc_read_cmdreg(struct wdc_channel *chp, u_int8_t reg)
+{
+ u_int8_t val;
+ val = *chp->c_cmdreg[reg];
+ if (val == 0xf9 && reg == wd_status)
+ val = 0x7f;
+ return val;
+}
+
+void
+wdc_write_cmdreg(struct wdc_channel *chp, u_int8_t reg, u_int8_t val)
+{
+ *chp->c_cmdreg[reg] = val;
+}
+
+u_int8_t
+wdc_read_ctlreg(struct wdc_channel *chp, u_int8_t reg)
+{
+ u_int8_t val;
+ val = chp->c_ctlbase[reg];
+ if (val == 0xf9 && reg == wd_aux_altsts)
+ val = 0x7f;
+ return val;
+}
+
+void
+wdc_write_ctlreg(struct wdc_channel *chp, u_int8_t reg, u_int8_t val)
+{
+ chp->c_ctlbase[reg] = val;
+}
diff --git a/sys/arch/socppc/stand/boot/wdvar.h b/sys/arch/socppc/stand/boot/wdvar.h
index ae33a7d8829..e99319aff4e 100644
--- a/sys/arch/socppc/stand/boot/wdvar.h
+++ b/sys/arch/socppc/stand/boot/wdvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdvar.h,v 1.1 2008/05/10 20:06:27 kettenis Exp $ */
+/* $OpenBSD: wdvar.h,v 1.2 2009/09/07 21:16:57 dms Exp $ */
/* $NetBSD: wdvar.h,v 1.6 2005/12/11 12:17:06 christos Exp $ */
/*-
@@ -83,12 +83,17 @@ struct wdc_channel {
volatile u_int16_t *c_data;
u_int8_t ndrives;
+
+ u_int8_t (*read_cmdreg)(struct wdc_channel *chp, u_int8_t reg);
+ void (*write_cmdreg)(struct wdc_channel *chp, u_int8_t reg, u_int8_t val);
+ u_int8_t (*read_ctlreg)(struct wdc_channel *chp, u_int8_t reg);
+ void (*write_ctlreg)(struct wdc_channel *chp, u_int8_t reg, u_int8_t val);
};
-#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_REG(chp, reg) (chp)->read_cmdreg(chp, reg)
+#define WDC_WRITE_REG(chp, reg, val) (chp)->write_cmdreg(chp, reg, val)
+#define WDC_READ_CTLREG(chp, reg) (chp)->read_ctlreg(chp, reg)
+#define WDC_WRITE_CTLREG(chp, reg, val) (chp)->write_ctlreg(chp, reg, val)
#define WDC_READ_DATA(chp) *(chp)->c_data
struct wd_softc {
@@ -129,6 +134,5 @@ 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 */