diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2006-07-28 17:12:07 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2006-07-28 17:12:07 +0000 |
commit | 15e0980d8f0b251e6cfdfbe72fc67e79b514466c (patch) | |
tree | a567a5307e80cea488d60c5c8fc934fcd3fb9649 | |
parent | c8b15e982f697762676be53dca799e0f7ce902fd (diff) |
First stab at an armish bootloader. It will load /bsd from the drive in the
upper slot of the Thecus n2100. Glued together from bits from the NetBSD
cobalt and evbarm ports.
-rw-r--r-- | sys/arch/armish/stand/boot/Makefile | 39 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/boot.c | 75 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/boot.h | 31 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/clock.c | 56 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/conf.c | 59 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/devopen.c | 146 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/exec.c | 31 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/ldscript | 84 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/ns16550.c | 133 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/pciide.c | 109 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/start.S | 83 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/wd.c | 279 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/wdc.c | 419 | ||||
-rw-r--r-- | sys/arch/armish/stand/boot/wdvar.h | 103 |
14 files changed, 1647 insertions, 0 deletions
diff --git a/sys/arch/armish/stand/boot/Makefile b/sys/arch/armish/stand/boot/Makefile new file mode 100644 index 00000000000..b265ba3a7b5 --- /dev/null +++ b/sys/arch/armish/stand/boot/Makefile @@ -0,0 +1,39 @@ +PROG= boot + +S= ${.CURDIR}/../../../.. + +CPPFLAGS+= -nostdinc -I../.. -I. -I${S} -D_STANDALONE +CPPFLAGS+= -DCONSPEED=115200 +CPPFLAGS+= -DCONADDR=0xfe800000UL + +COPTS+= -ffreestanding -fno-stack-protector -malignment-traps + +SRCS= start.S boot.c conf.c clock.c ns16550.c wd.c wdc.c pciide.c +SRCS+= devopen.c exec.c + +### find out what to use for libkern +KERN_AS= library +.include "${S}/lib/libkern/Makefile.inc" +LIBKERN= ${KERNLIB} + +### find out what to use for libsa +SA_AS= library +SAREL= +USE_LOADFILE= yes +.include "${S}/lib/libsa/Makefile.inc" +LIBSA= ${SALIB} + +LDFLAGS= -T ${.CURDIR}/ldscript + +${PROG}: ${OBJS} ${LIBKERN} ${LIBSA} + ${LD} ${LDFLAGS} -o boot ${OBJS} ${LIBSA} ${LIBKERN} ${LIBSA} + +.if !make(obj) +.BEGIN: + @([ -h machine ] || ln -s ${.CURDIR}/../../../${MACHINE}/include machine) + @([ -h arm ] || ln -s ${.CURDIR}/../../../arm/include arm) +.NOPATH: machine arm +CLEANFILES+= machine arm +.endif + +.include <bsd.prog.mk> diff --git a/sys/arch/armish/stand/boot/boot.c b/sys/arch/armish/stand/boot/boot.c new file mode 100644 index 00000000000..ed47f80bc92 --- /dev/null +++ b/sys/arch/armish/stand/boot/boot.c @@ -0,0 +1,75 @@ +/* $OpenBSD: boot.c,v 1.1 2006/07/28 17:12:06 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 <lib/libsa/stand.h> +#include <lib/libsa/loadfile.h> + +int +main(void) +{ + u_long marks[MARK_MAX]; + + cons_init(); + + printf("OpenBSD/armish boot\n"); + + printf("OIOWTVR: 0x%x\n", *((volatile uint32_t *)0xffffe15c)); + printf("ATUCR: 0x%x\n", *((volatile uint32_t *)0xffffe180)); + printf("ATU_OIOWTVR: 0x%x\n", *((volatile uint32_t *)0xffffe15c)); + printf("ATU_OMWTVR0: 0x%x\n", *((volatile uint32_t *)0xffffe160)); + printf("ATU_OUMWTVR0: 0x%x\n", *((volatile uint32_t *)0xffffe164)); + printf("ATU_OMWTVR1: 0x%x\n", *((volatile uint32_t *)0xffffe168)); + printf("ATU_OUMWTVR1: 0x%x\n", *((volatile uint32_t *)0xffffe16c)); + volatile uint32_t *p = ((volatile uint32_t *)0xffffe180); + *p = 1<<1; + printf("ATUCR: 0x%x\n", *((volatile uint32_t *)0xffffe180)); + +#define L1_S_SHIFT 20 + { + uint32_t *pde; + + __asm volatile("mrc p15, 0, %0, c2, c0, 0" : "=r" (pde)); + + printf("pde %x\n", pde); + pde = (uint32_t *)((uint32_t) pde & 0x0fffffff); + printf("mapping of %x is %x\n", p, pde[(u_int32_t)p >> L1_S_SHIFT]); + p = (u_int32_t *)0x90000000; + printf("mapping of %x is %x\n", p, pde[(u_int32_t)p >> L1_S_SHIFT]); + p = (u_int32_t *)0xa0000000; + printf("mapping of %x is %x\n", p, pde[(u_int32_t)p >> L1_S_SHIFT]); + p = (u_int32_t *)0x00000000; + printf("mapping of %x is %x\n", p, pde[(u_int32_t)p >> L1_S_SHIFT]); + + p = (u_int32_t *)0x90000000; + pde[(u_int32_t)p >> L1_S_SHIFT] = ((uint32_t)p & 0xfff00000) | 0xc02; + printf("new mapping of %x is %x\n", p, pde[(u_int32_t)p >> L1_S_SHIFT]); + + } + + marks[MARK_START] = 0; + if (loadfile("wd2a:/bsd", marks, LOAD_ALL) < 0) { + printf("loadfile: errno %\n", errno); + goto err; + } + + run_loadfile(marks, 0); + + err: + printf("halted..."); + for (;;) ; +} diff --git a/sys/arch/armish/stand/boot/boot.h b/sys/arch/armish/stand/boot/boot.h new file mode 100644 index 00000000000..c5499e34ac5 --- /dev/null +++ b/sys/arch/armish/stand/boot/boot.h @@ -0,0 +1,31 @@ +/* $OpenBSD: boot.h,v 1.1 2006/07/28 17:12:06 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. + */ + +#define DPRINTF(x) printf x; + +#define MAXDEVNAME 16 +#define DEFBOOTDEV "wd0a" +#define DEFKERNELNAME "bsd" + + +/* + * 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/armish/stand/boot/clock.c b/sys/arch/armish/stand/boot/clock.c new file mode 100644 index 00000000000..d3f1a61dee7 --- /dev/null +++ b/sys/arch/armish/stand/boot/clock.c @@ -0,0 +1,56 @@ +/* $OpenBSD: clock.c,v 1.1 2006/07/28 17:12:06 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 <lib/libsa/stand.h> + +#include "boot.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/armish/stand/boot/conf.c b/sys/arch/armish/stand/boot/conf.c new file mode 100644 index 00000000000..65145648755 --- /dev/null +++ b/sys/arch/armish/stand/boot/conf.c @@ -0,0 +1,59 @@ +/* $OpenBSD: conf.c,v 1.1 2006/07/28 17:12:06 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 <lib/libsa/stand.h> +#include <lib/libsa/ufs.h> + +#include "boot.h" + +/* + * Device configuration + */ +struct devsw devsw[] = { + { "wd", wdstrategy, wdopen, wdclose, noioctl }, +}; + +int ndevs = (sizeof(devsw)/sizeof(devsw[0])); + +/* + * Filesystem configuration + */ +struct fs_ops file_system[] = { + { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, + ufs_stat, ufs_readdir } +}; + +int nfsys = sizeof(file_system) / sizeof(file_system[0]); diff --git a/sys/arch/armish/stand/boot/devopen.c b/sys/arch/armish/stand/boot/devopen.c new file mode 100644 index 00000000000..78521074535 --- /dev/null +++ b/sys/arch/armish/stand/boot/devopen.c @@ -0,0 +1,146 @@ +/* $OpenBSD: devopen.c,v 1.1 2006/07/28 17:12:06 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 <lib/libsa/stand.h> + +#include "boot.h" + +/* + * Parse a device spec. + * + * Format: + * [device:][filename] + */ +int +devparse(const char *fname, int *dev, u_int8_t *unit, + u_int8_t *part, const char **file) +{ + const char *col; + + *unit = 0; /* default to wd0a */ + *part = 0; + *dev = 0; + *file = DEFKERNELNAME; + + if (fname == NULL) + return (0); + + if ( (col = strchr(fname, ':')) != NULL) { + int devlen; + u_int8_t i, u, p; + struct devsw *dp; + char devname[MAXDEVNAME]; + + devlen = col - fname; + if (devlen > MAXDEVNAME) + return (EINVAL); + +#define isnum(c) (((c) >= '0') && ((c) <= '9')) +#if 0 +#define isalpha(c) (((c) >= 'a') && ((c) <= 'z')) +#endif + + /* extract device name */ + for (i = 0; isalpha(fname[i]) && (i < devlen); i++) + devname[i] = fname[i]; + devname[i] = 0; + + if (!isnum(fname[i])) + return (EUNIT); + + /* device number */ + for (u = 0; isnum(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 = ++col; + } + + if (*fname) + *file = fname; + + return (0); +} + +int +devopen(struct open_file *f, const char *fname, char **file) +{ + struct devsw *dp; + u_int8_t unit, part; + int dev, error; + + DPRINTF(("devopen(%s)\n", fname)); + + if ( (error = devparse(fname, &dev, &unit, &part, + (const char **)file)) != 0) + return error; + + dp = &devsw[dev]; + if ((void *)dp->dv_open == (void *)nodev) + return ENXIO; + + f->f_dev = dp; + + if ( (error = (*dp->dv_open)(f, unit, part)) != 0) + printf("%s%d%c: %d = %s\n", devsw[dev].dv_name, + unit, 'a' + part, error, strerror(error)); + + return error; +} diff --git a/sys/arch/armish/stand/boot/exec.c b/sys/arch/armish/stand/boot/exec.c new file mode 100644 index 00000000000..d44aae439ba --- /dev/null +++ b/sys/arch/armish/stand/boot/exec.c @@ -0,0 +1,31 @@ +/* $OpenBSD: exec.c,v 1.1 2006/07/28 17:12:06 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> + +typedef void (*startfuncp)(void) __attribute__ ((noreturn)); + +void +run_loadfile(u_long *marks, int howto) +{ + (*(startfuncp)(marks[MARK_ENTRY]))(); + + /* NOTREACHED */ +} diff --git a/sys/arch/armish/stand/boot/ldscript b/sys/arch/armish/stand/boot/ldscript new file mode 100644 index 00000000000..fab694cfc57 --- /dev/null +++ b/sys/arch/armish/stand/boot/ldscript @@ -0,0 +1,84 @@ +/* $OpenBSD: ldscript,v 1.1 2006/07/28 17:12:06 kettenis Exp $ */ +/* $NetBSD: ldscript,v 1.6 2005/12/11 12:17:10 christos Exp $ */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", + "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(FLASH) +MEMORY +{ + /* We will locate the .text section in flash, and will run directly + from there just long enough to relocate our .text and .data into + a small chunk of SDRAM starting at (SDRAM + 1M). */ + flash : o = 0xf0080000, l = 6M + sdram : o = 0x00100000, l = 1M /* kernel loads at 0xa0200000 */ +} +SECTIONS +{ + FLASH = 0x00100000; + + /* Read-only sections, merged into text segment: */ + __text_store = FLASH; + .text : + AT (FLASH) + { + *(.text) + *(.text.*) + *(.stub) + *(.glue_7t) *(.glue_7) + *(.rodata) *(.rodata.*) + } > sdram =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + __data_store = FLASH + SIZEOF(.text); + .data : + AT (LOADADDR(.text) + SIZEOF(.text)) + { + __data_start = . ; + *(.data) + *(.data.*) + } > sdram + .sdata : + AT (LOADADDR(.data) + SIZEOF(.data)) + { + *(.sdata) + *(.sdata.*) + . = ALIGN(32 / 8); + } > sdram + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .sbss : + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + } > sdram + .bss : + { + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + } > sdram + . = ALIGN(32 / 8); + _end = .; + _bss_end__ = . ; __bss_end__ = . ; __end__ = . ; + PROVIDE (end = .); + .image (FLASH + SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.sdata)) : + AT (LOADADDR(.sdata) + SIZEOF(.sdata)) + { + *(.image) + } +} diff --git a/sys/arch/armish/stand/boot/ns16550.c b/sys/arch/armish/stand/boot/ns16550.c new file mode 100644 index 00000000000..66690e8eb2c --- /dev/null +++ b/sys/arch/armish/stand/boot/ns16550.c @@ -0,0 +1,133 @@ +/* $OpenBSD: ns16550.c,v 1.1 2006/07/28 17:12:06 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 the cons_init() function and console I/O routines + * for boards that use 16550-compatible UARTs. + */ + +#include <sys/types.h> +#include <dev/ic/comreg.h> +#include <lib/libsa/stand.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 +cons_init(void) +{ + 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 +getchar(void) +{ + uint8_t stat; + + while (!ISSET(stat = INB(com_lsr), LSR_RXRDY)) + /* spin */ ; + return (INB(com_data)); +} + +static void +iputchar(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); +} + +void +putchar(int c) +{ + + if (c == '\n') + iputchar('\r'); + iputchar(c); +} diff --git a/sys/arch/armish/stand/boot/pciide.c b/sys/arch/armish/stand/boot/pciide.c new file mode 100644 index 00000000000..97cc4885186 --- /dev/null +++ b/sys/arch/armish/stand/boot/pciide.c @@ -0,0 +1,109 @@ +/* $OpenBSD: pciide.c,v 1.1 2006/07/28 17:12:06 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 <lib/libsa/stand.h> + +#include "boot.h" +#include "wdvar.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 */ + +int +pciide_init(chp, unit) + struct wdc_channel *chp; + u_int *unit; +{ + u_int32_t cmdreg, ctlreg; + int i, compatchan = 0; + + /* + * two channels per chip, two drives per channel + */ + compatchan = *unit / PCIIDE_CHANNEL_NDEV; + if (compatchan >= PCIIDE_NUM_CHANNELS) + return (ENXIO); + *unit %= PCIIDE_CHANNEL_NDEV; + + DPRINTF(("[pciide] unit: %d, channel: %d\n", *unit, compatchan)); + + /* + * XXX map? + */ + cmdreg = 0x90000200 + compatchan * 0x10; + ctlreg = 0x90000208 + compatchan * 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/armish/stand/boot/start.S b/sys/arch/armish/stand/boot/start.S new file mode 100644 index 00000000000..03f3e10d2de --- /dev/null +++ b/sys/arch/armish/stand/boot/start.S @@ -0,0 +1,83 @@ +/* $OpenBSD: start.S,v 1.1 2006/07/28 17:12:06 kettenis Exp $ */ +/* $NetBSD: srtbegin.S,v 1.7 2005/12/11 12:17:10 christos 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. + */ + +#include <machine/asm.h> +#include <arm/armreg.h> + +#define STACKSIZE 8192 + +ENTRY(start) + /* + * We assume we've been loaded VA==PA, or that the MMU + * is disabled. Make sure the MMU is disabled so that + * we don't have to care about the caches. + */ + /* Clear the BSS. */ + adr r1, Lbss + ldmia r1, {r1, r2} + sub r2, r2, r1 + mov r3, #0 + +1: strb r3, [r1], #0x01 + subs r2, r2, #0x01 + bgt 1b + + /* Set the stack pointer */ + adr r1, Lstack + ldr r1, [r1] + add sp, r1, #STACKSIZE + + b _C_LABEL(main) + +Ltext: + .word _C_LABEL(__text_store) + .word _C_LABEL(start) + .word _C_LABEL(_etext) + +Ldata: + .word _C_LABEL(__data_store) + .word _C_LABEL(__data_start) + +Lbss: + .word _C_LABEL(_edata) + .word _C_LABEL(_end) + +Lstack: + .word Lstackspace + + .comm Lstackspace, STACKSIZE diff --git a/sys/arch/armish/stand/boot/wd.c b/sys/arch/armish/stand/boot/wd.c new file mode 100644 index 00000000000..f907d271e1a --- /dev/null +++ b/sys/arch/armish/stand/boot/wd.c @@ -0,0 +1,279 @@ +/* $OpenBSD: wd.c,v 1.1 2006/07/28 17:12:06 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 <lib/libsa/stand.h> +#include <machine/param.h> + +#include "boot.h" +#include "wdvar.h" + +static int wd_get_params(struct wd_softc *wd); +static int wdgetdisklabel(struct wd_softc *wd); +static void wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp); + +/* + * 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); + + 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_secsize / DEV_BSIZE); + 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]; + + 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; + + if (*(u_int16_t *)&buf[DOSMAGICOFF] == DOSMAGIC) { + 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; + 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: %d:%d\n", unit, part)); + + wd = alloc(sizeof(struct wd_softc)); + if (wd == NULL) + return ENOMEM; + + memset(wd, 0, sizeof(struct wd_softc)); + + if (wdc_init(wd, &unit) != 0) + return (ENXIO); + + wd->sc_part = part; + wd->sc_unit = unit; + + if ( (error = wd_get_params(wd)) != 0) + return (error); + + 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/armish/stand/boot/wdc.c b/sys/arch/armish/stand/boot/wdc.c new file mode 100644 index 00000000000..d6e151dc175 --- /dev/null +++ b/sys/arch/armish/stand/boot/wdc.c @@ -0,0 +1,419 @@ +/* $OpenBSD: wdc.c,v 1.1 2006/07/28 17:12:06 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> +#if 0 +#include <sys/disklabel.h> +#endif + +#include <lib/libsa/stand.h> +#include <machine/param.h> + +#include "boot.h" +#include "wdvar.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 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(sc, wd_c) + struct wd_softc *sc; + struct wdc_command *wd_c; +{ + u_int8_t err; + struct wdc_channel *chp = &sc->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) { + printf("wd%d: error %x\n", chp->compatchan, + 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) { + printf("wd%d: error %x\n", chp->compatchan, + 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_unit; + 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_unit; + 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/armish/stand/boot/wdvar.h b/sys/arch/armish/stand/boot/wdvar.h new file mode 100644 index 00000000000..57e9076b941 --- /dev/null +++ b/sys/arch/armish/stand/boot/wdvar.h @@ -0,0 +1,103 @@ +/* $OpenBSD: wdvar.h,v 1.1 2006/07/28 17:12:06 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 <dev/ic/wdcreg.h> +#include <dev/ata/atareg.h> +#include <dev/pci/pciidereg.h> + +#include <sys/disklabel.h> + +#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 compatchan; +}; + +#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; +}; + +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 */ |