diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-05-10 20:06:28 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-05-10 20:06:28 +0000 |
commit | ba4e3222839204021e000d34b676712b9aa14b24 (patch) | |
tree | 0c03cc82f4b06da1e609511ccbcac0c0bff64170 /sys/arch | |
parent | f0b7557aa0bd4ef68437345a996cf2cc749c70db (diff) |
First stab at a bootloader for the Thecus N1200.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/socppc/stand/Makefile | 5 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/Makefile | 53 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/clock.c | 55 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/conf.c | 69 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/dev_socppc.c | 115 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/devopen.c | 129 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/exec.c | 63 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/libsa.h | 42 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/machdep.c | 62 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/ns16550.c | 137 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/pciide.c | 77 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/start.S | 13 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/time.c | 8 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/wd.c | 322 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/wdc.c | 383 | ||||
-rw-r--r-- | sys/arch/socppc/stand/boot/wdvar.h | 134 |
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 */ |