diff options
| author | bjh21 <bjh21@NetBSD.org> | 2000-05-09 21:55:44 +0000 |
|---|---|---|
| committer | bjh21 <bjh21@NetBSD.org> | 2000-05-09 21:55:44 +0000 |
| commit | 6c97e2bd7817f6eb36ea04f65488ea1e95cb158f (patch) | |
| tree | 499bc6851619a39119e4f4e8919311cbb9b2948d /sys | |
| parent | 6a36c27519360fbbcb9b0533b93429d400c5e315 (diff) | |
Initial commit of arm26 port
Diffstat (limited to 'sys')
137 files changed, 24369 insertions, 3 deletions
diff --git a/sys/arch/arm26/Makefile b/sys/arch/arm26/Makefile new file mode 100644 index 00000000000..87c745ea262 --- /dev/null +++ b/sys/arch/arm26/Makefile @@ -0,0 +1,33 @@ +# $NetBSD: Makefile,v 1.1 2000/05/09 21:55:54 bjh21 Exp $ + +# Makefile for arm26 tags file and boot blocks + +TARM26= ../arm26/tags +SARM26= ../arm26/arm26/*.[ch] ../arm26/include/*.h \ + ../arm26/iobus/*.[ch] ../arm26/ioc/*.[ch] ../arm32/mainbus/*.[ch] \ + ../arm26/vidc/*.[ch] +AARM26= ../arm26/arm26/*.S ../arm26/iobus/*.S + +# Directories in which to place tags links +DARM26= arm26 include iobus ioc mainbus vidc + +.include "../../kern/Make.tags.inc" + +tags: TAGS + -ctags -wdtf ${TARM26} ${SARM26} ${COMM} + egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AARM26} | \ + sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \ + >> ${TARM26} + sort -o ${TARM26} ${TARM26} + +TAGS: + etags ${SARM26} ${COMM} ${AARM26} + +links: + -for i in ${DARM26}; do \ + cd $$i && rm -f tags; ln -s ../tags tags; done + + +SUBDIR= include + +.include <bsd.subdir.mk> diff --git a/sys/arch/arm26/arm26/Locore.c b/sys/arch/arm26/arm26/Locore.c new file mode 100644 index 00000000000..05fb4577323 --- /dev/null +++ b/sys/arch/arm26/arm26/Locore.c @@ -0,0 +1,151 @@ +/* $NetBSD: Locore.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ + +/* + * Copyright (c) 2000 Ben Harris. + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* + * Some additional routines that happened to be in locore.S traditionally, + * but have no need to be coded in assembly. + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: Locore.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $"); + +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/user.h> + +#include <vm/vm.h> + +#include <machine/machdep.h> + +static void idle(void); + +volatile int whichqs; + +/* + * Put process p on the run queue indicated by its priority. + * Calls should be made at splstatclock(), and p->p_stat should be SRUN. + */ +void +setrunqueue(struct proc *p) +{ + struct prochd *q; + struct proc *oldlast; + int which = p->p_priority >> 2; + +#ifdef DIAGNOSTIC + if (p->p_back) + panic("setrunqueue"); +#endif + q = &qs[which]; + whichqs |= 1 << which; + p->p_forw = (struct proc *)q; + p->p_back = oldlast = q->ph_rlink; + q->ph_rlink = p; + oldlast->p_forw = p; +} + +/* + * Remove process p from its run queue, which should be the one + * indicated by its priority. + * Calls should be made at splstatclock(). + */ +void +remrunqueue(struct proc *p) +{ + int which = p->p_priority >> 2; + struct prochd *q; + +#ifdef DIAGNOSTIC + if (!(whichqs & (1 << which))) + panic("remrunqueue"); +#endif + p->p_forw->p_back = p->p_back; + p->p_back->p_forw = p->p_forw; + p->p_back = NULL; + q = &qs[which]; + if (q->ph_link == (struct proc *)q) + whichqs &= ~(1 << which); +} + +/* + * Idle + */ +static void +idle() +{ + + spl0(); + while (whichqs == 0) + continue; + splhigh(); +} + +extern int want_resched; /* XXX should be in <machine/cpu.h> */ + +/* + * Find the highest-priority runnable process and switch to it. + */ +void +cpu_switch(struct proc *p1) +{ + int which; + int s; + struct prochd *q; + struct proc *p2; + +#if 0 + printf("cpu_switch: %p ->", p1); +#endif + curproc = NULL; + s = splhigh(); + while (whichqs == 0) + idle(); + which = ffs(whichqs) - 1; + q = &qs[which]; + p2 = q->ph_link; + remrunqueue(p2); + want_resched = 0; + curproc = p2; +#if 0 + printf(" %p\n", p2); +#endif + if (p2 == p1) + return; + pmap_deactivate(p1); + pmap_activate(p2); + cpu_loswitch(&p1->p_addr->u_pcb.pcb_sf, p2->p_addr->u_pcb.pcb_sf); + /* We only get back here after the other process has run. */ + splx(s); +} diff --git a/sys/arch/arm26/arm26/aout_machdep.c b/sys/arch/arm26/arm26/aout_machdep.c new file mode 100644 index 00000000000..547b12cbc70 --- /dev/null +++ b/sys/arch/arm26/arm26/aout_machdep.c @@ -0,0 +1,104 @@ +/* $NetBSD: aout_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ + +/* + * Copyright (c) 2000 Ben Harris + * Copyright (c) 1993, 1994 Christopher G. Demetriou + * 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 Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * aout_machdep.c - odd a.out executable formats + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: aout_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $"); + +#include <sys/exec.h> +#include <sys/exec_aout.h> +#include <sys/systm.h> +#include <sys/vnode.h> +#include <machine/aout_machdep.h> +#include <vm/vm.h> + +int cpu_exec_aout_prep_ozmagic(struct proc *, struct exec_package *); + +int +cpu_exec_aout_makecmds(struct proc *p, struct exec_package *epp) +{ + struct exec *execp = epp->ep_hdr; + + if (execp->a_midmag == ZMAGIC) + /* GNU binutils arm-acorn-aout format */ + return cpu_exec_aout_prep_ozmagic(p, epp); + return ENOEXEC; +} + + +int cpu_exec_aout_prep_ozmagic(struct proc *p, struct exec_package *epp) +{ + struct exec *execp = epp->ep_hdr; + + epp->ep_taddr = USRTEXT; + epp->ep_tsize = execp->a_text; + epp->ep_daddr = epp->ep_taddr + execp->a_text; + epp->ep_dsize = execp->a_data + execp->a_bss; + epp->ep_entry = execp->a_entry; + + /* + * check if vnode is in open for writing, because we want to + * demand-page out of it. if it is, don't do it, for various + * reasons + */ + if ((execp->a_text != 0 || execp->a_data != 0) && + epp->ep_vp->v_writecount != 0) { +#ifdef DIAGNOSTIC + if (epp->ep_vp->v_flag & VTEXT) + panic("exec: a VTEXT vnode has writecount != 0\n"); +#endif + return ETXTBSY; + } + epp->ep_vp->v_flag |= VTEXT; + + /* set up command for text segment */ + NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text, + epp->ep_taddr, epp->ep_vp, __LDPGSZ, VM_PROT_READ|VM_PROT_EXECUTE); + + /* set up command for data segment */ + NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data, + epp->ep_daddr, epp->ep_vp, __LDPGSZ + execp->a_text, + VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); + + /* set up command for bss segment */ + NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss, + epp->ep_daddr + execp->a_data, NULLVP, 0, + VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); + + return exec_aout_setup_stack(p, epp); + +} diff --git a/sys/arch/arm26/arm26/autoconf.c b/sys/arch/arm26/arm26/autoconf.c new file mode 100644 index 00000000000..8ab3a0008a5 --- /dev/null +++ b/sys/arch/arm26/arm26/autoconf.c @@ -0,0 +1,68 @@ +/* $NetBSD: autoconf.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ +/*- + * Copyright (c) 1998, 1999 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * autoconf.c - top level device-finding code + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: autoconf.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $"); + +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/systm.h> + +#include <machine/irq.h> +#include <machine/machdep.h> + +void +cpu_configure() +{ + + irq_init(); + config_rootfound("cpu", NULL); + config_rootfound("iobus", NULL); + config_rootfound("arcvideo", NULL); + spl0(); +} + +void +cpu_rootconf() +{ + + /* XXX This could actually do something */ + setroot(NULL, 0); +} + +void +cpu_dumpconf() +{ + + printf("cpu_dumpconf: Doing something here would be useful\n"); +} diff --git a/sys/arch/arm26/arm26/bus.c b/sys/arch/arm26/arm26/bus.c new file mode 100644 index 00000000000..fff776014c6 --- /dev/null +++ b/sys/arch/arm26/arm26/bus.c @@ -0,0 +1,220 @@ +/* $NetBSD: bus.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ +/*- + * Copyright (c) 1999, 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * bus.c - bus space functions for Archimedes I/O bus + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: bus.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $"); + +#include <machine/bus.h> +#include <machine/memcreg.h> + +int +bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size, + int flags, bus_space_handle_t *bshp) +{ + + if (flags & BUS_SPACE_MAP_LINEAR) + return -1; + *bshp = (bus_space_handle_t)(MEMC_IO_BASE + addr); + return 0; +} + +int +bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, + bus_space_handle_t *nbshp) +{ + + *nbshp = bsh + (offset << bst); + return 0; +} + +int +bus_space_shift(bus_space_tag_t bst, bus_space_handle_t bsh, int shift, + bus_space_tag_t *nbstp, bus_space_handle_t *nbshp) +{ + + *nbstp = shift; + *nbshp = bsh; + return 0; +} + +void +bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *datap, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + datap[i] = bus_space_read_1(bst, bsh, offset); +} + +void +bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *datap, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + datap[i] = bus_space_read_2(bst, bsh, offset); +} + +void +bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t const *datap, + bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_1(bst, bsh, offset, datap[i]); +} + +void +bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t const *datap, + bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_2(bst, bsh, offset, datap[i]); +} + +void +bus_space_set_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t value, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_1(bst, bsh, offset, value); +} + +void +bus_space_set_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t value, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_2(bst, bsh, offset, value); +} + +void +bus_space_read_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *datap, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + datap[i] = bus_space_read_1(bst, bsh, offset + i); +} + +void +bus_space_read_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *datap, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + datap[i] = bus_space_read_2(bst, bsh, offset + i); +} + +void +bus_space_write_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t const *datap, + bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_1(bst, bsh, offset + i, datap[i]); +} + +void +bus_space_write_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t const *datap, + bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_2(bst, bsh, offset + i, datap[i]); +} + +void +bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t value, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_1(bst, bsh, offset + i, value); +} + +void +bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t value, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_2(bst, bsh, offset + i, value); +} + +void +bus_space_copy_1(bus_space_tag_t bst, + bus_space_handle_t bsh1, bus_size_t offset1, + bus_space_handle_t bsh2, bus_size_t offset2, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_1(bst, bsh2, offset2 + 1, + bus_space_read_1(bst, bsh1, offset1 + i)); +} + +void +bus_space_copy_2(bus_space_tag_t bst, + bus_space_handle_t bsh1, bus_size_t offset1, + bus_space_handle_t bsh2, bus_size_t offset2, bus_size_t count) +{ + int i; + + for (i = 0; i < count; i++) + bus_space_write_2(bst, bsh2, offset2 + 1, + bus_space_read_1(bst, bsh1, offset1 + i)); +} + + + diff --git a/sys/arch/arm26/arm26/conf.c b/sys/arch/arm26/arm26/conf.c new file mode 100644 index 00000000000..269b054e9ec --- /dev/null +++ b/sys/arch/arm26/arm26/conf.c @@ -0,0 +1,193 @@ +/* $NetBSD: conf.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ +/*- + * Copyright (c) 1998, 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * conf.c -- Device switch tables and related gumf. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/conf.h> +#include <sys/vnode.h> +#include <dev/cons.h> + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); +bdev_decl(sw); +cdev_decl(sw); +#include "pty.h" +#include "md.h" +#include "vnd.h" +#include "ccd.h" +#include "wd.h" +bdev_decl(wd); +cdev_decl(wd); +#include "sd.h" +#include "cd.h" +#include "bpfilter.h" +#include "tun.h" +#include "ipfilter.h" +#include "rnd.h" +#include "rs.h" +#include "wsdisplay.h" +cdev_decl(wsdisplay); +#include "wskbd.h" +cdev_decl(wskbd); +#include "wsmouse.h" +cdev_decl(wsmouse); +#include "wsmux.h" +cdev_decl(wsmux); + +cons_decl(rs); + +struct bdevsw bdevsw[] = { + bdev_swap_init(1, sw), /* 0: swap pseudo-device */ + bdev_disk_init(NMD, md), /* 1: memory "disk" */ + bdev_disk_init(NVND, vnd), /* 2: vnode "disk" */ + bdev_disk_init(NCCD, ccd), /* 3: concatenated disks */ + bdev_disk_init(NWD, wd), /* 4: IDE disks */ + bdev_disk_init(NSD, sd), /* 5: SCSI disks */ + bdev_disk_init(NCD, cd), /* 6: SCSI CD-ROMs */ +}; + +int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + +struct cdevsw cdevsw[] = { + /* First seven are standard across most ports */ + cdev_cn_init(1, cn), /* 0: /dev/console */ + cdev_ctty_init(1, ctty), /* 1: /dev/tty */ + cdev_mm_init(1, mm), /* 2: /dev/{null,mem,kmem,zero} */ + cdev_swap_init(1, sw), /* 3: /dev/drum */ + cdev_tty_init(NPTY, pts), /* 4: pseudo-tty slave */ + cdev_ptc_init(NPTY, ptc), /* 5: pseudo-tty master */ + cdev_log_init(1, log), /* 6: /dev/klog */ + cdev_fd_init(1, filedesc), /* 7: file descriptors */ + + cdev_disk_init(NMD, md), /* 8: memory "disk" */ + cdev_disk_init(NVND, vnd), /* 9: vnode "disk" */ + cdev_disk_init(NCCD, ccd), /* 10: concatenated disks */ + cdev_mouse_init(NWSKBD, wskbd), /* 11: keyboards */ + cdev_mouse_init(NWSMOUSE, wsmouse), + /* 12: mice */ + cdev_mouse_init(NWSMUX, wsmux), /* 13: keyboard/mouse multiplexor */ + cdev_wsdisplay_init(NWSDISPLAY, wsdisplay), + /* 14: console display */ + cdev_disk_init(NWD, wd), /* 15: IDE disks */ + cdev_disk_init(NSD, sd), /* 16: SCSI disks */ + cdev_disk_init(NCD, cd), /* 17: SCSI CD-ROMs */ +}; + +int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + + +int mem_no = 2; /* major device number of memory special file */ + +/* + * Swapdev is a fake device implemented + * in sw.c used only internally to get to swstrategy. + * It cannot be provided to the users, because the + * swstrategy routine munches the b_dev and b_blkno entries + * before calling the appropriate driver. This would horribly + * confuse, e.g. the hashing routines. Instead, /dev/drum is + * provided as a character (raw) device. + */ +dev_t swapdev = makedev(1, 0); + +/* + * Returns true if dev is /dev/mem or /dev/kmem. + */ +int +iskmemdev(dev) + dev_t dev; +{ + return (major(dev) == mem_no && minor(dev) < 2); +} + +/* + * Returns true if dev is /dev/zero. + */ +int +iszerodev(dev) + dev_t dev; +{ + return (major(dev) == mem_no && minor(dev) == 3); +} + + +static int chrtoblktbl[] = { +/* XXXX This needs to be dynamic for LKMs. */ + /*VCHR*/ /*VBLK*/ + /* 0 */ NODEV, + /* 1 */ NODEV, + /* 2 */ NODEV, + /* 3 */ NODEV, + /* 4 */ NODEV, + /* 5 */ NODEV, + /* 6 */ NODEV, + /* 7 */ NODEV, + /* 8 */ 1, /* md */ + /* 9 */ 2, /* vnd */ + /* 10 */ 3, /* ccd */ + /* 11 */ NODEV, + /* 12 */ NODEV, + /* 13 */ NODEV, + /* 14 */ NODEV, + /* 15 */ 4, /* wd */ + /* 16 */ 5, /* sd */ + /* 17 */ 6, /* cd */ +}; + +/* + * Convert a character device number to a block device number. + */ + +dev_t +chrtoblk(dev) + dev_t dev; +{ + int blkmaj; + + if (major(dev) >= nchrdev) + return (NODEV); + + blkmaj = chrtoblktbl[major(dev)]; + if (blkmaj == NODEV) + return (NODEV); + return (makedev(blkmaj, minor(dev))); +} + +struct consdev constab[] = { +#if NRS > 0 + cons_init(rs), +#endif + { 0 } +}; diff --git a/sys/arch/arm26/arm26/cons_machdep.c b/sys/arch/arm26/arm26/cons_machdep.c new file mode 100644 index 00000000000..91e285c2ff9 --- /dev/null +++ b/sys/arch/arm26/arm26/cons_machdep.c @@ -0,0 +1,71 @@ +/* $NetBSD: cons_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * cons_machdep.c -- machine dependent console routines + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: cons_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $"); + +#include <sys/syslog.h> +#include <sys/systm.h> + +#include <dev/cons.h> + +#include "arcvideo.h" +#include "opt_ddb.h" + +#ifdef DDB +#include <machine/db_machdep.h> +#include <ddb/db_extern.h> +#include <ddb/db_interface.h> + +#include <machine/boot.h> +#include <machine/memcreg.h> +#endif + +extern void arccons_init __P((void)); + +void +consinit() +{ + +#if NARCVIDEO > 0 + arccons_init(); +#endif +/* cninit();*/ + +#ifdef DDB + db_machine_init(); + ddb_init(bootconfig.esym - bootconfig.ssym, + MEMC_PHYS_BASE + bootconfig.ssym, + MEMC_PHYS_BASE + bootconfig.esym); +#endif /* DDB */ +} diff --git a/sys/arch/arm26/arm26/copyinout.S b/sys/arch/arm26/arm26/copyinout.S new file mode 100644 index 00000000000..69b6154da37 --- /dev/null +++ b/sys/arch/arm26/arm26/copyinout.S @@ -0,0 +1,177 @@ +/* $NetBSD: copyinout.S,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * copyinout.S - copy data between user and kernel space + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: copyinout.S,v 1.1 2000/05/09 21:55:55 bjh21 Exp $") + +#include <sys/errno.h> +#include "assym.h" + +/* + * Note that most of these need special handling on data aborts. I + * haven't coded that bit yet. + */ + +/* + * int copyin(const void *ua, void *ka, size_t len); + * int copyout(const void *ka, void *ua, size_t len); + * int kcopy(const void *src, void *dst, size_t len); + */ + +/* + * memcpy isn't currently data-abort-safe (it uses R14). This is much + * slower, but safer. + */ + +ENTRY(copyin) + mov ip, sp + stmfd sp!, {r4, fp, ip, lr, pc} + sub fp, ip, #4 + adr r3, Lcopyfault + ldr r4, Lcurproc + ldr r4, [r4] + ldr r4, [r4, #P_ADDR] + str r3, [r4, #(U_PCB + PCB_ONFAULT)] +Lcopyinloop: + ldrbt r3, [r0], #1 + strb r3, [r1], #1 + subs r2, r2, #1 + bne Lcopyinloop + mov r0, #0 + str r0, [r4, #(U_PCB + PCB_ONFAULT)] + ldmdb fp, {r4, fp, sp, pc}^ + +ENTRY(copyout) + mov ip, sp + stmfd sp!, {r4, fp, ip, lr, pc} + sub fp, ip, #4 + adr r3, Lcopyfault + ldr r4, Lcurproc + ldr r4, [r4] + ldr r4, [r4, #P_ADDR] + str r3, [r4, #(U_PCB + PCB_ONFAULT)] +Lcopyoutloop: + ldrb r3, [r0], #1 + strbt r3, [r1], #1 + subs r2, r2, #1 + bne Lcopyoutloop + mov r0, #0 + str r0, [r4, #(U_PCB + PCB_ONFAULT)] + ldmdb fp, {r4, fp, sp, pc}^ + +ENTRY(kcopy) + mov ip, sp + stmfd sp!, {r4, fp, ip, lr, pc} + sub fp, ip, #4 + adr r3, Lcopyfault + ldr r4, Lcurproc + ldr r4, [r4] + ldr r4, [r4, #P_ADDR] + str r3, [r4, #(U_PCB + PCB_ONFAULT)] +Lkcopyloop: + ldrb r3, [r0], #1 + strb r3, [r1], #1 + subs r2, r2, #1 + bne Lkcopyloop + mov r0, #0 + str r0, [r4, #(U_PCB + PCB_ONFAULT)] + ldmdb fp, {r4, fp, sp, pc}^ + +Lcopyfault: + mov r0, #0 + str r0, [r4, #(U_PCB + PCB_ONFAULT)] + mov r0, #EFAULT + ldmdb fp, {r4, fp, sp, pc}^ + +/* int fubyte(void *base); */ +ENTRY(fubyte) + mov ip, lr /* data-abort safety */ + adr r1, Lfusufault + ldr r2, Lcurproc + ldr r2, [r2] + ldr r2, [r2, #P_ADDR] + str r1, [r2, #(U_PCB + PCB_ONFAULT)] + ldrbt r0, [r0] + mov r1, #0 + str r1, [r2, #(U_PCB + PCB_ONFAULT)] + movs pc, ip + +/* int fuword(void *base); */ +ENTRY(fuword) + mov ip, lr + adr r1, Lfusufault + ldr r2, Lcurproc + ldr r2, [r2] + ldr r2, [r2, #P_ADDR] + str r1, [r2, #(U_PCB + PCB_ONFAULT)] + ldrt r0, [r0] + mov r1, #0 + str r1, [r2, #(U_PCB + PCB_ONFAULT)] + movs pc, lr + +/* int subyte(void *base, int c); */ +ENTRY(subyte) + mov ip, lr + adr r3, Lfusufault + ldr r2, Lcurproc + ldr r2, [r2] + ldr r2, [r2, #P_ADDR] + str r3, [r2, #(U_PCB + PCB_ONFAULT)] + strbt r1, [r0] + mov r0, #0 + str r0, [r2, #(U_PCB + PCB_ONFAULT)] + movs pc, ip + +/* int suword(void *base, long c); */ +ENTRY(suword) + mov ip, lr + adr r3, Lfusufault + ldr r2, Lcurproc + ldr r2, [r2] + ldr r2, [r2, #P_ADDR] + str r3, [r2, #(U_PCB + PCB_ONFAULT)] + strt r1, [r0] + mov r0, #0 + str r0, [r2, #(U_PCB + PCB_ONFAULT)] + movs pc, ip + +Lfusufault: + mov r0, #0 + str r0, [r2, #(U_PCB + PCB_ONFAULT)] + mvn r0, #0 + movs pc, ip + +Lcurproc: + .word _C_LABEL(curproc) + diff --git a/sys/arch/arm26/arm26/copyinoutstr.c b/sys/arch/arm26/arm26/copyinoutstr.c new file mode 100644 index 00000000000..370db98d670 --- /dev/null +++ b/sys/arch/arm26/arm26/copyinoutstr.c @@ -0,0 +1,108 @@ +/* $NetBSD: copyinoutstr.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * copyinoutstr.c -- copy strings with sanity checking + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: copyinoutstr.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $"); + +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/user.h> +#include <machine/pcb.h> +#include <vm/vm_param.h> + +/* + * FIXME: These are bogus. They should use LDRT and friends for user + * accesses. + */ + +int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) +{ + int err; + + /* Check if this is an easy case */ + if (uaddr < (void *)VM_MIN_ADDRESS || + uaddr >= (void *)VM_MAXUSER_ADDRESS) + return EFAULT; + if (uaddr + len < (void *)VM_MAXUSER_ADDRESS) + return copystr(uaddr, kaddr, len, done); + err = copystr(uaddr, kaddr, (void *)VM_MAXUSER_ADDRESS - uaddr, done); + if (err == ENAMETOOLONG) + return EFAULT; + return err; +} + +int copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done) +{ + int err; + + /* Check if this is an easy case */ + if (uaddr < (void *)VM_MIN_ADDRESS || + uaddr > (void *)VM_MAXUSER_ADDRESS) + return EFAULT; + if (uaddr + len < (void *)VM_MAXUSER_ADDRESS) + return copystr(kaddr, uaddr, len, done); + err = copystr(kaddr, uaddr, (void *)VM_MAXUSER_ADDRESS - uaddr, done); + if (err == ENAMETOOLONG) + return EFAULT; + return err; +} + +int copystr(const void *src, void *dest, size_t len, size_t *done) +{ + label_t here; + size_t count; + int c; + char const *s; + char *d; + + if (setjmp(&here) == 0) { + s = src; d = dest; + curproc->p_addr->u_pcb.pcb_onfault = &here; + c = -1; + *done = count = 0; + while (count < len) { + c = d[count] = s[count]; + *done = ++count; + if (c == 0) + break; + } + curproc->p_addr->u_pcb.pcb_onfault = NULL; + if (c == 0) + return 0; + return ENAMETOOLONG; + } else { + curproc->p_addr->u_pcb.pcb_onfault = NULL; + return EFAULT; + } +} diff --git a/sys/arch/arm26/arm26/cpu.c b/sys/arch/arm26/arm26/cpu.c new file mode 100644 index 00000000000..a2db2bafd2c --- /dev/null +++ b/sys/arch/arm26/arm26/cpu.c @@ -0,0 +1,206 @@ +/* $NetBSD: cpu.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * cpu.c - high-level CPU detection etc + */ + +#include <sys/param.h> + +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/time.h> +#include <sys/user.h> +#include <machine/armreg.h> +#include <machine/machdep.h> +#include <machine/pcb.h> + +#include <arch/arm26/arm26/cpuvar.h> + +#include "opt_cputypes.h" + +static int cpu_match(struct device *, struct cfdata *, void *); +static void cpu_attach(struct device *, struct device *, void *); +static register_t cpu_identify(void); +#ifdef CPU_ARM3 +static void cpu_arm3_setup(struct device *); +#endif +static void cpu_delay_calibrate(struct device *); + +register_t cpu_type; + +struct cpu_softc { + struct device sc_dev; +}; + +struct cfattach cpu_ca = { + sizeof(struct cpu_softc), cpu_match, cpu_attach +}; + +static int +cpu_match(struct device *parent, struct cfdata *cf, void *aux) +{ + + if (cf->cf_unit == 0) + return 1; + return 0; +} + +static void +cpu_attach(struct device *parent, struct device *self, void *aux) +{ + int supported; + + printf(": "); + cpu_type = cpu_identify(); + supported = 0; + switch (cpu_type & CPU_ID_CPU_MASK) { + case CPU_ID_ARM2: + printf("ARM2"); +#ifdef CPU_ARM2 + supported = 1; +#endif + break; + case CPU_ID_ARM250: + printf("ARM250"); +#ifdef CPU_ARM250 + supported = 1; +#endif + break; + case CPU_ID_ARM3: + printf("ARM3 (rev. %d)", cpu_type & CPU_ID_REVISION_MASK); +#ifdef CPU_ARM3 + supported = 1; + cpu_arm3_setup(self); +#endif + break; + default: + printf("Unknown type, ID=0x%08x", cpu_type); + break; + } + printf("\n"); + if (!supported) + printf("%s: WARNING: CPU type not supported by kernel\n", + self->dv_xname); + config_interrupts(self, cpu_delay_calibrate); +} + +static register_t +cpu_identify() +{ + label_t here; + register_t dummy; + volatile register_t id; + + if (setjmp(&here) == 0) { + curproc->p_addr->u_pcb.pcb_onundef_lj = &here; + id = CPU_ID_ARM2; + /* ARM250 and ARM3 support SWP. */ + asm volatile ("swp r0, r0, [%0]" : : "r" (&dummy) : "r0"); + id = CPU_ID_ARM250; + /* ARM3 has an internal coprocessor 15 with an ID register. */ + asm volatile ("mrc 15, 0, %0, cr0, cr0" : "=r" (id)); + } + curproc->p_addr->u_pcb.pcb_onundef_lj = NULL; + return id; +} + +#ifdef CPU_ARM3 + +#define ARM3_READ(reg, var) \ + asm ("mrc 15, 0, %0, cr" __STRING(reg) ", cr0" : "=r" (var)) +#define ARM3_WRITE(reg, val) \ + asm ("mcr 15, 0, %0, cr" __STRING(reg) ", cr0" : : "r" (val)) + +static void +cpu_arm3_setup(struct device *self) +{ + int oldctl; + + /* + * We decide whether to enable the cache based on its current + * state. This is very dodgy, since the bootloader really + * _should_ disable it for us, but currently BBBB doesn't. In + * future, this should probably be a flag in the cpu + * attachment. + */ + ARM3_READ(ARM3_CP15_CONTROL, oldctl); + if (oldctl & ARM3_CTL_CACHE_ON) { + /* Disable the cache while we set things up. */ + ARM3_WRITE(ARM3_CP15_CONTROL, ARM3_CTL_SHARED); + /* All RAM and ROM is cacheable. */ + ARM3_WRITE(ARM3_CP15_CACHEABLE, 0xfcffffff); + /* All RAM is updateable. */ + ARM3_WRITE(ARM3_CP15_UPDATEABLE, 0x00ffffff); + /* Nothing is disruptive. We'll do cache flushing manually. */ + ARM3_WRITE(ARM3_CP15_DISRUPTIVE, 0x00000000); + /* Flush the cache and turn it on. */ + ARM3_WRITE(ARM3_CP15_FLUSH, 0); + ARM3_WRITE(ARM3_CP15_CONTROL, + ARM3_CTL_CACHE_ON | ARM3_CTL_SHARED); + printf(", cache enabled"); + cpu_delay_factor = 8; + } else { + ARM3_WRITE(ARM3_CP15_CONTROL, ARM3_CTL_SHARED); + printf(", cache disabled"); + } +} +#endif + +/* XXX This should be inlined. */ +void +cpu_cache_flush(void) +{ + +#ifdef CPU_ARM3 +#if defined(CPU_ARM2) || defined(CPU_ARM250) + if ((cpu_type & CPU_ID_CPU_MASK) == CPU_ID_ARM3) +#endif + ARM3_WRITE(ARM3_CP15_FLUSH, 0); +#endif +} + +int cpu_delay_factor = 1; + +static void +cpu_delay_calibrate(struct device *self) +{ + struct timeval start, end, diff; + + microtime(&start); + cpu_delayloop(10000); + microtime(&end); + timersub(&end, &start, &diff); + cpu_delay_factor = 10000 / diff.tv_usec + 1; + printf("%s: 10000 loops in %ld microseconds, delay factor = %d\n", + self->dv_xname, diff.tv_usec, cpu_delay_factor); +} diff --git a/sys/arch/arm26/arm26/cpuvar.h b/sys/arch/arm26/arm26/cpuvar.h new file mode 100644 index 00000000000..96381a9b278 --- /dev/null +++ b/sys/arch/arm26/arm26/cpuvar.h @@ -0,0 +1,42 @@ +/* $NetBSD: cpuvar.h,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARM26_CPUVAR_H_ +#define _ARM26_CPUVAR_H_ + +extern register_t cpu_type; +extern int cpu_delay_factor; + +/* Fixed code sequence for reliability */ +#define cpu_delayloop(loops) \ + asm volatile ("1:subs %0, %0, #1; bne 1b" : : "r" (loops) : "cc") + +extern void cpu_cache_flush(void); + +#endif diff --git a/sys/arch/arm26/arm26/db_disasm.c b/sys/arch/arm26/arm26/db_disasm.c new file mode 100644 index 00000000000..136cb6e4aa2 --- /dev/null +++ b/sys/arch/arm26/arm26/db_disasm.c @@ -0,0 +1,75 @@ +/* $NetBSD: db_disasm.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Mark Brinicombe. + * Copyright (c) 1996 Brini. + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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/param.h> +#include <machine/db_machdep.h> +#include <ddb/db_sym.h> +#include <ddb/db_output.h> +#include <ddb/db_access.h> + +#include <arm32/arm32/disassem.h> + +/* Glue code to interface db_disasm to the generic ARM disassembler */ + +static u_int db_disasm_read_word(u_int); +static void db_disasm_printaddr(u_int); + +static disasm_interface_t db_disasm_interface = { + db_disasm_read_word, db_disasm_printaddr, db_printf +}; + +static u_int +db_disasm_read_word(u_int address) +{ + + return db_get_value(address, 4, 0); +} + +static void +db_disasm_printaddr(u_int address) +{ + + db_printsym((db_addr_t)address, DB_STGY_ANY); +} + +vm_offset_t +db_disasm(vm_offset_t loc, boolean_t altfmt) +{ + + return disasm(&db_disasm_interface, loc, altfmt); +} + +/* End of db_disasm.c */ diff --git a/sys/arch/arm26/arm26/db_interface.c b/sys/arch/arm26/arm26/db_interface.c new file mode 100644 index 00000000000..5fa8bd94ad5 --- /dev/null +++ b/sys/arch/arm26/arm26/db_interface.c @@ -0,0 +1,345 @@ +/* $NetBSD: db_interface.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Scott K. Stevens + * + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) + */ + +/* + * Interface to new debugger. + */ +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/reboot.h> +#include <sys/systm.h> /* just for boothowto */ +#include <sys/exec.h> + +#include <vm/vm.h> + +#include <machine/db_machdep.h> +#include <ddb/db_access.h> +#include <ddb/db_command.h> +#include <ddb/db_output.h> +#include <ddb/db_interface.h> +#include <ddb/db_variables.h> +#include <ddb/db_sym.h> +#include <ddb/db_extern.h> +#include <dev/cons.h> + +static int nil; + +int db_access_und_sp __P((struct db_variable *, db_expr_t *, int)); +int db_access_abt_sp __P((struct db_variable *, db_expr_t *, int)); +int db_access_irq_sp __P((struct db_variable *, db_expr_t *, int)); +u_int db_fetch_reg __P((int, db_regs_t *)); + +static int db_validate_address __P((vm_offset_t)); +static void db_write_text __P((unsigned char *, int ch)); + +struct db_variable db_regs[] = { + { "r0", (long *)&DDB_TF->tf_r0, FCN_NULL }, + { "r1", (long *)&DDB_TF->tf_r1, FCN_NULL }, + { "r2", (long *)&DDB_TF->tf_r2, FCN_NULL }, + { "r3", (long *)&DDB_TF->tf_r3, FCN_NULL }, + { "r4", (long *)&DDB_TF->tf_r4, FCN_NULL }, + { "r5", (long *)&DDB_TF->tf_r5, FCN_NULL }, + { "r6", (long *)&DDB_TF->tf_r6, FCN_NULL }, + { "r7", (long *)&DDB_TF->tf_r7, FCN_NULL }, + { "r8", (long *)&DDB_TF->tf_r8, FCN_NULL }, + { "r9", (long *)&DDB_TF->tf_r9, FCN_NULL }, + { "r10", (long *)&DDB_TF->tf_r10, FCN_NULL }, + { "r11", (long *)&DDB_TF->tf_r11, FCN_NULL }, + { "r12", (long *)&DDB_TF->tf_r12, FCN_NULL }, + { "r13", (long *)&DDB_TF->tf_r13, FCN_NULL }, + { "r14", (long *)&DDB_TF->tf_r14, FCN_NULL }, + { "r15", (long *)&DDB_TF->tf_r15, FCN_NULL }, +}; + +struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); + +extern label_t *db_recover; + +int db_active = 0; + +/* + * kdb_trap - field a TRACE or BPT trap + */ +int +kdb_trap(type, regs) + int type; + db_regs_t *regs; +{ + int s; + + switch (type) { + case T_BREAKPOINT: /* breakpoint */ + case -1: /* keyboard interrupt */ + break; + default: + if (db_recover != 0) { + db_error("Faulted in DDB; continuing...\n"); + /*NOTREACHED*/ + } + } + + /* Should switch to kdb`s own stack here. */ + + ddb_regs = *regs; + + s = splhigh(); + db_active++; + cnpollc(TRUE); + db_trap(type, 0/*code*/); + cnpollc(FALSE); + db_active--; + splx(s); + + *regs = ddb_regs; + + return 1; +} + +static int +db_validate_address(addr) + vm_offset_t addr; +{ + + /* FIXME */ + return 0; +} + +/* + * Read bytes from kernel address space for debugger. + */ +void +db_read_bytes(addr, size, data) + vm_offset_t addr; + size_t size; + char *data; +{ + char *src; + + src = (char *)addr; + for (; size > 0; size--) { + if (db_validate_address((u_int)src)) { + db_printf("address %p is invalid\n", src); + return; + } + *data++ = *src++; + } +} + +static void +db_write_text(dst, ch) + unsigned char *dst; + int ch; +{ + + if (db_validate_address((u_int)dst)) { + db_printf(" address %p not a valid page\n", dst); + return; + } + + *dst = (unsigned char)ch; +} + +/* + * Write bytes to kernel address space for debugger. + */ +void +db_write_bytes(addr, size, data) + vm_offset_t addr; + size_t size; + char *data; +{ +#if 0 + extern char _stext_[], _etext[]; +#endif + char *dst; + int loop; + + dst = (char *)addr; + loop = size; + while (--loop >= 0) { +#if 0 /* FIXME */ + if ((dst >= _stext_) && (dst < _etext)) +#endif + db_write_text(dst, *data); +#if 0 + else { + if (db_validate_address((u_int)dst)) { + db_printf("address %p is invalid\n", dst); + return; + } + *dst = *data; + } +#endif + dst++, data++; + } +} + +void db_show_vmstat_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif)); +void db_show_vnode_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif)); +void db_show_intrchain_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif)); +void db_show_panic_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif)); +void db_show_frame_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif)); + +struct db_command arm26_db_command_table[] = { + { "frame", db_show_frame_cmd, 0, NULL }, +#if 0 + { "intrchain", db_show_intrchain_cmd, 0, NULL }, +#endif + { "panic", db_show_panic_cmd, 0, NULL }, + { "vmstat", db_show_vmstat_cmd, 0, NULL }, + { "vnode", db_show_vnode_cmd, 0, NULL }, + { NULL, NULL, 0, NULL } +}; + +int +db_trapper(addr, inst, frame, fault_code) + u_int addr; + u_int inst; + trapframe_t *frame; + int fault_code; +{ + if (fault_code == 0) { + if ((inst & ~0xf0000000) == (BKPT_INST & ~0xf0000000)) + kdb_trap(T_BREAKPOINT, frame); + else + kdb_trap(-1, frame); + } else + return 1; + return 0; +} + +extern u_int esym; +extern u_int end; + +void +db_machine_init() +{ + + db_machine_commands_install(arm26_db_command_table); +} + +u_int +db_fetch_reg(reg, db_regs) + int reg; + db_regs_t *db_regs; +{ + + switch (reg) { + case 0: + return (db_regs->ddb_tf.tf_r0); + case 1: + return (db_regs->ddb_tf.tf_r1); + case 2: + return (db_regs->ddb_tf.tf_r2); + case 3: + return (db_regs->ddb_tf.tf_r3); + case 4: + return (db_regs->ddb_tf.tf_r4); + case 5: + return (db_regs->ddb_tf.tf_r5); + case 6: + return (db_regs->ddb_tf.tf_r6); + case 7: + return (db_regs->ddb_tf.tf_r7); + case 8: + return (db_regs->ddb_tf.tf_r8); + case 9: + return (db_regs->ddb_tf.tf_r9); + case 10: + return (db_regs->ddb_tf.tf_r10); + case 11: + return (db_regs->ddb_tf.tf_r11); + case 12: + return (db_regs->ddb_tf.tf_r12); + case 13: + return (db_regs->ddb_tf.tf_r13); + case 14: + return (db_regs->ddb_tf.tf_r14); + case 15: + return (db_regs->ddb_tf.tf_r15); + default: + panic("db_fetch_reg: botch"); + } +} + +u_int +branch_taken(insn, pc, db_regs) + u_int insn; + u_int pc; + db_regs_t *db_regs; +{ + u_int addr, nregs; + + switch ((insn >> 24) & 0xf) { + case 0xa: /* b ... */ + case 0xb: /* bl ... */ + addr = ((insn << 2) & 0x03ffffff); + if (addr & 0x02000000) + addr |= 0xfc000000; + return (pc + 8 + addr); + case 0x7: /* ldr pc, [pc, reg, lsl #2] */ + addr = db_fetch_reg(insn & 0xf, db_regs); + addr = pc + 8 + (addr << 2); + db_read_bytes(addr, 4, (char *)&addr); + return (addr); + case 0x1: /* mov pc, reg */ + addr = db_fetch_reg(insn & 0xf, db_regs); + return (addr); + case 0x8: /* ldmxx reg, {..., pc} */ + case 0x9: + addr = db_fetch_reg((insn >> 16) & 0xf, db_regs); + nregs = (insn & 0x5555) + ((insn >> 1) & 0x5555); + nregs = (nregs & 0x3333) + ((nregs >> 2) & 0x3333); + nregs = (nregs + (nregs >> 4)) & 0x0f0f; + nregs = (nregs + (nregs >> 8)) & 0x001f; + switch ((insn >> 23) & 0x3) { + case 0x0: /* ldmda */ + addr = addr - 0; + break; + case 0x1: /* ldmia */ + addr = addr + 0 + ((nregs - 1) << 2); + break; + case 0x2: /* ldmdb */ + addr = addr - 4; + break; + case 0x3: /* ldmib */ + addr = addr + 4 + ((nregs - 1) << 2); + break; + } + db_read_bytes(addr, 4, (char *)&addr); + return (addr); + default: + panic("branch_taken: botch"); + } +} diff --git a/sys/arch/arm26/arm26/db_machdep.c b/sys/arch/arm26/arm26/db_machdep.c new file mode 100644 index 00000000000..b9c90b40983 --- /dev/null +++ b/sys/arch/arm26/arm26/db_machdep.c @@ -0,0 +1,227 @@ +/* $NetBSD: db_machdep.c,v 1.1 2000/05/09 21:55:55 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Mark Brinicombe + * + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/vnode.h> +#include <sys/systm.h> + +#include <machine/db_machdep.h> + +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_output.h> + +/* + * Print out a description of a vnode. + * Some parts borrowed from kern/vfs_subr.c + */ + +static char *typename[] = + { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" }; + +void +db_show_vnode_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + char buf[64]; + struct vnode *vp; + + if (!have_addr) { + db_printf("vnode address must be specified\n"); + return; + } + + vp = (struct vnode *)addr; + +/* Decode the one argument */ + + db_printf("vp : %08x\n", (u_int)vp); + db_printf("vp->v_type = %d\n", vp->v_type); + db_printf("vp->v_flag = %ld\n", vp->v_flag); + db_printf("vp->v_numoutput = %ld\n", vp->v_numoutput); + + db_printf("type %s, usecount %ld, writecount %ld, refcount %ld,", + typename[vp->v_type], vp->v_usecount, vp->v_writecount, + vp->v_holdcnt); + buf[0] = '\0'; + if (vp->v_flag & VROOT) + strcat(buf, "|VROOT"); + if (vp->v_flag & VTEXT) + strcat(buf, "|VTEXT"); + if (vp->v_flag & VSYSTEM) + strcat(buf, "|VSYSTEM"); + if (vp->v_flag & VXLOCK) + strcat(buf, "|VXLOCK"); + if (vp->v_flag & VXWANT) + strcat(buf, "|VXWANT"); + if (vp->v_flag & VBWAIT) + strcat(buf, "|VBWAIT"); + if (vp->v_flag & VALIASED) + strcat(buf, "|VALIASED"); + if (buf[0] != '\0') + db_printf(" flags (%s)", &buf[1]); + db_printf("\n"); + if (vp->v_data != NULL) { + db_printf("data=%08x\n", (u_int)vp->v_data); + } +} + +void +db_show_vmstat_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + + db_printf("Current UVM status:\n"); + db_printf(" pagesize=%d (0x%x), pagemask=0x%x, pageshift=%d\n", + uvmexp.pagesize, uvmexp.pagesize, uvmexp.pagemask, + uvmexp.pageshift); + db_printf(" %d VM pages: %d active, %d inactive, %d wired, %d free\n", + uvmexp.npages, uvmexp.active, uvmexp.inactive, uvmexp.wired, + uvmexp.free); + db_printf(" freemin=%d, free-target=%d, inactive-target=%d, " + "wired-max=%d\n", uvmexp.freemin, uvmexp.freetarg, uvmexp.inactarg, + uvmexp.wiredmax); + db_printf(" faults=%d, traps=%d, intrs=%d, ctxswitch=%d\n", + uvmexp.faults, uvmexp.traps, uvmexp.intrs, uvmexp.swtch); + db_printf(" softint=%d, syscalls=%d, swapins=%d, swapouts=%d\n", + uvmexp.softs, uvmexp.syscalls, uvmexp.swapins, uvmexp.swapouts); + + db_printf(" fault counts:\n"); + db_printf(" noram=%d, noanon=%d, pgwait=%d, pgrele=%d\n", + uvmexp.fltnoram, uvmexp.fltnoanon, uvmexp.fltpgwait, + uvmexp.fltpgrele); + db_printf(" ok relocks(total)=%d(%d), anget(retrys)=%d(%d), " + "amapcopy=%d\n", uvmexp.fltrelckok, uvmexp.fltrelck, + uvmexp.fltanget, uvmexp.fltanretry, uvmexp.fltamcopy); + db_printf(" neighbor anon/obj pg=%d/%d, gets(lock/unlock)=%d/%d\n", + uvmexp.fltnamap, uvmexp.fltnomap, uvmexp.fltlget, uvmexp.fltget); + db_printf(" cases: anon=%d, anoncow=%d, obj=%d, prcopy=%d, przero=%d\n", + uvmexp.flt_anon, uvmexp.flt_acow, uvmexp.flt_obj, uvmexp.flt_prcopy, + uvmexp.flt_przero); + + db_printf(" daemon and swap counts:\n"); + db_printf(" woke=%d, revs=%d, scans=%d, swout=%d\n", uvmexp.pdwoke, + uvmexp.pdrevs, uvmexp.pdscans, uvmexp.pdswout); + db_printf(" busy=%d, freed=%d, reactivate=%d, deactivate=%d\n", + uvmexp.pdbusy, uvmexp.pdfreed, uvmexp.pdreact, uvmexp.pddeact); + db_printf(" pageouts=%d, pending=%d, nswget=%d\n", uvmexp.pdpageouts, + uvmexp.pdpending, uvmexp.nswget); + db_printf(" nswapdev=%d, nanon=%d, nfreeanon=%d\n", uvmexp.nswapdev, + uvmexp.nanon, uvmexp.nfreeanon); + + db_printf(" kernel pointers:\n"); + db_printf(" objs(kmem/mb)=%p/%p\n", uvmexp.kmem_object, + uvmexp.mb_object); +} + +#if 0 +void +db_show_intrchain_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + int loop; + irqhandler_t *ptr; + char *name; + db_expr_t offset; + + for (loop = 0; loop < NIRQS; ++loop) { + ptr = irqhandlers[loop]; + if (ptr) { + db_printf("IRQ %d\n", loop); + + while (ptr) { + db_printf(" %-13s %d ", ptr->ih_name, ptr->ih_level); + db_find_sym_and_offset((u_int)ptr->ih_func, &name, &offset); + if (name == NULL) + name = "?"; + + db_printf("%s(", name); + db_printsym((u_int)ptr->ih_func, DB_STGY_PROC); + db_printf(") %08x\n", (u_int)ptr->ih_arg); + ptr = ptr->ih_next; + } + } + } +} +#endif + +void +db_show_panic_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + int s; + + s = splhigh(); + + db_printf("Panic string: %s\n", panicstr); + + (void)splx(s); +} + + +void +db_show_frame_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + struct trapframe *frame; + + if (!have_addr) { + db_printf("frame address must be specified\n"); + return; + } + + frame = (struct trapframe *)addr; + + db_printf("frame address = %08x ", (u_int)frame); + db_printf("r0 =%08x r1 =%08x r2 =%08x r3 =%08x\n", + frame->tf_r0, frame->tf_r1, frame->tf_r2, frame->tf_r3); + db_printf("r4 =%08x r5 =%08x r6 =%08x r7 =%08x\n", + frame->tf_r4, frame->tf_r5, frame->tf_r6, frame->tf_r7); + db_printf("r8 =%08x r9 =%08x r10=%08x r11=%08x\n", + frame->tf_r8, frame->tf_r9, frame->tf_r10, frame->tf_r11); + db_printf("r12=%08x r13=%08x r14=%08x r15=%08x\n", + frame->tf_r12, frame->tf_r13, frame->tf_r14, frame->tf_r15); +} diff --git a/sys/arch/arm26/arm26/db_trace.c b/sys/arch/arm26/arm26/db_trace.c new file mode 100644 index 00000000000..1c31804dfb0 --- /dev/null +++ b/sys/arch/arm26/arm26/db_trace.c @@ -0,0 +1,150 @@ +/* $NetBSD: db_trace.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Scott K. Stevens + * + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <machine/armreg.h> +#include <machine/db_machdep.h> + +#include <ddb/db_access.h> +#include <ddb/db_interface.h> +#include <ddb/db_sym.h> +#include <ddb/db_output.h> + +#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS) + +void +db_stack_trace_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + struct frame *frame, *lastframe; + char c, *cp = modif; + boolean_t kernel_only = TRUE; + boolean_t trace_thread = FALSE; + + while ((c = *cp++) != 0) { + if (c == 'u') + kernel_only = FALSE; + if (c == 't') + trace_thread = TRUE; + } + + if (count == -1) + count = 65535; + + /* + * The frame pointer points to the top word of the stack frame so we + * need to adjust it by sizeof(struct frame) - sizeof(u_int)) + * to get the address of the start of the frame structure. + */ + + if (!have_addr) + frame = (struct frame *)(DDB_TF->tf_r11 + - (sizeof(struct frame) - sizeof(u_int))); + else { + if (trace_thread) { + struct proc *p; + struct user *u; + db_printf ("trace: pid %d ", (int)addr); + p = pfind(addr); + if (p == NULL) { + db_printf("not found\n"); + return; + } + if (!(p->p_flag & P_INMEM)) { + db_printf("swapped out\n"); + return; + } + u = p->p_addr; + frame = (struct frame *) (u->u_pcb.pcb_sf->sf_r11 + - (sizeof(struct frame) - sizeof(u_int))); + db_printf("at %p\n", frame); + } else + frame = (struct frame *)(addr - (sizeof(struct frame) + - sizeof(u_int))); + } + lastframe = NULL; + + while (count--) { + db_expr_t offset; + char *name; + db_addr_t pc; + +/* db_printf("fp=%08x: fp=%08x sp=%08x lr=%08x pc=%08x\n", + (u_int)frame, frame->fr_fp, frame->fr_sp, frame->fr_lr, + frame->fr_r15);*/ + + pc = frame->fr_r15 & R15_PC; + if (!INKERNEL(pc)) + break; + + db_find_sym_and_offset(pc, &name, &offset); + if (name == NULL) + name = "?"; + + db_printf("%s(", name); + db_printsym(pc, DB_STGY_PROC); + db_printf(")"); + db_printf("\n"); + + /* + * Switch to next frame up + */ + if (frame->fr_fp == 0) + break; /* Top of stack */ + + lastframe = frame; + frame = (struct frame *)(frame->fr_fp - (sizeof(struct frame) + - sizeof(u_int))); + + if (INKERNEL((int)frame)) { + /* staying in kernel */ + if (frame <= lastframe) { + db_printf("Bad frame pointer: %p\n", frame); + break; + } + } else if (INKERNEL((int)lastframe)) { + /* switch from user to kernel */ + if (kernel_only) + break; /* kernel stack only */ + } else { + /* in user */ + if (frame <= lastframe) { + db_printf("Bad user frame pointer: %p\n", + frame); + break; + } + } + } +} diff --git a/sys/arch/arm26/arm26/disksubr.c b/sys/arch/arm26/arm26/disksubr.c new file mode 100644 index 00000000000..befc2509295 --- /dev/null +++ b/sys/arch/arm26/arm26/disksubr.c @@ -0,0 +1,447 @@ +/* $NetBSD: disksubr.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ + +/* + * Copyright (c) 1998 Christopher G. Demetriou. 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 Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * Copyright (c) 1995 Mark Brinicombe + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/dkbad.h> +#include <sys/disklabel.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <sys/disk.h> + +/* + * Attempt to read a disk label from a device + * using the indicated stategy routine. + * The label must be partly set up before this: + * secpercyl, secsize and anything required for a block i/o read + * operation in the driver's strategy/start routines + * must be filled in before calling us. + * + * If dos partition table requested, attempt to load it and + * find disklabel inside a DOS partition. Also, if bad block + * table needed, attempt to extract it as well. Return buffer + * for use in signalling errors if requested. + * + * Returns null on success and an error string on failure. + */ + +char * +readdisklabel(dev, strat, lp, osdep) + dev_t dev; + void (*strat) __P((struct buf *)); + struct disklabel *lp; + struct cpu_disklabel *osdep; +{ + struct buf *bp; + struct disklabel *dlp; + char *msg = NULL; + int cyl, netbsdpartoff, i; + +/* printf("Reading disclabel for %04x\n", dev);*/ + + /* minimal requirements for archtypal disk label */ + + if (lp->d_secsize == 0) + lp->d_secsize = DEV_BSIZE; + + if (lp->d_secperunit == 0) + lp->d_secperunit = 0x1fffffff; + + lp->d_npartitions = MAXPARTITIONS; + for (i = 0; i < MAXPARTITIONS; i++) { + if (i == RAW_PART) continue; + lp->d_partitions[i].p_offset = 0; + lp->d_partitions[i].p_fstype = FS_UNUSED; + lp->d_partitions[i].p_size = 0; + } + + if (lp->d_partitions[RAW_PART].p_size == 0) { + lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; + lp->d_partitions[RAW_PART].p_offset = 0; + lp->d_partitions[RAW_PART].p_size = 0x1fffffff; + } + + /* obtain buffer to probe drive with */ + + bp = geteblk((int)lp->d_secsize); + + /* request no partition relocation by driver on I/O operations */ + + bp->b_dev = dev; + + /* do netbsd partitions in the process of getting disklabel? */ + + netbsdpartoff = 0; + cyl = LABELSECTOR / lp->d_secpercyl; + + if (osdep) { + if (filecore_label_read(dev, strat,lp, osdep, &msg, &cyl, + &netbsdpartoff) || + mbr_label_read(dev, strat, lp, osdep, &msg, &cyl, + &netbsdpartoff)) { + if (msg != NULL) + goto done; + } else { + /* + * We didn't find anything we like; NetBSD native. + * netbsdpartoff and cyl should be unchanged. + */ + KASSERT(netbsdpartoff == 0); + KASSERT(cyl == (LABELSECTOR / lp->d_secpercyl)); + } + } + + /* next, dig out disk label */ + +/* printf("Reading disklabel addr=%08x\n", netbsdpartoff * DEV_BSIZE);*/ + + bp->b_blkno = netbsdpartoff + LABELSECTOR; + bp->b_cylinder = bp->b_blkno / lp->d_secpercyl; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + + /* if successful, locate disk label within block and validate */ + + if (biowait(bp)) { + msg = "disk label I/O error"; + goto done; + } + for (dlp = (struct disklabel *)bp->b_data; + dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp)); + dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { + if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { + if (msg == NULL) + msg = "no disk label"; + } else if (dlp->d_npartitions > MAXPARTITIONS || + dkcksum(dlp) != 0) + msg = "disk label corrupted"; + else { + *lp = *dlp; + msg = NULL; + break; + } + } + + if (msg) + goto done; + + /* obtain bad sector table if requested and present */ + if (osdep && (lp->d_flags & D_BADSECT)) { + struct dkbad *bdp = &osdep->bad; + struct dkbad *db; + + i = 0; + do { + /* read a bad sector table */ + bp->b_flags = B_BUSY | B_READ; + bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i; + if (lp->d_secsize > DEV_BSIZE) + bp->b_blkno *= lp->d_secsize / DEV_BSIZE; + else + bp->b_blkno /= DEV_BSIZE / lp->d_secsize; + bp->b_bcount = lp->d_secsize; + bp->b_cylinder = lp->d_ncylinders - 1; + (*strat)(bp); + + /* if successful, validate, otherwise try another */ + if (biowait(bp)) { + msg = "bad sector table I/O error"; + } else { + db = (struct dkbad *)(bp->b_data); +#define DKBAD_MAGIC 0x4321 + if (db->bt_mbz == 0 + && db->bt_flag == DKBAD_MAGIC) { + msg = NULL; + *bdp = *db; + break; + } else + msg = "bad sector table corrupted"; + } + } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 && + i < lp->d_nsectors); + } + +done: + bp->b_flags = B_INVAL | B_AGE | B_READ; + brelse(bp); + return (msg); +} + + +/* + * Check new disk label for sensibility + * before setting it. + */ + +int +setdisklabel(olp, nlp, openmask, osdep) + struct disklabel *olp; + struct disklabel *nlp; + u_long openmask; + struct cpu_disklabel *osdep; +{ + int i; + struct partition *opp, *npp; + + /* sanity clause */ + + if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 + || (nlp->d_secsize % DEV_BSIZE) != 0) + return(EINVAL); + + /* special case to allow disklabel to be invalidated */ + + if (nlp->d_magic == 0xffffffff) { + *olp = *nlp; + return (0); + } + + if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC + || dkcksum(nlp) != 0) + return (EINVAL); + + /* XXX missing check if other acorn/dos partitions will be overwritten */ + + while (openmask != 0) { + i = ffs(openmask) - 1; + openmask &= ~(1 << i); + if (nlp->d_npartitions <= i) + return (EBUSY); + opp = &olp->d_partitions[i]; + npp = &nlp->d_partitions[i]; + if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size) + return (EBUSY); + /* + * Copy internally-set partition information + * if new label doesn't include it. XXX + */ + if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) { + npp->p_fstype = opp->p_fstype; + npp->p_fsize = opp->p_fsize; + npp->p_frag = opp->p_frag; + npp->p_cpg = opp->p_cpg; + } + } + + nlp->d_checksum = 0; + nlp->d_checksum = dkcksum(nlp); + *olp = *nlp; + return (0); +} + + +/* + * Write disk label back to device after modification. + */ + +int +writedisklabel(dev, strat, lp, osdep) + dev_t dev; + void (*strat) __P((struct buf *)); + struct disklabel *lp; + struct cpu_disklabel *osdep; +{ + struct buf *bp; + struct disklabel *dlp; + int cyl, netbsdpartoff; + int error = 0, rv; + + /* get a buffer and initialize it */ + + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + /* do netbsd partitions in the process of getting disklabel? */ + + netbsdpartoff = 0; + cyl = LABELSECTOR / lp->d_secpercyl; + + if (osdep) { + if ((rv = filecore_label_locate(dev, strat,lp, osdep, &cyl, + &netbsdpartoff)) != 0|| + (rv = mbr_label_locate(dev, strat, lp, osdep, &cyl, + &netbsdpartoff)) != 0) { + if (rv < 0) { + error = -rv; + goto done; + } + } else { + /* + * We didn't find anything we like; NetBSD native. + * netbsdpartoff and cyl should be unchanged. + */ + KASSERT(netbsdpartoff == 0); + KASSERT(cyl == (LABELSECTOR / lp->d_secpercyl)); + } + } + +/* writelabel: */ + +/* printf("writedisklabel: Reading disklabel addr=%08x\n", + netbsdpartoff * DEV_BSIZE);*/ + + /* next, dig out disk label */ + + bp->b_blkno = netbsdpartoff + LABELSECTOR; + bp->b_cylinder = cyl; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + + /* if successful, locate disk label within block and validate */ + + if ((error = biowait(bp))) + goto done; + for (dlp = (struct disklabel *)bp->b_data; + dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp)); + dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { + if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && + dkcksum(dlp) == 0) { + *dlp = *lp; + bp->b_flags = B_BUSY | B_WRITE; + (*strat)(bp); + error = biowait(bp); + goto done; + } + } + + error = ESRCH; + +done: + bp->b_flags |= B_INVAL; + brelse(bp); + return (error); +} + + +/* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. Adjust transfer + * if needed, and signal errors or early completion. + */ +int +bounds_check_with_label(bp, lp, wlabel) + struct buf *bp; + struct disklabel *lp; + int wlabel; +{ + struct partition *p = lp->d_partitions + DISKPART(bp->b_dev); + int labelsector = lp->d_partitions[0].p_offset + LABELSECTOR; + int sz; + + sz = howmany(bp->b_bcount, lp->d_secsize); + + if (bp->b_blkno + sz > p->p_size) { + sz = p->p_size - bp->b_blkno; + if (sz == 0) { + /* If exactly at end of disk, return EOF. */ + bp->b_resid = bp->b_bcount; + goto done; + } + if (sz < 0) { + /* If past end of disk, return EINVAL. */ + bp->b_error = EINVAL; + goto bad; + } + /* Otherwise, truncate request. */ + bp->b_bcount = sz << DEV_BSHIFT; + } + + /* Overwriting disk label? */ + if (bp->b_blkno + p->p_offset <= labelsector && +#if LABELSECTOR != 0 + bp->b_blkno + p->p_offset + sz > labelsector && +#endif + (bp->b_flags & B_READ) == 0 && !wlabel) { + bp->b_error = EROFS; + goto bad; + } + + /* calculate cylinder for disksort to order transfers with */ + bp->b_cylinder = (bp->b_blkno + p->p_offset) / + (lp->d_secsize / DEV_BSIZE) / lp->d_secpercyl; + return (1); + +bad: + bp->b_flags |= B_ERROR; +done: + return (0); +} + + +void +dk_establish(dk, dev) + struct disk *dk; + struct device *dev; +{ + return; +} + +/* End of disksubr.c */ diff --git a/sys/arch/arm26/arm26/disksubr_acorn.c b/sys/arch/arm26/arm26/disksubr_acorn.c new file mode 100644 index 00000000000..db66b10f0e4 --- /dev/null +++ b/sys/arch/arm26/arm26/disksubr_acorn.c @@ -0,0 +1,359 @@ +/* $NetBSD: disksubr_acorn.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ + +/* + * Copyright (c) 1998 Christopher G. Demetriou. 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 Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * Copyright (c) 1995 Mark Brinicombe + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/disklabel.h> + +static int filecore_checksum __P((u_char *)); + +/* + * static int filecore_checksum(u_char *bootblock) + * + * Calculates the filecore boot block checksum. This is used to validate + * a filecore boot block on the disk. If a boot block is validated then + * it is used to locate the partition table. If the boot block is not + * validated, it is assumed that the whole disk is NetBSD. + * + * The basic algorithm is: + * + * for (each byte in block, excluding checksum) { + * sum += byte; + * if (sum > 255) + * sum -= 255; + * } + * + * That's equivalent to summing all of the bytes in the block + * (excluding the checksum byte, of course), then calculating the + * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That + * expression may or may not yield a faster checksum function, + * but it's easier to reason about. + * + * Note that if you have a block filled with bytes of a single + * value "X" (regardless of that value!) and calculate the cksum + * of the block (excluding the checksum byte), you will _always_ + * end up with a checksum of X. (Do the math; that can be derived + * from the checksum calculation function!) That means that + * blocks which contain bytes which all have the same value will + * always checksum properly. That's a _very_ unlikely occurence + * (probably impossible, actually) for a valid filecore boot block, + * so we treat such blocks as invalid. + */ +static int +filecore_checksum(bootblock) + u_char *bootblock; +{ + u_char byte0, accum_diff; + u_int sum; + int i; + + sum = 0; + accum_diff = 0; + byte0 = bootblock[0]; + + /* + * Sum the contents of the block, keeping track of whether + * or not all bytes are the same. If 'accum_diff' ends up + * being zero, all of the bytes are, in fact, the same. + */ + for (i = 0; i < 511; ++i) { + sum += bootblock[i]; + accum_diff |= bootblock[i] ^ byte0; + } + + /* + * Check to see if the checksum byte is the same as the + * rest of the bytes, too. (Note that if all of the bytes + * are the same except the checksum, a checksum compare + * won't succeed, but that's not our problem.) + */ + accum_diff |= bootblock[i] ^ byte0; + + /* All bytes in block are the same; call it invalid. */ + if (accum_diff == 0) + return (-1); + + return (sum - ((sum - 1) / 255) * 255); +} + + +int +filecore_label_read(dev, strat, lp, osdep, msgp, cylp, netbsd_label_offp) + dev_t dev; + void (*strat) __P((struct buf *)); + struct disklabel *lp; + struct cpu_disklabel *osdep; + char **msgp; + int *cylp, *netbsd_label_offp; +{ + struct filecore_bootblock *bb; + int heads; + int sectors; + int rv = 1; + int cyl, netbsdpartoff; + struct buf *bp; + +#ifdef __GNUC__ + netbsdpartoff = 0; /* XXX -Wuninitialized */ +#endif + + /* get a buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + /* read the Acorn filecore boot block */ + + bp->b_blkno = FILECORE_BOOT_SECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + bp->b_cylinder = bp->b_blkno / lp->d_secpercyl; + (*strat)(bp); + + /* + * if successful, validate boot block and + * locate partition table + */ + + if (biowait(bp)) { + *msgp = "filecore boot block I/O error"; + goto out; + } + + bb = (struct filecore_bootblock *)bp->b_data; + + /* Validate boot block */ + + if (bb->checksum != filecore_checksum((u_char *)bb)) { + /* + * Invalid boot block so lets assume the + * entire disc is NetBSD + */ + rv = 0; + goto out; + } + + /* Get some information from the boot block */ + + cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8); + + heads = bb->heads; + sectors = bb->secspertrack; + + /* Do we have a NETBSD partition table ? */ + + if (bb->partition_type == PARTITION_FORMAT_RISCBSD) { +/* printf("heads = %d nsectors = %d\n", heads, sectors);*/ + netbsdpartoff = cyl * heads * sectors; + } else if (bb->partition_type == PARTITION_FORMAT_RISCIX) { + struct riscix_partition_table *rpt; + int loop; + + /* + * We have a RISCiX partition table :-( groan + * + * Read the RISCiX partition table and see if + * there is a NetBSD partition + */ + + bp->b_blkno = cyl * heads * sectors; +/* printf("Found RiscIX partition table @ %08x\n", + bp->b_blkno);*/ + bp->b_cylinder = bp->b_blkno / lp->d_secpercyl; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + + /* + * if successful, locate disk label within block + * and validate + */ + + if (biowait(bp)) { + *msgp = "disk label I/O error"; + goto out; + } + + rpt = (struct riscix_partition_table *)bp->b_data; +/* for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) + printf("p%d: %16s %08x %08x %08x\n", loop, + rpt->partitions[loop].rp_name, + rpt->partitions[loop].rp_start, + rpt->partitions[loop].rp_length, + rpt->partitions[loop].rp_type); +*/ + for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) { + if (strcmp(rpt->partitions[loop].rp_name, + "RiscBSD") == 0 || + strcmp(rpt->partitions[loop].rp_name, + "NetBSD") == 0 || + strcmp(rpt->partitions[loop].rp_name, + "Empty:") == 0) { + netbsdpartoff = + rpt->partitions[loop].rp_start; + break; + } + } + if (loop == NRISCIX_PARTITIONS) { + *msgp = "NetBSD partition identifier string not found."; + goto out; + } + } else { + *msgp = "Invalid partition format"; + goto out; + } + + *cylp = cyl; + *netbsd_label_offp = netbsdpartoff; + *msgp = NULL; +out: + bp->b_flags = B_INVAL | B_AGE | B_READ; + brelse(bp); + return (rv); +} + + +int +filecore_label_locate(dev, strat, lp, osdep, cylp, netbsd_label_offp) + dev_t dev; + void (*strat) __P((struct buf *)); + struct disklabel *lp; + struct cpu_disklabel *osdep; + int *cylp, *netbsd_label_offp; +{ + struct filecore_bootblock *bb; + int heads; + int sectors; + int rv; + int cyl, netbsdpartoff; + struct buf *bp; + + /* get a buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + /* read the filecore boot block */ + +/* printf("writedisklabel: Reading boot block\n");*/ + + bp->b_blkno = FILECORE_BOOT_SECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + bp->b_cylinder = bp->b_blkno / lp->d_secpercyl; + (*strat)(bp); + + /* + * if successful, validate boot block and locate + * partition table + */ + + if ((rv = biowait(bp)) != 0) { + rv = -rv; + goto out; + } + + bb = (struct filecore_bootblock *)bp->b_data; + rv = 1; + + /* Validate boot block */ + + if (bb->checksum != filecore_checksum((u_char *)bb)) { + /* + * Invalid boot block so lets assume the + * entire disc is NetBSD + */ + +/* printf("writedisklabel: Invalid filecore boot block (incorrect checksum)\n");*/ + rv = 0; + goto out; + } + + /* Do we have a NetBSD partition ? */ + + if (bb->partition_type != PARTITION_FORMAT_RISCBSD) { + printf("writedisklabel: Invalid partition format\n"); + rv = -1; + goto out; + } + + cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8); + + heads = bb->heads; + sectors = bb->secspertrack; + + /*printf("heads = %d nsectors = %d\n", heads, sectors);*/ + + netbsdpartoff = cyl * heads * sectors; + + *cylp = cyl; + *netbsd_label_offp = netbsdpartoff; +out: + bp->b_flags = B_INVAL | B_AGE | B_READ; + brelse(bp); + return (rv); +} diff --git a/sys/arch/arm26/arm26/disksubr_mbr.c b/sys/arch/arm26/arm26/disksubr_mbr.c new file mode 100644 index 00000000000..9bdd1479681 --- /dev/null +++ b/sys/arch/arm26/arm26/disksubr_mbr.c @@ -0,0 +1,278 @@ +/* $NetBSD: disksubr_mbr.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ + +/* + * Copyright (c) 1998 Christopher G. Demetriou. 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 Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + */ + +/* + * From i386 disklabel.c rev 1.29, with cleanups and modifications to + * make it easier to use on the arm32 and to use as MI code (not quite + * clean enough, yet). + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/disklabel.h> + +#include "opt_mbr.h" + +#define MBRSIGOFS 0x1fe +static char mbrsig[2] = {0x55, 0xaa}; + +int fat_types[] = { + MBR_PTYPE_FAT12, MBR_PTYPE_FAT16S, + MBR_PTYPE_FAT16B, MBR_PTYPE_FAT32, + MBR_PTYPE_FAT32L, MBR_PTYPE_FAT16L, + -1 +}; + +int +mbr_label_read(dev, strat, lp, osdep, msgp, cylp, netbsd_label_offp) + dev_t dev; + void (*strat) __P((struct buf *)); + struct disklabel *lp; + struct cpu_disklabel *osdep; + char **msgp; + int *cylp, *netbsd_label_offp; +{ + struct mbr_partition *mbrp; + struct partition *pp; + int cyl, mbrpartoff, i, *ip; + struct buf *bp; + int rv = 1; + + /* get a buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + /* In case nothing sets them */ + mbrpartoff = 0; + cyl = LABELSECTOR / lp->d_secpercyl; + + mbrp = osdep->mbrparts; + + /* read master boot record */ + bp->b_blkno = MBR_BBSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl; + (*strat)(bp); + + /* if successful, wander through dos partition table */ + if (biowait(bp)) { + *msgp = "dos partition I/O error"; + goto out; + } else { + struct mbr_partition *ourmbrp = NULL; + + /* XXX "there has to be a better check than this." */ + if (bcmp(bp->b_data + MBRSIGOFS, mbrsig, sizeof(mbrsig))) { + rv = 0; + goto out; + } + + /* XXX how do we check veracity/bounds of this? */ + bcopy(bp->b_data + MBR_PARTOFF, mbrp, + NMBRPART * sizeof(*mbrp)); + + /* look for NetBSD partition */ + ourmbrp = NULL; + for (i = 0; !ourmbrp && i < NMBRPART; i++) { + if (mbrp[i].mbrp_typ == MBR_PTYPE_NETBSD) + ourmbrp = &mbrp[i]; + } +#ifdef COMPAT_386BSD_MBRPART + /* didn't find it -- look for 386BSD partition */ + for (i = 0; !ourmbrp && i < NMBRPART; i++) { + if (mbrp[i].mbrp_typ == MBR_PTYPE_386BSD) { + printf("WARNING: old BSD partition ID!\n"); + ourmbrp = &mbrp[i]; + break; + } + } +#endif + for (i = 0; i < NMBRPART; i++, mbrp++) { + + strncpy(lp->d_packname, "fictitious-MBR", + sizeof lp->d_packname); + + /* Install in partition e, f, g, or h. */ + pp = &lp->d_partitions['e' - 'a' + i]; + pp->p_offset = mbrp->mbrp_start; + pp->p_size = mbrp->mbrp_size; + for (ip = fat_types; *ip != -1; ip++) { + if (mbrp->mbrp_typ == *ip) + pp->p_fstype = FS_MSDOS; + } + if (mbrp->mbrp_typ == MBR_PTYPE_LNXEXT2) + pp->p_fstype = FS_EX2FS; + + /* is this ours? */ + if (mbrp == ourmbrp) { + /* need sector address for SCSI/IDE, + cylinder for ESDI/ST506/RLL */ + mbrpartoff = mbrp->mbrp_start; + cyl = MBR_PCYL(mbrp->mbrp_scyl, mbrp->mbrp_ssect); + +#ifdef __i386__ /* XXX? */ + /* update disklabel with details */ + lp->d_partitions[2].p_size = + mbrp->mbrp_size; + lp->d_partitions[2].p_offset = + mbrp->mbrp_start; + lp->d_ntracks = mbrp->mbrp_ehd + 1; + lp->d_nsectors = MBR_PSECT(mbrp->mbrp_esect); + lp->d_secpercyl = + lp->d_ntracks * lp->d_nsectors; +#endif + } + } + lp->d_npartitions = 'e' - 'a' + i; + } + + *cylp = cyl; + *netbsd_label_offp = mbrpartoff; + *msgp = NULL; +out: + bp->b_flags = B_INVAL | B_AGE | B_READ; + brelse(bp); + return (rv); +} + +int +mbr_label_locate(dev, strat, lp, osdep, cylp, netbsd_label_offp) + dev_t dev; + void (*strat) __P((struct buf *)); + struct disklabel *lp; + struct cpu_disklabel *osdep; + int *cylp, *netbsd_label_offp; +{ + struct mbr_partition *mbrp; + int cyl, mbrpartoff, i; + struct mbr_partition *ourmbrp = NULL; + struct buf *bp; + int rv = 1; + + /* get a buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + /* do MBR partitions in the process of getting disklabel? */ + mbrpartoff = 0; + cyl = LABELSECTOR / lp->d_secpercyl; + + mbrp = osdep->mbrparts; + + /* read master boot record */ + bp->b_blkno = MBR_BBSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + bp->b_cylinder = MBR_BBSECTOR / lp->d_secpercyl; + (*strat)(bp); + + if ((rv = biowait(bp)) != 0) { + rv = -rv; + goto out; + } + + if (bcmp(bp->b_data + MBRSIGOFS, mbrsig, sizeof(mbrsig))) { + rv = 0; + goto out; + } + + /* XXX how do we check veracity/bounds of this? */ + bcopy(bp->b_data + MBR_PARTOFF, mbrp, NMBRPART * sizeof(*mbrp)); + + /* look for NetBSD partition */ + ourmbrp = NULL; + for (i = 0; !ourmbrp && i < NMBRPART; i++) { + if (mbrp[i].mbrp_typ == MBR_PTYPE_NETBSD) + ourmbrp = &mbrp[i]; + } +#ifdef COMPAT_386BSD_MBRPART + /* didn't find it -- look for 386BSD partition */ + for (i = 0; !ourmbrp && i < NMBRPART; i++) { + if (mbrp[i].mbrp_typ == MBR_PTYPE_386BSD) { + printf("WARNING: old BSD partition ID!\n"); + ourmbrp = &mbrp[i]; + } + } +#endif + if (!ourmbrp) { + rv = 0; /* XXX allow easy clobber? */ + goto out; + } + + /* need sector address for SCSI/IDE, cylinder for ESDI/ST506/RLL */ + mbrpartoff = ourmbrp->mbrp_start; + cyl = MBR_PCYL(ourmbrp->mbrp_scyl, ourmbrp->mbrp_ssect); + + *cylp = cyl; + *netbsd_label_offp = mbrpartoff; +out: + bp->b_flags = B_INVAL | B_AGE | B_READ; + brelse(bp); + return (rv); +} diff --git a/sys/arch/arm26/arm26/except.c b/sys/arch/arm26/arm26/except.c new file mode 100644 index 00000000000..9f28e889e08 --- /dev/null +++ b/sys/arch/arm26/arm26/except.c @@ -0,0 +1,717 @@ +/* $NetBSD: except.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ +/*- + * Copyright (c) 1998, 1999, 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * except.c -- ARM exception handling. + */ + +#include <sys/param.h> + +__KERNEL_RCSID(0, "$NetBSD: except.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $"); + +#include <sys/syscall.h> +#include <sys/syslog.h> +#include <sys/systm.h> +#include <sys/user.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/armreg.h> +#include <machine/machdep.h> +#include <machine/pcb.h> + +#ifdef DEBUG +#include <arm32/arm32/disassem.h> +#endif + +#include "opt_cputypes.h" +#include "opt_ddb.h" +#include "opt_ktrace.h" + +#ifdef DDB +#include <machine/db_machdep.h> +#endif + +#ifdef KTRACE +#include <sys/ktrace.h> +#endif + +static void data_abort_fixup(struct trapframe *); +static vaddr_t data_abort_address(struct trapframe *); +static vm_prot_t data_abort_atype(struct trapframe *); +#ifdef DEBUG +static void printregs(struct trapframe *tf); +#endif + +int want_resched; + +/* + * userret() is called just before any return to userland after a trap. + * It's all boilerplate stuff. + */ + +static void +userret(struct proc *p, vaddr_t pc, u_quad_t oticks) +{ + int sig; + + /* take pending signals */ + while ((sig = CURSIG(p)) != 0) + postsig(sig); + p->p_priority = p->p_usrpri; + if (want_resched) { + preempt(NULL); + while ((sig = CURSIG(p)) != 0) + postsig(sig); + } + + /* + * If profiling, charge system time to the trapped pc. + */ + if (p->p_flag & P_PROFIL) { + extern int psratio; + + addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio); + } + curpriority = p->p_priority; +#ifdef DIAGNOSTIC + /* Mark trapframe as invalid. */ + p->p_addr->u_pcb.pcb_tf = (void *)-1; +#endif +} + +void +undefined_handler(struct trapframe *tf) +{ + u_quad_t sticks; + struct proc *p; + u_int32_t insn; + vaddr_t pc; + + pc = tf->tf_r15 & R15_PC; + insn = *(register_t *)pc; +#ifdef CPU_ARM2 + /* + * Check if the aborted instruction was a SWI (ARM2 bug -- + * ARM3 data sheet p87) and call SWI handler if so. + */ + if ((insn & 0x0f000000) == 0x0f000000) { + swi_handler(tf); + return; + } +#endif + /* Enable interrupts if they were enabled before the trap. */ + if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0) + int_on(); + uvmexp.traps++; + p = curproc; + if (p == NULL) + p = &proc0; + if (p->p_addr->u_pcb.pcb_onundef_lj != NULL) + longjmp(p->p_addr->u_pcb.pcb_onundef_lj); + if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) { +#ifdef DDB + if (insn == 0xe7ffffff) { + kdb_trap(T_BREAKPOINT, (db_regs_t *)tf); + return; + } +#endif +#ifdef DEBUG + printf("Undefined instruction:\n"); + printregs(tf); + printf("pc -> "); + disassemble(tf->tf_r15 & R15_PC); +#endif + panic("undefined instruction in kernel mode"); + } else { + p->p_addr->u_pcb.pcb_tf = tf; + sticks = p->p_sticks; + trapsignal(p, SIGILL, insn); + userret(p, pc, sticks); + } +} + +void +swi_handler(struct trapframe *tf) +{ + u_quad_t sticks; + struct proc *p; + vaddr_t pc; + int code, regparams, nextreg; + struct sysent *sy; + size_t argsize, regargsize, stkargsize; + char args[32]; /* XXX just enough for mmap... */ + register_t rval[2], or15; + int error; + + /* Enable interrupts if they were enabled before the trap. */ + if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0) + int_on(); + uvmexp.traps++; + uvmexp.syscalls++; + p = curproc; + if (p == NULL) + p = &proc0; + sticks = p->p_sticks; + if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR) + p->p_addr->u_pcb.pcb_tf = tf; + + if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) { +#ifdef DEBUG + printf("SWI:\n"); + printregs(tf); + printf("pc -> "); + disassemble(tf->tf_r15 & R15_PC); +#endif + panic("SWI in kernel mode"); + } + + pc = tf->tf_r15 & R15_PC; + +#ifdef DIAGNOSTIC + if ((*(u_int32_t *)pc & 0x0f000000) != 0x0f000000) { + disassemble(pc); + panic("SWI on non-SWI instruction"); + } +#endif + + /* Look up the system call and see if it's magic. */ + code = *(register_t *)pc & 0x00ffffff; + switch (code) { + case SYS_syscall: /* Indirect system call. First arg is new code */ + code = tf->tf_r0; + regparams = 3; nextreg = 1; + break; + case SYS___syscall: /* As above, but quad_t arg */ + if (p->p_emul->e_sysent == sysent) { /* NetBSD emulation */ + code = tf->tf_r0; /* XXX assume little-endian */ + regparams = 2; nextreg = 2; + break; + } + /* FALLTHROUGH */ + default: + regparams = 4; nextreg = 0; + } + if (code > p->p_emul->e_nsysent) + sy = p->p_emul->e_sysent + p->p_emul->e_nosys; + else + sy = p->p_emul->e_sysent + code; + + argsize = sy->sy_argsize; + if (argsize > (regparams * sizeof(int))) { + regargsize = regparams*sizeof(int); + stkargsize = argsize - regargsize; + } else { + regargsize = argsize; + stkargsize = 0; + } + + if (regargsize) + bcopy((char *)tf + nextreg * sizeof(int), args, regargsize); + + if (stkargsize) { + error = copyin((caddr_t)tf->tf_r13, args + regargsize, + stkargsize); + if (error) { +#ifdef SYSCALL_DEBUG + scdebug_call(p, code, (register_t *)args); +#endif + goto bad; + } + } + +#ifdef SYSCALL_DEBUG + scdebug_call(p, code, (register_t *)args); +#endif +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, argsize, args); +#endif + + rval[0] = 0; + rval[1] = tf->tf_r1; + + /* Set return address */ + or15 = tf->tf_r15; + tf->tf_r15 += 4; + + error = sy->sy_call(p, args, rval); + + switch (error) { + case 0: + tf->tf_r0 = rval[0]; + tf->tf_r1 = rval[1]; + tf->tf_r15 &= ~R15_FLAG_C; + break; + case ERESTART: + tf->tf_r15 = or15; + break; + case EJUSTRETURN: + /* nothing to do */ + break; + default: + bad: + tf->tf_r0 = rval[0] = error; + tf->tf_r15 |= R15_FLAG_C; + break; + } +#ifdef SYSCALL_DEBUG + scdebug_ret(p, code, error, rval); +#endif + userret(p, pc, sticks); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, rval[0]); +#endif +} + +/* + * Return from fork(2) in the child. This is effectively the tail end of + * a normal successful syscall return. + */ +void +child_return(void* ignore) +{ + struct proc *p; + struct trapframe *tf; + + p = curproc; + tf = p->p_addr->u_pcb.pcb_tf; + tf->tf_r0 = 0; + tf->tf_r15 &= ~R15_FLAG_C; + +#ifdef SYSCALL_DEBUG + scdebug_ret(p, SYS_fork /* XXX */, 0, &tf->tf_r0); +#endif + userret(p, tf->tf_r15 & R15_PC, 0); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, SYS_fork /* XXX */, 0, &tf->tf_r0); +#endif +} + +void +prefetch_abort_handler(struct trapframe *tf) +{ + u_quad_t sticks; + vaddr_t pc; + struct proc *p; + int ret; + + /* Enable interrupts if they were enabled before the trap. */ + if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0) + int_on(); + + /* + * Check if the page being requested is already present. If + * so, call the undefined instruction handler instead (ARM3 ds + * p15). + */ + + uvmexp.traps++; + p = curproc; + if (p == NULL) + p = &proc0; + sticks = p->p_sticks; + + if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR) + p->p_addr->u_pcb.pcb_tf = tf; + + if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) { +#ifdef DEBUG + printf("Prefetch abort:\n"); + printregs(tf); +#endif + panic("prefetch abort in kernel mode"); + } + + /* User-mode prefetch abort */ + pc = tf->tf_r15 & R15_PC; + + if (pmap_fault(p->p_vmspace->vm_map.pmap, pc, VM_PROT_EXECUTE)) + goto out; + ret = uvm_fault(&p->p_vmspace->vm_map, pc, 0, VM_PROT_EXECUTE); + + if (ret != KERN_SUCCESS) { +#ifdef DEBUG + printf("unhandled fault at %p (ret = %d)\n", (void *)pc, ret); + printf("Prefetch abort:\n"); + printregs(tf); +#endif + panic("prefetch_abort_handler: uvm_fault failed"); + } +out: + userret(p, pc, sticks); +} + +void +data_abort_handler(struct trapframe *tf) +{ + u_quad_t sticks; + vaddr_t pc, va; + int ret; + struct proc *p; + vm_prot_t atype; + vm_map_t map; + struct pcb *curpcb; + + /* + * Data aborts in kernel mode are possible (copyout etc), so + * we hope the compiler (or programmer) has ensured that + * R14_svc gets saved. + * + * We may need to fix up an STM or LDM instruction. This + * involves seeing if the base was being written back, and if + * so resetting it (by counting the number of registers being + * transferred) before retrying (ARM 2 ds pp 10 & 33). + */ + + /* Enable interrupts if they were enabled before the trap. */ + if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0) + int_on(); + uvmexp.traps++; + p = curproc; + if (p == NULL) + p = &proc0; + if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR) + p->p_addr->u_pcb.pcb_tf = tf; + sticks = p->p_sticks; + pc = tf->tf_r15 & R15_PC; + data_abort_fixup(tf); + va = data_abort_address(tf); + atype = data_abort_atype(tf); + map = va >= VM_MIN_KERNEL_ADDRESS ? kernel_map : &p->p_vmspace->vm_map; + if (pmap_fault(map->pmap, va, atype)) + goto out; + ret = uvm_fault(map, va, 0, atype); + + if (ret != KERN_SUCCESS) { +#ifdef DEBUG + printf("unhandled fault at %p (ret = %d)\n", (void *)va, ret); +#endif + curpcb = &p->p_addr->u_pcb; + if (curpcb->pcb_onfault != NULL) { + tf->tf_r15 = (tf->tf_r15 & ~R15_PC) | + (register_t)curpcb->pcb_onfault; + return; + } + if (curpcb->pcb_onfault_lj != NULL) + longjmp(curpcb->pcb_onfault_lj); +#ifdef DEBUG + printf("Data abort:\n"); + printregs(tf); + printf("pc -> "); + disassemble(tf->tf_r15 & R15_PC); +#endif + panic("data_abort_handler: uvm_fault failed"); + } + +out: + if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR) + userret(p, pc, sticks); +} + +#define getreg(r) (((register_t *)tf)[r]) + +/* + * Undo any effects of the aborted instruction that need to be undone + * in order for us to restart it. This is just a case of spotting + * aborted LDMs and STMs and reversing any base writeback. This code + * is derived loosely from the arm32 late-abort fixup. + */ +static void +data_abort_fixup(struct trapframe *tf) +{ + register_t insn; + int rn, count, loop; + + /* Get the faulting instruction */ + insn = *(register_t *)(tf->tf_r15 & R15_PC); + if ((insn & 0x0e000000) == 0x08000000 && + (insn & 1 << 21)) { + /* LDM/STM with writeback*/ + rn = (insn >> 16) & 0x0f; + if (rn == 15) + return; /* No writeback on R15 */ + /* Count registers transferred */ + count = 0; + for (loop = 0; loop < 16; ++loop) { + if (insn & (1<<loop)) + ++count; + } + if (insn & (1 << 23)) /* up/down bit -- we reverse it. */ + getreg(rn) -= count * 4; + else + getreg(rn) += count * 4; + } +} + +/* + * Work out where a data abort happened. This involves emulating the + * faulting instruction. Some of this code is derived from the arm32 + * abort fixup stuff too. + */ +static vaddr_t +data_abort_address(struct trapframe *tf) +{ + register_t insn; + int rn, rm, offset, shift, p, i, u; + vaddr_t base; + + /* Get the faulting instruction */ + insn = *(register_t *)(tf->tf_r15 & R15_PC); + if ((insn & 0x0c000000) == 0x04000000) { + /* Single data transfer */ + rn = (insn & 0x000f0000) >> 16; + base = getreg(rn); + if (rn == 15) + base = (base & R15_PC) + 8; + p = insn & 1 << 24; + if (p == 0) + /* Post-indexed, so offset doesn't concern us */ + return base; + u = insn & 1 << 23; + i = insn & 1 << 25; + if (i == 0) { + /* Immediate offset (str r0, [r1, #42]) */ + offset = insn & 0x00000fff; + if (u == 0) + return base - offset; + else + return base + offset; + } + rm = insn & 0x0000000f; + offset = getreg(rm); + if (rm == 15) + offset += 8; + if ((insn & 1 << 4) == 0) + /* immediate shift */ + shift = (insn & 0x00000f80) >> 7; + else + goto croak; /* register shifts can't happen in ARMv2 */ + switch ((insn & 0x00000060) >> 5) { + case 0: /* Logical left */ + offset = (int)(((u_int)offset) << shift); + break; + case 1: /* Logical Right */ + if (shift == 0) shift = 32; + offset = (int)(((u_int)offset) >> shift); + break; + case 2: /* Arithmetic Right */ + if (shift == 0) shift = 32; + offset = (int)(((int)offset) >> shift); + break; + case 3: /* Rotate right -- FIXME support this*/ + default: /* help GCC */ + goto croak; + } + if (u == 0) + return base - offset; + else + return base + offset; + } else if ((insn & 0x0e000000) == 0x08000000) { + vaddr_t sva, eva; + int loop, count; + + /* LDM/STM */ + rn = (insn >> 16) & 0x0f; + /* Need to find both ends of the range being transferred. */ + p = insn & 1 << 24; + u = insn & 1 << 23; + if (p == 0) + sva = getreg(rn); + else + if (u == 0) + sva = getreg(rn) - 4; + else + sva = getreg(rn) + 4; + /* + * This is currently bogus. We should check the + * lowest address first. I doubt they'll notice. + */ + if (pmap_confess(sva, data_abort_atype(tf))) + return sva; + /* Count registers transferred */ + count = 0; + for (loop = 0; loop < 16; ++loop) { + if (insn & (1<<loop)) + ++count; + } + if (u == 0) /* up/down bit */ + eva = sva - count * 4; + else + eva = sva + count * 4; + return eva; +#if defined(CPU_ARM250) || defined(CPU_ARM3) + } else if ((insn & 0x0fb00ff0) == 0x01000090) { + /* SWP */ + rm = insn & 0x0000000f; + base = getreg(rm); + if (rm == 15) + return base + 8; + else + return base; +#endif + } +croak: +#ifdef DEBUG + printf("Data abort:\n"); + printregs(tf); + printf("pc -> "); + disassemble(tf->tf_r15 & R15_PC); +#endif + panic("data_abort_address"); +} + +/* + * We need to know whether the page should be mapped as R or R/W. We + * need to disassemble the instruction responsible and determine if it + * was a read or write instruction. This code is based on the arm32 + * version. + */ +static vm_prot_t +data_abort_atype(struct trapframe *tf) +{ + register_t insn; + + insn = *(register_t *)(tf->tf_r15 & R15_PC); + /* STR instruction ? */ + if ((insn & 0x0c100000) == 0x04000000) + return VM_PROT_READ | VM_PROT_WRITE; + /* STM or CDT instruction ? */ + else if ((insn & 0x0a100000) == 0x08000000) + return VM_PROT_READ | VM_PROT_WRITE; +#if defined(CPU_ARM250) || defined(CPU_ARM3) + /* SWP instruction ? */ + else if ((insn & 0x0fb00ff0) == 0x01000090) + return VM_PROT_READ | VM_PROT_WRITE; +#endif + return VM_PROT_READ; +} + +void +address_exception_handler(struct trapframe *tf) +{ + u_quad_t sticks; + struct proc *p; + vaddr_t pc; + + /* Enable interrupts if they were enabled before the trap. */ + if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0) + int_on(); + uvmexp.traps++; + p = curproc; + if (p == NULL) + p = &proc0; + if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR) + p->p_addr->u_pcb.pcb_tf = tf; + +/* if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) */{ +#ifdef DEBUG + printf("Address exception:\n"); + printregs(tf); + printf("pc -> "); + disassemble(tf->tf_r15 & R15_PC); +#endif + panic("address exception in kernel mode"); + } + + pc = tf->tf_r15 & R15_PC; + sticks = p->p_sticks; + trapsignal(p, SIGBUS, pc); + userret(p, pc, sticks); +} + +/* + * An AST isn't a real hardware trap, but locore.S makes it look like one + * for consistency. + */ +int astpending; + +void +ast_handler(struct trapframe *tf) +{ + u_quad_t sticks; + vaddr_t pc; + struct proc *p; + + /* Enable interrupts if they were enabled before the trap. */ + if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0) + int_on(); + astpending = 0; + p = curproc; + if (p == NULL) + p = &proc0; + sticks = p->p_sticks; + if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR) + p->p_addr->u_pcb.pcb_tf = tf; + pc = tf->tf_r15 & R15_PC; + + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + ADDUPROF(p); + } + + userret(p, pc, sticks); +} + + +void +setsoftast() +{ + astpending = 1; +} + +extern int want_resched; /* XXX */ + +void +need_resched(void) +{ + want_resched = 1; + setsoftast(); +} + + +#ifdef DEBUG +static void +printregs(struct trapframe *tf) +{ + + printf("R0 = 0x%08x R1 = 0x%08x R2 = 0x%08x R3 = 0x%08x\n" + "R4 = 0x%08x R5 = 0x%08x R6 = 0x%08x R7 = 0x%08x\n" + "R8 = 0x%08x R9 = 0x%08x R10 = 0x%08x R11 = 0x%08x\n" + "R12 = 0x%08x R13 = 0x%08x R14 = 0x%08x R15 = 0x%08x\n", + tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3, + tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7, + tf->tf_r8, tf->tf_r9, tf->tf_r10, tf->tf_r11, + tf->tf_r12, tf->tf_r13, tf->tf_r14, tf->tf_r15); +} +#endif + +/* irq_handler is over in irq.c */ diff --git a/sys/arch/arm26/arm26/genassym.cf b/sys/arch/arm26/arm26/genassym.cf new file mode 100644 index 00000000000..9e1a13c57db --- /dev/null +++ b/sys/arch/arm26/arm26/genassym.cf @@ -0,0 +1,46 @@ +# $NetBSD: genassym.cf,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ +# +# Copyright (c) 1999 Ben Harris +# 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. 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. +# +# This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. + +include <sys/param.h> + +include <sys/proc.h> +include <sys/user.h> +include <machine/pcb.h> + +define U_PCB offsetof(struct user, u_pcb) +define PCB_ONFAULT offsetof(struct pcb, pcb_onfault) +define P_ADDR offsetof(struct proc, p_addr) + +define TF_R15 offsetof(struct trapframe, tf_r15) +define TF_SIZE sizeof(struct trapframe) + +define IF_R15 offsetof(struct irqframe, if_r15) +define IF_SIZE sizeof(struct irqframe) + +define SF_SC offsetof(struct sigframe, sf_sc) diff --git a/sys/arch/arm26/arm26/intrnames.S b/sys/arch/arm26/arm26/intrnames.S new file mode 100644 index 00000000000..1a7ed4d6ceb --- /dev/null +++ b/sys/arch/arm26/arm26/intrnames.S @@ -0,0 +1,86 @@ +/* $NetBSD: intrnames.S,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * intrnames.S -- interrupt names for systat etc. + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: intrnames.S,v 1.1 2000/05/09 21:55:56 bjh21 Exp $") + + .text + .global _C_LABEL(intrnames) +_C_LABEL(intrnames): +.macro irqname irq +Lirq\irq: + .asciz "IRQ \irq" +.endm + irqname 0 + irqname 1 + irqname 2 + irqname 3 + irqname 4 + irqname 5 + irqname 6 + irqname 7 + irqname 8 + irqname 9 + irqname 10 + irqname 11 + irqname 12 + irqname 13 + irqname 14 + irqname 15 + .global _C_LABEL(eintrnames) +_C_LABEL(eintrnames): + .global _C_LABEL(irqnames) +_C_LABEL(irqnames): + .word Lirq0 + .word Lirq1 + .word Lirq2 + .word Lirq3 + .word Lirq4 + .word Lirq5 + .word Lirq6 + .word Lirq7 + .word Lirq8 + .word Lirq9 + .word Lirq10 + .word Lirq11 + .word Lirq12 + .word Lirq13 + .word Lirq14 + .word Lirq15 + + .data + .global _C_LABEL(intrcnt) +_C_LABEL(intrcnt): + .fill 16, 4 + .global _C_LABEL(eintrcnt) +_C_LABEL(eintrcnt): diff --git a/sys/arch/arm26/arm26/irq.c b/sys/arch/arm26/arm26/irq.c new file mode 100644 index 00000000000..8104d72de50 --- /dev/null +++ b/sys/arch/arm26/arm26/irq.c @@ -0,0 +1,297 @@ +/* $NetBSD: irq.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * irq.c - IOC IRQ handler. + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: irq.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/kernel.h> /* for cold */ +#include <sys/malloc.h> +#include <sys/queue.h> +#include <sys/systm.h> + +#include <vm/vm.h> +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> +#include <machine/frame.h> +#include <machine/intr.h> +#include <machine/irq.h> +#include <machine/machdep.h> +#include <machine/spl.h> + +#include <arch/arm26/iobus/iocreg.h> +#include <arch/arm26/iobus/iocvar.h> + +extern struct cfdriver ioc_cd; + +#define NIRQ 16 +extern char *irqnames[]; + +/* + * Interrupt masks are held in 32-bit integers. At present, the + * bottom eight bits are interrupt register A on the IOC, and the next + * eight are interrupt register B. FIQs and the Unix backplane should + * be represented eventually. + */ + +static u_int32_t irqmask[NIPL]; + +LIST_HEAD(irq_handler_head, irq_handler) irq_list_head = + LIST_HEAD_INITIALIZER(irq_list_head); + +struct irq_handler { + LIST_ENTRY(irq_handler) link; + int (*func) __P((void *)); + void *arg; + u_int32_t mask; + int irqnum; + int ipl; + int enabled; +}; + +volatile static int current_spl = IPL_HIGH; + +void +irq_init(void) +{ + + irq_genmasks(); + softintr_init(); +} + +/* + * This is optimised for speed rather than generality. It expects to + * be called an awful lot. + * + * On entry, IRQs are disabled on the CPU. + */ + +void +irq_handler(struct irqframe *irqf) +{ + int s, status, result, stray; + struct irq_handler *h; + +#ifdef DIAGNOSTIC + if (ioc_cd.cd_ndevs == 0 || ioc_cd.cd_devs == NULL || + ioc_cd.cd_devs[0] == NULL) + panic("irq_handler: no ioc0"); +#endif + /* Get the current interrupt state */ + status = ioc_irq_status_full(ioc_cd.cd_devs[0]); + + /* Get interrupt-disabling back to the IOC */ + s = splhigh(); + int_on(); + +#if 0 + printf("*"); +#endif + uvmexp.intrs++; + + stray = 1; + /* Find the highest-priority requested interrupt. */ + for (h = irq_list_head.lh_first; + h != NULL && h->ipl > s; + h = h->link.le_next) + if (h->enabled && ((status & h->mask) != 0)) { + splx(h->ipl); +#if 0 + printf("IRQ %d...", h->irqnum); +#endif + if (h->mask & IOC_IRQ_CLEARABLE_MASK) + ioc_irq_clear(ioc_cd.cd_devs[0], h->mask); + /* XXX IOEB support needed */ + if (h->arg == NULL) + result = (h->func)(irqf); + else + result = (h->func)(h->arg); + if (result == IRQ_HANDLED) { + stray = 0; + break; /* XXX handle others? */ + } + if (result == IRQ_MAYBE_HANDLED) + stray = 0; + } + + if (stray) { + panic("Stray IRQ, status = 0x%x, spl = %d, mask = 0x%x", + status, s, irqmask[s]); + } +#if 0 + printf(" handled\n"); +#endif + dosoftints(s); /* May lower spl to s + 1, but no lower. */ + + int_off(); + hardsplx(s); +} + +struct irq_handler * +irq_establish(int irqnum, int ipl, int (*func)(void *), void *arg) +{ + struct irq_handler *h, *new; + +#ifdef DIAGNOSTIC + if (irqnum >= NIRQ) + panic("irq_register: bad irq: %d", irqnum); +#endif + MALLOC(new, struct irq_handler *, sizeof(struct irq_handler), + M_DEVBUF, M_WAITOK); + new->irqnum = irqnum; + new->mask = 1 << irqnum; /* XXX unix BP etc */ + new->ipl = ipl; + new->func = func; + new->arg = arg; + new->enabled = 0; + if (irq_list_head.lh_first == NULL || + irq_list_head.lh_first->ipl <= ipl) + /* XXX This shouldn't need to be a special case */ + LIST_INSERT_HEAD(&irq_list_head, new, link); + else { + for (h = irq_list_head.lh_first; + h->link.le_next != NULL && h->link.le_next->ipl > ipl; + h = h->link.le_next); + LIST_INSERT_AFTER(h, new, link); + } + if (new->mask & IOC_IRQ_CLEARABLE_MASK) + ioc_irq_clear(ioc_cd.cd_devs[0], new->mask); + /* XXX IOEB support needed */ + irq_genmasks(); + return new; +} + +char const * +irq_string(struct irq_handler *h) +{ + + return irqnames[h->irqnum]; +} + +void +irq_disable(struct irq_handler *h) +{ + int s; + + s = splhigh(); + h->enabled = 0; + irq_genmasks(); + splx(s); +} + +void +irq_enable(struct irq_handler *h) +{ + int s; + + s = splhigh(); + h->enabled = 1; + irq_genmasks(); + splx(s); +} + + +void irq_genmasks() +{ + struct irq_handler *h; + int s, i; + + /* Paranoia? */ + s = splhigh(); + /* Disable anything we don't understand */ + for (i = 0; i < NIPL; i++) + irqmask[i] = 0; + /* Enable interrupts in levels lower than their own */ + for (h = irq_list_head.lh_first; h != NULL; h = h->link.le_next) + if (h->enabled) { + if ((h->mask & irqmask[IPL_NONE]) == h->mask) + /* Shared interrupt -- use lowest priority. */ + for (i = h->ipl; i < NIPL; i++) + irqmask[i] &= ~h->mask; + else + for (i = 0; i < h->ipl; i++) + irqmask[i] |= h->mask; + } + splx(s); +} + +int +raisespl(int s) +{ + + if (s > current_spl) + return splx(s); + else + return current_spl; +} + +int +lowerspl(int s) +{ + + if (s < current_spl) + return splx(s); + else + return current_spl; +} + +int +splx(int s) +{ + + if (current_spl > s) + dosoftints(s); + return hardsplx(s); +} + +int +hardsplx(int s) +{ + int was; + + int_off(); + was = current_spl; + /* Don't try this till we've found the IOC */ + /* + * XXX Note that second check should be redundant, but config_attach + * changes cd_ndevs before cd_devs, and can call up (via malloc) in + * the meantime. + */ + if (ioc_cd.cd_ndevs > 0 && ioc_cd.cd_devs != NULL && + ioc_cd.cd_devs[0] != NULL) + ioc_irq_setmask(ioc_cd.cd_devs[0], irqmask[s]); + current_spl = s; + return was; /* Restore interrupt state */ +} diff --git a/sys/arch/arm26/arm26/locore.S b/sys/arch/arm26/arm26/locore.S new file mode 100644 index 00000000000..2d8b2053f13 --- /dev/null +++ b/sys/arch/arm26/arm26/locore.S @@ -0,0 +1,398 @@ +/* $NetBSD: locore.S,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ +/* + * Copyright (c) 1998, 2000 Ben Harris + * Copyright (C) 1994-1997 Mark Brinicombe + * Copyright (C) 1994 Brini + * 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 Brini. + * 4. The name of Brini may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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 is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * locore.S - the (physical) start of the kernel and low-level handlers + */ +/* Note that the actual kernel startup is in start.c */ + +#include <machine/asm.h> + +RCSID("$NetBSD: locore.S,v 1.1 2000/05/09 21:55:56 bjh21 Exp $") + +#include <sys/syscall.h> +#include <machine/frame.h> +#include <machine/cpu.h> +#include <machine/armreg.h> +#include "assym.h" + +#include "opt_cputypes.h" + +fp .req r11 +ip .req r12 +sp .req r13 +lr .req r14 +pc .req r15 + + +/* + * MODE_CHANGE_NOP should be inserted between a mode change and a + * banked register (R8--R15) access. + */ +#if defined(CPU_ARM2) || defined(CPU_ARM250) +#define MODE_CHANGE_NOP mov r0, r0 +#else +#define MODE_CHANGE_NOP /* Data sheet says ARM3 doesn't need it */ +#endif + +/* + * USR_LDM_NOP should be inserted between an LDM to the user bank + * and a read from a banked register. (ARM DS sec 6.6.4) + */ +#define USR_LDM_NOP mov r0, r0 + + .text + .balign 4 + +/* + * This is for kvm_mkdb, and should be the address of the beginning + * of the kernel text segment (not necessarily the same as kernbase). + */ + + .global _C_LABEL(kernel_text) +_C_LABEL(kernel_text): + b _C_LABEL(start) /* Just in case the linker loses it */ + +/* + * Trap handlers + * + * These take an exception and get up into a state to enter the kernel + * proper. This currently involves fixing up the return address (to + * point to the faulting instruction in all cases), pushing a + * trapframe onto the stack, calling the C handler restoring the + * (possibly modified) trapframe and returning to userland. + */ +#define TRAP_REGS r0-r14 + .macro HANDLER handler, lr_fixup + sub lr, lr, #\lr_fixup /* Compensate for prefetch */ + sub sp, sp, #TF_SIZE /* Adjust SP */ + str lr, [sp, #TF_R15] /* Push return address */ + stmia sp, {TRAP_REGS}^ /* Push user mode registers */ + + mov r0, sp /* Supply handler with argument */ + tst lr, #R15_MODE /* If the trap was from USR mode... */ + moveq fp, #0 /* ... this is the end of the stack */ + bl \handler + +/* + * AST handling stuff. We have to disable IRQs between loading the + * flag and returning to user mode, since otherwise an IRQ might + * happen in the interim and set the flag again. For simplicity, we + * just leave IRQs off throughout (ast_handler will re-enable them). + */ + ldr lr, [sp, #TF_R15] /* Pull return address and PSR */ + tst lr, #R15_MODE /* Was trap in USR mode? */ + bne 3f /* If not, return */ + ldr r4, Lastpending +1: + ldr r1, [r4] + cmp r1, #0 /* AST pending? */ + bne 2f /* If not, return */ + mov r0, sp /* Reuse old trapframe */ + bl _C_FUNC(ast_handler) /* Handle AST */ + b 1b /* Try again */ + +2: + ldr lr, [sp, #TF_R15] /* Pull return address */ +3: /* ... which we may have done above */ + ldmia sp, {TRAP_REGS}^ /* Restore USR mode registers */ + USR_LDM_NOP + add sp, sp, #TF_SIZE /* Adjust SP */ + movs pc, lr + .endm + +Lastpending: + .word _C_LABEL(astpending) + .global reset_entry +reset_entry: + adr r0, Lreset_panicmsg + bl _C_LABEL(panic) + /* NOTREACHED */ +Lreset_panicmsg: + .asciz "Reset handler called. Branch through zero?" + .balign 4 + + .global undefined_entry +undefined_entry: + HANDLER _C_FUNC(undefined_handler), 4 + + .global swi_entry +swi_entry: + HANDLER _C_FUNC(swi_handler), 4 + + .global prefetch_abort_entry +prefetch_abort_entry: + HANDLER _C_FUNC(prefetch_abort_handler), 4 + + .global data_abort_entry +data_abort_entry: + HANDLER _C_FUNC(data_abort_handler), 8 + + .global address_exception_entry +address_exception_entry: + HANDLER _C_FUNC(address_exception_handler), 8 + +/* + * The stack frame messing is different here since we're handling an + * irqframe, not a trapframe. IRQ handlers generally don't need to + * get at the contents of user registers (except R15), so we leave + * them to be saved by irq_handler's prologue. On the other hand, + * IRQs can happen in SVC mode, and we need to do a bit of juggling to + * save R14_svc before we enter the IRQ handler. + * + * The "R15" slot in the irqframe hols the value of R15 to return to. + * Conceptually, IRQs happen at the start of an instruction. + */ + +#define IRQ_REGS_SVC r0-r3, r12, r14 +#define IRQ_REGS_USR r0-r3, r11-r12 + .global irq_entry +irq_entry: + sub r14, r14, #4 /* Fix up return address */ + tst r14, #(R15_MODE) + beq Lirq_from_usr + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC) + MODE_CHANGE_NOP + sub sp, sp, #IF_SIZE /* mark space for irqframe */ + stmia sp, {IRQ_REGS_SVC} /* save SVC mode regs */ + mov r0, sp /* copy frame pointer */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ) + MODE_CHANGE_NOP + str lr, [r0, #IF_R15] /* Finally, save return addr */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC) + MODE_CHANGE_NOP + + mov r0, sp + bl _C_FUNC(irq_handler) + + mov r0, sp + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ) + MODE_CHANGE_NOP + ldr lr, [r0, #IF_R15] /* Retrieve return address */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC) + MODE_CHANGE_NOP + ldmia sp, {IRQ_REGS_SVC} /* Restore SVC registers */ + add sp, sp, #IF_SIZE /* Free irqframe */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ) + MODE_CHANGE_NOP + movs r15, lr /* and return. */ + +Lirq_from_usr: + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC) + MODE_CHANGE_NOP + sub sp, sp, #IF_SIZE /* mark space for irqframe */ + stmia sp, {IRQ_REGS_USR} /* save SVC/USR mode regs */ + mov r0, sp /* copy frame pointer */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ) + MODE_CHANGE_NOP + str lr, [r0, #IF_R15] /* Finally, save return addr */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC) + MODE_CHANGE_NOP + + mov fp, #0 /* This is the top of the stack */ + mov r0, sp + bl _C_FUNC(irq_handler) + + ldr r0, Lastpending + ldr r0, [r0] + cmp r0, #0 + bne Lirq_to_ast + mov r0, sp + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ) + MODE_CHANGE_NOP + ldr lr, [r0, #IF_R15] /* Retrieve return address */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC) + MODE_CHANGE_NOP + ldmia sp, {IRQ_REGS_USR} /* Restore SVC/USR registers */ + add sp, sp, #IF_SIZE /* Free irqframe */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ) + MODE_CHANGE_NOP + movs r15, lr /* and return. */ + +Lirq_to_ast: + ldmia sp, {IRQ_REGS_USR} /* Slurp up irqframe */ + sub sp, sp, #(TF_SIZE - IF_SIZE) + stmia sp, {TRAP_REGS}^ /* Spit out trapframe */ + + mov fp, #0 +Last_again: + mov r0, sp + bl _C_FUNC(ast_handler) + + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC) + ldr r0, Lastpending + ldr r0, [r0] + cmp r0, #0 + bne Last_again + ldr lr, [sp, #TF_R15] /* Pull return address */ + ldmia sp, {TRAP_REGS}^ /* Restore USR mode registers */ + USR_LDM_NOP + add sp, sp, #TF_SIZE /* Adjust SP */ + movs pc, lr + +ENTRY(atomic_set_bit) + /* disable interrupts */ + /* Note that this is evil and only works due to prefetching */ + mov r2, r15 + orrs r15, r2, #(R15_IRQ_DISABLE | R15_FIQ_DISABLE) + ldr r2, [r0] + orr r2, r2, r1 + str r2, [r0] + /* restore interrupt state and return */ + movs pc, lr +ENTRY(atomic_clear_bit) + /* disable interrupts */ + /* Note that this is evil and only works due to prefetching */ + mov r2, r15 + orrs r15, r2, #(R15_IRQ_DISABLE | R15_FIQ_DISABLE) + ldr r2, [r0] + bic r2, r2, r1 + str r2, [r0] + /* restore interrupt state and return */ + movs pc, lr + +ENTRY(set_r13_irq) + /* register_t set_r13_irq(register_t r13_irq) */ + /* XXX Is enabling FIQs OK? */ + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_IRQ) + mov r1, r0 + mov r0, r13 + mov r13, r1 + teqp r15, #(R15_IRQ_DISABLE | R15_MODE_SVC) + MODE_CHANGE_NOP + movs r15, lr + + /* + * These are grotty, and very non-APCS. The CPU interrupt status + * is part of the state that's restored on function exit, so the + * effect of these only persists until then. + */ +ENTRY(int_on) + bics r15, r14, #(R15_IRQ_DISABLE | R15_FIQ_DISABLE) +ENTRY(int_off) + orrs r15, r14, #(R15_IRQ_DISABLE) + + /* + * Low-level context-switch operation. cpu_switch() is in C -- this + * just handles the bits that can't be done in C. + * + * void cpu_loswitch(struct switchframe **fromp, + * struct switchframe *to) + * + * We leave a switchframe on the stack pointed to by fromp, + * and return to the context in to. This should be called in + * splhigh(); + */ +ENTRY(cpu_loswitch) + mov r2, sp /* Temporary stack pointer */ + stmfd r2!, {r4-r11, r13-r14} /* Save all relevant registers */ + str r2, [r0] /* Save switchframe pointer */ + ldmfd r1, {r4-r11, r13-r14} /* Restore from old switchframe */ + movs pc, r14 /* and return */ + + /* + * This funny little routine implements starting a process. + * It's called by cpu_loswitch returning from a faked + * switchframe set up by cpu_fork() and cpu_set_kpc(), and gets + * the function it's meant to enter passed in R4 with its + * argument in R5. If that function's NULL, or if it returns, + * we hope there's a trapframe on the stack that'll take us + * back to userland. + */ +ENTRY(proc_trampoline) + mov fp, #0 /* Tie knot in top of stack */ + mov r0, #0 + bl _C_FUNC(splx) /* spl0() */ + cmp r4, #0 /* Function to call? */ + beq Lproc_trampoline_nofunc + mov r0, r5 + mov r14, pc /* Save return address */ + mov pc, r4 /* Call function */ +Lproc_trampoline_nofunc: + ldr lr, [sp, #TF_R15] /* Pull return address */ + ldmia sp, {r0-r14}^ /* Restore USR mode registers */ + USR_LDM_NOP + add sp, sp, #TF_SIZE /* Adjust SP */ + movs pc, lr + +/* int setjmp(label_t *); */ +ENTRY(setjmp) + stmia r0, {r4-r11, r13-r14} /* Save relevant registers */ + mov r0, #0 /* Return 0 */ + movs pc, lr + +/* void longjmp(label_t *); */ +ENTRY(longjmp) + ldmia r0, {r4-r11, r13-r14} /* Restore registers */ + mov r0, #1 /* Return 1 through longjmp */ + movs pc, lr + +/* Enter DDB -- shove registers in a trapframe first */ +/* void cpu_Debugger(void); */ +ENTRY(cpu_Debugger) + stmfd r13!, {r14} + stmfd r13!, {r0-r15} /* Save all SVC-mode regs */ + mov r1, r13 + mov r0, #0 + bl _C_FUNC(kdb_trap) + add r13, r13, #(4 * 16) + ldmfd r13!, {pc}^ + +/* + * Signal trampoline; copied to top of user stack. + */ + +ENTRY_NP(sigcode) +/* + * r0-r2 are our signal handler parameters + * r3 is the handler address + */ + + add lr, pc, #0 /* Set return address */ + mov pc, r3 /* Call the handler */ + +/* + * Call sig_return with address of the signal context + * Note: Don't use SIG_SCP as this make have been trashed by the program + */ + add r0, sp, #SF_SC + swi SYS___sigreturn14 + +/* Well if that failed we better exit quick ! */ + + swi SYS_exit + b . - 8 + + .align 0 + .global _C_LABEL(esigcode) +_C_LABEL(esigcode): diff --git a/sys/arch/arm26/arm26/machdep.c b/sys/arch/arm26/arm26/machdep.c new file mode 100644 index 00000000000..fc6ede31e2e --- /dev/null +++ b/sys/arch/arm26/arm26/machdep.c @@ -0,0 +1,205 @@ +/* $NetBSD: machdep.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ + +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * machdep.c -- standard machine-dependent functions + */ + +#include <sys/param.h> + +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $"); + +#include <sys/buf.h> +#include <sys/mbuf.h> +#include <sys/reboot.h> +#include <sys/systm.h> +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <machine/memcreg.h> + +int physmem; +char machine[] = MACHINE; +char machine_arch[] = MACHINE_ARCH; +char cpu_model[] = "Archimedes"; + +vm_map_t exec_map = NULL; +vm_map_t phys_map = NULL; +vm_map_t mb_map = NULL; /* and ever more shall be so */ + +void +cpu_reboot(howto, b) + int howto; + char *b; +{ + /* FIXME This needs much more sophistication */ + splhigh(); + /* XXX Temporary measure */ + howto |= RB_HALT; + if (howto & RB_HALT) { + printf("system halted\n"); + for (;;); + } else { + printf("rebooting..."); + /* + * On a real reset, the ROM is mapped into address + * zero. On RISC OS 3.11 at least, this can be faked + * by copying the first instruction in the ROM to + * address zero -- it immediately branches into the + * ROM at its usual address, and hence would remove + * the ROM mapped at zero anyway. + * + * In order to convince RISC OS to do a hard reset, we + * fake a *FX 200,2. Note that I don't know if this + * will work on RISC OS <3.10. This is slightly + * suboptimal as it causes RISC OS to zero the whole + * of RAM on startup (farewell, message buffer). If + * anyone can tell me how to fake a control-reset in + * software, I'd be most grateful. + */ + *(volatile u_int8_t *)0x9c2 = 2; /* Zero page magic */ + *(volatile u_int32_t *)0 + = *(volatile u_int32_t *)MEMC_ROM_LOW_BASE; + asm volatile("movs pc, #3"); /* reboot in SVC mode */ + } + panic("cpu_reboot failed"); +} + +/* + * This is provided because GCC seems to generate calls to it. + */ +void abort __P((void)) __attribute__((__noreturn__)); + +void +abort() +{ + + panic("abort() called -- noreturn function returned?"); +} + +/* + * cpu_startup: allocate memory for variable-sized tables, + * initialize cpu, and do autoconfiguration. + */ +void +cpu_startup() +{ + int i, base, residual; + vaddr_t minaddr, maxaddr; + vsize_t size; + char pbuf[9]; + + /* Stuff to do here: */ + /* initmsgbuf() is called from start() */ + + printf("%s", version); + format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); + printf("total memory = %s\n", pbuf); + + /* allocsys() is called from start() */ + + /* Various boilerplate memory allocations. */ + + /* + * Allocate virtual address space for file I/O buffers. + * Note they are different than the array of headers, 'buf', + * and usually occupy more virtual memory than physical. + */ + size = MAXBSIZE * nbuf; + if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), + NULL, UVM_UNKNOWN_OFFSET, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_NORMAL, 0)) != KERN_SUCCESS) + panic("cpu_startup: cannot allocate VM for buffers"); + base = bufpages / nbuf; + residual = bufpages % nbuf; + for (i = 0; i < nbuf; i++) { + vsize_t curbufsize; + vaddr_t curbuf; + struct vm_page *pg; + + /* + * Each buffer has MAXBSIZE bytes of VM space allocated. Of + * that MAXBSIZE space, we allocate and map (base+1) pages + * for the first "residual" buffers, and then we allocate + * "base" pages for the rest. + */ + curbuf = (vaddr_t) buffers + (i * MAXBSIZE); + curbufsize = NBPG * ((i < residual) ? (base+1) : base); + + while (curbufsize) { + pg = uvm_pagealloc(NULL, 0, NULL, 0); + if (pg == NULL) + panic("cpu_startup: not enough memory for " + "buffer cache"); + pmap_kenter_pgs(curbuf, &pg, 1); + curbuf += PAGE_SIZE; + curbufsize -= PAGE_SIZE; + } + } + + /* + * Allocate a submap for exec arguments. This map effectively + * limits the number of processes exec'ing at any time. + */ + minaddr = kernel_map->min_offset; + exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); + + /* + * Allocate a submap for physio + */ + phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + 512 * 1024, 0, FALSE, NULL); + + /* + * No need to allocate an mbuf cluster submap. Mbuf clusters + * are allocated via the pool allocator, and we use direct-mapped + * pool pages. + */ + + format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); + printf("avail memory = %s\n", pbuf); + format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); + printf("using %d buffers containing %s of memory\n", nbuf, pbuf); + + /* + * Set up buffers, so they can be used to read disk labels. + */ + bufinit(); + +#if 0 + /* Test exception handlers */ + asm(".word 0x06000010"); /* undefined instruction */ + asm("swi 0"); /* SWI */ + (*(void (*)(void))(0x00008000))(); /* prefetch abort */ + *(volatile int *)(0x00008000) = 0; /* data abort */ + *(volatile int *)(0x10000000) = 0; /* address exception */ +#endif +} diff --git a/sys/arch/arm26/arm26/md_root.c b/sys/arch/arm26/arm26/md_root.c new file mode 100644 index 00000000000..b3ef0712840 --- /dev/null +++ b/sys/arch/arm26/arm26/md_root.c @@ -0,0 +1,88 @@ +/* $NetBSD: md_root.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Gordon W. Ross + * 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. 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. + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: md_root.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $"); + +#include <sys/systm.h> +#include <sys/reboot.h> + +#include <dev/md.h> + +#include "opt_mdsize.h" + +extern int boothowto; + +#ifndef MINIROOTSIZE +#define MINIROOTSIZE 512 +#endif + +#define ROOTBYTES (MINIROOTSIZE << DEV_BSHIFT) + +/* + * This array will be patched to contain a file-system image. + * See the program mdsetimage(8) for details. + */ +u_int32_t md_root_size = ROOTBYTES; +char md_root_image[ROOTBYTES] = "|This is the root ramdisk!\n"; + +/* + * This is called during autoconfig. + */ +void +md_attach_hook(unit, md) + int unit; + struct md_conf *md; +{ + char pbuf[9]; + + if (unit == 0) { + /* Setup root ramdisk */ + md->md_addr = (caddr_t)md_root_image; + md->md_size = (size_t)md_root_size; + md->md_type = MD_KMEM_FIXED; + format_bytes(pbuf, sizeof(pbuf), ROOTBYTES); + printf("md%d: internal %s image area\n", unit, pbuf); + } +} + +/* + * This is called during open (i.e. mountroot) + */ +void +md_open_hook(unit, md) + int unit; + struct md_conf *md; +{ + if (unit == 0) { + /* The root ramdisk only works single-user. */ + boothowto |= RB_SINGLE; + } +} diff --git a/sys/arch/arm26/arm26/mem.c b/sys/arch/arm26/arm26/mem.c new file mode 100644 index 00000000000..10f93e8049a --- /dev/null +++ b/sys/arch/arm26/arm26/mem.c @@ -0,0 +1,214 @@ +/* $NetBSD: mem.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Memory special file + */ + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/buf.h> +#include <sys/systm.h> +#include <sys/uio.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/fcntl.h> + +#include <machine/cpu.h> +#include <machine/memcreg.h> + +#include <vm/vm.h> +#if defined(UVM) +#include <uvm/uvm_extern.h> +#endif + +caddr_t zeropage; +int physlock; + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +/*ARGSUSED*/ +int +mmopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + switch (minor(dev)) { + default: + break; + } + return (0); +} + +/*ARGSUSED*/ +int +mmclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + + return (0); +} + +/*ARGSUSED*/ +int +mmrw(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + register vm_offset_t v; + register int c; + register struct iovec *iov; + int error = 0; + + while (uio->uio_resid > 0 && error == 0) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("mmrw"); + continue; + } + switch (minor(dev)) { + + /* minor device 0 is physical memory */ + case 0: + /* + * On arm26, there's no need to map in the + * relevant page, as we've got physical memory + * mapped in at another address and can just + * use that. + */ + /* XXX Should use pmap_find(). */ + if (v < 0 || + (caddr_t)v + c > MEMC_PHYS_BASE + ptoa(physmem)) + return EFAULT; + error = uiomove(MEMC_PHYS_BASE + uio->uio_offset, + uio->uio_resid, uio); + continue; + + /* minor device 1 is kernel memory */ + case 1: + v = uio->uio_offset; + c = min(iov->iov_len, MAXPHYS); + /* Allow reading from physically mapped space. */ + if (((caddr_t)v >= MEMC_PHYS_BASE && + (caddr_t)v + c < + MEMC_PHYS_BASE + ptoa(physmem)) || + uvm_kernacc((caddr_t)v, c, + uio->uio_rw == UIO_READ ? + B_READ : B_WRITE)) + error = uiomove((caddr_t)v, c, uio); + else + return (EFAULT); + continue; + + /* minor device 2 is EOF/RATHOLE */ + case 2: + if (uio->uio_rw == UIO_WRITE) + uio->uio_resid = 0; + return (0); + + /* minor device 3 (/dev/zero) is source of nulls on read, rathole on write */ + case 3: + if (uio->uio_rw == UIO_WRITE) { + c = iov->iov_len; + break; + } + if (zeropage == NULL) { + zeropage = (caddr_t) + malloc(NBPG, M_TEMP, M_WAITOK); + bzero(zeropage, NBPG); + } + c = min(iov->iov_len, NBPG); + error = uiomove(zeropage, c, uio); + continue; + + default: + return (ENXIO); + } + if (error) + break; + (caddr_t)iov->iov_base += c; + iov->iov_len -= c; + uio->uio_offset += c; + uio->uio_resid -= c; + } + if (minor(dev) == 0) { +/*unlock:*/ + if (physlock > 1) + wakeup((caddr_t)&physlock); + physlock = 0; + } + return (error); +} + +int +mmmmap(dev, off, prot) + dev_t dev; + int off, prot; +{ + int ppn; + + /* + * /dev/mem is the only one that makes sense through this + * interface. For /dev/kmem any physaddr we return here + * could be transient and hence incorrect or invalid at + * a later time. /dev/null just doesn't make any sense + * and /dev/zero is a hack that is handled via the default + * pager in mmap(). + */ + if (minor(dev) != 0) + return (-1); + + /* minor device 0 is physical memory */ + + /* XXX This may botch our cacheing assumptions. Do we care? */ + ppn = atop(off); + if (ppn >= 0 && ppn < physmem ) + return ppn; + return -1; +} diff --git a/sys/arch/arm26/arm26/pmap.c b/sys/arch/arm26/arm26/pmap.c new file mode 100644 index 00000000000..b74603ee159 --- /dev/null +++ b/sys/arch/arm26/arm26/pmap.c @@ -0,0 +1,930 @@ +/* $NetBSD: pmap.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $ */ +/*- + * Copyright (c) 1997, 1998, 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +/* + * pmap.c - Interfacing the MEMC to the BSD VM system. + */ + +/* + * The MEMC has variable page sizes, and moreover it's necessary to + * change the page size depending on the amount of DRAM under the + * MEMC's control. This code currently only handles 32k pages. + * + * The bottom 32k of logically-mapped RAM is zero page, and is mapped + * in all address spaces (though it's not accessible in user mode). + * This contains interrupt vectors, and probably context-switching + * code. It doesn't appear in any pmap as it's never unmapped. + * + * Wired pages are an interesting proposition. We aren't allowed to + * let page faults on them reach the MI fault handler, and in general + * we shouldn't let them get dropped from the map in the MEMC at all. + * This is tricky when we have kernel and user space shared, as we + * have to ensure that no wired page in the kernel is mapped by any + * user process or vice versa. + */ + +/* + * On an ARM3, the cache must be flushed whenever: + * + * 1 - We remove read access to a page, since we need to ensure reads + * will abort. Write access doesn't matter since the cache is + * write-through. + * + * 2 - We write to a page and need to be able to read it elsewhere. + * Since the MEMC can only map each page once, this only occurs + * without case one when one of the accesses is physical and the other + * logical, which I think only happens when doing odd things with + * /dev/mem. In all other cases, a physical page should only be + * accessed through one of its mappings (virtual if it has one, + * physical if it doesn't). pmap_find is useful for this. + */ + +/* + * We assume the following rules apply: + * + * Accesses to memory managed by user pmaps will always be from USR + * mode, or from LDR/STR with the T bit set (which looks the same to + * the MEMC). + * + * Accesses to memory managed by the kernel pmap will always be from + * SVC mode. + * + * Breaking these rules (especially the first) is likely to upset + * referenced/modified emulation. + */ + +#include "opt_cputypes.h" +#include "opt_ddb.h" +#include "arcvideo.h" + +#include <sys/param.h> + +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.1 2000/05/09 21:55:56 bjh21 Exp $"); + +#include <sys/kernel.h> /* for cold */ +#include <sys/malloc.h> +#define __POOL_EXPOSE /* We need to allocate one statically. */ +#include <sys/pool.h> +#include <sys/systm.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_kern.h> + +#include <machine/machdep.h> +#include <machine/memcreg.h> + +#include <arch/arm26/arm26/cpuvar.h> + +/* + * We store all the mapping information in the pv_table, and the pmaps + * just contain references to it. This is suggested in the Daemon + * Book as a sensible thing to do on systems without real page tables. + */ +struct pv_entry { + struct pv_entry *pv_next; + pmap_t pv_pmap; + int pv_ppn; + int pv_lpn; + u_int32_t pv_activate; /* MEMC command to activate mapping */ + u_int32_t pv_deactivate;/* MEMC command to deactivate mapping */ + vm_prot_t pv_prot; /* requested protection */ + u_int8_t pv_ppl; /* Actual PPL */ + u_int8_t pv_vflags; /* Per-mapping flags */ +#define PV_WIRED 0x01 /* This is a wired mapping */ + u_int8_t pv_pflags; /* Per-physical-page flags */ +#define PV_REFERENCED 0x01 +#define PV_MODIFIED 0x02 +}; + +struct pmap { + int pm_count; /* Reference count */ + int pm_flags; +#define PM_ACTIVE 0x00000001 + struct pv_entry *pm_entries[1024]; +}; + +/* + * All physical pages must map to _some_ logical page, even though + * they can have all access disabled. This means we need a logical + * page reseved for this purpose. We use the last page of kernel VM. + */ +#define PMAP_DEAD_PAGE (atop(VM_MAX_KERNEL_ADDRESS) - 1) +#define PMAP_UNMAP_ENTRY_32K(ppn) \ + MEMC_TRANS_ENTRY_32K(ppn, PMAP_DEAD_PAGE, MEMC_PPL_NOACCESS) +#if 0 +{} /* shut up emacs */ +#endif + +/* + * Global array of pv_entries. Should be dynamically allocated based on + * number of physical pages in system, or something. + */ +struct pv_entry pv_table[1024]; + +/* Kernel pmap -- statically allocated to make life slightly less odd. */ + +struct pmap kernel_pmap_store; + +static boolean_t pmap_initialised = FALSE; + +static struct pool pmap_pool_store; +static struct pool *pmap_pool = &pmap_pool_store; + +static pmap_t active_pmap; + +static void pv_update(struct pv_entry *); +static struct pv_entry *pv_alloc(void); +static void pv_free(struct pv_entry *pv); +static struct pv_entry *pv_get(pmap_t pmap, int ppn, int lpn); +static void pv_release(pmap_t pmap, int ppn, int lpn); + +static caddr_t pmap_find(paddr_t); + +static void pmap_update_page(int); + +/* + * No-one else wanted to take responsibility for the MEMC control register, + * so it's ended up here. + */ + +static register_t memc_control = 0; + +register_t +update_memc(register_t mask, register_t value) +{ + register_t old; + int s; + + s = splhigh(); + old = memc_control; + memc_control &= ~mask; + memc_control |= value & mask; + MEMC_WRITE(memc_control); + splx(s); + return old; +} + +/* + * pmap_bootstrap: first-stage pmap initialisation + * + * This is called very early, and has to get the pmap system into a + * state where pmap_virtual_space and pmap_kenter_pa at least will + * work. If we need memory here, we have to work out how to get it + * ourselves. + */ +void +pmap_bootstrap(int npages, paddr_t zp_physaddr) +{ + int i; + struct pmap *pmap; + + /* Set up the kernel's pmap */ + pmap = pmap_kernel(); + bzero(pmap, sizeof(*pmap)); + pmap->pm_count = 1; + pmap->pm_flags = PM_ACTIVE; /* Kernel pmap always is */ + /* pmap_pinit(pmap); */ + /* Clear the MEMC's page table */ + /* XXX Maybe we should leave zero page alone? */ + for (i=0; i < npages; i++) + MEMC_WRITE(PMAP_UNMAP_ENTRY_32K(i)); + bzero(pv_table, sizeof(pv_table)); + /* TODO: Set up control register? */ + update_memc(0xffffffff, MEMC_CONTROL | MEMC_CTL_PGSZ_32K | + MEMC_CTL_LROMSPD_4N | MEMC_CTL_HROMSPD_4N | +#if NARCVIDEO > 0 + MEMC_CTL_RFRSH_FLYBACK | MEMC_CTL_VIDEODMA +#else + MEMC_CTL_RFRSH_CONTIN +#endif + ); + /* Manually map zero page (it doesn't appear in pmaps) */ + MEMC_WRITE(MEMC_TRANS_ENTRY_32K(atop(zp_physaddr), 0, + MEMC_PPL_NOACCESS)); +} + +/* + * pmap_init: second stage pmap initialisation. + * + * Sets up everything that will be needed for normal running. We can + * allocate memory in page-rounded chunks with uvm_km_(z)alloc(), or + * use the pool allocator. malloc is still taboo. + */ +void +pmap_init() +{ + + pool_init(pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappool", + 0, NULL, NULL, M_VMPMAP); + pmap_initialised = 1; +} + +struct pmap * +pmap_create() +{ + struct pmap *pmap; + + pmap = pool_get(pmap_pool, PR_WAITOK); + bzero(pmap, sizeof(*pmap)); + return pmap; +} + +void +pmap_destroy(pmap_t pmap) +{ +#ifdef DIAGNOSTIC + int i; +#endif + + if (--pmap->pm_count > 0) + return; +#ifdef DIAGNOSTIC + if (pmap->pm_flags & PM_ACTIVE) + panic("pmap_destroy: pmap is active"); + for (i = 0; i < 1024; i++) + if (pmap->pm_entries[i] != NULL) + panic("pmap_destroy: pmap isn't empty"); +#endif + pool_put(pmap_pool, pmap); +} + +void +pmap_activate(struct proc *p) +{ + pmap_t pmap; + int i; + + pmap = p->p_vmspace->vm_map.pmap; + + if (pmap == pmap_kernel()) + return; /* kernel pmap is always active */ + +#ifdef DIAGNOSTIC + if (active_pmap != NULL || (pmap->pm_flags & PM_ACTIVE) != 0) + panic("pmap_activate"); +#endif + + active_pmap = pmap; + pmap->pm_flags |= PM_ACTIVE; + for (i = 0; i < 1024; i++) + if (pmap->pm_entries[i] != NULL) + MEMC_WRITE(pmap->pm_entries[i]->pv_activate); +} + +void +pmap_deactivate(struct proc *p) +{ + pmap_t pmap; + int i; + + pmap = p->p_vmspace->vm_map.pmap; + + if (pmap == pmap_kernel()) + return; /* kernel pmap is always active */ + +#ifdef DIAGNOSTIC + if (active_pmap != pmap || (pmap->pm_flags & PM_ACTIVE) == 0) + panic("pmap_deactivate"); +#endif + + active_pmap = NULL; + pmap->pm_flags &=~ PM_ACTIVE; + for (i = 0; i < 1024; i++) + if (pmap->pm_entries[i] != NULL) + MEMC_WRITE(pmap->pm_entries[i]->pv_deactivate); + cpu_cache_flush(); +} + +void +pmap_unwire(pmap_t pmap, vaddr_t va) +{ + struct pv_entry *pv; + + if (pmap == NULL) return; + pv = pmap->pm_entries[atop(va)]; + if (pv == NULL) return; + pv->pv_vflags &= ~PV_WIRED; +} + +void +pmap_collect(pmap) + pmap_t pmap; +{ + /* This is allowed to be a no-op. */ +} + +void +pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) + pmap_t dst_pmap, src_pmap; + vaddr_t dst_addr, src_addr; + vsize_t len; +{ + /* This is allowed to be a no-op. */ +} + +/* + * Update the pv_activate and pv_deactivate fields in a pv_entry to + * match the rest. + */ +static void +pv_update(struct pv_entry *pv) +{ + int ppl; + int pflags; + + pflags = pv_table[pv->pv_ppn].pv_pflags; + if (pv->pv_pmap == pmap_kernel()) { + if (1) { + /* Don't risk faults till everything's happy */ + ppl = MEMC_PPL_NOACCESS; + pv_table[pv->pv_ppn].pv_pflags |= + PV_REFERENCED | PV_MODIFIED; + } else if ((pflags & PV_REFERENCED) && (pflags & PV_MODIFIED)) + ppl = MEMC_PPL_NOACCESS; + else { + /* + * To keep SVC mode from seeing a page, we + * have to unmap it entirely. + */ + pv->pv_ppl = MEMC_PPL_NOACCESS; + pv->pv_activate = pv->pv_deactivate = + PMAP_UNMAP_ENTRY_32K(pv->pv_ppn); + return; + } + } else { + if ((pv->pv_prot & VM_PROT_WRITE) && + (pflags & PV_REFERENCED) && (pflags & PV_MODIFIED)) + ppl = MEMC_PPL_RDWR; + else if ((pv->pv_prot & (VM_PROT_READ | VM_PROT_EXECUTE)) && + (pflags & PV_REFERENCED)) + ppl = MEMC_PPL_RDONLY; + else + ppl = MEMC_PPL_NOACCESS; + } + pv->pv_ppl = ppl; + pv->pv_activate = MEMC_TRANS_ENTRY_32K(pv->pv_ppn, pv->pv_lpn, ppl); + pv->pv_deactivate = PMAP_UNMAP_ENTRY_32K(pv->pv_ppn); +} + + +static struct pv_entry * +pv_alloc() +{ + struct pv_entry *pv; + + MALLOC(pv, struct pv_entry *, sizeof(*pv), M_VMPMAP, M_WAITOK); + bzero(pv, sizeof(*pv)); + return pv; +} + +static void +pv_free(struct pv_entry *pv) +{ + + FREE(pv, M_VMPMAP); +} + +static struct pv_entry * +pv_get(pmap_t pmap, int ppn, int lpn) +{ + struct pv_entry *pv; + + /* If the head entry's free use that. */ + pv = &pv_table[ppn]; + if (pv->pv_pmap == NULL) + return pv; + /* If this mapping exists already, use that. */ + for (pv = pv; pv != NULL; pv = pv->pv_next) + if (pv->pv_pmap == pmap && pv->pv_lpn == lpn) + return pv; + /* Otherwise, allocate a new entry and link it in after the head. */ + pv = pv_alloc(); + pv->pv_next = pv_table[ppn].pv_next; + pv_table[ppn].pv_next = pv; + return pv; +} + +/* + * Release the pv_entry for a mapping. Code derived from hp300 pmap. + */ +static void +pv_release(pmap_t pmap, int ppn, int lpn) +{ + struct pv_entry *pv, *npv; + + pv = &pv_table[ppn]; + /* + * If it is the first entry on the list, it is actually + * in the header and we must copy the following entry up + * to the header. Otherwise we must search the list for + * the entry. In either case we free the now unused entry. + */ + if (pmap == pv->pv_pmap && lpn == pv->pv_lpn) { + npv = pv->pv_next; + if (npv) { + /* Pull up first entry from chain. */ + npv->pv_pflags = pv->pv_pflags; + *pv = *npv; + pv->pv_pmap->pm_entries[lpn] = pv; + pv_free(npv); + } else + pv->pv_pmap = NULL; + } else { + for (npv = pv->pv_next; npv; npv = npv->pv_next) { + if (pmap == npv->pv_pmap && lpn == npv->pv_lpn) + break; + pv = npv; + } +#ifdef DIAGNOSTIC + if (npv == NULL) + panic("pv_release"); +#endif + pv->pv_next = npv->pv_next; + pv_free(npv); + } + pmap->pm_entries[lpn] = NULL; +} + + +/* + * Insert the given physical page (pa) at the specified virtual + * address (va) in the target physical map with the protection + * requested. + * + * NB: This is the only routine which MAY NOT lazy-evaluate or lose + * information. That is, this routine must actually insert this page + * into the given map NOW. + */ +int +pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags) +{ + int ppn, lpn, s; + struct pv_entry *pv; + + ppn = atop(pa); lpn = atop(va); + +#if 0 + printf("pmap_enter: mapping ppn %d at lpn %d in pmap %p\n", + ppn, lpn, pmap); +#endif + s = splimp(); + /* Check if the physical page is mapped already elsewhere. */ + if (pmap == pmap_kernel()) { + for (pv = &pv_table[ppn]; pv != NULL; pv = pv->pv_next) + if (pv->pv_pmap != NULL && + (pv->pv_pmap != pmap || pv->pv_lpn != lpn)) { + printf("new: pmap = %p, ppn = %d, lpn = %d\n", + pmap, ppn, lpn); + printf("old: pmap = %p, ppn = %d, lpn = %d\n", + pv->pv_pmap, pv->pv_ppn, pv->pv_lpn); + panic("Mapping clash not handled"); + } + } else { + for (pv = &pv_table[ppn]; pv != NULL; pv = pv->pv_next) + if (pv->pv_pmap == pmap_kernel() || + (pv->pv_pmap == pmap && pv->pv_lpn != lpn)) { + printf("new: pmap = %p, ppn = %d, lpn = %d\n", + pmap, ppn, lpn); + printf("old: pmap = %p, ppn = %d, lpn = %d\n", + pv->pv_pmap, pv->pv_ppn, pv->pv_lpn); + panic("Mapping clash not handled"); + } + } + + /* Remove any existing mapping at this lpn */ + if (pmap->pm_entries[lpn] != NULL && + pmap->pm_entries[lpn]->pv_ppn != ppn) + pmap_remove(pmap, va, va + PAGE_SIZE); + + /* Make a note */ + pv = pv_get(pmap, ppn, lpn); + pv->pv_pmap = pmap; + pv->pv_ppn = ppn; + pv->pv_lpn = lpn; + pv->pv_prot = prot; + pv->pv_vflags = 0; + pv->pv_pflags = 0; + if (flags & PMAP_WIRED) + pv->pv_vflags |= PV_WIRED; + pv_update(pv); + pmap->pm_entries[lpn] = pv; + splx(s); + /* Poke the MEMC */ + if (pmap->pm_flags & PM_ACTIVE) + MEMC_WRITE(pv->pv_activate); + + return KERN_SUCCESS; +} + +/* Remove a range of virtual mappings from a pmap */ +void +pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva) +{ + int slpn, elpn, lpn, s; + struct pv_entry *pv; + + slpn = atop(sva); elpn = atop(eva); +#if 0 + printf("pmap_remove: clearing from lpn %d to lpn %d in pmap %p\n", + slpn, elpn - 1, pmap); +#endif + s = splimp(); + for (lpn = slpn; lpn < elpn; lpn++) { + pv = pmap->pm_entries[lpn]; + if (pv != NULL) { + if (pmap->pm_flags & PM_ACTIVE) { + MEMC_WRITE(pv->pv_deactivate); + cpu_cache_flush(); + } + pmap->pm_entries[lpn] = NULL; + pv_release(pmap, pv->pv_ppn, lpn); + } + } + splx(s); +} + +boolean_t +pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *ppa) +{ + struct pv_entry *pv; + + pv = pmap->pm_entries[atop(va)]; + if (pv == NULL) + return FALSE; + *ppa = ptoa(pv->pv_ppn); + return TRUE; +} + +void +pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) +{ + + pmap_enter(pmap_kernel(), va, pa, prot, PMAP_WIRED); +} + +void +pmap_kenter_pgs(vaddr_t va, struct vm_page **pages, int npages) +{ + + while (npages > 0) { + pmap_kenter_pa(va, (*pages)->phys_addr, VM_PROT_ALL); + va += NBPG; + pages++; + npages--; + } +} + +void +pmap_kremove(vaddr_t va, vsize_t len) +{ + + pmap_remove(pmap_kernel(), va, va+len); +} + +boolean_t +pmap_is_modified(page) + struct vm_page *page; +{ + int ppn; + + ppn = atop(page->phys_addr); + return (pv_table[ppn].pv_pflags & PV_MODIFIED) != 0; +} + +boolean_t +pmap_is_referenced(page) + struct vm_page *page; +{ + int ppn; + + ppn = atop(page->phys_addr); + return (pv_table[ppn].pv_pflags & PV_REFERENCED) != 0; +} + +static void +pmap_update_page(int ppn) +{ + struct pv_entry *pv; + + for (pv = &pv_table[ppn]; pv != NULL; pv = pv->pv_next) + if (pv->pv_pmap != NULL) { + pv_update(pv); + if (pv->pv_pmap->pm_flags & PM_ACTIVE) { + if (pv->pv_activate) + MEMC_WRITE(pv->pv_activate); + else + MEMC_WRITE(pv->pv_deactivate); + } + } +} + +boolean_t +pmap_clear_modify(struct vm_page *page) +{ + int ppn; + boolean_t rv; + + ppn = atop(page->phys_addr); + rv = pmap_is_modified(page); + pv_table[ppn].pv_pflags &= ~PV_MODIFIED; + pmap_update_page(ppn); + return rv; +} + +boolean_t +pmap_clear_reference(struct vm_page *page) +{ + int ppn; + boolean_t rv; + + ppn = atop(page->phys_addr); + rv = pmap_is_referenced(page); + pv_table[ppn].pv_pflags &= ~PV_REFERENCED; + pmap_update_page(ppn); + return rv; +} + +/* + * Work out if a given page fault was our fault (e.g. through + * referenced/modified emulation). If it was, handle it and return + * TRUE. Otherwise, return FALSE. + */ +boolean_t +pmap_fault(struct pmap *pmap, vaddr_t va, vm_prot_t atype) +{ + int lpn, ppn; + struct pv_entry *pv, *ppv; + + lpn = atop(va); + pv = pmap->pm_entries[lpn]; + if (pv == NULL) + return FALSE; + ppn = pv->pv_ppn; + ppv = &pv_table[ppn]; + if (pmap == pmap_kernel()) { + /* + * If we allow the kernel to access the page, we can't + * stop it writing to it as well, so we have to handle + * referenced and modified bits together. + */ + if ((ppv->pv_pflags & PV_REFERENCED) == 0 || + (ppv->pv_pflags & PV_MODIFIED) == 0) { + ppv->pv_pflags |= PV_REFERENCED | PV_MODIFIED; + pmap_update_page(ppn); + return TRUE; + } + } else { + if ((ppv->pv_pflags & PV_REFERENCED) == 0) { + ppv->pv_pflags |= PV_REFERENCED; + pmap_update_page(ppn); + return TRUE; + } + if ((atype & VM_PROT_WRITE) && (pv->pv_prot & VM_PROT_WRITE) && + (ppv->pv_pflags & PV_MODIFIED) == 0) { + ppv->pv_pflags |= PV_MODIFIED; + pmap_update_page(ppn); + return TRUE; + } + } + return FALSE; +} + +void +pmap_page_protect(struct vm_page *page, vm_prot_t prot) +{ + int ppn; + struct pv_entry *pv; + + ppn = atop(page->phys_addr); + if (prot == VM_PROT_NONE) { +#if 0 + printf("pmap_page_protect: removing ppn %d\n", ppn); +#endif + pv = &pv_table[ppn]; + while (pv->pv_pmap != NULL) { + if (pv->pv_pmap->pm_flags & PM_ACTIVE) { + MEMC_WRITE(pv->pv_deactivate); + cpu_cache_flush(); + } + pv->pv_pmap->pm_entries[pv->pv_lpn] = NULL; + pv_release(pv->pv_pmap, pv->pv_ppn, pv->pv_lpn); + } + } else if (prot != VM_PROT_ALL) { + for (pv = &pv_table[ppn]; pv != NULL; pv = pv->pv_next) + if (pv->pv_pmap != NULL) { + pv->pv_prot &= prot; + pv_update(pv); + if (pv->pv_pmap->pm_flags & PM_ACTIVE) + MEMC_WRITE(pv->pv_activate); + } + } +} + +paddr_t +pmap_phys_address(ppn) + int ppn; +{ + panic("pmap_phys_address not implemented"); +} + +void +pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) +{ + struct pv_entry *pv; + int s, slpn, elpn, lpn; + + if (prot == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + if (prot & VM_PROT_WRITE) + return; /* apparently we're meant to */ + if (pmap == pmap_kernel()) + return; /* can't restrict kernel w/o unmapping. */ + + slpn = atop(sva); elpn = atop(eva); + s = splimp(); + for (lpn = slpn; lpn < elpn; lpn++) { + pv = pmap->pm_entries[lpn]; + if (pv != NULL) { + pv->pv_prot &= prot; + pv_update(pv); + if (pv->pv_pmap->pm_flags & PM_ACTIVE) + MEMC_WRITE(pv->pv_activate); + } + } + splx(s); +} + +void +pmap_reference(pmap_t pmap) +{ + + pmap->pm_count++; +} + +/* + * If there were any actions we could delay committing to hardware, + * this would be where they'd be committed. We should perhaps delay + * cache flushes till here, but I've heard rumours that pmap_update() + * isn't called as often as it should be, so I'll play it safe for + * now. + */ +void +pmap_update() +{ + + /* Do nothing */ +} + +/* + * See if the given physical address has a logical mapping. Return + * its address if so, otherwise return the logical address in MEMC + * physical space. This means that we can safely write here without + * flushing the cache. Only necessary on ARM3. + */ +static caddr_t +pmap_find(paddr_t pa) +{ +#ifdef CPU_ARM3 + struct pv_entry *pv; + + for (pv = &pv_table[atop(pa)]; pv != NULL; pv = pv->pv_next) + if (pv->pv_pmap != NULL && (pv->pv_pmap->pm_flags & PM_ACTIVE)) + return (caddr_t)ptoa(pv->pv_lpn); +#endif + return MEMC_PHYS_BASE + pa; +} + +void +pmap_zero_page(paddr_t pa) +{ + + bzero(pmap_find(pa), PAGE_SIZE); + pv_table[atop(pa)].pv_pflags |= PV_MODIFIED | PV_REFERENCED; +} + +void +pmap_copy_page(paddr_t src, paddr_t dest) +{ + + memcpy(pmap_find(dest), pmap_find(src), PAGE_SIZE); + pv_table[atop(src)].pv_pflags |= PV_REFERENCED; + pv_table[atop(dest)].pv_pflags |= PV_MODIFIED | PV_REFERENCED; +} + +/* + * This is meant to return the range of kernel vm that is available + * after loading the kernel. Since NetBSD/arm26 runs the kernel from + * physically-mapped space, we just return all of kernel vm. Oh, + * except for the single page at the end where we map + * otherwise-unmapped pages. + */ +void +pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp) +{ + + *vstartp = VM_MIN_KERNEL_ADDRESS; + *vendp = VM_MAX_KERNEL_ADDRESS - PAGE_SIZE; +} + +/* + * Check if the given access should have aborted. Used in various abort + * handlers to work out what happened. + */ +boolean_t +pmap_confess(vaddr_t va, vm_prot_t atype) +{ + pmap_t pmap; + struct pv_entry *pv; + + /* XXX Assume access was from user mode (or equiv). */ + pmap = va < VM_MIN_KERNEL_ADDRESS ? active_pmap : pmap_kernel(); + pv = pmap->pm_entries[atop(va)]; + if (pv == NULL) + return TRUE; + if (pv->pv_ppl == MEMC_PPL_NOACCESS) + return TRUE; + if (pv->pv_ppl == MEMC_PPL_RDONLY && (atype & VM_PROT_WRITE)) + return TRUE; + return FALSE; +} + +#ifdef DDB +#include <ddb/db_output.h> + +void +pmap_dump(struct pmap *pmap) +{ + int i; + struct pv_entry *pv; + int pflags; + + db_printf("PMAP %p:\n", pmap); + db_printf("\tcount = %d, flags = %d\n", + pmap->pm_count, pmap->pm_flags); + for (i = 0; i < 1024; i++) + if ((pv = pmap->pm_entries[i]) != NULL) { + db_printf("\t%03d->%p: ", i, pv); + if (pv->pv_pmap != pmap) + db_printf("pmap=%p!, ", pv->pv_pmap); + db_printf("ppn=%d, lpn=%d, ", + pv->pv_ppn, pv->pv_lpn); + db_printf("act=%08x, deact=%08x,\n", + pv->pv_activate, pv->pv_deactivate); + db_printf("\t\tprot=%c%c%c, ", + pv->pv_prot & VM_PROT_READ ? 'r' : '-', + pv->pv_prot & VM_PROT_WRITE ? 'w' : '-', + pv->pv_prot & VM_PROT_EXECUTE ? 'x' : '-'); + db_printf("ppl="); + switch(pv->pv_ppl) { + case MEMC_PPL_RDWR: + db_printf("rw, "); + break; + case MEMC_PPL_RDONLY: + db_printf("r-, "); + break; + case MEMC_PPL_NOACCESS: + db_printf("--, "); + break; + default: + db_printf("0x%x, ", pv->pv_ppl); + break; + } + db_printf("vflags=%c, ", + pv->pv_vflags & PV_WIRED ? 'W' : '-'); + pflags = pv_table[pv->pv_ppn].pv_pflags; + db_printf("pflags=%c%c\n", + pflags & PV_MODIFIED ? 'M' : '-', + pflags & PV_REFERENCED ? 'R' : '-'); + + } +} +#endif diff --git a/sys/arch/arm26/arm26/rscons.c b/sys/arch/arm26/arm26/rscons.c new file mode 100644 index 00000000000..af33f83c22e --- /dev/null +++ b/sys/arch/arm26/arm26/rscons.c @@ -0,0 +1,99 @@ +/* $NetBSD: rscons.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */ +/*- + * Copyright (c) 1997, 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * rscons.c - Really basic routines for the Arc serial port + */ + +#include <sys/param.h> +#include <sys/conf.h> + +#include <dev/cons.h> +#include <dev/ic/r6551reg.h> + +#define RS_BASE 0x033B0000 + +cons_decl(rs); + +void rscnprobe(cp) + struct consdev *cp; +{ + + /* Be optimistic! */ + cp->cn_pri = CN_NORMAL; + cp->cn_dev = makedev(13, 0); +} + +void rscninit(cp) + struct consdev *cp; +{ + volatile char *rs_base = (volatile char *)RS_BASE; + + /* Reset 6551 */ + rs_base[R6551_RESET<<2] = 1; + /* 9600, 8N1 */ + rs_base[R6551_CONTROL<<2] = R6551_CTL_SBR_9600 | + R6551_CTL_WL_8 | R6551_CTL_RCS_INT; + /* Enable transmission, disable interrupts, set DTR. */ + rs_base[R6551_COMMAND<<2] = R6551_CMD_DTR | R6551_CMD_IRD | + R6551_CMD_TIC_NOIRQ; + /* The 6551 is now sane. Well, as sane as a 6551 can be. */ +} + +int rscngetc(dev) + dev_t dev; +{ + volatile char *rs_base = (volatile char *)RS_BASE; + int c; + + /* Wait for reception */ + while ((rs_base[R6551_STATUS<<2] & R6551_STAT_RDRF) == 0); + c = rs_base[R6551_RX_DATA<<2]; + if (c == '\r') + c = '\n'; + return c; +} + +void rscnputc(dev, c) + dev_t dev; + int c; +{ + volatile char *rs_base = (volatile char *)RS_BASE; + + while (!(rs_base[R6551_STATUS<<2] & R6551_STAT_TDRE)); + /* And it's now ready to transmit. */ + rs_base[R6551_TX_DATA<<2] = c; + /* Wait for it to finish (me? paranoid?) */ + while (!(rs_base[R6551_STATUS<<2] & R6551_STAT_TDRE)); +} + +void rscnpollc(dev, on) + dev_t dev; + int on; +{ +} diff --git a/sys/arch/arm26/arm26/softintr.c b/sys/arch/arm26/arm26/softintr.c new file mode 100644 index 00000000000..42122412c54 --- /dev/null +++ b/sys/arch/arm26/arm26/softintr.c @@ -0,0 +1,175 @@ +/* $NetBSD: softintr.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */ + +/* + * Copyright (c) 1999 Ben Harris. + * Copyright (c) 1994-1998 Mark Brinicombe. + * 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 Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may 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 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. + * + * Soft interrupt and other generic interrupt functions. + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: softintr.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $"); + +#include <sys/malloc.h> +#include <sys/queue.h> +#include <sys/systm.h> + +#include <machine/intr.h> +#include <machine/spl.h> + +#include <vm/vm.h> +#include <uvm/uvm_extern.h> + +#include <machine/machdep.h> +#include <machine/softintr.h> + +#include <net/netisr.h> + +struct softintr_handler { + LIST_ENTRY(softintr_handler) sh_link; + int sh_ipl; + void (*sh_func)(void *); + void *sh_arg; + int sh_pending; +}; + +LIST_HEAD(sh_head, softintr_handler); + +static struct sh_head sh_head; + +static struct softintr_handler *sh_softnet; +static struct softintr_handler *sh_softclock; + +static void dosoftnet(void *); +static void dosoftclock(void *); + +extern int hardsplx(int); /* XXX should be in a header somewhere */ + +void +softintr_init() +{ + + LIST_INIT(&sh_head); + sh_softnet = softintr_establish(IPL_SOFTNET, dosoftnet, NULL); + sh_softclock = softintr_establish(IPL_SOFTCLOCK, dosoftclock, NULL); +} + +void +setsoftclock() +{ + + softintr_schedule(sh_softclock); +} + +void +setsoftnet() +{ + + softintr_schedule(sh_softnet); +} + +/* Handle software interrupts */ + +void +dosoftints(int level) +{ + struct softintr_handler *sh; + + for (sh = LIST_FIRST(&sh_head); sh != NULL && sh->sh_ipl > level; + sh = LIST_NEXT(sh, sh_link)) + if (sh->sh_pending) { + hardsplx(sh->sh_ipl); + uvmexp.softs++; + sh->sh_pending = 0; + sh->sh_func(sh->sh_arg); + } +} + +void * +softintr_establish(int ipl, void (*func)(void *), void *arg) +{ + struct softintr_handler *new, *sh; + + MALLOC(new, struct softintr_handler *, sizeof(*sh), + M_DEVBUF, M_WAITOK); + new->sh_ipl = ipl; + new->sh_func = func; + new->sh_arg = arg; + if (LIST_FIRST(&sh_head) == NULL || + LIST_FIRST(&sh_head)->sh_ipl <= ipl) + /* XXX This shouldn't need to be a special case */ + LIST_INSERT_HEAD(&sh_head, new, sh_link); + else { + for (sh = LIST_FIRST(&sh_head); + LIST_NEXT(sh, sh_link) != NULL + && LIST_NEXT(sh, sh_link)->sh_ipl > ipl; + sh = LIST_NEXT(sh, sh_link)); + LIST_INSERT_AFTER(sh, new, sh_link); + } + return new; +} + +void +softintr_disestablish(void *cookie) +{ + + panic("softintr_disestablish not implemented"); +} + +void +softintr_schedule(void *cookie) +{ + struct softintr_handler *sh = cookie; + + sh->sh_pending = 1; +} + +static void +dosoftclock(void *arg) +{ + + softclock(); +} + + +static void +dosoftnet(void *arg) +{ + +#define DONETISR(bit, fn) do { \ + atomic_clear_bit(&netisr, 1 << (bit)); \ + fn(); \ +} while (0) +#include <net/netisr_dispatch.h> +#undef DONETISR +} diff --git a/sys/arch/arm26/arm26/start.c b/sys/arch/arm26/arm26/start.c new file mode 100644 index 00000000000..699dac8a827 --- /dev/null +++ b/sys/arch/arm26/arm26/start.c @@ -0,0 +1,225 @@ +/* $NetBSD: start.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */ +/*- + * Copyright (c) 1998, 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * start.c -- In the beginning... + */ + +#include <sys/param.h> + +__KERNEL_RCSID(0, "SId$"); + +#include <sys/msgbuf.h> +#include <sys/syslog.h> +#include <sys/systm.h> + +#include <machine/armreg.h> +#include <machine/boot.h> +#include <machine/machdep.h> +#include <machine/memcreg.h> + +#include <dev/cons.h> + +#include <vm/vm.h> + +#include "arcvideo.h" +#include "ioc.h" + +#if NIOC > 0 +#include <arch/arm26/iobus/iocreg.h> +#endif + +extern void main __P((void)); /* XXX Should be in a header file */ + +struct bootconfig bootconfig; + +#define BOOT_SANITY 0x89345846 +static int boot_sanity = BOOT_SANITY; + +#ifndef __ELF__ +/* Odd symbols declared by the linker */ +extern char _stext_, _etext, _sdata_, _edata, _bss_start, _end; +#else /* ELF */ +extern char __bss_start__[], __bss_end__[]; +#endif + +/* + * This is where it all begins. The bootloader is expected to enter + * in an APCS-compliant manner so we don't have to mess around in + * assembler to get things going. + */ +void +start(initbootconfig) + struct bootconfig *initbootconfig; +{ + extern char page0[], page0_end[]; + size_t size; + caddr_t v; + char pbuf[9]; + + /* + * State of the world as of BBBB 0.02: + * Registers per APCS + * physmem (set up by RISC OS and BBBB): + * 0x02000000 -- 0x02080000 == Screen (potentially) + * 0x02080000 -- 0x02088000 == Zero page + * 0x02088000 -- 0x02090000 == Initial kernel stack + * 0x02090000 -- 0x02098000 == Kernel message buffer + * 0x02098000 -- freebase == Kernel image + * bss is cleared for us + */ + +#define ZP_PHYSADDR ((paddr_t)0x00080000) +#define MSGBUF_PHYSADDR ((paddr_t)0x00090000) + + /* We can't trust the BSS (at least not with my linker) */ + bzero(__bss_start__, __bss_end__ - __bss_start__); + + /* Save boot configuration somewhere */ + memcpy(&bootconfig, initbootconfig, sizeof(struct bootconfig)); + + if (bootconfig.magic != BOOT_MAGIC) + panic("bootloader is ancient"); + /* initialise kernel variables */ + boothowto = bootconfig.boothowto; + physmem = bootconfig.npages; + uvmexp.pagesize = bootconfig.nbpp; + uvm_setpagesize(); + + /* Any others? */ + + /* Set up kernel message buffer */ + /* XXX Should be in cpu_startup, yesno? */ + /* Probably not actually -- the sooner it's run, the better. */ + initmsgbuf(MEMC_PHYS_BASE + MSGBUF_PHYSADDR, MSGBUFSIZE); + +#ifdef DIAGNOSTIC + /* + * Check that the linker and loader agree about where + * everything should be loaded. + */ + +#ifndef __ELF__ /* BBBB doesn't set everything for ELF */ + if (&_stext_ != (MEMC_PHYS_BASE + bootconfig.txtbase) || + &_etext - &_stext_ != bootconfig.txtsize || + &_sdata_ != (MEMC_PHYS_BASE + bootconfig.database) +#if 0 /* BBBB gets this wrong, but that's because the a.out header is wrong */ + || + &_edata - &_sdata_ != bootconfig.datasize || + &_bss_start != (MEMC_PHYS_BASE + bootconfig.bssbase) || + &_end - &_bss_start != bootconfig.bsssize +#endif + ) { + printf("text: %p + %08x vs %p + %08x\n", + &_stext_, &_etext - &_stext_, + MEMC_PHYS_BASE + bootconfig.txtbase, + bootconfig.txtsize); + printf("data: %p + %08x vs %p + %08x\n", + &_sdata_, &_edata - &_sdata_, + MEMC_PHYS_BASE + bootconfig.database, + bootconfig.datasize); + printf("bss: %p + %08x vs %p + %08x\n", + &_bss_start, &_end - &_bss_start, + MEMC_PHYS_BASE + bootconfig.bssbase, + bootconfig.bsssize); + panic("bootloader disagreement"); + } +#endif + + if (boot_sanity != BOOT_SANITY) + panic("Bootloader mislaid the data segment"); +#endif + + /* + * Allocate space for system data structures. These data structures + * are allocated here instead of cpu_startup() because physical + * memory is directly addressable. We don't have to map these into + * virtual address space. This trick is stolen from the alpha port. + */ + size = (vsize_t)allocsys(0, NULL); + v = MEMC_PHYS_BASE + bootconfig.freebase; + bootconfig.freebase += size; + if (bootconfig.freebase > ptoa(physmem)) { + format_bytes(pbuf, sizeof(pbuf), size); + panic("start: out of memory (wanted %s)", pbuf); + } + bzero(v, size); + if ((allocsys(v, NULL) - v) != size) + panic("start: table size inconsistency"); + + /* Tell UVM about memory */ +#if NARCVIDEO == 0 + /* + * DMA-able space. If the video driver's configured, it'll + * register this later once it knows how much it's using. + */ + uvm_page_physload(0, atop(MEMC_DMA_MAX), 0, atop(MEMC_DMA_MAX), + VM_FREELIST_LOW); +#endif + /* + * Normal memory -- we expect the bootloader to tell us where + * the kernel ends. + */ + uvm_page_physload(atop(MEMC_DMA_MAX), bootconfig.npages, + atop(round_page(bootconfig.freebase)), + bootconfig.npages, + VM_FREELIST_DEFAULT); + + /* printf("Memory registered with UVM.\n"); */ + /* Set up CPU vectors in zero page */ + memcpy(MEMC_PHYS_BASE + ZP_PHYSADDR, page0, page0_end - page0); + + /* Get the MEMC set up and map zero page */ + pmap_bootstrap(bootconfig.npages, ZP_PHYSADDR); + + /* + * This is a nasty bit. Because the kernel uses a 26-bit APCS + * variant, the CPU interrupt disable flags get munged on + * every function return. Thus, we need to enable interrupts + * at the CPU now since this is the last function we control + * that won't return. In order to be able to do this, we need + * to ensure we won't get any interrupts before we're ready + * for them. For now, I'll assume we've got an IOC doing all + * this at the usual location, but it should be done more + * elegantly. + */ + +#if NIOC > 0 + *(volatile u_char *)(0x03200000 + (IOC_IRQMSKA << 2)) = 0; + *(volatile u_char *)(0x03200000 + (IOC_IRQMSKB << 2)) = 0; + *(volatile u_char *)(0x03200000 + (IOC_FIQMSK << 2)) = 0; +#endif + int_on(); + + /* TODO: anything else? */ + + main(); + + panic("main() returned"); + /* NOTREACHED */ +} diff --git a/sys/arch/arm26/arm26/stubs.c b/sys/arch/arm26/arm26/stubs.c new file mode 100644 index 00000000000..a0b72740b5c --- /dev/null +++ b/sys/arch/arm26/arm26/stubs.c @@ -0,0 +1,205 @@ +/* $NetBSD: stubs.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */ +/* + * stubs.c -- functions I haven't written yet + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: stubs.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $"); + +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/user.h> + +void +need_proftick(p) + struct proc *p; +{ + panic("need_proftick not implemented"); +} + +void +resettodr() +{ + + printf("resettodr: not doing anything\n"); +} + +int +suibyte(base, c) + void *base; + int c; +{ + panic("suibyte not implemented"); +} + +int +susword(base, c) + void *base; + short c; +{ + panic("susword not implemented"); +} + +int +suisword(base, c) + void *base; + short c; +{ + panic("suisword not implemented"); +} + +int +suswintr(base, c) + void *base; + short c; +{ + panic("suswintr not implemented"); +} + +int +suiword(base, c) + void *base; + long c; +{ + panic("suiword not implemented"); +} + +int +fuibyte(base) + const void *base; +{ + panic("fuibyte not implemented"); +} + +int +fusword(base) + const void *base; +{ + panic("fusword not implemented"); +} + +int +fuisword(base) + const void *base; +{ + panic("fuisword not implemented"); +} + +int +fuswintr(base) + const void *base; +{ + panic("fuswintr not implemented"); +} + +long +fuiword(base) + const void *base; +{ + panic("fuiword not implemented"); +} + +int +cpu_coredump(p, vp, cred, chdr) + struct proc *p; + struct vnode *vp; + struct ucred *cred; + struct core *chdr; +{ + panic("cpu_coredump not implemented"); +} + +int +cpu_sysctl(name, namelen, oldval, oldlenp, newval, newlen, p) + int *name; + u_int namelen; + void *oldval, *newval; + size_t *oldlenp, newlen; + struct proc *p; +{ + panic("cpu_sysctl not implemented"); +} + +void +vmapbuf(buf, len) + struct buf *buf; + vsize_t len; +{ + panic("vmapbuf not implemented"); +} + +void +vunmapbuf(buf, len) + struct buf *buf; + vsize_t len; +{ + panic("vunmapbuf not implemented"); +} + +void +pagemove(foo, bar, len) + caddr_t foo, bar; + size_t len; +{ + panic("pagemove not implemented"); +} + +int sys_sysarch(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + panic("sys_sysarch not implemented"); +} + +static struct user user0; +struct user *proc0paddr = &user0; + +int +process_read_fpregs(p, regs) + struct proc *p; + struct fpreg *regs; +{ + panic("process_read_fpregs not implemented"); +} + +int +process_read_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + panic("process_read_regs not implemented"); +} + +int +process_set_pc(p, addr) + struct proc *p; + caddr_t addr; +{ + panic("process_set_pc not implemented"); +} + +int +process_sstep(p, sstep) + struct proc *p; + int sstep; +{ + panic("process_sstep not implemented"); +} + +int +process_write_fpregs(p, regs) + struct proc *p; + struct fpreg *regs; +{ + panic("process_write_fpregs not implemented"); +} + +int +process_write_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + panic("process_write_regs not implemented"); +} diff --git a/sys/arch/arm26/arm26/vm_machdep.c b/sys/arch/arm26/arm26/vm_machdep.c new file mode 100644 index 00000000000..df0e559a1b9 --- /dev/null +++ b/sys/arch/arm26/arm26/vm_machdep.c @@ -0,0 +1,330 @@ +/* $NetBSD: vm_machdep.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#include <sys/param.h> + +__RCSID("$NetBSD: vm_machdep.c,v 1.1 2000/05/09 21:55:57 bjh21 Exp $"); + +#include <sys/exec.h> +#include <sys/mount.h> /* XXX syscallargs.h uses fhandle_t and fsid_t */ +#include <sys/proc.h> +#include <sys/syscallargs.h> +#include <sys/user.h> + +#include <vm/vm.h> + +#include <machine/armreg.h> +#include <machine/frame.h> +#include <machine/machdep.h> + +/* + * Finish a fork operation, with process p2 nearly set up. + * Copy and update the pcb and trap frame, making the child ready to run. + * + * p1 is the process being forked; if p1 == &proc0, we are creating + * a kernel thread, and the return path will later be changed in cpu_set_kpc. + * + * If an alternate user-level stack is requested (with non-zero values + * in both the stack and stacksize args), set up the user stack pointer + * accordingly. + */ + +/* + * Note: + * + * p->p_addr points to a page containing the user structure + * (see <sys/user.h>) and the kernel stack. The user structure has to be + * at the start of the area -- we start the kernel stack from the end. + */ + +void +cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize) +{ + struct pcb *pcb; + struct trapframe *tf; + struct switchframe *sf; + char *stacktop; + +#if 0 + printf("cpu_fork: %p -> %p\n", p1, p2); +#endif + pcb = &p2->p_addr->u_pcb; + /* Copy the pcb */ + *pcb = p1->p_addr->u_pcb; + + /* pmap_activate(p2); XXX Other ports do. Why? */ + + /* Set up the kernel stack */ + stacktop = (char *)p2->p_addr + USPACE; + tf = (struct trapframe *)stacktop - 1; + sf = (struct switchframe *)tf - 1; + /* Duplicate old process's trapframe (if it had one) */ + if (p1->p_addr->u_pcb.pcb_tf == NULL) + bzero(tf, sizeof(*tf)); + else + *tf = *p1->p_addr->u_pcb.pcb_tf; + p2->p_addr->u_pcb.pcb_tf = tf; + /* Fabricate a new switchframe */ + bzero(sf, sizeof(*sf)); + sf->sf_r13 = (register_t)tf; /* Initial stack pointer */ + sf->sf_r14 = (register_t)proc_trampoline | R15_MODE_SVC; + + pcb->pcb_tf = tf; + pcb->pcb_sf = sf; + pcb->pcb_onfault = NULL; + cpu_set_kpc(p2, child_return, NULL); +} + +/* + * Change the initial entry point of a process that's been created by + * cpu_fork() but hasn't run yet. It will still start up through + * proc_trampoline, but will call pc instead of child_return(). + */ +void +cpu_set_kpc(struct proc *p, void (*pc)(void *), void *arg) +{ + struct switchframe *sf; + + sf = p->p_addr->u_pcb.pcb_sf; +#ifdef DIAGNOSTIC + if (sf->sf_r14 != ((register_t)proc_trampoline | R15_MODE_SVC)) + panic("cpu_set_kpc"); +#endif + sf->sf_r4 = (register_t)pc; + sf->sf_r5 = (register_t)arg; +} + +/* + * Set up the registers for a newly-execked image. + */ +void +setregs(struct proc *p, struct exec_package *pack, u_long stack) +{ + struct trapframe *tf; + + tf = p->p_addr->u_pcb.pcb_tf; + bzero(tf, sizeof(*tf)); + tf->tf_r0 = (register_t)PS_STRINGS; + tf->tf_r13 = stack; /* sp */ + tf->tf_r15 = pack->ep_entry; +} + +void +cpu_exit(struct proc *p) +{ + + /* Nothing to do here? */ + exit2(p); /* I think this is safe on a uniprocessor machine */ + cpu_switch(p); +} + +/* ARGSUSED */ +void +cpu_wait(struct proc *p) +{ + + /* Nothing left for us to free... */ +} + + +/* + * Send an interrupt to process. + * + * Stack is set up to allow sigcode stored in u. to call routine, + * followed by kcall to sigreturn routine below. After sigreturn + * resets the signal mask, the stack, and the frame pointer, it + * returns to the user specified pc. + */ +void +sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) +{ + struct proc *p = curproc; + struct trapframe *tf; + struct sigframe *fp, frame; + struct sigacts *psp = p->p_sigacts; + int onstack; + + tf = p->p_addr->u_pcb.pcb_tf; + + /* Do we need to jump onto the signal stack? */ + onstack = + (psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && + (psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0; + + /* Allocate space for the signal handler context. */ + if (onstack) + fp = (struct sigframe *)((caddr_t)psp->ps_sigstk.ss_sp + + psp->ps_sigstk.ss_size); + else + fp = (struct sigframe *)tf->tf_r13; + fp--; + + /* Build stack frame for signal trampoline. */ + frame.sf_signum = sig; + frame.sf_code = code; + frame.sf_scp = &fp->sf_sc; + frame.sf_handler = catcher; + + /* Save register context. */ + frame.sf_sc.sc_r0 = tf->tf_r0; + frame.sf_sc.sc_r1 = tf->tf_r1; + frame.sf_sc.sc_r2 = tf->tf_r2; + frame.sf_sc.sc_r3 = tf->tf_r3; + frame.sf_sc.sc_r4 = tf->tf_r4; + frame.sf_sc.sc_r5 = tf->tf_r5; + frame.sf_sc.sc_r6 = tf->tf_r6; + frame.sf_sc.sc_r7 = tf->tf_r7; + frame.sf_sc.sc_r8 = tf->tf_r8; + frame.sf_sc.sc_r9 = tf->tf_r9; + frame.sf_sc.sc_r10 = tf->tf_r10; + frame.sf_sc.sc_r11 = tf->tf_r11; + frame.sf_sc.sc_r12 = tf->tf_r12; + frame.sf_sc.sc_r13 = tf->tf_r13; + frame.sf_sc.sc_r14 = tf->tf_r14; + frame.sf_sc.sc_r15 = tf->tf_r15; + + /* Save signal stack. */ + frame.sf_sc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; + + /* Save signal mask. */ + frame.sf_sc.sc_mask = *mask; + + if (copyout(&frame, fp, sizeof(frame)) != 0) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + sigexit(p, SIGILL); + /* NOTREACHED */ + } + + /* + * Build context to run handler in. + */ + tf->tf_r0 = frame.sf_signum; + tf->tf_r1 = frame.sf_code; + tf->tf_r2 = (int)frame.sf_scp; + tf->tf_r3 = (int)frame.sf_handler; + tf->tf_r13 = (int)fp; + tf->tf_r15 = (int)psp->ps_sigcode; + + /* Remember that we're now on the signal stack. */ + if (onstack) + psp->ps_sigstk.ss_flags |= SS_ONSTACK; +} + +/* + * System call to cleanup state after a signal has been taken. Reset + * signal mask and stack state from context left by sendsig (above). + * Return to previous pc and psl as specified by context left by + * sendsig. Check carefully to make sure that the user has not + * modified the psr to gain improper privileges or to cause a machine + * fault. + */ +int +sys___sigreturn14(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys___sigreturn14_args /* { + syscallarg(struct sigcontext *) sigcntxp; + } */ *uap = v; + struct sigcontext *scp, context; + struct trapframe *tf; + + /* + * The trampoline code hands us the context. + * It is unsafe to keep track of it ourselves, in the event that a + * program jumps out of a signal handler. + */ + scp = SCARG(uap, sigcntxp); + if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) + return EFAULT; + + /* Make sure the processor mode has not been tampered with. */ + if ((context.sc_r15 & R15_MODE) != R15_MODE_USR || + (context.sc_r15 & (R15_IRQ_DISABLE | R15_FIQ_DISABLE)) != 0) + return EINVAL; + + /* Restore register context. */ + tf = p->p_addr->u_pcb.pcb_tf; + tf->tf_r0 = context.sc_r0; + tf->tf_r1 = context.sc_r1; + tf->tf_r2 = context.sc_r2; + tf->tf_r3 = context.sc_r3; + tf->tf_r4 = context.sc_r4; + tf->tf_r5 = context.sc_r5; + tf->tf_r6 = context.sc_r6; + tf->tf_r7 = context.sc_r7; + tf->tf_r8 = context.sc_r8; + tf->tf_r9 = context.sc_r9; + tf->tf_r10 = context.sc_r10; + tf->tf_r11 = context.sc_r11; + tf->tf_r12 = context.sc_r12; + tf->tf_r13 = context.sc_r13; + tf->tf_r14 = context.sc_r14; + tf->tf_r15 = context.sc_r15; + + /* Restore signal stack. */ + if (context.sc_onstack & SS_ONSTACK) + p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; + + /* Restore signal mask. */ + (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0); + + return EJUSTRETURN; +} + +void +cpu_swapin(struct proc *p) +{ + + /* Can anyone think of anything I should do here? */ +} + +void +cpu_swapout(struct proc *p) +{ + + /* ... or here, for that matter. */ +} + diff --git a/sys/arch/arm26/arm26/zeropage.S b/sys/arch/arm26/arm26/zeropage.S new file mode 100644 index 00000000000..5424a96bfd0 --- /dev/null +++ b/sys/arch/arm26/arm26/zeropage.S @@ -0,0 +1,100 @@ +/* $NetBSD: zeropage.S,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ */ +/*- + * Copyright (c) 1999 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * Data to be copied to zero page at runtime. + */ + +#include <machine/asm.h> + +RCSID("$NetBSD: zeropage.S,v 1.1 2000/05/09 21:55:57 bjh21 Exp $") + +/* + * Now, here we could do with the ability to change the assembler's + * idea of where we're assembling to without changing where it puts + * the output. Unfortunately, this kind of thing needs the connivance + * of the linker, which is asking a bit much. Thus... + * + * B and BL can be used normally within zero-page, but not between + * zero-page and the outside world. + * + * LDR can safely be used with a label within zero-page, but not to + * outside. + * + * Absolute references only work to outside. Relative references only + * work to inside. + */ + + .text + .align 0 + +/* + * Instructions to copy to the bottom of zero page + * These are the entry point to the system exception routines + * + * They go: + * Reset + * Undefined instruction + * SWI + * Prefetch abort + * Data abort + * Address exception + * IRQ + * FIQ + */ + + .global _C_LABEL(page0), _C_LABEL(page0_end) +_C_LABEL(page0): + ldr pc, Lreset_target + ldr pc, Lundefined_target + ldr pc, Lswi_target + ldr pc, Lprefetch_abort_target + ldr pc, Ldata_abort_target + ldr pc, Laddress_exception_target + ldr pc, Lirq_target +Lfiqhandler: + .global _C_LABEL(fiqhandler) + .set _C_LABEL(fiqhandler), . - _C_LABEL(page0) + subs pc, lr, #4 + .org Lfiqhandler + 0x100 + +Lreset_target: + .word reset_entry +Lundefined_target: + .word undefined_entry +Lswi_target: + .word swi_entry +Lprefetch_abort_target: + .word prefetch_abort_entry +Ldata_abort_target: + .word data_abort_entry +Laddress_exception_target: + .word address_exception_entry +Lirq_target: + .word irq_entry +_C_LABEL(page0_end): diff --git a/sys/arch/arm26/boot/BBBB,fd1 b/sys/arch/arm26/boot/BBBB,fd1 new file mode 100644 index 00000000000..70115b453a0 --- /dev/null +++ b/sys/arch/arm26/boot/BBBB,fd1 @@ -0,0 +1,448 @@ +REM>BBBB +REM $NetBSD: BBBB,fd1,v 1.1 2000/05/09 21:55:57 bjh21 Exp $ +REM +REM Copyright (c) 1998, 1999, 2000 Ben Harris +REM All rights reserved. +REM +REM Redistribution and use in source and binary forms, with or without +REM modification, are permitted provided that the following conditions +REM are met: +REM 1. Redistributions of source code must retain the above copyright +REM notice, this list of conditions and the following disclaimer. +REM 2. Redistributions in binary form must reproduce the above copyright +REM notice, this list of conditions and the following disclaimer in the +REM documentation and/or other materials provided with the distribution. +REM 3. The name of the author may not be used to endorse or promote products +REM derived from this software without specific prior written permission. +REM +REM THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +REM IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +REM OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +REM IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +REM INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +REM NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +REM DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +REM THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +REM (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +REM THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +REM +REM This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. +REM +REM Ben's BASIC BSD Booter (allegedly) +debug% = 1 +PRINT ">> BBBB, Revision 0.30" +SYS "OS_ReadMemMapInfo" TO nbpp%, npages% +IF debug% THEN + PRINT "Machine has ";npages%;" pages of ";nbpp% DIV 1024;"K each. "; + PRINT "Total RAM: ";npages% * nbpp% DIV 1024 DIV 1024;"Mb" + PRINT "Lowering HIMEM: &";~HIMEM; +ENDIF +HIMEM = &10000 +IF debug% THEN PRINT " -> &";~HIMEM + +twirl% = 0 + +DIM vaddr%(npages%-1), access%(npages%-1), pgok%(npages%-1) +pgok%() = FALSE + +PROCget_mem_map +SYS "OS_GetEnv" TO A$ +IF debug% THEN PRINT A$ +WHILE LEFT$(A$, 1) <> " " AND LEN(A$) > 0 A$ = MID$(A$, 2) : ENDWHILE +WHILE LEFT$(A$, 1) = " " A$ = MID$(A$, 2) : ENDWHILE +WHILE RIGHT$(A$,1) = " " A$ = LEFT$(A$) : ENDWHILE +IF FNtolower(LEFT$(A$, 5)) = "-quit" THEN + A$ = MID$(A$, 7) + WHILE LEFT$(A$, 1) <> " " AND LEN(A$) > 0 A$ = MID$(A$, 2) : ENDWHILE + WHILE LEFT$(A$, 1) = " " A$ = MID$(A$, 2) : ENDWHILE +ENDIF +file$ = "" +howto% = 0 +WHILE LEN(A$) > 0 + CASE LEFT$(A$, 1) OF + WHEN "-" + done% = FALSE + REPEAT + A$ = MID$(A$, 2) + CASE FNtolower(LEFT$(A$, 1)) OF + WHEN "a" : howto% = howto% OR &01 : REM RB_ASKNAME + WHEN "s" : howto% = howto% OR &02 : REM RB_SINGLE + WHEN "d" : howto% = howto% OR &40 : REM RB_KDB + WHEN " ", "" : done% = TRUE + OTHERWISE : ERROR EXT 0, "Bad option: " + LEFT$(A$, 1) + ENDCASE + UNTIL done% + WHEN " " + A$ = MID$(A$, 2) + OTHERWISE + IF file$ <> "" THEN ERROR EXT 0, "Too many files!" + WHILE LEFT$(A$, 1) <> " " AND LEN(A$) > 0 + file$ += LEFT$(A$,1) + A$ = MID$(A$, 2) + ENDWHILE + ENDCASE +ENDWHILE +IF file$ = "" AND (howto% AND &01) THEN + INPUT "boot: "file$ +ELSE + IF file$ = "" THEN file$ = "netbsd" +ENDIF +PRINT "Booting "; file$; " (howto = 0x"; ~howto%; ")" +PROCload_kernel(file$) +DIM P% 1023 +REM +[ OPT 2 + .config% + EQUD &942B7DFE ; magic + EQUD 0 ; version + EQUD howto% ; boothowto + EQUD 0 ; bootdev + EQUD ssym% ; ssym + EQUD esym% ; esym + EQUD nbpp% ; nbpp + EQUD npages% ; npages + EQUD txtbase% ; txtbase + EQUD txtsize% ; txtsize + EQUD database% ; database + EQUD datasize% ; datasize + EQUD bssbase% ; bssbase + EQUD bsssize% ; bsssize + EQUD freebase% ; freebase + EQUD FNvdu_var(11) + 1 ; xpixels + EQUD FNvdu_var(12) + 1 ; ypixels + EQUD 1 << FNvdu_var(9) ; bpp + EQUD FNvdu_var(149) + FNvdu_var(150) - &02000000 ; screenbase (XXX?) + EQUD FNvdu_var(150) ; screensize +] +SYS "OS_Byte", 165 TO ,,crow% +[ OPT 2 + EQUD crow% * FNvdu_var(170) ; cpixelrow +] +REM }; +PROCstart_kernel(config%, 0, 0, 0, entry%) +END + +DEF PROCget_mem_map + LOCAL block% + DIM block% (npages%+1)*12 + FOR page%=0 TO npages%-1 + block%!(page%*12) = page% + NEXT + block%!(npages%*12) = -1 + SYS "OS_ReadMemMapEntries", block% + FOR page% = 0 TO npages%-1 + vaddr%(page%) = block%!(page%*12+4) + access%(page%) = block%!(page%*12+8) + NEXT + IF debug% THEN PRINT "--------/-------/-------/-------" + FOR page%=0 TO npages%-1 + IF access%(page%) = 3 THEN + IF debug% THEN PRINT "."; + ELSE + CASE TRUE OF + WHEN vaddr%(page%) < &0008000: IF debug% THEN PRINT "0"; + WHEN vaddr%(page%) < &0010000: IF debug% THEN PRINT "+"; + WHEN vaddr%(page%) < &1000000: + IF access%(page%) = 0 THEN + IF debug% THEN PRINT "*"; + pgok%(page%) = TRUE + ELSE + IF debug% THEN PRINT "a"; + ENDIF + WHEN vaddr%(page%) < &1400000: IF debug% THEN PRINT "d"; + WHEN vaddr%(page%) < &1800000: IF debug% THEN PRINT "s"; + WHEN vaddr%(page%) < &1C00000: IF debug% THEN PRINT "m"; + WHEN vaddr%(page%) < &1E00000: IF debug% THEN PRINT "h"; + WHEN vaddr%(page%) < &1F00000: IF debug% THEN PRINT "f"; + WHEN vaddr%(page%) < &2000000: IF debug% THEN PRINT "S"; + ENDCASE + ENDIF + IF page% MOD 32 = 31 AND debug% THEN PRINT + NEXT +ENDPROC + +DEF PROCload_kernel(file$) + LOCAL file%, magic% + file% = OPENIN(file$) + IF file% = 0 THEN ERROR 1, "Can't open kernel" + DIM magic% 3 + SYS "OS_GBPB", 3, file%, magic%, 4, 0 + IF magic%?0 = 127 AND magic%?1 = ASC("E") AND magic%?2 = ASC("L") AND magic%?3 = ASC("F") THEN + PROCload_kernel_elf(file%) + ELSE + PROCload_kernel_aout(file%) + ENDIF + CLOSE#file% +ENDPROC + +DEF PROCload_kernel_elf(file%) + LOCAL hdr%, phoff%, phentsize%, phnum%, phdrs%, ph% + LOCAL offset%, vaddr%, filesz%, memsz%, flags%, first% + LOCAL shoff%, shentsize%, shnum%, shdrs%, sh%, havesyms%, mshdrs% + DIM hdr% 51 + SYS "OS_GBPB", 3, file%, hdr%, 52, 0 + IF hdr%?4 <> 1 THEN ERROR 1, "Not a 32-bit ELF file" + IF hdr%?5 <> 1 THEN ERROR 1, "Not an LSB ELF file" + IF hdr%?6 <> 1 THEN ERROR 1, "Not a version-1 ELF file" + REM hdr%?7 is EI_OSABI. Should it be 255 (ELFOSABI_STANDALONE)? + IF (hdr%!16 AND &FFFF) <> 2 THEN ERROR 1, "Not an executable ELF file" + IF (hdr%!18 AND &FFFF) <> 40 THEN ERROR 1, "Not an ARM ELF file" + entry% = hdr%!24 + phoff% = hdr%!28 + shoff% = hdr%!32 + phentsize% = hdr%!42 AND &FFFF + phnum% = hdr%!44 AND &FFFF + shentsize% = hdr%!46 AND &FFFF + shnum% = hdr%!48 AND &FFFF + DIM phdrs% phnum% * phentsize% - 1 + SYS "OS_GBPB", 3, file%, phdrs%, phnum% * phentsize%, phoff% + IF phnum% = 0 THEN ERROR 1, "No program headers" + first% = TRUE + FOR ph% = phdrs% TO phdrs% + (phnum% - 1) * phentsize% STEP phentsize% + IF ph%!0 <> 1 THEN NEXT : REM We only do PT_LOAD + IF NOT first% THEN PRINT "+"; + first% = FALSE + offset% = ph%!4 + vaddr% = ph%!8 + filesz% = ph%!16 + memsz% = ph%!20 + flags% = ph%!24 + PROCload_chunk(file%, offset%, vaddr%, filesz%, memsz%) + freebase% = vaddr% - &02000000 + memsz% : REM XXX + NEXT + txtbase% = 0 + txtsize% = 0 + database% = 0 + datasize% = 0 + bssbase% = 0 + bsssize% = 0 + ssym% = 0 + esym% = 0 + DIM shdrs% shnum% * shentsize% - 1 + SYS "OS_GBPB", 3, file%, shdrs%, shnum% * shentsize%, shoff% + IF shnum% <> 0 THEN + havesyms% = FALSE + FOR sh% = shdrs% TO shdrs% + (shnum% - 1) * shentsize% STEP shentsize% + IF sh%!4 = 2 THEN havesyms% = TRUE + NEXT + IF havesyms% THEN + ssym% = freebase% + REM First, we have the munged ELF header + PRINT "+["; + PROCload_chunk(file%, 0, &02000000 + ssym%, 52, 52) + PROCwrite_word(ssym%+32, 52) + freebase% += 52 + REM then, the munged section headers + mshdrs% = freebase% + PRINT "+"; + PROCload_chunk(file%, shoff%, &02000000 + mshdrs%, shnum% * shentsize%, shnum% * shentsize%) + freebase% += shnum% * shentsize% + FOR sh% = shdrs% TO shdrs% + (shnum% - 1) * shentsize% STEP shentsize% + IF sh%!4 = 2 OR sh%!4 = 3 THEN + PRINT "+"; + PROCload_chunk(file%, sh%!16, &02000000 + freebase%, sh%!20, sh%!20) + PROCwrite_word(mshdrs% + sh% - shdrs% + 16, freebase% - ssym%) + freebase% += FNroundup(sh%!20, 4) + ENDIF + NEXT + esym% = freebase% + PRINT "]"; + ENDIF + ENDIF + PRINT " " + REM XXX +ENDPROC + +DEF PROCload_chunk(file%, offset%, vaddr%, filesz%, memsz%) + LOCAL paddr%, ppn%, fragaddr%, fragsz% + PRINT ;filesz%; + WHILE filesz% > 0 + paddr% = vaddr% - &02000000 + ppn% = paddr% DIV nbpp% + IF NOT pgok%(ppn%) THEN ERROR 1, "Page " + STR$(ppn$) + " not free" + fragaddr% = vaddr%(ppn%) + paddr% MOD nbpp% + fragsz% = nbpp% - (paddr% MOD nbpp%) + IF fragsz% > filesz% THEN fragsz% = filesz% + SYS "OS_GBPB", 3, file%, fragaddr%, fragsz%, offset% + PROCtwirl + offset% += fragsz% + vaddr% += fragsz% + filesz% -= fragsz% + memsz% -= fragsz% + ENDWHILE + IF memsz% > 0 PRINT "+";memsz%; + WHILE memsz% > 0 + paddr% = vaddr% - &02000000 + ppn% = paddr% DIV nbpp% + IF NOT pgok%(ppn%) THEN ERROR 1, "Page " + STR$(ppn$) + " not free" + fragaddr% = vaddr%(ppn%) + paddr% MOD nbpp% + fragsz = nbpp% - (paddr% MOD nbpp%) + IF fragsz% > memsz% THEN fragsz% = memsz% + PROCbzero(fragaddr%, fragsz%) + PROCtwirl + offset% += fragsz% + vaddr% += fragsz% + filesz% -= fragsz% + memsz% -= fragsz% + ENDWHILE +ENDPROC + +DEF PROCwrite_word(paddr%, val%) + !(vaddr%(paddr% DIV nbpp%) + paddr% MOD nbpp%) = val% +ENDPROC + +DEF PROCload_kernel_aout(file%) + LOCAL hdr% + DIM hdr% 32 + ssym% = 0 : esym% = 0 + SYS "OS_GBPB", 3, file%, hdr%, 32, 0 + bemagic% = (hdr%?0 << 24) OR (hdr%?1 <<16) OR (hdr%?2 << 8) OR hdr%?3 + IF debug% THEN + CASE bemagic% AND &0000FFFF OF + WHEN &0107 + PRINT "(OMAGIC)"; + WHEN &0108 + PRINT "(NMAGIC)"; + WHEN &010B + PRINT "(ZMAGIC)"; + WHEN &00CC + PRINT "(QMAGIC)"; + ENDCASE + ENDIF + REM XXX: Assume ZMAGIC + + REM foooff% is byte offset in file. foobasepage% is base page in RAM. + txtoff% = nbpp% + txtbase% = &98000 + txtbasepage% = txtbase% DIV nbpp% + txtsize% = hdr%!4 + IF txtsize% MOD nbpp% <> 0 THEN + ERROR EXT 1, "Text size not a multiple of page size" + ENDIF + txtpages% = txtsize% DIV nbpp% + dataoff% = txtoff% + txtsize% + databasepage% = txtbasepage% + txtpages% + database% = databasepage% * nbpp% + datasize% = hdr%!8 + IF datasize% MOD nbpp% <> 0 THEN + ERROR EXT 1, "Data size not a multiple of page size" + ENDIF + datapages% = datasize% DIV nbpp% + bssbasepage% = databasepage% + datapages% + bssbase% = bssbasepage% * nbpp% + bsssize% = hdr%!12 + freebase% = bssbase% + bsssize% + entry% = hdr%!20 + + PRINT ;txtsize%; + FOR pg% = 0 TO txtpages%-1 + IF NOT pgok%(txtbasepage% + pg%) THEN ERROR 0,"Page not mine!" + SYS "OS_GBPB", 3, file%, vaddr%(txtbasepage%+pg%), nbpp%, txtoff% + pg%*nbpp% + PROCtwirl + NEXT + + PRINT "+";datasize%; + FOR pg% = 0 TO datapages%-1 + IF NOT pgok%(databasepage% + pg%) THEN ERROR 0,"Page not mine!" + SYS "OS_GBPB", 3, file%, vaddr%(databasepage%+pg%), nbpp%, dataoff% + pg%*nbpp% + PROCtwirl + NEXT + + PRINT "+";bsssize%; + FOR pg% = 0 TO bsssize% DIV nbpp% : REM overshoot is safe + IF NOT pgok%(bssbasepage% + pg%) THEN ERROR 0,"Page not mine!" + PROCbzero(vaddr%(bssbasepage%+pg%), nbpp%) + PROCtwirl + NEXT + + PRINT " " + +ENDPROC + +DEF PROCtwirl + PRINT MID$("|/-\", twirl%+1, 1)+CHR$(8); + twirl% += 1 + twirl% = twirl% MOD 4 +ENDPROC + +DEF FNtolower(string$) + LOCAL ptr%, c%, out$ + out$ = "" + IF string$ = "" THEN =string$ + FOR ptr% = 1 TO LEN(string$) + c% = ASC(MID$(string$, ptr%, 1)) + IF c% >= ASC("A") AND c% <= ASC("Z") THEN c% += 32 + out$ += CHR$(c%) + NEXT +=out$ + +DEF PROCbzero(addr%, len%) + LOCAL a% + FOR a% = 0 TO len%-4 STEP 4 + addr%!a% = 0 + NEXT +ENDPROC + +DEF PROCstart_kernel(A%, B%, C%, D%, E%) + REM parameters: + REM R0: -> bootconfig structure + REM R1: unused + REM R2: unused + REM R3: unused + REM R4: kernel entry point + LOCAL asm%, P% + DIM asm% 256 + FOR pass% = 0 TO 2 STEP 2 + P%=asm% + [ OPT pass% + STMFD R13!,{R14} + STMFD R13!,{R0-R4} + ] + IF FNswi_valid("Cache_Control") THEN + [ OPT pass% + MOV R0, 1 + MVN R1, 1 ; Disable cache + SWI "Cache_Control" + SWI "Cache_Flush" + ] + ENDIF + [ OPT pass% + MOV R0, #1 + SWI "Sound_Enable" + SWI "OS_IntOff" + LDMFD R13!, {R0-R4} + SWI "OS_EnterOS" + ; We now attempt to be APCS compliant on entry to the kernel. + ; Kernel APCS is 26bit/explicit/nofpregs/non-reentrant + ; Kernel stack is &02090000--&02088000 and coincides with RISC OS's + ; system stack page on >=4Mb machines. + ADR R5, regs% + LDMIA R5, {R10-R14} + MOV PC, R4 + .regs% + EQUD &02088000; R10 -- Stack limit + EQUD &00000000; R11 -- Frame pointer (NULL in this case) + EQUD &00000000; R12 -- Scratch in non-re-entrant APCS + EQUD &02090000; R13 -- Stack pointer + EQUD &03800003; R14 -- Return address and mode + ] + NEXT + CALL asm% +ENDPROC + +DEF FNswi_valid(swi$) + LOCAL flags% + SYS "XOS_SWINumberFromString",,swi$ TO ;flags% + IF flags% AND 1 THEN =FALSE +=TRUE + +DEF FNvdu_var(var%) + LOCAL b% + DIM b% 7 + b%!0 = var% + b%!4 = -1 + SYS "OS_ReadVduVariables", b%, b% += b%!0 + +DEF FNroundup(val%, size%) +=val% + (size% - 1) AND NOT (size% - 1) diff --git a/sys/arch/arm26/compile/.keep_me b/sys/arch/arm26/compile/.keep_me new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/sys/arch/arm26/compile/.keep_me diff --git a/sys/arch/arm26/conf/GENERIC b/sys/arch/arm26/conf/GENERIC new file mode 100644 index 00000000000..451c46bc328 --- /dev/null +++ b/sys/arch/arm26/conf/GENERIC @@ -0,0 +1,178 @@ +# $NetBSD: GENERIC,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ + +# GENERIC arm26 configuration -- everything I've implemented so far + +include "arch/arm26/conf/std.arm26" + +maxusers 8 + +# CPU support +options CPU_ARM2 +options CPU_ARM250 +options CPU_ARM3 + +# Diagnostic/debugging support options +options DIAGNOSTIC # Cheap kernel consistency checks +options DEBUG # More expensive checks and printfs +options DDB # kernel debugger +#options SYSCALL_DEBUG # trace syscall entry/exit +options SCSIDEBUG + +## Compile the kernel with debugging symbols (`netbsd.gdb' is the debug file), +## such that gdb(1) can be used on a kernel coredump. +#makeoptions DEBUG="-g" + +# File systems +file-system FFS # Fast file system +#file-system LFS # log-structured file system +#file-system MFS # Memory-based file system +#file-system EXT2FS # second extended file system (linux) +#file-system CD9660 # ISO-9660 CD-ROM FS (w/RockRidge extensions) +file-system FILECORE # Acorn filecore file system +#file-system ADOSFS # AmigaDOS-compatible file system +#file-system MSDOSFS # MS-DOS-compatible file system +#file-system NTFS # Windows/NT file system (experimental) +file-system NFS # Sun NFS-compatible file system client +#file-system NULLFS # loopback file system +#file-system OVERLAY # overlay filesystem +#file-system PORTAL # portal filesystem (still experimental) +#file-system UMAPFS # NULLFS + uid and gid remapping +#file-system UNION # union file system +file-system PROCFS # /proc +file-system KERNFS # /kern +file-system FDESC # /dev/fd + +# File system options +#options QUOTA # UFS quotas +#options NFSSERVER # Sun NFS-compatible file system server +#options FFS_EI # FFS endianness-independence support +#options SOFTDEP # FFS soft updates support. + +# Pull in config fragments for kernel crypto. This is required for +# options IPSEC etc. to work. If you want to run with IPSEC, uncomment +# one of these, based on whether you use crypto-us or crypto-intl, and +# adjust the prefixes as necessary. + +#prefix ../crypto-us/sys +#cinclude "conf/files.crypto-us" +#prefix + +#prefix ../crypto-intl/sys +#cinclude "conf/files.crypto-intl" +#prefix + +# Executable format options +#options EXEC_AOUT +options EXEC_ELF32 +options EXEC_SCRIPT + +# Networking options +options GATEWAY # packet forwarding +options INET # Internet protocol suite +#options INET6 # IPV6 +#options IPSEC # IP security +#options IPSEC_ESP # IP security (encryption part; define w/IPSEC) +#options IPSEC_DEBUG # debug for IP security +#options MROUTING # IP multicast routing +#options NS # XNS +#options NSIP # XNS tunneling over IP +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options CCITT,LLC,HDLC # X.25 +#options NETATALK # AppleTalk networking +#options PFIL_HOOKS # pfil(9) packet filter hooks +#options PPP_BSDCOMP # BSD-Compress compression support for PPP +#options PPP_DEFLATE # Deflate compression support for PPP +#options PPP_FILTER # Active filter support for PPP (requires bpf) +#options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD + +# 4.3BSD compatibility. +#options COMPAT_43 + +# Binary compatibility with previous versions of NetBSD. +# None yet, since NetBSD/arm26 hasn't been released. + +# System V IPC +#options SYSVMSG # System V-like message queues +#options SYSVSEM # System V-like semaphores +#options SYSVSHM # System V-like shared memory +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Miscellaneous kernel options +options KTRACE # system call tracing, a la ktrace(1) +#options IRQSTATS # manage IRQ statistics +#options LKM # loadable kernel modules +#options KMEMSTATS # kernel memory statistics +#options SCSIVERBOSE # Verbose SCSI errors + +# Disable kernel security. +#options INSECURE + +# NFS boot options +options NFS_BOOT_DHCP # superset of BOOTP +options NFS_BOOT_BOOTPARAM + +# WS console uses DUMB, SUN or VT100 terminal emulation +#options WSEMUL_NODUMB +#options WSEMUL_SUN +options WSEMUL_VT100 +options FONT_VT220L8x8 # 8x8 font for console + +config netbsd root on ? type ? +#config netbsd root on sd0 type ffs +#config netbsd root on ? type nfs + +cpu0 at root + +iobus0 at root # 16-bit I/O bus + +ioc0 at iobus0 base 0x200000 # I/O controller + +iic0 at ioc0 # I^2C serial bus +rtc0 at iic0 addr 0xa0 # Real-time clock + +arckbd0 at ioc0 bank 0 offset 0x04 # System keyboard +arcwskbd0 at arckbd0 # Logical devices... +wskbd0 at arcwskbd0 +arcwsmouse0 at arckbd0 +wsmouse0 at arcwsmouse0 + +ioeb0 at ioc0 bank 5 # I/O Extension Block (A5000) + +podulebus0 at ioc0 bank 4 # Expansion card bus +unixbp0 at ioc0 bank 6 # Unix Backplane (interrupt routing) + +ei* at podulebus0 slot ? # Acorn AKA25 (Ether1) +ea* at podulebus0 slot ? # Acorn/Atomwide Ether3 + +dtide* at podulebus0 slot ? # D.T. Software IDE interface +wd* at dtide? channel ? drive ? + +#asc* at podulebus0 slot ? # Acorn SCSI card (AKA30, AKA31) +#scsibus* at asc? + +arcvideo0 at root # On-board video +wsdisplay0 at arcvideo0 + +pseudo-device bpfilter 16 +#pseudo-device ccd 4 +#pseudo-device raid 4 # RAIDframe disk driver +#options RAID_AUTOCONFIG # auto-configuration of RAID components +#pseudo-device ipfilter 1 +pseudo-device loop 1 +pseudo-device md 1 +#options MEMORY_DISK_HOOKS +#options MINIROOTSIZE= +#pseudo-device ppp 4 +pseudo-device pty 64 +#pseudo-device sl 4 +#pseudo-device vnd 4 +#pseudo-device gre 2 # generic L3 over IP tunnel +#pseudo-device gif 4 # IPv[46] over IPv[46] tunnel (RFC1933) +#pseudo-device faith 1 # IPv[46] tcp relay translation i/f +#pseudo-device sequencer 1 # MIDI sequencer +#pseudo-device wsmux 2 # keyboard/mouse multiplexor + +# rnd is EXPERIMENTAL +#pseudo-device rnd # /dev/random and in-kernel generator + diff --git a/sys/arch/arm26/conf/Makefile.arm26 b/sys/arch/arm26/conf/Makefile.arm26 new file mode 100644 index 00000000000..69cf8a0ec63 --- /dev/null +++ b/sys/arch/arm26/conf/Makefile.arm26 @@ -0,0 +1,190 @@ +# $NetBSD: Makefile.arm26,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ + +# Makefile for NetBSD/arm26 +# +# This makefile is constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/arch/arm26/conf/``machineid'' +# after which you should do +# config machineid +# Machine generic makefile changes should be made in +# /sys/arch/arm26/conf/Makefile.arm26 +# after which config should be rerun for all machines of that type. +# +# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE +# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING +# +# -DTRACE compile in kernel tracing hooks +# -DQUOTA compile in file system quotas + +# DEBUG is set to -g if debugging. +# PROF is set to -pg if profiling. + +MACHINE=arm26 +MACHINE_ARCH=arm26 + +AR?= ar +AS?= as +CC?= gcc +CPP?= gcc -E +LD?= ld +LORDER?= lorder +MKDEP?= mkdep +NM?= nm +RANLIB?=ranlib +SIZE?= size +STRIP?= strip +TSORT?= tsort -q + +COPTS?= -O2 + +# source tree is located via $S relative to the compilation directory +.ifndef S +S!= cd ../../../..; pwd +.endif +ARM26= $S/arch/arm26 + +INCLUDES= -I. -I$S/arch -I$S -nostdinc +CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Darm26 -Wcomment +CWARNFLAGS= -Wall -Wstrict-prototypes -Wmissing-prototypes +CFLAGS= -mcpu=arm2 -ffixed-r14 ${DEBUG} ${COPTS} ${CWARNFLAGS} +AFLAGS= -x assembler-with-cpp -D_LOCORE + +LINKFLAGS= -Ttext 02098000 -e start +STRIPFLAGS= -d + +# Re-arrange for cross-compiling +HOSTED_CC= cc +HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//} +HOSTED_CFLAGS= ${CFLAGS} + +### find out what to use for libkern +.include "$S/lib/libkern/Makefile.inc" +.ifndef PROF +LIBKERN= ${KERNLIB} +.else +LIBKERN= ${KERNLIB_PROF} +.endif + +### find out what to use for libcompat +.include "$S/compat/common/Makefile.inc" +.ifndef PROF +LIBCOMPAT= ${COMPATLIB} +.else +LIBCOMPAT= ${COMPATLIB_PROF} +.endif + +# compile rules: rules are named ${TYPE}_${SUFFIX} where TYPE is NORMAL or +# HOSTED}, and SUFFIX is the file suffix, capitalized (e.g. C for a .c file). + +NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< +NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< + +HOSTED_C= ${HOSTED_CC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $< + +%OBJS + +%CFILES + +%SFILES + +# load lines for config "xxx" will be emitted as: +# xxx: ${SYSTEM_DEP} swapxxx.o +# ${SYSTEM_LD_HEAD} +# ${SYSTEM_LD} swapxxx.o +# ${SYSTEM_LD_TAIL} +SYSTEM_OBJ= locore.o \ + param.o ioconf.o ${OBJS} ${LIBKERN} ${LIBCOMPAT} +SYSTEM_DEP= Makefile ${SYSTEM_OBJ} +SYSTEM_LD_HEAD= rm -f $@ +SYSTEM_LD= @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_OBJ}' vers.o; \ + ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_OBJ} vers.o +SYSTEM_LD_TAIL= @${SIZE} $@; chmod 755 $@ + +DEBUG?= +.if ${DEBUG} == "-g" +LINKFLAGS+= -X +SYSTEM_LD_TAIL+=; \ + echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \ + echo ${STRIP} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@ +.else +#LINKFLAGS+= -S +LINKFLAGS+= -x +.endif + +%LOAD + +assym.h: $S/kern/genassym.sh ${ARM26}/arm26/genassym.cf + sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} \ + < ${ARM26}/arm26/genassym.cf > assym.h.tmp && \ + mv -f assym.h.tmp assym.h + +param.c: $S/conf/param.c + rm -f param.c + cp $S/conf/param.c . + +param.o: param.c Makefile + ${NORMAL_C} + +ioconf.o: ioconf.c + ${NORMAL_C} + +newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} + sh $S/conf/newvers.sh + ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c + +__CLEANKERNEL: .USE + @echo "${.TARGET}ing the kernel objects" + rm -f eddep *netbsd netbsd.gdb tags *.[io] [a-z]*.s \ + [Ee]rrs linterrs makelinks assym.h.tmp assym.h + +__CLEANDEPEND: .USE + rm -f .depend + +clean: __CLEANKERNEL + +cleandir: __CLEANKERNEL __CLEANDEPEND + +lint: + @lint -hbxncez -Dvolatile= ${CPPFLAGS} -UKGDB \ + ${CFILES} ioconf.c param.c | \ + grep -v 'static function .* unused' + +tags: + @echo "see $S/kern/Makefile for tags" + +links: + egrep '#if' ${CFILES} | sed -f $S/conf/defines | \ + sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink + echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ + sort -u | comm -23 - dontlink | \ + sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks + sh makelinks && rm -f dontlink + +SRCS= ${ARM26}/arm26/locore.S \ + param.c ioconf.c ${CFILES} ${SFILES} +depend: .depend +.depend: ${SRCS} assym.h + ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${ARM26}/arm26/locore.S + ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} + ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES} +# ${MKDEP} -a ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} ${ARM26}/arm26/genassym.c + +# depend on root or device configuration +autoconf.o conf.o: Makefile + +# depend on network or filesystem configuration +uipc_proto.o vfs_conf.o: Makefile + +# depend on maxusers +genassym.o machdep.o: Makefile + +# depend on CPU configuration +cpufunc.o cpufunc_asm.o cpuswitch.o fault.o machdep.o: Makefile + + +locore.o: ${ARM26}/arm26/locore.S assym.h + ${NORMAL_S} + +%RULES diff --git a/sys/arch/arm26/conf/files.arm26 b/sys/arch/arm26/conf/files.arm26 new file mode 100644 index 00000000000..b230c4012b5 --- /dev/null +++ b/sys/arch/arm26/conf/files.arm26 @@ -0,0 +1,236 @@ +# $NetBSD: files.arm26,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ + +# Copyright (c) 1997, 1998, 2000 Ben Harris +# 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. 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. + +# This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. + +maxpartitions 8 +maxusers 2 8 64 + +include "dev/wscons/files.wscons" +include "dev/rasops/files.rasops" +include "dev/wsfont/files.wsfont" + +include "dev/ata/files.ata" +major { wd = 4 } +include "dev/scsipi/files.scsipi" +major {sd = 5} +major {cd = 6} + +# CPU +device cpu +attach cpu at root +defopt opt_cputypes.h CPU_ARM2 CPU_ARM250 CPU_ARM3 +file arch/arm26/arm26/cpu.c cpu + +# I/O bus (on the far side of the address and data latches) +device iobus { base = -1 } +attach iobus at root +file arch/arm26/iobus/iobus.c iobus + +# 82C710/1 on A5000 etc will be at iobus0 base 0x00010000 (and 0x00012000???) + +# I/O controller (Albion) (usually at iobus0 base 0x00200000) +device ioc { [bank = -1], [offset = 0] } +attach ioc at iobus +file arch/arm26/iobus/ioc.c ioc needs-flag + +# I^2C bus (bit-banged through IOC control register) +device iic { addr = -1 } +attach iic at ioc +file arch/arm26/ioc/iic.c iic + +# PCF8583 I^2C Clock/calendar/RAM +device rtc +attach rtc at iic +file arch/arm26/ioc/rtc.c rtc +file dev/clock_subr.c rtc + +# I/O Extension Block (usually at ioc0 bank 5) +device ioeb { [offset = -1] } +attach ioeb at ioc +file arch/arm26/ioc/ioeb.c ioeb needs-flag + +# A3010 joysticks +device joy +attach joy at ioeb + +# Latches (random internal use) (usually at bank 5 offset 0x18 and 0x40) +device latch +attach latch at ioc + +# On-board keyboard interface +device arckbd { } +attach arckbd at ioc +device arcwskbd: wskbddev +attach arcwskbd at arckbd +device arcwsmouse: wsmousedev +attach arcwsmouse at arckbd +file arch/arm26/ioc/arckbd.c arckbd needs-flag +file arch/arm26/ioc/arckbdmap.c arckbd + +# On-board WD 1772 floppy controller (usually at bank 1 irq 12 fiq 0/1) +# Not to be confused with fdc, which will be the PC-style one on A5k etc. +device wfdc {drive = -1} +attach wfdc at ioc +device wf: disk +attach wf at wfdc +# Steal code from arch/atari/dev/fd{.c,reg.h} +#major {...} + +# Econet module (Motorola 6854) (usually at bank 2 fiq 2) +device ec: ifnet, arp +attach ec at ioc + +# On-board Rockwell 6551 serial (usually at bank 3 irq 10/1) +device rs: tty +attach rs at ioc +file arch/arm26/arm26/rscons.c rs needs-flag + +# Podule interface (podules listed later) (usually at bank 4 irq 13 fiq 6) +# Unix backplanes also use bank 6 +# MEMC podules also use the iobus directly +# XXX How on Earth do we codify all that? +device unixbp +attach unixbp at ioc +device podulebus { [slot = -1] } +attach podulebus at ioc +file arch/arm26/podulebus/podulebus.c podulebus +file arch/arm26/podulebus/unixbp.c unixbp needs-flag + +# Acorn ST506 interface (usually at bank 5 irq 11, or sometimes on a podule) +device hdc { drive = -1 } +attach hdc at ioc with hdc_ioc +attach hdc at podulebus with hdc_podulebus +device hd: disk +attach hd at hdc +#major {hd = ?} + +# On-board printer port (usually at bank 5 addr 0x10 irq 0/2) +device arclpt +attach arclpt at ioc + +# VIDC/MEMC audio/video subsystems. +# XXX: should be rasops4 as well +device arcvideo: rasops1, rasops2, rasops8, wsemuldisplaydev +attach arcvideo at root +file arch/arm26/vidc/arcvideo.c arcvideo needs-flag + +device arcaudio: audio +attach arcaudio at root + +# 82C7xx Universal Peripheral Controller +device upc { [offset = -1] } +attach upc at iobus + +attach wdc at upc with wdc_upc +device lpt +attach lpt at upc with lpt_upc +attach com at upc with com_upc + +device fdc { drive } +attach fdc at upc with fdc_upc +device fd: disk +attach fd at fdc + +### +# Assorted podules +# + +# Acorn Ether1 +device ei: ether, ifnet, arp, i82586 +attach ei at podulebus +file arch/arm26/podulebus/if_ei.c ei + +# Acorn/Atomwide Ether3 +device ea: ether, ifnet, arp +attach ea at podulebus +file arch/arm26/podulebus/if_ea.c ea + +# D.T. software IDE +device dtide {[channel = -1]}: wdc_base, ata, atapi +attach dtide at podulebus +file arch/arm26/podulebus/dtide.c dtide + +# Generic sbic (WD3393) driver +define sbic +file arch/arm26/podulebus/sbic.c sbic + +# Acorn SCSI I specific layer for sbic +device asc: scsi, sbic +attach asc at podulebus +file arch/arm26/podulebus/asc.c asc needs-flag + + +# Memory disk for installation (or ROM versions?) +file arch/arm26/arm26/md_root.c memory_disk_hooks +major { md = 1 } + +#### +# Other files +# + +file dev/cons.c +file dev/cninit.c + +file arch/arm32/arm32/in_cksum_arm32.c inet +file netinet/in4_cksum.c inet +file netns/ns_cksum.c ns + +file arch/arm26/arm26/db_disasm.c ddb +file arch/arm26/arm26/db_interface.c ddb +file arch/arm26/arm26/db_machdep.c ddb +file arch/arm26/arm26/db_trace.c ddb + +file arch/arm26/arm26/disksubr.c disk +file arch/arm26/arm26/disksubr_mbr.c disk +file arch/arm26/arm26/disksubr_acorn.c disk + +file arch/arm26/arm26/aout_machdep.c exec_aout + +file arch/arm26/arm26/start.c +file arch/arm26/arm26/autoconf.c +file arch/arm26/arm26/bus.c +file arch/arm26/arm26/conf.c +file arch/arm26/arm26/cons_machdep.c +file arch/arm26/arm26/copyinout.S +file arch/arm26/arm26/copyinoutstr.c +#file arch/arm26/arm26/copystr.S +file arch/arm26/arm26/except.c +file arch/arm26/arm26/irq.c +file arch/arm26/arm26/intrnames.S +file arch/arm26/arm26/Locore.c +file arch/arm26/arm26/machdep.c +file arch/arm26/arm26/mem.c +file arch/arm26/arm26/pmap.c +#file arch/arm26/arm26/rscons.c +#file arch/arm26/arm26/spl_machdep.c +file arch/arm26/arm26/softintr.c +file arch/arm26/arm26/stubs.c +file arch/arm26/arm26/vm_machdep.c +file arch/arm26/arm26/zeropage.S +file arch/arm32/arm32/disassem.c + diff --git a/sys/arch/arm26/conf/std.arm26 b/sys/arch/arm26/conf/std.arm26 new file mode 100644 index 00000000000..881bf59e792 --- /dev/null +++ b/sys/arch/arm26/conf/std.arm26 @@ -0,0 +1,6 @@ +# $NetBSD: std.arm26,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ + +# Standard NetBSD/arm26 options + +machine arm26 + diff --git a/sys/arch/arm26/include/Makefile b/sys/arch/arm26/include/Makefile new file mode 100644 index 00000000000..aad8a8ff38e --- /dev/null +++ b/sys/arch/arm26/include/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ + +KDIR= /sys/arch/arm26/include +INCSDIR= /usr/include/arm26 + +INCS= ansi.h aout_machdep.h armreg.h asm.h boot.h bswap.h bus.h cdefs.h \ + cpu.h db_machdep.h disklabel.h \ + disklabel_acorn.h elf_machdep.h endian.h endian_machdep.h float.h \ + fp.h frame.h ieee.h ieeefp.h intr.h ipkdb.h irq.h \ + limits.h lock.h math.h \ + param.h pcb.h pmap.h proc.h profile.h ptrace.h reg.h \ + setjmp.h signal.h spl.h stdarg.h trap.h types.h undefined.h \ + varargs.h vmparam.h + +.include <bsd.kinc.mk> diff --git a/sys/arch/arm26/include/ansi.h b/sys/arch/arm26/include/ansi.h new file mode 100644 index 00000000000..2e90eff8cc4 --- /dev/null +++ b/sys/arch/arm26/include/ansi.h @@ -0,0 +1,81 @@ +/* $NetBSD: ansi.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */ + +/* + * Copyright (c) 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _ANSI_H_ +#define _ANSI_H_ + +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _BSD_SIZE_T_ + * typedef _BSD_SIZE_T_ size_t; + * #undef _BSD_SIZE_T_ + * #endif + */ +#define _BSD_CLOCK_T_ unsigned long /* clock() */ +#define _BSD_PTRDIFF_T_ int /* ptr1 - ptr2 */ +#define _BSD_SIZE_T_ unsigned int /* sizeof() */ +#define _BSD_SSIZE_T_ int /* byte count or error */ +#define _BSD_TIME_T_ long /* time() */ +#define _BSD_VA_LIST_ char * /* va_list */ +#define _BSD_CLOCKID_T_ int /* clockid_t */ +#define _BSD_TIMER_T_ int /* timer_t */ +#define _BSD_SUSECONDS_T_ int /* suseconds_t */ +#define _BSD_USECONDS_T_ unsigned int /* useconds_t */ +#define _BSD_INTPTR_T_ int /* intptr_t */ +#define _BSD_UINTPTR_T_ unsigned int /* uintptr_t */ + +/* + * Runes (wchar_t) is declared to be an ``int'' instead of the more natural + * ``unsigned long'' or ``long''. Two things are happening here. It is not + * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, + * it looks like 10646 will be a 31 bit standard. This means that if your + * ints cannot hold 32 bits, you will be in trouble. The reason an int was + * chosen over a long is that the is*() and to*() routines take ints (says + * ANSI C), but they use _RUNE_T_ instead of int. By changing it here, you + * lose a bit of ANSI conformance, but your programs will still work. + * + * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type. When wchar_t + * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains + * defined for ctype.h. + */ +#define _BSD_WCHAR_T_ int /* wchar_t */ +#define _BSD_WINT_T_ int /* wint_t */ +#define _BSD_RUNE_T_ int /* rune_t */ + +#endif /* _ANSI_H_ */ diff --git a/sys/arch/arm26/include/aout_machdep.h b/sys/arch/arm26/include/aout_machdep.h new file mode 100644 index 00000000000..a57dd888346 --- /dev/null +++ b/sys/arch/arm26/include/aout_machdep.h @@ -0,0 +1,37 @@ +/* $NetBSD: aout_machdep.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARM26_AOUT_MACHDEP_H +#define _ARM26_AOUT_MACHDEP_H + +#define __LDPGSZ 32768 + +#define MID_ARM2 170 + +#endif diff --git a/sys/arch/arm26/include/armreg.h b/sys/arch/arm26/include/armreg.h new file mode 100644 index 00000000000..d6f7bf893be --- /dev/null +++ b/sys/arch/arm26/include/armreg.h @@ -0,0 +1,79 @@ +/* $NetBSD: armreg.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARM26_ARMREG_H +#define _ARM26_ARMREG_H + +/* All the junk the old ARMs stuff in R15 */ + +#define R15_MODE 0x00000003 +#define R15_MODE_USR 0x00000000 +#define R15_MODE_FIQ 0x00000001 +#define R15_MODE_IRQ 0x00000002 +#define R15_MODE_SVC 0x00000003 + +#define R15_PC 0x03fffffc + +#define R15_FIQ_DISABLE 0x04000000 +#define R15_IRQ_DISABLE 0x08000000 + +#define R15_FLAGS 0xf0000000 +#define R15_FLAG_N 0x80000000 +#define R15_FLAG_Z 0x40000000 +#define R15_FLAG_C 0x20000000 +#define R15_FLAG_V 0x10000000 + +#define ARM_CP15_CPU_ID 0 + +/* Not really many CPUs to consider */ +#define CPU_ID_DESIGNER_MASK 0xff000000 +#define CPU_ID_ARM_LTD 0x41000000 +#define CPU_ID_TYPE_MASK 0x00ff0000 +#define CPU_ID_ARM 0x00560000 +#define CPU_ID_CPU_MASK 0x0000fff0 +#define CPU_ID_ARM3 0x00000300 +#define CPU_ID_REVISION_MASK 0x0000000f + +/* Fake CPU IDs for older ARMs */ +#define CPU_ID_ARM2 0x00000200 +#define CPU_ID_ARM250 0x00000250 + +/* ARM3-specific coprocessor 15 register */ +#define ARM3_CP15_FLUSH 1 +#define ARM3_CP15_CONTROL 2 +#define ARM3_CP15_CACHEABLE 3 +#define ARM3_CP15_UPDATEABLE 4 +#define ARM3_CP15_DISRUPTIVE 5 + +/* Control register bits */ +#define ARM3_CTL_CACHE_ON 1 +#define ARM3_CTL_SHARED 2 +#define ARM3_CTL_MONITOR 4 + +#endif diff --git a/sys/arch/arm26/include/asm.h b/sys/arch/arm26/include/asm.h new file mode 100644 index 00000000000..dd20b261c11 --- /dev/null +++ b/sys/arch/arm26/include/asm.h @@ -0,0 +1,117 @@ +/* $NetBSD: asm.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _ARM32_ASM_H_ +#define _ARM32_ASM_H_ + +#define _BEGIN_ENTRY_NP .text; .align 0 +#define _END_ENTRY_NP + +#ifdef GPROF +# define _BEGIN_ENTRY _BEGIN_ENTRY_NP +# define _END_ENTRY _END_ENTRY_NP +#else +# define _BEGIN_ENTRY _BEGIN_ENTRY_NP +# define _END_ENTRY _END_ENTRY_NP +#endif + +#ifdef __ELF__ +# define _C_FUNC(x) x +# define _C_LABEL(x) x +#else +# ifdef __STDC__ +# define _C_FUNC(x) _ ## x +# define _C_LABEL(x) _ ## x +# else +# define _C_FUNC(x) _/**/x +# define _C_LABEL(x) _/**/x +# endif +#endif + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif +#define _ASM_FUNC(x) x + +/* + * gas/arm uses @ as a single comment character and thus cannot be used here + * Instead it recognised the # instead of an @ symbols in .type directives + * We define a couple of macros so that assembly code will not be dependant + * on one or the other. + */ +#define _ASM_TYPE_FUNCTION #function +#define _ASM_TYPE_OBJECT #object +#define _ENTRY(x) .globl x; .type x,_ASM_TYPE_FUNCTION; x: + +#define ENTRY(y) _BEGIN_ENTRY; _ENTRY(_C_FUNC(y)); _END_ENTRY +#define TWOENTRY(y,z) _BEGIN_ENTRY; _ENTRY(_C_FUNC(y)); _ENTRY(_C_FUNC(z)); \ + _END_ENTRY +#define ASENTRY(y) _BEGIN_ENTRY; _ENTRY(_ASM_FUNC(y)); _END_ENTRY + +#define ENTRY_NP(y) _BEGIN_ENTRY_NP; _ENTRY(_C_FUNC(y)); _END_ENTRY_NP +#define ASENTRY_NP(y) _BEGIN_ENTRY_NP; _ENTRY(_ASM_FUNC(y)); _END_ENTRY_NP + +#define ASMSTR .asciz + +#ifdef __ELF__ +#define RCSID(x) .section ".ident"; .asciz x +#else +#define RCSID(x) .text; .asciz x +#endif + +#ifdef __STDC__ +#define WARN_REFERENCES(sym,msg) \ + .stabs msg ## ,30,0,0,0 ; \ + .stabs __STRING(_C_LABEL(sym)) ## ,1,0,0,0 +#elif defined(__ELF__) +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(sym),1,0,0,0 +#else +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(_/**/sym),1,0,0,0 +#endif /* __STDC__ */ + +#endif /* !_ARM_ASM_H_ */ diff --git a/sys/arch/arm26/include/boot.h b/sys/arch/arm26/include/boot.h new file mode 100644 index 00000000000..1da0a0e476b --- /dev/null +++ b/sys/arch/arm26/include/boot.h @@ -0,0 +1,86 @@ +/* $NetBSD: boot.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * bootconfig.h -- Stuff to do with starting the kernel + */ + +#ifndef _ARM26_BOOT_H +#define _ARM26_BOOT_H + +#include <sys/types.h> + +/* + * Bootloader contract 0.2: + * + APCS conformant entry. + * + SVC mode. + * + Interrupts (IRQ and FIQ) disabled on CPU. + * + CPU caches disabled. + * + Physical memory below 512k is unused except for screen. + * + First three 32k blocks above 512k are zero page, stack and msgbuf. + * + From there to freebase should be preserved unless you know better. + * + From freebase to top of RAM is for general use. + * + VIDC is set up as specified (not really bootloader's job). + */ + +#define BOOT_MAGIC 0x942B7DFE + +struct bootconfig { + u_int32_t magic; /* BOOT_MAGIC */ + u_int32_t version; /* minor version of structure */ + /* Standard NetBSD boot parameters */ + u_int32_t boothowto; /* Reboot flags (single-user etc) */ + u_int32_t bootdev; /* Boot device */ + u_int32_t ssym; /* Start of debugging symbols */ + u_int32_t esym; /* End of debugging symbols */ + /* Parameters gathered by OS_ReadMemMapInfo */ + u_int32_t nbpp; /* Machine page size in bytes */ + u_int32_t npages; /* Number of pages */ + /* Layout of physical memory. */ + u_int32_t txtbase; /* Kernel text base */ + u_int32_t txtsize; /* ... and size */ + u_int32_t database; /* Ditto for data */ + u_int32_t datasize; /* and bss */ + u_int32_t bssbase; /* Note that base addresses are */ + u_int32_t bsssize; /* "physical" ie bytes above 0x02000000 */ + u_int32_t freebase; /* Start of free space */ + /* Framebuffer state -- used to initialise raster console */ + u_int32_t xpixels; /* Pixels across screen (XWindLimit + 1) */ + u_int32_t ypixels; /* Pixels down screen (YWindLimit + 1) */ + u_int32_t bpp; /* Bits per pixel (1 << Log2BPP) */ + u_int32_t screenbase; /* Physical base of screen */ + u_int32_t screensize; /* Size of framebuffer (TotalScreenSize) */ + u_int32_t cpixelrow; /* first free pixel row on screen */ + /* Version 0 ends here */ +}; + +void start __P((struct bootconfig *)); + +extern struct bootconfig bootconfig; + +#endif diff --git a/sys/arch/arm26/include/bswap.h b/sys/arch/arm26/include/bswap.h new file mode 100644 index 00000000000..b0d71f11f44 --- /dev/null +++ b/sys/arch/arm26/include/bswap.h @@ -0,0 +1,9 @@ +/* $NetBSD: bswap.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */ + +#ifndef _MACHINE_BSWAP_H_ +#define _MACHINE_BSWAP_H_ + +#define __BSWAP_RENAME +#include <sys/bswap.h> + +#endif /* !_MACHINE_BSWAP_H_ */ diff --git a/sys/arch/arm26/include/bus.h b/sys/arch/arm26/include/bus.h new file mode 100644 index 00000000000..e8b4c48f28e --- /dev/null +++ b/sys/arch/arm26/include/bus.h @@ -0,0 +1,128 @@ +/* $NetBSD: bus.h,v 1.1 2000/05/09 21:55:58 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * bus.h - Bus space functions for brivers + */ + +#ifndef _ARM26_BUS_H_ +#define _ARM26_BUS_H_ + +/* + * I believe that there's only one sensible bus space on the Archimedes, + * which corresponds to the system I/O bus. + * + * Some IDE cards have an odd shift applied to their registers. This is + * contained in the bus_space_tag_t. + */ + +/* Addresses (in bus space). */ +typedef u_int bus_addr_t; +typedef u_int bus_size_t; + +/* Access methods for bus space. */ +typedef int bus_space_tag_t; +typedef bus_addr_t bus_space_handle_t; + +/* Mapping and unmapping operations. */ +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 +extern int bus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, + bus_space_handle_t *); +#define bus_space_unmap(t,h,s) /* Do nothing */ +extern int bus_space_subregion(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_size_t, bus_space_handle_t *); +extern int bus_space_shift(bus_space_tag_t, bus_space_handle_t, int, + bus_space_tag_t *, bus_space_handle_t *); + +/* Allocating and freeing bus space */ +#define bus_space_alloc(t, rs, re, s, a, b, c, ap, hp) (-1) +#define bus_space_free(t, h, s) /* Do nothing */ + +/* Bus barrier operations. */ +#define BUS_SPACE_BARRIER_READ 0 +#define BUS_SPACE_BARRIER_WRITE 0 +#define bus_space_barrier(t, h, o, l, f) /* Do nothing */ + +/* Bus read (single) operations. */ +#define bus_space_read_1(t, h, o) (*(volatile u_int8_t *)((h) + ((o) << (t)))) +#define bus_space_read_2(t, h, o) (*(volatile u_int16_t *)((h) + ((o) << (t)))) + +/* Bus write (single) operations. */ +#define bus_space_write_1(t, h, o, v) \ + (*(volatile u_int8_t *)((h) + ((o) << (t))) = (v)) +#define bus_space_write_2(t, h, o, v) \ + (*(volatile u_int32_t *)((h) + ((o) << (t))) = (v) | ((v) << 16)) + +/* Bus read multiple operations. */ +extern void bus_space_read_multi_1(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); +extern void bus_space_read_multi_2(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); +#define bus_space_read_multi_4(t, h, o, d, s) panic("bus_space_read_multi_4") + +/* Bus write multiple operations. */ +extern void bus_space_write_multi_1(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int8_t const *, bus_size_t); +extern void bus_space_write_multi_2(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int16_t const *, bus_size_t); +#define bus_space_write_multi_4(t, h, o, d, s) panic("bus_space_write_multi_4") + +/* Bus set multiple operations. */ +extern void bus_space_set_multi_1(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int8_t, bus_size_t); +extern void bus_space_set_multi_2(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int16_t, bus_size_t); + +/* Bus read region operations. */ +extern void bus_space_read_region_1(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int8_t *, bus_size_t); +extern void bus_space_read_region_2(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int16_t *, bus_size_t); + +/* Bus write region operations. */ +extern void bus_space_write_region_1(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int8_t const *, bus_size_t); +extern void bus_space_write_region_2(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int16_t const *, + bus_size_t); + +/* Bus set region operations. */ +extern void bus_space_set_region_1(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int8_t, bus_size_t); +extern void bus_space_set_region_2(bus_space_tag_t, bus_space_handle_t, + bus_size_t, u_int16_t, bus_size_t); + +/* Copy operations. */ +extern void bus_space_copy_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); +extern void bus_space_copy_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, + bus_space_handle_t, bus_size_t, bus_size_t); + +#endif /* _ARM26_BUS_H_ */ diff --git a/sys/arch/arm26/include/cdefs.h b/sys/arch/arm26/include/cdefs.h new file mode 100644 index 00000000000..ef8862a1086 --- /dev/null +++ b/sys/arch/arm26/include/cdefs.h @@ -0,0 +1,3 @@ +/* $NetBSD: cdefs.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* Nothing here -- we're ordinary ELF */ diff --git a/sys/arch/arm26/include/cpu.h b/sys/arch/arm26/include/cpu.h new file mode 100644 index 00000000000..180bacc8f5c --- /dev/null +++ b/sys/arch/arm26/include/cpu.h @@ -0,0 +1,41 @@ +/* $NetBSD: cpu.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARM26_CPU_H +#define _ARM26_CPU_H + +#include <machine/frame.h> + +/* Only one CPU */ + +#define cpu_number() 0 + +#define INSN_SIZE 4 + +#endif diff --git a/sys/arch/arm26/include/db_machdep.h b/sys/arch/arm26/include/db_machdep.h new file mode 100644 index 00000000000..2f1fcaf06a4 --- /dev/null +++ b/sys/arch/arm26/include/db_machdep.h @@ -0,0 +1,90 @@ +/* $NetBSD: db_machdep.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Scott K Stevens + * + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _ARM26_DB_MACHDEP_H_ +#define _ARM26_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + +#include <vm/vm.h> +#include <machine/armreg.h> +#include <machine/frame.h> + +typedef vm_offset_t db_addr_t; /* address - unsigned */ +typedef long db_expr_t; /* expression - signed */ + +typedef struct { + trapframe_t ddb_tf; +} db_regs_t; + +db_regs_t ddb_regs; /* register state */ +#define DDB_REGS (&ddb_regs) +#define DDB_TF (&ddb_regs.ddb_tf) + +#define PC_REGS(regs) ((db_addr_t)(regs)->ddb_tf.tf_r15 & R15_PC) +#define PC_ADVANCE(regs) ((regs)->ddb_tf.tf_r15 += 4) + +#define BKPT_INST (0xe7ffffff) /* breakpoint instruction */ +#define BKPT_SIZE (INSN_SIZE) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +/*#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->ddb_tf.tf_pc -= BKPT_SIZE)*/ + +#define T_BREAKPOINT (1) + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT) +#define IS_WATCHPOINT_TRAP(type, code) (0) + +#define inst_trap_return(ins) ((ins)&0) +#define inst_return(ins) ((ins)&0) +#define inst_call(ins) (((ins) & 0x0f000000) == 0x0b000000) +#define inst_branch(ins) (((ins) & 0x0f000000) == 0x0a000000) +#define inst_load(ins) 0 +#define inst_store(ins) 0 +#define inst_unconditional_flow_transfer(ins) (((ins) & 0xf0000000) == 0xe0000000) + +#define getreg_val (0) +#define next_instr_address(pc, bd) (pc + INSN_SIZE) + +#define DB_MACHINE_COMMANDS + +#define SOFTWARE_SSTEP + +u_int branch_taken __P((u_int insn, u_int pc, db_regs_t *db_regs)); + +/* + * We use ELF symbols in DDB. + */ +#define DB_ELF_SYMBOLS +#define DB_ELFSIZE 32 + +#endif /* _ARM26_DB_MACHDEP_H_ */ diff --git a/sys/arch/arm26/include/disklabel.h b/sys/arch/arm26/include/disklabel.h new file mode 100644 index 00000000000..41230fd0498 --- /dev/null +++ b/sys/arch/arm26/include/disklabel.h @@ -0,0 +1,84 @@ +/* $NetBSD: disklabel.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Copyright (c) 1994 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * disklabel.h + * + * machine specific disk label info + * + * Created : 04/10/94 + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 8 /* number of partitions */ +#define RAW_PART 2 /* raw partition: XX?c */ + +#include <sys/dkbad.h> +#include <machine/disklabel_acorn.h> +#include <sys/disklabel_mbr.h> + +struct cpu_disklabel { +#if 0 /* XXX not actually used by anything */ + u_int pad0; + u_int pad1; + struct riscbsd_partition partitions[NRISCBSD_PARTITIONS]; +#endif + struct mbr_partition mbrparts[NMBRPART]; + struct dkbad bad; +}; + +#ifdef _KERNEL +struct buf; +struct disklabel; +int bounds_check_with_label __P((struct buf *, struct disklabel *, int)); + +/* for readdisklabel. rv != 0 -> matches, msg == NULL -> success */ +int mbr_label_read __P((dev_t, void (*)(struct buf *), struct disklabel *, + struct cpu_disklabel *, char **, int *, int *)); + +/* for writedisklabel. rv == 0 -> dosen't match, rv > 0 -> success */ +int mbr_label_locate __P((dev_t, void (*)(struct buf *), + struct disklabel *, struct cpu_disklabel *, int *, int *)); +#endif /* _KERNEL */ + +#endif /* _MACHINE_DISKLABEL_H_ */ + +/* End of disklabel.h */ diff --git a/sys/arch/arm26/include/disklabel_acorn.h b/sys/arch/arm26/include/disklabel_acorn.h new file mode 100644 index 00000000000..9f6ef6a60ee --- /dev/null +++ b/sys/arch/arm26/include/disklabel_acorn.h @@ -0,0 +1,121 @@ +/* $NetBSD: disklabel_acorn.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Copyright (c) 1994 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * disklabel.h + * + * machine specific disk label info + * + * Created : 04/10/94 + */ + +#define NRISCBSD_PARTITIONS MAXPARTITIONS + +#define PARTITION_TYPE_UNUSED 0 +#define PARTITION_TYPE_ADFS 1 +#define PARTITION_TYPE_RISCIX 2 + +#define PARTITION_FORMAT_RISCIX 2 +#define PARTITION_FORMAT_RISCBSD 0x42 + +#define FILECORE_BOOT_SECTOR 6 + +/* Stuff to deal with RISCiX partitions */ + +#define NRISCIX_PARTITIONS 8 +#define RISCIX_PARTITION_OFFSET 8 + +struct riscix_partition { + u_int rp_start; + u_int rp_length; + u_int rp_type; + char rp_name[16]; +}; + +struct riscix_partition_table { + u_int pad0; + u_int pad1; + struct riscix_partition partitions[NRISCIX_PARTITIONS]; +}; + +struct riscbsd_partition { + u_int rp_start; + u_int rp_length; + u_int rp_type; + char rp_name[16]; +}; + +struct filecore_bootblock { + u_char padding0[0x1c0]; + u_char log2secsize; + u_char secspertrack; + u_char heads; + u_char density; + u_char idlen; + u_char log2bpmb; + u_char skew; + u_char bootoption; + u_char lowsector; + u_char nzones; + u_short zone_spare; + u_int root; + u_int disc_size; + u_short disc_id; + u_char disc_name[10]; + u_int disc_type; + + u_char padding1[24]; + + u_char partition_type; + u_char partition_cyl_low; + u_char partition_cyl_high; + u_char checksum; +}; + +#if defined(_KERNEL) && !defined(__ASSEMBLER__) +struct buf; +struct cpu_disklabel; +struct disklabel; + +/* for readdisklabel. rv != 0 -> matches, msg == NULL -> success */ +int filecore_label_read __P((dev_t, void (*)(struct buf *), + struct disklabel *, struct cpu_disklabel *, char **, int *, + int *)); +/* for writedisklabel. rv == 0 -> dosen't match, rv > 0 -> success */ +int filecore_label_locate __P((dev_t, void (*)(struct buf *), + struct disklabel *, struct cpu_disklabel *, int *, int *)); +#endif diff --git a/sys/arch/arm26/include/elf_machdep.h b/sys/arch/arm26/include/elf_machdep.h new file mode 100644 index 00000000000..f250a680a0a --- /dev/null +++ b/sys/arch/arm26/include/elf_machdep.h @@ -0,0 +1,44 @@ +/* $NetBSD: elf_machdep.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x00000001 +#define EF_ARM_HASENTRY 0x00000002 +#define EF_ARM_INTERWORK 0x00000004 /* GNU binutils 000413 */ +#define EF_ARM_SYMSARESORTED 0x00000004 /* ARM ELF A08 */ +#define EF_ARM_APCS_26 0x00000008 +#define EF_ARM_APCS_FLOAT 0x00000010 +#define EF_ARM_PIC 0x00000020 +#define EF_ARM_ALIGN8 0x00000040 /* 8-bit structure alignment. */ +#define EF_ARM_NEW_ABI 0x00000080 +#define EF_ARM_OLD_ABI 0x00000100 +#define EF_ARM_SOFT_FLOAT 0x00000200 +#define EF_ARM_EABIMASK 0xff000000 + +#define ELF32_MACHDEP_ID_CASES \ + case EM_ARM: \ + break; + +#define ARCH_ELFSIZE 32 /* MD native binary size */ + +#define R_ARM_NONE 0 +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 + +#define R_TYPE(name) __CONCAT(R_ARM_,name) + diff --git a/sys/arch/arm26/include/endian.h b/sys/arch/arm26/include/endian.h new file mode 100644 index 00000000000..a6977570e0c --- /dev/null +++ b/sys/arch/arm26/include/endian.h @@ -0,0 +1,3 @@ +/* $NetBSD: endian.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +#include <sys/endian.h> diff --git a/sys/arch/arm26/include/endian_machdep.h b/sys/arch/arm26/include/endian_machdep.h new file mode 100644 index 00000000000..a0a8d999042 --- /dev/null +++ b/sys/arch/arm26/include/endian_machdep.h @@ -0,0 +1,3 @@ +/* $NetBSD: endian_machdep.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +#define _BYTE_ORDER _LITTLE_ENDIAN diff --git a/sys/arch/arm26/include/float.h b/sys/arch/arm26/include/float.h new file mode 100644 index 00000000000..70c89e04ff3 --- /dev/null +++ b/sys/arch/arm26/include/float.h @@ -0,0 +1,89 @@ +/* $NetBSD: float.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)float.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _ARM32_FLOAT_H_ +#define _ARM32_FLOAT_H_ + +#include <sys/cdefs.h> + +__BEGIN_DECLS +extern int __flt_rounds(); +__END_DECLS + +#define FLT_RADIX 2 /* b */ +#define FLT_ROUNDS __flt_rounds() + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP -125 /* emin */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MIN_10_EXP -37 /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP -1021 +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP -307 +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MAX_10_EXP 308 + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON DBL_EPSILON +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN DBL_MIN +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX DBL_MAX +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#endif /* _ARM32_FLOAT_H_ */ diff --git a/sys/arch/arm26/include/fp.h b/sys/arch/arm26/include/fp.h new file mode 100644 index 00000000000..4778bd4c14c --- /dev/null +++ b/sys/arch/arm26/include/fp.h @@ -0,0 +1,86 @@ +/* $NetBSD: fp.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * Copyright (c) 1995 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * fp.h + * + * FP info + * + * Created : 10/10/95 + */ + +#ifndef __ARM32_FP_H +#define __ARM32_FP_H + +/* + * An extended precision floating point number + */ + +typedef struct fp_extended_precision { + u_int32_t fp_exponent; + u_int32_t fp_mantissa_hi; + u_int32_t fp_mantissa_lo; +} fp_extended_precision_t; + +typedef struct fp_extended_precision fp_reg_t; + +/* + * Information about the FPE-SP state that is stored in the pcb + * + * This needs to move and be hidden from userland. + */ + +struct fpe_sp_state { + unsigned int fp_flags; + unsigned int fp_sr; + unsigned int fp_cr; + fp_reg_t fp_registers[16]; +}; + +/* + * Type for a saved FP context, if we want to translate the context to a + * user-readable form + */ + +typedef struct { + u_int32_t fpsr; + fp_extended_precision_t regs[8]; +} fp_state_t; + +#endif + +/* End of fp.h */ diff --git a/sys/arch/arm26/include/frame.h b/sys/arch/arm26/include/frame.h new file mode 100644 index 00000000000..45f777d44b8 --- /dev/null +++ b/sys/arch/arm26/include/frame.h @@ -0,0 +1,165 @@ +/* $NetBSD: frame.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ +/* $NetBSD: frame.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Copyright (c) 1999 Ben Harris. + * Copyright (c) 1994-1997 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + */ +/* + * frame.h - Stack frames structures + */ + +#ifndef _ARM26_FRAME_H_ +#define _ARM26_FRAME_H_ + +#ifndef _LOCORE + +#include <sys/signal.h> + +#include <machine/armreg.h> + +/* + * System stack frames. + */ + +/* + * irqframes just contain registers that APCS specifies the callee + * need not preserve. + */ +typedef struct irqframe { + union { + struct { + register_t if_r0; + register_t if_r1; + register_t if_r2; + register_t if_r3; + register_t if_r12; + register_t if_r14; + } svc; + struct { + register_t if_r0; + register_t if_r1; + register_t if_r2; + register_t if_r3; + register_t if_r11; + register_t if_r12; + } usr; + } if_mode; + register_t if_r15; /* Must be fixed so we know which branch to use */ +} irqframe_t; + +#define clockframe irqframe + +/* All the CLKF_* macros take a struct clockframe * as an argument. */ + +/* True if we took the interrupt in user mode */ +#define CLKF_USERMODE(frame) ((frame->if_r15 & R15_MODE) == R15_MODE_USR) + +/* True if we were at spl0 before the interrupt */ +#define CLKF_BASEPRI(frame) 0 /* FIXME */ + +/* Extract the program counter from a clockframe */ +#define CLKF_PC(frame) (frame->if_r15 & R15_PC) + +/* True if we took the interrupt from inside another interrupt handler. */ +/* Non-trivial to check because we handle interrupts in SVC mode. */ +#define CLKF_INTR(frame) 0 /* FIXME */ + +typedef struct trapframe { + register_t tf_r0; + register_t tf_r1; + register_t tf_r2; + register_t tf_r3; + register_t tf_r4; + register_t tf_r5; + register_t tf_r6; + register_t tf_r7; + register_t tf_r8; + register_t tf_r9; + register_t tf_r10; + register_t tf_r11; + register_t tf_r12; + register_t tf_r13; + register_t tf_r14; + register_t tf_r15; +} trapframe_t; + +/* + * Signal frame + */ + +struct sigframe { + int sf_signum; + int sf_code; + struct sigcontext *sf_scp; + sig_t sf_handler; + struct sigcontext sf_sc; +}; + +/* + * Switch frame + */ + +struct switchframe { + register_t sf_r4; /* Callee-saved registers */ + register_t sf_r5; + register_t sf_r6; + register_t sf_r7; + register_t sf_r8; + register_t sf_r9; + register_t sf_r10; + register_t sf_r11; /* Frame pointer */ + register_t sf_r13; /* Stack pointer */ + register_t sf_r14; /* Return address */ +}; + +/* + * Stack frame. Used during stack traces (db_trace.c) + */ +struct frame { + register_t fr_fp; + register_t fr_sp; + register_t fr_lr; + register_t fr_r15; +}; + +#ifdef _KERNEL +void validate_trapframe __P((trapframe_t *, int)); +#endif /* _KERNEL */ + +#endif _LOCORE + +#endif /* _ARM26_FRAME_H_ */ + +/* End of frame.h */ diff --git a/sys/arch/arm26/include/ieee.h b/sys/arch/arm26/include/ieee.h new file mode 100644 index 00000000000..d0056fc8a0e --- /dev/null +++ b/sys/arch/arm26/include/ieee.h @@ -0,0 +1,150 @@ +/* $NetBSD: ieee.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACBITS 52 + +#define E80_EXPBITS 15 +#define E80_FRACBITS 64 + +#define EXT_EXPBITS 15 +#define EXT_FRACBITS 112 + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exponent:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; + u_int dbl_fracl; +}; + +struct ieee_e80 { + u_int e80_exp:15; + u_int e80_zero:16; + u_int e80_sign:1; + u_int e80_frach:31; + u_int e80_j:1; + u_int e80_fracl; +}; + +struct ieee_ext { + u_int ext_frach:16; + u_int ext_exp:15; + u_int ext_sign:1; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define E80_EXP_INFNAN 32767 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define E80_QUIETNAN (1 << 15) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define E80_EXP_BIAS 16383 +#define EXT_EXP_BIAS 16383 diff --git a/sys/arch/arm26/include/ieeefp.h b/sys/arch/arm26/include/ieeefp.h new file mode 100644 index 00000000000..ed76824723b --- /dev/null +++ b/sys/arch/arm26/include/ieeefp.h @@ -0,0 +1,40 @@ +/* $NetBSD: ieeefp.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Based on ieeefp.h written by J.T. Conklin, Apr 28, 1995 + * Public domain. + */ + +#ifndef _ARM32_IEEEFP_H_ +#define _ARM32_IEEEFP_H_ + +/* FP exception codes */ + +#define FP_EXCEPT_INV 0 +#define FP_EXCEPT_DZ 1 +#define FP_EXCEPT_OFL 2 +#define FP_EXCEPT_UFL 3 +#define FP_EXCEPT_IMP 4 + +/* Exception type (used by fpsetmask() et al.) */ + +typedef int fp_except; + +/* Bit defines for fp_except */ + +#define FP_X_INV (1 << FP_EXCEPT_INV) /* invalid operation exception */ +#define FP_X_DZ (1 << FP_EXCEPT_DZ) /* divide-by-zero exception */ +#define FP_X_OFL (1 << FP_EXCEPT_OFL) /* overflow exception */ +#define FP_X_UFL (1 << FP_EXCEPT_UFL) /* underflow exception */ +#define FP_X_IMP (1 << FP_EXCEPT_IMP) /* imprecise (loss of precision; "inexact") */ + +/* Rounding modes */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RP=1, /* round toward positive infinity */ + FP_RM=2, /* round toward negative infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +#endif /* _ARM32_IEEEFP_H_ */ diff --git a/sys/arch/arm26/include/intr.h b/sys/arch/arm26/include/intr.h new file mode 100644 index 00000000000..abb836f2d14 --- /dev/null +++ b/sys/arch/arm26/include/intr.h @@ -0,0 +1,53 @@ +/* $NetBSD: intr.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * intr.h - Interrupt stuff for the consumption of MI code. + * + * arm26-specific functions are in irq.h + */ + +#ifndef _ARM26_INTR_H_ +#define _ARM26_INTR_H_ + +#include <machine/spl.h> /* XXX should be merged into here */ + +extern int hardsplx(int); + +extern void softintr_init(void); +extern void setsoftclock(void); +extern void setsoftnet(void); +extern void dosoftints(int); + +#define __GENERIC_SOFT_INTERRUPTS + +extern void *softintr_establish(int, void (*)(void *), void *); +extern void softintr_disestablish(void *); +extern void softintr_schedule(void *); + +#endif diff --git a/sys/arch/arm26/include/ipkdb.h b/sys/arch/arm26/include/ipkdb.h new file mode 100644 index 00000000000..c349305477a --- /dev/null +++ b/sys/arch/arm26/include/ipkdb.h @@ -0,0 +1,43 @@ +/* $NetBSD: ipkdb.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ + +/* + * Copyright (C) 1993, 1994 Wolfgang Solfrank. + * Copyright (C) 1993, 1994 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* define certain registers */ +#define SP 13 +#define LR 14 +#define PC 15 +#define NREG 16 + +extern int ipkdbregs[NREG]; + +extern int *ipkdb_find_stack(); +extern void ipkdb_free_stack __P((int *)); diff --git a/sys/arch/arm26/include/irq.h b/sys/arch/arm26/include/irq.h new file mode 100644 index 00000000000..cb86037ce7f --- /dev/null +++ b/sys/arch/arm26/include/irq.h @@ -0,0 +1,46 @@ +/* $NetBSD: irq.h,v 1.1 2000/05/09 21:55:59 bjh21 Exp $ */ +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +/* return values from interrupt handlers */ +/* These are the same as arm32 uses */ +#define IRQ_HANDLED 1 +#define IRQ_NOT_HANDLED 0 +#define IRQ_MAYBE_HANDLED -1 + +struct irq_handler; + +extern void irq_init __P((void)); +/* irq_handler is declared in machdep.h */ +/* splx, raisespl and lowerspl are declared in spl.h */ +extern struct irq_handler *irq_establish __P((int irqnum, int ipl, + int func(void *), void *arg)); +extern char const *irq_string __P((struct irq_handler *h)); +extern void irq_enable __P((struct irq_handler *h)); +extern void irq_disable __P((struct irq_handler *h)); +extern void irq_genmasks __P((void)); diff --git a/sys/arch/arm26/include/limits.h b/sys/arch/arm26/include/limits.h new file mode 100644 index 00000000000..bd2d24341d6 --- /dev/null +++ b/sys/arch/arm26/include/limits.h @@ -0,0 +1,97 @@ +/* $NetBSD: limits.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/* + * Copyright (c) 1988 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)limits.h 7.2 (Berkeley) 6/28/90 + */ + +#ifndef _ARM32_LIMITS_H_ +#define _ARM32_LIMITS_H_ + +#define CHAR_BIT 8 /* number of bits in a char */ +#define MB_LEN_MAX 1 /* no multibyte characters */ + +#define SCHAR_MIN (-0x7f-1) /* max value for a signed char */ +#define SCHAR_MAX 0x7f /* min value for a signed char */ + +#define UCHAR_MAX 0xff /* max value for an unsigned char */ +#define CHAR_MAX 0xff /* max value for a char */ +#define CHAR_MIN 0 /* min value for a char */ + +#define USHRT_MAX 0xffff /* max value for an unsigned short */ +#define SHRT_MAX 0x7fff /* max value for a short */ +#define SHRT_MIN (-0x7fff-1) /* min value for a short */ + +#define UINT_MAX 0xffffffff /* max value for an unsigned int */ +#define INT_MAX 0x7fffffff /* max value for an int */ +#define INT_MIN (-0x7fffffff-1) /* min value for an int */ + +#define ULONG_MAX 0xffffffff /* max value for an unsigned long */ +#define LONG_MAX 0x7fffffff /* max value for a long */ +#define LONG_MIN (-0x7fffffff-1) /* min value for a long */ + +#if !defined(_ANSI_SOURCE) +#define SSIZE_MAX INT_MAX /* max value for a ssize_t */ + +#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) || \ + defined(_ISOC99_SOURCE) || (__STDC_VERSION__ - 0) >= 199901L +#define ULLONG_MAX 0xffffffffffffffffULL /* max unsigned long long */ +#define LLONG_MAX 0x7fffffffffffffffLL /* max signed long long */ +#define LLONG_MIN (-0x7fffffffffffffffLL-1) /* min signed long long */ +#endif + +#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) +#define SIZE_T_MAX UINT_MAX /* max value for a size_t */ + +#define UQUAD_MAX 0xffffffffffffffffLL /* max unsigned quad */ +#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */ +#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */ + +#endif /* !_POSIX_C_SOURCE && !_XOPEN_SOURCE */ +#endif /* !_ANSI_SOURCE */ + +#if !defined(_ANSI_SOURCE) && !defined(_POSIX_C_SOURCE) || \ + defined(_XOPEN_SOURCE) +#define LONG_BIT 32 +#define WORD_BIT 32 + +#define DBL_DIG 15 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MIN 2.2250738585072014E-308 + +#define FLT_DIG 6 +#define FLT_MAX 3.40282347E+38F +#define FLT_MIN 1.17549435E-38F +#endif + +#endif /* _ARM32_LIMITS_H_ */ diff --git a/sys/arch/arm26/include/lock.h b/sys/arch/arm26/include/lock.h new file mode 100644 index 00000000000..72310a6a372 --- /dev/null +++ b/sys/arch/arm26/include/lock.h @@ -0,0 +1,51 @@ +/* $NetBSD: lock.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * 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. + */ + +/* + * Machine-dependent spin lock operations. + */ + +#ifndef _ARM32_LOCK_H_ +#define _ARM32_LOCK_H_ + +typedef int __cpu_simple_lock_t; + +#define __SIMPLELOCK_LOCKED 1 +#define __SIMPLELOCK_UNLOCKED 0 + +#endif /* _ARM32_LOCK_H_ */ diff --git a/sys/arch/arm26/include/machdep.h b/sys/arch/arm26/include/machdep.h new file mode 100644 index 00000000000..5d22f0fd9ea --- /dev/null +++ b/sys/arch/arm26/include/machdep.h @@ -0,0 +1,64 @@ +/* $NetBSD: machdep.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * machdep.h - random exported functions that have to be declared somewhere. + */ + +#ifndef _ARM26_MACHDEP_H +#define _ARM26_MACHDEP_H + +struct bootconfig; + +/* start.c */ +extern void start __P((struct bootconfig *initbootconfig)); + +/* except.c */ +extern void undefined_handler(struct trapframe *); +extern void swi_handler(struct trapframe *); +extern void data_abort_handler(struct trapframe *); +extern void prefetch_abort_handler(struct trapframe *); +extern void address_exception_handler(struct trapframe *); +extern void ast_handler(struct trapframe *); + +/* irq.c */ +extern void irq_handler __P((struct irqframe *irqf)); + +/* locore.S */ +extern void atomic_set_bit __P((u_int *address, u_int setmask)); +extern void atomic_clear_bit __P((u_int *address, u_int clearmask)); +extern register_t set_r13_irq __P((register_t r13_irq)); +extern void int_on __P((void)); +extern void int_off __P((void)); +extern void cpu_loswitch(struct switchframe **, struct switchframe *); +extern void proc_trampoline(void); /* not quite true */ +extern void child_return(void *); + +/* pmap.c */ +extern register_t update_memc __P((register_t, register_t)); +#endif diff --git a/sys/arch/arm26/include/math.h b/sys/arch/arm26/include/math.h new file mode 100644 index 00000000000..e1d1b72795c --- /dev/null +++ b/sys/arch/arm26/include/math.h @@ -0,0 +1,11 @@ +/* $NetBSD: math.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/* + * ISO C99 + */ +#if !defined(_ANSI_SOURCE) && \ + (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) || \ + defined(_ISOC99_SOURCE) || (__STDC_VERSION__ - 0) >= 199901L) +extern __const char __nanf[]; +#define NAN (*(__const float *)(__const void *)__nanf) +#endif diff --git a/sys/arch/arm26/include/memcreg.h b/sys/arch/arm26/include/memcreg.h new file mode 100644 index 00000000000..c1ea658c45c --- /dev/null +++ b/sys/arch/arm26/include/memcreg.h @@ -0,0 +1,226 @@ +/* $NetBSD: memcreg.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ +/*- + * Copyright (c) 1997, 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * memcreg.h - Acorn/ARM MEMC (Anna/VC2304/VL2304/MEMC1A/VL2304A/VL86C110/VY86C110) + * registers + */ + +#ifndef _ARM26_MEMCREG_H +#define _ARM26_MEMCREG_H + +/* + * Accessing the MEMC is a little odd. It's not connected to the data + * bus, so the register and the new value are coded into an address. + * Thus, to set a register, OR together the register specifier and the + * new value, and write any word to the resultant address. + */ + +#define MEMC_WRITE(value) *(volatile u_int32_t *)value = 0 + +/* + * This information is mostly derived from: + * MEMC Datasheet + * Published by Acorn Computers Limited. + * Part no 0460,019 + * Issue No 1.0 + * 30 September 1986 + * ISBN 1 85250 025 6 + * + * Thanks must go to Jeanette Draper at ARM Ltd + * <jeanette.draper@arm.com> for finding it for me. + * + * Information on master/slave MEMCs came from Tony Duell + * <ard@p850ug1.demon.co.uk>, who has a copy of the MEMC1A data + * sheet and might photocopy it for me one day. + */ + +/* General memory-map layout provided by MEMC */ +#define MEMC_PHYS_BASE ((caddr_t)0x02000000) +#define MEMC_IO_BASE ((caddr_t)0x03000000) +#define MEMC_VIDC_BASE ((caddr_t)0x03400000) +#define MEMC_ROM_LOW_BASE ((caddr_t)0x03400000) +#define MEMC_ROM_HIGH_BASE ((caddr_t)0x03800000) + +/* + * Each MEMC can manage 4Mb in 128 pages. The memory map only has + * space for 16Mb of physical RAM. + */ +#define MEMC_MAX_PHYSPAGES 512 + +/* + * DMA address generator control registers. Addresses (>>4) go in + * bits 2-16, and must thus be in the bottom 512k of physical RAM. + */ +#define MEMC_DMA_MAX 0x00080000 +/* Video */ +#define MEMC_VINIT 0x03600000 +#define MEMC_VSTART 0x03620000 +#define MEMC_VEND 0x03640000 +/* Cursor */ +#define MEMC_CINIT 0x03660000 +/* Sound */ +#define MEMC_SSTARTN 0x03680000 +#define MEMC_SENDN 0x036A0000 +#define MEMC_SPTR 0x036C0000 +#define MEMC_SET_PTR(reg,addr) (reg | (addr >> 2)) + +/* MEMC control register (sec 6.5) */ +#define MEMC_CONTROL 0x036E0000 + +/* Page size */ +#define MEMC_CTL_PGSZ_MASK 0x0000000C +#define MEMC_CTL_PGSZ_4K 0x00000000 +#define MEMC_CTL_PGSZ_8K 0x00000004 +#define MEMC_CTL_PGSZ_16K 0x00000008 +#define MEMC_CTL_PGSZ_32K 0x0000000C + +/* ROM speeds; low and high banks, relative to RAM speed */ +#define MEMC_CTL_LROMSPD_MASK 0x00000030 +#define MEMC_CTL_LROMSPD_4N 0x00000000 +#define MEMC_CTL_LROMSPD_3N 0x00000010 +#define MEMC_CTL_LROMSPD_2N 0x00000020 +#define MEMC_CTL_LROMSPD_PAGED 0x00000030 + +#define MEMC_CTL_HROMSPD_MASK 0x000000C0 +#define MEMC_CTL_HROMSPD_4N 0x00000000 +#define MEMC_CTL_HROMSPD_3N 0x00000040 +#define MEMC_CTL_HROMSPD_2N 0x00000080 +#define MEMC_CTL_HROMSPD_PAGED 0x000000C0 + +/* DRAM refresh control */ +#define MEMC_CTL_RFRSH_MASK 0x00000300 +#define MEMC_CTL_RFRSH_NONE 0x00000000 +#define MEMC_CTL_RFRSH_FLYBACK 0x00000100 +#define MEMC_CTL_RFRSH_CONTIN 0x00000300 + +/* Enable video DMA */ +#define MEMC_CTL_VIDEODMA 0x00000400 +/* Enable sound DMA */ +#define MEMC_CTL_SOUNDDMA 0x00000800 +/* Operating System Mode Select */ +#define MEMC_CTL_OSMODE 0x00001000 + +/* Test mode */ +/* This should never be set in a running system */ +#define MEMC_CTL_TESTMODE 0x00002000 + +/* + * Address translation control + */ + +/* Absolute address of translation table */ +#define MEMC_TRANS_BASE 0x03800000 + +/* + * MEMC translation entries are painful, and vary with the page size + * in use. Here, ppn is the physical page number, lpn is the logical + * page number and ppl is the page protection level. + * + * This is correct for one or two MEMCs. Where the extra bits of ppn + * go with >2 is anyone's guess. + * + * The list of transformations at the start of each macro is copied + * verbatim from the MEMC datasheet (Figure 5). They don't mention + * the fact that, in all page sizes, A[7] selects whether to use the + * master or slave MEMC in dual-MEMC configurations. This would be + * represented here as "PPN[7]->A[7]". + */ + +/* Page protection levels (data sheet section 6.6) */ +/*- + * PPL + * Mode 00 01 10 11 + * SVC R/W R/W R/W R/W + * OS R/W R/W R R + * User R/W R - - + */ + +#define MEMC_PPL_RDWR 0 +#define MEMC_PPL_RDONLY 1 +#define MEMC_PPL_NOACCESS 2 + +/*- + * 4k pages: + * PPN[6:0] -> A[6:0] + * PPL[1:0] -> A[9:8] + * LPN[12:11] -> A[11:10] + * LPN[10:0] -> A[22:12] + */ +#define MEMC_TRANS_ENTRY_4K(ppn, lpn, ppl) \ + (MEMC_TRANS_BASE | \ + ((ppn) & 0xff) | \ + ((ppl) & 0x3) << 8 | \ + ((lpn) & 0x7ff) << 12 | ((lpn) & 0x1800) >> 1) +/*- + * 8k pages: + * PPN[6] -> A[0] + * PPN[5:0] -> A[6:1] + * PPL[1:0] -> A[9:8] + * LPN[11:10] -> A[11:10] + * LPN[9:0] -> A[22:13] + */ +#define MEMC_TRANS_ENTRY_8K(ppn, lpn, ppl) \ + (MEMC_TRANS_BASE | \ + ((ppn) & 0x3f) << 1 | ((ppn) & 0x40) >> 6 | \ + ((ppn) & 0x80) | \ + ((ppl) & 0x3) << 8 | \ + ((lpn) & 0x3ff) << 13 | ((lpn) & 0xc00)) +/*- + * 16k pages: + * PPN[6:5] -> A[1:0] + * PPN[4:0] -> A[6:2] + * PPL[1:0] -> A[9:8] + * LPN[10:9] -> A[11:10] + * LPN[9:0] -> A[22:14] + */ +#define MEMC_TRANS_ENTRY_16K(ppn, lpn, ppl) \ + (MEMC_TRANS_BASE | \ + ((ppn) & 0x1f) << 2 | ((ppn) & 0x60) >> 5 | \ + ((ppn) & 0x80) | \ + ((ppl) & 0x3) << 8 | \ + ((lpn) & 0x1ff) << 14 | ((lpn) & 0x600) << 1) +/*- + * 32k pages (here, the MEMC descends into madness...): + * PPN[6] -> A[1] + * PPN[5] -> A[2] + * PPN[4] -> A[0] + * PPN[3:0] -> A[6:3] + * PPL[1:0] -> A[9:8] + * LPN[9:8] -> A[11:10] + * LPN[7:0] -> A[22:15] + */ +#define MEMC_TRANS_ENTRY_32K(ppn, lpn, ppl) \ + (MEMC_TRANS_BASE | \ + ((ppn) & 0x0f) << 3 | ((ppn) & 0x10) >> 4 | \ + ((ppn) & 0x20) >> 3 | ((ppn) & 0x40) >> 5 | \ + ((ppn) & 0x80) | \ + ((ppl) & 0x3) << 8 | \ + ((lpn) & 0x0ff) << 15 | ((lpn) & 0x300) << 2) + +#endif diff --git a/sys/arch/arm26/include/param.h b/sys/arch/arm26/include/param.h new file mode 100644 index 00000000000..afacd017500 --- /dev/null +++ b/sys/arch/arm26/include/param.h @@ -0,0 +1,144 @@ +/* $NetBSD: param.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/* + * Copyright (c) 1994,1995 Mark Brinicombe. + * 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 RiscBSD team. + * 4. The name "RiscBSD" nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY RISCBSD ``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 RISCBSD 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. + */ + +#ifndef _ARM26_PARAM_H_ +#define _ARM26_PARAM_H_ + +#ifdef _KERNEL +# include <machine/cpu.h> +#endif + +#include <machine/spl.h> + +#define _MACHINE arm26 +#define MACHINE "arm26" +#define _MACHINE_ARCH arm26 +#define MACHINE_ARCH "arm26" +#define MID_MACHINE MID_ARM2 + +/* + * Round p (pointer or byte index) up to a correctly-aligned value + * for all data types (int, long, ...). The result is u_int and + * must be cast to any desired pointer type. + * + * ALIGNED_POINTER is a boolean macro that checks whether an address + * is valid to fetch data elements of type t from on this architecture. + * This does not reflect the optimal alignment, just the possibility + * (within reasonable limits). + * + */ +#define ALIGNBYTES (sizeof(int) - 1) +#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES) +#define ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t)-1)) == 0) + +#define PGSHIFT 15 /* LOG2(NBPG) */ +#define NBPG (1 << PGSHIFT) /* bytes/page */ +#define PGOFSET (NBPG-1) /* byte offset into page */ + +#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ +#define DEV_BSIZE (1 << DEV_BSHIFT) +#define BLKDEV_IOSIZE 2048 +#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */ + +#define CLSIZELOG2 0 +#define CLSIZE (1 << CLSIZELOG2) + +/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */ +#define SSIZE 1 /* initial stack size/NBPG */ +#define SINCR 1 /* increment of stack/NBPG */ +#define UPAGES 1 /* pages of u-area */ +#define USPACE (UPAGES * NBPG) /* total size of u-area */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE NBPG /* default message buffer size */ +#endif + +/* + * Constants related to network buffer management. + * MCLBYTES must be no larger than CLBYTES (the software page size), and, + * on machines that exchange pages of input or output buffers with mbuf + * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple + * of the hardware page size. + */ +#define MSIZE 128 /* size of an mbuf */ +#define MCLSHIFT 11 /* convert bytes to m_buf clusters */ +#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */ +#define MCLOFSET (MCLBYTES - 1) /* offset within a m_buf cluster */ + +#ifndef NMBCLUSTERS +#ifdef GATEWAY +#define NMBCLUSTERS 512 /* map size, max cluster allocation */ +#else +#define NMBCLUSTERS 256 /* map size, max cluster allocation */ +#endif +#endif + +/* + * Defaults for lower- and upper-bounds for the kmem_map page count. + * Can be overridden by kernel config options. + */ +#define NKMEMPAGES_MIN_DEFAULT 0 +#define NKMEMPAGES_MAX_DEFAULT 32 + +/* pages ("clicks") to disk blocks */ +#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT)) +#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT)) +/*#define dtob(x) ((x) << DEV_BSHIFT)*/ + +#define ctob(x) ((x) << PGSHIFT) + +/* bytes to pages */ +#define btoc(x) (((x) + PGOFSET) >> PGSHIFT) + +#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \ + ((bytes) >> DEV_BSHIFT) +#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \ + ((db) << DEV_BSHIFT) + +/* + * Map a ``block device block'' to a file system block. + * This should be device dependent, and should use the bsize + * field from the disk label. + * For now though just use DEV_BSIZE. + */ +#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE / DEV_BSIZE)) + +#ifdef _KERNEL +#ifndef _LOCORE +void delay __P((unsigned)); +#define DELAY(x) delay(x) +#endif +#endif + +#endif /* _ARM_PARAM_H_ */ diff --git a/sys/arch/arm26/include/pcb.h b/sys/arch/arm26/include/pcb.h new file mode 100644 index 00000000000..310fc2e343e --- /dev/null +++ b/sys/arch/arm26/include/pcb.h @@ -0,0 +1,52 @@ +/* $NetBSD: pcb.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARM26_PCB_H +#define _ARM26_PCB_H + +struct trapframe; +struct switchframe; + +struct pcb { + struct trapframe *pcb_tf; + struct switchframe *pcb_sf; + void *pcb_onfault; /* return here after failed page fault */ + label_t *pcb_onfault_lj; /* longjmp here ditto */ + label_t *pcb_onundef_lj; /* longjmp here on undefined instruction */ +}; + +/* + * No additional data for core dumps. + */ + +struct md_coredump { +}; + + +#endif diff --git a/sys/arch/arm26/include/pmap.h b/sys/arch/arm26/include/pmap.h new file mode 100644 index 00000000000..d79485f256f --- /dev/null +++ b/sys/arch/arm26/include/pmap.h @@ -0,0 +1,60 @@ +/* $NetBSD: pmap.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ +/*- + * Copyright (c) 1997, 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +/* + * machine/pmap.h - Machine-dependent pmap stuff from MEMC1A + */ + +#ifndef _ARM26_PMAP_H +#define _ARM26_PMAP_H + +struct pmap; + +typedef struct pmap *pmap_t; + +#ifdef _KERNEL +#include <machine/memcreg.h> + +extern void pmap_bootstrap __P((int, paddr_t)); + +extern struct pmap kernel_pmap_store; + +#define pmap_kernel() (&kernel_pmap_store) + +extern boolean_t pmap_confess(vaddr_t, vm_prot_t); + +extern boolean_t pmap_fault(pmap_t, vaddr_t, vm_prot_t); + +/* Save on hassle and kernel VM */ +#define PMAP_MAP_POOLPAGE(pa) ((vaddr_t)MEMC_PHYS_BASE + (pa)) +#define PMAP_UNMAP_POOLPAGE(va) ((va) - (vaddr_t)MEMC_PHYS_BASE) + +#endif /* _KERNEL */ + +#endif diff --git a/sys/arch/arm26/include/proc.h b/sys/arch/arm26/include/proc.h new file mode 100644 index 00000000000..5469f673e16 --- /dev/null +++ b/sys/arch/arm26/include/proc.h @@ -0,0 +1,38 @@ +/* $NetBSD: proc.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARM26_PROC_H +#define _ARM26_PROC_H + +/* arm26-specific part of struct proc */ + +struct mdproc { +}; + +#endif diff --git a/sys/arch/arm26/include/profile.h b/sys/arch/arm26/include/profile.h new file mode 100644 index 00000000000..1216b0c72b1 --- /dev/null +++ b/sys/arch/arm26/include/profile.h @@ -0,0 +1,76 @@ +/* $NetBSD: profile.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/* + * Copyright (c) 1995-1996 Mark Brinicombe + * + * 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 Mark Brinicombe. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define _MCOUNT_DECL void _mcount + +/* + * Cannot implement mcount in C as GCC will trash the ip register when it + * pushes a trapframe. Pity we cannot insert assembly before the function + * prologue. + */ +#define MCOUNT \ + __asm__(".text"); \ + __asm__(".align 0"); \ + __asm__(".type mcount,%function"); \ + __asm__(".global mcount"); \ + __asm__("mcount:"); \ + /* \ + * Preserve registers that are trashed during mcount \ + */ \ + __asm__("stmfd sp!, {r0-r3, lr}"); \ + /* \ + * find the return address for mcount, \ + * and the return address for mcount's caller. \ + * \ + * frompcindex = pc pushed by call into self. \ + */ \ + __asm__("mov r0, ip"); \ + /* \ + * selfpc = pc pushed by mcount call \ + */ \ + __asm__("mov r1, lr"); \ + /* \ + * Call the real mcount code \ + */ \ + __asm__("bl __mcount"); \ + /* \ + * Restore registers that were trashed during mcount \ + */ \ + __asm__("ldmfd sp!, {r0-r3, pc}^"); + +#ifdef _KERNEL +/* + * Note that we assume splhigh() and splx() cannot call mcount() + * recursively. + */ +#define MCOUNT_ENTER s = splhigh() +#define MCOUNT_EXIT splx(s) +#endif /* _KERNEL */ diff --git a/sys/arch/arm26/include/pte.h b/sys/arch/arm26/include/pte.h new file mode 100644 index 00000000000..d513a47b1f5 --- /dev/null +++ b/sys/arch/arm26/include/pte.h @@ -0,0 +1,33 @@ +/* $NetBSD: pte.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARM26_PTE_H +#define _ARM26_PTE_H + +#endif diff --git a/sys/arch/arm26/include/ptrace.h b/sys/arch/arm26/include/ptrace.h new file mode 100644 index 00000000000..65a3e74e0c2 --- /dev/null +++ b/sys/arch/arm26/include/ptrace.h @@ -0,0 +1,41 @@ +/* $NetBSD: ptrace.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Frank Lancaster + * Copyright (c) 1995 Tools GmbH + * 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 Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + */ + +/* + * arm-dependent ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) diff --git a/sys/arch/arm26/include/reg.h b/sys/arch/arm26/include/reg.h new file mode 100644 index 00000000000..d31906c1492 --- /dev/null +++ b/sys/arch/arm26/include/reg.h @@ -0,0 +1,53 @@ +/* $NetBSD: reg.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/* + * Copyright (C) 1994, 1995 Frank Lancaster + * Copyright (C) 1994, 1995 TooLs GmbH. + * 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 TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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. + * + * @(#)reg.h 5.5 (Berkeley) 1/18/91 + */ + +#ifndef _ARM26_REG_H_ +#define _ARM26_REG_H_ + +#include <machine/fp.h> + +struct reg { + unsigned int r[13]; + unsigned int r_sp; + unsigned int r_lr; + unsigned int r_pc; +}; + +struct fpreg { + unsigned int fpr_fpsr; + fp_reg_t fpr[8]; +}; + +#endif /* !_ARM26_REG_H_ */ diff --git a/sys/arch/arm26/include/setjmp.h b/sys/arch/arm26/include/setjmp.h new file mode 100644 index 00000000000..f1f832788b0 --- /dev/null +++ b/sys/arch/arm26/include/setjmp.h @@ -0,0 +1,79 @@ +/* $NetBSD: setjmp.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 29 /* size, in longs, of a jmp_buf */ + +/* + * NOTE: The internal structure of a jmp_buf is *PRIVATE* + * This information is provided as there is software + * that fiddles with this with obtain the stack pointer + * (yes really ! and its commercial !). + * + * Description of the setjmp buffer + * + * word 0 magic number (dependant on creator) + * 1 - 3 f4 fp register 4 + * 4 - 6 f5 fp register 5 + * 7 - 9 f6 fp register 6 + * 10 - 12 f7 fp register 7 + * 13 fpsr fp status register + * 14 r4 register 4 + * 15 r5 register 5 + * 16 r6 register 6 + * 17 r7 register 7 + * 18 r8 register 8 + * 19 r9 register 9 + * 20 r10 register 10 (sl) + * 21 r11 register 11 (fp) + * 22 r12 register 12 (ip) + * 23 r13 register 13 (sp) + * 24 r14 register 14 (lr) + * 25 signal mask (dependant on magic) + * + * The magic number number identifies the jmp_buf and + * how the buffer was created as well as providing + * a sanity check + * + * A side note I should mention - Please do not tamper + * with the floating point fields. While they are + * always saved and restored at the moment this cannot + * be garenteed especially if the compiler happens + * to be generating soft-float code so no fp + * registers will be used. + * + * Whilst this can be seen an encouraging people to + * use the setjmp buffer in this way I think that it + * is for the best then if changes occur compiles will + * break rather than just having new builds falling over + * mysteriously. + */ + +#define _JB_MAGIC__SETJMP 0x4278f500 +#define _JB_MAGIC_SETJMP 0x4278f501 + +/* Valid for all jmp_buf's */ + +#define _JB_MAGIC 0 +#define _JB_REG_F4 1 +#define _JB_REG_F5 4 +#define _JB_REG_F6 7 +#define _JB_REG_F7 10 +#define _JB_REG_FPSR 13 +#define _JB_REG_R4 14 +#define _JB_REG_R5 15 +#define _JB_REG_R6 16 +#define _JB_REG_R7 17 +#define _JB_REG_R8 18 +#define _JB_REG_R9 19 +#define _JB_REG_R10 20 +#define _JB_REG_R11 21 +#define _JB_REG_R12 22 +#define _JB_REG_R13 23 +#define _JB_REG_R14 24 + +/* Only valid with the _JB_MAGIC_SETJMP magic */ + +#define _JB_SIGMASK 25 diff --git a/sys/arch/arm26/include/signal.h b/sys/arch/arm26/include/signal.h new file mode 100644 index 00000000000..5f551e440ed --- /dev/null +++ b/sys/arch/arm26/include/signal.h @@ -0,0 +1,136 @@ +/* $NetBSD: signal.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ + +/* + * Copyright (c) 1994-1996 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * signal.h + * + * Architecture dependant signal types and structures + * + * Created : 30/09/94 + */ + +#ifndef _ARM26_SIGNAL_H_ +#define _ARM26_SIGNAL_H_ + +#ifndef _LOCORE +typedef int sig_atomic_t; +#endif + +#if !defined(_ANSI_SOURCE) && !defined(_POSIX_C_SOURCE) && \ + !defined(_XOPEN_SOURCE) +#ifndef _LOCORE +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ + +#if defined(__LIBC12_SOURCE__) || defined(_KERNEL) +struct sigcontext13; /* No COMPAT_13 on arm26. */ +#endif /* __LIBC12_SOURCE__ || _KERNEL */ + +struct sigcontext { + int sc_onstack; /* sigstack state to restore */ + + unsigned int sc_r0; + unsigned int sc_r1; + unsigned int sc_r2; + unsigned int sc_r3; + unsigned int sc_r4; + unsigned int sc_r5; + unsigned int sc_r6; + unsigned int sc_r7; + unsigned int sc_r8; + unsigned int sc_r9; + unsigned int sc_r10; + unsigned int sc_r11; + unsigned int sc_r12; + unsigned int sc_r13; + unsigned int sc_r14; + unsigned int sc_r15; + + sigset_t sc_mask; /* signal mask to restore */ +}; + +#endif /* !_LOCORE */ + +/* Signals codes */ + +/* + * SIGFPE codes + * + * see ieeefp.h for definition of FP exception codes + */ + +#define SIG_CODE_FPE_CODE_MASK 0x00000f00 /* Mask for exception code */ +#define SIG_CODE_FPE_CODE_SHIFT 8 /* Shift for exception code */ +#define SIG_CODE_FPE_TYPE_MASK 0x000000ff /* Mask for specific code */ + +/* + * SIGILL codes + * + * the signal code is the instruction that raised the signal + */ + +#if 0 + +/* + * SIGBUS and SIGSEGV codes + * + * The signal code is combination of the fault address and the fault code. + * + * The fault code is the coproc #15 fault status code + * + * The exception to this is a SIGBUS or SIGSEGV from a prefetch abort. + * In this case the fault status code is not valid so the TYPE_MASK + * should be treated as undefined (in practice it is the bottom 4 bits + * of the fault address). + */ + +#define SIG_CODE_BUS_ADDR_MASK 0xfffffff0 +#define SIG_CODE_BUS_TYPE_MASK 0x0000000f +#define SIG_CODE_SEGV_ADDR_MASK SIG_CODE_BUS_ADDR_MASK +#define SIG_CODE_SEGV_TYPE_MASK SIG_CODE_BUS_TYPE_MASK + +#endif + +#endif /* !_ANSI_SOURCE && !_POSIX_C_SOURCE && !_XOPEN_SOURCE */ +#endif /* !_ARM_SIGNAL_H_ */ + +/* End of signal.h */ diff --git a/sys/arch/arm26/include/softintr.h b/sys/arch/arm26/include/softintr.h new file mode 100644 index 00000000000..f5ce12e4155 --- /dev/null +++ b/sys/arch/arm26/include/softintr.h @@ -0,0 +1,40 @@ +/* $NetBSD: softintr.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ +/*- + * Copyright (c) 1999 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* Software interrupt priority levels */ + +#ifndef _ARM26_SOFTINTR_H +#define _ARM26_SOFTINTR_H + +#define SOFTIRQ_CLOCK 0 +#define SOFTIRQ_NET 1 +#define SOFTIRQ_SERIAL 2 + +#define SOFTIRQ_BIT(x) (1 << x) + +#endif /* _ARM26_SOFTINTR_H */ diff --git a/sys/arch/arm26/include/spl.h b/sys/arch/arm26/include/spl.h new file mode 100644 index 00000000000..d2f7705d83e --- /dev/null +++ b/sys/arch/arm26/include/spl.h @@ -0,0 +1,93 @@ +/* $NetBSD: spl.h,v 1.1 2000/05/09 21:56:00 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * spl.h -- Software priority levels, I think. + */ + +#ifndef _ARM26_SPL_H +#define _ARM26_SPL_H + +/* + * These are the different SPL states + * + * Each state has an interrupt mask associated with it which + * indicate which interrupts are allowed. + */ + +#define IPL_NONE 0 +#define IPL_SOFTCLOCK 1 +#define IPL_SOFTNET 2 +#define IPL_BIO 3 +#define IPL_NET 4 +#define IPL_TTY 5 +#define IPL_IMP 6 +#define IPL_AUDIO 7 +#define IPL_SERIAL 8 +#define IPL_CLOCK 9 +#define IPL_STATCLOCK 10 +#define IPL_SCHED 11 +#define IPL_HIGH 12 +#define NIPL IPL_HIGH + 1 + +#define spl0() splx(IPL_NONE) +#define splsoftnet() raisespl(IPL_SOFTNET) +#define splsoftclock() raisespl(IPL_SOFTCLOCK) +#define spllowersoftclock() lowerspl(IPL_SOFTCLOCK) +#define splsoft() splsoftnet() +#define splbio() raisespl(IPL_BIO) +#define splnet() raisespl(IPL_NET) +#define spltty() raisespl(IPL_TTY) +#define splimp() raisespl(IPL_IMP) +#define splaudio() raisespl(IPL_AUDIO) +#define splclock() raisespl(IPL_CLOCK) +#define splstatclock() raisespl(IPL_STATCLOCK) +#define splhigh() splx(IPL_HIGH) + +#define signotify(p) setsoftast() + +#ifdef _KERNEL +#ifndef ASSEMBLER +extern int raisespl __P((int)); +extern int lowerspl __P((int)); +extern int splx __P((int)); + +void setsoftnet __P((void)); +void setsoftast __P((void)); +void setsoftclock __P((void)); +void setsoftintr __P((u_int intrmask)); + +extern int current_spl_level; /* XXX tautological name */ + +void need_resched __P((void)); +void need_proftick __P((struct proc *)); + +#endif /* ASSEMBLER */ +#endif /* _KERNEL */ + +#endif /* ! _ARM26_SPL_H */ diff --git a/sys/arch/arm26/include/stdarg.h b/sys/arch/arm26/include/stdarg.h new file mode 100644 index 00000000000..b6449d8bcf9 --- /dev/null +++ b/sys/arch/arm26/include/stdarg.h @@ -0,0 +1,60 @@ +/* $NetBSD: stdarg.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ + +/* + * Copyright (c) 1991, 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _STDARG_H_ +#define _STDARG_H_ + +typedef char *va_list; + +#define __va_promote(type) \ + (((sizeof(type) + sizeof(int) - 1) / sizeof(int)) * sizeof(int)) + +#define va_start(ap, last) \ + (ap = ((char *)&(last) + __va_promote(last))) + +#ifdef _KERNEL +#define va_arg(ap, type) \ + ((type *)(ap += sizeof(type)))[-1] +#else +#define va_arg(ap, type) \ + ((type *)(ap += sizeof(type) < sizeof(int) ? \ + (abort(), 0) : sizeof(type)))[-1] +#endif + +#define va_end(ap) + +#endif /* !_STDARG_H_ */ diff --git a/sys/arch/arm26/include/trap.h b/sys/arch/arm26/include/trap.h new file mode 100644 index 00000000000..bbe07e7ffb0 --- /dev/null +++ b/sys/arch/arm26/include/trap.h @@ -0,0 +1,58 @@ +/* $NetBSD: trap.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * 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 Mark Brinicombe. + * 4. The name of the company nor the name of the author may 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 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. + * + * RiscBSD kernel project + * + * trap.h + * + * Various trap definitions + */ + +/* + * Instructions used for breakpoints. + * + * These are an undefined instructions. + * Technically the userspace breakpoint could be a SWI + * but we want to keep this the same as IPKDB which + * needs an undefined instruction as a break point. + * Ideally ARM would define several standard instruction + * sequences for use as breakpoints. + */ + +#define GDB_BREAKPOINT 0xe6000011 /* Used by GDB */ +#define IPKDB_BREAKPOINT 0xe6000010 /* Used by IPKDB */ +#define KERNEL_BREAKPOINT 0xe7ffffff /* Used by DDB */ + +#define USER_BREAKPOINT GDB_BREAKPOINT + +/* End of trap.h */ diff --git a/sys/arch/arm26/include/types.h b/sys/arch/arm26/include/types.h new file mode 100644 index 00000000000..cf181f9202d --- /dev/null +++ b/sys/arch/arm26/include/types.h @@ -0,0 +1,88 @@ +/* $NetBSD: types.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ + +/* + * Copyright (c) 1990 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)types.h 7.5 (Berkeley) 3/9/91 + */ + +#ifndef _ARM32_TYPES_H_ +#define _ARM32_TYPES_H_ + +#include <sys/cdefs.h> + +/* NB: This should probably be if defined(_KERNEL) */ +#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) +typedef unsigned long vm_offset_t; +typedef unsigned long vm_size_t; + +typedef vm_offset_t paddr_t; +typedef vm_size_t psize_t; +typedef vm_offset_t vaddr_t; +typedef vm_size_t vsize_t; +#endif + +/* + * Basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ +#define __BIT_TYPES_DEFINED__ +typedef __signed char int8_t; +typedef unsigned char u_int8_t; +typedef short int16_t; +typedef unsigned short u_int16_t; +typedef int int32_t; +typedef unsigned int u_int32_t; +/* LONGLONG */ +typedef long long int64_t; +/* LONGLONG */ +typedef unsigned long long u_int64_t; + +typedef int32_t register_t; + +#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) +/* This structure must be kept synchronised with setjmp.S */ +typedef struct label_t { /* Used by setjmp & longjmp */ + register_t jb_r4; + register_t jb_r5; + register_t jb_r6; + register_t jb_r7; + register_t jb_r8; + register_t jb_r9; + register_t jb_r10; + register_t jb_r11; + register_t jb_r13; + register_t jb_r14; +} label_t; +#endif + +#endif /* _ARM32_TYPES_H_ */ diff --git a/sys/arch/arm26/include/undefined.h b/sys/arch/arm26/include/undefined.h new file mode 100644 index 00000000000..4cbd9feba67 --- /dev/null +++ b/sys/arch/arm26/include/undefined.h @@ -0,0 +1,63 @@ +/* $NetBSD: undefined.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ + +/* + * Copyright (c) 1995-1996 Mark Brinicombe. + * Copyright (c) 1995 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * undefined.h + * + * Undefined instruction types, symbols and prototypes + * + * Created : 08/02/95 + */ + +#ifdef _KERNEL + +typedef int (*undef_handler_t) __P((unsigned int, unsigned int, trapframe_t *, int)); + +#define FP_COPROC 1 +#define FP_COPROC2 2 +#define MAX_COPROCS 16 + +extern undef_handler_t undefined_handlers[MAX_COPROCS]; + +/* Prototypes for undefined.c */ + +int install_coproc_handler __P((int, undef_handler_t)); +void undefined_init __P((void)); + +#endif + +/* End of undefined.h */ diff --git a/sys/arch/arm26/include/varargs.h b/sys/arch/arm26/include/varargs.h new file mode 100644 index 00000000000..9fc0a8baab9 --- /dev/null +++ b/sys/arch/arm26/include/varargs.h @@ -0,0 +1,64 @@ +/* $NetBSD: varargs.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, 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 by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)varargs.h 8.2 (Berkeley) 3/22/94 + */ + +#ifndef _MACHINE_VARARGS_H_ +#define _MACHINE_VARARGS_H_ + +typedef char *va_list; + +#define va_dcl int va_alist; ... + +#define va_start(ap) \ + ap = (char *)&va_alist + +#ifdef _KERNEL +#define va_arg(ap, type) \ + ((type *)(ap += sizeof(type)))[-1] +#else +#define va_arg(ap, type) \ + ((type *)(ap += sizeof(type) < sizeof(int) ? \ + (abort(), 0) : sizeof(type)))[-1] +#endif + +#define va_end(ap) + +#endif /* !_MACHINE_VARARGS_H_ */ diff --git a/sys/arch/arm26/include/vmparam.h b/sys/arch/arm26/include/vmparam.h new file mode 100644 index 00000000000..96b3f4b97d2 --- /dev/null +++ b/sys/arch/arm26/include/vmparam.h @@ -0,0 +1,122 @@ +/* $NetBSD: vmparam.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ + +/* + * Copyright (c) 1988 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARM32_VMPARAM_H_ +#define _ARM32_VMPARAM_H_ + +#define USRTEXT VM_MIN_ADDRESS +#define USRSTACK VM_MAXUSER_ADDRESS + +#define MAXTSIZ (0x007f8000) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ (0x00800000) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (0x00800000) /* max data size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (512*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (0x00200000) /* max stack size */ +#endif + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * The time for a process to be blocked before being very swappable. + * This is a number of seconds which the system takes as being a non-trivial + * amount of real time. You probably shouldn't change this; + * it is used in subtle ways (fractions and multiples of it are, that is, like + * half of a `long time'', almost a long time, etc.) + * It is related to human patience and other factors which don't really + * change over time. + */ +#define MAXSLP 20 + +/* + * Mach derived constants + */ + +/* Need to link some of these with some in param.h */ + +/* + * These specify the range of virtual pages available to user + * processes and to the kernel. This is a bit of a delicate balancing + * act, as we've only got 32Mb between them. There should probably be + * an option to have separate kernel and user spaces to ease this. + */ + +#define KVM_SIZE 0x00800000 /* 8Mb */ + +/* User VM range */ +#define VM_MIN_ADDRESS ((vm_offset_t)0x00008000) +#define VM_MAX_ADDRESS ((vm_offset_t)0x02000000 - KVM_SIZE) +#define VM_MAXUSER_ADDRESS VM_MAX_ADDRESS + +/* Kernel VM range */ +#define VM_MIN_KERNEL_ADDRESS VM_MAX_ADDRESS +#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0x02000000) +#define VM_MAXKERN_ADDRESS VM_MAX_KERNEL_ADDRESS + +/* XXX max. amount of KVM to be used by buffers. */ +#ifndef VM_MAX_KERNEL_BUF +#define VM_MAX_KERNEL_BUF \ + ((VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) / 4) +#endif + +/* Physical memory parameters */ + +#define VM_PHYSSEG_MAX 2 + +#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST + +#define VM_PHYSSEG_NOADD /* We won't turn up extra memory during autoconfig */ + +#define VM_NFREELIST 2 +#define VM_FREELIST_LOW 1 /* DMA-able memory (bottom 512k phys) */ +#define VM_FREELIST_DEFAULT 0 /* The rest */ + +struct pmap_physseg { +}; + +#endif + +/* End of vmparam.h */ diff --git a/sys/arch/arm26/iobus/iobus.c b/sys/arch/arm26/iobus/iobus.c new file mode 100644 index 00000000000..2f20191f291 --- /dev/null +++ b/sys/arch/arm26/iobus/iobus.c @@ -0,0 +1,116 @@ +/* $NetBSD: iobus.c,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * iobus.c - when the IORQ* calls... + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: iobus.c,v 1.1 2000/05/09 21:56:01 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/systm.h> + +#include <machine/bus.h> + +#include <arch/arm26/iobus/iobusvar.h> + +#include "locators.h" + +static int iobus_match __P((struct device *parent, struct cfdata *cf, void *aux)); +static void iobus_attach __P((struct device *parent, struct device *self, void *aux)); +static int iobus_search __P((struct device *parent, struct cfdata *cf, void *aux)); +static int iobus_print __P((void *aux, const char *pnp)); + +struct iobus_softc { + struct device sc_dev; +}; + +struct cfattach iobus_ca = { + sizeof(struct iobus_softc), iobus_match, iobus_attach +}; + +extern struct cfdriver iobus_cd; + +static int +iobus_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + + /* There can be only one! */ + if (cf->cf_unit == 0) + return 1; + else + return 0; +} + +static void +iobus_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + + printf("\n"); + + config_search(iobus_search, self, NULL); +} + +extern struct bus_space iobus_bs_tag; + +static int +iobus_search(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct iobus_attach_args ioa; + + ioa.ioa_tag = 2; + ioa.ioa_base = cf->cf_loc[IOBUSCF_BASE]; + if ((cf->cf_attach->ca_match)(parent, cf, &ioa) > 0) + config_attach(parent, cf, &ioa, iobus_print); + + return 0; +} + +static int +iobus_print(aux, pnp) + void *aux; + const char *pnp; +{ + struct iobus_attach_args *ioa = aux; + + if (ioa->ioa_base != IOBUSCF_BASE_DEFAULT) + printf(" base 0x%06x", ioa->ioa_base); + return UNCONF; +} + diff --git a/sys/arch/arm26/iobus/iobusvar.h b/sys/arch/arm26/iobus/iobusvar.h new file mode 100644 index 00000000000..e9034c9c07e --- /dev/null +++ b/sys/arch/arm26/iobus/iobusvar.h @@ -0,0 +1,45 @@ +/* $NetBSD: iobusvar.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * iobusvar.h - Things other people need to know about iobus.c + */ + +#ifndef _ARM26_IOBUSVAR_H +#define _ARM26_IOBUSVAR_H + +#include <machine/bus.h> + +/* Structure passed to children of an iobus */ + +struct iobus_attach_args { + bus_space_tag_t ioa_tag; + bus_addr_t ioa_base; +}; + +#endif diff --git a/sys/arch/arm26/iobus/ioc.c b/sys/arch/arm26/iobus/ioc.c new file mode 100644 index 00000000000..cdbad40105f --- /dev/null +++ b/sys/arch/arm26/iobus/ioc.c @@ -0,0 +1,529 @@ +/* $NetBSD: ioc.c,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ +/*- + * Copyright (c) 1998, 1999, 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * ioc.c - Acorn/ARM I/O Controller (Albion/VC2311/VL2311/VY86C410) + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: ioc.c,v 1.1 2000/05/09 21:56:01 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/queue.h> +#include <sys/systm.h> + +#include <machine/bus.h> +#include <machine/irq.h> +#include <machine/spl.h> + +#include <arch/arm26/arm26/cpuvar.h> +#include <arch/arm26/iobus/iobusvar.h> +#include <arch/arm26/iobus/iocvar.h> +#include <arch/arm26/iobus/iocreg.h> + +#include "locators.h" + +static int ioc_match __P((struct device *parent, struct cfdata *cf, void *aux)); +static void ioc_attach __P((struct device *parent, struct device *self, void *aux)); +static int ioc_search __P((struct device *parent, struct cfdata *cf, void *aux)); +static int ioc_print __P((void *aux, const char *pnp)); +static int ioc_irq_clock __P((void *cookie)); +static int ioc_irq_statclock __P((void *cookie)); + +struct ioc_softc { + struct device sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + struct irq_handler *sc_clkirq; + struct irq_handler *sc_sclkirq; + u_int8_t sc_ctl; +}; + +struct cfattach ioc_ca = { + sizeof(struct ioc_softc), ioc_match, ioc_attach +}; + +extern struct cfdriver ioc_cd; + +/* + * Autoconfiguration glue + */ + +static int +ioc_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + + /* + * This is tricky. Accessing non-existant devices in iobus + * space can hang the machine (MEMC datasheet section 5.3.3), + * so probes would have to be very delicate. This isn't + * _much_ of a problem with the IOC, since all machines I know + * of have exactly one. + */ + if (cf->cf_unit == 0) + return 1; + else + return 0; +} + +static void +ioc_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct ioc_softc *sc = (void *)self; + struct iobus_attach_args *ioa = aux; + bus_space_tag_t bst; + bus_space_handle_t bsh; + + sc->sc_bst = ioa->ioa_tag; + if (bus_space_map(ioa->ioa_tag, ioa->ioa_base, 0x00200000, + 0, &(sc->sc_bsh)) != 0) + panic("%s: couldn't map", sc->sc_dev.dv_xname); + bst = sc->sc_bst; + bsh = sc->sc_bsh; + /* Now we need to set up bits of the IOC */ + /* Control register: All bits high (input) is probably safe */ + ioc_ctl_write(self, 0xff, 0xff); + /* + * IRQ/FIQ: mask out all, leave clearing latched interrupts + * till someone asks. + * + * In fact, the masks will be in this state already. See + * start.c for details. + */ + bus_space_write_1(bst, bsh, IOC_IRQMSKA, 0x00); + bus_space_write_1(bst, bsh, IOC_IRQMSKB, 0x00); + bus_space_write_1(bst, bsh, IOC_FIQMSK, 0x00); + /*- + * Timers: + * Timers 0/1 are set up by ioc_initclocks (called by cpu_initclocks). + * XXX What if we need timers before then? + * Timer 2 is set up by whatever's connected to BAUD. + * Timer 3 is set up by the arckbd driver. + */ + printf("\n"); + + config_search(ioc_search, self, NULL); +} + +extern struct bus_space ioc_bs_tag; + +static int +ioc_search(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct ioc_softc *sc = (void *)parent; + struct ioc_attach_args ioc; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + + ioc.ioc_bank = cf->cf_loc[IOCCF_BANK]; + ioc.ioc_offset = cf->cf_loc[IOCCF_OFFSET]; + ioc.ioc_slow_t = bst; + bus_space_subregion(bst, bsh, (ioc.ioc_bank << IOC_BANK_SHIFT) + + (IOC_TYPE_SLOW << IOC_TYPE_SHIFT) + + (ioc.ioc_offset >> 2), + 1 << IOC_BANK_SHIFT, &ioc.ioc_slow_h); + ioc.ioc_medium_t = bst; + bus_space_subregion(bst, bsh, (ioc.ioc_bank << IOC_BANK_SHIFT) + + (IOC_TYPE_MEDIUM << IOC_TYPE_SHIFT) + + (ioc.ioc_offset >> 2), + 1 << IOC_BANK_SHIFT, &ioc.ioc_medium_h); + ioc.ioc_fast_t = bst; + bus_space_subregion(bst, bsh, (ioc.ioc_bank << IOC_BANK_SHIFT) + + (IOC_TYPE_FAST << IOC_TYPE_SHIFT) + + (ioc.ioc_offset >> 2), + 1 << IOC_BANK_SHIFT, &ioc.ioc_fast_h); + ioc.ioc_sync_t = bst; + bus_space_subregion(bst, bsh, (ioc.ioc_bank << IOC_BANK_SHIFT) + + (IOC_TYPE_SYNC << IOC_TYPE_SHIFT) + + (ioc.ioc_offset >> 2), + 1 << IOC_BANK_SHIFT, &ioc.ioc_sync_h); + if ((cf->cf_attach->ca_match)(parent, cf, &ioc) > 0) + config_attach(parent, cf, &ioc, ioc_print); + + return 0; +} + +static int +ioc_print(aux, pnp) + void *aux; + const char *pnp; +{ + struct ioc_attach_args *ioc = aux; + + if (ioc->ioc_bank != IOCCF_BANK_DEFAULT) + printf(" bank %d", ioc->ioc_bank); + if (ioc->ioc_offset != IOCCF_OFFSET_DEFAULT) + printf(" offset 0x%02x", ioc->ioc_offset); + return UNCONF; +} + +/* + * Control Register + */ + +/* + * ioc_ctl_{read,write} + * + * Functions to manipulate the IOC control register. The bottom six + * bits of the control register map to bidirectional pins on the chip. + * The output circuits are open-drain, so a pin is made an input by + * writing '1' to it. + */ + +u_int +ioc_ctl_read(self) + struct device *self; +{ + struct ioc_softc *sc = (void *)self; + + return bus_space_read_1(sc->sc_bst, sc->sc_bsh, IOC_CTL); +} + +void +ioc_ctl_write(self, value, mask) + struct device *self; + u_int value, mask; +{ + struct ioc_softc *sc = (void *)self; + int s; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + + s = splhigh(); + sc->sc_ctl = (sc->sc_ctl & ~mask) | (value & mask); + bus_space_barrier(bst, bsh, IOC_CTL, 1, BUS_BARRIER_WRITE); + bus_space_write_1(bst, bsh, IOC_CTL, sc->sc_ctl); + bus_space_barrier(bst, bsh, IOC_CTL, 1, BUS_BARRIER_WRITE); + splx(s); +} + +/* + * Interrupt handling + */ + +struct irq_handler * +ioc_irq_establish(self, irq, level, handler, cookie) + struct device *self; + int irq, level; + int handler __P((void *)); + void *cookie; +{ + /* struct ioc_softc *sc = (void *)self; */ + + return irq_establish(irq, level, handler, cookie); +} + +/* + * Find out if an interrupt line is currently active + */ + +int +ioc_irq_status(self, irq) + struct device *self; + int irq; +{ + struct ioc_softc *sc = (void *)self; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + + if (irq < 8) + return (bus_space_read_1(bst, bsh, IOC_IRQSTA) & + IOC_IRQA_BIT(irq)) != 0; + else + return (bus_space_read_1(bst, bsh, IOC_IRQSTB) & + IOC_IRQB_BIT(irq)) != 0; +} + +u_int32_t +ioc_irq_status_full(self) + struct device *self; +{ + struct ioc_softc *sc = (void *)self; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + +#if 0 /* XXX */ + printf("IRQ mask: 0x%x\n", + bus_space_read_1(bst, bsh, IOC_IRQMSKA) | + (bus_space_read_1(bst, bsh, IOC_IRQMSKB) << 8)); +#endif + return bus_space_read_1(bst, bsh, IOC_IRQSTA) | + (bus_space_read_1(bst, bsh, IOC_IRQSTB) << 8); +} + +void +ioc_irq_setmask(self, mask) + struct device *self; + u_int32_t mask; +{ + struct ioc_softc *sc = (void *)self; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + + bus_space_write_1(bst, bsh, IOC_IRQMSKA, mask & 0xff); + bus_space_write_1(bst, bsh, IOC_IRQMSKB, (mask >> 8) & 0xff); +} + +void +ioc_irq_waitfor(self, irq) + struct device *self; + int irq; +{ + + while (!ioc_irq_status(self, irq)); +} + +void +ioc_irq_clear(self, mask) + struct device *self; + int mask; +{ + struct ioc_softc *sc = (void *)self; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + + bus_space_write_1(bst, bsh, IOC_IRQRQA, mask); +} + +#if 0 + +/* + * ioc_get_irq_level: + * + * Find out the current level of an edge-triggered interrupt line. + * Useful for the VIDC driver to know if it's in VSYNC if nothing + * else. + */ + +int ioc_get_irq_level(self, irq) + struct device *self; + int irq; +{ + struct ioc_softc *sc = (void *)self; + + switch (irq) { + case IOC_IRQ_IF: + return (bus_space_read_1(sc->sc_bst, sc->sc_bsh, IOC_CTL) & + IOC_CTL_NIF) != 0; + case IOC_IRQ_IR: + return (bus_space_read_1(sc->sc_bst, sc->sc_bsh, IOC_CTL) & + IOC_CTL_IR) != 0; + } + panic("ioc_get_irq_level called for irq %d, which isn't edge-triggered", + irq); +} + +#endif /* 0 */ + + +/* + * Counters + */ + +void ioc_counter_start(self, counter, value) + struct device *self; + int counter, value; +{ + struct ioc_softc *sc = (void *)self; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + int tlow, thigh, tgo; + + switch (counter) { + case 0: tlow = IOC_T0LOW; thigh = IOC_T0HIGH; tgo = IOC_T0GO; break; + case 1: tlow = IOC_T1LOW; thigh = IOC_T1HIGH; tgo = IOC_T1GO; break; + case 2: tlow = IOC_T2LOW; thigh = IOC_T2HIGH; tgo = IOC_T2GO; break; + case 3: tlow = IOC_T3LOW; thigh = IOC_T3HIGH; tgo = IOC_T3GO; break; + default: panic("%s: ioc_counter_start: bad counter (%d)", + self->dv_xname, counter); + } + bus_space_barrier(bst, bsh, tlow, tgo - tlow + 1, BUS_BARRIER_WRITE); + bus_space_write_1(bst, bsh, tlow, value & 0xff); + bus_space_write_1(bst, bsh, thigh, value >> 8 & 0xff); + bus_space_barrier(bst, bsh, tlow, tgo - tlow + 1, BUS_BARRIER_WRITE); + bus_space_write_1(bst, bsh, tgo, 0); + bus_space_barrier(bst, bsh, tlow, tgo - tlow, BUS_BARRIER_WRITE); +} + +/* Cache to save microtime recalculating it */ +static int t0_count; + +void +cpu_initclocks() +{ + struct device *self; + struct ioc_softc *sc; + +#ifdef DIAGNOSTIC + if (ioc_cd.cd_ndevs <= 0 || ioc_cd.cd_devs[0] == NULL) + panic("cpu_initclocks: no ioc0"); +#endif + self = ioc_cd.cd_devs[0]; + sc = (struct ioc_softc *)self; + stathz = hz; /* XXX what _should_ it be? */ + + if (hz == 0 || IOC_TIMER_RATE % hz != 0 || + (t0_count = IOC_TIMER_RATE / hz) > 65535) + panic("ioc_initclocks: Impossible clock rate: %d Hz", hz); + ioc_counter_start(self, 0, t0_count); + sc->sc_clkirq = ioc_irq_establish(self, IOC_IRQ_TM0, IPL_CLOCK, + ioc_irq_clock, NULL); + printf("%s: %d Hz clock interrupting at %s\n", + self->dv_xname, hz, irq_string(sc->sc_clkirq)); + irq_enable(sc->sc_clkirq); + + if (stathz) { + setstatclockrate(stathz); + sc->sc_sclkirq = ioc_irq_establish(self, IOC_IRQ_TM1, + IPL_STATCLOCK, + ioc_irq_statclock, NULL); + printf("%s: %d Hz statclock interrupting at %s\n", + self->dv_xname, stathz, irq_string(sc->sc_sclkirq)); + irq_enable(sc->sc_sclkirq); + } +} + +static int +ioc_irq_clock(cookie) + void *cookie; +{ + + hardclock(cookie); + return IRQ_HANDLED; +} + +static int +ioc_irq_statclock(cookie) + void *cookie; +{ + + statclock(cookie); + return IRQ_HANDLED; +} + +void +setstatclockrate(hzrate) + int hzrate; +{ + struct device *self; + int count; + +#ifdef DIAGNOSTIC + if (ioc_cd.cd_ndevs <= 0 || ioc_cd.cd_devs[0] == NULL) + panic("setstatclockrate: no ioc0"); +#endif + self = ioc_cd.cd_devs[0]; + + /* XXX This currently restarts the counter -- should it? */ + if (hzrate == 0 || IOC_TIMER_RATE % hzrate != 0 || + (count = IOC_TIMER_RATE / hz) > 65535) + panic("Impossible statclock rate: %d Hz", hzrate); + ioc_counter_start(self, 1, count); +} + +void +microtime(tv) + struct timeval *tv; +{ + struct device *self; + struct ioc_softc *sc; + bus_space_tag_t bst; + bus_space_handle_t bsh; + int t0, s, intbefore, intafter; + +#ifdef DIAGNOSTIC + if (ioc_cd.cd_ndevs <= 0 || ioc_cd.cd_devs[0] == NULL) + panic("microtime: no ioc0"); +#endif + self = ioc_cd.cd_devs[0]; + sc = (struct ioc_softc *)self; + + bst = sc->sc_bst; + bsh = sc->sc_bsh; + + s = splclock(); + + *tv = time; + + intbefore = ioc_irq_status(self, IOC_IRQ_TM0); + bus_space_write_1(bst, bsh, IOC_T0LATCH, 0); + t0 = bus_space_read_1(bst, bsh, IOC_T0LOW); + t0 += bus_space_read_1(bst, bsh, IOC_T0HIGH) << 8; + intafter = ioc_irq_status(self, IOC_IRQ_TM0); + + splx(s); + + /* + * If there's a timer interrupt pending, the counter has + * probably wrapped around once since "time" was last updated. + * Things are complicated by the fact that this could happen + * while we're trying to work out the time. We include some + * heuristics to spot this. + */ + + if (intbefore || (intafter && t0 < t0_count / 2)) + t0 -= t0_count; + + tv->tv_usec += (t0_count - t0) / (IOC_TIMER_RATE / 1000000); + + while (tv->tv_usec > 1000000) { + tv->tv_sec += 1; + tv->tv_usec -= 1000000; + } +} + +void +delay(u_int usecs) +{ + + if (usecs <= 10 || cold) + cpu_delayloop(usecs * cpu_delay_factor); + else { + struct timeval start, gap, now, end; + + microtime(&start); + gap.tv_sec = usecs / 1000000; + gap.tv_usec = usecs % 1000000; + timeradd(&start, &gap, &end); + do { + microtime(&now); + } while (timercmp(&now, &end, <)); + } + +} diff --git a/sys/arch/arm26/iobus/iocreg.h b/sys/arch/arm26/iobus/iocreg.h new file mode 100644 index 00000000000..c5c3f35144b --- /dev/null +++ b/sys/arch/arm26/iobus/iocreg.h @@ -0,0 +1,153 @@ +/* $NetBSD: iocreg.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ + +/* + * Copyright (c) 1997 Ben Harris. + * Copyright (c) 1994 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + */ + +/* + * iocreg.h - Acorn IOC (Albion/VC2311) registers + * + * Based on arch/arm32/include/iomd.h 1.7: + * Created : 18/09/94 + * Based on kate/display/iomd.h + */ + +#ifndef _ARM26_IOCREG_H +#define _ARM26_IOCREG_H + +/* + * These addresses are intended to be inputs to bus_space functions, + * and as such bits 0-4 here map to A[2:6] on the IOC. + */ + +/* Read Write */ +#define IOC_CTL 0x00 /* Control Control */ +#define IOC_KBDDAT 0x01 /* Kbd receive Kbd send */ + +#define IOC_IRQSTA 0x04 /* IRQ status A - */ +#define IOC_IRQRQA 0x05 /* IRQ request A IRQ clear */ +#define IOC_IRQMSKA 0x06 /* IRQ mask A IRQ mask A */ + +#define IOC_IRQSTB 0x08 /* IRQ status B - */ +#define IOC_IRQRQB 0x09 /* IRQ request B - */ +#define IOC_IRQMSKB 0x0a /* IRQ mask B IRQ mask B */ + +#define IOC_FIQST 0x0c /* FIQ status - */ +#define IOC_FIQRQ 0x0d /* FIQ request - */ +#define IOC_FIQMSK 0x0e /* FIQ mask FIQ mask */ + +#define IOC_T0LOW 0x10 /* T0 count low T0 latch low */ +#define IOC_T0HIGH 0x11 /* T0 count high T0 latch high */ +#define IOC_T0GO 0x12 /* - T0 go command */ +#define IOC_T0LATCH 0x13 /* - T0 latch command */ + +#define IOC_T1LOW 0x14 /* T1 count low T1 latch low */ +#define IOC_T1HIGH 0x15 /* T1 count high T1 latch high */ +#define IOC_T1GO 0x16 /* - T1 go command */ +#define IOC_T1LATCH 0x17 /* - T1 latch command */ + +#define IOC_T2LOW 0x18 /* T2 count low T2 latch low */ +#define IOC_T2HIGH 0x19 /* T2 count high T2 latch high */ +#define IOC_T2GO 0x1a /* - T2 go command */ +#define IOC_T2LATCH 0x1b /* - T2 latch command */ + +#define IOC_T3LOW 0x1c /* T3 count low T3 latch low */ +#define IOC_T3HIGH 0x1d /* T3 count high T3 latch high */ +#define IOC_T3GO 0x1e /* - T3 go command */ +#define IOC_T3LATCH 0x1f /* - T3 latch command */ + +#define IOC_SIZE 0x20 /* Total amount of bus space used by the IOC */ + +/* Control register bits (should most of these be defined here?) */ +#define IOC_CTL_SDA 0x01 /* IIC serial data */ +#define IOC_CTL_SCL 0x02 /* IIC serial clock */ +#define IOC_CTL_FDREADY 0x04 /* Floppy disc ready */ +#define IOC_CTL_SMUTE 0x20 /* Speaker mute */ +#define IOC_CTL_LPTACK 0x40 /* Printer acknowledge */ +#define IOC_CTL_FLYBACK 0x80 /* Video flyback */ + +/* Internal control register bits */ +/* These give the current state of the edge-sensitive IRQ lines */ +#define IOC_CTL_NIF 0x04 /* Set if IF* is high (IRQ 2) */ +#define IOC_CTL_IR 0x08 /* Set if IR is high (IRQ 3) */ + +/* IOC definitions of interrupt sources (independent of machine) */ +/* Hmm Interrupt numbers or masks? Numbers for now. */ +#define IOC_IRQ_IL6 0 /* Active low input */ +#define IOC_IRQ_IL7 1 /* Active low input */ +#define IOC_IRQ_IF 2 /* Falling edge-triggered */ +#define IOC_IRQ_IR 3 /* Rising edge-triggered */ +#define IOC_IRQ_POR 4 /* Power-on reset */ +#define IOC_IRQ_TM0 5 /* Timer 0 reloaded */ +#define IOC_IRQ_TM1 6 /* Timer 1 reloaded */ +#define IOC_IRQ_1 7 /* Always interrupt */ +#define IOC_IRQ_IL0 8 /* Active low input */ +#define IOC_IRQ_IL1 9 /* Active low input */ +#define IOC_IRQ_IL2 10 /* Active low input */ +#define IOC_IRQ_IL3 11 /* Active low input */ +#define IOC_IRQ_IL4 12 /* Active low input */ +#define IOC_IRQ_IL5 13 /* Active low input */ +#define IOC_IRQ_STX 14 /* KART transmit finished */ +#define IOC_IRQ_SRX 15 /* KART receive finished */ +#define IOC_IRQA_BIT(n) ((n) < 8 ? 1 << (n) : 0) +#define IOC_IRQB_BIT(n) ((n) < 8 ? 0 : 1 << ((n) - 8)) + +#define IOC_IRQ_CLEARABLE_MASK 0x7c + +/* FIQ sources */ +#define IOC_FIQ_FH0 0 /* Active high input */ +#define IOC_FIQ_FH1 1 /* Active high input */ +#define IOC_FIQ_FL 2 /* Active low input */ +#define IOC_FIQ_C3 3 /* Active low input (also ctl reg) */ +#define IOC_FIQ_C4 4 /* Active low input (also ctl reg) */ +#define IOC_FIQ_C5 5 /* Active low input (also ctl reg) */ +#define IOC_FIQ_IL0 6 /* Active low input (also IRQ) */ +#define IOC_FIQ_1 7 /* Always interrupt */ +#define IOC_FIQ_BIT(n) (1 << (n)) + +/* Cycle types */ +#define IOC_TYPE_SLOW 0 +#define IOC_TYPE_MEDIUM 1 +#define IOC_TYPE_FAST 2 +#define IOC_TYPE_SYNC 3 + +/* Counter decrement rate */ +#define IOC_TIMER_RATE 2000000 /* 2 MHz */ + +/* Archimedes-specific defines */ +#define IOC_TYPE_SHIFT (19 - 2) /* A[20:19] -> T[1:0] */ +#define IOC_BANK_SHIFT (16 - 2) /* A[18:16] -> B[2:0] */ + +#endif diff --git a/sys/arch/arm26/iobus/iocvar.h b/sys/arch/arm26/iobus/iocvar.h new file mode 100644 index 00000000000..12ccd7346f5 --- /dev/null +++ b/sys/arch/arm26/iobus/iocvar.h @@ -0,0 +1,72 @@ +/* $NetBSD: iocvar.h,v 1.1 2000/05/09 21:56:01 bjh21 Exp $ */ +/*- + * Copyright (c) 1998, 1999 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * iocvar.h - aspects of the IOC driver that are visible to the world. + */ + +#ifndef _ARM26_IOCVAR_H +#define _ARM26_IOCVAR_H + +#include <machine/irq.h> + +/* Structure passed to children of an IOC */ + +struct ioc_attach_args { + /* Means of accessing the device at various speeds */ + bus_space_tag_t ioc_fast_t; + bus_space_handle_t ioc_fast_h; + bus_space_tag_t ioc_medium_t; + bus_space_handle_t ioc_medium_h; + bus_space_tag_t ioc_slow_t; + bus_space_handle_t ioc_slow_h; + bus_space_tag_t ioc_sync_t; + bus_space_handle_t ioc_sync_h; + int ioc_bank; /* only for ioc_print */ + int ioc_offset; +}; + +/* Public IOC functions */ + +extern u_int ioc_ctl_read __P((struct device *self)); +extern void ioc_ctl_write __P((struct device *self, u_int value, u_int mask)); + +extern struct irq_handler *ioc_irq_establish __P((struct device *self, int irq, int level, int handler __P((void *)), void *cookie)); +extern int ioc_irq_status __P((struct device *self, int irq)); +extern void ioc_irq_waitfor __P((struct device *self, int irq)); +extern void ioc_irq_clear __P((struct device *self, int mask)); +extern u_int32_t ioc_irq_status_full __P((struct device *self)); +extern void ioc_irq_setmask __P((struct device *self, u_int32_t mask)); + +extern void ioc_counter_start __P((struct device *self, int counter, int value)); + +extern void ioc_initclocks __P((struct device *self)); +extern void ioc_setstatclockrate __P((struct device *self, int hzrate)); +extern void ioc_microtime __P((struct device *self, struct timeval *tv)); + +#endif diff --git a/sys/arch/arm26/ioc/arckbd.c b/sys/arch/arm26/ioc/arckbd.c new file mode 100644 index 00000000000..5823f68fe05 --- /dev/null +++ b/sys/arch/arm26/ioc/arckbd.c @@ -0,0 +1,740 @@ +/* $NetBSD: arckbd.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ +/*- + * Copyright (c) 1998, 1999, 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * arckbd.c - Archimedes keyboard driver + */ + +/* + * Most of the information used to write this driver came from the + * A3000 Technical Reference Manual (ISBN 1-85250-074-3). + * + * We keep a queue of one command in the softc for use by the recieve + * interrupt handler in case it finds the KART is already transmitting + * a command (presumably as a consequence of a user request) when it + * wants to. I think this is safe in all cases, and it will never + * happen more than once at a time (I hope). + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: arckbd.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/proc.h> +#include <sys/syslog.h> +#include <sys/systm.h> + +#include <machine/bus.h> +#include <machine/irq.h> +#include <machine/spl.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsmousevar.h> + +#include <arch/arm26/iobus/iocreg.h> +#include <arch/arm26/iobus/iocvar.h> +#include <arch/arm26/ioc/arckbdreg.h> +#include <arch/arm26/ioc/arckbdvar.h> + +#include "locators.h" + +/* XXX These should move into sys/dev/wscons/wsconsio.h */ +#define WSKBD_TYPE_ARCHIMEDES 42 +#define WSMOUSE_TYPE_ARCHIMEDES 42 + +/* #define ARCKBD_DEBUG */ + +enum arckbd_state { + AS_HRST, AS_RAK1, AS_RAK2, /* reset protocol */ + AS_IDLE, /* idle, waiting for data */ + AS_KDDA, AS_KUDA, AS_MDAT /* Receiving two-byte message */ +}; + +static const char *arckbd_statenames[] = { + "hrst", "rak1", "rak2", "idle", "kdda", "kuda", "mdat" +}; + +static int arckbd_match __P((struct device *parent, struct cfdata *cf, void *aux)); +static void arckbd_attach __P((struct device *parent, struct device *self, void *aux)); +static kbd_t arckbd_pick_layout __P((int kbid)); +static int arcwskbd_match __P((struct device *parent, struct cfdata *cf, void *aux)); +static void arcwskbd_attach __P((struct device *parent, struct device *self, void *aux)); +static int arcwsmouse_match __P((struct device *parent, struct cfdata *cf, void *aux)); +static void arcwsmouse_attach __P((struct device *parent, struct device *self, void *aux)); + +static int arckbd_rint __P((void *self)); +static int arckbd_xint __P((void *self)); +static void arckbd_mousemoved __P((struct device *self, int byte1, int byte2)); +static void arckbd_keyupdown __P((struct device *self, int byte1, int byte2)); +static int arckbd_send __P((struct device *self, int data, enum arckbd_state newstate, int waitok)); + +static int arckbd_enable __P((void *cookie, int on)); +static int arckbd_led_encode __P((int)); +static int arckbd_led_decode __P((int)); +static void arckbd_set_leds __P((void *cookie, int new_state)); +static int arckbd_ioctl __P((void *cookie, u_long cmd, caddr_t data, int flag, struct proc *p)); +static void arckbd_getc __P((void *cookie, u_int *typep, int *valuep)); +static void arckbd_pollc __P((void *cookie, int poll)); +static int arcmouse_enable __P((void *cookie)); +static int arcmouse_ioctl __P((void *cookie, u_long cmd, caddr_t data, int flag, struct proc *p)); +static void arcmouse_disable __P((void *cookie)); + +struct arckbd_softc { + struct device sc_dev; + bus_space_tag_t sc_bst; + bus_space_handle_t sc_bsh; + u_int sc_mouse_buttons; + enum arckbd_state sc_state; + u_char sc_byteone; + u_char sc_kbid; + struct device *sc_wskbddev; + struct device *sc_wsmousedev; + struct wskbd_mapdata sc_mapdata; + int sc_cmdqueue; /* Single-command queue */ + enum arckbd_state sc_statequeue; + int sc_cmdqueued; + int sc_flags; + int sc_leds; + u_int sc_poll_type; + int sc_poll_value; + struct irq_handler *sc_xirq; + struct irq_handler *sc_rirq; +}; + +#define AKF_WANTKBD 0x01 +#define AKF_WANTMOUSE 0x02 +#define AKF_SENTRQID 0x04 +#define AKF_SENTLEDS 0x08 +#define AKF_POLLING 0x10 + +struct cfattach arckbd_ca = { + sizeof(struct arckbd_softc), arckbd_match, arckbd_attach +}; + +/* + * Internal devices used because arckbd can't be both a wskbddev and a + * wsmousedev. I suspect the right way to do this is through an + * "attach wskbd at arckbd with wskbd_arckbd" type thing, but we can't + * as the size of a wskbd_softc isn't public. Come to think of it, + * this isn't very evil -- I just don't like having yet another line + * of configuration. + */ + +struct cfattach arcwskbd_ca = { + sizeof(struct device), arcwskbd_match, arcwskbd_attach +}; + +struct cfattach arcwsmouse_ca = { + sizeof(struct device), arcwsmouse_match, arcwsmouse_attach +}; + +struct arckbd_attach_args { + enum { ARCKBD_KBDDEV, ARCKBD_MOUSEDEV } aka_devtype; + struct wskbddev_attach_args aka_wskbdargs; + struct wsmousedev_attach_args aka_wsmouseargs; +}; + +extern struct cfdriver arckbd_cd, arcwskbd_cd, arcwsmouse_cd; + +static struct wskbd_accessops arckbd_accessops = { + arckbd_enable, arckbd_set_leds, arckbd_ioctl +}; + +static struct wskbd_consops arckbd_consops = { + arckbd_getc, arckbd_pollc +}; + +static struct wsmouse_accessops arcmouse_accessops = { + arcmouse_enable, arcmouse_ioctl, arcmouse_disable +}; + +/* ARGSUSED */ +static int +arckbd_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + + /* Assume presence for now */ + return 1; +} + +static void +arckbd_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct arckbd_softc *sc = (void *)self; + struct ioc_attach_args *ioc = aux; + bus_space_tag_t bst; + bus_space_handle_t bsh; + struct arckbd_attach_args aka; + + bst = sc->sc_bst = ioc->ioc_fast_t; + bsh = sc->sc_bsh = ioc->ioc_fast_h; + + printf("\n"); + sc->sc_rirq = ioc_irq_establish(sc->sc_dev.dv_parent, IOC_IRQ_SRX, + IPL_TTY, arckbd_rint, self); + printf("%s: interrupting at %s (rx)", self->dv_xname, + irq_string(sc->sc_rirq)); + sc->sc_xirq = ioc_irq_establish(sc->sc_dev.dv_parent, IOC_IRQ_STX, + IPL_TTY, arckbd_xint, self); + printf(" and %s (tx)", irq_string(sc->sc_xirq)); + irq_enable(sc->sc_rirq); + + /* Initialisation of IOC KART per IOC Data Sheet section 6.2.3. */ + + /* Set up IOC counter 3 */ + /* k_BAUD = 1/((latch+1)*16) MHz */ + ioc_counter_start(parent, 3, 62500 / ARCKBD_BAUD - 1); + + /* Read from Rx register and discard. */ + (void)bus_space_read_1(bst, bsh, 0); + + /* Kick the keyboard into life */ + arckbd_send(self, ARCKBD_HRST, AS_HRST, 0); + + sc->sc_mapdata = arckbd_mapdata_default; + sc->sc_mapdata.layout = KB_UK; /* Reasonable default */ + + /* XXX set the LEDs to a known state? (or will wskbd do this?) */ + + /* Attach the wskbd console */ + arckbd_cnattach(self); + + printf("\n"); + + /* Attach the dummy drivers */ + aka.aka_wskbdargs.console = 1; /* XXX FIXME */ + aka.aka_wskbdargs.keymap = &sc->sc_mapdata; + aka.aka_wskbdargs.accessops = &arckbd_accessops; + aka.aka_wskbdargs.accesscookie = self; + aka.aka_wsmouseargs.accessops = &arcmouse_accessops; + aka.aka_wsmouseargs.accesscookie = self; + aka.aka_devtype = ARCKBD_KBDDEV; + config_found(self, &aka, NULL); + aka.aka_devtype = ARCKBD_MOUSEDEV; + config_found(self, &aka, NULL); +} + +static kbd_t +arckbd_pick_layout(kbid) + int kbid; +{ + int i; + + for (i = 0; arckbd_kbidtab[i].kbid != 0; i++) { + if (arckbd_kbidtab[i].kbid == kbid) + return arckbd_kbidtab[i].layout; + } + return KB_UK; +} + + +/* ARGSUSED */ +static int +arcwskbd_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct arckbd_attach_args *aka = aux; + + if (aka->aka_devtype == ARCKBD_KBDDEV) + return 1; + return 0; +} + +/* ARGSUSED */ +static int +arcwsmouse_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct arckbd_attach_args *aka = aux; + + if (aka->aka_devtype == ARCKBD_MOUSEDEV) + return 1; + return 0; +} + +static void +arcwskbd_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct arckbd_attach_args *aka = aux; + struct arckbd_softc *sc = (void *)parent; + + printf("\n"); + + sc->sc_wskbddev = config_found(self, &(aka->aka_wskbdargs), + wskbddevprint); +} + +static void +arcwsmouse_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct arckbd_attach_args *aka = aux; + struct arckbd_softc *sc = (void *)parent; + + printf("\n"); + + sc->sc_wsmousedev = config_found(self, &(aka->aka_wsmouseargs), + wsmousedevprint); +} + + +/* + * We don't really _need_ a console keyboard before + * autoconfiguration's finished, so for now this function's written to + * be called from arckbd_attach. The console functions should still + * try not to rely on much, and perhaps one day we should make it + * happen in consinit instead. + */ + +void +arckbd_cnattach(self) + struct device *self; +{ + struct arckbd_softc *sc = (void*)self; + + wskbd_cnattach(&arckbd_consops, sc, &arckbd_mapdata_default); +} + +static void +arckbd_getc(cookie, typep, valuep) + void *cookie; + u_int *typep; + int *valuep; +{ + struct arckbd_softc *sc = cookie; + int s; + + if (!(sc->sc_flags & AKF_POLLING)) + panic("%s: arckbd_getc called with polling disabled", + sc->sc_dev.dv_xname); + while (sc->sc_poll_type == 0) { + if (ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX)) + arckbd_xint(&sc->sc_dev); + if (ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_SRX)) + arckbd_rint(&sc->sc_dev); + } + s = spltty(); + *typep = sc->sc_poll_type; + *valuep = sc->sc_poll_value; + sc->sc_poll_type = 0; + sc->sc_poll_value = 0; + splx(s); +} + +static void +arckbd_pollc(cookie, poll) + void *cookie; + int poll; +{ + struct arckbd_softc *sc = cookie; + int s; + + s = spltty(); + if (poll) { + sc->sc_flags |= AKF_POLLING; + irq_disable(sc->sc_rirq); + irq_disable(sc->sc_xirq); + } else { + sc->sc_flags &= ~AKF_POLLING; + irq_enable(sc->sc_rirq); + irq_enable(sc->sc_xirq); + } + splx(s); +} + +static int +arckbd_send(self, data, newstate, waitok) + struct device *self; + int data, waitok; + enum arckbd_state newstate; +{ + struct arckbd_softc *sc = (void *)self; + int s, res; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + + s = spltty(); + if (waitok) { + while (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX)) + if ((sc->sc_flags & AKF_POLLING) == 0) { + res = tsleep(arckbd_send, PWAIT, "kbdsend", 0); + if (res != 0) + return res; + } + } else if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX)) { + if (sc->sc_cmdqueued) + panic("%s: queue overflow", sc->sc_dev.dv_xname); + else { + sc->sc_cmdqueue = data; + sc->sc_statequeue = newstate; + sc->sc_cmdqueued = 1; + return 0; + } + } + bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_WRITE); + bus_space_write_1(bst, bsh, 0, data); + bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_WRITE); + sc->sc_state = newstate; +#ifdef ARCKBD_DEBUG + log(LOG_DEBUG, "%s: sent 0x%02x. now in state %s\n", + sc->sc_dev.dv_xname, data, arckbd_statenames[newstate]); +#endif + wakeup(&sc->sc_state); + splx(s); + if ((sc->sc_flags & AKF_POLLING) == 0) + irq_enable(sc->sc_xirq); + return 0; +} + +static int +arckbd_xint(cookie) + void *cookie; +{ + struct arckbd_softc *sc = cookie; + + if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX)) { + printf("%s: Stray tx interrupt\n", sc->sc_dev.dv_xname); + return IRQ_NOT_HANDLED; + } + irq_disable(sc->sc_xirq); + /* First, process queued commands (acks from the last receive) */ + if (sc->sc_cmdqueued) { + sc->sc_cmdqueued = 0; + arckbd_send(&sc->sc_dev, sc->sc_cmdqueue, sc->sc_statequeue, 0); + } else if (sc->sc_state == AS_IDLE) { + /* Do things that need doing after a reset */ + if (!(sc->sc_flags & AKF_SENTRQID)) { + arckbd_send(&sc->sc_dev, ARCKBD_RQID, AS_IDLE, 0); + sc->sc_flags |= AKF_SENTRQID; + } else if (!(sc->sc_flags & AKF_SENTLEDS)) { + arckbd_send(&sc->sc_dev, ARCKBD_LEDS | sc->sc_leds, + AS_IDLE, 0); + sc->sc_flags |= AKF_SENTLEDS; + } + } else if ((sc->sc_flags & AKF_POLLING) == 0) + wakeup(&arckbd_send); + return IRQ_HANDLED; +} + +static int +arckbd_rint(cookie) + void *cookie; +{ + struct device *self = cookie; + struct arckbd_softc *sc = (void *)self; + bus_space_tag_t bst = sc->sc_bst; + bus_space_handle_t bsh = sc->sc_bsh; + int data; + + if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_SRX)) { + printf("%s: Stray rx interrupt\n", sc->sc_dev.dv_xname); + return IRQ_NOT_HANDLED; + } + bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_READ); + data = bus_space_read_1(bst, bsh, 0); + bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_READ); + /* Reset protocol */ +#ifdef ARCKBD_DEBUG + log(LOG_DEBUG, "%s: got 0x%02x in state %s\n", self->dv_xname, data, + arckbd_statenames[sc->sc_state]); +#endif + if (data == ARCKBD_HRST && sc->sc_state == AS_HRST) + arckbd_send(self, ARCKBD_RAK1, AS_RAK1, 0); + else if (data == ARCKBD_RAK1 && + (sc->sc_state == AS_RAK1 || sc->sc_state == AS_HRST)) + arckbd_send(self, ARCKBD_RAK2, AS_RAK2, 0); + else if (data == ARCKBD_RAK2 && sc->sc_state == AS_RAK2) + arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0); + + /* + * Note that for data messages, we acknowledge first and + * _then_ process the data. This is important because the + * processing may end up trying to use the keyboard in polled + * mode (e.g. through DDB) and we'd like its state to be + * self-consistent. + */ + + /* Mouse data */ + else if (ARCKBD_IS_MDAT(data) && sc->sc_state == AS_IDLE) { + arckbd_send(self, ARCKBD_BACK, AS_MDAT, 0); + sc->sc_byteone = data; + } else if (ARCKBD_IS_MDAT(data) && sc->sc_state == AS_MDAT) { + arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0); + arckbd_mousemoved(self, sc->sc_byteone, data); + } + + /* Key down data */ + else if (ARCKBD_IS_KDDA(data) && sc->sc_state == AS_IDLE) { + arckbd_send(self, ARCKBD_BACK, AS_KDDA, 0); + sc->sc_byteone = data; + } else if (ARCKBD_IS_KDDA(data) && sc->sc_state == AS_KDDA) { + arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0); + arckbd_keyupdown(self, sc->sc_byteone, data); + } + + /* Key up data */ + else if (ARCKBD_IS_KUDA(data) && sc->sc_state == AS_IDLE) { + arckbd_send(self, ARCKBD_BACK, AS_KUDA, 0); + sc->sc_byteone = data; + } else if (ARCKBD_IS_KUDA(data) && sc->sc_state == AS_KUDA) { + arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0); + arckbd_keyupdown(self, sc->sc_byteone, data); + } + + /* Other cruft */ + else if (ARCKBD_IS_KBID(data)) { + arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0); + if (sc->sc_kbid != data) { + printf("%s: layout %d\n", + self->dv_xname, data & ~ARCKBD_KBID); + sc->sc_kbid = data; + } + } else if (ARCKBD_IS_PDAT(data)) + /* unused -- ignore it */; + else { + /* Protocol error */ + log(LOG_WARNING, "%s: protocol error: got 0x%02x in state %s\n", + self->dv_xname, data, arckbd_statenames[sc->sc_state]); + arckbd_send(self, ARCKBD_HRST, AS_HRST, 0); + } + return IRQ_HANDLED; +} + +static void +arckbd_mousemoved(self, byte1, byte2) + struct device *self; + int byte1, byte2; +{ + struct arckbd_softc *sc = (void *)self; + int dx, dy; + + if (sc->sc_wsmousedev != NULL) { + /* deltas are 7-bit signed */ + dx = byte1 < 0x40 ? byte1 : byte1 - 0x80; + dy = byte2 < 0x40 ? byte2 : byte2 - 0x80; + wsmouse_input(sc->sc_wsmousedev, + sc->sc_mouse_buttons, dx, dy, 0, + WSMOUSE_INPUT_DELTA); + } +} + +static void +arckbd_keyupdown(self, byte1, byte2) + struct device *self; + int byte1, byte2; +{ + struct arckbd_softc *sc = (void *)self; + u_int type; + int value; + + if ((byte1 & 0x0f) == 7) { + /* Mouse button event */ + /* + * This is all very silly, as the wsmouse driver then + * differentiates the button state to see if there's + * an event worth passing to the user. + * + * Oh well, at least NetBSD and Acorn number their + * mouse buttons the same way. + */ + if (ARCKBD_IS_KDDA(byte1)) + sc->sc_mouse_buttons |= (1 << (byte2 & 0x0f)); + else + sc->sc_mouse_buttons &= ~(1 << (byte2 & 0x0f)); + if (sc->sc_wsmousedev != NULL) + wsmouse_input(sc->sc_wsmousedev, sc->sc_mouse_buttons, + 0, 0, 0, WSMOUSE_INPUT_DELTA); + } else { + type = ARCKBD_IS_KDDA(byte1) ? + WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; + value = ((byte1 & 0x0f) << 4) | (byte2 & 0x0f); + if (sc->sc_flags & AKF_POLLING) { + sc->sc_poll_type = type; + sc->sc_poll_value = value; + } else if (sc->sc_wskbddev != NULL) + wskbd_input(sc->sc_wskbddev, type, value); + } +} + +/* + * Keyboard access functions + */ + +static int +arckbd_enable(cookie, on) + void *cookie; + int on; +{ + struct arckbd_softc *sc = cookie; + + if (on) { + sc->sc_flags |= AKF_WANTKBD; + /* XXX send RQMP? */ + } else + sc->sc_flags &= ~ AKF_WANTKBD; + return 0; +} + +static int +arckbd_led_encode(wsleds) + int wsleds; +{ + int arcleds; + + arcleds = 0; + if (wsleds & WSKBD_LED_CAPS) + arcleds |= ARCKBD_LEDS_CAPSLOCK; + if (wsleds & WSKBD_LED_NUM) + arcleds |= ARCKBD_LEDS_NUMLOCK; + if (wsleds & WSKBD_LED_SCROLL) + arcleds |= ARCKBD_LEDS_SCROLLLOCK; + /* No "compose" LED */ + return arcleds; +} + +static int +arckbd_led_decode(arcleds) + int arcleds; +{ + int wsleds; + + wsleds = 0; + if (arcleds & ARCKBD_LEDS_CAPSLOCK) + wsleds |= WSKBD_LED_CAPS; + if (arcleds & ARCKBD_LEDS_NUMLOCK) + wsleds |= WSKBD_LED_NUM; + if (arcleds & ARCKBD_LEDS_SCROLLLOCK) + wsleds |= WSKBD_LED_SCROLL; + /* No "compose" LED */ + return wsleds; +} + +/* + * Set the LEDs to the requested state. + * + * Be warned: This function gets called from interrupts. + */ +static void +arckbd_set_leds(cookie, new_state) + void *cookie; + int new_state; +{ + struct arckbd_softc *sc = cookie; + int s; + + s = spltty(); + sc->sc_leds = arckbd_led_encode(new_state); + if (arckbd_send(cookie, ARCKBD_LEDS | sc->sc_leds, AS_IDLE, 0) == 0) + sc->sc_flags |= AKF_SENTLEDS; + splx(s); +} + +/* ARGSUSED */ +static int +arckbd_ioctl(cookie, cmd, data, flag, p) + void *cookie; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct arckbd_softc *sc = cookie; + + switch (cmd) { + case WSKBDIO_GTYPE: + *(int *)data = WSKBD_TYPE_ARCHIMEDES; + return 0; + case WSKBDIO_SETLEDS: + arckbd_set_leds(sc, *(int *)data); + return 0; + case WSKBDIO_GETLEDS: + *(int *)data = arckbd_led_decode(sc->sc_leds); + return 0; + } + return -1; +} + +/* + * Mouse access functions + */ + +static int +arcmouse_enable(cookie) + void *cookie; +{ + struct arckbd_softc *sc = cookie; + + sc->sc_flags |= AKF_WANTMOUSE; + /* XXX send RQMP */ + return 0; +} + +/* ARGSUSED */ +static int +arcmouse_ioctl(cookie, cmd, data, flag, p) + void *cookie; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ +/* struct arckbd_softc *sc = cookie; */ + + switch (cmd) { + case WSMOUSEIO_GTYPE: + *(int *)data = WSMOUSE_TYPE_ARCHIMEDES; + return 0; + } + return -1; +} + +static void +arcmouse_disable(cookie) + void *cookie; +{ + struct arckbd_softc *sc = cookie; + + sc->sc_flags &= ~AKF_WANTMOUSE; +} diff --git a/sys/arch/arm26/ioc/arckbdmap.c b/sys/arch/arm26/ioc/arckbdmap.c new file mode 100644 index 00000000000..5be0d83eea9 --- /dev/null +++ b/sys/arch/arm26/ioc/arckbdmap.c @@ -0,0 +1,238 @@ +/* $NetBSD: arckbdmap.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * arckbdmap.c - Archimedes keyboard maps + */ + +#include <sys/types.h> + +__RCSID("$NetBSD: arckbdmap.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $"); + +#include <sys/device.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> +#include <arch/arm26/ioc/arckbdvar.h> +#include <arch/arm26/ioc/arckbdreg.h> + +/* XXX These should be in sys/dev/wscons/wskeysymdef.h */ +#define KB_SE 0x4300 +#define KS_KP_Numbersign 0xf223 + +#define KC(n) (0xe000 | (n)) /* see wsksymdef.h */ + +/* Arc keycodes are 0xrc where r and c are the row and column codes */ + +static const keysym_t arckbd_keydesc_uk[] = { +/* pos command normal shifted */ + KC(0x00), KS_Cmd_Debugger,KS_Escape, + KC(0x01), KS_Cmd_Screen0, KS_f1, + KC(0x02), KS_Cmd_Screen1, KS_f2, + KC(0x03), KS_Cmd_Screen2, KS_f3, + KC(0x04), KS_Cmd_Screen3, KS_f4, + KC(0x05), KS_Cmd_Screen4, KS_f5, + KC(0x06), KS_Cmd_Screen5, KS_f6, + KC(0x07), KS_Cmd_Screen6, KS_f7, + KC(0x08), KS_Cmd_Screen7, KS_f8, + KC(0x09), KS_Cmd_Screen8, KS_f9, + KC(0x0a), KS_Cmd_Screen9, KS_f10, + KC(0x0b), KS_f11, + KC(0x0c), KS_f12, + KC(0x0d), KS_voidSymbol, /* print: no keysym yet */ + KC(0x0e), KS_Hold_Screen, /* scroll lock */ + KC(0x0f), KS_voidSymbol, /* break: no keysym yet */ + + KC(0x10), KS_grave, KS_asciitilde, + KC(0x11), KS_1, KS_exclam, + KC(0x12), KS_2, KS_at, + KC(0x13), KS_3, KS_numbersign, + KC(0x14), KS_4, KS_dollar, + KC(0x15), KS_5, KS_percent, + KC(0x16), KS_6, KS_asciicircum, + KC(0x17), KS_7, KS_ampersand, + KC(0x18), KS_8, KS_asterisk, + KC(0x19), KS_9, KS_parenleft, + KC(0x1a), KS_0, KS_parenright, + KC(0x1b), KS_minus, KS_underscore, + KC(0x1c), KS_equal, KS_plus, + KC(0x1d), KS_sterling, KS_currency, + KC(0x1e), KS_BackSpace, + KC(0x1f), KS_Insert, + KC(0x20), KS_Home, + KC(0x21), KS_Prior, + KC(0x22), KS_Num_Lock, + KC(0x23), KS_KP_Divide, + KC(0x24), KS_KP_Multiply, + KC(0x25), KS_KP_Numbersign, + + KC(0x26), KS_Tab, + KC(0x27), KS_q, + KC(0x28), KS_w, + KC(0x29), KS_e, + KC(0x2a), KS_r, + KC(0x2b), KS_t, + KC(0x2c), KS_y, + KC(0x2d), KS_u, + KC(0x2e), KS_i, + KC(0x2f), KS_o, + KC(0x30), KS_p, + KC(0x31), KS_bracketleft, KS_braceleft, + KC(0x32), KS_bracketright,KS_braceright, + KC(0x33), KS_backslash, KS_bar, + KC(0x34), KS_Delete, + KC(0x35), KS_End, /* really Copy */ + KC(0x36), KS_Next, + KC(0x37), KS_KP_7, + KC(0x38), KS_KP_8, + KC(0x39), KS_KP_9, + KC(0x3a), KS_KP_Subtract, + + KC(0x3b), KS_Cmd1, KS_Control_L, + KC(0x3c), KS_a, + KC(0x3d), KS_s, + KC(0x3e), KS_d, + KC(0x3f), KS_f, + KC(0x40), KS_g, + KC(0x41), KS_h, + KC(0x42), KS_j, + KC(0x43), KS_k, + KC(0x44), KS_l, + KC(0x45), KS_semicolon, KS_colon, + KC(0x46), KS_apostrophe, KS_quotedbl, + KC(0x47), KS_Return, + KC(0x48), KS_KP_4, + KC(0x49), KS_KP_5, + KC(0x4a), KS_KP_6, + KC(0x4b), KS_KP_Add, + + KC(0x4c), KS_Shift_L, + KC(0x4e), KS_z, + KC(0x4f), KS_x, + KC(0x50), KS_c, + KC(0x51), KS_v, + KC(0x52), KS_b, + KC(0x53), KS_n, + KC(0x54), KS_m, + KC(0x55), KS_comma, KS_less, + KC(0x56), KS_period, KS_greater, + KC(0x57), KS_slash, KS_question, + KC(0x58), KS_Shift_R, + KC(0x59), KS_Up, + KC(0x5a), KS_KP_1, + KC(0x5b), KS_KP_2, + KC(0x5c), KS_KP_3, + + KC(0x5d), KS_Caps_Lock, + KC(0x5e), KS_Cmd2, KS_Alt_L, + KC(0x5f), KS_space, + KC(0x60), KS_Alt_R, + KC(0x61), KS_Control_R, + KC(0x62), KS_Left, + KC(0x63), KS_Down, + KC(0x64), KS_Right, + KC(0x65), KS_KP_0, + KC(0x66), KS_KP_Decimal, + KC(0x67), KS_KP_Enter, + + /* Mouse buttons */ + KC(0x70), KS_voidSymbol, /* left */ + KC(0x71), KS_voidSymbol, /* middle */ + KC(0x72), KS_voidSymbol, /* right */ +}; + +static const keysym_t arckbd_keydesc_no[] = { +/* Based on uk */ + KC(0x12), KS_2, KS_quotedbl, KS_apostrophe, + KC(0x14), KS_4, KS_dollar, KS_currency, + KC(0x16), KS_6, KS_ampersand, + KC(0x17), KS_7, KS_slash, KS_braceleft, + KC(0x18), KS_8, KS_parenleft, KS_bracketleft, + KC(0x19), KS_9, KS_parenright, KS_bracketright, + KC(0x1a), KS_0, KS_equal, KS_braceright, + KC(0x1b), KS_plus, KS_question, + KC(0x1c), KS_less, KS_greater, KS_bar, + KC(0x1d), KS_at, KS_sterling, + KC(0x31), KS_aring, + KC(0x32), KS_asciicircum, KS_asterisk, + KC(0x45), KS_oslash, + KC(0x46), KS_ae, + KC(0x4d), KS_less, KS_greater, + KC(0x55), KS_comma, KS_semicolon, + KC(0x56), KS_period, KS_colon, + KC(0x57), KS_minus, KS_underscore, +}; + +static const keysym_t arckbd_keydesc_se[] = { +/* Based on no */ +/* pos normal shifted altgred */ + KC(0x32), KS_udiaeresis, + KC(0x33), KS_asciicircum, KS_asterisk, KS_backslash, + KC(0x45), KS_odiaeresis, + KC(0x46), KS_adiaeresis, +}; + +static const keysym_t arckbd_keydesc_de[] = { +/* Based on se */ +/* pos normal shifted altgred */ + KC(0x10), KS_asciicircum, KS_degree, + KC(0x12), KS_2, KS_quotedbl, + KC(0x13), KS_3, KS_section, + KC(0x14), KS_4, KS_dollar, + KC(0x1b), KS_ssharp, KS_question, KS_backslash, + KC(0x1c), KS_dead_acute, KS_dead_grave, + KC(0x27), KS_q, KS_Q, KS_at, + KC(0x2c), KS_z, + KC(0x31), KS_udiaeresis, + KC(0x32), KS_plus, KS_asterisk, KS_asciitilde, + KC(0x33), KS_numbersign, KS_apostrophe, + KC(0x4e), KS_y, + KC(0x54), KS_m, KS_M, KS_mu, +}; + +#define KBD_MAP(name, base, map) \ + { name, base, sizeof(map)/sizeof(keysym_t), map } + +static const struct wscons_keydesc arckbd_keydesctab[] = { + KBD_MAP(KB_UK, 0, arckbd_keydesc_uk), + KBD_MAP(KB_NO, KB_UK, arckbd_keydesc_no), + KBD_MAP(KB_SE, KB_NO, arckbd_keydesc_se), + KBD_MAP(KB_DE, KB_SE, arckbd_keydesc_de), + {0}, +}; + +const struct wskbd_mapdata arckbd_mapdata_default = { + arckbd_keydesctab, KB_UK +}; + +const struct arckbd_kbidtab arckbd_kbidtab[] = { + { ARCKBD_KBID_UK, KB_UK }, + { ARCKBD_KBID_NO, KB_NO }, + { ARCKBD_KBID_SE, KB_SE }, + { ARCKBD_KBID_DE, KB_DE }, + { -1 }, +}; diff --git a/sys/arch/arm26/ioc/arckbdreg.h b/sys/arch/arm26/ioc/arckbdreg.h new file mode 100644 index 00000000000..025354302fb --- /dev/null +++ b/sys/arch/arm26/ioc/arckbdreg.h @@ -0,0 +1,94 @@ +/* $NetBSD: arckbdreg.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ +/*- + * Copyright (c) 1997, 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * arckbdreg.h - Archimedes keyboard codes + */ + +#ifndef _ARCKBDREG_H +#define _ARCKBDREG_H + +#define ARCKBD_HRST 0xff /* keyboard reset */ +#define ARCKBD_RAK1 0xfe /* first reset acknowledge */ +#define ARCKBD_RAK2 0xfd /* second reset acknowledge */ +#define ARCKBD_RQPD 0x40 /* reserved */ +#define ARCKBD_PDAT 0xe0 /* response to RQPD */ +#define ARCKBD_IS_PDAT(d) (((d) & 0xf0) == ARCKBD_PDAT) +#define ARCKBD_RQID 0x20 /* request keyboard ID */ +#define ARCKBD_KBID 0x80 /* keyboard ID (bottom 6 bits) */ +#define ARCKBD_IS_KBID(d) (((d) & 0xc0) == ARCKBD_KBID) +#define ARCKBD_KDDA 0xc0 /* key down data (bottom 4 bits plus next byte) */ +#define ARCKBD_IS_KDDA(d) (((d) & 0xf0) == ARCKBD_KDDA) +#define ARCKBD_KUDA 0xd0 /* key up data (bottom 4 bits plus next byte) */ +#define ARCKBD_IS_KUDA(d) (((d) & 0xf0) == ARCKBD_KUDA) +#define ARCKBD_RQMP 0x22 /* request mouse position */ +#define ARCKBD_MDAT 0x00 /* mouse movement data */ +#define ARCKBD_IS_MDAT(d) (((d) & 0x80) == ARCKBD_MDAT) +#define ARCKBD_BACK 0x3f /* acknowledge first byte of pair */ +#define ARCKBD_NACK 0x30 /* acknowledge -- send no more */ +#define ARCKBD_SACK 0x31 /* acknowledge -- send only keyup/down */ +#define ARCKBD_MACK 0x32 /* acknowledge -- send only mouse events */ +#define ARCKBD_SMAK 0x33 /* acknowledge -- send mouse or kbd events */ +#define ARCKBD_LEDS 0x00 /* Set LEDs: */ +#define ARCKBD_LEDS_CAPSLOCK 0x01 /* Caps lock */ +#define ARCKBD_LEDS_NUMLOCK 0x02 /* Num lock */ +#define ARCKBD_LEDS_SCROLLLOCK 0x04 /* Scroll lock */ +#define ARCKBD_PRST 0x21 /* reserved */ + +#define ARCKBD_BAUD 31250 /* Data rate on keyboard serial link */ + +/* Keyboard ID codes */ + +/* Inferred from the ARMsi documentation */ +#define ARCKBD_KBID_A500 0x80 /* A500 prototype keyboard */ +/* Determined by experiment */ +#define ARCKBD_KBID_UK 0x81 /* Archimedes UK keyboard */ +/* These are from the RISC OS 2 PRM, page 1666: */ +#define ARCKBD_KBID_MASTER 0x82 +#define ARCKBD_KBID_COMPACT 0x83 +#define ARCKBD_KBID_IT 0x84 +#define ARCKBD_KBID_ES 0x85 +#define ARCKBD_KBID_FR 0x86 +#define ARCKBD_KBID_DE 0x87 +#define ARCKBD_KBID_PT 0x88 +#define ARCKBD_KBID_ESPERANTO 0x89 +#define ARCKBD_KBID_GR 0x8a +#define ARCKBD_KBID_SE 0x8b +#define ARCKBD_KBID_FI 0x8c +#define ARCKBD_KBID_DK 0x8e +#define ARCKBD_KBID_NO 0x8f +#define ARCKBD_KBID_IS 0x90 +#define ARCKBD_KBID_CA1 0x91 +#define ARCKBD_KBID_CA2 0x92 +#define ARCKBD_KBID_CA 0x93 +#define ARCKBD_KBID_TR 0x94 +#define ARCKBD_KBID_ARABIC 0x95 +#define ARCKBD_KBID_IE 0x96 +#define ARCKBD_KBID_HK 0x97 + +#endif /* !_ARCKBDREG_H */ diff --git a/sys/arch/arm26/ioc/arckbdvar.h b/sys/arch/arm26/ioc/arckbdvar.h new file mode 100644 index 00000000000..fb8ee4e34c8 --- /dev/null +++ b/sys/arch/arm26/ioc/arckbdvar.h @@ -0,0 +1,45 @@ +/* $NetBSD: arckbdvar.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARCKBDVAR_H +#define _ARCKBDVAR_H + +#include <dev/wscons/wsksymvar.h> + +struct arckbd_kbidtab { + int kbid; + kbd_t layout; +}; + +extern const struct wskbd_mapdata arckbd_mapdata_default; +extern const struct arckbd_kbidtab arckbd_kbidtab[]; + +extern void arckbd_cnattach __P((struct device * self)); + +#endif diff --git a/sys/arch/arm26/ioc/iic.c b/sys/arch/arm26/ioc/iic.c new file mode 100644 index 00000000000..22b6eff2ff8 --- /dev/null +++ b/sys/arch/arm26/ioc/iic.c @@ -0,0 +1,351 @@ +/* $NetBSD: iic.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ + +/* + * Copyright (c) 1994-1996 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Mark Brinicombe. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * iic.c + * + * Routines to communicate with IIC devices + * + * Created : 13/10/94 + * + * Based of kate/display/iiccontrol.c + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: iic.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $"); + +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/malloc.h> +#include <sys/device.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <arm26/iobus/iocreg.h> +#include <arm26/iobus/iocvar.h> +#include <arm26/ioc/iic.h> + +#include "locators.h" + +struct iic_softc { + struct device sc_dev; +}; + +/* Autoconfiguration glue */ +static int iic_match (struct device *, struct cfdata *, void *); +static void iic_attach(struct device *, struct device *, void *); +static int iicsearch(struct device *, struct cfdata *, void *); + +struct cfattach iic_ca = { + sizeof(struct iic_softc), iic_match, iic_attach +}; + +/* Local function prototypes */ + +static int iic_getack(struct device *); +static void iic_write_bit(struct device *, int); +static int iic_write_byte(struct device *, int); +static int iic_read_byte(struct device *); +static void iic_start_bit(struct device *); +static void iic_stop_bit(struct device *); + +static int iicprint(void *, const char *); + +/* Functions that do the bit twiddling */ +static int iic_get_state(struct device *); +static void iic_set_state_and_ack(struct device *, int, int); +static void iic_set_state(struct device *, int, int); + +extern struct cfdriver iic_cd; + +/* + * iic device probe function + */ + +/* ARGSUSED */ +static int +iic_match(struct device *parent, struct cfdata *cf, void *aux) +{ + + return(1); +} + +/* + * iic device attach function + * + * Initialise the softc structure and do a search for children + */ + +static void +iic_attach(struct device *parent, struct device *self, void *aux) +{ + + printf("\n"); + config_search(iicsearch, self, NULL); +} + +/* + * Main entry to IIC driver. + */ + +int +iic_control(struct device *self, int address, u_char *buffer, int count) +{ + int loop; + + /* Send the start bit */ + + iic_start_bit(self); + + /* Send the address */ + + if (!iic_write_byte(self, address)) { + iic_stop_bit(self); + return -1; + } + + /* Read or write the data as required */ + + if ((address & 1) == 0) { + /* Write bytes */ + for (loop = 0; loop < count; ++loop) { + if (!iic_write_byte(self, buffer[loop])) { + iic_stop_bit(self); + return -1; + } + } + } + else { + /* Read bytes */ + for (loop = 0; loop < count; ++loop) { + buffer[loop] = iic_read_byte(self); + + /* Send final acknowledge */ + + if (loop == (count - 1)) + iic_write_bit(self, 1); + else + iic_write_bit(self, 0); + } + } + + /* Send stop bit */ + + iic_stop_bit(self); + + return 0; +} + + +static int +iic_getack(struct device *self) +{ + int ack; + + iic_set_state(self, 1, 0); + delay(5); + iic_set_state_and_ack(self, 1, 1); + ack = iic_get_state(self); + delay(4); + iic_set_state(self, 1, 0); + + return (ack & 1) == 0; +} + +/* + * Put the IIC bus lines in the given state (MD) + */ +static void +iic_set_state(struct device *self, int sda, int scl) +{ + int bits; + + bits = 0; + if (sda) bits |= IOC_CTL_SDA; + if (scl) bits |= IOC_CTL_SCL; + ioc_ctl_write(self->dv_parent, bits, IOC_CTL_SDA | IOC_CTL_SCL); +} + +/* + * Put the IIC bus lines in a given state and wait for the SCL line + * to actually do what we asked (so the slave is ready). + */ +static void +iic_set_state_and_ack(struct device *self, int sda, int scl) +{ + + iic_set_state(self, sda, scl); + while ((ioc_ctl_read(self->dv_parent) & IOC_CTL_SCL) == 0) + continue; +} + +/* + * Read state of IIC data line + */ +static int +iic_get_state(struct device *self) +{ + + return (ioc_ctl_read(self->dv_parent) & IOC_CTL_SDA) != 0; +} + +static void +iic_write_bit(struct device *self, int bit) +{ + + iic_set_state(self, bit, 0); + delay(1); /* Data setup time (250 ns) */ + iic_set_state_and_ack(self, bit, 1); + delay(4); /* Clock high time (4.0 us) */ + iic_set_state(self, bit, 0); + delay(5); /* Clock low time (4.7 us) */ +} + + +static int +iic_write_byte(struct device *self, int value) +{ + int loop; + int bit; + + for (loop = 0x80; loop != 0; loop = loop >> 1) { + bit = ((value & loop) != 0); + iic_write_bit(self, bit); + } + + return(iic_getack(self)); +} + + +static int +iic_read_byte(struct device *self) +{ + int loop; + u_char byte; + + iic_set_state(self, 1, 0); + + byte = 0; + + for (loop = 0; loop < 8; ++loop) { + iic_set_state_and_ack(self, 1, 1); + delay(4); /* Clock high time (4.0 us) */ + byte = (byte << 1) + (iic_get_state(self) & 1); + iic_set_state(self, 1, 0); + delay(5); /* Clock low time (4.7 us) */ + } + + return(byte); +} + + +static void +iic_start_bit(struct device *self) +{ + + iic_set_state(self, 1, 1); + delay(5); /* Bus free time (4.7 us) */ + iic_set_state(self, 0, 1); + delay(4); /* Start hold time (4.0 us) */ + iic_set_state(self, 0, 0); + delay(5); /* Clock low time (4.7 us) */ +} + + +static void +iic_stop_bit(struct device *self) +{ + + iic_set_state(self, 0, 1); + delay(4); /* Stop setup time (4.0 us) */ + iic_set_state(self, 1, 1); +} + +/* + * int iicprint(void *aux, const char *name) + * + * print function for child device configuration + */ + +static int +iicprint(void *aux, const char *name) +{ + struct iicbus_attach_args *iba = aux; + + if (!name) { + if (iba->ib_addr) + printf(" addr 0x%02x", iba->ib_addr); + } + + /* XXXX print flags */ + return (UNCONF); +} + +/* + * iic search function + * + * search for devices that are children of the iic device + * fill out the attach arguments and call the probe and + * attach function (as required). + * + * Note: since the offsets of the devices need to be specified in the + * config file we ignore the FSTAT_STAR. + */ + +static int +iicsearch(struct device *parent, struct cfdata *cf, void *aux) +{ + struct iic_softc *sc = (struct iic_softc *)parent; + struct iicbus_attach_args iba; + int tryagain; + + do { + iba.ib_iic_softc = sc; + iba.ib_addr = cf->cf_loc[IICCF_ADDR]; + iba.ib_aux = NULL; + + tryagain = 0; + if ((*cf->cf_attach->ca_match)(parent, cf, &iba) > 0) { + config_attach(parent, cf, &iba, iicprint); +/* tryagain = (cf->cf_fstate == FSTATE_STAR);*/ + } + } while (tryagain); + + return (0); +} diff --git a/sys/arch/arm26/ioc/iic.h b/sys/arch/arm26/ioc/iic.h new file mode 100644 index 00000000000..1bea797e0fa --- /dev/null +++ b/sys/arch/arm26/ioc/iic.h @@ -0,0 +1,64 @@ +/* $NetBSD: iic.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Mark Brinicombe. + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * iic.h + * + * header file for IIC + * + * Created : 15/04/96 + */ + +/* + * IIC bus driver attach arguments + */ + +#ifdef _KERNEL + +struct iicbus_attach_args { + int ib_addr; /* i/o address */ + void *ib_aux; /* driver specific */ + void *ib_iic_softc; /* softc of iic parent */ +}; + +#define IIC_WRITE 0x00 +#define IIC_READ 0x01 + +/* Prototype for kernel interface to IIC bus */ + +extern int iic_control(struct device *, int, u_char *, int); + +#endif /* _KERNEL */ + +/* End of iic.h */ diff --git a/sys/arch/arm26/ioc/ioeb.c b/sys/arch/arm26/ioc/ioeb.c new file mode 100644 index 00000000000..68122585ff8 --- /dev/null +++ b/sys/arch/arm26/ioc/ioeb.c @@ -0,0 +1,73 @@ +/* $NetBSD: ioeb.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#include <sys/param.h> + +__KERNEL_RCSID(0, "$NetBSD: ioeb.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/systm.h> + +#include <machine/bus.h> + +#include <arch/arm26/iobus/iocvar.h> +#include <arch/arm26/ioc/ioebreg.h> + +struct ioeb_softc { + struct device sc_dev; +}; + +static int ioeb_match(struct device *, struct cfdata *, void *); +static void ioeb_attach(struct device *, struct device *, void *); + +struct cfattach ioeb_ca = { + sizeof(struct ioeb_softc), ioeb_match, ioeb_attach +}; + +/* IOEB is only four bits wide */ +#define ioeb_read(t, h, o) (bus_space_read_1(t, h, o) & 0xf) + +static int +ioeb_match(struct device *parent, struct cfdata *cf, void *aux) +{ + struct ioc_attach_args *ioc = aux; + + if (ioeb_read(ioc->ioc_fast_t, ioc->ioc_fast_h, IOEB_REG_ID) == + IOEB_ID_IOEB) + return 1; + return 0; +} + +static void +ioeb_attach(struct device *parent, struct device *self, void *aux) +{ + + printf("\n"); +} diff --git a/sys/arch/arm26/ioc/ioebreg.h b/sys/arch/arm26/ioc/ioebreg.h new file mode 100644 index 00000000000..75c29db1313 --- /dev/null +++ b/sys/arch/arm26/ioc/ioebreg.h @@ -0,0 +1,40 @@ +/* $NetBSD: ioebreg.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ + +/* + * This file is in the public domain. + * + * Derived from: + * RISC OS 3 Programmer's Reference Manual + * A3010/A3020/A4000 Technical Reference Manual + */ + +/* Acorn IOEB (Input/Output Extension Block) registers */ + +#ifndef _IOEBREG_H_ +#define _IOEBREG_H_ + +/* + * IOEB starts at a rather high offset because it avoids the ranges + * used on older machines. + */ + +#define IOEB_REG_VIDCTL 18 /* Video control latch */ +#define IOEB_REG_ID 20 /* Device ID */ +#define IOEB_REG_SPEED 21 /* Clock speed (A4?) */ +#define IOEB_REG_INTRCLR 22 /* Printer interrupt clear */ +#define IOEB_REG_MONID 28 /* Monitor ID */ +#define IOEB_REG_VGATEST 29 /* VGA test pin/SCART sound ??? */ +#define IOEB_REG_JOY1 30 /* Joystick 1 */ +#define IOEB_REG_JOY2 31 /* Joystick 2 */ + +/* The IOEB is connected to D[3:0], so its internal registers are 4-bit */ +#define IOEB_VIDCTL_HSINV 0x1 /* Invert horizontal sync */ +#define IOEB_VIDCTL_VSINV 0x2 /* Invert vertical sync */ +#define IOEB_VIDCTL_CLK_MASK 0xc /* VIDCLK select */ +#define IOEB_VIDCTL_CLK_24MHZ 0x0 /* 24 MHz */ +#define IOEB_VIDCTL_CLK_25MHZ 0x4 /* 25.175 MHz */ +#define IOEB_VIDCTL_CLK_36MHZ 0x8 /* 36 MHz */ + +#define IOEB_ID_IOEB 0x5 + +#endif diff --git a/sys/arch/arm26/ioc/latchreg.h b/sys/arch/arm26/ioc/latchreg.h new file mode 100644 index 00000000000..927ff1460f1 --- /dev/null +++ b/sys/arch/arm26/ioc/latchreg.h @@ -0,0 +1,60 @@ +/* $NetBSD: latchreg.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ +/*- + * Copyright (c) 1997, 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * latchreg.h - Archimedes internal latches + */ + +/* Under NetBSD, Latch A is latch0 and Latch B is latch1. */ + +#ifndef _LATCHREG_H +#define _LATCHREG_H + +/* Latch A controls some of the floppy disc system */ + +#define LATCH0_DRIVESEL0 0x01 /* Floppy drive 0 select */ +#define LATCH0_DRIVESEL1 0x02 /* Floppy drive 1 select */ +#define LATCH0_DRIVESEL2 0x04 /* Floppy drive 2 select */ +#define LATCH0_DRIVESEL3 0x08 /* Floppy drive 3 select */ +#define LATCH0_SIDESEL 0x10 /* Floppy side select, inverted. */ +#define LATCH0_SIDE0 0x10 +#define LATCH0_SIDE1 0x00 /* Just to be friendly... */ +#define LATCH0_MOTORONOFF 0x20 /* Motor on/off */ +#define LATCH0_INUSE 0x40 /* 'In Use' */ + +/* Latch B does all sorts of random stuff */ + +#define LATCH1_DENSITY 0x02 /* Floppy disc density setting */ +#define LATCH1_DOUBLEDENSITY 0x00 /* Double density */ +#define LATCH1_SINGLEDENSITY 0x02 /* Single density */ +#define LATCH1_NOTFDCRESET 0x08 /* Floppy controller reset (inverted) */ +#define LATCH1_LPTSTROBE 0x10 /* Printer strobe line */ +#define LATCH1_AUX1 0x20 /* Spare (VIDC Enhancer?) */ +#define LATCH1_AUX2 0x40 /* Spare */ + +#endif /* !_LATCHREG_H */ diff --git a/sys/arch/arm26/ioc/pcf8583reg.h b/sys/arch/arm26/ioc/pcf8583reg.h new file mode 100644 index 00000000000..552753eba9b --- /dev/null +++ b/sys/arch/arm26/ioc/pcf8583reg.h @@ -0,0 +1,81 @@ +/* $NetBSD: pcf8583reg.h,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ + +/* + * Ben Harris, 2000 + * + * This file is in the public domain + */ +/* + * Philips PCF8583 RTC registers + */ + +/* We only have clock mode registers here */ + +#ifndef _PCF8583REG_H +#define _PCF8583REG_H + +#define PCF8583_ADDR 0xa0 +#define PCF8583_MASK 0xfc + +#define PCF8583_REG_CSR 0x00 +#define PCF8583_REG_CENTI 0x01 +#define PCF8583_REG_SEC 0x02 +#define PCF8583_REG_MIN 0x03 +#define PCF8583_REG_HOUR 0x04 +#define PCF8583_REG_YEARDATE 0x05 +#define PCF8583_REG_WKDYMON 0x06 +#define PCF8583_REG_TIMER 0x07 +#define PCF8583_REG_ALMCTL 0x08 +#define PCF8583_REG_ALMCENTI 0x09 +#define PCF8583_REG_ALMSEC 0x0a +#define PCF8583_REG_ALMMIN 0x0b +#define PCF8583_REG_ALMHOUR 0x0c +#define PCF8583_REG_ALMDAY 0x0d +#define PCF8583_REG_ALMMON 0x0e +#define PCF8583_REG_ALMTIMER 0x0f + +#define PCF8583_CSR_TIMER 0x01 +#define PCF8583_CSR_SECTICK 0x01 +#define PCF8583_CSR_ALARM 0x02 +#define PCF8583_CSR_MINTICK 0x02 +#define PCF8583_CSR_ALARMENABLE 0x04 +#define PCF8583_CSR_MASK 0x08 +#define PCF8583_CSR_FN_MASK 0x30 +#define PCF8583_CSR_FN_32768HZ 0x00 +#define PCF8583_CSR_FN_50HZ 0x10 +#define PCF8583_CSR_FN_EVENT 0x20 +#define PCF8583_CSR_FN_TEST 0x30 +#define PCF8583_CSR_HOLD 0x40 +#define PCF8583_CSR_STOP 0x80 + +#define PCF8583_HOUR_MASK 0x3f +#define PCF8583_HOUR_PM 0x40 +#define PCF8583_HOUR_12H 0x80 + +#define PCF8583_DATE_MASK 0x3f +#define PCF8583_YEAR_MASK 0xc0 +#define PCF8583_YEAR_SHIFT 6 + +#define PCF8583_MON_MASK 0x1f +#define PCF8583_WKDY_MASK 0xe0 +#define PCF8583_WKDY_SHIFT 5 + +#define PCF8583_ALMCTL_TIMER_MASK 0x07 +#define PCF8583_ALMCTL_TIMER_OFF 0x00 +#define PCF8583_ALMCTL_TIMER_CENTI 0x01 +#define PCF8583_ALMCTL_TIMER_SEC 0x02 +#define PCF8583_ALMCTL_TIMER_MIN 0x03 +#define PCF8583_ALMCTL_TIMER_HOUR 0x04 +#define PCF8583_ALMCTL_TIMER_DAY 0x05 +#define PCF8583_ALMCTL_TIMER_TEST 0x07 +#define PCF8583_ALMCTL_TIMERINT 0x08 +#define PCF8583_ALMCTL_CLKALM_MASK 0x30 +#define PCF8583_ALMCTL_CLKALM_NONE 0x00 +#define PCF8583_ALMCTL_CLKALM_DAILY 0x10 +#define PCF8583_ALMCTL_CLKALM_WKDY 0x20 +#define PCF8583_ALMCTL_CLKALM_DATED 0x30 +#define PCF8583_ALMCTL_TIMERALM 0x40 +#define PCF8583_ALMCTL_ALMINT 0x80 + + +#endif diff --git a/sys/arch/arm26/ioc/rtc.c b/sys/arch/arm26/ioc/rtc.c new file mode 100644 index 00000000000..c5219e845b7 --- /dev/null +++ b/sys/arch/arm26/ioc/rtc.c @@ -0,0 +1,470 @@ +/* $NetBSD: rtc.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ + +/* + * Copyright (c) 2000 Ben Harris + * Copyright (c) 1994-1996 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * rtc.c + * + * Routines to read and write the RTC and CMOS RAM + * + * Created : 13/10/94 + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: rtc.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $"); + +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> +#include <sys/malloc.h> +#include <sys/device.h> +#include <dev/clock_subr.h> +#include <arm26/ioc/iic.h> +#include <arm26/ioc/pcf8583reg.h> + +struct rtc_softc { + struct device sc_dev; + int sc_flags; +#define RTC_BROKEN 1 +#define RTC_OPEN 2 + int sc_addr; +}; + +static int rtcmatch(struct device *parent, struct cfdata *cf, void *aux); +static void rtcattach(struct device *parent, struct device *self, void *aux); +static int rtc_gettime(struct device *, struct timeval *); +static int rtc_settime(struct device *, struct timeval *); + +#define RTC_ADDR_YEAR 0xc0 +#define RTC_ADDR_CENT 0xc1 + +extern struct cfdriver rtc_cd; + +/* device and attach structures */ + +struct cfattach rtc_ca = { + sizeof(struct rtc_softc), rtcmatch, rtcattach +}; + +/* + * rtcmatch() + * + * Validate the IIC address to make sure its an RTC we understand + */ + +int +rtcmatch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct iicbus_attach_args *ib = aux; + + if ((ib->ib_addr & PCF8583_MASK) == PCF8583_ADDR && + iic_control(parent, ib->ib_addr | IIC_READ, NULL, 0) == 0) + return 1; + return 0; +} + +/* + * rtcattach() + * + * Attach the rtc device + */ + +void +rtcattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct rtc_softc *sc = (struct rtc_softc *)self; + struct iicbus_attach_args *ib = aux; + u_char buff[1]; + + sc->sc_flags |= RTC_BROKEN; + sc->sc_addr = ib->ib_addr; + if ((ib->ib_addr & PCF8583_MASK) == PCF8583_ADDR) { + printf(": PCF8583"); + + /* Read RTC register 0 and report info found */ + + buff[0] = PCF8583_REG_CSR; + + if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, + buff, 1)) + return; + + if (iic_control(self->dv_parent, sc->sc_addr | IIC_READ, + buff, 1)) + return; + + switch (buff[0] & PCF8583_CSR_FN_MASK) { + case PCF8583_CSR_FN_32768HZ: + printf(", 32.768 kHz clock"); + break; + case PCF8583_CSR_FN_50HZ: + printf(", 50 Hz clock"); + break; + case PCF8583_CSR_FN_EVENT: + printf(", event counter"); + break; + case PCF8583_CSR_FN_TEST: + printf(", test mode"); + break; + } + + if (buff[0] & PCF8583_CSR_STOP) + printf(", stopped"); + if (buff[0] & PCF8583_CSR_ALARMENABLE) + printf(", alarm enabled"); + sc->sc_flags &= ~RTC_BROKEN; + } + + printf("\n"); +} + +/* Read a byte from CMOS RAM */ + +int +cmos_read(struct device *self, int location) +{ + u_char buff; + struct rtc_softc *sc = (struct rtc_softc *)self; + + buff = location; + + if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, &buff, 1)) + return(-1); + if (iic_control(self->dv_parent, sc->sc_addr | IIC_READ, &buff, 1)) + return(-1); + + return(buff); +} + + +/* Write a byte to CMOS RAM */ + +int +cmos_write(struct device *self, int location, int value) +{ + u_char buff[2]; + struct rtc_softc *sc = (struct rtc_softc *)self; + + buff[0] = location; + buff[1] = value; + + if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, buff, 2)) + return(-1); + + return(0); +} + +static int +rtc_settime(struct device *self, struct timeval *tv) +{ + struct rtc_softc *sc = (struct rtc_softc *)self; + u_char buff[8]; + struct clock_ymdhms ymdhms; + + clock_secs_to_ymdhms(tv->tv_sec, &ymdhms); + + buff[0] = PCF8583_REG_CENTI; + + buff[PCF8583_REG_CENTI] = TOBCD(tv->tv_usec / 10000); + buff[PCF8583_REG_SEC] = TOBCD(ymdhms.dt_sec); + buff[PCF8583_REG_MIN] = TOBCD(ymdhms.dt_min); + buff[PCF8583_REG_HOUR] = TOBCD(ymdhms.dt_hour); + buff[PCF8583_REG_YEARDATE] = TOBCD(ymdhms.dt_day) | + ((ymdhms.dt_year % 4) << PCF8583_YEAR_SHIFT); + buff[PCF8583_REG_WKDYMON] = TOBCD(ymdhms.dt_mon) | + ((ymdhms.dt_wday % 4) << PCF8583_WKDY_SHIFT); + + if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, buff, 7)) + return -1; + + if (cmos_write(self, RTC_ADDR_YEAR, ymdhms.dt_year % 100)) + return -1; + if (cmos_write(self, RTC_ADDR_CENT, ymdhms.dt_year / 100)) + return -1; + return(0); +} + +void +inittodr(time_t base) +{ + int check; + + check = 0; + if (rtc_cd.cd_ndevs == 0 || rtc_cd.cd_devs[0] == NULL) { + printf("inittodr: rtc0 not present"); + time.tv_sec = base; + time.tv_usec = 0; + check = 1; + } else { + rtc_gettime(rtc_cd.cd_devs[0], &time); + if (time.tv_sec > base + 3 * SECDAY) { + printf("inittodr: Clock has gained %ld days", + (time.tv_sec - base) / SECDAY); + check = 1; + } else if (time.tv_sec + SECDAY < base) { + printf("inittodr: Clock has lost %ld day(s)", + (base - time.tv_sec) / SECDAY); + check = 1; + } + } + if (check) + printf(" - CHECK AND RESET THE DATE.\n"); +} + + +static int +rtc_gettime(struct device *self, struct timeval *tv) +{ + u_char buff[8]; + int byte, centi; + struct rtc_softc *sc = (struct rtc_softc *)self; + struct clock_ymdhms ymdhms; + + buff[0] = 0; + + if (iic_control(self->dv_parent, sc->sc_addr | IIC_WRITE, buff, 1)) + return -1; + + if (iic_control(self->dv_parent, sc->sc_addr | IIC_READ, buff, 8)) + return -1; + + centi = FROMBCD(buff[PCF8583_REG_CENTI]); + ymdhms.dt_sec = FROMBCD(buff[PCF8583_REG_SEC]); + ymdhms.dt_min = FROMBCD(buff[PCF8583_REG_MIN]); + ymdhms.dt_hour = FROMBCD(buff[PCF8583_REG_HOUR] & PCF8583_HOUR_MASK); + + /* If in 12 hour mode need to look at the AM/PM flag */ + + if (buff[PCF8583_REG_HOUR] & PCF8583_HOUR_12H) { + ymdhms.dt_hour %= 12; /* 12AM -> 0, 12PM -> 12 */ + if (buff[PCF8583_REG_HOUR] & PCF8583_HOUR_PM) + ymdhms.dt_hour += 12; + } + + ymdhms.dt_day = FROMBCD(buff[PCF8583_REG_YEARDATE] & + PCF8583_DATE_MASK); + ymdhms.dt_mon = FROMBCD(buff[PCF8583_REG_WKDYMON] & + PCF8583_MON_MASK); + + byte = cmos_read(self, RTC_ADDR_YEAR); + if (byte == -1) + return -1; + ymdhms.dt_year = byte; + byte = cmos_read(self, RTC_ADDR_CENT); + if (byte == -1) + return -1; + ymdhms.dt_year += 100 * byte; + + /* Try to notice if the year's rolled over. */ + if (buff[PCF8583_REG_CSR] & PCF8583_CSR_MASK) + printf("%s: cannot check year in mask mode\n", self->dv_xname); + else + while (ymdhms.dt_year % 4 != + (buff[PCF8583_REG_YEARDATE] & + PCF8583_YEAR_MASK) >> PCF8583_YEAR_SHIFT) + ymdhms.dt_year++; + + tv->tv_sec = clock_ymdhms_to_secs(&ymdhms); + tv->tv_usec = centi * 10000; + return 0; +} + +#if 0 +int +rtcopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct rtc_softc *sc; + int unit = minor(dev); + + if (unit >= rtc_cd.cd_ndevs) + return(ENXIO); + + sc = rtc_cd.cd_devs[unit]; + + if (!sc) return(ENXIO); + + if (sc->sc_flags & RTC_BROKEN) return(ENXIO); + if (sc->sc_flags & RTC_OPEN) return(EBUSY); + + sc->sc_flags |= RTC_OPEN; + + return(0); +} + + +int +rtcclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + int unit = minor(dev); + struct rtc_softc *sc = rtc_cd.cd_devs[unit]; + + sc->sc_flags &= ~RTC_OPEN; + + return(0); +} + + +int +rtcread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + rtc_t rtc; + int s; + char buffer[32]; + int length; + + s = splclock(); + if (rtc_read(NULL, &rtc) == 0) { + (void)splx(s); + return(ENXIO); + } + + (void)splx(s); + + sprintf(buffer, "%02d:%02d:%02d.%02d%02d %02d/%02d/%02d%02d\n", + rtc.rtc_hour, rtc.rtc_min, rtc.rtc_sec, rtc.rtc_centi, + rtc.rtc_micro, rtc.rtc_day, rtc.rtc_mon, rtc.rtc_cen, + rtc.rtc_year); + + if (uio->uio_offset > strlen(buffer)) + return 0; + + length = strlen(buffer) - uio->uio_offset; + if (length > uio->uio_resid) + length = uio->uio_resid; + + return(uiomove((caddr_t)buffer, length, uio)); +} + + +static int +twodigits(buffer, pos) + char *buffer; + int pos; +{ + int result = 0; + + if (buffer[pos] >= '0' && buffer[pos] <= '9') + result = (buffer[pos] - '0') * 10; + if (buffer[pos+1] >= '0' && buffer[pos+1] <= '9') + result += (buffer[pos+1] - '0'); + return(result); +} + +int +rtcwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + rtc_t rtc; + int s; + char buffer[25]; + int length; + int error; + + /* + * We require atomic updates! + */ + length = uio->uio_resid; + if (uio->uio_offset || (length != sizeof(buffer) + && length != sizeof(buffer - 1))) + return(EINVAL); + + if ((error = uiomove((caddr_t)buffer, sizeof(buffer), uio))) + return(error); + + if (length == sizeof(buffer) && buffer[sizeof(buffer) - 1] != '\n') + return(EINVAL); + + printf("rtcwrite: %s\n", buffer); + + rtc.rtc_micro = 0; + rtc.rtc_centi = twodigits(buffer, 9); + rtc.rtc_sec = twodigits(buffer, 6); + rtc.rtc_min = twodigits(buffer, 3); + rtc.rtc_hour = twodigits(buffer, 0); + rtc.rtc_day = twodigits(buffer, 14); + rtc.rtc_mon = twodigits(buffer, 17); + rtc.rtc_year = twodigits(buffer, 22); + rtc.rtc_cen = twodigits(buffer, 20); + + s = splclock(); + rtc_write(NULL, &rtc); + (void)splx(s); + + return(0); +} + + +int +rtcioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ +/* struct rtc_softc *sc = rtc_cd.cd_devs[minor(dev)];*/ + +/* switch (cmd) { + case RTCIOC_READ: + return(0); + }*/ + + return(EINVAL); +} +#endif + +/* End of rtc.c */ diff --git a/sys/arch/arm26/mainbus/mainbus.c b/sys/arch/arm26/mainbus/mainbus.c new file mode 100644 index 00000000000..287002952dc --- /dev/null +++ b/sys/arch/arm26/mainbus/mainbus.c @@ -0,0 +1,104 @@ +/* $NetBSD: mainbus.c,v 1.1 2000/05/09 21:56:02 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * mainbus.c - the root device + */ + +#include <sys/param.h> + +#include <sys/device.h> +#include <sys/systm.h> + +static int mainbus_match __P((struct device *parent, struct cfdata *cf, void *aux)); +static void mainbus_attach __P((struct device *parent, struct device *self, void *aux)); +static int mainbus_search __P((struct device *parent, struct cfdata *cf, void *aux)); +static int mainbus_print __P((void *aux, const char *pnp)); + +struct mainbus_softc { + struct device sc_dev; +}; + +struct cfattach mainbus_ca = { + sizeof(struct mainbus_softc), mainbus_match, mainbus_attach +}; + +extern struct cfdriver mainbus_cd; + +static int +mainbus_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + + /* Only one mainbus */ + if (cf->cf_unit == 0) + return 1; + else + return 0; +} + +static void +mainbus_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + + printf("\n"); + + config_search(mainbus_search, self, NULL); +} + +static int +mainbus_search(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + + /* + * Things attached at mainbus are assumed not to need to be + * told where they are. + */ + + if ((cf->cf_attach->ca_match)(parent, cf, NULL) > 0) + config_attach(parent, cf, NULL, mainbus_print); + + return 0; +} + +static int +mainbus_print(aux, pnp) + void *aux; + const char *pnp; +{ + + return UNCONF; +} diff --git a/sys/arch/arm26/podulebus/asc.c b/sys/arch/arm26/podulebus/asc.c new file mode 100644 index 00000000000..90cdefd81a2 --- /dev/null +++ b/sys/arch/arm26/podulebus/asc.c @@ -0,0 +1,469 @@ +/* $NetBSD: asc.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Mark Brinicombe + * Copyright (c) 1982, 1990 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from:ahsc.c + */ + +/* + * Driver for the Acorn SCSI card using the SBIC (WD3393) generic driver + * + * Thanks to Acorn for supplying programming information on this card. + */ + +/* + * Ok this driver is not wonderful yet. It only supports POLLING mode + * The Acorn SCSI card (or any WD3393 based card) does not support + * DMA so the DMA section of this driver and the sbic driver needs + * to be rewritten. + */ + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/buf.h> +#include <dev/scsipi/scsi_all.h> +#include <dev/scsipi/scsipi_all.h> +#include <dev/scsipi/scsiconf.h> +#include <arm26/podulebus/podulebus.h> +#include <arm26/podulebus/sbicreg.h> +#include <arm26/podulebus/sbicvar.h> +#include <arm26/podulebus/ascreg.h> +#include <arm26/podulebus/ascvar.h> +#include <arm32/podulebus/podules.h> + +void ascattach __P((struct device *, struct device *, void *)); +int ascmatch __P((struct device *, struct cfdata *, void *)); + +void asc_enintr __P((struct sbic_softc *)); +void asc_dmastop __P((struct sbic_softc *)); +int asc_dmanext __P((struct sbic_softc *)); +int asc_dmaintr __P((struct sbic_softc *)); +int asc_dmago __P((struct sbic_softc *, char *, int, int)); +int asc_scsicmd __P((struct scsipi_xfer *xs)); +int asc_intr __P((void *arg)); +void asc_minphys __P((struct buf *bp)); + +struct scsipi_device asc_scsidev = { + NULL, /* use default error handler */ + NULL, /* do not have a start functio */ + NULL, /* have no async handler */ + NULL, /* Use default done routine */ +}; + + +#ifdef DEBUG +int asc_dmadebug = 0; +#endif + +struct cfattach asc_ca = { + sizeof(struct asc_softc), ascmatch, ascattach +}; + +extern struct cfdriver asc_cd; + +u_long scsi_nosync; +int shift_nosync; + +#if ASC_POLL > 0 +int asc_poll = 0; + +#endif + +int +ascmatch(pdp, cf, auxp) + struct device *pdp; + struct cfdata *cf; + void *auxp; +{ + struct podulebus_attach_args *pa = auxp; + +/* Look for the card */ + + if (matchpodule(pa, MANUFACTURER_ACORN, PODULE_ACORN_SCSI, -1) == 0) + return(0); + + if (strncmp(pa->pa_descr, "MCS", 3) == 0) + return(0); + + return(1); +} + +void +ascattach(pdp, dp, auxp) + struct device *pdp, *dp; + void *auxp; +{ +/* volatile struct sdmac *rp;*/ + struct asc_softc *sc; + struct sbic_softc *sbic; + struct podulebus_attach_args *pa; + + sc = (struct asc_softc *)dp; + pa = auxp; + + sc->sc_podule_number = pa->pa_slotnum; + + sbic = &sc->sc_softc; + + sbic->sc_enintr = asc_enintr; + sbic->sc_dmago = asc_dmago; + sbic->sc_dmanext = asc_dmanext; + sbic->sc_dmastop = asc_dmastop; + sbic->sc_dmacmd = 0; + + /* + * eveything is a valid dma address + */ + sbic->sc_dmamask = 0; + sbic->sc_sbicp = (sbic_regmap_p) (pa->pa_memc_h + ASC_SBIC); + sbic->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 143; + + sbic->sc_adapter.scsipi_cmd = asc_scsicmd; + sbic->sc_adapter.scsipi_minphys = asc_minphys; + + sbic->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE; + sbic->sc_link.adapter_softc = sbic; + sbic->sc_link.scsipi_scsi.adapter_target = 7; + sbic->sc_link.adapter = &sbic->sc_adapter; + sbic->sc_link.device = &asc_scsidev; + sbic->sc_link.openings = 1; /* was 2 */ + sbic->sc_link.scsipi_scsi.max_target = 7; + sbic->sc_link.scsipi_scsi.max_lun = 7; + sbic->sc_link.type = BUS_SCSI; + + printf(": hostid=%d", sbic->sc_link.scsipi_scsi.adapter_target); + +#if ASC_POLL > 0 + if (asc_poll) + printf(" polling"); +#endif + printf("\n"); + + sc->sc_pagereg = pa->pa_fast_h + ASC_PAGEREG; + sc->sc_intstat = pa->pa_fast_h + ASC_INTSTATUS; + + /* Reset the card */ + + WriteByte(sc->sc_pagereg, 0x80); + DELAY(500000); + WriteByte(sc->sc_pagereg, 0x00); + DELAY(250000); + + sbicinit(sbic); + + if (!asc_poll) { + sc->sc_ih = + podulebus_irq_establish(sc->sc_softc.sc_dev.dv_parent, + pa->pa_slotnum, IPL_BIO, asc_intr, sc); + irq_enable(sc->sc_ih); + } + + /* + * attach all scsi units on us + */ + config_found(dp, &sbic->sc_link, scsiprint); +} + + +void +asc_enintr(sbicsc) + struct sbic_softc *sbicsc; +{ + struct asc_softc *sc = (struct asc_softc *)sbicsc; +/* printf("asc_enintr\n");*/ +/* + volatile struct sdmac *sdp; + + sdp = dev->sc_cregs; + + dev->sc_flags |= SBICF_INTR; + sdp->CNTR = CNTR_PDMD | CNTR_INTEN; +*/ + sbicsc->sc_flags |= SBICF_INTR; + WriteByte(sc->sc_pagereg, 0x40); +} + + +int +asc_dmago(dev, addr, count, flags) + struct sbic_softc *dev; + char *addr; + int count, flags; +{ + printf("asc_dmago(addr=%p, count=%d,flags=%d)\n", addr, count, flags); + printf("dmago: dc_addr=%p tcnt=%lx\n", dev->sc_cur->dc_addr, dev->sc_tcnt); +#ifdef DDB + Debugger(); +#else + panic("Hit a brick wall\n"); +#endif +#if 0 + volatile struct sdmac *sdp; + + sdp = dev->sc_cregs; + /* + * Set up the command word based on flags + */ + dev->sc_dmacmd = CNTR_PDMD | CNTR_INTEN; + if ((flags & DMAGO_READ) == 0) + dev->sc_dmacmd |= CNTR_DDIR; +#ifdef DEBUG + if (ahsc_dmadebug & DDB_IO) + printf("ahsc_dmago: cmd %x\n", dev->sc_dmacmd); +#endif + + dev->sc_flags |= SBICF_INTR; + sdp->CNTR = dev->sc_dmacmd; + sdp->ACR = (u_int) dev->sc_cur->dc_addr; + sdp->ST_DMA = 1; + + return(dev->sc_tcnt); +#endif + return(0); +} + +void +asc_dmastop(dev) + struct sbic_softc *dev; +{ +/* printf("asc_dmastop\n");*/ +#if 0 + volatile struct sdmac *sdp; + int s; + + sdp = dev->sc_cregs; + +#ifdef DEBUG + if (ahsc_dmadebug & DDB_FOLLOW) + printf("ahsc_dmastop()\n"); +#endif + if (dev->sc_dmacmd) { + s = splbio(); + if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) { + /* + * only FLUSH if terminal count not enabled, + * and reading from peripheral + */ + sdp->FLUSH = 1; + while ((sdp->ISTR & ISTR_FE_FLG) == 0) + ; + } + /* + * clear possible interrupt and stop dma + */ + sdp->CINT = 1; + sdp->SP_DMA = 1; + dev->sc_dmacmd = 0; + splx(s); + } +#endif +} + +int +asc_dmaintr(dev) + struct sbic_softc *dev; +{ + panic("asc_dmaintr"); +#if 0 + volatile struct sdmac *sdp; + int stat, found; + + sdp = dev->sc_cregs; + stat = sdp->ISTR; + + if ((stat & (ISTR_INT_F|ISTR_INT_P)) == 0) + return (0); + +#ifdef DEBUG + if (ahsc_dmadebug & DDB_FOLLOW) + printf("%s: dmaintr 0x%x\n", dev->sc_dev.dv_xname, stat); +#endif + + /* + * both, SCSI and DMA interrupts arrive here. I chose + * arbitrarily that DMA interrupts should have higher + * precedence than SCSI interrupts. + */ + found = 0; + if (stat & ISTR_E_INT) { + ++found; + + sdp->CINT = 1; /* clear possible interrupt */ + + /* + * check for SCSI ints in the same go and + * eventually save an interrupt + */ + } + + if (dev->sc_flags & SBICF_INTR && stat & ISTR_INTS) + found += sbicintr(dev); + return(found); +#endif + return(0); +} + + +int +asc_dmanext(dev) + struct sbic_softc *dev; +{ + printf("asc_dmanext\n"); +#ifdef DDB + Debugger(); +#else + panic("Hit a brick wall\n"); +#endif +#if 0 + volatile struct sdmac *sdp; + int i, stat; + + sdp = dev->sc_cregs; + + if (dev->sc_cur > dev->sc_last) { + /* shouldn't happen !! */ + printf("ahsc_dmanext at end !!!\n"); + asc_dmastop(dev); + return(0); + } + if ((dev->sc_dmacmd & (CNTR_TCEN | CNTR_DDIR)) == 0) { + /* + * only FLUSH if terminal count not enabled, + * and reading from peripheral + */ + sdp->FLUSH = 1; + while ((sdp->ISTR & ISTR_FE_FLG) == 0) + ; + } + /* + * clear possible interrupt and stop dma + */ + sdp->CINT = 1; /* clear possible interrupt */ + sdp->SP_DMA = 1; /* stop dma */ + sdp->CNTR = dev->sc_dmacmd; + sdp->ACR = (u_int)dev->sc_cur->dc_addr; + sdp->ST_DMA = 1; + + dev->sc_tcnt = dev->sc_cur->dc_count << 1; + return(dev->sc_tcnt); +#endif + return(0); +} + +void +asc_dump() +{ + int i; + + for (i = 0; i < asc_cd.cd_ndevs; ++i) + if (asc_cd.cd_devs[i]) + sbic_dump(asc_cd.cd_devs[i]); +} + +int +asc_scsicmd(xs) + struct scsipi_xfer *xs; +{ +/* struct scsipi_link *sc_link = xs->sc_link;*/ + + /* ensure command is polling for the moment */ +#if ASC_POLL > 0 + if (asc_poll) + xs->xs_control |= XS_CTL_POLL; +#endif + +/* printf("id=%d lun=%dcmdlen=%d datalen=%d opcode=%02x flags=%08x status=%02x blk=%02x %02x\n", + sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun, xs->cmdlen, xs->datalen, xs->cmd->opcode, + xs->xs_control, xs->status, xs->cmd->bytes[0], xs->cmd->bytes[1]);*/ + + return(sbic_scsicmd(xs)); +} + + +int +asc_intr(arg) + void *arg; +{ + struct asc_softc *sc = arg; + int intr; + +/* printf("ascintr:");*/ + intr = ReadByte(sc->sc_intstat); +/* printf("%02x\n", intr);*/ + + if (intr & IS_SBIC_IRQ) + return sbicintr((struct sbic_softc *)sc); + + return(0); /* Pass interrupt on down the chain */ +} + + +void alloc_z2mem() +{ + panic("allocz2mem"); +} + +void isztwomem() +{ + panic("isz2mem"); +} + +void PREP_DMA_MEM() +{ + panic("PREP_DMA_MEM"); +} + +/* + * limit the transfer as required. + */ +void +asc_minphys(bp) + struct buf *bp; +{ +#if 0 + /* + * We must limit the DMA xfer size + */ + if (bp->b_bcount > MAX_DMA_LEN) { + printf("asc: Reducing dma length\n"); + bp->b_bcount = MAX_DMA_LEN; + } +#endif + minphys(bp); +} + diff --git a/sys/arch/arm26/podulebus/ascreg.h b/sys/arch/arm26/podulebus/ascreg.h new file mode 100644 index 00000000000..af363ea9682 --- /dev/null +++ b/sys/arch/arm26/podulebus/ascreg.h @@ -0,0 +1,279 @@ +/* $NetBSD: ascreg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Mark Brinicombe + * Copyright (c) 1994 Christian E. Hopps + * Copyright (c) 1982, 1990 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from:ahscreg.h,v 1.2 1994/10/26 02:02:46 + */ + +#ifndef _ASCREG_H_ +#define _ASCREG_H_ + +/* + * Hardware layout of the A3000 SDMAC. This also contains the + * registers for the sbic chip, but in favor of separating DMA and + * scsi, the scsi-driver doesn't make use of this dependency + */ + +#define v_char volatile char +#define v_int volatile int +#define vu_char volatile u_char +#define vu_short volatile u_short +#define vu_int volatile u_int + +struct sdmac { + short pad0; + vu_short DAWR; /* DACK Width Register WO */ + vu_int WTC; /* Word Transfer Count Register RW */ + short pad1; + vu_short CNTR; /* Control Register RW */ + vu_int ACR; /* Address Count Register RW */ + short pad2; + vu_short ST_DMA; /* Start DMA Transfers RW-Strobe */ + short pad3; + vu_short FLUSH; /* Flush FIFO RW-Strobe */ + short pad4; + vu_short CINT; /* Clear Interrupts RW-Strobe */ + short pad5; + vu_short ISTR; /* Interrupt Status Register RO */ + int pad6[7]; + short pad7; + vu_short SP_DMA; /* Stop DMA Transfers RW-Strobe */ + char pad8; + vu_char SASR; /* sbic asr */ + char pad9; + vu_char SCMD; /* sbic data */ +}; + +/* + * value to go into DAWR + */ +#define DAWR_AHSC 3 /* according to A3000T service-manual */ + +/* + * bits defined for CNTR + */ +#define CNTR_TCEN (1<<5) /* Terminal Count Enable */ +#define CNTR_PREST (1<<4) /* Perp Reset (not implemented :-((( ) */ +#define CNTR_PDMD (1<<3) /* Perp Device Mode Select (1=SCSI,0=XT/AT) */ +#define CNTR_INTEN (1<<2) /* Interrupt Enable */ +#define CNTR_DDIR (1<<1) /* Device Direction. 1==rd host, wr perp */ +#define CNTR_IO_DX (1<<0) /* IORDY & CSX1 Polarity Select */ + +/* + * bits defined for ISTR + */ +#define ISTR_INTX (1<<8) /* XT/AT Interrupt pending */ +#define ISTR_INT_F (1<<7) /* Interrupt Follow */ +#define ISTR_INTS (1<<6) /* SCSI Peripheral Interrupt */ +#define ISTR_E_INT (1<<5) /* End-Of-Process Interrupt */ +#define ISTR_INT_P (1<<4) /* Interrupt Pending */ +#define ISTR_UE_INT (1<<3) /* Under-Run FIFO Error Interrupt */ +#define ISTR_OE_INT (1<<2) /* Over-Run FIFO Error Interrupt */ +#define ISTR_FF_FLG (1<<1) /* FIFO-Full Flag */ +#define ISTR_FE_FLG (1<<0) /* FIFO-Empty Flag */ + +#define DMAGO_READ 0x01 + + +/* Addresses relative to podule base */ + +#define ASC_INTSTATUS 0x2000 +#define ASC_CLRINT 0x2000 +#define ASC_PAGEREG 0x3000 + +/* Addresses relative to module base */ + +#define ASC_DMAC 0x3000 +#define ASC_SBIC 0x2000 +#define ASC_SRAM 0x0000 + +#define ASC_SRAM_BLKSIZE 0x1000 + +#define IS_IRQREQ 0x01 +#define IS_DMAC_IRQ 0x02 +#define IS_SBIC_IRQ 0x08 + +#if 0 +/* SBIC Commands */ + +#define SBIC_CMD_Reset 0x00 /* Reset the SBIC */ +#define SBIC_Abort 0x01 /* Abort command */ +#define SBIC_Sel_tx_wATN 0x08 /* Select and Transfer with ATN */ +#define SBIC_Sel_tx_woATN 0x09 /* Select and Transfer without ATN */ + +/* SBIC status codes */ + +#define SBIC_ResetOk 0x00 +#define SBIC_ResetAFOk 0x01 + +/* SBIC registers bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 */ + +#define SBIC_OWNID 0x00 /* RW FS1 FS0 0 EHP EAF ID2 ID1 ID0 */ +#define SBIC_CONTROL 0x01 /* RW DM2 DM1 DM0 HHP EDI IDI HA HSP */ +#define SBIC_TIMEREG 0x02 /* RW timeout period value = Tper*Ficlk/80d */ +#define SBIC_CDB1TSECT 0x03 /* RW CDB byte 1 & Total sectors per track */ +#define SBIC_CDB2THEAD 0x04 /* RW CDB byte 2 & Total number of heads */ +#define SBIC_CDB3TCYL1 0x05 /* RW CDB byte 3 & Total no. of cylinders MSB */ +#define SBIC_CDB4TCYL2 0x06 /* RW CDB byte 4 & Total no. of cylinders LSB */ +#define SBIC_CDB5LADR1 0x07 /* RW CDB byte 5 & Logical addr to translate */ +#define SBIC_CBD6LADR2 0x08 /* RW CDB byte 6 & Logical addr to translate */ +#define SBIC_CDB7LADR3 0x09 /* RW CDB byte 7 & Logical addr to translate */ +#define SBIC_CDB8LADR4 0x0A /* RW CDB byte 8 & Logical addr to translate */ +#define SBIC_CDB9SECT 0x0B /* RW CDB byte 9 & Translation sector result */ +#define SBIC_CDB10HEAD 0x0C /* RW CDB byte 10 & Translation head result */ +#define SBIC_CDB11CYL1 0x0D /* RW CDB byte 11 & Translation cyl result MSB*/ +#define SBIC_CDB12CYL2 0x0E /* RW CDB byte 12 & Translation cyl result LSB*/ +#define SBIC_TARGETLUN 0x0F /* RW TLV DOK 0 0 0 TL2 TL1 TL0 */ +#define SBIC_COMPHASE 0x10 /* RW Command Phase Register for multi-phase */ +#define SBIC_SYNCTX 0x11 /* RW 0 TP2 TP1 TP0 OF3 OF2 OF1 OF0 */ +#define SBIC_TXCOUNT1 0x12 /* RW Transfer count MSB */ +#define SBIC_TXCOUNT2 0x13 /* RW Transfer count */ +#define SBIC_TXCOUNT3 0x14 /* RW Transfer count LSB */ +#define SBIC_DESTID 0x15 /* RW SCC DPD 0 0 0 DI2 DI1 DI0 */ +#define SBIC_SOURCEID 0x16 /* RW ER ES DSP 0 SIV SI2 SI1 SI0 */ +#define SBIC_SCSISTAT 0x17 /* RO **Interrupt type*** **Int. qualifier** */ +#define SBIC_COMMAND 0x18 /* RW SBT *********Command code************* */ +#define SBIC_DATA 0x19 /* RW Access to data i/o FIFO for polled use */ + +#define SBIC_ADDRREG 0x00 +#define SBIC_DATAREG 0x04 +#define SBIC_AUX_STATUS 0x00 + +/* + * My ID register, and/or CDB Size + */ + +#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */ + /* 11 Mhz is invalid */ +#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */ +#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */ +#define SBIC_ID_EHP 0x10 /* Enable host parity */ +#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */ +#define SBIC_ID_MASK 0x07 +#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */ + +/* + * Control register +*/ + +#define SBIC_CTL_DMA 0x80 /* Single byte dma */ +#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/ +#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */ +#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */ +#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */ +#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */ +#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/ +#define SBIC_CTL_HA 0x02 /* Halt on ATN */ +#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */ + +/* + * Destination ID register + */ + +#define SBIC_DID_DPD 0x40 /* Data Phase Direction */ + +/* + * Auxiliary Status Register + */ + +#define SBIC_ASR_INT 0x80 /* Interrupt pending */ +#define SBIC_ASR_LCI 0x40 /* Last command ignored */ +#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */ +#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */ +#define SBIC_ASR_xxx 0x0c +#define SBIC_ASR_PE 0x02 /* Parity error (even) */ +#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */ + +/* DMAC constants */ + +#define DMAC_Bits 0x01 +#define DMAC_Ctrl1 0x60 +#define DMAC_Ctrl2 0x01 +#define DMAC_CLEAR_MASK 0x0E +#define DMAC_SET_MASK 0x0F +#define DMAC_DMA_RD_MODE 0x04 +#define DMAC_DMA_WR_MODE 0x08 + +/* DMAC registers */ + +#define DMAC_INITIALISE 0x0000 /* WO ---- ---- ---- ---- ---- ---- 16B RES */ +#define DMAC_CHANNEL 0x0200 /* R ---- ---- ---- BASE SEL3 SEL2 SEL1 SEL0 */ + /* W ---- ---- ---- ---- ---- BASE *SELECT** */ +#define DMAC_TXCNTLO 0x0004 /* RW C7 C6 C5 C4 C3 C2 C1 C0 */ +#define DMAC_TXCNTHI 0x0204 /* RW C15 C14 C13 C12 C11 C10 C9 C8 */ +#define DMAC_TXADRLO 0x0008 /* RW A7 A6 A5 A4 A3 A2 A1 A0 */ +#define DMAC_TXADRMD 0x0208 /* RW A15 A14 A13 A12 A11 A10 A9 A8 */ +#define DMAC_TXADRHI 0x000C /* RW A23 A22 A21 A20 A19 A18 A17 A16 */ +#define DMAC_DEVCON1 0x0010 /* RW AKL RQL EXW ROT CMP DDMA AHLD MTM */ +#define DMAC_DEVCON2 0x0210 /* RW ---- ---- ---- ---- ---- ---- WEV BHLD */ +#define DMAC_MODECON 0x0014 /* RW **TMODE** ADIR AUTI **TDIR*** ---- WORD */ +#define DMAC_STATUS 0x0214 /* RO RQ3 RQ2 RQ1 RQ0 TC3 TC2 TC1 TC0 */ +#if 0 +templo = dmac + 0x0018;/* RO T7 T6 T5 T4 T3 T2 T1 T0 */ +temphi = dmac + 0x0218;/* RO T15 T14 T13 T12 T11 T10 T9 T8 */ +#endif +#define DMAC_REQREG 0x001C /* RW ---- ---- ---- ---- SRQ3 SRQ2 SRQ1 SRQ0 */ +#define DMAC_MASKREG 0x021C /* RW ---- ---- ---- ---- M3 M2 M1 M0 */ + +#ifndef _LOCORE +#define WriteSBIC(a, d) \ + WriteByte(sbic_base + SBIC_ADDRREG, a); \ + WriteByte(sbic_base + SBIC_DATAREG, d); + +/* +#define ReadSBIC(a) \ + (WriteByte(sbic_base, a), ReadWord(sbic_base + 4) & 0xff) +*/ +#define ReadSBIC(a) \ + ReadSBIC1(sbic_base, a) + + +static __inline int +ReadSBIC1(sbic_base, a) + u_int sbic_base; + int a; +{ + WriteByte(sbic_base + SBIC_ADDRREG, a); + return(ReadByte(sbic_base + SBIC_DATAREG)); +} + + +#define WriteDMAC(a, d) WriteByte(dmac_base + a, d) +#define ReadDMAC(a) ReadByte(dmac_base + a) +#endif + + +#endif +#endif /* _ASCREG_H_ */ diff --git a/sys/arch/arm26/podulebus/ascvar.h b/sys/arch/arm26/podulebus/ascvar.h new file mode 100644 index 00000000000..61a147d085d --- /dev/null +++ b/sys/arch/arm26/podulebus/ascvar.h @@ -0,0 +1,51 @@ +/* $NetBSD: ascvar.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * Copyright (c) 1996 Mark Brinicombe + * + * 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 Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ASCVAR_H_ +#define _ASCVAR_H_ + +#include <arm26/podulebus/sbicvar.h> +#include <arm26/podulebus/ascreg.h> + +#define ASC_POLL 1 + +struct asc_softc { + struct sbic_softc sc_softc; + + int sc_podule_number; + struct irq_handler *sc_ih; + + vu_int sc_pagereg; + vu_int sc_intstat; + }; + +#endif /* _ASCVAR_H_ */ diff --git a/sys/arch/arm26/podulebus/dtide.c b/sys/arch/arm26/podulebus/dtide.c new file mode 100644 index 00000000000..e988a4e9074 --- /dev/null +++ b/sys/arch/arm26/podulebus/dtide.c @@ -0,0 +1,122 @@ +/* $NetBSD: dtide.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * dtide.c - Driver for the D.T. Software IDE interface. + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: dtide.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/systm.h> +#include <machine/bus.h> +#include <machine/irq.h> + +#include <arch/arm26/podulebus/podulebus.h> +#include <arch/arm32/podulebus/podules.h> +#include <arch/arm26/podulebus/dtidereg.h> + +#include <dev/ata/atavar.h> +#include <dev/ic/wdcvar.h> + +struct dtide_softc { + struct wdc_softc sc_wdc; + struct channel_softc *sc_chp[2]; /* pointers to the following */ + struct channel_softc sc_chan[2]; + struct irq_handler *sc_ih[2]; + bus_space_tag_t sc_magict; + bus_space_handle_t sc_magich; +}; + +static int dtide_match(struct device *, struct cfdata *, void *); +static void dtide_attach(struct device *, struct device *, void *); + +struct cfattach dtide_ca = { + sizeof(struct dtide_softc), dtide_match, dtide_attach +}; + +static int +dtide_match(struct device *parent, struct cfdata *cf, void *aux) +{ + struct podulebus_attach_args *pa = aux; + + return IS_PODULE(pa, MANUFACTURER_DTSOFT, PODULE_DTSOFT_IDE); +} + +static void +dtide_attach(struct device *parent, struct device *self, void *aux) +{ + struct podulebus_attach_args *pa = aux; + struct dtide_softc *sc = (void *)self; + int i; + bus_space_tag_t bst; + bus_space_handle_t bsh; + + sc->sc_wdc.cap = WDC_CAPABILITY_DATA16; + sc->sc_wdc.PIO_cap = 0; /* XXX correct? */ + sc->sc_wdc.DMA_cap = 0; /* XXX correct? */ + sc->sc_wdc.UDMA_cap = 0; + sc->sc_wdc.nchannels = 2; + sc->sc_wdc.channels = sc->sc_chp; + sc->sc_chp[0] = &sc->sc_chan[0]; + sc->sc_chp[1] = &sc->sc_chan[1]; + sc->sc_magict = pa->pa_fast_t; + bus_space_subregion(pa->pa_fast_t, pa->pa_fast_h, DTIDE_MAGICBASE >> 2, + 1, &sc->sc_magich); + bus_space_shift(pa->pa_fast_t, pa->pa_fast_h, DTIDE_REGSHIFT, + &bst, &bsh); + for (i = 0; i < 2; i++) { + sc->sc_chan[i].channel = i; + sc->sc_chan[i].wdc = &sc->sc_wdc; + sc->sc_chan[i].cmd_iot = bst; + sc->sc_chan[i].ctl_iot = bst; + } + bus_space_subregion(bst, bsh, DTIDE_CMDBASE0 >> 5, 0x100, + &sc->sc_chan[0].cmd_ioh); + bus_space_subregion(bst, bsh, DTIDE_CTLBASE0 >> 5, 0x100, + &sc->sc_chan[0].ctl_ioh); + bus_space_subregion(bst, bsh, DTIDE_CMDBASE1 >> 5, 0x100, + &sc->sc_chan[1].cmd_ioh); + bus_space_subregion(bst, bsh, DTIDE_CTLBASE1 >> 5, 0x100, + &sc->sc_chan[1].ctl_ioh); + sc->sc_ih[0] = + podulebus_irq_establish(self->dv_parent, pa->pa_slotnum, + IPL_BIO, wdcintr, &sc->sc_chan[0]); + sc->sc_ih[1] = + podulebus_irq_establish(self->dv_parent, pa->pa_slotnum, + IPL_BIO, wdcintr, &sc->sc_chan[1]); + printf(": interrupting at %s\n", irq_string(sc->sc_ih[0])); + wdcattach(&sc->sc_chan[0]); + irq_enable(sc->sc_ih[0]); + wdcattach(&sc->sc_chan[1]); + irq_enable(sc->sc_ih[1]); +/* bus_space_write_1(sc->sc_magict, sc->sc_magich, 0, 1); */ +} diff --git a/sys/arch/arm26/podulebus/dtidereg.h b/sys/arch/arm26/podulebus/dtidereg.h new file mode 100644 index 00000000000..cc94a9dcdf3 --- /dev/null +++ b/sys/arch/arm26/podulebus/dtidereg.h @@ -0,0 +1,21 @@ +/* $NetBSD: dtidereg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* This file is in the public domain */ + +/* + * dtidereg.h - hardware-related constants of the D.T. Software IDE interface. + */ + +/* + * This is mostly reverse-engineered by Ben Harris from the driver that + * comes with the board and the board itself. Treat with caution. + */ + +#define DTIDE_MAGICBASE 0x2000 + +#define DTIDE_REGSHIFT 5 /* ie DA0 == LA5 */ +#define DTIDE_CMDBASE0 0x2400 +#define DTIDE_CTLBASE0 0x2500 +#define DTIDE_CMDBASE1 0x2600 +#define DTIDE_CTLBASE1 0x2700 + diff --git a/sys/arch/arm26/podulebus/if_ea.c b/sys/arch/arm26/podulebus/if_ea.c new file mode 100644 index 00000000000..c254f83c29d --- /dev/null +++ b/sys/arch/arm26/podulebus/if_ea.c @@ -0,0 +1,1537 @@ +/* $NetBSD: if_ea.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe + * 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 Mark Brinicombe. + * 4. The name of the company nor the name of the author may 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 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. + * + * RiscBSD kernel project + * + * if_ea.c + * + * Ether3 device driver + * + * Created : 08/07/95 + */ + +/* + * SEEQ 8005 device driver + */ + +/* + * Bugs/possible improvements: + * - Does not currently support DMA + * - Does not currently support multicasts + * - Does not transmit multiple packets in one go + */ + +#include "opt_inet.h" +#include "opt_ns.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/syslog.h> +#include <sys/device.h> + +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> +#include <net/if_ether.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#include <netinet/if_inarp.h> +#endif + +#ifdef NS +#include <netns/ns.h> +#include <netns/ns_if.h> +#endif + +#include "bpfilter.h" +#if NBPFILTER > 0 +#include <net/bpf.h> +#include <net/bpfdesc.h> +#endif + +#include <machine/cpu.h> +#include <machine/irq.h> + +#include <arm26/podulebus/if_eareg.h> +#include <arm26/podulebus/podulebus.h> +#include <arm32/podulebus/podules.h> + +#ifndef EA_TIMEOUT +#define EA_TIMEOUT 60 +#endif + +/*#define EA_TX_DEBUG*/ +/*#define EA_RX_DEBUG*/ +/*#define EA_DEBUG*/ +/*#define EA_PACKET_DEBUG*/ + +/* for debugging convenience */ +#ifdef EA_DEBUG +#define dprintf(x) printf x +#else +#define dprintf(x) +#endif + +/* + * per-line info and status + */ + +struct ea_softc { + struct device sc_dev; + struct irq_handler *sc_ih; + int sc_podule_number; /* Our podule number */ + u_int sc_iobase; /* base I/O addr */ + struct ethercom sc_ethercom; /* Ethernet common */ + char sc_pktbuf[EA_BUFSIZ]; /* frame buffer */ + int sc_config1; /* Current config1 bits */ + int sc_config2; /* Current config2 bits */ + int sc_command; /* Current command bits */ + int sc_irqclaimed; /* Whether we have an IRQ claimed */ + int sc_rx_ptr; /* Receive buffer pointer */ + int sc_tx_ptr; /* Transmit buffer pointer */ +}; + +/* + * prototypes + */ + +int eaintr __P((void *)); +static int ea_init __P((struct ea_softc *)); +static int ea_ioctl __P((struct ifnet *, u_long, caddr_t)); +static void ea_start __P((struct ifnet *)); +static void ea_watchdog __P((struct ifnet *)); +static void ea_reinit __P((struct ea_softc *)); +static void ea_chipreset __P((struct ea_softc *)); +static void ea_ramtest __P((struct ea_softc *)); +static int ea_stoptx __P((struct ea_softc *)); +static int ea_stoprx __P((struct ea_softc *)); +static void ea_stop __P((struct ea_softc *)); +static void ea_writebuf __P((struct ea_softc *, u_char *, int, int)); +static void ea_readbuf __P((struct ea_softc *, u_char *, int, int)); +static void earead __P((struct ea_softc *, caddr_t, int)); +static struct mbuf *eaget __P((caddr_t, int, struct ifnet *)); +static void ea_hardreset __P((struct ea_softc *)); +static void eagetpackets __P((struct ea_softc *)); +static void eatxpacket __P((struct ea_softc *)); + +int eaprobe __P((struct device *, struct cfdata *, void *)); +void eaattach __P((struct device *, struct device *, void *)); + +/* driver structure for autoconf */ + +struct cfattach ea_ca = { + sizeof(struct ea_softc), eaprobe, eaattach +}; + +#if 0 + +/* + * Dump the chip registers + */ + +void +eadump(iobase) + u_int iobase; +{ + dprintf(("%08x: %04x %04x %04x %04x %04x %04x %04x %04x\n", iobase, + ReadShort(iobase + 0x00), ReadShort(iobase + 0x40), + ReadShort(iobase + 0x80), ReadShort(iobase + 0xc0), + ReadShort(iobase + 0x100), ReadShort(iobase + 0x140), + ReadShort(iobase + 0x180), ReadShort(iobase + 0x1c0))); +} +#endif + +/* + * Dump the interface buffer + */ + +void +ea_dump_buffer(sc, offset) + struct ea_softc *sc; + int offset; +{ +#ifdef EA_PACKET_DEBUG + u_int iobase = sc->sc_iobase; + int addr; + int loop; + int size; + int ctrl; + int ptr; + + addr = offset; + + do { + WriteShort(sc->sc_iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_READ); + WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM); + WriteShort(iobase + EA_8005_DMA_ADDR, addr); + + ptr = ReadShort(iobase + EA_8005_BUFWIN); + ctrl = ReadShort(iobase + EA_8005_BUFWIN); + ptr = ((ptr & 0xff) << 8) | ((ptr >> 8) & 0xff); + + if (ptr == 0) break; + size = ptr - addr; + + printf("addr=%04x size=%04x ", addr, size); + printf("cmd=%02x st=%02x\n", ctrl & 0xff, ctrl >> 8); + + for (loop = 0; loop < size - 4; loop += 2) + printf("%04x ", ReadShort(iobase + EA_8005_BUFWIN)); + printf("\n"); + addr = ptr; + } while (size != 0); +#endif +} + +/* + * Probe routine. + */ + +/* + * int eaprobe(struct device *parent, struct cfdata *cf, void *aux) + * + * Probe for the ether3 podule. + */ + +int +eaprobe(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct podulebus_attach_args *pa = (void *)aux; + u_int iobase; + +/* Look for a network slot interface */ + + if ((matchpodule(pa, MANUFACTURER_ATOMWIDE, PODULE_ATOMWIDE_ETHER3, -1) == 0) + && (matchpodule(pa, MANUFACTURER_ACORN, PODULE_ACORN_ETHER3XXX, -1) == 0) + && (matchpodule(pa, MANUFACTURER_ANT, PODULE_ANT_ETHER3, -1) == 0)) + return(0); + + iobase = pa->pa_memc_h + EA_8005_BASE; + +/* Reset it - Why here ? */ + + WriteShort(iobase + EA_8005_CONFIG2, EA_CFG2_RESET); + delay(100); + + return(1); +} + + +/* + * void eaattach(struct device *parent, struct device *dev, void *aux) + * + * Attach podule. + */ + +void +eaattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct ea_softc *sc = (void *)self; + struct podulebus_attach_args *pa = (void *)aux; + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + int loop; + int sum; + u_int8_t myaddr[ETHER_ADDR_LEN]; + +/* dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));*/ + +/* Note the podule number and validate */ + + sc->sc_podule_number = pa->pa_slotnum; + +/* Set the address of the controller for easy access */ + + sc->sc_iobase = pa->pa_memc_h + EA_8005_BASE; + +/* Read the station address - the receiver must be off */ + + WriteShort(sc->sc_iobase + EA_8005_CONFIG1, EA_BUFCODE_STATION_ADDR0); + + for (sum = 0, loop = 0; loop < ETHER_ADDR_LEN; ++loop) { + myaddr[loop] = + ReadByte(sc->sc_iobase + EA_8005_BUFWIN); + sum += myaddr[loop]; + } + +/* + * Hard code the ether address if we don't have one. + * Need to work out how I get the real address + * until then use the one a network slot card + * would used, based on the machine id. + */ + +/* + * Unfortunately, arm26 machines don't necessarily have a SSN, and I don't + * support them yet anyway. Erm, ideas anyone? + */ + + if (sum == 0) { + printf(": Ethernet address not found. Giving up.\n"); +#if 0 + myaddr[0] = 0x00; + myaddr[1] = 0x00; + myaddr[2] = bootconfig.machine_id[3]; + myaddr[3] = bootconfig.machine_id[2]; + myaddr[4] = bootconfig.machine_id[1]; + myaddr[5] = bootconfig.machine_id[0]; +#endif + } + + /* Print out some information for the user. */ + + printf(": SEEQ8005 address %s", ether_sprintf(myaddr)); + + sc->sc_irqclaimed = 0; + +/* Claim a podule interrupt */ + + sc->sc_ih = podulebus_irq_establish(sc->sc_dev.dv_parent, + pa->pa_slotnum, IPL_NET, eaintr, sc); + + /* Stop the board. */ + + ea_chipreset(sc); + ea_stoptx(sc); + ea_stoprx(sc); + + /* Initialise ifnet structure. */ + + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; + ifp->if_start = ea_start; + ifp->if_ioctl = ea_ioctl; + ifp->if_watchdog = ea_watchdog; + ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS; + + /* Now we can attach the interface. */ + +/* dprintf(("Attaching interface...\n"));*/ + if_attach(ifp); + ether_ifattach(ifp, myaddr); + + /* Finally, attach to bpf filter if it is present. */ + +#if NBPFILTER > 0 +/* dprintf(("Attaching to BPF...\n"));*/ + bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); +#endif + + /* Should test the RAM */ + + ea_ramtest(sc); + +/* dprintf(("eaattach() finished.\n"));*/ +} + + +/* + * Test the RAM on the ethernet card. This does not work yet + */ + +void +ea_ramtest(sc) + struct ea_softc *sc; +{ + register u_int iobase = sc->sc_iobase; + register int loop; + register u_int sum = 0; + +/* dprintf(("ea_ramtest()\n"));*/ + + /* + * Test the buffer memory on the board. + * Write simple pattens to it and read them back. + */ + + /* Set up the whole buffer RAM for writing */ + + WriteShort(iobase + EA_8005_CONFIG1, EA_BUFCODE_TX_EAP); + WriteShort(iobase + EA_8005_BUFWIN, ((EA_BUFFER_SIZE >> 8) - 1)); + WriteShort(iobase + EA_8005_TX_PTR, 0x0000); + WriteShort(iobase + EA_8005_RX_PTR, EA_BUFFER_SIZE - 2); + + /* Set the write start address and write a pattern */ + + ea_writebuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2) + WriteShort(iobase + EA_8005_BUFWIN, loop); + + /* Set the read start address and verify the pattern */ + + ea_readbuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2) + if (ReadShort(iobase + EA_8005_BUFWIN) != loop) + ++sum; + + if (sum != 0) + dprintf(("sum=%d\n", sum)); + + /* Set the write start address and write a pattern */ + + ea_writebuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2) + WriteShort(iobase + EA_8005_BUFWIN, loop ^ (EA_BUFFER_SIZE - 1)); + + /* Set the read start address and verify the pattern */ + + ea_readbuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2) + if (ReadShort(iobase + EA_8005_BUFWIN) != (loop ^ (EA_BUFFER_SIZE - 1))) + ++sum; + + if (sum != 0) + dprintf(("sum=%d\n", sum)); + + /* Set the write start address and write a pattern */ + + ea_writebuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2) + WriteShort(iobase + EA_8005_BUFWIN, 0xaa55); + + /* Set the read start address and verify the pattern */ + + ea_readbuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2) + if (ReadShort(iobase + EA_8005_BUFWIN) != 0xaa55) + ++sum; + + if (sum != 0) + dprintf(("sum=%d\n", sum)); + + /* Set the write start address and write a pattern */ + + ea_writebuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2) + WriteShort(iobase + EA_8005_BUFWIN, 0x55aa); + + /* Set the read start address and verify the pattern */ + + ea_readbuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EA_BUFFER_SIZE; loop += 2) + if (ReadShort(iobase + EA_8005_BUFWIN) != 0x55aa) + ++sum; + + if (sum != 0) + dprintf(("sum=%d\n", sum)); + + /* Report */ + + if (sum == 0) + printf(" %dK buffer RAM\n", EA_BUFFER_SIZE / 1024); + else + printf(" buffer RAM failed self test, %d faults\n", sum); +} + + +/* Claim an irq for the board */ + +void +ea_claimirq(sc) + struct ea_softc *sc; +{ +/* Have we claimed one already ? */ + + if (sc->sc_irqclaimed) return; + +/* Claim it */ + + irq_enable(sc->sc_ih); + + sc->sc_irqclaimed = 1; +} + + +/* Release an irq */ + +void +ea_releaseirq(sc) + struct ea_softc *sc; +{ +/* Have we claimed one ? */ + + if (!sc->sc_irqclaimed) return; + + irq_disable(sc->sc_ih); + + sc->sc_irqclaimed = 0; +} + + +/* + * Stop and reinitialise the interface. + */ + +static void +ea_reinit(sc) + struct ea_softc *sc; +{ + int s; + + dprintf(("eareinit()\n")); + +/* Stop and reinitialise the interface */ + + s = splnet(); + ea_stop(sc); + ea_init(sc); + (void)splx(s); +} + + +/* + * Stop the tx interface. + * + * Returns 0 if the tx was already stopped or 1 if it was active + */ + +static int +ea_stoptx(sc) + struct ea_softc *sc; +{ + u_int iobase = sc->sc_iobase; + int timeout; + int status; + + dprintf(("ea_stoptx()\n")); + + status = ReadShort(iobase + EA_8005_STATUS); + if (!(status & EA_STATUS_TX_ON)) + return(0); + +/* Stop any tx and wait for confirmation */ + + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_OFF); + + timeout = 20000; + do { + status = ReadShort(iobase + EA_8005_STATUS); + } while ((status & EA_STATUS_TX_ON) && --timeout > 0); + if (timeout == 0) + dprintf(("ea_stoptx: timeout waiting for tx termination\n")); + +/* Clear any pending tx interrupt */ + + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_INTACK); + return(1); +} + + +/* + * Stop the rx interface. + * + * Returns 0 if the tx was already stopped or 1 if it was active + */ + +static int +ea_stoprx(sc) + struct ea_softc *sc; +{ + u_int iobase = sc->sc_iobase; + int timeout; + int status; + + dprintf(("ea_stoprx()\n")); + + status = ReadShort(iobase + EA_8005_STATUS); + if (!(status & EA_STATUS_RX_ON)) + return(0); + +/* Stop any rx and wait for confirmation */ + + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_OFF); + + timeout = 20000; + do { + status = ReadShort(iobase + EA_8005_STATUS); + } while ((status & EA_STATUS_RX_ON) && --timeout > 0); + if (timeout == 0) + dprintf(("ea_stoprx: timeout waiting for rx termination\n")); + +/* Clear any pending rx interrupt */ + + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_INTACK); + return(1); +} + + +/* + * Stop interface. + * Stop all IO and shut the interface down + */ + +static void +ea_stop(sc) + struct ea_softc *sc; +{ + u_int iobase = sc->sc_iobase; + + dprintf(("ea_stop()\n")); + +/* Stop all IO */ + + ea_stoptx(sc); + ea_stoprx(sc); + +/* Disable rx and tx interrupts */ + + sc->sc_command &= (EA_CMD_RX_INTEN | EA_CMD_TX_INTEN); + +/* Clear any pending interrupts */ + + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command + | EA_CMD_RX_INTACK | EA_CMD_TX_INTACK | EA_CMD_DMA_INTACK + | EA_CMD_BW_INTACK); + dprintf(("st=%08x", ReadShort(iobase + EA_8005_STATUS))); + +/* Release the irq */ + + ea_releaseirq(sc); + + /* Cancel any watchdog timer */ + + sc->sc_ethercom.ec_if.if_timer = 0; +} + + +/* + * Reset the chip + * Following this the software registers are reset + */ + +static void +ea_chipreset(sc) + struct ea_softc *sc; +{ + u_int iobase = sc->sc_iobase; + + dprintf(("ea_chipreset()\n")); + +/* Reset the controller. Min of 4us delay here */ + + WriteShort(iobase + EA_8005_CONFIG2, EA_CFG2_RESET); + delay(100); + + sc->sc_command = 0; + sc->sc_config1 = 0; + sc->sc_config2 = 0; +} + + +/* + * Do a hardware reset of the board, and upload the ethernet address again in + * case the board forgets. + */ + +static void +ea_hardreset(sc) + struct ea_softc *sc; +{ + u_int iobase = sc->sc_iobase; + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + int loop; + + + dprintf(("ea_hardreset()\n")); + +/* Stop any activity */ + + ea_stoptx(sc); + ea_stoprx(sc); + + ea_chipreset(sc); + +/* Set up defaults for the registers */ + + sc->sc_config2 = 0; + WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2); + sc->sc_command = 0x00; + sc->sc_config1 = EA_CFG1_STATION_ADDR0 | EA_CFG1_DMA_BSIZE_1 | EA_CFG1_DMA_BURST_CONT; + WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1); + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command); + + WriteShort(iobase + EA_8005_CONFIG1, EA_BUFCODE_TX_EAP); + WriteShort(iobase + EA_8005_BUFWIN, ((EA_TX_BUFFER_SIZE >> 8) - 1)); + +/* Write the station address - the receiver must be off */ + + WriteShort(sc->sc_iobase + EA_8005_CONFIG1, + sc->sc_config1 | EA_BUFCODE_STATION_ADDR0); + for (loop = 0; loop < ETHER_ADDR_LEN; ++loop) { + WriteByte(sc->sc_iobase + EA_8005_BUFWIN, + LLADDR(ifp->if_sadl)[loop]); + } +} + + +/* + * write to the buffer memory on the interface + * + * If addr is within range for the interface buffer then the buffer + * address is set to addr. + * If len != 0 then data is copied from the address starting at buf + * to the interface buffer. + */ + +static void +ea_writebuf(sc, buf, addr, len) + struct ea_softc *sc; + u_char *buf; + int addr; + int len; +{ + u_int iobase = sc->sc_iobase; + int loop; + int timeout; + + dprintf(("writebuf: st=%04x\n", ReadShort(iobase + EA_8005_STATUS))); + +/* If we have a valid buffer address set the buffer pointer and direction */ + + if (addr >= 0 && addr < EA_BUFFER_SIZE) { + WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM); + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_WRITE); + + /* Should wait here of FIFO empty flag */ + + timeout = 20000; + while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0); + + + WriteShort(iobase + EA_8005_DMA_ADDR, addr); + } + + for (loop = 0; loop < len; loop += 2) + WriteShort(iobase + EA_8005_BUFWIN, buf[loop] | buf[loop + 1] << 8); + +/* if (len > 0) + outsw(iobase + EA_8005_BUFWIN, buf, len / 2);*/ +} + + +/* + * read from the buffer memory on the interface + * + * If addr is within range for the interface buffer then the buffer + * address is set to addr. + * If len != 0 then data is copied from the interface buffer to the + * address starting at buf. + */ + +static void +ea_readbuf(sc, buf, addr, len) + struct ea_softc *sc; + u_char *buf; + int addr; + int len; +{ + u_int iobase = sc->sc_iobase; + int loop; + int word; + int timeout; + + dprintf(("readbuf: st=%04x addr=%04x len=%d\n", ReadShort(iobase + EA_8005_STATUS), addr, len)); + +/* If we have a valid buffer address set the buffer pointer and direction */ + + if (addr >= 0 && addr < EA_BUFFER_SIZE) { + if ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_DIR) == 0) { + /* Should wait here of FIFO empty flag */ + + timeout = 20000; + while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0); + } + WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_LOCAL_MEM); + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_WRITE); + + /* Should wait here of FIFO empty flag */ + + timeout = 20000; + while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_EMPTY) == 0 && --timeout > 0); + + WriteShort(iobase + EA_8005_DMA_ADDR, addr); + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_FIFO_READ); + + /* Should wait here of FIFO full flag */ + + timeout = 20000; + while ((ReadShort(iobase + EA_8005_STATUS) & EA_STATUS_FIFO_FULL) == 0 && --timeout > 0); + + + } + + for (loop = 0; loop < len; loop += 2) { + word = ReadShort(iobase + EA_8005_BUFWIN); + buf[loop] = word & 0xff; + buf[loop + 1] = word >> 8; + } +} + + +/* + * Initialize interface. + * + * This should leave the interface in a state for packet reception and transmission + */ + +static int +ea_init(sc) + struct ea_softc *sc; +{ + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + u_int iobase = sc->sc_iobase; + int s; + + dprintf(("ea_init()\n")); + + s = splnet(); + +/* Grab an irq */ + + ea_claimirq(sc); + + /* First, reset the board. */ + + ea_hardreset(sc); + +/* Configure rx. */ + + dprintf(("Configuring rx...\n")); + if (ifp->if_flags & IFF_PROMISC) + sc->sc_config1 = EA_CFG1_PROMISCUOUS; + else + sc->sc_config1 = EA_CFG1_BROADCAST; + + sc->sc_config1 |= EA_CFG1_DMA_BSIZE_8 | EA_CFG1_STATION_ADDR0 | EA_CFG1_DMA_BURST_CONT; + WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1); + +/* Configure TX. */ + + dprintf(("Configuring tx...\n")); + + WriteShort(iobase + EA_8005_CONFIG1, sc->sc_config1 | EA_BUFCODE_TX_EAP); + WriteShort(iobase + EA_8005_BUFWIN, ((EA_TX_BUFFER_SIZE >> 8) - 1)); + WriteShort(iobase + EA_8005_TX_PTR, 0x0000); + + sc->sc_config2 |= EA_CFG2_OUTPUT; + WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2); + +/* Place a NULL header at the beginning of the transmit area */ + + ea_writebuf(sc, NULL, 0x0000, 0); + + WriteShort(iobase + EA_8005_BUFWIN, 0x0000); + WriteShort(iobase + EA_8005_BUFWIN, 0x0000); + + sc->sc_command |= EA_CMD_TX_INTEN; + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command); + +/* Setup the Rx pointers */ + + sc->sc_rx_ptr = EA_TX_BUFFER_SIZE; + + WriteShort(iobase + EA_8005_RX_PTR, sc->sc_rx_ptr); + WriteShort(iobase + EA_8005_RX_END, (sc->sc_rx_ptr >> 8)); + +/* Place a NULL header at the beginning of the receive area */ + + ea_writebuf(sc, NULL, sc->sc_rx_ptr, 0); + + WriteShort(iobase + EA_8005_BUFWIN, 0x0000); + WriteShort(iobase + EA_8005_BUFWIN, 0x0000); + +/* Turn on Rx */ + + sc->sc_command |= EA_CMD_RX_INTEN; + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_RX_ON); + + /* Set flags appropriately. */ + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + + dprintf(("init: st=%04x\n", ReadShort(iobase + EA_8005_STATUS))); + + /* And start output. */ + ea_start(ifp); + + (void)splx(s); + return(0); +} + + +/* + * Start output on interface. Get datagrams from the queue and output them, + * giving the receiver a chance between datagrams. Call only from splnet or + * interrupt level! + */ + +static void +ea_start(ifp) + struct ifnet *ifp; +{ + struct ea_softc *sc = ifp->if_softc; + int s; + + s = splnet(); +#ifdef EA_TX_DEBUG + dprintf(("ea_start()...\n")); +#endif + + /* Don't do anything if output is active. */ + + if (ifp->if_flags & IFF_OACTIVE) + return; + + /* Mark interface as output active */ + + ifp->if_flags |= IFF_OACTIVE; + + /* tx packets */ + + eatxpacket(sc); + (void)splx(s); +} + + +/* + * Transfer a packet to the interface buffer and start transmission + * + * Called at splnet() + */ + +void +eatxpacket(sc) + struct ea_softc *sc; +{ + u_int iobase = sc->sc_iobase; + struct mbuf *m, *m0; + struct ifnet *ifp; + int len; + + ifp = &sc->sc_ethercom.ec_if; + +/* Dequeue the next datagram. */ + + IF_DEQUEUE(&ifp->if_snd, m0); + +/* If there's nothing to send, return. */ + + if (!m0) { + ifp->if_flags &= ~IFF_OACTIVE; + sc->sc_config2 |= EA_CFG2_OUTPUT; + WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2); +#ifdef EA_TX_DEBUG + dprintf(("tx finished\n")); +#endif + return; + } + + /* Give the packet to the bpf, if any. */ +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m0); +#endif + +#ifdef EA_TX_DEBUG + dprintf(("Tx new packet\n")); +#endif + +/* + * Copy the datagram to the temporary buffer. + * + * Eventually we may as well just copy straight into the interface buffer + */ + + len = 0; + for (m = m0; m; m = m->m_next) { + if (m->m_len == 0) + continue; + bcopy(mtod(m, caddr_t), sc->sc_pktbuf + len, m->m_len); + len += m->m_len; + } + m_freem(m0); + +/* If packet size is odd round up to the next 16 bit boundry */ + + if (len % 2) + ++len; + + len = max(len, ETHER_MIN_LEN); + + if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) + log(LOG_WARNING, "ea: oversize packet = %d bytes\n", len); + +/* Ok we now have a packet len bytes long in our packet buffer */ + +/* Transfer datagram to board. */ + +#ifdef EA_TX_DEBUG + dprintf(("ea: xfr pkt length=%d...\n", len)); + + dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6))); + dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf))); +#endif + + sc->sc_config2 &= ~EA_CFG2_OUTPUT; + WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2); + +/* dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/ + +/* Write the packet to the interface buffer, skipping the packet header */ + + ea_writebuf(sc, sc->sc_pktbuf, 0x0004, len); + +/* Follow it with a NULL packet header */ + + WriteShort(iobase + EA_8005_BUFWIN, 0x00); + WriteShort(iobase + EA_8005_BUFWIN, 0x00); + +/* Write the packet header */ + + ea_writebuf(sc, NULL, 0x0000, 0); + + WriteShort(iobase + EA_8005_BUFWIN, (((len+4) & 0xff00) >> 8) | (((len+4) & 0xff) << 8)); + WriteShort(iobase + EA_8005_BUFWIN, 0x00aa); + + WriteShort(iobase + EA_8005_TX_PTR, 0x0000); + +/* dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/ + +#ifdef EA_DEBUG + ea_dump_buffer(sc, 0); +#endif + +/* Now transmit the datagram. */ + +/* dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS)));*/ + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command | EA_CMD_TX_ON); +#ifdef EA_TX_DEBUG + dprintf(("st=%04x\n", ReadShort(iobase + EA_8005_STATUS))); + dprintf(("tx: queued\n")); +#endif +} + + +/* + * Ethernet controller interrupt. + */ + +int +eaintr(arg) + void *arg; +{ + register struct ea_softc *sc = arg; + u_int iobase = sc->sc_iobase; + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + int status, s, handled; + u_int txstatus; + + handled = 0; + dprintf(("eaintr: ")); + +/* Get the controller status */ + + status = ReadShort(iobase + EA_8005_STATUS); + dprintf(("st=%04x ", status)); + +/* Tx interrupt ? */ + + if (status & EA_STATUS_TX_INT) { + dprintf(("txint ")); + handled = 1; + +/* Acknowledge the interrupt */ + + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command + | EA_CMD_TX_INTACK); + + ea_readbuf(sc, (u_char *)&txstatus, 0x0000, 4); + +#ifdef EA_TX_DEBUG + dprintf(("txstatus=%08x\n", txstatus)); +#endif + txstatus = (txstatus >> 24) & 0xff; + +/* + * Did it succeed ? Did we collide ? + * + * The exact proceedure here is not clear. We should get + * an interrupt on a sucessfull tx or on a collision. + * The done flag is set after successfull tx or 16 collisions + * We should thus get a interrupt for each of collision + * and the done bit should not be set. However it does appear + * to be set at the same time as the collision bit ... + * + * So we will count collisions and output errors and will assume + * that if the done bit is set the packet was transmitted. + * Stats may be wrong if 16 collisions occur on a packet + * as the done flag should be set but the packet may not have been + * transmitted. so the output count might not require incrementing + * if the 16 collisions flags is set. I don;t know abou this until + * it happens. + */ + + if (txstatus & EA_TXHDR_COLLISION) { + ifp->if_collisions++; + } else if (txstatus & EA_TXHDR_ERROR_MASK) { + ifp->if_oerrors++; + } + +/* if (txstatus & EA_TXHDR_ERROR_MASK) { + log(LOG_WARNING, "tx packet error =%02x\n", txstatus); + }*/ + + if (txstatus & EA_PKTHDR_DONE) { + ifp->if_opackets++; + + /* Tx next packet */ + + s = splnet(); + eatxpacket(sc); + (void)splx(s); + } + } + +/* Rx interrupt ? */ + + if (status & EA_STATUS_RX_INT) { + dprintf(("rxint ")); + handled = 1; + +/* Acknowledge the interrupt */ + + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command + | EA_CMD_RX_INTACK); + +/* Install a watchdog timer needed atm to fixed rx lockups */ + + ifp->if_timer = EA_TIMEOUT; + +/* Processes the received packets */ + eagetpackets(sc); + +/* Make sure the receiver is on */ + +/* if ((status & EA_STATUS_RX_ON) == 0) { + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command + | EA_CMD_RX_ON); + printf("rxintr: rx is off st=%04x\n",status); + }*/ + } + +#ifdef EA_DEBUG + status = ReadShort(iobase + EA_8005_STATUS); + dprintf(("st=%04x\n", status)); +#endif + + return handled; /* Pass interrupt on down the chain */ +} + + +void +eagetpackets(sc) + struct ea_softc *sc; +{ + u_int iobase = sc->sc_iobase; + int addr; + int len; + int ctrl; + int ptr; + int pack; + int status; + u_int rxstatus; + struct ifnet *ifp; + + ifp = &sc->sc_ethercom.ec_if; + +/* We start from the last rx pointer position */ + + addr = sc->sc_rx_ptr; + sc->sc_config2 &= ~EA_CFG2_OUTPUT; + WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2); + + do { +/* Read rx header */ + + ea_readbuf(sc, (u_char *)&rxstatus, addr, 4); + +/* Split the packet header */ + + ptr = ((rxstatus & 0xff) << 8) | ((rxstatus >> 8) & 0xff); + ctrl = (rxstatus >> 16) & 0xff; + status = (rxstatus >> 24) & 0xff; + +#ifdef EA_RX_DEBUG + dprintf(("addr=%04x ptr=%04x ctrl=%02x status=%02x\n", addr, ptr, ctrl, status)); +#endif + +/* Zero packet ptr ? then must be null header so exit */ + + if (ptr == 0) break; + +/* Get packet length */ + + len = (ptr - addr) - 4; + + if (len < 0) { + len += EA_RX_BUFFER_SIZE; + } + +#ifdef EA_RX_DEBUG + dprintf(("len=%04x\n", len)); +#endif + +/* Has the packet rx completed ? if not then exit */ + + if ((status & EA_PKTHDR_DONE) == 0) + break; + +/* Did we have any errors ? then note error and go to next packet */ + + if (status & 0x0f) { + ++ifp->if_ierrors; + printf("rx packet error (%02x) - dropping packet\n", status & 0x0f); + sc->sc_config2 |= EA_CFG2_OUTPUT; + WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2); + ea_reinit(sc); + return; + } + +/* Is the packet too big ? - this will probably be trapped above as a receive error */ + + if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) { + ++ifp->if_ierrors; + printf("rx packet size error len=%d\n", len); + sc->sc_config2 |= EA_CFG2_OUTPUT; + WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2); + ea_reinit(sc); + return; + } + + ea_readbuf(sc, sc->sc_pktbuf, addr + 4, len); + +#ifdef EA_RX_DEBUG + dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6))); + dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf))); +#endif + ifp->if_ipackets++; + /* Pass data up to upper levels. */ + earead(sc, (caddr_t)sc->sc_pktbuf, len); + + addr = ptr; + ++pack; + } while (len != 0); + + sc->sc_config2 |= EA_CFG2_OUTPUT; + WriteShort(iobase + EA_8005_CONFIG2, sc->sc_config2); + +#ifdef EA_RX_DEBUG + dprintf(("new rx ptr=%04x\n", addr)); +#endif + +/* Store new rx pointer */ + + sc->sc_rx_ptr = addr; + WriteShort(iobase + EA_8005_RX_END, (sc->sc_rx_ptr >> 8)); + +/* Make sure the receiver is on */ + + WriteShort(iobase + EA_8005_COMMAND, sc->sc_command + | EA_CMD_RX_ON); + +} + + +/* + * Pass a packet up to the higher levels. + */ + +static void +earead(sc, buf, len) + struct ea_softc *sc; + caddr_t buf; + int len; +{ + register struct ether_header *eh; + struct mbuf *m; + struct ifnet *ifp; + + ifp = &sc->sc_ethercom.ec_if; + eh = (struct ether_header *)buf; + + /* Pull packet off interface. */ + m = eaget(buf, len, ifp); + if (m == 0) + return; + +#if NBPFILTER > 0 + /* + * Check if there's a BPF listener on this interface. + * If so, hand off the raw packet to bpf. + */ + if (ifp->if_bpf) { + bpf_mtap(ifp->if_bpf, m); + + /* + * Note that the interface cannot be in promiscuous mode if + * there are no BPF listeners. And if we are in promiscuous + * mode, we have to check if this packet is really ours. + */ + if ((ifp->if_flags & IFF_PROMISC) && + (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ + bcmp(eh->ether_dhost, LLADDR(ifp->if_sadl), + sizeof(eh->ether_dhost)) != 0) { + m_freem(m); + return; + } + } +#endif + + (*ifp->if_input)(ifp, m); +} + +/* + * Pull read data off a interface. Len is length of data, with local net + * header stripped. We copy the data into mbufs. When full cluster sized + * units are present we copy into clusters. + */ + +struct mbuf * +eaget(buf, totlen, ifp) + caddr_t buf; + int totlen; + struct ifnet *ifp; +{ + struct mbuf *top, **mp, *m; + int len; + register caddr_t cp = buf; + char *epkt; + + cp = buf; + epkt = cp + totlen; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) + return 0; + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + m->m_len = MHLEN; + top = 0; + mp = ⊤ + + while (totlen > 0) { + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + return 0; + } + m->m_len = MLEN; + } + len = min(totlen, epkt - cp); + if (len >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + m->m_len = len = min(len, MCLBYTES); + else + len = m->m_len; + } else { + /* + * Place initial small packet/header at end of mbuf. + */ + if (len < m->m_len) { + if (top == 0 && len + max_linkhdr <= m->m_len) + m->m_data += max_linkhdr; + m->m_len = len; + } else + len = m->m_len; + } + bcopy(cp, mtod(m, caddr_t), (unsigned)len); + cp += len; + *mp = m; + mp = &m->m_next; + totlen -= len; + if (cp == epkt) + cp = buf; + } + + return top; +} + +/* + * Process an ioctl request. This code needs some work - it looks pretty ugly. + */ +static int +ea_ioctl(ifp, cmd, data) + register struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + struct ea_softc *sc = ifp->if_softc; + struct ifaddr *ifa = (struct ifaddr *)data; +/* struct ifreq *ifr = (struct ifreq *)data;*/ + int s, error = 0; + + s = splnet(); + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + dprintf(("if_flags=%08x\n", ifp->if_flags)); + + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + arp_ifinit(ifp, ifa); + dprintf(("Interface ea is coming up (AF_INET)\n")); + ea_init(sc); + break; +#endif +#ifdef NS + /* XXX - This code is probably wrong. */ + case AF_NS: + { + register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; + + if (ns_nullhost(*ina)) + ina->x_host = + *(union ns_host *)LLADDR(ifp->if_sadl); + else + bcopy(ina->x_host.c_host, + LLADDR(ifp->if_sadl), ETHER_ADDR_LEN); + /* Set new address. */ + dprintf(("Interface ea is coming up (AF_NS)\n")); + ea_init(sc); + break; + } +#endif + default: + dprintf(("Interface ea is coming up (default)\n")); + ea_init(sc); + break; + } + break; + + case SIOCSIFFLAGS: + dprintf(("if_flags=%08x\n", ifp->if_flags)); + if ((ifp->if_flags & IFF_UP) == 0 && + (ifp->if_flags & IFF_RUNNING) != 0) { + /* + * If interface is marked down and it is running, then + * stop it. + */ + dprintf(("Interface ea is stopping\n")); + ea_stop(sc); + ifp->if_flags &= ~IFF_RUNNING; + } else if ((ifp->if_flags & IFF_UP) != 0 && + (ifp->if_flags & IFF_RUNNING) == 0) { + /* + * If interface is marked up and it is stopped, then + * start it. + */ + dprintf(("Interface ea is restarting(1)\n")); + ea_init(sc); + } else { + /* + * Some other important flag might have changed, so + * reset. + */ + dprintf(("Interface ea is reinitialising\n")); + ea_reinit(sc); + } + break; + + default: + error = EINVAL; + break; + } + + (void)splx(s); + return error; +} + +/* + * Device timeout routine. + * + * Ok I am not sure exactly how the device timeout should work.... + * Currently what will happens is that that the device timeout is only + * set when a packet it received. This indicates we are on an active + * network and thus we should expect more packets. If non arrive in + * in the timeout period then we reinitialise as we may have jammed. + * We zero the timeout at this point so that we don't end up with + * an endless stream of timeouts if the network goes down. + */ + +static void +ea_watchdog(ifp) + struct ifnet *ifp; +{ + struct ea_softc *sc = ifp->if_softc; + + log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); + ifp->if_oerrors++; + dprintf(("ea_watchdog: ")); + dprintf(("st=%04x\n", ReadShort(sc->sc_iobase + EA_8005_STATUS))); + + /* Kick the interface */ + + ea_reinit(sc); + +/* ifp->if_timer = EA_TIMEOUT;*/ + ifp->if_timer = 0; +} + +/* End of if_ea.c */ diff --git a/sys/arch/arm26/podulebus/if_eareg.h b/sys/arch/arm26/podulebus/if_eareg.h new file mode 100644 index 00000000000..e3c841ad53a --- /dev/null +++ b/sys/arch/arm26/podulebus/if_eareg.h @@ -0,0 +1,168 @@ +/* $NetBSD: if_eareg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe + * 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 Mark Brinicombe. + * 4. The name of the company nor the name of the author may 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 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. + * + * RiscBSD kernel project + * + * if_eareg.h + * + * Ether3 device driver + * + * Created : 08/07/95 + */ + +/* + * SEEQ 8005 Register Definitions + */ + +#define EA_8005_BASE 0x000 + +/* + * SEEQ 8005 registers + */ + + +#define EA_8005_COMMAND 0x000 +#define EA_8005_STATUS 0x000 +#define EA_8005_CONFIG1 0x040 +#define EA_8005_CONFIG2 0x080 +#define EA_8005_RX_END 0x0c0 +#define EA_8005_BUFWIN 0x100 +#define EA_8005_RX_PTR 0x140 +#define EA_8005_TX_PTR 0x180 +#define EA_8005_DMA_ADDR 0x1c0 + +/* */ + +#define EA_CMD_DMA_INTEN (1 << 0) +#define EA_CMD_RX_INTEN (1 << 1) +#define EA_CMD_TX_INTEN (1 << 2) +#define EA_CMD_BW_INTEN (1 << 3) +#define EA_CMD_DMA_INTACK (1 << 4) +#define EA_CMD_RX_INTACK (1 << 5) +#define EA_CMD_TX_INTACK (1 << 6) +#define EA_CMD_BW_INTACK (1 << 7) +#define EA_CMD_DMA_ON (1 << 8) +#define EA_CMD_RX_ON (1 << 9) +#define EA_CMD_TX_ON (1 << 10) +#define EA_CMD_DMA_OFF (1 << 11) +#define EA_CMD_RX_OFF (1 << 12) +#define EA_CMD_TX_OFF (1 << 13) +#define EA_CMD_FIFO_READ (1 << 14) +#define EA_CMD_FIFO_WRITE (1 << 15) + +#define EA_STATUS_DMA_INT (1 << 4) +#define EA_STATUS_RX_INT (1 << 5) +#define EA_STATUS_TX_INT (1 << 6) +#define EA_STATUS_RX_ON (1 << 9) +#define EA_STATUS_TX_ON (1 << 10) +#define EA_STATUS_FIFO_FULL (1 << 13) +#define EA_STATUS_FIFO_EMPTY (1 << 14) +#define EA_STATUS_FIFO_DIR (1 << 15) +#define EA_STATUS_FIFO_READ (1 << 15) + +#define EA_CFG1_DMA_BURST_CONT 0x00 +#define EA_CFG1_DMA_BURST_800 0x10 +#define EA_CFG1_DMA_BURST_1600 0x20 +#define EA_CFG1_DMA_BURST_3200 0x30 +#define EA_CFG1_DMA_BSIZE_1 0x00 +#define EA_CFG1_DMA_BSIZE_4 0x40 +#define EA_CFG1_DMA_BSIZE_8 0x80 +#define EA_CFG1_DMA_BSIZE_16 0xc0 + +#define EA_CFG1_STATION_ADDR0 (1 << 8) +#define EA_CFG1_STATION_ADDR1 (1 << 9) +#define EA_CFG1_STATION_ADDR2 (1 << 10) +#define EA_CFG1_STATION_ADDR3 (1 << 11) +#define EA_CFG1_STATION_ADDR4 (1 << 12) +#define EA_CFG1_STATION_ADDR5 (1 << 13) +#define EA_CFG1_SPECIFIC ((0 << 15) | (0 << 14)) +#define EA_CFG1_BROADCAST ((0 << 15) | (1 << 14)) +#define EA_CFG1_MULTICAST ((1 << 15) | (0 << 14)) +#define EA_CFG1_PROMISCUOUS ((1 << 15) | (1 << 14)) + +#define EA_CFG2_BYTESWAP (1 << 0) +#define EA_CFG2_CRC_ERR_ENABLE (1 << 3) +#define EA_CFG2_DRIB_ERR_ENABLE (1 << 4) +#define EA_CFG2_PASS_SHORT (1 << 5) +#define EA_CFG2_SLOT_SELECT (1 << 6) +#define EA_CFG2_PREAM_SELECT (1 << 7) +#define EA_CFG2_ADDR_LENGTH (1 << 8) +#define EA_CFG2_RX_CRC (1 << 9) +#define EA_CFG2_NO_TX_CRC (1 << 10) +#define EA_CFG2_LOOPBACK (1 << 11) +#define EA_CFG2_OUTPUT (1 << 12) +#define EA_CFG2_RESET (1 << 15) + +#define EA_BUFCODE_STATION_ADDR0 0x00 +#define EA_BUFCODE_STATION_ADDR1 0x01 +#define EA_BUFCODE_STATION_ADDR2 0x02 +#define EA_BUFCODE_STATION_ADDR3 0x03 +#define EA_BUFCODE_STATION_ADDR4 0x04 +#define EA_BUFCODE_STATION_ADDR5 0x05 +#define EA_BUFCODE_ADDRESS_PROM 0x06 +#define EA_BUFCODE_TX_EAP 0x07 +#define EA_BUFCODE_LOCAL_MEM 0x08 +#define EA_BUFCODE_INT_VECTOR 0x09 +/*#define EA_BUFCODE_MULTICAST 0x0f*/ + +#define EA_PKTHDR_TX (1 << 7) +#define EA_PKTHDR_RX (0 << 7) +#define EA_PKTHDR_CHAIN_CONT (1 << 6) +#define EA_PKTHDR_DATA_FOLLOWS (1 << 5) + +#define EA_PKTHDR_DONE (1 << 7) + +#define EA_TXHDR_BABBLE (1 << 0) +#define EA_TXHDR_COLLISION (1 << 1) +#define EA_TXHDR_COLLISION16 (1 << 2) + +#define EA_TXHDR_BABBLE_INT (1 << 0) +#define EA_TXHDR_COLLISION_INT (1 << 1) +#define EA_TXHDR_COLLISION16_INT (1 << 2) +#define EA_TXHDR_XMIT_SUCCESS_INT (1 << 3) +#define EA_TXHDR_ERROR_MASK (0x07) + +#define EA_RXHDR_OVERSIZE (1 << 0) +#define EA_RXHDR_CRC_ERROR (1 << 1) +#define EA_RXHDR_DRIBBLE_ERROR (1 << 2) +#define EA_RXHDR_SHORT_FRAME (1 << 3) + +#define EA_BUFFER_SIZE 0x10000 +#define EA_TX_BUFFER_SIZE 0x4000 +#define EA_RX_BUFFER_SIZE 0xC000 + +/* Packet buffer size */ + +#define EA_BUFSIZ 2048 + +/* End of if_eareg.h */ diff --git a/sys/arch/arm26/podulebus/if_ei.c b/sys/arch/arm26/podulebus/if_ei.c new file mode 100644 index 00000000000..83d5c7a45ca --- /dev/null +++ b/sys/arch/arm26/podulebus/if_ei.c @@ -0,0 +1,371 @@ +/* $NetBSD: if_ei.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * if_ei.c -- driver for Acorn AKA25 Ether1 card + */ +/* + * This is not directly based on the arm32 ie driver, as that doesn't + * use the MI 82586 driver, and generally looks a mess (not to mention + * having dodgy copyright status). Let's try again. + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: if_ei.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/socket.h> +#include <sys/syslog.h> +#include <sys/systm.h> +#include <net/if.h> +#include <net/if_ether.h> +#include <net/if_media.h> +#include <machine/bus.h> +#include <machine/irq.h> +#include <dev/ic/i82586reg.h> +#include <dev/ic/i82586var.h> +#include <arch/arm26/podulebus/podulebus.h> +#include <arch/arm32/podulebus/podules.h> +#include <arch/arm26/podulebus/if_eireg.h> + +/* Callbacks from the MI 82586 driver */ +static void ei_hwreset(struct ie_softc *, int); +/* static void ei_hwinit(struct ie_softc *); */ +static void ei_attn(struct ie_softc *); +static int ei_intrhook(struct ie_softc *, int); + +static void ei_copyin(struct ie_softc *, void *, int, size_t); +static void ei_copyout(struct ie_softc *, const void *, int, size_t); +static u_int16_t ei_read16(struct ie_softc *, int); +static void ei_write16(struct ie_softc *, int, u_int16_t); +static void ei_write24(struct ie_softc *, int, int); + +/* autoconfiguration glue */ +static int ei_match(struct device *, struct cfdata *, void *); +static void ei_attach(struct device *, struct device *, void *); + +struct ei_softc { + struct ie_softc sc_ie; + bus_space_tag_t sc_ctl_t; + bus_space_handle_t sc_ctl_h; + bus_space_tag_t sc_mem_t; + bus_space_handle_t sc_mem_h; + bus_space_tag_t sc_rom_t; + bus_space_handle_t sc_rom_h; + u_int8_t sc_idrom[EI_ROMSIZE]; + struct irq_handler *sc_ih; +}; + +struct cfattach ei_ca = { + sizeof(struct ei_softc), ei_match, ei_attach +}; + +static inline void +ei_setpage(struct ei_softc *sc, int page) +{ + + bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, EI_PAGE, page); +} + +static inline void +ei_cli(struct ei_softc *sc) +{ + + bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, EI_CONTROL, EI_CTL_CLI); +} + +static int +ei_match(struct device *parent, struct cfdata *cf, void *aux) +{ + struct podulebus_attach_args *pa = aux; + + return IS_PODULE(pa, MANUFACTURER_ACORN, PODULE_ACORN_ETHER1); +} + +static void +ei_attach(struct device *parent, struct device *self, void *aux) +{ + struct podulebus_attach_args *pa = aux; + struct ei_softc *sc = (struct ei_softc *)self; + int i; + char descr[16]; + + /* Set up bus spaces */ + sc->sc_ctl_t = sc->sc_mem_t = pa->pa_fast_t; + bus_space_subregion(sc->sc_ctl_t, pa->pa_fast_h, + 0, EI_MEMOFF, &sc->sc_ctl_h); + bus_space_subregion(sc->sc_mem_t, pa->pa_fast_h, + EI_MEMOFF, EI_PAGESIZE / 2, &sc->sc_mem_h); + sc->sc_rom_t = pa->pa_sync_t; + sc->sc_rom_h = pa->pa_sync_h; + + /* Set up callbacks */ + sc->sc_ie.hwinit = NULL; + sc->sc_ie.intrhook = ei_intrhook; + sc->sc_ie.hwreset = ei_hwreset; + sc->sc_ie.chan_attn = ei_attn; + + sc->sc_ie.memcopyin = ei_copyin; + sc->sc_ie.memcopyout = ei_copyout; + sc->sc_ie.ie_bus_read16 = ei_read16; + sc->sc_ie.ie_bus_write16 = ei_write16; + sc->sc_ie.ie_bus_write24 = ei_write24; + + sc->sc_ie.do_xmitnopchain = 0; /* Does it listen? */ + + sc->sc_ie.sc_mediachange = NULL; + sc->sc_ie.sc_mediastatus = NULL; + + sc->sc_ie.bt = sc->sc_mem_t; /* XXX hope it doesn't use them */ + sc->sc_ie.bh = sc->sc_mem_h; + + printf(":"); + + /* All Ether1s are 64k (I believe) */ + sc->sc_ie.sc_msize = EI_MEMSIZE; + + /* set up pointers to important on-card control structures */ + sc->sc_ie.iscp = 0; + sc->sc_ie.scb = IE_ISCP_SZ; + sc->sc_ie.scp = sc->sc_ie.sc_msize + IE_SCP_ADDR - (1 << 24); + + sc->sc_ie.buf_area = sc->sc_ie.scb + IE_SCB_SZ; + sc->sc_ie.buf_area_sz = + sc->sc_ie.sc_msize - IE_ISCP_SZ - IE_SCB_SZ - IE_SCP_SZ; + + /* Wipe the whole of the card's memory */ + for (i = 0; i < EI_NPAGES; i++) { + ei_setpage(sc, i); + bus_space_set_region_2(sc->sc_mem_t, sc->sc_mem_h, + 0, 0,EI_PAGESIZE / 2); + } + + /* set up pointers to key structures */ + ei_write24(&sc->sc_ie, IE_SCP_ISCP((u_long)sc->sc_ie.scp), + (u_long) sc->sc_ie.iscp); + ei_write16(&sc->sc_ie, IE_ISCP_SCB((u_long)sc->sc_ie.iscp), + (u_long) sc->sc_ie.scb); + ei_write24(&sc->sc_ie, IE_ISCP_BASE((u_long)sc->sc_ie.iscp), + (u_long) sc->sc_ie.iscp); + + /* check if chip answers */ + if (i82586_proberam(&sc->sc_ie) == 0) { + printf(" memory probe failed\n"); + return; + } + + /* Read ROM */ + bus_space_read_region_1(sc->sc_rom_t, sc->sc_rom_h, 0, + sc->sc_idrom, EI_ROMSIZE); + + snprintf(descr, 15, "AKA25 iss. %d", sc->sc_idrom[EI_ROM_HWREV]); + i82586_attach(&sc->sc_ie, descr, sc->sc_idrom + EI_ROM_EADDR, + NULL, 0, 0); + + sc->sc_ih = podulebus_irq_establish(self->dv_parent, pa->pa_slotnum, + IPL_NET, i82586_intr, self); + printf("%s: interrupting at %s\n", + self->dv_xname, irq_string(sc->sc_ih)); + ei_cli(sc); + irq_enable(sc->sc_ih); +} + +static void +ei_hwreset(struct ie_softc *sc_ie, int why) +{ + struct ei_softc *sc = (struct ei_softc *)sc_ie; + + bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, + EI_CONTROL, EI_CTL_RESET); + DELAY(1000); + bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, EI_CONTROL, 0); + DELAY(1000); + ei_cli(sc); +} + +static int +ei_intrhook(struct ie_softc *sc_ie, int why) +{ + struct ei_softc *sc = (struct ei_softc *)sc_ie; + + switch (why) { + case INTR_EXIT: + case INTR_ACK: + ei_cli(sc); + break; + } + return 0; +} + +static void +ei_attn(struct ie_softc *sc_ie) +{ + struct ei_softc *sc = (void *)sc_ie; + + bus_space_write_1(sc->sc_ctl_t, sc->sc_ctl_h, EI_CONTROL, EI_CTL_ATTN); +} + +/* + * Various access functions to allow the MI 82586 driver to get at the + * board's memory. All memory accesses must go through these, as + * nothing else knows how to manipulate the page register. Note that + * all addresses and lengths passed in are in bytes of actual data. + * The bus_space functions deal in words, though, so we have to + * convert on the way through. + */ + +static void +ei_copyin(struct ie_softc *sc_ie, void *dest, int src, size_t size) +{ + struct ei_softc *sc = (struct ei_softc *)sc_ie; + int cnt, s, extra_byte; + +#ifdef DIAGNOSTIC + if (src % 2 != 0 || !ALIGNED_POINTER(dest, u_int16_t)) + panic("%s: unaligned copyin", sc_ie->sc_dev.dv_xname); +#endif + extra_byte = size % 2; + size -= extra_byte; + while (size > 0) { + cnt = EI_PAGESIZE - src % EI_PAGESIZE; + if (cnt > size) + cnt = size; + s = splnet(); + ei_setpage(sc, ei_atop(src)); + /* bus ops are in words */ + bus_space_read_region_2(sc->sc_mem_t, sc->sc_mem_h, + ei_atopo(src) / 2, dest, cnt / 2); + splx(s); + src += cnt; + dest += cnt; + size -= cnt; + } + if (extra_byte) { + /* Do we need to be this careful? */ + s = splnet(); + ei_setpage(sc, ei_atop(src)); + *(u_int8_t *)dest = + bus_space_read_2(sc->sc_mem_t, sc->sc_mem_h, + ei_atopo(src) / 2) & 0xff; + splx(s); + } + +} + +static void +ei_copyout(struct ie_softc *sc_ie, const void *src, int dest, size_t size) +{ + struct ei_softc *sc = (struct ei_softc *)sc_ie; + int cnt, s; + u_int16_t *bounce = NULL; + +#ifdef DIAGNOSTIC + if (dest % 2 != 0) + panic("%s: unaligned copyout", sc_ie->sc_dev.dv_xname); +#endif + if (!ALIGNED_POINTER(src, u_int16_t)) { + MALLOC(bounce, u_int16_t *, size, M_DEVBUF, M_NOWAIT); + if (bounce == NULL) + panic("%s: no memory to align copyout", + sc_ie->sc_dev.dv_xname); + memcpy(bounce, src, size); + src = bounce; + } + if (size % 2 != 0) + size++; /* This is safe, since the buffer is 16bit aligned */ + while (size > 0) { + cnt = EI_PAGESIZE - dest % EI_PAGESIZE; + if (cnt > size) + cnt = size; + s = splnet(); + ei_setpage(sc, ei_atop(dest)); + /* bus ops are in words */ + bus_space_write_region_2(sc->sc_mem_t, sc->sc_mem_h, + ei_atopo(dest) / 2, src, cnt / 2); + splx(s); + src += cnt; + dest += cnt; + size -= cnt; + } + if (bounce != NULL) + FREE(bounce, M_DEVBUF); +} + +static u_int16_t +ei_read16(struct ie_softc *sc_ie, int addr) +{ + struct ei_softc *sc = (struct ei_softc *)sc_ie; + int result, s; + +#ifdef DIAGNOSTIC + if (addr % 2 != 0) + panic("%s: unaligned read16", sc_ie->sc_dev.dv_xname); +#endif + s = splnet(); + ei_setpage(sc, ei_atop(addr)); + result = bus_space_read_2(sc->sc_mem_t, sc->sc_mem_h, + ei_atopo(addr) / 2); + splx(s); + return result; +} + +static void +ei_write16(struct ie_softc *sc_ie, int addr, u_int16_t value) +{ + struct ei_softc *sc = (struct ei_softc *)sc_ie; + int s; + +#ifdef DIAGNOSTIC + if (addr % 2 != 0) + panic("%s: unaligned write16", sc_ie->sc_dev.dv_xname); +#endif + s = splnet(); + ei_setpage(sc, ei_atop(addr)); + bus_space_write_2(sc->sc_mem_t, sc->sc_mem_h, ei_atopo(addr) / 2, + value); + splx(s); +} + +static void +ei_write24(struct ie_softc *sc_ie, int addr, int value) +{ + int s; + +#ifdef DIAGNOSTIC + if (addr % 2 != 0) + panic("%s: unaligned write24", sc_ie->sc_dev.dv_xname); +#endif + s = splnet(); + ei_write16(sc_ie, addr, value & 0xffff); + ei_write16(sc_ie, addr + 2, (value >> 16) & 0xff); + splx(s); +} + diff --git a/sys/arch/arm26/podulebus/if_eireg.h b/sys/arch/arm26/podulebus/if_eireg.h new file mode 100644 index 00000000000..63995b5b21e --- /dev/null +++ b/sys/arch/arm26/podulebus/if_eireg.h @@ -0,0 +1,62 @@ +/* $NetBSD: if_eireg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * 2000 Ben Harris + * + * This file is in the public domain. + */ + +/* + * if_eireg.h - register definitions etc for the Acorn Ether1 card + */ + +#ifndef _IF_EIREG_H_ +#define _IF_EIREG_H_ + +/* + * My understanding of this card is as follows. Note that this is + * mostly derived from reading other people's code, so it may be + * hideously inaccurate. + * + * The card has three address spaces. The ROM is mapped into the + * bottom n (16?) bytes of SYNC address space, and contains the + * expansion card ID information and the Ethernet address. There is a + * (write only?) set of registers at the start of the FAST address + * space. One of these performs miscellaneous control functions, and + * the other acts as a page selector for the board memory. The board + * has 64k of RAM, and 4k pages of this can be mapped at offset 0x2000 + * in the FAST space by writing the page number to the page register. + * The 82586 has access to the whole of this memory and (I believe) + * sees it as the top 64k of its address space. + */ + +/* Registers in the board's control space */ +#define EI_PAGE 0 +#define EI_CONTROL 1 +#define EI_CTL_RESET 0x01 +#define EI_CTL_LOOP 0x02 +#define EI_CTL_ATTN 0x04 +#define EI_CTL_CLI 0x08 + +/* Offset of base of memory in bus_space */ +#define EI_MEMOFF 0x800 + +/* + * All addresses within board RAM are in bytes of actual RAM. RAM is + * 16 bis wide, and can only be accessed by word transfers + * (bus_space_xxx_2). + */ +#define EI_MEMSIZE 0x10000 +#define EI_MEMBASE (0x1000000 - EI_MEMSIZE) +#define EI_PAGESIZE 0x1000 +#define EI_NPAGES (EI_MEMSIZE / EI_PAGESIZE) +#define ei_atop(a) (((a) % EI_MEMSIZE) / EI_PAGESIZE) +#define ei_atopo(a) ((a) % EI_PAGESIZE) + +#define EI_SCP_ADDR IE_SCP_ADDR % EI_MEMSIZE + +#define EI_ROMSIZE 16 +#define EI_ROM_HWREV 8 +#define EI_ROM_EADDR 9 + +#endif diff --git a/sys/arch/arm26/podulebus/podulebus.c b/sys/arch/arm26/podulebus/podulebus.c new file mode 100644 index 00000000000..2530cd47b82 --- /dev/null +++ b/sys/arch/arm26/podulebus/podulebus.c @@ -0,0 +1,251 @@ +/* $NetBSD: podulebus.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#include <sys/param.h> + +__RCSID("$NetBSD: podulebus.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/systm.h> +#include <machine/bus.h> +#include <machine/irq.h> +#include <machine/memcreg.h> +#include <arch/arm26/iobus/iocreg.h> +#include <arch/arm26/iobus/iocvar.h> +#include <arch/arm26/podulebus/podulebus.h> +#include <arch/arm26/podulebus/podulebusreg.h> + +#include "locators.h" + +static int podulebus_match(struct device *, struct cfdata *, void *); +static void podulebus_attach(struct device *, struct device *, void *); +static void podulebus_probe_podule(struct device *, int); +static int podulebus_print(void *, char const *); +static int podulebus_submatch(struct device *, struct cfdata *, void *); +static void podulebus_read_chunks(struct device *, + struct podulebus_attach_args *); +static u_int8_t *podulebus_get_chunk(struct podulebus_attach_args *pa, int type); + +struct podulebus_softc { + struct device sc_dev; + struct ioc_attach_args sc_ioc; +}; + +struct cfattach podulebus_ca = { + sizeof(struct podulebus_softc), podulebus_match, podulebus_attach +}; + +extern struct cfdriver podulebus_cd; + +/* ARGSUSED */ +static int +podulebus_match(struct device *parent, struct cfdata *cf, void *aux) +{ + + /* We can't usefully probe for this */ + return 1; +} + +static void +podulebus_attach(struct device *parent, struct device *self, void *aux) +{ + int i; + struct podulebus_softc *sc = (struct podulebus_softc *)self; + struct ioc_attach_args *ioc = aux; + + sc->sc_ioc = *ioc; + printf("\n"); + + /* Iterate over the podules attaching them */ + for (i = 0; i < MAX_PODULES; i++) + podulebus_probe_podule(self, i); +} + +static void +podulebus_probe_podule(struct device *self, int slotnum) +{ + struct podulebus_softc *sc = (struct podulebus_softc *)self; + bus_space_tag_t id_bst; + bus_space_handle_t id_bsh; + int ecid; + u_int8_t extecid[EXTECID_SIZE]; + struct podulebus_attach_args pa; + + bzero(&pa, sizeof(pa)); + id_bst = sc->sc_ioc.ioc_sync_t; + bus_space_subregion(id_bst, sc->sc_ioc.ioc_sync_h, + slotnum * PODULE_GAP, PODULE_GAP, &id_bsh); + ecid = bus_space_read_1(id_bst, id_bsh, 0); + /* Skip empty or strange slots */ + if (ecid & (ECID_NOTPRESENT | ECID_NONCONF)) + return; + if ((ecid & ECID_ID_MASK) == ECID_ID_EXTEND) { + pa.pa_fast_t = sc->sc_ioc.ioc_fast_t; + bus_space_subregion(pa.pa_fast_t, sc->sc_ioc.ioc_fast_h, + slotnum * PODULE_GAP, PODULE_GAP, + &pa.pa_fast_h); + pa.pa_medium_t = sc->sc_ioc.ioc_medium_t; + bus_space_subregion(pa.pa_medium_t, sc->sc_ioc.ioc_medium_h, + slotnum * PODULE_GAP, PODULE_GAP, + &pa.pa_medium_h); + pa.pa_slow_t = sc->sc_ioc.ioc_slow_t; + bus_space_subregion(pa.pa_slow_t, sc->sc_ioc.ioc_slow_h, + slotnum * PODULE_GAP, PODULE_GAP, + &pa.pa_slow_h); + pa.pa_sync_t = sc->sc_ioc.ioc_sync_t; + bus_space_subregion(pa.pa_sync_t, sc->sc_ioc.ioc_sync_h, + slotnum * PODULE_GAP, PODULE_GAP, + &pa.pa_sync_h); + /* XXX This is a hack! */ + pa.pa_memc_t = 2; + bus_space_subregion(pa.pa_memc_t, + (bus_space_handle_t)MEMC_IO_BASE, slotnum * PODULE_GAP, + PODULE_GAP, &pa.pa_memc_h); + bus_space_read_region_1(id_bst, id_bsh, 0, + extecid, EXTECID_SIZE); + pa.pa_ecid = ecid; + pa.pa_flags1 = extecid[EXTECID_F1]; + pa.pa_manufacturer = (extecid[EXTECID_MLO] | + extecid[EXTECID_MHI] << 8); + pa.pa_product = (extecid[EXTECID_PLO] | + extecid[EXTECID_PHI] << 8); + pa.pa_slotnum = slotnum; + if (pa.pa_flags1 & EXTECID_F1_CD) { + podulebus_read_chunks(self, &pa); + pa.pa_descr = podulebus_get_chunk(&pa, + CHUNK_DEV_DESCR); + } + config_found_sm(self, &pa, + podulebus_print, podulebus_submatch); + if (pa.pa_chunks) + FREE(pa.pa_chunks, M_DEVBUF); + if (pa.pa_descr) + FREE(pa.pa_descr, M_DEVBUF); + } else + printf("%s:%d: non-extended podule ignored.\n", + self->dv_xname, slotnum); +} + +static void +podulebus_read_chunks(struct device *self, struct podulebus_attach_args *pa) +{ + u_int8_t chunk[8]; + u_int ptr, w, nchunks, type, length, offset; + + nchunks = 0; + ptr = EXTECID_SIZE + IRQPTR_SIZE; + w = pa->pa_flags1 & EXTECID_F1_W_MASK; + if (w != EXTECID_F1_W_8BIT) { + /* RISC OS 3 can't handle this either. */ + printf("%s:%d: ROM is not 8 bits wide; ignoring it\n", + self->dv_xname, pa->pa_slotnum); + return; + } + for (;;) { + bus_space_read_region_1(pa->pa_sync_t, pa->pa_sync_h, + ptr, chunk, 8); + ptr += 8; + type = chunk[0]; + length = chunk[1] | chunk[2] << 8 | chunk[3] << 16; + if (length == 0) + break; + offset = chunk[4] | chunk[5] << 8 | + chunk[6] << 16 | chunk[7] << 24; + if ((offset + length) > PODULE_GAP) + continue; + nchunks++; + pa->pa_chunks = realloc(pa->pa_chunks, + nchunks * sizeof(*pa->pa_chunks), + M_DEVBUF, M_WAITOK); + pa->pa_chunks[nchunks-1].pc_type = type; + pa->pa_chunks[nchunks-1].pc_length = length; + pa->pa_chunks[nchunks-1].pc_offset = offset; + } + pa->pa_nchunks = nchunks; +} + +static u_int8_t * +podulebus_get_chunk(struct podulebus_attach_args *pa, int type) +{ + int i; + u_int8_t *chunk; + + for (i = 0; i < pa->pa_nchunks; i++) + if (pa->pa_chunks[i].pc_type == type) { + MALLOC(chunk, u_int8_t *, + pa->pa_chunks[i].pc_length + 1, + M_DEVBUF, M_WAITOK); + bus_space_read_region_1(pa->pa_sync_t, pa->pa_sync_h, + pa->pa_chunks[i].pc_offset, + chunk, + pa->pa_chunks[i].pc_length); + chunk[pa->pa_chunks[i].pc_length] = 0; + return chunk; + } + return NULL; +} + +static int +podulebus_print(void *aux, char const *pnp) +{ + struct podulebus_attach_args *pa = aux; + + if (pnp) { + if (pa->pa_descr) + printf("%s", pa->pa_descr); + else + printf("podule"); + printf(" <%04x:%04x> at %s", + pa->pa_manufacturer, pa->pa_product, pnp); + } + printf(" slot %d", pa->pa_slotnum); + return UNCONF; +} + +static int +podulebus_submatch(struct device *parent, struct cfdata *cf, void *aux) +{ + struct podulebus_attach_args *pa = aux; + + if (cf->cf_loc[PODULEBUSCF_SLOT] == PODULEBUSCF_SLOT_DEFAULT || + cf->cf_loc[PODULEBUSCF_SLOT] == pa->pa_slotnum) + return (*cf->cf_attach->ca_match)(parent, cf, aux); + return 0; +} + +struct irq_handler * +podulebus_irq_establish(struct device *self, int slot, int ipl, + int (*func)(void *), void *arg) +{ + + /* XXX: support for checking IRQ bit on podule? */ + return ioc_irq_establish(self->dv_parent, IOC_IRQ_IL5, ipl, func, arg); +} diff --git a/sys/arch/arm26/podulebus/podulebus.h b/sys/arch/arm26/podulebus/podulebus.h new file mode 100644 index 00000000000..661e0de8570 --- /dev/null +++ b/sys/arch/arm26/podulebus/podulebus.h @@ -0,0 +1,98 @@ +/* $NetBSD: podulebus.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * Copyright (c) 1995 Brini. + * 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 Brini. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * podulebus.h + * + * Podule bus header file + * + * Created : 26/04/95 + */ + +#include <sys/param.h> +#include <machine/bus.h> + +struct podulebus_chunk { + int pc_type; + int pc_length; + int pc_offset; +}; + +struct podulebus_attach_args { + bus_space_tag_t pa_memc_t; + bus_space_handle_t pa_memc_h; + bus_space_tag_t pa_fast_t; + bus_space_handle_t pa_fast_h; + bus_space_tag_t pa_medium_t; + bus_space_handle_t pa_medium_h; + bus_space_tag_t pa_slow_t; + bus_space_handle_t pa_slow_h; + bus_space_tag_t pa_sync_t; + bus_space_handle_t pa_sync_h; + int pa_slotnum; + int pa_ecid; + int pa_flags1; + int pa_manufacturer; + int pa_product; + struct podulebus_chunk *pa_chunks; + int pa_nchunks; + char *pa_descr; +}; + +#define IS_PODULE(pa, man, prod) \ + ((pa)->pa_manufacturer == (man) && (pa)->pa_product == (prod)) + +#ifdef _KERNEL + +extern struct irq_handler *podulebus_irq_establish(struct device *, int, int, + int (*)(void *), void *); + +#endif + +/* arm32 compatibility */ + +#define WriteByte(a, v) bus_space_write_1(2, (a), 0, (v)) +#define WriteShort(a, v) bus_space_write_2(2, (a), 0, (v)) +#define ReadByte(a) bus_space_read_1(2, (a), 0) +#define ReadShort(a) bus_space_read_2(2, (a), 0) + +/* XXX The arm32 version ignores "slot" too. */ +#define matchpodule(pa, man, prod, slot) IS_PODULE(pa, man, prod) + +#define mod_base + +/* end arm32 compatibility */ + +/* End of podulebus.h */ diff --git a/sys/arch/arm26/podulebus/podulebusreg.h b/sys/arch/arm26/podulebus/podulebusreg.h new file mode 100644 index 00000000000..834293930ef --- /dev/null +++ b/sys/arch/arm26/podulebus/podulebusreg.h @@ -0,0 +1,62 @@ +/* $NetBSD: podulebusreg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * 2000 Ben Harris + * + * This file is in the public domain. + */ + +#ifndef _PODULEBUSREG_H_ +#define _PODULEBUSREG_H_ + +#define MAX_PODULES 4 +#define PODULE_GAP 0x4000 >> 2 + +/* Podule identity byte (ECId) flags */ +#define ECID_IRQING 0x01 +#define ECID_NOTPRESENT 0x02 +#define ECID_FIQING 0x04 +#define ECID_ID_MASK 0x78 +#define ECID_ID_SHIFT 3 +#define ECID_ID_EXTEND 0x00 +#define ECID_NONCONF 0x80 + +/* Extended ECId bytes */ +#define EXTECID_F1 1 +#define EXTECID_F1_CD 0x01 +#define EXTECID_F1_IS 0x02 +#define EXTECID_F1_W_MASK 0xc0 +#define EXTECID_F1_W_8BIT 0x00 +#define EXTECID_F1_W_16BIT 0x40 +#define EXTECID_F1_W_32BIT 0x80 + +#define EXTECID_PLO 3 +#define EXTECID_PHI 4 +#define EXTECID_MLO 5 +#define EXTECID_MHI 6 + +#define EXTECID_SIZE 8 + +/* Extended interrupt pointers */ +#define IRQPTR_SIZE 8 + +/* Chunk types */ +#define CHUNK_RISCOS_LOADER 0x80 +#define CHUNK_RISCOS_MODULE 0x81 +#define CHUNK_RISCOS_BBCROM 0x82 +#define CHUNK_RISCOS_SPRITE 0x83 +#define CHUNK_OS1_LOADER 0x90 +#define CHUNK_RISCIX_LOADER 0xa0 +#define CHUNK_HELIOS 0xa3 +#define CHUNK_DEV_LINK 0xf0 +#define CHUNK_DEV_SERIAL 0xf1 +#define CHUNK_DEV_DATE 0xf2 +#define CHUNK_DEV_MODS 0xf3 +#define CHUNK_DEV_PLACE 0xf4 +#define CHUNK_DEV_DESCR 0xf5 +#define CHUNK_DEV_PARTNO 0xf6 +#define CHUNK_DEV_EADDR 0xf7 +#define CHUNK_DEV_HWREV 0xf8 +#define CHUNK_DEV_ROMCRC 0xf9 + +#endif diff --git a/sys/arch/arm26/podulebus/sbic.c b/sys/arch/arm26/podulebus/sbic.c new file mode 100644 index 00000000000..05bdbcefa99 --- /dev/null +++ b/sys/arch/arm26/podulebus/sbic.c @@ -0,0 +1,3011 @@ +/* $NetBSD: sbic.c,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * Copyright (c) 1994 Christian E. Hopps + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: sbic.c,v 1.21 1996/01/07 22:01:54 + */ +#define UNPROTECTED_CSR +/*#define SBIC_DEBUG*/ +/* + * WD 33C93 scsi adaptor driver + */ + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> /* For hz */ +#include <sys/disklabel.h> +#include <sys/dkstat.h> +#include <sys/buf.h> +#include <dev/scsipi/scsi_all.h> +#include <dev/scsipi/scsipi_all.h> +#include <dev/scsipi/scsiconf.h> +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +/*#include <machine/pmap.h> +#include <machine/cpu.h>*/ +#include <arm26/podulebus/podulebus.h> +#include <arm26/podulebus/sbicreg.h> +#include <arm26/podulebus/sbicvar.h> +#include <arm26/podulebus/ascreg.h> + +/* These are for bounce buffers */ + +/*#include <vm/pmap.h>*/ + +/* Since I can't find this in any other header files */ +#define SCSI_PHASE(reg) (reg&0x07) + +/* + * SCSI delays + * In u-seconds, primarily for state changes on the SPC. + */ +#define SBIC_CMD_WAIT 50000 /* wait per step of 'immediate' cmds */ +#define SBIC_DATA_WAIT 50000 /* wait per data in/out step */ +#define SBIC_INIT_WAIT 50000 /* wait per step (both) during init */ + +#define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__) + +int sbicicmd __P((struct sbic_softc *, int, int, void *, int, void *, int)); +int sbicgo __P((struct sbic_softc *, struct scsipi_xfer *)); +int sbicdmaok __P((struct sbic_softc *, struct scsipi_xfer *)); +int sbicwait __P((sbic_regmap_p, char, int , int)); +int sbiccheckdmap __P((void *, u_long, u_long)); +int sbicselectbus __P((struct sbic_softc *, sbic_regmap_p, u_char, u_char, u_char)); +int sbicxfstart __P((sbic_regmap_p, int, u_char, int)); +int sbicxfout __P((sbic_regmap_p regs, int, void *, int)); +int sbicfromscsiperiod __P((struct sbic_softc *, sbic_regmap_p, int)); +int sbictoscsiperiod __P((struct sbic_softc *, sbic_regmap_p, int)); +int sbicintr __P((struct sbic_softc *)); +int sbicpoll __P((struct sbic_softc *)); +int sbicnextstate __P((struct sbic_softc *, u_char, u_char)); +int sbicmsgin __P((struct sbic_softc *)); +int sbicxfin __P((sbic_regmap_p regs, int, void *)); +int sbicabort __P((struct sbic_softc *, sbic_regmap_p, char *)); +void sbicxfdone __P((struct sbic_softc *, sbic_regmap_p, int)); +void sbicerror __P((struct sbic_softc *, sbic_regmap_p, u_char)); +void sbicstart __P((struct sbic_softc *)); +void sbicreset __P((struct sbic_softc *)); +void sbic_scsidone __P((struct sbic_acb *, int)); +void sbic_sched __P((struct sbic_softc *)); +void sbic_save_ptrs __P((struct sbic_softc *, sbic_regmap_p,int,int)); +void sbic_load_ptrs __P((struct sbic_softc *, sbic_regmap_p,int,int)); +u_int kvtop(void *); + +u_int kvtop(void *va) { + panic("kvtop not implemented"); +} + +/* + * Synch xfer parameters, and timing conversions + */ +int sbic_min_period = SBIC_SYN_MIN_PERIOD; /* in cycles = f(ICLK,FSn) */ +int sbic_max_offset = SBIC_SYN_MAX_OFFSET; /* pure number */ + +int sbic_cmd_wait = SBIC_CMD_WAIT; +int sbic_data_wait = SBIC_DATA_WAIT; +int sbic_init_wait = SBIC_INIT_WAIT; + +/* + * was broken before.. now if you want this you get it for all drives + * on sbic controllers. + */ +u_char sbic_inhibit_sync[8]; +int sbic_enable_reselect = 1; +int sbic_clock_override = 0; +int sbic_no_dma = 1; /* was 0 */ +int sbic_parallel_operations = 1; + +#ifdef DEBUG +sbic_regmap_p debug_sbic_regs; +int sbicdma_ops = 0; /* total DMA operations */ +int sbicdma_bounces = 0; /* number operations using bounce buffer */ +int sbicdma_hits = 0; /* number of DMA chains that were contiguous */ +int sbicdma_misses = 0; /* number of DMA chains that were not contiguous */ +int sbicdma_saves = 0; +#define QPRINTF(a) if (sbic_debug > 1) printf a +int sbic_debug = 0; +int sync_debug = 0; +int sbic_dma_debug = 0; +int reselect_debug = 0; +int report_sense = 0; +int data_pointer_debug = 0; +u_char debug_asr, debug_csr, routine; +void sbictimeout __P((struct sbic_softc *dev)); +void sbic_dump __P((struct sbic_softc *dev)); + +#define CSR_TRACE_SIZE 32 +#if CSR_TRACE_SIZE +#define CSR_TRACE(w,c,a,x) do { \ + int s = splbio(); \ + csr_trace[csr_traceptr].whr = (w); csr_trace[csr_traceptr].csr = (c); \ + csr_trace[csr_traceptr].asr = (a); csr_trace[csr_traceptr].xtn = (x); \ +/* dma_cachectl(&csr_trace[csr_traceptr], sizeof(csr_trace[0]));*/ \ + csr_traceptr = (csr_traceptr + 1) & (CSR_TRACE_SIZE - 1); \ +/* dma_cachectl(&csr_traceptr, sizeof(csr_traceptr));*/ \ + splx(s); \ +} while (0) +int csr_traceptr; +int csr_tracesize = CSR_TRACE_SIZE; +struct { + u_char whr; + u_char csr; + u_char asr; + u_char xtn; +} csr_trace[CSR_TRACE_SIZE]; +#else +#define CSR_TRACE +#endif + +#define SBIC_TRACE_SIZE 0 +#if SBIC_TRACE_SIZE +#define SBIC_TRACE(dev) do { \ + int s = splbio(); \ + sbic_trace[sbic_traceptr].sp = &s; \ + sbic_trace[sbic_traceptr].line = __LINE__; \ + sbic_trace[sbic_traceptr].sr = s; \ + sbic_trace[sbic_traceptr].csr = csr_traceptr; \ +/* dma_cachectl(&sbic_trace[sbic_traceptr], sizeof(sbic_trace[0]));*/ \ + sbic_traceptr = (sbic_traceptr + 1) & (SBIC_TRACE_SIZE - 1); \ +/* dma_cachectl(&sbic_traceptr, sizeof(sbic_traceptr));*/ \ +/* if (dev) dma_cachectl(dev, sizeof(*dev));*/ \ + splx(s); \ +} while (0) +int sbic_traceptr; +int sbic_tracesize = SBIC_TRACE_SIZE; +struct { + void *sp; + u_short line; + u_short sr; + int csr; +} sbic_trace[SBIC_TRACE_SIZE]; +#else +#define SBIC_TRACE(dev) +#endif + +#else +#define QPRINTF +#define CSR_TRACE +#define SBIC_TRACE +#endif + +/* + * default minphys routine for sbic based controllers + */ +void +sbic_minphys(bp) + struct buf *bp; +{ + + /* + * No max transfer at this level. + */ + minphys(bp); +} + +/* + * Save DMA pointers. Take into account partial transfer. Shut down DMA. + */ +void +sbic_save_ptrs(dev, regs, target, lun) + struct sbic_softc *dev; + sbic_regmap_p regs; + int target, lun; +{ + int count, asr, s; +/* int csr; */ +/* unsigned long ptr;*/ +/* char *vptr;*/ + struct sbic_acb* acb; + +/* extern vm_offset_t vm_first_phys;*/ + + SBIC_TRACE(dev); + if( !dev->sc_cur ) return; + if( !(dev->sc_flags & SBICF_INDMA) ) return; /* DMA not active */ + + s = splbio(); + + acb = dev->sc_nexus; + count = -1; + do { + GET_SBIC_asr(regs, asr); + if( asr & SBIC_ASR_DBR ) { + printf("sbic_save_ptrs: asr %02x canceled!\n", asr); + splx(s); + SBIC_TRACE(dev); + return; + } + } while( asr & (SBIC_ASR_BSY|SBIC_ASR_CIP) ); + + /* Save important state */ + /* must be done before dmastop */ + acb->sc_dmacmd = dev->sc_dmacmd; + SBIC_TC_GET(regs, count); + + /* Shut down DMA ====CAREFUL==== */ + dev->sc_dmastop(dev); + dev->sc_flags &= ~SBICF_INDMA; + SBIC_TC_PUT(regs, 0); + +#ifdef DEBUG + if(!count && sbic_debug) printf("%dcount0",target); + if(data_pointer_debug == -1) + printf("SBIC saving target %d data pointers from (%p,%x)%xASR:%02x", + target, dev->sc_cur->dc_addr, dev->sc_cur->dc_count, + acb->sc_dmacmd, asr); +#endif + + /* Fixup partial xfers */ + acb->sc_kv.dc_addr += (dev->sc_tcnt - count); + acb->sc_kv.dc_count -= (dev->sc_tcnt - count); + acb->sc_pa.dc_addr += (dev->sc_tcnt - count); + acb->sc_pa.dc_count -= ((dev->sc_tcnt - count)>>1); + + acb->sc_tcnt = dev->sc_tcnt = count; +#ifdef DEBUG + if(data_pointer_debug) + printf(" at (%p,%x):%x\n", + dev->sc_cur->dc_addr, dev->sc_cur->dc_count,count); + sbicdma_saves++; +#endif + splx(s); + SBIC_TRACE(dev); +} + + +/* + * DOES NOT RESTART DMA!!! + */ +void sbic_load_ptrs(dev, regs, target, lun) + struct sbic_softc *dev; + sbic_regmap_p regs; + int target, lun; +{ + int s, count; +/* int i, asr;*/ + char* vaddr; +/* char* paddr;*/ + struct sbic_acb *acb; + + SBIC_TRACE(dev); + acb = dev->sc_nexus; + if( !acb->sc_kv.dc_count ) { + /* No data to xfer */ + SBIC_TRACE(dev); + return; + } + + s = splbio(); + + dev->sc_last = dev->sc_cur = &acb->sc_pa; + dev->sc_tcnt = acb->sc_tcnt; + dev->sc_dmacmd = acb->sc_dmacmd; + +#ifdef DEBUG + sbicdma_ops++; +#endif + if( !dev->sc_tcnt ) { + /* sc_tcnt == 0 implies end of segment */ + + /* do kvm to pa mappings */ +#if 0 /* mark */ + paddr = acb->sc_pa.dc_addr = + (char *) kvtop(acb->sc_kv.dc_addr); +#endif + vaddr = acb->sc_kv.dc_addr; + count = acb->sc_kv.dc_count; +#if 0 /* mark */ + for(count = (NBPG - ((int)vaddr & PGOFSET)); + count < acb->sc_kv.dc_count + && (char*)kvtop(vaddr + count + 4) == paddr + count + 4; + count += NBPG); +#endif + /* If it's all contiguous... */ + if(count > acb->sc_kv.dc_count ) { + count = acb->sc_kv.dc_count; +#ifdef DEBUG + sbicdma_hits++; +#endif + } else { +#ifdef DEBUG + sbicdma_misses++; +#endif + } + acb->sc_tcnt = count; + acb->sc_pa.dc_count = count >> 1; + +#ifdef DEBUG + if(data_pointer_debug) + printf("DMA recalc:kv(%p,%x)pa(%p,%lx)\n", + acb->sc_kv.dc_addr, + acb->sc_kv.dc_count, + acb->sc_pa.dc_addr, + acb->sc_tcnt); +#endif + } + splx(s); +#ifdef DEBUG + if(data_pointer_debug) + printf("SBIC restoring target %d data pointers at (%p,%x)%x\n", + target, dev->sc_cur->dc_addr, dev->sc_cur->dc_count, + dev->sc_dmacmd); +#endif + SBIC_TRACE(dev); +} + +/* + * used by specific sbic controller + * + * it appears that the higher level code does nothing with LUN's + * so I will too. I could plug it in, however so could they + * in scsi_scsi_cmd(). + */ +int +sbic_scsicmd(xs) + struct scsipi_xfer *xs; +{ + struct sbic_acb *acb; + struct sbic_softc *dev; + struct scsipi_link *slp; + int flags, s, stat; + + slp = xs->sc_link; + dev = slp->adapter_softc; + SBIC_TRACE(dev); + flags = xs->xs_control; + + if (flags & XS_CTL_DATA_UIO) + panic("sbic: scsi data uio requested"); + + if (dev->sc_nexus && flags & XS_CTL_POLL) + panic("sbic_scsicmd: busy"); + + if (slp->scsipi_scsi.target == slp->scsipi_scsi.adapter_target) + return ESCAPE_NOT_SUPPORTED; + + s = splbio(); + acb = dev->free_list.tqh_first; + if (acb) + TAILQ_REMOVE(&dev->free_list, acb, chain); + splx(s); + + if (acb == NULL) { +#ifdef DEBUG + printf("sbic_scsicmd: unable to queue request for target %d\n", + slp->scsipi_scsi.target); +#ifdef DDB + Debugger(); +#endif +#endif + xs->error = XS_DRIVER_STUFFUP; + SBIC_TRACE(dev); + return(TRY_AGAIN_LATER); + } + + acb->flags = ACB_ACTIVE; + if (flags & XS_CTL_DATA_IN) + acb->flags |= ACB_DATAIN; + acb->xs = xs; + bcopy(xs->cmd, &acb->cmd, xs->cmdlen); + acb->clen = xs->cmdlen; + acb->sc_kv.dc_addr = xs->data; + acb->sc_kv.dc_count = xs->datalen; +#if 0 + acb->pa_addr = xs->data ? (char *)kvtop(xs->data) : 0; /* XXXX check */ +#endif + if (flags & XS_CTL_POLL) { + s = splbio(); + /* + * This has major side effects -- it locks up the machine + */ + + dev->sc_flags |= SBICF_ICMD; + do { + while(dev->sc_nexus) + sbicpoll(dev); + dev->sc_nexus = acb; + dev->sc_stat[0] = -1; + dev->sc_xs = xs; + dev->target = slp->scsipi_scsi.target; + dev->lun = slp->scsipi_scsi.lun; + stat = sbicicmd(dev, slp->scsipi_scsi.target, slp->scsipi_scsi.lun, + &acb->cmd, acb->clen, + acb->sc_kv.dc_addr, acb->sc_kv.dc_count); + } while (dev->sc_nexus != acb); + sbic_scsidone(acb, stat); + + splx(s); + SBIC_TRACE(dev); + return(COMPLETE); + } + + s = splbio(); + TAILQ_INSERT_TAIL(&dev->ready_list, acb, chain); + + if (dev->sc_nexus) { + splx(s); + SBIC_TRACE(dev); + return(SUCCESSFULLY_QUEUED); + } + + /* + * nothing is active, try to start it now. + */ + sbic_sched(dev); + splx(s); + + SBIC_TRACE(dev); +/* TODO: add sbic_poll to do XS_CTL_POLL operations */ +#if 0 + if (flags & XS_CTL_POLL) + return(COMPLETE); +#endif + return(SUCCESSFULLY_QUEUED); +} + +/* + * attempt to start the next available command + */ +void +sbic_sched(dev) + struct sbic_softc *dev; +{ + struct scsipi_xfer *xs; + struct scsipi_link *slp; + struct sbic_acb *acb; + int flags, /*phase,*/ stat, i; + + SBIC_TRACE(dev); + if (dev->sc_nexus) + return; /* a command is current active */ + + SBIC_TRACE(dev); + for (acb = dev->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) { + slp = acb->xs->sc_link; + i = slp->scsipi_scsi.target; + if (!(dev->sc_tinfo[i].lubusy & (1 << slp->scsipi_scsi.lun))) { + struct sbic_tinfo *ti = &dev->sc_tinfo[i]; + + TAILQ_REMOVE(&dev->ready_list, acb, chain); + dev->sc_nexus = acb; + slp = acb->xs->sc_link; + ti = &dev->sc_tinfo[slp->scsipi_scsi.target]; + ti->lubusy |= (1 << slp->scsipi_scsi.lun); + acb->sc_pa.dc_addr = acb->pa_addr; /* XXXX check */ + break; + } + } + + SBIC_TRACE(dev); + if (acb == NULL) + return; /* did not find an available command */ + + dev->sc_xs = xs = acb->xs; + slp = xs->sc_link; + flags = xs->xs_control; + + if (flags & XS_CTL_RESET) + sbicreset(dev); + +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("sbic_sched(%d,%d)\n",slp->scsipi_scsi.target,slp->scsipi_scsi.lun); +#endif + dev->sc_stat[0] = -1; + dev->target = slp->scsipi_scsi.target; + dev->lun = slp->scsipi_scsi.lun; + if ( flags & XS_CTL_POLL || ( !sbic_parallel_operations + && (/*phase == STATUS_PHASE ||*/ + sbicdmaok(dev, xs) == 0) ) ) + stat = sbicicmd(dev, slp->scsipi_scsi.target, slp->scsipi_scsi.lun, &acb->cmd, + acb->clen, acb->sc_kv.dc_addr, acb->sc_kv.dc_count); + else if (sbicgo(dev, xs) == 0) { + SBIC_TRACE(dev); + return; + } else + stat = dev->sc_stat[0]; + + sbic_scsidone(acb, stat); + SBIC_TRACE(dev); +} + +void +sbic_scsidone(acb, stat) + struct sbic_acb *acb; + int stat; +{ + struct scsipi_xfer *xs; + struct scsipi_link *slp; + struct sbic_softc *dev; +/* int s;*/ + int dosched = 0; + + xs = acb->xs; + slp = xs->sc_link; + dev = slp->adapter_softc; + SBIC_TRACE(dev); +#ifdef DIAGNOSTIC + if (acb == NULL || xs == NULL) { + printf("sbic_scsidone -- (%d,%d) no scsipi_xfer\n", + dev->target, dev->lun); +#ifdef DDB + Debugger(); +#endif + return; + } +#endif + /* + * is this right? + */ + xs->status = stat; + +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("scsidone: (%d,%d)->(%d,%d)%02x\n", + slp->scsipi_scsi.target, slp->scsipi_scsi.lun, + dev->target, dev->lun, stat); + if( xs->sc_link->scsipi_scsi.target == dev->sc_link.scsipi_scsi.adapter_target ) + panic("target == hostid"); +#endif + + if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) { + if (stat == SCSI_CHECK) { + /* Schedule a REQUEST SENSE */ + struct scsipi_sense *ss = (void *)&acb->cmd; +#ifdef DEBUG + if (report_sense) + printf("sbic_scsidone: autosense %02x targ %d lun %d", + acb->cmd.opcode, slp->scsipi_scsi.target, slp->scsipi_scsi.lun); +#endif + bzero(ss, sizeof(*ss)); + ss->opcode = REQUEST_SENSE; + ss->byte2 = slp->scsipi_scsi.lun << 5; + ss->length = sizeof(struct scsipi_sense_data); + acb->clen = sizeof(*ss); + acb->sc_kv.dc_addr = (char *)&xs->sense.scsi_sense; + acb->sc_kv.dc_count = sizeof(struct scsipi_sense_data); +#if 0 + acb->pa_addr = (char *)kvtop(&xs->sense.scsi_sense); /* XXX check */ +#endif + acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN; + bzero(acb->sc_kv.dc_addr, acb->clen); + TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain); + dev->sc_tinfo[slp->scsipi_scsi.target].lubusy &= + ~(1 << slp->scsipi_scsi.lun); + dev->sc_tinfo[slp->scsipi_scsi.target].senses++; + if (dev->sc_nexus == acb) { + dev->sc_nexus = NULL; + dev->sc_xs = NULL; + sbic_sched(dev); + } + SBIC_TRACE(dev); + return; + } + } + if (xs->error == XS_NOERROR && (acb->flags & ACB_CHKSENSE)) { + QPRINTF(("status = %0x\n", stat)); + if (xs->sense.scsi_sense.error_code == 0) + { + struct scsipi_sense *ss = (void *)&acb->cmd; + + QPRINTF(("Retrying sense.\n")); + bzero(ss, sizeof(*ss)); + ss->opcode = REQUEST_SENSE; + ss->byte2 = slp->scsipi_scsi.lun << 5; + ss->length = sizeof(struct scsipi_sense_data); + acb->clen = sizeof(*ss); + acb->sc_kv.dc_addr = (char *)&xs->sense.scsi_sense; + acb->sc_kv.dc_count = sizeof(struct scsipi_sense_data); + + acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN; + bzero(acb->sc_kv.dc_addr, acb->clen); + TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain); + dev->sc_tinfo[slp->scsipi_scsi.target].lubusy &= + ~(1 << slp->scsipi_scsi.lun); + dev->sc_tinfo[slp->scsipi_scsi.target].senses++; + if (dev->sc_nexus == acb) { + dev->sc_nexus = NULL; + dev->sc_xs = NULL; + sbic_sched(dev); + } + SBIC_TRACE(dev); + return; + } + xs->error = XS_SENSE; +#ifdef DEBUG + if (report_sense) + printf(" => %02x %02x %02x\n", xs->sense.scsi_sense.error_code, + xs->sense.scsi_sense.flags, + xs->sense.scsi_sense.extra_bytes[3]); +#endif + } else { + xs->resid = 0; /* XXXX */ + } +#if whataboutthisone + case SCSI_BUSY: + xs->error = XS_BUSY; + break; +#endif + xs->xs_status |= XS_STS_DONE; + + /* + * Remove the ACB from whatever queue it's on. We have to do a bit of + * a hack to figure out which queue it's on. Note that it is *not* + * necessary to cdr down the ready queue, but we must cdr down the + * nexus queue and see if it's there, so we can mark the unit as no + * longer busy. This code is sickening, but it works. + */ + if (acb == dev->sc_nexus) { + dev->sc_nexus = NULL; + dev->sc_xs = NULL; + dev->sc_tinfo[slp->scsipi_scsi.target].lubusy &= ~(1<<slp->scsipi_scsi.lun); + if (dev->ready_list.tqh_first) + dosched = 1; /* start next command */ + } else if (dev->ready_list.tqh_last == &acb->chain.tqe_next) { + TAILQ_REMOVE(&dev->ready_list, acb, chain); + } else { + register struct sbic_acb *acb2; + for (acb2 = dev->nexus_list.tqh_first; acb2; + acb2 = acb2->chain.tqe_next) { + if (acb2 == acb) { + TAILQ_REMOVE(&dev->nexus_list, acb, chain); + dev->sc_tinfo[slp->scsipi_scsi.target].lubusy + &= ~(1<<slp->scsipi_scsi.lun); + break; + } + } + if (acb2) + ; + else if (acb->chain.tqe_next) { + TAILQ_REMOVE(&dev->ready_list, acb, chain); + } else { + printf("%s: can't find matching acb\n", + dev->sc_dev.dv_xname); +#ifdef DDB + Debugger(); +#endif + } + } + /* Put it on the free list. */ + acb->flags = ACB_FREE; + TAILQ_INSERT_HEAD(&dev->free_list, acb, chain); + + dev->sc_tinfo[slp->scsipi_scsi.target].cmds++; + + scsipi_done(xs); + + if (dosched) + sbic_sched(dev); + SBIC_TRACE(dev); +} + +int +sbicdmaok(dev, xs) + struct sbic_softc *dev; + struct scsipi_xfer *xs; +{ + if (sbic_no_dma || xs->datalen & 0x1 || (u_int)xs->data & 0x3) + return(0); + /* + * controller supports dma to any addresses? + */ + else if ((dev->sc_flags & SBICF_BADDMA) == 0) + return(1); + /* + * this address is ok for dma? + */ + else if (sbiccheckdmap(xs->data, xs->datalen, dev->sc_dmamask) == 0) + return(1); + /* + * we have a bounce buffer? + */ + else if (dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce) + return(1); + /* + * try to get one + */ + else + panic("sbic: cannot do DMA\n"); +#if 0 + else if (dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce + = (char *)alloc_z2mem(MAXPHYS)) { + if (isztwomem(dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce)) + printf("alloc ZII target %d bounce pa 0x%x\n", + xs->sc_link->scsipi_scsi.target, + kvtop(dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce)); + else if (dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce) + printf("alloc CHIP target %d bounce pa 0x%x\n", + xs->sc_link->scsipi_scsi.target, + PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce)); + return(1); + } +#endif + return(0); +} + + +int +sbicwait(regs, until, timeo, line) + sbic_regmap_p regs; + char until; + int timeo; + int line; +{ + u_char val; + int csr; + + SBIC_TRACE((struct sbic_softc *)0); + if (timeo == 0) + timeo = 1000000; /* some large value.. */ + + GET_SBIC_asr(regs,val); + while ((val & until) == 0) { + if (timeo-- == 0) { + GET_SBIC_csr(regs, csr); + printf("sbicwait TIMEO @%d with asr=x%x csr=x%x\n", + line, val, csr); +#if defined(DDB) && defined(DEBUG) + Debugger(); +#endif + return(val); /* Maybe I should abort */ + break; + } + DELAY(1); + GET_SBIC_asr(regs,val); + } + SBIC_TRACE((struct sbic_softc *)0); + return(val); +} + +int +sbicabort(dev, regs, where) + struct sbic_softc *dev; + sbic_regmap_p regs; + char *where; +{ + u_char csr, asr; + + GET_SBIC_asr(regs, asr); + GET_SBIC_csr(regs, csr); + + printf ("%s: abort %s: csr = 0x%02x, asr = 0x%02x\n", + dev->sc_dev.dv_xname, where, csr, asr); + + +#if 0 + /* Clean up running command */ + if (dev->sc_nexus != NULL) { + dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP; + sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]); + } + while (acb = dev->nexus_list.tqh_first) { + acb->xs->error = XS_DRIVER_STUFFUP; + sbic_scsidone(acb, -1 /*acb->stat[0]*/); + } +#endif + + /* Clean up chip itself */ + if (dev->sc_flags & SBICF_SELECTED) { + while( asr & SBIC_ASR_DBR ) { + /* sbic is jammed w/data. need to clear it */ + /* But we don't know what direction it needs to go */ + GET_SBIC_data(regs, asr); + printf("%s: abort %s: clearing data buffer 0x%02x\n", + dev->sc_dev.dv_xname, where, asr); + GET_SBIC_asr(regs, asr); + if( asr & SBIC_ASR_DBR ) /* Not the read direction, then */ + SET_SBIC_data(regs, asr); + GET_SBIC_asr(regs, asr); + } + WAIT_CIP(regs); +printf("%s: sbicabort - sending ABORT command\n", dev->sc_dev.dv_xname); + SET_SBIC_cmd(regs, SBIC_CMD_ABORT); + WAIT_CIP(regs); + + GET_SBIC_asr(regs, asr); + if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI)) { + /* ok, get more drastic.. */ + +printf("%s: sbicabort - asr %x, trying to reset\n", dev->sc_dev.dv_xname, asr); + sbicreset(dev); + dev->sc_flags &= ~SBICF_SELECTED; + return -1; + } +printf("%s: sbicabort - sending DISC command\n", dev->sc_dev.dv_xname); + SET_SBIC_cmd(regs, SBIC_CMD_DISC); + + do { + asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0); + GET_SBIC_csr (regs, csr); + CSR_TRACE('a',csr,asr,0); + } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) + && (csr != SBIC_CSR_CMD_INVALID)); + + /* lets just hope it worked.. */ + dev->sc_flags &= ~SBICF_SELECTED; + } + return -1; +} + + +/* + * Initialize driver-private structures + */ + +void +sbicinit(dev) + struct sbic_softc *dev; +{ + sbic_regmap_p regs; + u_int i; +/* u_int my_id, s;*/ +/* u_char csr;*/ + struct sbic_acb *acb; + u_int inhibit_sync; + + extern u_long scsi_nosync; + extern int shift_nosync; + +#ifdef SBIC_DEBUG + printf("sbicinit:\n"); +#endif + + regs = dev->sc_sbicp; + + if ((dev->sc_flags & SBICF_ALIVE) == 0) { + TAILQ_INIT(&dev->ready_list); + TAILQ_INIT(&dev->nexus_list); + TAILQ_INIT(&dev->free_list); + callout_init(&dev->sc_timo_ch); + dev->sc_nexus = NULL; + dev->sc_xs = NULL; + acb = dev->sc_acb; + bzero(acb, sizeof(dev->sc_acb)); +#ifdef SBIC_DEBUG + printf("sbicinit: %d\n", __LINE__); +#endif + + for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) { + TAILQ_INSERT_TAIL(&dev->free_list, acb, chain); + acb++; + } + bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo)); +#ifdef DEBUG + /* make sure timeout is really not needed */ + callout_reset(&dev->sc_timo_ch, 30 * hz, + (void *)sbictimeout, dev); +#endif + + } else panic("sbic: reinitializing driver!"); + +#ifdef SBIC_DEBUG + printf("sbicinit: %d\n", __LINE__); +#endif + + dev->sc_flags |= SBICF_ALIVE; + dev->sc_flags &= ~SBICF_SELECTED; + + /* initialize inhibit array */ + if (scsi_nosync) { +#ifdef SBIC_DEBUG + printf("sbicinit: %d\n", __LINE__); +#endif + inhibit_sync = (scsi_nosync >> shift_nosync) & 0xff; + shift_nosync += 8; +#ifdef DEBUG + if (inhibit_sync) + printf("%s: Inhibiting synchronous transfer %02x\n", + dev->sc_dev.dv_xname, inhibit_sync); +#endif + for (i = 0; i < 8; ++i) + if (inhibit_sync & (1 << i)) + sbic_inhibit_sync[i] = 1; + } + +#ifdef SBIC_DEBUG + printf("sbicinit: %d\n", __LINE__); +#endif + + sbicreset(dev); +} + +void +sbicreset(dev) + struct sbic_softc *dev; +{ + sbic_regmap_p regs; + u_int my_id, s; +/* u_int i;*/ + u_char csr; +/* struct sbic_acb *acb;*/ + +#ifdef SBIC_DEBUG + printf("sbicreset: %d\n", __LINE__); +#endif + + regs = dev->sc_sbicp; + +#ifdef SBIC_DEBUG + printf("sbicreset: regs = %08x\n", regs); +#endif +#if 0 + if (dev->sc_flags & SBICF_ALIVE) { + SET_SBIC_cmd(regs, SBIC_CMD_ABORT); + WAIT_CIP(regs); + } +#else + SET_SBIC_cmd(regs, SBIC_CMD_ABORT); +#ifdef SBIC_DEBUG + printf("sbicreset: %d\n", __LINE__); +#endif + WAIT_CIP(regs); +#ifdef SBIC_DEBUG + printf("sbicreset: %d\n", __LINE__); +#endif +#endif + s = splbio(); + my_id = dev->sc_link.scsipi_scsi.adapter_target & SBIC_ID_MASK; + + /* Enable advanced mode */ + my_id |= SBIC_ID_EAF /*| SBIC_ID_EHP*/ ; + SET_SBIC_myid(regs, my_id); +#ifdef SBIC_DEBUG + printf("sbicreset: %d\n", __LINE__); +#endif + + /* + * Disable interrupts (in dmainit) then reset the chip + */ + SET_SBIC_cmd(regs, SBIC_CMD_RESET); + DELAY(25); + SBIC_WAIT(regs, SBIC_ASR_INT, 0); + GET_SBIC_csr(regs, csr); /* clears interrupt also */ + + if (dev->sc_clkfreq < 110) + my_id |= SBIC_ID_FS_8_10; + else if (dev->sc_clkfreq < 160) + my_id |= SBIC_ID_FS_12_15; + else if (dev->sc_clkfreq < 210) + my_id |= SBIC_ID_FS_16_20; + + SET_SBIC_myid(regs, my_id); +#ifdef SBIC_DEBUG + printf("sbicreset: %d\n", __LINE__); +#endif + + /* + * Set up various chip parameters + */ + SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /* | SBIC_CTL_HSP */ + | SBIC_MACHINE_DMA_MODE); + /* + * don't allow (re)selection (SBIC_RID_ES) + * until we can handle target mode!! + */ + SET_SBIC_rselid(regs, SBIC_RID_ER); + SET_SBIC_syn(regs, 0); /* asynch for now */ + + /* + * anything else was zeroed by reset + */ + splx(s); + +#if 0 + if ((dev->sc_flags & SBICF_ALIVE) == 0) { + TAILQ_INIT(&dev->ready_list); + TAILQ_INIT(&dev->nexus_list); + TAILQ_INIT(&dev->free_list); + dev->sc_nexus = NULL; + dev->sc_xs = NULL; + acb = dev->sc_acb; + bzero(acb, sizeof(dev->sc_acb)); + for (i = 0; i < sizeof(dev->sc_acb) / sizeof(*acb); i++) { + TAILQ_INSERT_TAIL(&dev->free_list, acb, chain); + acb++; + } + bzero(dev->sc_tinfo, sizeof(dev->sc_tinfo)); + } else { + if (dev->sc_nexus != NULL) { + dev->sc_nexus->xs->error = XS_DRIVER_STUFFUP; + sbic_scsidone(dev->sc_nexus, dev->sc_stat[0]); + } + while (acb = dev->nexus_list.tqh_first) { + acb->xs->error = XS_DRIVER_STUFFUP; + sbic_scsidone(acb, -1 /*acb->stat[0]*/); + } + } + + dev->sc_flags |= SBICF_ALIVE; +#endif + dev->sc_flags &= ~SBICF_SELECTED; +} + +void +sbicerror(dev, regs, csr) + struct sbic_softc *dev; + sbic_regmap_p regs; + u_char csr; +{ + struct scsipi_xfer *xs; + + xs = dev->sc_xs; + +#ifdef DIAGNOSTIC + if (xs == NULL) + panic("sbicerror"); +#endif + if (xs->xs_control & XS_CTL_SILENT) + return; + + printf("%s: ", dev->sc_dev.dv_xname); + printf("csr == 0x%02x\n", csr); /* XXX */ +} + +/* + * select the bus, return when selected or error. + */ +int +sbicselectbus(dev, regs, target, lun, our_addr) + struct sbic_softc *dev; + sbic_regmap_p regs; + u_char target, lun, our_addr; +{ + u_char asr, csr, id; + + SBIC_TRACE(dev); + QPRINTF(("sbicselectbus %d\n", target)); + + /* + * if we're already selected, return (XXXX panic maybe?) + */ + if (dev->sc_flags & SBICF_SELECTED) { + SBIC_TRACE(dev); + return(1); + } + + /* + * issue select + */ + SBIC_TC_PUT(regs, 0); + SET_SBIC_selid(regs, target); + SET_SBIC_timeo(regs, SBIC_TIMEOUT(250,dev->sc_clkfreq)); + + /* + * set sync or async + */ + if (dev->sc_sync[target].state == SYNC_DONE) + SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[target].offset, + dev->sc_sync[target].period)); + else + SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period)); + + GET_SBIC_asr(regs, asr); + if( asr & (SBIC_ASR_INT|SBIC_ASR_BSY) ) { + /* This means we got ourselves reselected upon */ +/* printf("sbicselectbus: INT/BSY asr %02x\n", asr);*/ +#ifdef DDB +/* Debugger();*/ +#endif + SBIC_TRACE(dev); + return 1; + } + + SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN); + + /* + * wait for select (merged from seperate function may need + * cleanup) + */ + WAIT_CIP(regs); + do { + asr = SBIC_WAIT(regs, SBIC_ASR_INT | SBIC_ASR_LCI, 0); + if (asr & SBIC_ASR_LCI) { +#ifdef DEBUG + if (reselect_debug) + printf("sbicselectbus: late LCI asr %02x\n", asr); +#endif + SBIC_TRACE(dev); + return 1; + } + GET_SBIC_csr (regs, csr); + CSR_TRACE('s',csr,asr,target); + QPRINTF(("%02x ", csr)); + if( csr == SBIC_CSR_RSLT_NI || csr == SBIC_CSR_RSLT_IFY) { +#ifdef DEBUG + if(reselect_debug) + printf("sbicselectbus: reselected asr %02x\n", asr); +#endif + /* We need to handle this now so we don't lock up later */ + sbicnextstate(dev, csr, asr); + SBIC_TRACE(dev); + return 1; + } + if( csr == SBIC_CSR_SLT || csr == SBIC_CSR_SLT_ATN) { + panic("sbicselectbus: target issued select!"); + return 1; + } + } while (csr != (SBIC_CSR_MIS_2|MESG_OUT_PHASE) + && csr != (SBIC_CSR_MIS_2|CMD_PHASE) && csr != SBIC_CSR_SEL_TIMEO); + + /* Enable (or not) reselection */ + if(!sbic_enable_reselect && dev->nexus_list.tqh_first == NULL) + SET_SBIC_rselid (regs, 0); + else + SET_SBIC_rselid (regs, SBIC_RID_ER); + + if (csr == (SBIC_CSR_MIS_2|CMD_PHASE)) { + dev->sc_flags |= SBICF_SELECTED; /* device ignored ATN */ + GET_SBIC_selid(regs, id); + dev->target = id; + GET_SBIC_tlun(regs,dev->lun); + if( dev->lun & SBIC_TLUN_VALID ) + dev->lun &= SBIC_TLUN_MASK; + else + dev->lun = lun; + } else if (csr == (SBIC_CSR_MIS_2|MESG_OUT_PHASE)) { + /* + * Send identify message + * (SCSI-2 requires an identify msg (?)) + */ + GET_SBIC_selid(regs, id); + dev->target = id; + GET_SBIC_tlun(regs,dev->lun); + if( dev->lun & SBIC_TLUN_VALID ) + dev->lun &= SBIC_TLUN_MASK; + else + dev->lun = lun; + /* + * handle drives that don't want to be asked + * whether to go sync at all. + */ + if (sbic_inhibit_sync[id] + && dev->sc_sync[id].state == SYNC_START) { +#ifdef DEBUG + if (sync_debug) + printf("Forcing target %d asynchronous.\n", id); +#endif + dev->sc_sync[id].offset = 0; + dev->sc_sync[id].period = sbic_min_period; + dev->sc_sync[id].state = SYNC_DONE; + } + + + if (dev->sc_sync[id].state != SYNC_START){ + if( dev->sc_xs->xs_control & XS_CTL_POLL + || (dev->sc_flags & SBICF_ICMD) + || !sbic_enable_reselect ) + SEND_BYTE (regs, MSG_IDENTIFY | lun); + else + SEND_BYTE (regs, MSG_IDENTIFY_DR | lun); + } else { + /* + * try to initiate a sync transfer. + * So compose the sync message we're going + * to send to the target + */ + +#ifdef DEBUG + if (sync_debug) + printf("Sending sync request to target %d ... ", + id); +#endif + /* + * setup scsi message sync message request + */ + dev->sc_msg[0] = MSG_IDENTIFY | lun; + dev->sc_msg[1] = MSG_EXT_MESSAGE; + dev->sc_msg[2] = 3; + dev->sc_msg[3] = MSG_SYNC_REQ; + dev->sc_msg[4] = sbictoscsiperiod(dev, regs, + sbic_min_period); + dev->sc_msg[5] = sbic_max_offset; + + if (sbicxfstart(regs, 6, MESG_OUT_PHASE, sbic_cmd_wait)) + sbicxfout(regs, 6, dev->sc_msg, MESG_OUT_PHASE); + + dev->sc_sync[id].state = SYNC_SENT; +#ifdef DEBUG + if (sync_debug) + printf ("sent\n"); +#endif + } + + asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0); + GET_SBIC_csr (regs, csr); + CSR_TRACE('y',csr,asr,target); + QPRINTF(("[%02x]", csr)); +#ifdef DEBUG + if (sync_debug && dev->sc_sync[id].state == SYNC_SENT) + printf("csr-result of last msgout: 0x%x\n", csr); +#endif + + if (csr != SBIC_CSR_SEL_TIMEO) + dev->sc_flags |= SBICF_SELECTED; + } + if (csr == SBIC_CSR_SEL_TIMEO) + dev->sc_xs->error = XS_SELTIMEOUT; + + QPRINTF(("\n")); + + SBIC_TRACE(dev); + return(csr == SBIC_CSR_SEL_TIMEO); +} + +int +sbicxfstart(regs, len, phase, wait) + sbic_regmap_p regs; + int len, wait; + u_char phase; +{ + u_char id; + + switch (phase) { + case DATA_IN_PHASE: + case MESG_IN_PHASE: + GET_SBIC_selid (regs, id); + id |= SBIC_SID_FROM_SCSI; + SET_SBIC_selid (regs, id); + SBIC_TC_PUT (regs, (unsigned)len); + break; + case DATA_OUT_PHASE: + case MESG_OUT_PHASE: + case CMD_PHASE: + GET_SBIC_selid (regs, id); + id &= ~SBIC_SID_FROM_SCSI; + SET_SBIC_selid (regs, id); + SBIC_TC_PUT (regs, (unsigned)len); + break; + default: + SBIC_TC_PUT (regs, 0); + } + QPRINTF(("sbicxfstart %d, %d, %d\n", len, phase, wait)); + + return(1); +} + +int +sbicxfout(regs, len, bp, phase) + sbic_regmap_p regs; + int len; + void *bp; + int phase; +{ + u_char orig_csr, asr, *buf; +/* u_char csr;*/ + int wait; + + buf = bp; + wait = sbic_data_wait; + + QPRINTF(("sbicxfout {%d} %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x\n", len, buf[0], buf[1], buf[2], + buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9])); + +#ifdef UNPROTECTED_CSR + GET_SBIC_csr (regs, orig_csr); + CSR_TRACE('>',orig_csr,0,0); +#endif + + /* + * sigh.. WD-PROTO strikes again.. sending the command in one go + * causes the chip to lock up if talking to certain (misbehaving?) + * targets. Anyway, this procedure should work for all targets, but + * it's slightly slower due to the overhead + */ + WAIT_CIP (regs); + SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO); + for (;len > 0; len--) { + GET_SBIC_asr (regs, asr); + while ((asr & SBIC_ASR_DBR) == 0) { + if ((asr & SBIC_ASR_INT) || --wait < 0) { +#ifdef DEBUG + if (sbic_debug) + printf("sbicxfout fail: l%d i%x w%d\n", + len, asr, wait); +#endif + return (len); + } +/* DELAY(1);*/ + GET_SBIC_asr (regs, asr); + } + + SET_SBIC_data (regs, *buf); + buf++; + } + SBIC_TC_GET(regs, len); + QPRINTF(("sbicxfout done %d bytes\n", len)); + /* + * this leaves with one csr to be read + */ + return(0); +} + +/* returns # bytes left to read */ +int +sbicxfin(regs, len, bp) + sbic_regmap_p regs; + int len; + void *bp; +{ + int wait; +/* int read;*/ + u_char *obp, *buf; + u_char orig_csr, csr, asr; + + wait = sbic_data_wait; + obp = bp; + buf = bp; + +#ifdef UNPROTECTED_CSR + GET_SBIC_csr (regs, orig_csr); + CSR_TRACE('<',orig_csr,0,0); + + QPRINTF(("sbicxfin %d, csr=%02x\n", len, orig_csr)); +#endif + + WAIT_CIP (regs); + SET_SBIC_cmd (regs, SBIC_CMD_XFER_INFO); + for (;len > 0; len--) { + GET_SBIC_asr (regs, asr); + if((asr & SBIC_ASR_PE)) { +#ifdef DEBUG + printf("sbicxfin parity error: l%d i%x w%d\n", + len, asr, wait); +/* return ((unsigned long)buf - (unsigned long)bp); */ +#ifdef DDB + Debugger(); +#endif +#endif + } + while ((asr & SBIC_ASR_DBR) == 0) { + if ((asr & SBIC_ASR_INT) || --wait < 0) { +#ifdef DEBUG + if (sbic_debug) { + QPRINTF(("sbicxfin fail:{%d} %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2], + obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9])); + printf("sbicxfin fail: l%d i%x w%d\n", + len, asr, wait); +} +#endif + return len; + } + +#ifdef UNPROTECTED_CSR + if( ! asr & SBIC_ASR_BSY ) { + GET_SBIC_csr(regs, csr); + CSR_TRACE('<',csr,asr,len); + QPRINTF(("[CSR%02xASR%02x]", csr, asr)); + } +#endif + +/* DELAY(1);*/ + GET_SBIC_asr (regs, asr); + } + + GET_SBIC_data (regs, *buf); +/* QPRINTF(("asr=%02x, csr=%02x, data=%02x\n", asr, csr, *buf));*/ + buf++; + } + + QPRINTF(("sbicxfin {%d} %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x\n", len, obp[0], obp[1], obp[2], + obp[3], obp[4], obp[5], obp[6], obp[7], obp[8], obp[9])); + + /* this leaves with one csr to be read */ + return len; +} + +/* + * SCSI 'immediate' command: issue a command to some SCSI device + * and get back an 'immediate' response (i.e., do programmed xfer + * to get the response data). 'cbuf' is a buffer containing a scsi + * command of length clen bytes. 'buf' is a buffer of length 'len' + * bytes for data. The transfer direction is determined by the device + * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the + * command must supply no data. + */ +int +sbicicmd(dev, target, lun, cbuf, clen, buf, len) + struct sbic_softc *dev; + void *cbuf, *buf; + int clen, len; +{ + sbic_regmap_p regs; + u_char phase, csr, asr; + int wait; +/* int newtarget, cmd_sent, parity_err;*/ + struct sbic_acb *acb; + +/* int discon;*/ + int i; + +#define CSR_LOG_BUF_SIZE 0 +#if CSR_LOG_BUF_SIZE + int bufptr; + int csrbuf[CSR_LOG_BUF_SIZE]; + bufptr=0; +#endif + + SBIC_TRACE(dev); + regs = dev->sc_sbicp; + acb = dev->sc_nexus; + + /* Make sure pointers are OK */ + dev->sc_last = dev->sc_cur = &acb->sc_pa; + dev->sc_tcnt = acb->sc_tcnt = 0; + acb->sc_pa.dc_count = 0; /* No DMA */ + acb->sc_kv.dc_addr = buf; + acb->sc_kv.dc_count = len; + +#ifdef DEBUG + routine = 3; + debug_sbic_regs = regs; /* store this to allow debug calls */ + if( data_pointer_debug > 1 ) + printf("sbicicmd(%d,%d):%d\n", target, lun, + acb->sc_kv.dc_count); +#endif + + /* + * set the sbic into non-DMA mode + */ + SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI /*| SBIC_CTL_HSP*/); + + dev->sc_stat[0] = 0xff; + dev->sc_msg[0] = 0xff; + i = 1; /* pre-load */ + + /* We're stealing the SCSI bus */ + dev->sc_flags |= SBICF_ICMD; + + do { + /* + * select the SCSI bus (it's an error if bus isn't free) + */ + if (!( dev->sc_flags & SBICF_SELECTED ) + && sbicselectbus(dev, regs, target, lun, dev->sc_scsiaddr)) { + /*printf("sbicicmd trying to select busy bus!\n");*/ + dev->sc_flags &= ~SBICF_ICMD; + return(-1); + } + + /* + * Wait for a phase change (or error) then let the device sequence + * us through the various SCSI phases. + */ + + wait = sbic_cmd_wait; + + asr = GET_SBIC_asr (regs, asr); + GET_SBIC_csr (regs, csr); + CSR_TRACE('I',csr,asr,target); + QPRINTF((">ASR:%02xCSR:%02x<", asr, csr)); + +#if CSR_LOG_BUF_SIZE + csrbuf[bufptr++] = csr; +#endif + + + switch (csr) { + case SBIC_CSR_S_XFERRED: + case SBIC_CSR_DISC: + case SBIC_CSR_DISC_1: + dev->sc_flags &= ~SBICF_SELECTED; + GET_SBIC_cmd_phase (regs, phase); + if (phase == 0x60) { + GET_SBIC_tlun (regs, dev->sc_stat[0]); + i = 0; /* done */ +/* break;*/ /* Bypass all the state gobldygook */ + } else { +#ifdef DEBUG + if(reselect_debug>1) + printf("sbicicmd: handling disconnect\n"); +#endif + i = SBIC_STATE_DISCONNECT; + } + break; + + case SBIC_CSR_XFERRED|CMD_PHASE: + case SBIC_CSR_MIS|CMD_PHASE: + case SBIC_CSR_MIS_1|CMD_PHASE: + case SBIC_CSR_MIS_2|CMD_PHASE: + if (sbicxfstart(regs, clen, CMD_PHASE, sbic_cmd_wait)) + if (sbicxfout(regs, clen, + cbuf, CMD_PHASE)) + i = sbicabort(dev, regs,"icmd sending cmd"); +#if 0 + GET_SBIC_csr(regs, csr); /* Lets us reload tcount */ + WAIT_CIP(regs); + GET_SBIC_asr(regs, asr); + CSR_TRACE('I',csr,asr,target); + if( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI|SBIC_ASR_CIP) ) + printf("next: cmd sent asr %02x, csr %02x\n", + asr, csr); +#endif + break; + +#if 0 + case SBIC_CSR_XFERRED|DATA_OUT_PHASE: + case SBIC_CSR_XFERRED|DATA_IN_PHASE: + case SBIC_CSR_MIS|DATA_OUT_PHASE: + case SBIC_CSR_MIS|DATA_IN_PHASE: + case SBIC_CSR_MIS_1|DATA_OUT_PHASE: + case SBIC_CSR_MIS_1|DATA_IN_PHASE: + case SBIC_CSR_MIS_2|DATA_OUT_PHASE: + case SBIC_CSR_MIS_2|DATA_IN_PHASE: + if (acb->sc_kv.dc_count <= 0) + i = sbicabort(dev, regs, "icmd out of data"); + else { + wait = sbic_data_wait; + if (sbicxfstart(regs, + acb->sc_kv.dc_count, + SBIC_PHASE(csr), wait)) + if (csr & 0x01) + /* data in? */ + i=sbicxfin(regs, + acb->sc_kv.dc_count, + acb->sc_kv.dc_addr); + else + i=sbicxfout(regs, + acb->sc_kv.dc_count, + acb->sc_kv.dc_addr, + SBIC_PHASE(csr)); + acb->sc_kv.dc_addr += + (acb->sc_kv.dc_count - i); + acb->sc_kv.dc_count = i; + i = 1; + } + break; + +#endif + case SBIC_CSR_XFERRED|STATUS_PHASE: + case SBIC_CSR_MIS|STATUS_PHASE: + case SBIC_CSR_MIS_1|STATUS_PHASE: + case SBIC_CSR_MIS_2|STATUS_PHASE: + /* + * the sbic does the status/cmd-complete reading ok, + * so do this with its hi-level commands. + */ +#ifdef DEBUG + if(sbic_debug) + printf("SBICICMD status phase\n"); +#endif + SBIC_TC_PUT(regs, 0); + SET_SBIC_cmd_phase(regs, 0x46); + SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER); + break; + +#if THIS_IS_A_RESERVED_STATE + case BUS_FREE_PHASE: /* This is not legal */ + if( dev->sc_stat[0] != 0xff ) + goto out; + break; +#endif + + default: + i = sbicnextstate(dev, csr, asr); + } + + /* + * make sure the last command was taken, + * ie. we're not hunting after an ignored command.. + */ + GET_SBIC_asr(regs, asr); + + /* tapes may take a loooong time.. */ + while (asr & SBIC_ASR_BSY){ + if(asr & SBIC_ASR_DBR) { + printf("sbicicmd: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n", + csr,asr); +#ifdef DDB + Debugger(); +#endif + /* SBIC is jammed */ + /* DUNNO which direction */ + /* Try old direction */ + GET_SBIC_data(regs,i); + GET_SBIC_asr(regs, asr); + if( asr & SBIC_ASR_DBR) /* Wants us to write */ + SET_SBIC_data(regs,i); + } + GET_SBIC_asr(regs, asr); + } + + /* + * wait for last command to complete + */ + if (asr & SBIC_ASR_LCI) { + printf("sbicicmd: last command ignored\n"); + } + else if( i == 1 ) /* Bsy */ + SBIC_WAIT (regs, SBIC_ASR_INT, wait); + + /* + * do it again + */ + } while ( i > 0 && dev->sc_stat[0] == 0xff); + + /* Sometimes we need to do an extra read of the CSR */ + GET_SBIC_csr(regs, csr); + CSR_TRACE('I',csr,asr,0xff); + +#if CSR_LOG_BUF_SIZE + if(reselect_debug>1) + for(i=0; i<bufptr; i++) + printf("CSR:%02x", csrbuf[i]); +#endif + +#ifdef DEBUG + if(data_pointer_debug > 1) + printf("sbicicmd done(%d,%d):%d =%d=\n", + dev->target, lun, + acb->sc_kv.dc_count, + dev->sc_stat[0]); +#endif + + QPRINTF(("=STS:%02x=", dev->sc_stat[0])); + dev->sc_flags &= ~SBICF_ICMD; + + SBIC_TRACE(dev); + return(dev->sc_stat[0]); +} + +/* + * Finish SCSI xfer command: After the completion interrupt from + * a read/write operation, sequence through the final phases in + * programmed i/o. This routine is a lot like sbicicmd except we + * skip (and don't allow) the select, cmd out and data in/out phases. + */ +void +sbicxfdone(dev, regs, target) + struct sbic_softc *dev; + sbic_regmap_p regs; + int target; +{ + u_char phase, asr, csr; + int s; + + SBIC_TRACE(dev); + QPRINTF(("{")); + s = splbio(); + + /* + * have the sbic complete on its own + */ + SBIC_TC_PUT(regs, 0); + SET_SBIC_cmd_phase(regs, 0x46); + SET_SBIC_cmd(regs, SBIC_CMD_SEL_ATN_XFER); + + do { + asr = SBIC_WAIT (regs, SBIC_ASR_INT, 0); + GET_SBIC_csr (regs, csr); + CSR_TRACE('f',csr,asr,target); + QPRINTF(("%02x:", csr)); + } while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1) + && (csr != SBIC_CSR_S_XFERRED)); + + dev->sc_flags &= ~SBICF_SELECTED; + + GET_SBIC_cmd_phase (regs, phase); + QPRINTF(("}%02x", phase)); + if (phase == 0x60) + GET_SBIC_tlun(regs, dev->sc_stat[0]); + else + sbicerror(dev, regs, csr); + + QPRINTF(("=STS:%02x=\n", dev->sc_stat[0])); + splx(s); + SBIC_TRACE(dev); +} + + /* + * No DMA chains + */ + +int +sbicgo(dev, xs) + struct sbic_softc *dev; + struct scsipi_xfer *xs; +{ + int i, dmaflags, count, usedma; +/* int wait;*/ +/* u_char cmd;*/ + u_char *addr, asr = 0, csr = 0; + sbic_regmap_p regs; + struct sbic_acb *acb; + + SBIC_TRACE(dev); + dev->target = xs->sc_link->scsipi_scsi.target; + dev->lun = xs->sc_link->scsipi_scsi.lun; + acb = dev->sc_nexus; + regs = dev->sc_sbicp; + + usedma = sbicdmaok(dev, xs); +#ifdef DEBUG + routine = 1; + debug_sbic_regs = regs; /* store this to allow debug calls */ + if( data_pointer_debug > 1 ) + printf("sbicgo(%d,%d)\n", dev->target, dev->lun); +#endif + + /* + * set the sbic into DMA mode + */ + if( usedma ) + SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI | + SBIC_MACHINE_DMA_MODE); + else + SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI); + + + /* + * select the SCSI bus (it's an error if bus isn't free) + */ + if (sbicselectbus(dev, regs, dev->target, dev->lun, + dev->sc_scsiaddr)) { +/* printf("sbicgo: Trying to select busy bus!\n"); */ + SBIC_TRACE(dev); + return(0); /* Not done: needs to be rescheduled */ + } + dev->sc_stat[0] = 0xff; + + /* + * Calculate DMA chains now + */ + + dmaflags = 0; + if (acb->flags & ACB_DATAIN) + dmaflags |= DMAGO_READ; + + + /* + * Deal w/bounce buffers. + */ + + addr = acb->sc_kv.dc_addr; + count = acb->sc_kv.dc_count; +#if 0 /* mark */ + if (count && (char *)kvtop(addr) != acb->sc_pa.dc_addr) { /* XXXX check */ + printf("sbic: DMA buffer mapping changed %x->%x\n", + acb->sc_pa.dc_addr, kvtop(addr)); +#ifdef DDB + Debugger(); +#endif + } +#endif + +#ifdef DEBUG + ++sbicdma_ops; /* count total DMA operations */ +#endif + if (usedma) + panic("sbic: Cannot use DMA\n"); +#if 0 + if (count && usedma && dev->sc_flags & SBICF_BADDMA && + sbiccheckdmap(addr, count, dev->sc_dmamask)) { + /* + * need to bounce the dma. + */ + if (dmaflags & DMAGO_READ) { + acb->flags |= ACB_BBUF; + acb->sc_dmausrbuf = addr; + acb->sc_dmausrlen = count; + acb->sc_usrbufpa = (u_char *)kvtop(addr); + if(!dev->sc_tinfo[dev->target].bounce) { + printf("sbicgo: HELP! no bounce allocated for %d\n", + dev->target); + printf("xfer: (%p->%p,%lx)\n", acb->sc_dmausrbuf, + acb->sc_usrbufpa, acb->sc_dmausrlen); + dev->sc_tinfo[xs->sc_link->target].bounce + = (char *)alloc_z2mem(MAXPHYS); + if (isztwomem(dev->sc_tinfo[xs->sc_link->target].bounce)) + printf("alloc ZII target %d bounce pa 0x%x\n", + xs->sc_link->target, + kvtop(dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce)); + else if (dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce) + printf("alloc CHIP target %d bounce pa 0x%x\n", + xs->sc_link->scsipi_scsi.target, + PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->scsipi_scsi.target].bounce)); + + printf("Allocating %d bounce at %x\n", + dev->target, + kvtop(dev->sc_tinfo[dev->target].bounce)); + } + } else { /* write: copy to dma buffer */ +#ifdef DEBUG + if(data_pointer_debug) + printf("sbicgo: copying %x bytes to target %d bounce %x\n", + count, dev->target, + kvtop(dev->sc_tinfo[dev->target].bounce)); +#endif + bcopy (addr, dev->sc_tinfo[dev->target].bounce, count); + } + addr = dev->sc_tinfo[dev->target].bounce;/* and use dma buffer */ + acb->sc_kv.dc_addr = addr; +#ifdef DEBUG + ++sbicdma_bounces; /* count number of bounced */ +#endif + } +#endif + /* + * Allocate the DMA chain + */ + + /* Set start KVM addresses */ +#if 0 + acb->sc_kv.dc_addr = addr; + acb->sc_kv.dc_count = count; +#endif + + /* Mark end of segment */ + acb->sc_tcnt = dev->sc_tcnt = 0; + acb->sc_pa.dc_count = 0; + + sbic_load_ptrs(dev, regs, dev->target, dev->lun); + SBIC_TRACE(dev); + /* Enable interrupts but don't do any DMA */ + dev->sc_enintr(dev); + if (usedma) { + dev->sc_tcnt = dev->sc_dmago(dev, acb->sc_pa.dc_addr, + acb->sc_pa.dc_count, + dmaflags); +#ifdef DEBUG + dev->sc_dmatimo = dev->sc_tcnt ? 1 : 0; +#endif + } else + dev->sc_dmacmd = 0; /* Don't use DMA */ + dev->sc_flags |= SBICF_INDMA; +/* SBIC_TC_PUT(regs, dev->sc_tcnt);*/ /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ + SBIC_TRACE(dev); + sbic_save_ptrs(dev, regs, dev->target, dev->lun); + +#if 0 + /* XXX - This code was used on the 68040. This is left as a + * reminder that consideration needs to be given to this when + * DMA support is implemented + */ + /* + * push the data cache ( I think this won't work (EH)) + */ + if (usedma && count) { + dma_cachectl(addr, count); + if (((u_int)addr & 0xF) || (((u_int)addr + count) & 0xF)) + dev->sc_flags |= SBICF_DCFLUSH; + } +#endif + + /* + * enintr() also enables interrupts for the sbic + */ +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("sbicgo dmago:%d(%p:%lx)\n", + dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt); + debug_asr = asr; + debug_csr = csr; +#endif + + /* + * Lets cycle a while then let the interrupt handler take over + */ + + asr = GET_SBIC_asr(regs, asr); + do { + GET_SBIC_csr(regs, csr); + CSR_TRACE('g',csr,asr,dev->target); +#ifdef DEBUG + debug_csr = csr; + routine = 1; +#endif + QPRINTF(("go[0x%x]", csr)); + + i = sbicnextstate(dev, csr, asr); + + WAIT_CIP(regs); + GET_SBIC_asr(regs, asr); +#ifdef DEBUG + debug_asr = asr; +#endif + if(asr & SBIC_ASR_LCI) printf("sbicgo: LCI asr:%02x csr:%02x\n", + asr,csr); + } while( i == SBIC_STATE_RUNNING + && asr & (SBIC_ASR_INT|SBIC_ASR_LCI) ); + + CSR_TRACE('g',csr,asr,i<<4); + SBIC_TRACE(dev); +if (i == SBIC_STATE_DONE && dev->sc_stat[0] == 0xff) printf("sbicgo: done & stat = 0xff\n"); + if (i == SBIC_STATE_DONE && dev->sc_stat[0] != 0xff) { +/* if( i == SBIC_STATE_DONE && dev->sc_stat[0] ) { */ + /* Did we really finish that fast? */ + return 1; + } + return 0; +} + + +int +sbicintr(dev) + struct sbic_softc *dev; +{ + sbic_regmap_p regs; +/* struct dma_chain *df, *dl;*/ + u_char asr, csr; +/* u_char *tmpaddr;*/ +/* struct sbic_acb *acb;*/ + int i; +/* int newtarget, newlun;*/ +/* unsigned tcnt;*/ + + regs = dev->sc_sbicp; + + /* + * pending interrupt? + */ + GET_SBIC_asr (regs, asr); + if ((asr & SBIC_ASR_INT) == 0) + return(0); + + SBIC_TRACE(dev); + do { + GET_SBIC_csr(regs, csr); + CSR_TRACE('i',csr,asr,dev->target); +#ifdef DEBUG + debug_csr = csr; + routine = 2; +#endif + QPRINTF(("intr[0x%x]", csr)); + + i = sbicnextstate(dev, csr, asr); + + WAIT_CIP(regs); + GET_SBIC_asr(regs, asr); +#ifdef DEBUG + debug_asr = asr; +#endif +#if 0 + if(asr & SBIC_ASR_LCI) printf("sbicintr: LCI asr:%02x csr:%02x\n", + asr,csr); +#endif + } while(i == SBIC_STATE_RUNNING && + asr & (SBIC_ASR_INT|SBIC_ASR_LCI)); + CSR_TRACE('i',csr,asr,i<<4); + SBIC_TRACE(dev); + return(1); +} + +/* + * Run commands and wait for disconnect + */ +int +sbicpoll(dev) + struct sbic_softc *dev; +{ + sbic_regmap_p regs; + u_char asr, csr; +/* struct sbic_pending* pendp;*/ + int i; +/* unsigned tcnt;*/ + + SBIC_TRACE(dev); + regs = dev->sc_sbicp; + + do { + GET_SBIC_asr (regs, asr); +#ifdef DEBUG + debug_asr = asr; +#endif + GET_SBIC_csr(regs, csr); + CSR_TRACE('p',csr,asr,dev->target); +#ifdef DEBUG + debug_csr = csr; + routine = 2; +#endif + QPRINTF(("poll[0x%x]", csr)); + + i = sbicnextstate(dev, csr, asr); + + WAIT_CIP(regs); + GET_SBIC_asr(regs, asr); + /* tapes may take a loooong time.. */ + while (asr & SBIC_ASR_BSY){ + if(asr & SBIC_ASR_DBR) { + printf("sbipoll: Waiting while sbic is jammed, CSR:%02x,ASR:%02x\n", + csr,asr); +#ifdef DDB + Debugger(); +#endif + /* SBIC is jammed */ + /* DUNNO which direction */ + /* Try old direction */ + GET_SBIC_data(regs,i); + GET_SBIC_asr(regs, asr); + if( asr & SBIC_ASR_DBR) /* Wants us to write */ + SET_SBIC_data(regs,i); + } + GET_SBIC_asr(regs, asr); + } + + if(asr & SBIC_ASR_LCI) printf("sbicpoll: LCI asr:%02x csr:%02x\n", + asr,csr); + else if( i == 1 ) /* BSY */ + SBIC_WAIT(regs, SBIC_ASR_INT, sbic_cmd_wait); + } while(i == SBIC_STATE_RUNNING); + CSR_TRACE('p',csr,asr,i<<4); + SBIC_TRACE(dev); + return(1); +} + +/* + * Handle a single msgin + */ + +int +sbicmsgin(dev) + struct sbic_softc *dev; +{ + sbic_regmap_p regs; + int recvlen; + u_char asr, csr, *tmpaddr; + + regs = dev->sc_sbicp; + + dev->sc_msg[0] = 0xff; + dev->sc_msg[1] = 0xff; + + GET_SBIC_asr(regs, asr); +#ifdef DEBUG + if(reselect_debug>1) + printf("sbicmsgin asr=%02x\n", asr); +#endif + + sbic_save_ptrs(dev, regs, dev->target, dev->lun); + + GET_SBIC_selid (regs, csr); + SET_SBIC_selid (regs, csr | SBIC_SID_FROM_SCSI); + + SBIC_TC_PUT(regs, 0); + tmpaddr = dev->sc_msg; + recvlen = 1; + do { + while( recvlen-- ) { + asr = GET_SBIC_asr(regs, asr); + GET_SBIC_csr(regs, csr); + QPRINTF(("sbicmsgin ready to go (csr,asr)=(%02x,%02x)\n", + csr, asr)); + + RECV_BYTE(regs, *tmpaddr); + CSR_TRACE('m',csr,asr,*tmpaddr); +#if 1 + /* + * get the command completion interrupt, or we + * can't send a new command (LCI) + */ + SBIC_WAIT(regs, SBIC_ASR_INT, 0); + GET_SBIC_csr(regs, csr); + CSR_TRACE('X',csr,asr,dev->target); +#else + WAIT_CIP(regs); + do { + GET_SBIC_asr(regs, asr); + csr = 0xff; + GET_SBIC_csr(regs, csr); + CSR_TRACE('X',csr,asr,dev->target); + if( csr == 0xff ) + printf("sbicmsgin waiting: csr %02x asr %02x\n", csr, asr); + } while( csr == 0xff ); +#endif +#ifdef DEBUG + if(reselect_debug>1) + printf("sbicmsgin: got %02x csr %02x asr %02x\n", + *tmpaddr, csr, asr); +#endif +#if do_parity_check + if( asr & SBIC_ASR_PE ) { + printf ("Parity error"); + /* This code simply does not work. */ + WAIT_CIP(regs); + SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN); + WAIT_CIP(regs); + GET_SBIC_asr(regs, asr); + WAIT_CIP(regs); + SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); + WAIT_CIP(regs); + if( !(asr & SBIC_ASR_LCI) ) + /* Target wants to send garbled msg*/ + continue; + printf("--fixing\n"); + /* loop until a msgout phase occurs on target */ + while(csr & 0x07 != MESG_OUT_PHASE) { + while( asr & SBIC_ASR_BSY && + !(asr & SBIC_ASR_DBR|SBIC_ASR_INT) ) + GET_SBIC_asr(regs, asr); + if( asr & SBIC_ASR_DBR ) + panic("msgin: jammed again!\n"); + GET_SBIC_csr(regs, csr); + CSR_TRACE('e',csr,asr,dev->target); + if( csr & 0x07 != MESG_OUT_PHASE ) { + sbicnextstate(dev, csr, asr); + sbic_save_ptrs(dev, regs, + dev->target, + dev->lun); + } + } + /* Should be msg out by now */ + SEND_BYTE(regs, MSG_PARITY_ERROR); + } + else +#endif + tmpaddr++; + + if(recvlen) { + /* Clear ACK */ + WAIT_CIP(regs); + GET_SBIC_asr(regs, asr); + GET_SBIC_csr(regs, csr); + CSR_TRACE('X',csr,asr,dev->target); + QPRINTF(("sbicmsgin pre byte CLR_ACK (csr,asr)=(%02x,%02x)\n", + csr, asr)); + SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); + SBIC_WAIT(regs, SBIC_ASR_INT, 0); + } + + }; + + if(dev->sc_msg[0] == 0xff) { + printf("sbicmsgin: sbic swallowed our message\n"); + break; + } +#ifdef DEBUG + if (sync_debug) + printf("msgin done csr 0x%x asr 0x%x msg 0x%x\n", + csr, asr, dev->sc_msg[0]); +#endif + /* + * test whether this is a reply to our sync + * request + */ + if (MSG_ISIDENTIFY(dev->sc_msg[0])) { + QPRINTF(("IFFY")); +#if 0 + /* There is an implied load-ptrs here */ + sbic_load_ptrs(dev, regs, dev->target, dev->lun); +#endif + /* Got IFFY msg -- ack it */ + } else if (dev->sc_msg[0] == MSG_REJECT + && dev->sc_sync[dev->target].state == SYNC_SENT) { + QPRINTF(("REJECT of SYN")); +#ifdef DEBUG + if (sync_debug) + printf("target %d rejected sync, going async\n", + dev->target); +#endif + dev->sc_sync[dev->target].period = sbic_min_period; + dev->sc_sync[dev->target].offset = 0; + dev->sc_sync[dev->target].state = SYNC_DONE; + SET_SBIC_syn(regs, + SBIC_SYN(dev->sc_sync[dev->target].offset, + dev->sc_sync[dev->target].period)); + } else if ((dev->sc_msg[0] == MSG_REJECT)) { + QPRINTF(("REJECT")); + /* + * we'll never REJECt a REJECT message.. + */ + } else if ((dev->sc_msg[0] == MSG_SAVE_DATA_PTR)) { + QPRINTF(("MSG_SAVE_DATA_PTR")); + /* + * don't reject this either. + */ + } else if ((dev->sc_msg[0] == MSG_DISCONNECT)) { + QPRINTF(("DISCONNECT")); +#ifdef DEBUG + if( reselect_debug>1 && dev->sc_msg[0] == MSG_DISCONNECT ) + printf("sbicmsgin: got disconnect msg %s\n", + (dev->sc_flags & SBICF_ICMD)?"rejecting":""); +#endif + if( dev->sc_flags & SBICF_ICMD ) { + /* We're in immediate mode. Prevent disconnects. */ + /* prepare to reject the message, NACK */ + SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN); + WAIT_CIP(regs); + } + } else if (dev->sc_msg[0] == MSG_CMD_COMPLETE ) { + QPRINTF(("CMD_COMPLETE")); + /* !! KLUDGE ALERT !! quite a few drives don't seem to + * really like the current way of sending the + * sync-handshake together with the ident-message, and + * they react by sending command-complete and + * disconnecting right after returning the valid sync + * handshake. So, all I can do is reselect the drive, + * and hope it won't disconnect again. I don't think + * this is valid behavior, but I can't help fixing a + * problem that apparently exists. + * + * Note: we should not get here on `normal' command + * completion, as that condition is handled by the + * high-level sel&xfer resume command used to walk + * thru status/cc-phase. + */ + +#ifdef DEBUG + if (sync_debug) + printf ("GOT MSG %d! target %d acting weird.." + " waiting for disconnect...\n", + dev->sc_msg[0], dev->target); +#endif + /* Check to see if sbic is handling this */ + GET_SBIC_asr(regs, asr); + if(asr & SBIC_ASR_BSY) + return SBIC_STATE_RUNNING; + + /* Let's try this: Assume it works and set status to 00 */ + dev->sc_stat[0] = 0; + } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE + && tmpaddr == &dev->sc_msg[1]) { + QPRINTF(("ExtMSG\n")); + /* Read in whole extended message */ + SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); + SBIC_WAIT(regs, SBIC_ASR_INT, 0); + GET_SBIC_asr(regs, asr); + GET_SBIC_csr(regs, csr); + QPRINTF(("CLR ACK asr %02x, csr %02x\n", asr, csr)); + RECV_BYTE(regs, *tmpaddr); + CSR_TRACE('x',csr,asr,*tmpaddr); + /* Wait for command completion IRQ */ + SBIC_WAIT(regs, SBIC_ASR_INT, 0); + recvlen = *tmpaddr++; + QPRINTF(("Recving ext msg, asr %02x csr %02x len %02x\n", + asr, csr, recvlen)); + } else if (dev->sc_msg[0] == MSG_EXT_MESSAGE && dev->sc_msg[1] == 3 + && dev->sc_msg[2] == MSG_SYNC_REQ) { + QPRINTF(("SYN")); + dev->sc_sync[dev->target].period = + sbicfromscsiperiod(dev, + regs, dev->sc_msg[3]); + dev->sc_sync[dev->target].offset = dev->sc_msg[4]; + dev->sc_sync[dev->target].state = SYNC_DONE; + SET_SBIC_syn(regs, + SBIC_SYN(dev->sc_sync[dev->target].offset, + dev->sc_sync[dev->target].period)); + printf("%s: target %d now synchronous," + " period=%dns, offset=%d.\n", + dev->sc_dev.dv_xname, dev->target, + dev->sc_msg[3] * 4, dev->sc_msg[4]); + } else { +#ifdef DEBUG + if (sbic_debug || sync_debug) + printf ("sbicmsgin: Rejecting message 0x%02x\n", + dev->sc_msg[0]); +#endif + /* prepare to reject the message, NACK */ + SET_SBIC_cmd(regs, SBIC_CMD_SET_ATN); + WAIT_CIP(regs); + } + /* Clear ACK */ + WAIT_CIP(regs); + GET_SBIC_asr(regs, asr); + GET_SBIC_csr(regs, csr); + CSR_TRACE('X',csr,asr,dev->target); + QPRINTF(("sbicmsgin pre CLR_ACK (csr,asr)=(%02x,%02x)%d\n", + csr, asr, recvlen)); + SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); + SBIC_WAIT(regs, SBIC_ASR_INT, 0); + } +#if 0 + while((csr == SBIC_CSR_MSGIN_W_ACK) + || (SBIC_PHASE(csr) == MESG_IN_PHASE)); +#else + while (recvlen>0); +#endif + + QPRINTF(("sbicmsgin finished: csr %02x, asr %02x\n",csr, asr)); + + /* Should still have one CSR to read */ + return SBIC_STATE_RUNNING; +} + + +/* + * sbicnextstate() + * return: + * 0 == done + * 1 == working + * 2 == disconnected + * -1 == error + */ +int +sbicnextstate(dev, csr, asr) + struct sbic_softc *dev; + u_char csr, asr; +{ + sbic_regmap_p regs; +/* struct dma_chain *df, *dl;*/ + struct sbic_acb *acb; +/* int i;*/ + int newtarget, newlun, wait; +/* unsigned tcnt;*/ + + SBIC_TRACE(dev); + regs = dev->sc_sbicp; + acb = dev->sc_nexus; + + QPRINTF(("next[%02x,%02x]",asr,csr)); + + switch (csr) { + case SBIC_CSR_XFERRED|CMD_PHASE: + case SBIC_CSR_MIS|CMD_PHASE: + case SBIC_CSR_MIS_1|CMD_PHASE: + case SBIC_CSR_MIS_2|CMD_PHASE: + sbic_save_ptrs(dev, regs, dev->target, dev->lun); + if (sbicxfstart(regs, acb->clen, CMD_PHASE, sbic_cmd_wait)) + if (sbicxfout(regs, acb->clen, + &acb->cmd, CMD_PHASE)) + goto abort; + break; + + case SBIC_CSR_XFERRED|STATUS_PHASE: + case SBIC_CSR_MIS|STATUS_PHASE: + case SBIC_CSR_MIS_1|STATUS_PHASE: + case SBIC_CSR_MIS_2|STATUS_PHASE: + /* + * this should be the normal i/o completion case. + * get the status & cmd complete msg then let the + * device driver look at what happened. + */ + sbicxfdone(dev,regs,dev->target); + /* + * check for overlapping cache line, flush if so + */ +#if 0 + if (dev->sc_flags & SBICF_DCFLUSH) { + /* XXX - This check was used on the 68040. This is + * left as a reminder that consideration needs to + * be given to this when DMA support is implemented + */ + } +#endif +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("next dmastop: %d(%p:%lx)\n", + dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt); + dev->sc_dmatimo = 0; +#endif + dev->sc_dmastop(dev); /* was dmafree */ + if (acb->flags & ACB_BBUF) { + if ((u_char *)kvtop(acb->sc_dmausrbuf) != acb->sc_usrbufpa) + printf("%s: WARNING - buffer mapping changed %p->%x\n", + dev->sc_dev.dv_xname, acb->sc_usrbufpa, + kvtop(acb->sc_dmausrbuf)); +#ifdef DEBUG + if(data_pointer_debug) + printf("sbicgo:copying %lx bytes from target %d bounce %x\n", + acb->sc_dmausrlen, + dev->target, + kvtop(dev->sc_tinfo[dev->target].bounce)); +#endif + bcopy(dev->sc_tinfo[dev->target].bounce, + acb->sc_dmausrbuf, + acb->sc_dmausrlen); + } + dev->sc_flags &= ~(SBICF_INDMA | SBICF_DCFLUSH); + sbic_scsidone(acb, dev->sc_stat[0]); + SBIC_TRACE(dev); + return SBIC_STATE_DONE; + + case SBIC_CSR_XFERRED|DATA_OUT_PHASE: + case SBIC_CSR_XFERRED|DATA_IN_PHASE: + case SBIC_CSR_MIS|DATA_OUT_PHASE: + case SBIC_CSR_MIS|DATA_IN_PHASE: + case SBIC_CSR_MIS_1|DATA_OUT_PHASE: + case SBIC_CSR_MIS_1|DATA_IN_PHASE: + case SBIC_CSR_MIS_2|DATA_OUT_PHASE: + case SBIC_CSR_MIS_2|DATA_IN_PHASE: + { + int i = 0; + + if( dev->sc_xs->xs_control & XS_CTL_POLL || dev->sc_flags & SBICF_ICMD + || acb->sc_dmacmd == 0 ) { + /* Do PIO */ + SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI); + if (acb->sc_kv.dc_count <= 0) { + printf("sbicnextstate:xfer count %d asr%x csr%x\n", + acb->sc_kv.dc_count, asr, csr); + goto abort; + } + wait = sbic_data_wait; + if( sbicxfstart(regs, + acb->sc_kv.dc_count, + SBIC_PHASE(csr), wait)) { + if( SBIC_PHASE(csr) == DATA_IN_PHASE ) + /* data in? */ + i=sbicxfin(regs, + acb->sc_kv.dc_count, + acb->sc_kv.dc_addr); + else + i=sbicxfout(regs, + acb->sc_kv.dc_count, + acb->sc_kv.dc_addr, + SBIC_PHASE(csr)); + } + acb->sc_kv.dc_addr += + (acb->sc_kv.dc_count - i); + acb->sc_kv.dc_count = i; + } else { + if (acb->sc_kv.dc_count <= 0) { + printf("sbicnextstate:xfer count %d asr%x csr%x\n", + acb->sc_kv.dc_count, asr, csr); + goto abort; + } + /* + * do scatter-gather dma + * hacking the controller chip, ouch.. + */ + SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI | + SBIC_MACHINE_DMA_MODE); + /* + * set next dma addr and dec count + */ +#if 0 + SBIC_TC_GET(regs, tcnt); + dev->sc_cur->dc_count -= ((dev->sc_tcnt - tcnt) >> 1); + dev->sc_cur->dc_addr += (dev->sc_tcnt - tcnt); + dev->sc_tcnt = acb->sc_tcnt = tcnt; +#else + sbic_save_ptrs(dev, regs, dev->target, dev->lun); + sbic_load_ptrs(dev, regs, dev->target, dev->lun); +#endif +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("next dmanext: %d(%p:%lx)\n", + dev->target,dev->sc_cur->dc_addr, + dev->sc_tcnt); + dev->sc_dmatimo = 1; +#endif + dev->sc_tcnt = dev->sc_dmanext(dev); + SBIC_TC_PUT(regs, (unsigned)dev->sc_tcnt); + SET_SBIC_cmd(regs, SBIC_CMD_XFER_INFO); + dev->sc_flags |= SBICF_INDMA; + } + break; + } + case SBIC_CSR_XFERRED|MESG_IN_PHASE: + case SBIC_CSR_MIS|MESG_IN_PHASE: + case SBIC_CSR_MIS_1|MESG_IN_PHASE: + case SBIC_CSR_MIS_2|MESG_IN_PHASE: + SBIC_TRACE(dev); + return sbicmsgin(dev); + + case SBIC_CSR_MSGIN_W_ACK: + SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); /* Dunno what I'm ACKing */ + printf("Acking unknown msgin CSR:%02x",csr); + break; + + case SBIC_CSR_XFERRED|MESG_OUT_PHASE: + case SBIC_CSR_MIS|MESG_OUT_PHASE: + case SBIC_CSR_MIS_1|MESG_OUT_PHASE: + case SBIC_CSR_MIS_2|MESG_OUT_PHASE: +#ifdef DEBUG + if (sync_debug) + printf ("sending REJECT msg to last msg.\n"); +#endif + + sbic_save_ptrs(dev, regs, dev->target, dev->lun); + /* + * should only get here on reject, + * since it's always US that + * initiate a sync transfer + */ + SEND_BYTE(regs, MSG_REJECT); + WAIT_CIP(regs); + if( asr & (SBIC_ASR_BSY|SBIC_ASR_LCI|SBIC_ASR_CIP) ) + printf("next: REJECT sent asr %02x\n", asr); + SBIC_TRACE(dev); + return SBIC_STATE_RUNNING; + + case SBIC_CSR_DISC: + case SBIC_CSR_DISC_1: + dev->sc_flags &= ~(SBICF_INDMA|SBICF_SELECTED); + + /* Try to schedule another target */ +#ifdef DEBUG + if(reselect_debug>1) + printf("sbicnext target %d disconnected\n", dev->target); +#endif + TAILQ_INSERT_HEAD(&dev->nexus_list, acb, chain); + ++dev->sc_tinfo[dev->target].dconns; + dev->sc_nexus = NULL; + dev->sc_xs = NULL; + + if((acb->xs->xs_control & XS_CTL_POLL) + || (dev->sc_flags & SBICF_ICMD) + || (!sbic_parallel_operations) ) { + SBIC_TRACE(dev); + return SBIC_STATE_DISCONNECT; + } + sbic_sched(dev); + SBIC_TRACE(dev); + return SBIC_STATE_DISCONNECT; + + case SBIC_CSR_RSLT_NI: + case SBIC_CSR_RSLT_IFY: + GET_SBIC_rselid(regs, newtarget); + /* check SBIC_RID_SIV? */ + newtarget &= SBIC_RID_MASK; + if (csr == SBIC_CSR_RSLT_IFY) { + /* Read IFY msg to avoid lockup */ + GET_SBIC_data(regs, newlun); + WAIT_CIP(regs); + newlun &= SBIC_TLUN_MASK; + CSR_TRACE('r',csr,asr,newtarget); + } else { + /* Need to get IFY message */ + for (newlun = 256; newlun; --newlun) { + GET_SBIC_asr(regs, asr); + if (asr & SBIC_ASR_INT) + break; + delay(1); + } + newlun = 0; /* XXXX */ + if ((asr & SBIC_ASR_INT) == 0) { +#ifdef DEBUG + if (reselect_debug) + printf("RSLT_NI - no IFFY message? asr %x\n", asr); +#endif + } else { + GET_SBIC_csr(regs,csr); + CSR_TRACE('n',csr,asr,newtarget); + if ((csr == (SBIC_CSR_MIS|MESG_IN_PHASE)) || + (csr == (SBIC_CSR_MIS_1|MESG_IN_PHASE)) || + (csr == (SBIC_CSR_MIS_2|MESG_IN_PHASE))) { + sbicmsgin(dev); + newlun = dev->sc_msg[0] & 7; + } else { + printf("RSLT_NI - not MESG_IN_PHASE %x\n", + csr); + } + } + } +#ifdef DEBUG + if(reselect_debug>1 || (reselect_debug && csr==SBIC_CSR_RSLT_NI)) + printf("sbicnext: reselect %s from targ %d lun %d\n", + csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", + newtarget, newlun); +#endif + if (dev->sc_nexus) { +#ifdef DEBUG + if (reselect_debug > 1) + printf("%s: reselect %s with active command\n", + dev->sc_dev.dv_xname, + csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY"); +#ifdef DDB +/* Debugger();*/ +#endif +#endif + TAILQ_INSERT_HEAD(&dev->ready_list, dev->sc_nexus, chain); + dev->sc_tinfo[dev->target].lubusy &= ~(1 << dev->lun); + dev->sc_nexus = NULL; + dev->sc_xs = NULL; + } + /* Reload sync values for this target */ + if (dev->sc_sync[newtarget].state == SYNC_DONE) + SET_SBIC_syn(regs, SBIC_SYN (dev->sc_sync[newtarget].offset, + dev->sc_sync[newtarget].period)); + else + SET_SBIC_syn(regs, SBIC_SYN (0, sbic_min_period)); + for (acb = dev->nexus_list.tqh_first; acb; + acb = acb->chain.tqe_next) { + if (acb->xs->sc_link->scsipi_scsi.target != newtarget || + acb->xs->sc_link->scsipi_scsi.lun != newlun) + continue; + TAILQ_REMOVE(&dev->nexus_list, acb, chain); + dev->sc_nexus = acb; + dev->sc_xs = acb->xs; + dev->sc_flags |= SBICF_SELECTED; + dev->target = newtarget; + dev->lun = newlun; + break; + } + if (acb == NULL) { + printf("%s: reselect %s targ %d not in nexus_list %p\n", + dev->sc_dev.dv_xname, + csr == SBIC_CSR_RSLT_NI ? "NI" : "IFY", newtarget, + &dev->nexus_list.tqh_first); + panic("bad reselect in sbic"); + } + if (csr == SBIC_CSR_RSLT_IFY) + SET_SBIC_cmd(regs, SBIC_CMD_CLR_ACK); + break; + + default: + abort: + /* + * Something unexpected happened -- deal with it. + */ + printf("sbicnextstate: aborting csr %02x asr %02x\n", csr, asr); +#ifdef DDB + Debugger(); +#endif +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("next dmastop: %d(%p:%lx)\n", + dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt); + dev->sc_dmatimo = 0; +#endif + dev->sc_dmastop(dev); + SET_SBIC_control(regs, SBIC_CTL_EDI | SBIC_CTL_IDI); + sbicerror(dev, regs, csr); + sbicabort(dev, regs, "next"); + if (dev->sc_flags & SBICF_INDMA) { + /* + * check for overlapping cache line, flush if so + */ +#if 0 + if (dev->sc_flags & SBICF_DCFLUSH) { + /* XXX - This check was used on the 68040. + * This is left as a reminder that + * consideration needs to be given to this + * when DMA support is implemented + */ + } +#endif + dev->sc_flags &= + ~(SBICF_INDMA | SBICF_DCFLUSH); +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("next dmastop: %d(%p:%lx)\n", + dev->target,dev->sc_cur->dc_addr,dev->sc_tcnt); + dev->sc_dmatimo = 0; +#endif + dev->sc_dmastop(dev); + sbic_scsidone(acb, -1); + } + SBIC_TRACE(dev); + return SBIC_STATE_ERROR; + } + + SBIC_TRACE(dev); + return(SBIC_STATE_RUNNING); +} + + +/* + * Check if DMA can not be used with specified buffer + */ + +int +sbiccheckdmap(bp, len, mask) + void *bp; + u_long len, mask; +{ + u_char *buffer; + u_long phy_buf; + u_long phy_len; + + buffer = bp; + + if (len == 0) + return(0); + + while (len) { + phy_buf = kvtop(buffer); + if (len < (phy_len = NBPG - ((int) buffer & PGOFSET))) + phy_len = len; + if (phy_buf & mask) + return(1); + buffer += phy_len; + len -= phy_len; + } + return(0); +} + +int +sbictoscsiperiod(dev, regs, a) + struct sbic_softc *dev; + sbic_regmap_p regs; + int a; +{ + unsigned int fs; + + /* + * cycle = DIV / (2*CLK) + * DIV = FS+2 + * best we can do is 200ns at 20Mhz, 2 cycles + */ + + GET_SBIC_myid(regs,fs); + fs = (fs >>6) + 2; /* DIV */ + fs = (fs * 10000) / (dev->sc_clkfreq<<1); /* Cycle, in ns */ + if (a < 2) a = 8; /* map to Cycles */ + return ((fs*a)>>2); /* in 4 ns units */ +} + +int +sbicfromscsiperiod(dev, regs, p) + struct sbic_softc *dev; + sbic_regmap_p regs; + int p; +{ + register unsigned int fs, ret; + + /* Just the inverse of the above */ + + GET_SBIC_myid(regs,fs); + fs = (fs >>6) + 2; /* DIV */ + fs = (fs * 10000) / (dev->sc_clkfreq<<1); /* Cycle, in ns */ + + ret = p << 2; /* in ns units */ + ret = ret / fs; /* in Cycles */ + if (ret < sbic_min_period) + return(sbic_min_period); + + /* verify rounding */ + if (sbictoscsiperiod(dev, regs, ret) < p) + ret++; + return (ret >= 8) ? 0 : ret; +} + +#ifdef DEBUG + +void sbicdumpstate() +{ + u_char csr, asr; + + GET_SBIC_asr(debug_sbic_regs,asr); + GET_SBIC_csr(debug_sbic_regs,csr); + printf("%s: asr:csr(%02x:%02x)->(%02x:%02x)\n", + (routine==1)?"sbicgo": + (routine==2)?"sbicintr": + (routine==3)?"sbicicmd": + (routine==4)?"sbicnext":"unknown", + debug_asr, debug_csr, asr, csr); + +} + +void sbictimeout(dev) + struct sbic_softc *dev; +{ + int s, asr; + + s = splbio(); + if (dev->sc_dmatimo) { + if (dev->sc_dmatimo > 1) { + printf("%s: dma timeout #%d\n", + dev->sc_dev.dv_xname, dev->sc_dmatimo - 1); + GET_SBIC_asr(dev->sc_sbicp, asr); + if( asr & SBIC_ASR_INT ) { + /* We need to service a missed IRQ */ + printf("Servicing a missed int:(%02x,%02x)->(%02x,??)\n", + debug_asr, debug_csr, asr); + sbicintr(dev); + } + sbicdumpstate(); + } + dev->sc_dmatimo++; + } + splx(s); + callout_reset(&dev->sc_timo_ch, 30 * hz, + (void *)sbictimeout, dev); +} + +void +sbic_dump_acb(acb) + struct sbic_acb *acb; +{ + u_char *b = (u_char *) &acb->cmd; + int i; + + printf("acb@%p ", acb); + if (acb->xs == NULL) { + printf("<unused>\n"); + return; + } + printf("(%d:%d) flags %2x clen %2d cmd ", acb->xs->sc_link->scsipi_scsi.target, + acb->xs->sc_link->scsipi_scsi.lun, acb->flags, acb->clen); + for (i = acb->clen; i; --i) + printf(" %02x", *b++); + printf("\n"); + printf(" xs: %8p data %8p:%04x ", acb->xs, acb->xs->data, + acb->xs->datalen); + printf("va %8p:%04x ", acb->sc_kv.dc_addr, acb->sc_kv.dc_count); + printf("pa %8p:%04x tcnt %lx\n", acb->sc_pa.dc_addr, acb->sc_pa.dc_count + ,acb->sc_tcnt); +} + +void +sbic_dump(dev) + struct sbic_softc *dev; +{ + sbic_regmap_p regs; + u_char csr, asr; + struct sbic_acb *acb; + int s; + int i; + + s = splbio(); + regs = dev->sc_sbicp; +#if CSR_TRACE_SIZE + printf("csr trace: "); + i = csr_traceptr; + do { + printf("%c%02x%02x%02x ", csr_trace[i].whr, + csr_trace[i].csr, csr_trace[i].asr, csr_trace[i].xtn); + switch(csr_trace[i].whr) { + case 'g': + printf("go "); break; + case 's': + printf("select "); break; + case 'y': + printf("select+ "); break; + case 'i': + printf("intr "); break; + case 'f': + printf("finish "); break; + case '>': + printf("out "); break; + case '<': + printf("in "); break; + case 'm': + printf("msgin "); break; + case 'x': + printf("msginx "); break; + case 'X': + printf("msginX "); break; + case 'r': + printf("reselect "); break; + case 'I': + printf("icmd "); break; + case 'a': + printf("abort "); break; + default: + printf("? "); + } + switch(csr_trace[i].csr) { + case 0x11: + printf("INITIATOR"); break; + case 0x16: + printf("S_XFERRED"); break; + case 0x20: + printf("MSGIN_ACK"); break; + case 0x41: + printf("DISC"); break; + case 0x42: + printf("SEL_TIMEO"); break; + case 0x80: + printf("RSLT_NI"); break; + case 0x81: + printf("RSLT_IFY"); break; + case 0x85: + printf("DISC_1"); break; + case 0x18: case 0x19: case 0x1a: + case 0x1b: case 0x1e: case 0x1f: + case 0x28: case 0x29: case 0x2a: + case 0x2b: case 0x2e: case 0x2f: + case 0x48: case 0x49: case 0x4a: + case 0x4b: case 0x4e: case 0x4f: + case 0x88: case 0x89: case 0x8a: + case 0x8b: case 0x8e: case 0x8f: + switch(csr_trace[i].csr & 0xf0) { + case 0x10: + printf("DONE_"); break; + case 0x20: + printf("STOP_"); break; + case 0x40: + printf("ERR_"); break; + case 0x80: + printf("REQ_"); break; + } + switch(csr_trace[i].csr & 7) { + case 0: + printf("DATA_OUT"); break; + case 1: + printf("DATA_IN"); break; + case 2: + printf("CMD"); break; + case 3: + printf("STATUS"); break; + case 6: + printf("MSG_OUT"); break; + case 7: + printf("MSG_IN"); break; + default: + printf("invld phs"); + } + break; + default: printf("****"); break; + } + if (csr_trace[i].asr & SBIC_ASR_INT) + printf(" ASR_INT"); + if (csr_trace[i].asr & SBIC_ASR_LCI) + printf(" ASR_LCI"); + if (csr_trace[i].asr & SBIC_ASR_BSY) + printf(" ASR_BSY"); + if (csr_trace[i].asr & SBIC_ASR_CIP) + printf(" ASR_CIP"); + printf("\n"); + i = (i + 1) & (CSR_TRACE_SIZE - 1); + } while (i != csr_traceptr); +#endif + GET_SBIC_asr(regs, asr); + if ((asr & SBIC_ASR_INT) == 0) + GET_SBIC_csr(regs, csr); + else + csr = 0; + printf("%s@%p regs %p asr %x csr %x\n", dev->sc_dev.dv_xname, + dev, regs, asr, csr); + if ((acb = dev->free_list.tqh_first)) { + printf("Free list:\n"); + while (acb) { + sbic_dump_acb(acb); + acb = acb->chain.tqe_next; + } + } + if ((acb = dev->ready_list.tqh_first)) { + printf("Ready list:\n"); + while (acb) { + sbic_dump_acb(acb); + acb = acb->chain.tqe_next; + } + } + if ((acb = dev->nexus_list.tqh_first)) { + printf("Nexus list:\n"); + while (acb) { + sbic_dump_acb(acb); + acb = acb->chain.tqe_next; + } + } + if (dev->sc_nexus) { + printf("nexus:\n"); + sbic_dump_acb(dev->sc_nexus); + } + printf("sc_xs %p targ %d lun %d flags %x tcnt %lx dmacmd %x mask %lx\n", + dev->sc_xs, dev->target, dev->lun, dev->sc_flags, dev->sc_tcnt, + dev->sc_dmacmd, dev->sc_dmamask); + for (i = 0; i < 8; ++i) { + if (dev->sc_tinfo[i].cmds > 2) { + printf("tgt %d: cmds %d disc %d senses %d lubusy %x\n", + i, dev->sc_tinfo[i].cmds, + dev->sc_tinfo[i].dconns, + dev->sc_tinfo[i].senses, + dev->sc_tinfo[i].lubusy); + } + } + splx(s); +} + +#endif diff --git a/sys/arch/arm26/podulebus/sbicreg.h b/sys/arch/arm26/podulebus/sbicreg.h new file mode 100644 index 00000000000..939c2556381 --- /dev/null +++ b/sys/arch/arm26/podulebus/sbicreg.h @@ -0,0 +1,426 @@ +/* $NetBSD: sbicreg.h,v 1.1 2000/05/09 21:56:03 bjh21 Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)scsireg.h 7.3 (Berkeley) 2/5/91 + */ + +/* + * AMD AM33C93A SCSI interface hardware description. + * + * Using parts of the Mach scsi driver for the 33C93 + */ + +#define SBIC_myid 0 +#define SBIC_cdbsize 0 +#define SBIC_control 1 +#define SBIC_timeo 2 +#define SBIC_cdb1 3 +#define SBIC_tsecs 3 +#define SBIC_cdb2 4 +#define SBIC_theads 4 +#define SBIC_cdb3 5 +#define SBIC_tcyl_hi 5 +#define SBIC_cdb4 6 +#define SBIC_tcyl_lo 6 +#define SBIC_cdb5 7 +#define SBIC_addr_hi 7 +#define SBIC_cdb6 8 +#define SBIC_addr_2 8 +#define SBIC_cdb7 9 +#define SBIC_addr_3 9 +#define SBIC_cdb8 10 +#define SBIC_addr_lo 10 +#define SBIC_cdb9 11 +#define SBIC_secno 11 +#define SBIC_cdb10 12 +#define SBIC_headno 12 +#define SBIC_cdb11 13 +#define SBIC_cylno_hi 13 +#define SBIC_cdb12 14 +#define SBIC_cylno_lo 14 +#define SBIC_tlun 15 +#define SBIC_cmd_phase 16 +#define SBIC_syn 17 +#define SBIC_count_hi 18 +#define SBIC_count_med 19 +#define SBIC_count_lo 20 +#define SBIC_selid 21 +#define SBIC_rselid 22 +#define SBIC_csr 23 +#define SBIC_cmd 24 +#define SBIC_data 25 +/* sbic_asr is addressed directly */ + +/* + * Register defines + */ + +/* + * Auxiliary Status Register + */ + +#define SBIC_ASR_INT 0x80 /* Interrupt pending */ +#define SBIC_ASR_LCI 0x40 /* Last command ignored */ +#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */ +#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */ +#define SBIC_ASR_xxx 0x0c +#define SBIC_ASR_PE 0x02 /* Parity error (even) */ +#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */ + +/* + * My ID register, and/or CDB Size + */ + +#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */ + /* 11 Mhz is invalid */ +#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */ +#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */ +#define SBIC_ID_EHP 0x10 /* Enable host parity */ +#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */ +#define SBIC_ID_MASK 0x07 +#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */ + +/* + * Control register + */ + +#define SBIC_CTL_DMA 0x80 /* Single byte dma */ +#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/ +#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */ +#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */ +#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */ +#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */ +#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/ +#define SBIC_CTL_HA 0x02 /* Halt on ATN */ +#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */ + +/* + * Timeout period register + * [val in msecs, input clk in 0.1 Mhz] + */ + +#define SBIC_TIMEOUT(val,clk) ((((val) * (clk)) / 800) + 1) + +/* + * CDBn registers, note that + * cdb11 is used for status byte in target mode (send-status-and-cc) + * cdb12 sez if linked command complete, and w/flag if so + */ + +/* + * Target LUN register + * [holds target status when select-and-xfer] + */ + +#define SBIC_TLUN_VALID 0x80 /* did we receive an Identify msg */ +#define SBIC_TLUN_DOK 0x40 /* Disconnect OK */ +#define SBIC_TLUN_xxx 0x38 +#define SBIC_TLUN_MASK 0x07 + +/* + * Command Phase register + */ + +#define SBIC_CPH_MASK 0x7f /* values/restarts are cmd specific */ +#define SBIC_CPH(p) ((p) & SBIC_CPH_MASK) + +/* + * FIFO register + */ + +#define SBIC_FIFO_DEEP 12 + +/* + * maximum possible size in TC registers. Since this is 24 bit, it's easy + */ +#define SBIC_TC_MAX ((1 << 24) - 1) + +/* + * Synchronous xfer register + */ + +#define SBIC_SYN_OFF_MASK 0x0f +#define SBIC_SYN_MAX_OFFSET SBIC_FIFO_DEEP +#define SBIC_SYN_PER_MASK 0x70 +#define SBIC_SYN_MIN_PERIOD 2 /* upto 8, encoded as 0 */ + +#define SBIC_SYN(o,p) \ + (((o) & SBIC_SYN_OFF_MASK) | (((p) << 4) & SBIC_SYN_PER_MASK)) + +/* + * Transfer count register + * optimal access macros depend on addressing + */ + +/* + * Destination ID (selid) register + */ + +#define SBIC_SID_SCC 0x80 /* Select command chaining (tgt) */ +#define SBIC_SID_DPD 0x40 /* Data phase direction (inittor) */ +#define SBIC_SID_FROM_SCSI 0x40 +#define SBIC_SID_TO_SCSI 0x00 +#define SBIC_SID_xxx 0x38 +#define SBIC_SID_IDMASK 0x07 + +/* + * Source ID (rselid) register + */ + +#define SBIC_RID_ER 0x80 /* Enable reselection */ +#define SBIC_RID_ES 0x40 /* Enable selection */ +#define SBIC_RID_DSP 0x20 /* Disable select parity */ +#define SBIC_RID_SIV 0x08 /* Source ID valid */ +#define SBIC_RID_MASK 0x07 + +/* + * Status register + */ + +#define SBIC_CSR_CAUSE 0xf0 +#define SBIC_CSR_RESET 0x00 /* chip was reset */ +#define SBIC_CSR_CMD_DONE 0x10 /* cmd completed */ +#define SBIC_CSR_CMD_STOPPED 0x20 /* interrupted or abrted*/ +#define SBIC_CSR_CMD_ERR 0x40 /* end with error */ +#define SBIC_CSR_BUS_SERVICE 0x80 /* REQ pending on the bus */ + + +#define SBIC_CSR_QUALIFIER 0x0f +/* Reset State Interrupts */ +#define SBIC_CSR_RESET 0x00 /* reset w/advanced features*/ +#define SBIC_CSR_RESET_AM 0x01 /* reset w/advanced features*/ +/* Successful Completion Interrupts */ +#define SBIC_CSR_TARGET 0x10 /* reselect complete */ +#define SBIC_CSR_INITIATOR 0x11 /* select complete */ +#define SBIC_CSR_WO_ATN 0x13 /* tgt mode completion */ +#define SBIC_CSR_W_ATN 0x14 /* ditto */ +#define SBIC_CSR_XLATED 0x15 /* translate address cmd */ +#define SBIC_CSR_S_XFERRED 0x16 /* initiator mode completion*/ +#define SBIC_CSR_XFERRED 0x18 /* phase in low bits */ +/* Paused or Aborted Interrupts */ +#define SBIC_CSR_MSGIN_W_ACK 0x20 /* (I) msgin, ACK asserted*/ +#define SBIC_CSR_SDP 0x21 /* (I) SDP msg received */ +#define SBIC_CSR_SEL_ABRT 0x22 /* sel/resel aborted */ +#define SBIC_CSR_XFR_PAUSED 0x23 /* (T) no ATN */ +#define SBIC_CSR_XFR_PAUSED_ATN 0x24 /* (T) ATN is asserted */ +#define SBIC_CSR_RSLT_AM 0x27 /* (I) lost selection (AM) */ +#define SBIC_CSR_MIS 0x28 /* (I) xfer aborted, ph mis */ +/* Terminated Interrupts */ +#define SBIC_CSR_CMD_INVALID 0x40 +#define SBIC_CSR_DISC 0x41 /* (I) tgt disconnected */ +#define SBIC_CSR_SEL_TIMEO 0x42 +#define SBIC_CSR_PE 0x43 /* parity error */ +#define SBIC_CSR_PE_ATN 0x44 /* ditto, ATN is asserted */ +#define SBIC_CSR_XLATE_TOOBIG 0x45 +#define SBIC_CSR_RSLT_NOAM 0x46 /* (I) lost sel, no AM mode */ +#define SBIC_CSR_BAD_STATUS 0x47 /* status byte was nok */ +#define SBIC_CSR_MIS_1 0x48 /* ph mis, see low bits */ +/* Service Required Interrupts */ +#define SBIC_CSR_RSLT_NI 0x80 /* reselected, no ify msg */ +#define SBIC_CSR_RSLT_IFY 0x81 /* ditto, AM mode, got ify */ +#define SBIC_CSR_SLT 0x82 /* selected, no ATN */ +#define SBIC_CSR_SLT_ATN 0x83 /* selected with ATN */ +#define SBIC_CSR_ATN 0x84 /* (T) ATN asserted */ +#define SBIC_CSR_DISC_1 0x85 /* (I) bus is free */ +#define SBIC_CSR_UNK_GROUP 0x87 /* strange CDB1 */ +#define SBIC_CSR_MIS_2 0x88 /* (I) ph mis, see low bits */ + +#define SBIC_PHASE(csr) SCSI_PHASE(csr) + +/* + * Command register (command codes) + */ + +#define SBIC_CMD_SBT 0x80 /* Single byte xfer qualifier */ +#define SBIC_CMD_MASK 0x7f + + /* Miscellaneous */ +#define SBIC_CMD_RESET 0x00 /* (DTI) lev I */ +#define SBIC_CMD_ABORT 0x01 /* (DTI) lev I */ +#define SBIC_CMD_DISC 0x04 /* ( TI) lev I */ +#define SBIC_CMD_SSCC 0x0d /* ( TI) lev I */ +#define SBIC_CMD_SET_IDI 0x0f /* (DTI) lev I */ +#define SBIC_CMD_XLATE 0x18 /* (DT ) lev II */ + + /* Initiator state */ +#define SBIC_CMD_SET_ATN 0x02 /* ( I) lev I */ +#define SBIC_CMD_CLR_ACK 0x03 /* ( I) lev I */ +#define SBIC_CMD_XFER_PAD 0x19 /* ( I) lev II */ +#define SBIC_CMD_XFER_INFO 0x20 /* ( I) lev II */ + + /* Target state */ +#define SBIC_CMD_SND_DISC 0x0e /* ( T ) lev II */ +#define SBIC_CMD_RCV_CMD 0x10 /* ( T ) lev II */ +#define SBIC_CMD_RCV_DATA 0x11 /* ( T ) lev II */ +#define SBIC_CMD_RCV_MSG_OUT 0x12 /* ( T ) lev II */ +#define SBIC_CMD_RCV 0x13 /* ( T ) lev II */ +#define SBIC_CMD_SND_STATUS 0x14 /* ( T ) lev II */ +#define SBIC_CMD_SND_DATA 0x15 /* ( T ) lev II */ +#define SBIC_CMD_SND_MSG_IN 0x16 /* ( T ) lev II */ +#define SBIC_CMD_SND 0x17 /* ( T ) lev II */ + + /* Disconnected state */ +#define SBIC_CMD_RESELECT 0x05 /* (D ) lev II */ +#define SBIC_CMD_SEL_ATN 0x06 /* (D ) lev II */ +#define SBIC_CMD_SEL 0x07 /* (D ) lev II */ +#define SBIC_CMD_SEL_ATN_XFER 0x08 /* (D I) lev II */ +#define SBIC_CMD_SEL_XFER 0x09 /* (D I) lev II */ +#define SBIC_CMD_RESELECT_RECV 0x0a /* (DT ) lev II */ +#define SBIC_CMD_RESELECT_SEND 0x0b /* (DT ) lev II */ +#define SBIC_CMD_WAIT_SEL_RECV 0x0c /* (DT ) lev II */ + +/* approximate, but we won't do SBT on selects */ +#define sbic_isa_select(cmd) (((cmd) > 0x5) && ((cmd) < 0xa)) + +#define PAD(n) char n +#define SBIC_MACHINE_DMA_MODE SBIC_CTL_DMA + +typedef struct { + volatile unsigned char sbic_asr; /* r : Aux Status Register */ +#define sbic_address sbic_asr /* w : desired register no */ + PAD(pad1); + PAD(pad2); + PAD(pad3); + volatile unsigned char sbic_value; /* rw: register value */ +} sbic_padded_ind_regmap_t; +typedef volatile sbic_padded_ind_regmap_t *sbic_regmap_p; + +#define sbic_read_reg(regs,regno,val) do { \ + (regs)->sbic_address = (regno); \ + (val) = (regs)->sbic_value; \ + } while (0) + +#define sbic_write_reg(regs,regno,val) do { \ + (regs)->sbic_address = (regno); \ + (regs)->sbic_value = (val); \ + } while (0) + +#define SET_SBIC_myid(regs,val) sbic_write_reg(regs,SBIC_myid,val) +#define GET_SBIC_myid(regs,val) sbic_read_reg(regs,SBIC_myid,val) +#define SET_SBIC_cdbsize(regs,val) sbic_write_reg(regs,SBIC_cdbsize,val) +#define GET_SBIC_cdbsize(regs,val) sbic_read_reg(regs,SBIC_cdbsize,val) +#define SET_SBIC_control(regs,val) sbic_write_reg(regs,SBIC_control,val) +#define GET_SBIC_control(regs,val) sbic_read_reg(regs,SBIC_control,val) +#define SET_SBIC_timeo(regs,val) sbic_write_reg(regs,SBIC_timeo,val) +#define GET_SBIC_timeo(regs,val) sbic_read_reg(regs,SBIC_timeo,val) +#define SET_SBIC_cdb1(regs,val) sbic_write_reg(regs,SBIC_cdb1,val) +#define GET_SBIC_cdb1(regs,val) sbic_read_reg(regs,SBIC_cdb1,val) +#define SET_SBIC_cdb2(regs,val) sbic_write_reg(regs,SBIC_cdb2,val) +#define GET_SBIC_cdb2(regs,val) sbic_read_reg(regs,SBIC_cdb2,val) +#define SET_SBIC_cdb3(regs,val) sbic_write_reg(regs,SBIC_cdb3,val) +#define GET_SBIC_cdb3(regs,val) sbic_read_reg(regs,SBIC_cdb3,val) +#define SET_SBIC_cdb4(regs,val) sbic_write_reg(regs,SBIC_cdb4,val) +#define GET_SBIC_cdb4(regs,val) sbic_read_reg(regs,SBIC_cdb4,val) +#define SET_SBIC_cdb5(regs,val) sbic_write_reg(regs,SBIC_cdb5,val) +#define GET_SBIC_cdb5(regs,val) sbic_read_reg(regs,SBIC_cdb5,val) +#define SET_SBIC_cdb6(regs,val) sbic_write_reg(regs,SBIC_cdb6,val) +#define GET_SBIC_cdb6(regs,val) sbic_read_reg(regs,SBIC_cdb6,val) +#define SET_SBIC_cdb7(regs,val) sbic_write_reg(regs,SBIC_cdb7,val) +#define GET_SBIC_cdb7(regs,val) sbic_read_reg(regs,SBIC_cdb7,val) +#define SET_SBIC_cdb8(regs,val) sbic_write_reg(regs,SBIC_cdb8,val) +#define GET_SBIC_cdb8(regs,val) sbic_read_reg(regs,SBIC_cdb8,val) +#define SET_SBIC_cdb9(regs,val) sbic_write_reg(regs,SBIC_cdb9,val) +#define GET_SBIC_cdb9(regs,val) sbic_read_reg(regs,SBIC_cdb9,val) +#define SET_SBIC_cdb10(regs,val) sbic_write_reg(regs,SBIC_cdb10,val) +#define GET_SBIC_cdb10(regs,val) sbic_read_reg(regs,SBIC_cdb10,val) +#define SET_SBIC_cdb11(regs,val) sbic_write_reg(regs,SBIC_cdb11,val) +#define GET_SBIC_cdb11(regs,val) sbic_read_reg(regs,SBIC_cdb11,val) +#define SET_SBIC_cdb12(regs,val) sbic_write_reg(regs,SBIC_cdb12,val) +#define GET_SBIC_cdb12(regs,val) sbic_read_reg(regs,SBIC_cdb12,val) +#define SET_SBIC_tlun(regs,val) sbic_write_reg(regs,SBIC_tlun,val) +#define GET_SBIC_tlun(regs,val) sbic_read_reg(regs,SBIC_tlun,val) +#define SET_SBIC_cmd_phase(regs,val) sbic_write_reg(regs,SBIC_cmd_phase,val) +#define GET_SBIC_cmd_phase(regs,val) sbic_read_reg(regs,SBIC_cmd_phase,val) +#define SET_SBIC_syn(regs,val) sbic_write_reg(regs,SBIC_syn,val) +#define GET_SBIC_syn(regs,val) sbic_read_reg(regs,SBIC_syn,val) +#define SET_SBIC_count_hi(regs,val) sbic_write_reg(regs,SBIC_count_hi,val) +#define GET_SBIC_count_hi(regs,val) sbic_read_reg(regs,SBIC_count_hi,val) +#define SET_SBIC_count_med(regs,val) sbic_write_reg(regs,SBIC_count_med,val) +#define GET_SBIC_count_med(regs,val) sbic_read_reg(regs,SBIC_count_med,val) +#define SET_SBIC_count_lo(regs,val) sbic_write_reg(regs,SBIC_count_lo,val) +#define GET_SBIC_count_lo(regs,val) sbic_read_reg(regs,SBIC_count_lo,val) +#define SET_SBIC_selid(regs,val) sbic_write_reg(regs,SBIC_selid,val) +#define GET_SBIC_selid(regs,val) sbic_read_reg(regs,SBIC_selid,val) +#define SET_SBIC_rselid(regs,val) sbic_write_reg(regs,SBIC_rselid,val) +#define GET_SBIC_rselid(regs,val) sbic_read_reg(regs,SBIC_rselid,val) +#define SET_SBIC_csr(regs,val) sbic_write_reg(regs,SBIC_csr,val) +#define GET_SBIC_csr(regs,val) sbic_read_reg(regs,SBIC_csr,val) +#define SET_SBIC_cmd(regs,val) sbic_write_reg(regs,SBIC_cmd,val) +#define GET_SBIC_cmd(regs,val) sbic_read_reg(regs,SBIC_cmd,val) +#define SET_SBIC_data(regs,val) sbic_write_reg(regs,SBIC_data,val) +#define GET_SBIC_data(regs,val) sbic_read_reg(regs,SBIC_data,val) + +#define SBIC_TC_PUT(regs,val) do { \ + sbic_write_reg(regs,SBIC_count_hi,((val)>>16)); \ + (regs)->sbic_value = (val)>>8; \ + (regs)->sbic_value = (val); \ +} while (0) +#define SBIC_TC_GET(regs,val) do { \ + sbic_read_reg(regs,SBIC_count_hi,(val)); \ + (val) = ((val)<<8) | (regs)->sbic_value; \ + (val) = ((val)<<8) | (regs)->sbic_value; \ +} while (0) + +#define SBIC_LOAD_COMMAND(regs,cmd,cmdsize) do { \ + int n=(cmdsize)-1; \ + char *ptr = (char*)(cmd); \ + sbic_write_reg(regs,SBIC_cdb1,*ptr++); \ + while (n-- > 0) (regs)->sbic_value = *ptr++; \ +} while (0) + +#define GET_SBIC_asr(regs,val) (val) = (regs)->sbic_asr + +#define WAIT_CIP(regs) do { \ + while ((regs)->sbic_asr & SBIC_ASR_CIP) \ + ; \ +} while (0) + +/* transmit a byte in programmed I/O mode */ +#define SEND_BYTE(regs, ch) do { \ + WAIT_CIP(regs); \ + SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \ + SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \ + SET_SBIC_data(regs, ch); \ + } while (0) + +/* receive a byte in programmed I/O mode */ +#define RECV_BYTE(regs, ch) do { \ + WAIT_CIP(regs); \ + SET_SBIC_cmd(regs, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \ + SBIC_WAIT(regs, SBIC_ASR_DBR, 0); \ + GET_SBIC_data(regs, ch); \ + } while (0) diff --git a/sys/arch/arm26/podulebus/sbicvar.h b/sys/arch/arm26/podulebus/sbicvar.h new file mode 100644 index 00000000000..3f7d9f3a610 --- /dev/null +++ b/sys/arch/arm26/podulebus/sbicvar.h @@ -0,0 +1,236 @@ +/* $NetBSD: sbicvar.h,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson of Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)scsivar.h 7.1 (Berkeley) 5/8/90 + */ + +#ifndef _SBICVAR_H_ +#define _SBICVAR_H_ +#include <sys/malloc.h> +#include <sys/callout.h> + +/* + * The largest single request will be MAXPHYS bytes which will require + * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of + * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the + * buffer is not page aligned (+1). + */ +#define DMAMAXIO (MAXPHYS/NBPG+1) + +struct dma_chain { + int dc_count; + char *dc_addr; +}; + +/* + * ACB. Holds additional information for each SCSI command Comments: We + * need a separate scsi command block because we may need to overwrite it + * with a request sense command. Basicly, we refrain from fiddling with + * the scsi_xfer struct (except do the expected updating of return values). + * We'll generally update: xs->{flags,resid,error,sense,status} and + * occasionally xs->retries. + */ +struct sbic_acb { + TAILQ_ENTRY(sbic_acb) chain; + struct scsipi_xfer *xs; /* SCSI xfer ctrl block from above */ + int flags; /* Status */ +#define ACB_FREE 0x00 +#define ACB_ACTIVE 0x01 +#define ACB_DONE 0x04 +#define ACB_CHKSENSE 0x08 +#define ACB_BBUF 0x10 /* DMA input needs to be copied from bounce */ +#define ACB_DATAIN 0x20 /* DMA direction flag */ + struct scsi_generic cmd; /* SCSI command block */ + int clen; + struct dma_chain sc_kv; /* Virtual address of whole DMA */ + struct dma_chain sc_pa; /* Physical address of DMA segment */ + u_long sc_tcnt; /* number of bytes for this DMA */ + u_char *sc_dmausrbuf; /* user buffer kva - for bounce copy */ + u_long sc_dmausrlen; /* length of bounce copy */ + u_short sc_dmacmd; /* Internal data for this DMA */ + char *pa_addr; /* XXXX initial phys addr */ + u_char *sc_usrbufpa; /* user buffer phys addr */ +}; + +/* + * Some info about each (possible) target on the SCSI bus. This should + * probably have been a "per target+lunit" structure, but we'll leave it at + * this for now. Is there a way to reliably hook it up to sc->fordriver?? + */ +struct sbic_tinfo { + int cmds; /* #commands processed */ + int dconns; /* #disconnects */ + int touts; /* #timeouts */ + int perrs; /* #parity errors */ + int senses; /* #request sense commands sent */ + u_char* bounce; /* Bounce buffer for this device */ + ushort lubusy; /* What local units/subr. are busy? */ + u_char flags; + u_char period; /* Period suggestion */ + u_char offset; /* Offset suggestion */ +} tinfo_t; + +struct sbic_softc { + struct device sc_dev; +/* struct isr sc_isr;*/ + struct callout sc_timo_ch; + struct target_sync { + u_char state; + u_char period; + u_char offset; + } sc_sync[8]; + u_char target; /* Currently active target */ + u_char lun; + struct scsipi_link sc_link; /* proto for sub devices */ + struct scsipi_adapter sc_adapter; + sbic_regmap_p sc_sbicp; /* the SBIC */ + volatile void *sc_cregs; /* driver specific regs */ + + /* Lists of command blocks */ + TAILQ_HEAD(acb_list, sbic_acb) free_list, + ready_list, + nexus_list; + + struct sbic_acb *sc_nexus; /* current command */ + struct sbic_acb sc_acb[8]; /* the real command blocks */ + struct sbic_tinfo sc_tinfo[8]; + + struct scsipi_xfer *sc_xs; /* transfer from high level code */ + u_char sc_flags; + u_char sc_scsiaddr; + u_char sc_stat[2]; + u_char sc_msg[7]; + u_long sc_clkfreq; + u_long sc_tcnt; /* number of bytes transfered */ + u_short sc_dmacmd; /* used by dma drivers */ + u_short sc_dmatimo; /* dma timeout */ + u_long sc_dmamask; /* dma valid mem mask */ + struct dma_chain *sc_cur; + struct dma_chain *sc_last; + int (*sc_dmago) __P((struct sbic_softc *, char *, int, int)); + int (*sc_dmanext) __P((struct sbic_softc *)); + void (*sc_enintr) __P((struct sbic_softc *)); + void (*sc_dmastop) __P((struct sbic_softc *)); + u_short gtsc_bankmask; /* GVP specific bank selected */ +}; + +/* sc_flags */ +#define SBICF_ALIVE 0x01 /* controller initialized */ +#define SBICF_DCFLUSH 0x02 /* need flush for overlap after dma finishes */ +#define SBICF_SELECTED 0x04 /* bus is in selected state. */ +#define SBICF_ICMD 0x08 /* Immediate command in execution */ +#define SBICF_BADDMA 0x10 /* controller can only DMA to ztwobus space */ +#define SBICF_INTR 0x40 /* SBICF interrupt expected */ +#define SBICF_INDMA 0x80 /* not used yet, DMA I/O in progress */ + +/* sync states */ +#define SYNC_START 0 /* no sync handshake started */ +#define SYNC_SENT 1 /* we sent sync request, no answer yet */ +#define SYNC_DONE 2 /* target accepted our (or inferior) settings, + or it rejected the request and we stay async */ +#ifdef DEBUG +#define DDB_FOLLOW 0x04 +#define DDB_IO 0x08 +#endif +extern u_char sbic_inhibit_sync[8]; +extern int sbic_no_dma; +extern int sbic_clock_override; + +#define PHASE 0x07 /* mask for psns/pctl phase */ +#define DATA_OUT_PHASE 0x00 +#define DATA_IN_PHASE 0x01 +#define CMD_PHASE 0x02 +#define STATUS_PHASE 0x03 +#define BUS_FREE_PHASE 0x04 +#define ARB_SEL_PHASE 0x05 /* Fuji chip combines arbitration with sel. */ +#define MESG_OUT_PHASE 0x06 +#define MESG_IN_PHASE 0x07 + +#define MSG_CMD_COMPLETE 0x00 +#define MSG_EXT_MESSAGE 0x01 +#define MSG_SAVE_DATA_PTR 0x02 +#define MSG_RESTORE_PTR 0x03 +#define MSG_DISCONNECT 0x04 +#define MSG_INIT_DETECT_ERROR 0x05 +#define MSG_ABORT 0x06 +#define MSG_REJECT 0x07 +#define MSG_NOOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define MSG_BUS_DEVICE_RESET 0x0C +#define MSG_IDENTIFY 0x80 +#define MSG_IDENTIFY_DR 0xc0 /* (disconnect/reconnect allowed) */ +#define MSG_SYNC_REQ 0x01 + +#define MSG_ISIDENTIFY(x) (x&MSG_IDENTIFY) +#define IFY_TRN 0x20 +#define IFY_LUNTRN(x) (x&0x07) +#define IFY_LUN(x) (!(x&0x20)) + +/* Check if high bit set */ + +#define STS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */ +#define STS_CONDMET 0x04 /* Condition Met (ie., search worked) */ +#define STS_BUSY 0x08 +#define STS_INTERMED 0x10 /* Intermediate status sent */ +#define STS_EXT 0x80 /* Extended status valid */ + + +/* States returned by our state machine */ + +#define SBIC_STATE_ERROR -1 +#define SBIC_STATE_DONE 0 +#define SBIC_STATE_RUNNING 1 +#define SBIC_STATE_DISCONNECT 2 + +/* + * XXXX + */ +struct scsi_fmt_cdb { + int len; /* cdb length (in bytes) */ + u_char cdb[28]; /* cdb to use on next read/write */ +}; + +struct buf; +struct scsipi_xfer; + +void sbic_minphys __P((struct buf *bp)); +int sbic_scsicmd __P((struct scsipi_xfer *)); +void sbicinit __P((struct sbic_softc *dev)); +int sbicintr __P((struct sbic_softc *)); +void sbic_dump __P((struct sbic_softc *dev)); + +#endif /* _SBICVAR_H_ */ diff --git a/sys/arch/arm26/podulebus/unixbp.c b/sys/arch/arm26/podulebus/unixbp.c new file mode 100644 index 00000000000..21785ac9bee --- /dev/null +++ b/sys/arch/arm26/podulebus/unixbp.c @@ -0,0 +1,85 @@ +/* $NetBSD: unixbp.c,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */ + +/*- + * Copyright (c) 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * unixbp.c - driver for the Unix Backplane, found in the R140 etc + */ + +#include <sys/param.h> + +__KERNEL_RCSID(0, "$NetBSD: unixbp.c,v 1.1 2000/05/09 21:56:04 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/systm.h> +#include <machine/bus.h> +#include <arch/arm26/iobus/iocvar.h> +#include <arch/arm26/podulebus/unixbpreg.h> + +struct unixbp_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +}; + +static int unixbp_match(struct device *, struct cfdata *, void *); +static void unixbp_attach(struct device *, struct device *, void *); + +struct cfattach unixbp_ca = { + sizeof(struct unixbp_softc), unixbp_match, unixbp_attach +}; + +static int +unixbp_match(struct device *parent, struct cfdata *cf, void *aux) +{ + struct ioc_attach_args *ioc = aux; + bus_space_tag_t bst = ioc->ioc_fast_t; + bus_space_handle_t bsh = ioc->ioc_fast_h; + + /* Ask to disable all interrupts and check the request lines go low. */ + bus_space_write_1(bst, bsh, UNIXBP_REG_MASK, 0); + if ((bus_space_read_1(bst, bsh, UNIXBP_REG_REQUEST) & 0xf) != 0) + return 0; + /* Re-enable interrupts. */ + bus_space_write_1(bst, bsh, UNIXBP_REG_MASK, 0xf); + return 1; +} + +static void +unixbp_attach(struct device *parent, struct device *self, void *aux) + +{ + struct ioc_attach_args *ioc = aux; + struct unixbp_softc *sc = (void *)self; + + sc->sc_iot = ioc->ioc_fast_t; + sc->sc_ioh = ioc->ioc_fast_h; + + printf(": not yet used\n"); +} + diff --git a/sys/arch/arm26/podulebus/unixbpreg.h b/sys/arch/arm26/podulebus/unixbpreg.h new file mode 100644 index 00000000000..16c077eae13 --- /dev/null +++ b/sys/arch/arm26/podulebus/unixbpreg.h @@ -0,0 +1,15 @@ +/* $NetBSD: unixbpreg.h,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */ + +/* + * This file is in the public domain. + */ + +/* Acorn "Unix Backplane" registers */ + +#ifndef _UNIXBPREG_H_ +#define _UNIXBPREG_H_ + +#define UNIXBP_REG_REQUEST 0 /* Enabled _and_ active */ +#define UNIXBP_REG_MASK 1 + +#endif diff --git a/sys/arch/arm26/vidc/arcvideo.c b/sys/arch/arm26/vidc/arcvideo.c new file mode 100644 index 00000000000..c40650116ae --- /dev/null +++ b/sys/arch/arm26/vidc/arcvideo.c @@ -0,0 +1,501 @@ +/* $NetBSD: arcvideo.c,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */ +/*- + * Copyright (c) 1998, 2000 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * arcvideo.c - Archimedes video system driver. + */ + +/* + * The Arc video system is rather closely tied into the heart of the + * machine, being partly controlled by the MEMC. Similarly, this + * driver will probably end up with its tentacles throughout the + * kernel, though in theory it should be posible to leave it out. + */ + +#include <sys/param.h> + +__RCSID("$NetBSD: arcvideo.c,v 1.1 2000/05/09 21:56:04 bjh21 Exp $"); + +#include <sys/device.h> +#include <sys/errno.h> +#include <sys/systm.h> + +#include <vm/vm.h> + +#include <dev/wscons/wsconsio.h> +#define WSDISPLAY_TYPE_ARCHIMEDES 42 /* XXX Should be in wsconsio.h */ +#include <dev/wscons/wscons_raster.h> +#include <dev/wscons/wsdisplayvar.h> +#include <dev/rasops/rasops.h> + +#include <machine/boot.h> +#include <machine/bus.h> +#include <machine/irq.h> +#include <machine/memcreg.h> +#include <machine/spl.h> + +#include <arch/arm26/iobus/iocreg.h> +#include <arch/arm26/iobus/iocvar.h> +#include <arch/arm26/vidc/vidcreg.h> +#include <arch/arm26/vidc/arcvideovar.h> + +#include "ioc.h" + +static int arcvideo_match __P((struct device *parent, struct cfdata *cf, + void *aux)); +static void arcvideo_attach __P((struct device *parent, struct device *self, + void *aux)); +#if 0 +static int arcvideo_setmode __P((struct device *self, + struct arcvideo_mode *mode)); +static void arcvideo_await_vsync __P((struct device *self)); +#endif +static int arcvideo_intr __P((void *cookie)); +static int arcvideo_ioctl __P((void *cookie, u_long cmd, caddr_t data, + int flag, struct proc *p)); +static int arcvideo_mmap __P((void *cookie, off_t off, int prot)); +static int arcvideo_alloc_screen __P((void *cookie, + const struct wsscreen_descr *scr, + void **scookiep, int *curxp, int *curyp, + long *defattrp)); +static void arcvideo_free_screen __P((void *cookie, void *scookie)); +static void arcvideo_show_screen __P((void *cookie, void *scookie, int waitok, + void (*cb)(void *, int, int), + void *cbarg)); +static int arcvideo_load_font __P((void *cookie, void *scookie, + struct wsdisplay_font *)); +static void arccons_8bpp_hack __P((struct rasops_info *ri)); + +struct arcvideo_softc { + struct device sc_dev; + paddr_t sc_screenmem_base; + struct arcvideo_mode sc_current_mode; + u_int32_t sc_vidc_ctl; + struct device *sc_ioc; + struct irq_handler *sc_irq; + int sc_flags; +#define AV_VIDEO_ON 0x01 +}; + +struct cfattach arcvideo_ca = { + sizeof(struct arcvideo_softc), arcvideo_match, arcvideo_attach +}; + +extern struct cfdriver arcvideo_cd; +#if NIOC > 0 +extern struct cfdriver ioc_cd; +#endif + +static struct rasops_info arccons_ri; + +static struct wsscreen_descr arcscreen; + +static struct wsdisplay_accessops arcvideo_accessops = { + arcvideo_ioctl, arcvideo_mmap, arcvideo_alloc_screen, + arcvideo_free_screen, arcvideo_show_screen, arcvideo_load_font +}; + +static int arcvideo_isconsole = 0; + +static int +arcvideo_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + + /* A system can't sensibly have more than one VIDC. */ + if (cf->cf_unit == 0) + return 1; + else + return 0; +} + +static void +arcvideo_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct wsemuldisplaydev_attach_args da; + struct wsscreen_list scrdata; + const struct wsscreen_descr *screenp; + struct arcvideo_softc *sc = (void *)self; + + printf(": "); + + if (!arcvideo_isconsole) { + printf("Not console -- I can't cope with this!\n"); + return; + } + + sc->sc_flags = AV_VIDEO_ON; + /* Detect monitor type? */ + /* Reset VIDC */ + + /* Find IRQ */ +#if NIOC > 0 + /* + * We could probe, but until someone comes up with a machine + * that's different from all the others, why bother? + */ + if (ioc_cd.cd_ndevs > 0 && ioc_cd.cd_devs[0] != NULL) { + /* ioc0 exists */ + sc->sc_ioc = ioc_cd.cd_devs[0]; + sc->sc_irq = ioc_irq_establish(sc->sc_ioc, IOC_IRQ_IR, IPL_TTY, + arcvideo_intr, self); + printf("VSYNC interrupts at %s", irq_string(sc->sc_irq)); + } else +#endif /* NIOC > 0 */ + printf("no VSYNC sensing"); + + printf("\n"); + + scrdata.nscreens = 1; + scrdata.screens = &screenp; + screenp = &arcscreen; + + da.console = arcvideo_isconsole; + da.scrdata = &scrdata; + da.accessops = &arcvideo_accessops; + da.accesscookie = sc; + + config_found(self, &da, wsemuldisplaydevprint); +} + +#if 0 +static int +arcvideo_setmode(self, mode) + struct device *self; + struct arcvideo_mode *mode; +{ + struct arcvideo_softc *sc = (void *)self; + u_int32_t newctl, ctlmask; + u_int32_t newhswr, newhbsr, newhdsr, newhder, newhber, newhcr, newhir; + u_int32_t newvswr, newvbsr, newvdsr, newvder, newvber, newvcr; + + newctl = 0; + /* Dot clock */ + /* XXX: should this be abstracted a little to allow for + variable VIDCLKs? */ + switch (mode->timings.pixelrate) { + case 8000000: + newctl |= VIDC_CTL_DOTCLOCK_8MHZ; + break; + case 12000000: + newctl |= VIDC_CTL_DOTCLOCK_12MHZ; + break; + case 16000000: + newctl |= VIDC_CTL_DOTCLOCK_16MHZ; + break; + case 24000000: + newctl |= VIDC_CTL_DOTCLOCK_24MHZ; + break; + default: + return ENXIO; + }; + /* Bits per pixel */ + switch (mode->bpp) { + case 1: + newctl |= VIDC_CTL_BPP_ONE; + break; + case 2: + newctl |= VIDC_CTL_BPP_TWO; + break; + case 4: + newctl |= VIDC_CTL_BPP_FOUR; + break; + case 8: + newctl |= VIDC_CTL_BPP_EIGHT; + break; + default: + return EINVAL; + } + /* DMA timings */ + /* XXX: should work this out from pixelrate, bpp and MCLK rate. */ + newctl |= VIDC_CTL_DMARQ_37; + + ctlmask = ~(VIDC_CTL_DOTCLOCK_MASK + | VIDC_CTL_BPP_MASK + | VIDC_CTL_DMARQ_MASK); + + newhswr = (mode->timings.hsw - 2) / 2 << 14; + newhbsr = (mode->timings.hbs - 1) / 2 << 14; + switch (mode->bpp) { + case 8: + newhdsr = (mode->timings.hds - 5) / 2 << 14; + newhder = (mode->timings.hde - 5) / 2 << 14; + break; + case 4: + newhdsr = (mode->timings.hds - 7) / 2 << 14; + newhder = (mode->timings.hde - 7) / 2 << 14; + break; + case 2: + newhdsr = (mode->timings.hds - 11) / 2 << 14; + newhder = (mode->timings.hde - 11) / 2 << 14; + break; + case 1: + newhdsr = (mode->timings.hds - 19) / 2 << 14; + newhder = (mode->timings.hde - 19) / 2 << 14; + break; + } + newhber = (mode->timings.hbe - 1) / 2 << 14; + newhcr = (mode->timings.hc - 2) / 2 << 14; + newhir = mode->timings.hc / 4 << 14; + newvswr = (mode->timings.vsw - 1) << 14; + newvbsr = (mode->timings.vbs - 1) << 14; + newvdsr = (mode->timings.vds - 1) << 14; + newvder = (mode->timings.vde - 1) << 14; + newvber = (mode->timings.vbe - 1) << 14; + newvcr = (mode->timings.vc - 1) << 14; + arcvideo_await_vsync(self); + spltty(); /* XXX audio? */ + newctl |= sc->sc_vidc_ctl & ctlmask; + VIDC_WRITE(VIDC_CONTROL | newctl); + sc->sc_vidc_ctl = newctl; + VIDC_WRITE(VIDC_VCR | newvcr); + VIDC_WRITE(VIDC_VSWR | newvswr); + VIDC_WRITE(VIDC_VBSR | newvbsr); + VIDC_WRITE(VIDC_VDSR | newvdsr); + VIDC_WRITE(VIDC_VDER | newvder); + VIDC_WRITE(VIDC_VBER | newvber); + VIDC_WRITE(VIDC_HCR | newhcr); + VIDC_WRITE(VIDC_HIR | newhir); + VIDC_WRITE(VIDC_HSWR | newhswr); + VIDC_WRITE(VIDC_HBSR | newhbsr); + VIDC_WRITE(VIDC_HDSR | newhdsr); + VIDC_WRITE(VIDC_HDER | newhder); + VIDC_WRITE(VIDC_HBER | newhber); + return 0; +} + +static void +arcvideo_await_vsync(self) + struct device *self; +{ + + panic("arcvideo_await_vsync not implemented"); +} +#endif + +static int +arcvideo_intr(cookie) + void *cookie; +{ +/* struct arcvideo_softc *sc = cookie; */ + + return IRQ_HANDLED; +} + +/* + * In the standard RISC OS 8-bit palette (which we use), the bits go + * BGgRbrTt, feeding RrTt, GgTt and BbTt to the DACs. The top four of + * these bits are fixed in hardware. + * + * The following table is the closest match I can get to the colours + * at the top of rasops.c. + */ + +static u_int8_t rasops_cmap_8bpp[] = { + 0x00, 0x10, 0x40, 0x50, 0x80, 0x90, 0xc0, 0xfc, + 0xd0, 0x17, 0x63, 0x77, 0x8b, 0x9f, 0xeb, 0xff, +}; + +void +arccons_init() +{ + long defattr; + int clear = 0; + int crow; + struct rasops_info *ri = &arccons_ri; + + /* Force the screen to be at a known location */ + if (bootconfig.screenbase != 0) + clear = 1; + MEMC_WRITE(MEMC_SET_PTR(MEMC_VSTART, 0)); + MEMC_WRITE(MEMC_SET_PTR(MEMC_VINIT, 0)); + MEMC_WRITE(MEMC_SET_PTR(MEMC_VEND, 0x00080000)); + + /* Register video memory with UVM now we know how much we're using. */ + uvm_page_physload(0, atop(MEMC_DMA_MAX), + atop(round_page(bootconfig.screensize)), + atop(MEMC_DMA_MAX), VM_FREELIST_LOW); + + /* TODO: We should really set up the VIDC ourselves here. */ + + /* Set up arccons_ri */ + memset(ri, 0, sizeof(*ri)); + ri->ri_depth = bootconfig.bpp; + ri->ri_bits = (u_char *)(MEMC_PHYS_BASE + 0); + ri->ri_width = bootconfig.xpixels; + ri->ri_height = bootconfig.ypixels; + ri->ri_stride = ((bootconfig.xpixels * bootconfig.bpp + 31) >> 5) << 2; + ri->ri_flg = RI_CENTER | (clear ? RI_CLEAR : 0); + + if (rasops_init(ri, 1000, 1000) < 0) + panic("rasops_init failed"); + + if (ri->ri_depth == 8) + arccons_8bpp_hack(&arccons_ri); + + /* Take rcons stuff and put it in arcscreen */ + /* XXX shouldn't this kind of thing be done by rcons_init? */ + arcscreen.name = "arccons"; + arcscreen.ncols = ri->ri_cols; + arcscreen.nrows = ri->ri_rows; + arcscreen.textops = &ri->ri_ops; + arcscreen.fontwidth = ri->ri_font->fontwidth; + arcscreen.fontheight = ri->ri_font->fontheight; + arcscreen.capabilities = ri->ri_caps; + + /* work out cursor row */ + if (clear) + crow = 0; + else + /* +/-1 is to round up */ + crow = (bootconfig.cpixelrow - ri->ri_yorigin - 1) / + ri->ri_font->fontheight + 1; + if (crow < 0) crow = 0; + if (crow > ri->ri_rows) crow = ri->ri_rows; + + if ((arccons_ri.ri_ops.alloc_attr)(&arccons_ri, 0, 0, 0, &defattr) != + 0) + panic("alloc_attr failed"); + wsdisplay_cnattach(&arcscreen, &arccons_ri, 0, crow, defattr); + + /* That should be all */ + arcvideo_isconsole = 1; +} + +/* + * The following is a gross hack because the rasops code has no way + * for us to specify the devcmap if we don't want the default. I think + * it assumes that all 8-bit displays are PseudoColor. + */ + +static void +arccons_8bpp_hack(ri) + struct rasops_info *ri; +{ + int i, c; + + for (i = 0; i < 16; i++) { + c = rasops_cmap_8bpp[i]; + ri->ri_devcmap[i] = c | (c<<8) | (c<<16) | (c<<24); + } +} + + +/* wsdisplay access functions */ + +static int +arcvideo_ioctl(cookie, cmd, data, flag, p) + void *cookie; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct arcvideo_softc *sc = cookie; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_ARCHIMEDES; + return 0; + case WSDISPLAYIO_GVIDEO: + if (sc->sc_flags & AV_VIDEO_ON) + *(u_int *)data = WSDISPLAYIO_VIDEO_ON; + else + *(u_int *)data = WSDISPLAYIO_VIDEO_OFF; + return 0; + case WSDISPLAYIO_SVIDEO: + switch (*(u_int *)data) { + case WSDISPLAYIO_VIDEO_OFF: + sc->sc_flags &= ~AV_VIDEO_ON; + update_memc(MEMC_CTL_VIDEODMA | MEMC_CTL_RFRSH_MASK, + MEMC_CTL_RFRSH_CONTIN); + return 0; + case WSDISPLAYIO_VIDEO_ON: + sc->sc_flags |= AV_VIDEO_ON; + update_memc(MEMC_CTL_VIDEODMA | MEMC_CTL_RFRSH_MASK, + MEMC_CTL_VIDEODMA | + MEMC_CTL_RFRSH_FLYBACK); + return 0; + } + } + return -1; +} + +static int +arcvideo_mmap(cookie, off, prot) + void *cookie; + off_t off; + int prot; +{ + + return ENODEV; +} + +static int +arcvideo_alloc_screen(cookie, scr, scookiep, curxp, curyp, defattrp) + void *cookie, **scookiep; + const struct wsscreen_descr *scr; + int *curxp, *curyp; + long *defattrp; +{ + + return ENODEV; +} + +static void +arcvideo_free_screen(cookie, scookie) + void *cookie, *scookie; +{ + + panic("arcvideo_free_screen not implemented"); +} + +static void +arcvideo_show_screen(cookie, scookie, waitok, cb, cbarg) + void *cookie, *scookie; + int waitok; + void (*cb) __P((void *cbarg, int error, int waitok)); + void *cbarg; +{ + + panic("arcvideo_show_screen not implemented"); +} + +static int +arcvideo_load_font(cookie, emulcookie, font) + void *cookie, *emulcookie; + struct wsdisplay_font *font; +{ + + return ENODEV; +} diff --git a/sys/arch/arm26/vidc/arcvideovar.h b/sys/arch/arm26/vidc/arcvideovar.h new file mode 100644 index 00000000000..f970a08dfa2 --- /dev/null +++ b/sys/arch/arm26/vidc/arcvideovar.h @@ -0,0 +1,47 @@ +/* $NetBSD: arcvideovar.h,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ + +#ifndef _ARM26_ARCVIDEOVAR_H +#define _ARM26_ARCVIDEOVAR_H + +struct arcvideo_timings { + int pixelrate; /* in Hz */ + int hsw, hbs, hds, hde, hbe, hc; /* In pixels */ + int vsw, vbs, vds, vde, vbe, vc; /* In rasters */ +}; + +struct arcvideo_mode { + struct arcvideo_timings timings; + int bpp; + int sync_pol; +}; + +extern void arccons_init __P((void)); + +#endif diff --git a/sys/arch/arm26/vidc/vidcreg.h b/sys/arch/arm26/vidc/vidcreg.h new file mode 100644 index 00000000000..7b7bb7a74c7 --- /dev/null +++ b/sys/arch/arm26/vidc/vidcreg.h @@ -0,0 +1,131 @@ +/* $NetBSD: vidcreg.h,v 1.1 2000/05/09 21:56:04 bjh21 Exp $ */ +/*- + * Copyright (c) 1998 Ben Harris + * 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. 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. + */ +/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */ +/* + * vidcreg.h - Acorn/ARM VIDC (Arabella) registers + */ + +#ifndef _ARM26_VIDCREG_H +#define _ARM26_VIDCREG_H + +/* + * The VIDC is accessed by writing words to addresses starting at + * MEMC_VIDC_BASE definied in memcreg.h. + * + * As with the MEMC, the value is the logical OR of the register + * specifier and the new value. + */ + +/* Palette entries */ + +#define VIDC_PALETTE 0x00000000 +#define VIDC_PALETTE_LCOL(n) (n << 26) +#define VIDC_PALETTE_BCOL 0x40000000 +#define VIDC_PALETTE_CCOL(n) (0x40000000 + (n << 26)) + +#define VIDC_PALETTE_ENTRY(r, g, b, s) ((s != 0) << 12 | b << 8 | g << 4 | r) + +/* Stereo image registers */ +/* They're in the order 70123456 */ +#define VIDC_SIR(n) (0x60000000 + ((n + 1) % 8 << 26)) +#define VIDC_STEREO_L100 1 +#define VIDC_STEREO_L83 2 +#define VIDC_STEREO_L67 3 +#define VIDC_STEREO_C 4 +#define VIDC_STEREO_R67 5 +#define VIDC_STEREO_R83 6 +#define VIDC_STEREO_R100 7 + +/* Video timing register */ +#define VIDC_HCR 0x80000000 +#define VIDC_HSWR 0x84000000 +#define VIDC_HBSR 0x88000000 +#define VIDC_HDSR 0x8c000000 +#define VIDC_HDER 0x90000000 +#define VIDC_HBER 0x94000000 +#define VIDC_HCSR 0x98000000 +#define VIDC_HIR 0x9c000000 + +#define VIDC_VCR 0xa0000000 +#define VIDC_VSWR 0xa4000000 +#define VIDC_VBSR 0xa8000000 +#define VIDC_VDSR 0xac000000 +#define VIDC_VDER 0xb0000000 +#define VIDC_VBER 0xb4000000 +#define VIDC_VCSR 0xb8000000 +#define VIDC_VCER 0xbc000000 + +/* + * Horizontal timings have units of two pixels (except HCSR). + * Vertical timings have units of a raster. Most have to have one or + * two subtracted from them. + */ +#define VIDC_VIDTIMING(x) (x << 14) +#define VIDC_HCS(x) (x << 13) +#define VIDC_HCS_HIRES(x) (x << 11) + +/* Sound frequency register */ +#define VIDC_SFR 0xc0000000 +/* Units are us */ +#define VIDC_SF(x) (x & 0x100) + +/* Control register */ +#define VIDC_CONTROL 0xe0000000 + +#define VIDC_CTL_DOTCLOCK_MASK 0x00000003 +#define VIDC_CTL_DOTCLOCK_8MHZ 0x00000000 +#define VIDC_CTL_DOTCLOCK_12MHZ 0x00000001 +#define VIDC_CTL_DOTCLOCK_16MHZ 0x00000002 +#define VIDC_CTL_DOTCLOCK_24MHZ 0x00000003 + +#define VIDC_CTL_BPP_MASK 0x0000000c +#define VIDC_CTL_BPP_ONE 0x00000000 +#define VIDC_CTL_BPP_TWO 0x00000004 +#define VIDC_CTL_BPP_FOUR 0x00000008 +#define VIDC_CTL_BPP_EIGHT 0x0000000c + +#define VIDC_CTL_DMARQ_MASK 0x00000030 +#define VIDC_CTL_DMARQ_04 0x00000000 +#define VIDC_CTL_DMARQ_15 0x00000010 +#define VIDC_CTL_DMARQ_26 0x00000020 +#define VIDC_CTL_DMARQ_37 0x00000030 + +#define VIDC_CTL_INTERLACE 0x00000040 + +#define VIDC_CTL_CSYNC 0x00000080 + +#define VIDC_CTL_TEST_MASK 0x0000c100 +#define VIDC_CTL_TEST_OFF 0x00000000 +#define VIDC_CTL_TEST_MODE0 0x00004000 +#define VIDC_CTL_TEST_MODE1 0x00008000 +#define VIDC_CTL_TEST_MODE2 0x0000c000 +#define VIDC_CTL_TEST_MODE3 0x00000100 + +#define VIDC_WRITE(value) *(volatile u_int32_t *)MEMC_VIDC_BASE = value + +#endif diff --git a/sys/arch/arm26/vidc/vidmodes.c b/sys/arch/arm26/vidc/vidmodes.c new file mode 100644 index 00000000000..99e8edfcb13 --- /dev/null +++ b/sys/arch/arm26/vidc/vidmodes.c @@ -0,0 +1,48 @@ +/* + * XFree86 modes are: + * Modeline "name" dotclock hdisp hsyncstart hsyncend htotal \ + * vdisp vsyncstart vsyncend vtotal flags + * + * hswr = hsyncend - hsyncstart + * hdsr = htotal - hsyncstart + * hder = hdsr + hdisp + * hcr = htotal + * Same for vertical. XFree doesn't do borders. + */ + +/* RISC OS Mode 0 etc (I think) 640x256 @ 50Hz, 15.6kHz hsync */ +struct arcvideo_timings timing_std640x256 = { + 16000000, + 72, 217, 265, 905, 953, 1024, + 3, 21, 39, 295, 312, 312 +}; + +/* + * # 640x400 @ 70 Hz, 31.5 kHz hsync + * Modeline "640x400" 25.175 640 664 760 800 400 409 411 450 + */ +struct arcvideo_timings timing_vga640x400 = { + 25175000, + 96, 136, 136, 776, 776, 800, + 2, 41, 41, 441, 441, 450 +}; + +/* + * # 640x480 @ 60 Hz, 31.5 kHz hsync + * Modeline "640x480" 25.175 640 664 760 800 480 491 493 525 + */ +struct arcvideo_timings timing_vga640x480 = { + 25175000, + 96, 136, 136, 776, 776, 800, + 2, 34, 34, 514, 514, 525 +}; + +/* + * # 800x600 @ 56 Hz, 35.15 kHz hsync + * ModeLine "800x600" 36 800 824 896 1024 600 601 603 625 + */ +struct arcvideo_timings timing_svga800x600 = { + 36000000, + 72, 200, 200, 1000, 1000, 1024, + 2, 24, 24, 624, 624, 625 +}; diff --git a/sys/arch/arm32/podulebus/podule_data.h b/sys/arch/arm32/podulebus/podule_data.h index e37a471a05b..4c3106a8bd1 100644 --- a/sys/arch/arm32/podulebus/podule_data.h +++ b/sys/arch/arm32/podulebus/podule_data.h @@ -1,4 +1,4 @@ -/* $NetBSD: podule_data.h,v 1.13 1999/11/12 07:38:51 mark Exp $ */ +/* $NetBSD: podule_data.h,v 1.14 2000/05/09 21:56:04 bjh21 Exp $ */ /* * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. @@ -178,6 +178,11 @@ static struct podule_description podules_castle[] = { { 0x0000, NULL } }; +static struct podule_description podules_dtsoft[] = { + { PODULE_DTSOFT_IDE, "IDE interface" }, + { 0x0000, NULL } +}; + static struct podule_description podules_alsystems[] = { { PODULE_ALSYSTEMS_SCSI, "SCSI II host adapter" }, { 0x0000, NULL } @@ -228,6 +233,7 @@ struct podule_list known_podules[] = { { MANUFACTURER_BRINI, "Brini", podules_brini }, { MANUFACTURER_ANT, "ANT", podules_ant }, { MANUFACTURER_CASTLE, "Castle Technology", podules_castle }, + { MANUFACTURER_DTSOFT, "D.T. Software", podules_dtsoft }, { MANUFACTURER_ALSYSTEMS, "Alsystems", podules_alsystems }, { MANUFACTURER_SIMTEC, "Simtec Electronics", podules_simtec }, { MANUFACTURER_YES, "Yellowstone Educational Solutions", podules_yes }, diff --git a/sys/arch/arm32/podulebus/podules b/sys/arch/arm32/podulebus/podules index 15598de0b2e..cd2f00a6657 100644 --- a/sys/arch/arm32/podulebus/podules +++ b/sys/arch/arm32/podulebus/podules @@ -1,4 +1,4 @@ -$NetBSD: podules,v 1.10 1999/11/12 07:37:21 mark Exp $ +$NetBSD: podules,v 1.11 2000/05/09 21:56:04 bjh21 Exp $ /* * Copyright (c) 1996 Mark Brinicombe @@ -57,6 +57,7 @@ manufacturer ICUBED 0x0046 I-Cubed manufacturer BRINI 0x0050 Brini manufacturer ANT 0x0053 ANT manufacturer CASTLE 0x0055 Castle Technology +manufacturer DTSOFT 0x0037 D.T. Software manufacturer ALSYSTEMS 0x005b Alsystems manufacturer SIMTEC 0x005f Simtec Electronics manufacturer YES 0x0060 Yellowstone Educational Solutions @@ -105,6 +106,8 @@ podule MORLEY SCSI 0x0067 SCSI interface podule VTI SCSI 0x008d SCSI interface +podule DTSOFT IDE 0x00ae IDE interface + podule CUMANA SCSI2 0x003a SCSI II interface podule CUMANA SCSI1 0x00a0 SCSI I interface podule CUMANA SLCD 0x00dd CDFS & SLCD expansion card diff --git a/sys/arch/arm32/podulebus/podules.h b/sys/arch/arm32/podulebus/podules.h index 0a7ba9c695c..18a22fec6ac 100644 --- a/sys/arch/arm32/podulebus/podules.h +++ b/sys/arch/arm32/podulebus/podules.h @@ -1,4 +1,4 @@ -/* $NetBSD: podules.h,v 1.13 1999/11/12 07:38:51 mark Exp $ */ +/* $NetBSD: podules.h,v 1.14 2000/05/09 21:56:04 bjh21 Exp $ */ /* * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. @@ -64,6 +64,7 @@ #define MANUFACTURER_BRINI 0x0050 /* Brini */ #define MANUFACTURER_ANT 0x0053 /* ANT */ #define MANUFACTURER_CASTLE 0x0055 /* Castle Technology */ +#define MANUFACTURER_DTSOFT 0x0037 /* D.T. Software */ #define MANUFACTURER_ALSYSTEMS 0x005b /* Alsystems */ #define MANUFACTURER_SIMTEC 0x005f /* Simtec Electronics */ #define MANUFACTURER_YES 0x0060 /* Yellowstone Educational Solutions */ @@ -112,6 +113,8 @@ #define PODULE_VTI_SCSI 0x008d /* SCSI interface */ +#define PODULE_DTSOFT_IDE 0x00ae /* IDE interface */ + #define PODULE_CUMANA_SCSI2 0x003a /* SCSI II interface */ #define PODULE_CUMANA_SCSI1 0x00a0 /* SCSI I interface */ #define PODULE_CUMANA_SLCD 0x00dd /* CDFS & SLCD expansion card */ diff --git a/sys/lib/libkern/arch/arm26/Makefile.inc b/sys/lib/libkern/arch/arm26/Makefile.inc new file mode 100644 index 00000000000..0bb37876769 --- /dev/null +++ b/sys/lib/libkern/arch/arm26/Makefile.inc @@ -0,0 +1,9 @@ +# $NetBSD: Makefile.inc,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ + +SRCS+= __main.c imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c \ + byte_swap_2.S byte_swap_4.S bswap64.c bcmp.c ffs.c strcat.c strcmp.c \ + strcpy.c strlen.c strncmp.c strncpy.c scanc.c skpc.c random.c \ + strncasecmp.c __assert.c +SRCS+= divsi3.S +SRCS+= memchr.c memcmp.c _memcpy.S memcpy.S memmove.S memset.S +SRCS+= bcopy.S bzero.S diff --git a/sys/lib/libkern/arch/arm26/_memcpy.S b/sys/lib/libkern/arch/arm26/_memcpy.S new file mode 100644 index 00000000000..d217837947c --- /dev/null +++ b/sys/lib/libkern/arch/arm26/_memcpy.S @@ -0,0 +1,463 @@ +/* $Id: _memcpy.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ +/* $NetBSD: _memcpy.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/* + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * 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 <machine/asm.h> + +/* + * This is one fun bit of code ... + * Some easy listening music is suggested while trying to understand this + * code e.g. Iron Maiden + * + * For anyone attempting to understand it : + * + * The core code is implemented here with simple stubs for memcpy() + * memmove() and bcopy(). + * + * All local labels are prefixed with Lmemcpy_ + * Following the prefix a label starting f is used in the forward copy code + * while a label using b is used in the backwards copy code + * The source and destination addresses determine whether a forward or + * backward copy is performed. + * Separate bits of code are used to deal with the following situations + * for both the forward and backwards copy. + * unaligned source address + * unaligned destination address + * Separate copy routines are used to produce an optimised result for each + * of these cases. + * The copy code will use LDM/STM instructions to copy up to 32 bytes at + * a time where possible. + * + * Note: r12 (aka ip) can be trashed during the function along with + * r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out. + * Additional registers are preserved prior to use i.e. r4, r5 & lr + * + * Apologies for the state of the comments ;-) + */ + +ENTRY(_memcpy) + /* Determine copy direction */ + cmp r1, r0 + bcc Lmemcpy_backwards + + moveq r0, #0 /* Quick abort for len=0 */ +#ifdef __APCS_26__ + moveqs pc, lr +#else + moveq pc, lr +#endif + + stmdb sp!, {r0, lr} /* memcpy() returns dest addr */ + subs r2, r2, #4 + blt Lmemcpy_fl4 /* less than 4 bytes */ + ands r12, r0, #3 + bne Lmemcpy_fdestul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne Lmemcpy_fsrcul /* oh unaligned source addr */ + +Lmemcpy_ft8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt Lmemcpy_fl12 /* less than 12 bytes (4 from above) */ + subs r2, r2, #0x14 + blt Lmemcpy_fl32 /* less than 32 bytes (12 from above) */ + stmdb sp!, {r4} /* borrow r4 */ + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +Lmemcpy_floop32: + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge Lmemcpy_floop32 + + cmn r2, #0x10 + ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */ + stmgeia r0!, {r3, r4, r12, lr} + subge r2, r2, #0x10 + ldmia sp!, {r4} /* return r4 */ + +Lmemcpy_fl32: + adds r2, r2, #0x14 + + /* blat 12 bytes at a time */ +Lmemcpy_floop12: + ldmgeia r1!, {r3, r12, lr} + stmgeia r0!, {r3, r12, lr} + subges r2, r2, #0x0c + bge Lmemcpy_floop12 + +Lmemcpy_fl12: + adds r2, r2, #8 + blt Lmemcpy_fl4 + + subs r2, r2, #4 + ldrlt r3, [r1], #4 + strlt r3, [r0], #4 + ldmgeia r1!, {r3, r12} + stmgeia r0!, {r3, r12} + subge r2, r2, #4 + +Lmemcpy_fl4: + /* less than 4 bytes to go */ + adds r2, r2, #4 + ldmeqia sp!, {r0, pc} /* done */ + + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 +#ifdef __APCS_26__ + ldmia sp!, {r0, pc}^ +#else + ldmia sp!, {r0, pc} +#endif + + /* erg - unaligned destination */ +Lmemcpy_fdestul: + rsb r12, r12, #4 + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1], #1 + strb r3, [r0], #1 + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 + subs r2, r2, r12 + blt Lmemcpy_fl4 /* less the 4 bytes */ + + ands r12, r1, #3 + beq Lmemcpy_ft8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +Lmemcpy_fsrcul: + bic r1, r1, #3 + ldr lr, [r1], #4 + cmp r12, #2 + bgt Lmemcpy_fsrcul3 + beq Lmemcpy_fsrcul2 + cmp r2, #0x0c + blt Lmemcpy_fsrcul1loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +Lmemcpy_fsrcul1loop16: + mov r3, lr, lsr #8 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r12, lsl #24 + mov r12, r12, lsr #8 + orr r12, r12, lr, lsl #24 + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge Lmemcpy_fsrcul1loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt Lmemcpy_fsrcul1l4 + +Lmemcpy_fsrcul1loop4: + mov r12, lr, lsr #8 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #24 + str r12, [r0], #4 + subs r2, r2, #4 + bge Lmemcpy_fsrcul1loop4 + +Lmemcpy_fsrcul1l4: + sub r1, r1, #3 + b Lmemcpy_fl4 + +Lmemcpy_fsrcul2: + cmp r2, #0x0c + blt Lmemcpy_fsrcul2loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +Lmemcpy_fsrcul2loop16: + mov r3, lr, lsr #16 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r12, lsl #16 + mov r12, r12, lsr #16 + orr r12, r12, lr, lsl #16 + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge Lmemcpy_fsrcul2loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt Lmemcpy_fsrcul2l4 + +Lmemcpy_fsrcul2loop4: + mov r12, lr, lsr #16 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #16 + str r12, [r0], #4 + subs r2, r2, #4 + bge Lmemcpy_fsrcul2loop4 + +Lmemcpy_fsrcul2l4: + sub r1, r1, #2 + b Lmemcpy_fl4 + +Lmemcpy_fsrcul3: + cmp r2, #0x0c + blt Lmemcpy_fsrcul3loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +Lmemcpy_fsrcul3loop16: + mov r3, lr, lsr #24 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r12, lsl #8 + mov r12, r12, lsr #24 + orr r12, r12, lr, lsl #8 + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge Lmemcpy_fsrcul3loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt Lmemcpy_fsrcul3l4 + +Lmemcpy_fsrcul3loop4: + mov r12, lr, lsr #24 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #8 + str r12, [r0], #4 + subs r2, r2, #4 + bge Lmemcpy_fsrcul3loop4 + +Lmemcpy_fsrcul3l4: + sub r1, r1, #1 + b Lmemcpy_fl4 + +Lmemcpy_backwards: + add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt Lmemcpy_bl4 /* less than 4 bytes */ + ands r12, r0, #3 + bne Lmemcpy_bdestul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne Lmemcpy_bsrcul /* oh unaligned source addr */ + +Lmemcpy_bt8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt Lmemcpy_bl12 /* less than 12 bytes (4 from above) */ + stmdb sp!, {r4, lr} + subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */ + blt Lmemcpy_bl32 + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +Lmemcpy_bloop32: + ldmdb r1!, {r3, r4, r12, lr} + stmdb r0!, {r3, r4, r12, lr} + ldmdb r1!, {r3, r4, r12, lr} + stmdb r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge Lmemcpy_bloop32 + +Lmemcpy_bl32: + cmn r2, #0x10 + ldmgedb r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */ + stmgedb r0!, {r3, r4, r12, lr} + subge r2, r2, #0x10 + adds r2, r2, #0x14 + ldmgedb r1!, {r3, r12, lr} /* blat a remaining 12 bytes */ + stmgedb r0!, {r3, r12, lr} + subge r2, r2, #0x0c + ldmia sp!, {r4, lr} + +Lmemcpy_bl12: + adds r2, r2, #8 + blt Lmemcpy_bl4 + subs r2, r2, #4 + ldrlt r3, [r1, #-4]! + strlt r3, [r0, #-4]! + ldmgedb r1!, {r3, r12} + stmgedb r0!, {r3, r12} + subge r2, r2, #4 + +Lmemcpy_bl4: + /* less than 4 bytes to go */ + adds r2, r2, #4 + moveq pc, lr /* done */ + + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! +#ifdef __APCS_26__ + movs pc, lr +#else + mov pc, lr +#endif + + /* erg - unaligned destination */ +Lmemcpy_bdestul: + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! + subs r2, r2, r12 + blt Lmemcpy_bl4 /* less than 4 bytes to go */ + ands r12, r1, #3 + beq Lmemcpy_bt8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +Lmemcpy_bsrcul: + bic r1, r1, #3 + ldr r3, [r1, #0] + cmp r12, #2 + blt Lmemcpy_bsrcul1 + beq Lmemcpy_bsrcul2 + cmp r2, #0x0c + blt Lmemcpy_bsrcul3loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +Lmemcpy_bsrcul3loop16: + mov lr, r3, lsl #8 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #24 + mov r12, r12, lsl #8 + orr r12, r12, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r3, lsr #24 + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge Lmemcpy_bsrcul3loop16 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt Lmemcpy_bsrcul3l4 + +Lmemcpy_bsrcul3loop4: + mov r12, r3, lsl #8 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #24 + str r12, [r0, #-4]! + subs r2, r2, #4 + bge Lmemcpy_bsrcul3loop4 + +Lmemcpy_bsrcul3l4: + add r1, r1, #3 + b Lmemcpy_bl4 + +Lmemcpy_bsrcul2: + cmp r2, #0x0c + blt Lmemcpy_bsrcul2loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +Lmemcpy_bsrcul2loop16: + mov lr, r3, lsl #16 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #16 + mov r12, r12, lsl #16 + orr r12, r12, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r3, lsr #16 + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge Lmemcpy_bsrcul2loop16 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt Lmemcpy_bsrcul2l4 + +Lmemcpy_bsrcul2loop4: + mov r12, r3, lsl #16 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #16 + str r12, [r0, #-4]! + subs r2, r2, #4 + bge Lmemcpy_bsrcul2loop4 + +Lmemcpy_bsrcul2l4: + add r1, r1, #2 + b Lmemcpy_bl4 + +Lmemcpy_bsrcul1: + cmp r2, #0x0c + blt Lmemcpy_bsrcul1loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +Lmemcpy_bsrcul1loop32: + mov lr, r3, lsl #24 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #8 + mov r12, r12, lsl #24 + orr r12, r12, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r3, lsr #8 + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge Lmemcpy_bsrcul1loop32 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt Lmemcpy_bsrcul1l4 + +Lmemcpy_bsrcul1loop4: + mov r12, r3, lsl #24 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #8 + str r12, [r0, #-4]! + subs r2, r2, #4 + bge Lmemcpy_bsrcul1loop4 + +Lmemcpy_bsrcul1l4: + add r1, r1, #1 + b Lmemcpy_bl4 + diff --git a/sys/lib/libkern/arch/arm26/bcopy.S b/sys/lib/libkern/arch/arm26/bcopy.S new file mode 100644 index 00000000000..cebada98b57 --- /dev/null +++ b/sys/lib/libkern/arch/arm26/bcopy.S @@ -0,0 +1,48 @@ +/* $NetBSD: bcopy.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * 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 <machine/asm.h> + +/* bcopy = memcpy/memmove with arguments reversed. */ + +TWOENTRY(bcopy,ovbcopy) + /* switch the source and destination registers */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + b __memcpy diff --git a/sys/lib/libkern/arch/arm26/byte_swap_2.S b/sys/lib/libkern/arch/arm26/byte_swap_2.S new file mode 100644 index 00000000000..a7a9da236aa --- /dev/null +++ b/sys/lib/libkern/arch/arm26/byte_swap_2.S @@ -0,0 +1,53 @@ +/* $NetBSD: byte_swap_2.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * 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 <machine/asm.h> + +_BEGIN_ENTRY; +_ENTRY(_C_FUNC(bswap16)); +_ENTRY(_C_FUNC(ntohs)); +_ENTRY(_C_FUNC(htons)); +_END_ENTRY + and r1, r0, #0xFF00 + mov r0, r0, lsl #8 + orr r0, r0, r1, lsr #8 +#ifdef __APCS_26__ + movs pc, lr +#else + mov pc, lr +#endif
\ No newline at end of file diff --git a/sys/lib/libkern/arch/arm26/byte_swap_4.S b/sys/lib/libkern/arch/arm26/byte_swap_4.S new file mode 100644 index 00000000000..1b1878090b8 --- /dev/null +++ b/sys/lib/libkern/arch/arm26/byte_swap_4.S @@ -0,0 +1,54 @@ +/* $NetBSD: byte_swap_4.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson + * + * 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 <machine/asm.h> + +_BEGIN_ENTRY; +_ENTRY(_C_FUNC(bswap32)); +_ENTRY(_C_FUNC(ntohl)); +_ENTRY(_C_FUNC(htonl)); +_END_ENTRY + eor r1, r0, r0, ror #16 + bic r1, r1, #0x00FF0000 + mov r0, r0, ror #8 + eor r0, r0, r1, lsr #8 +#ifdef __APCS_26__ + movs pc,lr +#else + mov pc, lr +#endif
\ No newline at end of file diff --git a/sys/lib/libkern/arch/arm26/bzero.S b/sys/lib/libkern/arch/arm26/bzero.S new file mode 100644 index 00000000000..5e0fc5654c3 --- /dev/null +++ b/sys/lib/libkern/arch/arm26/bzero.S @@ -0,0 +1,44 @@ +/* $NetBSD: bzero.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * 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 <machine/asm.h> + +ENTRY(bzero) + mov r2, r1 + mov r1, #0 + b _memset diff --git a/sys/lib/libkern/arch/arm26/divsi3.S b/sys/lib/libkern/arch/arm26/divsi3.S new file mode 100644 index 00000000000..9c28b7157cd --- /dev/null +++ b/sys/lib/libkern/arch/arm26/divsi3.S @@ -0,0 +1,398 @@ +/* $NetBSD: divsi3.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/* + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <machine/asm.h> + +ENTRY(__umodsi3) + stmfd sp!, {lr} + bl L_udivide + mov r0, r1 +#ifdef __APCS_26__ + ldmfd sp!, {pc}^ +#else /* APCS-32 */ + ldmfd sp!, {pc} +#endif + +ENTRY(__modsi3) + stmfd sp!, {lr} + bl L_divide + mov r0, r1 +#ifdef __APCS_26__ + ldmfd sp!, {pc}^ +#else + ldmfd sp!, {pc} +#endif + +L_overflow: +#if 0 /* FIXME */ + mov r0, #8 /* SIGFPE */ + bl _C_FUNC(raise) /* raise it */ +#endif + mov r0, #0 +#ifdef __APCS_26__ + movs pc, lr +#else + mov pc, lr +#endif + +ENTRY(__udivsi3) +L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + /* r0 = r1 / r0; r1 = r1 % r0 */ + cmp r0, #1 + bcc L_overflow + beq L_divide_l0 + mov ip, #0 + movs r1, r1 + bpl L_divide_l1 + orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ + movs r1, r1, lsr #1 + orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ + b L_divide_l1 + +L_divide_l0: /* r0 == 1 */ + mov r0, r1 + mov r1, #0 +#ifdef __APCS_26__ + movs pc, lr +#else + mov pc, lr +#endif + +ENTRY(__divsi3) +L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + /* r0 = r1 / r0; r1 = r1 % r0 */ + cmp r0, #1 + bcc L_overflow + beq L_divide_l0 + ands ip, r0, #0x80000000 + rsbmi r0, r0, #0 + ands r2, r1, #0x80000000 + eor ip, ip, r2 + rsbmi r1, r1, #0 + orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ + /* ip bit 0x80000000 = -ve remainder */ + +L_divide_l1: + mov r2, #1 + mov r3, #0 + + /* + * If the highest bit of the dividend is set, we have to be + * careful when shifting the divisor. Test this. + */ + movs r1,r1 + bpl L_old_code + + /* + * At this point, the highest bit of r1 is known to be set. + * We abuse this below in the tst instructions. + */ + tst r1, r0 /*, lsl #0 */ + bmi L_divide_b1 + tst r1, r0, lsl #1 + bmi L_divide_b2 + tst r1, r0, lsl #2 + bmi L_divide_b3 + tst r1, r0, lsl #3 + bmi L_divide_b4 + tst r1, r0, lsl #4 + bmi L_divide_b5 + tst r1, r0, lsl #5 + bmi L_divide_b6 + tst r1, r0, lsl #6 + bmi L_divide_b7 + tst r1, r0, lsl #7 + bmi L_divide_b8 + tst r1, r0, lsl #8 + bmi L_divide_b9 + tst r1, r0, lsl #9 + bmi L_divide_b10 + tst r1, r0, lsl #10 + bmi L_divide_b11 + tst r1, r0, lsl #11 + bmi L_divide_b12 + tst r1, r0, lsl #12 + bmi L_divide_b13 + tst r1, r0, lsl #13 + bmi L_divide_b14 + tst r1, r0, lsl #14 + bmi L_divide_b15 + tst r1, r0, lsl #15 + bmi L_divide_b16 + tst r1, r0, lsl #16 + bmi L_divide_b17 + tst r1, r0, lsl #17 + bmi L_divide_b18 + tst r1, r0, lsl #18 + bmi L_divide_b19 + tst r1, r0, lsl #19 + bmi L_divide_b20 + tst r1, r0, lsl #20 + bmi L_divide_b21 + tst r1, r0, lsl #21 + bmi L_divide_b22 + tst r1, r0, lsl #22 + bmi L_divide_b23 + tst r1, r0, lsl #23 + bmi L_divide_b24 + tst r1, r0, lsl #24 + bmi L_divide_b25 + tst r1, r0, lsl #25 + bmi L_divide_b26 + tst r1, r0, lsl #26 + bmi L_divide_b27 + tst r1, r0, lsl #27 + bmi L_divide_b28 + tst r1, r0, lsl #28 + bmi L_divide_b29 + tst r1, r0, lsl #29 + bmi L_divide_b30 + tst r1, r0, lsl #30 + bmi L_divide_b31 +/* + * instead of: + * tst r1, r0, lsl #31 + * bmi L_divide_b32 + */ + b L_divide_b32 + +L_old_code: + cmp r1, r0 + bcc L_divide_b0 + cmp r1, r0, lsl #1 + bcc L_divide_b1 + cmp r1, r0, lsl #2 + bcc L_divide_b2 + cmp r1, r0, lsl #3 + bcc L_divide_b3 + cmp r1, r0, lsl #4 + bcc L_divide_b4 + cmp r1, r0, lsl #5 + bcc L_divide_b5 + cmp r1, r0, lsl #6 + bcc L_divide_b6 + cmp r1, r0, lsl #7 + bcc L_divide_b7 + cmp r1, r0, lsl #8 + bcc L_divide_b8 + cmp r1, r0, lsl #9 + bcc L_divide_b9 + cmp r1, r0, lsl #10 + bcc L_divide_b10 + cmp r1, r0, lsl #11 + bcc L_divide_b11 + cmp r1, r0, lsl #12 + bcc L_divide_b12 + cmp r1, r0, lsl #13 + bcc L_divide_b13 + cmp r1, r0, lsl #14 + bcc L_divide_b14 + cmp r1, r0, lsl #15 + bcc L_divide_b15 + cmp r1, r0, lsl #16 + bcc L_divide_b16 + cmp r1, r0, lsl #17 + bcc L_divide_b17 + cmp r1, r0, lsl #18 + bcc L_divide_b18 + cmp r1, r0, lsl #19 + bcc L_divide_b19 + cmp r1, r0, lsl #20 + bcc L_divide_b20 + cmp r1, r0, lsl #21 + bcc L_divide_b21 + cmp r1, r0, lsl #22 + bcc L_divide_b22 + cmp r1, r0, lsl #23 + bcc L_divide_b23 + cmp r1, r0, lsl #24 + bcc L_divide_b24 + cmp r1, r0, lsl #25 + bcc L_divide_b25 + cmp r1, r0, lsl #26 + bcc L_divide_b26 + cmp r1, r0, lsl #27 + bcc L_divide_b27 + cmp r1, r0, lsl #28 + bcc L_divide_b28 + cmp r1, r0, lsl #29 + bcc L_divide_b29 + cmp r1, r0, lsl #30 + bcc L_divide_b30 +L_divide_b32: + cmp r1, r0, lsl #31 + subhs r1, r1,r0, lsl #31 + addhs r3, r3,r2, lsl #31 +L_divide_b31: + cmp r1, r0, lsl #30 + subhs r1, r1,r0, lsl #30 + addhs r3, r3,r2, lsl #30 +L_divide_b30: + cmp r1, r0, lsl #29 + subhs r1, r1,r0, lsl #29 + addhs r3, r3,r2, lsl #29 +L_divide_b29: + cmp r1, r0, lsl #28 + subhs r1, r1,r0, lsl #28 + addhs r3, r3,r2, lsl #28 +L_divide_b28: + cmp r1, r0, lsl #27 + subhs r1, r1,r0, lsl #27 + addhs r3, r3,r2, lsl #27 +L_divide_b27: + cmp r1, r0, lsl #26 + subhs r1, r1,r0, lsl #26 + addhs r3, r3,r2, lsl #26 +L_divide_b26: + cmp r1, r0, lsl #25 + subhs r1, r1,r0, lsl #25 + addhs r3, r3,r2, lsl #25 +L_divide_b25: + cmp r1, r0, lsl #24 + subhs r1, r1,r0, lsl #24 + addhs r3, r3,r2, lsl #24 +L_divide_b24: + cmp r1, r0, lsl #23 + subhs r1, r1,r0, lsl #23 + addhs r3, r3,r2, lsl #23 +L_divide_b23: + cmp r1, r0, lsl #22 + subhs r1, r1,r0, lsl #22 + addhs r3, r3,r2, lsl #22 +L_divide_b22: + cmp r1, r0, lsl #21 + subhs r1, r1,r0, lsl #21 + addhs r3, r3,r2, lsl #21 +L_divide_b21: + cmp r1, r0, lsl #20 + subhs r1, r1,r0, lsl #20 + addhs r3, r3,r2, lsl #20 +L_divide_b20: + cmp r1, r0, lsl #19 + subhs r1, r1,r0, lsl #19 + addhs r3, r3,r2, lsl #19 +L_divide_b19: + cmp r1, r0, lsl #18 + subhs r1, r1,r0, lsl #18 + addhs r3, r3,r2, lsl #18 +L_divide_b18: + cmp r1, r0, lsl #17 + subhs r1, r1,r0, lsl #17 + addhs r3, r3,r2, lsl #17 +L_divide_b17: + cmp r1, r0, lsl #16 + subhs r1, r1,r0, lsl #16 + addhs r3, r3,r2, lsl #16 +L_divide_b16: + cmp r1, r0, lsl #15 + subhs r1, r1,r0, lsl #15 + addhs r3, r3,r2, lsl #15 +L_divide_b15: + cmp r1, r0, lsl #14 + subhs r1, r1,r0, lsl #14 + addhs r3, r3,r2, lsl #14 +L_divide_b14: + cmp r1, r0, lsl #13 + subhs r1, r1,r0, lsl #13 + addhs r3, r3,r2, lsl #13 +L_divide_b13: + cmp r1, r0, lsl #12 + subhs r1, r1,r0, lsl #12 + addhs r3, r3,r2, lsl #12 +L_divide_b12: + cmp r1, r0, lsl #11 + subhs r1, r1,r0, lsl #11 + addhs r3, r3,r2, lsl #11 +L_divide_b11: + cmp r1, r0, lsl #10 + subhs r1, r1,r0, lsl #10 + addhs r3, r3,r2, lsl #10 +L_divide_b10: + cmp r1, r0, lsl #9 + subhs r1, r1,r0, lsl #9 + addhs r3, r3,r2, lsl #9 +L_divide_b9: + cmp r1, r0, lsl #8 + subhs r1, r1,r0, lsl #8 + addhs r3, r3,r2, lsl #8 +L_divide_b8: + cmp r1, r0, lsl #7 + subhs r1, r1,r0, lsl #7 + addhs r3, r3,r2, lsl #7 +L_divide_b7: + cmp r1, r0, lsl #6 + subhs r1, r1,r0, lsl #6 + addhs r3, r3,r2, lsl #6 +L_divide_b6: + cmp r1, r0, lsl #5 + subhs r1, r1,r0, lsl #5 + addhs r3, r3,r2, lsl #5 +L_divide_b5: + cmp r1, r0, lsl #4 + subhs r1, r1,r0, lsl #4 + addhs r3, r3,r2, lsl #4 +L_divide_b4: + cmp r1, r0, lsl #3 + subhs r1, r1,r0, lsl #3 + addhs r3, r3,r2, lsl #3 +L_divide_b3: + cmp r1, r0, lsl #2 + subhs r1, r1,r0, lsl #2 + addhs r3, r3,r2, lsl #2 +L_divide_b2: + cmp r1, r0, lsl #1 + subhs r1, r1,r0, lsl #1 + addhs r3, r3,r2, lsl #1 +L_divide_b1: + cmp r1, r0 + subhs r1, r1, r0 + addhs r3, r3, r2 +L_divide_b0: + + tst ip, #0x20000000 + bne L_udivide_l1 + mov r0, r3 + cmp ip, #0 + rsbmi r1, r1, #0 + movs ip, ip, lsl #1 + bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ + rsbmi r0, r0, #0 +#ifdef __APCS_26__ + movs pc, lr +#else + mov pc, lr +#endif + +L_udivide_l1: + tst ip, #0x10000000 + mov r1, r1, lsl #1 + orrne r1, r1, #1 + mov r3, r3, lsl #1 + cmp r1, r0 + subhs r1, r1, r0 + addhs r3, r3, r2 + mov r0, r3 +#ifdef __APCS_26__ + movs pc, lr +#else + mov pc, lr +#endif diff --git a/sys/lib/libkern/arch/arm26/memcpy.S b/sys/lib/libkern/arch/arm26/memcpy.S new file mode 100644 index 00000000000..27edaf15ee7 --- /dev/null +++ b/sys/lib/libkern/arch/arm26/memcpy.S @@ -0,0 +1,48 @@ +/* $NetBSD: memcpy.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * 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 <machine/asm.h> + +ENTRY(memcpy) + stmfd sp!, {r0, lr} + bl _C_FUNC(_memcpy) +#ifdef __APCS_26__ + ldmfd sp!, {r0, pc}^ +#else + ldmfd sp!, {r0, pc} +#endif diff --git a/sys/lib/libkern/arch/arm26/memmove.S b/sys/lib/libkern/arch/arm26/memmove.S new file mode 100644 index 00000000000..b67a40f15bc --- /dev/null +++ b/sys/lib/libkern/arch/arm26/memmove.S @@ -0,0 +1,48 @@ +/* $NetBSD: memmove.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * 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 <machine/asm.h> + +ENTRY(memmove) + stmfd sp!, {r0, lr} + bl _C_FUNC(_memcpy) +#ifdef __APCS_26__ + ldmfd sp!, {r0, pc}^ +#else + ldmfd sp!, {r0, pc} +#endif diff --git a/sys/lib/libkern/arch/arm26/memset.S b/sys/lib/libkern/arch/arm26/memset.S new file mode 100644 index 00000000000..3f62aed5563 --- /dev/null +++ b/sys/lib/libkern/arch/arm26/memset.S @@ -0,0 +1,134 @@ +/* $NetBSD: memset.S,v 1.1 2000/05/09 21:56:05 bjh21 Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * 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 Mark Brinicombe. + * 4. The name of the company nor the name of the author may 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 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 <machine/asm.h> + +/* + * Sets a block of memory to the specified value + * + * On entry: + * r0 - dest address + * r1 - byte to write + * r2 - number of bytes to write + * + * On exit: + * r0 - dest address + */ + +ENTRY(memset) + stmfd sp!, {r0} /* Remember address for return value */ + and r1, r1, #0x000000ff /* We write bytes */ + + cmp r2, #0x00000004 /* Do we have less than 4 bytes */ + blt Lmemset_lessthanfour + + /* Ok first we will word align the address */ + + ands r3, r0, #0x00000003 /* Get the bottom two bits */ + beq Lmemset_addraligned /* The address is word aligned */ + + rsb r3, r3, #0x00000004 + sub r2, r2, r3 + cmp r3, #0x00000002 + strb r1, [r0], #0x0001 /* Set 1 byte */ + strgeb r1, [r0], #0x0001 /* Set another byte */ + strgtb r1, [r0], #0x0001 /* and a third */ + + cmp r2, #0x00000004 + blt Lmemset_lessthanfour + + /* Now we must be word aligned */ + +Lmemset_addraligned: + + orr r3, r1, r1, lsl #8 /* Repeat the byte into a word */ + orr r3, r3, r3, lsl #16 + + /* We know we have at least 4 bytes ... */ + + cmp r2, #0x00000020 /* If less than 32 then use words */ + blt Lmemset_lessthan32 + + /* We have at least 32 so lets use quad words */ + + stmfd sp!, {r4-r6} /* Store registers */ + mov r4, r3 /* Duplicate data */ + mov r5, r3 + mov r6, r3 + +Lmemset_loop16: + stmia r0!, {r3-r6} /* Store 16 bytes */ + sub r2, r2, #0x00000010 /* Adjust count */ + cmp r2, #0x00000010 /* Still got at least 16 bytes ? */ + bgt Lmemset_loop16 + + ldmfd sp!, {r4-r6} /* Restore registers */ + + /* Do we need to set some words as well ? */ + + cmp r2, #0x00000004 + blt Lmemset_lessthanfour + + /* Have either less than 16 or less than 32 depending on route taken */ + +Lmemset_lessthan32: + + /* We have at least 4 bytes so copy as words */ + +Lmemset_loop4: + str r3, [r0], #0x0004 + sub r2, r2, #0x0004 + cmp r2, #0x00000004 + bge Lmemset_loop4 + +Lmemset_lessthanfour: + cmp r2, #0x00000000 + ldmeqfd sp!, {r0} +#ifdef __APCS_26__ + moveqs pc, lr /* Zero length so exit */ +#else + moveq pc, lr /* Zero length so exit */ +#endif + + cmp r2, #0x00000002 + strb r1, [r0], #0x0001 /* Set 1 byte */ + strgeb r1, [r0], #0x0001 /* Set another byte */ + strgtb r1, [r0], #0x0001 /* and a third */ + + ldmfd sp!, {r0} +#ifdef __APCS_26__ + movs pc, lr /* Exit */ +#else + mov pc, lr /* Exit */ +#endif |
