From: deraadt Date: Wed, 24 Apr 1996 11:08:22 +0000 (+0000) Subject: Initial import of arm32 port X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=94b3a3fc1df5e76e826fd619df4a7a9d62561f73;p=openbsd Initial import of arm32 port --- diff --git a/sys/arch/arm32/Makefile b/sys/arch/arm32/Makefile new file mode 100644 index 00000000000..4b3fb67f788 --- /dev/null +++ b/sys/arch/arm32/Makefile @@ -0,0 +1,32 @@ +# $NetBSD: Makefile,v 1.1 1996/01/31 23:14:53 mark Exp $ +# @(#)Makefile 7.3 (Berkeley) 6/9/91 + +# Makefile for arm32 tags file and boot blocks + +NOPROG= noprog +NOMAN= noman + +SUBDIR= + +TARM32= ../arm32/tags +SARM32= ../arm32/arm32/*.[ch] ../arm32/include/*.h ../arm32/dev/*.[ch] \ + ../arm32/podulebus/*.[ch] ../arm32/mainbus/*.[ch] +AARM32= ../arm32/arm32/*.s + +# Directories in which to place arm32 tags links +DARM32= dev mainbus podulebus include + +tags: + -ctags -dtf ${TARM32} ${COMM} ${SARM32} + egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AARM32} | \ + sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \ + >> ${TARM32} + sort -o ${TARM32} ${TARM32} + +links: + -for i in ${DARM32}; do \ + cd $$i && rm -f tags; ln -s ../tags tags; done + +obj: _SUBDIRUSE + +.include diff --git a/sys/arch/arm32/arm32/ast.c b/sys/arch/arm32/arm32/ast.c new file mode 100644 index 00000000000..62c87bd8dee --- /dev/null +++ b/sys/arch/arm32/arm32/ast.c @@ -0,0 +1,168 @@ +/* $NetBSD: ast.c,v 1.2 1996/03/08 18:54:55 mark 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 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 CONTRIBUTERS 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 + * + * ast.c + * + * Code to handle ast's and returns to user mode + * + * Created : 11/10/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int want_resched = 0; + +void +userret(p, pc, oticks) + register struct proc *p; + int pc; + u_quad_t oticks; +{ + int sig, s; + + if (p == NULL) + panic("userret: p=0 curproc=%08x", curproc); + +#ifdef DIAGNOSTIC + if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) { + traceback(); + panic("userret called in non SVC mode !"); + } + + if (current_spl_level != SPL_0) + printf("WARNING: (1) current spl level=%d\n", current_spl_level); +#endif + +/* take pending signals */ + + while ((sig = (CURSIG(p))) != 0) { + postsig(sig); + } + + p->p_priority = p->p_usrpri; + +/* + * Check for reschedule request + */ + + if (want_resched) { + /* + * Since we are curproc, a clock interrupt could + * change our priority without changing run queues + * (the running process is not kept on a run queue). + * If this happened after we setrunqueue ourselves but + * before we switch()'ed, we might not be on the queue + * indicated by our priority + */ + + s = splstatclock(); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + + mi_switch(); + + (void)splx(s); + while ((sig = (CURSIG(p))) != 0) { + postsig(sig); + } + } + +/* + * Not sure if this profiling bit is working yet ... Not been tested + */ + + 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 + if (current_spl_level != SPL_0) + printf("WARNING: (2) current spl level=%d\n", current_spl_level); +#endif +} + + +/* + * void ast(trapframe_t *frame) + * + * Handle asynchronous system traps. + * This is called from the irq handler to deliver signals + * and switch processes if required. + * userret() does all the signal delivery and process switching work + */ + +void +ast(frame) + trapframe_t *frame; +{ + register struct proc *p; + + cnt.v_trap++; + + if ((p = curproc) == 0) + p = &proc0; + if (&p->p_addr->u_pcb == 0) + panic("ast: nopcb!"); + + cnt.v_soft++; + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + ADDUPROF(p); + } +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 3); +#endif + + userret(p, frame->tf_pc, p->p_sticks); + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 3); +#endif +} + +/* End of ast.c */ diff --git a/sys/arch/arm32/arm32/autoconf.c b/sys/arch/arm32/arm32/autoconf.c new file mode 100644 index 00000000000..e70cb3177c2 --- /dev/null +++ b/sys/arch/arm32/arm32/autoconf.c @@ -0,0 +1,281 @@ +/* $NetBSD: autoconf.c,v 1.2 1996/03/06 23:11:36 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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 + * + * autoconf.c + * + * Autoconfiguration functions + * + * Created : 08/10/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "wdc.h" +#include "fdc.h" +#include "rd.h" +#include "sd.h" +#include "cd.h" +#include "wcd.h" + +extern dev_t rootdev; +extern dev_t swapdev; +extern dev_t dumpdev; +extern dev_t argdev; + +extern struct swdevt swdevt[]; + +extern char *boot_args; +extern int pmap_debug_level; + +char * strstr __P((char */*s1*/, char */*s2*/)); +long strtoul __P((const char *, char **, int)); + +/* Table major numbers for the device names, NULL terminated */ + +struct { + char *name; + dev_t dev; +} rootdevices[] = { +#if NWDC > 0 + { "wd", 0x10 }, +#endif +#if NFDC > 0 + { "fd", 0x11 }, +#endif +#if NRD > 0 + { "rd", 0x12 }, +#endif +#if NSD > 0 + { "sd", 0x18 }, +#endif +#if NCD > 0 + { "cd", 0x1a }, +#endif +#if NWCD > 0 + { "wcd", 0x14 }, +#endif + { NULL, 0x00 }, +}; + +/* Decode a device name to a major and minor number */ + +dev_t +get_device(name) + char *name; +{ + int loop; + int unit; + int part; + + if (strncmp(name, "/dev/", 5) == 0) + name += 5; + + for (loop = 0; rootdevices[loop].name; ++loop) { + if (strncmp(name, rootdevices[loop].name, + strlen(rootdevices[loop].name)) == 0) { + name += strlen(rootdevices[loop].name); + unit = name[0] - '0'; + part = name[1] - 'a'; + if (unit < 0 || unit > 9) + return(NODEV); + if (part < 0 || part > MAXPARTITIONS) + return(NODEV); + return(makedev(rootdevices[loop].dev, + unit * MAXPARTITIONS + part)); + } + } + return(NODEV); +} + + +/* Set the rootdev variable from the root specifier in the boot args */ + +void +set_root_device() +{ + char *ptr; + + if (boot_args) { + ptr = strstr(boot_args, "root="); + if (ptr) { + ptr += 5; + rootdev = get_device(ptr); + + if (pmap_debug_level >= 0) + printf("rootdev = %08x\n", rootdev); + } + } + + if (rootdev == NODEV) + panic("No root device specified in boot config\n"); +} + + +/* Set the swap devices from the swap specifiers in the boot ars */ + +void +set_swap_device() +{ + char *ptr; + int nswap = 0; + + if (boot_args) { + ptr = boot_args; + do { + ptr = strstr(ptr, "swap="); + if (ptr) { + ptr += 5; + swdevt[nswap].sw_dev = get_device(ptr); + + /* + * Remember the first swap device + */ + + if (nswap == 0) + swapdev = get_device(ptr); + ++nswap; + } + } while (ptr); + } +} + + +/* + * Configure swap space and related parameters. + */ + +void +swapconf() +{ + register struct swdevt *swp; + register int nblks; + int swapsize = -1; + char *ptr; + int maj; + int s; /* The spl stuff was here for debugging reaons */ + + /* + * Loop round all the defined swap device configuring them. + */ + + for (swp = swdevt; swp->sw_dev != NODEV; swp++) { + maj = major(swp->sw_dev); + if (maj > nblkdev) + break; + if (bdevsw[maj].d_psize) { + s = spltty(); + printf("swap dev %04x ", swp->sw_dev); + (void)splx(s); + if (swapsize == -1) + nblks = (*bdevsw[maj].d_psize)(swp->sw_dev); + else + nblks = swapsize; + s = spltty(); + if (nblks == -1) + printf("-> device not configured for swap\n"); + else + printf("-> %d bytes\n", nblks*DEV_BSIZE); + (void)splx(s); + if (nblks != -1 && + (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) + swp->sw_nblks = nblks; + swp->sw_nblks = ctod(dtoc(swp->sw_nblks)); + } + } +} + + +/* Set up the root and swap device numbers, configure the swap space and dump space */ + +void +set_boot_devs() +{ + set_root_device(); + set_swap_device(); + + if (swapdev == NODEV && minor(rootdev) < (MAXPARTITIONS - 2)) + swapdev = makedev(major(rootdev), minor(rootdev) + 1); + + dumpdev = swapdev; + argdev = swapdev; + swdevt[0].sw_dev = swapdev; + + swapconf(); + dumpconf(); +} + + +/* + * void configure() + * + * Configure all the root devices + * The root devices are expected to configure their own children + */ + +void +configure() +{ + +/* + * Loop round all the root devices configuring them. Configure failure + * is not expected for the root devices + */ + + config_rootfound("mainbus", NULL); + config_rootfound("podulebus", NULL); + +/* Debugging information */ + + printf("ipl_bio=%08x ipl_net=%08x ipl_tty=%08x ipl_clock=%08x ipl_imp=%08x\n", + irqmasks[IPL_BIO], irqmasks[IPL_NET], irqmasks[IPL_TTY], + irqmasks[IPL_CLOCK], irqmasks[IPL_IMP]); + +/* Time to start taking interrupts so lets open the flood gates .... */ + + (void)spl0(); +} + +/* End of autoconf.c */ diff --git a/sys/arch/arm32/arm32/bcopy.S b/sys/arch/arm32/arm32/bcopy.S new file mode 100644 index 00000000000..61bc76da171 --- /dev/null +++ b/sys/arch/arm32/arm32/bcopy.S @@ -0,0 +1,113 @@ +/* $NetBSD: bcopy.S,v 1.1 1996/01/31 23:15:12 mark 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 + * + * memset.S + * + * optimized memset function + * + * Created : 16/05/95 + * Last updated : 16/05/95 + * + * $Id: bcopy.S,v 1.1.1.1 1996/04/24 11:08:23 deraadt Exp $ + */ + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + .global _bcopy + .global _ovbcopy + +_bcopy: +_ovbcopy: + teq r2, #0x00000000 + moveq r0, #0x00000000 + moveq pc, lr + cmp r0, r1 + blt bcopy_back + +bcopy_loop: + ldrb r3, [r0], #0x0001 + strb r3, [r1], #0x0001 + subs r2, r2, #0x00000001 + bne bcopy_loop + + mov pc, r14 + +bcopy_back: + add r0, r0, r2 + add r1, r1, r2 + +bcopy_bloop: + ldrb r3, [r0, #-0x0001]! + strb r3, [r1, #-0x0001]! + subs r2, r2, #0x00000001 + bne bcopy_bloop + + mov pc, r14 + + + .global _memcpy + +_memcpy: + teq r2, #0x00000000 + moveq r0, #0x00000000 + moveq pc, lr + cmp r1, r0 + blt memcpy_back + +memcpy_loop: + ldrb r3, [r1], #0x0001 + strb r3, [r0], #0x0001 + subs r2, r2, #0x00000001 + bne memcpy_loop + + mov pc, r14 + +memcpy_back: + add r0, r0, r2 + add r1, r1, r2 + +memcpy_bloop: + ldrb r3, [r1, #-0x0001]! + strb r3, [r0, #-0x0001]! + subs r2, r2, #0x00000001 + bne memcpy_bloop + + mov pc, r14 diff --git a/sys/arch/arm32/arm32/bcopy_page.S b/sys/arch/arm32/arm32/bcopy_page.S new file mode 100644 index 00000000000..b445275205a --- /dev/null +++ b/sys/arch/arm32/arm32/bcopy_page.S @@ -0,0 +1,150 @@ +/* $NetBSD: bcopy_page.S,v 1.1 1996/01/31 23:15:17 mark Exp $ */ + +/* + * Copyright (c) 1995 Scott Stevens + * 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 Scott Stevens. + * 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. + * + * RiscBSD kernel project + * + * bcopy_page.S + * + * page optimised bcopy and bzero routines + * + * Created : 08/04/95 + * Last updated : 12/05/95 + * + * $Id: bcopy_page.S,v 1.1.1.1 1996/04/24 11:08:23 deraadt Exp $ + */ + +#include + +/* TODO: + * + * Use r2 as the counter so that r3-r10 can be used instead of r4-r11 + * This means r11 will not need to be pushed on the stack. + */ + +/* bcopy_page(src, dest) + * r0 - src + * r1 - dest + * number of bytes (NBPG) is a multiple of 512 + */ + + .global _bcopy_page +_bcopy_page: + mov r3, #(NBPG >> 9) + + STMFD r13!, {r4-r11, r14} + +loopcopy: + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + ldmia r0!, {r4-r11} + stmia r1!, {r4-r11} + + subs r3, r3, #1 + bgt loopcopy + + ldmfd r13!, {r4-r11, r15} + +/* bzero_page(dest) + * r0 - dest + * number of bytes is a multiple of 512 + */ + + .global _bzero_page +_bzero_page: + mov r3, #(NBPG >> 9) + + stmfd r13!, {r4-r11, r14} + + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0 + mov r8, #0 + mov r9, #0 + mov r10, #0 + mov r11, #0 + +loopzero: + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + stmia r0!, {r4-r11} + + subs r3, r3, #1 + bgt loopzero + + ldmfd r13!, {r4-r11, r15} diff --git a/sys/arch/arm32/arm32/bcopyinout.S b/sys/arch/arm32/arm32/bcopyinout.S new file mode 100644 index 00000000000..c047e519ed2 --- /dev/null +++ b/sys/arch/arm32/arm32/bcopyinout.S @@ -0,0 +1,132 @@ +/* $NetBSD: bcopyinout.S,v 1.3 1996/02/02 18:05:47 mycroft 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 + * + * bcopyinout.S + * + * optimized and fault protected copyinout function + * + * Created : 16/05/95 + * Last updated : 16/05/95 + * + * $Id: bcopyinout.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $ + */ + +#include "assym.h" +#include + +sp .req r13 +lr .req r14 +pc .req r15 + +.text +Lcurpcb: + .word _curpcb + +Lcurproc: + .word _curproc + +bcopyinoutfault: + mov r0, #0x00000000 + str r0, [r4, #PCB_ONFAULT] + mov r0, #EFAULT + ldmfd sp!, {r4} + mov pc, lr + +bcopyinoutpcbfault: + stmfd sp!, {lr} + mov r3, r1 + mov r1, r4 + add r0, pc, #bcopyinouttext - . - 8 + mov r2, r3 + ldr r3, Lcurproc + ldr r3, [r3] + bl _printf + mov r0, #EFAULT + ldmfd sp!, {lr} + ldmfd sp!, {r4} + mov pc, lr + +bcopyinouttext: + .asciz "Alert ! PCB = %08x during bcopyinout addr=%08x curproc=%08x\n" + + .align 0 + + .global _bcopyinout + +_bcopyinout: + teq r2, #0x00000000 + moveq r0, #0x000000000 + moveq pc,lr + + stmfd sp!, {r4} + ldr r4, Lcurpcb + ldr r4, [r4] + teq r4, #0x00000000 + beq bcopyinoutpcbfault + add r3, pc, #bcopyinoutfault - . - 8 + str r3, [r4, #PCB_ONFAULT] + + cmp r0, r1 + blt bcopy_back + +bcopy_loop: + ldrb r3, [r0], #0x0001 + strb r3, [r1], #0x0001 + subs r2, r2, #0x00000001 + bne bcopy_loop + + mov r0, #0x00000000 + str r0, [r4, #PCB_ONFAULT] + ldmfd sp!, {r4} + mov pc, lr + +bcopy_back: + add r0, r0, r2 + add r1, r1, r2 + +bcopy_bloop: + ldrb r3, [r0, #-0x0001]! + strb r3, [r1, #-0x0001]! + subs r2, r2, #0x00000001 + bne bcopy_bloop + + mov r0, #0x00000000 + str r0, [r4, #PCB_ONFAULT] + ldmfd sp!, {r4} + mov pc, r14 + diff --git a/sys/arch/arm32/arm32/blockio.S b/sys/arch/arm32/arm32/blockio.S new file mode 100644 index 00000000000..dfa0405cd29 --- /dev/null +++ b/sys/arch/arm32/arm32/blockio.S @@ -0,0 +1,312 @@ +/* $NetBSD: blockio.S,v 1.1 1996/01/31 23:15:22 mark 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 + * + * blockio.S + * + * optimised block read/write from/to IO routines. + * + * Created : 08/10/94 + * Last updated : 12/05/95 + * + * $Id: blockio.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $ + */ + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + + .global _insw +/* + * Reads short ints (16 bits) from an I/O address into a block of memory + * + * r0 = address to read from (IO) + * r1 = address to write to (memory) + * r2 = length + */ + +_insw: +/* Make sure that we have a positive length */ + cmp r2, #0x00000000 + movle pc, lr + +/* If the destination address and the size is word aligned, do it fast */ + + tst r2, #0x00000001 + tsteq r1, #0x00000003 + beq fastinsw + +/* Non aligned insw */ + +inswloop: + ldr r3, [r0] + strb r3, [r1], #0x0001 + mov r3, r3, lsr #8 + strb r3, [r1], #0x0001 + subs r2, r2, #0x00000001 + bgt inswloop + + mov pc, lr + +/* Word aligned insw */ + +fastinsw: + stmfd r13!, {r4} + +fastinswloop: + ldr r3, [r0, #0x0002] /* take advantage of nonaligned + * word accesses */ + ldr r4, [r0] + mov r3, r3, lsr #16 /* Put the two shorts together */ + orr r3, r3, r4, lsl #16 + str r3, [r1], #0x0004 /* Store */ + subs r2, r2, #0x00000002 /* Next */ + bgt fastinswloop + + ldmfd r13!, {r4} + + mov pc, lr + + + .global _outsw + +/* + * Writes short ints (16 bits) from a block of memory to an I/O address + * + * r0 = address to write to (IO) + * r1 = address to read from (memory) + * r2 = length + */ + +_outsw: +/* Make sure that we have a positive length */ + cmp r2, #0x00000000 + movle pc, lr + +#ifdef notyet + +/* + * The optimised routines have not been tested yet and I don't feel + * like testing the new write code on 2.8 Gig of valuable data. + * Need to wait until I hang another HD on my machine + */ + +/* If the destination address and the size is word aligned, do it fast */ + + tst r2, #0x00000001 + tsteq r1, #0x00000003 + beq fastoutsw +#endif + +/* Non aligned outsw */ + + stmfd sp!, {r4} + +outswloop: + ldrb r3, [r1], #0x0001 + ldrb r4, [r1], #0x0001 + orr r3, r3, r4, lsl #8 + orr r3, r3, r3, lsl #16 + str r3, [r0] + subs r2, r2, #0x00000001 + bgt outswloop + + ldmfd sp!, {r4} + + mov pc, lr + +#ifdef notyet +/* Word aligned outsw */ + +fastoutsw: + stmfd r13!, {r4} + +fastoutswloop: + ldr r3, [r1], #0x0004 + + mov r4, r3, lsl #16 + orr r4, r4, lsr #16 + str r4, [r0] + + mov r4, r3, lsr #16 + orr r4, r4, lsl #16 + str r4, [r0] + + subs r2, r2, #0x00000002 + bgt outswloop + + ldmfd sp!, {r4} + + mov pc, lr +#endif + + .global _insw16 +/* + * reads short ints (16 bits) from an I/O address into a block of memory + * with a length garenteed to be a multiple of 16 bytes + * with a word aligned destination address + * + * r0 = address to read from (IO) + * r1 = address to write to (memory) + * r2 = length + */ + +_insw16: +/* Make sure that we have a positive length */ + cmp r2, #0x00000000 + movle pc, lr + +/* If the destination address and the size is word aligned, do it fast */ + + tst r2, #0x0000000f + tsteq r1, #0x00000003 + + bne _insw + +/* Word aligned insw */ + + stmfd r13!, {r4-r7} + +insw16loop: + ldr r3, [r0, #0x0002] /* take advantage of nonaligned + * word accesses */ + ldr r7, [r0] + mov r3, r3, lsr #16 /* Put the two shorts together */ + orr r3, r3, r7, lsl #16 + + ldr r4, [r0, #0x0002] /* take advantage of nonaligned + * word accesses */ + ldr r7, [r0] + mov r4, r4, lsr #16 /* Put the two shorts together */ + orr r4, r4, r7, lsl #16 + + ldr r5, [r0, #0x0002] /* take advantage of nonaligned + * word accesses */ + ldr r7, [r0] + mov r5, r5, lsr #16 /* Put the two shorts together */ + orr r5, r5, r7, lsl #16 + + ldr r6, [r0, #0x0002] /* take advantage of nonaligned + * word accesses */ + ldr r7, [r0] + mov r6, r6, lsr #16 /* Put the two shorts together */ + orr r6, r6, r7, lsl #16 + + stmia r1!, {r3-r6} + subs r2, r2, #0x00000008 /* Next */ + bgt insw16loop + + ldmfd r13!, {r4-r7} + + mov pc, lr + + +#ifdef notyet +/* + * The optimised routines have not been tested yet and I don't feel + * like testing the new write code on 2.8 Gig of valuable data. + * Need to wait until I hang another HD on my machine + */ + .global _outsw16 +/* + * Writes short ints (16 bits) from a block of memory to an I/O address + * + * r0 = address to write to (IO) + * r1 = address to read from (memory) + * r2 = length + */ + +_outsw16: +/* Make sure that we have a positive length */ + cmp r2, #0x00000000 + movle pc, lr + +/* If the destination address and the size is word aligned, do it fast */ + + tst r2, #0x0000000f + tsteq r1, #0x00000003 + + bne _outsw + +/* Word aligned outsw */ + + stmfd r13!, {r4-r8} + +outsw16loop: + ldmia r1!, {r4-r8} + + mov r3, r4, lsl #16 + orr r3, r3, lsr #16 + str r3, [r0] + + mov r3, r4, lsr #16 + orr r3, r4, lsl #16 + str r3, [r0] + + mov r3, r5, lsl #16 + orr r3, r3, lsr #16 + str r3, [r0] + + mov r3, r5, lsr #16 + orr r3, r4, lsl #16 + str r3, [r0] + + mov r3, r6, lsl #16 + orr r3, r3, lsr #16 + str r3, [r0] + + mov r3, r6, lsr #16 + orr r3, r4, lsl #16 + str r3, [r0] + + mov r3, r7, lsl #16 + orr r3, r3, lsr #16 + str r3, [r0] + + mov r3, r7, lsr #16 + orr r3, r4, lsl #16 + str r3, [r0] + + subs r2, r2, #0x00000008 + bgt outsw16loop + + ldmfd sp!, {r4-r8} + + mov pc, lr +#endif diff --git a/sys/arch/arm32/arm32/clock.c b/sys/arch/arm32/arm32/clock.c new file mode 100644 index 00000000000..203830aee65 --- /dev/null +++ b/sys/arch/arm32/arm32/clock.c @@ -0,0 +1,394 @@ +/* $NetBSD: clock.c,v 1.4 1996/04/19 19:39:17 mark 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 + * + * clock.c + * + * Timer related machine specific code + * + * Created : 29/09/94 + */ + +/* Include header files */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define TIMER0_COUNT 20000 /* 100Hz */ +#define TIMER_FREQUENCY 20000000 /* 2MHz clock */ +#define TICKS_PER_MICROSECOND (TIMER_FREQUENCY / 10000000) + +static irqhandler_t clockirq; +static irqhandler_t statclockirq; + + +/* + * int clockhandler(struct clockframe *frame) + * + * Function called by timer 0 interrupts. This just calls + * hardclock(). Eventually the irqhandler can call hardclock() directly + * but for now we use this function so that we can debug IRQ's + */ + +int +clockhandler(frame) + struct clockframe *frame; +{ + hardclock(frame); + return(1); +} + + +/* + * int statclockhandler(struct clockframe *frame) + * + * Function called by timer 1 interrupts. This just calls + * statclock(). Eventually the irqhandler can call statclock() directly + * but for now we use this function so that we can debug IRQ's + */ + +int +statclockhandler(frame) + struct clockframe *frame; +{ + statclock(frame); + return(1); +} + + +/* + * void setstatclockrate(int hz) + * + * Set the stat clock rate. The stat clock uses timer1 + */ + +void +setstatclockrate(hz) + int hz; +{ + int count; + + count = TIMER_FREQUENCY / hz; + + printf("Setting statclock to %dHz (%d ticks)\n", hz, count); + + WriteByte(IOMD_T1LOW, (count >> 0) & 0xff); + WriteByte(IOMD_T1HIGH, (count >> 8) & 0xff); + +/* reload the counter */ + + WriteByte(IOMD_T1GO, 0); +} + + +/* + * void cpu_initclocks(void) + * + * Initialise the clocks. + * This sets up the two timers in the IOMD and installs the IRQ handlers + * + * NOTE: Currently only timer 0 is setup and the IRQ handler is not installed + */ + +void +cpu_initclocks() +{ +/* + * Load timer 0 with count down value + * This timer generates 100Hz interrupts for the system clock + */ + + printf("clock: hz=%d stathz = %d profhz = %d\n", hz, stathz, profhz); + + WriteByte(IOMD_T0LOW, (TIMER0_COUNT >> 0) & 0xff); + WriteByte(IOMD_T0HIGH, (TIMER0_COUNT >> 8) & 0xff); + +/* reload the counter */ + + WriteByte(IOMD_T0GO, 0); + + clockirq.ih_func = clockhandler; + clockirq.ih_arg = 0; + clockirq.ih_level = IPL_CLOCK; + clockirq.ih_name = "TMR0 hard clk"; + if (irq_claim(IRQ_TIMER0, &clockirq) == -1) + panic("Cannot installer timer 0 IRQ handler\n"); + + if (stathz) { + setstatclockrate(stathz); + + statclockirq.ih_func = statclockhandler; + statclockirq.ih_arg = 0; + statclockirq.ih_level = IPL_CLOCK; + if (irq_claim(IRQ_TIMER1, &clockirq) == -1) + panic("Cannot installer timer 1 IRQ handler\n"); + } +} + + +/* + * void microtime(struct timeval *tvp) + * + * Fill in the specified timeval struct with the current time + * accurate to the microsecond. + */ + +void +microtime(tvp) + struct timeval *tvp; +{ + int s; + int tm; + int deltatm; + static int oldtm; + static struct timeval oldtv; + + s = splhigh(); + +/* + * Latch the current value of the timer and then read it. This garentees + * an atmoic reading of the time. + */ + + WriteByte(IOMD_T0LATCH, 0); + tm = ReadByte(IOMD_T0LOW) + (ReadByte(IOMD_T0HIGH) << 8); + deltatm = tm - oldtm; + if (deltatm < 0) deltatm += TIMER0_COUNT; + if (deltatm < 0) { + printf("opps deltatm < 0 tm=%d oldtm=%d deltatm=%d\n", + tm, oldtm, deltatm); + } + oldtm = tm; + +/* Fill in the timeval struct */ + + *tvp = time; + tvp->tv_usec += (deltatm / TICKS_PER_MICROSECOND); + +/* Make sure the micro seconds don't overflow. */ + + while (tvp->tv_usec > 1000000) { + tvp->tv_usec -= 1000000; + ++tvp->tv_sec; + } + +/* Make sure the time has advanced. */ + + if (tvp->tv_sec == oldtv.tv_sec && + tvp->tv_usec <= oldtv.tv_usec) { + tvp->tv_usec = oldtv.tv_usec + 1; + if (tvp->tv_usec > 1000000) { + tvp->tv_usec -= 1000000; + ++tvp->tv_sec; + } + } + + + oldtv = *tvp; + (void)splx(s); +} + + +void +need_proftick(p) + struct proc *p; +{ +} + + +static inline int +yeartoday(year) + int year; +{ + return((year % 4) ? 365 : 366); +} + + +static int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +static int timeset = 0; + +#define SECPERDAY (24*60*60) +#define SECPERNYEAR (365*SECPERDAY) +#define SECPER4YEARS (4*SECPERNYEAR+SECPERDAY) +#define EPOCHYEAR 1970 + +/* + * Write back the time of day to the rtc + */ + +void +resettodr() +{ + int s; + time_t year, mon, day, hour, min, sec; + rtc_t rtc; + + if (!timeset) + return; + + sec = time.tv_sec; + year = (sec / SECPER4YEARS) * 4; + sec %= SECPER4YEARS; + + /* year now hold the number of years rounded down 4 */ + + while (sec > (yeartoday(EPOCHYEAR+year) * SECPERDAY)) { + sec -= yeartoday(EPOCHYEAR+year)*SECPERDAY; + year++; + } + + /* year is now a correct offset from the EPOCHYEAR */ + + year+=EPOCHYEAR; + mon=0; + if (yeartoday(year) == 366) + month[1]=29; + else + month[1]=28; + while ((sec/SECPERDAY) > month[mon]) { + sec -= month[mon]*SECPERDAY; + mon++; + } + + day = sec / SECPERDAY; + sec %= SECPERDAY; + hour = sec / 3600; + sec %= 3600; + min = sec / 60; + sec %= 60; + rtc.rtc_cen = year / 100; + rtc.rtc_year = year % 100; + rtc.rtc_mon = mon+1; + rtc.rtc_day = day+1; + rtc.rtc_hour = hour; + rtc.rtc_min = min; + rtc.rtc_sec = sec; + rtc.rtc_centi = + rtc.rtc_micro = 0; + +/* + printf("resettod: %d/%d/%d%d %d:%d:%d\n", rtc.rtc_day, + rtc.rtc_mon, rtc.rtc_cen, rtc.rtc_year, rtc.rtc_hour, + rtc.rtc_min, rtc.rtc_sec); +*/ + + s = splclock(); + rtc_write(&rtc); + (void)splx(s); +} + +/* + * Initialise the time of day register, based on the time base which is, e.g. + * from a filesystem. + */ + +void +inittodr(base) + time_t base; +{ + time_t n; + int i, days = 0; + int s; + int year; + rtc_t rtc; + +/* + * We ignore the suggested time for now and go for the RTC + * clock time stored in the CMOS RAM. + */ + + s = splclock(); + if (rtc_read(&rtc) == 0) { + (void)splx(s); + return; + } + + (void)splx(s); + + n = rtc.rtc_sec + 60 * rtc.rtc_min + 3600 * rtc.rtc_hour; + n += (rtc.rtc_day - 1) * 3600 * 24; + year = (rtc.rtc_year + rtc.rtc_cen * 100) - 1900; + + if (yeartoday(year) == 366) + month[1] = 29; + for (i = rtc.rtc_mon - 2; i >= 0; i--) + days += month[i]; + month[1] = 28; + + for (i = 70; i < year; i++) + days += yeartoday(i); + + n += days * 3600 * 24; + + n += tz.tz_minuteswest * 60; + if (tz.tz_dsttime) + n -= 3600; + + time.tv_sec = n; + time.tv_usec = 0; + +/* timeset is used to ensure the time is valid before a resettodr() */ + + timeset = 1; + +/* If the base was 0 then keep quiet */ + + if (base) { + printf("inittodr: %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 (n > base + 60) { + days = (n - base) / SECPERDAY; + printf("Clock has gained %d day%c %ld hours %ld minutes %ld secs\n", + days, ((days == 1) ? 0 : 's'), ((n - base) / 3600) % 24, + ((n - base) / 60) % 60, (n - base) % 60); + } + } +} + +/* End of clock.c */ diff --git a/sys/arch/arm32/arm32/conf.c b/sys/arch/arm32/arm32/conf.c new file mode 100644 index 00000000000..8262efdfbc4 --- /dev/null +++ b/sys/arch/arm32/arm32/conf.c @@ -0,0 +1,437 @@ +/* $NetBSD: conf.c,v 1.6 1996/04/19 19:40:29 mark 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 + * + * conf.c + * + * Character and Block Device configuration + * Console configuration + * + * Defines the structures cdevsw and constab + * + * Created : 17/09/94 + */ + +#include +#include +#include +#include +#include +#include +#include + +int ttselect __P((dev_t, int, struct proc *)); + +#ifndef LKM +#define lkmenodev enodev +#else +int lkmenodev(); +#endif + +#include "wdc.h" +bdev_decl(wd); +bdev_decl(sw); +#include "fdc.h" +bdev_decl(fd); +#include "rd.h" +bdev_decl(rd); +#include "sd.h" +bdev_decl(sd); +#include "st.h" +bdev_decl(st); +#include "cd.h" +bdev_decl(cd); +#include "vnd.h" +bdev_decl(vnd); +#include "ccd.h" +bdev_decl(ccd); +/* Temporary hack for ATAPI CDROM */ +#include "wcd.h" +bdev_decl(wcd); + +/* Block devices */ + +struct bdevsw bdevsw[] = { + bdev_lkm_dummy(), /* 0: */ + bdev_swap_init(1, sw), /* 1: swap pseudo-device */ + bdev_lkm_dummy(), /* 2: */ + bdev_lkm_dummy(), /* 3: */ + bdev_lkm_dummy(), /* 4: */ + bdev_lkm_dummy(), /* 5: */ + bdev_lkm_dummy(), /* 6: */ + bdev_lkm_dummy(), /* 7: */ + bdev_lkm_dummy(), /* 8: */ + bdev_lkm_dummy(), /* 9: */ + bdev_lkm_dummy(), /* 10: */ + bdev_lkm_dummy(), /* 11: */ + bdev_lkm_dummy(), /* 12: */ + bdev_lkm_dummy(), /* 13: */ + bdev_lkm_dummy(), /* 14: */ + bdev_lkm_dummy(), /* 15: */ + bdev_disk_init(NWDC, wd), /* 16: Internal IDE disk */ + bdev_disk_init(NFDC, fd), /* 17: floppy diskette */ + bdev_disk_init(NRD, rd), /* 18: ramdisk */ + bdev_disk_init(NVND,vnd), /* 19: vnode disk driver */ + bdev_disk_init(NWCD, wcd), /* 20: */ + bdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */ + bdev_lkm_dummy(), /* 22: */ + bdev_lkm_dummy(), /* 23: */ + bdev_disk_init(NSD,sd), /* 24: SCSI disk */ + bdev_tape_init(NST,st), /* 25: SCSI tape */ + bdev_disk_init(NCD,cd), /* 26: SCSI cdrom */ + bdev_lkm_dummy(), /* 27: */ + bdev_lkm_dummy(), /* 28: */ + bdev_lkm_dummy(), /* 29: */ + bdev_lkm_dummy(), /* 30: */ + bdev_lkm_dummy(), /* 31: */ + bdev_lkm_dummy(), /* 32: */ + bdev_lkm_dummy(), /* 33: */ + bdev_lkm_dummy(), /* 34: */ + bdev_lkm_dummy(), /* 35: */ + bdev_lkm_dummy(), /* 36: */ + bdev_lkm_dummy(), /* 37: */ + bdev_lkm_dummy(), /* 38: */ + bdev_lkm_dummy(), /* 39: */ + bdev_lkm_dummy(), /* 40: */ + bdev_lkm_dummy(), /* 41: */ + bdev_lkm_dummy(), /* 42: */ + bdev_lkm_dummy(), /* 43: */ + }; + +int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + + +/* Character device declarations */ + +/* open, close, read, write, ioctl, tty, mmap */ +#define cdev_physcon_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ + dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), 0 } + +/* open, close, write, ioctl */ +#define cdev_lpt_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, seltrue, (dev_type_mmap((*))) enodev, 0 } + +/* open, close, write, ioctl */ +#define cdev_beep_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, \ + 0, seltrue, (dev_type_mmap((*))) enodev, 0 } + +/* open, close, write, ioctl */ +#define cdev_kbd_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, \ + 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, 0 } + +/* open, close, write, ioctl */ +#define cdev_cpu_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, \ + 0, seltrue, (dev_type_mmap((*))) enodev, 0 } + +/* open, close, write, ioctl */ +#define cdev_vidcvid_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, \ + 0, seltrue, dev_init(c,n,mmap), 0 } + +/* open, close, write, ioctl */ +#define cdev_uk_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, \ + 0, seltrue, (dev_type_mmap((*))) enodev, 0 } + +/* open, close, read, ioctl */ +#define cdev_ss_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, seltrue, \ + (dev_type_mmap((*))) enodev } + +/* open, close, write, ioctl */ +#define cdev_iic_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, seltrue, (dev_type_mmap((*))) enodev, 0 } + +/* open, close, write, ioctl */ +#define cdev_rtc_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ + 0, seltrue, (dev_type_mmap((*))) enodev, 0 } + +cdev_decl(cn); +cdev_decl(ctty); +#include "vt.h" +cdev_decl(physcon); +cdev_decl(vidcvideo); +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); +cdev_decl(wd); +cdev_decl(sw); +#include "pty.h" +#define ptstty ptytty +#define ptsioctl ptyioctl +cdev_decl(pts); +#define ptctty ptytty +#define ptcioctl ptyioctl +cdev_decl(ptc); +cdev_decl(log); +#include "com.h" +cdev_decl(com); +#include "lpt.h" +cdev_decl(lpt); +cdev_decl(fd); +dev_decl(filedesc,open); +cdev_decl(rd); +#include "bpfilter.h" +cdev_decl(bpf); +cdev_decl(sd); +cdev_decl(st); +cdev_decl(cd); +#include "ch.h" +cdev_decl(ch); +#include "uk.h" +cdev_decl(uk); +#include "ss.h" +cdev_decl(ss); +#ifdef LKM +#define NLKM 1 +#else +#define NLKM 0 +#endif +cdev_decl(lkm); +#include "tun.h" +cdev_decl(tun); +cdev_decl(vnd); +cdev_decl(ccd); +#include "quadmouse.h" +cdev_decl(quadmouse); +#include "pms.h" +cdev_decl(pms); +#include "beep.h" +cdev_decl(beep); +#include "kbd.h" +cdev_decl(kbd); +#include "audio.h" +cdev_decl(audio); +#include "cpu.h" +cdev_decl(cpu); +#include "iic.h" +cdev_decl(iic); +#include "rtc.h" +cdev_decl(rtc); +/* Temporary hack for ATAPI CDROM */ +cdev_decl(wcd); + +/* Character devices */ + +struct cdevsw cdevsw[] = { + cdev_mm_init(1, mm), /* 0: /dev/{null,mem,kmem,...} */ + cdev_swap_init(1, sw), /* 1: /dev/drum (swap pseudo-device) */ + cdev_cn_init(1, cn), /* 2: virtual console */ + cdev_ctty_init(1,ctty), /* 3: controlling terminal */ + cdev_physcon_init(NVT, physcon), /* 4: RPC console */ + cdev_log_init(1,log), /* 5: /dev/klog */ + cdev_ptc_init(NPTY,ptc), /* 6: pseudo-tty master */ + cdev_tty_init(NPTY,pts), /* 7: pseudo-tty slave */ + cdev_lpt_init(NLPT,lpt), /* 8: parallel printer */ + cdev_mouse_init(NQUADMOUSE,quadmouse), /* 9: quadmouse driver */ + cdev_beep_init(NBEEP,beep), /* 10: simple beep device */ + cdev_kbd_init(NKBD,kbd), /* 11: kbd device */ + cdev_tty_init(NCOM,com), /* 12: serial port */ + cdev_lkm_dummy(), /* 13: */ + cdev_lkm_dummy(), /* 14: */ + cdev_lkm_dummy(), /* 15: */ + cdev_disk_init(NWDC, wd), /* 16: ST506/ESDI/IDE disk */ + cdev_disk_init(NFDC, fd), /* 17: floppy diskette */ + cdev_disk_init(NRD, rd), /* 18: ram disk driver */ + cdev_disk_init(NVND,vnd), /* 19: vnode disk driver */ + cdev_disk_init(NWCD, wcd), /* 20: */ + cdev_disk_init(NCCD,ccd), /* 21: concatenated disk driver */ + cdev_lkm_dummy(), /* 22: */ + cdev_lkm_dummy(), /* 23: */ + cdev_disk_init(NSD,sd), /* 24: SCSI disk */ + cdev_tape_init(NST,st), /* 25: SCSI tape */ + cdev_disk_init(NCD,cd), /* 26: SCSI CD-ROM */ + cdev_ch_init(NCH,ch), /* 27: SCSI autochanger */ + cdev_ch_init(NUK,uk), /* 28: SCSI unknown */ + cdev_ss_init(NSS,ss), /* 29: SCSI scanner */ + cdev_lkm_dummy(), /* 30: */ + cdev_lkm_dummy(), /* 31: */ + cdev_bpftun_init(NBPFILTER,bpf),/* 32: Berkeley packet filter */ + cdev_bpftun_init(NTUN,tun), /* 33: network tunnel */ + cdev_fd_init(1,filedesc), /* 34: file descriptor pseudo-device */ + cdev_lkm_init(NLKM,lkm), /* 35: loadable module driver */ + cdev_audio_init(NAUDIO,audio), /* 36: generic audio I/O */ + cdev_vidcvid_init(1,vidcvideo), /* 37: vidcvideo device */ + cdev_cpu_init(NCPU,cpu), /* 38: cpu device */ + cdev_lkm_dummy(), /* 39: */ + cdev_mouse_init(NPMS,pms), /* 40: PS2 mouse driver */ + cdev_lkm_dummy(), /* 41: */ + cdev_iic_init(NIIC, iic), /* 42: IIC bus driver */ + cdev_rtc_init(NRTC, rtc), /* 43: RTC driver */ +}; + +int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]); + +int mem_no = 0; /* major device number of memory special file */ + + +/* + * 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 */ 1, + /* 2 */ NODEV, + /* 3 */ NODEV, + /* 4 */ NODEV, + /* 5 */ NODEV, + /* 6 */ NODEV, + /* 7 */ NODEV, + /* 8 */ NODEV, + /* 9 */ NODEV, + /* 10 */ NODEV, + /* 11 */ NODEV, + /* 12 */ NODEV, + /* 13 */ NODEV, + /* 14 */ NODEV, + /* 15 */ NODEV, + /* 16 */ 16, + /* 17 */ 17, + /* 18 */ 18, + /* 19 */ 19, + /* 20 */ 20, + /* 21 */ 21, + /* 22 */ NODEV, + /* 23 */ NODEV, + /* 24 */ 24, + /* 25 */ 25, + /* 26 */ 26, + /* 27 */ NODEV, + /* 28 */ NODEV, + /* 29 */ NODEV, + /* 30 */ NODEV, + /* 31 */ NODEV, + /* 32 */ NODEV, + /* 33 */ NODEV, + /* 34 */ NODEV, + /* 35 */ NODEV, + /* 36 */ NODEV, + /* 37 */ NODEV, + /* 38 */ NODEV, + /* 39 */ NODEV, + /* 40 */ NODEV, + /* 41 */ NODEV, + /* 42 */ NODEV, + /* 43 */ NODEV, +}; + +/* + * 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))); +} + +/* + * This entire table could be autoconfig()ed but that would mean that + * the kernel's idea of the console would be out of sync with that of + * the standalone boot. I think it best that they both use the same + * known algorithm unless we see a pressing need otherwise. + */ + +#include + +cons_decl(rpcconsole); +cons_decl(com); + +struct consdev constab[] = { +#if (NVT + NRPC > 0) + cons_init(rpcconsole), +#endif + +/*#if (NCOM > 0) + cons_init(com), +#endif*/ + { 0 }, +}; + +/* End of conf.c */ diff --git a/sys/arch/arm32/arm32/coproc15.S b/sys/arch/arm32/arm32/coproc15.S new file mode 100644 index 00000000000..ceb3a0db8b5 --- /dev/null +++ b/sys/arch/arm32/arm32/coproc15.S @@ -0,0 +1,150 @@ +/* $NetBSD: coproc15.S,v 1.1 1996/01/31 23:15:33 mark 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 + * + * coproc15.S + * + * Manipulation of the CPU internal coprocessor #15 registers + * + * Created : 29/11/94 + * Last updated : 28/08/95 + * + * Based on arm/readcoproc15.S & arm/writecoproc15.S + * + * $Id: coproc15.S,v 1.1.1.1 1996/04/24 11:08:24 deraadt Exp $ + */ + +lr .req r14 +pc .req r15 + +.text +/* + * Functions to read the internal coprocessor registers + * + * Currently the only registers that can be read are + * r0 - CPU ID + * r5 - Fault status + * r6 - Fault address + * + * Eventually these should be inlined. + */ + + .global _cpu_id + +_cpu_id: + mrc 15, 0, r0, c0, c0, 0 + mov pc, lr + + .global _cpu_faultstatus + +_cpu_faultstatus: + mrc 15, 0, r0, c5, c0, 0 + mov pc, lr + + .global _cpu_faultaddress + +_cpu_faultaddress: + mrc 15, 0, r0, c6, c0, 0 + mov pc, lr + + +/* + * Functions to write the internal coprocessor registers + * + * + * Currently the only registers that can be write are + * r1 - CPU Control + * r2 - TTB + * r3 - Domain Access Control + * r5 - Flush TLB + * r6 - Purge TLB + * r7 - Flush IDC + * + * Eventually these should be inlined. + */ + + .global _cpu_control + +_cpu_control: + mcr 15, 0, r0, c1, c0, 0 + mov pc, lr + + .global _setttb + +_setttb: +/* We need to flush the cache as it uses virtual addresses that are about to change */ + mcr 15, 0, r0, c7, c0, 0 + +/* Write the TTB */ + mcr 15, 0, r0, c2, c0, 0 + +/* If we have updated the TTB we must flush the TLB */ + mcr 15, 0, r0, c5, c0, 0 + +/* For good measure we will flush the IDC as well - do we need this */ + mcr 15, 0, r0, c7, c0, 0 + +/* Make sure that pipeline is emptied */ + + mov r0, r0 + mov r0, r0 + + mov pc, lr + + .global _cpu_domains + +_cpu_domains: + mcr 15, 0, r0, c3, c0, 0 + mov pc, lr + + .global _tlbflush + +_tlbflush: + mcr 15, 0, r0, c5, c0, 0 + mov pc, lr + + .global _tlbpurge + +_tlbpurge: + mcr 15, 0, r0, c6, c0, 0 + mov pc, lr + + .global _idcflush + +_idcflush: + mcr 15, 0, r0, c7, c0, 0 + mov pc, lr diff --git a/sys/arch/arm32/arm32/copystr.S b/sys/arch/arm32/arm32/copystr.S new file mode 100644 index 00000000000..0c22370138f --- /dev/null +++ b/sys/arch/arm32/arm32/copystr.S @@ -0,0 +1,132 @@ +/* $NetBSD: copystr.S,v 1.4 1996/03/27 22:19:32 mark 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 + * + * copystr.S + * + * optimised and fault protected copystr function + * + * Created : 16/05/95 + */ + +#include "assym.h" +#include + +sp .req r13 +lr .req r14 +pc .req r15 + + .text +Lcurpcb: + .word _curpcb + +Lcurproc: + .word _curproc + +copystrfault: + mov r0, #0x00000000 + str r0, [r4, #PCB_ONFAULT] + mov r0, #EFAULT + ldmfd sp!, {r4-r6} + mov pc, lr + +copystrpcbfault: + stmfd sp!, {lr} + mov r3, r1 + mov r1, r4 + add r0, pc, #copystrtext - . - 8 + mov r2, r3 + ldr r3, Lcurproc + ldr r3, [r3] + bl _printf + + bl _traceback + + mov r0, #EFAULT + ldmfd sp!, {lr} + ldmfd sp!, {r4-r6} + mov pc, lr + +copystrtext: + .asciz "Alert ! PCB = %08x during copystr addr=%08x curproc=%08x\n" + + .align 0 + +/* + * r0 - from + * r1 - to + * r2 - maxlens + * r3 - lencopied + */ + + .global _copystrinout + +_copystrinout: + stmfd sp!, {r4-r6} + teq r2, #0x00000000 + moveq r5, #0x00000000 + moveq r6, #0x00000000 + beq copystrexit + + ldr r4, Lcurpcb + ldr r4, [r4] + teq r4, #0x00000000 + beq copystrpcbfault + add r5, pc, #copystrfault - . - 8 + str r5, [r4, #PCB_ONFAULT] + mov r6, #0x00000000 + +copystr_loop: + ldrb r5, [r0], #0x0001 + strb r5, [r1], #0x0001 + add r6, r6, #0x00000001 + teq r5, #0x00000000 + teqne r6, r2 + bne copystr_loop + +copystrexit: + teq r3, #0x00000000 + strne r6, [r3] + + teq r5, #0x00000000 + moveq r0, #0x00000000 + movne r0, #ENAMETOOLONG + + mov r6, #0x00000000 + str r6, [r4, #PCB_ONFAULT] + ldmfd sp!, {r4-r6} + mov pc, lr diff --git a/sys/arch/arm32/arm32/cpuswitch.S b/sys/arch/arm32/arm32/cpuswitch.S new file mode 100644 index 00000000000..e40d6c5a643 --- /dev/null +++ b/sys/arch/arm32/arm32/cpuswitch.S @@ -0,0 +1,786 @@ +/* $NetBSD: cpuswitch.S,v 1.6 1996/03/27 21:24:39 mark 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 + * + * cpu.S + * + * cpu switching functions + * + * Created : 15/10/94 + */ + +#include "assym.h" +#include +#include + +sp .req r13 +lr .req r14 +pc .req r15 + +/* + * PULLFRAME - macro to pull a trap frame from the stack in the current mode + * Since the current mode is used, the SVC R14 field is ignored. + */ + +#define PULLFRAME \ + ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ + msr spsr_all, r0; \ + add sp, sp, #(4*15); /* Adjust the stack pointer */ \ + ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ + add sp, sp, #0x00000004; /* Skip SVC R14 */ \ + ldr lr, [sp], #0x0004; /* Pull the return address */ + +/* + * setrunqueue() and remrq() + * + * Functions to add and remove a process for the run queue. + */ + + .text + +Lwhichqs: + .word _whichqs + +Lqs: + .word _qs + +/* + * On entry + * r0 = process + */ + + .global _setrunqueue +_setrunqueue: +/* + * Local register usage + * r0 = process + * r1 = queue + * r2 = &qs[queue] + * r3 = temp + * r4 = whichqs + */ + stmfd sp!, {r4} + +#ifdef DIAGNOSTIC + ldr r1, [r0, #(P_BACK)] + teq r1, #0x00000000 + bne Lsetrunqueue_erg + + ldr r1, [r0, #(P_WCHAN)] + teq r1, #0x00000000 + bne Lsetrunqueue_erg +#endif + +/* Get the priority of the queue */ + + ldrb r1, [r0, #(P_PRIORITY)] + mov r1, r1, lsr #2 + +/* Indicate that there is a process on this queue */ + + ldr r4, Lwhichqs + ldr r2, [r4] + mov r3, #0x00000001 + mov r3, r3, lsl r1 + orr r2, r2, r3 + str r2, [r4] + +/* Get the address of the queue */ + + ldr r2, Lqs + add r1, r2, r1, lsl # 3 + +/* Hook the process in */ + str r1, [r0, #(P_FORW)] + ldr r2, [r1, #(P_BACK)] + + str r0, [r1, #(P_BACK)] +#ifdef DIAGNOSTIC + teq r2, #0x00000000 + beq Lsetrunqueue_erg +#endif + str r0, [r2, #(P_FORW)] + str r2, [r0, #(P_BACK)] + + ldmfd sp!, {r4} + + mov pc, lr + +#ifdef DIAGNOSTIC +Lsetrunqueue_erg: + mov r2, r1 + mov r1, r0 + add r0, pc, #Ltext1 - . - 8 + bl _printf + + ldr r2, Lqs + ldr r1, [r2] + add r0, pc, #Ltext2 - . - 8 + b _panic + +Ltext1: + .asciz "setrunqueue : %08x %08x\n" +Ltext2: + .asciz "setrunqueue : [qs]=%08x qs=%08x\n" + .align 0 +#endif + +/* + * On entry + * r0 = process + */ + + .global _remrq +_remrq: + +/* + * Local register usage + * r0 = oldproc + * r1 = queue + * r2 = &qs[queue] + * r3 = scratch + * r4 = whichqs + */ + stmfd sp!, {r4} + +/* Get the priority of the queue */ + + ldrb r1, [r0, #(P_PRIORITY)] + mov r1, r1, lsr #2 + +/* Unhook the process */ + + ldr r2, [r0, #(P_FORW)] + ldr r3, [r0, #(P_BACK)] + + str r3, [r2, #(P_BACK)] + str r2, [r3, #(P_FORW)] + +/* If the queue is now empty clear the queue not empty flag */ + + teq r2, r3 + +/* This could be reworked to avoid the use of r4 */ + + ldreq r4, Lwhichqs + ldreq r2, [r4] + moveq r3, #0x00000001 + moveq r3, r3, lsl r1 + biceq r2, r2, r3 + streq r2, [r4] + +/* Remove the back pointer for the process */ + + mov r1, #0x00000000 + str r1, [r0, #(P_BACK)] + + ldmfd sp!, {r4} + + mov pc, lr + + +/* + * cpuswitch() + * + * preforms a process context switch. + * This function has several entry points + */ + + +Lcurproc: + .word _curproc + + .global _curpcb + +_curpcb: + .word 0x00000000 + +Lcurpcb: + .word _curpcb + +Lwant_resched: + .word _want_resched + + +/* + * Idle loop, exercised while waiting for a process to wake up. + */ + + .global _idle +_idle: +idle: + +/* Enable interrupts */ + + IRQenable + +#ifdef CPU_ARM7500 +/* ARM7500 has a suspend mode so use it ! [danny, does this work ? - mark] */ + + mov r7, #(IOMD_BASE) + orr r7, r7, #(IOMD_SUSPEND - IOMD_BASE) + mov r3, #0x00000001 + strb r3, [r7] +#endif + +/* Disable interrupts while we check for an active queue */ + + IRQdisable + ldr r7, Lwhichqs + ldr r3, [r7] + teq r3, #0x00000000 + bne sw1 + +/* All processes are still asleep so idle a while longer */ + + b idle + + +/* + * Find a new process to run, save the current context and + * load the new context + */ + + .global _cpu_switch +_cpu_switch: +/* + * Local register usage. Some of these registers are out of date. + * r1 = oldproc + * r2 = spl level + * r3 = whichqs + * r4 = queue + * r5 = &qs[queue] + * r6 = newproc + * r7 = scratch + */ + stmfd sp!, {r4-r7, lr} + +/* + * Get the current process and indicate that there is no longer a valid + * process (curproc = 0) + */ + + ldr r7, Lcurproc + ldr r1, [r7] + mov r0, #0x00000000 + str r0, [r7] + +/* Zero the pcb */ + + ldr r7, Lcurpcb + str r0, [r7] + +/* Lower the spl level to spl0 and get the current spl level. */ + + mov r7, r1 + +#ifdef spl0 + mov r0, #(SPL_0) + bl _splx +#else + bl _spl0 +#endif + +/* Push the old spl level onto the stack */ + + str r0, [sp, #-0x0004]! + + mov r1, r7 + +/* First phase : find a new process */ + +/* rem: r1 = old proc */ + +switch_search: + IRQdisable + +/* Do we have any active queues */ + + ldr r7, Lwhichqs + ldr r3, [r7] + +/* If not we must idle until we do. */ + + teq r3, #0x00000000 + beq idle + +sw1: +/* rem: r1 = old proc */ +/* rem: r3 = whichqs */ +/* rem: interrupts are disabled */ + +/* + * Paranoid debug time .... + * Is this overkill ? If we are not in SVC mode then things are + * very sick and will probably have already died. + */ + +#ifdef DIAGNOSTIC + mrs r4, cpsr_all + and r4, r4, #(PSR_MODE) + teq r4, #(PSR_SVC32_MODE) + beq switchmodeok + + add r0, pc, #switchpanic - . - 8 + mrs r1, cpsr_all + bl _panic + +switchpanic: + .asciz "Yikes! In cpu_switch() but not in SVC mode (%08x)\n" + .align 0 + +switchmodeok: +#endif + +/* + * We have found an active queue. Currently we do not know which queue + * is active just that one of them is. + * We must check each queue to find the active one. + * r3 contains a bit for each of the 32 queues. A one indicates that + * that the queue has something in it. + */ + +/* This ffs() type routine code be optimised */ + + mov r4, #0x00000000 + +findqueue: + mov r0, #0x00000001 + mov r0, r0, lsl r4 + + tst r3, r0 + addeq r4, r4, #0x00000001 + beq findqueue + +/* + * Ok we have found the active queue. The above code can never fail as + * we only get to it if r3 != 0 + * r4 contains the number of the first queue found with a process in it. + */ + +/* rem: r0 = bit mask of chosen queue (1 << r4) */ +/* rem: r1 = old proc */ +/* rem: r3 = whichqs */ +/* rem: r4 = queue number */ +/* rem: interrupts are disabled */ + +/* Get the address of the queue (&qs[queue]) */ + + ldr r5, Lqs + add r5, r5, r4, lsl #3 + +/* + * Get the process from the queue and place the next process in the queue + * at the head. This basically unlinks the process at the head of the queue. + */ + ldr r6, [r5, #(P_FORW)] + +/* rem: r6 = new process */ + + ldr r7, [r6, #(P_FORW)] + str r7, [r5, #(P_FORW)] + +/* + * Test to see if the queue is now empty. If the head of the queue points + * to the queue itself then there are no more processes in the queue. + * We can therefore clear the queue not empty flag held in r3. + */ + + teq r5, r7 + biceq r3, r3, r0 + +/* rem: r0 = bit mask of chosen queue (1 << r4) - NOT NEEDED AN MORE */ + +/* Fix the back pointer for the process now at the head of the queue. */ + + ldr r0, [r6, #(P_BACK)] + str r0, [r7, #(P_BACK)] + +/* Update the RAM copy of the queue not empty flags word. */ + + ldr r7, Lwhichqs + str r3, [r7] + +/* rem: r1 = old proc */ +/* rem: r3 = whichqs - NOT NEEDED ANY MORE */ +/* rem: r4 = queue number - NOT NEEDED ANY MORE */ +/* rem: r6 = new process */ +/* rem: interrupts are disabled */ + +/* Clear the want_resched flag */ + + mov r0, #0x00000000 + ldr r7, Lwant_resched + str r0, [r7] + +/* + * Clear the back pointer of the process we have removed from the head + * of the queue. The new process is isolated now. + */ + + mov r0, #0x00000000 + str r0, [r6, #(P_BACK)] + +/* We have a new curproc now so make a note it */ + + ldr r7, Lcurproc + str r6, [r7] + +/* Hook in a new pcb */ + + ldr r7, Lcurpcb + ldr r0, [r6, #(P_ADDR)] + str r0, [r7] + +/* At this point we can allow IRQ's again. */ + +/* + IRQenable + IRQdisable +*/ + +/* rem: r1 = old proc */ +/* rem: r6 = new process */ +/* rem: interrupts are disabled */ + +/* + * If the new process is the same as the process that called cpu_switch + * Then we do not need to save and restore any contexts. This means + * we can make a quick exit. + * The test is simple if curproc on entry (now in r1) is the same as the + * proc removed from the queue we can jump to the exit. + */ + + teq r1, r6 + beq switch_return + +/* + * If the curproc on entry to cpu_switch was zero then the process that + * called it was exiting. This means that we do not need to save the current + * context. Instead we can jump straight to restoring the context for + * the new process. + */ + + teq r1, #0x00000000 + beq switch_exited + +/* rem: r1 = old proc */ +/* rem: r6 = new process */ +/* rem: interrupts are disabled */ + +/* Stage two : Save old context */ + +/* Remember the old process in r0 */ + + mov r0, r1 + +/* Get the user structure for the old process. */ + + ldr r1, [r1, #(P_ADDR)] + +/* Save all the registers in the old process's pcb */ + + add r7, r1, #(PCB_R8) + stmia r7, {r8-r13} + +/* + * This can be optimised... We know we want to go from SVC32 mode to UND32 + * mode + */ + + mrs r3, cpsr_all + bic r2, r3, #(PSR_MODE) + orr r2, r2, #(PSR_UND32_MODE | I32_bit | F32_bit) + msr cpsr_all, r2 + + str sp, [r1, #(PCB_UND_SP)] + + msr cpsr_all, r3 /* Restore the old mode */ + +/* rem: r0 = old proc */ +/* rem: r0 = old pcb */ +/* rem: r6 = new process */ +/* rem: interrupts are disabled */ + +/* What else needs to be saved Only FPA stuff when that is supported */ + +/* Third phase : restore saved context */ + +switch_exited: + +/* At this point we need to kill IRQ's again. */ + + mrs r0, cpsr_all + orr r0, r0, #(I32_bit | F32_bit) + msr cpsr_all , r0 + +/* IRQdisable*/ + +/* Get the user structure for the new process in r1 */ + + ldr r1, [r6, #(P_ADDR)] + +/* Get the pagedir physical address for the process. */ + + ldr r0, [r1, #(PCB_PAGEDIR)] + +/* Switch the memory to the new process */ + +/* For good measure we will flush the IDC as well */ + mcr 15, 0, r0, c7, c0, 0 + +/* Write the TTB */ + mcr 15, 0, r0, c2, c0, 0 + +/* If we have updated the TTB we must flush the TLB */ + mcr 15, 0, r0, c5, c0, 0 + +/* For good measure we will flush the IDC as well */ + mcr 15, 0, r0, c7, c0, 0 + +/* Make sure that pipeline is emptied */ + mov r0, r0 + mov r0, r0 + +/* + * This can be optimised... We know we want to go from SVC32 mode to UND32 + * mode + */ + + mrs r3, cpsr_all + bic r2, r3, #(PSR_MODE) + orr r2, r2, #(PSR_UND32_MODE) + msr cpsr_all, r2 + + ldr sp, [r1, #(PCB_UND_SP)] + + msr cpsr_all, r3 /* Restore the old mode */ + +/* Restore all the save registers */ + + add r7, r1, #PCB_R8 + ldmia r7, {r8-r13} + +/* Remember the pcb currently in use */ + + ldr r7, Lcurpcb + str r1, [r7] + +/* We can enable interrupts again */ + +/* + IRQenable +*/ + +#ifdef ARMFPE + add r0, r1, #(USER_SIZE) & 0x00ff + add r0, r0, #(USER_SIZE) & 0xff00 + bl _arm_fpe_core_changecontext +#endif + +switch_return: + +/* We have a new curproc now so make a note it */ + +/* + ldr r7, Lcurproc + str r6, [r7] +*/ + +/* Get the spl level from the stack and update the current spl level */ + + ldr r0, [sp], #0x0004 + bl _splx + +/* IRQenable*/ + +/* cpu_switch returns the proc it switched to. */ + + mov r0, r6 + +/* + * Pull the registers that got pushed when either savectx or cpu_switch + * was called and return. + */ + ldmfd sp!, {r4-r7, pc} + +Lproc0: + .word _proc0 + +Lkernel_map: + .word _kernel_map + + + .global _switch_exit + +_switch_exit: + +/* + * r0 = proc + * r1 = proc0 + */ + + ldr r1, Lproc0 + +/* In case we fault */ + + mov r2, #0x00000000 + ldr r3, Lcurproc + str r2, [r3] + +/* ldr r3, Lcurpcb + str r2, [r3]*/ + +/* Switch to proc0 context */ + + IRQdisable + + ldr r2, [r1, #(P_ADDR)] + ldr r3, [r2, #(PCB_PAGEDIR)] + +/* For good measure we will flush the IDC as well */ + mcr 15, 0, r0, c7, c0, 0 + +/* Write the TTB */ + mcr 15, 0, r3, c2, c0, 0 + +/* If we have updated the TTB we must flush the TLB */ + mcr 15, 0, r0, c5, c0, 0 + +/* For good measure we will flush the IDC as well */ + mcr 15, 0, r0, c7, c0, 0 + +/* Make sure that pipeline is emptied */ + mov r0, r0 + mov r0, r0 + +/* Restore all the save registers */ + + add r7, r2, #PCB_R8 + ldmia r7, {r8-r13} + +/* This is not really needed ! */ +/* Yes it is for the su and fu routines */ + +/* ldr sp, [r2, #(PCB_SP)]*/ + ldr r3, Lcurpcb + str r2, [r3] + +/* IRQenable*/ + + str r0, [sp, #-0x0004]! + +/* Thoroughly nuke the old process's resources. */ + +/* This has to be done here, before we lose the pmap */ + + mov r1, #0x00000000 + add r2, r1, #NBPG + ldr r0, [r0, #(P_VMSPACE)] + add r0, r0, #(VM_PMAP) + bl _pmap_remove + ldr r0, [sp] + +/* + * Have to wait until we have switched to proc0 as the pmap gets released + * in vmspace_free() + */ + + ldr r0, [r0, #(P_VMSPACE)] + bl _vmspace_free + +/* This has to be done here */ + + mov r2, #(UPAGES << PGSHIFT) + ldr r0, [sp], #0x0004 + ldr r1, [r0, #(P_ADDR)] + ldr r0, Lkernel_map + ldr r0, [r0] + bl _kmem_free + +/* Paranoia */ + + mov r0, #0x00000000 + ldr r1, Lcurproc + str r0, [r1] + + ldr r1, Lproc0 + b switch_search + + +Lcurrent_spl_level: + .word _current_spl_level + + .global _savectx +_savectx: +/* + * r0 = pcb + */ + +/* Push registers.*/ + + stmfd sp!, {r4-r7, lr} + +/* Store all the registers in the process's pcb */ + + add r2, r0, #(PCB_R8) + stmia r2, {r8-r13} + +/* Pull the regs of the stack */ + + ldmfd sp!, {r4-r7, pc} + + + .global _proc_trampoline +_proc_trampoline: + add lr, pc, #(trampoline_return - . - 8) + mov r0, r5 + mov r1, sp + mov pc, r4 + +trampoline_return: +/* Kill irq's */ + + mrs r0, cpsr_all + orr r0, r0, #(I32_bit) + msr cpsr_all, r0 + + PULLFRAME + + movs pc, lr /* Exit */ + diff --git a/sys/arch/arm32/arm32/db_disasm.c b/sys/arch/arm32/arm32/db_disasm.c new file mode 100644 index 00000000000..7e7d8b9d075 --- /dev/null +++ b/sys/arch/arm32/arm32/db_disasm.c @@ -0,0 +1,558 @@ +/* $NetBSD: db_disasm.c,v 1.2 1996/03/06 22:46:37 mark 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. + * + * RiscBSD kernel project + * + * db_disasm.c + * + * Kernel disassembler + * + * Created : 10/02/96 + * + * Structured after the sparc/sparc/db_disasm.c by David S. Miller & + * Paul Kranenburg + * + * This code is not complete. Not all instructions are disassembled. + * Current LDF, STF, CDT and MSRF are not supported. + */ + +#include +#include +#include + +/* + * General instruction format + * + * insn[cc][mod] [operands] + * + * Those fields with an uppercase format code indicate that the field follows + * directly after the instruction before the separator i.e. they modify the instruction + * rather than just being an operand to the instruction. The only exception is the + * writeback flag which follows a operand. + * + * + * 2 - print Operand 2 of a data processing instrcution + * d - destination register (bits 12-15) + * n - n register (bits 16-19) + * s - s register (bits 8-11) + * o - indirect register rn (bits 16-19) (used by swap) + * m - m register (bits 0-4) + * a - address operand of ldr/str instruction + * l - register list for ldm/stm instruction + * f - 1st fp operand (register) (bits 12-14) + * g - 2nd fp operand (register) (bits 16-18) + * h - 3rd fp operand (register/immediate) (bits 0-4) + * b - branch address + * X - block transfer type + * c - comment field bits(0-23) + * p - saved or current status register + * B - byte transfer flag + * S - set status flag + * T - user mode transfer + * P - fp precision + * R - fp rounding + * w - writeback flag + * # - co-processor number + * y - co-processor data processing registers + * z - co-processor data transfer registers + */ + +struct arm32_insn { + u_int mask; + u_int pattern; + char* name; + char* format; +}; + +struct arm32_insn arm32_i[] = { + { 0x0f000000, 0x0f000000, "swi", "c" }, + { 0x0f000000, 0x0a000000, "b", "b" }, + { 0x0f000000, 0x0b000000, "bl", "b" }, + { 0x0fe000f0, 0x00000090, "mul", "Sdms" }, + { 0x0fe000f0, 0x00200090, "mla", "Sdmsn" }, + { 0x0e100000, 0x04000000, "str", "BTdaW" }, + { 0x0e100000, 0x04100000, "ldr", "BTdaW" }, + { 0x0c100010, 0x04000000, "str", "BTdaW" }, + { 0x0c100010, 0x04100000, "ldr", "BTdaW" }, + { 0x0e100000, 0x08000000, "stm", "XnWl" }, + { 0x0e100000, 0x08100000, "ldm", "XnWl" }, + { 0x0fb00ff0, 0x01000090, "swap", "Bdmo" }, + { 0x0fbf0fff, 0x010f0000, "mrs", "dp" }, + { 0x0dbffff0, 0x0129f000, "msr", "pm" }, + { 0x0dbffff0, 0x0128f000, "msrf", "pm" }, + { 0x0de00000, 0x00000000, "and", "Sdn2" }, + { 0x0de00000, 0x00200000, "eor", "Sdn2" }, + { 0x0de00000, 0x00400000, "sub", "Sdn2" }, + { 0x0de00000, 0x00600000, "rsb", "Sdn2" }, + { 0x0de00000, 0x00800000, "add", "Sdn2" }, + { 0x0de00000, 0x00a00000, "adc", "Sdn2" }, + { 0x0de00000, 0x00c00000, "sbc", "Sdn2" }, + { 0x0de00000, 0x00e00000, "rsc", "Sdn2" }, + { 0x0de00000, 0x01000000, "tst", "Sn2" }, + { 0x0de00000, 0x01200000, "teq", "Sn2" }, + { 0x0de00000, 0x01400000, "cmp", "Sn2" }, + { 0x0de00000, 0x01600000, "cmn", "Sn2" }, + { 0x0de00000, 0x01800000, "orr", "Sdn2" }, + { 0x0de00000, 0x01a00000, "mov", "Sd2" }, + { 0x0de00000, 0x01c00000, "bic", "Sdn2" }, + { 0x0de00000, 0x01e00000, "mvn", "Sd2" }, + { 0x0ff08f10, 0x0e000100, "adf", "PRfgh" }, + { 0x0ff08f10, 0x0e100100, "muf", "PRfgh" }, + { 0x0ff08f10, 0x0e200100, "suf", "PRfgh" }, + { 0x0ff08f10, 0x0e300100, "rsf", "PRfgh" }, + { 0x0ff08f10, 0x0e400100, "dvf", "PRfgh" }, + { 0x0ff08f10, 0x0e500100, "rdf", "PRfgh" }, + { 0x0ff08f10, 0x0e600100, "pow", "PRfgh" }, + { 0x0ff08f10, 0x0e700100, "rpw", "PRfgh" }, + { 0x0ff08f10, 0x0e800100, "rmf", "PRfgh" }, + { 0x0ff08f10, 0x0e900100, "fml", "PRfgh" }, + { 0x0ff08f10, 0x0ea00100, "fdv", "PRfgh" }, + { 0x0ff08f10, 0x0eb00100, "frd", "PRfgh" }, + { 0x0ff08f10, 0x0ec00100, "pol", "PRfgh" }, + { 0x0f008f10, 0x0e000100, "fpbop", "PRfgh" }, + { 0x0ff08f10, 0x0e008100, "mvf", "PRfh" }, + { 0x0ff08f10, 0x0e108100, "mnf", "PRfh" }, + { 0x0ff08f10, 0x0e208100, "abs", "PRfh" }, + { 0x0ff08f10, 0x0e308100, "rnd", "PRfh" }, + { 0x0ff08f10, 0x0e408100, "sqt", "PRfh" }, + { 0x0ff08f10, 0x0e508100, "log", "PRfh" }, + { 0x0ff08f10, 0x0e608100, "lgn", "PRfh" }, + { 0x0ff08f10, 0x0e708100, "exp", "PRfh" }, + { 0x0ff08f10, 0x0e808100, "sin", "PRfh" }, + { 0x0ff08f10, 0x0e908100, "cos", "PRfh" }, + { 0x0ff08f10, 0x0ea08100, "tan", "PRfh" }, + { 0x0ff08f10, 0x0eb08100, "asn", "PRfh" }, + { 0x0ff08f10, 0x0ec08100, "acs", "PRfh" }, + { 0x0ff08f10, 0x0ed08100, "atn", "PRfh" }, + { 0x0f008f10, 0x0e008100, "fpuop", "PRfh" }, + { 0x0e100f00, 0x0c000100, "stf", "P" }, + { 0x0e100f00, 0x0c100100, "ldf", "P" }, + { 0x0f100010, 0x0e000010, "mcr", "#z" }, + { 0x0f100010, 0x0e100010, "mrc", "#z" }, + { 0x0f000010, 0x0e000000, "cdp", "#y" }, + { 0x0e000000, 0x0c000000, "cdt", "#" }, + { 0x00000000, 0x00000000, NULL, NULL } +}; + +char *arm32_insn_conditions[] = { + "eq", + "ne", + "cs", + "cc", + "mi", + "pl", + "vs", + "vc", + "hi", + "ls", + "ge", + "lt", + "gt", + "le", + "", + "nv" +}; + +char *insn_block_transfers[] = { + "da", + "ia", + "db", + "ib" +}; + +char *insn_stack_block_transfers[] = { + "fa", + "ea", + "fd", + "fa" +}; + +char *op_shifts[] = { + "lsl", + "lsr", + "asr", + "ror" +}; + +char *insn_fpa_rounding[] = { + "", + "p", + "m", + "z" +}; + +char *insn_fpa_precision[] = { + "s", + "d", + "e", + "p" +}; + +char *insn_fpaconstants[] = { + "0.0", + "1.0", + "2.0", + "3.0", + "4.0", + "5.0", + "0.5", + "10.0" +}; + +#define insn_condition(x) arm32_insn_conditions[(x >> 28) & 0x0f] +#define insn_blktrans(x) insn_block_transfers[(x >> 23) & 3] +#define insn_stkblktrans(x) insn_stack_block_transfers[(x >> 23) & 3] +#define op2_shift(x) op_shifts[(x >> 5) & 3] +#define insn_fparnd(x) insn_fpa_rounding[(x >> 5) & 0x03] +#define insn_fpaprec(x) insn_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 3] +#define insn_fpaimm(x) insn_fpaconstants[x & 0x07] + +void db_register_shift __P((u_int insn)); +void db_print_reglist __P((u_int insn)); +void db_insn_ldrstr __P((u_int insn, u_int loc)); + + +vm_offset_t +db_disasm(loc, altfmt) + vm_offset_t loc; + boolean_t altfmt; +{ + struct arm32_insn* i_ptr = (struct arm32_insn *)&arm32_i; + + u_int insn; + int matchp; + int branch; + char* f_ptr, *cp; + int fmt; + + fmt = 0; + matchp = 0; + insn = db_get_value(loc, 4, 0); + +/* db_printf("loc=%08x insn=%08x : ", loc, insn);*/ +/* db_printf("loc=%08x : ", loc);*/ + + while (i_ptr->name) { + if ((insn & i_ptr->mask) == i_ptr->pattern) { + matchp = 1; + break; + } + i_ptr++; + } + + if (!matchp) { + db_printf("undefined\n"); + return(loc + 4); + } + + db_printf("%s%s", i_ptr->name, insn_condition(insn)); + + f_ptr = i_ptr->format; + + while (*f_ptr) { + switch (*f_ptr) { + case '2': + if (insn & 0x02000000) { + db_printf("#0x%08x", (insn & 0xff) << (((insn >> 7) & 0x1e))); + } else { + db_register_shift(insn); + } + break; + case 'd': + db_printf("r%d", ((insn >> 12) & 0x0f)); + break; + case 'n': + db_printf("r%d", ((insn >> 16) & 0x0f)); + break; + case 's': + db_printf("r%d", ((insn >> 8) & 0x0f)); + break; + case 'o': + db_printf("[r%d]", ((insn >> 16) & 0x0f)); + break; + case 'm': + db_printf("r%d", ((insn >> 0) & 0x0f)); + break; + case 'a': + db_insn_ldrstr(insn, loc); + break; + case 'l': + db_print_reglist(insn); + break; + case 'f': + db_printf("f%d", (insn >> 12) & 7); + break; + case 'g': + db_printf("f%d", (insn >> 16) & 7); + break; + case 'h': + if (insn & (1 << 3)) + db_printf("#%s", insn_fpaimm(insn)); + else + db_printf("f%d", insn & 7); + break; + case 'b': + branch = ((insn << 2) & 0x03ffffff); + if (branch & 0x02000000) + branch |= 0xfc000000; + db_printsym((db_addr_t)(loc + 8 + branch), + DB_STGY_ANY); + break; + case 'X': + db_printf("%s", insn_blktrans(insn)); + break; + case 'c': + db_printf("0x%08x", (insn & 0x00ffffff)); + break; + case 'p': + if (insn & 0x00400000) + db_printf("spsr"); + else + db_printf("cpsr"); + case 'B': + if (insn & 0x00400000) + db_printf("b"); + break; + case 'S': + if (insn & 0x00100000) + db_printf("s"); + break; + case 'T': + if ((insn & 0x01200000) == 0x00200000) + db_printf("t"); + break; + case 'P': + db_printf("%s", insn_fpaprec(insn)); + break; + case 'R': + db_printf("%s", insn_fparnd(insn)); + break; + case 'W': + if (insn & (1 << 21)) + db_printf("!"); + break; + case '#': + db_printf("CP #%d", (insn >> 8) & 0x0f); + break; + case 'y': + db_printf("%d, ", (insn >> 20) & 0x0f); + + db_printf("cr%d, cr%d, cr%d", (insn >> 12) & 0x0f, (insn >> 16) & 0x0f, + insn & 0x0f); + + db_printf(", %d", (insn >> 5) & 0x07); + break; + case 'z': + db_printf("%d, ", (insn >> 21) & 0x07); + db_printf("r%d, cr%d, cr%d", (insn >> 12) & 0x0f, (insn >> 16) & 0x0f, + insn & 0x0f); + + if (((insn >> 5) & 0x07) != 0) + db_printf(", %d", (insn >> 5) & 0x07); + break; + default: + db_printf("[%02x:c](unknown)", *f_ptr, *f_ptr); + break; + } + ++fmt; + if (*(f_ptr+1) > 'A' && *(f_ptr+1) < 'Z') + ++f_ptr; + else if (*(++f_ptr)) { + if (fmt == 1) + db_printf("\t"); + else + db_printf(", "); + } + }; + + db_printf("\n"); + + return(loc + 4); +} + + +void +db_register_shift(insn) + u_int insn; +{ + db_printf("r%d", (insn & 0x0f)); + if ((insn & 0x00000ff0) == 0) + ; + else if ((insn & 0x00000ff0) == 0x00000060) + db_printf(", RRX"); + else { + if (insn & 0x10) + db_printf(", %s r%d", op2_shift(insn), + (insn >> 8) & 0x0f); + else + db_printf(", %s #%d", op2_shift(insn), + (insn >> 7) & 0x1f); + } +} + + +void +db_print_reglist(insn) + u_int insn; +{ + int loop; + int start; + int comma; + + db_printf("{"); + start = -1; + comma = 0; + + for (loop = 0; loop < 17; ++loop) { + if (start != -1) { + if (!(insn & (1 << loop)) || loop == 16) { + if (comma) + db_printf(", "); + else + comma = 1; + if (start == loop - 1) + db_printf("r%d", start); + else + db_printf("r%d-r%d", start, loop - 1); + start = -1; + } + } else { + if (insn & (1 << loop)) + start = loop; + } + } + db_printf("}"); + + if (insn & (1 << 22)) + db_printf("^"); +} + +void +db_insn_ldrstr(insn, loc) + u_int insn; + u_int loc; +{ + if (((insn >> 16) & 0x0f) == 15 && (insn & (1 << 21)) == 0 + && (insn & (1 << 24)) != 0 && (insn & (1 << 25) == 0)) { + if (insn & 0x00800000) + loc += (insn & 0xffff); + else + loc -= (insn & 0xffff); + db_printsym((db_addr_t)(loc - 8), DB_STGY_ANY); + } else { + printf("[r%d", (insn >> 16) & 0x0f); + printf("%s, ", (insn & (1 << 24)) ? "" : "]"); + + if (!(insn & 0x00800000)) + printf("-"); + if (insn & (1 << 25)) + db_register_shift(insn); + else + printf("#0x%04x", insn & 0xfff); + if (insn & (1 << 24)) + printf("]"); + } +} + + + +#if 0 + +u_int instruction_msrf(u_int addr, u_int word) + { + printf("MSR%s\t", opcode_condition(word)); + + printf("%s_flg, ", (word & 0x00400000) ? "SPSR" : "CPSR"); + + if (word & 0x02000000) + printf("#0x%08x", (word & 0xff) << (32 - ((word >> 7) & 0x1e))); + else + printf("r%d", word &0x0f); + return(addr); + } + + +u_int instruction_cdt(u_int addr, u_int word) + { + printf("%s%s%s\t", (word & (1 << 20)) ? "LDC" : "STC", + opcode_condition(word), (word & (1 << 22)) ? "L" : ""); + + printf("CP #%d, cr%d, ", (word >> 8) & 0x0f, (word >> 12) & 0x0f); + + printf("[r%d", (word >> 16) & 0x0f); + + printf("%s, ", (word & (1 << 24)) ? "" : "]"); + + if (!(word & (1 << 23))) + printf("-"); + + printf("#0x%02x", word & 0xff); + + if (word & (1 << 24)) + printf("]"); + + if (word & (1 << 21)) + printf("!"); + + return(addr); + } + + +u_int instruction_ldfstf(u_int addr, u_int word) + { + printf("%s%s%s\t", (word & (1 << 20)) ? "LDF" : "STF", + opcode_condition(word), (word & (1 << 22)) ? "L" : ""); + + printf("f%d, [r%d", (word >> 12) & 0x07, (word >> 16) & 0x0f); + + printf("%s, ", (word & (1 << 24)) ? "" : "]"); + + if (!(word & (1 << 23))) + printf("-"); + + printf("#0x%03x", (word & 0xff) << 2); + + if (word & (1 << 24)) + printf("]"); + + if (word & (1 << 21)) + printf("!"); + + return(addr); + } + +#endif + +/* End of db_disasm.c */ diff --git a/sys/arch/arm32/arm32/db_interface.c b/sys/arch/arm32/arm32/db_interface.c new file mode 100644 index 00000000000..47c8b4e1cbf --- /dev/null +++ b/sys/arch/arm32/arm32/db_interface.c @@ -0,0 +1,288 @@ +/* $NetBSD: db_interface.c,v 1.5 1996/03/18 21:33:05 mark 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 + * 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 +#include +#include +#include /* just for boothowto */ +#include + +#include + +#include +#include +#include +#include +#include + +static int nil; + +int db_access_svc_sp __P((struct db_variable *, db_expr_t *, int)); + +struct db_variable db_regs[] = { + { "spsr", (int *)&DDB_TF->tf_spsr, FCN_NULL, }, + { "r0", (int *)&DDB_TF->tf_r0, FCN_NULL, }, + { "r1", (int *)&DDB_TF->tf_r1, FCN_NULL, }, + { "r2", (int *)&DDB_TF->tf_r2, FCN_NULL, }, + { "r3", (int *)&DDB_TF->tf_r3, FCN_NULL, }, + { "r4", (int *)&DDB_TF->tf_r4, FCN_NULL, }, + { "r5", (int *)&DDB_TF->tf_r5, FCN_NULL, }, + { "r6", (int *)&DDB_TF->tf_r6, FCN_NULL, }, + { "r7", (int *)&DDB_TF->tf_r7, FCN_NULL, }, + { "r8", (int *)&DDB_TF->tf_r8, FCN_NULL, }, + { "r9", (int *)&DDB_TF->tf_r9, FCN_NULL, }, + { "r10", (int *)&DDB_TF->tf_r10, FCN_NULL, }, + { "r11", (int *)&DDB_TF->tf_r11, FCN_NULL, }, + { "r12", (int *)&DDB_TF->tf_r12, FCN_NULL, }, + { "usr_sp", (int *)&DDB_TF->tf_usr_sp, FCN_NULL, }, + { "svc_sp", (int *)&nil, db_access_svc_sp, }, + { "usr_lr", (int *)&DDB_TF->tf_usr_lr, FCN_NULL, }, + { "svc_lr", (int *)&DDB_TF->tf_svc_lr, FCN_NULL, }, + { "pc", (int *)&DDB_TF->tf_pc, 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; + +int db_access_svc_sp(vp, valp, rw) + struct db_variable *vp; + db_expr_t *valp; + int rw; +{ + if(rw == DB_VAR_GET) + *valp = get_stackptr(PSR_SVC32_MODE); + return(0); +} + +#if 0 +extern char *trap_type[]; +#endif + +/* + * Received keyboard interrupt sequence. + */ +kdb_kbd_trap(tf) + struct trapframe *tf; +{ + if (db_active == 0 && (boothowto & RB_KDB)) { + printf("\n\nkernel: keyboard interrupt\n"); + kdb_trap(-1, tf); + } +} + +/* + * kdb_trap - field a TRACE or BPT trap + */ +kdb_trap(type, tf) + int type; + register struct trapframe *tf; +{ + +#if 0 + fb_unblank(); +#endif + + switch (type) { + case T_BREAKPOINT: /* breakpoint */ + case -1: /* keyboard interrupt */ + break; + default: + db_printf("kernel: trap"); + if (db_recover != 0) { + db_error("Faulted in DDB; continuing...\n"); + /*NOTREACHED*/ + } + } + + /* Should switch to kdb`s own stack here. */ + + ddb_regs.ddb_tf = *tf; + ddb_regs.ddb_tf.tf_pc -= 4; + + db_active++; + cnpollc(TRUE); + db_trap(type, 0/*code*/); + cnpollc(FALSE); + db_active--; + + *tf = ddb_regs.ddb_tf; + + return (1); +} + +/* + * Read bytes from kernel address space for debugger. + */ +void +db_read_bytes(addr, size, data) + vm_offset_t addr; + register int size; + register char *data; +{ + register char *src; + + src = (char *)addr; + while (--size >= 0) + *data++ = *src++; +} + +#define splpmap() splimp() + +static void +db_write_text(dst, ch) + unsigned char *dst; + int ch; +{ + pt_entry_t *ptep, pte, pteo; + int s; + vm_offset_t va; + + s = splpmap(); + va = (unsigned long)dst & (~PGOFSET); + ptep = vtopte(va); + + if ((*ptep & L2_MASK) == L2_INVAL) { + db_printf(" address 0x%x not a valid page\n", dst); + splx(s); + return; + } + + pteo = ReadWord(ptep); + pte = pteo | PT_AP(AP_KRW); + WriteWord(ptep, pte); + tlbflush(); + + *dst = (unsigned char)ch; + + WriteWord(ptep, pteo); + tlbflush(); + splx(s); +} + +/* + * Write bytes to kernel address space for debugger. + */ +void +db_write_bytes(addr, size, data) + vm_offset_t addr; + register int size; + register char *data; +{ + extern char etext[]; + register char *dst; + + dst = (char *)addr; + while (--size >= 0) { + if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS) && (dst < etext)) + db_write_text(dst, *data); + else + *dst = *data; + dst++, data++; + } +} + +void +Debugger() +{ + asm(".word 0xe7ffffff"); +} + +void db_show_vmstat_cmd __P((db_expr_t addr, int have_addr, db_expr_t count, char *modif)); +void db_show_fs_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)); + +struct db_command arm32_db_command_table[] = { + { "vmstat", db_show_vmstat_cmd, 0, NULL }, + { "fs", db_show_fs_cmd, 0, NULL }, + { "vnode", db_show_vnode_cmd, 0, NULL }, + { NULL, NULL, 0, NULL } +}; + +int +db_trapper(addr, inst, frame) + u_int addr; + u_int inst; + trapframe_t *frame; +{ +/* db_printf("db_trapper\n");*/ + kdb_trap(1, frame); + return(0); +} + +extern u_int esym; +extern u_int end; + +void +db_machine_init() +{ + struct exec *kernexec = (struct exec *)KERNEL_BASE; + u_int *ptr; + int len; + +/* + * The boot loader currently loads the kernel with the a.out header still attached. + */ + + if (kernexec->a_syms == 0) { + printf("[No symbol table]\n"); + } else { + esym = (int)&end + kernexec->a_syms + sizeof(int); + len = *((u_int *)esym); + esym += (len + (sizeof(u_int) - 1)) & ~(sizeof(u_int) - 1); + } + + install_coproc_handler(0, db_trapper); + db_machine_commands_install(arm32_db_command_table); +} + + +u_int +branch_taken(insn, pc, reg, db_regs) + u_int insn; + u_int pc; + u_int reg; + db_regs_t *db_regs; +{ + int branch; + + branch = ((insn << 2) & 0x03ffffff); + if (branch & 0x02000000) + branch |= 0xfc000000; + return(pc + 8 + branch); +} diff --git a/sys/arch/arm32/arm32/db_machdep.c b/sys/arch/arm32/arm32/db_machdep.c new file mode 100644 index 00000000000..ef013173ee6 --- /dev/null +++ b/sys/arch/arm32/arm32/db_machdep.c @@ -0,0 +1,163 @@ +/* $NetBSD: db_machdep.c,v 1.1 1996/03/06 23:08:36 mark 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 + * 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 +#include +#include +#include +#include + +#include +#include + +void +db_show_fs_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; +{ + struct vfsops **vfsp; + int s; + + s = splhigh(); + + db_printf("Registered filesystems (%d)\n", nvfssw); + + for (vfsp = &vfssw[0]; vfsp < &vfssw[nvfssw]; vfsp++) { + if (*vfsp == NULL) + continue; + db_printf(" %s\n", (*vfsp)->vfs_name); + } + (void)splx(s); +} + + +/* + * 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 %d, writecount %d, refcount %d,", + 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", 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; +{ + struct vmmeter sum; + + sum = cnt; + db_printf("%9u cpu context switches\n", sum.v_swtch); + db_printf("%9u device interrupts\n", sum.v_intr); + db_printf("%9u software interrupts\n", sum.v_soft); + db_printf("%9u traps\n", sum.v_trap); + db_printf("%9u system calls\n", sum.v_syscall); + db_printf("%9u total faults taken\n", sum.v_faults); + db_printf("%9u swap ins\n", sum.v_swpin); + db_printf("%9u swap outs\n", sum.v_swpout); + db_printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); + db_printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); + db_printf("%9u page ins\n", sum.v_pageins); + db_printf("%9u page outs\n", sum.v_pageouts); + db_printf("%9u pages paged in\n", sum.v_pgpgin); + db_printf("%9u pages paged out\n", sum.v_pgpgout); + db_printf("%9u pages reactivated\n", sum.v_reactivated); + db_printf("%9u intransit blocking page faults\n", sum.v_intrans); + db_printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); + db_printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); + db_printf("%9u pages examined by the clock daemon\n", sum.v_scan); + db_printf("%9u revolutions of the clock hand\n", sum.v_rev); + db_printf("%9u VM object cache lookups\n", sum.v_lookups); + db_printf("%9u VM object hits\n", sum.v_hits); + db_printf("%9u total VM faults taken\n", sum.v_vm_faults); + db_printf("%9u copy-on-write faults\n", sum.v_cow_faults); + db_printf("%9u pages freed by daemon\n", sum.v_dfree); + db_printf("%9u pages freed by exiting processes\n", sum.v_pfree); + db_printf("%9u pages free\n", sum.v_free_count); + db_printf("%9u pages wired down\n", sum.v_wire_count); + db_printf("%9u pages active\n", sum.v_active_count); + db_printf("%9u pages inactive\n", sum.v_inactive_count); + db_printf("%9u bytes per page\n", sum.v_page_size); +} diff --git a/sys/arch/arm32/arm32/db_trace.c b/sys/arch/arm32/arm32/db_trace.c new file mode 100644 index 00000000000..c44b4325a37 --- /dev/null +++ b/sys/arch/arm32/arm32/db_trace.c @@ -0,0 +1,101 @@ +/* $NetBSD: db_trace.c,v 1.2 1996/03/06 22:49:51 mark 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 + * 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 +#include +#include + +#include +#include + +#define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK) + +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; + boolean_t kernel_only = TRUE; + + { + register char c, *cp = modif; + while ((c = *cp++) != 0) + if (c == 'u') + kernel_only = FALSE; + } + + 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 + frame = (struct frame *)(addr - (sizeof(struct frame) - sizeof(u_int))); + + while (count--) { + int i; + db_expr_t offset; + db_sym_t sym; + 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_pc);*/ + + pc = frame->fr_pc; + if (!INKERNEL(pc)) + break; + + db_find_sym_and_offset(pc, &name, &offset); + if (name == NULL) + name = "?"; + + db_printf("%s(", name); + + /* + * Switch to next frame up + */ + frame = (struct frame *)(frame->fr_fp - (sizeof(struct frame) - sizeof(u_int))); + + db_printsym(pc, DB_STGY_PROC); + db_printf(")"); + db_printf("\n"); + if (frame == NULL) + break; + } +} diff --git a/sys/arch/arm32/arm32/debug.c b/sys/arch/arm32/arm32/debug.c new file mode 100644 index 00000000000..9654a893dde --- /dev/null +++ b/sys/arch/arm32/arm32/debug.c @@ -0,0 +1,251 @@ +/* $NetBSD: debug.c,v 1.2 1996/03/08 20:14:48 mark Exp $ */ + +/* + * Copyright (c) 1994 Melvin Tang-Richardson (Nut) + * Copyright (c) 1994 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 RiscBSD. + * 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 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 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. + * + * RiscBSD kernel project + * + * debug.c + * + * Debugging functions + * + * Created : 11/10/94 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +int +debug_count_processes_on_q(queue) + int queue; +{ + struct proc *lastproc, *queue_head; + int counter; + int s; + + counter = 0; + s = splhigh(); + queue_head=(struct proc *)&qs[queue]; + for (lastproc=qs[queue].ph_link;lastproc!=queue_head;lastproc=lastproc->p_forw) { + if (lastproc != queue_head) + printf("Process queue=%8x proc=%08x p_addr=%8x, comm=%s\n", + queue, (u_int) lastproc, (u_int) lastproc->p_addr, + lastproc->p_comm); + counter++; + } + (void)splx(s); + return(counter); +} + +void +debug_show_q_details() +{ + int counter=0; + int s; + + s = splhigh(); + for (counter=0; counter<32; counter++ ) + debug_count_processes_on_q(counter); + + if (whichqs == 0) + printf("queues empty\n"); + (void)splx(s); +} + +void +debug_show_all_procs(argc, argv) + int argc; + char *argv[]; +{ + int np; + struct proc *ap, *p, *pp; + int s; + + s = splhigh(); + + np = nprocs; + p = ap = (struct proc *)allproc.lh_first; + if (argc > 1) + printf(" pid proc addr map pcb pmap comm wchan\n"); + else + printf(" pid proc addr uid ppid pgrp flag stat comm cputime \n"); + while (--np >= 0) { + pp = p->p_pptr; + if (pp == 0) + pp = p; + if (p->p_stat) { + if (argc > 1) + printf("%5d %08x %08x %08x %08x %08x %12s ", + p->p_pid, (u_int) ap, (u_int)p->p_addr, + (u_int) p->p_vmspace, + (u_int) &p->p_addr->u_pcb, (p->p_vmspace ? (u_int)&p->p_vmspace->vm_pmap : 0), + ((p->p_comm == 0) ? "..." : p->p_comm)); + else + printf("%5d %08x %08x %5d %5d %5d %08x %d %12s %5u.%02d ", + p->p_pid, (u_int) ap, (u_int) p->p_addr, + p->p_cred->p_ruid, + pp->p_pid, p->p_pgrp->pg_id, p->p_flag, + p->p_stat, p->p_comm, + (u_int)p->p_rtime.tv_sec, + (u_int)p->p_rtime.tv_usec / 10000); + if (p->p_wchan && argc > 1) { + if (p->p_wmesg) + printf("%12s ", p->p_wmesg); + printf("%x", (u_int)p->p_wchan); + } + printf("\n"); + } + ap = p->p_list.le_next; + if (ap == 0 && np > 0) + ap = (struct proc*)zombproc.lh_first; + p = ap; + } + (void)splx(s); +} + + +void +debug_show_callout(argc, argv) + int argc; + char *argv[]; +{ + register struct callout *p1; + register int cum; + register int s; + register int t; + + s = splhigh(); + printf(" cum ticks func arg\n"); + for (cum = 0, p1 = calltodo.c_next; p1; p1 = p1->c_next) { + t = p1->c_time; + if (t > 0) + cum += t; + printf("%9d %9d %08x %08x\n", cum, t, (u_int) p1->c_func, + (u_int) p1->c_arg); + } + (void)splx(s); +} + +void +debug_show_fs(argc, argv) + int argc; + char *argv[]; +{ + struct vfsops **vfsp; + int s; + + s = splhigh(); + + printf("Registered filesystems (%d)\n", nvfssw); + + for (vfsp = &vfssw[0]; vfsp < &vfssw[nvfssw]; vfsp++) { + if (*vfsp == NULL) + continue; + printf(" %s\n", (*vfsp)->vfs_name); + } + (void)splx(s); +} + + +void +debug_show_vm_map(map, text) + vm_map_t map; + char *text; +{ + vm_map_entry_t mapentry; + int s; + + s = splhigh(); + + printf("vm_map dump : %s\n", text); + + mapentry = &map->header; + + do { + printf("vm_map_entry: start = %08x end = %08x\n", + (u_int) mapentry->start, (u_int) mapentry->end); + mapentry = mapentry->next; + } while (mapentry != &map->header); + (void)splx(s); +} + + +void +debug_show_pmap(pmap) + pmap_t pmap; +{ + u_int loop; + u_int loop1; + u_int start; + pt_entry_t *pt; + pd_entry_t *pd; + int s; + + s = splhigh(); + + pd = (pd_entry_t *)pmap; + + printf("pdir=%08x\n", (u_int) pd); + for (loop = 0; loop < 4096; ++loop) { + if (pd[loop] == 0) + continue; + printf("%08x : %08x\n", loop * 1024*1024, pd[loop]); + if ((pd[loop] & 0xff) == 0x11) { + pt = (pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + + loop * 1024); + loop1 = 0; + while (loop1 < 256) { + if (pt[loop1]) { + start = loop1; + ++loop1; + while (loop1 < 256 && pt[loop1]) + ++loop1; + printf(" %08x -> %08x\n", + loop * 1024*1024 + start * 4096, + loop * 1024*1024 + loop1 * 4096 - 1); + } + ++loop1; + } + } + } + (void)splx(s); +} + +/* End of debug.c */ diff --git a/sys/arch/arm32/arm32/disassem.c b/sys/arch/arm32/arm32/disassem.c new file mode 100644 index 00000000000..4ebddbd8975 --- /dev/null +++ b/sys/arch/arm32/arm32/disassem.c @@ -0,0 +1,650 @@ +/* $NetBSD: disassem.c,v 1.3 1996/03/16 00:13:09 thorpej 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 + * + * disassem.c + * + * Debug / Monitor disassembler + * + * Created : 09/10/94 + */ + +/* Include standard header files */ + +#include +#include + +/* Local header files */ + +#include + +typedef u_int (*instruction_decoder) (u_int addr, u_int word); + +typedef struct _opcodes { + u_int mask; + u_int pattern; + u_int colour; + instruction_decoder decoder; +} opcodes_struct; + +u_int instruction_swi(u_int addr, u_int word); +u_int instruction_branch(u_int addr, u_int word); +u_int instruction_mul(u_int addr, u_int word); +u_int instruction_mla(u_int addr, u_int word); +u_int instruction_ldrstr(u_int addr, u_int word); +u_int instruction_ldmstm(u_int addr, u_int word); +u_int instruction_dataproc(u_int addr, u_int word); +u_int instruction_swap(u_int addr, u_int word); +u_int instruction_mrs(u_int addr, u_int word); +u_int instruction_msr(u_int addr, u_int word); +u_int instruction_msrf(u_int addr, u_int word); +u_int instruction_mrcmcr(u_int addr, u_int word); +u_int instruction_cdp(u_int addr, u_int word); +u_int instruction_cdt(u_int addr, u_int word); +u_int instruction_fpabinop(u_int addr, u_int word); +u_int instruction_fpaunop(u_int addr, u_int word); +u_int instruction_ldfstf(u_int addr, u_int word); + +/* Declare global variables */ + +opcodes_struct opcodes[] = { + { 0x0f000000, 0x0f000000, 7, instruction_swi }, + { 0x0e000000, 0x0a000000, 7, instruction_branch }, + { 0x0fe000f0, 0x00000090, 7, instruction_mul }, + { 0x0fe000f0, 0x00200090, 7, instruction_mla }, + { 0x0e000000, 0x04000000, 7, instruction_ldrstr }, + { 0x0c000010, 0x04000000, 7, instruction_ldrstr }, + { 0x0e000000, 0x08000000, 6, instruction_ldmstm }, + { 0x0FB00FF0, 0x01000090, 7, instruction_swap }, + { 0x0FBF0FFF, 0x010F0000, 1, instruction_mrs }, + { 0x0DBFFFF0, 0x0129F000, 1, instruction_msr }, + { 0x0DBFFFF0, 0x0128F000, 1, instruction_msrf }, + { 0x0C000000, 0x00000000, 7, instruction_dataproc }, + { 0x0F008F10, 0x0E000100, 3, instruction_fpabinop }, + { 0x0F008F10, 0x0E008100, 3, instruction_fpaunop }, + { 0x0E000F00, 0x0C000100, 3, instruction_ldfstf }, + { 0x0F000010, 0x0E000010, 2, instruction_mrcmcr }, + { 0x0F000010, 0x0E000000, 2, instruction_cdp }, + { 0x0E000000, 0x0C000000, 2, instruction_cdt }, + { 0x00000000, 0x00000000, 0, NULL } +}; + +char *opcode_conditions[] = { + "EQ", + "NE", + "CS", + "CC", + "MI", + "PL", + "VS", + "VC", + "HI", + "LS", + "GE", + "LT", + "GT", + "LE", + "", + "NV" +}; + +char *opcode_data_procs[] = { + "AND", + "EOR", + "SUB", + "RSB", + "ADD", + "ADC", + "SBC", + "RSC", + "TST", + "TEQ", + "CMP", + "CMN", + "ORR", + "MOV", + "BIC", + "MVN" +}; + +char *opcode_shifts[] = { + "LSL", + "LSR", + "ASR", + "ROR" +}; + +char *opcode_block_transfers[] = { + "DA", + "IA", + "DB", + "IB" +}; + +char *opcode_stack_block_transfers[] = { + "FA", + "EA", + "FD", + "FA" +}; + +char *opcode_fpabinops[] = { + "ADF", + "MUF", + "SUF", + "RSF", + "DVF", + "RDF", + "POW", + "RPW", + "RMF", + "FML", + "FDV", + "FRD", + "POL", + "???", + "???", + "???", + "???" +}; + +char *opcode_fpaunops[] = { + "MVF", + "MNF", + "ABS", + "RND", + "SQT", + "LOG", + "LGN", + "EXP", + "SIN", + "COS", + "TAN", + "ASN", + "ACS", + "ATN", + "???", + "???", + "???" +}; + +char *opcode_fpaconstants[] = { + "0.0", + "1.0", + "2.0", + "3.0", + "4.0", + "5.0", + "0.5", + "10.0" +}; + +char *opcode_fpa_rounding[] = { + "", + "P", + "M", + "Z" +}; + +char *opcode_fpa_precision[] = { + "S", + "D", + "E", + "P" +}; + +#define opcode_condition(x) opcode_conditions[x >> 28] + +#define opcode_s(x) ((x & 0x00100000) ? "S" : "") + +#define opcode_b(x) ((x & 0x00400000) ? "B" : "") + +#define opcode_t(x) ((x & 0x01200000) == 0x00200000 ? "T" : "") + +#define opcode_dataproc(x) opcode_data_procs[(x >> 21) & 0x0f] + +#define opcode_shift(x) opcode_shifts[(x >> 5) & 3] + +#define opcode_blktrans(x) opcode_block_transfers[(x >> 23) & 3] + +#define opcode_stkblktrans(x) opcode_stack_block_transfers[(x >> 23) & 3] + +#define opcode_fpabinop(x) opcode_fpabinops[(x >> 20) & 0x0f] + +#define opcode_fpaunop(x) opcode_fpaunops[(x >> 20) & 0x0f] + +#define opcode_fpaimm(x) opcode_fpaconstants[x & 0x07] + +#define opcode_fparnd(x) opcode_fpa_rounding[(x >> 5) & 0x03] + +#define opcode_fpaprec(x) opcode_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 3] + +/* Declare external variables */ + +extern caddr_t shell_ident; + +/* Local function prototypes */ + +u_int disassemble(u_char *addr); + +/* Now for the main code */ + +void +printascii(byte) + int byte; +{ + if (byte < 0x20) + printf("\x1b[31m%c\x1b[0m", byte + '@'); + else if (byte == 0x7f) + printf("\x1b[31m?\x1b[0m"); + else + printf("%c", byte); +} + + +u_int disassemble(u_char *addr) + { + int loop; + u_int word; + u_int result = 0; + + printf("%08x : ", (u_int)addr); + + word = *((u_int *)addr); + + for (loop = 0; loop < 4; ++loop) + printascii(addr[loop]); + + printf(" : %08x : ", word); + + loop = 0; + + while (opcodes[loop].mask != 0) + { + if ((word & opcodes[loop].mask) == opcodes[loop].pattern) + { + printf("\x1b[3%dm", opcodes[loop].colour); + result = (*opcodes[loop].decoder)((u_int )addr, word); + printf("\x1b[0m"); + break; + } + ++loop; + } + + if (opcodes[loop].mask == 0) + printf("Undefined instruction"); + + printf("\n\r"); + return(result); + } + + +u_int instruction_swi(u_int addr, u_int word) + { + printf("SWI%s\t0x%08x", opcode_condition(word), (word & 0x00ffffff)); + return(addr); + } + + +u_int instruction_branch(u_int addr, u_int word) + { + u_int branch; + + branch = ((word << 2) & 0x03ffffff); + if (branch & 0x02000000) + branch |= 0xfc000000; + + branch += addr + 8; + + if (word & 0x01000000) + printf("BL%s\t0x%08x", opcode_condition(word), branch); + else + printf("B%s\t0x%08x", opcode_condition(word), branch); + + return(branch); + } + + +u_int instruction_mul(u_int addr, u_int word) + { + printf("MUL%s%s\t", opcode_condition(word), opcode_s(word)); + + printf("r%d, r%d, r%d", (word >> 16) & 0x0f, word & 0x0f, + (word >> 8) & 0x0f); + return(addr); + } + + +u_int instruction_mla(u_int addr, u_int word) + { + printf("MLA%s%s\t", opcode_condition(word), opcode_s(word)); + + printf("r%d, r%d, r%d, r%d", (word >> 16) & 0x0f, word & 0x0f, + (word >> 8) & 0x0f, (word >> 12) & 0x0f); + return(addr); + } + + +void register_shift(u_int word) + { + printf("r%d", (word & 0x0f)); + if ((word & 0x00000ff0) == 0) + ; + else if ((word & 0x00000ff0) == 0x00000060) + printf(", RRX"); + else + { + if (word & 0x10) + { + printf(", %s r%d", opcode_shift(word), (word >> 8) & 0x0f); + } + else + { + printf(", %s #%d", opcode_shift(word), (word >> 7) & 0x1f); + } + } + } + + +u_int instruction_ldrstr(u_int addr, u_int word) + { + printf("%s%s%s%s\t", (word & 0x00100000) ? "LDR" : "STR", + opcode_condition(word), opcode_b(word), opcode_t(word)); + + printf("r%d, ", (word >> 12) & 0x0f); + + if (((word >> 16) & 0x0f) == 16) + { +/* u_int location; + + location = addr + 8; + + addr = */ + } + else + { + printf("[r%d", (word >> 16) & 0x0f); + + printf("%s, ", (word & (1 << 24)) ? "" : "]"); + + if (!(word & 0x00800000)) + printf("-"); + + if (word & (1 << 25)) + register_shift(word); + else + printf("#0x%04x", word & 0xfff); + + if (word & (1 << 24)) + printf("]"); + + if (word & (1 << 21)) + printf("!"); + } + + return(addr); + } + + +u_int instruction_ldmstm(u_int addr, u_int word) + { + int loop; + int start; + + printf("%s%s%s\t", (word & 0x00100000) ? "LDM" : "STM", + opcode_condition(word), opcode_blktrans(word)); + + printf("r%d", (word >> 16) & 0x0f); + + if (word & (1 << 21)) + printf("!"); + + printf(", {"); + + start = -1; + + for (loop = 0; loop < 17; ++loop) + { + if (start != -1) + { + if (!(word & (1 << loop)) || loop == 16) + { + if (start == loop - 1) + printf("r%d, ", start); + else + printf("r%d-r%d, ", start, loop - 1); + start = -1; + } + } + else + { + if (word & (1 << loop)) + start = loop; + } + + } + printf("\x7f\x7f}"); + + if (word & (1 << 22)) + printf("^"); + return(addr); + } + + +u_int instruction_dataproc(u_int addr, u_int word) + { + if ((word & 0x01800000) == 0x01000000) + word = word & ~(1<<20); + + printf("%s%s%s\t", opcode_dataproc(word), opcode_condition(word), + opcode_s(word)); + + if ((word & 0x01800000) != 0x01000000) + printf("r%d, ", (word >> 12) & 0x0f); + + if ((word & 0x01a00000) != 0x01a00000) + printf("r%d, ", (word >> 16) & 0x0f); + + if (word & 0x02000000) + { + printf("#&%08x", (word & 0xff) << (((word >> 7) & 0x1e))); + } + else + { + register_shift(word); + } + return(addr); + } + + +u_int instruction_swap(u_int addr, u_int word) + { + printf("SWP%s%s\t", opcode_condition(word), opcode_b(word)); + + printf("r%d, r%d, [r%d]", (word >> 12) & 0x0f, (word & 0x0f), + (word >> 16) & 0x0f); + return(addr); + } + + +u_int instruction_mrs(u_int addr, u_int word) + { + printf("MRS%s\tr%d, ", opcode_condition(word), (word >> 12) & 0x0f); + + printf("%s", (word & 0x00400000) ? "SPSR" : "CPSR"); + return(addr); + } + + +u_int instruction_msr(u_int addr, u_int word) + { + printf("MSR%s\t", opcode_condition(word)); + + printf("%s, r%d", (word & 0x00400000) ? "SPSR" : "CPSR", word & 0x0f); + + return(addr); + } + + +u_int instruction_msrf(u_int addr, u_int word) + { + printf("MSR%s\t", opcode_condition(word)); + + printf("%s_flg, ", (word & 0x00400000) ? "SPSR" : "CPSR"); + + if (word & 0x02000000) + printf("#0x%08x", (word & 0xff) << (32 - ((word >> 7) & 0x1e))); + else + printf("r%d", word &0x0f); + return(addr); + } + + +u_int instruction_mrcmcr(u_int addr, u_int word) + { + printf("%s%s\t", (word & (1 << 20)) ? "MRC" : "MCR", + opcode_condition(word)); + + printf("CP #%d, %d, ", (word >> 8) & 0x0f, (word >> 21) & 0x07); + + printf("r%d, cr%d, cr%d", (word >> 12) & 0x0f, (word >> 16) & 0x0f, + word & 0x0f); + + if (((word >> 5) & 0x07) != 0) + printf(", %d", (word >> 5) & 0x07); + + return(addr); + } + + +u_int instruction_cdp(u_int addr, u_int word) + { + printf("CDP%s\t", opcode_condition(word)); + + printf("CP #%d, %d, ", (word >> 8) & 0x0f, (word >> 20) & 0x0f); + + printf("cr%d, cr%d, cr%d", (word >> 12) & 0x0f, (word >> 16) & 0x0f, + word & 0x0f); + + printf(", %d", (word >> 5) & 0x07); + + return(addr); + } + + +u_int instruction_cdt(u_int addr, u_int word) + { + printf("%s%s%s\t", (word & (1 << 20)) ? "LDC" : "STC", + opcode_condition(word), (word & (1 << 22)) ? "L" : ""); + + printf("CP #%d, cr%d, ", (word >> 8) & 0x0f, (word >> 12) & 0x0f); + + printf("[r%d", (word >> 16) & 0x0f); + + printf("%s, ", (word & (1 << 24)) ? "" : "]"); + + if (!(word & (1 << 23))) + printf("-"); + + printf("#0x%02x", word & 0xff); + + if (word & (1 << 24)) + printf("]"); + + if (word & (1 << 21)) + printf("!"); + + return(addr); + } + + +u_int instruction_fpabinop(u_int addr, u_int word) + { + printf("%s%s%s%s\t", opcode_fpabinop(word), opcode_condition(word), + opcode_fpaprec(word), opcode_fparnd(word)); + + printf("f%d, f%d, ", (word >> 12) & 0x07, (word >> 16) & 0x07); + + if (word & (1 << 3)) + printf("#%s", opcode_fpaimm(word)); + else + printf("f%d", word & 0x07); + + return(addr); + } + + +u_int instruction_fpaunop(u_int addr, u_int word) + { + printf("%s%s%s%s\t", opcode_fpaunop(word), opcode_condition(word), + opcode_fpaprec(word), opcode_fparnd(word)); + + printf("f%d, ", (word >> 12) & 0x07); + + if (word & (1 << 3)) + printf("#%s", opcode_fpaimm(word)); + else + printf("f%d", word & 0x07); + + return(addr); + } + + +u_int instruction_ldfstf(u_int addr, u_int word) + { + printf("%s%s%s\t", (word & (1 << 20)) ? "LDF" : "STF", + opcode_condition(word), (word & (1 << 22)) ? "L" : ""); + + printf("f%d, [r%d", (word >> 12) & 0x07, (word >> 16) & 0x0f); + + printf("%s, ", (word & (1 << 24)) ? "" : "]"); + + if (!(word & (1 << 23))) + printf("-"); + + printf("#0x%03x", (word & 0xff) << 2); + + if (word & (1 << 24)) + printf("]"); + + if (word & (1 << 21)) + printf("!"); + + return(addr); + } + +/* End of disassem.c */ diff --git a/sys/arch/arm32/arm32/disksubr.c b/sys/arch/arm32/arm32/disksubr.c new file mode 100644 index 00000000000..d35dd1d69c5 --- /dev/null +++ b/sys/arch/arm32/arm32/disksubr.c @@ -0,0 +1,572 @@ +/* $NetBSD: disksubr.c,v 1.2 1996/03/06 22:43:11 mark Exp $ */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#define b_cylin b_resid + +/* int filecore_checksum(char *bootblock) + * + * Calculates the filecore boot block checksum. This is used to validate + * a filecore boot block on the disc. 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 disc is RiscBSD. + */ + +/* + * This can be coded better using add with carry but as it is used rarely + * there is not much point writing it in assembly. + */ + +u_int +filecore_checksum(bootblock) + u_char *bootblock; +{ + register u_int sum; + register u_int loop; + +/* A boot block of zero has a zero checksum - clever thinking Acorn, NOT ! */ + + sum = 0; + + for (loop = 0; loop < 512; ++loop) + sum += bootblock[loop]; + +/* If the whole block is zero then it is invalid */ + + if (sum == 0) return(0xffff); + + sum = 0; + + for (loop = 0; loop < 511; ++loop) { + sum += bootblock[loop]; + if (sum > 255) + sum -= 255; + } + + return(sum); +} + + +/* + * 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)(); + struct disklabel *lp; + struct cpu_disklabel *osdep; +{ + struct riscbsd_partition *rp = osdep->partitions; + struct dkbad *bdp = &osdep->bad; + register struct buf *bp; + struct disklabel *dlp; + char *msg = NULL; + int cyl, riscbsdpartoff, 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 riscbsd partitions in the process of getting disklabel? */ + + riscbsdpartoff = 0; + cyl = LABELSECTOR / lp->d_secpercyl; + + if (rp) { + struct filecore_bootblock *bb; + int heads; + int sectors; + +/* read the filecore boot block */ + +/* printf("readdisclabel: 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_cylin = bp->b_blkno / lp->d_secpercyl; + (*strat)(bp); + +/* if successful, validate boot block and locate parition table */ + + if (biowait(bp)) { + msg = "filecore boot block I/O error"; + goto done; + } + + 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 RiscBSD */ + +/* printf("readdisklabel: Invalid filecore boot block (incorrect checksum)\n");*/ + goto readlabel; + } + +/* 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 RiscBSD partition table ? */ + + if (bb->partition_type == PARTITION_FORMAT_RISCBSD) { +/* printf("heads = %d nsectors = %d\n", heads, sectors);*/ + + riscbsdpartoff = 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 */ + +/* Ok read the RISCiX partition table and see if there is a RiscBSD partition */ + + bp->b_blkno = cyl * heads * sectors; + printf("Found RiscIX partition table @ %08x\n", bp->b_blkno); + bp->b_cylin = 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; + } + + 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) { + riscbsdpartoff = rpt->partitions[loop].rp_start; + break; + } + } + if (loop == NRISCIX_PARTITIONS) { + msg = "RiscBSD partition identifier string not found."; + goto done; + } + } else { + msg = "Invalid partition format"; + goto done; + } + } + +/* next, dig out disk label */ + +readlabel: +/* printf("Reading disklabel addr=%08x\n", riscbsdpartoff * DEV_BSIZE);*/ + + bp->b_blkno = riscbsdpartoff + LABELSECTOR; + bp->b_cylin = 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 (bdp && (lp->d_flags & D_BADSECT)) { + 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_cylin = 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; +{ + register i; + register 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 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)(); + struct disklabel *lp; + struct cpu_disklabel *osdep; +{ + struct riscbsd_partition *rp = osdep->partitions; + register struct buf *bp; + struct disklabel *dlp; + int cyl, riscbsdpartoff; + int error = 0; + +/* get a buffer and initialize it */ + + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + +/* do riscbsd partitions in the process of getting disklabel? */ + + riscbsdpartoff = 0; + cyl = LABELSECTOR / lp->d_secpercyl; + + if (rp) { + struct filecore_bootblock *bb; + int heads; + int sectors; + +/* 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_cylin = bp->b_blkno / lp->d_secpercyl; + (*strat)(bp); + +/* if successful, validate boot block and locate parition table */ + + if (biowait(bp)) { + printf("writedisklabel: filecore boot block I/O error\n"); + goto done; + } + + 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 RiscBSD */ + + printf("writedisklabel: Invalid filecore boot block (incorrect checksum)\n"); + goto writelabel; + } + +/* Do we have a RiscBSD partition ? */ + + if (bb->partition_type != PARTITION_FORMAT_RISCBSD) { + printf("writedisklabel: Invalid partition format\n"); + goto done; + } + + cyl = bb->partition_cyl_low + (bb->partition_cyl_high << 8); + + heads = bb->heads; + sectors = bb->secspertrack; + + /*printf("heads = %d nsectors = %d\n", heads, sectors);*/ + + riscbsdpartoff = cyl * heads * sectors; + } + +writelabel: + +/* printf("writedisklabel: Reading disklabel addr=%08x\n", riscbsdpartoff * DEV_BSIZE);*/ + +/* next, dig out disk label */ + + bp->b_blkno = riscbsdpartoff + LABELSECTOR; + bp->b_cylin = 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_cylin = (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); +} + + +int +dk_establish(dk, dev) + struct dkdevice *dk; + struct device *dev; +{ + return(-1); +} + +/* End of disksubr.c */ diff --git a/sys/arch/arm32/arm32/exception.S b/sys/arch/arm32/arm32/exception.S new file mode 100644 index 00000000000..8e4783fd31c --- /dev/null +++ b/sys/arch/arm32/arm32/exception.S @@ -0,0 +1,340 @@ +/* $NetBSD: exception.S,v 1.5 1996/03/13 21:00:26 mark 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 + * + * exception.S + * + * Low level handlers for exception vectors + * + * Created : 24/09/94 + * + * Based on kate/display/abort.s + */ + +#include +#include "assym.h" + +/* + * PUSHFRAME - macro to push a trap frame on the stack in the current mode + * Since the current mode is used, the SVC R14 field is not defined. + */ + +#define PUSHFRAME \ + str lr, [sp, #-4]!; /* Push the return address */ \ + sub sp, sp, #0x00000004; /* Skip SVC R14 */ \ + stmdb sp, {r0-r14}^; /* Push the user mode registers */ \ + sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ + mrs r0, spsr_all; /* Put the SPSR on the stack */ \ + str r0, [sp, #-4]!; + +/* + * PULLFRAME - macro to pull a trap frame from the stack in the current mode + * Since the current mode is used, the SVC R14 field is ignored. + */ + +#define PULLFRAME \ + ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ + msr spsr_all, r0; \ + add sp, sp, #(4*15); /* Adjust the stack pointer */ \ + ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ + add sp, sp, #0x00000004; /* Skip SVC R14 */ \ + ldr lr, [sp], #0x0004; /* Pull the return address */ + +/* + * PUSHFRAMEINSVC - macro to push a trap frame on the stack in SVC32 mode + * This should only be used if the processor is not currently in SVC32 + * mode. The processor mode is switched to SVC mode and the trap frame is + * stored. The SVC R14 field is used to store the previous value of + * R14 in SVC mode. + */ + +#define PUSHFRAMEINSVC \ + stmdb sp, {r0-r3}; /* Save 4 registers */ \ + mov r0, lr; /* Save xxx32 r14 */ \ + mov r1, sp; /* Save xxx32 sp */ \ + mrs r3, spsr_all; /* Save xxx32 spsr */ \ + mrs r2, cpsr_all; /* Get the CPSR */ \ + bic r2, r2, #(PSR_MODE); /* Fix for SVC mode */ \ + orr r2, r2, #(PSR_SVC32_MODE); \ + msr cpsr_all, r2; /* Punch into SVC mode */ \ + str r0, [sp, #-4]!; /* Push return address */ \ + str lr, [sp, #-4]!; /* Push SVC r14 */ \ + msr spsr_all, r3; /* Restore correct spsr */ \ + ldmdb r1, {r0-r3}; /* Restore 4 regs from xxx mode */ \ + stmdb sp, {r0-r14}^; /* Push the user mode registers */ \ + sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ + mrs r0, spsr_all; /* Put the SPSR on the stack */ \ + str r0, [sp, #-4]! + +/* + * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack + * in SVC32 mode and restore the saved processor mode and PC. + * This should be used when the SVC R14 register needs to be restored on + * exit. + */ + +#define PULLFRAMEFROMSVCANDEXIT \ + ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ + msr spsr_all, r0; /* restore SPSR */ \ + add sp, sp, #(4*15); /* Adjust the stack pointer */ \ + ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ + ldmia sp!, {lr, pc}^ /* Restore lr and exit */ + +sp .req r13 +lr .req r14 +pc .req r15 + + .text + .align 0 + +/* entry point for CPU data abort */ + + .global data_abort_entry + +data_abort_entry: + sub lr, lr, #0x00000008 /* Adjust the lr */ + + PUSHFRAMEINSVC /* Push trap frame and switch */ + /* to SVC32 mode */ + + mov r0, sp /* pass the stack pointer as r0 */ + + add lr, pc, #Ldata_abort_return - . - 8 + ldr r1, Ldata_abort_handler_address + ldr pc, [r1] + +Ldata_abort_return: +#if 0 /* For now only handle ast's after interrupts */ + ldr r0, [sp] /* Get the SPSR from stack */ + and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the ABT */ + teq r0, #(PSR_USR32_MODE) + ldreq r0, Lastpending /* Do we have an AST pending ? */ + ldreq r1, [r0] + teqeq r1, #0x00000001 + moveq r1, #0x00000000 /* Clear it */ + streq r1, [r0] + + moveq r0, sp /* arg 0 = irq frame */ + bleq _ast /* call the AST handler */ +#endif + +/* Kill IRQ's */ + mrs r0, cpsr_all + orr r0, r0, #(I32_bit) + msr cpsr_all, r0 + + PULLFRAMEFROMSVCANDEXIT /* Restore the trap frame and exit */ + +Ldata_abort_handler_address: + .word _data_abort_handler_address + + .data + .global _data_abort_handler_address + +_data_abort_handler_address: + .word abortdata + + .text +abortdata: + add r0, pc, #abortdatamsg - . - 8 + b _panic + +abortdatamsg: + .asciz "abortdata" + .align 0 + + + .global prefetch_abort_entry + +prefetch_abort_entry: + sub lr, lr, #0x00000004 /* Adjust the lr */ + + PUSHFRAMEINSVC + + mov r0, sp /* pass the stack pointer as r0 */ + + add lr, pc, #Lprefetch_abort_return - . - 8 + ldr r1, Lprefetch_abort_handler_address + ldr pc, [r1] + +Lprefetch_abort_return: +#if 0 /* For the moment ast's are only handled by irq handler */ + ldr r0, [sp] /* Get the SPSR from stack */ + and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the IRQ */ + teq r0, #(PSR_USR32_MODE) + ldreq r0, Lastpending /* Do we have an AST pending ? */ + ldreq r1, [r0] + teqeq r1, #0x00000001 + moveq r1, #0x00000000 /* Clear it */ + streq r1, [r0] + + moveq r0, sp /* arg 0 = irq frame */ + bleq _ast /* call the AST handler */ +#endif + +/* Kill IRQ's */ + mrs r0, cpsr_all + orr r0, r0, #(I32_bit) + msr cpsr_all, r0 + + PULLFRAMEFROMSVCANDEXIT + +Lprefetch_abort_handler_address: + .word _prefetch_abort_handler_address + + .data + .global _prefetch_abort_handler_address + +_prefetch_abort_handler_address: + .word abortprefetch + + .text +abortprefetch: + add r0, pc, #abortprefetchmsg - . - 8 + b _panic + +abortprefetchmsg: + .asciz "abortprefetch" + .align 0 + + +/* + * swi_entry + * + * Main entry point for the SWI vector + */ + + .global swi_entry +swi_entry: + PUSHFRAME + + sub r0, lr, #0x00000004 /* Get the address of the SWI */ + ldr r4, [r0] /* Get the instruction */ + + bic r1, r4, #0xff000000 /* Extract the comment field */ + + mov r0, sp /* Pass the frame to any function */ + + bl _syscall /* It's a syscall ! */ + +#if 0 /* Ast's only from the irqhandler .... */ + ldr r0, Lastpending /* Do we have an AST pending ? */ + ldr r1, [r0] + teq r1, #0x00000001 + moveq r1, #0x00000000 /* Clear it */ + streq r1, [r0] + + moveq r0, sp /* arg 0 = irq frame */ + bleq _ast /* call the AST handler */ +#endif + +/* Kill irq's */ + + mrs r0, cpsr_all + orr r0, r0, #(I32_bit) + msr cpsr_all, r0 + + PULLFRAME + + movs pc, lr /* Exit */ + +Lastpending: + .word _astpending + + .text + .align 0 + +/* + * We indirect the undefined vector via the handler address + * in the data area. + * Entry to the undefined handler must look like direct + * entry from the vector. + */ + + .global undefined_entry +undefined_entry: + stmfd sp!, {r0, r1} + ldr r0, Lundefined_handler_indirection + ldr r1, [sp], #0x0004 + str r1, [r0, #0x0000] + ldr r1, [sp], #0x0004 + str r1, [r0, #0x0004] + ldmia r0, {r0, r1, pc} + +Lundefined_handler_indirection: + .word Lundefined_handler_indirection_data + +/* + * assembly bounce code for calling the kernel + * undefined instruction handler. This uses + * a standard trap frame and is called in SVC mode. + */ + + .global _undefinedinstruction_bounce +_undefinedinstruction_bounce: + PUSHFRAMEINSVC + mov r0, sp + bl _undefinedinstruction + +/* Kill irq's */ + mrs r0, cpsr_all + orr r0, r0, #(I32_bit) + msr cpsr_all, r0 + + PULLFRAMEFROMSVCANDEXIT + + + .data + .align 0 + +/* + * Indirection data + * 2 words use for preserving r0 and r1 + * 3rd word contains the undefined handler address. + */ + +Lundefined_handler_indirection_data: + .word 0 + .word 0 + + .global _undefined_handler_address +_undefined_handler_address: + .word _undefinedinstruction_bounce + +/* End of exception.S */ diff --git a/sys/arch/arm32/arm32/fault.c b/sys/arch/arm32/arm32/fault.c new file mode 100644 index 00000000000..c93f5c143df --- /dev/null +++ b/sys/arch/arm32/arm32/fault.c @@ -0,0 +1,1242 @@ +/* $NetBSD: fault.c,v 1.3 1996/03/13 21:41:41 mark 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 + * + * fault.c + * + * Fault handlers + * + * Created : 28/11/94 + */ + +/* + * Special compilation symbols + * + * DEBUG_FAULT_CORRECTION - Add debug code used to develop the register + * correction following a data abort. + * + * CONTINUE_AFTER_SVC_PREFETCH - Do not panic following a prefetch abort + * in SVC mode. Used during developement. + */ + +#define DEBUG_FAULT_CORRECTION +/*#define CONTINUE_AFTER_SVC_PREFETCH*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +extern int pmap_debug_level; +extern int nopagefault; +static int onfault_count = 0; +int nopagefault = 0; /* gross hack, has to go anyway */ + +int pmap_modified_emulation __P((pmap_t, vm_offset_t)); +int pmap_handled_emulation __P((pmap_t, vm_offset_t)); + +u_int disassemble __P((u_int)); +u_int ReadWordWithChecks __P((u_int, u_int *)); + +/* Abort code */ + +/* Define text descriptions of the different aborts */ + +static char *aborts[16] = { + "Write buffer fault", + "Alignment fault", + "Write buffer fault", + "Alignment fault", + "Bus error (LF section)", + "Translation fault (section)", + "Bus error (page)", + "Translation fault (page)", + "Bus error (section)", + "Domain error (section)", + "Bus error (page)", + "Domain error (page)", + "Bus error trans (L1)", + "Permission error (section)", + "Bus error trans (L2)", + "Permission error (page)" +}; + +/* + * void data_abort_handler(trapframe_t *frame) + * + * Abort handler called when read/write occurs at an address of + * a non existant or restricted (access permissions) memory page. + * We first need to identify the type of page fault. + */ + +void +data_abort_handler(frame) + trapframe_t *frame; +{ + struct proc *p; + struct pcb *pcb; + u_int fault_address; + u_int fault_status; + u_int fault_pc; + u_int fault_instruction; + u_int s; + int fault_code; + u_quad_t sticks; + int saved_lr; + +/* + * OK you did not see this :-) This is worse than your worst nightmare + * This bug was found when implementing LDR/STR late abort fixes + * Don't know why I did not spot it before. + * I really need to rethink the trapframe structure ... + */ + + if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { + +/* Ok an abort in SVC mode */ + +/* CHEAT CHEAT CHEAT - SHUT YOUR EYES NOW ! */ + +/* Copy the SVC r14 into the usr r14 - The usr r14 is garbage as the fault + * happened in svc mode but we need it in the usr slot so we can + * treat the registers as an array of ints during fixing. + * NOTE: This PC is in the position but writeback is not allowed on r15. + */ + saved_lr = frame->tf_usr_lr; + frame->tf_usr_lr = frame->tf_svc_lr; + +/* Note the trapframe does not have the SVC r13 so a fault from an + * instruction with writeback to r13 in SVC mode is not allowed. + * This should not happen as the kstack is always valid. + */ + } + + +/* + * Enable IRQ's and FIQ's (disabled by CPU on abort) if trapframe shows + * they were enabled. + */ + +#ifndef BLOCK_IRQS + if (!(frame->tf_spsr & I32_bit)) + enable_interrupts(I32_bit); +#endif + +/* Update vmmeter statistics */ + + cnt.v_trap++; + +/* Get fault address and status from the CPU */ + + fault_address = cpu_faultaddress(); + fault_status = cpu_faultstatus(); + fault_pc = frame->tf_pc; + + fault_instruction = ReadWord(fault_pc); + +/* More debug stuff */ + + s = splhigh(); + if (pmap_debug_level >= 0) { + printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n", + aborts[fault_status & 0xf], fault_status & 0xfff, + fault_address, fault_pc); + + printf("Instruction @V%08x = %08x\n", + fault_pc, fault_instruction); + } + +/* Decode the fault instruction and fix the registers as needed */ + +/* Was is a swap instruction ? */ + + if ((fault_instruction & 0x0fb00ff0) == 0x01000090) { + if (pmap_debug_level >= 0) { + printf("SWP\n"); + disassemble(fault_pc); + } + } else if ((fault_instruction & 0x0c000000) == 0x04000000) { + +/* Was is a ldr/str instruction */ + +#ifdef CPU_LATE_ABORT + +/* This is for late abort only */ + + int base; + int offset; + int *registers = &frame->tf_r0; +#endif + +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >= 0) { +/* printf("LDR/STR\n");*/ + disassemble(fault_pc); + } +#endif + +#ifdef CPU_LATE_ABORT + +/* This is for late abort only */ + + if ((fault_instruction & (1 << 24)) == 0 + || (fault_instruction & (1 << 21)) != 0) { + base = (fault_instruction >> 16) & 0x0f; + if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { + disassemble(fault_pc); + panic("Abort handler cannot fix this :-(\n"); + } + if (base == 15) { + disassemble(fault_pc); + panic("Abort handler cannot fix this :-(\n"); + } +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >=0) + printf("late abt fix: r%d=%08x ", base, registers[base]); +#endif + if ((fault_instruction & (1 << 25)) == 0) { +/* Immediate offset - easy */ + offset = fault_instruction & 0xfff; + if ((fault_instruction & (1 << 23))) + offset = -offset; + registers[base] += offset; +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >=0) + printf("imm=%08x ", offset); +#endif + } else { + int shift; + + offset = fault_instruction & 0x0f; + if (offset == base) { + disassemble(fault_pc); + panic("Abort handler cannot fix this :-(\n"); + } + +/* Register offset - hard we have to cope with shifts ! */ + offset = registers[offset]; + + if ((fault_instruction & (1 << 4)) == 0) + shift = (fault_instruction >> 7) & 0x1f; + else { + if ((fault_instruction & (1 << 7)) != 0) { + disassemble(fault_pc); + panic("Abort handler cannot fix this :-(\n"); + } + shift = ((fault_instruction >> 8) & 0xf); + if (base == shift) { + disassemble(fault_pc); + panic("Abort handler cannot fix this :-(\n"); + } +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >=0) + printf("shift reg=%d ", shift); +#endif + shift = registers[shift]; + } +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >=0) + printf("shift=%08x ", shift); +#endif + switch (((fault_instruction >> 5) & 0x3)) { + 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 */ + disassemble(fault_pc); + panic("Abort handler cannot fix this yet :-(\n"); + break; + } + +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >=0) + printf("abt: fixed LDR/STR with register offset\n"); +#endif + if ((fault_instruction & (1 << 23))) + offset = -offset; +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >=0) + printf("offset=%08x ", offset); +#endif + registers[base] += offset; + } +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >=0) + printf("r%d=%08x\n", base, registers[base]); +#endif + } +#endif + } + else if ((fault_instruction & 0x0e000000) == 0x08000000) { + int base; + int loop; + int count; + int *registers = &frame->tf_r0; + +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >= 0) { + printf("LDM/STM\n"); + disassemble(fault_pc); + } +#endif + if (fault_instruction & (1 << 21)) { +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >= 0) + printf("This instruction must be corrected\n"); +#endif + base = (fault_instruction >> 16) & 0x0f; + if (base == 15) { + disassemble(fault_pc); + panic("Abort handler cannot fix this :-(\n"); + } + count = 0; + for (loop = 0; loop < 16; ++loop) { + if (fault_instruction & (1<= 0) { + printf("%d registers used\n", count); + printf("Corrected r%d by %d bytes ", base, count * 4); + } +#endif + if (fault_instruction & (1 << 23)) { +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >= 0) + printf("down\n"); +#endif + registers[base] -= count * 4; + } else { +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >= 0) + printf("up\n"); +#endif + registers[base] += count * 4; + } + } + } else if ((fault_instruction & 0x0e000000) == 0x0c000000) { + int base; + int offset; + int *registers = &frame->tf_r0; + +/* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */ + +#ifdef DEBUG_FAULT_CORRECTION + if (pmap_debug_level >= 0) { + printf("LDC/STC\n"); + disassemble(fault_pc); + } +#endif + +/* Only need to fix registers if write back is turned on */ + + if ((fault_instruction & (1 << 21)) != 0) { + base = (fault_instruction >> 16) & 0x0f; + if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { + disassemble(fault_pc); + panic("Abort handler cannot fix this :-(\n"); + } + if (base == 15) { + disassemble(fault_pc); + panic("Abort handler cannot fix this :-(\n"); + } + + offset = (fault_instruction & 0xff) << 2; + if (pmap_debug_level >= 0) + printf("r%d=%08x\n", base, registers[base]); + if ((fault_instruction & (1 << 23)) != 0) + offset = -offset; + registers[base] += offset; + if (pmap_debug_level >= 0) + printf("r%d=%08x\n", base, registers[base]); + } + } else if ((fault_instruction & 0x0e000000) == 0x0c000000) { + disassemble(fault_pc); + panic("How did this happen ...\nWe have faulted on a non data transfer instruction"); + } + +/* + * OK you did not see this :-) This is worse than your worst nightmare + * This bug was found when implementing LDR/STR late abort fixes + * Don't know why I did not spot it before. + * I really need to rethink the trapframe structure ... + */ + + if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { + +/* Ok an abort in SVC mode */ + +/* CHEAT CHEAT CHEAT - SHUT YOUR EYES NOW ! */ + +/* Copy the SVC r14 into the usr r14 - The usr r14 is garbage as the fault + * happened in svc mode but we need it in the usr slot so we can + * treat the registers as an array of ints during fixing. + * NOTE: This PC is in the position but writeback is not allowed on r15. + */ + + frame->tf_svc_lr = frame->tf_usr_lr; + frame->tf_usr_lr = saved_lr; + +/* Note the trapframes does not have the SVC r13 so a fault from an + * instruction with writeback to r13 in SVC mode is not allowed. + * This should not happen as the kstack is always valid. + */ + } + + (void)splx(s); + +/* Extract the fault code from the fault status */ + + fault_code = fault_status & FAULT_TYPE_MASK; + +/* Get the current proc structure or proc0 if there is none */ + + if ((p = curproc) == 0) + p = &proc0; + + if (pmap_debug_level >= 0) + printf("fault in process %08x\n", (u_int)p); + +/* can't use curpcb, as it might be NULL; and we have p in a register anyway */ + + pcb = &p->p_addr->u_pcb; + if (pcb == 0) { + vm_offset_t va; + + va = trunc_page((vm_offset_t)fault_address); + if (pmap_handled_emulation(kernel_pmap, va)) + return; + if (pmap_modified_emulation(kernel_pmap, va)) + return; + panic("no pcb ... we're toast !\n"); + } + + if (pcb != curpcb) { + printf("data_abort: Alert ! pcb(%08x) != curpcb(%08x)\n", (u_int)pcb, + (u_int)curpcb); + printf("data_abort: Alert ! proc(%08x), curproc(%08x)\n", (u_int)p, + (u_int)curproc); + } + +/* fusubail is used by [fs]uswintr to avoid page faulting */ + +/* + * To get this correct I need to talk to the person coding the + * fubyte and subyte routines etc. + * There appear to be cases where a fault should be swallowed. + * The 386 does this by checking the error handler being used. + */ +/* + * Well it looks like I am doing this so I will talk to myself. + * Need to allow perm faults in case of modified bit emulation. + */ + + if (nopagefault != 0) + printf("fault occured with no_page_fault == %d\n", nopagefault); + + if (pcb->pcb_onfault + && ((fault_code != FAULT_TRANS_S && fault_code != FAULT_TRANS_P) +/* || pcb->pcb_onfault == fusubailout*/)) { +copyfault: + printf("Using pcb_onfault=%08x addr=%08x st=%08x\n", + (u_int)pcb->pcb_onfault, fault_address, fault_status); + frame->tf_pc = (u_int)pcb->pcb_onfault; + if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) + printf("Yikes pcb_onfault=%08x during USR mode fault\n", + (u_int)pcb->pcb_onfault); +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 1); +#endif + ++onfault_count; + if (onfault_count > 10) { + traceback(); + panic("Eaten by zombies\n"); + } + return; + } + +/* Were we in user mode when the abort occurred ? */ + + if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) { + sticks = p->p_sticks; + +/* Modify the fault_code to reflect the USR/SVC state at time of fault */ + + fault_code |= FAULT_USER; + p->p_md.md_regs = frame; + } + +/* Now act of the fault type */ + + switch (fault_code) { + case FAULT_WRTBUF_0 | FAULT_USER: /* Write Buffer Fault */ + case FAULT_WRTBUF_1 | FAULT_USER: /* Write Buffer Fault */ + case FAULT_WRTBUF_0: /* Write Buffer Fault */ + case FAULT_WRTBUF_1: /* Write Buffer Fault */ +/* If this happens forget it no point in continuing */ + + panic("Write Buffer Fault - Halting\n"); + break; + + case FAULT_ALIGN_0 | FAULT_USER: /* Alignment Fault */ + case FAULT_ALIGN_1 | FAULT_USER: /* Alignment Fault */ + case FAULT_ALIGN_0: /* Alignment Fault */ + case FAULT_ALIGN_1: /* Alignment Fault */ + +/* + * Really this should just kill the process. Alignment faults are turned + * off in the kernel in order to get better performance from shorts with + * GCC so an alignment fault means somebody has played with the control + * register in the CPU. Might as well panic as the kernel was not compiled + * for aligned accesses. + */ + panic("Alignment fault - Halting\n"); +/* trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/ + break; + + case FAULT_BUSERR_0 | FAULT_USER: /* Bus Error LF Section */ + case FAULT_BUSERR_1 | FAULT_USER: /* Bus Error Page */ + case FAULT_BUSERR_2 | FAULT_USER: /* Bus Error Section */ + case FAULT_BUSERR_3 | FAULT_USER: /* Bus Error Page */ + case FAULT_BUSERR_0: /* Bus Error LF Section */ + case FAULT_BUSERR_1: /* Bus Error Page */ + case FAULT_BUSERR_2: /* Bus Error Section */ + case FAULT_BUSERR_3: /* Bus Error Page */ + +/* What will accutally cause a bus error ? */ +/* Real bus errors are not a process problem but hardware */ + + panic("Bus Error - Halting\n"); +/* trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/ + break; + + case FAULT_DOMAIN_S | FAULT_USER: /* Section Domain Error Fault */ + case FAULT_DOMAIN_P | FAULT_USER: /* Page Domain Error Fault*/ + case FAULT_DOMAIN_S: /* Section Domain Error Fault */ + case FAULT_DOMAIN_P: /* Page Domain Error Fault*/ + +/* + * Right well we dont use domains, everything is always a client and thus + * subject to access permissions. + * If we get a domain error then we have corrupts PTE's so we might + * as well die ! + * I suppose eventually this should just kill the process who owns the + * PTE's but if this happens it implies a kernel problem. + */ + + panic("Domain Error - Halting\n"); +/* trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK);*/ + break; + + case FAULT_PERM_P: /* Page Permission Fault*/ + case FAULT_PERM_P | FAULT_USER: /* Page Permission Fault*/ +/* Ok we have a permission fault in user or kernel mode */ + { + register vm_offset_t va; + register struct vmspace *vm = p->p_vmspace; + register vm_map_t map; + int rv; + vm_prot_t ftype; + +/* + * Ok we have a permission fault in user mode. The only cause must be + * that a read only page has been written to. This may be genuine or it + * may be a bad access. In the future it may also be cause by the software + * emulation of the modified flag. + */ + + va = trunc_page((vm_offset_t)fault_address); + + if (pmap_debug_level >= 0) + printf("ok we have a page permission fault - addr=V%08x ", + (u_int)va); + +/* + * It is only a kernel address space fault iff: + * 1. (fault_code & FAULT_USER) == 0 and + * 2. pcb_onfault not set or + * 3. pcb_onfault set but supervisor space fault + * The last can occur during an exec() copyin where the + * argument space is lazy-allocated. + */ + + if ((fault_code & FAULT_USER) == 0 + && (va >= KERNEL_BASE || va <= VM_MIN_ADDRESS)) { + /* Was the fault due to the FPE ? */ + + if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) { + printf("FPE Data abort: '%s' status = %03x address = %08x PC = %08x\n", + aborts[fault_status & 0xf], fault_status & 0xfff, fault_address, + fault_pc); + postmortem(frame); + trapsignal(p, SIGBUS, FAULT_PERM_P); + goto out; + } + + printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n", + aborts[fault_status & 0xf], fault_status & 0xfff, fault_address, + fault_pc); + postmortem(frame); + panic("permission fault in kernel by kernel\n"); + } else + map = &vm->vm_map; + +#ifdef DIAGNOSTIC + if (va == 0 && map == kernel_map) { + printf("fault: bad kernel access at %x\n", (u_int)va); + goto we_re_toast; + } +#endif + + if (pmap_debug_level >= 0) + printf("vmmap=%08x ", (u_int)map); + +/* + * We need to know whether the page should be mapped as R or R/W. + * The MMU does not give us the info as to whether the fault was caused + * by a read or a write. This means we need to disassemble the instruction + * responcible and determine if it was a read or write instruction. + */ + + ftype = VM_PROT_READ; + + if ((fault_instruction & 0x0c100000) == 0x04000000) + ftype |= VM_PROT_WRITE; + else if ((fault_instruction & 0x0a100000) == 0x08000000) + ftype |= VM_PROT_WRITE; + else if ((fault_instruction & 0x0fb00ff0) == 0x01000090) + ftype |= VM_PROT_WRITE; + +/* if (!(ftype & VM_PROT_WRITE)) { + panic("permission fault on a read !\n"); + }*/ + + if (pmap_modified_emulation(map->pmap, va)) + goto out; + else { + +/* The page must be mapped to cause a permission fault. */ + + rv = vm_fault(map, va, ftype, FALSE); + if (pmap_debug_level >= 0) + printf("fault result=%d\n", rv); + if (rv == KERN_SUCCESS) + goto out; + printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n", + aborts[fault_status & 0xf], fault_status & 0xfff, fault_address, + fault_pc); + postmortem(frame); + trapsignal(p, (rv == KERN_PROTECTION_FAILURE) + ? SIGBUS : SIGSEGV, FAULT_PERM_P); + break; + } + } +/* panic("Page Permission Fault - Halting\n");*/ + break; + +#if 0 + case FAULT_PERM_P: /* Page Permission Fault is non USR mode */ + +/* + * Kernel permission faults should not happen. The kernel should never + * access memory it does not have permission for. Since the kernel has + * read access on all mapped pages it means the kernel has written to + * a read only kernel page. e.g. page 0 + * + * Erg: Major cock up time. The kernel can take permission faults during + * the emulation of FP instructions. How comes I have not hit this problem ? + * ok out with the superglue ... This condition needs to be integrated with + * the FAULT_PERM_P | FAULT_USER case similarly to FAULT_TRANS_P + */ + + printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n", + aborts[fault_status & 0xf], fault_status & 0xfff, fault_address, + fault_pc); + postmortem(frame); + panic("Page Permission Fault - (in SVC mode) Halting\n"); + break; +#endif + + case FAULT_PERM_S | FAULT_USER: /* Section Permission Fault */ +/* + * Section permission fault should not happen yet. + * However I have had this panic once so it can occor + * Yes they do ... Writing to -1 in user space does it ... + */ + printf("Data abort: '%s' status = %03x address = %08x PC = %08x\n", + aborts[fault_status & 0xf], fault_status & 0xfff, fault_address, + fault_pc); + disassemble(fault_pc); + postmortem(frame); + trapsignal(p, SIGBUS, FAULT_PERM_S); + break; + +/* panic("Section Permission Fault - Halting\n"); + trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK); + break;*/ + + case FAULT_BUSTRNL1 | FAULT_USER: /* Bus Error Trans L1 Fault */ + case FAULT_BUSTRNL2 | FAULT_USER: /* Bus Error Trans L2 Fault */ + case FAULT_BUSTRNL1: /* Bus Error Trans L1 Fault */ + case FAULT_BUSTRNL2: /* Bus Error Trans L2 Fault */ +/* + * These faults imply that the PTE is corrupt. Likely to be a kernel + * fault so we had better stop. + */ + panic("Bus Error Translation - Halting\n"); + break; +/* trapsignal(p, SIGBUS, fault_status & FAULT_TYPE_MASK); + break;*/ + + case FAULT_TRANS_P: /* Page Translation Fault */ + case FAULT_TRANS_P | FAULT_USER: /* Page Translation Fault */ +/* Ok page translation fault - The page does not exist */ + { + register vm_offset_t va; + register struct vmspace *vm = p->p_vmspace; + register vm_map_t map; + int rv; + vm_prot_t ftype; + extern vm_map_t kernel_map; + u_int nss; + + va = trunc_page((vm_offset_t)fault_address); + + if (pmap_debug_level >= 0) + printf("ok we have a page fault - addr=V%08x ", (u_int)va); + +/* + * It is only a kernel address space fault iff: + * 1. (fault_code & FAULT_USER) == 0 and + * 2. pcb_onfault not set or + * 3. pcb_onfault set but supervisor space fault + * The last can occur during an exec() copyin where the + * argument space is lazy-allocated. + */ + + if (fault_code == FAULT_TRANS_P + && (va >= KERNEL_BASE || va < VM_MIN_ADDRESS)) + map = kernel_map; + else + map = &vm->vm_map; + + if (pmap_debug_level >= 0) + printf("vmmap=%08x ", (u_int)map); + + if (pmap_handled_emulation(map->pmap, va)) + goto out; + +/* debug_show_vm_map(map, "fault");*/ + +/* We need to know whether the page should be mapped as R or R/W. + * The MMU does not give us the info as to whether the fault was caused + * by a read or a write. This means we need to disassemble the instruction + * responcible and determine if it was a read or write instruction. + * For the moment we will cheat and make it read only. If it was a write + * When the instruction is re-executed we will get a permission fault + * instead. + */ + + ftype = VM_PROT_READ; + +/* STR instruction ? */ + if ((fault_instruction & 0x0c100000) == 0x04000000) + ftype |= VM_PROT_WRITE; +/* STM instruction ? */ + else if ((fault_instruction & 0x0a100000) == 0x08000000) + ftype |= VM_PROT_WRITE; +/* SWP instruction ? */ + else if ((fault_instruction & 0x0fb00ff0) == 0x01000090) + ftype |= VM_PROT_WRITE; + + if (pmap_debug_level >= 0) + printf("fault protection = %d\n", ftype); + +#ifdef DIAGNOSTIC + if (va == 0 && map == kernel_map) { + printf("trap: bad kernel access at %x\n", (u_int)va); + goto we_re_toast; + } +#endif + + nss = 0; + if ((caddr_t)va >= vm->vm_maxsaddr + && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS + && map != kernel_map) { + nss = clrnd(btoc(USRSTACK-(u_int)va)); + if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) { + rv = KERN_FAILURE; + goto nogo; + } + } + +/* check if page table is mapped, if not, fault it first */ + +/* + if (*(((pt_entry_t **)(PROCESS_PAGE_TBLS_BASE + va >> (PD_SHIFT+2)))[]) == 0) + panic("vm_fault: Page table is needed first\n") +*/ + + rv = vm_fault(map, va, ftype, FALSE); +/*printf("fault result=%d\n", rv);*/ + if (rv == KERN_SUCCESS) { + if (nss > vm->vm_ssize) + vm->vm_ssize = nss; + va = trunc_page(vtopte(va)); +/* + * for page table, increment wiring as long as not a page + * table fault as well + */ + if (map != kernel_map) + vm_map_pageable(map, va, round_page(va+1), FALSE); + if (fault_code == FAULT_TRANS_P) + return; + goto out; + } +nogo: + if (fault_code == FAULT_TRANS_P) { + printf("Failed page fault in kernel\n"); + if (pcb->pcb_onfault) + goto copyfault; + printf("vm_fault(%x, %x, %x, 0) -> %x\n", + (u_int)map, (u_int)va, ftype, rv); + goto we_re_toast; + } + printf("nogo, Data abort: '%s' status = %03x address = %08x PC = %08x\n", + aborts[fault_status & 0xf], fault_status & 0xfff, fault_address, + fault_pc); + disassemble(fault_pc); + postmortem(frame); + trapsignal(p, (rv == KERN_PROTECTION_FAILURE) + ? SIGBUS : SIGSEGV, FAULT_TRANS_P); + break; + } +/* panic("Page Fault - Halting\n");*/ + break; + + case FAULT_TRANS_S: /* Section Translation Fault */ + case FAULT_TRANS_S | FAULT_USER: /* Section Translation Fault */ +/* Section translation fault - the L1 page table does not exist */ + { + register vm_offset_t va; + register struct vmspace *vm = p->p_vmspace; + register vm_map_t map; + int rv; + vm_prot_t ftype; + u_int nss, v; + + va = trunc_page((vm_offset_t)fault_address); + + if (pmap_debug_level >= 0) + printf("ok we have a section fault page addr=V%08x\n", + (u_int)va); + +/* + * It is only a kernel address space fault iff: + * 1. (fault_code & FAULT_USER) == 0 and + * 2. pcb_onfault not set or + * 3. pcb_onfault set but supervisor space fault + * The last can occur during an exec() copyin where the + * argument space is lazy-allocated. + */ + + if (fault_code == FAULT_TRANS_S && va >= KERNEL_BASE) + map = kernel_map; + else + map = &vm->vm_map; + +/* + debug_show_vm_map(map, "fault"); + debug_show_vm_map(kernel_map, "kernel"); +*/ + +/* We are mapping a page table so this must be kernel r/w */ + + ftype = VM_PROT_READ | VM_PROT_WRITE; +#ifdef DIAGNOSTIC + if (map == kernel_map && va == 0) { + printf("trap: bad kernel access at %x\n", (u_int)va); + goto we_re_toast; + } +#endif + + nss = 0; + if ((caddr_t)va >= vm->vm_maxsaddr + && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS + && map != kernel_map) { +/* printf("Address is in the stack\n");*/ + nss = clrnd(btoc(USRSTACK-(u_int)va)); + if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) { + printf("Stack limit exceeded %08x %08x\n", + nss, btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)); + rv = KERN_FAILURE; + goto nogo1; + } + } + +/* check if page table is mapped, if not, fault it first */ + + v = trunc_page(vtopte(va)); + if (pmap_debug_level >= 0) + printf("v=%08x\n", v); + rv = vm_fault(map, v, ftype, FALSE); + if (rv != KERN_SUCCESS) + goto nogo1; + + if (pmap_debug_level >= 0) + printf("vm_fault succeeded\n"); + +/* update increment wiring as this is a page table fault */ + + vm_map_pageable(map, v, round_page(v+1), FALSE); + + if (pmap_debug_level >= 0) + printf("faulting in page %08x\n", (u_int)va); + + ftype = VM_PROT_READ; + + rv = vm_fault(map, va, ftype, FALSE); + if (rv == KERN_SUCCESS) { + if (nss > vm->vm_ssize) + vm->vm_ssize = nss; + va = trunc_page(vtopte(va)); +/* + * for page table, increment wiring as long as not a page + * table fault as well + */ + if (!v && map != kernel_map) + vm_map_pageable(map, va, round_page(va+1), FALSE); + if (fault_code == FAULT_TRANS_S) + return; + goto out; + } +nogo1: + printf("nogo1, Data abort: '%s' status = %03x address = %08x PC = %08x\n", + aborts[fault_status & 0xf], fault_status & 0xfff, fault_address, + fault_pc); + disassemble(fault_pc); + if (fault_code == FAULT_TRANS_S) { + printf("Section fault in SVC mode\n"); + if (pcb->pcb_onfault) + goto copyfault; + printf("vm_fault(%x, %x, %x, 0) -> %x\n", + (u_int)map, (u_int)va, ftype, rv); + goto we_re_toast; + } + postmortem(frame); + trapsignal(p, (rv == KERN_PROTECTION_FAILURE) + ? SIGBUS : SIGSEGV, FAULT_TRANS_S); + break; + } +/* panic("Section Fault - Halting\n"); + break;*/ + + default : +/* Are there any combinations I have missed ? */ + + printf("fault status = %08x fault code = %08x\n", + fault_status, fault_code); + +we_re_toast: +/* Were are dead, try and provide some debug infomation before dying */ + + postmortem(frame); + + panic("Fault cannot be handled\n"); + break; + } + +out: + if ((fault_code & FAULT_USER) == 0) + return; + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 1); +#endif + userret(p, frame->tf_pc, sticks); + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 1); +#endif +} + + +/* + * void prefetch_abort_handler(trapframe_t *frame) + * + * Abort handler called when instruction execution occurs at + * a non existant or restricted (access permissions) memory page. + * If the address is invalid and we were in SVC mode then panic as + * the kernel should never prefetch abort. + * If the address is invalid and the page is mapped then the user process + * does no have read permission so send it a signal. + * Otherwise fault the page in and try again. + */ + +void +prefetch_abort_handler(frame) + trapframe_t *frame; +{ + register u_int fault_pc; + register struct proc *p; + register struct pcb *pcb; + u_int fault_instruction; + u_int s; + int fault_code; + u_quad_t sticks; + +/* Debug code */ + + if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) { + s = splhigh(); + printf("fault being handled in non SVC32 mode\n"); + postmortem(frame); + pmap_debug_level = 0; + (void)splx(s); + panic("Fault handler not in SVC mode\n"); + } + + +/* + * Enable IRQ's & FIQ's (disabled by the abort) This always comes + * from user mode so we know interrupts were not disabled. + * But we check anyway. + */ + +#ifndef BLOCK_IRQS + if (!(frame->tf_spsr & I32_bit)) + enable_interrupts(I32_bit); +#endif + +/* Update vmmeter statistics */ + + cnt.v_trap++; + +/* Get the current proc structure or proc0 if there is none */ + + if ((p = curproc) == 0) { + p = &proc0; + printf("Prefetch about with curproc == 0\n"); + } + + if (pmap_debug_level >= 0) + printf("prefetch fault in process %08x\n", (u_int)p); + +/* can't use curpcb, as it might be NULL; and we have p in a register anyway */ + + pcb = &p->p_addr->u_pcb; + if (pcb == 0) + panic("no pcb ... we're toast !\n"); + + if (pcb != curpcb) { + printf("data_abort: Alert ! pcb(%08x) != curpcb(%08x)\n", (u_int)pcb, + (u_int)curpcb); + printf("data_abort: Alert ! proc(%08x), curproc(%08x)\n", (u_int)p, + (u_int)curproc); + } + + if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) { + sticks = p->p_sticks; + +/* Modify the fault_code to reflect the USR/SVC state at time of fault */ + + fault_code |= FAULT_USER; + p->p_md.md_regs = frame; + } else { +/* All the kernel code pages are loaded at boot and do not get paged */ + + s = splhigh(); + printf("Prefetch address = %08x\n", frame->tf_pc); + + postmortem(frame); + +#ifdef CONTINUE_AFTER_SVC_PREFETCH + + printf("prefetch abort in SVC mode !\n"); + printf("The system should now be considered very unstable :-)\n"); + sigexit(curproc, SIGILL); +/* Not reached */ + (void)splx(s); +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 4); +#endif + userret(p, frame->tf_pc, sticks); + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 4); +#endif +#else + panic("Prefetch abort in SVC mode\n"); +#endif + } + +/* Get fault address */ + + fault_pc = frame->tf_pc; + + if (pmap_debug_level >= 0) + printf("Prefetch abort: PC = %08x\n", fault_pc); + +/* Ok validate the address, can only execute in USER space */ + + if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) { + s = splhigh(); + printf("prefetch: pc (%08x) not in user process space\n", fault_pc); + postmortem(frame); + trapsignal(p, SIGBUS, FAULT_PERM_P); + (void)splx(s); + userret(p, frame->tf_pc, sticks); + return; + } + +/* Ok read the fault address. This will fault the page in for us */ + + if (ReadWordWithChecks(fault_pc, &fault_instruction) != 0) { + s = splhigh(); + printf("prefetch: faultin failed for address %08x!!\n", fault_pc); + postmortem(frame); + trapsignal(p, SIGSEGV, fault_pc); + (void)splx(s); + } else { + +/* More debug stuff */ + + if (pmap_debug_level >= 0) { + s = splhigh(); + printf("Instruction @V%08x = %08x\n", fault_pc, fault_instruction); + disassemble(fault_pc); + printf("return addr=%08x\n", frame->tf_pc); + + (void)splx(s); + } + } + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 4); +#endif + + userret(p, frame->tf_pc, sticks); + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 2); +#endif +} + + +void +validate_trapframe(frame, where) + trapframe_t *frame; + int where; +{ + char *ptr; + u_int mode; + + if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) + printf("VTF Warning : validate_trapframe : Not in SVC32 mode\n"); + + mode = frame->tf_spsr & PSR_MODE; + + switch (where) { + case 1: + ptr = "data abort handler"; + break; + case 2: + ptr = "prefetch abort handler"; + if (mode != PSR_USR32_MODE) + printf("VTF Warning : %s : not USR32 mode\n", ptr); + break; + case 3: + ptr = "ast handler"; + if (mode != PSR_USR32_MODE) + printf("VTF Warning : %s : not USR32 mode\n", ptr); + break; + case 4: + ptr = "syscall handler"; + if (mode != PSR_USR32_MODE) + printf("VTF Warning : %s : not USR32 mode\n", ptr); + break; + case 5: + ptr = "undefined handler"; + if (mode != PSR_USR32_MODE) + printf("VTF Warning : %s : not USR32 mode\n", ptr); + break; + case 6: + ptr = "sigreturn handler"; + if (mode != PSR_USR32_MODE) + printf("VTF Warning : %s : not USR32 mode\n", ptr); + break; + default: + ptr = "unknown handler"; + break; + } + + if (frame->tf_usr_sp >= VM_MAXUSER_ADDRESS) + printf("VTF WARNING: %s : frame->tf_usr_sp >= VM_MAXUSER_ADDRESS [%08x]\n", ptr, frame->tf_usr_sp); + if (frame->tf_svc_lr >= 0xf1000000) + printf("VTF WARNING: %s : frame->tf_svc_lr >= 0xf1000000 [%08x]\n", ptr, frame->tf_svc_lr); + if (frame->tf_pc >= 0xf1000000) + printf("VTF WARNING: %s: frame->tf_pc >= 0xf1000000 [%08x]\n", ptr, frame->tf_pc); + if (frame->tf_pc < VM_MIN_ADDRESS) + printf("VTF WARNING: %s: frame->tf_pc >= VM_MIN_ADDRESS [%08x]\n", ptr, frame->tf_pc); + if (mode != PSR_USR32_MODE) { + if (frame->tf_svc_lr < 0xf0000000) + printf("VTF WARNING: %s : frame->tf_svc_lr < 0xf0000000 [%08x]\n", ptr, frame->tf_svc_lr); + if (frame->tf_pc < 0xf0000000) + printf("VTF WARNING: %s: frame->tf_pc < 0xf0000000 [%08x]\n", ptr, frame->tf_pc); + } +} + +/* End of fault.c */ diff --git a/sys/arch/arm32/arm32/fiq.S b/sys/arch/arm32/arm32/fiq.S new file mode 100644 index 00000000000..4495cc4f295 --- /dev/null +++ b/sys/arch/arm32/arm32/fiq.S @@ -0,0 +1,78 @@ +/* $NetBSD: fiq.S,v 1.1 1996/01/31 23:15:55 mark 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 + * + * fiq.S + * + * Low level fiq handlers + * + * Created : 27/09/94 + * Last updated : 28/11/94 + * + * $Id: fiq.S,v 1.1.1.1 1996/04/24 11:08:26 deraadt Exp $ + */ + +#include + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + + .global _floppy_read_fiq + .global _floppy_read_fiq_end + +_floppy_read_fiq: + subs r11, r11, #0x00000001 + addeq r13, r13, #0x00018000 + ldrb r10, [r13] + strb r10, [r12], #0x0001 + subs pc, lr, #0x00000004 +_floppy_read_fiq_end: + + .global _floppy_write_fiq + .global _floppy_write_fiq_end + +_floppy_write_fiq: + subs r11, r11, #0x00000001 + addeq r13, r13, #0x00018000 + ldrb r10, [r12], #0x0001 + strb r10, [r13] + subs pc, lr, #0x00000004 + +_floppy_write_fiq_end: diff --git a/sys/arch/arm32/arm32/fusu.c b/sys/arch/arm32/arm32/fusu.c new file mode 100644 index 00000000000..824c6e33ccd --- /dev/null +++ b/sys/arch/arm32/arm32/fusu.c @@ -0,0 +1,224 @@ +/* $NetBSD: fusu.c,v 1.2 1996/03/27 22:42:08 mark Exp $ */ + +/* + * Copyright (C) 1993 Wolfgang Solfrank. + * Copyright (C) 1993 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. + */ + +/* + * Emulate fubyte. + */ + +int +fubyte(addr) +char *addr; +{ + unsigned char c; + + if (copyin(addr,&c,sizeof(c))) + return -1; + return c; +} + +/* + * Emulate fuibyte. + * Note: This is the same as fubyte. + * In case of separate I&D space this MUST be replaced. + */ + +int +fuibyte(addr) +char *addr; +{ + unsigned char c; + + if (copyin(addr,&c,sizeof(c))) + return -1; + return c; +} + +/* + * Emulate fuiword + * Note: This is the same as fuword. + * In case of separate I&D space this MUST be replaced. + */ + +int +fuiword(addr) +char *addr; +{ + unsigned long l; + + if (copyin(addr,&l,sizeof(l))) + return -1; + return l; +} + +/* + * Emulate fuswintr + */ + +int +fuswintr(addr) +char *addr; +{ + unsigned short s; + extern int nopagefault; + int ret; + + nopagefault++; + if (copyin(addr,&s,sizeof(s))) + ret = -1; + else + ret = s; + nopagefault--; + return ret; +} + +/* + * Emulate fusword + */ + +int +fusword(addr) +char *addr; +{ + unsigned short s; + + if (copyin(addr,&s,sizeof(s))) + return -1; + return s; +} + +/* + * Emulate fuword + */ + +int +fuword(addr) +char *addr; +{ + unsigned long l; + + if (copyin(addr,&l,sizeof(l))) + return -1; + return l; +} + +/* + * Emulate subyte. + */ + +int +subyte(addr,c) +char *addr; +unsigned char c; +{ + if (copyout(&c,addr,sizeof(c))) + return -1; + return 0; +} + +/* + * Emulate suibyte. + * Note: This is the same as subyte. + * In case of separate I&D space this MUST be replaced. + */ + +int +suibyte(addr,c) +char *addr; +unsigned char c; +{ + if (copyout(&c,addr,sizeof(c))) + return -1; + return 0; +} + +/* + * Emulate suiword + * Note: This is the same as suword. + * In case of separate I&D space this MUST be replaced. + */ + +int +suiword(addr,l) +char *addr; +unsigned long l; +{ + if (copyout(&l,addr,sizeof(l))) + return -1; + return 0; +} + +/* + * Emulate suswintr + */ + +int +suswintr(addr,s) +char *addr; +unsigned short s; +{ + extern int nopagefault; + int ret; + + nopagefault++; + ret = copyout(&s,addr,sizeof(s)) ? -1 : 0; + nopagefault--; + return ret; +} + +/* + * Emulate susword + */ + +int +susword(addr,s) +char *addr; +unsigned short s; +{ + if (copyout(&s,addr,sizeof(s))) + return -1; + return 0; +} + +/* + * Emulate suword + */ + +int +suword(addr,l) +char *addr; +unsigned long l; +{ + if (copyout(&l,addr,sizeof(l))) + return -1; + return 0; +} diff --git a/sys/arch/arm32/arm32/genassym.c b/sys/arch/arm32/arm32/genassym.c new file mode 100644 index 00000000000..9fe837d9842 --- /dev/null +++ b/sys/arch/arm32/arm32/genassym.c @@ -0,0 +1,138 @@ +/* $NetBSD: genassym.c,v 1.4 1996/03/13 21:22:32 mark Exp $ */ + +/*- + * Copyright (c) 1982, 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. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +main() +{ + struct proc *p = 0; + struct vmmeter *vm = 0; + struct pcb *pcb = 0; + struct trapframe *tf = 0; + struct sigframe *sigf = 0; + struct uprof *uprof = 0; + irqhandler_t *ih = 0; + struct vconsole *vc = 0; + struct vidc_info *vi = 0; + struct vmspace *vms = 0; + +#define def(N,V) printf("#define\t%s %d\n", N, V) + + def("UPAGES", UPAGES); + def("PGSHIFT", PGSHIFT); + def("PDSHIFT", PDSHIFT); + + def("P_ADDR", &p->p_addr); + def("P_BACK", &p->p_back); + def("P_FORW", &p->p_forw); + def("P_PRIORITY", &p->p_priority); + def("P_STAT", &p->p_stat); + def("P_WCHAN", &p->p_wchan); + def("P_VMSPACE", &p->p_vmspace); + def("P_SPARE", &p->p_md.__spare); + + def("PCB_PAGEDIR", &pcb->pcb_pagedir); + def("PCB_FLAGS", &pcb->pcb_flags); + def("PCB_R0", &pcb->pcb_r0); + def("PCB_R1", &pcb->pcb_r1); + def("PCB_R2", &pcb->pcb_r2); + def("PCB_R3", &pcb->pcb_r3); + def("PCB_R4", &pcb->pcb_r4); + def("PCB_R5", &pcb->pcb_r5); + def("PCB_R6", &pcb->pcb_r6); + def("PCB_R7", &pcb->pcb_r7); + def("PCB_R8", &pcb->pcb_r8); + def("PCB_R9", &pcb->pcb_r9); + def("PCB_R10", &pcb->pcb_r10); + def("PCB_R11", &pcb->pcb_r11); + def("PCB_R12", &pcb->pcb_r12); + def("PCB_SP", &pcb->pcb_sp); + def("PCB_LR", &pcb->pcb_lr); + def("PCB_PC", &pcb->pcb_pc); + def("PCB_UND_SP", &pcb->pcb_und_sp); + def("PCB_ONFAULT", &pcb->pcb_onfault); + + def("USER_SIZE", sizeof(struct user)); + + def("V_TRAP", &vm->v_trap); + def("V_INTR", &vm->v_intr); + def("V_SOFT", &vm->v_soft); + + def("VM_MAP", &vms->vm_map); + def("VM_PMAP", &vms->vm_pmap); + + def("PR_BASE", &uprof->pr_base); + def("PR_SIZE", &uprof->pr_size); + def("PR_OFF", &uprof->pr_off); + def("PR_SCALE", &uprof->pr_scale); + + def("IH_FUNC", &ih->ih_func); + def("IH_ARG", &ih->ih_arg); + def("IH_LEVEL", &ih->ih_level); + def("IH_NUM", &ih->ih_num); + def("IH_FLAGS", &ih->ih_flags); + def("IH_MASK", &ih->ih_irqmask); + def("IH_BIT", &ih->ih_irqbit); + def("IH_NEXT", &ih->ih_next); + + def("SIGF_HANDLER", &sigf->sf_handler); + def("SIGF_SC", &sigf->sf_sc); + + def("SIGTRAP", SIGTRAP); + def("SIGEMT", SIGEMT); + + def("TF_R0", &tf->tf_r0); + def("TF_R10", &tf->tf_r10); + def("TF_PC", &tf->tf_pc); + + def("PROCSIZE", sizeof(struct proc)); + def("TRAPFRAMESIZE", sizeof(struct trapframe)); + exit(0); +} diff --git a/sys/arch/arm32/arm32/irq.S b/sys/arch/arm32/arm32/irq.S new file mode 100644 index 00000000000..c1f9ed0d2e3 --- /dev/null +++ b/sys/arch/arm32/arm32/irq.S @@ -0,0 +1,508 @@ +/* $NetBSD: irq.S,v 1.4 1996/03/27 20:42:53 mark 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 + * + * irq.S + * + * Low level irq and fiq handlers + * + * Created : 27/09/94 + */ + +#include "assym.h" +#include +#include + +#define PUSHFRAME \ + str lr, [sp, #-4]!; /* Push the return address */ \ + sub sp, sp, #0x00000004; /* Skip SVC R14 */ \ + stmdb sp, {r0-r14}^; /* Push the user mode registers */ \ + sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ + mrs r0, spsr_all; /* Put the SPSR on the stack */ \ + str r0, [sp, #-4]!; + +#define PULLFRAME \ + ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ + msr spsr_all, r0; \ + add sp, sp, #(4*15); /* Adjust the stack pointer */ \ + ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ + add sp, sp, #0x00000004; /* Skip SVC R14 */ \ + ldr lr, [sp], #0x0004; /* Pull the return address */ + +#define PULLFRAMEANDEXIT \ + ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ + msr spsr_all, r0; \ + add sp, sp, #(4*15); /* Adjust the stack pointer */ \ + ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ + add sp, sp, #0x00000004; /* Skip SVC R14 */ \ + ldmia sp!, {pc}^ /* Pull the return address */ + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + +/* + * + * irq_entry + * + * Main entry point for the IRQ vector + * + * This function reads the irq request bits in the IOMD registers + * IRQRQA, IRQRQB and DMARQ + * It then calls an installed handler for each bit that is set. + * The function stray_irqhandler is called if a handler is not defined + * for a particular interrupt. + * If a interrupt handler is found then it is called with r0 containing + * the argument defined in the handler structure. If the field ih_arg + * is zero then a pointer to the IRQ frame on the stack is passed instead. + */ + +Ldisabled_mask: + .word _disabled_mask + +Lcurrent_spl_level: + .word _current_spl_level + + .global irq_entry + +/* + * Regsister usage + * + * r6 - Address of current handler + * r7 - Pointer to handler pointer list + * r8 - Current IRQ requests. + * r9 - Used to count through possible IRQ bits. + * r10 - Base address of IOMD + */ + +irq_entry: + sub lr, lr, #0x00000004 /* Adjust the lr */ + + PUSHFRAME + +/* Raise the spl level and re-enable interrupts */ + +#if 0 + ldr r1, Lcurrent_spl_level + ldr r0, [r1] + add r0, r0, #1 + bl _raisespl +#endif +#if 0 + mrs r0, cpsr_all /* Enable IRQ's */ + bic r0, r0, #I32_bit + msr cpsr_all, r0 +#endif + +/* + * If we did not raise the spl level high enough we will get another + * interrupt here. + */ + + mov r11, #0x00000000 + mov r10, #(IOMD_BASE) /* Point to the IOMD */ + ldrb r8, [r10, #(IOMD_IRQRQA - IOMD_BASE)] /* Get IRQ request A */ +/* strb r8, [r10, #(IOMD_IRQRQA - IOMD_BASE)]*/ + ldrb r9, [r10, #(IOMD_IRQRQB - IOMD_BASE)] /* Get IRQ request B */ + orr r8, r8, r9, lsl #8 + ldrb r9, [r10, #(IOMD_DMARQ - IOMD_BASE)] /* Get DMA Request */ + orr r8, r8, r9, lsl #16 + +/*#if 0*/ + mov r0, #0x7d /* Clear IOMD IRQ bits */ + strb r0, [r10, #(IOMD_IRQRQA - IOMD_BASE)] +/*#endif*/ + +/* ldr r1, Ldisabled_mask + ldr r0, [r1] + orr r0, r0, r8 + str r0, [r1] + + bl _irq_setmasks*/ + +#if 0 + mrs r0, cpsr_all /* Enable IRQ's */ + bic r0, r0, #I32_bit + msr cpsr_all, r0 +#endif + mov r0, sp + mov r1, r8 + bl _validate_irq_address + + ldr r7, [pc, #irqhandlers - . - 8] + mov r9, #0x00000001 + + stmfd sp!, {r8} + +irqloop: + tst r8, r9 /* Is a bit set ? */ + + beq nextirq /* No ? try next bit */ + + ldr r6, [r7] /* Get address of first handler structure */ + + teq r6, #0x00000000 /* Do we have a handler */ + moveq r0, r8 /* IRQ requests as arg 0 */ + beq _stray_irqhandler /* call special handler */ + + ldr r0, Lcnt + ldr r1, [r0, #(V_INTR)] + add r1, r1, #0x00000001 + str r1, [r0, #(V_INTR)] + +irqchainloop: + add lr, pc, #nextinchain - . - 8 /* return address */ + +#ifdef IRQSTATS + ldr r0, Lintrcnt + ldr r1, [r6, #(IH_NUM)] + + add r0, r0, r1, lsl #2 + ldr r1, [r0] + add r1, r1, #0x00000001 + str r1, [r0] +#endif + + ldr r0, [r6, #(IH_ARG)] /* Get argument pointer */ + teq r0, #0x00000000 /* If arg is zero pass stack frame */ + addeq r0, sp, #4 /* ... stack frame */ + ldr pc, [r6, #(IH_FUNC)] /* Call handler */ + +nextinchain: +/* ldr r1, Ldisabled_mask + ldr r2, [r1] + bic r2, r2, r9 + str r2, [r1] + bl _irq_setmasks*/ + + teq r0, #0x00000001 /* Was the irq serviced ? */ + beq nextirq + + ldr r6, [r6, #(IH_NEXT)] + teq r6, #0x00000000 +/* bne irqchainloop*/ + +nextirq: + add r7, r7, #0x00000004 /* update pointer to handlers */ + mov r9, r9, lsl #1 /* move on to next bit */ + teq r9, #(1 << 24) /* done the last bit ? */ + bne irqloop /* no - loop back. */ + + ldmfd sp!, {r8} + + +#if 0 + mrs r0, cpsr_all /* Enable IRQ's */ + orr r0, r0, #I32_bit + msr cpsr_all, r0 +#endif + + bl _dosoftints /* Handle the soft interrupts */ + +/* Disable interrupts and lower the spl level */ + +#if 0 + mrs r0, cpsr_all /* Enable IRQ's */ + orr r0, r0, #I32_bit + msr cpsr_all, r0 +#endif +#if 0 + ldr r1, Lcurrent_spl_level + ldr r0, [r1] + sub r0, r0, #1 + bl _lowerspl +#endif + + ldr r0, [sp] /* Get the SPSR from stack */ + + and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the IRQ */ + teq r0, #(PSR_USR32_MODE) + ldreq r0, Lastpending /* Do we have an AST pending ? */ + ldreq r1, [r0] + teqeq r1, #0x00000001 + moveq r1, #0x00000000 /* Clear it */ + streq r1, [r0] + + moveq r0, sp /* arg 0 = irq frame */ + beq _irqast /* exit via the AST handler */ + + PULLFRAME + + movs pc, lr /* Exit */ + + + .global _irqast +_irqast: +/* Punch into SVC32 mode (R0 points to the irqframe) */ +/* We can trash all the registers we like :-) */ + +/* Debug message */ + +/* stmfd sp!, {r0-r3} + add r0, pc, #Lirqtext0 - . - 8 + bl _printf + ldmfd sp!, {r0-r3}*/ + + mrs r2, cpsr_all + tst r2, #(I32_bit) + bne Lis + + orr r2, r2, #(I32_bit) + msr cpsr_all, r2 + + stmfd sp!, {r0-r3, lr} + add r0, pc, #Lirqtext0 - . - 8 + bl _printf + ldmfd sp!, {r0-r3, lr} +Lis: + add sp, sp, #72 /* Correct IRQ32 sp */ + +/* + * We have now put IRQ mode back correct so we never need to return to + * IRQ mode we can just exit via SVC mode. We must copy the trap frame + * which still lies on the IRQ stack over to the SVC stack. + */ + +/* Punch into SVC 32 mode (IRQ's still disabled) */ + + mrs r2, cpsr_all + bic r2, r2, #(PSR_MODE) + eor r2, r2, #(PSR_SVC32_MODE) + orr r2, r2, #(I32_bit) /* Overkill */ + msr cpsr_all, r2 + + sub sp, sp, #72 /* Correct SVC32 sp */ + mov r12, sp + +/* r0 points to the trap frame on the IRQ stack (SP corrected) */ +/* r12 points to the trap frame on the SVC stack */ + + ldmia r0!, {r1-r9} /* Pull 9 regs off the IRQ stack */ + stmia r12!, {r1-r9} /* Store on the SVC stack */ + ldmia r0!, {r1-r9} /* Pull 9 regs off the IRQ stack */ + stmia r12!, {r1-r9} /* Store on the SVC stack */ + +/* Ok the IRQ trapframe is now the SVC trapframe */ + +/* IRQ's could be enabled here */ + +/* Debug message */ + +/* stmfd sp!, {r0-r3} + add r0, pc, #Lirqtext1 - . - 8 + bl _printf + ldmfd sp!, {r0-r3} +*/ +/* r0 points to trap frame on entry to ast() */ + + mov r0, sp + stmfd sp!, {lr} /* Is this needed ? */ + + bl _ast + + ldmfd sp!, {lr} /* Is this needed ? */ + +/* Remember the address of the trap frame */ + +/* stmfd sp!, {r0-r3} + add r0, pc, #Lirqtext2 - . - 8 + bl _printf + ldmfd sp!, {r0-r3} +*/ + +/* Pull the frame from the SVC stack and return */ + +/* mov lr, #0*/ + +/* Kill IRQ's incase ast as somehow re-enabled them ... */ + + mrs r0, cpsr_all + orr r0, r0, #(I32_bit) + msr cpsr_all, r0 + + PULLFRAMEANDEXIT + + mov r4, #0x000000A0 + mov pc, #0x00000000 + +Lirqtext0: + .asciz "irqs enabled during ast\n" + .align 0 + +Lirqtext1: + .asciz "irqframe copied to SVC stack\n" + .align 0 + +Lirqtext2: + .asciz "irqframe restored from SVC stack\n" + .align 0 + +Lspl_mask: + .word _spl_mask + +Lcurrent_mask: + .word _current_mask + + .global _irq_setmasks + +_irq_setmasks: + ldr r1, Lcurrent_mask + ldr r1, [r1] + ldr r2, Lspl_mask + ldr r2, [r2] + and r1, r1, r2 + ldr r2, Ldisabled_mask + ldr r2, [r2] + bic r1, r1, r2 + + mov r0, #(IOMD_BASE) /* Point to the IOMD */ + strb r1, [r0, #(IOMD_IRQMSKA - IOMD_BASE)] /* Set IRQ mask A */ + mov r1, r1, lsr #8 + strb r1, [r0, #(IOMD_IRQMSKB - IOMD_BASE)] /* Set IRQ mask B */ + mov r1, r1, lsr #8 + strb r1, [r0, #(IOMD_DMAMSK - IOMD_BASE)] /* Set DMA mask */ + mov pc, r14 + + +Lcnt: + .word _cnt + +Lintrcnt: + .word _intrcnt + + +irqhandlers: + .word _irqhandlers /* Pointer to array of irqhandlers */ + +Lastpending: + .word _astpending + +#ifdef IRQSTATS +/* These symbols are used by vmstat */ + + .text + .global __intrnames +__intrnames: + .word _intrnames + + .data + + .globl _intrnames, _eintrnames, _intrcnt, _eintrcnt +_intrnames: + .asciz "interrupt 0 " + .asciz "softnet " /* reserved0 */ + .asciz "interrupt 2 " + .asciz "interrupt 3 " + .asciz "interrupt 4 " + .asciz "interrupt 5 " + .asciz "interrupt 6 " + .asciz "softclock " /* reserved1 */ + .asciz "reserved 2 " + .asciz "interrupt 9 " + .asciz "interrupt 10 " + .asciz "interrupt 11 " + .asciz "interrupt 12 " + .asciz "interrupt 13 " + .asciz "interrupt 14 " + .asciz "interrupt 15 " + .asciz "dma channel 0" + .asciz "dma channel 1" + .asciz "dma channel 2" + .asciz "dma channel 3" + .asciz "interrupt 20 " + .asciz "interrupt 21 " + .asciz "reserved 3 " + .asciz "reserved 4 " + .asciz "exp card 0 " + .asciz "exp card 1 " + .asciz "exp card 2 " + .asciz "exp card 3 " + .asciz "exp card 4 " + .asciz "exp card 5 " + .asciz "exp card 6 " + .asciz "exp card 7 " +_eintrnames: + + .bss + .align 0 +_intrcnt: + .space 32*4 +_eintrcnt: + +#else +/* Dummy entries to keep vmstat happy */ + + .text + .globl _intrnames, _eintrnames, _intrcnt, _eintrcnt +_intrnames: + .long 0 +_eintrnames: + +_intrcnt: + .long 0 +_eintrcnt: +#endif + +/* FIQ code */ + + .text + .align 0 + .global _fiq_setregs /* Sets up the FIQ handler */ + +_fiq_setregs: + mrs r2, cpsr_all + mov r3, r2 + bic r2, r2, #(PSR_MODE) + orr r2, r2, #(PSR_FIQ32_MODE) + msr cpsr_all, r2 + + ldr r8, [r0, #0x000c] /* Update FIQ registers*/ + ldr r9, [r0, #0x0010] + ldr r10, [r0, #0x0014] + ldr r11, [r0, #0x0018] + ldr r12, [r0, #0x001c] + ldr r13, [r0, #0x0020] + + msr cpsr_all, r3 /* Back to old mode */ + + mov pc, lr /* Exit */ + +/* End of irq.S */ diff --git a/sys/arch/arm32/arm32/irqhandler.c b/sys/arch/arm32/arm32/irqhandler.c new file mode 100644 index 00000000000..fe3a764706f --- /dev/null +++ b/sys/arch/arm32/arm32/irqhandler.c @@ -0,0 +1,573 @@ +/* $NetBSD: irqhandler.c,v 1.4 1996/03/28 21:43:52 mark 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 + * + * irqhandler.c + * + * IRQ/FIQ initialisation, claim, release and handler routines + * + * NOTE: Although the irqhandlers support chaining and the claim + * and release routines install handlers at the top of the chain + * The low level IRQ handler will only call the top handler in a + * chain. + * + * Created : 30/09/94 + */ + +/* Note: Need to remove IRQ_FLAG_ACTIVE as it is not used */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +irqhandler_t *irqhandlers[NIRQS]; +fiqhandler_t *fiqhandlers; + +u_int irqmasks[IRQ_LEVELS]; +u_int current_mask; +u_int actual_mask; +u_int disabled_mask; +u_int spl_mask; +u_int soft_interrupts; +extern u_int intrcnt[]; + +typedef struct { + vm_offset_t physical; + vm_offset_t virtual; +} pv_addr_t; + +extern pv_addr_t systempage; + +/* Prototypes */ + +int podule_irqhandler __P((void)); +int irq_claim __P((int /*irq*/, irqhandler_t */*handler*/)); +void zero_page_readonly __P((void)); +void zero_page_readwrite __P((void)); + +int fiq_setregs __P((fiqhandler_t *)); + +/* + * void irq_init(void) + * + * Initialise the IRQ/FIQ sub system + */ + +void +irq_init() +{ + int loop; + +/* Clear all the IRQ handlers */ + + for (loop = 0; loop < NIRQS; ++loop) + irqhandlers[loop] = NULL; + +/* Clear the FIQ handler */ + + fiqhandlers = NULL; + +/* Clear the IRQ/FIQ masks in the IOMD */ + + WriteByte(IOMD_IRQMSKA, 0x00); + WriteByte(IOMD_IRQMSKB, 0x00); + WriteByte(IOMD_FIQMSK, 0x00); + WriteByte(IOMD_DMAMSK, 0x00); + +/* + * Setup the irqmasks for the different Interrupt Priority Levels + * We will start with no bits set and these will be updated as handlers + * are installed at different IPL's. + */ + + irqmasks[IPL_BIO] = 0x00000000; + irqmasks[IPL_NET] = 0x00000000; + irqmasks[IPL_TTY] = 0x00000000; + irqmasks[IPL_CLOCK] = 0x00000000; + irqmasks[IPL_IMP] = 0x00000000; + + current_mask = 0x00000000; + actual_mask = 0x00000000; + spl_mask = 0x00000000; + soft_interrupts = 0x00000000; + + set_spl_masks(); + +/* Enable IRQ's and FIQ's */ + + enable_interrupts(I32_bit | F32_bit); +} + + +/* + * int irq_claim(int irq, irqhandler_t *handler) + * + * Enable an IRQ and install a handler for it. + */ + +int +irq_claim(irq, handler) + int irq; + irqhandler_t *handler; +{ + int level; + +/* IRQ_INSTRUCT indicates that we should get the irq number from the irq structure */ + + if (irq == IRQ_INSTRUCT) + irq = handler->ih_num; + +/* Make sure the irq number is valid */ + + if (irq < 0 || irq >= NIRQS) + return(-1); + +/* Install the handler at the top of the chain */ + + handler->ih_next = irqhandlers[irq]; + irqhandlers[irq] = handler; + +/* if (irq == IRQ_VSYNC) + { + irqhandler_t *x; + x = irqhandlers[irq]; + while (x) { + printf("handler = %08x %08x\n", x, handler); + x = x->ih_next; + } + }*/ + +/* + * Reset the flags for this handler. As it is at the top of the list it + * must be the active handler. + */ +/* amb - no needed these days */ + handler->ih_flags = 0 | IRQ_FLAG_ACTIVE; + +/* + * Record the interrupt number for accounting. + * Done here as the accounting number may not be the same as the IRQ number + * though for the moment they are + */ + + handler->ih_num = irq; + +/* If this is the first interrupt to be attached make a not of any name */ + +#ifdef IRQSTATS + if (handler->ih_next == NULL && handler->ih_name) { + extern char *_intrnames; + char *ptr = _intrnames + (irq * 14); +/* printf("intrnames=%08x ptr=%08x irq=%d\n", (u_int)_intrnames, (u_int)ptr, irq);*/ + strcpy(ptr, " "); + strncpy(ptr, handler->ih_name, min(strlen(handler->ih_name), 13)); + } +#endif + +/* + * Update the irq masks. + * This IRQ is allowable at all lower Interrupt Priority Levels. + */ + if (handler->ih_level >= 0 && handler->ih_level < IRQ_LEVELS) { + level = handler->ih_level - 1; + while (level >= 0) { + irqmasks[level] |= (1 << irq); + --level; + } + +#include "sl.h" +#include "ppp.h" +#if NSL > 0 || NPPP > 0 +/* In the presence of SLIP or PPP, splimp > spltty. */ + irqmasks[IPL_NET] &= irqmasks[IPL_TTY]; +#endif + } + +/* + for (level = 0; level < IRQ_LEVELS; ++level) + printf("irqmask[%d] = %08x\n", level, irqmasks[level]); +*/ + +/* + * Is this an expansion card IRQ and is there a PODULE IRQ handler + * installed ? + * If not panic as the podulebus irq handler should have been installed + * when the podulebus was attached. + */ + + if (irq >= IRQ_EXPCARD0 && irqhandlers[IRQ_PODULE] == NULL) + panic("Podule IRQ %d claimed but no podulebus handler installed\n", + irq); + + enable_irq(irq); + set_spl_masks(); + + return(0); +} + + +/* + * int irq_release(int irq, irqhandler_t *handler) + * + * Disable an IRQ and remove a handler for it. + */ + +int +irq_release(irq, handler) + int irq; + irqhandler_t *handler; +{ + int level; + + irqhandler_t *irqhand; + irqhandler_t **prehand; + +/* IRQ_INSTRUCT indicates that we should get the irq number from the irq structure */ + + if (irq == IRQ_INSTRUCT) + irq = handler->ih_num; + +/* Make sure the irq number is valid */ + + if (irq < 0 || irq >= NIRQS) + return(-1); + +/* + * Update the irq masks. + * Remove the IRQ from all the approriate IPL's + */ + + if (handler->ih_level >= 0 && handler->ih_level < IRQ_LEVELS) { + level = handler->ih_level - 1; + while (level >= 0) { + irqmasks[level] &= ~(1 << irq); + --level; + } + } + +/* Locate the handler */ + + irqhand = irqhandlers[irq]; + prehand = &irqhandlers[irq]; + + while (irqhand && handler != irqhand) { + prehand = &irqhand; + irqhand = irqhand->ih_next; + } + +/* Remove the handler if located */ + + if (irqhand) + *prehand = irqhand->ih_next; + else + return(-1); + +/* Flag the handler being removed as non active (in case it was) */ +/* Not needed these days - AMB */ + irqhand->ih_flags &= ~IRQ_FLAG_ACTIVE; + +/* Make sure the head of the handler list is active */ + + if (irqhandlers[irq]) + irqhandlers[irq]->ih_flags |= IRQ_FLAG_ACTIVE; + +/* + * Disable the appropriate mask bit if there are no handlers left for + * this IRQ. + */ + + if (irqhandlers[irq] == NULL) + disable_irq(irq); + + set_spl_masks(); + + return(0); +} + + +u_int +disable_interrupts(mask) + u_int mask; +{ + register u_int cpsr; + + cpsr = SetCPSR(mask, mask); + if ((GetCPSR() & I32_bit) == 0) + printf("Alert ! disable_interrupts has failed\n"); + + return(cpsr); +} + + +u_int +restore_interrupts(old_cpsr) + u_int old_cpsr; +{ + register int mask = I32_bit | F32_bit; + return(SetCPSR(mask, old_cpsr & mask)); +} + + +u_int +enable_interrupts(mask) + u_int mask; +{ + return(SetCPSR(mask, 0)); +} + + +/* + * void disable_irq(int irq) + * + * Disables a specific irq. The irq is removed from the master irq mask + */ + +void +disable_irq(irq) + int irq; +{ + register int oldirqstate; + + oldirqstate = disable_interrupts(I32_bit); + current_mask &= ~(1 << irq); + irq_setmasks(); + restore_interrupts(oldirqstate); +} + + +/* + * void enable_irq(int irq) + * + * Enables a specific irq. The irq is added to the master irq mask + * This routine should be used with caution. A handler should already + * be installed. + */ + +void +enable_irq(irq) + int irq; +{ + register u_int oldirqstate; + + oldirqstate = disable_interrupts(I32_bit); + current_mask |= (1 << irq); + irq_setmasks(); + restore_interrupts(oldirqstate); +} + + +/* + * void stray_irqhandler(u_int mask) + * + * Handler for stray interrupts. This gets called if a handler cannot be + * found for an interrupt. + */ + +void +stray_irqhandler(mask) + u_int mask; +{ +/* panic("Stray IRQ received (%08x)\n", mask);*/ + static u_int stray_irqs = 0; + + if (++stray_irqs <= 8) + log(LOG_ERR, "Stray interrupt %08x%s\n", mask, + stray_irqs >= 8 ? ": stopped logging" : ""); +} + + +void +dosoftints() +{ + register u_int softints; + + softints = soft_interrupts & spl_mask; + if (softints & IRQMASK_SOFTCLOCK) { + int s; + + ++cnt.v_soft; + ++intrcnt[IRQ_SOFTCLOCK]; + soft_interrupts &= ~IRQMASK_SOFTCLOCK; + s = lowerspl(SPL_SOFT); + softclock(); + (void)splx(s); + } + if (softints & IRQMASK_SOFTNET) { + ++cnt.v_soft; + ++intrcnt[IRQ_SOFTNET]; + soft_interrupts &= ~IRQMASK_SOFTNET; +#ifdef INET +#include "ether.h" +#if NETHER > 0 + arpintr(); +#endif + ipintr(); +#endif +#ifdef IMP + impintr(); +#endif +#ifdef NS + nsintr(); +#endif +#ifdef ISO + clnlintr(); +#endif +#ifdef CCITT + ccittintr(); +#endif +#include "ppp.h" +#if NPPP > 0 + pppintr(); +#endif + } +} + +extern vgone(); +extern vfinddev(); +extern idle(); +extern cpu_switch(); +extern switch_exit(); + +void +validate_irq_address(irqf, mask) + irqframe_t *irqf; + u_int mask; +{ + return; + if (irqf->if_pc > (int)idle && irqf->if_pc < (int)switch_exit) + return; + if (irqf->if_pc > (int)SetCPSR && irqf->if_pc < (int)GetCPSR) + return; + if ((irqf->if_spsr & PSR_MODE) != PSR_USR32_MODE) { + printf("Alert! IRQ while in non USR mode (%08x) pc=%08x\n", + irqf->if_spsr, irqf->if_pc); + } + if ((GetCPSR() & I32_bit) == 0) { + printf("Alert! IRQ's enabled during IRQ handler\n"); + } + if (irqf->if_pc >= (int)vgone && irqf->if_pc < (int)vfinddev) + printf("Alert! IRQ between vgone & vfinddev : pc=%08x\n", + irqf->if_pc); +} + + +/* + * int fiq_claim(fiqhandler_t *handler) + * + * Claim FIQ's and install a handler for them. + */ + +int +fiq_claim(handler) + fiqhandler_t *handler; +{ +/* Fail if the FIQ's are already claimed */ + + if (fiqhandlers) + return(-1); + + if (handler->fh_size > 0xc0) + return(-1); + +/* Install the handler */ + + fiqhandlers = handler; + +/* Now we have to actually install the FIQ handler */ + +/* Eventually we will copy this down but for the moment ... */ + + zero_page_readwrite(); + + WriteWord(0x0000003c, (u_int) handler->fh_func); + + zero_page_readonly(); + +/* bcopy(handler->fh_func, 0x0000001c, handler->fh_size);*/ + +/* We must now set up the FIQ registers */ + + fiq_setregs(handler); + +/* Set up the FIQ mask */ + + WriteWord(IOMD_FIQMSK, handler->fh_mask); + +/* Make sure that the FIQ's are enabled */ + + enable_interrupts(F32_bit); + return(0); +} + + +/* + * int fiq_release(fiqhandler_t *handler) + * + * Release FIQ's and remove a handler for them. + */ + +int +fiq_release(handler) + fiqhandler_t *handler; +{ +/* Fail if the handler is wrong */ + + if (fiqhandlers != handler) + return(-1); + +/* Disable FIQ interrupts */ + + disable_interrupts(F32_bit); + +/* Clear up the FIQ mask */ + + WriteWord(IOMD_FIQMSK, 0x00); + +/* Remove the handler */ + + fiqhandlers = NULL; + return(0); +} + +/* End of irqhandler.c */ diff --git a/sys/arch/arm32/arm32/kgdb_glue.c b/sys/arch/arm32/arm32/kgdb_glue.c new file mode 100644 index 00000000000..f8ed9b6ada8 --- /dev/null +++ b/sys/arch/arm32/arm32/kgdb_glue.c @@ -0,0 +1,258 @@ +/* $NetBSD: kgdb_glue.c,v 1.2 1996/03/27 22:42:16 mark Exp $ */ + +/* + * Copyright (C) 1994 Wolfgang Solfrank. + * Copyright (C) 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. + */ + +#include +#include +#include + +#include + +#include +#include +#include + +int kgdbregs[NREG]; + +dump(p, l) + u_char *p; +{ + int i, j, n; + + while (l > 0) { + printf("%08x: ", p); + n = l > 16 ? 16 : l; + for (i = 4; --i >= 0;) { + for (j = 4; --j >= 0;) + printf(--n >= 0 ? "%02x " : " ", *p++); + printf(" "); + } + p -= 16; + n = l > 16 ? 16 : l; + n = (n + 3) & ~3; + for (i = 4; --i >= 0;) + printf((n -= 4) >= 0 ? "%08x " : "", *((long *)p)++); + printf("\n"); + l -= 16; + } +} + +#define NDBGSTKS 8 /* number of debugstacks */ +#define SZDBGSTK 512 /* size of one debugstack */ +static int debugstack[NDBGSTKS * SZDBGSTK]; +static int dbgstkused; + +int * +kgdb_find_stack() +{ + int i; + + for (i = 0; i < NDBGSTKS; i++) + if (!(dbgstkused&(1 << i))) { + dbgstkused |= 1 << i; + return debugstack + (i + 1) * SZDBGSTK; + } + panic("KGDB: no stack"); +} + +void +kgdb_free_stack(sp) + int *sp; +{ + int i; + + for (i = 0; i < NDBGSTKS; i++) + if (sp == debugstack + (i + 1) * SZDBGSTK) { + if (!(dbgstkused&(1 << i))) + panic("KGDB: free free stack"); + dbgstkused &= ~(1 << i); + return; + } + panic("KGDB: free non-stack"); +} + +void +kgdbinit() +{ + /* initialize undefined mode & setup trap vector */ + initmode(PSR_UND32_MODE|F32_bit|I32_bit, kgdb_find_stack()); +} + +void +kgdb_connect(when) + int when; +{ + boothowto |= RB_KDB; + if (when == 0) + printf("waiting for remote GDB\n"); + __asm(".word 0xe6000010"); +} + +int +kgdb_poll() +{ + return 0; +} + +void +kgdb_panic() +{ + kgdbpanic = 1; + __asm(".word 0xe6000010"); +} + +int +kgdb_trap_glue(regs) + int *regs; +{ + int inst; + int cnt; + + inst = fetchinst(regs[PC] - 4); + switch (inst) { + default: + /* unexpected */ +#ifdef __notyet__ + return 0; +#endif + case 0xe6000011: /* KGDB installed breakpoint */ + regs[PC] -= 4; + break; + case 0xe6000010: /* breakpoint in kgdb_connect */ + break; + } + while (1) { + kgdbcopy(regs, kgdbregs, sizeof kgdbregs); + switch (kgdbcmds()) { + case 1: + kgdbcopy(kgdbregs, regs, sizeof kgdbregs); + if ((cnt = singlestep(regs)) < 0) + panic("singlestep"); + regs[PC] += cnt; + continue; + default: + break; + } + break; + } + kgdbcopy(kgdbregs, regs, sizeof kgdbregs); + if (PSR_USER(regs[PSR]) || !PSR_32(regs[PSR])) + panic("KGDB: invalid mode %x", regs[PSR]); + return 1; +} + +void +kgdbcopy(vs, vd, n) + void *vs, *vd; + int n; +{ + char *s = vs, *d = vd; + long *ls, *ld; + int ln; + + if (((int)s&(sizeof(long)-1)) == ((int)d&(sizeof(long)-1)) + && n >= 2 * sizeof(long)) { + while (((int)s&(sizeof(long)-1)) && --n >= 0) + *d++ = *s++; + ln = n / sizeof(long); + n -= ln * sizeof(long); + ls = (long *)s; + ld = (long *)d; + while (--ln >= 0) + *ld++ = *ls++; + s = (char *)ls; + d = (char *)ld; + } + while (--n >= 0) + *d++ = *s++; +} + +void +kgdbzero(vd, n) + void *vd; + int n; +{ + char *d = vd; + long *ld; + int ln; + + if (n >= 2 * sizeof(long)) { + while (--n >= 0) { + if (!((int)d&sizeof(long)-1)) + break; + *d++ = 0; + } + ln = n / sizeof(long); + n -= ln * sizeof(long); + ld = (long *)d; + while (--ln >= 0) + *ld++ = 0; + d = (char *)ld; + } + while (--n >= 0) + *d++ = 0; +} + +int +kgdbcmp(vs, vd, n) + void *vs, *vd; + int n; +{ + char *s = vs, *d = vd; + long *ls, *ld; + int ln; + + if (((int)s&(sizeof(long)-1)) == ((int)d&(sizeof(long)-1)) + && n >= 2 * sizeof(long)) { + while (--n >= 0) { + if (!((int)s&(sizeof(long)-1))) + break; + if (*d++ != *s++) + return *--d - *--s; + } + ln = n / sizeof(long); + n -= ln * sizeof(long); + ls = (long *)s; + ld = (long *)d; + while (--ln >= 0) + if (*ld++ != *ls++) { + n += ++ln * sizeof(long); + break; + } + s = (char *)ls; + d = (char *)ld; + } + while (--n >= 0) + if (*d++ != *s++) + return *--d - *--s; + return 0; +} diff --git a/sys/arch/arm32/arm32/kgdb_step.c b/sys/arch/arm32/arm32/kgdb_step.c new file mode 100644 index 00000000000..c3b260ba22b --- /dev/null +++ b/sys/arch/arm32/arm32/kgdb_step.c @@ -0,0 +1,440 @@ +/* $NetBSD: kgdb_step.c,v 1.2 1996/03/27 22:42:20 mark Exp $ */ + +/* + * Copyright (C) 1994 Wolfgang Solfrank. + * Copyright (C) 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. + */ + +#include + +#include +#include +#include + +/* + * Faults during instruction fetch? XXX + */ +int +fetchinst(pc) + void *pc; +{ + int inst, byte, n; + + inst = 0; + pc += sizeof(int); + for (n = sizeof(int); --n >= 0;) { + inst <<= 8; + byte = kgdbfbyte(--pc); + if (byte < 0) + return 0xe7ffffff; /* special hack! */ + inst |= byte; + } + return inst; +} + +static __inline void +execute(inst, args, regs) + int inst; + int *args; + int *regs; +{ + int *sp; + + /* + * For now, no user level emulation + */ + if (PSR_USER(regs[PSR]) || !PSR_32(regs[PSR])) + panic("execute"); + sp = kgdb_find_stack(); + regs[PSR] = Execute(inst, regs[PSR], args, sp); + kgdb_free_stack(sp); +} + +static __inline int +condition(inst, args, regs) + int inst; + int *args; + int *regs; +{ + args[0] = 0; + /* mov{cond} r0, #1 */ + execute((inst&0xf0000000)|0x03a00001, args, regs); + return args[0]; +} + +static __inline int +immediate(inst) + int inst; +{ + int imm = inst&0xff; + int rot = (inst >> 8)&0xf; + + rot *= 2; + return (imm >> rot)|(imm << (32 - rot)); +} + +static __inline int +getreg(reg, ahead, regs) + int reg; + int ahead; + int *regs; +{ + if (reg == PC) + return regs[PC] + (ahead ? 12 : 8); + return regs[reg]; +} + +static __inline void +setreg(reg, val, regs) + int reg; + int val; + int *regs; +{ + if (reg == PC) + val &= ~3; + regs[reg] = val; +} + +int +singlestep(regs) + int *regs; +{ + int inst; + int args[5]; + int dst, idx; + int val; + + inst = fetchinst(regs[PC]); + switch (inst&0x0c000000) { + case 0x00000000: + if ((inst&0x0fb00ff0) == 0x01000090) { + /* swp */ + dst = (inst >> 12)&0xf; + if (dst == PC) + return -1; + idx = inst&0xf; + if (idx == PC) + return -1; + args[0] = getreg(idx, 0, regs); + args[1] = getreg(dst, 0, regs); + idx = (inst >> 16)&0xf; + if (idx == PC) + return -1; + args[2] = getreg(idx, 0, regs); + execute((inst&0xf0400000)|0x01021090, args, regs); + setreg(dst, args[1], regs); + return 4; + } + if ((inst&0x0fbf0fff) == 0x01000090) { + /* mrs */ + if ((regs[PSR]&0xf) == 0 + && (inst&0x00400000)) + /* mrs xx, spsr in user mode */ + return 4; /* ??? */ + dst = (inst >> 12)&0xf; + if (dst == PC) + return -1; + if (condition(inst, args, regs)) + setreg(dst, regs[(inst&0x00400000) ? SPSR : PSR], regs); + return 4; + } + if ((inst&0x0fbffff0) == 0x0129f000) { + /* msr */ + if (condition(inst, args, regs)) { + idx = inst&0xf; + if (idx == PC) + return -1; + val = getreg(idx, 0, regs); + if ((regs[PSR]&0xf) == 0) { + if (inst&0x00400000) + /* msr spsr, xx in user mode */ + return 4; /* ??? */ + val &= 0xf0000000; + val |= regs[PSR]&0x0fffffff; + } + regs[(inst&0x00400000) ? SPSR : PSR] = val; + } + return 4; + } + if ((inst&0x0dbff000) == 0x0128f000) { + /* msrf */ + if (condition(inst, args, regs)) { + if ((regs[PSR]&0xf) == 0 + && (inst&0x00400000)) + /* msr spsr_flg, xx in user mode */ + return 4; /* ??? */ + if (inst&0x02000000) + val = immediate(inst); + else if (inst&0x00000ff0) + return -1; + else { + idx = inst&0xf; + if (idx == PC) + return -1; + val = getreg(idx, 0, regs); + } + val &= 0xf0000000; + val |= regs[PSR]&0x0fffffff; + regs[(inst&0x00400000) ? SPSR : PSR] = val; + } + return 4; + } + if ((inst&0x0fc000f0) == 0x00000090) { + /* mul/mla */ + dst = (inst >> 16)&0xf; + if (dst == PC) + return -1; + idx = inst&0xf; + if (idx == dst || idx == PC) + return -1; + args[1] = getreg(idx, 0, regs); + idx = (inst >> 8)&0xf; + if (idx == PC) + return -1; + args[2] = getreg(idx, 0, regs); + idx = (inst >> 12)&0xf; + if (idx == PC) + return -1; + if (idx && !(inst&0x00200000)) + /* mul with rn != 0 */ + return -1; + args[0] = getreg(idx, 0, regs); + args[3] = getreg(dst, 0, regs); + execute((inst&0xfff00000)|0x30291, args, regs); + setreg(dst, args[3], regs); + return 4; + } + { + /* data processing */ + if (condition(inst, args, regs)) { + dst = (inst >> 12)&0xf; + if (inst&0x00100000) { + /* S-Bit set */ + if (dst == PC) + /* S-Bit set and destination is R15 */ + return -1; /* not yet */ + } else + /* S-Bit not set */ + switch ((inst >> 21)&0xf) { + case 0x8: /* TST */ + case 0x9: /* TEQ */ + case 0xa: /* CMP */ + case 0xb: /* CMN */ + return -1; + } + val = ((inst&0x02000010) == 0x00000010); + args[0] = getreg((inst >> 16)&0xf, val, regs); + if (!(inst&0x02000000)) { + args[2] = getreg(inst&0xf, val, regs); + if (inst&0x00000010) { + if (inst&0x00000080) + return -1; + args[3] = getreg((inst >> 8)&0xf, val, regs); + inst = (inst&0xfff000f0)|0x00001302; + } else + inst = (inst&0xfff00ff0)|0x00001002; + } else + inst = (inst&0xfff00fff)|0x00001000; + execute(inst, args, regs); + switch ((inst >> 21)&0xf) { + case 0x8: /* TST */ + case 0x9: /* TEQ */ + case 0xa: /* CMP */ + case 0xb: /* CMN */ + break; + default: + setreg(dst, args[1], regs); + break; + } + return dst == PC ? 0 : 4; + } + return 4; + } + break; + case 0x04000000: + if ((inst&0x0e000010) == 0x06000010) + /* undefined */ + return -1; + { + /* ldr/str */ + if (condition(inst, args, regs)) { + dst = (inst >> 12)&0xf; + if (inst&0x00100000) + args[1] = regs[dst]; + else + args[1] = getreg(dst, 1, regs); + val = (inst >> 16)&0xf; + if ((inst&0x00200000) && val == PC) + /* write back with pc as base */ + return -1; + args[2] = getreg(val, 0, regs); + if (inst&0x02000000) { + if (inst&0x00000010) + /* shift amount in register */ + return -1; + idx = inst&0xf; + if (idx == PC) + /* offset in PC */ + return -1; + args[0] = getreg(idx, 0, regs); + inst = (inst&0xfff00ff0)|0x21000; + } else + inst = (inst&0xfff00fff)|0x21000; + execute(inst, args, regs); + if (inst&0x00200000) + regs[val] = args[2]; + if (inst&0x00100000) + setreg(dst, args[1], regs); + return dst == PC ? 0 : 4; + } + return 4; + } + break; + case 0x08000000: + switch (inst&0x0e000000) { + case 0x08000000: + /* ldm/stm */ + if (condition(inst, args, regs)) { + int cnt; + int val, is1; + int final; + + if (inst&0x00400000) + /* S-bit not yet supported */ + return -1; + dst = (inst >> 16)&0xf; + if (dst == PC) + return -1; + args[0] = final = val = getreg(dst, 0, regs); + cnt = 0; + is1 = 0; + for (idx = 0; idx < 16; idx++) + if ((inst&(1 << idx)) + && (cnt += 4) <= 4 /* count the registers */ + && idx == dst) + /* indicate unmodified store */ + is1 = 1; + if ((inst&0x00300000) == 0x00200000 + && (inst&(1 << dst)) + && !is1) { + /* + * The destination is in the list of a stm + * with write-back and is not the first + * register + */ + if (inst&0x00800000) + val -= cnt; + else + val += cnt; + } + if (!(inst&0x00800000)) { + /* lowest address involved */ + args[0] -= cnt; + if (!(inst&0x01000000)) + /* post-decrement */ + args[0] += 4; + if (inst&0x00200000) + final -= cnt; + } else { + if (inst&0x01000000) + /* pre-increment */ + args[0] += 4; + if (inst&0x00200000) + final += cnt; + } + for (idx = 0; idx < 16; idx++) + if (inst&(1 << idx)) { + args[1] = dst == idx + ? val + : getreg(idx, 1, regs); + execute((inst&0xfe100000)|0x00a00002, args, regs); + if (inst&0x00100000) + regs[idx] = args[1]; + } + switch (inst&0x00300000) { + case 0x00300000: /* ldm! */ + if (inst&(1 << dst)) + break; + case 0x00200000: /* stm! */ + regs[dst] = final; + break; + } + return (inst&(1 << PC)) && (inst&0x00100000) ? 0 : 4; + } + return 4; + case 0x0a000000: + /* branch */ + if (condition(inst, args, regs)) { + if (inst&0x01000000) + regs[LR] = regs[PC] + 4; + if (inst&0x00800000) + inst |= 0xff000000; + else + inst &= ~0xff000000; + regs[PC] += 8 + (inst << 2); + return 0; + } + return 4; + } + break; + case 0x0c000000: + switch (inst&0x0f000000) { + case 0x0c000000: + case 0x0d000000: + /* ldc/stc */ + return -1; + case 0x0f000000: + /* swi */ + return -1; + case 0x0e000000: + /* cdp/mrc/mcr */ + if ((regs[PSR]&0xf) == 0) + /* user mode */ + return -1; + if ((inst&0x00e00fff) != 0x00000f10) + /* cdp, different cp# or unknown operation */ + return -1; + dst = (inst >> 12)&0xf; + if (dst == PC) + args[0] = regs[PSR]; + else + args[0] = getreg(dst, 1, regs); + execute(inst&0xffff0fff, args, regs); + if (!(inst&0x00100000)) + if (dst == PC) + regs[PSR] = (regs[PSR]&0x0fffffff) + |(args[0]&0xf0000000); + else + regs[dst] = args[0]; + return 4; + } + break; + } + return -1; +} diff --git a/sys/arch/arm32/arm32/locore.S b/sys/arch/arm32/arm32/locore.S new file mode 100644 index 00000000000..57ea4805b11 --- /dev/null +++ b/sys/arch/arm32/arm32/locore.S @@ -0,0 +1,563 @@ +/* $NetBSD: locore.S,v 1.8 1996/03/20 18:57:58 mark Exp $ */ + +/* + * Copyright (C) 1994 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. + */ + +#include "assym.h" +#include +#include +#include +#include + +/* What size shoudl this really be ? It is only used by init_arm() */ + +#define INIT_ARM_STACK_SIZE 2048 + +#define PUSHFRAME \ + str lr, [sp, #-4]!; /* Push the return address */ \ + sub sp, sp, #0x00000004; /* Skip SVC R14 */ \ + stmdb sp, {r0-r14}^; /* Push the user mode registers */ \ + sub sp, sp, #(4*15); /* Adjust the stack pointer */ \ + mrs r0, spsr_all; /* Put the SPSR on the stack */ \ + str r0, [sp, #-4]!; + +#define PULLFRAME \ + ldr r0, [sp], #0x0004; /* Get the SPSR from stack */ \ + msr spsr_all, r0; \ + add sp, sp, #(4*15); /* Adjust the stack pointer */ \ + ldmdb sp, {r0-r14}^; /* Restore the registers (user mode) */ \ + mov r0, r0; /* NOP for previous instruction */ \ + add sp, sp, #0x00000004; /* Skip SVC R14 */ \ + ldr lr, [sp], #0x0004; /* Pull the return address */ + +/* register equates */ +fp .req r11 +ip .req r12 +sp .req r13 +lr .req r14 +pc .req r15 + +.text + .align 0 + .global start +start: + add r1, pc, #(Lstart - . - 8) + ldmia r1, { r1, r2, r13 } /* Set initial stack and */ + sub r2, r2, r1 /* get zero init data */ + mov r3, #0 + +L1: + str r3, [r1], #0x0004 /* Zero the bss */ + subs r2, r2, #4 + bgt L1 + + mov fp, #0x00000000 /* trace back starts here */ + bl _initarm /* Off we go */ + +/* init arm will return the new stack pointer. */ + + mov sp, r0 + +/* Debug code */ + +/* mov r1, sp + add r0, pc, #(Ltext9 - . - 8) + bl _printf +*/ + +/* Setup an initial trap frame for start_init to use */ + + PUSHFRAME + + mov fp, #0x00000000 /* trace back starts here */ + mov r0, sp /* parameter to main is trap frame*/ + +/* Debug */ + +#if 0 +stmfd r13!, {r0-r3} + ldr r1, Lproc0 + ldr r2, [r1] +/* mov r1, r0*/ + add r0, pc, #(Ltext7 - . - 8) + bl _printf +ldmfd r13!, {r0-r3} +#endif + + bl _main /* Lets light the flame and start her up */ + + PULLFRAME /* Pull the trap frame, now valid */ + + movs pc, lr /* Exit to user process */ + +/* Never gets here */ + + b . + +Lstart: + .word _edata + .word _end + .word svcstk + INIT_ARM_STACK_SIZE + +Lproc0: + .word _proc0 + +/* +Ltext7: + .asciz "proc0=%08x %08x\n" + .align 0 + + +Ltext9: + .asciz "proc0 stack at V%08x %08x\n" + .align 0 +*/ + +/* What size shoudl this really be ? It is only used by init_arm() */ + + .bss +svcstk: .space INIT_ARM_STACK_SIZE + +/* + * Instructions to copy to the bottom of zero page + * These are the entry point to the system exception routines + */ + + .text + .align 0 + .global _page0, _page0_end +_page0: + ldr pc, [pc, #Lreset - . - 8] + ldr pc, [pc, #Lundefined - . - 8] + ldr pc, [pc, #Lswi - . - 8] + ldr pc, [pc, #Labortpre - . - 8] + ldr pc, [pc, #Labortdata - . - 8] + ldr pc, [pc, #Laddrexc - . - 8] + ldr pc, [pc, #Lirq - . - 8] + ldr pc, [pc, #Lfiq - . - 8] + +Lreset: + .word reset_entry +Lundefined: + .word undefined_entry +Lswi: + .word swi_entry +Labortpre: + .word prefetch_abort_entry +Labortdata: + .word data_abort_entry +Laddrexc: + .word addrexc +Lirq: + .word irq_entry + +Lfiq: + .word fiq +_page0_end = . + +#if 0 +reset: + add r0, pc, #Wreset - . - 8 + ldmia r0, {r0, pc} +resetmsg: + .asciz "reset" + .align 0 +Wreset: + .word resetmsg + .word _panic +#endif + +reset_entry: + PUSHFRAME + + mov r0, sp /* Pass the frame to any function */ + + bl _resethandler /* It's a branch throught zero ! */ + + PULLFRAME + + movs pc, lr /* Exit */ + +#if 0 +undefined: +#ifndef KGDB + add r0, pc, #Wundefined - . - 8 + ldmia r0, {r0, pc} +undmsg: + .asciz "undefined" + .align 0 +Wundefined: + .word undmsg + .word _panic +#else +/* + * lr is the saved pc, and we make space for the saved psr + */ + stmfd sp!, {lr, pc} +/* + * now save all the rest of the registers (r13&r14) are redone later + */ + stmfd sp!, {r0-lr} +/* + * now switch to the old mode to get r13&r14, but disable interrupts +*/ +/* stupid gas doesn't yet know about the psr transfers */ + .word 0xe10f3000 @ mrs r3, cpsr + .word 0xe14f2000 @ mrs r2, spsr + str r2, [sp, #64] + orr r2, r2, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE) + .word 0xe129f002 @ msr cpsr, r2 + mov r0, r13 + mov r1, r14 + orr r3, r3, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE) + .word 0xe129f003 @ msr cpsr, r3 + str r0, [sp, #52] + str r1, [sp, #56] + mov r0, sp + mov lr, pc + ldr pc, [pc, #Wundefined - . - 8] + add sp, sp, #52 /* adjust stack to r13 */ +/* + * set saved psr and get r13&r14 to new (saved) mode first + */ + ldr r2, [sp, #12] + ldr r0, [sp] + ldr r1, [sp, #4] +/* stupid gas doesn't yet know about the psr transfers */ + .word 0xe169f002 @ msr spsr, r2 + .word 0xe10f3000 @ mrs r3, cpsr + orr r2, r2, #(PSR_FIQ32_MODE|PSR_IRQ32_MODE) + .word 0xe129f002 @ msr cpsr, r2 + mov r13, r0 + mov r14, r1 + .word 0xe129f003 @ msr cpsr, r3 + ldmea sp, {r0-r12} /* now the rest of the registers */ + add sp, sp, #16 /* Adjust stack to top */ + ldr lr, [sp, #-8] /* get link address */ + movs pc, lr /* return */ +Wundefined: + .word _kgdb_trap_glue +#endif +#endif + +addrexc: + .word 0xe10f1000 + .word 0xe14f2000 + mov r3, lr + add r0, pc, #addrexcmsg - . - 8 + bl _printf + b data_abort_entry + +addrexcmsg: + .asciz "address exception CPSR=%08x SPSR=%08x lr=%08x\n" + .align 0 +Waddrexc: + .word addrexcmsg + .word _panic + +irq: + add r0, pc, #Wirq - . - 8 + ldmia r0, {r0, pc} +irqmsg: + .asciz "irq" + .align 0 +Wirq: + .word irqmsg + .word _panic + +fiq: + add r0, pc, #Wfiq - . - 8 + ldmia r0, {r0, pc} +fiqmsg: + .asciz "fiq" + .align 0 +Wfiq: + .word fiqmsg + .word _panic + + .global _initmode +_initmode: +/* stupid gas doesn't yet know about the psr transfers */ + mrs r2, cpsr_all + msr cpsr_all, r0 + mov sp, r1 + msr cpsr_all, r2 + mov pc, lr + + + .global _boot0 +_boot0: + mrs r2, cpsr_all + bic r2, r2, #(PSR_MODE) + orr r2, r2, #(PSR_SVC32_MODE) + orr r2, r2, #(I32_bit | F32_bit) + msr cpsr_all, r2 + + mov r0, #0 + mcr 15, 0, r0, c1, c0, 0 + mov pc, r0 + + +/* Debug routine to print trace back information from stack */ + + .global _traceback + +_traceback: + stmfd sp!, {r4, r5, r6, lr} + mov r4, r11 + ldr r5, Ltracebackmin + ldr r6, Ltracebackmax + +tbloop: + mov r1, r4 + ldr r2, [r4, #-12] + ldr r3, [r4, #-8] + add r0, pc, #Ltb1 - . - 8 + bl _printf + +/* ldr r1, [r4, #-4] + ldr r2, [r4] + add r0, pc, #Ltb2 - . - 8 + bl _printf*/ + ldr r0, [r4, #-4] + ldr r1, [r4] + bl _traceback_sym + + mov r3, r4 + ldr r4, [r4, #-12] + teq r3, r4 + beq tbexit + cmp r4, r5 + bls tbexit + cmp r4, r6 + bge tbexit + teq r4, #0x00000000 + bne tbloop + +tbexit: + mov r0, r4 + ldmfd sp!, {r4, r5, r6, pc} + +Ltracebackmin: + .word 0xefbfe000 + +Ltracebackmax: + .word 0xefc00000 + +Ltb1: + .asciz "traceback: fp=%08x fp->fp=%08x fp->sp=%08x " + +Ltb2: + .asciz "fp->lr=%08x fp->pc=%08x\n" + + .align 0 + +/* Debug routine to print trace back information from stack */ + + .global _simpletraceback + +_simpletraceback: + stmfd sp!, {r4, r5, r6, lr} + mov r4, r11 + ldr r5, Ltracebackmin + ldr r6, Ltracebackmax + +stbloop: +/* ldr r1, [r4, #-4] + ldr r2, [r4] + add r0, pc, #Ltb2 - . - 8 + bl _printf*/ + ldr r0, [r4, #-4] + ldr r1, [r4] + bl _traceback_sym + + mov r3, r4 + ldr r4, [r4, #-12] + teq r3, r4 + beq stbexit + cmp r4, r5 + bls stbexit + cmp r4, r6 + bge stbexit + teq r4, #0x00000000 + bne stbloop + +stbexit: + mov r0, r4 + ldmfd sp!, {r4, r5, r6, pc} + + +/* Debug routine to print trace back information from stack */ + + .global _irqtraceback + +_irqtraceback: + stmfd sp!, {r4, r5, r6, lr} + mov r4, r0 + mov r5, r1 + add r6, r5, #(NBPG) + +itbloop: + mov r1, r4 + ldr r2, [r4, #-12] + ldr r3, [r4, #-8] + add r0, pc, #Ltb1 - . - 8 + bl _printf + +/* ldr r1, [r4, #-4] + ldr r2, [r4] + add r0, pc, #Ltb2 - . - 8 + bl _printf*/ + ldr r0, [r4, #-4] + ldr r1, [r4] + bl _traceback_sym + + mov r3, r4 + ldr r4, [r4, #-12] + teq r3, r4 + beq itbexit + cmp r4, r5 + bls itbexit + cmp r4, r6 + bge itbexit + teq r4, #0x00000000 + bne itbloop + +itbexit: + mov r0, r4 + ldmfd sp!, {r4, r5, r6, pc} + + + .global _user_traceback + +_user_traceback: + stmfd sp!, {r4, r5, r6, lr} + mov r4, r0 + ldr r5, Lusertracebackmin + ldr r6, Lusertracebackmax + +usertbloop: + mov r1, r4 + ldr r2, [r4, #-12] + ldr r3, [r4, #-8] + add r0, pc, #Lusertb1 - . - 8 + bl _printf + + ldr r1, [r4, #-4] + ldr r2, [r4] + add r0, pc, #Lusertb2 - . - 8 + bl _printf + + mov r3, r4 + ldr r4, [r4, #-12] + teq r3, r4 + beq usertbexit + cmp r4, r5 + bls tbexit + cmp r4, r6 + bge usertbexit + teq r4, #0x00000000 + bne usertbloop + +usertbexit: + mov r0, r4 + ldmfd sp!, {r4, r5, r6, pc} + +Lusertracebackmin: + .word 0x00001000 + +Lusertracebackmax: + .word 0xefbfe000 + +Lusertb1: + .asciz "traceback: fp=%08x fp->fp=%08x fp->sp=%08x " + +Lusertb2: + .asciz "fp->lr=%08x fp->pc=%08x\n" + + .align 0 + + + +/* + * Signal trampoline; copied to top of user stack. + */ + .global _sigcode +ENTRY(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, #SIGF_SC + swi SYS_sigreturn + +/* Well if that failed we better exit quick ! */ + + add r0, pc, #Lsigerr - . - 8 + swi 0x1002 + + swi SYS_exit + +Lsigerr: + .asciz "sigreturn syscall failed\n" + .align 0 + .globl _esigcode +_esigcode: + +/* + * setjump + longjmp + */ + .global _setjmp +ENTRY(setjmp) + stmia r0, {r4-r14} + mov r0, #0x00000000 + mov r15, r14 + + .global _longjmp +ENTRY(longjmp) + ldmia r2, {r4-r14} + mov r0, #0x00000001 + mov r15, r14 + + .global _esym +_esym: .word _end + + .global _abort +_abort: + b _abort diff --git a/sys/arch/arm32/arm32/machdep.c b/sys/arch/arm32/arm32/machdep.c new file mode 100644 index 00000000000..6ec881a5d9b --- /dev/null +++ b/sys/arch/arm32/arm32/machdep.c @@ -0,0 +1,2153 @@ +/* $NetBSD: machdep.c,v 1.6 1996/03/13 21:32:39 mark 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 + * + * machdep.c + * + * Machine dependant functions for kernel setup + * + * This file needs a lot of work. + * + * Created : 17/09/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SYSVMSG +#include +#endif +#ifdef SYSVSEM +#include +#endif +#ifdef SYSVSHM +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hydrabus.h" + +/* Describe different actions to take when boot() is called */ + +#define ACTION_HALT 0x01 /* Halt and boot */ +#define ACTION_REBOOT 0x02 /* Halt and request RiscBSD reboot */ +#define ACTION_KSHELL 0x04 /* Call kshell */ +#define ACTION_DUMP 0x08 /* Dump the system to the dump dev */ + +#define HALT_ACTION ACTION_HALT | ACTION_KSHELL /* boot(RB_HALT) */ +#define REBOOT_ACTION ACTION_REBOOT /* boot(0) */ +#define PANIC_ACTION ACTION_HALT | ACTION_KSHELL /* panic() */ + +BootConfig bootconfig; /* Boot config storage */ +videomemory_t videomemory; /* Video memory descriptor */ + +vm_offset_t physical_start; +vm_offset_t physical_freestart; +vm_offset_t physical_freeend; +vm_offset_t physical_end; +int physical_memoryblock; +u_int free_pages; +vm_offset_t pagetables_start; +int physmem = 0; + +int debug_flags; +int max_processes; +int cpu_cache; +int cpu_ctrl; + +u_int ramdisc_size; /* Ramdisc size */ + +u_int kmodule_base; +u_int kmodule_size; + +u_int videodram_size; /* Amount of DRAM to reserve for video */ +vm_offset_t videodram_start; + +vm_offset_t physical_pt_start; +vm_offset_t virtual_pt_end; + +u_int *cursor_data; /* Will move to the vidc code */ + +typedef struct { + vm_offset_t physical; + vm_offset_t virtual; +} pv_addr_t; + +pv_addr_t systempage; +pv_addr_t irqstack; +pv_addr_t undstack; +pv_addr_t abtstack; +pv_addr_t kernelstack; +#if NHYDRABUS > 0 +pv_addr_t hydrascratch; +#endif + +pt_entry_t kernel_pt_table[15]; + +/* the following is used externally (sysctl_hw) */ +char machine[] = "arm32"; /* cpu "architecture" */ + +char *boot_args; + +extern pt_entry_t msgbufpte; +int msgbufmapped; +vm_offset_t msgbufphys; + +extern u_int data_abort_handler_address; +extern u_int prefetch_abort_handler_address; +extern u_int undefined_handler_address; + +extern int pmap_debug_level; + +#define KERNEL_PT_PAGEDIR 0 +#define KERNEL_PT_PDE 1 +#define KERNEL_PT_PTE 2 +#define KERNEL_PT_VMEM 3 +#define KERNEL_PT_SYS 4 +#define KERNEL_PT_KERNEL 5 +#define KERNEL_PT_VMDATA0 6 +#define KERNEL_PT_VMDATA1 7 +#define KERNEL_PT_VMDATA2 8 +#define KERNEL_PT_VMDATA3 9 +#define KERNEL_PT_VMDATA4 10 +#define KERNEL_PT_VMDATA5 11 +#define KERNEL_PT_VMDATA6 12 +#define KERNEL_PT_VMDATA7 13 +#define KERNEL_PT_VMDATA7 13 +#define KERNEL_PT_KSTACK 14 + +struct user *proc0paddr; + +/* + * Declare these as initialized data so we can patch them. + */ +int nswbuf = 0; +#ifdef NBUF +int nbuf = NBUF; +#else +int nbuf = 0; +#endif +#ifdef BUFPAGES +int bufpages = BUFPAGES; +#else +int bufpages = 0; +#endif + +int cold = 1; + +/* Prototypes */ + +void boot0 __P((void)); +void bootsync __P((void)); + +char *strstr __P((char */*s1*/, char */*s2*/)); + +void physconputchar __P((char)); +void physcon_display_base __P((u_int)); +void consinit __P((void)); + +void map_section __P((vm_offset_t, vm_offset_t, vm_offset_t)); +void map_pagetable __P((vm_offset_t, vm_offset_t, vm_offset_t)); +void map_entry __P((vm_offset_t, vm_offset_t va, vm_offset_t)); +void map_entry_ro __P((vm_offset_t, vm_offset_t, vm_offset_t)); + +void pmap_bootstrap __P((vm_offset_t /*kernel_l1pt*/)); +void process_kernel_args __P((void)); +u_long strtoul __P((const char */*s*/, char **/*ptr*/, int /*base*/)); +caddr_t allocsys __P((caddr_t /*v*/)); +void identify_cpu __P((void)); +void data_abort_handler __P((trapframe_t */*frame*/)); +void prefetch_abort_handler __P((trapframe_t */*frame*/)); +void undefinedinstruction_bounce __P((trapframe_t */*frame*/)); +void set_boot_devs __P((void)); +void configure __P((void)); +void zero_page_readonly __P((void)); +void zero_page_readwrite __P((void)); +u_int disassemble __P((u_int /*addr*/)); +int setup_cursor __P((void)); +void init_fpe_state __P((struct proc *)); + +void pmap_debug __P((int /*level*/)); +void dumpsys __P((void)); +void hydrastop __P((void)); + +void vtbugreport __P((void)); + +/* + * Debug function just to park the CPU + * + * This should be updated to power down an ARM7500 + */ + +void +halt() +{ + while (1); +} + + +/* + * void boot(int howto) + * + * Reboots the system + * + * This gets called when a reboot is request by the user or after a panic. + * Call boot0() will reboot the machine. For the moment we will try and be + * clever and return to the booting environment. This may work if we + * have be booted with the Kate boot loader as long as we have not messed + * the system up to much. Until we have our own memory management running + * this should work. The only use of being able to return (to RISC OS) + * is so I don't have to wait while the machine reboots. + */ + +/* NOTE: These variables will be removed, well some of them */ + +extern u_int spl_mask; +extern u_int current_mask; +struct pcb dumppcb; +extern u_int arm700bugcount; +extern int ioctlconsolebug; + +void +boot(howto) + int howto; +{ + int loop; + int action; + +/* Debugging here */ + + if (curproc == NULL) + printf("curproc = 0 - must have been in cpu_idle()\n"); + +/* if (panicstr) + printf("ioctlconsolebug=%d %08x\n", ioctlconsolebug, ioctlconsolebug);*/ + +/* if (curpcb) + printf("curpcb=%08x pcb_sp=%08x pcb_und_sp=%08x\n", curpcb, curpcb->pcb_sp, curpcb->pcb_und_sp);*/ + +#if NHYDRABUS > 0 +/* + * If we are halting the master then we should halt the slaves :-) + * otherwise it can get a bit disconcerting to have 4 other + * processor still tearing away doing things. + */ + + hydrastop(); +#endif + +/* Debug info */ + + printf("boot: howto=%08x %08x curproc=%08x\n", howto, spl_mask, (u_int)curproc); + + printf("current_mask=%08x spl_mask=%08x\n", current_mask, spl_mask); + printf("ipl_bio=%08x ipl_net=%08x ipl_tty=%08x ipl_clock=%08x ipl_imp=%08x\n", + irqmasks[IPL_BIO], irqmasks[IPL_NET], irqmasks[IPL_TTY], + irqmasks[IPL_CLOCK], irqmasks[IPL_IMP]); + + dump_spl_masks(); + +/* vtbugreport();*/ + +/* Did we encounter the ARM700 bug we discovered ? */ + + if (arm700bugcount > 0) + printf("ARM700 PREFETCH/SWI bug count = %d\n", arm700bugcount); + +/* Disable console buffering */ + + cnpollc(1); + +/* If we are still cold then hit the air brakes */ + + if (cold) { + printf("Halted while still in the ICE age.\n"); + printf("Hit a key to reboot\n"); + cngetc(); + boot0(); + } + +/* + * Depending on how we got here and with what intructions, choose + * the actions to take. (See the actions defined above) + */ + + if (panicstr) + action = PANIC_ACTION; + else if (howto & RB_HALT) + action = HALT_ACTION; + else + action = REBOOT_ACTION; + +/* + * If RB_NOSYNC was not specified sync the discs. + * Note: Unless cold is set to 1 here, syslogd will die during the unmount. + * It looks like syslogd is getting woken up only to find that it cannot + * page part of the binary in as the filesystem has been unmounted. + */ + + + if (!(howto & RB_NOSYNC)) { + cold = 1; /* no sleeping etc. */ + bootsync(); + } + +/* Say NO to interrupts */ + + splhigh(); + +#ifdef KSHELL + +/* Now enter our crude debug shell if required. Soon to be replaced with DDB */ + + if (action & ACTION_KSHELL) + shell(); +#else + if (action & ACTION_KSHELL) { + printf("Halted.\n"); + printf("Hit a key to reboot "); + cngetc(); + } +#endif + +/* Auto reboot overload protection */ + +/* + * This code stops the kernel entering an endless loop of reboot - panic + * cycles. This will only effect kernels that have been configured to + * reboot on a panic and will have the effect of stopping further reboots + * after it has rebooted 16 times after panics and clean halt or reboot + * will reset the counter. + */ + +/* + * Have we done 16 reboots in a row ? If so halt rather than reboot + * since 16 panics in a row without 1 clean halt means something is + * seriously wrong + */ + + if (cmos_read(RTC_ADDR_REBOOTCNT) > 16) + action = (action & ~ACTION_REBOOT) | ACTION_HALT; + +/* + * If we are rebooting on a panic then up the reboot count otherwise reset + * This will thus be reset if the kernel changes the boot action from + * reboot to halt due to too any reboots. + */ + + if ((action & ACTION_REBOOT) && panicstr) + cmos_write(RTC_ADDR_REBOOTCNT, + cmos_read(RTC_ADDR_REBOOTCNT) + 1); + else + cmos_write(RTC_ADDR_REBOOTCNT, 0); + +/* + * If we need a RiscBSD reboot, request it but setting a bit in the CMOS RAM + * This can be detected by the RiscBSD boot loader during a RISC OS boot + * No other way to do this as RISC OS is in ROM. + */ + + if (action & ACTION_REBOOT) + cmos_write(RTC_ADDR_BOOTOPTS, + cmos_read(RTC_ADDR_BOOTOPTS) | 0x02); + +/* If we need to do a dump, do it */ + + if ((howto & RB_DUMP) && (action & ACTION_DUMP)) { + savectx(&dumppcb); + dumpsys(); + } + +/* Run any shutdown hooks */ + + printf("Running shutdown hooks ...\n"); + doshutdownhooks(); + +/* Make sure IRQ's are disabled */ + + IRQdisable; + +/* Tell the user we are booting */ + + printf("boot..."); + +/* Give the user time to read the last couple of lines of text. */ + + for (loop = 5; loop > 0; --loop) { + printf("%d..", loop); + delay(500000); + } + + boot0(); +} + + +/* Sync the discs and unmount the filesystems */ + +void +bootsync(void) +{ + int iter; + int nbusy; + struct buf *bp; + static int bootsyncdone = 0; + + if (bootsyncdone) return; + + bootsyncdone = 1; + +/* Make sure we can still manage to do things */ + + if (GetCPSR() & I32_bit) { +/* + * If we get then boot has been called with out RB_NOSYNC and interrupts were + * disabled. This means the boot() call did not come from a user process e.g. + * shutdown, but must have come from somewhere in the kernel. + */ + + IRQenable; + printf("Warning IRQ's disabled during boot()\n"); + } + + vfs_shutdown(); +} + + +/* + * Estimated loop for n microseconds + */ + +/* Need to re-write this to use the timers */ + +/* One day soon I will actually do this */ + +void +delay(n) + u_int n; +{ + u_int i; + + while (--n > 0) + for (i = 8; --i;); +} + + +/* + * u_int initarm(BootConfig *bootconf) + * + * Initial entry point on startup. This gets called before main() is + * entered. + * It should be responcible for setting up everything that must be + * in place when main is called. + * This includes + * Taking a copy of the boot configuration structure. + * Initialising the physical console so characters can be printed. + * Setting up page tables for the kernel + * Relocating the kernel to the bottom of physical memory + */ + +/* This routine is frightening mess ! This is what my mind looks like -mark */ + +u_int +initarm(bootconf) + BootConfig *bootconf; +{ + int loop; + int loop1; + u_int logical; + u_int physical; + u_int kerneldatasize; + u_int l1pagetable; + u_int l2pagetable; + extern char page0[], page0_end[]; + struct exec *kernexec = (struct exec *)KERNEL_BASE; + +/* Copy the boot configuration structure */ + + bootconfig = *bootconf; + +/* + * Initialise the video memory descriptor + * + * This will change in the future to correctly report DRAM as well + * but for the moment hardwire it. This will allow the console code + * to use the structure now. + * + * Note: all references to the video memory virtual/physical address + * should go via this structure. + */ + +/* + * In the future ... + * + * All console output will be postponed until the primary bootstrap + * has been completed so that we have had a chance to reserve some + * memory for the video system if we do not have separate VRAM. + */ + + videomemory.vidm_vbase = bootconfig.display_start; + videomemory.vidm_pbase = VRAM_BASE; + videomemory.vidm_type = VIDEOMEM_TYPE_VRAM; + videomemory.vidm_size = bootconfig.display_size; + +/* + * Initialise the physical console + * This is done in main() but for the moment we do it here so that + * we can use printf in initarm() before main() has been called. + */ + + consinit(); + +/* Talk to the user */ + + printf("initarm...\n"); + + printf("Kernel loaded from file %s\n", bootconfig.kernelname); + printf("Kernel arg string %s\n", (char *)bootconfig.argvirtualbase); + + printf("\nBoot configuration structure reports the following memory\n"); + + printf(" DRAM block 0a at %08x size %08x DRAM block 0b at %08x size %08x\n\r", + bootconfig.dram[0].address, + bootconfig.dram[0].pages * bootconfig.pagesize, + bootconfig.dram[1].address, + bootconfig.dram[1].pages * bootconfig.pagesize); + printf(" DRAM block 1a at %08x size %08x DRAM block 1b at %08x size %08x\n\r", + bootconfig.dram[2].address, + bootconfig.dram[2].pages * bootconfig.pagesize, + bootconfig.dram[3].address, + bootconfig.dram[3].pages * bootconfig.pagesize); + printf(" VRAM block 0 at %08x size %08x\n\r", + bootconfig.vram[0].address, + bootconfig.vram[0].pages * bootconfig.pagesize); + + printf(" videomem = %08x %08x\n", bootconfig.display_start, videomemory.vidm_vbase); + +/* Check to make sure the page size is correct */ + + if (NBPG != bootconfig.pagesize) + panic("Page size is not %d bytes\n", NBPG); + +/* + * Ok now we have the hard bit. + * We have the kernel allocated up high. The rest of the memory map is + * available. We are still running on RISC OS page tables. + * + * We need to construct new page tables move the kernel in physical + * memory and switch to them. + * + * The booter will have left us 6 pages at the top of memory. + * Two of these are used as L2 page tables and the other 4 form the L1 + * page table. + */ + +/* + * Ok we must construct own own page table tables. + * Once we have these we can reorganise the memory as required + */ + +/* + * We better check to make sure the booter has set up the scratch + * area for us correctly. We use this area to create temporary pagetables + * while we reorganise the memory map. + */ + + if ((bootconfig.scratchphysicalbase & 0x3fff) != 0) + panic("initarm: Scratch area not aligned on 16KB boundry\n"); + + if ((bootconfig.scratchsize < 0xc000) != 0) + panic("initarm: Scratch area too small (need >= 48KB)\n"); + +/* + * Ok start the primary bootstrap. + * The primary bootstrap basically replaces the booter page tables with + * new ones that it creates in the boot scratch area. These page tables + * map the rest of the physical memory into the virtaul memory map. + * This allows low physical memory to be accessed to create the + * kernels page tables, relocate the kernel code from high physical + * memory to low physical memory etc. + */ + + printf("initarm: Primary bootstrap ... "); + +/* + * Update the videomemory structure to reflect the mapping changes + */ + + videomemory.vidm_vbase = VMEM_VBASE; + videomemory.vidm_pbase = VRAM_BASE; + videomemory.vidm_type = VIDEOMEM_TYPE_VRAM; + videomemory.vidm_size = bootconfig.vram[0].pages * NBPG; + + kerneldatasize = bootconfig.kernsize + bootconfig.argsize; + + l2pagetable = bootconfig.scratchvirtualbase; + l1pagetable = l2pagetable + 0x4000; + +/* + * Now we construct a L2 pagetables for the VRAM, the current kernel memory + * and the new kernel memory + */ + + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable + 0x1000, logical, + bootconfig.vram[0].address + logical); + map_entry(l2pagetable + 0x1000, logical + 0x200000, + bootconfig.vram[0].address + logical); + } + + for (logical = 0; logical < kerneldatasize + bootconfig.scratchsize; + logical += NBPG) { + map_entry(l2pagetable + 0x3000, logical, + bootconfig.kernphysicalbase + logical); + } + +#if NHYDRABUS > 0 + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable + 0x2000, logical, + bootconfig.dram[0].address + logical + NBPG); + } +#else + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable + 0x2000, logical, + bootconfig.dram[0].address + logical); + } +#endif + +/* + * Now we construct the L1 pagetable. This only needs the minimum to + * keep us going until we can contruct the proper kernel L1 page table. + */ + + map_section(l1pagetable, VIDC_BASE, VIDC_HW_BASE); + map_section(l1pagetable, IOMD_BASE, IOMD_HW_BASE); + + map_pagetable(l1pagetable, 0x00000000, + bootconfig.scratchphysicalbase + 0x2000); + map_pagetable(l1pagetable, KERNEL_BASE, + bootconfig.scratchphysicalbase + 0x3000); + map_pagetable(l1pagetable, VMEM_VBASE, + bootconfig.scratchphysicalbase + 0x1000); + +/* Print some debugging info */ + +/* + printf("page tables look like this ...\n"); + printf("V0x00000000 - %08x\n", ReadWord(l1pagetable + 0x0000)); + printf("V0x03500000 - %08x\n", ReadWord(l1pagetable + 0x00d4)); + printf("V0x00200000 - %08x\n", ReadWord(l1pagetable + 0x0080)); + printf("V0xf4000000 - %08x\n", ReadWord(l1pagetable + 0x3d00)); + printf("V0xf0000000 - %08x\n", ReadWord(l1pagetable + 0x3c00)); + printf("page dir = P%08x\n", bootconfig.scratchphysicalbase + 0x4000); + printf("l1= V%08x\n", l1pagetable); +*/ + +/* + * Pheww right we are ready to switch page tables !!! + * The L1 table is at bootconfig.scratchphysicalbase + 0x4000 + */ + +/* Switch tables */ + + setttb(bootconfig.scratchphysicalbase + 0x4000); + +/* Since we have mapped the VRAM up into kernel space we must now update the + * the bootconfig and display structures by hand. + */ + + bootconfig.display_start = VMEM_VBASE; + physcon_display_base(VMEM_VBASE); + + printf("done.\n"); + +/* + * Ok we have finished the primary boot strap. All this has done is to + * allow us to access all the physical memory from known virtual + * location. We also now know that all the used pages are at the top + * of the physical memory and where they are in the virtual memory map. + * + * This should be the stage we are at at the end of the bootstrap when + * we have a two stage booter. + * + * The secondary bootstrap has the responcibility to sort locating the + * kernel to the correct address and for creating the kernel page tables. + * It must also set up various memory pointers that are used by pmap etc. + */ + + process_kernel_args(); + + printf("initarm: Secondary bootstrap ... "); + +/* Zero down the memory we mapped in for the secondary bootstrap */ + + bzero(0x00000000, 0x200000); + +/* Set up the variables that define the availablilty of physcial memory */ + + physical_start = bootconfig.dram[0].address; + physical_freestart = physical_start; + physical_end = bootconfig.dram[bootconfig.dramblocks - 1].address + + bootconfig.dram[bootconfig.dramblocks - 1].pages * NBPG; + physical_freeend = physical_end; + physical_memoryblock = 0; + free_pages = bootconfig.drampages; + + for (loop = 0; loop < bootconfig.dramblocks; ++loop) + physmem += bootconfig.dram[loop].pages; + +/* + * Reserve some pages at the top of the memory for later use + * + * This area is not currently used but could be used for the allocation + * of L1 page tables for each process. + * The size of this memory would be determined by the maximum number of + * processes. + * + * For the moment we just reserve a few pages just to make sure the + * system copes. + */ + + physical_freeend -= videodram_size; + free_pages -= (videodram_size / NBPG); + videodram_start = physical_freeend; + + physical_freeend -= PD_SIZE * max_processes; + free_pages -= 4 * max_processes; + pagetables_start = physical_freeend; + +/* Right We have the bottom meg of memory mapped to 0x00000000 + * so was can get at it. The kernel will ocupy the start of it. + * After the kernel/args we allocate some the the fixed page tables + * we need to get the system going. + * We allocate one page directory and 8 page tables and store the + * physical addresses in the kernel_pt_table array. + * Must remember that neither the page L1 or L2 page tables are the same + * size as a page ! + * + * Ok the next bit of physical allocate may look complex but it is + * simple really. I have done it like this so that no memory gets wasted + * during the allocate of various pages and tables that are all different + * sizes. + * The start address will be page aligned. + * We allocate the kernel page directory on the first free 16KB boundry + * we find. + * We allocate the kernel page tables on the first 1KB boundry we find. + * We allocate 9 PT's. This means that in the process we + * KNOW that we will encounter at least 1 16KB boundry. + * + * Eventually if the top end of the memory gets used for process L1 page + * tables the kernel L1 page table may be moved up there. + */ + +/* + * The Simtec Hydra board needs a 2MB aligned page for bootstrapping. + * Simplest thing is to nick the bottom page of physical memory. + */ + +#if NHYDRABUS > 0 + hydrascratch.physical = physical_start; + physical_start += NBPG; + --free_pages; +#endif + + physical = physical_start + kerneldatasize; +/* printf("physical=%08x next_phys=%08x\n", physical, pmap_next_phys_page(physical - NBPG));*/ + loop1 = 1; + kernel_pt_table[0] = 0; + for (loop = 0; loop < 15; ++loop) { + if ((physical & (PD_SIZE-1)) == 0 && kernel_pt_table[0] == 0) { + kernel_pt_table[KERNEL_PT_PAGEDIR] = physical; + bzero((char *)physical - physical_start, PD_SIZE); + physical += PD_SIZE; + } else { + kernel_pt_table[loop1] = physical; + bzero((char *)physical - physical_start, PT_SIZE); + physical += PT_SIZE; + ++loop1; + } + } + +/* A bit of debugging info */ + +/* + for (loop=0; loop < 10; ++loop) + printf("%d - P%08x\n", loop, kernel_pt_table[loop]); +*/ + +/* This should never be able to happen but better confirm that. */ + + if ((kernel_pt_table[0] & (PD_SIZE-1)) != 0) + panic("initarm: Failed to align the kernel page directory\n"); + +/* Update the address of the first free page of physical memory */ + + physical_freestart = physical; +/* printf("physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/ + free_pages -= (physical - physical_start) / NBPG; + +/* Allocate a page for the system page mapped to 0x00000000 */ + + systempage.physical = physical_freestart; + physical_freestart += NBPG; +/* printf("(0)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/ + --free_pages; + bzero((char *)systempage.physical - physical_start, NBPG); + +/* Allocate another 3 pages for the stacks in different CPU modes. */ + + irqstack.physical = physical_freestart; + physical_freestart += NBPG; + abtstack.physical = physical_freestart; + physical_freestart += NBPG; + undstack.physical = physical_freestart; + physical_freestart += NBPG; + bzero((char *)irqstack.physical - physical_start, 3*NBPG); + free_pages -= 3; + irqstack.virtual = KERNEL_BASE + irqstack.physical-physical_start; + abtstack.virtual = KERNEL_BASE + abtstack.physical-physical_start; + undstack.virtual = KERNEL_BASE + undstack.physical-physical_start; +/* printf("(1)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/ + + kernelstack.physical = physical_freestart; + physical_freestart += UPAGES * NBPG; + bzero((char *)kernelstack.physical - physical_start, UPAGES * NBPG); + free_pages -= UPAGES; + +/* printf("(2)physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/ + + + kernelstack.virtual = KERNEL_BASE + kernelstack.physical + - physical_start; + + msgbufphys = physical_freestart; + physical_freestart += round_page(sizeof(struct msgbuf)); + free_pages -= round_page(sizeof(struct msgbuf)) / NBPG; + +/* printf("physical_fs=%08x next_phys=%08x\n", (u_int)physical_freestart, (u_int)pmap_next_phys_page(physical_freestart - NBPG));*/ + +/* Ok we have allocated physical pages for the primary kernel page tables */ + +/* Now we fill in the L2 pagetable for the kernel code/data */ + + l2pagetable = kernel_pt_table[KERNEL_PT_KERNEL] - physical_start; + + if (N_GETMAGIC(kernexec[0]) == ZMAGIC) { +/* printf("[ktext read-only] "); + printf("[%08x %08x %08x] \n", (u_int)kerneldatasize, (u_int)kernexec->a_text, + (u_int)(kernexec->a_text+kernexec->a_data+kernexec->a_bss));*/ +/* printf("physical start=%08x physical freestart=%08x hydra phys=%08x\n", physical_start, physical_freestart, hydrascratch.physical);*/ + for (logical = 0; logical < 0x00/*kernexec->a_text*/; + logical += NBPG) + map_entry_ro(l2pagetable, logical, physical_start + + logical); + for (; logical < kerneldatasize; logical += NBPG) + map_entry(l2pagetable, logical, physical_start + + logical); + } else + for (logical = 0; logical < kerneldatasize; logical += NBPG) + map_entry(l2pagetable, logical, physical_start + + logical); + +/* Map the stack pages */ + + map_entry(l2pagetable, irqstack.physical-physical_start, + irqstack.physical); + map_entry(l2pagetable, abtstack.physical-physical_start, + abtstack.physical); + map_entry(l2pagetable, undstack.physical-physical_start, + undstack.physical); + map_entry(l2pagetable, kernelstack.physical - physical_start, + kernelstack.physical); + map_entry(l2pagetable, kernelstack.physical + NBPG - physical_start, + kernelstack.physical + NBPG); + + l2pagetable = kernel_pt_table[KERNEL_PT_KSTACK] - physical_start; + + map_entry(l2pagetable, 0x003fe000, kernelstack.physical); + map_entry(l2pagetable, 0x003ff000, kernelstack.physical + NBPG); + +/* Now we fill in the L2 pagetable for the VRAM */ + +/* + * Current architectures mean that the VRAM is always in 1 continuous + * bank. + * This means that we can just map the 2 meg that the VRAM would occupy. + * In theory we don't need a page table for VRAM, we could section map + * it but we would need the page tables if DRAM was in use. + */ + + l2pagetable = kernel_pt_table[KERNEL_PT_VMEM] - physical_start; + + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable, logical, bootconfig.vram[0].address + + logical); + map_entry(l2pagetable, logical + 0x200000, + bootconfig.vram[0].address + logical); + } + +/* Map entries in the page table used to map PDE's */ + + l2pagetable = kernel_pt_table[KERNEL_PT_PDE] - physical_start; + map_entry(l2pagetable, 0x0000000, + kernel_pt_table[KERNEL_PT_PAGEDIR]); + map_entry(l2pagetable, 0x0001000, + kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x1000); + map_entry(l2pagetable, 0x0002000, + kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x2000); + map_entry(l2pagetable, 0x0003000, + kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x3000); + +/* + * Map entries in the page table used to map PTE's + * Basically every kernel page table gets mapped here + */ + + l2pagetable = kernel_pt_table[KERNEL_PT_PTE] - physical_start; + map_entry(l2pagetable, (KERNEL_BASE >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_KERNEL]); + map_entry(l2pagetable, (PAGE_DIRS_BASE >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_PDE]); + map_entry(l2pagetable, (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_PTE]); + map_entry(l2pagetable, (VMEM_VBASE >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMEM]); + map_entry(l2pagetable, (0x00000000 >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_SYS]); + map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00000000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA0]); + map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00400000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA1]); + map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00800000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA2]); + map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x00c00000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA3]); + map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01000000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA4]); + map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01400000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA5]); + map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01800000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA6]); + map_entry(l2pagetable, ((KERNEL_VM_BASE + 0x01c00000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_VMDATA7]); + map_entry(l2pagetable, ((0xef800000) >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_KSTACK]); + + map_entry(l2pagetable, (0xf5000000 >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x0000); + map_entry(l2pagetable, (0xf5400000 >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x1000); + map_entry(l2pagetable, (0xf5800000 >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x2000); + map_entry(l2pagetable, (0xf5c00000 >> (PGSHIFT-2)), + kernel_pt_table[KERNEL_PT_PAGEDIR] + 0x3000); + +/* + * Map the system page in the kernel page table for the bottom 1Meg + * of the virtual memory map. + */ + + l2pagetable = kernel_pt_table[KERNEL_PT_SYS] - physical_start; + map_entry(l2pagetable, 0x0000000, systempage.physical); + +/* Now we construct the L1 pagetable */ + + l1pagetable = kernel_pt_table[KERNEL_PT_PAGEDIR] - physical_start; + +/* Map the VIDC20, IOMD, COMBO and podules */ + +/* Map the VIDC20 */ + + map_section(l1pagetable, VIDC_BASE, VIDC_HW_BASE); + +/* Map the IOMD (and SLOW and MEDIUM simple podules) */ + + map_section(l1pagetable, IOMD_BASE, IOMD_HW_BASE); + +/* Map the COMBO (and module space) */ + + map_section(l1pagetable, IO_BASE, IO_HW_BASE); + +/* Map the L2 pages tables in the L1 page table */ + + map_pagetable(l1pagetable, 0x00000000, + kernel_pt_table[KERNEL_PT_SYS]); + map_pagetable(l1pagetable, 0xef800000, + kernel_pt_table[KERNEL_PT_KSTACK]); + map_pagetable(l1pagetable, KERNEL_BASE, + kernel_pt_table[KERNEL_PT_KERNEL]); + map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00000000, + kernel_pt_table[KERNEL_PT_VMDATA0]); + map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00400000, + kernel_pt_table[KERNEL_PT_VMDATA1]); + map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00800000, + kernel_pt_table[KERNEL_PT_VMDATA2]); + map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x00c00000, + kernel_pt_table[KERNEL_PT_VMDATA3]); + map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01000000, + kernel_pt_table[KERNEL_PT_VMDATA4]); + map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01400000, + kernel_pt_table[KERNEL_PT_VMDATA5]); + map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01800000, + kernel_pt_table[KERNEL_PT_VMDATA6]); + map_pagetable(l1pagetable, KERNEL_VM_BASE + 0x01c00000, + kernel_pt_table[KERNEL_PT_VMDATA7]); + map_pagetable(l1pagetable, PAGE_DIRS_BASE, + kernel_pt_table[KERNEL_PT_PDE]); + map_pagetable(l1pagetable, PROCESS_PAGE_TBLS_BASE, + kernel_pt_table[KERNEL_PT_PTE]); + map_pagetable(l1pagetable, VMEM_VBASE, + kernel_pt_table[KERNEL_PT_VMEM]); + +/* Bit more debugging info */ + +/* + printf("page tables look like this ...\n"); + printf("V0x00000000 - %08x\n", ReadWord(l1pagetable + 0x0000)); + printf("V0x03200000 - %08x\n", ReadWord(l1pagetable + 0x00c8)); + printf("V0x03500000 - %08x\n", ReadWord(l1pagetable + 0x00d4)); + printf("V0xf0000000 - %08x\n", ReadWord(l1pagetable + 0x3c00)); + printf("V0xf1000000 - %08x\n", ReadWord(l1pagetable + 0x3c40)); + printf("V0xf2000000 - %08x\n", ReadWord(l1pagetable + 0x3c80)); + printf("V0xf3000000 - %08x\n", ReadWord(l1pagetable + 0x3cc0)); + printf("V0xf3300000 - %08x\n", ReadWord(l1pagetable + 0x3ccc)); + printf("V0xf4000000 - %08x\n", ReadWord(l1pagetable + 0x3d00)); + printf("V0xf6000000 - %08x\n", ReadWord(l1pagetable + 0x3d80)); +*/ +/* printf("V0xefc00000 - %08x\n", ReadWord(l1pagetable + 0x3bf8)); + printf("V0xef800000 - %08x\n", ReadWord(l1pagetable + 0x3bfc));*/ + +/* + * Now we have the real page tables in place so we can switch to them. + * Once this is done we will be running with the REAL kernel page tables. + */ + +/* + * The last thing we must do is copy the kernel down to the new memory. + * This copies all our kernel data structures and variables as well + * which is why it is left to the last moment. + */ + + printf("mapping ... "); + + bcopy((char *)KERNEL_BASE, (char *)0x00000000, kerneldatasize); + +/* Switch tables */ + + setttb(kernel_pt_table[KERNEL_PT_PAGEDIR]); + + printf("done.\n"); + +/* Right set up the vectors at the bottom of page 0 */ + + bcopy(page0, (char *)0x00000000, page0_end - page0); + +/* + * Pages were allocated during the secondary bootstrap for the + * stacks for different CPU modes. + * We must now set the r13 registers in the different CPU modes to + * point to these stacks. + * Since the ARM stacks use STMFD etc. we must set r13 to the top end + * of the stack memory. + */ + +#ifdef DIAGNOSTIC + printf("IRQ stack V%08x P%08x\n", (u_int) irqstack.virtual, + (u_int) irqstack.physical); + printf("ABT stack V%08x P%08x\n", (u_int) abtstack.virtual, + (u_int) abtstack.physical); + printf("UND stack V%08x P%08x\n", (u_int) undstack.virtual, + (u_int) undstack.physical); +#endif + + printf("init subsystems: stacks "); + + set_stackptr(PSR_IRQ32_MODE, irqstack.virtual + NBPG); + set_stackptr(PSR_ABT32_MODE, abtstack.virtual + NBPG); + set_stackptr(PSR_UND32_MODE, undstack.virtual + NBPG); + + if (pmap_debug_level >= 0) + printf("kstack V%08x P%08x\n", (int) kernelstack.virtual, + (int) kernelstack.physical); + +/* + * Well we should set a data abort handler. + * Once things get going this will change as we will need a proper handler. + * Until then we will use a handler that just panics but tells us + * why. + * Initialisation of the vectors will just panic on a data abort. + * This just fills in a slighly better one. + */ + + printf("vectors "); + data_abort_handler_address = (u_int)data_abort_handler; + prefetch_abort_handler_address = (u_int)prefetch_abort_handler; + undefined_handler_address = (u_int)undefinedinstruction_bounce; + +/* Diagnostic stuff. while writing the boot code */ + +/* + for (loop = 0x0; loop < 0x1000; ++loop) { + if (ReadWord(PAGE_DIRS_BASE + loop * 4) != 0) + printf("Pagetable for V%08x = %08x\n", loop << 20, + ReadWord(0xf2000000 + loop * 4)); + } + +*/ + +/* Diagnostic stuff. while writing the boot code */ + +/* + for (loop = 0x0; loop < 0x400; ++loop) { + if (ReadWord(kernel_pt_table[KERNEL_PT_PTE] + loop * 4) != 0) + printf("Pagetable for V%08x P%08x = %08x\n", + loop << 22, kernel_pt_table[KERNEL_PT_PTE]+loop*4, + ReadWord(kernel_pt_table[KERNEL_PT_PTE]+loop * 4)); + } +*/ + +/* At last ! + * We now have the kernel in physical memory from the bottom upwards. + * Kernel page tables are physically above this. + * The kernel is mapped to 0xf0000000 + * The kernel data PTs will handle the mapping of 0xf1000000-0xf1ffffff + * 2Meg of VRAM is mapped to 0xf4000000 + * The kernel page directory is mapped to 0xf3000000 + * The page tables are mapped to 0xefc00000 + * The IOMD is mapped to 0xf6000000 + * The VIDC is mapped to 0xf6100000 + */ + +/* Initialise the undefined instruction handlers */ + + printf("undefined "); + undefined_init(); + +/* Boot strap pmap telling it where the kernel page table is */ + + printf("pmap "); + pmap_bootstrap(PAGE_DIRS_BASE); + +/* Setup the IRQ system */ + + printf("irq "); + irq_init(); + printf("done.\n"); + +#ifdef DDB + printf("ddb: "); + db_machine_init(); + ddb_init(); + + if (boothowto & RB_KDB) + Debugger(); +#endif + +/* We return the new stack pointer address */ + return(kernelstack.virtual + USPACE_SVC_STACK_TOP); +} + + +/* + * void cpu_startup(void) + * + * Machine dependant startup code. + * + */ + +void +cpu_startup() +{ + int loop; + vm_offset_t minaddr; + vm_offset_t maxaddr; + caddr_t sysbase; + caddr_t size; + vm_size_t bufsize; + int base, residual; + +/* Set the cpu control register */ + + cpu_ctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE + | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE; + + if (cpu_cache & 1) + cpu_ctrl |= CPU_CONTROL_IDC_ENABLE; + if (cpu_cache & 2) + cpu_ctrl |= CPU_CONTROL_WBUF_ENABLE; + + if (!(cpu_cache & 4)) + cpu_ctrl |= CPU_CONTROL_CPCLK; + +#ifdef CPU_LATE_ABORT + cpu_ctrl |= CPU_CONTROL_LABT_ENABLE; +#endif + +/* Clear out the cache */ + + idcflush(); + + cpu_control(cpu_ctrl); + +/* All domains MUST be clients, permissions are VERY important */ + + cpu_domains(DOMAIN_CLIENT); + +/* Lock down zero page */ + + zero_page_readonly(); + +/* + * Initialize error message buffer (at end of core). + */ + +/* msgbufphys was setup during the secondary boot strap */ + + for (loop = 0; loop < btoc(sizeof(struct msgbuf)); ++loop) + pmap_enter(pmap_kernel(), + (vm_offset_t)((caddr_t)msgbufp + loop * NBPG), + msgbufphys + loop * NBPG, VM_PROT_ALL, TRUE); + + msgbufmapped = 1; + +/* + * Identify ourselves for the msgbuf (everything printed earlier will + * not be buffered). + */ + + printf(version); + + printf("screen: %d x %d x %d\n", bootconfig.width + 1, bootconfig.height + 1, bootconfig.framerate); + + if (cmos_read(RTC_ADDR_REBOOTCNT) > 0) + printf("Warning: REBOOTCNT = %d\n", cmos_read(RTC_ADDR_REBOOTCNT)); + + printf("real mem = %d (%d pages)\n", arm_page_to_byte(physmem), physmem); + + /* + * Find out how much space we need, allocate it, + * and then give everything true virtual addresses. + */ + + size = allocsys((caddr_t)0); + sysbase = (caddr_t)kmem_alloc(kernel_map, round_page(size)); + if (sysbase == 0) + panic("cpu_startup: no room for system tables %d bytes required", size); + if ((caddr_t)((allocsys(sysbase) - sysbase)) != size) + panic("cpu_startup: system table size inconsistency"); + +/* + * Now allocate buffers proper. They are different than the above + * in that they usually occupy more virtual memory than physical. + */ + + bufsize = MAXBSIZE * nbuf; + buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers, + &maxaddr, bufsize, TRUE); + minaddr = (vm_offset_t)buffers; + if (vm_map_find(buffer_map, vm_object_allocate(bufsize), + (vm_offset_t)0, &minaddr, bufsize, FALSE) != KERN_SUCCESS) + panic("startup: cannot allocate buffers"); + + if ((bufpages / nbuf) >= btoc(MAXBSIZE)) { +/* don't want to alloc more physical mem than needed */ + bufpages = btoc(MAXBSIZE) * nbuf; + } + + base = bufpages / nbuf; + residual = bufpages % nbuf; + for (loop = 0; loop < nbuf; ++loop) { + vm_size_t curbufsize; + vm_offset_t curbuf; + +/* + * First buffers get (base+1) physical pages + * allocated for them. The rest get (base) physical pages. + * + * The rest of each buffer occupies virtual space, + * but has no physical memory allocated for it. + */ + + curbuf = (vm_offset_t)buffers + loop * MAXBSIZE; + curbufsize = CLBYTES * (loop < residual ? base+1 : base); + vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE); + vm_map_simplify(buffer_map, curbuf); + } + +/* + * Allocate a submap for exec arguments. This map effectively + * limits the number of processes exec'ing at any time. + */ + + exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, + 16*NCARGS, TRUE); + +/* + * Allocate a submap for physio + */ + + phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, + VM_PHYS_SIZE, TRUE); + +/* + * Finally, allocate mbuf pool. Since mclrefcnt is an off-size + * we use the more space efficient malloc in place of kmem_alloc. + */ + + mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES, + M_MBUF, M_NOWAIT); + bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES); + mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr, + VM_MBUF_SIZE, FALSE); + +/* + printf("mb_buf: map=%08x maxaddr = %08x mbutl = %08x\n", mb_map, maxaddr, mbutl); +*/ + +/* + * Initialise callouts + */ + + callfree = callout; + + for (loop = 1; loop < ncallout; ++loop) + callout[loop - 1].c_next = &callout[loop]; + + printf("avail mem = %d (%d pages)\n", (int)ptoa(cnt.v_free_count), + (int)ptoa(cnt.v_free_count) / NBPG); + printf("using %d buffers containing %d bytes of memory\n", + nbuf, bufpages * CLBYTES); + +/* + * Set up buffers, so they can be used to read disk labels. + */ + + bufinit(); + + proc0paddr = (struct user *)kernelstack.virtual; + proc0.p_addr = proc0paddr; + + curpcb = &proc0.p_addr->u_pcb; + curpcb->pcb_flags = 0; + curpcb->pcb_und_sp = (u_int)proc0.p_addr + USPACE_UNDEF_STACK_TOP; + curpcb->pcb_sp = (u_int)proc0.p_addr + USPACE_SVC_STACK_TOP; + curpcb->pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap, + (vm_offset_t)(kernel_pmap)->pm_pdir); + + proc0.p_md.md_regs = (struct trapframe *)curpcb->pcb_sp - 1; +#if 0 +/* Hack proc0 */ + + proc0paddr = (struct user *)kernelstack.virtual; + proc0.p_addr = proc0paddr; + + curpcb = &proc0.p_addr->u_pcb; + proc0.p_addr->u_pcb.pcb_flags = 0; + proc0.p_addr->u_pcb.pcb_und_sp = (u_int)proc0.p_addr + USPACE_UNDEF_STACK_TOP; + + proc0.p_addr->u_pcb.pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap, + (vm_offset_t)(kernel_pmap)->pm_pdir); +#endif +/* + * Install an IRQ handler on the VSYNC interrupt to reboot if the + * middle mouse button is pressed. + */ + + setup_cursor(); + +/* Allocate memory for the kmodule area if required */ + + if (kmodule_size) { + kmodule_size = round_page(kmodule_size); + kmodule_base = (u_int)kmem_alloc(kernel_map, kmodule_size); + if (kmodule_base) + printf("KMODULE SPACE = %08x\n", kmodule_base); + else + printf("\x1b[31mNO KMODULE SPACE\n\x1b[0m"); + } + +/* + * Configure the hardware + */ + + configure(); + +/* Set the root, swap and dump devices from the boot args */ + + set_boot_devs(); + + dump_spl_masks(); + + cold = 0; /* We are warm now ... */ +} + + +/* + * Allocate space for system data structures. We are given + * a starting virtual address and we return a final virtual + * address; along the way we set each data structure pointer. + * + * We call allocsys() with 0 to find out how much space we want, + * allocate that much and fill it with zeroes, and then call + * allocsys() again with the correct base virtual address. + */ + +caddr_t +allocsys(v) + register caddr_t v; +{ + +#define valloc(name, type, num) \ + (caddr_t)(name) = (type *)v; \ + v = (caddr_t)((name) + (num)); + + valloc(callout, struct callout, ncallout); + valloc(swapmap, struct map, nswapmap = maxproc * 2); + +#ifdef SYSVSHM + valloc(shmsegs, struct shmid_ds, shminfo.shmmni); +#endif +#ifdef SYSVSEM + valloc(sema, struct semid_ds, seminfo.semmni); + valloc(sem, struct sem, seminfo.semmns); + /* This is pretty disgusting! */ + valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); +#endif +#ifdef SYSVMSG + valloc(msgpool, char, msginfo.msgmax); + valloc(msgmaps, struct msgmap, msginfo.msgseg); + valloc(msghdrs, struct msg, msginfo.msgtql); + valloc(msqids, struct msqid_ds, msginfo.msgmni); +#endif + +/* + * Determine how many buffers to allocate. We use 10% of the + * first 2MB of memory, and 5% of the rest, with a minimum of 16 + * buffers. We allocate 1/2 as many swap buffer headers as file + * i/o buffers. + */ + + if (bufpages == 0) + if (physmem < arm_byte_to_page(2 * 1024 * 1024)) + bufpages = physmem / (10 * CLSIZE); + else + bufpages = (arm_byte_to_page(2 * 1024 * 1024) + + physmem) / (20 * CLSIZE); + +#ifdef DIAGNOSTIC + if (bufpages == 0) + panic("bufpages = 0\n"); +#endif + + if (nbuf == 0) { + nbuf = bufpages; + if (nbuf < 16) + nbuf = 16; + } + + if (nswbuf == 0) { + nswbuf = (nbuf / 2) & ~1; /* force even */ + if (nswbuf > 256) + nswbuf = 256; /* sanity */ + } + + valloc(swbuf, struct buf, nswbuf); + valloc(buf, struct buf, nbuf); + + return(v); +} + + +/* A few functions that are used to help construct the page tables + * during the bootstrap process. + */ + +void +map_section(pagetable, va, pa) + vm_offset_t pagetable; + vm_offset_t va; + vm_offset_t pa; +{ + if ((va & 0xfffff) != 0) + panic("initarm: Cannot allocate 1MB section on non 1MB boundry\n"); + + ((u_int *)pagetable)[(va >> 20)] = L1_SEC((pa & PD_MASK)); +} + + +void +map_pagetable(pagetable, va, pa) + vm_offset_t pagetable; + vm_offset_t va; + vm_offset_t pa; +{ + if ((pa & 0xc00) != 0) + panic("pagetables should be group allocated on pageboundry"); + ((u_int *)pagetable)[(va >> 20) + 0] = L1_PTE((pa & PG_FRAME) + 0x000); + ((u_int *)pagetable)[(va >> 20) + 1] = L1_PTE((pa & PG_FRAME) + 0x400); + ((u_int *)pagetable)[(va >> 20) + 2] = L1_PTE((pa & PG_FRAME) + 0x800); + ((u_int *)pagetable)[(va >> 20) + 3] = L1_PTE((pa & PG_FRAME) + 0xc00); +} + + +void +map_entry(pagetable, va, pa) + vm_offset_t pagetable; + vm_offset_t va; + vm_offset_t pa; +{ + WriteWord(pagetable + ((va >> 10) & 0x00000ffc), + L2_PTE((pa & PG_FRAME), AP_KRW)); +} + + +void +map_entry_nc(pagetable, va, pa) + vm_offset_t pagetable; + vm_offset_t va; + vm_offset_t pa; +{ + WriteWord(pagetable + ((va >> 10) & 0x00000ffc), + L2_PTE_NC((pa & PG_FRAME), AP_KRW)); +} + + +void +map_entry_ro(pagetable, va, pa) + vm_offset_t pagetable; + vm_offset_t va; + vm_offset_t pa; +{ + WriteWord(pagetable + ((va >> 10) & 0x00000ffc), + L2_PTE((pa & PG_FRAME), AP_KR)); +} + + +int wdresethack = 1; + +void +process_kernel_args() +{ + char *ptr; + char *args; + +/* Ok now we will check the arguments for interesting parameters. */ + + args = (char *)bootconfig.argvirtualbase; + max_processes = 64; + boothowto = 0; + kmodule_size = 0; + cpu_cache = 0x03; + debug_flags = 0; + videodram_size = 0; + +/* Skip the first parameter (the boot loader filename) */ + + while (*args != ' ' && *args != 0) + ++args; + + while (*args == ' ') + ++args; + +/* Skip the kernel image filename */ + + while (*args != ' ' && *args != 0) + ++args; + + while (*args == ' ') + ++args; + + boot_args = NULL; + + if (*args != 0) { + boot_args = args; + + if (strstr(args, "nocache")) + cpu_cache &= ~1; + + if (strstr(args, "nowritebuf")) + cpu_cache &= ~2; + + if (strstr(args, "fpaclk2")) + cpu_cache |= 4; + + ptr = strstr(args, "maxproc="); + if (ptr) { + max_processes = (int)strtoul(ptr + 8, NULL, 10); + if (max_processes < 16) + max_processes = 16; + if (max_processes > 256) + max_processes = 256; + printf("Maximum \"in memory\" processes = %d\n", + max_processes); + } + ptr = strstr(args, "ramdisc="); + if (ptr) { + ramdisc_size = (u_int)strtoul(ptr + 8, NULL, 10); + ramdisc_size *= 1024; + if (ramdisc_size < 32*1024) + ramdisc_size = 32*1024; + if (ramdisc_size > 2048*1024) + ramdisc_size = 2048*1024; + } + ptr = strstr(args, "kmodule="); + if (ptr) { + kmodule_size = (u_int)strtoul(ptr + 8, NULL, 10); + kmodule_size *= 1024; + if (kmodule_size < 4*1024) + kmodule_size = 4*1024; + if (kmodule_size > 256*1024) + kmodule_size = 256*1024; + } + ptr = strstr(args, "videodram="); + if (ptr) { + videodram_size = (u_int)strtoul(ptr + 10, NULL, 10); + /* Round to 4K page */ + videodram_size *= 1024; + videodram_size = round_page(videodram_size); + if (videodram_size > 1024*1024) + videodram_size = 1024*1024; + printf("VIDEO DRAM = %d\n", videodram_size); + } + if (strstr(args, "single")) + boothowto |= RB_SINGLE; + if (strstr(args, "kdb")) + boothowto |= RB_KDB; + ptr = strstr(args, "pmapdebug="); + if (ptr) { + pmap_debug_level = (int)strtoul(ptr + 10, NULL, 10); + pmap_debug(pmap_debug_level); + debug_flags |= 0x01; + } + if (strstr(args, "termdebug")) + debug_flags |= 0x02; + if (strstr(args, "nowdreset")) + wdresethack = 0; + if (strstr(args, "notermcls")) + debug_flags |= 0x04; + } +} + +/* This should happen in the console code - This really must move soon */ + +int +setup_cursor() +{ + +/* The cursor currently gets set up here. slightly wasteful on memory */ + +/* + * This should be done in the vidc code as that is responcible for the cursor. + * This will probably happen when the vidc code is separated from the console + * (currently work in progress) + */ + + cursor_data = (u_int *)kmem_alloc(kernel_map, NBPG); +/* printf("Cursor data page = V%08x P%08x\n", cursor_data, pmap_extract(kernel_pmap, (vm_offset_t)cursor_data));*/ + WriteWord(IOMD_CURSINIT, pmap_extract(kernel_pmap, + (vm_offset_t)cursor_data)); + return(0); +} + + +/* + * Clear registers on exec + */ + +void +setregs(p, pack, stack, retval) + struct proc *p; + struct exec_package *pack; + u_long stack; + register_t *retval; +{ + register struct trapframe *tf; + + if (pmap_debug_level >= -1) + printf("setregs: ip=%08x sp=%08x proc=%08x\n", + (u_int) pack->ep_entry, (u_int) stack, (u_int) p); + + tf = p->p_md.md_regs; + + if (pmap_debug_level >= -1) + printf("mdregs=%08x pc=%08x lr=%08x sp=%08x\n", + (u_int) tf, tf->tf_pc, tf->tf_usr_lr, tf->tf_usr_sp); + + tf->tf_r11 = 0; /* bottom of the fp chain */ + tf->tf_r12 = 0; /* ??? */ + tf->tf_pc = pack->ep_entry; + tf->tf_usr_lr = pack->ep_entry; + tf->tf_svc_lr = 0x77777777; /* Something we can see */ + tf->tf_usr_sp = stack; + tf->tf_r10 = 0xaa55aa55; /* Something we can see */ + tf->tf_spsr = PSR_USR32_MODE; + + p->p_addr->u_pcb.pcb_flags = 0; + + retval[1] = 0; +} + + +/* + * Modify the current mapping for zero page to make it read only + * + * This routine is only used until things start forking. Then new + * system pages are mapped read only in pmap_enter(). + */ + +void +zero_page_readonly() +{ + WriteWord(0xefc00000, L2_PTE((systempage.physical & PG_FRAME), AP_KR)); + tlbflush(); +} + + +/* + * Modify the current mapping for zero page to make it read/write + * + * This routine is only used until things start forking. Then system + * pages belonging to user processes are never made writable. + */ + +void +zero_page_readwrite() +{ + WriteWord(0xefc00000, L2_PTE((systempage.physical & PG_FRAME), AP_KRW)); + tlbflush(); +} + + +/* + * 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(catcher, sig, mask, code) + sig_t catcher; + int sig; + int mask; + u_long code; +{ + struct proc *p = curproc; + struct trapframe *tf; + struct sigframe *fp, frame; + struct sigacts *psp = p->p_sigacts; + int oonstack; + extern char sigcode[], esigcode[]; + + if (pmap_debug_level >= 0) + printf("Sendsig: sig=%d mask=%08x catcher=%08x code=%08x\n", + sig, mask, (u_int)catcher, (u_int)code); + + tf = p->p_md.md_regs; + oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; + +/* + * Allocate space for the signal handler context. + */ + + if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && + (psp->ps_sigonstack & sigmask(sig))) { + fp = (struct sigframe *)(psp->ps_sigstk.ss_sp + + psp->ps_sigstk.ss_size - sizeof(struct sigframe)); + psp->ps_sigstk.ss_flags |= SA_ONSTACK; + } else { + fp = (struct sigframe *)tf->tf_usr_sp - 1; + } + +/* + * Build the argument list for the signal handler. + */ + + frame.sf_signum = sig; + + frame.sf_code = code; + frame.sf_scp = &fp->sf_sc; + frame.sf_handler = catcher; + +/* + * Build the signal context to be used by sigreturn. + */ + + frame.sf_sc.sc_onstack = oonstack; + frame.sf_sc.sc_mask = mask; + 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_usr_sp = tf->tf_usr_sp; + frame.sf_sc.sc_usr_lr = tf->tf_usr_lr; + frame.sf_sc.sc_svc_lr = tf->tf_svc_lr; + frame.sf_sc.sc_pc = tf->tf_pc; + frame.sf_sc.sc_spsr = tf->tf_spsr; + + 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 = (u_int)frame.sf_scp; + tf->tf_r3 = (u_int)frame.sf_handler; + tf->tf_usr_sp = (int)fp; + tf->tf_pc = (int)(((char *)PS_STRINGS) - (esigcode - sigcode)); + + if (pmap_debug_level >= 0) + printf("Sendsig: sig=%d pc=%08x\n", sig, tf->tf_pc); +} + + + +/* + * 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_sigreturn(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_sigreturn_args /* { + syscallarg(struct sigcontext *) sigcntxp; + } */ *uap = v; + struct sigcontext *scp, context; +/* register struct sigframe *fp;*/ + register struct trapframe *tf; + + if (pmap_debug_level >= 0) + printf("sigreturn: context=%08x\n", (int)SCARG(uap, sigcntxp)); + + tf = p->p_md.md_regs; + + /* + * 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); + +/* + * Check for security violations. + */ + +/* Make sure the processor mode has not been tampered with */ + + if ((context.sc_spsr & PSR_MODE) != PSR_USR32_MODE) + return(EINVAL); + + if (context.sc_onstack & 01) + p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; + else + p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; + p->p_sigmask = context.sc_mask & ~sigcantmask; + + /* + * Restore signal context. + */ + + 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_usr_sp = context.sc_usr_sp; + tf->tf_usr_lr = context.sc_usr_lr; + tf->tf_svc_lr = context.sc_svc_lr; + tf->tf_pc = context.sc_pc; + tf->tf_spsr = context.sc_spsr; + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(tf, 6); +#endif + + return (EJUSTRETURN); +} + +/* + * machine dependent system variables. + */ + +int +cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; + struct proc *p; +{ + printf("cpu_sysctl: Currently stoned - Cannot support the operation\n"); + return(EOPNOTSUPP); +} + + +/* + * Ok these are some development functions. They map blocks of memory + * into the video ram virtual memory. + * The idea is to follow this with a call to the vidc device to + * reinitialise the vidc20 for the new video ram. + */ + +/* Map DRAM into the video memory */ + +int +vmem_mapdram() +{ + u_int l2pagetable; + u_int logical; + + if (videodram_start == 0 || videodram_size == 0) + return(ENOMEM); + +/* Flush any video data in the cache */ + + idcflush(); + +/* Get the level 2 pagetable for the video memory */ + + l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase); + +/* Map a block of DRAM into the video memory area */ + + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable, logical, videodram_start + + logical); + map_entry(l2pagetable, logical + 0x200000, + videodram_start + logical); + } + +/* Flush the TLB so we pick up the new mappings */ + + tlbflush(); + +/* Rebuild the video memory descriptor */ + + videomemory.vidm_vbase = VMEM_VBASE; + videomemory.vidm_pbase = videodram_start; + videomemory.vidm_type = VIDEOMEM_TYPE_DRAM; + videomemory.vidm_size = videodram_size; + +/* Reinitialise the video system */ + +/* video_reinit();*/ + return(0); +} + + +/* Map VRAM into the video memory */ + +int +vmem_mapvram() +{ + u_int l2pagetable; + u_int logical; + + if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0) + return(ENOMEM); + +/* Flush any video data in the cache */ + + idcflush(); + +/* Get the level 2 pagetable for the video memory */ + + l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase); + +/* Map the VRAM into the video memory area */ + + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable, logical, bootconfig.vram[0].address + + logical); + map_entry(l2pagetable, logical + 0x200000, + bootconfig.vram[0].address + logical); + } + +/* Flush the TLB so we pick up the new mappings */ + + tlbflush(); + +/* Rebuild the video memory descriptor */ + + videomemory.vidm_vbase = VMEM_VBASE; + videomemory.vidm_pbase = VRAM_BASE; + videomemory.vidm_type = VIDEOMEM_TYPE_VRAM; + videomemory.vidm_size = bootconfig.vram[0].pages * NBPG; + +/* Reinitialise the video system */ + +/* video_reinit();*/ + return(0); +} + + +/* Set the cache behaviour for the video memory */ + +int +vmem_cachectl(flag) + int flag; +{ + u_int l2pagetable; + u_int logical; + + if (bootconfig.vram[0].address == 0 || bootconfig.vram[0].pages == 0) + return(ENOMEM); + +/* Flush any video data in the cache */ + + idcflush(); + +/* Get the level 2 pagetable for the video memory */ + + l2pagetable = pmap_pte(kernel_pmap, videomemory.vidm_vbase); + +/* Map the VRAM into the video memory area */ + + if (flag & 1) { + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry(l2pagetable, logical, bootconfig.vram[0].address + + logical); + map_entry(l2pagetable, logical + 0x200000, + bootconfig.vram[0].address + logical); + } + } else { + for (logical = 0; logical < 0x200000; logical += NBPG) { + map_entry_nc(l2pagetable, logical, bootconfig.vram[0].address + + logical); + map_entry_nc(l2pagetable, logical + 0x200000, + bootconfig.vram[0].address + logical); + } + } + +/* Flush the TLB so we pick up the new mappings */ + + tlbflush(); + + return(0); +} + +#if 0 +extern int vtvalbug; +extern char *vtlastbug; +extern u_int vtbugaddr; +extern u_int vtbugcaddr; + +void +vtbugreport() +{ + printf("vtvalbug = %d\n", vtvalbug); + if (vtlastbug) + printf("vtlastbug = %s\n", vtlastbug); + printf("vtbugaddr = %08x\n", vtbugaddr); + printf("vtbugcaddr = %08x\n", vtbugcaddr); +} +#endif + +/* End of machdep.c */ diff --git a/sys/arch/arm32/arm32/makemodes.c b/sys/arch/arm32/arm32/makemodes.c new file mode 100644 index 00000000000..6a1f5e354a8 --- /dev/null +++ b/sys/arch/arm32/arm32/makemodes.c @@ -0,0 +1,362 @@ +/* $NetBSD: makemodes.c,v 1.3 1996/03/16 00:13:12 thorpej 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 the RiscBSD team. + * 4. The name of the group 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 + * + * makemodes.c + * + * VIDC20 mode configuration program. + * + * Builds a list of configured modes using mode specifiers to select + * the VIDC timings from a monitor definition file + * + * Not yet perfect, this is just experimental. + * + * Created : 17/05/95 + * Last updated : 17/05/95 + */ + +#include + +/*#define VERBOSE*/ + +#define MAX_MD 100 /* Support up to 100 modes from a file */ + +struct md { + int md_xres; + int md_yres; + int md_pixelrate; + int md_htimings[6]; + int md_vtimings[6]; + int md_syncpol; + int md_framerate; +} mds[MAX_MD]; + +int md; /* Number of modes defined in the mds array */ + + +void makemode __P((FILE *, int, int, int, int)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char line[100]; /* Line read from mdf */ + char token[40]; /* token read from mdf line */ + char value[60]; /* value of token read form mdf line */ + int startmode; /* Are we between startmode and endmode tokens */ + char monitor[40]; /* monitor name */ + int dpms; /* DPMS state for monitor */ + FILE *mdf_fd; /* mdf file descriptor */ + FILE *out_fd; /* output file descriptor */ + int loop; /* loop counter */ + int x, y, c, f; /* mode specifier variables */ + int params; + char *ptr; + +/* Check the args */ + + if (argc < 3) { + fprintf(stderr, "Syntax: makemodes \n"); + exit(10); + } + +/* Open the monitor definition file */ + + mdf_fd = fopen(argv[1], "r"); + if (!mdf_fd) { + fprintf(stderr, "Cannot open monitor definition file\n"); + exit(10); + } + +/* Open the output file */ + + out_fd = fopen(argv[2], "w"); + if (!out_fd) { + fprintf(stderr, "Cannot open output file\n"); + exit(10); + } + +/* Initialise some variables */ + + startmode = 0; + md = 0; + dpms = 0; + monitor[0] = 0; + +/* Loop for each line in the monitor definition file */ + + do { + +/* get a line */ + + if (fgets(line, 99, mdf_fd) == NULL) + break; + + ptr = line; + +/* Skip any spaces or tabs */ + + while (*ptr == ' ' || *ptr == '\t') + ++ptr; + +/* Ignore comment or blank lines */ + + if (*ptr == '#' || strlen(ptr) < 2) + continue; + +/* Do we have a startmode or endmode token ? */ + + if (sscanf(ptr, "%s", token) == 1) { + if (strcmp(token, "startmode") == 0) { + if (md < MAX_MD) + startmode = 1; + } + if (strcmp(token, "endmode") == 0) { + startmode = 0; + ++md; + } + } + +/* Do we have a token:value line ? */ + + if (sscanf(ptr, "%[^:]:%[^\n]\n", token, value) == 2) { + if (strcmp(token, "monitor_title") == 0) + strcpy(monitor, value); + if (strcmp(token, "file_format") == 0) { + if (atoi(value) != 1) { + fprintf(stderr, "Unrecognised file format\n"); + exit(10); + } + } + if (strcmp(token, "DPMS_state") == 0) + dpms = atoi(value); + if (strcmp(token, "x_res") == 0 && startmode) + mds[md].md_xres = atoi(value); + if (strcmp(token, "y_res") == 0 && startmode) + mds[md].md_yres = atoi(value); + if (strcmp(token, "pixel_rate") == 0 && startmode) + mds[md].md_pixelrate = atoi(value); + if (strcmp(token, "h_timings") == 0 && startmode) + sscanf(value, "%d,%d,%d,%d,%d,%d", + &mds[md].md_htimings[0], + &mds[md].md_htimings[1], + &mds[md].md_htimings[2], + &mds[md].md_htimings[3], + &mds[md].md_htimings[4], + &mds[md].md_htimings[5]); + if (strcmp(token, "v_timings") == 0 && startmode) + sscanf(value, "%d,%d,%d,%d,%d,%d", + &mds[md].md_vtimings[0], + &mds[md].md_vtimings[1], + &mds[md].md_vtimings[2], + &mds[md].md_vtimings[3], + &mds[md].md_vtimings[4], + &mds[md].md_vtimings[5]); + if (strcmp(token, "sync_pol") == 0 && startmode) + mds[md].md_syncpol = atoi(value); + } + + } + while (!feof(mdf_fd)); + +/* We have finished with the monitor definition file */ + + fclose(mdf_fd); + +#ifdef VERBOSE + +/* This was for debugging */ + + for (loop = 0; loop < md; ++loop) { + printf("%d x %d: %d %d [%d,%d,%d,%d,%d,%d] [%d,%d,%d,%d,%d,%d]\n", + mds[loop].md_xres, + mds[loop].md_yres, + mds[loop].md_pixelrate, + mds[loop].md_syncpol, + mds[loop].md_htimings[0], + mds[loop].md_htimings[1], + mds[loop].md_htimings[2], + mds[loop].md_htimings[3], + mds[loop].md_htimings[4], + mds[loop].md_htimings[5], + mds[loop].md_vtimings[0], + mds[loop].md_vtimings[1], + mds[loop].md_vtimings[2], + mds[loop].md_vtimings[3], + mds[loop].md_vtimings[4], + mds[loop].md_vtimings[5]); + } +#endif + +/* Start building the output file */ + + fprintf(out_fd, "/*\n"); + fprintf(out_fd, " * MACHINE GENERATED: DO NOT EDIT\n"); + fprintf(out_fd, " *\n"); + fprintf(out_fd, " * %s, from %s\n", argv[2], argv[1]); + fprintf(out_fd, " */\n\n"); + fprintf(out_fd, "#include \n"); + fprintf(out_fd, "#include \n\n"); + fprintf(out_fd, "char *monitor=\"%s\";\n", monitor); + fprintf(out_fd, "int dpms=%d;\n", dpms); + fprintf(out_fd, "\n", dpms); + fprintf(out_fd, "struct vidc_mode vidcmodes[] = {\n"); + + loop = 3; + +/* Loop over the rest of the args processing then as mode specifiers */ + +/* NOTE: A mode specifier cannot have a space in it at the moment */ + + while (argv[loop]) { + printf("%s ==> ", argv[loop]); + f = -1; + c = 256; + params = sscanf(argv[loop], "X%dY%dC%dF%d", &x, &y, &c, &f); + if (params < 2) + params = sscanf(argv[loop], "%d,%d,%d,%d", &x, &y, &c, &f); + if (params == 2 || params == 4) + makemode(out_fd, x, y, c, f); + else if (params == 3) + makemode(out_fd, x, y, 256, c); + else + printf("Invalid mode specifier\n"); + printf("\n"); + ++loop; + } + +/* Finish off the output file */ + + fprintf(out_fd, " { 0 }\n"); + fprintf(out_fd, "};\n"); + + fclose(out_fd); +} + + +/* Locate an appropriate mode for the specifier and write it to the file */ + +void makemode(out_fd, x, y, c, f) + FILE *out_fd; + int x, y, c, f; +{ + int loop; /* loop counter */ + float framerate; /* frame rate */ + int fr; /* integer frame rate */ + int found = -1; /* array index of found mode */ + int max = -1; /* maximum frame rate found */ + int pos = -1; /* array index of max frame rate */ + +/* Print some info */ + + printf("%d x %d x %d x %d : ", x, y, c, f); + +/* Scan the modes */ + + for (loop = 0; loop < md; ++loop) { + +/* X and Y have to match */ + + if (mds[loop].md_xres == x && mds[loop].md_yres == y) { + +/* Now calculate the frame rate */ + + framerate = (float)mds[loop].md_pixelrate / + (float)(mds[loop].md_htimings[0] + + mds[loop].md_htimings[1] + + mds[loop].md_htimings[2] + + mds[loop].md_htimings[3] + + mds[loop].md_htimings[4] + + mds[loop].md_htimings[5]) / + (float)(mds[loop].md_vtimings[0] + + mds[loop].md_vtimings[1] + + mds[loop].md_vtimings[2] + + mds[loop].md_vtimings[3] + + mds[loop].md_vtimings[4] + + mds[loop].md_vtimings[5]); + framerate = framerate * 1000; + fr = (framerate + 0.5); + mds[loop].md_framerate = fr; + +/* Print it as info */ + + printf("%d ", fr); + +/* Is this a new maximum ? */ + + if (max < fr) { + max = fr; + pos = loop; + } + +/* Does it match the specified frame rate ? */ + + if (fr == f) + found = loop; + } + } + +/* No exact match so use the max */ + + if (found == -1) + found = pos; + +/* Do we have an entry for this X & Y resolution */ + + if (found != -1) { + fprintf(out_fd, " { %d,/**/%d, %d, %d, %d, %d, %d,/**/%d, %d, %d, %d, %d, %d,/**/%d,/**/%d, %d },\n", + mds[found].md_pixelrate, + mds[found].md_htimings[0], + mds[found].md_htimings[1], + mds[found].md_htimings[2], + mds[found].md_htimings[3], + mds[found].md_htimings[4], + mds[found].md_htimings[5], + mds[found].md_vtimings[0], + mds[found].md_vtimings[1], + mds[found].md_vtimings[2], + mds[found].md_vtimings[3], + mds[found].md_vtimings[4], + mds[found].md_vtimings[5], + ffs(c), + mds[found].md_syncpol, + mds[found].md_framerate); + } + else { + fprintf(stderr, "Cannot find mode\n"); + } +} + +/* End of makemodes.c */ diff --git a/sys/arch/arm32/arm32/mcount.S b/sys/arch/arm32/arm32/mcount.S new file mode 100644 index 00000000000..f54a8b92568 --- /dev/null +++ b/sys/arch/arm32/arm32/mcount.S @@ -0,0 +1,47 @@ +/* $NetBSD: mcount.S,v 1.1 1996/01/31 23:16:32 mark Exp $ */ + +/* + * Copyright (C) 1994 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. + * + * $Id: mcount.S,v 1.1.1.1 1996/04/24 11:08:27 deraadt Exp $ + */ + +fp .req r11 +ip .req r12 +sp .req r13 +lr .req r14 +pc .req r15 + +.text + .align 0 + + .global mcount +mcount: + add pc, lr, #0x00000004 diff --git a/sys/arch/arm32/arm32/mem.c b/sys/arch/arm32/arm32/mem.c new file mode 100644 index 00000000000..13f87adb395 --- /dev/null +++ b/sys/arch/arm32/arm32/mem.c @@ -0,0 +1,207 @@ +/* $NetBSD: mem.c,v 1.2 1996/03/27 22:42:24 mark 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +extern char *memhook; /* poor name! */ +caddr_t zeropage; + +/*ARGSUSED*/ +int +mmopen(dev, flag, mode) + dev_t dev; + int flag, mode; +{ + switch (minor(dev)) { + default: + break; + } + return (0); +} + +/*ARGSUSED*/ +int +mmclose(dev, flag, mode) + dev_t dev; + int flag, mode; +{ + + return (0); +} + +/*ARGSUSED*/ +int +mmrw(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + register vm_offset_t o, v; + register int c; + register struct iovec *iov; + int error = 0; + static int physlock; + + if (minor(dev) == 0) { + /* lock against other uses of shared vmmap */ + while (physlock > 0) { + physlock++; + error = tsleep((caddr_t)&physlock, PZERO | PCATCH, + "mmrw", 0); + if (error) + return (error); + } + physlock = 1; + } + 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: + v = uio->uio_offset; + pmap_enter(pmap_kernel(), (vm_offset_t)memhook, + trunc_page(v), uio->uio_rw == UIO_READ ? + VM_PROT_READ : VM_PROT_WRITE, TRUE); + o = uio->uio_offset & PGOFSET; + c = min(uio->uio_resid, (int)(NBPG - o)); + error = uiomove((caddr_t)memhook + o, c, uio); + pmap_remove(pmap_kernel(), (vm_offset_t)memhook, + (vm_offset_t)memhook + NBPG); + continue; + +/* minor device 1 is kernel memory */ + case 1: + v = uio->uio_offset; + c = min(iov->iov_len, MAXPHYS); + if (!kernacc((caddr_t)v, c, + uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) + return (EFAULT); + error = uiomove((caddr_t)v, c, uio); + 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(CLBYTES, M_TEMP, M_WAITOK); + bzero(zeropage, CLBYTES); + } + c = min(iov->iov_len, CLBYTES); + error = uiomove(zeropage, c, uio); + continue; + + default: + return (ENXIO); + } + if (error) + break; + 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; +{ + struct proc *p = curproc; /* XXX */ + + switch (minor(dev)) { +/* minor device 0 is physical memory */ + case 0: + if (off > ctob(physmem) && + suser(p->p_ucred, &p->p_acflag) != 0) + return -1; + return arm_byte_to_page(off); + +/* minor device 1 is kernel memory */ + case 1: + /* XXX - writability, executability checks? */ + if (!kernacc((caddr_t)off, NBPG, B_READ)) + return -1; + return arm_byte_to_page(vtophys(off)); + + default: + return -1; + } +} diff --git a/sys/arch/arm32/arm32/memset.S b/sys/arch/arm32/arm32/memset.S new file mode 100644 index 00000000000..4599b23586a --- /dev/null +++ b/sys/arch/arm32/arm32/memset.S @@ -0,0 +1,136 @@ +/* $NetBSD: memset.S,v 1.1 1996/01/31 23:16:35 mark 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 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 + * + * memset.S + * + * optimized memset function + * + * Created : 16/05/95 + * Last updated : 16/05/95 + * + * $Id: memset.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $ + */ + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + + .global _memset + +/* Sets a block of memory to the specified value + * + * r0 - address + * r1 - byte to write + * r2 - number of bytes to write + */ + +_memset: + and r1, r1, #0x000000ff /* We write bytes */ + + cmp r2, #0x00000004 /* Do we have less than 4 bytes */ + blt memset_lessthanfour + +/* Ok first we will word align the address */ + + ands r3, r0, #0x00000003 /* Get the bottom two bits */ + beq memset_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 memset_lessthanfour + +/* Now we must be word aligned */ + +memset_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 memset_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 + +memset_loop16: + stmia r0!, {r3-r6} /* Store 16 bytes */ + sub r2, r2, #0x00000010 /* Adjust count */ + cmp r2, #0x00000010 /* Still got at least 16 bytes ? */ + bgt memset_loop16 + + ldmfd sp!, {r4-r6} /* Restore registers */ + +/* Do we need to set some words as well ? */ + + cmp r2, #0x00000004 + blt memset_lessthanfour + +/* Have either less than 16 or less than 32 depending on route taken */ + +memset_lessthan32: + +/* We have at least 4 bytes so copy as words */ + +memset_loop4: + str r3, [r0], #0x0004 + sub r2, r2, #0x0004 + cmp r2, #0x00000004 + bge memset_loop4 + +memset_lessthanfour: + cmp r2, #0x00000000 + moveq pc, lr /* Zero length so exit */ + + cmp r2, #0x00000002 + strb r1, [r0], #0x0001 /* Set 1 byte */ + strgeb r1, [r0], #0x0001 /* Set another byte */ + strgtb r1, [r0], #0x0001 /* and a third */ + + mov pc, lr /* Exit */ diff --git a/sys/arch/arm32/arm32/pmap.c b/sys/arch/arm32/arm32/pmap.c new file mode 100644 index 00000000000..66b5a935d39 --- /dev/null +++ b/sys/arch/arm32/arm32/pmap.c @@ -0,0 +1,2571 @@ +/* $NetBSD: pmap.c,v 1.4 1996/03/13 21:25:04 mark 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 + * + * pmap.c + * + * Machine dependant vm stuff + * + * Created : 20/09/94 + */ + +/* + * The dram block info is currently referenced from the bootconfig. + * This should be placed in a separate structure + * + * Need a pmap_map() routine for multiple pmap_enter() calls + * + * sob sob sob - been looking at other pmap code ... don't think + * I should have base mine of the i386 code ... + */ + +#define PMAPDEBUG 0 + +/* + * Special compilation symbols + * DEBUG_PMAP + * PMAPDEBUG + */ + +/* Include header files */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "hydrabus.h" + +/*#define bcopy_page(s, d) bcopy(s, d, NBPG)*/ +/*#define bzero_page(s) bzero(s, NBPG)*/ +#define bzero_pagedir(s) bzero(s, PD_SIZE) + +#define VM_KERNEL_VIRTUAL_MIN KERNEL_VM_BASE + 0x00000000 +#define VM_KERNEL_VIRTUAL_MAX KERNEL_VM_BASE + 0x01ffffff + +#define pmap_pde(m, v) (&((m)->pm_pdir[((vm_offset_t)(v) >> PDSHIFT)&4095])) + +#define pmap_pte_pa(pte) (*(pte) & PG_FRAME) +#define pmap_pde_v(pde) (*(pde) != 0) +#define pmap_pte_v(pte) (*(pte) != 0) + +#define PT_KS 0x80 + +int pmap_debug_level = -2; + +struct pmap kernel_pmap_store; +pmap_t kernel_pmap; + +pagehook_t page_hook0; +pagehook_t page_hook1; +char *memhook; +pt_entry_t msgbufpte; + +u_char *pmap_attributes = NULL; +pv_entry_t pv_table = NULL; +TAILQ_HEAD(pv_page_list, pv_page) pv_page_freelist; +int pv_nfree = 0; + +vm_size_t npages; + +extern vm_offset_t physical_start; +extern vm_offset_t physical_freestart; +extern vm_offset_t physical_end; +extern vm_offset_t physical_freeend; +extern int physical_memoryblock; +extern unsigned int free_pages; +extern vm_offset_t pagetables_start; +extern int max_processes; +extern pt_entry_t kernel_pt_table[9]; +extern videomemory_t videomemory; + +extern struct proc *proc1; + +struct pmap **pagedirectories; + +vm_offset_t virtual_start; +vm_offset_t virtual_end; + +vm_offset_t avail_start; +vm_offset_t avail_end; + +typedef struct { + vm_offset_t physical; + vm_offset_t virtual; +} pv_addr_t; + +extern pv_addr_t kernelstack; +#if NHYDRABUS > 0 +extern pv_addr_t hydrascratch; +#endif + +#define ALLOC_PAGE_HOOK(x, s) \ + x.va = virtual_start; \ + x.pte = (pt_entry_t *)pmap_pte(kernel_pmap, virtual_start); \ + virtual_start += s; + + +/* Local variables (not used outside this file) */ + +/* Local function prototypes (not used outside this file) */ + +pt_entry_t *pmap_pte __P((pmap_t /*pmap*/, vm_offset_t /*va*/)); +int pmap_page_index __P((vm_offset_t /*pa*/)); +void map_pagetable __P((vm_offset_t /*pagetable*/, vm_offset_t /*va*/, + vm_offset_t /*pa*/, unsigned int /*flags*/)); +void pmap_copy_on_write __P((vm_offset_t /*pa*/)); + +void bzero_page __P((vm_offset_t)); +void bcopy_page __P((vm_offset_t, vm_offset_t)); + + +/* Function to set the debug level of the pmap code */ + +void +pmap_debug(level) + int level; +{ + pmap_debug_level = level; + printf("pmap_debug: level=%d\n", pmap_debug_level); +} + + +/* + * Functions for manipluation pv_entry structures. These are used to keep a + * record of the mappings of virtual addresses and the associated physical + * pages. + */ + +struct pv_entry * +pmap_alloc_pv() +{ + struct pv_page *pvp; + struct pv_entry *pv; + int i; + +/* + * Do we have any free pv_entry structures left ? + * If not allocate a page of them + */ + + if (pv_nfree == 0) { + pvp = (struct pv_page *)kmem_alloc(kernel_map, NBPG); + if (pvp == 0) + panic("pmap_alloc_pv: kmem_alloc() failed"); + pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1]; + for (i = NPVPPG - 2; i; i--, pv++) + pv->pv_next = pv + 1; + pv->pv_next = 0; + pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1; + TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + pv = &pvp->pvp_pv[0]; + } else { + --pv_nfree; + pvp = pv_page_freelist.tqh_first; + if (--pvp->pvp_pgi.pgi_nfree == 0) { + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + } + pv = pvp->pvp_pgi.pgi_freelist; +#ifdef DIAGNOSTIC + if (pv == 0) + panic("pmap_alloc_pv: pgi_nfree inconsistent"); +#endif + pvp->pvp_pgi.pgi_freelist = pv->pv_next; + } + return pv; +} + +void +pmap_free_pv(pv) + struct pv_entry *pv; +{ + register struct pv_page *pvp; + + pvp = (struct pv_page *) trunc_page(pv); + switch (++pvp->pvp_pgi.pgi_nfree) { + case 1: + TAILQ_INSERT_TAIL(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + default: + pv->pv_next = pvp->pvp_pgi.pgi_freelist; + pvp->pvp_pgi.pgi_freelist = pv; + ++pv_nfree; + break; + case NPVPPG: + pv_nfree -= NPVPPG - 1; + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + kmem_free(kernel_map, (vm_offset_t)pvp, NBPG); + break; + } +} + + +void +pmap_collect_pv() +{ + struct pv_page_list pv_page_collectlist; + struct pv_page *pvp, *npvp; + struct pv_entry *ph, *ppv, *pv, *npv; + int s; + + TAILQ_INIT(&pv_page_collectlist); + + for (pvp = pv_page_freelist.tqh_first; pvp; pvp = npvp) { + if (pv_nfree < NPVPPG) + break; + npvp = pvp->pvp_pgi.pgi_list.tqe_next; + if (pvp->pvp_pgi.pgi_nfree > NPVPPG / 3) { + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + TAILQ_INSERT_TAIL(&pv_page_collectlist, pvp, pvp_pgi.pgi_list); + pv_nfree -= pvp->pvp_pgi.pgi_nfree; + pvp->pvp_pgi.pgi_nfree = -1; + } + } + + if (pv_page_collectlist.tqh_first == 0) + return; + + for (ph = &pv_table[npages - 1]; ph >= &pv_table[0]; ph--) { + if (ph->pv_pmap == 0) + continue; + s = splimp(); + for (ppv = ph; (pv = ppv->pv_next) != 0; ) { + pvp = (struct pv_page *) trunc_page(pv); + if (pvp->pvp_pgi.pgi_nfree == -1) { + pvp = pv_page_freelist.tqh_first; + if (--pvp->pvp_pgi.pgi_nfree == 0) { + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + } + npv = pvp->pvp_pgi.pgi_freelist; +#ifdef DIAGNOSTIC + if (npv == 0) + panic("pmap_collect_pv: pgi_nfree inconsistent"); +#endif + pvp->pvp_pgi.pgi_freelist = npv->pv_next; + *npv = *pv; + ppv->pv_next = npv; + ppv = npv; + } else + ppv = pv; + } + splx(s); + } + + for (pvp = pv_page_collectlist.tqh_first; pvp; pvp = npvp) { + npvp = pvp->pvp_pgi.pgi_list.tqe_next; + kmem_free(kernel_map, (vm_offset_t)pvp, NBPG); + } +} + + +/*__inline*/ int +pmap_enter_pv(pmap, va, pind, flags) + pmap_t pmap; + vm_offset_t va; + int pind; + u_int flags; +{ + register struct pv_entry *pv, *npv; + u_int s; + + if (!pv_table) + return(1); + + s = splimp(); + pv = &pv_table[pind]; + + if (pmap_debug_level >= 5) + printf("pmap_enter_pv: pind=%08x pv %08x: %08x/%08x/%08x\n", + pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next); + + if (pv->pv_pmap == NULL) { +/* + * No entries yet, use header as the first entry + */ + pv->pv_va = va; + pv->pv_pmap = pmap; + pv->pv_next = NULL; + pv->pv_flags = flags; + splx(s); + return(1); + } else { +/* + * There is at least one other VA mapping this page. + * Place this entry after the header. + */ +/*#ifdef DEBUG*/ + for (npv = pv; npv; npv = npv->pv_next) + if (pmap == npv->pv_pmap && va == npv->pv_va) { +/* + * HACK HACK HACK - The system vector page is wired in with pmap_enter() + * this mapping should be deleted during switch_exit() but at the moment it + * is not so a duplicate mapping is possible. For the moment we just updated + * flags and exit ... This should work as it is a special case. + */ + npv->pv_va = va; + npv->pv_pmap = pmap; + npv->pv_flags = flags; + printf("pmap_enter_pv: already in pv_tab pind=%08x pv %08x: %08x/%08x/%08x", + pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next); + splx(s); + return(0); +/* } else + panic("pmap_enter_pv: already in pv_tab pind=%08x pv %08x: %08x/%08x/%08x", + pind, (int) pv, (int) pv->pv_va, (int) pv->pv_pmap, (int) pv->pv_next);*/ + } +/*#endif*/ + npv = pmap_alloc_pv(); + npv->pv_va = va; + npv->pv_pmap = pmap; + npv->pv_flags = flags; + npv->pv_next = pv->pv_next; + pv->pv_next = npv; + } + splx(s); + return(0); +} + + +/* __inline*/ u_int +pmap_remove_pv(pmap, va, pind) + pmap_t pmap; + vm_offset_t va; + int pind; +{ + register struct pv_entry *pv, *npv; + u_int s; + u_int flags = 0; + + if (pv_table == NULL) + return(0); + +/* + * Remove from the PV table (raise IPL since we + * may be called at interrupt time). + */ + + s = splimp(); + pv = &pv_table[pind]; + +/* if (va == 0xefbfe000 || va == 0xefbff000 || va == 0xf1003000 || va == 0xf1004000) + printf("pmap_remove_pv(%08x, %08x, %d)\n", + (u_int)pmap, (u_int)va, pind);*/ + +/* + * 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 && va == pv->pv_va) { + npv = pv->pv_next; + if (npv) { + *pv = *npv; + + flags = npv->pv_flags; + + pmap_attributes[pind] |= flags & (PT_M | PT_H); + + pmap_free_pv(npv); + } else + pv->pv_pmap = NULL; + } else { + for (npv = pv->pv_next; npv; pv = npv, npv = npv->pv_next) { + if (pmap == npv->pv_pmap && va == npv->pv_va) + break; + } + if (npv) { + pv->pv_next = npv->pv_next; + + flags = npv->pv_flags; + pmap_attributes[pind] |= flags & (PT_M | PT_H); + + pmap_free_pv(npv); + } + } + splx(s); + return(flags); +} + + +/*__inline */ u_int +pmap_modify_pv(pmap, va, pind, bic_mask, eor_mask) + pmap_t pmap; + vm_offset_t va; + int pind; + u_int bic_mask; + u_int eor_mask; +{ + register struct pv_entry *pv, *npv; + u_int s; + u_int flags; + + if (pmap_debug_level >= 5) + printf("pmap_modify_pv: pmap=%08x va=%08x pi=%08x bic_mask=%08x eor_mask=%08x\n", + (int) pmap, (int) va, pind, bic_mask, eor_mask); + + if (!pv_table) + return(0); + +#ifdef DIAGNOSTIC + if (pind > 0x00010000 || pind < 0) { + traceback(); + panic("pmap_modify_pv: pind out of range pind = %08x va=%08x\n", pind, va); + } +#endif + + s = splimp(); + pv = &pv_table[pind]; + + if (pmap_debug_level >= 5) + printf("pmap_modify_pv: pind=%08x pv %08x: %08x/%08x/%08x/%08x ", + pind, (int) pv, (int)pv->pv_va, (int)pv->pv_pmap, (int)pv->pv_next, + pv->pv_flags); + +/* + * There is at least one VA mapping this page. + */ + + for (npv = pv; npv; npv = npv->pv_next) { + if (pmap == npv->pv_pmap && va == npv->pv_va) { + flags = npv->pv_flags; + npv->pv_flags = ((flags & ~bic_mask) ^ eor_mask); + if (pmap_debug_level >= 0) + printf("done flags=%08x\n", flags); + splx(s); + return(flags); + } + } + + if (pmap_debug_level >= 0) + printf("done.\n"); + splx(s); + return(0); +} + + +/* + * Used to map a range of physical addresses into kernel + * virtual address space. + * + * For now, VM is already on, we only need to map the + * specified memory. + */ + +vm_offset_t +pmap_map(va, spa, epa, prot) + vm_offset_t va, spa, epa; + int prot; +{ + while (spa < epa) { + pmap_enter(pmap_kernel(), va, spa, prot, FALSE); + va += NBPG; + spa += NBPG; + } + return(va); +} + + +/* + * void pmap_bootstrap(pd_entry_t *kernel_l1pt) + * + * bootstrap the pmap system. This is called from initarm and allows + * the pmap system to initailise any structures it requires. + * + * Currently this sets up the kernel_pmap that is statically allocated + * and also allocated virtual addresses for certain page hooks. + * Currently the only one page hook is allocated that is used + * to zero physical pages of memory. + * It also initialises the start and end address of the kernel data space. + */ + +void +pmap_bootstrap(kernel_l1pt) + pd_entry_t *kernel_l1pt; +{ + kernel_pmap = &kernel_pmap_store; + + kernel_pmap->pm_pdir = kernel_l1pt; + kernel_pmap->pm_pptpt = kernel_pt_table[2]; + simple_lock_init(&kernel_pmap->pm_lock); + kernel_pmap->pm_count = 1; + + virtual_start = VM_KERNEL_VIRTUAL_MIN; + virtual_end = VM_KERNEL_VIRTUAL_MAX; + + ALLOC_PAGE_HOOK(page_hook0, NBPG); + ALLOC_PAGE_HOOK(page_hook1, NBPG); + +/* The mem special device needs a virtual hook but we don't need a pte */ + + memhook = (char *)virtual_start; + virtual_start += NBPG; + + msgbufp = (struct msgbuf *)virtual_start; + msgbufpte = (pt_entry_t)pmap_pte(kernel_pmap, virtual_start); + virtual_start += round_page(sizeof(struct msgbuf)); + +#if PMAPDEBUG > 0 + printf("pmap_bootstrap: page_hook = V%08x pte = V%08x\n", + page_hook_addr0, page_hook_pte0); +#endif + +#if NHYDRABUS > 0 + hydrascratch.virtual = virtual_start; + virtual_start += NBPG; + + *((pt_entry_t *)pmap_pte(kernel_pmap, hydrascratch.virtual)) = L2_PTE_NC(hydrascratch.physical, AP_KRW); + tlbflush(); +#endif +} + + +/* + * void pmap_init(void) + * + * Initialize the pmap module. + * Called by vm_init() in vm/vm_init.c in order to initialise + * any structures that the pmap system needs to map virtual memory. + */ + +extern int physmem; + +void +pmap_init() +{ + vm_size_t s; + vm_offset_t addr; + +/* printf("pmap_init:\n");*/ + + npages = pmap_page_index(physical_freeend - 1) + 1; + printf("Number of pages to handle = %ld\n", npages); + +/* + * Set the available memory vars - These do not map to real memory + * addresses. They are used by ps for %mem calculations. + */ + +/* avail_start = pmap_page_index(physical_start) * NBPG; + avail_end = pmap_page_index(physical_freeend) * NBPG;*/ + avail_start = 0; + avail_end = physmem * NBPG; + + s = (vm_size_t) (sizeof(struct pv_entry) * npages + npages); +/* printf("pv_table size = %08x\n", s);*/ + s = round_page(s); + addr = (vm_offset_t) kmem_alloc(kernel_map, s); +/* printf("addr = %08x", addr);*/ + pv_table = (pv_entry_t) addr; + addr += sizeof(struct pv_entry) * npages; + pmap_attributes = (char *) addr; +/* printf(" attributes = %08x\n", pmap_attributes);*/ + +/* Ok currently there are some difficulties in allocating the process + * page directories on the fly. This is because the page directories + * are 16KB in size and there are no garentees that we can get 16KB + * continuous physical memory starting on a 16KB boundry from + * kmem_alloc() etc. + * + * For the moment a number of pages will have been reserved at the top + * of the physical memory map. + */ + + s = max_processes * sizeof(struct pmap *); + pagedirectories = (struct pmap **)kmem_alloc(kernel_map, s); + +#if PMAPDEBUG > 0 + printf("pagedirectories pointers at %08x\n", pagedirectories); +#endif + + bzero(pagedirectories, s); + printf("%dKB reserved for L1 page tables\n", + max_processes * NBPG * 4 / 1024); +} + + +/* + * Create and return a physical map. + * + * If the size specified for the map is zero, the map is an actual physical + * map, and may be referenced by the hardware. + * + * If the size specified is non-zero, the map will be used in software only, + * and is bounded by that size. + */ + +pmap_t +pmap_create(size) + vm_size_t size; +{ + register pmap_t pmap; + +/* + * Software use map does not need a pmap + */ + + if (size) return NULL; + +/* Allocate memory for pmap structure and zero it */ +/* XXX: I assume waiting here us ok */ + + pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK); + bzero(pmap, sizeof(*pmap)); + +/* Now init the machine part of the pmap */ + + pmap_pinit(pmap); + return(pmap); +} + + +/* + * Initialize a preallocated and zeroed pmap structure, + * such as one in a vmspace structure. + * + * MAJOR rewrite pending + */ + +int +pmap_allocpagedir(pmap) + struct pmap *pmap; +{ + int loop; + vm_offset_t pd; + pt_entry_t *pte; + + if (pmap_debug_level >= 0) + printf("pmap_allocpagedir: pmap=%08x\n", (int)pmap); + +/* + * No need to allocate page table space yet but we do need a + * valid page directory table. + */ + +/* Ok we need a 16KB aligned check of memory */ + + for (loop = 0; loop < max_processes; ++loop) { +/* Locate a free page directory */ + + if (pagedirectories[loop] == 0) { +/* Register the pmap for this page directory */ + + pagedirectories[loop] = pmap; + +/* Calculate the virtual address of the page directory */ + + pmap->pm_pdir = (pd_entry_t *) ((PAGE_DIRS_BASE + + PD_SIZE) + loop * PD_SIZE); + pd = (vm_offset_t)(pagetables_start + loop * PD_SIZE); +#if PMAP_DEBUG > 0 + printf("pmap_pinit: page dir at V%08x P%08x\n", + pmap->pm_pdir, pde); +#endif + +/* Calculate the address of the page table entry needed to map this page dir */ + + pte = (pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + + ((unsigned int)pmap->pm_pdir >> (PGSHIFT-2))); + +/* See if it is already mapped */ + + if (*(pte + 0) != 0 || *(pte + 1) != 0 + || *(pte + 2) != 0 || *(pte + 3) != 0) { + if (pmap_debug_level >= 0) + printf("pmap_pinit = V%08x (%08x) (%08x) (%08x) (%08x)\n", + (int) pte, *(pte+0), *(pte+1), + *(pte+2), *(pte+3)); + } + +/* Hook this page directory into the memory map */ + + *(pte + 0) = L2_PTE((pd + (0 * NBPG)) & PG_FRAME, AP_KRW); + *(pte + 1) = L2_PTE((pd + (1 * NBPG)) & PG_FRAME, AP_KRW); + *(pte + 2) = L2_PTE((pd + (2 * NBPG)) & PG_FRAME, AP_KRW); + *(pte + 3) = L2_PTE((pd + (3 * NBPG)) & PG_FRAME, AP_KRW); + +#if PMAP_DEBUG > 0 + printf("pmap_pinit = V%08x (%08x) (%08x) (%08x) (%08x)\n", + pte, *(pte+0), *(pte+1), *(pte+2), *(pte+3)); +#endif + +/* Flush the TLB so that the page directory is accessible */ + + tlbflush(); + +/* Clear it down */ + + bzero_pagedir(pmap->pm_pdir); + +/* Duplicate the kernel mapping i.e. all mappings 0xf0000000 + */ + + bcopy((char *)kernel_pmap->pm_pdir + 0x3c00, + (char *)pmap->pm_pdir + 0x3c00, 0x400); + +/* Borrow the kernel's system page as well */ + +/* pmap->pm_pdir[0] = kernel_pmap->pm_pdir[0]; + pmap->pm_pdir[1] = kernel_pmap->pm_pdir[1]; + pmap->pm_pdir[2] = kernel_pmap->pm_pdir[2]; + pmap->pm_pdir[3] = kernel_pmap->pm_pdir[3];*/ + +/*printf("L1 pagetable V%08x, P%08x\n", pmap->pm_pdir, pd);*/ + +/* Allocate a page table to map all the page tables for this pmap */ + + if (pmap->pm_vptpt == 0) { + pmap->pm_vptpt = kmem_alloc(kernel_map, NBPG); + pmap->pm_pptpt = pmap_extract(kernel_pmap, + pmap->pm_vptpt) & PG_FRAME; + } + +/* printf("pagetable = V%08x P%08x\n", pagetable, + pmap_extract(kernel_pmap, pagetable)); + printf("L1 addr = %08x\n", + &((pd_entry_t **)pmap->pm_pdir)[0xefc]); +*/ + +/* Wire in this page table */ + + pmap->pm_pdir[0xefc] = L1_PTE(pmap->pm_pptpt + 0x000); + pmap->pm_pdir[0xefd] = L1_PTE(pmap->pm_pptpt + 0x400); + pmap->pm_pdir[0xefe] = L1_PTE(pmap->pm_pptpt + 0x800); + pmap->pm_pdir[0xeff] = L1_PTE(pmap->pm_pptpt + 0xc00); + +/* printf("copying %08x\n", (PROCESS_PAGE_TBLS_BASE + + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0xf00)); +*/ + +/* + * Map the kernel page tables for 0xf0000000 + and 0x00000000 into + * the page table used to map the pmap's page tables + */ + + bcopy((char *)(PROCESS_PAGE_TBLS_BASE + + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0xf00), + (char *)pmap->pm_vptpt + 0xf00, 0x100); +/* bcopy((char *)(PROCESS_PAGE_TBLS_BASE + + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) + 0x000), + (char *)pmap->pm_vptpt + 0x000, 0x004);*/ + +/* Add a self reference reference */ + + *((pt_entry_t *)(pmap->pm_vptpt + 0xefc)) = + L2_PTE(pmap->pm_pptpt, AP_KRWUR); + +/* + if (pmap_debug_level >= 0) { + printf("::::%08x %08x\n", + ((pt_entry_t *)(pmap->pm_vptpt + 0xefc)), + &((pt_entry_t *)pmap->pm_vptpt)[0xefc >> 2]); + } +*/ + +/* + * Now we get nasty. We need to map the page directory to a standard address + * in the memory map. This means we can easily find the active page directory. + * This is needed by pmap_pte to hook in an alternate pmap's page tables. + * This means that a page table is needed in each process to map this memory + * as the kernel tables cannot be used as they are shared. + * The HACK is to borrow some of the space in the page table that maps all + * the pmap page tables. + * Mapping a 16KB page directory into that means that a 16MB chunk of the + * memory map will no longer be mappable. + * Eventually a chuck of user space (at the top end) could be reserved for + * this but for the moment the 16MB block at 0xf5000000 is not allocated and + * so has become reserved for this processes. + */ + + *((pt_entry_t *)(pmap->pm_vptpt + 0xf50)) = + L2_PTE(pd + 0x0000, AP_KRW); + *((pt_entry_t *)(pmap->pm_vptpt + 0xf54)) = + L2_PTE(pd + 0x1000, AP_KRW); + *((pt_entry_t *)(pmap->pm_vptpt + 0xf58)) = + L2_PTE(pd + 0x2000, AP_KRW); + *((pt_entry_t *)(pmap->pm_vptpt + 0xf5c)) = + L2_PTE(pd + 0x3000, AP_KRW); + + pmap->pm_count = 1; + simple_lock_init(&pmap->pm_lock); + return(0); + } + } + + return(1); +} + + +/* + * Initialize a preallocated and zeroed pmap structure, + * such as one in a vmspace structure. + * + * MAJOR rewrite pending + */ + +void +pmap_pinit(pmap) + struct pmap *pmap; +{ + if (pmap_debug_level >= 0) + printf("pmap_pinit: pmap=%08x\n", (int)pmap); + +/* Keep looping until we succeed in allocating a page directory */ + + while (pmap_allocpagedir(pmap) != 0) { +/* + * Ok all the allocated L1 page tables are in use so we should sleep for + * a while. We only sleep for 10 secs at most. Although we will be wakened + * if a slot became available it could be possible for things to jamup with + * every process waiting on a process that is waiting for a page table. + * If we time out then it means that all the page tables are in use and + * there has not be a process termination in 10 secs i.e. possible deadlock + */ + +/* + * The snag with this routine is it is not allowed to fail. If we + * do detect a possible deadlock then we can report it. The Q is what to + * do next. We could start randomly killing processes or process groups. + * Since this process is only part formed it is not easy to kill. The + * best thing may be to kill it parent. + */ + +/* What we should do here is start swapping out processes. That way + * the page directory for the process will be released. + * The pagedaemon will swap out processes but only in low memory conditions. + * Lack of page directories does not count so we will have to swapout + * processes ourselves. + */ + + if (tsleep((caddr_t)pagedirectories, PZERO, "l1ptwait", 1000) + == EWOULDBLOCK) + printf("Warning: Possible process deadlock due to shortage of L1 page tables\n"); + } +} + + +/* + * Retire the given physical map from service. + * Should only be called if the map contains no valid mappings. + */ + +void +pmap_destroy(pmap) + pmap_t pmap; +{ + int count; + + if (pmap_debug_level >= 0) + printf("pmap_destroy: pmap = %08x\n", (int) pmap); + + if (pmap == NULL) + return; + + simple_lock(&pmap->pm_lock); + count = --pmap->pm_count; + simple_unlock(&pmap->pm_lock); + if (count == 0) { + pmap_release(pmap); + free((caddr_t)pmap, M_VMPMAP); + } else + printf("pmap_destroy: pm_count=%d\n", count); +} + + +void +pmap_freepagedir(pmap) + register pmap_t pmap; +{ + int index; + + index = (((u_int) pmap->pm_pdir) - PAGE_DIRS_BASE - PD_SIZE) / PD_SIZE; + if (pagedirectories[index] != pmap) + panic("pm_pdir inconsistancy found\n"); + + pagedirectories[index] = 0; + +/* Wake up any sleeping processes waiting for a l1 page table */ + + wakeup((caddr_t)pagedirectories); +} + + +/* + * Release any resources held by the given physical map. + * Called when a pmap initialized by pmap_pinit is being released. + * Should only be called if the map contains no valid mappings. + */ + +void +pmap_release(pmap) + register pmap_t pmap; +{ + if (pmap_debug_level >= 0) + printf("pmap_release: pmap=%08x\n", (int) pmap); + + if (pmap->pm_count != 1) /* XXX: needs sorting */ + panic("pmap_release count"); + +/* Free the memory used for the page table mapping */ + + kmem_free(kernel_map, (vm_offset_t)pmap->pm_vptpt, NBPG); + + pmap_freepagedir(pmap); +} + + +/* + * void pmap_reference(pmap_t pmap) + * + * Add a reference to the specified pmap. + */ + +void +pmap_reference(pmap) + pmap_t pmap; +{ + if (pmap == NULL) + return; + + simple_lock(&pmap->pm_lock); + pmap->pm_count++; + simple_unlock(&pmap->pm_lock); +} + + +/* + * void pmap_virtual_space(vm_offset_t *start, vm_offset_t *end) + * + * Return the start and end addresses of the kernel's virtual space. + * These values are setup in pmap_bootstrap and are updated as pages + * are allocated. + */ + +void +pmap_virtual_space(start, end) + vm_offset_t *start; + vm_offset_t *end; +{ + *start = virtual_start; + *end = virtual_end; +} + + +/* + * void pmap_pageable(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, + * boolean_t pageable) + * + * Make the specified pages (by pmap, offset) pageable (or not) as requested. + * + * A page which is not pageable may not take a fault; therefore, its + * page table entry must remain valid for the duration. + * + * This routine is merely advisory; pmap_enter will specify that these + * pages are to be wired down (or not) as appropriate. + */ + +void +pmap_pageable(pmap, sva, eva, pageable) + pmap_t pmap; + vm_offset_t sva; + vm_offset_t eva; + boolean_t pageable; +{ +/* + * Ok we can only make the specified pages pageable under the following + * conditions. + * 1. pageable == TRUE + * 2. eva = sva + NBPG + * 3. the pmap is the kernel_pmap ??? - got this from i386/pmap.c ?? + * + * right this will get called when making pagetables pageable + */ + + if (pmap_debug_level >= 5) + printf("pmap_pageable: pmap=%08x sva=%08x eva=%08x p=%d\n", + (int) pmap, (int) sva, (int) eva, (int) pageable); + + if (pmap == kernel_pmap && pageable && eva == (sva + NBPG)) { + vm_offset_t pa; + pt_entry_t *pte; + + pte = pmap_pte(pmap, sva); + if (!pte) + return; + if (!pmap_pte_v(pte)) + return; + pa = pmap_pte_pa(pte); + +/* + * Mark it unmodified to avoid pageout + */ + pmap_clear_modify(pa); + + if (pmap_debug_level >= 0) + printf("pmap_pageable: ermm can't really do this yet (%08x)!\n", + (int) sva); + } +} + + +void +pmap_activate(pmap, pcbp) + pmap_t pmap; + struct pcb *pcbp; +{ + if (pmap != NULL) { +#if PMAP_DEBUG > 1 + printf("pmap_activate: pagedir = V%08x\n", pmap->pm_pdir); +#endif + pcbp->pcb_pagedir = (pd_entry_t *)pmap_extract(kernel_pmap, + (vm_offset_t)pmap->pm_pdir); + if (pmap_debug_level >= 0) + printf("pmap_activate: pmap=%08x pcb=%08x pdir=%08x l1=%08x\n", + (int) pmap, (int) pcbp, (int) pmap->pm_pdir, + (int) pcbp->pcb_pagedir); +#if PMAP_DEBUG > 1 + printf("pmap_activate: pagedir = P%08x\n", pcbp->pcb_pagedir); +#endif + + if (pmap == &curproc->p_vmspace->vm_pmap) { + printf("pmap: Setting TTB\n"); + setttb((u_int)pcbp->pcb_pagedir); + } + pmap->pm_pdchanged = FALSE; + } +#if PMAP_DEBUG > 1 + printf("pmap_activate: done\n"); +#endif +} + + +/* + * void pmap_zero_page(vm_offset_t phys) + * + * zero fill the specific physical page. To do this the page must be + * mapped into the virtual memory. Then bzero can be used to zero it. + */ + +void +pmap_zero_page(phys) + vm_offset_t phys; +{ +#if PMAPDEBUG > 4 + printf("pmap_zero_page: pa = %08x", phys); +#endif + +/* Hook the physical page into the memory at our special hook point */ + + *page_hook0.pte = L2_PTE(phys & PG_FRAME, AP_KRW); + +/* Flush the tlb - eventually this can be a purge tlb */ + + tlbflush(); + +/* Zero the memory */ + +#if PMAPDEBUG > 4 + printf(" zeroing..."); +#endif + bzero_page(page_hook0.va); + idcflush(); +#if PMAPDEBUG > 4 + printf("done.\n"); +#endif +} + + +/* + * void pmap_copy_page(vm_offset_t src, vm_offset_t dest) + * + * pmap_copy_page copies the specified page by mapping it into virtual + * memory and using bcopy to copy its contents. + */ + +void +pmap_copy_page(src, dest) + vm_offset_t src; + vm_offset_t dest; +{ + if (pmap_debug_level >= -1) + printf("pmap_copy_page: src=P%08x dest=P%08x\n", + (int) src, (int) dest); + +/* Hook the physical page into the memory at our special hook point */ + + *page_hook0.pte = L2_PTE(src & PG_FRAME, AP_KRW); + *page_hook1.pte = L2_PTE(dest & PG_FRAME, AP_KRW); + +/* Flush the tlb - eventually this can be a purge tlb */ + + tlbflush(); + +/* Copy the memory */ + + bcopy_page(page_hook0.va, page_hook1.va); + idcflush(); +} + + +/* + * int pmap_next_page(vm_offset_t *addr) + * + * Allocate another physical page returning true or false depending + * on whether a page could be allocated. + * + * MARK - This needs optimising ... look at the amiga version + */ + +int +pmap_next_page(addr) + vm_offset_t *addr; +{ + if (physical_freestart == physical_freeend) { + if (pmap_debug_level >= 0) + printf("pmap_next_page: Trying to allocate beyond memory\n"); + return(FALSE); + } + + pmap_zero_page(physical_freestart); + *addr = physical_freestart; + --free_pages; + + physical_freestart += NBPG; + if (physical_freestart == (bootconfig.dram[physical_memoryblock].address + + bootconfig.dram[physical_memoryblock].pages * NBPG)) { + ++physical_memoryblock; + if (bootconfig.dram[physical_memoryblock].address != 0) + physical_freestart = bootconfig.dram[physical_memoryblock].address; + } + +#if PMAPDEBUG > 10 + printf("pmap_next_page: Allocated physpage %08x\n", *addr); + printf("pmap_next_page: Next page is %08x\n", physical_freestart); +#endif + + return(TRUE); +} + + +/* + * int pmap_next_phys_page(vm_offset_t *addr) + * + * Allocate another physical page returning true or false depending + * on whether a page could be allocated. + */ + +vm_offset_t +pmap_next_phys_page(addr) + vm_offset_t addr; + +{ + int loop; + + if (addr < bootconfig.dram[0].address) + return(bootconfig.dram[0].address); + + loop = 0; + + while (bootconfig.dram[loop].address != 0 + && addr > (bootconfig.dram[loop].address + bootconfig.dram[loop].pages * NBPG)) + ++loop; + + if (bootconfig.dram[loop].address == 0) + return(0); + + addr += NBPG; + + if (addr >= (bootconfig.dram[loop].address + bootconfig.dram[loop].pages * NBPG)) { + if (bootconfig.dram[loop + 1].address == 0) + return(0); + addr = bootconfig.dram[loop + 1].address; + } + + return(addr); +} + + +/* + * unsigned int pmap_free_pages(void) + * + * Returns the number of free pages the system has. + * free_pages is set up during initarm and decremented every time a page + * is allocated. + */ + +unsigned int +pmap_free_pages() +{ +#if PMAPDEBUG > 0 + printf("pmap_free_pages: %08x pages free\n", free_pages); +#endif + return(free_pages); +} + + +/* + * int pmap_page_index(vm_offset_t pa) + * + * returns a linear index to the physical page. This routine has to take + * a physical address and work out the corresponding physical page number. + * There does not appear to be a simple way of doing this as the memory + * is split into a series of blocks. We search each block to determine + * which block the physical page is. Once we have scanned the blocks to + * this point we can calculate the physical page index. + */ + +int +pmap_page_index(pa) + vm_offset_t pa; +{ + int index; + int loop; + +#if PMAPDEBUG > 0 + printf("pmap_page_index: pa = P%08x", (int)pa); +#endif + + if (pa < bootconfig.dram[0].address) + return(-1); + + index = 0; + for (loop = 0; loop < bootconfig.dramblocks; ++loop) { + if (pa < (bootconfig.dram[loop].address + + bootconfig.dram[loop].pages * NBPG)) { + index += (pa - bootconfig.dram[loop].address) >> PGSHIFT; +#if PMAPDEBUG > 0 + printf(" index = %08x\n" ,index); +#endif +#ifdef DIAGNOSTIC + if (index > 0x00010000 || index < 0) + printf("pmap_page_index: pa = %08x\n", (int)pa); +#endif + return(index); + } else + index += bootconfig.dram[loop].pages; + } +#if PMAPDEBUG > 0 + printf(" index = Invalid\n"); +#endif + if (pmap_debug_level >= 1) + printf("page invalid - no index %08x\n", (int) pa); + return(-1); +} + + +void +pmap_remove(pmap, sva, eva) + struct pmap *pmap; + vm_offset_t sva; + vm_offset_t eva; +{ + register pt_entry_t *pte = NULL; + vm_offset_t pa; + int pind; + int flush = 0; + + idcflush(); + + if (pmap_debug_level >= 0) + printf("pmap_remove: pmap=%08x sva=%08x eva=%08x\n", (int) pmap, + (int) sva, (int) eva); + + sva &= PG_FRAME; + eva &= PG_FRAME; + +/* + * We need to acquire a pointer to a page table page before entering + * the following loop. + */ + + while (sva < eva) { + pte = pmap_pte(pmap, sva); + if (pte) break; + sva = (sva & PD_MASK) + NBPD; + } + + while (sva < eva) { +/* only check once in a while */ + if ((sva & PT_MASK) == 0) { + if (!pmap_pde_v(pmap_pde(pmap, sva))) { +/* We can race ahead here, to the next pde. */ + sva += NBPD; + pte += arm_byte_to_page(NBPD); + continue; + } + } + + if (!pmap_pte_v(pte)) + goto next; + + flush = 1; + +/* + * Update statistics + */ + +/* Wired bit done below */ + +/* + if (pmap_pte_w(pte)) + pmap->pm_stats.wired_count--; +*/ + pmap->pm_stats.resident_count--; + + pa = pmap_pte_pa(pte); + +/* + * Invalidate the PTEs. + * XXX: should cluster them up and invalidate as many + * as possible at once. + */ + +#ifdef DEBUG + if (pmapdebug & PDB_REMOVE) + printf("remove: inv pte at %x(%x) ", pte, *pte); +#endif + + if ((pind = pmap_page_index(pa)) != -1) { +/* pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/ +/* pmap_remove_pv will update pmap_attributes */ +#ifdef DIAGNOSTIC + if (pind > 0x00010000 || pind < 0) { + printf("eerk ! pind=%08x pa=%08x\n", pind, (int) pa); + panic("The axe has fallen, were dead\n"); + } +#endif + if (pmap_remove_pv(pmap, sva, pind) & PT_W) + pmap->pm_stats.wired_count--; + } + + *pte = 0; +next: + sva += NBPG; + pte++; + } + + if (flush) + pmap_update(); +} + + +/* + * Routine: pmap_remove_all + * Function: + * Removes this physical page from + * all physical maps in which it resides. + * Reflects back modify bits to the pager. + */ + +void +pmap_remove_all(pa) + vm_offset_t pa; +{ + struct pv_entry *ph, *pv, *npv; + register pmap_t pmap; + register pt_entry_t *pte; + int pind; + int s; + + idcflush(); + if (pmap_debug_level >= 0) + printf("pmap_remove_all: pa=%08x ", (int) pa); +#ifdef DEBUG + if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) + printf("pmap_remove_all(%x)", (int) pa); + /*pmap_pvdump(pa);*/ +#endif + + if ((pind = pmap_page_index(pa)) == -1) { + if (pmap_debug_level >= 0) + printf("no accounting\n"); + return; + } + + s = splimp(); + pv = ph = &pv_table[pind]; + + if (ph->pv_pmap == NULL) { + if (pmap_debug_level >= 0) + printf("free page\n"); + splx(s); + return; + } + + while (pv) { + pmap = pv->pv_pmap; + pte = pmap_pte(pmap, pv->pv_va); + + if (pmap_debug_level >= 0) + printf("[%08x,%08x,%08x,%08x] ", (int) pmap, *pte, + (int) pv->pv_va, pv->pv_flags); + +#ifdef DEBUG + if (!pte || !pmap_pte_v(pte) || pmap_pte_pa(pte) != pa) + panic("pmap_remove_all: bad mapping"); +#endif + +/* + * Update statistics + */ +/* Wired bit done below */ + +/* + if (pmap_pte_w(pte)) + pmap->pm_stats.wired_count--; +*/ + pmap->pm_stats.resident_count--; + + if (pv->pv_flags & PT_W) + pmap->pm_stats.wired_count--; + +/* + * Invalidate the PTEs. + * XXX: should cluster them up and invalidate as many + * as possible at once. + */ +#ifdef DEBUG + if (pmapdebug & PDB_REMOVE) + printf("remove: inv pte at %x(%x) ", pte, *pte); +#endif + +#ifdef needednotdone +reduce wiring count on page table pages as references drop +#endif + +/* + * Update saved attributes for managed page + */ + +/* pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/ + pmap_attributes[pind] |= pv->pv_flags & (PT_M | PT_H); + + *pte = 0; + + npv = pv->pv_next; + if (pv == ph) + ph->pv_pmap = NULL; + else + pmap_free_pv(pv); + pv = npv; + } + splx(s); + + if (pmap_debug_level >= 0) + printf("done\n"); + + pmap_update(); +} + + +/* + * Set the physical protection on the specified range of this map as requested. + */ + +void +pmap_protect(pmap, sva, eva, prot) + pmap_t pmap; + vm_offset_t sva; + vm_offset_t eva; + vm_prot_t prot; +{ + register pt_entry_t *pte = NULL; + register int armprot; + int flush = 0; + vm_offset_t pa; + int pind; + + if (pmap_debug_level >= 0) + printf("pmap_protect: pmap=%08x %08x->%08x %08x\n", + (int) pmap, (int) sva, (int) eva, prot); + + if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + if (prot & VM_PROT_WRITE) + return; + + sva &= PG_FRAME; + eva &= PG_FRAME; + +/* + * We need to acquire a pointer to a page table page before entering + * the following loop. + */ + + while (sva < eva) { + pte = pmap_pte(pmap, sva); + if (pte) + break; + sva = (sva & PD_MASK) + NBPD; + } + + while (sva < eva) { +/*printf("pmap_protect: sva = %08x eva=%08x\n", sva, eva);*/ +/* only check once in a while */ + if ((sva & PT_MASK) == 0) { + if (!pmap_pde_v(pmap_pde(pmap, sva))) { +/* We can race ahead here, to the next pde. */ + sva += NBPD; + pte += arm_byte_to_page(NBPD); + continue; + } + } + + if (!pmap_pte_v(pte)) + goto next; + + flush = 1; + + armprot = 0; +/* + if (prot & VM_PROT_WRITE) + armprot |= PT_AP(AP_W); +*/ + if (sva < VM_MAXUSER_ADDRESS) + armprot |= PT_AP(AP_U); + else if (sva < VM_MAX_ADDRESS) + armprot |= PT_AP(AP_W); /* XXX Ekk what is this ? */ + *pte = (*pte & 0xfffff00f) | armprot; + + pa = pmap_pte_pa(pte); + +/* Get the physical page index */ + + if ((pind = pmap_page_index(pa)) == -1) + panic("pmap_protect: pmap_page_index failed for pte %08x\n", pte); + +/* Clear write flag */ + + pmap_modify_pv(pmap, sva, pind, PT_Wr, 0); +next: + sva += NBPG; + pte++; + } + + if (flush) + pmap_update(); +} + + +/* + * void pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, + * boolean_t wired) + * + * Insert the given physical page (p) at + * the specified virtual address (v) in the + * target physical map with the protection requested. + * + * If specified, the page will be wired down, meaning + * that the related pte can not be reclaimed. + * + * 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. + */ + +void +pmap_enter(pmap, va, pa, prot, wired) + pmap_t pmap; + vm_offset_t va; + vm_offset_t pa; + vm_prot_t prot; + boolean_t wired; +{ + register pt_entry_t *pte; + register u_int npte; + int pind = -2; + u_int cacheable = 0; + +#if PMAP_DEBUG > 5 + printf("pmap_enter: V%08x P%08x in pmap V%08x\n", va, pa, pmap); +#endif + + if (pmap_debug_level >= 5) + printf("pmap_enter: V%08x P%08x in pmap V%08x prot=%08x, wired = %d\n", + (int) va, (int) pa, (int) pmap, prot, wired); + +/* Valid pmap ? */ + + if (pmap == NULL) + return; + +/* Valid address ? */ + + if (va >= VM_KERNEL_VIRTUAL_MAX) + panic("pmap_enter: too big"); + +/* + * Get a pointer to the pte for this virtual address. We should always have + * a page table ready for us so if the page table is missing .... + */ + + pte = pmap_pte(pmap, va); + if (!pte) { + printf("pmap_enter: pde = %08x\n", (u_int) pmap_pde(pmap, va)); + printf("pmap_enter: pte = %08x\n", (u_int) pmap_pte(pmap, va)); + panic("Failure 01 in pmap_enter (V%08x P%08x)\n", (u_int) va, (u_int) pa); + } + +/* More debugging info */ + + if (pmap_debug_level >= 5) { + printf("pmap_enter: pte for V%08x = V%08x", (u_int) va, (u_int) pte); + printf(" (%08x)\n", *pte); + } + +/* Is the pte valid ? If so then this page is already mapped */ + + if (pmap_pte_v(pte)) + { + vm_offset_t opa; + +/* Get the physical address of the current page mapped */ + + opa = pmap_pte_pa(pte); + +/* Are we mapping the same page ? */ + + if (opa == pa) + { + int flags; + +/* All we must be doing is changing the protection */ + + if (pmap_debug_level >= 0) + printf("Failure 02 in pmap_enter (V%08x P%08x)\n", (u_int) va, (u_int) pa); + + pind = pmap_page_index(pa); + cacheable = (*pte) & PT_C; + +/* Has the wiring changed ? */ + + flags = pmap_modify_pv(pmap, va, pind, 0, 0) & PT_W; + if (flags && !wired) + --pmap->pm_stats.wired_count; + else if (!flags && wired) + ++pmap->pm_stats.wired_count; + + } + else + { +/* We are replacing the page with a new one. */ + + idcflush(); + + if (pmap_debug_level >= 0) + printf("Failure 03 in pmap_enter (V%08x P%08x P%08x)\n", + (int) va, (int) pa, (int) opa); + +/* + * If it is part of our managed memory then we must remove it from the PV list + */ + + if ((pind = pmap_page_index(opa)) != -1) + { +/* pmap_attributes[pind] |= *pte & (PG_M | PG_U);*/ +/* pmap_remove_pv updates pmap_attribute */ +/* Adjust the wiring count if the page was wired */ + if (pmap_remove_pv(pmap, va, pind) & PT_W) + --pmap->pm_stats.wired_count; + + } + +/* Update the wiring stats for the new page */ + + if (wired) + ++pmap->pm_stats.wired_count; + +/* + * Enter on the PV list if part of our managed memory + */ + if ((pind = pmap_page_index(pa)) != -1) + { + if (pmap_enter_pv(pmap, va, pind, 0)) + cacheable = PT_C; + } + else + /* + * Assumption: if it is not part of our managed memory + * then it must be device memory which may be volatile. + * The video memory may be double mapped but should only be accesses from + * one address at a time. Will be double mapped by the X server and + * we must keep the cache on for performance. + */ + if (pa >= videomemory.vidm_pbase + && pa < videomemory.vidm_pbase + videomemory.vidm_size) + cacheable = PT_C; + else + cacheable = 0; + } + } + else + { +/* pte is not valid so we must be hooking in a new page */ + + idcflush(); + + ++pmap->pm_stats.resident_count; + if (wired) + ++pmap->pm_stats.wired_count; + +/* + * Enter on the PV list if part of our managed memory + */ + if ((pind = pmap_page_index(pa)) != -1) + { + if (pmap_enter_pv(pmap, va, pind, 0)) + cacheable = PT_C; + } + else + /* + * Assumption: if it is not part of our managed memory + * then it must be device memory which may be volatile. + */ + { + /* + * Bit of a hack really as all doubly mapped addresses should be uncached + * as the cache works on virtual addresses not physical ones. + * However for the video memory this kill performance and the screen + * should be locked anyway so there should only be one process trying + * to write to it at once. + */ + + if (pa >= videomemory.vidm_pbase + && pa < videomemory.vidm_pbase + videomemory.vidm_size) + cacheable = PT_C; + else + cacheable = 0; + if (pmap_debug_level > 0) + printf("pmap_enter: non-managed memory mapping va=%08x pa=%08x\n", + (int) va, (int) pa); + } + } + +/* Construct the pte, giving the correct access */ + + npte = (pa & PG_FRAME) | cacheable | PT_B; + +if (va == 0 && (prot & VM_PROT_WRITE)) + printf("va=0 prot=%d\n", prot); + +/*if (va < VM_MIN_ADDRESS) + printf("pmap_enter: va=%08x\n", (u_int)va);*/ + +/* if (va >= VM_MIN_ADDRESS && va < VM_MAXUSER_ADDRESS && !wired) + npte |= L2_INVAL; + else*/ + npte |= L2_SPAGE; + +/************ not sure about wired *************/ + + if (prot & VM_PROT_WRITE) + npte |= PT_AP(AP_W); + + if (va >= VM_MIN_ADDRESS) { + if (va < VM_MAXUSER_ADDRESS) + npte |= PT_AP(AP_U); + else if (va < VM_MAX_ADDRESS) /* This must be a page table */ + npte |= PT_AP(AP_W); + } + + if (va >= VM_MIN_ADDRESS && va < VM_MAXUSER_ADDRESS && pind != -1) /* Inhibit write access for user pages */ + *pte = (npte & ~PT_AP(AP_W)); + else + *pte = npte; + + if (*pte == 0) + { + panic("oopss: *pte = 0 in pmap_enter() npte=%08x\n", npte); + } + + if (pind != -1) + { + int flags = 0; + + if (wired) flags |= PT_W; + flags |= npte & (PT_Wr | PT_Us); +/* if (flags & PT_Wr) flags |= PT_M;*/ + #ifdef DIAGNOSTIC + if (pind > 0x00010000 || pind < 0) + { + printf("pind=%08x\n", pind); + } + #endif +/* pmap_modify_pv(pmap, va, pind, 0xffffffff, flags);*/ + pmap_modify_pv(pmap, va, pind, ~(PT_Wr | PT_Us | PT_W), flags); + } + +/* + * If we are mapping in a page to where the page tables are store then we + * must be mapping a page table. In this case we should also map the + * page table into the page directory + */ + + if (va >= 0xefc00000 && va < 0xf0000000) + { + if (pmap_debug_level >= 0) + { + printf("Page being mapped in the page table area\n"); + printf("page P%08x will be installed in the L1 table as well\n", + (int) pa); + } + pa = pa & PG_FRAME; + pmap->pm_pdir[((va - 0xefc00000)>>10)+0] = L1_PTE(pa + 0x000); + pmap->pm_pdir[((va - 0xefc00000)>>10)+1] = L1_PTE(pa + 0x400); + pmap->pm_pdir[((va - 0xefc00000)>>10)+2] = L1_PTE(pa + 0x800); + pmap->pm_pdir[((va - 0xefc00000)>>10)+3] = L1_PTE(pa + 0xc00); + } + +/* Better flush the TLB ... */ + + tlbflush(); + +#if PMAP_DEBUG > 5 + printf("pmap_enter: pte = V%08x %08x\n", pte, *pte); +#endif + } + + +/* + * pmap_page_protect: + * + * Lower the permission for all mappings to a given page. + */ + +void +pmap_page_protect(phys, prot) + vm_offset_t phys; + vm_prot_t prot; +{ + if (pmap_debug_level >= 0) + printf("pmap_page_protect: pa=%08x, prot=%d\n", (int) phys, prot); + + switch(prot) { + case VM_PROT_READ: + case VM_PROT_READ|VM_PROT_EXECUTE: + pmap_copy_on_write(phys); + break; + + case VM_PROT_ALL: + break; + + default: + pmap_remove_all(phys); + break; + } +} + + +/* + * Routine: pmap_change_wiring + * Function: Change the wiring attribute for a map/virtual-address + * pair. + * In/out conditions: + * The mapping must already exist in the pmap. + */ + +void +pmap_change_wiring(pmap, va, wired) + pmap_t pmap; + vm_offset_t va; + boolean_t wired; +{ + register pt_entry_t *pte; + vm_offset_t pa; + int pind; + int current; + +/* Get the pte */ + + pte = pmap_pte(pmap, va); + if (!pte) + return; + +/* Extract the physical address of the page */ + + pa = pmap_pte_pa(pte); + +/* Get the physical page index */ + + if ((pind = pmap_page_index(pa)) == -1) + return; + +/* Update the wired bit in the pv entry for this page. */ + + current = pmap_modify_pv(pmap, va, pind, PT_W, wired ? PT_W : 0) & PT_W; + +/* Update the statistics */ + + if (wired & !current) + pmap->pm_stats.wired_count++; + else if (!wired && current) + pmap->pm_stats.wired_count--; +} + + +/* + * pt_entry_t *pmap_pte(pmap_t pmap, vm_offset_t va) + * + * Return the pointer to a page table entry corresponding to the supplied + * virtual address. + * + * The page directory is first checked to make sure that a page table + * for the address in question exists and if it does a pointer to the + * entry is returned. + * + * The way this works is that that the kernel page tables are mapped + * into the memory map at 0xf3c00000 to 0xf3fffffff. This allows + * page tables to be located quickly. + */ + +pt_entry_t * +pmap_pte(pmap, va) + pmap_t pmap; + vm_offset_t va; +{ + pd_entry_t *pde; + pt_entry_t *ptp; + pt_entry_t *result; + int s; + +/* The pmap must be valid */ + + if (!pmap) + return(NULL); + +/* Return the address of the pte */ + +#if PMAP_DEBUG > 10 + printf("pmap_pte: pmap=V%08x va=V%08x pde = V%08x", pmap, va, + pmap_pde(pmap, va)); + printf(" (%08x)\n", *(pmap_pde(pmap, va))); +#endif + + if (pmap_debug_level >= 10) { + printf("pmap_pte: pmap=V%08x va=V%08x pde = V%08x", (int) pmap, + (int) va, (int) pmap_pde(pmap, va)); + printf(" (%08x)\n", *(pmap_pde(pmap, va))); + } + +/* Do we have a valid pde ? If not we don't have a page table */ + + if (!pmap_pde_v(pmap_pde(pmap, va))) { + if (pmap_debug_level >= 0) + printf("pmap_pte: failed - pde = %08x\n", (int) pmap_pde(pmap, va)); + return(NULL); + } + + if (pmap_debug_level >= 10) + printf("pmap pagetable = P%08x current = P%08x\n", (int) pmap->pm_pptpt, + (*((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + + (PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2))+0xefc)) & PG_FRAME)); + + if (pmap == kernel_pmap || pmap->pm_pptpt + == (*((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + + ((PROCESS_PAGE_TBLS_BASE >> (PGSHIFT-2)) & ~3)+0xefc)) & PG_FRAME)) { + ptp = (pt_entry_t *)PROCESS_PAGE_TBLS_BASE; + } else { + pde = (pd_entry_t *)CURRENT_PAGEDIR_BASE; + idcflush(); + +/*printf("\x1b[33mpde=%08x kernel pmap=%08x pmap=%08x\x1b[0m\n", pde, kernel_pmap, pmap);*/ + ptp = (pt_entry_t *)ALT_PAGE_TBLS_BASE; + pde[(ALT_PAGE_TBLS_BASE >> 20) + 0] = L1_PTE(pmap->pm_pptpt + 0x000); + pde[(ALT_PAGE_TBLS_BASE >> 20) + 1] = L1_PTE(pmap->pm_pptpt + 0x400); + pde[(ALT_PAGE_TBLS_BASE >> 20) + 2] = L1_PTE(pmap->pm_pptpt + 0x800); + pde[(ALT_PAGE_TBLS_BASE >> 20) + 3] = L1_PTE(pmap->pm_pptpt + 0xc00); + + *((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + ((PROCESS_PAGE_TBLS_BASE + >> (PGSHIFT-2)) & ~3) + (ALT_PAGE_TBLS_BASE >> 20))) = + L2_PTE(pmap->pm_pptpt, AP_KRWUR); + tlbflush(); + } + if (pmap_debug_level >= 10) + printf("page tables base = %08x\n", (int) ptp); + result = (pt_entry_t *)((char *)ptp + ((va >> (PGSHIFT-2)) & ~3)); + return(result); +} + + +/* + * Routine: pmap_extract + * Function: + * Extract the physical page address associated + * with the given map/virtual_address pair. + */ + +vm_offset_t +pmap_extract(pmap, va) + pmap_t pmap; + vm_offset_t va; +{ + register pt_entry_t *pte; + register vm_offset_t pa; +/* + printf("pmap_extract: pmap = %08x va = V%08x\n", pmap, va); +*/ + +/* + * Get the pte for this virtual address. If there is no pte then there is + * no page table etc. + */ + + pte = pmap_pte(pmap, va); + if (!pte) + return(0); + +/* Is the pte valid ? If not then no paged is actually mapped here */ + + if (!pmap_pte_v(pte)) + return(0); + +/* Extract the physical address from the pte */ + + pa = pmap_pte_pa(pte); + +/* printf("pmap_extract: pa = P%08x\n", (pa | (va & ~PG_FRAME))); */ + + return(pa | (va & ~PG_FRAME)); +} + + +#if 0 /* Macro in pmap.h */ +pt_entry_t * +vtopte(va) + vm_offset_t va; +{ + return((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + + (arm_byte_to_page(va) << 2))); +} +#endif + +#if 0 /* Macro in pmap.h */ +u_int +vtophys(va) + vm_offset_t va; +{ + return((*vtopte(va) & PG_FRAME) | ((unsigned)(va) & ~PG_FRAME)); +} +#endif + + +/* + * Copy the range specified by src_addr/len from the source map to the + * range dst_addr/len in the destination map. + * + * This routine is only advisory and need not do anything. + */ + +void +pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) + pmap_t dst_pmap; + pmap_t src_pmap; + vm_offset_t dst_addr; + vm_size_t len; + vm_offset_t src_addr; +{ + if (pmap_debug_level >= 0) + printf("pmap_copy(%x, %x, %x, %x, %x)\n", + (int) dst_pmap, (int) src_pmap, (int) dst_addr, + (int) len, (int) src_addr); +} + + +void +pmap_dump_pvlist(phys, m) + vm_offset_t phys; + char *m; +{ + register struct pv_entry *pv; + + if (!pv_table) + return; + + printf("%s %08x:", m, (int) phys); + pv = &pv_table[pmap_page_index(phys)]; + if (pv->pv_pmap == NULL) { + printf(" no mappings\n"); + return; + } + + for (; pv; pv = pv->pv_next) + printf(" pmap %08x va %08x flags %08x", (int) pv->pv_pmap, + (int) pv->pv_va, pv->pv_flags); + + printf("\n"); +} + + +void +pmap_dump_pvs() +{ + register struct pv_entry *pv; + register int loop; + + if (!pv_table) + return; + + printf("pv dump\n"); + + for (loop = 0; loop < npages; ++loop) { + pv = &pv_table[loop]; + if (pv->pv_pmap != NULL) { + printf("%4d : ", loop); + for (; pv; pv = pv->pv_next) { + printf(" pmap %08x va %08x flags %08x", (int) pv->pv_pmap, + (int) pv->pv_va, pv->pv_flags); + } + printf("\n"); + } + } + } + + +boolean_t +pmap_testbit(pa, setbits) + vm_offset_t pa; + int setbits; +{ + register struct pv_entry *pv; +/* register pt_entry_t *pte;*/ + int pind; + int s; + + if (pmap_debug_level >= 1) + printf("pmap_testbit: pa=%08x set=%08x\n", (int) pa, setbits); + + if (pv_table == NULL || pmap_attributes == NULL) + return(FALSE); + + if ((pind = pmap_page_index(pa)) == -1) + return(FALSE); + + s = splimp(); + pv = &pv_table[pind]; + +/* + if (pmap_debug_level >= 0) + printf("pmap_attributes = %02x\n", pmap_attributes[pind]); +*/ + +/* + * Check saved info first + */ + + if (pmap_attributes[pind] & setbits) { + if (pmap_debug_level >= 0) + printf("pmap_attributes = %02x\n", pmap_attributes[pind]); + + splx(s); + return(TRUE); + } + +/* + * Not found, check current mappings returning + * immediately if found. + */ + + if (pv->pv_pmap != NULL) { + for (; pv; pv = pv->pv_next) { +/* pte = pmap_pte(pv->pv_pmap, pv->pv_va);*/ + +/* The write bit is in the flags */ + + if ((pv->pv_flags & setbits) /*|| (*pte & (setbits & PT_Wr))*/) { + splx(s); + return(TRUE); + } + if ((setbits & PT_M) && pv->pv_va >= VM_MAXUSER_ADDRESS) { + splx(s); + return(TRUE); + } + if ((setbits & PT_H) && pv->pv_va >= VM_MAXUSER_ADDRESS) { + splx(s); + return(TRUE); + } + } + } + + splx(s); + return(FALSE); +} + + +/* + * Modify pte bits for all ptes corresponding to the given physical address. + * We use `maskbits' rather than `clearbits' because we're always passing + * constants and the latter would require an extra inversion at run-time. + */ + +void +pmap_changebit(pa, setbits, maskbits) + vm_offset_t pa; + int setbits; + int maskbits; +{ + register struct pv_entry *pv; + register pt_entry_t *pte; + vm_offset_t va; + int pind; + int s; + + if (pmap_debug_level >= 1) + printf("pmap_changebit: pa=%08x set=%08x mask=%08x\n", + (int) pa, setbits, maskbits); + + if (pv_table == NULL || pmap_attributes == NULL) + return; + + if ((pind = pmap_page_index(pa)) == -1) + return; + + s = splimp(); + pv = &pv_table[pind]; + +/* + * Clear saved attributes (modify, reference) + */ + + if (pmap_debug_level >= 0 && pmap_attributes[pind]) + printf("pmap_attributes = %02x\n", pmap_attributes[pind]); + + if (~maskbits) + pmap_attributes[pind] &= maskbits; + +/* + * Loop over all current mappings setting/clearing as appropos + */ + + if (pv->pv_pmap != NULL) { + for (; pv; pv = pv->pv_next) { + va = pv->pv_va; + +/* + * XXX don't write protect pager mappings + */ + + if (maskbits == ~PT_Wr) { + extern vm_offset_t pager_sva, pager_eva; + + if (va >= pager_sva && va < pager_eva) + continue; + } + + pv->pv_flags = (pv->pv_flags & maskbits) | setbits; + pte = pmap_pte(pv->pv_pmap, va); + if ((maskbits & PT_Wr) == 0) + *pte = (*pte) & ~PT_AP(AP_W); + if (setbits & PT_Wr) + *pte = (*pte) | PT_AP(AP_W); +/* + if ((maskbits & PT_H) == 0) + *pte = ((*pte) & ~L2_MASK) | L2_INVAL; +*/ + } + pmap_update(); + } + splx(s); +} + + +void +pmap_clear_modify(pa) + vm_offset_t pa; +{ + if (pmap_debug_level >= 0) + printf("pmap_clear_modify pa=%08x\n", (int) pa); + pmap_changebit(pa, 0, ~PT_M); +} + + +void +pmap_clear_reference(pa) + vm_offset_t pa; +{ + if (pmap_debug_level >= 0) + printf("pmap_clear_reference pa=%08x\n", (int) pa); + pmap_changebit(pa, 0, ~PT_H); +} + + +void +pmap_copy_on_write(pa) + vm_offset_t pa; +{ + if (pmap_debug_level >= 0) + printf("pmap_copy_on_write pa=%08x\n", (int) pa); + pmap_changebit(pa, 0, ~PT_Wr); +} + +boolean_t +pmap_is_modified(pa) + vm_offset_t pa; +{ + boolean_t result; + + result = pmap_testbit(pa, PT_M); + if (pmap_debug_level >= 0) + printf("pmap_is_modified pa=%08x %08x\n", (int) pa, result); + + return(result); +} + + +boolean_t +pmap_is_referenced(pa) + vm_offset_t pa; +{ + boolean_t result; +/* int pind;*/ + + result = pmap_testbit(pa, PT_H); + if (pmap_debug_level >= 0) + printf("pmap_is_referenced pa=%08x %08x\n", (int) pa, result); + + return(result); +} + + +int +pmap_modified_emulation(pmap, va) + pmap_t pmap; + vm_offset_t va; +{ + pt_entry_t *pte; + vm_offset_t pa; + int pind; + u_int flags; + +/* Get the pte */ + + pte = pmap_pte(pmap, va); + if (!pte) + return(0); + +/* Extract the physical address of the page */ + + pa = pmap_pte_pa(pte); + +/* Get the physical page index */ + + if ((pind = pmap_page_index(pa)) == -1) + return(0); + +/* Get the current flags for this page. */ + + flags = pmap_modify_pv(pmap, va, pind, 0, 0); + if (pmap_debug_level > 2) + printf("pmap_modified_emulation: flags = %08x\n", flags); + +/* + * Do the flags say this page is writable ? If not then it is a genuine + * write fault. If yes then the write fault is our fault as we did not + * reflect the write access in the PTE. Now we know a write has occurred + * we can correct this and also set the modified bit + */ + + if (!(flags & PT_Wr)) + return(0); + + if (pmap_debug_level > 0) + printf("pmap_modified_emulation: Got a hit va=%08x\n", (int) va); + + if (pmap_debug_level > 0) + printf("pte = %08x (%08x)", (int) pte, *pte); + *pte = *pte | PT_AP(AP_W); + if (pmap_debug_level > 0) + printf("->(%08x)\n", *pte); + + tlbflush(); + +/* pmap_modify_pv(pmap, va, pind, PT_M, PT_M);*/ + + if (pmap_attributes) + pmap_attributes[pind] |= PT_M; + +/* panic("pmap_modified_emulation: Not yet completed\n");*/ + +/* Return, indicating the problem has been dealt with */ + + return(1); +} + + +int +pmap_handled_emulation(pmap, va) + pmap_t pmap; + vm_offset_t va; +{ + pt_entry_t *pte; + vm_offset_t pa; + int pind; +/* u_int flags;*/ + + if (pmap_debug_level > 2) + printf("pmap_handled_emulation\n"); + +/* return(0);*/ + +/* Get the pte */ + + pte = pmap_pte(pmap, va); + if (!pte) { + if (pmap_debug_level > 2) + printf("no pte\n"); + return(0); + } + +/* Check for a zero pte */ + + if (pmap_debug_level > 1) + printf("*pte=%08x\n", *pte); + + if (*pte == 0) + return(0); + + if (pmap_debug_level > 1) + printf("pmap_handled_emulation: non zero pte %08x\n", *pte); + +/* Have we marked a valid pte as invalid ? */ + + if (((*pte) & L2_MASK) != L2_INVAL) + return(0); + + if (pmap_debug_level >=-1) + printf("Got an invalid pte\n"); + +/* Extract the physical address of the page */ + + pa = pmap_pte_pa(pte); + +/* Get the physical page index */ + + if ((pind = pmap_page_index(pa)) == -1) + return(0); + +/* + * Ok we just enable the pte and mark the flags as handled + */ + + if (pmap_debug_level > 0) + printf("pmap_handled_emulation: Got a hit va=%08x\n", (int) va); + + if (pmap_debug_level > 0) + printf("pte = %08x (%08x)", (int) pte, *pte); + *pte = ((*pte) & ~L2_MASK) | L2_SPAGE; + if (pmap_debug_level > 0) + printf("->(%08x)\n", *pte); + + tlbflush(); + + if (pmap_attributes) + pmap_attributes[pind] |= PT_H; + +/* Return, indicating the problem has been dealt with */ + + return(1); +} + + +void +pmap_pagedir_dump() +{ + int loop; + + printf("PD pmap PD pmap\n"); + + for (loop = 0; loop < max_processes / 2; ++loop) { + printf("%2d %08x %2d %08x\n", loop, + (int) pagedirectories[loop], loop + max_processes / 2, + (int) pagedirectories[loop + max_processes / 2]); + } +} + + +int +pmap_page_attributes(va) + vm_offset_t va; +{ + vm_offset_t pa; + int pind; + +/* Get the physical page */ + + pa = (vm_offset_t)vtopte(va); + +/* Get the physical page index */ + + if ((pind = pmap_page_index(pa)) == -1) + return(-1); + + if (pmap_attributes) + return((int)pmap_attributes[pind]); + + return(-1); +} + +#if 0 /* Macro in pmap.h */ +vm_offset_t +pmap_phys_address(ppn) + int ppn; +{ + return(arm_page_to_byte(ppn)); +} +#endif + + +void +pmap_collect(pmap) + pmap_t pmap; +{ +} + +/* End of pmap.c */ diff --git a/sys/arch/arm32/arm32/postmortem.c b/sys/arch/arm32/arm32/postmortem.c new file mode 100644 index 00000000000..0b855e3ecc6 --- /dev/null +++ b/sys/arch/arm32/arm32/postmortem.c @@ -0,0 +1,336 @@ +/* $NetBSD: postmortem.c,v 1.4 1996/03/13 21:26:52 mark 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 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 + * + * postmortem.c + * + * Postmortem routines + * + * Created : 17/09/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef POSTMORTEM + +typedef struct { + vm_offset_t physical; + vm_offset_t virtual; +} pv_addr_t; + +extern pv_addr_t irqstack; +extern pv_addr_t undstack; +extern pv_addr_t abtstack; +extern struct proc *proc1; + +int usertraceback = 0; + +/* dumpb - dumps memory in bytes */ + +void +pm_dumpb(addr, count) + u_char *addr; + int count; +{ + u_int byte; + int loop; + + for (; count > 0; count -= 16) { + printf("%08x: ", (int)addr); + + for (loop = 0; loop < 16; ++loop) { + byte = addr[loop]; + printf("%02x ", byte); + } + + printf(" "); + + for (loop = 0; loop < 16; ++loop) { + byte = addr[loop]; + if (byte < 0x20) + printf("\x1b[31m%c\x1b[0m", byte + '@'); + else if (byte == 0x7f) + printf("\x1b[31m?\x1b[0m"); + else if (byte < 0x80) + printf("%c", byte); + else if (byte < 0xa0) + printf("\x1b[32m%c\x1b[0m", byte - '@'); + else if (byte == 0xff) + printf("\x1b[32m?\x1b[0m"); + else + printf("%c", byte & 0x7f); + } + + printf("\r\n"); + addr += 16; + } +} + + +/* dumpw - dumps memory in bytes */ + +void +pm_dumpw(addr, count) + u_char *addr; + int count; +{ + u_int byte; + int loop; + + for (; count > 0; count -= 32) { + printf("%08x: ", (int)addr); + + for (loop = 0; loop < 8; ++loop) { + byte = ((u_int *)addr)[loop]; + printf("%08x ", byte); + } + + printf(" "); + + for (loop = 0; loop < 32; ++loop) { + byte = addr[loop]; + if (byte < 0x20) + printf("\x1b[31m%c\x1b[0m", byte + '@'); + else if (byte == 0x7f) + printf("\x1b[31m?\x1b[0m"); + else if (byte < 0x80) + printf("%c", byte); + else if (byte < 0xa0) + printf("\x1b[32m%c\x1b[0m", byte - '@'); + else if (byte == 0xff) + printf("\x1b[32m?\x1b[0m"); + else + printf("%c", byte & 0x7f); + } + + printf("\r\n"); + addr += 32; + } +} + + +/* Dump a trap frame */ + +void +dumpframe(frame) + trapframe_t *frame; +{ + u_int s; + + s = splhigh(); + printf("frame address = %08x ", (u_int)frame); + printf("spsr =%08x\n", frame->tf_spsr); + printf("r0 =%08x r1 =%08x r2 =%08x r3 =%08x\n", frame->tf_r0, frame->tf_r1, frame->tf_r2, frame->tf_r3); + printf("r4 =%08x r5 =%08x r6 =%08x r7 =%08x\n", frame->tf_r4, frame->tf_r5, frame->tf_r6, frame->tf_r7); + printf("r8 =%08x r9 =%08x r10=%08x r11=%08x\n", frame->tf_r8, frame->tf_r9, frame->tf_r10, frame->tf_r11); + printf("r12=%08x r13=%08x r14=%08x r15=%08x\n", frame->tf_r12, frame->tf_usr_sp, frame->tf_usr_lr, frame->tf_pc); + printf("slr=%08x\n", frame->tf_svc_lr); + + (void)splx(s); +} + + +/* Dump kstack information */ +/* +void kstack_stuff(p) + struct proc *p; +{ + struct pmap *pmap; + + if (p == 0) return; + if (p->p_addr == 0) return; + if (p->p_vmspace == 0) return; + + printf("proc=%08x comm=%s pid=%d\n", (u_int)p, p->p_comm, p->p_pid); + + pmap = &p->p_vmspace->vm_pmap; + + printf("pmap=%08x\n", (u_int)pmap); + + printf("p->p_addr=%08x pa=%08x,%d:%08x,%d\n", + (u_int)p->p_addr, + (u_int)pmap_extract(pmap, (vm_offset_t)p->p_addr), + pmap_page_index(pmap_extract(pmap, (vm_offset_t)p->p_addr)), + (u_int)pmap_extract(pmap, (vm_offset_t)p->p_addr + NBPG), + pmap_page_index(pmap_extract(pmap, (vm_offset_t)p->p_addr + NBPG))); +} +*/ + +void +check_stacks(p) + struct proc *p; +{ + u_char *ptr; + int loop; + + if (p) { + ptr = ((u_char *)p->p_addr) + USPACE_UNDEF_STACK_BOTTOM; + for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ; + printf("%d bytes of undefined stack fill pattern out of %d bytes\n", loop, + USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM); + ptr = ((u_char *)p->p_addr) + USPACE_SVC_STACK_BOTTOM; + for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ; + printf("%d bytes of svc stack fill pattern out of %d bytes\n", loop, + USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM); + } +} + + +/* Perform a postmortem */ + +void +postmortem(frame) + trapframe_t *frame; +{ + u_int s; + struct proc *p = curproc; + int loop; + u_int addr; + + s = splhigh(); + +/* Check the stack for a known pattern */ + + check_stacks(p); + +#ifdef ROTTEN_INARDS + addr = traceback(); + + dumpframe(frame); + + printf("curproc=%08x paddr=%08x pcb=%08x curpcb=%08x\n", + (u_int) curproc, (u_int) curproc->p_addr, + (u_int) &curproc->p_addr->u_pcb, (u_int) curpcb); + printf("CPSR=%08x ", GetCPSR()); + + printf("Process = %08x ", (u_int)curproc); + printf("pid = %d ", curproc->p_pid); + printf("comm = %s\n", curproc->p_comm); + + pm_dumpw(irqstack.virtual + NBPG - 0x100, 0x100); + pm_dumpw(undstack.virtual + NBPG - 0x20, 0x20); + pm_dumpw(abtstack.virtual + NBPG - 0x20, 0x20); + + printf("abt_sp=%08x irq_sp=%08x und_sp=%08x svc_sp=%08x\n", + get_stackptr(PSR_ABT32_MODE), + get_stackptr(PSR_IRQ32_MODE), + get_stackptr(PSR_UND32_MODE), + get_stackptr(PSR_SVC32_MODE)); + + if (curpcb) + printf("curpcb=%08x pcb_sp=%08x pcb_und_sp=%08x\n", curpcb, curpcb->pcb_sp, curpcb->pcb_und_sp); + + printf("proc0=%08x paddr=%08x pcb=%08x\n", (u_int)&proc0, + (u_int)proc0.p_addr, (u_int) &proc0.p_addr->u_pcb); + +/* + kstack_stuff(&proc0); + kstack_stuff(curproc); +*/ +#else + printf("Process = %08x ", (u_int)curproc); + printf("pid = %d ", curproc->p_pid); + printf("comm = %s\n", curproc->p_comm); + printf("CPSR=%08x ", GetCPSR()); + + printf("Traceback info\n"); + addr = simpletraceback(); + printf("Trapframe PC = %08x\n", frame->tf_pc); + printf("Trapframe SPSR = %08x\n", frame->tf_spsr); + + if (usertraceback) { + printf("Attempting user trackback\n"); + user_traceback(frame->tf_r11); + } + +#endif + if ((frame->tf_spsr & PSR_MODE) == PSR_IRQ32_MODE + && addr >= irqstack.virtual && addr < (irqstack.virtual + NBPG)) { + printf("Trap occurred in IRQ\n"); + printf("IRQ Traceback info\n"); + irqtraceback(addr, irqstack.virtual); + } + (void)splx(s); +} + + +void +buried_alive(p) + struct proc *p; +{ + printf("Ok major screw up detected on kernel stack\n"); + printf("Putting the process down to minimise further trashing\n"); + printf("Process was %08x pid=%d comm=%s\n", (u_int) p, p->p_pid, p->p_comm); + +} +#else +void +postmortem(frame) + trapframe_t *frame; +{ + printf("No postmortem support compiled in\n"); +} + +void +buried_alive(p) + struct proc *p; +{ +} +#endif + +void +traceback_sym(lr, pc) + u_int lr; + u_int pc; +{ +#ifdef DDB + printf("fp->lr=%08x fp->pc=%08x\n", lr, pc); +/* printf("fp->lr="); + db_printsym((db_addr_t)(lr), DB_STGY_ANY); + printf(" fp->pc="); + db_printsym((db_addr_t)(pc), DB_STGY_ANY); + printf("\n");*/ +#else + printf("fp->lr=%08x fp->pc=%08x\n", lr, pc); +#endif +} + +/* End of postmortem.c */ diff --git a/sys/arch/arm32/arm32/process_machdep.c b/sys/arch/arm32/arm32/process_machdep.c new file mode 100644 index 00000000000..2a087848afa --- /dev/null +++ b/sys/arch/arm32/arm32/process_machdep.c @@ -0,0 +1,178 @@ +/* $NetBSD: process_machdep.c,v 1.2 1996/03/27 22:42:26 mark Exp $ */ + +/* + * Copyright (c) 1995 Frank Lancaster. All rights reserved. + * Copyright (c) 1995 Tools GmbH. All rights reserved. + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1993 Jan-Simon Pendry + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * 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: + * Id: procfs_i386.c,v 4.1 1993/12/17 10:47:45 jsp Rel + */ + +/* + * This file may seem a bit stylized, but that so that it's easier to port. + * Functions to be implemented here are: + * + * process_read_regs(proc, regs) + * Get the current user-visible register set from the process + * and copy it into the regs structure (). + * The process is stopped at the time read_regs is called. + * + * process_write_regs(proc, regs) + * Update the current register set from the passed in regs + * structure. Take care to avoid clobbering special CPU + * registers or privileged bits in the PSL. + * The process is stopped at the time write_regs is called. + * + * process_sstep(proc, sstep) + * Arrange for the process to trap or not trap depending on sstep + * after executing a single instruction. + * + * process_set_pc(proc) + * Set the process's program counter. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static inline struct trapframe * +process_frame(p) + struct proc *p; +{ + + return (p->p_md.md_regs); +} + +static inline struct fp_state * +process_fpframe(p) + struct proc *p; +{ + + /* is this correct ? don't we need fpregs in the trapframe ? + or doesn't the kernel use fp ? */ + return (&p->p_addr->u_pcb.pcb_fpstate); +} + +int +process_read_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + struct trapframe *tf = process_frame(p); + + bcopy((caddr_t)&tf->tf_r0, (caddr_t)regs->r, sizeof(regs->r)); + regs->r_sp = tf->tf_usr_sp; + regs->r_lr = tf->tf_usr_lr; + regs->r_pc = tf->tf_pc; + regs->r_cpsr = tf->tf_spsr; + + return (0); +} + +int +process_read_fpregs(p, regs) + struct proc *p; + struct fpreg *regs; +{ + struct fp_state *statep; + + /* NOTE: struct fpreg == struct fpstate */ + statep = process_fpframe(p); + bcopy(statep, regs, sizeof(struct fpreg)); + return (0); +} + +int +process_write_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + struct trapframe *tf = process_frame(p); + + bcopy((caddr_t)regs->r, (caddr_t)&tf->tf_r0, sizeof(regs->r)); + tf->tf_usr_sp = regs->r_sp; + tf->tf_usr_lr = regs->r_lr; + tf->tf_pc = regs->r_pc; + tf->tf_spsr &= ~PSR_FLAGS; + tf->tf_spsr |= regs->r_cpsr & PSR_FLAGS; + + return (0); +} + +int +process_write_fpregs(p, regs) + struct proc *p; + struct fpreg *regs; +{ + struct fp_state *statep; + + /* NOTE: struct fpreg == struct fpstate */ + statep = process_fpframe(p); + bcopy(regs, statep, sizeof(struct fpreg)); + return (0); +} + +int +process_sstep(p, sstep) + struct proc *p; + int sstep; +{ + if (sstep) + /* this is going to be fun, I'll start off with kgdb_step ... */ + return (EINVAL); + return (0); +} + +int +process_set_pc(p, addr) + struct proc *p; + caddr_t addr; +{ + struct trapframe *tf = process_frame(p); + + tf->tf_pc = (int)addr; + + return (0); +} diff --git a/sys/arch/arm32/arm32/scratch.S b/sys/arch/arm32/arm32/scratch.S new file mode 100644 index 00000000000..09af00dc339 --- /dev/null +++ b/sys/arch/arm32/arm32/scratch.S @@ -0,0 +1,263 @@ +/* $NetBSD: scratch.S,v 1.2 1996/02/02 02:35:49 mycroft Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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 + * + * scratch.S + * + * Miscellaneous routines scratchpad routines + * + * Created : 02/04/95 + * Last updated : 04/06/95 + * + * $Id: scratch.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $ + */ + +#include "assym.h" + +lr .req r14 +pc .req r15 + +.text + + .global _ReadWordWithChecks + +/* Reads a word but traps failed faults + * + * r0 - address to read + * r1 - address to store result + */ + +Lcurpcb: + .word _curpcb + +_ReadWordWithChecks: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq ReadWordPCBFault + add r3, pc, #ReadWordFault - . - 8 + str r3, [r2, #PCB_ONFAULT] + + ldr r0, [r0] + str r0, [r1] + + mov r0, #0x00000000 + str r0, [r2, #PCB_ONFAULT] + mov pc, lr + +ReadWordFault: + mov r0, #0x00000000 + str r0, [r2, #PCB_ONFAULT] + mov r0, #0x00000001 + mov pc, lr + +ReadWordPCBFault: + stmfd sp!, {lr} + mov r2, r0 + add r0, pc, #ReadWordText1 - . - 8 + mov r1, r2 + bl _printf + mov r0, #0x00000001 + ldmfd sp!, {lr} + mov pc, lr + +ReadWordText1: + .asciz "Alert ! PCB = %08x during ReadWordWithChecks addr=%08x\n" + + + .global new_fuword + +new_fuword: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq fusupcbfault + add r1, pc, #fusufault - . - 8 + str r1, [r2, #PCB_ONFAULT] + + ldr r0, [r0] + + mov r1, #0x00000000 + str r1, [r2, #PCB_ONFAULT] + mov pc, lr + + .global new_fuswintr + +new_fuswintr: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq fusupcbfault + add r1, pc, #fusubailout - . - 8 + str r1, [r2, #PCB_ONFAULT] + + ldr r0, [r0] + bic r0, r0, #0xff000000 + bic r0, r0, #0x00ff0000 + + mov r1, #0x00000000 + str r1, [r2, #PCB_ONFAULT] + mov pc, lr + + .global new_fusword + +new_fusword: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq fusupcbfault + add r1, pc, #fusufault - . - 8 + str r1, [r2, #PCB_ONFAULT] + + ldr r0, [r0] + bic r0, r0, #0xff000000 + bic r0, r0, #0x00ff0000 + + mov r1, #0x00000000 + str r1, [r2, #PCB_ONFAULT] + mov pc, lr + + .global new_fubyte + +new_fubyte: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq fusupcbfault + add r1, pc, #fusufault - . - 8 + str r1, [r2, #PCB_ONFAULT] + + ldrb r0, [r0] + + mov r1, #0x00000000 + str r1, [r2, #PCB_ONFAULT] + mov pc, lr + + +fusufault: + mov r0, #0x00000000 + str r0, [r2, #PCB_ONFAULT] + mvn r0, #0x00000000 + mov pc, lr + + .global fusubailout + +fusubailout: + mov r0, #0x00000000 + str r0, [r2, #PCB_ONFAULT] + mvn r0, #0x00000000 + mov pc, lr + +fusuaddrfault: + mvn r0, #0x00000000 + mov pc, lr + +fusupcbfault: + stmfd sp!, {lr} + mov r2, r0 + add r0, pc, #ReadWordText1 - . - 8 + mov r1, r2 + bl _printf + mvn r0, #0x00000000 + ldmfd sp!, {lr} + mov pc, lr + + .global new_suword + +new_suword: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq fusupcbfault + add r3, pc, #fusufault - . - 8 + str r3, [r2, #PCB_ONFAULT] + + str r1, [r0] + + mov r0, #0x00000000 + str r0, [r2, #PCB_ONFAULT] + mov pc, lr + + .global new_suswintr + +new_suswintr: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq fusupcbfault + add r3, pc, #fusubailout - . - 8 + str r3, [r2, #PCB_ONFAULT] + + strb r1, [r0, #0x0000] + mov r1, r1, lsr #8 + strb r1, [r0, #0x0000] + + mov r0, #0x00000000 + str r0, [r2, #PCB_ONFAULT] + mov pc, lr + + .global new_susword + +new_susword: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq fusupcbfault + add r3, pc, #fusufault - . - 8 + str r3, [r2, #PCB_ONFAULT] + + strb r1, [r0, #0x0000] + mov r1, r1, lsr #8 + strb r1, [r0, #0x0000] + + mov r0, #0x00000000 + str r0, [r2, #PCB_ONFAULT] + mov pc, lr + + .global new_subyte + +new_subyte: + ldr r2, Lcurpcb + ldr r2, [r2] + teq r2, #0x00000000 + beq fusupcbfault + add r3, pc, #fusufault - . - 8 + str r3, [r2, #PCB_ONFAULT] + + strb r1, [r0] + + mov r0, #0x00000000 + str r0, [r2, #PCB_ONFAULT] + mov pc, lr diff --git a/sys/arch/arm32/arm32/setcpsr.S b/sys/arch/arm32/arm32/setcpsr.S new file mode 100644 index 00000000000..d62b797427e --- /dev/null +++ b/sys/arch/arm32/arm32/setcpsr.S @@ -0,0 +1,95 @@ +/* $NetBSD: setcpsr.S,v 1.1 1996/01/31 23:16:54 mark 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 + * + * setcpsr.S + * + * Miscellaneous routines to play with the CPSR register + * + * Eventually this routine can be inline assembly. + * + * Created : 12/09/94 + * Last updated : 28/05/95 + * + * Based of kate/display/setcpsr.s + * + * $Id: setcpsr.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $ + */ + +fp .req r11 +ip .req r12 +sp .req r13 +lr .req r14 +pc .req r15 + +.text + + .global _SetCPSR + +/* Sets and clears bits in the CPSR register + * + * r0 - bic mask + * r1 - eor mask + */ + +_SetCPSR: +/* mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4*/ + + mrs r3, cpsr_all /* Set the CPSR */ + bic r2, r3, r0 + eor r2, r2, r1 + msr cpsr_all, r2 + + mov r0, r3 /* Return the old CPSR */ + +/* ldmea fp, {fp, sp, pc}*/ + mov pc, lr + + .global _GetCPSR + +/* Gets the CPSR register + * + * Returns the CPSR in r0 + */ + +_GetCPSR: + mrs r0, cpsr_all /* Get the CPSR */ + + mov pc, lr + diff --git a/sys/arch/arm32/arm32/setstack.S b/sys/arch/arm32/arm32/setstack.S new file mode 100644 index 00000000000..2db02ea8f7a --- /dev/null +++ b/sys/arch/arm32/arm32/setstack.S @@ -0,0 +1,104 @@ +/* $NetBSD: setstack.S,v 1.1 1996/01/31 23:16:59 mark 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 + * + * setstack.S + * + * Miscellaneous routine to play with the stack pointer in different CPU modes + * + * Eventually this routine can be inline assembly. + * + * Created : 17/09/94 + * Last updated : 15/10/94 + * + * Based of kate/display/setstack.s + * + * $Id: setstack.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $ + */ + +#include + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + + .global _set_stackptr + +/* To set the stack pointer for a particular mode we must switch + * to that mode update the banked r13 and then switch back. + * This routine provides an easy way of doing this for any mode + * + * r0 = CPU mode + * r1 = stackptr + */ + +_set_stackptr: + mrs r3, cpsr_all /* Switch to the appropriate mode */ + bic r2, r3, #(PSR_MODE) + orr r2, r2, r0 + msr cpsr_all, r2 + + mov sp, r1 /* Set the stack pointer */ + + msr cpsr_all, r3 /* Restore the old mode */ + + mov pc, lr /* Exit */ + + .global _get_stackptr + +/* To get the stack pointer for a particular mode we must switch + * to that mode copy the banked r13 and then switch back. + * This routine provides an easy way of doing this for any mode + * + * r0 = CPU mode + */ + +_get_stackptr: + mrs r3, cpsr_all /* Switch to the appropriate mode */ + bic r2, r3, #(PSR_MODE) + orr r2, r2, r0 + msr cpsr_all, r2 + + mov r0, sp /* Set the stack pointer */ + + msr cpsr_all, r3 /* Restore the old mode */ + + mov pc, lr /* Exit */ + +/* End of setstack.S */ diff --git a/sys/arch/arm32/arm32/spl.S b/sys/arch/arm32/arm32/spl.S new file mode 100644 index 00000000000..ac797931607 --- /dev/null +++ b/sys/arch/arm32/arm32/spl.S @@ -0,0 +1,126 @@ +/* $NetBSD: spl.S,v 1.1 1996/03/08 18:03:15 mark Exp $ */ + +/* + * Copyright (c) 1996 Mark Brinicombe. + * Copyright (c) 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 + * + * splasm.S + * + * spl routines + * + * Created : 01/03/96 + * + * $Id: spl.S,v 1.1.1.1 1996/04/24 11:08:28 deraadt Exp $ + */ + +#include "assym.h" +#include + +sp .req r13 +lr .req r14 +pc .req r15 + + .text + .align 0 + +Lcurrent_spl_level: + .word _current_spl_level + +Lspl_masks: + .word _spl_masks + +Lspl_mask: + .word _spl_mask + + .global _raisespl +_raisespl: + mov r3, r0 /* Save the new value */ + ldr r1, Lcurrent_spl_level /* Get the current spl level */ + ldr r0, [r1] + cmp r3, r0 + movle pc, lr + + str r3, [r1] /* Store the new spl mask */ + + ldr r2, Lspl_masks /* Get the spl mask */ + ldr r2, [r2, r3, lsl #2] + + ldr r1, Lspl_mask /* Store in the current spl mask */ + str r2, [r1] + + stmfd sp!, {r0, lr} /* Preserve registers */ + bl _irq_setmasks /* Update the actual masks */ + ldmfd sp!, {r0, pc} /* Exit */ + + + .global _lowerspl +_lowerspl: + mov r3, r0 /* Save the new value */ + ldr r1, Lcurrent_spl_level /* Get the current spl level */ + ldr r0, [r1] + cmp r3, r0 + movge pc, lr + + str r3, [r1] /* Store the new spl mask */ + + ldr r2, Lspl_masks /* Get the spl mask */ + ldr r2, [r2, r3, lsl #2] + + ldr r1, Lspl_mask /* Store in the current spl mask */ + str r2, [r1] + + stmfd sp!, {r0, lr} /* Preserve registers */ + bl _irq_setmasks /* Update the actual masks */ + ldmfd sp!, {r0, pc} /* Exit */ + + + .global _splx +_splx: + mov r3, r0 /* Save the new value */ + ldr r1, Lcurrent_spl_level /* Get the current spl level */ + ldr r0, [r1] + cmp r3, r0 + moveq pc, lr + + str r3, [r1] /* Store the new spl mask */ + + ldr r2, Lspl_masks /* Get the spl mask */ + ldr r2, [r2, r3, lsl #2] + + ldr r1, Lspl_mask /* Store in the current spl mask */ + str r2, [r1] + + stmfd sp!, {r0, lr} /* Preserve registers */ + bl _irq_setmasks /* Update the actual masks */ + ldmfd sp!, {r0, pc} /* Exit */ + diff --git a/sys/arch/arm32/arm32/strstr.c b/sys/arch/arm32/arm32/strstr.c new file mode 100644 index 00000000000..5b3a0f9529e --- /dev/null +++ b/sys/arch/arm32/arm32/strstr.c @@ -0,0 +1,68 @@ +/* $NetBSD: strstr.c,v 1.2 1996/03/27 22:42:28 mark Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: strstr.c,v 1.4 1995/06/15 00:08:43 jtc Exp + */ + +#include +#include + +/* + * Find the first occurrence of find in s. + */ + +char * +strstr(s, find) + register const char *s, *find; +{ + register char c, sc; + register size_t len; + + if ((c = *find++) != 0) { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return (NULL); + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} + +/* End of strstr.c */ diff --git a/sys/arch/arm32/arm32/strtoul.c b/sys/arch/arm32/arm32/strtoul.c new file mode 100644 index 00000000000..d245930cc47 --- /dev/null +++ b/sys/arch/arm32/arm32/strtoul.c @@ -0,0 +1,83 @@ +#include + +#ifndef ULONG_MAX +#define ULONG_MAX ((u_long)(~0L)) /* 0xFFFFFFFF */ +#endif + +u_long +strtoul(s, ptr, base) + const char *s; + char **ptr; + int base; +{ + u_long total = 0; + u_int digit; + const char *start=s; + int did_conversion=0; + int overflow = 0; + int negate = 0; + u_long maxdiv, maxrem; + + if (s == NULL) { + if (!ptr) + *ptr = (char *)start; + return 0L; + } + + while (*s == ' ') + s++; + if (*s == '+') + s++; + else if (*s == '-') + s++, negate = 1; + if (base==0 || base==16) { /* the 'base==16' is for handling 0x */ + int tmp; + + /* + * try to infer base from the string + */ + if (*s != '0') + tmp = 10; /* doesn't start with 0 - assume decimal */ + else if (s[1] == 'X' || s[1] == 'x') + tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */ + else + tmp = 8; /* starts with 0 - hence octal */ + if (base==0) + base = (int)tmp; + } + + maxdiv = ULONG_MAX / base; + maxrem = ULONG_MAX % base; + + while ((digit = *s) != '\0') { + if (digit >= '0' && digit < ('0'+base)) + digit -= '0'; + else + if (base > 10) { + if (digit >= 'a' && digit < ('a'+(base-10))) + digit = digit - 'a' + 10; + else if (digit >= 'A' && digit < ('A'+(base-10))) + digit = digit - 'A' + 10; + else + break; + } + else + break; + did_conversion = 1; + if (total > maxdiv + || (total == maxdiv && digit > maxrem)) + overflow = 1; + total = (total * base) + digit; + s++; + } + if (overflow) { + if (ptr != NULL) + *ptr = (char *)s; + return (ULONG_MAX); + } + if (ptr != NULL) + *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start); + return negate ? -total : total; +} + +/* End of strtoul.c */ diff --git a/sys/arch/arm32/arm32/stubs.c b/sys/arch/arm32/arm32/stubs.c new file mode 100644 index 00000000000..116bfc30a08 --- /dev/null +++ b/sys/arch/arm32/arm32/stubs.c @@ -0,0 +1,618 @@ +/* $NetBSD: stubs.c,v 1.4 1996/03/08 18:41:52 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 + * + * stubs.c + * + * Routines that are temporary or do not have a home yet. + * + * Created : 17/09/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fdc.h" +#include "rd.h" + +#define VM_MAXKERN_ADDRESS 0xf3000000 + +extern int ffs_mountroot(); +extern int cd9660_mountroot(); +int do_mountroot(); +int (*mountroot)() = do_mountroot; + +extern u_int soft_interrupts; + +extern int msgbufmapped; +extern dev_t rootdev; +extern dev_t dumpdev; +#ifdef RAMDISK_HOOKS +extern struct rd_conf *bootrd; +#endif + +extern BootConfig bootconfig; +extern videomemory_t videomemory; + +int +do_mountroot() +{ + struct buf *bp; + int loop; + int s; + int type; + int floppysize; + int error; + +#if (NFDC > 0 && NRD > 0 && defined(RAMDISK_HOOKS)) + +/* + * Ok ideally the ramdisc would be loaded via the rd_open_hook() but since + * we are loading the ramdisc from floppy we only want to load it during + * the boot and not at any other time. + */ + +/* + * Ok bit of bodging here. The ramdisc minor is the unit number. However if booting + * from the ramdisc we limit to always booting off minor 0 i.e. rd0 The ramdisc + * device passed as the root device is only used to identify the ramdisc major. The + * minor, instead of indicating the ramdisc unit is used to indicate the floppy + * minor that should be used for loading the boot ramdisc which is unit 0. + */ + + if (major(rootdev) == 18 && bootrd) { + if (load_ramdisc_from_floppy(bootrd, makedev(17, minor(rootdev))) != 0) + panic("Failed to load ramdisc\n"); + boothowto |= RB_SINGLE; + rootdev = makedev(major(rootdev), 0); + } +#endif + +/* + * Slight bug with mounting CD's sometimes. The first mount may fail + * so we will try again. This only happens with the temporary ATAPI + * CDROM driver we are using + */ + +#ifdef CD9660 + if (major(rootdev) == 20 || major(rootdev) == 26) { + error = cd9660_mountroot(); + if (error) + error = cd9660_mountroot(); + } + else { +#endif +#ifdef FFS + error = ffs_mountroot(); +#else +#error FFS not configured +#endif +#ifdef CD9660 + if (error) + error = cd9660_mountroot(); + } +#endif + return(error); +} + + +/* + * All the copyin and copyout and copystr functions need to be recoded in assembly + * at some point. The guts of the functions now use an assembly bcopy routine but + * it would be nice to code them completely in assembly. The main reason they have + * not been is purely because it is easier to add debugging code to check the + * parameters in C. + */ + +#if 0 +int +copystr(from, to, maxlen, lencopied) + void *from; + void *to; + size_t maxlen; + size_t *lencopied; +{ + int byte = 0; + int len; + + len = 0; + + do { + if (len == maxlen) + break; + byte = *((caddr_t)from)++; + *((caddr_t)to)++ = byte; + ++len; + } while (byte != 0); + + if (lencopied) + *lencopied = len; + + if (byte == 0) + return(0); + else + return(ENAMETOOLONG); +} + + +#else +int +copystr(from, to, maxlen, lencopied) + void *from; + void *to; + size_t maxlen; + size_t *lencopied; + +{ + return(copystrinout(from, to, maxlen, lencopied)); +} +#endif + +int copystrinout __P((void */*from*/, void */*to*/, size_t /*maxlen*/, size_t */*lencopied*/)); + + +int +copyinstr(udaddr, kaddr, len, done) + void *udaddr; + void *kaddr; + u_int len; + u_int *done; +{ + if (udaddr < (void *)VM_MIN_ADDRESS + || udaddr >= (void *)VM_MAXUSER_ADDRESS) { + printf("akt: copyinstr: udaddr=%08x kaddr=%08x\n", + (u_int)udaddr, (u_int)kaddr); + return(EFAULT); + } + if (kaddr < (void *)VM_MAXUSER_ADDRESS + || kaddr >= (void *)VM_MAXKERN_ADDRESS) { + printf("akt: copyinstr: udaddr=%08x kaddr=%08x\n", + (u_int)udaddr, (u_int)kaddr); + return(EFAULT); + } + return(copystrinout(udaddr, kaddr, len, done)); +} + +int +copyoutstr(kaddr, udaddr, len, done) + void *kaddr; + void *udaddr; + u_int len; + u_int *done; +{ + if (udaddr < (void *)VM_MIN_ADDRESS + || udaddr >= (void*)VM_MAXUSER_ADDRESS) { + printf("akt: copyoutstr: udaddr=%08x kaddr=%08x\n", + (u_int)udaddr, (u_int)kaddr); + return(EFAULT); + } + if (kaddr < (void *)VM_MAXUSER_ADDRESS + || kaddr >= (void *)VM_MAXKERN_ADDRESS) { + printf("akt: copyoutstr: udaddr=%08x kaddr=%08x\n", + (u_int)udaddr, (u_int)kaddr); + return(EFAULT); + } + return(copystrinout(kaddr, udaddr, len, done)); +} + +int bcopyinout __P((void *, void *, u_int)); + +int +copyin(udaddr, kaddr, len) + void *udaddr; + void *kaddr; + u_int len; +{ + int error; + + if (udaddr < (void *)VM_MIN_ADDRESS + || udaddr >= (void *)VM_MAXUSER_ADDRESS) { + printf("akt: copyin: udaddr=%08x kaddr=%08x\n", + (u_int)udaddr, (u_int)kaddr); + return(EFAULT); + } + if (kaddr < (void *)VM_MAXUSER_ADDRESS + || kaddr >= (void *)VM_MAXKERN_ADDRESS) { + printf("akt: copyin: udaddr=%08x kaddr=%08x\n", + (u_int)udaddr, (u_int)kaddr); + return(EFAULT); + } + error = bcopyinout(udaddr, kaddr, len); + if (error) + printf("akt: copyin(%08x,%08x,%08x) failed\n", + (u_int)udaddr, (u_int)kaddr, len); + return(error); +} + +int +copyout(kaddr, udaddr, len) + void *kaddr; + void *udaddr; + u_int len; +{ + int error; + + if (udaddr < (void*)VM_MIN_ADDRESS + || udaddr >= (void*)VM_MAXUSER_ADDRESS) { + printf("akt: copyout: udaddr=%08x kaddr=%08x\n", + (u_int)udaddr, (u_int)kaddr); + return(EFAULT); + } + if (kaddr < (void *)VM_MAXUSER_ADDRESS + || kaddr >= (void *)VM_MAXKERN_ADDRESS) { + printf("akt: copyout: udaddr=%08x kaddr=%08x\n", + (u_int)udaddr, (u_int)kaddr); + return(EFAULT); + } + error = bcopyinout(kaddr, udaddr, len); + if (error) { + printf("akt: copyout(%08x,%08x,%08x) failed\n", + (u_int)kaddr, (u_int)udaddr, len); + traceback(); + } + return(error); +} + +void +setsoftnet() +{ + soft_interrupts |= IRQMASK_SOFTNET; +} + +int astpending; + +void +setsoftast() +{ + astpending = 1; +} + +extern int want_resched; + +void +need_resched(void) +{ + want_resched = 1; + setsoftast(); +} + + +struct queue { + struct queue *q_next, *q_prev; +}; + +/* + * insert an element into a queue + */ + +void +_insque(v1, v2) + void *v1; + void *v2; +{ + register struct queue *elem = v1, *head = v2; + register struct queue *next; + + next = head->q_next; + elem->q_next = next; + head->q_next = elem; + elem->q_prev = head; + next->q_prev = elem; +} + +/* + * remove an element from a queue + */ + +void +_remque(v) + void *v; +{ + register struct queue *elem = v; + register struct queue *next, *prev; + + next = elem->q_next; + prev = elem->q_prev; + next->q_prev = prev; + prev->q_next = next; + elem->q_prev = 0; +} + + + +/* + * These variables are needed by /sbin/savecore + */ +u_long dumpmag = 0x8fca0101; /* magic number */ +int dumpsize = 0; /* pages */ +long dumplo = 0; /* blocks */ + +/* + * This is called by configure to set dumplo and dumpsize. + * Dumps always skip the first CLBYTES of disk space + * in case there might be a disk label stored there. + * If there is extra space, put dump at the end to + * reduce the chance that swapping trashes it. + */ + +void +dumpconf() +{ + int nblks; /* size of dump area */ + int maj; + + if (dumpdev == NODEV) + return; + maj = major(dumpdev); + if (maj < 0 || maj >= nblkdev) + panic("dumpconf: bad dumpdev=0x%x", dumpdev); + if (bdevsw[maj].d_psize == NULL) + return; + nblks = (*bdevsw[maj].d_psize)(dumpdev); + if (nblks <= ctod(1)) + return; + + dumpsize = physmem; + + /* Always skip the first CLBYTES, in case there is a label there. */ + if (dumplo < ctod(1)) + dumplo = ctod(1); + + /* Put dump at end of partition, and make it fit. */ + if (dumpsize > dtoc(nblks - dumplo)) + dumpsize = dtoc(nblks - dumplo); + if (dumplo < nblks - ctod(dumpsize)) + dumplo = nblks - ctod(dumpsize); +} + + +extern pagehook_t page_hook0; + +/* + * Doadump comes here after turning off memory management and + * getting on the dump stack, either when called above, or by + * the auto-restart code. + */ + +void +dumpsys() +{ + daddr_t blkno; + int psize; + int error; + int addr; + int block; + vm_offset_t dumpspace; + + msgbufmapped = 0; + if (dumpdev == NODEV) + return; + if (dumpsize == 0) { + dumpconf(); + if (dumpsize == 0) + return; + } + printf("\ndumping to dev %x, offset %d\n", (u_int)dumpdev, + (u_int)dumplo); + + blkno = dumplo; + dumpspace = page_hook0.va; + + psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); + printf("dump "); + if (psize == -1) { + printf("area unavailable\n"); + return; + } + + error = 0; + for (block = 0; block < bootconfig.dramblocks && error == 0; ++block) { + for (addr = bootconfig.dram[block].address; + addr < bootconfig.dram[block].address + + bootconfig.dram[block].pages * NBPG; addr += NBPG) { + pmap_map(dumpspace, addr, addr + NBPG, VM_PROT_READ); + error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev, blkno, (caddr_t) dumpspace, NBPG); + if (error) break; + blkno += btodb(NBPG); + } + } + + if (error == 0 && videomemory.vidm_type == VIDEOMEM_TYPE_VRAM) { + for (addr = videomemory.vidm_pbase; addr < videomemory.vidm_pbase + + videomemory.vidm_size; addr += NBPG) { + pmap_map(dumpspace, addr, addr + NBPG, VM_PROT_READ); + error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev, blkno, (caddr_t) dumpspace, NBPG); + if (error) break; + blkno += btodb(NBPG); + } + } + + switch (error) { + case ENXIO: + printf("device bad\n"); + break; + + case EFAULT: + printf("device not ready\n"); + break; + + case EINVAL: + printf("area improper\n"); + break; + + case EIO: + printf("i/o error\n"); + break; + + case EINTR: + printf("aborted from console\n"); + break; + + default: + printf("succeeded\n"); + break; + } + printf("\n\n"); + delay(1000000); +} + +/* + * Dummy function is case no audio device has been configured + * Need to fix the code that uses this function (console) to check NBEEP. + */ + +#include "beep.h" +#if NBEEP == 0 +void +beep_generate() +{ +} +#endif + + +#if 0 +/* Debugging functions to dump the buffers linked to a vnode */ + +void +dumpvndbuf(vp) + register struct vnode *vp; +{ + register struct buf *bp, *nbp; + int s; + + s = splbio(); + for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { + nbp = bp->b_vnbufs.le_next; + + printf("buf=%08x\n", bp); + printf("flags=%08x proc=%08x bufsize=%08x dev=%04x\n", bp->b_flags, bp->b_proc, bp->b_bufsize, bp->b_dev); + printf("vp=%08x resid=%08x count=%08x addr=%08x\n", bp->b_vp, bp->b_resid, bp->b_bcount, bp->b_un.b_addr); + } + (void)splx(s); +} + + +void +dumpvncbuf(vp) + register struct vnode *vp; +{ + register struct buf *bp, *nbp; + int s; + + s = splbio(); + for (bp = vp->v_cleanblkhd.lh_first; bp; bp = nbp) { + nbp = bp->b_vnbufs.le_next; + + printf("buf=%08x\n", bp); + printf("flags=%08x proc=%08x bufsize=%08x dev=%04x\n", bp->b_flags, bp->b_proc, bp->b_bufsize, bp->b_dev); + printf("vp=%08x resid=%08x count=%08x addr=%08x\n", bp->b_vp, bp->b_resid, bp->b_bcount, bp->b_un.b_addr); + } + (void)splx(s); +} +#endif + + +extern u_int spl_mask; + +int current_spl_level = SPL_0; +u_int spl_masks[8]; + +int safepri = SPL_0; + +void +set_spl_masks() +{ + spl_masks[SPL_0] = 0xffffffff; + spl_masks[SPL_SOFT] = ~IRQMASK_SOFTNET; + spl_masks[SPL_BIO] = irqmasks[IPL_BIO]; + spl_masks[SPL_NET] = irqmasks[IPL_NET]; + spl_masks[SPL_TTY] = irqmasks[IPL_TTY]; + spl_masks[SPL_CLOCK] = irqmasks[IPL_CLOCK]; + spl_masks[SPL_IMP] = irqmasks[IPL_IMP]; + spl_masks[SPL_HIGH] = 0x00000000; +} + +void +dump_spl_masks() +{ + printf("spl0=%08x splsoft=%08x splbio=%08x splnet=%08x\n", + spl_masks[SPL_0], spl_masks[SPL_SOFT], spl_masks[SPL_BIO], spl_masks[SPL_NET]); + printf("spltty=%08x splclock=%08x splimp=%08x splhigh=%08x\n", + spl_masks[SPL_TTY], spl_masks[SPL_CLOCK], spl_masks[SPL_IMP], spl_masks[SPL_HIGH]); +} + +/* + * Ok things are broken here. If we lower the spl level to SPL_SOFT + * then, for the most things work. However wd interrupts start to get + * lost ... i.e. you either get wdc interrupt lost messages or + * wdc timeout messages. + * The fault is the CLKF_FRAME macro uses in kern_clock.c. This + * currently always returns 1 thus splsoftclock() is always + * called before calling softclock(). + * + * This is about to be fixed + */ + +int +splsoftclock() +{ +/* return(lowerspl(SPL_SOFT));*/ + return(current_spl_level); +} + +/* End of stubs.c */ diff --git a/sys/arch/arm32/arm32/swapgeneric.c b/sys/arch/arm32/arm32/swapgeneric.c new file mode 100644 index 00000000000..6c7a2b3e697 --- /dev/null +++ b/sys/arch/arm32/arm32/swapgeneric.c @@ -0,0 +1,60 @@ +/* $NetBSD: swapgeneric.c,v 1.2 1996/03/27 22:42:30 mark Exp $ */ + +/* + * Copyright (c) 1994 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 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 + * + * swapgeneric.h + * + * Miscellaneous swap stuff + * + * Created : 10/10/94 + */ + +#include +#include +#include + +dev_t rootdev = NODEV; +dev_t swapdev = NODEV; +dev_t argdev = NODEV; +dev_t dumpdev = NODEV; +int nswap; +struct swdevt swdevt[] = { + { NODEV, 0, 0 }, + { NODEV, 0, 0 }, + { NODEV, 0, 0 }, + { NODEV, 0, 0 }, +}; + +/* End of swapgeneric.c */ diff --git a/sys/arch/arm32/arm32/sys_machdep.c b/sys/arch/arm32/arm32/sys_machdep.c new file mode 100644 index 00000000000..64499aace16 --- /dev/null +++ b/sys/arch/arm32/arm32/sys_machdep.c @@ -0,0 +1,75 @@ +/* $NetBSD: sys_machdep.c,v 1.2 1996/03/27 22:42:31 mark 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 + * + * sys_machdep.c + * + * Machine dependant syscalls + * + * Created : 10/01/96 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +sys_sysarch(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_sysarch_args /* { + syscallarg(int) op; + syscallarg(char *) parms; + } */ *uap = v; + + printf("sys_sysarch: Currently stoned - Cannot support the operation (%d)\n", + SCARG(uap, op)); + + return(EINVAL); +} + +/* End of sys_machdep.c */ diff --git a/sys/arch/arm32/arm32/syscall.c b/sys/arch/arm32/arm32/syscall.c new file mode 100644 index 00000000000..318d99ecd64 --- /dev/null +++ b/sys/arch/arm32/arm32/syscall.c @@ -0,0 +1,573 @@ +/* $NetBSD: syscall.c,v 1.5 1996/03/13 21:21:00 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 + * + * syscall.c + * + * High level syscall handling + * + * Created : 09/11/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef KTRACE +#include +#endif +#include +#include +#include +#include + +#include "hydrabus.h" + +/* + * CONTINUE_AFTER_SYSCALL_BUG is used to determine whether the kernel + * should continue running following a swi instruction in SVC mode. + * This was used for debugging. + */ + +#define CONTINUE_AFTER_SYSCALL_BUG + +extern int pmap_debug_level; +extern u_int kmodule_size; +extern u_int kmodule_base; +u_int arm700bugcount = 0; +extern int vnodeconsolebug; +extern int usertraceback; + +#if NHYDRABUS > 0 +typedef struct { + vm_offset_t physical; + vm_offset_t virtual; +} pv_addr_t; + +extern pv_addr_t hydrascratch; +#endif + +void postmortem __P((trapframe_t *)); +void fpe_dump_prof __P(()); + +#define SYSCALL_SPECIAL_RETURN \ + userret(p, frame->tf_pc, sticks); \ + validate_trapframe(frame, 4); \ + return; + +/* + * syscall(frame): + * + * System call request from POSIX system call gate interface to kernel. + */ + +void +syscall(frame, code) + trapframe_t *frame; + int code; +{ + caddr_t params; + struct sysent *callp; + struct proc *p; + int error, opc; + u_int argsize; + int args[8], rval[2]; + int nsys; + u_quad_t sticks; + int regparams; + + cnt.v_syscall++; + +#ifdef DIAGNOSTIC + if ((frame->tf_spsr & PSR_MODE) != PSR_USR32_MODE) { + u_int s; + + s = splhigh(); + printf("swi code = %08x %d\n", code, code); + postmortem(frame); + + printf("nkt: syscall in kernel mode !\n"); +#ifdef CONTINUE_AFTER_SYSCALL_BUG + printf("The system should now be considered very unstable :-(\n"); + sigexit(curproc, SIGILL); + +/* Not reached */ + + (void)splx(s); + userret(curproc, frame->tf_pc, curproc->p_sticks); + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 4); +#endif + return; +#else + panic("syscall in kernel mode !\n"); +#endif + } +#endif + +/* + * ARM700/ARM710 match sticks and sellotape job ... + * + * I know this affects GPS/VLSI ARM700/ARM710. + * + * Not heard anything from ARM since I told them about this ... + * On occasion data aborts are mishandled and end up calling + * the swi vector. + */ + + if ((ReadWord(frame->tf_pc - 4) & 0x0f000000) != 0x0f000000) { + frame->tf_pc -= 4; + ++arm700bugcount; + + userret(curproc, frame->tf_pc, curproc->p_sticks); + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 4); +#endif + return; + } + +#ifdef DIAGNOSTIC + if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) { + splhigh(); + + printf("swi code = %08x %d\n", code, code); + postmortem(frame); + panic("syscall in non SVC mode !"); + } +#endif + +/* + * Enable interrupts if they were enable before the exception. + * Sinces all syscalls *should* come from user mode it will always + * be safe to enable them, but check anyway. + */ + +#ifndef BLOCK_IRQS + if (!(frame->tf_spsr & I32_bit)) + enable_interrupts(I32_bit); +#endif + + p = curproc; + sticks = p->p_sticks; + p->p_md.md_regs = frame; + opc = frame->tf_pc; + params = (caddr_t)&frame->tf_r0; + regparams = 4; + + if (pmap_debug_level >= -1) + printf("\x1b[31mSYSCALL\x1b[0m: code=%08x lr=%08x pid=%d\n", + code, frame->tf_pc, p->p_pid); + + nsys = p->p_emul->e_nsysent; + callp = p->p_emul->e_sysent; + + switch (code) { + case 0x1002: + printf((char *)frame->tf_r0, frame->tf_r1, frame->tf_r2, frame->tf_r3); + SYSCALL_SPECIAL_RETURN; + break; + + case 0x1003: + printf("%s", (char *)frame->tf_r0); + SYSCALL_SPECIAL_RETURN; + break; + +/* case 0x1004: + if (frame->tf_r0 != 0) + panic((char *)frame->tf_r0, frame->tf_r1, frame->tf_r2, + frame->tf_r3); + panic("SYSCALL 0x1004 panic\n"); + break;*/ + +/* case 0x1007: + pmap_debug(frame->tf_r0); + SYSCALL_SPECIAL_RETURN; + break;*/ + + case 0x1008: + switch (frame->tf_r0) { + case 0 : + debug_show_all_procs(frame->tf_r1, frame->tf_r2); + break; +#ifdef FPE + case 4 : + fpe_dump_prof(); + break; +#endif + case 5 : + pmap_dump_pvs(); + break; + case 6: + WriteWord(frame->tf_r1, frame->tf_r2); + break; + case 7: + frame->tf_r0 = ReadWord(frame->tf_r1); + break; + case 8: + WriteByte(frame->tf_r1, frame->tf_r2); + break; + case 9: + frame->tf_r0 = ReadByte(frame->tf_r1); + break; + case 10: + WriteShort(frame->tf_r1, frame->tf_r2); + break; + case 11: + frame->tf_r0 = ReadShort(frame->tf_r1); + break; + case 16: + pmap_pagedir_dump(); + break; +/* case 32: + frame->tf_r0 = pmap_next_phys_page(frame->tf_r1); + break;*/ + default: + printf("Unknown SYS_special call (%d)\n", frame->tf_r0); + break; + } + SYSCALL_SPECIAL_RETURN; + break; + + case 0x100a: + printf("Warning: This syscall is about to be revoked (0x100a)\n"); + frame->tf_r0 = pmap_page_attributes(frame->tf_r0); + SYSCALL_SPECIAL_RETURN; + break; +/* + case 0x1010: + frame->tf_r0 = kmodule_base; + SYSCALL_SPECIAL_RETURN; + break; + + case 0x1011: + frame->tf_r0 = kmodule_size; + SYSCALL_SPECIAL_RETURN; + break; + + case 0x1012: + if (frame->tf_r1 < kmodule_size) { + bcopy((char *)frame->tf_r0, (char *)kmodule_base, + frame->tf_r1); + frame->tf_r0 = 0; + } + else + frame->tf_r0 = 1; + SYSCALL_SPECIAL_RETURN; + break; + + case 0x1013: + { + int (*caller)(); + + caller = (void *)frame->tf_r0; + + frame->tf_r0 = (*caller)(printf, install_coproc_handler); + } + SYSCALL_SPECIAL_RETURN; + break; +*/ +#if NHYDRABUS > 0 + case 0x1014: + frame->tf_r0 = hydrascratch.physical; + SYSCALL_SPECIAL_RETURN; + break; + case 0x1015: + frame->tf_r0 = hydrascratch.virtual; + SYSCALL_SPECIAL_RETURN; + break; + case 0x1016: + frame->tf_r0 = (u_int)proc0.p_addr->u_pcb.pcb_pagedir; + SYSCALL_SPECIAL_RETURN; + break; + case 0x1017: + frame->tf_r0 = kmem_alloc(kernel_map, round_page(frame->tf_r0)); + SYSCALL_SPECIAL_RETURN; + break; + case 0x1018: + kmem_free(kernel_map, frame->tf_r0, frame->tf_r1); + SYSCALL_SPECIAL_RETURN; + break; +#endif +#if 0 + case 0x1020: + vprint(frame->tf_r0, frame->tf_r1); + SYSCALL_SPECIAL_RETURN; + break; + case 0x1021: + { struct vnode *vp; + vp = (struct vp *)frame->tf_r0; + if (vp->v_numoutput > 0 && vp->v_usecount == 0 && vp->v_writecount == 0) { + printf("Patching vnode %08x\n", vp); + vprint(NULL, vp); + if (--vp->v_numoutput < 0) + panic("vwakeup: neg numoutput"); + if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) { + vp->v_flag &= ~VBWAIT; + wakeup((caddr_t)&vp->v_numoutput); + } + } + SYSCALL_SPECIAL_RETURN; + } + break; + + case 0x1022: + { struct vnode *vp; + vp = (struct vp *)frame->tf_r0; + if (vp->v_numoutput == 0 && vp->v_usecount == 0 && vp->v_writecount == 0) { + printf("Patching vnode %08x\n", vp); + vprint(NULL, vp); + if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) { + vp->v_flag &= ~VBWAIT; + wakeup((caddr_t)&vp->v_numoutput); + } + } + SYSCALL_SPECIAL_RETURN; + } + break; + + case 0x1023: + wakeup((caddr_t)frame->tf_r0); + SYSCALL_SPECIAL_RETURN; + break; +/* + case 0x1024: + dumpvndbuf((struct vnode *)frame->tf_r0); + SYSCALL_SPECIAL_RETURN; + break; + + case 0x1025: + dumpvncbuf((struct vnode *)frame->tf_r0); + SYSCALL_SPECIAL_RETURN; + break; +*/ +/* case 0x1026: + vfs_bufstats(); + SYSCALL_SPECIAL_RETURN; + break; +*/ + case 0x1027: + bcopy(frame->tf_r0, frame->tf_r1, sizeof(struct vnode)); + SYSCALL_SPECIAL_RETURN; + break; + case 0x1028: + vnodeconsolebug = frame->tf_r0; + SYSCALL_SPECIAL_RETURN; + break; +#endif + case 0x102a: + usertraceback = frame->tf_r0; + SYSCALL_SPECIAL_RETURN; + break; + + case 0x102b: + frame->tf_r0 = vmem_mapdram(); + SYSCALL_SPECIAL_RETURN; + break; + + case 0x102c: + frame->tf_r0 = vmem_mapvram(); + SYSCALL_SPECIAL_RETURN; + break; + + case 0x102d: + frame->tf_r0 = vmem_cachectl(frame->tf_r0); + SYSCALL_SPECIAL_RETURN; + break; + + case SYS_syscall: +/* code = fuword(params);*/ + code = ReadWord(params); + params += sizeof(int); + regparams -= 1; + printf("SYS_syscall: code=%d %02x", code, code); + break; + + case SYS___syscall: + if (callp != sysent) + break; +/* code = fuword(params + _QUAD_LOWWORD * sizeof(int));*/ + +/* Since this will be a register ... */ + + code = ReadWord(params + _QUAD_LOWWORD * sizeof(int)); + params += sizeof(quad_t); + regparams -= 2; + break; + + default: + /* do nothing by default */ + break; + } + + if (code < 0 || code >= nsys) + callp += p->p_emul->e_nosys; /* illegal */ + else + callp += code; + + if (callp->sy_call == sys_nosys) { + printf("SYSCALL: nosys code=%08x lr=%08x proc=%08x pid=%d %s\n", + code, frame->tf_pc, (u_int)p, p->p_pid, p->p_comm); + postmortem(frame); +#ifdef POSTMORTEM + disassemble(frame->tf_pc-8); + disassemble(frame->tf_pc-4); + disassemble(frame->tf_pc); + disassemble(frame->tf_pc+4); +#endif + pmap_debug(-2); + } + + argsize = callp->sy_argsize; + if (argsize > (regparams * sizeof(int))) + argsize = regparams*sizeof(int); +/* if (argsize && (error = copyin(params, (caddr_t)args, argsize))) { +#ifdef SYSCALL_DEBUG + scdebug_call(p, code, callp->sy_narg, args); +#endif + goto bad; + }*/ + if (argsize) + bcopy(params, (caddr_t)args, argsize); + + argsize = callp->sy_argsize; + if (callp->sy_argsize > (regparams * sizeof(int)) + && (error = copyin((caddr_t)frame->tf_usr_sp, + (caddr_t)&args[regparams], argsize - (regparams * sizeof(int))))) { +#ifdef SYSCALL_DEBUG + scdebug_call(p, code, callp->sy_narg, args); +#endif + goto bad; + } + +#ifdef SYSCALL_DEBUG + scdebug_call(p, code, callp->sy_narg, args); +#endif +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, argsize, args); +#endif + rval[0] = 0; + rval[1] = frame->tf_r1; + + error = (*callp->sy_call)(p, args, rval); + + switch (error) { + case 0: +/* + * Reinitialize proc pointer `p' as it may be different + * if this is a child returning from fork syscall. + */ + p = curproc; + frame->tf_r0 = rval[0]; + frame->tf_r1 = rval[1]; + frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ + break; + + case ERESTART: +/* + * Reconstruct the pc. opc contains the odl pc address which is + * the instruction after the swi. + */ + frame->tf_pc = opc - 4; + break; + + case EJUSTRETURN: +/* nothing to do */ + break; + + default: + bad: + frame->tf_r0 = error; + frame->tf_spsr |= PSR_C_bit; /* carry bit */ + break; + } + +#ifdef SYSCALL_DEBUG + scdebug_ret(p, code, error, rval[0]); +#endif + + validate_trapframe(frame, 4); + + userret(p, frame->tf_pc, sticks); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, rval[0]); +#endif + + validate_trapframe(frame, 4); +} + + +void +child_return(p, frame) + struct proc *p; + struct trapframe *frame; +{ + frame->tf_r0 = 0; + frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ + + userret(p, frame->tf_pc, 0); + +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, SYS_fork, 0, 0); +#endif +} + +/* End of syscall.c */ diff --git a/sys/arch/arm32/arm32/undefined.c b/sys/arch/arm32/arm32/undefined.c new file mode 100644 index 00000000000..65f390740c5 --- /dev/null +++ b/sys/arch/arm32/arm32/undefined.c @@ -0,0 +1,325 @@ +/* $NetBSD: undefined.c,v 1.2 1996/03/08 20:54:25 mark 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 + * + * undefined.c + * + * Fault handler + * + * Created : 06/01/95 + */ + +#define CONTINUE_AFTER_RESET_BUG +#define FAST_FPE + +#include +#include +#include +#include +#include +#include +#include +#ifdef FAST_FPE +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef FAST_FPE +extern int want_resched; +#endif + +undef_handler_t undefined_handlers[MAX_COPROCS]; + +u_int disassemble __P((u_int)); + + +int +default_undefined_handler(address, instruction, frame) + u_int address; + u_int instruction; + trapframe_t *frame; +{ + struct proc *p; + + p = curproc; + if (p == NULL) + p = &proc0; + log(LOG_ERR, "Undefined instruction 0x%08x @ 0x%08x in process %s (pid %d)\n", + instruction, address, p->p_comm, p->p_pid); + return(1); +} + + +int +install_coproc_handler(coproc, handler) + int coproc; + undef_handler_t handler; +{ + if (coproc < 0 || coproc > MAX_COPROCS) + return(EINVAL); + if (handler == (undef_handler_t)0) + handler = default_undefined_handler; + + undefined_handlers[coproc] = handler; + return(0); +} + + +void +undefined_init() +{ + int loop; + + for (loop = 0; loop < MAX_COPROCS; ++loop) + undefined_handlers[loop] = default_undefined_handler; +} + + +void +undefinedinstruction(frame) + trapframe_t *frame; +{ + struct proc *p; +/* struct pcb *pcb;*/ + u_int fault_pc; + int fault_instruction; + int s; + int fault_code; + u_quad_t sticks; + int coprocessor; + +#ifndef BLOCK_IRQS + if (!(frame->tf_spsr & I32_bit)) + enable_interrupts(I32_bit); +#endif + +/* Update vmmeter statistics */ + + cnt.v_trap++; + + fault_pc = frame->tf_pc - 4; + +/* Should use fuword() here .. but in the interests of squeezing every bit + * of speed we will just use ReadWord(). We know the instruction can be + * read as was just executed so this will never fail unless the kernel + * is screwed up in which case it does not really matter does it ? + */ + + fault_instruction = ReadWord(fault_pc); + +/* Check for coprocessor instruction */ + +/* + * According to the datasheets you only need to look at bit 27 of the instruction + * to tell the difference between and undefined instruction and a + * coprocessor instruction. + */ + + if ((fault_instruction & (1 << 27)) != 0) + coprocessor = (fault_instruction >> 8) & 0x0f; + else { + coprocessor = 0; + s = splhigh(); + disassemble(fault_pc); + (void)splx(s); + } + +/* Get the current proc structure or proc0 if there is none */ + + if ((p = curproc) == 0) + p = &proc0; + +/* printf("fault in process %08x %d\n", p, p->p_pid);*/ + + if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) { +/* printf("USR32 mode : %08x\n", frame->tf_spsr);*/ + sticks = p->p_sticks; + +/* Modify the fault_code to reflect the USR/SVC state at time of fault */ + + fault_code = FAULT_USER; + p->p_md.md_regs = frame; + } else + fault_code = 0; + +#if 0 +/* can't use curpcb, as it might be NULL; and we have p in a register anyway */ + + pcb = &p->p_addr->u_pcb; + if (pcb == 0) + { + panic("no pcb ... we're toast !\n"); + } +#endif + +/* OK this is were we do something about the instruction */ + +/* Check for coprocessor instruction */ + +/* + s = splhigh(); + printf("Coprocessor number %d instruction fault\n", coprocessor); + (void)splx(s); +*/ + + if ((undefined_handlers[coprocessor](fault_pc, fault_instruction, + frame)) != 0) { + s = splhigh(); + + if ((fault_instruction & 0x0f000010) == 0x0e000000) { + printf("CDP\n"); + disassemble(fault_pc); + } + else if ((fault_instruction & 0x0e000000) == 0x0c000000) { + printf("LDC/STC\n"); + disassemble(fault_pc); + } + else if ((fault_instruction & 0x0f000010) == 0x0e000010) { + printf("MRC/MCR\n"); + disassemble(fault_pc); + } + else { + printf("Undefined instruction\n"); + disassemble(fault_pc); + } + + (void)splx(s); + + if ((fault_code & FAULT_USER) == 0) { + printf("Undefined instruction in kernel: Heavy man !\n"); + postmortem(frame); + } + + trapsignal(p, SIGILL, fault_instruction); + } + + if ((fault_code & FAULT_USER) == 0) + return; + +#ifdef FAST_FPE +/* Optimised exit code */ + + { + int sig; + +/* take pending signals */ + + while ((sig = (CURSIG(p))) != 0) { + postsig(sig); + } + + p->p_priority = p->p_usrpri; + +/* + * Check for reschedule request, at the moment there is only + * 1 ast so this code should always be run + */ + + if (want_resched) { + /* + * Since we are curproc, a clock interrupt could + * change our priority without changing run queues + * (the running process is not kept on a run queue). + * If this happened after we setrunqueue ourselves but + * before we switch()'ed, we might not be on the queue + * indicated by our priority + */ + + s = splstatclock(); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + + mi_switch(); + + (void)splx(s); + while ((sig = (CURSIG(p))) != 0) { + postsig(sig); + } + } + +/* + * The profiling bit is commented out at the moment. This can be reinstated + * later on. Currently addupc_task is not written. + */ + + if (p->p_flag & P_PROFIL) { + extern int psratio; + addupc_task(p, frame->tf_pc, (int)(p->p_sticks - sticks) * psratio ); + } + + curpriority = p->p_priority; + } + +#else +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 5); +#endif + + userret(p, frame->tf_pc, sticks); + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 5); +#endif +#endif +} + + +void +resethandler(frame) + trapframe_t *frame; +{ + postmortem(frame); + +#ifdef CONTINUE_AFTER_RESET_BUG + printf("Branch throuh zero\n"); + printf("The system should now be considered very unstable :-)\n"); + sigexit(curproc, SIGILL); + +#ifdef VALIDATE_TRAPFRAME + validate_trapframe(frame, 4); +#endif +#else + panic("Branch through zero..... were dead\n"); +#endif +} + +/* End of undefined.c */ diff --git a/sys/arch/arm32/arm32/vm_machdep.c b/sys/arch/arm32/arm32/vm_machdep.c new file mode 100644 index 00000000000..209e368e106 --- /dev/null +++ b/sys/arch/arm32/arm32/vm_machdep.c @@ -0,0 +1,562 @@ +/* $NetBSD: vm_machdep.c,v 1.3 1996/03/13 21:16:15 mark 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 + * + * vm_machdep.h + * + * vm machine specifiv bits + * + * Created : 08/10/94 + */ + +#define DEBUG_VMMACHDEP +/*#define FREESWAPPEDPAGEDIRS*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef ARMFPE +#include +#include +#include +#endif + +typedef struct { + vm_offset_t physical; + vm_offset_t virtual; +} pv_addr_t; + +extern pv_addr_t systempage; + +extern int pmap_debug_level; + +void switch_exit __P((struct proc */*p*/, struct proc */*proc0*/)); +int savectx __P((struct pcb *pcb)); +void pmap_activate __P((pmap_t /*pmap*/, struct pcb */*pcbp*/)); +extern void proc_trampoline __P(()); +extern void child_return __P(()); + +/* + * Special compilation symbols + * DEBUG_VMMACHDEP + */ + +/* + * Finish a fork operation, with process p2 nearly set up. + * Copy and update the kernel stack and pcb, making the child + * ready to run, and marking it so that it can return differently + * than the parent. Returns 1 in the child process, 0 in the parent. + * We currently double-map the user area so that the stack is at the same + * address in each process; in the future we will probably relocate + * the frame pointers on the stack after copying. + */ + +void +cpu_fork(p1, p2) + struct proc *p1; + struct proc *p2; +{ + struct user *up = p2->p_addr; + struct pcb *pcb = (struct pcb *)&p2->p_addr->u_pcb; + struct trapframe *tf; + struct switchframe *sf; + int loop; + vm_offset_t addr; + u_char *ptr; + vm_offset_t muaddr = VM_MAXUSER_ADDRESS; + struct vm_map *vp; + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) + printf("cpu_fork: %08x %08x %08x %08x\n", (u_int)p1, (u_int)p2, + (u_int) curproc, (u_int)&proc0); +#endif + +/* Sync the pcb */ + savectx(curpcb); + +/* Copy the pcb */ + *pcb = p1->p_addr->u_pcb; + +/* Set up the undefined stack for the process. Note: this stack is not in use if we are forking */ + pcb->pcb_und_sp = (u_int)p2->p_addr + USPACE_UNDEF_STACK_TOP; + pcb->pcb_sp = (u_int)p2->p_addr + USPACE_SVC_STACK_TOP; + +/* Fill the undefined stack with a known pattern */ + + ptr = ((u_char *)p2->p_addr) + USPACE_UNDEF_STACK_BOTTOM; + for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM); ++loop, ++ptr) { + *ptr = 0xdd; + } + +/* Fill the kernel stack with a known pattern */ + + ptr = ((u_char *)p2->p_addr) + USPACE_SVC_STACK_BOTTOM; + for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM); ++loop, ++ptr) { + *ptr = 0xdd; + } + +/* Now ... + * vm_fork has allocated UPAGES in kernel Vm space for us. p2->p_addr + * points to the start of this. The i386 releases this memory in vm_fork + * and relocates it in cpu_fork. + * We can work with it allocated by vm_fork. We we must do is + * copy the stack and activate the p2 page directory. + * We activate first and then call savectx which will copy the stack. + * This must also set the stack pointer for p2 to its correct address + * NOTE: This will be different from p1 stack address. + */ + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) { + printf("cpu_fork: pcb = %08x pagedir = %08x\n", + (u_int)&up->u_pcb, (u_int)up->u_pcb.pcb_pagedir); + printf("p1->procaddr=%08x p1->procaddr->u_pcb=%08x pid=%d pmap=%08x\n", + (u_int)p1->p_addr, (u_int)&p1->p_addr->u_pcb, p1->p_pid, (u_int)&p1->p_vmspace->vm_pmap); + printf("p2->procaddr=%08x p2->procaddr->u_pcb=%08x pid=%d pmap=%08x\n", + (u_int)p2->p_addr, (u_int)&p2->p_addr->u_pcb, p2->p_pid, (u_int)&p2->p_vmspace->vm_pmap); + } +#endif + +/* ream out old pagetables */ + + vp = &p2->p_vmspace->vm_map; + (void)vm_deallocate(vp, muaddr, VM_MAX_ADDRESS - muaddr); + (void)vm_allocate(vp, &muaddr, VM_MAX_ADDRESS - muaddr, FALSE); + (void)vm_map_inherit(vp, muaddr, VM_MAX_ADDRESS, VM_INHERIT_NONE); + + +/* Get the address of the page table containing 0x00000000 */ + + addr = trunc_page((u_int)vtopte(0)); + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) { + printf("fun time: paging in PT %08x for %08x\n", (u_int)addr, 0); + printf("p2->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p2->p_vmspace->vm_pmap.pm_pdir[0]); + printf("p2->pm_vptpt[0] = %08x", *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0))); + } +#endif + +/* Nuke the exising mapping */ + + p2->p_vmspace->vm_pmap.pm_pdir[0] = 0; + p2->p_vmspace->vm_pmap.pm_pdir[1] = 0; + p2->p_vmspace->vm_pmap.pm_pdir[2] = 0; + p2->p_vmspace->vm_pmap.pm_pdir[3] = 0; + + *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0)) = 0; + +/* Wire down a page to cover the page table zero page and the start of the user are in */ + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) { + printf("vm_map_pageable: addr=%08x\n", addr); + } +#endif + + if (vm_map_pageable(&p2->p_vmspace->vm_map, addr, addr+NBPG, FALSE) != 0) { + panic("Failed to fault in system page PT\n"); + } + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) { + printf("party on! acquired a page table for 0M->(4M-1)\n"); + printf("p2->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p2->p_vmspace->vm_pmap.pm_pdir[0]); + printf("p2->pm_vptpt[0] = %08x", *((int *)(p2->p_vmspace->vm_pmap.pm_vptpt + 0))); + } +#endif + +/* Map the system page */ + + pmap_enter(&p2->p_vmspace->vm_pmap, 0, + systempage.physical, VM_PROT_READ, TRUE); + + pmap_activate(&p2->p_vmspace->vm_pmap, &up->u_pcb); + +#ifdef ARMFPE +/* Initialise a new FP context for p2 and copy the context from p1 */ + arm_fpe_core_initcontext(FP_CONTEXT(p2)); + arm_fpe_copycontext(FP_CONTEXT(p1), FP_CONTEXT(p2)); +#endif + + p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_sp - 1; + + *tf = *p1->p_md.md_regs; + sf = (struct switchframe *)tf - 1; + sf->sf_spl = SPL_0; + sf->sf_r4 = (u_int)child_return; + sf->sf_r5 = (u_int)p2; + sf->sf_pc = (u_int)proc_trampoline; + pcb->pcb_sp = (u_int)sf; +} + + +void +cpu_set_kpc(p, pc) + struct proc *p; + u_long pc; +{ + struct switchframe *sf = (struct switchframe *)p->p_addr->u_pcb.pcb_sp; + + sf->sf_r4 = pc; + sf->sf_r5 = (u_int)p; +} + + +/* + * cpu_exit is called as the last action during exit. + * + * We clean up a little and then call switch_exit() with the old proc as an + * argument. switch_exit() first switches to proc0's context, then does the + * vmspace_free() and kmem_free() that we don't do here, and finally jumps + * into switch() to wait for another process to wake up. + */ + +void +cpu_exit(p) + register struct proc *p; +{ + struct vmspace *vm; + +#ifdef ARMFPE +/* Abort any active FP operation and deactivate the context */ + arm_fpe_core_abort(FP_CONTEXT(p), NULL, NULL); + arm_fpe_core_changecontext(0); +#endif + +/* Report how much stack has been used - debugging */ + +/* if (p) { + u_char *ptr; + int loop; + + ptr = ((u_char *)p2->p_addr) + USPACE_UNDEF_STACK_BOTTOM; + for (loop = 0; loop < (USPACE_UNDEF_STACK_TOP - USPACE_UNDEF_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ; + log(LOG_INFO, "%d bytes of undefined stack fill pattern\n", loop); + ptr = ((u_char *)p2->p_addr) + USPACE_SVC_STACK_BOTTOM; + for (loop = 0; loop < (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM) && *ptr == 0xdd; ++loop, ++ptr) ; + log(LOG_INFO, "%d bytes of svc stack fill pattern\n", loop); + + } +*/ + +/* printf("cpu_exit: proc=%08x pid=%d comm=%s\n", p, p->p_pid, p->p_comm);*/ + + vm = p->p_vmspace; + if (vm->vm_refcnt == 1) /* What does this do and is it needed ? */ + vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); + + cnt.v_swtch++; + + switch_exit(p, &proc0); +} + + +void +cpu_swapin(p) + struct proc *p; +{ + vm_offset_t addr; + int loop; + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) + printf("cpu_swapin(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap); +#endif + +#ifdef FREESWAPPEDPAGEDIRS + printf("cpu_swapin(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap); + if (p->p_vmspace->vm_pmap.pm_pdir) + printf("pdir = %08x\n", p->p_vmspace->vm_pmap.pm_pdir); + pmap_pinit(&p->p_vmspace->vm_pmap); + pmap_debug_level = 10; +#endif + +/* Get the address of the page table containing 0x00000000 */ + + addr = trunc_page((u_int)vtopte(0)); + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) { + printf("fun time: paging in PT %08x for %08x\n", (u_int)addr, 0); + printf("p->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p->p_vmspace->vm_pmap.pm_pdir[0]); + printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0))); + } +#endif + +/* Wire down a page to cover the page table zero page and the start of the user are in */ + + vm_map_pageable(&p->p_vmspace->vm_map, addr, addr+NBPG, FALSE); + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) { + printf("party on! acquired a page table for 0M->(4M-1)\n"); + printf("p->p_vmspace->vm_pmap.pm_pdir[0] = %08x\n", p->p_vmspace->vm_pmap.pm_pdir[0]); + printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0))); + } +#endif + +/* Map the system page */ + + pmap_enter(&p->p_vmspace->vm_pmap, 0, + systempage.physical, VM_PROT_READ, TRUE); +} + + +void +cpu_swapout(p) + struct proc *p; +{ +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) { + printf("cpu_swapout(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap); + printf("p->pm_vptpt[0] = %08x", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0))); + } +#endif + +/* Free the system page mapping */ + + pmap_remove(&p->p_vmspace->vm_pmap, 0, NBPG); + +#ifdef FREESWAPPEDPAGEDIRS + printf("cpu_swapout(%08x, %d, %s, %08x)\n", (u_int)p, p->p_pid, p->p_comm, (u_int)&p->p_vmspace->vm_pmap); + printf("p->pm_vptpt[0] = %08x pdir=%08x\n", *((int *)(p->p_vmspace->vm_pmap.pm_vptpt + 0)), p->p_vmspace->vm_pmap.pm_pdir); + pmap_freepagedir(&p->p_vmspace->vm_pmap); + p->p_vmspace->vm_pmap.pm_pdir = 0; +#endif + + idcflush(); +} + + +/* + * Move pages from one kernel virtual address to another. + * Both addresses are assumed to reside in the Sysmap, + * and size must be a multiple of CLSIZE. + */ + +void +pagemove(from, to, size) + caddr_t from, to; + int size; +{ + register pt_entry_t *fpte, *tpte; + + if (size % CLBYTES) + panic("pagemove: size=%08x", size); + +#ifdef DEBUG_VMMACHDEP + if (pmap_debug_level >= 0) + printf("pagemove: V%08x to %08x size %08x\n", (u_int)from, + (u_int)to, size); +#endif + fpte = vtopte(from); + tpte = vtopte(to); + + idcflush(); + + while (size > 0) { + *tpte++ = *fpte; + *fpte++ = 0; + size -= NBPG; + } + tlbflush(); +} + +extern vm_map_t phys_map; + +/* + * Map an IO request into kernel virtual address space. Requests fall into + * one of five catagories: + * + * B_PHYS|B_UAREA: User u-area swap. + * Address is relative to start of u-area (p_addr). + * B_PHYS|B_PAGET: User page table swap. + * Address is a kernel VA in usrpt (Usrptmap). + * B_PHYS|B_DIRTY: Dirty page push. + * Address is a VA in proc2's address space. + * B_PHYS|B_PGIN: Kernel pagein of user pages. + * Address is VA in user's address space. + * B_PHYS: User "raw" IO request. + * Address is VA in user's address space. + * + * All requests are (re)mapped into kernel VA space via the useriomap + * (a name with only slightly more meaning than "kernelmap") + */ + +void +vmapbuf(bp, len) + struct buf *bp; + vm_size_t len; +{ + vm_offset_t faddr, taddr, off; + pt_entry_t *fpte, *tpte; + pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t)); + + if (pmap_debug_level >= 0) + printf("vmapbuf: bp=%08x buf=%08x len=%08x\n", (u_int)bp, + (u_int)bp->b_data, (u_int)len); + + if ((bp->b_flags & B_PHYS) == 0) + panic("vmapbuf"); + + faddr = trunc_page(bp->b_saveaddr = bp->b_data); + off = (vm_offset_t)bp->b_data - faddr; + len = round_page(off + len); + taddr = kmem_alloc_wait(phys_map, len); + bp->b_data = (caddr_t)(taddr + off); + /* + * The region is locked, so we expect that pmap_pte() will return + * non-NULL. + */ + + fpte = pmap_pte(vm_map_pmap(&bp->b_proc->p_vmspace->vm_map), faddr); + tpte = pmap_pte(vm_map_pmap(phys_map), taddr); + + idcflush(); + + do { + *fpte = (*fpte) & ~PT_C; + *tpte++ = *fpte++; + len -= PAGE_SIZE; + } while (len > 0); + tlbflush(); +} + +/* + * Free the io map PTEs associated with this IO operation. + * We also invalidate the TLB entries and restore the original b_addr. + */ + +void +vunmapbuf(bp, len) + struct buf *bp; + vm_size_t len; +{ + vm_offset_t addr, off; + + if (pmap_debug_level >= 0) + printf("vunmapbuf: bp=%08x buf=%08x len=%08x\n", + (u_int)bp, (u_int)bp->b_data, (u_int)len); + + if ((bp->b_flags & B_PHYS) == 0) + panic("vunmapbuf"); + + idcflush(); + + addr = trunc_page(bp->b_data); + off = (vm_offset_t)bp->b_data - addr; + len = round_page(off + len); + kmem_free_wakeup(phys_map, addr, len); + bp->b_data = bp->b_saveaddr; + bp->b_saveaddr = 0; + + tlbflush(); +} + +/* + * Dump the machine specific segment at the start of a core dump. + */ + +int +cpu_coredump(p, vp, cred, chdr) + struct proc *p; + struct vnode *vp; + struct ucred *cred; + struct core *chdr; +{ + int error; + struct { + struct reg regs; + struct fpreg fpregs; + } cpustate; + struct coreseg cseg; + + CORE_SETMAGIC(*chdr, COREMAGIC, MID_ARM6, 0); + chdr->c_hdrsize = ALIGN(sizeof(*chdr)); + chdr->c_seghdrsize = ALIGN(sizeof(cseg)); + chdr->c_cpusize = sizeof(cpustate); + + /* Save integer registers. */ + error = process_read_regs(p, &cpustate.regs); + if (error) + return error; + /* Save floating point registers. */ + error = process_read_fpregs(p, &cpustate.fpregs); + if (error) + return error; + + CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ARM6, CORE_CPU); + cseg.c_addr = 0; + cseg.c_size = chdr->c_cpusize; + + error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, + (off_t)chdr->c_hdrsize, UIO_SYSSPACE, + IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); + if (error) + return error; + + error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cpustate, sizeof(cpustate), + (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, + IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); + if (error) + return error; + + chdr->c_nseg++; + + return error; +} + +/* End of vm_machdep.c */ diff --git a/sys/arch/arm32/boot/Makefile b/sys/arch/arm32/boot/Makefile new file mode 100644 index 00000000000..e97fa6865df --- /dev/null +++ b/sys/arch/arm32/boot/Makefile @@ -0,0 +1,96 @@ +# $NetBSD: Makefile,v 1.2 1996/02/01 22:29:25 mycroft Exp $ + +# Copyright (c) 1994,1995 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 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 +# +# Makefile +# +# Makefile for RiscBSD bootloader for RISCOS +# +# Created : 14/01/96 +# Last updated : 14/01/96 +# +# $Id: Makefile,v 1.1.1.1 1996/04/24 11:08:30 deraadt Exp $ +# + +S= ../../.. + +machine-links: + -rm -f machine && \ + ln -s ${.CURDIR}/../include machine + -rm -f ${MACHINE_ARCH} && \ + ln -s ${.CURDIR}/../include ${MACHINE_ARCH} + +all: machine-links boot + +NOPROG= noprog +NOMAN= noman + +CFLAGS= -O3 -fno-builtin -D_LOCORE -D_KERNEL -I. -I${.CURDIR} -I$S -I${.CURDIR}/../.. +AFLAGS= -D_LOCORE -D_KERNEL -I. -I${.CURDIR} -I$S -I${.CURDIR}/../.. + +### find out what to use for libkern and libsa +#SAREL= +#KERNREL= +#.include "Makefile.inc" +.include "$S/lib/libsa/Makefile.inc" +.include "$S/lib/libkern/Makefile.inc" + +all: boot ${SALIB} ${KERNLIB} + +#.PATH: $S/lib/libkern +#.PATH: $S/lib/libkern/arch/arm32 + +# start.o should be first +OBJS= start.o strcpy.o strlen.o strncmp.o strstr.o \ + svc32.o div.o exit.o enteros.o exitos.o setcpsr.o \ + memcpy.o memset.o ntohl.o _bsdboot.o _main.o \ + areahand.o vsprintf.o bsdbooter.o swiv.o + +boot: ${OBJS} + ${LD} -Bstatic -e start -N -Ttext 0x8000 -o boot ${OBJS} + cp boot boot.sym + @strip boot + @sh ${.CURDIR}/rmaouthdr boot boot.tmp + @mv -f boot.tmp boot + @ls -l boot + +CLEANFILES+=boot boot.sym machine ${MACHINE_ARCH} + +clean:: + rm -f a.out [Ee]rrs mklog core *.core + rm -f ${PROG} ${OBJS} ${LOBJS} ${CLEANFILES} + +.include diff --git a/sys/arch/arm32/boot/Makefile.inc b/sys/arch/arm32/boot/Makefile.inc new file mode 100644 index 00000000000..45bcede83bc --- /dev/null +++ b/sys/arch/arm32/boot/Makefile.inc @@ -0,0 +1,28 @@ +# $NetBSD: Makefile.inc,v 1.1 1996/01/31 23:17:48 mark Exp $ +# +# NOTE: $S must correspond to the top of the 'sys' tree + +KERNDIR= $S/lib/libkern + +KERNDST= lib/kern +KERNREL?= ../../ +KERNLIB?= ${KERNDST}/libkern.a + +${KERNLIB}: .NOTMAIN __always_make_kernlib + @echo making sure the kern library is up to date... + @(cd ${KERNDST} && ${MAKE} -f ${KERNREL}${KERNDIR}/Makefile \ + KERNCC="${CC}" \ + KERNCFLAGS="${CFLAGS}" \ + KERNREL="${KERNREL}" \ + KERNDIR="${KERNDIR}" libkern.o) + +clean:: .NOTMAIN __always_make_kernlib + @echo cleaning the kern library objects + @(cd ${KERNDST} && ${MAKE} -f ${KERNREL}${KERNDIR}/Makefile \ + KERNCC="${CC}" \ + KERNCFLAGS="${CFLAGS}" \ + KERNREL="${KERNREL}" \ + KERNDIR="${KERNDIR}" clean) + +__always_make_kernlib: .NOTMAIN + @([ -d ${KERNDST} ] || mkdir -p ${KERNDST}) diff --git a/sys/arch/arm32/boot/README b/sys/arch/arm32/boot/README new file mode 100644 index 00000000000..27aa4846887 --- /dev/null +++ b/sys/arch/arm32/boot/README @@ -0,0 +1,7 @@ +Ok, this is the bootloader source that can be used to boot NetBSD/arm32 +from RISCOS. This code was written for use with Norcroft C and +objasm under RISCOS. It has been modified to compile under NetBSD/arm32 +but is as yet untested. + +It is provided here for the moment as example code for a boot loader +and will be updated shortly to compile under NetBSD/arm32 diff --git a/sys/arch/arm32/boot/_bsdboot.S b/sys/arch/arm32/boot/_bsdboot.S new file mode 100644 index 00000000000..c9be417742f --- /dev/null +++ b/sys/arch/arm32/boot/_bsdboot.S @@ -0,0 +1,55 @@ +/* $NetBSD: _bsdboot.S,v 1.1 1996/01/31 23:17:52 mark 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 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. + * + * RiscBSD kernel project + * + * _boot.s + * + * Kernel entry/exit code + * + * Created : 12/09/94 + * Last updated : 12/09/94 + * + * Based on kate/boot/_boot.s + * + * $Id: _bsdboot.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $ + */ + +#include "regs.h" + + .text + .global __bsdboot +__bsdboot: + mov pc, r1 diff --git a/sys/arch/arm32/boot/_main.S b/sys/arch/arm32/boot/_main.S new file mode 100644 index 00000000000..c0bdb9ef819 --- /dev/null +++ b/sys/arch/arm32/boot/_main.S @@ -0,0 +1,141 @@ +/* $NetBSD: _main.S,v 1.1 1996/01/31 23:17:57 mark 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 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. + * + * RiscBSD kernel project + * + * _main.s + * + * Kernel entry/exit code + * + * Created : 12/09/94 + * Last updated : 12/09/94 + * + * Based on kate/boot/_main.s + * + * $Id: _main.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $ + */ + +#include "regs.h" + + .global ___main +___main: + swi 0x20010 + mov sp, r1 + sub sl, sp, #2048 + + ldr r3, [pc, #cli_ptr - . - 8] + str r0, [r3] +#if 0 + LDR a4,[pc,#|__cli_ptr|-.-8] + STR a1,[a4,#0] + LDR a4,[pc,#|__himem_ptr|-.-8] + STR a2,[a4,#0] + LDR a4,[pc,#|__stack_ptr|-.-8] + STR sl,[a4,#0] + LDR a4,[pc,#|__robase_ptr|-.-8] + LDR a1,[a4,#0] + LDR a4,[pc,#|__base_ptr|-.-8] + STR a1,[a4,#0] + LDR a4,[pc,#|__rwlimit_ptr|-.-8] + LDR a1,[a4,#0] + LDR a4,[pc,#|__lomem_ptr|-.-8] + STR a1,[a4,#0] + LDR a4,[pc,#|__break_ptr|-.-8] + STR a1,[a4,#0] +#endif +#if 0 + cmp sl, r0 + movlss pc, lr /* no stack - exit fast */ + add sl, sl, #256 +#endif + mov fp, #0 + b __main + +cli_ptr: + .word ___cli + + .data + .global ___cli +___cli: + .word 0 + +#if 0 + +|__cli_ptr| + DCD |__cli| + +|__robase_ptr| + DCD |__robase| +|__base_ptr| + DCD |__base| +|__rwbase_ptr| + DCD |__rwbase| +|__rwlimit_ptr| + DCD |__rwlimit| +|__himem_ptr| + DCD |__himem| +|__lomem_ptr| + DCD |__lomem| + +|__break_ptr| + DCD |__break| +|__stack_ptr| + DCD |__stack| + +|__time_ptr| + DCD |__time| + + EXPORT |__cli| ; CLI from OS_GetEnv +|__cli| + DCD 0 + + EXPORT |__base| ; BASE (application = 0x8000) +|__base| + DCD 0 + EXPORT |__lomem| ; LOMEM +|__lomem| + DCD 0 + EXPORT |__himem| ; HIMEM from OS_GetEnv +|__himem| + DCD 0 + + EXPORT |__break| ; the 'break' +|__break| + DCD 0 + EXPORT |__stack| ; stack limit +|__stack| + DCD 0 + +#endif diff --git a/sys/arch/arm32/boot/areahand.S b/sys/arch/arm32/boot/areahand.S new file mode 100644 index 00000000000..6955ec31778 --- /dev/null +++ b/sys/arch/arm32/boot/areahand.S @@ -0,0 +1,98 @@ +/* $NetBSD: areahand.S,v 1.1 1996/01/31 23:18:01 mark 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 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. + * + * RiscBSD kernel project + * + * areahand.s + * + * + * + * Created : 12/09/94 + * Last updated : 12/09/94 + * + * $Id: areahand.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $ + */ + +#include "regs.h" + + .text + .global _kernarea_handler +/* + * r0 - code + * r1 - page block + * r2 - entries + * r3 - size increase + * r4 - current size + * r5 - pagesize + * r12 - arrangement table + */ + +_kernarea_handler: +/* Is it a pregrow request ? */ + teq r0, #0x00000000 + bicnes pc, lr, #1<<28 + +/* Make sure that the area is currently 0 in size */ + teq r4, #0x00000000 + movne r0, #0x000000 + orrnes pc, lr, #1<<28 + + teq r1, #0x00000000 + biceqs pc, lr, #1<<28 + +/* Store registers */ + stmfd sp!, {r0-r12} + +/* Get first page number */ + ldr r8, [r12, #0x0004] + sub r8, r8, r2 + mov r8, #0x00000700 + str r1, [r12] + +loop: + str r8, [r1], #0x000c + add r8, r8, #0x00000001 + subs r2, r2, #0x00000001 + bne loop + + ldmfd sp!, {r0-r12} +/* bics pc, lr, #1<<28 */ + adr r0, error1 + orrs pc, lr, #1<<28 + +error1: + .word 0 + .asciz "error1" diff --git a/sys/arch/arm32/boot/arm6.h b/sys/arch/arm32/boot/arm6.h new file mode 100644 index 00000000000..9c52ce662a9 --- /dev/null +++ b/sys/arch/arm32/boot/arm6.h @@ -0,0 +1,161 @@ +; ARM6 PSR transfer macros + +; Condition code symbols + +Cond_EQ * 0 :SHL: 28 +Cond_NE * 1 :SHL: 28 +Cond_CS * 2 :SHL: 28 +Cond_HS * Cond_CS +Cond_CC * 3 :SHL: 28 +Cond_LO * Cond_CC +Cond_MI * 4 :SHL: 28 +Cond_PL * 5 :SHL: 28 +Cond_VS * 6 :SHL: 28 +Cond_VC * 7 :SHL: 28 +Cond_HI * 8 :SHL: 28 +Cond_LS * 9 :SHL: 28 +Cond_GE * 10 :SHL: 28 +Cond_LT * 11 :SHL: 28 +Cond_GT * 12 :SHL: 28 +Cond_LE * 13 :SHL: 28 +Cond_AL * 14 :SHL: 28 +Cond_ * Cond_AL +Cond_NV * 15 :SHL: 28 + +; New positions of I and F bits in 32-bit PSR + +I32_bit * 1 :SHL: 7 +F32_bit * 1 :SHL: 6 +IF32_26Shift * 26-6 + +; Processor mode numbers + +USR26_mode * 2_00000 +FIQ26_mode * 2_00001 +IRQ26_mode * 2_00010 +SVC26_mode * 2_00011 +USR32_mode * 2_10000 +FIQ32_mode * 2_10001 +IRQ32_mode * 2_10010 +SVC32_mode * 2_10011 +ABT32_mode * 2_10111 +UND32_mode * 2_11011 + +; New register names + +r13_abort RN 13 +r14_abort RN 14 +lr_abort RN 14 + +r13_undef RN 13 +r14_undef RN 14 +lr_undef RN 14 + + MACRO + mrs $cond, $rd, $psrs + LCLA psrtype +psrtype SETA -1 + [ "$psrs" = "CPSR" :LOR: "$psrs" = "CPSR_all" +psrtype SETA 0 :SHL: 22 + ] + [ "$psrs" = "SPSR" :LOR: "$psrs" = "SPSR_all" +psrtype SETA 1 :SHL: 22 + ] + ASSERT psrtype <> -1 + ASSERT $rd <> 15 + & Cond_$cond :OR: 2_00000001000011110000000000000000 :OR: psrtype :OR: ($rd :SHL: 12) + MEND + + MACRO + msr $cond, $psrl, $op2a, $op2b + LCLA psrtype + LCLS op2as + LCLA op + LCLA shift +psrtype SETA -1 + [ "$psrl" = "CPSR" :LOR: "$psrl" = "CPSR_all" +psrtype SETA (0:SHL:22) :OR: (1:SHL:19) :OR: (1:SHL:16) + ] + [ "$psrl" = "CPSR_flg" +psrtype SETA (0:SHL:22) :OR: (1:SHL:19) :OR: (0:SHL:16) + ] + [ "$psrl" = "CPSR_ctl" +psrtype SETA (0:SHL:22) :OR: (0:SHL:19) :OR: (1:SHL:16) + ] + [ "$psrl" = "SPSR" :LOR: "$psrl" = "SPSR_all" +psrtype SETA (1:SHL:22) :OR: (1:SHL:19) :OR: (1:SHL:16) + ] + [ "$psrl" = "SPSR_flg" +psrtype SETA (1:SHL:22) :OR: (1:SHL:19) :OR: (0:SHL:16) + ] + [ "$psrl" = "SPSR_ctl" +psrtype SETA (1:SHL:22) :OR: (0:SHL:19) :OR: (1:SHL:16) + ] + ASSERT psrtype <> -1 + [ ("$op2a" :LEFT: 1) = "#" + ; Immediate operand + +op2as SETS "$op2a" :RIGHT: ((:LEN: "$op2a")-1) +op SETA $op2as + + [ "$op2b" = "" + ; Rotate not specified in immediate operand +shift SETA 0 + WHILE (op :AND: &FFFFFF00)<>0 :LAND: shift<16 +op SETA ((op:SHR:30):AND:3):OR:(op:SHL:2) +shift SETA shift + 1 + WEND + ASSERT (op :AND: &FFFFFF00)=0 + | + ; Rotate of immediate operand specified explicitly + ASSERT (($op2b):AND:&FFFFFFE1)=0 +shift SETA ($opt2b):SHR:1 + ] +op SETA (shift :SHL: 8) :OR: op :OR: (1:SHL:25) + | + + ; Not an immediate operand + [ "$op2b" = "" + ; Unshifted register +op SETA ($op2a) :OR: (0:SHL:25) + | + ! 1, "Shifted register not yet implemented in this macro!" + ] + ] + & Cond_$cond :OR: 2_00000001001000001111000000000000 :OR: op :OR: psrtype + MEND + +; SetMode newmode, reg1, regoldpsr +; +; Sets processor mode to constant value newmode +; using register reg1 as a temporary. +; If regoldpsr is specified, then this register +; on exit holds the old PSR before the mode change +; reg1 on exit always holds the new PSR after the mode change + +; MACRO +; SetMode $newmode, $reg1, $regoldpsr +; [ "$regoldpsr"="" +; mrs AL, $reg1, CPSR_all +; BIC $reg1, $reg1, #&1F +; ORR $reg1, $reg1, #$newmode +; msr AL, CPSR_all, $reg1 +; | +; mrs AL, $regoldpsr, CPSR_all +; BIC $reg1, $regoldpsr, #&1F +; ORR $reg1, $reg1, #$newmode +; msr AL, CPSR_all, $reg1 +; ] +; MEND + + MACRO + mrc $cond, $coproc, $op, $rd, $crn, $crm, $info + & Cond_$cond :OR: 2_00001110000100000000000000010000 :OR: ($coproc :SHL: 8) :OR: ($op :SHL: 21) :OR: ($rd :SHL: 12) :OR: ($crn :SHL: 16) :OR: $crm :OR: ($info :SHL: 5) + MEND + + MACRO + mcr $cond, $coproc, $op, $rd, $crn, $crm, $info + & Cond_$cond :OR: 2_00001110000000000000000000010000 :OR: ($coproc :SHL: 8) :OR: ($op :SHL: 21) :OR: ($rd :SHL: 12) :OR: ($crn :SHL: 16) :OR: $crm :OR: ($info :SHL: 5) + MEND + + END diff --git a/sys/arch/arm32/boot/bsdbooter.c b/sys/arch/arm32/boot/bsdbooter.c new file mode 100644 index 00000000000..c1873358f5e --- /dev/null +++ b/sys/arch/arm32/boot/bsdbooter.c @@ -0,0 +1,777 @@ +/* $NetBSD: bsdbooter.c,v 1.1 1996/01/31 23:18:08 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 Mark Brinicombe. + * Copyright (c) 1994,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 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 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 + * + * bsdbooter.c + * + * RiscBSD boot loader + * + * Created : 12/09/94 + * Last updated : 08/03/95 + * + * Based on kate/boot/boot.c + * + * $Id: bsdbooter.c,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $ + */ + +/* Include standard header files */ + +# include +# include +# include + +/* Include local headers */ + +#include +#include +#include +#include +#include +#include "swiv.h" +#include "swis.h" + +/* + * Declare global variables + */ + +# define VERSION "2.10" + +# define USE_MODULEAREA + +# define KERNAREA 512 +# define KERNBASE 0xf0000000 + +# define TABLEAREA 513 +# define LOADAREA 514 + +# define SCRATCHSIZE 0xc000 + + +# define OS_DynamicArea 0x66 +# define OS_Memory 0x68 +# define OS_MMUControl 0x6b + +# define FASTBOOT_FILENAME ".booter.fastboot" + +/* + * Declare external variables + */ + +extern char *__cli; + +/* + * Local vars. Some of these have to be global because they are used after + * the processor has been switches to SVC mode local variables would be + * lost as they would be on the USR mode stack. + */ + +typedef struct exec aout_t; + +BootConfig bootconfig; +int in[3], out[3]; +char kernelname[1024]; +unsigned char *buffer; +static aout_t aout; +unsigned int kernelsize; +unsigned int logical; +unsigned int physical; +unsigned int filesize; +unsigned int copysize; + +/* + * Local function prototypes + */ + +void fatal(struct Error *error); +unsigned char *locate_memory_blocks(void); +void uprintf(char *formattoken, ...); +void _bsdboot(BootConfig *bootconfig, unsigned int address); +int vsprintf(char *buf, const char *fmt, va_list args); + +/* Now for the main code */ + +extern int main (int, char **); + +void __exit(int); + +void _main(void) + { + uprintf("_main entered\n"); + __exit (main (0, (char **)0)); /* ... ignition */ + +/* not reached */ + } + +/* The main booter code */ + +int main(int argc, char *argv[]) + { + char *cliptr; + int loop; + int filehandle; + unsigned char *arrangementtable; + + uprintf("main entered\n"); + +/* Analyse the command line */ + + cliptr = __cli; + + uprintf("command line is %s\n", cliptr); + +/* Skip the command name */ + + while (*cliptr != ' ' && *cliptr != 0) + ++cliptr; + +/* Skip any spaces */ + + while (*cliptr == ' ') + ++cliptr; + +/* Check for another parameter */ + + if (*cliptr != 0) + { + for (loop = 0; *cliptr != ' ' && *cliptr != 0; ++loop,++cliptr) + { + kernelname[loop] = *cliptr; + } + kernelname[loop] = 0; + } + else + strcpy(kernelname, "riscbsd"); + + strcpy(bootconfig.kernelname, kernelname); + +/* Write the command line used to a fastboot file. Execing or Obeying + * this file will boot RiscBSD. This can be used during the RiscOS bootup + * to enable a fast boot. + */ + +/* + * Open the autoboot file. Just skip if file cannot be opened. + */ + + swi(OS_Find, IN(R0|R1)|OUT(R0), 0x80, FASTBOOT_FILENAME, &filehandle); + if (filehandle != 0) + { + swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, __cli, + strlen(__cli), 0); + swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 2, filehandle, "\n", 1, 0); + +/* Close the file */ + + swi(OS_Find, IN(R0|R1), 0, filehandle); + + swi(OS_File, IN(R0|R1|R2), 18, FASTBOOT_FILENAME, 0xfeb); + } + else + { + uprintf("Warning: Cannot write fastboot file %s\n\r", FASTBOOT_FILENAME); + } + +/* Set the screen mode ... */ + +/* I know this is messy. It is currently just a hack to try things out + * Why didn't Acorn add a SWI call to interpret the mode string and return + * a mode specifer ? + */ + +/* Also this is temporary as eventually the console driver will set the VIDC + * up as required. + * It sort of expects the screenmode= options to be at the end of the string. + */ + + { + char *modeptr; + int modespec[6]; + + modeptr = strstr(__cli, "screenmode="); + if (modeptr) + { + modeptr += 11; + modespec[0] = 0x00000001; + modespec[1] = 0x00000000; + modespec[2] = 0x00000000; + modespec[3] = 0x00000003; + modespec[4] = 0x00000000; + modespec[5] = -1; + + while (*modeptr) + { + switch (*modeptr) + { + case 'X': + case 'x': + ++modeptr; + while (*modeptr >= '0' && *modeptr <= '9') + { + modespec[1] = (modespec[1] * 10) + (*modeptr - '0'); + ++modeptr; + } + break; + + case 'Y': + case 'y': + ++modeptr; + while (*modeptr >= '0' && *modeptr <= '9') + { + modespec[2] = (modespec[2] * 10) + (*modeptr - '0'); + ++modeptr; + } + break; +/* + case 'C': + case 'c': + case 'G': + case 'g': + ++modeptr; + while (*modeptr >= '0' && *modeptr <= '9') + { + modespec[3] = (modespec[3] * 10) + (*modeptr - '0'); + ++modeptr; + } + break; +*/ + case 'F': + case 'f': + ++modeptr; + while (*modeptr >= '0' && *modeptr <= '9') + { + modespec[4] = (modespec[4] * 10) + (*modeptr - '0'); + ++modeptr; + } + break; + + default: + ++modeptr; + break; + } + } + if (modespec[4] == 0) modespec[4] = -1; +/* uprintf("x=%d y=%d c=%d f=%d\n", modespec[1], modespec[2], + modespec[3], modespec[4]);*/ + fatal(swix(Wimp_SetMode, IN(R0), &modespec)); + bootconfig.framerate = modespec[4]; + } + else + bootconfig.framerate = 0; + } + +/* Announcement time .. */ +/* Used to be above but now moved to after the mode change */ + + + if (strstr(__cli, "verbose") != 0) + uprintf("RiscBSD BootLoader " VERSION " " __DATE__ "\n\r"); + +/* A bit of info */ + + if (strstr(__cli, "verbose") != 0) + uprintf("Kernel: %s\n\r", kernelname); + +/* Get the machine id */ + + fatal(swix(OS_ReadSysInfo, IN(R0)|OUT(R3), 2, &bootconfig.machine_id)); + +/* Get the display variables. Failure on any of these will abort the boot */ + + in[0] = 149; + in[1] = 150; + in[2] = -1; + + fatal(swix(OS_ReadVduVariables, IN(R0|R1), &in, &out)); + + bootconfig.display_start = out[0]; + bootconfig.display_size = out[1]; + + fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 9, + &bootconfig.bitsperpixel)); + fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 11, + &bootconfig.width)); + fatal(swix(OS_ReadModeVariable, IN(R0|R1) | OUT(R2), -1, 12, + &bootconfig.height)); + +/* Will the kernel support this mode ? */ + + if (bootconfig.bitsperpixel > 3) + { + swi(OS_Write0, IN(R0), + "Error: Only 1, 2, 4 or 8 bpp modes are currently supported\n\r"); + return(0); + } + +/* Get the arrangement table for the memory */ + + arrangementtable = locate_memory_blocks(); + +/* + * Ok we will support a.out files as well. This means that we need to + * identify the format. + */ + +/* Get the size of the file */ + + fatal(swix(OS_File, IN(R0|R1)|OUT(R4), 5, kernelname, &filesize)); + +/* + * Read the start of the file so that we change check for the a.out + * magic number. + */ + + swi(OS_Find, IN(R0|R1)|OUT(R0), 0x40, kernelname, &filehandle); + if (filehandle == 0) + { + uprintf("Error: Cannot read kernel file %s\n\r", kernelname); + return(0); + } + + aout.a_midmag = 0; + + fatal(swix(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, &aout, + sizeof(aout_t), 0)); + +/* Do we have an a.out file ? */ + + switch(N_GETMAGIC(aout)) { + case NMAGIC: + if (strstr(__cli, "verbose") != 0) + swi(OS_Write0, IN(R0), "Kernel binary is NMAGIC a.out format\n\r"); + kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss); + copysize = (unsigned int)(aout.a_text + aout.a_data); + break; + case OMAGIC: + if (strstr(__cli, "verbose") != 0) + swi(OS_Write0, IN(R0), "Kernel binary is OMAGIC a.out format\n\r"); + kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss); + copysize = (unsigned int)(aout.a_text + aout.a_data); + break; + case ZMAGIC: + if (strstr(__cli, "verbose") != 0) + swi(OS_Write0, IN(R0), "Kernel binary is ZMAGIC a.out format\n\r"); + kernelsize = (unsigned int)(aout.a_text + aout.a_data + aout.a_bss); + copysize = (unsigned int)(aout.a_text + aout.a_data); + break; + default: + if (strstr(__cli, "verbose") != 0) + swi(OS_Write0, IN(R0), "Kernel binary is AIF format\n\r"); + kernelsize = filesize; + copysize = filesize; + break; + } + +/* Give ourselves 16K of spare space and round off to a page */ + +/* + * This is messy. We should read the memory info first, but I have not + * changed things yet. This is part of the hack to support a.out files + * as well + */ + + kernelsize = (kernelsize + 0x4000) & ~(bootconfig.pagesize-1); + +/* Set the virtual address of the kernel in the bootconfig structure */ + + bootconfig.kernvirtualbase = KERNBASE; + bootconfig.kernsize = kernelsize; + bootconfig.argvirtualbase = bootconfig.kernvirtualbase + + bootconfig.kernsize; + bootconfig.argsize = bootconfig.pagesize; + bootconfig.scratchvirtualbase = bootconfig.argvirtualbase + + bootconfig.argsize; + bootconfig.scratchsize = SCRATCHSIZE; + + kernelsize += bootconfig.argsize; + + kernelsize += bootconfig.scratchsize; + +/* Verbose info to the user. This is mainly debugging */ + + if (strstr(__cli, "verbose") != 0) + { + uprintf("filesize = %08x\n\r", filesize); + uprintf("bootconfig.kernvirtualbase = %08x\n\r", + bootconfig.kernvirtualbase); + uprintf("bootconfig.kernsize = %08x\n\r", bootconfig.kernsize); + uprintf("bootconfig.argvirtualbase = %08x\n\r", + bootconfig.argvirtualbase); + uprintf("bootconfig.argsize = %08x\n\r", bootconfig.argsize); + uprintf("bootconfig.scratchvirtualbase = %08x\n\r", + bootconfig.scratchvirtualbase); + uprintf("bootconfig.scratchsize = %08x\n\r", bootconfig.scratchsize); + uprintf("kernelsize = %08x\n\r", kernelsize); + uprintf("copysize = %08x\n\r", copysize); + } + +# ifdef USE_MODULEAREA + +/* Allocate memory in module area to hold the data we are loading */ + + fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, filesize, &buffer)); + +# else + +/* Allocate memory to hold the data we are loading */ + + swix(OS_DynamicArea, IN(R0|R1), 1, LOADAREA); + + fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0, + LOADAREA, filesize, -1, 0x80, filesize, 0, 0, "Kate Data", &buffer)); + +# endif + +/* Load the appropriate part depending on the file type */ + + switch (N_GETMAGIC(aout)) { + case OMAGIC: + case NMAGIC: + swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer, + filesize, sizeof(aout_t)); + break; + case ZMAGIC: + default: + swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, filehandle, buffer, + filesize, 0); + break; + } + +/* Close the file */ + + fatal(swix(OS_Find, IN(R0|R1), 0, filehandle)); + + +/* This is redundant at the moment */ + + swix(OS_DynamicArea, IN(R0|R1), 1, KERNAREA); + + fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8), 0, + KERNAREA, 0, KERNBASE, 0x80, 0x1000, 0, 0, "Kate Kernel")); + +/* Shutdown RiscOS cleanly ... */ + +/* Close all open files and shutdown filing systems */ + + swix(OS_FSControl, IN(R0), 23); + +/* Issue a pre-reset service call to reset the podules */ + + swix(OS_ServiceCall, IN(R1), 0x45); + +/* Kill the etherH module to avoid locks up on reboot */ + + swix(OS_Module, IN(R0|R1), 4, "EtherH"); + +/* More user information describing the memory found */ + + if (strstr(__cli, "verbose") != 0) + { + uprintf("DRAM bank 0a = %08x %08x\n\r", bootconfig.dram[0].address, + bootconfig.dram[0].pages * bootconfig.pagesize); + uprintf("DRAM bank 0b = %08x %08x\n\r", bootconfig.dram[1].address, + bootconfig.dram[1].pages * bootconfig.pagesize); + uprintf("DRAM bank 1a = %08x %08x\n\r", bootconfig.dram[2].address, + bootconfig.dram[2].pages * bootconfig.pagesize); + uprintf("DRAM bank 1b = %08x %08x\n\r", bootconfig.dram[3].address, + bootconfig.dram[3].pages * bootconfig.pagesize); + uprintf("VRAM bank 0 = %08x %08x\n\r", bootconfig.vram[0].address, + bootconfig.vram[0].pages * bootconfig.pagesize); + } + +/* Hack for 2 Meg VRAM until the new console code is in place */ + +/* if (strstr(__cli, "vramhack") != 0) + { + bootconfig.display_size /= 1; + bootconfig.vram[0].pages /= 2; + + uprintf("VRAM bank 0 = %08x %08x\n\r", bootconfig.vram[0].address, + bootconfig.vram[0].pages * bootconfig.pagesize); + }*/ + +/* Jump to SVC26 mode - remember we have no local vars now ! */ + + EnterOS(); + +/* Find the number of the upper most bank of DRAM available */ + + loop = 3; + while (bootconfig.dram[loop].address == 0) + --loop; + +/* Allocate the physical addresses for the kernel in this bank */ + + physical = bootconfig.dram[loop].address - kernelsize + + bootconfig.dram[loop].pages * bootconfig.pagesize; + bootconfig.kernphysicalbase = physical; + bootconfig.argphysicalbase = bootconfig.kernphysicalbase + + bootconfig.kernsize; + bootconfig.scratchphysicalbase = bootconfig.argphysicalbase + + bootconfig.argsize; + +/* Yet more debugging info */ + + if (strstr(__cli, "verbose") != 0) + { + uprintf("buffer = %08x\n\r", buffer); + uprintf("physical = %08x\n\r", physical); + uprintf("bootconfig.kernphysicalbase = %08x\n\r", + bootconfig.kernphysicalbase); + uprintf("bootconfig.argphysicalbase = %08x\n\r", + bootconfig.argphysicalbase); + uprintf("bootconfig.scratchphysicalbase = %08x\n\r", + bootconfig.scratchphysicalbase); + } + +/* + * Ok just check to see if anything is mapped where we are about to map + * the kernel. + */ + +/* + for (logical = KERNBASE; logical < KERNBASE + kernelsize; + logical += bootconfig.pagesize) + { + if (ReadWord(0x02c00000 + (logical >> 10) & 0xfffffffc) != 0) + { + uprintf("Error: Memory required for RiscBSD boot not available\n\r"); + return(0); + } + } +*/ +/* Get out clause */ + + if (strstr(__cli, "noboot") != 0) + { + ExitOS(); + return(0); + } + +/* + * Hook the physical pages to the required virtual address directly by + * writing into RiscOS's page tables. This should be done via a + * dynamic area handler but I cannot get it to work as documented. + */ + + for (logical = KERNBASE; logical < KERNBASE + kernelsize; + logical += bootconfig.pagesize) + { + WriteWord(0x02c00000 + (logical >> 10) & 0xfffffffc, + 0x00000ffe | (physical & 0xfffff000)); + physical += bootconfig.pagesize; + } + +/* Map the IO up high so we can get at it */ + + WriteWord(0x02c0c000 + (0xf6000000 >> 18) & 0xfffffffc, + 0x00000412 | (0x03200000 & 0xfffff000)); + WriteWord(0x02c0c000 + (0xf6100000 >> 18) & 0xfffffffc, + 0x00000412 | (0x03400000 & 0xfffff000)); + + memset((char *)bootconfig.display_start, 0xcc, 0x4000); + +/* Disable IRQ and FIQ interrupts */ + + SetCPSR(I32_bit | F32_bit, I32_bit | F32_bit); + + memset((char *)bootconfig.display_start + 0x4000, 0x55, 0x4000); + + memcpy((char *)bootconfig.argvirtualbase, __cli, bootconfig.argsize); + + memset((char *)bootconfig.display_start + 0x8000, 0x80, 0x4000); + + memset((char *)bootconfig.argvirtualbase, SCRATCHSIZE, 0); + + memset((char *)bootconfig.display_start + 0xC000, 0xbb, 0x4000); + + memcpy((char *)bootconfig.kernvirtualbase, buffer, copysize); + + memset((char *)bootconfig.display_start + 0x10000, 0xaa, 0x4000); + +/* Real late debugging get out clause */ + + if (strstr(__cli, "nearboot") != 0) + { + SetCPSR(I32_bit | F32_bit, 0); + ExitOS(); + return(0); + } + +/* Punch into SVC32 mode */ + + SVC32(); + +/* Point of no return */ + + switch (N_GETMAGIC(aout)) { + case OMAGIC: + case NMAGIC: + case ZMAGIC: + _bsdboot(&bootconfig, (unsigned int)aout.a_entry); + break; + default: + _bsdboot(&bootconfig, KERNBASE); + break; + } + + return(0); + } + + +/* Report an error */ + +void fatal(struct Error *error) + { + if (error) + { + swi(OS_GenerateError, IN(R0), error); + } + } + + +/* Locate all the blocks of memory in the system */ + +unsigned char *locate_memory_blocks(void) + { + int loop; + int page; + int currentpage; + int currentpages; + int currentaddr; + unsigned char *table; + unsigned int pagesize; + unsigned int tablesize; + int dramblocks = 0; + int vramblocks = 0; + +/* Get table size and page size */ + + fatal(swix(OS_Memory, IN(R0)|OUT(R1|R2), 6, &tablesize, &pagesize)); + +/* Allocate memory for table */ + +/*# ifdef USE_MODULEAREA*/ + + fatal(swix(OS_Module, IN(R0|R3)|OUT(R2), 6, tablesize, &table)); + +/*# else*/ + +/* Allocate memory to hold the data we are loading */ + +/* swix(OS_DynamicArea, IN(R0|R1), 1, TABLEAREA); + + fatal(swix(OS_DynamicArea, IN(R0|R1|R2|R3|R4|R5|R6|R7|R8)|OUT(R3), 0, + TABLEAREA, tablesize, -1, 0x80, tablesize, 0, 0, "Kate Table", &table)); + +# endif*/ + + +/* read the table */ + + fatal(swix(OS_Memory, IN(R0|R1), 7, table)); + +/* Loop round locating all the valid blocks of memory */ + + currentpage = -1; + + for (loop = 0; loop < tablesize * 2; ++loop) + { + page = table[loop / 2]; + if (loop % 2) + page = page >> 4; + + page = page & 0x07; + + if (page != currentpage) + { + switch (currentpage) + { + case 1: + bootconfig.dram[dramblocks].address = currentaddr * pagesize; + bootconfig.dram[dramblocks].pages = currentpages; + ++dramblocks; + break; + + case 2: + bootconfig.vram[vramblocks].address = currentaddr * pagesize; + bootconfig.vram[vramblocks].pages = currentpages; + ++vramblocks; + break; + + default : + break; + } + + currentpage = page; + currentaddr = loop; + currentpages = 0; + } + ++currentpages; + } + +/* Get the number of dram and vram pages */ + + fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000108, &bootconfig.drampages)); + fatal(swix(OS_Memory, IN(R0)|OUT(R1), 0x00000208, &bootconfig.vrampages)); + +/* Fill in more bootconfig parameters */ + + bootconfig.pagesize = pagesize; + + bootconfig.dramblocks = dramblocks; + bootconfig.vramblocks = vramblocks; + + return(table); + } + + +/* printf ... */ + +void uprintf(char *formattoken, ...) + { + va_list ap; + char temp[1024]; + + temp[0] = '\0'; + + va_start(ap, formattoken); + vsprintf(temp, formattoken, ap); + va_end(ap); + + swi(OS_Write0, IN(R0), temp); + } + +/* End of bsdbooter.c */ diff --git a/sys/arch/arm32/boot/enteros.S b/sys/arch/arm32/boot/enteros.S new file mode 100644 index 00000000000..1dfb78a859f --- /dev/null +++ b/sys/arch/arm32/boot/enteros.S @@ -0,0 +1,65 @@ +/* $NetBSD: enteros.S,v 1.1 1996/01/31 23:18:11 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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. + * + * RiscBSD kernel project + * + * enteros.s + * + * Created : 12/09/94 + * Last updated : 12/09/94 + * + * Based on kate/library/enteros.s + * + * $Id: enteros.S,v 1.1.1.1 1996/04/24 11:08:31 deraadt Exp $ + */ + +#include "regs.h" + +#define OS_EnterOS 0x0016 + +/* + * Enters SVC26 mode + */ + + .text + .global _EnterOS +_EnterOS: + mov r1, lr + swi OS_EnterOS + + mov r0, pc + mov pc, r1 + diff --git a/sys/arch/arm32/boot/exit.S b/sys/arch/arm32/boot/exit.S new file mode 100644 index 00000000000..e4e72ca6afa --- /dev/null +++ b/sys/arch/arm32/boot/exit.S @@ -0,0 +1,64 @@ +/* $NetBSD: exit.S,v 1.1 1996/01/31 23:18:14 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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. + * + * RiscBSD kernel project + * + * _exit.s + * + * Boot loader exit point + * + * Created : 12/09/94 + * Last updated : 12/09/94 + * + * Based on kate/boot/_exit.s + * + * $Id: exit.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + */ + +#include "regs.h" + +#define OS_Exit 0x00000011 + + .text + .global ___exit +___exit: + mov r2, r0 + ldr r1, [pc, #Lexit_word - . - 8] + mov r0, #0x00000000 + swi OS_Exit + +Lexit_word: + .word 0x58454241 diff --git a/sys/arch/arm32/boot/exitos.S b/sys/arch/arm32/boot/exitos.S new file mode 100644 index 00000000000..45a5af29905 --- /dev/null +++ b/sys/arch/arm32/boot/exitos.S @@ -0,0 +1,63 @@ +/* $NetBSD: exitos.S,v 1.1 1996/01/31 23:18:16 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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. + * + * RiscBSD kernel project + * + * exitos.s + * + * + * + * Created : 12/09/94 + * Last updated : 12/09/94 + * + * Based on kate/library/exitos.s + * + * $Id: exitos.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + * + */ + +#include "regs.h" + +/* + * Returns from SVC26 mode to USR26 mode + */ + + .text + .global _ExitOS +_ExitOS: + mov r2, lr + bic r2, r2, #0x00000003 + movs pc, r2 diff --git a/sys/arch/arm32/boot/memcpy.S b/sys/arch/arm32/boot/memcpy.S new file mode 100644 index 00000000000..c1d58450479 --- /dev/null +++ b/sys/arch/arm32/boot/memcpy.S @@ -0,0 +1,113 @@ +/* $NetBSD: memcpy.S,v 1.1 1996/01/31 23:18:17 mark 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 + * + * memset.S + * + * optimized memset function + * + * Created : 16/05/95 + * Last updated : 16/05/95 + * + * $Id: memcpy.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + */ + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + .global _bcopy + .global _ovbcopy + +_bcopy: +_ovbcopy: + teq r2, #0x00000000 + moveq r0, #0x00000000 + moveq pc, lr + cmp r0, r1 + blt bcopy_back + +bcopy_loop: + ldrb r3, [r0], #0x0001 + strb r3, [r1], #0x0001 + subs r2, r2, #0x00000001 + bne bcopy_loop + + mov pc, r14 + +bcopy_back: + add r0, r0, r2 + add r1, r1, r2 + +bcopy_bloop: + ldrb r3, [r0, #-0x0001]! + strb r3, [r1, #-0x0001]! + subs r2, r2, #0x00000001 + bne bcopy_bloop + + mov pc, r14 + + + .global _memcpy + +_memcpy: + teq r2, #0x00000000 + moveq r0, #0x00000000 + moveq pc, lr + cmp r1, r0 + blt memcpy_back + +memcpy_loop: + ldrb r3, [r1], #0x0001 + strb r3, [r0], #0x0001 + subs r2, r2, #0x00000001 + bne memcpy_loop + + mov pc, r14 + +memcpy_back: + add r0, r0, r2 + add r1, r1, r2 + +memcpy_bloop: + ldrb r3, [r1, #-0x0001]! + strb r3, [r0, #-0x0001]! + subs r2, r2, #0x00000001 + bne memcpy_bloop + + mov pc, r14 diff --git a/sys/arch/arm32/boot/memset.S b/sys/arch/arm32/boot/memset.S new file mode 100644 index 00000000000..0a606ac640f --- /dev/null +++ b/sys/arch/arm32/boot/memset.S @@ -0,0 +1,136 @@ +/* $NetBSD: memset.S,v 1.1 1996/01/31 23:18:19 mark 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 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 + * + * memset.S + * + * optimized memset function + * + * Created : 16/05/95 + * Last updated : 16/05/95 + * + * $Id: memset.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + */ + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + + .global _memset + +/* Sets a block of memory to the specified value + * + * r0 - address + * r1 - byte to write + * r2 - number of bytes to write + */ + +_memset: + and r1, r1, #0x000000ff /* We write bytes */ + + cmp r2, #0x00000004 /* Do we have less than 4 bytes */ + blt memset_lessthanfour + +/* Ok first we will word align the address */ + + ands r3, r0, #0x00000003 /* Get the bottom two bits */ + beq memset_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 memset_lessthanfour + +/* Now we must be word aligned */ + +memset_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 memset_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 + +memset_loop16: + stmia r0!, {r3-r6} /* Store 16 bytes */ + sub r2, r2, #0x00000010 /* Adjust count */ + cmp r2, #0x00000010 /* Still got at least 16 bytes ? */ + bgt memset_loop16 + + ldmfd sp!, {r4-r6} /* Restore registers */ + +/* Do we need to set some words as well ? */ + + cmp r2, #0x00000004 + blt memset_lessthanfour + +/* Have either less than 16 or less than 32 depending on route taken */ + +memset_lessthan32: + +/* We have at least 4 bytes so copy as words */ + +memset_loop4: + str r3, [r0], #0x0004 + sub r2, r2, #0x0004 + cmp r2, #0x00000004 + bge memset_loop4 + +memset_lessthanfour: + cmp r2, #0x00000000 + moveq pc, lr /* Zero length so exit */ + + cmp r2, #0x00000002 + strb r1, [r0], #0x0001 /* Set 1 byte */ + strgeb r1, [r0], #0x0001 /* Set another byte */ + strgtb r1, [r0], #0x0001 /* and a third */ + + mov pc, lr /* Exit */ diff --git a/sys/arch/arm32/boot/regs.h b/sys/arch/arm32/boot/regs.h new file mode 100644 index 00000000000..c98be1d29d0 --- /dev/null +++ b/sys/arch/arm32/boot/regs.h @@ -0,0 +1,52 @@ +/* $NetBSD: regs.h,v 1.1 1996/01/31 23:18:21 mark Exp $ */ + +/* Copyright (c) 1994,1995 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 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. + * + * RiscBSD kernel project + * + * regs.h + * + * Assembly register definitions + * + * Created : 14/01/96 + * Last updated : 14/01/96 + * + * $Id: regs.h,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + */ + +fp .req r11 +sl .req r12 +sp .req r13 +lr .req r14 +pc .req r15 diff --git a/sys/arch/arm32/boot/rmaouthdr b/sys/arch/arm32/boot/rmaouthdr new file mode 100644 index 00000000000..39e09843891 --- /dev/null +++ b/sys/arch/arm32/boot/rmaouthdr @@ -0,0 +1,4 @@ +#!/bin/sh +# $NetBSD: rmaouthdr,v 1.1 1996/01/31 23:18:23 mark Exp $ + +dd if=$1 of=$2 ibs=32 skip=1 obs=1024b diff --git a/sys/arch/arm32/boot/setcpsr.S b/sys/arch/arm32/boot/setcpsr.S new file mode 100644 index 00000000000..3a9be1c9c28 --- /dev/null +++ b/sys/arch/arm32/boot/setcpsr.S @@ -0,0 +1,95 @@ +/* $NetBSD: setcpsr.S,v 1.1 1996/01/31 23:18:27 mark 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 + * + * setcpsr.S + * + * Miscellaneous routines to play with the CPSR register + * + * Eventually this routine can be inline assembly. + * + * Created : 12/09/94 + * Last updated : 28/05/95 + * + * Based of kate/display/setcpsr.s + * + * $Id: setcpsr.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + */ + +fp .req r11 +ip .req r12 +sp .req r13 +lr .req r14 +pc .req r15 + +.text + + .global _SetCPSR + +/* Sets and clears bits in the CPSR register + * + * r0 - bic mask + * r1 - eor mask + */ + +_SetCPSR: +/* mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4*/ + + mrs r3, cpsr_all /* Set the CPSR */ + bic r2, r3, r0 + eor r2, r2, r1 + msr cpsr_all, r2 + + mov r0, r3 /* Return the old CPSR */ + +/* ldmea fp, {fp, sp, pc}*/ + mov pc, lr + + .global _GetCPSR + +/* Gets the CPSR register + * + * Returns the CPSR in r0 + */ + +_GetCPSR: + mrs r0, cpsr_all /* Get the CPSR */ + + mov pc, lr + diff --git a/sys/arch/arm32/boot/start.S b/sys/arch/arm32/boot/start.S new file mode 100644 index 00000000000..6c6b1f8faa8 --- /dev/null +++ b/sys/arch/arm32/boot/start.S @@ -0,0 +1,54 @@ +/* $NetBSD: start.S,v 1.1 1996/01/31 23:18:30 mark 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 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. + * + * RiscBSD kernel project + * + * _main.s + * + * Kernel entry/exit code + * + * Created : 12/09/94 + * Last updated : 12/09/94 + * + * Based on kate/boot/_main.s + * + * $Id: start.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + */ + +#include "regs.h" + + .global start +start: + b ___main diff --git a/sys/arch/arm32/boot/strstr.c b/sys/arch/arm32/boot/strstr.c new file mode 100644 index 00000000000..0efc0ffab1f --- /dev/null +++ b/sys/arch/arm32/boot/strstr.c @@ -0,0 +1,70 @@ +/* $NetBSD: strstr.c,v 1.1 1996/01/31 23:18:34 mark Exp $ */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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: strstr.c,v 1.4 1995/06/15 00:08:43 jtc Exp + * + * $Id: strstr.c,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + */ + +#include +#include + +/* + * Find the first occurrence of find in s. + */ + +char * +strstr(s, find) + register const char *s, *find; +{ + register char c, sc; + register size_t len; + + if ((c = *find++) != 0) { + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return (NULL); + } while (sc != c); + } while (strncmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} + +/* End of strstr.c */ diff --git a/sys/arch/arm32/boot/svc32.S b/sys/arch/arm32/boot/svc32.S new file mode 100644 index 00000000000..0274c10eb69 --- /dev/null +++ b/sys/arch/arm32/boot/svc32.S @@ -0,0 +1,66 @@ +/* $NetBSD: svc32.S,v 1.1 1996/01/31 23:18:38 mark Exp $ */ + +/* + * Copyright (c) 1994,1955 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 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. + * + * RiscBSD kernel project + * + * svc32.s + * + * Created : 12/09/94 + * Last updated : 12/09/94 + * + * Based on kate/library/svc32.s + * + * $Id: svc32.S,v 1.1.1.1 1996/04/24 11:08:32 deraadt Exp $ + */ + +#include "regs.h" +#include + +/* + * Switches from SVC26 mode to SVC32 mode + */ + + .text + .global _SVC32 +_SVC32: + mrs r1, cpsr_all + bic r1, r1, #(PSR_MODE) + orr r1, r1, #(PSR_SVC32_MODE) + msr cpsr_all, r1 + + bic lr, lr, #0xfc000000 + + mov pc, lr diff --git a/sys/arch/arm32/boot/swis.h b/sys/arch/arm32/boot/swis.h new file mode 100644 index 00000000000..e1282b1a4c7 --- /dev/null +++ b/sys/arch/arm32/boot/swis.h @@ -0,0 +1,596 @@ +/* + Title: Swi numbers for RiscOs + Copyright (C) 1989, Acorn Computers Ltd., Cambridge, England + $Revision: 1.1.1.1 $ SWI_LIST 1.00 02-May-89 (Program generated) +*/ + +#ifndef __swis_h +#define __swis_h + +#define XOS_Bit 0x020000 + +#define OS_WriteI 0x000100 + +#define OS_WriteC 0x000000 +#define OS_WriteS 0x000001 +#define OS_Write0 0x000002 +#define OS_NewLine 0x000003 +#define OS_ReadC 0x000004 +#define OS_CLI 0x000005 +#define OS_Byte 0x000006 +#define OS_Word 0x000007 +#define OS_File 0x000008 +#define OS_Args 0x000009 +#define OS_BGet 0x00000a +#define OS_BPut 0x00000b +#define OS_GBPB 0x00000c +#define OS_Find 0x00000d +#define OS_ReadLine 0x00000e +#define OS_Control 0x00000f +#define OS_GetEnv 0x000010 +#define OS_Exit 0x000011 +#define OS_SetEnv 0x000012 +#define OS_IntOn 0x000013 +#define OS_IntOff 0x000014 +#define OS_CallBack 0x000015 +#define OS_EnterOS 0x000016 +#define OS_BreakPt 0x000017 +#define OS_BreakCtrl 0x000018 +#define OS_UnusedSWI 0x000019 +#define OS_UpdateMEMC 0x00001a +#define OS_SetCallBack 0x00001b +#define OS_Mouse 0x00001c +#define OS_Heap 0x00001d +#define OS_Module 0x00001e +#define OS_Claim 0x00001f +#define OS_Release 0x000020 +#define OS_ReadUnsigned 0x000021 +#define OS_GenerateEvent 0x000022 +#define OS_ReadVarVal 0x000023 +#define OS_SetVarVal 0x000024 +#define OS_GSInit 0x000025 +#define OS_GSRead 0x000026 +#define OS_GSTrans 0x000027 +#define OS_BinaryToDecimal 0x000028 +#define OS_FSControl 0x000029 +#define OS_ChangeDynamicArea 0x00002a +#define OS_GenerateError 0x00002b +#define OS_ReadEscapeState 0x00002c +#define OS_EvaluateExpression 0x00002d +#define OS_SpriteOp 0x00002e +#define OS_ReadPalette 0x00002f +#define OS_ServiceCall 0x000030 +#define OS_ReadVduVariables 0x000031 +#define OS_ReadPoint 0x000032 +#define OS_UpCall 0x000033 +#define OS_CallAVector 0x000034 +#define OS_ReadModeVariable 0x000035 +#define OS_RemoveCursors 0x000036 +#define OS_RestoreCursors 0x000037 +#define OS_SWINumberToString 0x000038 +#define OS_SWINumberFromString 0x000039 +#define OS_ValidateAddress 0x00003a +#define OS_CallAfter 0x00003b +#define OS_CallEvery 0x00003c +#define OS_RemoveTickerEvent 0x00003d +#define OS_InstallKeyHandler 0x00003e +#define OS_CheckModeValid 0x00003f +#define OS_ChangeEnvironment 0x000040 +#define OS_ClaimScreenMemory 0x000041 +#define OS_ReadMonotonicTime 0x000042 +#define OS_SubstituteArgs 0x000043 +#define OS_PrettyPrint 0x000044 +#define OS_Plot 0x000045 +#define OS_WriteN 0x000046 +#define OS_AddToVector 0x000047 +#define OS_WriteEnv 0x000048 +#define OS_ReadArgs 0x000049 +#define OS_ReadRAMFsLimits 0x00004a +#define OS_ClaimDeviceVector 0x00004b +#define OS_ReleaseDeviceVector 0x00004c +#define OS_DelinkApplication 0x00004d +#define OS_RelinkApplication 0x00004e +#define OS_HeapSort 0x00004f +#define OS_ExitAndDie 0x000050 +#define OS_ReadMemMapInfo 0x000051 +#define OS_ReadMemMapEntries 0x000052 +#define OS_SetMemMapEntries 0x000053 +#define OS_AddCallBack 0x000054 +#define OS_ReadDefaultHandler 0x000055 +#define OS_SetECFOrigin 0x000056 +#define OS_SerialOp 0x000057 +#define OS_ReadSysInfo 0x000058 +#define OS_Confirm 0x000059 +#define OS_ChangedBox 0x00005a +#define OS_CRC 0x00005b +#define OS_ReadDynamicArea 0x00005c +#define OS_PrintChar 0x00005d +#define OS_ChangeRedirection 0x00005e +#define OS_RemoveCallBack 0x00005f +#define OS_FindMemMapEntries 0x000060 +#define OS_SetColour 0x000061 +#define OS_ConvertStandardDateAndTime 0x0000c0 +#define OS_ConvertDateAndTime 0x0000c1 +#define OS_ConvertHex1 0x0000d0 +#define OS_ConvertHex2 0x0000d1 +#define OS_ConvertHex4 0x0000d2 +#define OS_ConvertHex6 0x0000d3 +#define OS_ConvertHex8 0x0000d4 +#define OS_ConvertCardinal1 0x0000d5 +#define OS_ConvertCardinal2 0x0000d6 +#define OS_ConvertCardinal3 0x0000d7 +#define OS_ConvertCardinal4 0x0000d8 +#define OS_ConvertInteger1 0x0000d9 +#define OS_ConvertInteger2 0x0000da +#define OS_ConvertInteger3 0x0000db +#define OS_ConvertInteger4 0x0000dc +#define OS_ConvertBinary1 0x0000dd +#define OS_ConvertBinary2 0x0000de +#define OS_ConvertBinary3 0x0000df +#define OS_ConvertBinary4 0x0000e0 +#define OS_ConvertSpacedCardinal1 0x0000e1 +#define OS_ConvertSpacedCardinal2 0x0000e2 +#define OS_ConvertSpacedCardinal3 0x0000e3 +#define OS_ConvertSpacedCardinal4 0x0000e4 +#define OS_ConvertSpacedInteger1 0x0000e5 +#define OS_ConvertSpacedInteger2 0x0000e6 +#define OS_ConvertSpacedInteger3 0x0000e7 +#define OS_ConvertSpacedInteger4 0x0000e8 +#define OS_ConvertFixedNetStation 0x0000e9 +#define OS_ConvertNetStation 0x0000ea +#define OS_ConvertFixedFileSize 0x0000eb +#define OS_ConvertFileSize 0x0000ec +#define IIC_Control 0x000240 +#define Cache_Control 0x000280 +#define Cache_Cacheable 0x000281 +#define Cache_Updateable 0x000282 +#define Cache_Disruptive 0x000283 +#define Cache_Flush 0x000284 +#define Trace_R0 0x00bf00 +#define Trace_R1 0x00bf01 +#define Trace_R2 0x00bf02 +#define Trace_R3 0x00bf03 +#define Trace_R4 0x00bf04 +#define Trace_R5 0x00bf05 +#define Trace_R6 0x00bf06 +#define Trace_R7 0x00bf07 +#define Trace_R8 0x00bf08 +#define Trace_R9 0x00bf09 +#define Trace_R10 0x00bf0a +#define Trace_R11 0x00bf0b +#define Trace_R12 0x00bf0c +#define Trace_R13 0x00bf0d +#define Trace_R14 0x00bf0e +#define Trace_R15 0x00bf0f +#define Trace_Regs 0x00bf10 +#define Trace_WriteC 0x00bf11 +#define Trace_NewLine 0x00bf12 +#define Trace_WriteS 0x00bf13 +#define Trace_Write0 0x00bf14 +#define Font_CacheAddr 0x040080 +#define Font_FindFont 0x040081 +#define Font_LoseFont 0x040082 +#define Font_ReadDefn 0x040083 +#define Font_ReadInfo 0x040084 +#define Font_StringWidth 0x040085 +#define Font_Paint 0x040086 +#define Font_Caret 0x040087 +#define Font_ConverttoOS 0x040088 +#define Font_Converttopoints 0x040089 +#define Font_SetFont 0x04008a +#define Font_CurrentFont 0x04008b +#define Font_FutureFont 0x04008c +#define Font_FindCaret 0x04008d +#define Font_CharBBox 0x04008e +#define Font_ReadScaleFactor 0x04008f +#define Font_SetScaleFactor 0x040090 +#define Font_ListFonts 0x040091 +#define Font_SetFontColours 0x040092 +#define Font_SetPalette 0x040093 +#define Font_ReadThresholds 0x040094 +#define Font_SetThresholds 0x040095 +#define Font_FindCaretJ 0x040096 +#define Font_StringBBox 0x040097 +#define Font_ReadColourTable 0x040098 +#define Font_MakeBitmap 0x040099 +#define Font_UnCacheFile 0x04009a +#define Font_SetFontMax 0x04009b +#define Font_ReadFontMax 0x04009c +#define Font_ReadFontPrefix 0x04009d +#define Font_SwitchOutputToBuffer 0x04009e +#define Font_ReadFontMetrics 0x04009f +#define Font_DecodeMenu 0x0400a0 +#define Font_ScanString 0x0400a1 +#define Font_SetColourTable 0x0400a2 +#define Font_CurrentRGB 0x0400a3 +#define Font_FutureRGB 0x0400a4 +#define Font_ReadEncodingFilename 0x0400a5 +#define Font_FindField 0x0400a6 +#define Font_ApplyFields 0x0400a7 +#define Font_LookupFont 0x0400a8 +#define Wimp_Initialise 0x0400c0 +#define Wimp_CreateWindow 0x0400c1 +#define Wimp_CreateIcon 0x0400c2 +#define Wimp_DeleteWindow 0x0400c3 +#define Wimp_DeleteIcon 0x0400c4 +#define Wimp_OpenWindow 0x0400c5 +#define Wimp_CloseWindow 0x0400c6 +#define Wimp_Poll 0x0400c7 +#define Wimp_RedrawWindow 0x0400c8 +#define Wimp_UpdateWindow 0x0400c9 +#define Wimp_GetRectangle 0x0400ca +#define Wimp_GetWindowState 0x0400cb +#define Wimp_GetWindowInfo 0x0400cc +#define Wimp_SetIconState 0x0400cd +#define Wimp_GetIconState 0x0400ce +#define Wimp_GetPointerInfo 0x0400cf +#define Wimp_DragBox 0x0400d0 +#define Wimp_ForceRedraw 0x0400d1 +#define Wimp_SetCaretPosition 0x0400d2 +#define Wimp_GetCaretPosition 0x0400d3 +#define Wimp_CreateMenu 0x0400d4 +#define Wimp_DecodeMenu 0x0400d5 +#define Wimp_WhichIcon 0x0400d6 +#define Wimp_SetExtent 0x0400d7 +#define Wimp_SetPointerShape 0x0400d8 +#define Wimp_OpenTemplate 0x0400d9 +#define Wimp_CloseTemplate 0x0400da +#define Wimp_LoadTemplate 0x0400db +#define Wimp_ProcessKey 0x0400dc +#define Wimp_CloseDown 0x0400dd +#define Wimp_StartTask 0x0400de +#define Wimp_ReportError 0x0400df +#define Wimp_GetWindowOutline 0x0400e0 +#define Wimp_PollIdle 0x0400e1 +#define Wimp_PlotIcon 0x0400e2 +#define Wimp_SetMode 0x0400e3 +#define Wimp_SetPalette 0x0400e4 +#define Wimp_ReadPalette 0x0400e5 +#define Wimp_SetColour 0x0400e6 +#define Wimp_SendMessage 0x0400e7 +#define Wimp_CreateSubMenu 0x0400e8 +#define Wimp_SpriteOp 0x0400e9 +#define Wimp_BaseOfSprites 0x0400ea +#define Wimp_BlockCopy 0x0400eb +#define Wimp_SlotSize 0x0400ec +#define Wimp_ReadPixTrans 0x0400ed +#define Wimp_ClaimFreeMemory 0x0400ee +#define Wimp_CommandWindow 0x0400ef +#define Wimp_TextColour 0x0400f0 +#define Wimp_TransferBlock 0x0400f1 +#define Wimp_ReadSysInfo 0x0400f2 +#define Wimp_SetFontColours 0x0400f3 +#define Wimp_GetMenuState 0x0400f4 +#define Wimp_RegisterFilter 0x0400f5 +#define Wimp_AddMessages 0x0400f6 +#define Wimp_RemoveMessages 0x0400f7 +#define Wimp_SetColourMapping 0x0400f8 +#define Sound_Configure 0x040140 +#define Sound_Enable 0x040141 +#define Sound_Stereo 0x040142 +#define Sound_Speaker 0x040143 +#define Sound_Volume 0x040180 +#define Sound_SoundLog 0x040181 +#define Sound_LogScale 0x040182 +#define Sound_InstallVoice 0x040183 +#define Sound_RemoveVoice 0x040184 +#define Sound_AttachVoice 0x040185 +#define Sound_ControlPacked 0x040186 +#define Sound_Tuning 0x040187 +#define Sound_Pitch 0x040188 +#define Sound_Control 0x040189 +#define Sound_AttachNamedVoice 0x04018a +#define Sound_ReadControlBlock 0x04018b +#define Sound_WriteControlBlock 0x04018c +#define Sound_QInit 0x0401c0 +#define Sound_QSchedule 0x0401c1 +#define Sound_QRemove 0x0401c2 +#define Sound_QFree 0x0401c3 +#define Sound_QSDispatch 0x0401c4 +#define Sound_QTempo 0x0401c5 +#define Sound_QBeat 0x0401c6 +#define Sound_QInterface 0x0401c7 +#define ADFS_DiscOp 0x040240 +#define ADFS_HDC 0x040241 +#define ADFS_Drives 0x040242 +#define ADFS_FreeSpace 0x040243 +#define ADFS_Retries 0x040244 +#define ADFS_DescribeDisc 0x040245 +#define ADFS_VetFormat 0x040246 +#define ADFS_FlpProcessDCB 0x040247 +#define ADFS_ControllerType 0x040248 +#define ADFS_PowerControl 0x040249 +#define ADFS_SetIDEController 0x04024a +#define ADFS_IDEUserOp 0x04024b +#define ADFS_MiscOp 0x04024c +#define ADFS_ECCSAndRetries 0x040250 +#define Podule_ReadID 0x040280 +#define Podule_ReadHeader 0x040281 +#define Podule_EnumerateChunks 0x040282 +#define Podule_ReadChunk 0x040283 +#define Podule_ReadBytes 0x040284 +#define Podule_WriteBytes 0x040285 +#define Podule_CallLoader 0x040286 +#define Podule_RawRead 0x040287 +#define Podule_RawWrite 0x040288 +#define Podule_HardwareAddress 0x040289 +#define Podule_EnumerateChunksWithInfo 0x04028a +#define Podule_HardwareAddresses 0x04028b +#define Podule_ReturnNumber 0x04028c +#define PCEmMod_KeyEvent_Init 0x0402c0 +#define PCEmMod_KeyEvent_Info 0x0402c1 +#define PCEmMod_KeyEvent_Accept 0x0402c2 +#define PCEmMod_KeyEvent_Ignore 0x0402c3 +#define PCEmMod_KeyEvent_Check 0x0402c4 +#define PCEmMod_KeyEvent_Get 0x0402c5 +#define PCEmMod_KeyEvent_Put 0x0402c6 +#define PCEmMod_MicroTimer_Get 0x0402c7 +#define PCEmMod_PCEvent_Init 0x0402c8 +#define PCEmMod_PCEvent_Accept 0x0402c9 +#define PCEmMod_PCEvent_Ignore 0x0402ca +#define PCEmMod_PCEvent_Check 0x0402cb +#define PCEmMod_PCEvent_Get 0x0402cc +#define PCEmMod_DelayFor 0x0402cd +#define PCEmMod_CodeBase 0x0402ce +#define PCEmMod_Profile_Init 0x0402cf +#define PCEmMod_Profile_On 0x0402d0 +#define PCEmMod_Profile_Off 0x0402d1 +#define PCEmMod_Profile_Write 0x0402d2 +#define PCEmMod_InterceptMouse 0x0402d3 +#define PCEmMod_RestoreMouse 0x0402d4 +#define PCEmMod_ReadMouse 0x0402d5 +#define Debugger_Disassemble 0x040380 +#define SCSI_Version 0x0403c0 +#define SCSI_Initialise 0x0403c1 +#define SCSI_Control 0x0403c2 +#define SCSI_Op 0x0403c3 +#define SCSI_Status 0x0403c4 +#define SCSI_Reserve 0x0403c7 +#define SCSI_List 0x0403c8 +#define FPEmulator_Version 0x040480 +#define FileCore_DiscOp 0x040540 +#define FileCore_Create 0x040541 +#define FileCore_Drives 0x040542 +#define FileCore_FreeSpace 0x040543 +#define FileCore_FloppyStructure 0x040544 +#define FileCore_DescribeDisc 0x040545 +#define FileCore_DiscardReadSectorsCache 0x040546 +#define FileCore_DiscFormat 0x040547 +#define FileCore_LayoutStructure 0x040548 +#define FileCore_MiscOp 0x040549 +#define Shell_Create 0x0405c0 +#define Shell_Destroy 0x0405c1 +#define Hourglass_On 0x0406c0 +#define Hourglass_Off 0x0406c1 +#define Hourglass_Smash 0x0406c2 +#define Hourglass_Start 0x0406c3 +#define Hourglass_Percentage 0x0406c4 +#define Hourglass_LEDs 0x0406c5 +#define Hourglass_Colours 0x0406c6 +#define Draw_ProcessPath 0x040700 +#define Draw_ProcessPathFP 0x040701 +#define Draw_Fill 0x040702 +#define Draw_FillFP 0x040703 +#define Draw_Stroke 0x040704 +#define Draw_StrokeFP 0x040705 +#define Draw_StrokePath 0x040706 +#define Draw_StrokePathFP 0x040707 +#define Draw_FlattenPath 0x040708 +#define Draw_FlattenPathFP 0x040709 +#define Draw_TransformPath 0x04070a +#define Draw_TransformPathFP 0x04070b +#define ColourTrans_SelectTable 0x040740 +#define ColourTrans_SelectGCOLTable 0x040741 +#define ColourTrans_ReturnGCOL 0x040742 +#define ColourTrans_SetGCOL 0x040743 +#define ColourTrans_ReturnColourNumber 0x040744 +#define ColourTrans_ReturnGCOLForMode 0x040745 +#define ColourTrans_ReturnColourNumberForMode 0x040746 +#define ColourTrans_ReturnOppGCOL 0x040747 +#define ColourTrans_SetOppGCOL 0x040748 +#define ColourTrans_ReturnOppColourNumber 0x040749 +#define ColourTrans_ReturnOppGCOLForMode 0x04074a +#define ColourTrans_ReturnOppColourNumberForMode 0x04074b +#define ColourTrans_GCOLToColourNumber 0x04074c +#define ColourTrans_ColourNumberToGCOL 0x04074d +#define ColourTrans_ReturnFontColours 0x04074e +#define ColourTrans_SetFontColours 0x04074f +#define ColourTrans_InvalidateCache 0x040750 +#define ColourTrans_SetCalibration 0x040751 +#define ColourTrans_ReadCalibration 0x040752 +#define ColourTrans_ConvertDeviceColour 0x040753 +#define ColourTrans_ConvertDevicePalette 0x040754 +#define ColourTrans_ConvertRGBToCIE 0x040755 +#define ColourTrans_ConvertCIEToRGB 0x040756 +#define ColourTrans_WriteCalibrationToFile 0x040757 +#define ColourTrans_ConvertRGBToHSV 0x040758 +#define ColourTrans_ConvertHSVToRGB 0x040759 +#define ColourTrans_ConvertRGBToCMYK 0x04075a +#define ColourTrans_ConvertCMYKToRGB 0x04075b +#define ColourTrans_ReadPalette 0x04075c +#define ColourTrans_WritePalette 0x04075d +#define ColourTrans_SetColour 0x04075e +#define ColourTrans_MiscOp 0x04075f +#define ColourTrans_WriteLoadingsToFile 0x040760 +#define ColourTrans_SetTextColour 0x040761 +#define ColourTrans_SetOppTextColour 0x040762 +#define ColourTrans_GenerateTable 0x040763 +#define SCSIFS_DiscOp 0x040980 +#define SCSIFS_Drives 0x040982 +#define SCSIFS_FreeSpace 0x040983 +#define SCSIFS_DescribeDisc 0x040985 +#define SCSIFS_TestReady 0x040986 +#define Super_Sample90 0x040d80 +#define Super_Sample45 0x040d81 +#define FilerAction_SendSelectedDirectory 0x040f80 +#define FilerAction_SendSelectedFile 0x040f81 +#define FilerAction_SendStartOperation 0x040f82 +#define SCSI_LogVersion 0x041080 +#define SCSI_LogList 0x041081 +#define MessageTrans_FileInfo 0x041500 +#define MessageTrans_OpenFile 0x041501 +#define MessageTrans_Lookup 0x041502 +#define MessageTrans_MakeMenus 0x041503 +#define MessageTrans_CloseFile 0x041504 +#define MessageTrans_EnumerateTokens 0x041505 +#define MessageTrans_ErrorLookup 0x041506 +#define MessageTrans_GSLookup 0x041507 +#define MessageTrans_CopyError 0x041508 +#define PDumper_Info 0x041b00 +#define PDumper_Claim 0x041b01 +#define PDumper_Free 0x041b02 +#define PDumper_Find 0x041b03 +#define PDumper_StartJob 0x041b04 +#define PDumper_TidyJob 0x041b05 +#define PDumper_SetColour 0x041b06 +#define PDumper_PrepareStrip 0x041b07 +#define PDumper_LookupError 0x041b08 +#define PDumper_CopyFilename 0x041b09 +#define ResourceFS_RegisterFiles 0x041b40 +#define ResourceFS_DeregisterFiles 0x041b41 +#define DragASprite_Start 0x042400 +#define DragASprite_Stop 0x042401 +#define DDEUtils_Prefix 0x042580 +#define DDEUtils_SetCLSize 0x042581 +#define DDEUtils_SetCL 0x042582 +#define DDEUtils_GetCLSize 0x042583 +#define DDEUtils_GetCl 0x042584 +#define DDEUtils_ThrowbackRegister 0x042585 +#define DDEUtils_ThrowbackUnRegister 0x042586 +#define DDEUtils_ThrowbackStart 0x042587 +#define DDEUtils_ThrowbackSend 0x042588 +#define DDEUtils_ThrowbackEnd 0x042589 +#define Filter_RegisterPreFilter 0x042640 +#define Filter_RegisterPostFilter 0x042641 +#define Filter_DeRegisterPreFilter 0x042642 +#define Filter_DeRegisterPostFilter 0x042643 +#define TaskManager_TaskNameFromHandle 0x042680 +#define TaskManager_EnumerateTasks 0x042681 +#define TaskManager_Shutdown 0x042682 +#define Squash_Compress 0x042700 +#define Squash_Decompress 0x042701 +#define DeviceFS_Register 0x042740 +#define DeviceFS_Deregister 0x042741 +#define DeviceFS_RegisterObjects 0x042742 +#define DeviceFS_DeregisterObjects 0x042743 +#define DeviceFS_CallDevice 0x042744 +#define DeviceFS_Threshold 0x042745 +#define DeviceFS_ReceivedCharacter 0x042746 +#define DeviceFS_TransmitCharacter 0x042747 +#define Impulse_Initialise 0x0428c0 +#define Impulse_Decode 0x0428c1 +#define Impulse_SendMessage 0x0428c2 +#define Impulse_TransmitData 0x0428c3 +#define Impulse_FetchData 0x0428c4 +#define Impulse_CloseDown 0x0428c5 +#define Impulse_DeferReply 0x0428c6 +#define Buffer_Create 0x042940 +#define Buffer_Remove 0x042941 +#define Buffer_Register 0x042942 +#define Buffer_Deregister 0x042943 +#define Buffer_ModifyFlags 0x042944 +#define Buffer_LinkDevice 0x042945 +#define Buffer_UnlinkDevice 0x042946 +#define Buffer_GetInfo 0x042947 +#define Buffer_Threshold 0x042948 +#define BASICTrans_HELP 0x042c80 +#define BASICTrans_Error 0x042c81 +#define BASICTrans_Message 0x042c82 +#define Parallel_HardwareAddress 0x042ec0 +#define Parallel_Op 0x042ec1 +#define Territory_Number 0x043040 +#define Territory_Register 0x043041 +#define Territory_Deregister 0x043042 +#define Territory_NumberToName 0x043043 +#define Territory_Exists 0x043044 +#define Territory_AlphabetNumberToName 0x043045 +#define Territory_SelectAlphabet 0x043046 +#define Territory_SetTime 0x043047 +#define Territory_ReadCurrentTimeZone 0x043048 +#define Territory_ConvertTimeToUTCOrdinals 0x043049 +#define Territory_ReadTimeZones 0x04304a +#define Territory_ConvertDateAndTime 0x04304b +#define Territory_ConvertStandardDateAndTime 0x04304c +#define Territory_ConvertStandardDate 0x04304d +#define Territory_ConvertStandardTime 0x04304e +#define Territory_ConvertTimeToOrdinals 0x04304f +#define Territory_ConvertTimeStringToOrdinals 0x043050 +#define Territory_ConvertOrdinalsToTime 0x043051 +#define Territory_Alphabet 0x043052 +#define Territory_AlphabetIdentifier 0x043053 +#define Territory_SelectKeyboardHandler 0x043054 +#define Territory_WriteDirection 0x043055 +#define Territory_CharacterPropertyTable 0x043056 +#define Territory_LowerCaseTable 0x043057 +#define Territory_UpperCaseTable 0x043058 +#define Territory_ControlTable 0x043059 +#define Territory_PlainTable 0x04305a +#define Territory_ValueTable 0x04305b +#define Territory_RepresentationTable 0x04305c +#define Territory_Collate 0x04305d +#define Territory_ReadSymbols 0x04305e +#define Territory_ReadCalendarInformation 0x04305f +#define Territory_NameToNumber 0x043060 +#define Territory_TransformString 0x043061 +#define Territory_Reserved1 0x043062 +#define Territory_Reserved2 0x043063 +#define Territory_Reserved3 0x043064 +#define Territory_Reserved4 0x043065 +#define Territory_Reserved5 0x043066 +#define Territory_Reserved6 0x043067 +#define Territory_Reserved7 0x043068 +#define Territory_Reserved8 0x043069 +#define Territory_Reserved9 0x04306a +#define Territory_Reserved10 0x04306b +#define Territory_Reserved11 0x04306c +#define Territory_Reserved12 0x04306d +#define Territory_Reserved13 0x04306e +#define Territory_Reserved14 0x04306f +#define Territory_Reserved15 0x043070 +#define Territory_Reserved16 0x043071 +#define Territory_Reserved17 0x043072 +#define Territory_Reserved18 0x043073 +#define Territory_Reserved19 0x043074 +#define Territory_ConvertTextToString 0x043075 +#define ScreenBlanker_Control 0x043100 +#define TaskWindow_TaskInfo 0x043380 +#define Free_Register 0x0444c0 +#define Free_DeRegister 0x0444c1 +#define DOSFS_DiscFormat 0x044b00 +#define DOSFS_LayoutStructure 0x044b01 +#define PDriver_Info 0x080140 +#define PDriver_SetInfo 0x080141 +#define PDriver_CheckFeatures 0x080142 +#define PDriver_PageSize 0x080143 +#define PDriver_SetPageSize 0x080144 +#define PDriver_SelectJob 0x080145 +#define PDriver_CurrentJob 0x080146 +#define PDriver_FontSWI 0x080147 +#define PDriver_EndJob 0x080148 +#define PDriver_AbortJob 0x080149 +#define PDriver_Reset 0x08014a +#define PDriver_GiveRectangle 0x08014b +#define PDriver_DrawPage 0x08014c +#define PDriver_GetRectangle 0x08014d +#define PDriver_CancelJob 0x08014e +#define PDriver_ScreenDump 0x08014f +#define PDriver_EnumerateJobs 0x080150 +#define PDriver_SetPrinter 0x080151 +#define PDriver_CancelJobWithError 0x080152 +#define PDriver_SelectIllustration 0x080153 +#define PDriver_InsertIllustration 0x080154 +#define PDriver_DeclareFont 0x080155 +#define PDriver_DeclareDriver 0x080156 +#define PDriver_RemoveDriver 0x080157 +#define PDriver_SelectDriver 0x080158 +#define PDriver_EnumerateDrivers 0x080159 +#define PDriver_MiscOp 0x08015a +#define PDriver_MiscOpForDriver 0x08015b +#define PDriver_SetDriver 0x08015c +#define SharedCLibrary_LibInitAPCS_A 0x080680 +#define SharedCLibrary_LibInitAPCS_R 0x080681 +#define SharedCLibrary_LibInitModule 0x080682 +#define FrontEnd_ExtendedCmdLine 0x081400 +#define FrontEnd_FreeCmdLine 0x081401 + +#endif diff --git a/sys/arch/arm32/boot/swiv.S b/sys/arch/arm32/boot/swiv.S new file mode 100644 index 00000000000..6e42afaa9d5 --- /dev/null +++ b/sys/arch/arm32/boot/swiv.S @@ -0,0 +1,80 @@ +#include "regs.h" + + .text + +SWIReturnInst: + ldr pc, [sp, #0*4] + + .global _swix +_swix: + orr r0, r0, #0x20000 + + .global _swi +_swi: + +/* + * Construct a stack frame that looks something like this: + * returnval + * LDMIA r12!, {r0..rn} + * SWI xxxxxx + * LDR pc, [sp] + * saved r4-r11,lr + * saved r1 + * saved input values (r2...rn) + */ + + mov pc, lr + + stmfd sp!, {r1-r3} /* Save r1 and put 1st two variadic args on stack */ + bic r2, r0, #0xff000000 + orr r2, r2, #0xef000000 /* Construct SWI instruction */ + adr r0, SWIReturn + tst r1, #0x20000 /* bit for write flags */ + adrne r0, SWIReturnFlags + bic r1, r1, #0xff000000 /* Construct LDMIA R12!, {regs} instruction, if */ + bics r1, r1, #0x00ff0000 /* {regs} = {} (IE no input regs) we must not */ + orrne r1, r1, #0xe8000000 /* use an LDMIA R12!, {} instruction as this is an */ + orrne r1, r1, #0x00bc0000 /* invalid instruction, we use a suitable NOP instead */ + moveq r1, #0 /* 0 = opcode for ANDEQ r0, r0, r0 (a suitable NOP) */ + ldr r3, SWIReturnInst + stmfd sp!, {r0-r9, r11, lr} /* Save regs and set up SWI call routine (in R0-R3) */ + add r12, sp, #(12+1)*4 /* Point R12 at input regs on stack. */ + add pc, sp, #4 /* Call routine on stack */ +SWIReturnFlags: + ldr r11, [r12], #4 + str pc, [r11] /* write flags */ +SWIReturn: + ldr lr, [sp, #(12+0)*4] /* Fetch reg mask again */ + movs lr, lr, asl #1 /* Shift out setting C if R0 to be written, N */ + ldrcs r11, [r12], #4 /* if R1 to be written. */ + strcs r0, [r11] + ldrmi r11, [r12], #4 + strmi r1, [r11] + movs lr, lr, asl #2 /* Shift 2 bits each time for the next 2 regs */ + ldrcs r11, [r12], #4 + strcs r2, [r11] + ldrmi r11, [r12], #4 + strmi r3, [r11] + movs lr, lr, asl #2 + ldrcs r11, [r12], #4 + strcs r4, [r11] + ldrmi r11, [r12], #4 + strmi r5, [r11] + movs lr, lr, asl #2 + ldrcs r11, [r12], #4 + strcs r6, [r11] + ldrmi r11, [r12], #4 + strmi r7, [r11] + movs lr, lr, asl #2 + ldrcs r11, [r12], #4 + strcs r8, [r11] + ldrmi r11, [r12], #4 + strmi r9, [r11] + ldr r1, [sp, #2*4] + tst r1, #0x20000 /* X-bit clear */ + cmpeq pc, #0x80000000 /* SET V flag if so, so R0 not cleared */ + movvc r0, #0 /* Clear R0 if no error (or X-bit clear) */ + add sp, sp, #4*4 /* Drop SWI call routine */ + ldmia sp!, {r4-r9,r11,lr} + add sp, sp, #3*4 /* Drop saved R1 and 1st two variadic args. */ + movs pc, lr diff --git a/sys/arch/arm32/boot/swiv.h b/sys/arch/arm32/boot/swiv.h new file mode 100644 index 00000000000..d60ee2e546a --- /dev/null +++ b/sys/arch/arm32/boot/swiv.h @@ -0,0 +1,80 @@ +/* SWI veneers: + * Written by Edward Nevill and Jonathan Roach in an idle moment between projects. + * Hacked by BDB to add flag returning + */ + +/* Anonymous Error type */ + +struct Error { int num; char msg[4]; }; + +typedef struct Error Error; + +/* Generic SWI interface + * swi(swino,mask,regs...) + * swino = SWI number to call as defined in h.swis, X bit set if you wish the + * X form of the SWI to be called, clear if you want the non X form. + * reg_mask = mask of in / out registers + * bits 0-9: Bit N set => Register N specified on input + * Bit N clear => Register N unspecified on input + * bits 22-31: Bit N set => Register N-22 on output stored + * in address specified in varargs list. + * ... In order, input registers followed by output registers, + * starting at r0 and going up. + * returns 0 or errorblock pointer if X-bit set + * returns r0 if X-bit clear + * swix(swino,mask,regs...) + * This behaves identically to 'swi' except that it always calls the X form. + * + * Eg: + * swi(OS_SWINumberToString, IN(R0|R1|R2), n, buf, 255); + * e = swi(XOS_SWINumberFromString, IN(R1)|OUT(R0), str, &n); + * - Error block pointer (or 0) is returned so must get returned R0 + * - via argument list. + * e = swix(OS_SWINumberFromString, IN(R1)|OUT(R0), str, &n); + * - As above but uses the swix function rather that setting the X bit + * explicitly (saves one instruction on SWI call). + * e = swi(OS_File, IN(R0|R1|R2|R3)|OUT(R4), 255, name, buff, 0, &len); + * - We don't care about the load, exec or attrs so don't specify + * them in the output registers. + */ + +extern Error *swix(int swino, int reg_mask, ...); +extern int swi(int swino, int reg_mask, ...); + +/* Register mask macros + * The bits in the register mask are arranged as follows: + * 31 30 29 ... 22 ... 8 ... 2 1 0 + * O0 O1 O2 ... O9 I9 ... I2 I1 I0 I(N) = bit set if R(N) used on entry + * O(N) = bit set if R(N) written on exit + * The bits are arranged like this to optimise the case where a SWI is being + * called with a small number of input and output registers. For example, a SWI + * call which uses R0-R5 on entry and R0-R1 on exit will have a register mask + * of 0xC000003f which can be loaded into an ARM register in one instruction + * (the compiler performs this optimisation, even when the constant wraps + * around between bits 0 and 31). Using the more obvious coding of I0-I9 in bits + * 0 - 9 and O0-O9 in bits 16-23 leads to a constant of 0x0003003f which require + * two instructions. + */ +#define IN(m) (m) +/* old, incorrect version +#define OUT(m) ((unsigned)(m&1)<<31|(m&2)<<29|(m&4)<<27|(m&8)<<25|(m&16)<<23|\ + (m&32)<<21|(m&64)<<19|(m&128)<<17|(m&256)<<15|(m&512)<<13) +*/ +#define OUT(m) ((unsigned)((m)&1)<<31|((m)&2)<<29|((m)&4)<<27|\ + ((m)&8)<<25|((m)&16)<<23|((m)&32)<<21|((m)&64)<<19|\ + ((m)&128)<<17|((m)&256)<<15|((m)&512)<<13|((m)&1024)<<11) + +/* The register names + * Change these to use different names if you use R0 - R9 elsewhere in your program + */ +#define PSW 0x400 /* Use only in OUT, orders BEFORE others */ +#define R0 0x001 +#define R1 0x002 +#define R2 0x004 +#define R3 0x008 +#define R4 0x010 +#define R5 0x020 +#define R6 0x040 +#define R7 0x080 +#define R8 0x100 +#define R9 0x200 diff --git a/sys/arch/arm32/boot/vsprintf.c b/sys/arch/arm32/boot/vsprintf.c new file mode 100644 index 00000000000..3e6e9ffb28a --- /dev/null +++ b/sys/arch/arm32/boot/vsprintf.c @@ -0,0 +1,275 @@ +#include +#include + +# define toupper(x) ((x >= 'a' && x <= 'z') ? (x & 0xdf) : x) +/*# define tolower(x) ((x >= 'A' && x <= 'Z') ? (x | 0x20) : x)*/ +# define islower(x) ((x >= 'a' && x <= 'z') ? 1 : 0) +# define isdigit(x) ((x >= '0' && x <= '9') ? 1 : 0) +# define isxdigit(x) (((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')) ? 1 : 0) + +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (!base) { + base = 10; + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + cp++; + base = 16; + } + } + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +/* we use this so that we can do without the ctype library */ +#define is_digit(c) ((c) >= '0' && (c) <= '9') + +static int skip_atoi(const char **s) +{ + int i=0; + + while (is_digit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ + +static unsigned int do_div(unsigned int *n, unsigned int base) + { + unsigned int d; + + d = *n % base; + *n /= base; + + return(d); + } + +static char * number(char * str, int num, int base, int size, int precision + ,int type) +{ + char c,sign,tmp[36]; + const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; + if (type&LEFT) type &= ~ZEROPAD; + if (base<2 || base>36) + return 0; + c = (type & ZEROPAD) ? '0' : ' ' ; + if (type&SIGN && num<0) { + sign='-'; + num = -num; + } else + sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0); + if (sign) size--; + if (type&SPECIAL) { + if (base==16) size -= 2; + else if (base==8) size--; + } + i=0; + if (num==0) + tmp[i++]='0'; + else while (num!=0) + tmp[i++]=digits[do_div((unsigned int *)&num,base)]; + if (i>precision) precision=i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type&SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + if (!(type&LEFT)) + while(size-->0) + *str++ = c; + while(i0) + *str++ = tmp[i]; + while(size-->0) + *str++ = ' '; + return str; +} + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + int len; + int i; + char * str; + char *s; + int *ip; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + for (str=buf ; *fmt ; ++fmt) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (is_digit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + break; + + case 's': + s = va_arg(args, char *); + if (!s) + s = ""; + len = strlen(s); + if (precision < 0) + precision = len; + else if (len > precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + break; + + case 'o': + str = number(str, va_arg(args, unsigned long), 8, + field_width, precision, flags); + break; + + case 'p': + if (field_width == -1) { + field_width = 8; + flags |= ZEROPAD; + } + str = number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + break; + + case 'x': + flags |= SMALL; + case 'X': + str = number(str, va_arg(args, unsigned long), 16, + field_width, precision, flags); + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + str = number(str, va_arg(args, unsigned long), 10, + field_width, precision, flags); + break; + + case 'n': + ip = va_arg(args, int *); + *ip = (str - buf); + break; + + default: + if (*fmt != '%') + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + break; + } + } + *str = '\0'; + return str-buf; +} + + +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsprintf(buf,fmt,args); + va_end(args); + return i; +} + diff --git a/sys/arch/arm32/compile/.keep_me b/sys/arch/arm32/compile/.keep_me new file mode 100644 index 00000000000..284b348c4af --- /dev/null +++ b/sys/arch/arm32/compile/.keep_me @@ -0,0 +1,3 @@ +$NetBSD: .keep_me,v 1.1 1996/01/31 23:19:04 mark Exp $ + +This file must remain so that 'cvs checkout' makes the compile directory. diff --git a/sys/arch/arm32/conf/BETA b/sys/arch/arm32/conf/BETA new file mode 100644 index 00000000000..7a608037e91 --- /dev/null +++ b/sys/arch/arm32/conf/BETA @@ -0,0 +1,186 @@ +# +# BETA -- Kernel configuration used for beta kernels +# + +include "std.arm32" + +# estimated number of users + +maxusers 8 + +# Standard system options + +options TIMEZONE=0 # time zone to adjust RTC time by +options DST=0 # daylight savings time used by RTC +options SWAPPAGER # paging; REQUIRED +options VNODEPAGER # mmap() of files +options DEVPAGER # mmap() of devices + +# CPU options + +options CPU_ARM6 +options CPU_LATE_ABORT # ARM7XX compatibility + +# FPA options + +options FPE # Single precision FPE +options ARMFPE # ARM Ltd FPE + +# File system options + +options FFS # UFS +#options QUOTA # UFS quotas +#options LFS # log-structured file system +#options MFS # memory file system + +options CD9660 # ISO 9660 + Rock Ridge file system +options MSDOSFS # MS-DOS file system +options FDESC # /dev/fd +options FIFO # FIFOs; RECOMMENDED +options KERNFS # /kern +#options NULLFS # loopback file system +#options PORTAL # ? +options PROCFS # /proc +#options UMAPFS # NULLFS + uid and gid remapping +options UNION # union file system + +# Networking options + +options NFSCLIENT +options NFSSERVER +#options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +#options NS # XNS +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options CCITT,LLC,HDLC # X.25 + +# Compatibility options + +options COMPAT_43 +options COMPAT_10 +options COMPAT_09 +options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD + +# Shared memory options + +#options SYSVMSG # System V-like message queues +#options SYSVSEM # System V-like semaphores +#options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Device options + +options RAMDISK_HOOKS # boottime setup of ramdisk +options RAMDISK_SIZE=0 # Size in KBytes +options PLIP # Build plip device into lpt driver + +# Development options + +options DIAGNOSTIC # internally consistency checks +options KTRACE # system call tracing, a la ktrace(1) +options IRQSTATS # IRQ statistics +options POSTMORTEM # perform postmortem on panic +#options ROTTEN_INNARDS # show the gory bit of the postmortem +options KSHELL # kernel developemnt shell (debug) +#options LKM # loadable kernel modules +#options DEBUGTERM # create a debug console +#options KGDB # remote kernel debugging +#options DDB # in-kernel debugger +#makeoptions DEBUG="-g" # compile full symbol table + +config netbsd swap generic +options GENERIC + +# The main bus device +mainbus0 at root + +# The boot cpu +cpu0 at mainbus? + +# The vidc +vidcvideo0 at mainbus? + +# generic VT console device +vt0 at mainbus? +vt1 at mainbus? +vt2 at mainbus? +vt3 at mainbus? +vt4 at mainbus? +vt5 at mainbus? + +# IDE disk controller +wdc0 at mainbus? base 0x002107c0 irq 9 +wd0 at wdc? drive ? +wd1 at wdc? drive ? + +# Floppy disk controller +fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000 +fd0 at fdc? drive ? + +# kbd via IOMD +kbd0 at mainbus? base 0x00000000 + +# quadrature mouse +quadmouse0 at mainbus? base 0x00000000 + +# Serial ports +com0 at mainbus? base 0x00210fe0 irq 10 +#com1 at mainbus? base 0x00210be0 + +# Parallel ports +lpt0 at mainbus? base 0x002109e0 irq 0 + +# Crude sound device +beep0 at mainbus? base 0x00000000 + +# IIC bus device +iic0 at mainbus? + +# RTC device +rtc0 at iic? addr 0xa0 + +# Podule bus device +podulebus0 at root + +asc0 at podulebus? # Acorn SCSI card +scsibus* at asc? + +csc0 at podulebus? # Cumana SCSI II card +scsibus* at csc? + +ptsc0 at podulebus? # Power-Tec SCSI II card +scsibus* at ptsc? + +oak0 at podulebus? # Oak SCSI I card +scsibus* at oak? + +sd* at scsibus? target ? lun ? # SCSI disk drives +st* at scsibus? target ? lun ? # SCSI tape drives +cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +ch* at scsibus? target ? lun ? # SCSI auto-changers +uk* at scsibus? target ? lun ? # SCSI unknown device + +#kie* at podulebus? slot ? offset ? + +ea0 at podulebus? # Ether3 podules +eb0 at podulebus? # EtherB network slot cards +eh0 at podulebus? # EtherH network slot cards +ie0 at podulebus? # Ether1 podules + +pseudo-device loop 1 # network loopback +pseudo-device bpfilter 8 # packet filter +pseudo-device sl 2 # CSLIP +pseudo-device ppp 2 # PPP +pseudo-device tun 2 # network tunneling over tty + +pseudo-device pty 32 # pseudo-terminals +pseudo-device tb 1 # tablet line discipline +pseudo-device vnd 4 # paging to files +pseudo-device ccd 2 # concatenated disk devices + +pseudo-device rd 1 # Ramdisk driver + +makeoptions MONITOR="Taxan875+LR" +#makeoptions MONITOR="AKF60" +makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900" diff --git a/sys/arch/arm32/conf/CLAIRE b/sys/arch/arm32/conf/CLAIRE new file mode 100644 index 00000000000..ebf0d0501ee --- /dev/null +++ b/sys/arch/arm32/conf/CLAIRE @@ -0,0 +1,185 @@ +# +# CLAIRE -- Nut's development machine +# + +include "std.arm32" + +# estimated number of users + +maxusers 8 + +# Standard system options + +options TIMEZONE=0 # time zone to adjust RTC time by +options DST=0 # daylight savings time used by RTC +options SWAPPAGER # paging; REQUIRED +options VNODEPAGER # mmap() of files +options DEVPAGER # mmap() of devices + +# CPU options + +options CPU_ARM6 +options CPU_LATE_ABORT # ARM7XX compatibility + +# FPA options + +options FPE # Single precision FPE +options ARMFPE # ARM Ltd FPE + +# File system options + +options FFS # UFS +#options QUOTA # UFS quotas +#options LFS # log-structured file system +#options MFS # memory file system + +options CD9660 # ISO 9660 + Rock Ridge file system +options MSDOSFS # MS-DOS file system +#options FDESC # /dev/fd +options FIFO # FIFOs; RECOMMENDED +options KERNFS # /kern +#options NULLFS # loopback file system +#options PORTAL # ? +options PROCFS # /proc +#options UMAPFS # NULLFS + uid and gid remapping +#options UNION # union file system + +# Networking options + +options NFSCLIENT +options NFSSERVER +options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +#options NS # XNS +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options CCITT,LLC,HDLC # X.25 + +# Compatibility options + +options COMPAT_43 +options COMPAT_10 +options COMPAT_09 +options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD + +# Shared memory options + +#options SYSVMSG # System V-like message queues +#options SYSVSEM # System V-like semaphores +#options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Device options + +options RAMDISK_HOOKS # boottime setup of ramdisk +options RAMDISK_SIZE=0 # Size in KBytes +options PLIP # Build plip device into lpt driver + +# Development options + +options DIAGNOSTIC # internally consistency checks +options KTRACE # system call tracing, a la ktrace(1) +options IRQSTATS # IRQ statistics +options POSTMORTEM # perform postmortem on panic +#options ROTTEN_INNARDS # show the gory bit of the postmortem +options KSHELL # kernel developemnt shell (debug) +options LKM # loadable kernel modules +#options DEBUGTERM # create a debug console +#options KGDB # remote kernel debugging +#options DDB # in-kernel debugger +#makeoptions DEBUG="-g" # compile full symbol table + +config netbsd swap generic +options GENERIC + +# The main bus device +mainbus0 at root + +# The boot cpu +cpu0 at mainbus? + +# The vidc +vidcvideo0 at mainbus? + +# generic VT console device +vt0 at mainbus? +vt1 at mainbus? +vt2 at mainbus? +vt3 at mainbus? +vt4 at mainbus? +vt5 at mainbus? + +# IDE disk controller +wdc0 at mainbus? base 0x002107c0 irq 9 +wd0 at wdc? drive ? +wd1 at wdc? drive ? + +# Floppy disk controller +fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000 +fd0 at fdc? drive ? + +# kbd via IOMD +kbd0 at mainbus? base 0x00000000 + +# quadrature mouse +quadmouse0 at mainbus? base 0x00000000 + +# Serial ports +com0 at mainbus? base 0x00210fe0 irq 10 +#com1 at mainbus? base 0x00210be0 + +# Parallel ports +lpt0 at mainbus? base 0x002109e0 irq 0 + +# Crude sound device +beep0 at mainbus? base 0x00000000 + +# IIC bus device +iic0 at mainbus? + +# RTC device +rtc0 at iic? addr 0xa0 + +# Podule bus device +podulebus0 at root + +#asc0 at podulebus? # Acorn SCSI card +#scsibus* at asc? + +#csc0 at podulebus? # Cumana SCSI II card +#scsibus* at csc? + +#ptsc0 at podulebus? # Power-Tec SCSI II card +#scsibus* at ptsc? + +oak0 at podulebus? # Oak SCSI I card +scsibus* at oak? + +sd* at scsibus? target ? lun ? # SCSI disk drives +st* at scsibus? target ? lun ? # SCSI tape drives +cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +ch* at scsibus? target ? lun ? # SCSI auto-changers +uk* at scsibus? target ? lun ? # SCSI unknown device + +#kie* at podulebus? slot ? offset ? + +#ea0 at podulebus? # Ether3 podules +#eb0 at podulebus? # EtherB network slot cards +eh0 at podulebus? # EtherH network slot cards +ie0 at podulebus? # Ether1 podules + +pseudo-device loop 1 # network loopback +pseudo-device bpfilter 8 # packet filter +pseudo-device sl 2 # CSLIP +pseudo-device ppp 2 # PPP +pseudo-device tun 2 # network tunneling over tty + +pseudo-device pty 32 # pseudo-terminals +pseudo-device tb 1 # tablet line discipline +pseudo-device vnd 4 # paging to files +pseudo-device ccd 2 # concatenated disk devices + +pseudo-device rd 1 # Ramdisk driver + +makeoptions MONITOR="AKF60" +makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900" diff --git a/sys/arch/arm32/conf/GENERIC b/sys/arch/arm32/conf/GENERIC new file mode 100644 index 00000000000..c54ee1aa88e --- /dev/null +++ b/sys/arch/arm32/conf/GENERIC @@ -0,0 +1,198 @@ +# +# GENERIC -- everything that's currently supported +# + +include "std.arm32" + +# estimated number of users + +maxusers 32 + +# Standard system options + +options TIMEZONE=0 # time zone to adjust RTC time by +options DST=0 # daylight savings time used by RTC +options SWAPPAGER # paging; REQUIRED +options VNODEPAGER # mmap() of files +options DEVPAGER # mmap() of devices + +# CPU options + +options CPU_ARM6 +options CPU_LATE_ABORT # ARM7XX compatibility + +# FPA options + +options FPE # Single precision FPE +options ARMFPE # ARM Ltd FPE + +# File system options + +options FFS # UFS +options QUOTA # UFS quotas +options LFS # log-structured file system +options MFS # memory file system + +options CD9660 # ISO 9660 + Rock Ridge file system +options MSDOSFS # MS-DOS file system +options FDESC # /dev/fd +options FIFO # FIFOs; RECOMMENDED +options KERNFS # /kern +options NULLFS # loopback file system +options PORTAL # ? +options PROCFS # /proc +options UMAPFS # NULLFS + uid and gid remapping +options UNION # union file system + +# Networking options + +options NFSCLIENT +options NFSSERVER +options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +options NS # XNS +options ISO,TPIP # OSI +options EON # OSI tunneling over IP +options CCITT,LLC,HDLC # X.25 + +# Compatibility options + +options COMPAT_43 +options COMPAT_10 +options COMPAT_09 +options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD + +# Shared memory options + +#options SYSVMSG # System V-like message queues +#options SYSVSEM # System V-like semaphores +#options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Device options + +options RAMDISK_HOOKS # boottime setup of ramdisk +options RAMDISK_SIZE=0 # Size in KBytes +options PLIP # Build plip device into lpt driver + +# Development options + +options DIAGNOSTIC # internally consistency checks +options KTRACE # system call tracing, a la ktrace(1) +options IRQSTATS # IRQ statistics +options POSTMORTEM # perform postmortem on panic +#options ROTTEN_INNARDS # show the gory bit of the postmortem +options KSHELL # kernel developemnt shell (debug) +options LKM # loadable kernel modules +#options DEBUGTERM # create a debug console +#options KGDB # remote kernel debugging +options DDB # in-kernel debugger +#makeoptions DEBUG="-g" # compile full symbol table + +config netbsd swap generic +options GENERIC + +# The main bus device +mainbus0 at root + +# The boot cpu +cpu0 at mainbus? + +# The hydra multiprocessor device +#hydrabus0 at mainbus? + +#cpu1 at hydrabus? +#cpu2 at hydrabus? +#cpu3 at hydrabus? +#cpu4 at hydrabus? + +# The vidc +vidcvideo0 at mainbus? + +# generic VT console device +vt0 at mainbus? +vt1 at mainbus? +vt2 at mainbus? +vt3 at mainbus? +vt4 at mainbus? +vt5 at mainbus? + +# IDE disk controller +wdc0 at mainbus? base 0x002107c0 irq 9 +wd0 at wdc? drive ? +wd1 at wdc? drive ? + +# Floppy disk controller +fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000 +fd0 at fdc? drive ? + +# kbd via IOMD +kbd0 at mainbus? base 0x00000000 + +# quadrature mouse +quadmouse0 at mainbus? base 0x00000000 + +# PS2 mouse +pms0 at mainbus? base 0x00000000 + +# Serial ports +com0 at mainbus? base 0x00210fe0 irq 10 +#com1 at mainbus? base 0x00210be0 + +# Parallel ports +lpt0 at mainbus? base 0x002109e0 irq 0 + +# Crude sound device +beep0 at mainbus? base 0x00000000 + +# IIC bus device +iic0 at mainbus? + +# RTC device +rtc0 at iic? addr 0xa0 + +# Podule bus device +podulebus0 at root + +asc0 at podulebus? # Acorn SCSI card +scsibus* at asc? + +#csc0 at podulebus? # Cumana SCSI II card +#scsibus* at csc? + +ptsc0 at podulebus? # Power-Tec SCSI II card +scsibus* at ptsc? + +oak0 at podulebus? # Oak SCSI I card +scsibus* at oak? + +sd* at scsibus? target ? lun ? # SCSI disk drives +st* at scsibus? target ? lun ? # SCSI tape drives +cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +ch* at scsibus? target ? lun ? # SCSI auto-changers +uk* at scsibus? target ? lun ? # SCSI unknown device +ss* at scsibus? target ? lun ? # SCSI scanner + +#kie* at podulebus? slot ? offset ? + +ea0 at podulebus? # Ether3 podules +eb0 at podulebus? # EtherB network slot cards +eh0 at podulebus? # EtherH network slot cards +ie0 at podulebus? # Ether1 podules + +pseudo-device loop 1 # network loopback +pseudo-device bpfilter 8 # packet filter +pseudo-device sl 2 # CSLIP +pseudo-device ppp 2 # PPP +pseudo-device tun 2 # network tunneling over tty + +pseudo-device pty 32 # pseudo-terminals +pseudo-device tb 1 # tablet line discipline +pseudo-device vnd 4 # paging to files +pseudo-device ccd 2 # concatenated disk devices + +pseudo-device rd 1 # Ramdisk driver + +makeoptions MONITOR="Taxan875+LR" +#makeoptions MONITOR="AKF60" +makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900" diff --git a/sys/arch/arm32/conf/Makefile.arm32 b/sys/arch/arm32/conf/Makefile.arm32 new file mode 100644 index 00000000000..10cc987869f --- /dev/null +++ b/sys/arch/arm32/conf/Makefile.arm32 @@ -0,0 +1,186 @@ +# $NetBSD: Makefile.arm32,v 1.10 1996/02/29 20:55:24 cgd Exp $ + +# Makefile for NetBSD +# +# This makefile is constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/arch/arm32/conf/``machineid'' +# after which you should do +# config machineid +# Machine generic makefile changes should be made in +# /sys/arch/arm32/conf/Makefile.arm32 +# 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. + +AS?= as +CC?= cc +CPP?= cpp +LD?= ld +STRIP?= strip -d +TOUCH?= touch -f -c + +# source tree is located via $S relative to the compilation directory +S= ../../../.. +ARM32= ../.. + +INCLUDES= -I. -I$S/arch -I$S +CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL -Darm32 +CFLAGS= ${DEBUG} -O2 -Werror -fno-builtin +AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE +LINKFLAGS= -Ttext F0000020 -e start + +### 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}${CONFIG_DEP} +# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix, +# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file +# is marked as config-dependent. + +NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< +NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< + +DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< +DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< + +NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< +NORMAL_S_C= ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -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 modedefs.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} $@; ${STRIP} $@ +.else +LINKFLAGS+= -x +.endif + +%LOAD + +assym.h: genassym + ./genassym >assym.h + +genassym: genassym.o + ${CC} -o $@ genassym.o + +genassym.o: ${ARM32}/arm32/genassym.c + ${NORMAL_C_C} + +param.c: $S/conf/param.c + rm -f param.c + cp $S/conf/param.c . + +param.o: param.c Makefile + ${NORMAL_C_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 + + +clean:: + rm -f eddep *netbsd netbsd.gdb tags *.[io] [a-z]*.s \ + [Ee]rrs linterrs makelinks genassym genassym.o assym.h + +lint: + @lint -hbxncez -DGENERIC -Dvolatile= ${CPPFLAGS} ${PARAM} -UKGDB \ + ${ARM32}/arm32/Locore.c ${CFILES} ${ARM32}/arm32/swapgeneric.c \ + 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= ${ARM32}/arm32/locore.S modedefs.c \ + param.c ioconf.c ${CFILES} ${SFILES} +depend: .depend +.depend: ${SRCS} assym.h param.c + mkdep ${AFLAGS} ${CPPFLAGS} ${ARM32}/arm32/locore.S + mkdep -a ${CFLAGS} ${CPPFLAGS} modedefs.c + mkdep -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} + mkdep -a ${AFLAGS} ${CPPFLAGS} ${SFILES} + mkdep -a ${CFLAGS} ${CPPFLAGS} ${PARAM} ${ARM32}/arm32/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 +cpuswitch.o fault.o machdep.o: Makefile + + +locore.o: ${ARM32}/arm32/locore.S assym.h + ${NORMAL_S} + +modedefs.c: makemodes ${ARM32}/conf/monitors/${MONITOR} Makefile + ./makemodes ${ARM32}/conf/monitors/${MONITOR} modedefs.c ${MODES} + +modedefs.o: modedefs.c + ${NORMAL_C} + +makemodes: makemodes.o + ${CC} -o $@ makemodes.o + +makemodes.o: ${ARM32}/arm32/makemodes.c + ${NORMAL_C_C} + +%RULES diff --git a/sys/arch/arm32/conf/PHARM b/sys/arch/arm32/conf/PHARM new file mode 100644 index 00000000000..517b4d4028a --- /dev/null +++ b/sys/arch/arm32/conf/PHARM @@ -0,0 +1,194 @@ +# +# PHARM -- Mark's development machine in the office +# + +include "std.arm32" + +# estimated number of users + +maxusers 32 + +# Standard system options + +options TIMEZONE=0 # time zone to adjust RTC time by +options DST=0 # daylight savings time used by RTC +options SWAPPAGER # paging; REQUIRED +options VNODEPAGER # mmap() of files +options DEVPAGER # mmap() of devices + +# CPU options + +options CPU_ARM6 +options CPU_LATE_ABORT # ARM7XX compatibility + +# FPA options + +#options FPE # Single precision FPE +options ARMFPE # ARM Ltd FPE + +# File system options + +options FFS # UFS +#options QUOTA # UFS quotas +#options LFS # log-structured file system +#options MFS # memory file system + +options CD9660 # ISO 9660 + Rock Ridge file system +options MSDOSFS # MS-DOS file system +options FDESC # /dev/fd +options FIFO # FIFOs; RECOMMENDED +options KERNFS # /kern +#options NULLFS # loopback file system +#options PORTAL # ? +options PROCFS # /proc +#options UMAPFS # NULLFS + uid and gid remapping +options UNION # union file system + +# Networking options + +options NFSCLIENT +options NFSSERVER +options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +#options NS # XNS +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options CCITT,LLC,HDLC # X.25 + +# Compatibility options + +options COMPAT_43 +options COMPAT_10 +options COMPAT_09 +options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD + +# Shared memory options + +#options SYSVMSG # System V-like message queues +#options SYSVSEM # System V-like semaphores +#options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Device options + +options RAMDISK_HOOKS # boottime setup of ramdisk +options RAMDISK_SIZE=0 # Size in KBytes +options PLIP # Build plip device into lpt driver + +# Development options + +options DIAGNOSTIC # internally consistency checks +options KTRACE # system call tracing, a la ktrace(1) +options IRQSTATS # IRQ statistics +options POSTMORTEM # perform postmortem on panic +#options ROTTEN_INNARDS # show the gory bit of the postmortem +options KSHELL # kernel developemnt shell (debug) +options LKM # loadable kernel modules +#options DEBUGTERM # create a debug console +#options KGDB # remote kernel debugging +options DDB # in-kernel debugger +#makeoptions DEBUG="-g" # compile full symbol table + +config netbsd swap generic +options GENERIC + +# The main bus device +mainbus0 at root + +# The boot cpu +cpu0 at mainbus? + +# The hydra multiprocessor device +#hydrabus0 at mainbus? + +#cpu1 at hydrabus? +#cpu2 at hydrabus? +#cpu3 at hydrabus? +#cpu4 at hydrabus? + +# The vidc +vidcvideo0 at mainbus? + +# generic VT console device +vt0 at mainbus? +vt1 at mainbus? +vt2 at mainbus? +vt3 at mainbus? +vt4 at mainbus? +vt5 at mainbus? + +# IDE disk controller +wdc0 at mainbus? base 0x002107c0 irq 9 +wd0 at wdc? drive ? +wd1 at wdc? drive ? + +# Floppy disk controller +fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000 +fd0 at fdc? drive ? + +# kbd via IOMD +kbd0 at mainbus? base 0x00000000 + +# quadrature mouse +quadmouse0 at mainbus? base 0x00000000 + +# Serial ports +com0 at mainbus? base 0x00210fe0 irq 10 +#com1 at mainbus? base 0x00210be0 + +# Parallel ports +lpt0 at mainbus? base 0x002109e0 irq 0 + +# Crude sound device +beep0 at mainbus? base 0x00000000 + +# IIC bus device +iic0 at mainbus? + +# RTC device +rtc0 at iic? addr 0xa0 + +# Podule bus device +podulebus0 at root + +#asc0 at podulebus? # Acorn SCSI card +#scsibus* at asc? + +#csc0 at podulebus? # Cumana SCSI II card +#scsibus* at csc? + +ptsc0 at podulebus? # Power-Tec SCSI II card +scsibus* at ptsc? + +#oak0 at podulebus? # Oak SCSI I card +#scsibus* at oak? + +sd* at scsibus? target ? lun ? # SCSI disk drives +st* at scsibus? target ? lun ? # SCSI tape drives +cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +ch* at scsibus? target ? lun ? # SCSI auto-changers +uk* at scsibus? target ? lun ? # SCSI unknown device + +#kie* at podulebus? slot ? offset ? + +#ea0 at podulebus? # Ether3 podules +eb0 at podulebus? # EtherB network slot cards +#eh0 at podulebus? # EtherH network slot cards +#ie0 at podulebus? # Ether1 podules + +pseudo-device loop 1 # network loopback +pseudo-device bpfilter 8 # packet filter +pseudo-device sl 2 # CSLIP +pseudo-device ppp 2 # PPP +pseudo-device tun 2 # network tunneling over tty + +pseudo-device pty 32 # pseudo-terminals +pseudo-device tb 1 # tablet line discipline +pseudo-device vnd 4 # paging to files +pseudo-device ccd 2 # concatenated disk devices + +pseudo-device rd 1 # Ramdisk driver + +makeoptions MONITOR="Taxan875+LR" +#makeoptions MONITOR="AKF60" +makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900" diff --git a/sys/arch/arm32/conf/REMY b/sys/arch/arm32/conf/REMY new file mode 100644 index 00000000000..f0f15cae5b6 --- /dev/null +++ b/sys/arch/arm32/conf/REMY @@ -0,0 +1,329 @@ +# +# REMY -- Scott's development machine +# + +include "std.arm32" + +# estimated number of users + +maxusers 8 + +# Standard system options + +options TIMEZONE=0 # time zone to adjust RTC time by +options DST=0 # daylight savings time used by RTC +options SWAPPAGER # paging; REQUIRED +options VNODEPAGER # mmap() of files +options DEVPAGER # mmap() of devices + +# CPU options + +options CPU_ARM6 +options CPU_LATE_ABORT # ARM7XX compatibility + +# FPA options + +options FPE # Single precision FPE +options ARMFPE # ARM Ltd FPE + +# File system options + +options FFS # UFS +#options QUOTA # UFS quotas +#options LFS # log-structured file system +#options MFS # memory file system + +options CD9660 # ISO 9660 + Rock Ridge file system +options MSDOSFS # MS-DOS file system +options FDESC # /dev/fd +options FIFO # FIFOs; RECOMMENDED +options KERNFS # /kern +#options NULLFS # loopback file system +#options PORTAL # ? +options PROCFS # /proc +#options UMAPFS # NULLFS + uid and gid remapping +options UNION # union file system + +# Networking options + +options NFSCLIENT +options NFSSERVER +#options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +#options NS # XNS +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options CCITT,LLC,HDLC # X.25 + +# Compatibility options + +options COMPAT_43 +options COMPAT_10 +options COMPAT_09 +options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD + +# Shared memory options + +#options SYSVMSG # System V-like message queues +#options SYSVSEM # System V-like semaphores +#options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Device options + +options RAMDISK_HOOKS # boottime setup of ramdisk +options RAMDISK_SIZE=0 # Size in KBytes +options PLIP # Build plip device into lpt driver + +# Development options + +options DIAGNOSTIC # internally consistency checks +options KTRACE # system call tracing, a la ktrace(1) +options IRQSTATS # IRQ statistics +options POSTMORTEM # perform postmortem on panic +#options ROTTEN_INNARDS # show the gory bit of the postmortem +options KSHELL # kernel developemnt shell (debug) +options LKM # loadable kernel modules +#options DEBUGTERM # create a debug console +#options KGDB # remote kernel debugging +#options DDB # in-kernel debugger +#makeoptions DEBUG="-g" # compile full symbol table + +config netbsd swap generic +options GENERIC + +# The main bus device +mainbus0 at root + +# The boot cpu +cpu0 at mainbus? + +# The vidc +vidcvideo0 at mainbus? + +# generic VT console device +vt0 at mainbus? +vt1 at mainbus? +vt2 at mainbus? +vt3 at mainbus? +vt4 at mainbus? +vt5 at mainbus? + +# IDE disk controller +wdc0 at mainbus? base 0x002107c0 irq 9 +wd0 at wdc? drive ? +wd1 at wdc? drive ? + +# Floppy disk controller +fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000 +fd0 at fdc? drive ? + +# kbd via IOMD +kbd0 at mainbus? base 0x00000000 + +# quadrature mouse +quadmouse0 at mainbus? base 0x00000000 + +# Serial ports +com0 at mainbus? base 0x00210fe0 irq 10 +#com1 at mainbus? base 0x00210be0 + +# Parallel ports +lpt0 at mainbus? base 0x002109e0 irq 0 + +# Crude sound device +beep0 at mainbus? base 0x00000000 + +# IIC bus device +iic0 at mainbus? + +# RTC device +rtc0 at iic? addr 0xa0 + +# Podule bus device +podulebus0 at root + +sd* at scsibus? target ? lun ? # SCSI disk drives +st* at scsibus? target ? lun ? # SCSI tape drives +cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +ch* at scsibus? target ? lun ? # SCSI auto-changers +uk* at scsibus? target ? lun ? # SCSI unknown device + +asc0 at podulebus0 slot 0 # Acorn SCSI card +asc1 at podulebus0 slot 1 # Acorn SCSI card +asc2 at podulebus0 slot 2 # Acorn SCSI card +asc3 at podulebus0 slot 3 # Acorn SCSI card +csc0 at podulebus0 slot 0 # Cumana SCSI card +csc1 at podulebus0 slot 1 # Cumana SCSI card +csc2 at podulebus0 slot 2 # Cumana SCSI card +csc3 at podulebus0 slot 3 # Cumana SCSI card +ptsc0 at podulebus0 slot 0 # Power-tec SCSI card +ptsc1 at podulebus0 slot 1 # Power-tec SCSI card +ptsc2 at podulebus0 slot 2 # Power-tec SCSI card +ptsc3 at podulebus0 slot 3 # Power-tec SCSI card +#oak0 at podulebus0 slot 0 # Oak SCSI card +#oak1 at podulebus0 slot 1 # Oak SCSI card +#oak2 at podulebus0 slot 2 # Oak SCSI card +#oak3 at podulebus0 slot 3 # Oak SCSI card + +scsibus0 at asc0 +scsibus1 at asc1 +scsibus2 at asc2 +scsibus3 at asc3 +scsibus0 at csc0 +scsibus1 at csc1 +scsibus2 at csc2 +scsibus3 at csc3 +scsibus0 at ptsc0 +scsibus1 at ptsc1 +scsibus2 at ptsc2 +scsibus3 at ptsc3 +#scsibus0 at oak0 +#scsibus1 at oak1 +#scsibus2 at oak2 +#scsibus3 at oak3 + +# First SCSI bus +sd0 at scsibus0 target 0 lun ? # SCSI disk drive +sd1 at scsibus0 target 1 lun ? # SCSI disk drive +sd2 at scsibus0 target 2 lun ? # SCSI disk drive +sd3 at scsibus0 target 3 lun ? # SCSI disk drive +sd4 at scsibus0 target 4 lun ? # SCSI disk drive +sd5 at scsibus0 target 5 lun ? # SCSI disk drive +sd6 at scsibus0 target 6 lun ? # SCSI disk drive +st0 at scsibus0 target 0 lun ? # SCSI tape drive +st1 at scsibus0 target 1 lun ? # SCSI tape drive +st2 at scsibus0 target 2 lun ? # SCSI tape drive +st3 at scsibus0 target 3 lun ? # SCSI tape drive +st4 at scsibus0 target 4 lun ? # SCSI tape drive +st5 at scsibus0 target 5 lun ? # SCSI tape drive +st6 at scsibus0 target 6 lun ? # SCSI tape drive +cd0 at scsibus0 target 0 lun ? # SCSI CD-ROM drive +cd1 at scsibus0 target 1 lun ? # SCSI CD-ROM drive +cd2 at scsibus0 target 2 lun ? # SCSI CD-ROM drive +cd3 at scsibus0 target 3 lun ? # SCSI CD-ROM drive +cd4 at scsibus0 target 4 lun ? # SCSI CD-ROM drive +cd5 at scsibus0 target 5 lun ? # SCSI CD-ROM drive +cd6 at scsibus0 target 6 lun ? # SCSI CD-ROM drive +uk0 at scsibus0 target 0 lun ? # SCSI Unknown device +uk1 at scsibus0 target 1 lun ? # SCSI Unknown device +uk2 at scsibus0 target 2 lun ? # SCSI Unknown device +uk3 at scsibus0 target 3 lun ? # SCSI Unknown device +uk4 at scsibus0 target 4 lun ? # SCSI Unknown device +uk5 at scsibus0 target 5 lun ? # SCSI Unknown device +uk6 at scsibus0 target 6 lun ? # SCSI Unknown device + +# Second SCSI bus +sd8 at scsibus1 target 0 lun ? # SCSI disk drive +sd9 at scsibus1 target 1 lun ? # SCSI disk drive +sd10 at scsibus1 target 2 lun ? # SCSI disk drive +sd11 at scsibus1 target 3 lun ? # SCSI disk drive +sd12 at scsibus1 target 4 lun ? # SCSI disk drive +sd13 at scsibus1 target 5 lun ? # SCSI disk drive +sd14 at scsibus1 target 6 lun ? # SCSI disk drive +st8 at scsibus1 target 0 lun ? # SCSI tape drive +st9 at scsibus1 target 1 lun ? # SCSI tape drive +st10 at scsibus1 target 2 lun ? # SCSI tape drive +st11 at scsibus1 target 3 lun ? # SCSI tape drive +st12 at scsibus1 target 4 lun ? # SCSI tape drive +st13 at scsibus1 target 5 lun ? # SCSI tape drive +st14 at scsibus1 target 6 lun ? # SCSI tape drive +cd8 at scsibus1 target 0 lun ? # SCSI CD-ROM drive +cd9 at scsibus1 target 1 lun ? # SCSI CD-ROM drive +cd10 at scsibus1 target 2 lun ? # SCSI CD-ROM drive +cd11 at scsibus1 target 3 lun ? # SCSI CD-ROM drive +cd12 at scsibus1 target 4 lun ? # SCSI CD-ROM drive +cd13 at scsibus1 target 5 lun ? # SCSI CD-ROM drive +cd14 at scsibus1 target 6 lun ? # SCSI CD-ROM drive +uk8 at scsibus1 target 0 lun ? # SCSI Unknown device +uk9 at scsibus1 target 1 lun ? # SCSI Unknown device +uk10 at scsibus1 target 2 lun ? # SCSI Unknown device +uk11 at scsibus1 target 3 lun ? # SCSI Unknown device +uk12 at scsibus1 target 4 lun ? # SCSI Unknown device +uk13 at scsibus1 target 5 lun ? # SCSI Unknown device +uk14 at scsibus1 target 6 lun ? # SCSI Unknown device + +# Third SCSI bus +sd16 at scsibus2 target 0 lun ? # SCSI disk drive +sd17 at scsibus2 target 1 lun ? # SCSI disk drive +sd18 at scsibus2 target 2 lun ? # SCSI disk drive +sd19 at scsibus2 target 3 lun ? # SCSI disk drive +sd20 at scsibus2 target 4 lun ? # SCSI disk drive +sd21 at scsibus2 target 5 lun ? # SCSI disk drive +sd22 at scsibus2 target 6 lun ? # SCSI disk drive +st16 at scsibus2 target 0 lun ? # SCSI tape drive +st17 at scsibus2 target 1 lun ? # SCSI tape drive +st18 at scsibus2 target 2 lun ? # SCSI tape drive +st19 at scsibus2 target 3 lun ? # SCSI tape drive +st20 at scsibus2 target 4 lun ? # SCSI tape drive +st21 at scsibus2 target 5 lun ? # SCSI tape drive +st22 at scsibus2 target 6 lun ? # SCSI tape drive +cd16 at scsibus2 target 0 lun ? # SCSI CD-ROM drive +cd17 at scsibus2 target 1 lun ? # SCSI CD-ROM drive +cd18 at scsibus2 target 2 lun ? # SCSI CD-ROM drive +cd19 at scsibus2 target 3 lun ? # SCSI CD-ROM drive +cd20 at scsibus2 target 4 lun ? # SCSI CD-ROM drive +cd21 at scsibus2 target 5 lun ? # SCSI CD-ROM drive +cd22 at scsibus2 target 6 lun ? # SCSI CD-ROM drive +uk16 at scsibus2 target 0 lun ? # SCSI Unknown device +uk17 at scsibus2 target 1 lun ? # SCSI Unknown device +uk18 at scsibus2 target 2 lun ? # SCSI Unknown device +uk19 at scsibus2 target 3 lun ? # SCSI Unknown device +uk20 at scsibus2 target 4 lun ? # SCSI Unknown device +uk21 at scsibus2 target 5 lun ? # SCSI Unknown device +uk22 at scsibus2 target 6 lun ? # SCSI Unknown device + +# Fourth SCSI bus +sd24 at scsibus3 target 0 lun ? # SCSI disk drive +sd25 at scsibus3 target 1 lun ? # SCSI disk drive +sd26 at scsibus3 target 2 lun ? # SCSI disk drive +sd27 at scsibus3 target 3 lun ? # SCSI disk drive +sd28 at scsibus3 target 4 lun ? # SCSI disk drive +sd29 at scsibus3 target 5 lun ? # SCSI disk drive +sd30 at scsibus3 target 6 lun ? # SCSI disk drive +st24 at scsibus3 target 0 lun ? # SCSI tape drive +st25 at scsibus3 target 1 lun ? # SCSI tape drive +st26 at scsibus3 target 2 lun ? # SCSI tape drive +st27 at scsibus3 target 3 lun ? # SCSI tape drive +st28 at scsibus3 target 4 lun ? # SCSI tape drive +st29 at scsibus3 target 5 lun ? # SCSI tape drive +st30 at scsibus3 target 6 lun ? # SCSI tape drive +cd24 at scsibus3 target 0 lun ? # SCSI CD-ROM drive +cd25 at scsibus3 target 1 lun ? # SCSI CD-ROM drive +cd26 at scsibus3 target 2 lun ? # SCSI CD-ROM drive +cd27 at scsibus3 target 3 lun ? # SCSI CD-ROM drive +cd28 at scsibus3 target 4 lun ? # SCSI CD-ROM drive +cd29 at scsibus3 target 5 lun ? # SCSI CD-ROM drive +cd30 at scsibus3 target 6 lun ? # SCSI CD-ROM drive +uk24 at scsibus3 target 0 lun ? # SCSI Unknown device +uk25 at scsibus3 target 1 lun ? # SCSI Unknown device +uk26 at scsibus3 target 2 lun ? # SCSI Unknown device +uk27 at scsibus3 target 3 lun ? # SCSI Unknown device +uk28 at scsibus3 target 4 lun ? # SCSI Unknown device +uk29 at scsibus3 target 5 lun ? # SCSI Unknown device +uk30 at scsibus3 target 6 lun ? # SCSI Unknown device + +ch* at scsibus? target ? lun ? # SCSI auto-changers + +#kie* at podulebus? slot ? offset ? + +#ea0 at podulebus? # Ether3 podules +#eb0 at podulebus? # EtherB network slot cards +#eh0 at podulebus? # EtherH network slot cards +#ie0 at podulebus? # Ether1 podules + +pseudo-device loop 1 # network loopback +pseudo-device bpfilter 8 # packet filter +pseudo-device sl 2 # CSLIP +pseudo-device ppp 2 # PPP +pseudo-device tun 2 # network tunneling over tty + +pseudo-device pty 32 # pseudo-terminals +pseudo-device tb 1 # tablet line discipline +pseudo-device vnd 4 # paging to files +pseudo-device ccd 2 # concatenated disk devices + +pseudo-device rd 1 # Ramdisk driver + +makeoptions MONITOR="AKF85" +makeoptions MODES="1280,1024 1024,768,60 1024,768,70 800,600,60 640,480,60 1152,900" diff --git a/sys/arch/arm32/conf/VOYAGER b/sys/arch/arm32/conf/VOYAGER new file mode 100644 index 00000000000..00cf42932dc --- /dev/null +++ b/sys/arch/arm32/conf/VOYAGER @@ -0,0 +1,197 @@ +# +# VOYAGER -- Mark's master development machine +# + +include "std.arm32" + +# estimated number of users + +maxusers 32 + +# Standard system options + +options TIMEZONE=0 # time zone to adjust RTC time by +options DST=0 # daylight savings time used by RTC +options SWAPPAGER # paging; REQUIRED +options VNODEPAGER # mmap() of files +options DEVPAGER # mmap() of devices + +# CPU options + +options CPU_ARM6 +options CPU_LATE_ABORT # ARM7XX compatibility + +# FPA options + +#options FPE # Single precision FPE +options ARMFPE # ARM Ltd FPE + +# File system options + +options FFS # UFS +#options QUOTA # UFS quotas +#options LFS # log-structured file system +options MFS # memory file system + +options CD9660 # ISO 9660 + Rock Ridge file system +options MSDOSFS # MS-DOS file system +options FDESC # /dev/fd +options FIFO # FIFOs; RECOMMENDED +options KERNFS # /kern +options NULLFS # loopback file system +#options PORTAL # ? +options PROCFS # /proc +#options UMAPFS # NULLFS + uid and gid remapping +options UNION # union file system + +# Networking options + +options NFSCLIENT +options NFSSERVER +options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +#options NS # XNS +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options CCITT,LLC,HDLC # X.25 + +# Compatibility options + +options COMPAT_43 +options COMPAT_10 +options COMPAT_09 +options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD + +# Shared memory options + +#options SYSVMSG # System V-like message queues +#options SYSVSEM # System V-like semaphores +#options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Device options + +options RAMDISK_HOOKS # boottime setup of ramdisk +options RAMDISK_SIZE=0 # Size in KBytes +options PLIP # Build plip device into lpt driver + +# Development options + +options DIAGNOSTIC # internally consistency checks +options KTRACE # system call tracing, a la ktrace(1) +options IRQSTATS # IRQ statistics +options POSTMORTEM # perform postmortem on panic +#options ROTTEN_INNARDS # show the gory bit of the postmortem +options KSHELL # kernel developemnt shell (debug) +options LKM # loadable kernel modules +#options DEBUGTERM # create a debug console +#options KGDB # remote kernel debugging +options DDB # in-kernel debugger +#makeoptions DEBUG="-g" # compile full symbol table + +config netbsd swap generic +options GENERIC + +# The main bus device +mainbus0 at root + +# The boot cpu +cpu0 at mainbus? + +# The hydra multiprocessor device +hydrabus0 at mainbus? + +#cpu1 at hydrabus? +#cpu2 at hydrabus? +#cpu3 at hydrabus? +#cpu4 at hydrabus? + +# The vidc +vidcvideo0 at mainbus? + +# generic VT console device +vt0 at mainbus? +vt1 at mainbus? +vt2 at mainbus? +vt3 at mainbus? +vt4 at mainbus? +vt5 at mainbus? + +# IDE disk controller +wdc0 at mainbus? base 0x002107c0 irq 9 +wd* at wdc? drive ? + +# Floppy disk controller +fdc0 at mainbus? base 0x00210fc0 irq 12 dack 0x00002000 +fd0 at fdc? drive ? + +# kbd via IOMD +kbd0 at mainbus? base 0x00000000 + +# quadrature mouse +quadmouse0 at mainbus? base 0x00000000 + +# PS2 mouse +pms0 at mainbus? base 0x00000000 + +# Serial ports +com0 at mainbus? base 0x00210fe0 irq 10 +#com1 at mainbus? base 0x00210be0 + +# Parallel ports +lpt0 at mainbus? base 0x002109e0 irq 0 + +# Crude sound device +beep0 at mainbus? base 0x00000000 + +# IIC bus device +iic0 at mainbus? + +# RTC device +rtc0 at iic? addr 0xa0 + +# Podule bus device +podulebus0 at root + +asc0 at podulebus? # Acorn SCSI card +scsibus* at asc? + +csc0 at podulebus? # Cumana SCSI II card +scsibus* at csc? + +ptsc0 at podulebus? # Power-Tec SCSI II card +scsibus* at ptsc? + +oak0 at podulebus? # Oak SCSI I card +scsibus* at oak? + +sd* at scsibus? target ? lun ? # SCSI disk drives +st* at scsibus? target ? lun ? # SCSI tape drives +cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +ch* at scsibus? target ? lun ? # SCSI auto-changers +uk* at scsibus? target ? lun ? # SCSI unknown device +ss* at scsibus? target ? lun ? # SCSI scanner + +#kie* at podulebus? slot ? offset ? + +ea0 at podulebus? # Ether3 podules +eb0 at podulebus? # EtherB network slot cards +eh0 at podulebus? # EtherH network slot cards +ie0 at podulebus? # Ether1 podules + +pseudo-device loop 1 # network loopback +pseudo-device bpfilter 8 # packet filter +pseudo-device sl 2 # CSLIP +pseudo-device ppp 2 # PPP +pseudo-device tun 2 # network tunneling over tty + +pseudo-device pty 32 # pseudo-terminals +pseudo-device tb 1 # tablet line discipline +pseudo-device vnd 4 # paging to files +pseudo-device ccd 2 # concatenated disk devices + +pseudo-device rd 1 # Ramdisk device + +makeoptions MONITOR="Taxan875+LR" +#makeoptions MONITOR="AKF60" +makeoptions MODES="1024,768,60 1024,768,70 800,600,60 640,480,60 1280,1024 1152,900" diff --git a/sys/arch/arm32/conf/files.arm32 b/sys/arch/arm32/conf/files.arm32 new file mode 100644 index 00000000000..ac8d54fa128 --- /dev/null +++ b/sys/arch/arm32/conf/files.arm32 @@ -0,0 +1,271 @@ +# +# First try for arm-specific configuration info +# + +maxpartitions 8 +maxusers 2 8 64 + +device mainbus { [base = -1], [dack = -1], [irq = -1] } +attach mainbus at root +file arch/arm32/mainbus/mainbus.c mainbus + +device hydrabus { [slot = -1] } +attach hydrabus at mainbus +file arch/arm32/mainbus/exp/hydra.c hydrabus needs-flag +file arch/arm32/mainbus/exp/hydraboot.S hydrabus + +device cpu +attach cpu at mainbus, hydrabus +file arch/arm32/mainbus/cpu.c cpu needs-flag +major {cpu = 38} + +#Standard NetBSD wd driver +device wdc {drive = -1} +attach wdc at mainbus +device wd: disk +attach wd at wdc +file arch/arm32/mainbus/wd.c wdc needs-flag +major {wd = 16} + +#Hacked NetBSD wd driver with cd and atapi support - nasty hack atm +#device wdc {drive = -1} +#attach wdc at mainbus +#device wd: disk +#attach wd at wdc +#file arch/arm32/mainbus/exp/wd.c wdc needs-flag +#major {wd = 16} + +device atapi: disk +attach atapi at mainbus +file arch/arm32/mainbus/exp/atapi.c atapi needs-flag + +device wcd: disk +attach wcd at mainbus +file arch/arm32/mainbus/exp/wcd.c wcd needs-flag +major {wcd = 20} + +#Standard NetBSD fd driver +device fdc {drive = -1} +attach fdc at mainbus +device fd: disk +attach fd at fdc +file arch/arm32/mainbus/fd.c fdc needs-flag +major {fd = 17} + +# RAM disk driver +pseudo-device rd +file dev/ramdisk.c rd needs-count +file arch/arm32/dev/rd_hooks.c rd | ramdisk_hooks +major {rd = 18} + +device lpt: tty, ether, ifnet +attach lpt at mainbus +file arch/arm32/mainbus/lpt.c lpt needs-flag +major {lpt = 8} + +device com: tty +attach com at mainbus +file arch/arm32/mainbus/com.c com needs-flag +major {com = 12} + +# Mouse devices +device quadmouse: tty +attach quadmouse at mainbus +file arch/arm32/mainbus/qmouse.c quadmouse needs-flag +major {quadmouse = 9} + +device pms: tty +attach pms at mainbus +file arch/arm32/mainbus/pms.c pms needs-flag +major {pms = 40} + +# Audio devices +device beep +attach beep at mainbus +file arch/arm32/mainbus/beep.c beep needs-flag +major {beep = 10} + +device audio: audio +attach audio at mainbus +file arch/arm32/mainbus/vidcaudio.c vidcaudio needs-flag +major {audio = 36} + +device kbd +attach kbd at mainbus +file arch/arm32/mainbus/kbd.c kbd needs-flag +major {kbd = 11} + +# Podule bus device +device podulebus { [slot = -1] } +attach podulebus at root +file arch/arm32/podulebus/podulebus.c podulebus + +# Ethernet devices +device ea: ether, ifnet +attach ea at podulebus +file arch/arm32/podulebus/if_ea.c ea + +device eb: ether, ifnet +attach eb at podulebus +file arch/arm32/podulebus/if_eb.c eb + +device eh: ether, ifnet +attach eh at podulebus +file arch/arm32/podulebus/if_eh.c eh + +device ie: ether, ifnet +attach ie at podulebus +file arch/arm32/podulebus/if_ie.c ie + +# IIC/RTC files +device iic { addr = -1 } +attach iic at mainbus +file arch/arm32/mainbus/iic_asm.S iic +file arch/arm32/mainbus/iic.c iic needs-flag + +device rtc +attach rtc at iic +file arch/arm32/mainbus/rtc.c rtc needs-count + +#define kgdb + +#device kie: kgdb +#attach kie at podule +#file arch/arm32/podulebus/kgdb_ie.c kie + +#file arch/arm32/arm32/kgdb_glue.c kgdb +#file arch/arm32/arm32/kgdb_step.c kgdb + +# +# Machine-independent SCSI drivers +# + +include "../../../scsi/files.scsi" +major {sd = 24} +major {st = 25} +major {cd = 26} +major {ch = 27} +major {uk = 28} +major {ss = 29} + +# Generic sbic (WD3393) driver +define sbic +file arch/arm32/podulebus/sbic.c sbic + +# Acorn SCSI I specific layer for sbic +device asc: scsi, sbic +attach asc at podulebus +file arch/arm32/podulebus/asc.c asc + +# Generic fas216 + esp216 driver +define sfas +file arch/arm32/podulebus/sfas.c sfas + +# Cumana specific layer for sfas +device csc: scsi, sfas +attach csc at podulebus +file arch/arm32/podulebus/exp/csc.c csc + +device ptsc: scsi, sfas +attach ptsc at podulebus +file arch/arm32/podulebus/ptsc.c ptsc + +# Generic NCR driver +define ncr +file arch/arm32/podulebus/ncr5380sbc.c ncr + +# Oak specific layer for ncr +device oak: scsi, ncr +attach oak at podulebus +file arch/arm32/podulebus/oak.c oak + +device vidcvideo +attach vidcvideo at mainbus +major {vidcvideo = 37} +device vt: tty +attach vt at mainbus +file arch/arm32/dev/console/console.c vt needs-count +file arch/arm32/dev/console/vidcconsole.c vt needs-count +file arch/arm32/dev/console/vidc_mc.S vt needs-count +file arch/arm32/dev/console/vidc.c vt needs-count +file arch/arm32/dev/console/vt220.c vt needs-count +file arch/arm32/dev/console/debugconsole.c vt needs-count +file arch/arm32/dev/console/dumb.c vt needs-count + +file arch/arm32/arm32/autoconf.c +file arch/arm32/arm32/blockio.S +file arch/arm32/arm32/clock.c +file arch/arm32/arm32/conf.c +file arch/arm32/arm32/cpuswitch.S +file arch/arm32/arm32/disksubr.c disk +file arch/arm32/arm32/stubs.c +file arch/arm32/arm32/exception.S +file arch/arm32/arm32/syscall.c +file arch/arm32/arm32/ast.c +file arch/arm32/arm32/fault.c +file arch/arm32/arm32/undefined.c +file arch/arm32/arm32/mem.c +file arch/arm32/arm32/scratch.S +file arch/arm32/arm32/process_machdep.c +file arch/arm32/arm32/machdep.c +file arch/arm32/arm32/sys_machdep.c +file arch/arm32/arm32/vm_machdep.c +file arch/arm32/arm32/pmap.c +file arch/arm32/arm32/fusu.c + +file netinet/in_cksum.c inet +file netns/ns_cksum.c ns + +# IRQ/FIQ files +file arch/arm32/arm32/spl.S +file arch/arm32/arm32/irq.S +file arch/arm32/arm32/irqhandler.c +file arch/arm32/arm32/fiq.S + +# library functions +file arch/arm32/arm32/strstr.c +file arch/arm32/arm32/strtoul.c +file arch/arm32/arm32/memset.S +file arch/arm32/arm32/bcopy_page.S +file arch/arm32/arm32/bcopy.S +file arch/arm32/arm32/bcopyinout.S +file arch/arm32/arm32/copystr.S +file arch/arm32/arm32/coproc15.S +file arch/arm32/arm32/setcpsr.S +file arch/arm32/arm32/setstack.S + +# files related to the shell +file arch/arm32/kshell/shell_input.c kshell +file arch/arm32/kshell/shell_shell.c kshell +file arch/arm32/kshell/shell_disassem.c kshell +file arch/arm32/kshell/strchr.c kshell +file arch/arm32/kshell/dumphex.c kshell + +# files related to debugging +file arch/arm32/arm32/debug.c +file arch/arm32/arm32/disassem.c +file arch/arm32/arm32/postmortem.c + +file dev/cons.c +file dev/cninit.c + +# Signal precision FPE +file arch/arm32/fpe-sp/fpe.c fpe +file arch/arm32/fpe-sp/fpeadd.S fpe +file arch/arm32/fpe-sp/fpesub.S fpe +file arch/arm32/fpe-sp/fpemul.S fpe +file arch/arm32/fpe-sp/fpediv.S fpe +file arch/arm32/fpe-sp/fpefix.S fpe +file arch/arm32/fpe-sp/fpecmf.S fpe +file arch/arm32/fpe-sp/fpetoe.S fpe + +# ARM FPE +file arch/arm32/fpe-arm/armfpe_glue.S armfpe +file arch/arm32/fpe-arm/armfpe_init.c armfpe +file arch/arm32/fpe-arm/armfpe.s armfpe + +# DDB +file arch/arm32/arm32/db_disasm.c ddb +file arch/arm32/arm32/db_interface.c ddb +file arch/arm32/arm32/db_trace.c ddb +file arch/arm32/arm32/db_machdep.c ddb diff --git a/sys/arch/arm32/conf/monitors/AKF60 b/sys/arch/arm32/conf/monitors/AKF60 new file mode 100644 index 00000000000..a420a66a0c1 --- /dev/null +++ b/sys/arch/arm32/conf/monitors/AKF60 @@ -0,0 +1,360 @@ +# Modefile written by !MakeModes version 0.19 (22-Aug-1994) +# Monitor description file for Acorn AKF60 monitor +# Line rate: 30 - 50 kHz + +file_format:1 +monitor_title:Acorn AKF60 +DPMS_state:1 + +# Letterbox modes + +# 240 x 352 (70Hz) +startmode +mode_name: +x_res:240 +y_res:352 +pixel_rate:9440 +h_timings:18,16,8,240,8,10 +v_timings:2,58,0,352,0,37 +sync_pol:2 +endmode + +# 320 x 250 (70Hz - Modes 6,7) +# Low band +startmode +mode_name: +x_res:320 +y_res:250 +pixel_rate:12587 +h_timings:36,14,12,320,12,6 +v_timings:2,109,0,250,0,88 +sync_pol:2 +endmode + +# 320 x 256 (70Hz - Modes 1,2,5,9,10,13) +# Low band +startmode +mode_name: +x_res:320 +y_res:256 +pixel_rate:12587 +h_timings:36,14,12,320,12,6 +v_timings:2,106,0,256,0,85 +sync_pol:2 +endmode + +# 384 x 288 (70Hz) +# Low band +startmode +mode_name: +x_res:384 +y_res:288 +pixel_rate:18881 +h_timings:64,16,66,384,66,4 +v_timings:2,58,32,288,32,37 +sync_pol:2 +endmode + +# 480 x 352 (70Hz) +# Low band +startmode +mode_name:480 x 352 +x_res:480 +y_res:352 +pixel_rate:18881 +h_timings:64,16,18,480,18,4 +v_timings:2,58,0,352,0,37 +sync_pol:2 +endmode + +# 640 x 200 (70Hz - Modes 44,45,46) +# Low band +startmode +mode_name: +x_res:640 +y_res:200 +pixel_rate:25175 +h_timings:88,22,22,640,22,6 +v_timings:2,134,0,200,0,113 +sync_pol:2 +endmode + +# 640 x 250 (70Hz - Modes 3,11,14) +# Low band +startmode +mode_name: +x_res:640 +y_res:250 +pixel_rate:25175 +h_timings:88,22,22,640,22,6 +v_timings:2,109,0,250,0,88 +sync_pol:2 +endmode + +# 640 x 256 (70Hz - Modes 0,4,8,12,15) +# Low band +startmode +mode_name: +x_res:640 +y_res:256 +pixel_rate:25175 +h_timings:88,22,22,640,22,6 +v_timings:2,106,0,256,0,85 +sync_pol:2 +endmode + +# 640 x 352 (70Hz - Modes 41,42,43) +# Low band +startmode +mode_name: +x_res:640 +y_res:352 +pixel_rate:25175 +h_timings:88,22,22,640,22,6 +v_timings:2,58,0,352,0,37 +sync_pol:2 +endmode + +# Other modes (some also numbered) + +# 320 x 480 (60Hz - Games modes 48,49) +# Low band +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:12587 +h_timings:36,14,12,320,12,6 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 320 x 480 (72Hz) +# Mid band +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:15750 +h_timings:28,30,16,320,16,6 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 320 x 480 (75Hz) +# Mid band +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:15750 +h_timings:26,34,16,320,16,8 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 360 x 480 (60Hz - PCSoft mode 47) +# Low band +startmode +mode_name: +x_res:360 +y_res:480 +pixel_rate:16783 +h_timings:62,44,16,360,16,34 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 640 x 480 (60Hz - Modes 25,26,27,28) +# Low band +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:25175 +h_timings:88,22,22,640,22,6 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 640 x 480 (72Hz) +# Mid band +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:31500 +h_timings:52,64,30,640,30,14 +# VESA:40,128,0,640,0,24 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 640 x 480 (75Hz) +# Mid band +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:31500 +h_timings:62,64,30,640,30,14 +# VESA:64,120,0,640,0,16 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 800 x 600 (56Hz - Modes 29,30,31) +# Mid band +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:36000 +h_timings:70,74,34,800,34,12 +# VESA:72,128,0,800,0,24 +v_timings:2,22,0,600,0,1 +sync_pol:0 +endmode + +# 800 x 600 (60Hz) +# Mid band +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:40000 +h_timings:112,64,40,800,40,0 +# VESA:128,88, 0,800,0,40 +v_timings:4,23,0,600,0,1 +sync_pol:0 +endmode + +# 800 x 600 (72Hz) +# High band +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:50000 +h_timings:88,34,42,800,42,34 +# VESA:120,64, 0,800,0,56 +v_timings:6,23,0,600,0,37 +sync_pol:0 +endmode + +# 800 x 600 (75Hz) +# High band +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:49500 +h_timings:80,46,42,800,42,46 +# VESA:80,160,0,800,0,16 +v_timings:3,21,0,600,0,1 +sync_pol:0 +endmode + +# 1024 x 768 (60Hz) +# High band +startmode +mode_name:1024 x 768 +x_res:1024 +y_res:768 +pixel_rate:65000 +h_timings:128,36,60,1024,60,36 +# VESA:136,160,0,1024,0,24 +v_timings:6,29,0,768,0,3 +sync_pol:0 +endmode + +# Pixel-doubled modes + +# 1280 x 480 (60Hz) +# Low band +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:50350 +h_timings:176,44,44,1280,44,12 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 1280 x 480 (72Hz) +# Mid band +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:63000 +h_timings:104,128,60,1280,60,28 +# VESA:80,256,0,1280,0,48 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 1280 x 480 (75Hz) +# Mid band +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:63000 +h_timings:124,128,60,1280,60,28 +# VESA:128,240,0,1280,0,32 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 1600 x 600 (56Hz) +# Mid band +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:72000 +h_timings:140,148,68,1600,68,24 +v_timings:2,22,0,600,0,1 +sync_pol:0 +endmode + +# 1600 x 600 (60Hz) +# Mid band +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:80000 +h_timings:224,128,80,1600,80,0 +# VESA:256,176, 0,1600,0,80 +v_timings:4,23,0,600,0,1 +sync_pol:0 +endmode + +# 1600 x 600 (72Hz) +# High band +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:100000 +h_timings:176,68,84,1600,84,68 +# VESA:240,128, 0,1600,0,112 +v_timings:6,23,0,600,0,37 +sync_pol:0 +endmode + +# 1600 x 600 (75Hz) +# High band +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:99000 +h_timings:160,92,84,1600,84,92 +# VESA:160,320,0,1600,0,32 +v_timings:3,21,0,600,0,1 +sync_pol:0 +endmode diff --git a/sys/arch/arm32/conf/monitors/AKF85 b/sys/arch/arm32/conf/monitors/AKF85 new file mode 100644 index 00000000000..7813bf90f4d --- /dev/null +++ b/sys/arch/arm32/conf/monitors/AKF85 @@ -0,0 +1,397 @@ +# Modefile written by !MakeModes version 0.19 (22-Aug-1994) +# Monitor description file for Acorn AKF85 monitor +# Line rate: 30 - 82 kHz +# Frame rate: 50 - 120 Hz +# Dot rate: Up to 135 MHz + + +file_format:1 +monitor_title:Acorn AKF85 +DPMS_state:0 + +# 240 x 352 (70Hz) +startmode +mode_name: +x_res:240 +y_res:352 +pixel_rate:9440 +h_timings:20,16,8,240,8,8 +v_timings:2,58,0,352,0,37 +sync_pol:2 +endmode + +# 320 x 250 (70Hz) +startmode +mode_name: +x_res:320 +y_res:250 +pixel_rate:12587 +h_timings:42,14,12,320,12,0 +v_timings:2,109,0,250,0,88 +sync_pol:2 +endmode + +# 320 x 256 (70Hz) +startmode +mode_name: +x_res:320 +y_res:256 +pixel_rate:12587 +h_timings:42,14,12,320,12,0 +v_timings:2,106,0,256,0,85 +sync_pol:2 +endmode + +# 320 x 480 (60Hz) +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:12587 +h_timings:42,14,12,320,12,0 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 320 x 480 (73Hz) +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:15750 +h_timings:24,40,16,320,16,0 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 320 x 480 (75Hz) +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:15750 +h_timings:24,44,16,320,16,0 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 360 x 480 (60Hz) +startmode +mode_name: +x_res:360 +y_res:480 +pixel_rate:16783 +h_timings:64,46,16,360,16,30 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 384 x 288 (70Hz) +startmode +mode_name: +x_res:384 +y_res:288 +pixel_rate:18881 +h_timings:68,16,66,384,66,0 +v_timings:2,58,32,288,32,37 +sync_pol:2 +endmode + +# 480 x 352 (70Hz) +startmode +mode_name:480 x 352 +x_res:480 +y_res:352 +pixel_rate:18881 +h_timings:68,16,18,480,18,0 +v_timings:2,58,0,352,0,37 +sync_pol:2 +endmode + +# 640 x 200 (70Hz) +startmode +mode_name: +x_res:640 +y_res:200 +pixel_rate:25175 +h_timings:92,24,22,640,22,0 +v_timings:2,134,0,200,0,113 +sync_pol:2 +endmode + +# 640 x 250 (70Hz) +startmode +mode_name: +x_res:640 +y_res:250 +pixel_rate:25175 +h_timings:92,24,22,640,22,0 +v_timings:2,109,0,250,0,88 +sync_pol:2 +endmode + +# 640 x 256 (70Hz) +startmode +mode_name: +x_res:640 +y_res:256 +pixel_rate:25175 +h_timings:92,24,22,640,22,0 +v_timings:2,106,0,256,0,85 +sync_pol:2 +endmode + +# 640 x 352 (70Hz) +startmode +mode_name: +x_res:640 +y_res:352 +pixel_rate:25175 +h_timings:92,24,22,640,22,0 +v_timings:2,58,0,352,0,37 +sync_pol:2 +endmode + +# 640 x 480 (60Hz) +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:25175 +h_timings:94,22,22,640,22,0 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 640 x 480 (73Hz) +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:31500 +h_timings:48,84,30,640,30,0 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 640 x 480 (75Hz) +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:31500 +h_timings:64,76,30,640,30,0 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 640 x 480 (120Hz) +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:52600 +h_timings:64,76,30,640,46,18 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 800 x 600 (60Hz) +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:40000 +h_timings:128,48,40,800,40,0 +v_timings:4,23,0,600,0,1 +sync_pol:0 +endmode + +# 800 x 600 (75Hz) +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:49500 +h_timings:80,92,42,800,42,0 +v_timings:3,21,0,600,0,1 +sync_pol:0 +endmode + +# 800 x 600 (100Hz) +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:69350 +h_timings:100,104,0,800,66,42 +v_timings:3,21,0,600,0,1 +sync_pol:0 +endmode + +# 1024 x 768 (60Hz) +startmode +mode_name:1024 x 768 +x_res:1024 +y_res:768 +pixel_rate:65000 +h_timings:136,64,60,1024,60,0 +v_timings:6,29,0,768,0,3 +sync_pol:0 +endmode + +# 1024 x 768 (70Hz) +startmode +mode_name:1024 x 768 +x_res:1024 +y_res:768 +pixel_rate:75000 +h_timings:124,36,72,1024,72,0 +v_timings:6,29,0,768,0,3 +sync_pol:0 +endmode + +# 1024 x 768 (75Hz) +startmode +mode_name:1024 x 768 +x_res:1024 +y_res:768 +pixel_rate:80310 +h_timings:122,86,30,1024,76,0 +v_timings:3,28,0,768,0,1 +sync_pol:0 +endmode + +# 1024 x 768 (102Hz) +startmode +mode_name:1024 x 768 +x_res:1024 +y_res:768 +pixel_rate:119000 +h_timings:130,96,46,1024,106,50 +v_timings:3,28,0,768,0,1 +sync_pol:0 +endmode + +# 1152 x 900 (55Hz) +startmode +mode_name:1152 x 900 +x_res:1152 +y_res:900 +pixel_rate:80000 +h_timings:156,40,98,1152,124,0 +v_timings:1,28,0,900,0,3 +sync_pol:0 +endmode + +# 1152 x 900 (86Hz) +startmode +mode_name:1152 x 900 +x_res:1152 +y_res:900 +pixel_rate:134480 +h_timings:132,70,124,1152,124,70 +v_timings:1,28,0,900,0,3 +sync_pol:0 +endmode + +# 1280 x 480 (60Hz) +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:50350 +h_timings:188,44,44,1280,44,0 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 1280 x 480 (73Hz) +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:63000 +h_timings:96,172,58,1280,58,0 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 1280 x 480 (75Hz) +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:63000 +h_timings:128,156,58,1280,58,0 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 1280 x 1024 (76Hz) +startmode +mode_name:1280 x 1024 +x_res:1280 +y_res:1024 +pixel_rate:139000 +h_timings:166,90,96,1280,96,0 +v_timings:3,32,0,1024,0,3 +sync_pol:0 +endmode + +# 1600 x 600 (56Hz) +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:72000 +h_timings:144,168,68,1600,68,0 +v_timings:2,22,0,600,0,1 +sync_pol:0 +endmode + +# 1600 x 600 (60Hz) +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:80000 +h_timings:256,98,78,1600,78,2 +v_timings:4,23,0,600,0,1 +sync_pol:0 +endmode + +# 1600 x 600 (72Hz) +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:100000 +h_timings:226,58,84,1600,84,28 +v_timings:6,23,0,600,0,37 +sync_pol:0 +endmode + +# 1600 x 600 (75Hz) +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:99000 +h_timings:160,188,82,1600,82,0 +v_timings:3,21,0,600,0,1 +sync_pol:0 +endmode + +# 1600 x 1200 (50Hz) +startmode +mode_name:1600 x 1200 +x_res:1600 +y_res:1200 +pixel_rate:131000 +h_timings:166,90,96,1600,128,44 +v_timings:3,32,0,1200,0,3 +sync_pol:0 +endmode + +# End diff --git a/sys/arch/arm32/conf/monitors/Taxan875+LR b/sys/arch/arm32/conf/monitors/Taxan875+LR new file mode 100644 index 00000000000..4a02e255477 --- /dev/null +++ b/sys/arch/arm32/conf/monitors/Taxan875+LR @@ -0,0 +1,412 @@ +# Modefile written by !MakeModes version 0.19 (22-Aug-1994) +# Monitor description file for Taxan 875+LR monitor +# Line rate: 30 - 82 kHz +# Frame rate: 50 - 120 Hz +# Dot rate: Up to 135 MHz + +file_format:1 +monitor_title:Taxan 875+LR +DPMS_state:0 + +# Letterbox modes + +# 240 x 352 (70Hz) +startmode +mode_name: +x_res:240 +y_res:352 +pixel_rate:9440 +h_timings:20,16,8,240,8,8 +v_timings:2,58,0,352,0,37 +sync_pol:2 +endmode + +# 320 x 250 (70Hz - Modes 6,7) +startmode +mode_name: +x_res:320 +y_res:250 +pixel_rate:12587 +h_timings:42,14,12,320,12,0 +v_timings:2,109,0,250,0,88 +sync_pol:2 +endmode + +# 320 x 256 (70Hz - Modes 1,2,5,9,10,13) +startmode +mode_name: +x_res:320 +y_res:256 +pixel_rate:12587 +h_timings:42,14,12,320,12,0 +v_timings:2,106,0,256,0,85 +sync_pol:2 +endmode + +# 384 x 288 (70Hz) +startmode +mode_name: +x_res:384 +y_res:288 +pixel_rate:18881 +h_timings: 68,16,66,384,66,0 +v_timings: 2,58,32,288,32,37 +sync_pol:2 +endmode + +# 480 x 352 (70Hz) +startmode +mode_name:480 x 352 +x_res:480 +y_res:352 +pixel_rate:18881 +h_timings: 68,16,18,480,18,0 +v_timings: 2,58,0,352,0,37 +sync_pol:2 +endmode + +# 640 x 200 (70Hz - Modes 44,45,46) +startmode +mode_name: +x_res:640 +y_res:200 +pixel_rate:25175 +h_timings:92,24,22,640,22,0 +v_timings:2,134,0,200,0,113 +sync_pol:2 +endmode + +# 640 x 250 (70Hz - Modes 3,11,14) +startmode +mode_name: +x_res:640 +y_res:250 +pixel_rate:25175 +h_timings:92,24,22,640,22,0 +v_timings:2,109,0,250,0,88 +sync_pol:2 +endmode + +# 640 x 256 (70Hz - Modes 0,4,8,12,15) +startmode +mode_name: +x_res:640 +y_res:256 +pixel_rate:25175 +h_timings:92,24,22,640,22,0 +v_timings:2,106,0,256,0,85 +sync_pol:2 +endmode + +# 640 x 352 (70Hz - Modes 41,42,43) +startmode +mode_name: +x_res:640 +y_res:352 +pixel_rate:25175 +h_timings:92,24,22,640,22,0 +v_timings:2,58,0,352,0,37 +sync_pol:2 +endmode + +# Other modes (some also numbered) + +# 320 x 480 (60Hz - Games modes 48,49) +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:12587 +h_timings:42,14,12,320,12,0 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 320 x 480 (72Hz) +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:15750 +h_timings:24,40,16,320,16,0 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 320 x 480 (75Hz) +startmode +mode_name: +x_res:320 +y_res:480 +pixel_rate:15750 +h_timings:24,44,16,320,16,0 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 360 x 480 (60Hz - PCSoft mode 47) +startmode +mode_name: +x_res:360 +y_res:480 +pixel_rate:16783 +h_timings:64,46,16,360,16,30 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 640 x 480 (60Hz - Modes 25,26,27,28) +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:25175 +h_timings:94,22,22,640,22,0 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 640 x 480 (72Hz) +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:31500 +h_timings:48,84,30,640,30,0 +# VESA:40,128,0,640,0,24 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 640 x 480 (75Hz) +startmode +mode_name:640 x 480 +x_res:640 +y_res:480 +pixel_rate:31500 +h_timings:64,76,30,640,30,0 +# VESA:64,120,0,640,0,16 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 800 x 600 (56Hz - Modes 29,30,31) +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:36000 +h_timings:72,84,34,800,34,0 +# VESA:72,128,0,800,0,24 +v_timings:2,22,0,600,0,1 +sync_pol:0 +endmode + +# 800 x 600 (60Hz) +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:40000 +h_timings:128,48,40,800,40,0 +# VESA:128,88, 0,800,0,40 +v_timings:4,23,0,600,0,1 +sync_pol:0 +endmode + +# 800 x 600 (72Hz) +startmode +mode_name:800 x 600 +x_res:800 +y_res:600 +pixel_rate:50000 +h_timings:100,42,42,800,42,14 +# VESA:120,64, 0,800,0,56 +v_timings:6,23,0,600,0,37 +sync_pol:0 +endmode + +# Stick with just the 72Hz mode as this is a factory default +# 800 x 600 (75Hz) +#startmode +#mode_name:800 x 600 +#x_res:800 +#y_res:600 +#pixel_rate:49500 +#h_timings:80,92,42,800,42,0 +# VESA:80,160,0,800,0,16 +#v_timings:3,21,0,600,0,1 +#sync_pol:0 +#endmode + +# 1024 x 768 (60Hz) +startmode +mode_name:1024 x 768 +x_res:1024 +y_res:768 +pixel_rate:65000 +h_timings:136,64,60,1024,60,0 +# VESA:136,160,0,1024,0,24 +v_timings:6,29,0,768,0,3 +sync_pol:0 +endmode + +# 1024 x 768 (70Hz) +startmode +mode_name:1024 x 768 +x_res:1024 +y_res:768 +pixel_rate:75000 +h_timings:124,36,72,1024,72,0 +# VESA:136,144,0,1024,0,24 +v_timings:6,29,0,768,0,3 +sync_pol:0 +endmode + +# this has been removed so that it does not get selected for the 16 colour +# version. 70Hz 1024x768 is a build in setting, 75Hz ain't ! +# 1024 x 768 (75Hz) +#startmode +#mode_name:1024 x 768 +#x_res:1024 +#y_res:768 +#pixel_rate:80310 +# VESA:78750 +#h_timings:122,86,30,1024,76,0 +# VESA: 96,176,0,1024,0,16 +#v_timings:3,28,0,768,0,1 +#sync_pol:0 +#endmode + +# 1152 x 900 (53Hz) +startmode +mode_name:1152 x 900 +x_res:1152 +y_res:900 +pixel_rate:76000 +h_timings:152,64,60,1152,100,0 +v_timings:6,29,0,900,0,3 +sync_pol:3 +endmode + +# 1152 x 900 (76Hz) +startmode +mode_name:1152 x 900 +x_res:1152 +y_res:900 +pixel_rate:117000 +h_timings:170,96,96,1152,104,12 +v_timings:3,33,0,900,0,3 +sync_pol:3 +endmode + +# 1280 x 1024 (60Hz) +startmode +mode_name:1280 x 1024 +x_res:1280 +y_res:1024 +pixel_rate:110000 +h_timings:166,90,96,1280,96,0 +#h_timings:128,256,0,1280,0,64 +v_timings:3,32,0,1024,0,3 +sync_pol:0 +endmode + +# The taxan has a 70Hz 1280 x 768 build in just got to find it. +# 1280 x 1024 (70Hz) +startmode +mode_name:1280 x 1024 +x_res:1280 +y_res:1024 +pixel_rate:128000 +h_timings:160,88,96,1280,96,0 +#h_timings:166,90,96,1280,96,0 +#h_timings:128,256,0,1280,0,64 +v_timings:3,32,0,1024,0,3 +sync_pol:0 +endmode + +# Pixel-doubled modes + +# 1280 x 480 (60Hz) +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:50350 +h_timings:188,44,44,1280,44,0 +v_timings:2,32,0,480,0,11 +sync_pol:3 +endmode + +# 1280 x 480 (72Hz) +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:63000 +h_timings:96,172,58,1280,58,0 +# VESA:80,256,0,1280,0,48 +v_timings:3,28,0,480,0,9 +sync_pol:3 +endmode + +# 1280 x 480 (75Hz) +startmode +mode_name:1280 x 480 +x_res:1280 +y_res:480 +pixel_rate:63000 +h_timings:128,156,58,1280,58,0 +# VESA:128,240,0,1280,0,32 +v_timings:3,16,0,480,0,1 +sync_pol:3 +endmode + +# 1600 x 600 (56Hz) +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:72000 +h_timings:144,168,68,1600,68,0 +v_timings:2,22,0,600,0,1 +sync_pol:0 +endmode + +# 1600 x 600 (60Hz) +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:80000 +h_timings:256,98,78,1600,78,2 +# VESA:256,176, 0,1600,0,80 +v_timings:4,23,0,600,0,1 +sync_pol:0 +endmode + +# 1600 x 600 (72Hz) +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:100000 +h_timings:226,58,84,1600,84,28 +# VESA:240,128, 0,1600,0,112 +v_timings:6,23,0,600,0,37 +sync_pol:0 +endmode + +# 1600 x 600 (75Hz) +startmode +mode_name:1600 x 600 +x_res:1600 +y_res:600 +pixel_rate:99000 +h_timings:160,188,82,1600,82,0 +# VESA:160,320,0,1600,0,32 +v_timings:3,21,0,600,0,1 +sync_pol:0 +endmode + diff --git a/sys/arch/arm32/conf/std.arm32 b/sys/arch/arm32/conf/std.arm32 new file mode 100644 index 00000000000..053df992201 --- /dev/null +++ b/sys/arch/arm32/conf/std.arm32 @@ -0,0 +1,5 @@ +# standard NetBSD/arm32 options + +machine arm32 + +options MACHINE_NONCONTIG # temporary kludge diff --git a/sys/arch/arm32/dev/console/console.c b/sys/arch/arm32/dev/console/console.c new file mode 100644 index 00000000000..6d0b1db5044 --- /dev/null +++ b/sys/arch/arm32/dev/console/console.c @@ -0,0 +1,1219 @@ +/* $NetBSD: console.c,v 1.6 1996/04/19 20:03:37 mark Exp $ */ + +/* + * Copyright (c) 1994-1995 Melvyn Tang-Richardson + * Copyright (c) 1994-1995 RiscBSD kernel team + * 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 kernel team + * 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 RISCBSD TEAM ``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 AUTHORS 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 + * + * console.c + * + * Console functions + * + * Created : 17/09/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "vt.h" + +#define CONSOLE_VERSION "[V203C] " + +/* + * Externals + */ + +extern struct tty *constty; +extern int debug_flags; +#define consmap_col(x) (x & 0x3) +#define CONSMAP_BOLD 8 +#define CONSMAP_ITALIC 16 + +/* + * Local variables (to this file) + */ + +int locked=0; /* Nut - is this really safe ? */ +struct tty *physcon_tty[NVT]; +struct vconsole vconsole_master_store; +struct vconsole *vconsole_master = &vconsole_master_store; +struct vconsole *vconsole_current; +struct vconsole *vconsole_head; +struct vconsole *vconsole_default; +struct cfdriver rpc_cd; +extern struct vconsole *debug_vc; /* rename this to vconsole_debug */ +int physcon_major=4; +static char undefined_string[] = "UNDEFINED"; +int lastconsole; +static int printing=0; +static int want_switch=-1; + +/* + * Prototypes + */ + +int physcon_switch __P((u_int /*number*/)); +void physconstart __P((struct tty */*tp*/)); +static struct vconsole *vconsole_spawn __P((dev_t , struct vconsole *)); +int physconparam __P((struct tty */*tp*/, struct termios */*t*/)); +void consinit __P((void)); +int physcon_switchup __P((void)); +int physcon_switchdown __P((void)); + +/* + * Exported variables + */ + +#define BLANKINIT (10*60*60) +int vconsole_pending=0; +int vconsole_blankinit=BLANKINIT; +int vconsole_blankcounter=BLANKINIT; + +/* + * Now list all my render engines and terminal emulators + */ + +extern struct render_engine vidcconsole; +extern struct terminal_emulator vt220; + +/* + * These find functions should move the console it finds to the top of + * the list to achieve a caching type of operation. A doubly + * linked list would be faster methinks. + */ + +struct tty * +find_tp(dev) + dev_t dev; +{ + struct vconsole *vc; + struct vconsole *last=0; + int unit = minor (dev); + int s; + + s = spltty(); + for (vc=vconsole_head; vc != NULL; vc=vc->next) { + if (vc->number==unit) { + if (vc != vconsole_head) { + last->next = vc->next; + vc->next = vconsole_head; + vconsole_head = vc; + } + (void)splx(s); + return vc->tp; + } + last = vc; + } + (void)splx(s); + return NULL; +} + +struct vconsole * +find_vc(dev) + dev_t dev; +{ + struct vconsole *vc; + struct vconsole *last=NULL; + int unit = minor (dev); + int s; + + s = spltty(); + + for (vc=vconsole_head; vc!=NULL; vc=vc->next) { + if (vc->number==unit) { + if (vc!=vconsole_head) { + last->next = vc->next; + vc->next = vconsole_head; + vconsole_head = vc; + } + (void)splx(s); + return vc; + } + last=vc; + } + (void)splx(s); + return NULL; +} + +struct tty *console_tty = NULL; + +/* + * Place a graphics driver under virtual console switching control. + */ + +struct vconsole * +vconsole_spawn_re(dev, vc) + dev_t dev; + struct vconsole *vc; +{ + struct vconsole *new; + register int num = minor(dev); + + MALLOC(new, struct vconsole *, sizeof(struct vconsole), + M_DEVBUF,M_NOWAIT ); + + bzero ( (char *)new, sizeof(struct vconsole) ); + *new = *vc; + new->number = num; + new->next = vconsole_head; + new->tp = vc->tp; /* Implied */ + new->data=0; + new->t_scrolledback=0; + new->r_scrolledback=0; + new->r_data=0; + new->flags=LOSSY; + new->vtty = 0; + vconsole_head = new; + new->R_INIT ( new ); + new->SPAWN ( new ); + new->data = 0; + /*new->charmap = 0;*/ + new->flags=LOSSY; + new->proc = curproc; + new->vtty = 0; + return new; +} + +static struct vconsole * +vconsole_spawn(dev, vc) + dev_t dev; + struct vconsole *vc; +{ + struct vconsole *new; + register int num = minor(dev); + + if ( find_vc ( dev ) != 0 ) + return 0; + + MALLOC(new, struct vconsole *, sizeof(struct vconsole), + M_DEVBUF, M_NOWAIT ); + + bzero ( (char *)new, sizeof(struct vconsole) ); + *new = *vc; + new->number = num; + new->next = vconsole_head; + new->tp=NULL; + new->opened=0; + new->data=0; + new->t_scrolledback=0; + new->r_scrolledback=0; + new->r_data=0; + new->vtty = 1; + vconsole_head = new; + new->R_INIT ( new ); + new->FLASH ( new, 1 ); + new->CURSOR_FLASH ( new, 1 ); + new->SPAWN ( new ); + new->vtty = 1; + + MALLOC (new->charmap, int *, sizeof(int)*((new->xchars)*(new->ychars)), + M_DEVBUF, M_NOWAIT ); + + if (new->charmap==0) + return 0; + { + int counter=0; + for ( counter=0; counter<((new->xchars)*(new->ychars)); counter++ ) + (new->charmap)[counter]=' '; + } + new->TERM_INIT ( new ); + new->proc = curproc; + return new; +} + +void +vconsole_addcharmap(vc) + struct vconsole *vc; +{ + int counter=0; + + MALLOC (vc->charmap, int *, sizeof(int)*((vc->xchars)*(vc->ychars)), + M_DEVBUF, M_NOWAIT ); + for ( counter=0; counter<((vc->xchars)*(vc->ychars)); counter++ ) + (vc->charmap)[counter]=' '; +} + +int +physconopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct vconsole *new; + + struct vconsole *vc; + int unit = minor(dev); + int found=0; + int majorhack=0; + int ret; + + /* + * To allow the raw consoles a permanat hook for ioctls + * Spawning another virtual console will actuall configure it + */ + + if ( unit >= NVT ) { + if ( find_vc(dev)==0 ) + return ENXIO; + } +/* + if (unit >= rpc_cd.cd_ndevs || !rpc_cd.cd_devs[unit]) + return ENXIO; +*/ + + /* If this virtual console is the real virtual console and hasn't got */ + /* a charmap then to allocate it one. We can be sure addcharmap works */ + /* here since this is the open routine. This is incase the console */ + /* was initialised before the system was brought up */ + + if ((unit==0)&&(vconsole_master->charmap==0)) { + if (vconsole_master==vconsole_current) + majorhack=1; + vconsole_addcharmap ( vconsole_master ); + vconsole_master->flags &= ~LOSSY; + } + + /* Check to see if this console has already been spawned */ + + for ( vc = vconsole_head; vc!=NULL; vc=vc->next ) { + if ( vc->number == unit ) { + found=1; + break; + } + } + + /* Sanity check. If we have no default console, set it to the master one */ + + if ( vconsole_default==0 ) + vconsole_default = vconsole_master; + + /* Ensure we have a vconsole structure. Allocate one if we dont already */ + + if (found==0) + new = vconsole_spawn ( dev, vconsole_default ); + else + new = vc; + + new->proc = p; + + /* Initialise the terminal subsystem for this device */ + +#define TP (new->tp) + + if (TP == NULL) + TP = ttymalloc(); + + physcon_tty[unit] = TP; + + TP->t_oproc = physconstart; + TP->t_param = physconparam; + TP->t_dev = dev; + if ((TP->t_state & TS_ISOPEN) == 0) { + TP->t_state |= TS_WOPEN; + ttychars(TP); + TP->t_iflag = TTYDEF_IFLAG; + TP->t_oflag = TTYDEF_OFLAG; + TP->t_cflag = TTYDEF_CFLAG; + TP->t_lflag = TTYDEF_LFLAG; + TP->t_ispeed = TP->t_ospeed = TTYDEF_SPEED; + physconparam(TP, &TP->t_termios); + ttsetwater(TP); + } else if (TP->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) + return EBUSY; + TP->t_state |= TS_CARR_ON; + + new->opened=1; + + TP->t_winsize.ws_col = new->xchars; + TP->t_winsize.ws_row = new->ychars; + ret = ((*linesw[TP->t_line].l_open)(dev, TP)); + + if ( majorhack==1 ) { + struct vconsole *vc_store; + int counter; + int end; + int lines; + int xs; + + end = msgbufp->msg_bufx-1; + if (end>=MSG_BSIZE) end-=MSG_BSIZE; + + /* + * Try some cute things. Count the number of lines in the msgbuf + * then scroll the real screen up, just to fit the msgbuf on the + * screen, then sink all output, and spew the msgbuf to the + * new consoles charmap! + */ + + lines = 0; xs=0; + + for (counter=0;countermsg_bufc)+counter)==0x0a) { + if (xs>vc->xchars) lines++; + lines++; + xs=0; + } + } + + if ( lines < vc->ychars ) { + counter=vc->ycur; + while ( (counter--) > lines ) + new->PUTSTRING ( "\x0a", 1, new ); + } + + new->SLEEP(new); + + vc_store = vconsole_current; + vconsole_current = 0; /* !!! */ + + /* HAHA, cant do this */ + /* new->CLS ( new ); */ + + new->PUTSTRING ( "\x0c", 1, new ); + + /* + * Hmmm, I could really pass the whole damn thing to putstring + * since it doesn't have zeros, but I need to do the crlf + * conversion + */ + + xs=0; + + if ( end < 0 ) + panic ( "msgbuf trashed reboot and try again" ); + + for (counter=0;countermsg_bufc)+counter)==0x0a) { + new->PUTSTRING ( "\x0d", 1, new ); + xs=0; + } + if ( (xs++)xchars ) + new->PUTSTRING ((msgbufp->msg_bufc)+counter, 1, new ); + } + vconsole_master->ycur = lines; + vconsole_current = vc_store; + new->WAKE(new); + vconsole_current->xcur = 0; + + printf ( "\x0a" ); + } + + return(ret); +} + +/* + * int physconclose(dev_t dev, int flag, int mode, struct proc *p) + * + * Close the physical console + */ + +int +physconclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + register struct tty *tp; + + tp = find_tp ( dev ); + if (tp == NULL) { + printf("physconclose: tp=0 dev=%04x\n", dev); + return(ENXIO); + } + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + + return(0); +} + +int +physconread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + register struct tty *tp = find_tp ( dev ); + if (tp == NULL) { + printf("physconread: tp=0 dev=%04x\n", dev); + return(ENXIO); + } + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +physconwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + register struct tty *tp; + + tp = find_tp(dev); + + if (tp == NULL) { + printf("physconwrite: tp=0 dev=%04x\n", dev); + return(ENXIO); + } + + return((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +struct tty * +physcontty(dev) + dev_t dev; +{ + return(find_tp(dev)); +} + +int ioctlconsolebug; + +int +physconioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct vconsole vconsole_new; + struct tty *tp=(struct tty *)0xDEADDEAD ; + int error; + int s; + struct vconsole *vc = find_vc(dev); + + ioctlconsolebug = cmd; + + tp = find_tp(dev); + + if ((vc==0)||(tp==0)) + return ENXIO; + + switch ( cmd ) { + case CONSOLE_SWITCHUP: + physcon_switchup (); + return 0; + case CONSOLE_SWITCHDOWN: + physcon_switchdown (); + return 0; + case CONSOLE_SWITCHTO: + if (!physcon_switch ( *(int *)data )) + return 0; + else + return EINVAL; + case CONSOLE_SWITCHPREV: + physcon_switch ( lastconsole ); + return 0; + case CONSOLE_CREATE: + if ( vconsole_spawn ( makedev ( physcon_major, *(int *)data ), + vconsole_default ) == 0 ) + return ENOMEM; + else + return 0; + break; + + case CONSOLE_RENDERTYPE: + strncpy ( (char *)data, vc->T_NAME, 20 ); + return 0; + + case CONSOLE_TERMTYPE: + strncpy ( (char *)data, vc->T_NAME, 20 ); + return 0; + + case CONSOLE_LOCK: + s = spltty(); + locked++; + (void)splx(s); + return 0; + case CONSOLE_UNLOCK: + s = spltty(); + locked--; + if ( locked<0 ) + locked=0; + (void)splx(s); + return 0; + case CONSOLE_SPAWN_VIDC: +/* + vconsole_new = *vconsole_default; +*/ + vconsole_new = *vc; + vconsole_new.render_engine = &vidcconsole; + if ( vconsole_spawn_re ( + makedev ( physcon_major, *(int *)data ), + &vconsole_new ) == 0 ) + return ENOMEM; + else + return 0; + + case CONSOLE_GETVC: + { +/* struct vconsole *vc_p; + vc_p = find_vc(dev); + *(int *)data = vc_p->number;*/ + *(int *)data = vconsole_current->number; + return 0; + } + + case CONSOLE_CURSORFLASHRATE: + vc->CURSORFLASHRATE ( vc, *(int *)data ); + return 0; + + case CONSOLE_BLANKTIME: + vconsole_blankinit = *(int *)data; + return 0; + + case CONSOLE_DEBUGPRINT: + { + struct vconsole *vc_p; + + vc_p = find_vc(makedev(physcon_major,*(int*)data)); + if (vc_p==0) return EINVAL; + printf ( "DEBUGPRINT for console %d\n", *(int*)data ); + printf ( "flags %08x vtty %01x\n", vc_p->flags, vc_p->vtty ); + printf ( "TTY INFO - winsize (%d, %d)\n", + vc_p->tp->t_winsize.ws_col, + vc_p->tp->t_winsize.ws_row); + vc_p->R_DEBUGPRINT ( vc_p ); + vc_p->T_DEBUGPRINT ( vc_p ); + return 0; + } + + default: + error = vc->IOCTL ( vc, dev, cmd, data, flag, p ); + if ( error >=0 ) + return error; + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return error; + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return error; + } + return(ENOTTY); +} + +int +physconmmap(dev, offset, nprot) + dev_t dev; + int offset; + int nprot; +{ + struct vconsole *vc = find_vc(dev); + u_int physaddr; + + if (minor(dev) < 64) { + log(LOG_WARNING, "You should no longer use ttyv to mmap a frame buffer\n"); + log(LOG_WARNING, "For vidc use /dev/vidcvideo0\n"); + } + physaddr = vc->MMAP(vc, offset, nprot); + return(physaddr); +} + +/* + * Perform output on specified tty stream + */ + +void +physconstart(tp) + struct tty *tp; +{ + int s, len; + struct clist *cl; + struct vconsole *vc; + u_char buf[128]; + + s = spltty(); + + vc = find_vc ( tp->t_dev ); + + /* Are we ready to perform output */ + + if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { + (void)splx(s); + return; + } + + tp->t_state |= TS_BUSY; + + /* Fill our buffer with the data to print */ + + cl = &tp->t_outq; + + if ( vc->r_scrolledback ) vc->R_SCROLLBACKEND ( vc ); + if ( vc->t_scrolledback ) vc->T_SCROLLBACKEND ( vc ); + + (void)splx(s); + + /* Apparently we do this out of spl since it _IS_ fairly expensive */ + /* and it stops the serial ports overflowing */ + + while ( (len = q_to_b(cl, buf, 128)) ) { + if ( vc!=NULL ) + vc->PUTSTRING(buf, len, vc); + } + + s = spltty (); + + tp->t_state &= ~TS_BUSY; + + if (cl->c_cc) { + tp->t_state |= TS_TIMEOUT; + timeout(ttrstrt, tp, 1); + } + + if (cl->c_cc <= tp->t_lowat) { + if (tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup(cl); + } + selwakeup(&tp->t_wsel); + } + + if ( want_switch != -1 ) { + physcon_switch ( want_switch ); + want_switch=-1; + } + + (void)splx(s); +} + +int +physconparam(tp, t) + struct tty *tp; + struct termios *t; +{ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + return(0); +} + +void +physconstop(tp, flag) + struct tty *tp; + int flag; +{ + /* Nothing necessary */ +} + +int +physconkbd(key) + int key; +{ + char *string; + register struct tty *tp; + int s; + + s = spltty(); + + tp = vconsole_current->tp; + + if (tp == NULL) return(1); + + if ((tp->t_state & TS_ISOPEN) == 0) { + (void)splx(s); + return(1); + } + + if (key < 0x100) + (*linesw[tp->t_line].l_rint)(key, tp); + else { + switch (key) { + case 0x100: + string = "\x1b[A"; + break; + case 0x101: + string = "\x1b[B"; + break; + case 0x102: + string = "\x1b[D"; + break; + case 0x103: + string = "\x1b[C"; + break; + case 0x104: + string = "\x1b[6~"; + break; + case 0x105: + string = "\x1b[5~"; + break; + case 0x108: + string = "\x1b[2~"; + break; + case 0x109: + string = "\x7f"; + break; + default: + string = ""; + break; + } + while (*string != 0) { + (*linesw[tp->t_line].l_rint)(*string, tp); + ++string; + } + } + (void)splx(s); + return(0); +} + +static int physconinit_called = 0; + +void +physconinit(cp) + struct consdev *cp; +{ + int *test; + int counter; + + /* + * Incase we're called more than once. All routines below here + * undergo once time initialisation + */ + + if ( physconinit_called ) + return; + + physconinit_called=1; + + locked=0; + + physcon_major = major ( cp->cn_dev ); + + /* + * Create the master console + */ + + vconsole_master->next = NULL; + vconsole_master->number = 0; + vconsole_master->opened = 1; + vconsole_master->tp = NULL; + + /* + * Right, here I can choose some render routines + */ + + vconsole_master->render_engine = &vidcconsole; + vconsole_master->terminal_emulator = &vt220; + + /* + * We will very soon loose the master console, and number 0 will + * become the current console so as not to waste a struct vconsole + */ + vconsole_current = vconsole_head = vconsole_master; + vconsole_master->data = NULL; + vconsole_master->vtty = 1; + + /* + * Perform initial checking + */ + + if ( vconsole_master->terminal_emulator->name == 0 ) + vconsole_master->terminal_emulator->name = undefined_string; + if ( vconsole_master->render_engine->name == 0 ) + vconsole_master->render_engine->name = undefined_string; + + /* + * Right, I have to assume the init and print procedures are ok + * or there's nothing else that can be done + */ + + vconsole_master->R_INIT ( vconsole_master); + vconsole_master->SPAWN ( vconsole_master ); + vconsole_master->TERM_INIT (vconsole_master); + vconsole_master->flags = LOSSY; + + /* + * Now I can do some productive verification + */ + + /* Ensure there are no zeros in the termulation and render_engine */ + + test = (int *) vconsole_master->render_engine; + for ( counter=0; counter<(sizeof(struct render_engine)/4)-1; counter++ ) + if (test[counter]==0) + panic ( "Render engine %i is missins a routine", + vconsole_master->render_engine->name ); + + test = (int *) vconsole_master->terminal_emulator; + for ( counter=0; counter<(sizeof(struct terminal_emulator)/4)-1; counter++ ) + if (test[counter]==0) + panic ( "Render engine %i is missing a routine", + vconsole_master->terminal_emulator->name ); +} + +/* + * void physconputstring(char *string, int length) + * + * Render a string on the physical console + */ + +void +physconputstring(string, length) + char *string; + int length; +{ + vconsole_current->PUTSTRING(string, length, vconsole_current); +} + +/* + * void physcongetchar(void) + * + * Get a character from the physical console + */ + +int getkey_polled __P(()); + +char +physcongetchar(void) +{ + return(getkey_polled()); +} + +void +consinit(void) +{ + static int consinit_called = 0; + + if (consinit_called != 0) + return; + + consinit_called = 1; + cninit(); + +/* Ok get our start up message in early ! */ + + printf("\x0cRiscBSD booting...\n%s\n", version); +} + +void +rpcconsolecnprobe(cp) + struct consdev *cp; +{ + int major; + +/* printf("rpcconsoleprobe: pc=%08x\n", cp);*/ + +/* + * Locate the major number for the physical console device + * We do this by searching the character device list until we find + * the device with the open function for the physical console + */ + + for (major = 0; major < nchrdev; ++major) { + if (cdevsw[major].d_open == physconopen) + break; + } + +/* Initialise the required fields */ + + cp->cn_dev = makedev(major, 0); + cp->cn_pri = CN_INTERNAL; +} + +#define RPC_BUF_LEN (64) +char rpc_buf[RPC_BUF_LEN]; +int rpc_buf_ptr = 0; + +#define RPC_BUF_FLUSH \ +{ \ + vconsole_current->PUTSTRING ( rpc_buf, rpc_buf_ptr, vconsole_current ); \ + rpc_buf_ptr=0; \ +} + +void +rpcconsolecninit(cp) + struct consdev *cp; +{ + physconinit(cp); /* woo Woo WOO!!!, woo, woo, yes ok bye */ +} + +void +rpcconsolecnputc(dev, character) + dev_t dev; + char character; +{ + extern int cold; + + if (( rpc_buf_ptr==RPC_BUF_LEN ) || (cold==0) ) + RPC_BUF_FLUSH + + rpc_buf[rpc_buf_ptr++] = character; + + if ((character == 0x0a )||(character==0x0d)||(character=='.')) + RPC_BUF_FLUSH +} + +int +console_switchdown() +{ + physcon_switchdown (); + return 0; +} + +int +console_switchup() +{ + physcon_switchup (); + return 0; +} + +int +console_unblank() +{ + vconsole_blankcounter = vconsole_blankinit; + vconsole_current->BLANK ( vconsole_current, BLANK_NONE ); + return 0; +} + +int +console_scrollback () +{ + if (vconsole_current==NULL) + return 0; + if ( vconsole_current->R_SCROLLBACK(vconsole_current) ==-1 ) { + if ( vconsole_current->T_SCROLLBACK(vconsole_current)==-1 ) { + } + } + return 0; +} + +int +console_scrollforward () +{ + if (vconsole_current==NULL) + return 0; + if ( vconsole_current->R_SCROLLFORWARD(vconsole_current) ==-1 ) { + if ( vconsole_current->T_SCROLLFORWARD(vconsole_current)==-1 ) { + } + } + return 0; +} + +int +console_switchlast () +{ + return (physcon_switch ( lastconsole )); +} + +int +physcon_switchdown () +{ + int start; + int next = (vconsole_current->number); + start=next; + do { + next--; + next = next&0xff; + if (next==start) return 0; + } while (physcon_switch ( next )); + return 0; +} + +int +physcon_switchup () +{ + int start; + int next = (vconsole_current->number); + start=next; + do { + next++; + next = next&0xff; + if (next==start) return 0; + } while (physcon_switch ( next )); + return 0; +} + +void +console_switch(number) + u_int number; +{ + physcon_switch ( number ); +} + +/* switchto */ +int +physcon_switch(number) + u_int number; +{ + register struct vconsole *vc; + int s = spltty (); + int ret; + + if ( locked!=0 ) { + ret=0; + goto out; + } + + if ( printing ) { + want_switch = number; + ret=0; + goto out; + } + + vc = find_vc ( makedev ( physcon_major, number ) ); + + if ( vc==0 ) { + ret = 1; + goto out; + } + + if ( vc==vconsole_current ) { + ret = 1; + goto out; + } + + /* Point of no return */ + + locked++; /* We cannot reenter this routine now */ + + /* De-activate the render engine functions */ + if ( vconsole_current->vtty==1 ) { + vconsole_current->SLEEP(vconsole_current); + vconsole_current->FLASH ( vc, 0 ); + vconsole_current->CURSOR_FLASH ( vc, 0 ); + } + + /* Swap in the new consoles state */ + + lastconsole = vconsole_current->number; + vconsole_current=vc; + vconsole_current->R_SWAPIN ( vc ); + + /* Re-activate the render engine functions */ + + if ( vconsole_current->vtty==1 ) { + vconsole_current->T_SWAPIN ( vc ); + vconsole_current->WAKE(vconsole_current); + vconsole_current->FLASH ( vc, 1 ); + vconsole_current->CURSOR_FLASH ( vc, 1 ); + } + + locked--; + + /* Tell the process about the switch, like the X server */ + + if ( vc->proc ) + psignal ( vc->proc, SIGIO ); + + ret = 0; +out: + (void)splx(s); + return(ret); +} + +char +rpcconsolecngetc(dev) + dev_t dev; +{ + return( physcongetchar () ); +} + +void +rpcconsolecnpollc(dev, on) + dev_t dev; + int on; +{ + RPC_BUF_FLUSH +} + +int +rpcprobe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + return(1); +} + +void +rpcattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + printf(" riscbsd generic console driver %susing %s %s\n", + CONSOLE_VERSION, vconsole_master->terminal_emulator->name, + vconsole_master->render_engine->name); + + vconsole_master->T_ATTACH(vconsole_master, parent, self, aux); + vconsole_master->R_ATTACH(vconsole_master, parent, self, aux); +} + +/* +struct cfattach rpc_ca = { + sizeof(struct device), rpcprobe, rpcattach +}; + +struct cfdriver rpc_cd = { + NULL, "rpc", DV_TTY +}; +*/ + +struct cfattach vt_ca = { + sizeof(struct device), rpcprobe, rpcattach +}; + +struct cfdriver vt_cd = { + NULL, "rpc", DV_TTY +}; + +extern struct terminal_emulator vt220; + +struct render_engine *render_engine_tab[] = { + &vidcconsole, +}; + +struct terminal_emulator *terminal_emulator_tab[] = { + &vt220, +}; diff --git a/sys/arch/arm32/dev/console/debugconsole.c b/sys/arch/arm32/dev/console/debugconsole.c new file mode 100644 index 00000000000..2fc947b4c2c --- /dev/null +++ b/sys/arch/arm32/dev/console/debugconsole.c @@ -0,0 +1,88 @@ +/* $NetBSD: debugconsole.c,v 1.2 1996/03/18 19:33:04 mark Exp $ */ + +/* + * Copyright (c) 1994-1995 Melvyn Tang-Richardson + * Copyright (c) 1994-1995 RiscBSD kernel team + * 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 kernel team + * 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 RISCBSD TEAM ``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 AUTHORS 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 + * + * debugconsole.c + * + * Console functions + * + * Created : 17/09/94 + */ + +#ifdef DEBUGTERM + +#include +#include +#include +#include +#include + +#define TOTTY 0x02 + +/* + * This code allows the kernel developer to have a 'nice' virtual + * console for debugging information. + * + * It is more useful than say, printf since the output is + * + * a) isolated + * + */ + +struct vconsole *debug_vc=0; +struct tty *debug_tty=0; + +void +dprintf(fmt, va_alist) + char *fmt; +{ + if ( debug_vc==0 ) + return; + + dumb_putstring ( fmt, strlen(fmt), debug_vc ); +/* + va_list *ap; + + if ( debug_tty == NULL ) + return; + + va_start(ap, fmt); + kprintf(fmt, TOTTY, debug_tty, ap); + va_end(ap); +*/ +} + +#endif + diff --git a/sys/arch/arm32/dev/console/dumb.c b/sys/arch/arm32/dev/console/dumb.c new file mode 100644 index 00000000000..40396cbf70b --- /dev/null +++ b/sys/arch/arm32/dev/console/dumb.c @@ -0,0 +1,146 @@ +/* $NetBSD: dumb.c,v 1.2 1996/03/18 19:33:05 mark Exp $ */ + +/* + * Copyright (c) 1994-1995 Melvyn Tang-Richardson + * Copyright (c) 1994-1995 RiscBSD kernel team + * 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 kernel team + * 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 RISCBSD TEAM ``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 AUTHORS 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 + * + * dumb.c + * + * Console functions + * + * Created : 17/09/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TERMTYPE_PUTSTRING dumb_putstring +#define TERMTYPE_INIT dumb_init + +int +TERMTYPE_INIT(vc) + struct vconsole *vc; +{ + /* This dumb termial is so dumb it requires very little init */ + return 0; +} + +static void +do_scrollup(vc) + struct vconsole *vc; +{ + + if (vc==vconsole_current) + vc->SCROLLUP ( vc, 0, vc->ychars-1 ); + + vc->ycur=vc->ychars-1; + + if ( ((vc->flags)&(LOSSY)) == 0 ) { + int counter; + for ( counter=vc->xchars; counter < ((vc->ychars)*(vc->xchars)); counter++ ) { + vc->charmap[counter-vc->xchars] = vc->charmap[counter]; + } + for ( counter=vc->xchars*(vc->ychars-1); counter < (vc->xchars*vc->ychars); counter++ ) { + vc->charmap[counter]=0x20; + } + } +} + +static int +do_render(c, vc) + char c; + struct vconsole *vc; +{ + /* THE RENDER STAGE **********************************/ + if ((c>=0x20)&&(c<=0x7f)) { + if (((vc->flags)&(LOSSY))==0) { + vc->charmap[ vc->xcur + vc->ycur*vc->xchars ] = c | 7<<8; + } + + if ( vc==vconsole_current ) + vc->RENDER ( vc, c ); + + vc->xcur++; + } + + if ( vc->xcur >= vc->xchars ) { + vc->xcur=0; + vc->ycur++; + } + + if ( vc->ycur >= vc->ychars ) { + do_scrollup ( vc ); + vc->xcur=0; + vc->ycur=vc->ychars-1; + } +} + +int +TERMTYPE_PUTSTRING(string, length, vc) + char *string; + int length; + struct vconsole *vc; +{ + char c; + + while ( ((c=*(string++))!=0) && ((length--)>0)) { + if ((c<31)||(c>127)) c='*'; + switch (c) { + case 0x0a: + vc->ycur++; + if ( vc->ycur>=vc->ychars ) { + do_scrollup ( vc ); + vc->ycur=vc->ychars-1; + } + break; + + case 0x0d: + vc->xcur=0; + break; + + default: + do_render ( c, vc ); + break; + } + } +} diff --git a/sys/arch/arm32/dev/console/fonts/font_bold.h b/sys/arch/arm32/dev/console/fonts/font_bold.h new file mode 100644 index 00000000000..7aa9f189cc3 --- /dev/null +++ b/sys/arch/arm32/dev/console/fonts/font_bold.h @@ -0,0 +1,265 @@ +/* $NetBSD: font_bold.h,v 1.1 1996/01/31 23:20:07 mark 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 + * + * font_terminal14_bold.h + * + * Font for physical console driver + * + * Created : 18/09/94 + * Last updated : 15/10/94 + * + * Based on kate/display/14bold.h + * + * $Id: font_bold.h,v 1.1.1.1 1996/04/24 11:08:37 deraadt Exp $ + */ + +unsigned char font_terminal_14bold_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x7e, 0x24, 0x7e, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x0c, 0x38, 0x60, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0x76, 0x3c, 0x30, 0x18, 0x78, 0xdc, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x34, 0x34, 0x98, 0x7c, 0x66, 0x66, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x66, 0x66, 0x66, 0x66, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x1a, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x70, 0x38, 0x1c, 0x0e, 0x66, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x38, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x70, 0x68, 0x64, 0x66, 0xfe, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x06, 0x06, 0x3e, 0x60, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x8e, 0xe6, 0xb6, 0xb6, 0xe6, 0x0e, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x76, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc6, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x6e, 0x6e, 0x76, 0x76, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x76, 0x3c, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x3e, 0x36, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x3e, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0x7c, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x60, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x0c, 0x3e, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xcc, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x46, 0x3e, 0x7c, 0x62, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3e, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x2c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x70, 0x38, 0x1c, 0x0e, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x30, 0x1c, 0x30, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x18, 0x18, 0x0c, 0x38, 0x0c, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x4c, 0x7e, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x36, 0x36, 0x76, 0x36, 0x36, 0x36, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xd6, 0xf6, 0x16, 0xd6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x66, 0x06, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x4c, 0x0c, 0x3e, 0x0c, 0x0c, 0xde, 0x7a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x42, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x66, 0x0e, 0x3c, 0x66, 0x66, 0x3c, 0x70, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0xc3, 0xdb, 0xcb, 0xcb, 0xdb, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x3c, 0x36, 0x3c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x7e, 0x81, 0x9d, 0xad, 0x9d, 0xad, 0x81, 0x7e, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x32, 0x30, 0x1c, 0x06, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x32, 0x18, 0x30, 0x32, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfe, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x5e, 0x5e, 0x5e, 0x5e, 0x5c, 0x58, 0x58, 0x58, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x1c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x36, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x0e, 0x8c, 0x4c, 0x3e, 0x10, 0x68, 0x74, 0x6a, 0xfd, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x0e, 0x8c, 0x4c, 0x3e, 0x10, 0x68, 0xd4, 0xc2, 0x61, 0x30, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x1e, 0x98, 0x4c, 0x38, 0x1e, 0x6c, 0x74, 0x6a, 0xfd, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x0c, 0x46, 0x66, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x5c, 0x3a, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x2c, 0x2c, 0x18, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x36, 0x36, 0x76, 0x3e, 0x36, 0x36, 0xf6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x10, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6c, 0x6c, 0x00, 0x7c, 0x0c, 0x0c, 0x3c, 0x0c, 0x0c, 0x0c, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1c, 0x2c, 0x4c, 0x4c, 0x5e, 0x4c, 0x2c, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x5c, 0x3a, 0x00, 0x66, 0x66, 0x6e, 0x6e, 0x76, 0x76, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x5c, 0x3a, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x78, 0x6c, 0x6c, 0x7c, 0x7c, 0x6c, 0x6c, 0x3c, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 0x3c, 0x6c, 0x6c, 0x3c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x66, 0x36, 0x66, 0x66, 0x66, 0x36, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x30, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x6c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x6e, 0x3c, 0x00, 0x3c, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xb2, 0xfc, 0x36, 0xb6, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x10, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x36, 0x36, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x1c, 0x30, 0x7c, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5c, 0x3a, 0x00, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5c, 0x3a, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x6c, 0x7c, 0x7c, 0x6c, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x3c, 0x6c, 0x6c, 0x6c, 0x6c, 0x3c, 0x0c, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +font_struct font_terminal_14bold = { + 199, + 1, + 16, + 8, + 16, + 8, + 16, + 3184, + font_terminal_14bold_data +}; + +/* End of font14bold.h */ diff --git a/sys/arch/arm32/dev/console/fonts/font_italic.h b/sys/arch/arm32/dev/console/fonts/font_italic.h new file mode 100644 index 00000000000..7abc07dab32 --- /dev/null +++ b/sys/arch/arm32/dev/console/fonts/font_italic.h @@ -0,0 +1,265 @@ +/* $NetBSD: font_italic.h,v 1.1 1996/01/31 23:20:13 mark 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 + * + * font_terminal14_italic.h + * + * Font for physical console driver + * + * Created : 18/09/94 + * Last updated : 15/10/94 + * + * Based on kate/display/14norm.h + * + * $Id: font_italic.h,v 1.1.1.1 1996/04/24 11:08:37 deraadt Exp $ + */ + +unsigned char font_terminal_14italic_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x18, 0x30, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x3a, 0x14, 0x10, 0x08, 0x28, 0x54, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x08, 0x54, 0x22, 0x22, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x38, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x28, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x3e, 0x42, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x72, 0x4a, 0x4a, 0x72, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x72, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x24, 0x14, 0x0c, 0x0c, 0x14, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0xaa, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x4a, 0x52, 0x3c, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3c, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x92, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc6, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1c, 0x22, 0x22, 0x1c, 0x02, 0x3c, 0x42, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x22, 0x12, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x92, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x4c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x3c, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x24, 0x18, 0x18, 0x24, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x42, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x08, 0x08, 0x10, 0x0c, 0x10, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x08, 0x30, 0x08, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x12, 0x12, 0x72, 0x12, 0x12, 0x12, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0xf2, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x24, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x14, 0x54, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x08, 0x08, 0x3c, 0x08, 0x8c, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x7c, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x44, 0x44, 0x38, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0xb2, 0x8a, 0x8a, 0xb2, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x1c, 0x12, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0x9a, 0xaa, 0x9a, 0xaa, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x08, 0x04, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x24, 0x12, 0x12, 0x6d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x2e, 0x2e, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x12, 0x0c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x48, 0x64, 0x52, 0xf8, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x68, 0x94, 0x42, 0x20, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x12, 0x08, 0x52, 0x2c, 0x50, 0x68, 0x54, 0xfa, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x08, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x4c, 0x32, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x18, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0x14, 0x72, 0x1e, 0x12, 0x12, 0xf2, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x10, 0x08, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x48, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x28, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x5c, 0x48, 0x48, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x4c, 0x32, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x4c, 0x32, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xbc, 0x42, 0x62, 0x52, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x08, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x26, 0x44, 0x44, 0x44, 0x34, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x44, 0x38, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x90, 0xfc, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x08, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x12, 0x0c, 0x0c, 0x12, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7c, 0x62, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x30, 0x10, 0x12, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x28, 0x10, 0x12, 0x0c, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +font_struct font_terminal_14italic = { + 199, + 1, + 16, + 8, + 16, + 8, + 16, + 3184, + font_terminal_14italic_data +}; + +/* End of font14norm.h */ diff --git a/sys/arch/arm32/dev/console/fonts/font_normal.h b/sys/arch/arm32/dev/console/fonts/font_normal.h new file mode 100644 index 00000000000..7a159a81aea --- /dev/null +++ b/sys/arch/arm32/dev/console/fonts/font_normal.h @@ -0,0 +1,265 @@ +/* $NetBSD: font_normal.h,v 1.1 1996/01/31 23:20:16 mark 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 + * + * font_terminal14_normal.h + * + * Font for physical console driver + * + * Created : 18/09/94 + * Last updated : 15/10/94 + * + * Based on kate/display/14norm.h + * + * $Id: font_normal.h,v 1.1.1.1 1996/04/24 11:08:38 deraadt Exp $ + */ + +unsigned char font_terminal_14normal_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x54, 0x18, 0x30, 0x54, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x3a, 0x14, 0x10, 0x08, 0x28, 0x54, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x08, 0x54, 0x22, 0x22, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x54, 0x38, 0x38, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x20, 0x18, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x38, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x28, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x3e, 0x42, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x72, 0x4a, 0x4a, 0x72, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x72, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x24, 0x14, 0x0c, 0x0c, 0x14, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0xc6, 0xaa, 0xaa, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x4a, 0x52, 0x3c, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x3c, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x92, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc6, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x5c, 0x62, 0x42, 0x42, 0x42, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x1c, 0x22, 0x22, 0x1c, 0x02, 0x3c, 0x42, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x22, 0x12, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x92, 0x92, 0x92, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x4c, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x3c, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x24, 0x18, 0x18, 0x24, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7c, 0x40, 0x42, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x08, 0x08, 0x10, 0x0c, 0x10, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x08, 0x30, 0x08, 0x10, 0x10, 0x10, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4c, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x12, 0x12, 0x72, 0x12, 0x12, 0x12, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x92, 0xf2, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x24, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x38, 0x54, 0x14, 0x54, 0x38, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x08, 0x08, 0x3c, 0x08, 0x8c, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x28, 0x7c, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x38, 0x44, 0x44, 0x38, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0xb2, 0x8a, 0x8a, 0xb2, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x1c, 0x12, 0x1c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x82, 0x9a, 0xaa, 0x9a, 0xaa, 0x82, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x08, 0x04, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x10, 0x20, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x24, 0x24, 0x12, 0x12, 0x6d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x2e, 0x2e, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x12, 0x12, 0x0c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x48, 0x64, 0x52, 0xf8, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x06, 0x44, 0x24, 0x1e, 0x68, 0x94, 0x42, 0x20, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x12, 0x08, 0x52, 0x2c, 0x50, 0x68, 0x54, 0xfa, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x08, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x08, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x4c, 0x32, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x24, 0x00, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x18, 0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x14, 0x14, 0x72, 0x1e, 0x12, 0x12, 0xf2, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3c, 0x10, 0x08, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x10, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x48, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x28, 0x00, 0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x10, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x28, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x48, 0x48, 0x48, 0x5c, 0x48, 0x48, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x4c, 0x32, 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x4c, 0x32, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xbc, 0x42, 0x62, 0x52, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x08, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x26, 0x44, 0x44, 0x44, 0x34, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x44, 0x38, 0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x90, 0xfc, 0x12, 0x92, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x42, 0x3c, 0x08, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x7e, 0x02, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0x18, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x12, 0x0c, 0x0c, 0x12, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x58, 0x34, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x7c, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7c, 0x62, 0x52, 0x4a, 0x46, 0x3e, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x30, 0x10, 0x12, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x28, 0x28, 0x00, 0xc6, 0x44, 0x44, 0x28, 0x28, 0x10, 0x12, 0x0c, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0x00, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a, 0x1c, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0xff, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x40, 0xff, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +font_struct font_terminal_14normal = { + 199, + 1, + 16, + 8, + 16, + 8, + 16, + 3184, + font_terminal_14normal_data +}; + +/* End of font14norm.h */ diff --git a/sys/arch/arm32/dev/console/fonts/font_wide.h b/sys/arch/arm32/dev/console/fonts/font_wide.h new file mode 100644 index 00000000000..c59c451670b --- /dev/null +++ b/sys/arch/arm32/dev/console/fonts/font_wide.h @@ -0,0 +1,259 @@ +/* $NetBSD: font_wide.h,v 1.1 1996/01/31 23:20:22 mark 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 + * + * font_terminal14_wide.h + * + * Font for physical console driver + * + * Created : 18/09/94 + * Last updated : 15/10/94 + * + * Based on kate/display/14widen.h + * + * $Id: font_wide.h,v 1.1.1.1 1996/04/24 11:08:38 deraadt Exp $ + */ + +unsigned char font_terminal_14widen_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x01, 0x98, 0x01, 0xfe, 0x07, 0x98, + 0x01, 0xfe, 0x07, 0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0xfc, 0x03, 0x66, 0x04, 0xfc, + 0x03, 0x60, 0x06, 0x66, 0x06, 0xfc, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x06, 0x44, 0x03, 0xb8, 0x01, 0xc0, + 0x00, 0x60, 0x00, 0xb0, 0x03, 0x58, 0x04, 0x8c, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0xf0, + 0x04, 0x8c, 0x05, 0x06, 0x03, 0x06, 0x03, 0xfc, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x66, 0x06, 0xf8, 0x01, 0xf8, + 0x01, 0x66, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, + 0x07, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, + 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0x80, + 0x03, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0xe0, + 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x01, 0xa0, 0x01, 0x90, + 0x01, 0x88, 0x01, 0x84, 0x01, 0xfe, 0x07, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x06, 0x00, 0x06, 0x00, 0xfe, + 0x03, 0x06, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x0c, 0x00, 0x06, 0x00, 0xfe, + 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x03, 0x80, 0x01, 0xc0, + 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0xfc, + 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0xfc, 0x07, 0x00, 0x06, 0x00, 0x03, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x30, + 0x00, 0x0c, 0x00, 0x30, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x30, 0x00, 0xc0, + 0x00, 0x00, 0x03, 0xc0, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x00, 0x06, 0xc0, + 0x03, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0xc6, 0x07, 0x66, + 0x06, 0x66, 0x06, 0xc6, 0x07, 0x06, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x0c, + 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0xfe, + 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0x06, + 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x0c, 0x00, 0x0c, 0x00, 0xfc, + 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x0c, 0x00, 0x0c, 0x00, 0x0c, + 0x00, 0xfc, 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0x06, + 0x00, 0x86, 0x07, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfe, + 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x86, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x86, 0x01, 0x66, 0x00, 0x1e, + 0x00, 0x1e, 0x00, 0x66, 0x00, 0x86, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, + 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0e, 0x07, 0x9e, 0x07, 0xf6, + 0x06, 0x66, 0x06, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0e, 0x06, 0x1e, 0x06, 0x36, + 0x06, 0x66, 0x06, 0xc6, 0x06, 0x86, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0xfe, 0x03, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x86, 0x07, 0xfc, 0x03, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0xfe, 0x03, 0x86, 0x01, 0x06, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, 0x06, 0x06, 0x00, 0xfc, + 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, + 0x06, 0x66, 0x06, 0xf6, 0x06, 0x9c, 0x03, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, + 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60, + 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xf0, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, + 0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, + 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf8, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x98, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, + 0x06, 0xfc, 0x07, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x03, 0x0e, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x0e, 0x06, 0xf6, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, + 0x06, 0x06, 0x00, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0xfc, 0x06, 0x06, + 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, + 0x06, 0xfe, 0x07, 0x06, 0x00, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x18, 0x00, 0x18, 0x00, 0xfe, + 0x03, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x07, 0x00, 0x06, 0x00, 0x03, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x03, 0x0e, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x78, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xf8, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x86, 0x01, 0x66, + 0x00, 0x1e, 0x00, 0x66, 0x00, 0x86, 0x01, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x03, 0x66, + 0x06, 0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x03, 0x0e, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x03, 0x0e, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x0e, 0x06, 0xf6, 0x03, 0x06, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x06, 0x06, + 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x06, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x03, 0x38, + 0x06, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x06, + 0x04, 0xfc, 0x03, 0x00, 0x06, 0x06, 0x06, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0xfe, 0x01, 0x18, + 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0xfc, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, + 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, + 0x06, 0x66, 0x06, 0x66, 0x06, 0xf6, 0x06, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x07, 0x98, + 0x01, 0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0e, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, + 0x06, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, + 0x07, 0xc0, 0x01, 0x70, 0x00, 0x1c, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x30, 0x00, 0x30, 0x00, 0x60, 0x00, 0x3c, + 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xe0, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, + 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x80, + 0x07, 0xc0, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x06, 0x66, 0x06, 0xc6, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x66, 0x00, 0x66, 0x00, 0xe6, + 0x01, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x66, +}; + +font_struct font_terminal_14widen = { + 193, + 2, + 13, + 12, + 13, + 12, + 13, + 5018, + font_terminal_14widen_data +}; + +/* End of font14widen.h */ diff --git a/sys/arch/arm32/dev/console/vidc.c b/sys/arch/arm32/dev/console/vidc.c new file mode 100644 index 00000000000..e289593fd56 --- /dev/null +++ b/sys/arch/arm32/dev/console/vidc.c @@ -0,0 +1,255 @@ +/* $NetBSD: vidc.c,v 1.2 1996/03/18 19:33:07 mark Exp $ */ + +/* + * Copyright (c) 1994-1995 Melvyn Tang-Richardson + * Copyright (c) 1994-1995 RiscBSD kernel team + * 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 kernel team + * 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 RISCBSD TEAM ``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 AUTHORS 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 + * + * vidc.c + * + * Old console ioctl declarations + * + * Created : 17/09/94 + */ + +#include +#include +#include + +/* VIDC STUFF */ + +/* + * A structure containing ALL the information required to restore + * the VIDC20 to any given state. ALL vidc transactions should + * go through these procedures, which record the vidc's state. + * it may be an idea to set the permissions of the vidc base address + * so we get a fault, so the fault routine can record the state but + * I guess that's not really necessary for the time being, since we + * can make the kernel more secure later on. Also, it is possible + * to write a routine to allow 'reading' of the vidc registers. + */ + +struct vidc_state vidc_lookup = { + { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 + }, + + VIDC_PALREG, + VIDC_BCOL, + VIDC_CP1 , + VIDC_CP2, + VIDC_CP3, + VIDC_HCR, + VIDC_HSWR, + VIDC_HBSR, + VIDC_HDSR, + VIDC_HDER, + VIDC_HBER, + VIDC_HCSR, + VIDC_HIR, + VIDC_VCR, + VIDC_VSWR, + VIDC_VBSR, + VIDC_VDSR, + VIDC_VDER, + VIDC_VBER, + VIDC_VCSR, + VIDC_VCER, + VIDC_EREG, + VIDC_FSYNREG, + VIDC_CONREG, + VIDC_DCTL +}; + +struct vidc_state vidc_current[1]; + +int +vidc_write(reg, value) + u_int reg; + int value; +{ + int counter; + + int *current; + int *tab; + + tab = (int *)&vidc_lookup; + current = (int *)vidc_current; + + /* End higly doddgy code */ +/* +WriteWord ( VIDC_BASE, reg | value ); +return 1; +*/ + + /* + * OK, the VIDC_PALETTE register is handled differently + * to the others on the VIDC, so take that into account here + */ + if (reg==VIDC_PALREG) { + vidc_current->palreg = 0; + WriteWord ( VIDC_BASE, reg | value ); + return 0; + } + + if (reg==VIDC_PALETTE) { + WriteWord ( VIDC_BASE, reg | value ); + vidc_current->palette[vidc_current->palreg] = value; + vidc_current->palreg++; + vidc_current->palreg = vidc_current->palreg & 0xff; + return 0; + } + + /* + * Undefine SAFER if you wish to speed things up (a little) + * although this means the function will assume things abou + * the structure of vidc_state. i.e. the first 256 words are + * the palette array + */ + +#define SAFER + +#ifdef SAFER +#define INITVALUE 0 +#else +#define INITVALUE 256 +#endif + + for ( counter=INITVALUE; counter<= sizeof(struct vidc_state); counter++ ) { + if ( reg==tab[counter] ) { + WriteWord ( VIDC_BASE, reg | value ); + current[counter] = value; + return 0; + } + } + return -1; +} + +void +vidc_setpalette(vidc) + struct vidc_state *vidc; +{ + int counter = 0; + + vidc_write(VIDC_PALREG, 0x00000000); + for (counter = 0; counter < 255; counter++) + vidc_write(VIDC_PALETTE, vidc->palette[counter]); +} + +void +vidc_setstate(vidc) + struct vidc_state *vidc; +{ + vidc_write ( VIDC_PALREG, vidc->palreg ); + vidc_write ( VIDC_BCOL, vidc->bcol ); + vidc_write ( VIDC_CP1, vidc->cp1 ); + vidc_write ( VIDC_CP2, vidc->cp2 ); + vidc_write ( VIDC_CP3, vidc->cp3 ); + vidc_write ( VIDC_HCR, vidc->hcr ); + vidc_write ( VIDC_HSWR, vidc->hswr ); + vidc_write ( VIDC_HBSR, vidc->hbsr ); + vidc_write ( VIDC_HDSR, vidc->hdsr ); + vidc_write ( VIDC_HDER, vidc->hder ); + vidc_write ( VIDC_HBER, vidc->hber ); + vidc_write ( VIDC_HCSR, vidc->hcsr ); + vidc_write ( VIDC_HIR, vidc->hir ); + vidc_write ( VIDC_VCR, vidc->vcr ); + vidc_write ( VIDC_VSWR, vidc->vswr ); + vidc_write ( VIDC_VBSR, vidc->vbsr ); + vidc_write ( VIDC_VDSR, vidc->vdsr ); + vidc_write ( VIDC_VDER, vidc->vder ); + vidc_write ( VIDC_VBER, vidc->vber ); + vidc_write ( VIDC_VCSR, vidc->vcsr ); + vidc_write ( VIDC_VCER, vidc->vcer ); +/* + * Right, dunno what to set these to yet, but let's keep RiscOS's + * ones for now, until the time is right to finish this code + */ + +/* vidc_write ( VIDC_EREG, vidc->ereg ); */ +/* vidc_write ( VIDC_FSYNREG, vidc->fsynreg ); */ +/* vidc_write ( VIDC_CONREG, vidc->conreg ); */ +/* vidc_write ( VIDC_DCTL, vidc->dctl ); */ + +} + + +void +vidc_getstate(vidc) + struct vidc_state *vidc; +{ + *vidc = *vidc_current; +} + +void +vidc_stdpalette() +{ + WriteWord(VIDC_BASE, VIDC_PALREG | 0x00000000); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL( 0, 0, 0)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 0, 0)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL( 0, 255, 0)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 0)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL( 0, 0, 255)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 0, 255)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL( 0, 255, 255)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 255)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 128, 128)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 128, 128)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 255, 128)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 128)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 128, 255)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 128, 255)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(128, 255, 255)); + WriteWord(VIDC_BASE, VIDC_PALETTE | VIDC_COL(255, 255, 255)); +} + +#if 0 +int +vidc_col(red, green, blue) + int red; + int green; + int blue; +{ + red = red & 0xFF; + green = green & 0xFF; + blue = blue & 0xFF; + + return ( (blue<<16) + (green<<8) + red ); +} + +#endif diff --git a/sys/arch/arm32/dev/console/vidc_mc.S b/sys/arch/arm32/dev/console/vidc_mc.S new file mode 100644 index 00000000000..d22ece5384a --- /dev/null +++ b/sys/arch/arm32/dev/console/vidc_mc.S @@ -0,0 +1,213 @@ +/* $NetBSD: vidc_mc.S,v 1.3 1996/03/18 19:33:08 mark Exp $ */ + +/* + * Copyright (c) 1994-1995 Melvyn Tang-Richardson + * Copyright (c) 1994-1995 RiscBSD kernel team + * 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 kernel team + * 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 RISCBSD TEAM ``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 AUTHORS 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 + * + * vidc_mc.S + * + * Console assembly functions + * + * Created : 17/09/94 + */ + +#include "assym.h" +#include + +lr .req r14 +pc .req r15 +sp .req r13 + +.text + .global _vidcconsole_loadtab +_vidcconsole_loadtab: + mov r0, r0 + ldmia r0!, { r2 } + ldmia r0!, { r2-r3 } + ldmia r0!, { r2-r4 } + ldmia r0!, { r2-r5 } + ldmia r0!, { r2-r6 } + ldmia r0!, { r2-r7 } + ldmia r0!, { r2-r8 } + ldmia r0!, { r2-r9 } + ldmia r0!, { r2-r10 } + ldmia r0!, { r2-r11 } + ldmia r0!, { r2-r12 } + ldmia r0!, { r2-r12, r14 } + + .global _vidcconsole_storetab +_vidcconsole_storetab: + mov r0, r0 + stmia r0!, { r2 } + stmia r0!, { r2-r3 } + stmia r0!, { r2-r4 } + stmia r0!, { r2-r5 } + stmia r0!, { r2-r6 } + stmia r0!, { r2-r7 } + stmia r0!, { r2-r8 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r10 } + stmia r0!, { r2-r11 } + stmia r0!, { r2-r12 } + stmia r0!, { r2-r12, r14 } + + .global _vidcconsole_pushtab +_vidcconsole_pushtab: + mov r0, r0 + stmfd r13!, { r0-r3 } + stmfd r13!, { r0-r7 } + stmfd r13!, { r0-r11 } + stmfd r13!, { r0-r14 } + + .global _vidcconsole_poptab +_vidcconsole_poptab: + mov r0, r0 + ldmfd r13!, { r0-r3 } + ldmfd r13!, { r0-r7 } + ldmfd r13!, { r0-r11 } + ldmfd r13!, { r0-r14 } + + .global _vidcconsole_enter +_vidcconsole_enter: + stmfd r13!, { r15 } + + .global _vidcconsole_exit +_vidcconsole_exit: + stmfd r13!, { r15 } + + .global _vidcconsolemc_render + + /* On entry r0 = addr */ + /* r1 = font */ + /* r2 = col */ + /* r3 = xres */ + + /* Optimise for 8x16 font */ + /* At the moment */ + +_vidcconsolemc_render: + + stmfd r13!, {r0-r9, lr} + + /* Generate colour mask */ + + mov r9, r2, lsr #16 + mov r4, r2, lsr #8 + and r9, r9, #0xff + and r4, r4, #0xff + and r2, r2, #0xff + + /* For each row (8 pixels) */ + +xloop: + ldrb r5, [r1], #1 + + mov r7, #0 + mov r8, #0 + +/* This loop will get *SOOOO* much faster with */ +/* the new algorithmn */ + tst r5, #8 + orrne r7, r2, r7, lsl #8 + orreq r7, r4, r7, lsl #8 + tst r5, #4 + orrne r7, r2, r7, lsl #8 + orreq r7, r4, r7, lsl #8 + tst r5, #2 + orrne r7, r2, r7, lsl #8 + orreq r7, r4, r7, lsl #8 + tst r5, #1 + orrne r7, r2, r7, lsl #8 + orreq r7, r4, r7, lsl #8 + tst r5, #0x80 + orrne r8, r2, r8, lsl #8 + orreq r8, r4, r8, lsl #8 + tst r5, #0x40 + orrne r8, r2, r8, lsl #8 + orreq r8, r4, r8, lsl #8 + tst r5, #0x20 + orrne r8, r2, r8, lsl #8 + orreq r8, r4, r8, lsl #8 + tst r5, #0x10 + orrne r8, r2, r8, lsl #8 + orreq r8, r4, r8, lsl #8 + + stmia r0, {r7, r8} + add r0, r0, r3 + + subs r9, r9, #1 + bne xloop + + ldmfd r13!, {r0-r9, pc} + + .global _vidcconsolemc_cls + + /* On entry r0 = start */ + /* r1 = end */ + /* r2 = col */ + + +_vidcconsolemc_cls: + stmfd r13!, {r0-r9, lr} + + mov r3, r2 + mov r4, r2 + mov r5, r2 + mov r6, r2 + mov r7, r2 + mov r8, r2 + mov r9, r2 + +loop: + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + stmia r0!, { r2-r9 } + + cmp r0, r1 + ble loop + + ldmfd r13!, {r0-r9, pc} + diff --git a/sys/arch/arm32/dev/console/vidcconsole.c b/sys/arch/arm32/dev/console/vidcconsole.c new file mode 100644 index 00000000000..bd8305e607e --- /dev/null +++ b/sys/arch/arm32/dev/console/vidcconsole.c @@ -0,0 +1,1818 @@ +/* $NetBSD: vidcconsole.c,v 1.7 1996/03/28 21:18:40 mark Exp $ */ + +/* + * Copyright (c) 1996 Robert Black + * Copyright (c) 1994-1995 Melvyn Tang-Richardson + * Copyright (c) 1994-1995 RiscBSD kernel team + * 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 kernel team + * 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 RISCBSD TEAM ``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 AUTHORS 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 + * + * vidcconsole.c + * + * Console assembly functions + * + * Created : 17/09/94 + * Last updated : 07/02/96 + */ + +/* woo */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#define BCOPY bcopy + +#ifndef DEBUGTERM +#define dprintf(x) ; +#endif + +/* Options ************************************/ +#define ACTIVITY_WARNING +#define SCREENBLANKER +#undef INVERSE_CONSOLE +/**********************************************/ + +/* Internal defines only **********************/ +#define DEVLOPING +#undef SELFTEST +#undef SILLIES +/**********************************************/ + +#ifdef SILLIES +#define PRETTYCURSOR +#endif + +extern int physcon_major; +extern struct vconsole *vconsole_default; + +extern videomemory_t videomemory; + +extern font_struct font_terminal_14normal; +extern font_struct font_terminal_14bold; +extern font_struct font_terminal_14italic; + +#define font_normal font_terminal_14normal +#define font_bold font_terminal_14bold +#define font_italic font_terminal_14italic + +#define VIDC_ENGINE_NAME "VIDC" +#define R_DATA ((struct vidc_info *)vc->r_data) +#define MODE (R_DATA->mode) + +static int cold_init = 0; + +extern struct vconsole *vconsole_master; +extern struct vconsole *vconsole_current; +static struct vidc_mode vidc_initialmode; +static struct vidc_mode *vidc_currentmode; + +unsigned int dispstart; +unsigned int dispsize; +unsigned int dispbase; +unsigned int dispend; +unsigned int ptov; +unsigned int transfersize; +unsigned int vmem_base; +unsigned int phys_base; +int flash; +int cursor_flash; +char *cursor_normal; +char *cursor_transparent; +int p_cursor_normal; +int p_cursor_transparent; + +/* Local function prototypes */ +static void vidcconsole_cls __P(( struct vconsole */*vc*/ )); +static int vidc_cursor_init __P(( struct vconsole */*vc*/ )); +static int vidcconsole_cursorintr __P(( struct vconsole */*vc*/ )); +int vidcconsole_flashintr __P(( struct vconsole */*vc*/ )); +static int vidcconsole_textpalette __P(( struct vconsole */*vc*/ )); +static void vidcconsole_render __P(( struct vconsole */*vc*/, char /*c*/ )); +static void vidcconsole_mode __P(( struct vconsole */*vc*/, struct vidc_mode */*mode*/ )); +int vidcconsole_flash __P(( struct vconsole */*vc*/, int /*flash*/ )); +int vidcconsole_cursorflash __P(( struct vconsole */*vc*/, int /*flash*/ )); +int vidcconsole_flash_go __P(( struct vconsole */*vc*/ )); +int vidcconsole_blank __P(( struct vconsole */*vc*/, int /*type*/ )); +void vidcconsole_putchar __P(( dev_t dev, char c, struct vconsole *vc)); +extern int vidcconsolemc_cls __P(( unsigned char *, unsigned char *, int )); + +void (*line_cpfunc) __P(( char *, char * )); + +/* + * This will be called while still in the mode that we were left + * in after exiting from riscos + */ + +static irqhandler_t cursor_ih; +irqhandler_t flash_ih; + + +#ifndef HARDCODEDMODES +/* The table of modes is separately compiled */ +extern struct vidc_mode vidcmodes[]; +#else /* HARDCODEDMODES */ +#ifdef RC7500 +static struct vidc_mode vidcmodes[] = { + {31500,/**/48, 84, 30, 640, 30, 0,/**/3, 28, 0, 480, 0, 9,/**/0,/**/3}, + {36000,/**/72, 84, 34, 800, 34, 0,/**/2, 22, 0, 600, 0, 1,/**/0,/**/3}, +}; +#else /* RC7500 */ +/* We have a hard compiled table of modes and a list of definable modes */ +static struct vidc_mode vidcmodes[] = { + {32500,/**/52, 64, 30, 640, 30, 14,/**/3, 28, 0, 480, 0, 9,/**/0,/**/3}, + {65000,/**/128, 36, 60, 1024, 60 ,36,/**/6, 29, 0, 768, 0, 3,/**/0,/**/3}, +}; +#endif /* RC7500 */ +#endif /* HARDCODEDMODES */ + +#ifdef RC7500 +struct vfreq { + u_int frqcon; + int freq; +}; + +static struct vfreq vfreq[] = { + { VIDFREQ_25_18, 25175}, + { VIDFREQ_25_18, 25180}, + { VIDFREQ_28_32, 28320}, + { VIDFREQ_31_50, 31500}, + { VIDFREQ_36_00, 36000}, + { VIDFREQ_40_00, 40000}, + { VIDFREQ_44_90, 44900}, + { VIDFREQ_50_00, 50000}, + { VIDFREQ_65_00, 65000}, + { VIDFREQ_72_00, 72000}, + { VIDFREQ_75_00, 75000}, + { VIDFREQ_77_00, 77000}, + { VIDFREQ_80_00, 80000}, + { VIDFREQ_94_50, 94500}, + { VIDFREQ_110_0, 110000}, + { VIDFREQ_120_0, 120000}, + { VIDFREQ_130_0, 130000} +}; + +#define NFREQ (sizeof (vfreq) / sizeof(struct vfreq)) +u_int vfreqcon = 0; +#else /* RC7500 */ + +struct fsyn { + int r, v, f; +}; + +static struct fsyn fsyn_pref[] = { + { 6, 2, 8000 }, + { 4, 2, 12000 }, + { 3, 2, 16000 }, + { 2, 2, 24000 }, + { 41, 43, 25171 }, + { 50, 59, 28320 }, + { 3, 4, 32000 }, + { 2, 3, 36000 }, + { 31, 58, 44903 }, + { 12, 35, 70000 }, + { 0, 0, 00000 } +}; +#endif /* RC7500 */ + +static inline int +mod ( int n ) +{ + if (n<0) return (-n); + else return n; +} + +static int +vidcconsole_coldinit(vc) + struct vconsole *vc; +{ + int found; + int loop; + + line_cpfunc = NULL; + + /* Do this first so it dont look messy */ + + vidc_write ( VIDC_CP1, 0x0 ); + vidc_write ( VIDC_CP2, 0x0 ); + vidc_write ( VIDC_CP3, 0x0 ); + + /* Try to determine the current mode */ + vidc_initialmode.hder = bootconfig.width+1; + vidc_initialmode.vder = bootconfig.height+1; +/* + vidc_initialmode.hder = 1024; + vidc_initialmode.vder = 768; +*/ + vidc_initialmode.bitsperpixel = 1 << bootconfig.bitsperpixel; + +/* Nut - should be using videomemory.vidm_vbase - mark */ + + dispbase = vmem_base = dispstart = bootconfig.display_start; + phys_base = videomemory.vidm_pbase; + +/* Nut - should be using videomemory.vidm_size - mark */ + +#ifdef RC7500 + dispsize = videomemory.vidm_size; + transfersize = 16; +#else /* RC7500 */ + dispsize = bootconfig.vram[0].pages * NBPG; + transfersize = dispsize >> 10; +#endif /* RC7500 */ + + ptov = dispbase - phys_base; + + dispend = dispstart+dispsize; + + vidc_currentmode = &vidcmodes[0]; + loop = 0; + found = 0; + + while (vidcmodes[loop].pixel_rate != 0) { + if (vidcmodes[loop].hder == (bootconfig.width + 1) + && vidcmodes[loop].vder == (bootconfig.height + 1) + && vidcmodes[loop].frame_rate == bootconfig.framerate) { + vidc_currentmode = &vidcmodes[loop]; + found = 1; + } + ++loop; + } + + if (!found) { + vidc_currentmode = &vidcmodes[0]; + loop = 0; + found = 0; + + while (vidcmodes[loop].pixel_rate != 0) { + if (vidcmodes[loop].hder == (bootconfig.width + 1) + && vidcmodes[loop].vder == (bootconfig.height + 1)) { + vidc_currentmode = &vidcmodes[loop]; + found = 1; + } + ++loop; + } + } + + /* vidc_currentmode = &vidcmodes[0];*/ + vidc_currentmode->bitsperpixel = 1 << bootconfig.bitsperpixel; + + R_DATA->flash = R_DATA->cursor_flash = 0; + + dispstart = dispbase; + dispend = dispstart+dispsize; + + WriteWord ( IOMD_VIDINIT, dispstart-ptov ); + WriteWord ( IOMD_VIDSTART, dispstart-ptov ); + WriteWord ( IOMD_VIDEND, (dispend-transfersize)-ptov ); + return 0; +} + +struct vidc_mode newmode; + +static const int bpp_mask_table[] = { + 0, /* 1bpp */ + 1, /* 2bpp */ + 2, /* 4bpp */ + 3, /* 8bpp */ + 4, /* 16bpp */ + 6 /* 32bpp */ +}; + +void +vidcconsole_mode(vc, mode) + struct vconsole *vc; + struct vidc_mode *mode; +{ + register int acc; + int bpp_mask; + int log_bpp; + int tmp_bpp; + +#ifndef RC7500 + int best_r, best_v, best_match; +#endif + +/* + * Find out what bit mask we need to or with the vidc20 control register + * in order to generate the desired number of bits per pixel. + * log_bpp is log base 2 of the number of bits per pixel. + */ + + tmp_bpp = mode->bitsperpixel; + if (tmp_bpp < 1 || tmp_bpp > 32) + tmp_bpp = 8; /* Set 8 bpp if we get asked for something silly */ + + for (log_bpp = 0; tmp_bpp != 1; tmp_bpp >>= 1) + log_bpp++; + + bpp_mask = bpp_mask_table[log_bpp]; + +/* + printf ( "res = (%d, %d) rate = %d\n", mode->hder, mode->vder, mode->pixel_rate ); +*/ + + newmode = *mode; + vidc_currentmode = &newmode; + +#ifdef RC7500 + { + int i; + int old, new; + u_int nfreq; + + old = vfreq[0].freq; + nfreq = vfreq[0].frqcon; + for (i = 0; i < (NFREQ - 1); i++) { + new = vfreq[i].freq - mode->pixel_rate; + if (new < 0) + new = -new; + if (new < old) { + nfreq = vfreq[i].frqcon; + old = new; + } + if (new == 0) + break; + } + nfreq |= (vfreqcon & 0xf0); + vfreqcon = nfreq; + } +#else /* RC7500 */ + /* Program the VCO Look up a preferred value before choosing one */ + { + int least_error = mod (fsyn_pref[0].f - vidc_currentmode->pixel_rate); + int counter; + best_r = fsyn_pref[0].r; + best_match = fsyn_pref[0].f; + best_v = fsyn_pref[0].v; + + /* Look up */ + + counter=0; + + while ( fsyn_pref[counter].r != 0 ) { + if (least_error > mod (fsyn_pref[counter].f - vidc_currentmode->pixel_rate)) { + best_match = fsyn_pref[counter].f; + least_error = mod (fsyn_pref[counter].f - vidc_currentmode->pixel_rate); + best_r = fsyn_pref[counter].r; + best_v = fsyn_pref[counter].v; + } + counter++; + } + + if ( least_error > 0) { /* Accuracy of 1000Hz */ + int r, v, f; + for ( v=63; v>0; v-- ) + for ( r=63; r>0; r-- ) { + f = (v * VIDC_FREF/1000) / r; + if (least_error >= mod (f - vidc_currentmode->pixel_rate)) { + best_match = f; + least_error = mod (f - vidc_currentmode->pixel_rate); + best_r = r; + best_v = v; + } + } + } + + if ( best_r>63 ) best_r=63; + if ( best_v>63 ) best_v=63; + if ( best_r<1 ) best_r= 1; + if ( best_v<1 ) best_v= 1; + + } +/* + printf ( "best_v = %d best_r = %d best_f = %d\n", best_v, best_r, best_match ); +*/ +#endif /* RC7500 */ + + if (vc==vconsole_current) { +#ifdef RC7500 + outb(FREQCON, vfreqcon); + /* + * Need to program the control register first. + */ + if ( dispsize>1024*1024 ) { + if ( vidc_currentmode->hder>=800 ) + vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5); + else + vidc_write ( VIDC_CONREG, 6<<8 | bpp_mask<<5); + } else { + vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5); + } + + /* + * We don't use VIDC_FSYNREG. Program it low. + */ + vidc_write(VIDC_FSYNREG, 0x2020); +#else /* RC7500 */ + vidc_write ( VIDC_FSYNREG, (best_v-1)<<8 | (best_r-1)<<0 ); +#endif /* RC7500 */ + acc=0; + acc+=vidc_currentmode->hswr;vidc_write(VIDC_HSWR,(acc - 8 )& (~1) ); + acc+=vidc_currentmode->hbsr;vidc_write(VIDC_HBSR,(acc - 12 )& (~1) ); + acc+=vidc_currentmode->hdsr;vidc_write(VIDC_HDSR,(acc - 18 )& (~1) ); + acc+=vidc_currentmode->hder;vidc_write(VIDC_HDER,(acc - 18 )& (~1) ); + acc+=vidc_currentmode->hber;vidc_write(VIDC_HBER,(acc - 12 )& (~1) ); + acc+=vidc_currentmode->hcr ;vidc_write(VIDC_HCR ,(acc - 8)&(~3)); + + acc=0; + acc+=vidc_currentmode->vswr; vidc_write(VIDC_VSWR,(acc - 1 )); + acc+=vidc_currentmode->vbsr; vidc_write(VIDC_VBSR,(acc - 1 )); + acc+=vidc_currentmode->vdsr; vidc_write(VIDC_VDSR,(acc - 1 )); + acc+=vidc_currentmode->vder; vidc_write(VIDC_VDER,(acc - 1 )); + acc+=vidc_currentmode->vber; vidc_write(VIDC_VBER,(acc - 1 )); + acc+=vidc_currentmode->vcr; vidc_write(VIDC_VCR ,(acc - 1 )); + + WriteWord(IOMD_FSIZE, vidc_currentmode->vcr + + vidc_currentmode->vswr + + vidc_currentmode->vber + + vidc_currentmode->vbsr - 1 ); + + if ( dispsize==1024*1024 ) + vidc_write ( VIDC_DCTL, vidc_currentmode->hder>>2 | 1<<16 | 1<<12); + else + vidc_write ( VIDC_DCTL, vidc_currentmode->hder>>2 | 3<<16 | 1<<12); + + vidc_write ( VIDC_EREG, 1<<12 ); + if ( dispsize>1024*1024) { + if ( vidc_currentmode->hder>=800 ) + vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5); + else + vidc_write ( VIDC_CONREG, 6<<8 | bpp_mask<<5); + } else { + vidc_write ( VIDC_CONREG, 7<<8 | bpp_mask<<5); + } + } + + R_DATA->mode = *vidc_currentmode; + R_DATA->screensize = R_DATA->XRES * R_DATA->YRES * R_DATA->BITSPERPIXEL/8; + R_DATA->pixelsperbyte = 8 / R_DATA->BITSPERPIXEL; + R_DATA->frontporch = MODE.hswr + MODE.hbsr + MODE.hdsr; + R_DATA->topporch = MODE.vswr + MODE.vbsr + MODE.vdsr; + R_DATA->bytes_per_line = R_DATA->XRES * + R_DATA->font->y_spacing/R_DATA->pixelsperbyte; + R_DATA->bytes_per_scroll = (vc->ycur % R_DATA->font->y_spacing) + * vc->xcur / R_DATA->pixelsperbyte; + R_DATA->text_width = R_DATA->XRES / R_DATA->font->x_spacing; + R_DATA->text_height = R_DATA->YRES / R_DATA->font->y_spacing; + vc->xchars = R_DATA->text_width; + vc->ychars = R_DATA->text_height; +} + +void +physcon_display_base(base) + u_int base; +{ + dispstart = dispstart-dispbase + base; + dispbase = vmem_base = base; + dispend = base + dispsize; + ptov = dispbase - phys_base; +} + +static struct vidc_info masterinfo; +static int cursor_init = 0; + +int +vidcconsole_init(vc) + struct vconsole *vc; +{ + struct vidc_info *new; + int loop; + + if ( cold_init==0 ) { + vidcconsole_coldinit ( vc ); + } else { + if ( cursor_init == 0 ) + vidcconsole_flash_go ( vc ); + } + + /* + * If vc->r_data is initialised then this means that the previous + * render engine on this vconsole was not freed properly. I should + * not try to clear it up, since I could panic the kernel. Instead + * I forget about its memory, which could cause a memory leak, but + * this would be easily detectable and fixable + */ + +#ifdef SELFTEST + if ( vc->r_data != 0 ) { + printf( "*********************************************************\n" ); + printf( "You have configured SELFTEST mode in the console driver\n" ); + printf( "vc->rdata non zero. This could mean a new console\n" ); + printf( "render engine has not freed up its data structure when\n" ); + printf( "exiting.\n" ); + printf( "DO NOT COMPILE NON DEVELOPMENT KERNELS WITH SELFTEST\n" ); + printf( "*********************************************************" ); + } +#endif + + if ( vc==vconsole_master ) { + vc->r_data = (char *)&masterinfo; + } else { + MALLOC ( (vc->r_data), char *, sizeof(struct vidc_info), + M_DEVBUF, M_NOWAIT ); + } + + if (vc->r_data==0) + panic ( "render engine initialisation failed. CLEAN THIS UP!" ); + + R_DATA->normalfont = &font_normal; + R_DATA->italicfont = &font_italic; + R_DATA->boldfont = &font_bold; + R_DATA->font = R_DATA->normalfont; + + vidcconsole_mode ( vc, vidc_currentmode ); + R_DATA->scrollback_end = dispstart; + + new = (struct vidc_info *)vc->r_data; + + R_DATA->text_colours = 1 << R_DATA->BITSPERPIXEL; + if ( R_DATA->text_colours > 8 ) R_DATA->text_colours = 8; + +#ifdef INVERSE_CONSOLE + R_DATA->n_backcolour = R_DATA->text_colours - 1; + R_DATA->n_forecolour = 0; +#else + R_DATA->n_backcolour = 0; + R_DATA->n_forecolour = R_DATA->text_colours - 1; +#endif + + R_DATA->backcolour = R_DATA->n_backcolour; + R_DATA->forecolour = R_DATA->n_forecolour; + + R_DATA->forefillcolour = 0; + R_DATA->backfillcolour = 0; + + R_DATA->bold = 0; + R_DATA->reverse = 0; + + for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) { + R_DATA->forefillcolour |= (R_DATA->forecolour << + loop * R_DATA->BITSPERPIXEL); + R_DATA->backfillcolour |= (R_DATA->backcolour << + loop * R_DATA->BITSPERPIXEL); + } + + R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16); + R_DATA->blanked=0; + vc->BLANK ( vc, BLANK_NONE ); + + if ( vc == vconsole_current ) + vidcconsole_textpalette ( vc ); + + vidc_cursor_init ( vc ) ; + + if ( cold_init == 0 ) { + vidc_write ( VIDC_CP1, 0x0 ); + vidc_write ( VIDC_CP2, 0x0 ); + vidc_write ( VIDC_CP3, 0x0 ); + } + cold_init=1; + return 0; +} + +void +vidcconsole_putchar(dev, c, vc) + dev_t dev; + char c; + struct vconsole *vc; +{ + vc->PUTSTRING ( &c, 1, vc ); +} + +int +vidcconsole_spawn(vc) + struct vconsole *vc; +{ + vc->xchars = R_DATA->text_width; + vc->ychars = R_DATA->text_height; + vc->xcur = 0; + vc->ycur = 0; + vc->flags = 0; + return 0; +} + +int +vidcconsole_redraw(vc, x, y, a, b) + struct vconsole *vc; + int x, y; + int a, b; +{ + int xs, ys; + struct vidc_state vidc; + font_struct *p_font = R_DATA->font; + int p_forecol = R_DATA->forecolour; + int p_backcol = R_DATA->backcolour; + if (x<0) x=0; + if (y<0) y=0; + if (x>(vc->xchars-1)) x=vc->xchars-1; + if (y>(vc->ychars-1)) x=vc->ychars-1; + + if (a>(vc->xchars-1)) a=vc->xchars-1; + if (b>(vc->ychars-1)) b=vc->ychars-1; + + if (axcur; + ys=vc->ycur; + + vc->xcur = 0; + vc->ycur = 0; + if ( (vc->flags&LOSSY) == 0 ) + { + register int c; + /* This has *GOT* to be turboed */ + for ( vc->ycur=y; vc->ycur<=b; vc->ycur++ ) + { + for ( vc->xcur=x; vc->xcur<=a; vc->xcur++ ) + { + c = (vc->charmap)[vc->xcur+vc->ycur*vc->xchars]; + if ((c&BOLD)!=0) + R_DATA->font = R_DATA->boldfont; + else + R_DATA->font = R_DATA->normalfont; +R_DATA->fast_render = ((c>>8)&0x7)|(((c>>11)&0x7)<<8)| (R_DATA->font->pixel_height<<16); +if ( c & BLINKING ) + c+=1<<8 | 1; + if ((c&BLINKING)!=0) + { + R_DATA->forecolour+=16; + R_DATA->backcolour+=16; + } + vidcconsole_render( vc, c&0xff ); + } + } + } + vc->xcur = xs; + vc->ycur = ys; + R_DATA->forecolour = p_forecol; + R_DATA->backcolour = p_backcol; + R_DATA->font = p_font; + return 0; +} + + +int +vidcconsole_swapin(vc) + struct vconsole *vc; +{ + register int counter; + int xs, ys; + struct vidc_state vidc; + font_struct *p_font = R_DATA->font; + int p_forecol = R_DATA->forecolour; + int p_backcol = R_DATA->backcolour; + +#ifdef ACTIVITY_WARNING + vconsole_pending = 0; +#endif + vidc_write ( VIDC_CP1, 0x0 ); + + vidc = *vidc_current; + vidc_write ( VIDC_PALREG, 0x00000000 ); + for ( counter=0; counter<255; counter++ ) + vidc_write ( VIDC_PALETTE, 0x00000000 ); + xs=vc->xcur; + ys=vc->ycur; +/*TODO This needs to be vidc_restore (something) */ + vidcconsole_mode ( vc, &MODE ); + + vc->xcur = 0; + vc->ycur = 0; + if ( (vc->flags&LOSSY) == 0 ) + { + register int c; + /* This has *GOT* to be turboed */ + for ( vc->ycur=0; vc->ycurychars; vc->ycur++ ) + { + for ( vc->xcur=0; vc->xcurxchars; vc->xcur++ ) + { + c = (vc->charmap)[vc->xcur+vc->ycur*vc->xchars]; + if ((c&BOLD)!=0) + R_DATA->font = R_DATA->boldfont; + else + R_DATA->font = R_DATA->normalfont; +/* + R_DATA->forecolour = ((c>>8)&0x7); + R_DATA->backcolour = ((c>>11)&0x7); +*/ +R_DATA->fast_render = ((c>>8)&0x7)|(((c>>11)&0x7)<<8)| (R_DATA->font->pixel_height<<16); +if ( c & BLINKING ) + c+=1<<8 | 1; + if ((c&BLINKING)!=0) + { + R_DATA->forecolour+=16; + R_DATA->backcolour+=16; + } + vidcconsole_render( vc, c&0xff ); + } + } + } + else + { + vc->CLS ( vc ); + } + + if ( vc->vtty==1 ) + { + vc->xcur = xs; + vc->ycur = ys; + vidcconsole_textpalette ( vc ); + vidc_write ( VIDC_CP1, 0xffffff ); + R_DATA->forecolour = p_forecol; + R_DATA->backcolour = p_backcol; + R_DATA->font = p_font; + } +/* Make the cursor blank */ + WriteWord(IOMD_CURSINIT,p_cursor_transparent); + return 0; + +} + +int +vidcconsole_mmap(vc, offset, nprot) + struct vconsole *vc; + int offset; + int nprot; +{ + if (offset > videomemory.vidm_size) + return (-1); + return(arm_byte_to_page(((videomemory.vidm_pbase) + (offset)))); +} + +extern void vidcconsolemc_render __P(( unsigned char *addr, unsigned char *fontaddr, + int fast_render, int xres )); + +void +vidcconsole_render(vc, c) + struct vconsole *vc; + char c; +{ + register unsigned char *fontaddr; + register unsigned char *addr; + + /* Calculate the font's address */ + + fontaddr = R_DATA->font->data + + ((c-(0x20)) * R_DATA->font->height + * R_DATA->font->width); + + addr = (unsigned char *)dispstart + + (vc->xcur * R_DATA->font->x_spacing) + + (vc->ycur * R_DATA->bytes_per_line); + + vidcconsolemc_render ( addr, fontaddr, R_DATA->fast_render, + R_DATA->XRES ); +} + +/* + * Uugh. vidc graphics dont support scrolling regions so we have to emulate + * it here. This would normally require much software scrolling which is + * horriblly slow, so I'm going to try and do a composite scroll, which + * causes problems for scrollback but it's less speed critical + */ + +void +vidcconsole_scrollup(vc, low, high) + struct vconsole *vc; + int low; + int high; +{ + unsigned char *start, *end; + + if ( ( low==0 ) && ( high==vc->ychars-1 )) + { + /* All hardware scroll */ + dispstart+=R_DATA->bytes_per_line; + if ( dispstart >= dispend ) + dispstart -= dispsize; + + high=high+1; /* Big hack */ + + WriteWord(IOMD_VIDINIT, dispstart - ptov ); + } + else + { + char *oldstart=(char *)dispstart; + + /* Composite scroll */ + + if ( (high-low) > (vc->ychars>>1) ) + { + /* Scroll region greater than half the screen */ + + dispstart+=R_DATA->bytes_per_line; + if ( dispstart >= dispend ) dispstart -= dispsize; + + WriteWord(IOMD_VIDINIT, dispstart - ptov ); + + if ( low!=0 ) + { + start = (unsigned char *)oldstart; + end=(unsigned char*)oldstart+((low+1) * R_DATA->bytes_per_line); + BCOPY ( start, start+R_DATA->bytes_per_line, + end-start-R_DATA->bytes_per_line); + } + + if ( high!=(vc->ychars-1) ) + { + start =(unsigned char *)dispstart+(high)*R_DATA->bytes_per_line; + end=(unsigned char*)dispstart+((vc->ychars)*R_DATA->bytes_per_line); + BCOPY ( start, start+R_DATA->bytes_per_line, + end-start-R_DATA->bytes_per_line); + } + high++; + } + else + { + /* Scroll region less than half the screen */ + + /* NO COMPOSITE SCROLL YET */ + + high++; + if (low<0) low=0; + if (high>(vc->ychars)) high=vc->ychars; + if (low>high) return; /* yuck */ + start = (unsigned char *)dispstart + ((low)*R_DATA->bytes_per_line); + end = (unsigned char *)dispstart + ((high)*R_DATA->bytes_per_line); + BCOPY ( start+R_DATA->bytes_per_line, start, + (end-start)-R_DATA->bytes_per_line ); + R_DATA->scrollback_end = dispstart; + } + } + memset ( (char *) dispstart + ((high-1)*R_DATA->bytes_per_line) , + R_DATA->backfillcolour, + R_DATA->bytes_per_line ); +} + +void +vidcconsole_scrolldown(vc, low, high) + struct vconsole *vc; + int low; + int high; +{ + unsigned char *start; + unsigned char *end; + + if ( low<0 ) low = 0; + if ( high>(vc->ychars-1) ) high=vc->ychars-1; + + if ( ( low==0 ) && ( high==vc->ychars-1 )) + { + dispstart-=R_DATA->bytes_per_line; + + if ( dispstart < dispbase ) + dispstart += dispsize; + + WriteWord(IOMD_VIDINIT, dispstart - ptov ); + } + else + { + if ( ((high-low) > (vc->ychars>>1)) ) + { +high--; + if (high!=(vc->ychars-1)) + { + start =(unsigned char*)dispstart+((high+1)*R_DATA->bytes_per_line); + end=(unsigned char*)dispstart+((vc->ychars)*R_DATA->bytes_per_line); + BCOPY ( start+R_DATA->bytes_per_line, start, + (end-start)-R_DATA->bytes_per_line ); + } + + dispstart-=R_DATA->bytes_per_line; + if ( dispstart < dispbase ) + dispstart += dispsize; + WriteWord(IOMD_VIDINIT, dispstart - ptov ); + start = (unsigned char *)dispstart + (low * R_DATA->bytes_per_line); + + if (low!=0) + { + end = (unsigned char *)dispstart + ((low+1)*R_DATA->bytes_per_line); + BCOPY ( (char*)(dispstart+R_DATA->bytes_per_line), + (char *)dispstart, + (int)((end-dispstart)-R_DATA->bytes_per_line )); + } + } + else + { + start = (unsigned char *)dispstart + (low * R_DATA->bytes_per_line); + end = (unsigned char *)dispstart + ((high+1) * R_DATA->bytes_per_line); + BCOPY ( start, start+R_DATA->bytes_per_line, end-start-R_DATA->bytes_per_line); + } + + } + memset ((char*) dispstart + (low*R_DATA->bytes_per_line) , + R_DATA->backfillcolour, R_DATA->bytes_per_line ); +} + +void +vidcconsole_cls(vc) + struct vconsole *vc; +{ +#ifdef RC7500 + dispstart = dispbase; + dispend = dispstart+dispsize; + + WriteWord ( IOMD_VIDINIT, dispstart-ptov ); + WriteWord ( IOMD_VIDSTART, dispstart-ptov ); + WriteWord ( IOMD_VIDEND, (dispend-transfersize)-ptov ); +#endif + + vidcconsolemc_cls ( (char *)dispstart, (char *)dispstart+R_DATA->screensize, R_DATA->backfillcolour ); + /* + memset((char *)dispstart, + R_DATA->backfillcolour, R_DATA->screensize); + */ + vc->xcur = vc->ycur = 0; +} + +void +vidcconsole_update(vc) + struct vconsole *vc; +{ +} + +static char vidcconsole_name[] = VIDC_ENGINE_NAME; + +static int scrollback_ptr = 0; + +int +vidcconsole_scrollback(vc) + struct vconsole *vc; +{ + int temp; + + if (scrollback_ptr==0) + scrollback_ptr=dispstart; + + temp = scrollback_ptr; + + scrollback_ptr-=R_DATA->bytes_per_line * (vc->ychars-2); + + if ( scrollback_ptr < dispbase ) + scrollback_ptr += dispsize; + + if ( (scrollback_ptr>dispstart)&& + (scrollback_ptr<(dispstart+R_DATA->screensize) ) ) + { + scrollback_ptr=temp; + return 0; + } + + vc->r_scrolledback = 1; + + WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov ); + return 0; +} + +int +vidcconsole_scrollforward(vc) + struct vconsole *vc; +{ + register int temp; + + if (scrollback_ptr==0) + return 0; + + temp = scrollback_ptr; + + scrollback_ptr+=R_DATA->bytes_per_line * (vc->ychars - 2); + + if ( scrollback_ptr >= dispend ) + scrollback_ptr -= dispsize; + + if ( scrollback_ptr == dispstart ) + { + WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov ); + scrollback_ptr=0; + vc->r_scrolledback = 0; + return 0; + } + + WriteWord(IOMD_VIDINIT, scrollback_ptr - ptov ); + return 0; +} + +int +vidcconsole_scrollbackend(vc) + struct vconsole *vc; +{ + scrollback_ptr = 0; + WriteWord(IOMD_VIDINIT, dispstart - ptov ); + vc->r_scrolledback = 0; + return 0; +} + +int +vidcconsole_clreos(vc, code) + struct vconsole *vc; + int code; +{ + char *addr; + char *endofscreen; + + addr = (unsigned char *)dispstart + + (vc->xcur * R_DATA->font->x_spacing) + + (vc->ycur * R_DATA->bytes_per_line); + + endofscreen = (unsigned char *)dispstart + + (vc->xchars * R_DATA->font->x_spacing) + + (vc->ychars * R_DATA->bytes_per_line); + + + switch (code) + { + case 0: + vidcconsolemc_cls ( addr, + (unsigned char *)dispend, + R_DATA->backfillcolour ); + if ((unsigned char *)endofscreen > (unsigned char *)dispend) { + char string[80]; + sprintf(string, "(addr=%08x eos=%08x dispend=%08x dispstart=%08x base=%08x)", + (u_int)addr, (u_int)endofscreen, dispend, dispstart, dispbase); + dprintf(string); + vidcconsolemc_cls((unsigned char *)dispbase, (unsigned char *)(dispbase + (endofscreen - dispend)), R_DATA->backfillcolour); + } + break; + + case 1: + vidcconsolemc_cls ( (unsigned char *)dispstart+R_DATA->screensize, + addr, + R_DATA->backfillcolour ); + break; + + case 2: + default: + vidcconsole_cls ( vc ); + break; + } + return 0; +} + +#define VIDC R_DATA->vidc + +int +vidcconsole_debugprint(vc) + struct vconsole *vc; +{ +#ifdef DEVLOPING + printf ( "VIDCCONSOLE DEBUG INFORMATION\n\n" ); + printf ( "res (%d, %d) charsize (%d, %d) cursor (%d, %d)\n" + , R_DATA->XRES, R_DATA->YRES + , vc->xchars, vc->ychars, vc->xcur, vc->ycur ); + printf ( "bytes_per_line %d\n" , R_DATA->bytes_per_line ); + printf ( "pixelsperbyte %d\n" , R_DATA->pixelsperbyte ); + printf ( "dispstart %08x\n" , dispstart ); + printf ( "dispend %08x\n" , dispend ); + printf ( "screensize %08x\n" , R_DATA->screensize ); + + printf ( "fontwidth %08x\n" , R_DATA->font->pixel_width ); + printf ( "fontheight %08x\n" , R_DATA->font->pixel_height ); + printf ( "\n" ); + printf ( "palreg = %08x bcol = %08x\n" , VIDC.palreg, VIDC.bcol ); + printf ( "cp1 = %08x cp2 = %08x cp3 = %08x\n" , VIDC.cp1, VIDC.cp2, VIDC.cp3 ); + printf ( "hcr = %08x hswr = %08x hbsr = %08x\n" , VIDC.hcr, VIDC.hswr, VIDC.hbsr ); + printf ( "hder = %08x hber = %08x hcsr = %08x\n" , VIDC.hder, VIDC.hber, VIDC.hcsr ); + printf ( "hir = %08x\n" , VIDC.hir ); + printf ( "vcr = %08x vswr = %08x vbsr = %08x\n" , VIDC.vcr, VIDC.vswr, VIDC.vbsr ); + printf ( "vder = %08x vber = %08x vcsr = %08x\n" , VIDC.vder, VIDC.vber, VIDC.vcsr ); + printf ( "vcer = %08x\n" , VIDC.vcer ); + printf ( "ereg = %08x fsynreg = %08x conreg = %08x\n" , VIDC.ereg, VIDC.fsynreg, VIDC.conreg ); + printf ( "\n" ); + printf ( "flash %08x, cursor_flash %08x", R_DATA->flash, R_DATA->cursor_flash ); +#else + printf ( "VIDCCONSOLE - NO DEBUG INFO\n" ); +#endif + return 0; +} + +#ifdef NICE_UPDATE +static int need_update = 0; + +void +vidcconsole_updatecursor(arg) + void *arg; +{ + struct vconsole *vc = vconsole_current; + + vidc_write(VIDC_HCSR, R_DATA->frontporch-17+ (vc->xcur)*R_DATA->font->pixel_width ); + vidc_write(VIDC_VCSR, R_DATA->topporch-2+ (vc->ycur+1)*R_DATA->font->pixel_height-2 + 3 + - R_DATA->font->pixel_height); + vidc_write(VIDC_VCER, R_DATA->topporch-2+ (vc->ycur+3)*R_DATA->font->pixel_height+2 + 3 ); + return; +} + +int +vidcconsole_cursorupdate(vc) + struct vconsole *vc; +{ + timeout ( vidcconsole_updatecursor, NULL, 20 ); + return 0; +} + +#else + +static int +vidcconsole_cursorupdate(vc) + struct vconsole *vc; +{ + vidc_write(VIDC_HCSR, R_DATA->frontporch-17+ (vc->xcur)*R_DATA->font->pixel_width ); + vidc_write(VIDC_VCSR, R_DATA->topporch-2+ (vc->ycur+1)*R_DATA->font->pixel_height-2 + 3 + - R_DATA->font->pixel_height); + vidc_write(VIDC_VCER, R_DATA->topporch-2+ (vc->ycur+3)*R_DATA->font->pixel_height+2 + 3 ); + return (0); +} + +#endif + +#define DEFAULT_CURSORSPEED (25) + +static int CURSORSPEED = DEFAULT_CURSORSPEED; + +static int +vidcconsole_cursorflashrate(vc, rate) + struct vconsole *vc; + int rate; +{ + CURSORSPEED = 60/rate; +} + +static int cursorcounter=DEFAULT_CURSORSPEED; +static int flashcounter=DEFAULT_CURSORSPEED; +#ifdef PRETTYCURSOR +static int pretty=0xff; +#endif + +static int cursor_col = 0x0; + +static int +vidcconsole_cursorintr(vc) + struct vconsole *vc; +{ + if ( cursor_flash==0 ) + return 0; + + /* + * We don't need this. + */ +#ifndef RC7500 + vconsole_blankcounter--; + + if ( vconsole_blankcounter<0 ) { + vconsole_blankcounter=vconsole_blankinit; + vidcconsole_blank ( vc, BLANK_OFF ); + } +#endif + + cursorcounter--; + if (cursorcounter<=0) { + cursorcounter=CURSORSPEED; + cursor_col = cursor_col ^ 0xffffff; +#ifdef ACTIVITY_WARNING + if (vconsole_pending) { + if ( cursor_col==0 ) + WriteWord(IOMD_CURSINIT,p_cursor_transparent); + else + WriteWord(IOMD_CURSINIT,p_cursor_normal); + vidc_write ( VIDC_CP1, cursor_col&0xff ); + } else +#endif + { + if ( cursor_col==0 ) + WriteWord(IOMD_CURSINIT,p_cursor_transparent); + else + WriteWord(IOMD_CURSINIT,p_cursor_normal); + vidc_write ( VIDC_CP1, 0xffffff ); + } + } + return(0); +} + +int +vidcconsole_flashintr(vc) + struct vconsole *vc; +{ + if ( flash==0 ) + return 0; + + flashcounter--; + if (flashcounter<=0) { + flashcounter=CURSORSPEED; + if ( cursor_col == 0 ) { + + vidc_write(VIDC_PALREG, 0x00000010); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL(255, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 255, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 255)); + vidc_write(VIDC_PALETTE, VIDC_COL(255, 0, 255)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 255, 255)); + vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 255)); + vidc_write(VIDC_PALETTE, VIDC_COL(128, 128, 128)); + vidc_write(VIDC_PALETTE, VIDC_COL(255, 128, 128)); + vidc_write(VIDC_PALETTE, VIDC_COL(128, 255, 128)); + vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 128)); + vidc_write(VIDC_PALETTE, VIDC_COL(128, 128, 255)); + vidc_write(VIDC_PALETTE, VIDC_COL(255, 128, 255)); + vidc_write(VIDC_PALETTE, VIDC_COL(255, 255, 255)); + } else { + vidc_write(VIDC_PALREG, 0x00000010); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + vidc_write(VIDC_PALETTE, VIDC_COL( 0, 0, 0)); + } + } + return(0); +} + +static int +vidc_cursor_init(vc) + struct vconsole *vc; +{ + extern char *cursor_data; + int counter; + int line; + + /* Blank the cursor while initialising it's sprite */ + + vidc_write ( VIDC_CP1, 0x0 ); + vidc_write ( VIDC_CP2, 0x0 ); + vidc_write ( VIDC_CP3, 0x0 ); + + cursor_normal = cursor_data; + cursor_transparent = cursor_data + (R_DATA->font->pixel_height * + R_DATA->font->pixel_width); + + cursor_transparent += 32; + cursor_transparent = (char *)((int)cursor_transparent & (~31) ); + + for ( line = 0; linefont->pixel_height; ++ line ) + { + for ( counter=0; counterfont->pixel_width/4;counter++ ) + cursor_normal[line*R_DATA->font->pixel_width + counter]=0x55; + for ( ; counter<8; counter++ ) + cursor_normal[line*R_DATA->font->pixel_width + counter]=0; + } + + for ( line = 0; linefont->pixel_height; ++ line ) + { + for ( counter=0; counterfont->pixel_width/4;counter++ ) + cursor_transparent[line*R_DATA->font->pixel_width + counter]=0x00; + for ( ; counter<8; counter++ ) + cursor_transparent[line*R_DATA->font->pixel_width + counter]=0; + } + + + p_cursor_normal = pmap_extract(kernel_pmap,(vm_offset_t)cursor_normal ); + p_cursor_transparent = pmap_extract(kernel_pmap,(vm_offset_t)cursor_transparent); + +/* + memset ( cursor_normal, 0x55, + R_DATA->font->pixel_width*R_DATA->font->pixel_height ); + + memset ( cursor_transparent, 0x55, + R_DATA->font->pixel_width*R_DATA->font->pixel_height ); +*/ + + /* Ok, now see the cursor */ + + vidc_write ( VIDC_CP1, 0xffffff ); + return 0; +} + +int +vidcconsole_setfgcol(vc, col) + struct vconsole *vc; + int col; +{ + register int loop; + + if ( R_DATA->forecolour >= 16 ) + R_DATA->forecolour=16; + else + R_DATA->forecolour=0; + + R_DATA->forefillcolour = 0; + + R_DATA->forecolour += col; + +/*TODO + if ( R_DATA->forecolour >> 1<BITSPERPIXEL ) + R_DATA->forecolour>>1; +*/ + + for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) { + R_DATA->forefillcolour |= (R_DATA->forecolour << + loop * R_DATA->BITSPERPIXEL); + } + R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16); + return 0; +} + +int +vidcconsole_setbgcol(vc, col) + struct vconsole *vc; + int col; +{ + register int loop; + + if ( R_DATA->backcolour >= 16 ) + R_DATA->backcolour=16; + else + R_DATA->backcolour=0; + + R_DATA->backfillcolour = 0; + R_DATA->backcolour += col; + /*TODO + if ( R_DATA->backcolour >> 1<BITSPERPIXEL ) + R_DATA->backcolour>>1; +*/ + + for (loop = 0; loop < R_DATA->pixelsperbyte; ++loop) { + R_DATA->backfillcolour |= (R_DATA->backcolour << + loop * R_DATA->BITSPERPIXEL); + } + return 0; +} + +int +vidcconsole_textpalette(vc) + struct vconsole *vc; +{ + R_DATA->forecolour = COLOUR_WHITE_8; + R_DATA->backcolour = COLOUR_BLACK_8; + + vidc_write( VIDC_PALREG , 0x00000000); + vidc_write( VIDC_PALETTE , VIDC_COL( 0, 0, 0)); + vidc_write( VIDC_PALETTE , VIDC_COL(255, 0, 0)); + vidc_write( VIDC_PALETTE , VIDC_COL( 0, 255, 0)); + vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 0)); + vidc_write( VIDC_PALETTE , VIDC_COL( 0, 0, 255)); + vidc_write( VIDC_PALETTE , VIDC_COL(255, 0, 255)); + vidc_write( VIDC_PALETTE , VIDC_COL( 0, 255, 255)); + vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 255)); + vidc_write( VIDC_PALETTE , VIDC_COL(128, 128, 128)); + vidc_write( VIDC_PALETTE , VIDC_COL(255, 128, 128)); + vidc_write( VIDC_PALETTE , VIDC_COL(128, 255, 128)); + vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 128)); + vidc_write( VIDC_PALETTE , VIDC_COL(128, 128, 255)); + vidc_write( VIDC_PALETTE , VIDC_COL(255, 128, 255)); + vidc_write( VIDC_PALETTE , VIDC_COL(255, 255, 255)); + +R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16); + return 0; +} + +int +vidcconsole_sgr (vc, type) + struct vconsole *vc; + int type; +{ + switch ( type ) + { + case 0: /* Normal */ + if (R_DATA->BITSPERPIXEL == 8) + { + R_DATA->n_forecolour = COLOUR_WHITE_8; + R_DATA->n_backcolour = COLOUR_BLACK_8; + } + + R_DATA->forecolour = R_DATA->n_forecolour; + R_DATA->backcolour = R_DATA->n_backcolour; + R_DATA->font = R_DATA->normalfont; + break; + + case 1: /* bold */ + R_DATA->font = R_DATA->boldfont; + break; + + case 22: /* not bold */ + R_DATA->font = R_DATA->normalfont; + break; + + case 5: /* blinking */ + if ( R_DATA->forecolour < 16 ) + { + R_DATA->forecolour+=16; + R_DATA->backcolour+=16; + R_DATA->n_forecolour+=16; + R_DATA->n_backcolour+=16; + } + break; + + case 25: /* not blinking */ + if ( R_DATA->forecolour >= 16 ) + { + R_DATA->forecolour-=16; + R_DATA->backcolour-=16; + R_DATA->n_forecolour-=16; + R_DATA->n_backcolour-=16; + } + break; + + case 7: /* reverse */ + R_DATA->forecolour = R_DATA->n_backcolour; + R_DATA->backcolour = R_DATA->n_forecolour; + break; + + case 27: /* not reverse */ + R_DATA->forecolour = R_DATA->n_forecolour; + R_DATA->backcolour = R_DATA->n_backcolour; + break; + } +R_DATA->fast_render = R_DATA->forecolour | (R_DATA->backcolour<<8) | (R_DATA->font->pixel_height<<16); + return 0; +} + +int +vidcconsole_scrollregion(vc, low, high) + struct vconsole *vc; + int low; + int high; +{ + return 0; +} + +int +vidcconsole_blank(vc, type) + struct vconsole *vc; + int type; +{ + vc->blanked=type; + switch (type) { + case 0: +#ifdef RC7500 + vidc_write ( VIDC_EREG, 0x51<<12 ); +#else + vidc_write ( VIDC_EREG, 1<<12 ); +#endif + break; + + case 1: /* not implemented yet */ + case 2: + case 3: + vidc_write ( VIDC_EREG, 0 ); + break; + } + return 0; +} + +extern struct tty *find_tp __P((dev_t dev)); + +int vidcconsole_ioctl ( struct vconsole *vc, dev_t dev, int cmd, caddr_t data, + int flag, struct proc *p ) +{ + int error; + struct tty *tp; + struct winsize ws; + switch ( cmd ) + { + case CONSOLE_MODE: + tp = find_tp(dev); + printf ( "mode ioctl called\n" ); + vidcconsole_mode ( vc, (struct vidc_mode *)data ); + vc->MODECHANGE ( vc ); + ws.ws_row=vc->ychars; + ws.ws_col=vc->xchars; + error = (*linesw[tp->t_line].l_ioctl)(tp, TIOCSWINSZ, (char *)&ws, flag, p); + error = ttioctl(tp, TIOCSWINSZ, (char *)&ws, flag, p); + return 0; + break; + + case CONSOLE_RESETSCREEN: + { + extern unsigned int dispbase; + extern unsigned int dispsize; + extern unsigned int ptov; + extern unsigned int transfersize; + + WriteWord ( IOMD_VIDINIT, dispbase-ptov ); + WriteWord ( IOMD_VIDSTART, dispbase-ptov ); + WriteWord ( IOMD_VIDEND, (dispbase+dispsize-transfersize)-ptov ); + return 0; + } + case CONSOLE_RESTORESCREEN: + { + extern unsigned int dispstart; + extern unsigned int dispsize; + extern unsigned int ptov; + extern unsigned int transfersize; + + WriteWord ( IOMD_VIDINIT, dispstart-ptov ); + WriteWord ( IOMD_VIDSTART, dispstart-ptov ); + WriteWord ( IOMD_VIDEND, (dispstart+dispsize-transfersize)-ptov ); + vidc_stdpalette(); + return 0; + } + case CONSOLE_GETINFO: + { + extern videomemory_t videomemory; + register struct console_info *inf = (void *)data; + + + inf->videomemory = videomemory; + inf->width = R_DATA->mode.hder; + inf->height = R_DATA->mode.vder; + inf->bpp = R_DATA->mode.bitsperpixel; + return 0; + } + case CONSOLE_PALETTE: + { + register struct console_palette *pal = (void *)data; + vidc_write(VIDC_PALREG, pal->entry); + vidc_write(VIDC_PALETTE, VIDC_COL(pal->red, pal->green, pal->blue)); + return 0; + } + } + return -1; +} + +int +vidcconsole_attach(vc, parent, self, aux) + struct vconsole *vc; + struct device *parent; + struct device *self; + void *aux; +{ + vidc_cursor_init ( vc ); + vidcconsole_flash_go ( vc ); + return 0; +} + +int +vidcconsole_flash_go(vc) + struct vconsole *vc; +{ + static lock=0; + if (lock==1) + return -1; + lock=0; + + cursor_ih.ih_func = vidcconsole_cursorintr; + cursor_ih.ih_arg = vc; + cursor_ih.ih_level = IPL_TTY; + cursor_ih.ih_name = "vsync"; + irq_claim ( IRQ_FLYBACK, &cursor_ih ); + + cursor_init = 0; + return 0; +} + +/* What does this function do ? */ +int +vidcconsole_flash(vc, flash) + struct vconsole *vc; + int flash; +{ + flash = flash; +} + +int +vidcconsole_cursorflash(vc, flash) + struct vconsole *vc; + int flash; +{ + cursor_flash = flash; + return(0); +} + +struct render_engine vidcconsole = { + vidcconsole_name, + vidcconsole_init, + + vidcconsole_putchar, + + vidcconsole_spawn, + vidcconsole_swapin, + vidcconsole_mmap, + vidcconsole_render, + vidcconsole_scrollup, + vidcconsole_scrolldown, + vidcconsole_cls, + vidcconsole_update, + vidcconsole_scrollback, + vidcconsole_scrollforward, + vidcconsole_scrollbackend, + vidcconsole_clreos, + vidcconsole_debugprint, + vidcconsole_cursorupdate, + vidcconsole_cursorflashrate, + vidcconsole_setfgcol, + vidcconsole_setbgcol, + vidcconsole_textpalette, + vidcconsole_sgr, + vidcconsole_blank, + vidcconsole_ioctl, + vidcconsole_redraw, + vidcconsole_attach, + vidcconsole_flash, + vidcconsole_cursorflash +}; + + + + + + + +struct vidcvideo_softc { + struct device device; + int sc_opened; +}; + +int +vidcvideo_probe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ +/* + struct vidcvideo_softc *vidcvideosoftc = (void *)match; + struct mainbus_attach_args *mb = aux; +*/ + + return 1; +} + +void +vidcvideo_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct vidcvideo_softc *vidcvideosoftc = (void *)self; + vidcvideosoftc->sc_opened=0; + + printf ( ": vidc 20\n" ); +} + +struct cfattach vidcvideo_ca = { + sizeof (struct vidcvideo_softc), vidcvideo_probe, vidcvideo_attach +}; + +struct cfdriver vidcvideo_cd = { + NULL, "vidcvideo", DV_DULL +}; + +int +vidcvideoopen(dev, flags, fmt, p) + dev_t dev; + int flags; + int fmt; + struct proc *p; +{ + struct vidcvideo_softc *sc; + struct vconsole vconsole_new; + int unit = minor(dev); + int s; + + if ( unit >= vidcvideo_cd.cd_ndevs ) + return ENXIO; + sc = vidcvideo_cd.cd_devs[unit]; + if (!sc) + return ENXIO; + + s = spltty(); +/* if (sc->sc_opened) { + (void)splx(s); + return(EBUSY); + }*/ + ++sc->sc_opened; + (void)splx(s); + + if (sc->sc_opened == 1) { + vconsole_new = *vconsole_default; + vconsole_new.render_engine = &vidcconsole; + vconsole_spawn_re ( + makedev ( physcon_major, 64 + minor(dev) ), + &vconsole_new ); + } else { + log(LOG_WARNING, "Multiple open of/dev/vidcvideo0 by proc %d\n", p->p_pid); + } + + return 0; +} + +int +vidcvideoclose(dev, flags, fmt, p) + dev_t dev; + int flags; + int fmt; + struct proc *p; +{ + struct vidcvideo_softc *sc; + int unit = minor(dev); + int s; + + if ( unit >= vidcvideo_cd.cd_ndevs ) + return ENXIO; + sc = vidcvideo_cd.cd_devs[unit]; + if (!sc) + return ENXIO; + + s = spltty(); + --sc->sc_opened; + (void)splx(s); + + return 0; +} + +extern int physconioctl __P(( dev_t, int, caddr_t, int, struct proc *)); + +int +vidcvideoioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + dev = makedev(physcon_major, 64 + minor(dev)); + return ( physconioctl ( dev, cmd, data, flag, p )); +} + +extern int physconmmap __P((dev_t, int, int)); + +int +vidcvideommap(dev, offset, prot) + dev_t dev; + int offset; + int prot; +{ + dev = makedev(physcon_major, 64 + minor(dev)); + return(physconmmap(dev, offset, prot)); +} + diff --git a/sys/arch/arm32/dev/console/vt220.c b/sys/arch/arm32/dev/console/vt220.c new file mode 100644 index 00000000000..41bb883da3b --- /dev/null +++ b/sys/arch/arm32/dev/console/vt220.c @@ -0,0 +1,2008 @@ +/* $NetBSD: vt220.c,v 1.3 1996/03/18 19:33:10 mark Exp $ */ + +/* + * Copyright (c) 1994-1995 Melvyn Tang-Richardson + * Copyright (c) 1994-1995 RiscBSD kernel team + * 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 kernel team + * 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 RISCBSD TEAM ``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 AUTHORS 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 + * + * vt220.c + * + * VT220 emulation functions + * + * Created : 17/09/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Temporary for debugging the vnode bug */ + +int vnodeconsolebug = 0; +u_int vnodeconsolebug1 = 0; +u_int vnodeconsolebug2 = 0; + +static char vt220_name[] = "vt100"; + +/* These defines are for the developer only !!!! */ +#define SELFTEST +#define dprintf(x) ; + +/*************************************************/ + +#define FGCOL 0x0700 +#define BGCOL 0x3800 + +/* Options */ +#define HARD_RESET_AT_INIT +#undef SIMPLE_CURSOR /* Define if any render engine is cursorless */ + +/*************************************************/ + +#define DA_VT220 "\033[?62;1;2;6;7;8;9c" + +char console_proc[41]; /* Is this debugging ? */ + +#ifdef SIMPLE_CURSOR +#define SIMPLE_CURSOR_CHAR ('_') +#endif + +#define TERMTYPE_PUTSTRING vt220_putstring +#define TERMTYPE_INIT vt220_init + +extern struct vconsole *vconsole_master; + +static int default_beepstate = 0; + +#define CDATA struct vt220_info *cdata = (struct vt220_info *)vc->data + +struct vt220_info master_termdata_store; +struct vt220_info *master_termdata = &master_termdata_store; + +int do_render __P(( char /*c*/, struct vconsole */*vc*/ )); +void do_render_noscroll __P(( char /*c*/, struct vconsole */*vc*/ )); +void do_scrollcheck __P(( struct vconsole */*vc*/ )); +void vt_ris __P((struct vconsole */*vc*/)); + +void +clr_params(cdata) + struct vt220_info *cdata; +{ + int i; + for (i=0; iparam[i] = 0; + cdata->parami = 0; +} + +int +TERMTYPE_INIT(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata; + + if (vc->data==NULL) { + if ( vc==vconsole_master ) { + vc->data = (char *) master_termdata; + } else { + MALLOC ( vc->data, char *, sizeof(struct vt220_info), + M_DEVBUF, M_NOWAIT ); + } + } + + cdata = (struct vt220_info *)vc->data; + + bzero ( (char *)cdata, sizeof (cdata) ); + +#ifdef HARD_RESET_AT_INIT + vt_ris ( vc ); +#else + cdata->state = STATE_INIT; + cdata->disable_function = 1; + cdata->m_om = 0; + vc->xcur = vc->ycur = 0; + cdata->beepoff=default_beepstate; + cdata->simple_cursor_store = ' '; + cdata->scrr_beg = 0; + cdata->scrr_len = vc->ychars; + cdata->scrr_end = vc->ychars-1; + cdata->simple_cursor_on = 0; + + for ( counter=0; countertab_stops[counter] = 1; + else + cdata->tab_stops[counter] = 0; + } +#endif + return 0; +} + +int +mapped_cls(vc) + struct vconsole *vc; +{ + int ptr; + if (vc->charmap == NULL) + return -1; + for ( ptr=0; ptr<(vc->xchars*vc->ychars); ptr++ ) + vc->charmap[ptr]=0x20; + return 0; +} + +void +do_scrolldown(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + +/* + if ( ( cdata->scrr_beg<0 ) || ( cdata->scrr_end>=vc->ychars) ) + dprintf ( "INVALID SCROLLDOWN" ); +*/ + + /* Clean up */ + +/* + if ( cdata->scrr_beg < 0 ) cdata->scrr_beg = 0; +*/ + if ( cdata->scrr_end >= vc->ychars ) cdata->scrr_end=vc->ychars-1; + + + if (vc==vconsole_current) + vc->SCROLLDOWN ( vc, cdata->scrr_beg, cdata->scrr_end ); + else + vconsole_pending=vc->number; + + if (vnodeconsolebug) { + if (ReadWord(0xf148a000) != vnodeconsolebug2) { + log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in do_scrolldown(1)\n", + vnodeconsolebug2, ReadWord(0xf148a000)); + log(LOG_WARNING, "vc=%08x vcur=%08x charmap=%08x\n", vc, vconsole_current, vc->charmap); + } + } + +/* + * This version of the following code was responcible for the vnode bug + * It can trash part of the word that follows the allocated block + * e.g. charmap = 0xf1484000, size 0x6000 + * vnode = 0xf148a000 + * first word of vnode is trashed. + * bug is an adjustment of -1 for counting backwards was not made. + + if ( ((vc->flags)&(LOSSY)) == 0 ) { + int counter; + for ( counter=((cdata->scrr_end+1)*(vc->xchars)); + counter > (cdata->scrr_beg+1)*(vc->xchars) ; counter-- ) { + vc->charmap[counter] = vc->charmap[counter-vc->xchars]; + } + + for ( counter=(cdata->scrr_beg)*(vc->xchars); + counter < (cdata->scrr_beg+1)*(vc->xchars); counter++ ) { + vc->charmap[counter]=0x20; + } + } +*/ + if ( ((vc->flags)&(LOSSY)) == 0 ) { + int counter; + for ( counter=((cdata->scrr_end+1)*(vc->xchars)) - 1; + counter >= (cdata->scrr_beg+1)*(vc->xchars) ; counter-- ) { + vc->charmap[counter] = vc->charmap[counter-vc->xchars]; + } + + for ( counter=(cdata->scrr_beg)*(vc->xchars); + counter < (cdata->scrr_beg+1)*(vc->xchars); counter++ ) { + vc->charmap[counter]=0x20; + } + } + if (vnodeconsolebug) { + if (ReadWord(0xf148a000) != vnodeconsolebug2) { + log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in do_scrolldown(2)\n", + vnodeconsolebug2, ReadWord(0xf148a000)); + log(LOG_WARNING, "vc=%08x vcur=%08x charmap=%08x\n", vc, vconsole_current, vc->charmap); + } + } +} + +void +do_scrollup(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + if (vc==vconsole_current) + vc->SCROLLUP ( vc, cdata->scrr_beg, cdata->scrr_end ); + else + vconsole_pending = vc->number; + + if ( cdata->scrr_end == 0 ) + vc->ycur=vc->ychars-1; + else + vc->ycur=cdata->scrr_end; + +/* Do a cyclic buffer for this !!!!!!!!!!!!!! */ + if ( ((vc->flags)&(LOSSY)) == 0 ) { +/* bcopy was weird, do this for now */ + int counter; + for ( counter=(cdata->scrr_beg+1)*vc->xchars; + counter < ((cdata->scrr_end+1)*(vc->xchars)); counter++ ) { + vc->charmap[counter-vc->xchars] = vc->charmap[counter]; + } + for ( counter=vc->xchars*(cdata->scrr_end); + counter < (vc->xchars*(cdata->scrr_end+1)); counter++ ) { + vc->charmap[counter]=0x20; + } + } +} + +void +respond(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + while (*cdata->report_chars && cdata->report_count > 0) { + (*linesw[vc->tp->t_line].l_rint) + (*cdata->report_chars++ & 0xff, vc->tp); + cdata->report_count--; + } +} + +void +vt_curadr(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + +#ifdef SELFTEST +strcpy ( console_proc, "vt_curadr" ); +#endif + + if ( cdata->m_om ) /* relative to scrolling region */ + { + cdata->param[0]+=cdata->scrr_beg; + if ( (cdata->param[0]==0) && (cdata->param[1]==0) ) + { + vc->xcur = 0; + vc->ycur = 0; + return; + } + /* Limit checking */ + cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; + cdata->param[0] = (cdata->param[0] > vc->ychars) ? vc->ychars : cdata->param[0]; + cdata->param[1] = (cdata->param[1] <= 0) ? 1 : cdata->param[1]; + cdata->param[1] = (cdata->param[1] >= vc->xchars) ? (vc->xchars-1) : cdata->param[1]; + (cdata->param[0])--; + (cdata->param[1])--; + vc->ycur = cdata->param[0]; + vc->xcur = cdata->param[1]; + } + else + { + if ( (cdata->param[0]==0) && (cdata->param[1]==0) ) + { + vc->xcur = 0; + vc->ycur = 0; + return; + } + /* Limit checking */ + + (cdata->param[0])--; + (cdata->param[1])--; + + vc->ycur = cdata->param[0]; + vc->xcur = cdata->param[1]; + +{ + char buf[80]; + sprintf ( buf, "vc->xcur %d vc->ycur %d", vc->xcur, vc->ycur ); + dprintf ( buf ); +} + } +} + +extern void beep_generate(void); + +void +vt_reset_dec_priv_qm(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; +#ifdef SELFTEST +strcpy ( console_proc, "vt_reset_dec_priv_qm" ); +#endif + switch(cdata->param[0]) + { + case 7: /* AWM - auto wrap mode */ + beep_generate(); + cdata->flags &= ~F_AWM; + break; + case 0: /* error, ignored */ + case 1: /* CKM - cursor key mode */ + case 2: /* ANM - ansi/vt52 mode */ + case 3: /* COLM - column mode */ + case 4: /* SCLM - scrolling mode */ + case 5: /* SCNM - screen mode */ + case 8: /* ARM - auto repeat mode */ + case 9: /* INLM - interlace mode */ + case 10: /* EDM - edit mode */ + case 11: /* LTM - line transmit mode */ + case 12: /* */ + case 13: /* SCFDM - space compression / field delimiting */ + case 14: /* TEM - transmit execution mode */ + case 15: /* */ + case 16: /* EKEM - edit key execution mode */ + case 25: /* TCEM - text cursor enable mode */ + case 42: /* NRCM - 7bit NRC characters */ + break; + + case 6: /* OM - origin mode */ + cdata->m_om = 0; + break; + } +} + +void +vt_sc(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + +#ifdef SELFTEST + strcpy ( console_proc, "vt_sc" ); +#endif + + cdata->sc_G0 = cdata->G0; + cdata->sc_G1 = cdata->G1; + cdata->sc_G2 = cdata->G2; + cdata->sc_G3 = cdata->G3; + cdata->sc_GL = cdata->GL; + cdata->sc_GR = cdata->GR; + cdata->sc_xcur = vc->xcur; + cdata->sc_ycur = vc->ycur; + cdata->sc_om = cdata->m_om; + cdata->sflags = cdata->flags; +/* + cdata->sc_attr = cdata->c_attr; + cdata->sc_awm = cdata->m_awm; + cdata->sc_sel = cdata->selchar; + cdata->sc_vtsgr = cdata->vtsgr; + cdata->sc_flag = 1; +*/ +} + +void +vt_rc(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + cdata->G0 = cdata->sc_G0; + cdata->G1 = cdata->sc_G1; + cdata->G2 = cdata->sc_G2; + cdata->G3 = cdata->sc_G3; + cdata->GL = cdata->sc_GL; + cdata->GR = cdata->sc_GR; + vc->xcur = cdata->sc_xcur; + vc->ycur = cdata->sc_ycur; + cdata->m_om = cdata->sc_om; + cdata->flags = cdata->sflags; + +/* + cdata->c_attr = cdata->sc_attr; + cdata->awm = cdata->sc_awm; + cdata->sel = cdata->sc_selchar; + cdata->vtsgr = cdata->sc_vtsgr; + cdata->flag = 0; +*/ +} + +void +vt_clreol(vc) + struct vconsole *vc; +{ +/* + struct vt220_info *cdata = (struct vt220_info *)vc->data; +*/ + int counter; + int x = vc->xcur; + int y = vc->ycur; + +#ifdef SELFTEST + strcpy ( console_proc, "vt_clreol" ); +#endif + + for ( counter=vc->xcur; counterxchars; counter++ ) + do_render_noscroll ( ' ', vc ); + + vc->xcur = x; + vc->ycur = y; +} + +/* index, move cursor down */ + +void +vt_ind(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + +#ifdef SELFTEST + strcpy ( console_proc, "vt_ind" ); +#endif + + vc->ycur++; + + { + char buf[80]; + sprintf ( buf, "{vt_ind [%d,%d] [%d,%d] }", + vc->xcur, vc->ycur, cdata->scrr_beg, cdata->scrr_end); + dprintf ( buf ); + } + + do_scrollcheck ( vc ); +} + +void +vt_nel(vc) + struct vconsole *vc; +{ + vc->ycur++; + do_scrollcheck ( vc ); + vc->xcur=0; +} + +void +vt_ri(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + if (vnodeconsolebug & 1) + vnodeconsolebug2 = ReadWord(0xf148a000); + + vc->ycur--; + + if (vc->ycur<=cdata->scrr_beg) + vc->ycur = cdata->scrr_beg; + + + if (vc->ycur <= cdata->scrr_beg) { + if (vnodeconsolebug & 4) { + if (ReadWord(0xf148a000) != vnodeconsolebug2) { + log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in vt_ri(1)\n", + vnodeconsolebug2, ReadWord(0xf148a000)); + log(LOG_WARNING, "vc=%08x ycur=%d scrr_beg=%d\n", vc, vc->ycur, cdata->scrr_beg); + vnodeconsolebug2 = ReadWord(0xf148a000); + } + } + do_scrolldown ( vc ); + if (vnodeconsolebug & 4) { + if (ReadWord(0xf148a000) != vnodeconsolebug2) { + log(LOG_WARNING, "vnode 0xf148a000 v_flag changed from %08x to %08x in vt_ri(2)\n", + vnodeconsolebug2, ReadWord(0xf148a000)); + log(LOG_WARNING, "vc=%08x ycur=%d scrr_beg=%d charmap=%08x\n", vc, vc->ycur, cdata->scrr_beg, vc->charmap); + vnodeconsolebug2 = ReadWord(0xf148a000); + } + } + vc->ycur = cdata->scrr_beg; + } +} + +/* selective in line erase */ + +int +vt_sel(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + register int counter; + register int x = vc->xcur; + register int y = vc->ycur; + + switch ( cdata->param[0] ) + { + case 0: /* Delete to the end of the line */ + for ( counter=x; counterxchars; counter++ ) + do_render_noscroll ( ' ', vc ); + break; + + case 1: /* Delete to the beginning of the line */ + vc->xcur = 0; + for ( counter=0; counterxcur = 0; + for ( counter=0; counterxchars; counter++ ) + do_render_noscroll ( ' ', vc ); + break; + } + + vc->xcur = x; + vc->ycur = y; + return 0; +} + +void +vt_cuu(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; + vc->ycur -= cdata->param[0]; + vc->ycur = vc->ycur < 0 ? 0 : vc->ycur; +} + +void +vt_cub(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; + + vc->xcur -= cdata->param[0]; + cdata->param[0] = (cdata->param[0] < 0 ) ? 0 : cdata->param[0]; +} + +void +vt_da(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + static u_char *response = (u_char *)DA_VT220; + + cdata->report_chars = response; + cdata->report_count = 18; + respond(vc); +} + +void +vt_str(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + int counter; + + if (cdata == NULL) { + return; + } + + clr_params ( cdata ); + + cdata->state = STATE_INIT; + cdata->disable_function = 1; + cdata->m_om = 0; /* origin mode */ + vc->xcur = vc->ycur = 0; + cdata->beepoff=default_beepstate; + cdata->simple_cursor_store = ' '; + cdata->scrr_beg = 0; + cdata->scrr_len = vc->ychars; + cdata->scrr_end = vc->ychars-1; + cdata->simple_cursor_on = 0; + cdata->nfgcol = 7; + cdata->nbgcol = 0; + cdata->fgcol = cdata->nfgcol; + cdata->bgcol = cdata->nbgcol; + cdata->attribs=cdata->fgcol<<8 | cdata->bgcol<<11; + cdata->sc_flag = 0; /* save cursor position */ + cdata->flags = F_AWM; + cdata->irm = 0; + + for ( counter=0; countertab_stops[counter] = 1; + else + cdata->tab_stops[counter] = 0; + } +} + +void +vt_ris(vc) + struct vconsole *vc; +{ + vc->xcur = vc->ycur = 0; + vt_str(vc); /* and soft terminal reset */ +} + +void +vt_cud(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; + + cdata->param[0] = (cdata->param[0] > (cdata->scrr_end-vc->ycur)) + ? (cdata->scrr_end-vc->ycur) : cdata->param[0]; + + vc->ycur += cdata->param[0]; + + do_scrollcheck ( vc ); +} + +void +vt_tst(vc) + struct vconsole *vc; +{ + int counter, times; + + for ( times=0; times<100; times++ ); + for ( counter=32; counter<127; counter++ ) + do_render ( counter, vc ); +} + +void +vt_il(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + register int beg, end; + + if ( vc->ycur >= (vc->ychars-2) ) + return; + + cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0]; + + beg = cdata->scrr_beg; + end = cdata->scrr_end; + + cdata->scrr_beg = vc->ycur; + cdata->scrr_end = vc->ychars-1; + + for ( ; cdata->param[0]>0; cdata->param[0]-- ) + do_scrolldown( vc ); + + cdata->scrr_beg = beg; + cdata->scrr_end = end; +} + +void +vt_ic(vc) + struct vconsole *vc; +{ + int counter; + int ox, oy; + int *ptr = vc->charmap + (vc->xcur + vc->ycur*vc->xchars); + for ( counter=vc->xchars-vc->xcur; counter>=0; counter-- ) + ptr[counter+1] = ptr[counter]; + ptr[0] = ' '; + ox = vc->xcur; oy = vc->ycur; + + for ( ; vc->xcur < vc->xchars; ) + do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc ); + vc->xcur = ox; vc->ycur = oy; +} + +void +vt_dch(vc) + struct vconsole *vc; +{ + int counter; + int ox, oy; + int *ptr = vc->charmap + (vc->ycur*vc->xchars); + + for ( counter=vc->xcur; counter<(vc->xchars-1); counter++ ) + ptr[counter] = ptr[counter+1]; + + ptr[vc->xchars] = ' '; + + ox = vc->xcur; oy = vc->ycur; + + for ( ; vc->xcur < vc->xchars; ) + do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc ); + + vc->xcur = ox; vc->ycur = oy; +} + +void +vt_dl(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + register int beg, end; + + cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0]; + cdata->param[0] = cdata->param[0]>vc->xchars ? vc->xchars : cdata->param[0]; + +/* + vc->xcur=0; +*/ + + beg = cdata->scrr_beg; + end = cdata->scrr_end; + + cdata->scrr_beg = vc->ycur; + cdata->scrr_end = vc->ychars-1; + + for ( ; cdata->param[0]>0; cdata->param[0]-- ) + do_scrollup( vc ); + + cdata->scrr_beg = beg; + cdata->scrr_end = end; +} + +/* Set scrolling region */ + +void +vt_stbm(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + if((cdata->param[0] == 0) && (cdata->param[1] == 0)) + { + cdata->xcur = 0; + cdata->ycur = 0; + cdata->scrr_beg = 0; + cdata->scrr_len = vc->ychars; + cdata->scrr_end = cdata->scrr_len - 1; + return; + } + if(cdata->param[1] <= cdata->param[0]) + return; + + /* range parm 1 */ + + cdata->scrr_beg = cdata->param[0]-1; + cdata->scrr_len = cdata->param[1] - cdata->param[0] + 1; + cdata->scrr_end = cdata->param[1]-1; + +/* + if (cdata->scrr_beg<0) + cdata->scrr_beg = 0; +*/ + + if (cdata->scrr_end>(vc->ychars-1)) + cdata->scrr_end = vc->ychars-1; + + cdata->scrr_len = cdata->scrr_end - cdata->scrr_beg - 1; +{ + char buf[80]; + sprintf ( buf, "scrr_beg %d, scrr_end %d", cdata->scrr_beg, + cdata->scrr_end ); + dprintf ( buf ); +} + + cdata->flags &= ~F_LASTCHAR; +} + +void +vt_dsr(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + static u_char *answr = (u_char *)"\033[0n"; + static u_char *panswr = (u_char *)"\033[?13n"; /* Printer Unattached */ + static u_char *udkanswr = (u_char *)"\033[?21n"; /* UDK Locked */ + static u_char *langanswr = (u_char *)"\033[?27;1n"; /* North American*/ + static u_char buffer[16]; + int i = 0; + + switch(cdata->param[0]) + { + case 5: /* return status */ + cdata->report_chars = answr; + cdata->report_count = 4; + respond(vc); + break; + + case 6: /* return cursor position */ + buffer[i++] = 0x1b; + buffer[i++] = '['; + if((vc->ycur+1) > 10) + buffer[i++] = ((vc->ycur+1) / 10) + '0'; + buffer[i++] = ((vc->ycur+1) % 10) + '0'; + buffer[i++] = ';'; + if((vc->xcur+1) > 10) + buffer[i++] = ((cdata->xcur+1) / 10) + '0'; + buffer[i++] = ((vc->xcur+1) % 10) + '0'; + buffer[i++] = 'R'; + buffer[i++] = '\0'; + + cdata->report_chars = buffer; + cdata->report_count = i; + respond(vc); + break; + + case 15: /* return printer status */ + cdata->report_chars = panswr; + cdata->report_count = 6; + respond(vc); + break; + + case 25: /* return udk status */ + cdata->report_chars = udkanswr; + cdata->report_count = 6; + respond(vc); + break; + + case 26: /* return language status */ + cdata->report_chars = langanswr; + cdata->report_count = 8; + respond(vc); + break; + + default: /* nothing else valid */ + break; + } +} + +void +vt_su(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + cdata->param[0] = cdata->param[0]<=0 ? 1 : cdata->param[0]; + cdata->param[0] = cdata->param[0]>(vc->xchars-1) ? vc->xchars-1 : cdata->param[0]; + + do_scrollup ( vc ); +} + +void +vt_set_dec_priv_qm(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + switch(cdata->param[0]) + { + case 7: /* AWM - auto wrap mode */ + cdata->flags |= F_AWM; + break; + + /* Implement these */ + case 1: /* CKM - cursor key mode */ + case 3: /* COLM - column mode */ + case 6: /* OM - origin mode */ + case 8: /* ARM - auto repeat mode */ + case 25: /* TCEM - text cursor enable mode */ + break; + + case 0: /* error, ignored */ + case 2: /* ANM - ansi/vt52 mode */ + case 4: /* SCLM - scrolling mode */ + case 5: /* SCNM - screen mode */ + case 9: /* INLM - interlace mode */ + case 10: /* EDM - edit mode */ + case 11: /* LTM - line transmit mode */ + case 12: /* */ + case 13: /* SCFDM - space compression / field delimiting */ + case 14: /* TEM - transmit execution mode */ + case 15: /* */ + case 16: /* EKEM - edit key execution mode */ + case 42: /* NRCM - 7bit NRC characters */ + break; + } +} + +void +vt_keyappl(vc) + struct vconsole *vc; +{ + dprintf ( "VT_KEYAPPL" ); +} + +void +vt_clrtab(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + int i; + + if(cdata->param[0] == 0) + cdata->tab_stops[vc->xcur] = 0; + else if(cdata->param[0] == 3) + { + for(i=0; itab_stops[i] = 0; + } +} + +/* +void +vt_cuf(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + cdata->param[0] = (cdata->param[0] <= 0) ? 1 : cdata->param[0]; + + vc->xcur += cdata->param[0]; + + cdata->param[0] = (cdata->param[0] > vc->xchars ) ? vc->xchars : cdata->param[0]; +} +*/ + +void +vt_cuf(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + register int p = cdata->param[0]; + + if(vc->xcur == ((vc->xchars)-1)) /* already at right margin */ + return; + if(p <= 0) /* parameter min = 1 */ + p = 1; + else if(p > ((vc->xchars)-1)) /* parameter max = 79 */ + p = ((vc->xchars)-1); + if((vc->xcur + p) > ((vc->xchars)-1)) /* not more than */ + p = ((vc->xchars)-1) - vc->xcur; + vc->xcur += p; +} + +void +vt_sgr(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + register int i=0; + + do + { + vc->SGR ( vc, cdata->param[i] ); + switch ( cdata->param[i++] ) + { + case 0: /* reset to normal attributes */ + cdata->fgcol = cdata->nfgcol; + cdata->bgcol = cdata->nbgcol; + cdata->attribs=cdata->fgcol<<8 | cdata->bgcol<<11; + break; + case 1: /* bold */ + cdata->attribs |= BOLD; + break; + case 4: /* underline */ + cdata->attribs |= UNDERLINE; + break; + case 5: /* blinking */ + cdata->attribs |= BLINKING; + break; + case 7: /* reverse */ + cdata->fgcol = cdata->nbgcol; + cdata->bgcol = cdata->nfgcol; + cdata->attribs |= REVERSE; + cdata->attribs&=~0x3F00; + cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11; + break; + case 22: /* not bold */ + cdata->attribs &= ~BOLD; + break; + case 24: /* not underlined */ + cdata->attribs &= ~UNDERLINE; + break; + case 25: /* not blinking */ + cdata->attribs &= ~BLINKING; + break; + case 27: /* not reverse */ + cdata->attribs &= ~REVERSE; + cdata->fgcol = cdata->nfgcol; + cdata->bgcol = cdata->nbgcol; + cdata->attribs&=~0x3F00; + cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11; + break; + + default: + if ( ( cdata->param[i-1] > 29 )&&( cdata->param[i-1] < 38 ) ) + { + vc->SETFGCOL ( vc, cdata->param[i-1] - 30 ); + cdata->fgcol = cdata->param[i-1] - 30; + cdata->attribs&=~0x3F00; + cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11; + + } + if ( ( cdata->param[i-1] > 39 )&&( cdata->param[i-1] < 48 ) ) + { + vc->SETBGCOL ( vc, cdata->param[i-1] - 40 ); + cdata->bgcol = cdata->param[i-1] - 40; + cdata->attribs&=~0x3F00; + cdata->attribs|=cdata->fgcol<<8 | cdata->bgcol<<11; + } + } + } while ( i<=cdata->parami ); +} + +void +vt_clreos(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + int ptr; + if ( vc == vconsole_current ) + vc->R_CLREOS ( vc, cdata->param[0] ); + else + vconsole_pending = vc->number; + + switch ( cdata->param[0] ) + { + case 0: /* Erase from cursor to end of screen */ + for ( ptr=vc->xcur + vc->ycur * vc->xchars + ; ptr<(vc->xchars*vc->ychars); ptr++ ) + vc->charmap[ptr]=0x20; + break; + + case 1: /* Erase from start to cursor */ + for ( ptr=0; + ptrycur*vc->xchars + vc->xcur; + ptr++ ) + vc->charmap[ptr]=0x20; + break; + + case 2: /* Blitz the whole bloody thing */ + if ((vc->flags&LOSSY)==0) + mapped_cls(vc); + if (vc==vconsole_current) + vc->CLS(vc); + else + vconsole_pending = vc->number; + break; + } +} + +void +vt_set_ansi(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + switch(cdata->param[0]) + { + case 0: /* error, ignored */ + case 1: /* GATM - guarded area transfer mode */ + case 2: /* KAM - keyboard action mode */ + case 3: /* CRM - Control Representation mode */ + case 20: /* LNM - line feed / newline mode */ + break; + + case 4: /* IRM - insert replacement mode */ + cdata->irm = 1; + break; + + case 5: /* SRTM - status report transfer mode */ + case 6: /* ERM - erasue mode */ + case 7: /* VEM - vertical editing mode */ + case 10: /* HEM - horizontal editing mode */ + case 11: /* PUM - position unit mode */ + case 12: /* SRM - send-receive mode */ + case 13: /* FEAM - format effector action mode */ + case 14: /* FETM - format effector transfer mode */ + case 15: /* MATM - multiple area transfer mode */ + case 16: /* TTM - transfer termination */ + case 17: /* SATM - selected area transfer mode */ + case 18: /* TSM - tabulation stop mode */ + case 19: /* EBM - editing boundary mode */ + break; + } +} + +void +vt_reset_ansi(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + switch(cdata->param[0]) + { + /* Implement these */ + case 0: /* error, ignored */ + case 1: /* GATM - guarded area transfer mode */ + case 2: /* KAM - keyboard action mode */ + case 3: /* CRM - Control Representation mode */ + case 20: /* LNM - line feed / newline mode */ + break; + + case 4: /* IRM - insert replacement mode */ + cdata->irm = 0; + break; + + case 5: /* SRTM - status report transfer mode */ + case 6: /* ERM - erasue mode */ + case 7: /* VEM - vertical editing mode */ + case 10: /* HEM - horizontal editing mode */ + case 11: /* PUM - position unit mode */ + case 12: /* SRM - send-receive mode */ + case 13: /* FEAM - format effector action mode */ + case 14: /* FETM - format effector transfer mode */ + case 15: /* MATM - multiple area transfer mode */ + case 16: /* TTM - transfer termination */ + case 17: /* SATM - selected area transfer mode */ + case 18: /* TSM - tabulation stop mode */ + case 19: /* EBM - editing boundary mode */ + break; + } +} + +/* DRN */ + +void +do_render_noscroll(c, vc) + char c; + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + /* THE RENDER STAGE **********************************/ + + if ((c>=0x20)&&(c<=0x7f)) + { + if (((vc->flags)&(LOSSY))==0) + { + if ( vc->charmap[vc->xcur+vc->ycur*vc->xchars] != c|cdata->attribs ) + { + if ( vc==vconsole_current ) + vc->RENDER ( vc, c ); + else + vconsole_pending = vc->number; + } + vc->charmap[ vc->xcur + vc->ycur*vc->xchars ] = c|cdata->attribs; + } + else + { + if ( vc==vconsole_current ) + vc->RENDER ( vc, c ); + else + vconsole_pending = vc->number; + } + } + + vc->xcur++; + + /*do_scrollcheck ( vc );*/ +} + +#ifdef SIMPLE_CURSOR +void +simple_cursor_on(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + if (cdata->simple_cursor_on) + return 0; + if (vc!=vconsole_current) + return 0; + if (((vc->flags)&(LOSSY))==0) + { + cdata->simple_cursor_store = vc->charmap[ vc->xcur + vc->ycur*vc->xchars ]; + vc->RENDER ( vc, SIMPLE_CURSOR_CHAR ); + } + cdata->simple_cursor_on = 1; +} + +void +simple_cursor_off(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + if (!cdata->simple_cursor_on) + return 0; + if (vc!=vconsole_current) + return 0; + if (((vc->flags)&(LOSSY))==0) + { + vc->RENDER ( vc, cdata->simple_cursor_store ); + } + cdata->simple_cursor_on = 0; +} +#endif + +/* DSC */ +void +do_scrollcheck(vc) + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + + /* BOUNDARY CHECK ************************************/ + if ((vc->xcur >= (vc->xchars))&&((cdata->flags&F_AWM)!=0)) + { + cdata->flags|=F_LASTCHAR; + cdata->lastpos = vc->ycur*vc->xchars+vc->xcur; + } + + /* SCROLL CHECK *************************************/ + if ( vc->ycur >= cdata->scrr_end+1 ) + { + do_scrollup ( vc ); + } +} + +/* DR */ + +int +do_render(c, vc) + char c; + struct vconsole *vc; +{ + struct vt220_info *cdata = (struct vt220_info *)vc->data; + /* THE RENDER STAGE **********************************/ + + if (((cdata->flags&F_AWM)==0)&&(vc->xcur >= 20)) + return 0; + + if ( cdata->flags & F_LASTCHAR ) + { + if ( cdata->lastpos==vc->ycur*vc->xchars+vc->xchars) + { + vc->ycur++; + vc->xcur = 0; + cdata->flags &= ~F_LASTCHAR; + do_scrollcheck(vc); + } + else + { + cdata->flags &= ~F_LASTCHAR; + } + } + + if ((c>=0x20)&&(c<=0x7f)) + { + if (((vc->flags)&(LOSSY))==0) + { + if ( cdata->irm == 0 ) + { + if(vc->charmap[vc->xcur+vc->ycur*vc->xchars]!=c|cdata->attribs ) + { + if ( vc==vconsole_current ) + vc->RENDER ( vc, c ); + else + vconsole_pending = vc->number; + } + vc->charmap[vc->xcur+vc->ycur*vc->xchars ] = c|cdata->attribs; + } + else + { + int counter; + int ox, oy; + int *ptr = vc->charmap + (vc->xcur + vc->ycur*vc->xchars); + for ( counter=vc->xchars-vc->xcur; counter>=0; counter-- ) + ptr[counter+1] = ptr[counter]; + ptr[0] = c; + ox = vc->xcur; oy = vc->ycur; + + for ( ; vc->xcur < vc->xchars; ) + do_render_noscroll ( vc->charmap[vc->xcur+vc->ycur*vc->xchars], vc ); + vc->xcur = ox; vc->ycur = oy; + + } + } + else + { + if ( vc==vconsole_current ) + vc->RENDER ( vc, c ); + else + vconsole_pending = vc->number; + } + } + + vc->xcur++; + + do_scrollcheck ( vc ); + + if ( cdata->flags & F_LASTCHAR ) + vc->xcur--; + return 0; +} + +int +TERMTYPE_PUTSTRING(string, length, vc) + char *string; + int length; + struct vconsole *vc; +{ + struct vt220_info *cdata; + register char c; + char dc[] = "x\0"; + cdata = (struct vt220_info *)vc->data; + + /* A piece of saftey code */ + if ( vconsole_current->vtty == 0 ) + return 0; + +#ifdef SIMPLE_CURSOR + if ( vc==vconsole_current ) + if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_off ( vc ); +#else + if ( vc==vconsole_current ) + vc->CURSORUPDATE (vc); +#endif + + while ( ((c=*(string++))!=0) && ((length--)>0) ) + { + + if ( cdata->state != STATE_INIT ) + cdata->flags &= ~F_LASTCHAR; + + if ( ( c == 0x0a ) || ( c== 0x0d ) ) + cdata->flags &= ~F_LASTCHAR; + +/* Middle mouse button freezes the display while active */ + + while ((ReadByte(IO_MOUSE_BUTTONS) & MOUSE_BUTTON_MIDDLE) == 0); + +/* Left mouse button slows down the display speed */ + + if ((ReadByte(IO_MOUSE_BUTTONS) & MOUSE_BUTTON_LEFT) == 0) + delay(5000); + +/* Always process characters in the range of 0x00 to 0x1f */ + + +#ifdef DEBUGTERM +*dc = c; +switch (c) +{ + case 0x0a: dprintf ( "[0a]" ); break; + case 0x0d: dprintf ( "[0d]" ); break; + case 0x0c: dprintf ( "[0c]" ); break; + case 0x1b: dprintf ( "[1b]" ); break; +} +#endif + if ( c <= 0x1f ) + { + if ( cdata->disable_function ) + { + if ( cdata->flags & F_LASTCHAR ) + { + if ( cdata->lastpos==vc->ycur*vc->xchars+vc->xchars) + { + vc->ycur++; + vc->xcur = 0; + cdata->flags &= ~F_LASTCHAR; + do_scrollcheck(vc); + } + else + { + cdata->flags &= ~F_LASTCHAR; + } + } + + switch (c) + { + case 0x00: /* NUL */ + case 0x01: /* SOH */ + case 0x02: /* STX */ + case 0x03: /* ETX */ + case 0x04: /* EOT */ + case 0x05: /* ENQ */ + case 0x06: /* ACK */ + break; + + case 0x07: /* BEL */ + beep_generate(); + if ( !cdata->beepoff ) + c = 'G'; + break; + + case 0x08: /* BS */ + cdata->flags &= ~F_LASTCHAR; + if ( vc->xcur>0 ) + vc->xcur--; + break; + + case 0x09: /* TAB */ + while ( vc->xcur < vc->xchars-1 ) + { + vc->xcur++; + if (cdata->tab_stops[vc->xcur]) + break; + } + break; + + case 0x0a: + cdata->flags &= ~F_LASTCHAR; + vc->ycur++; + do_scrollcheck ( vc ); + break; + + case 0x0c: + cdata->flags &= ~F_LASTCHAR; + if ((vc->flags&LOSSY)==0) + mapped_cls(vc); + if (vc==vconsole_current) + vc->CLS(vc); + vc->xcur=0; + vc->ycur=0; + + break; + case 0x0d: + cdata->flags &= ~F_LASTCHAR; + vc->xcur=0; + break; + + case 0x10: /* DLE */ + case 0x11: /* DC1/XON */ + case 0x12: /* DC2 */ + case 0x13: /* DC3/XOFF */ + case 0x14: /* DC4 */ + case 0x15: /* NAK */ + case 0x16: /* SYN */ + case 0x17: /* ETB */ + break; + + case 0x18: /* CAN */ + cdata->state = STATE_INIT; + clr_params(cdata); + break; + + case 0x19: /* EM */ + break; + + case 0x1a: /* SUB */ + cdata->state = STATE_INIT; + clr_params(cdata); + break; + + case 0x1b: /* ESC */ + cdata->state = STATE_ESC; + clr_params(cdata); + break; + + case 0x1c: /* FS */ + case 0x1d: /* GS */ + case 0x1e: /* RS */ + case 0x1f: /* US */ + break; + } + } + } + else + { + /* 0x20 to 0xff depends on current state */ + switch ( cdata->state ) + { + case STATE_INIT: + do_render ( c, vc ); + break; + + case STATE_ESC: +#ifdef DEBUGTERM +{ + char buf[]="x"; + buf[0] = c; + dprintf ( buf ); +} +#endif + switch (c) + { + case '7': /* SAVE CUSOR */ + vt_sc ( vc ); + cdata->state = STATE_INIT; + break; + + case '8': /* RESTORE CUSOR */ + vt_rc ( vc ); + cdata->state = STATE_INIT; + break; + + case '=': + vt_keyappl ( vc ); + cdata->state = STATE_INIT; + break; + + case '>': /* Keypad numeric mode */ +#ifdef DEBUGTERM +dprintf ( "\r\nKEYPAD NUMERIC MODE\r\n "); +#endif + cdata->state = STATE_INIT; + break; + + case 'D': + vt_ind ( vc ); + cdata->state = STATE_INIT; + break; + + case 'E': + vt_nel ( vc ); + cdata->state = STATE_INIT; + break; + + case 'H': + cdata->tab_stops[vc->xcur] = 1; + cdata->state = STATE_INIT; + break; + + case 'M': + vt_ri ( vc ); + cdata->state = STATE_INIT; + break; + + case 'N': + cdata->Gs = cdata->G2; + cdata->ss = 1; + cdata->state = STATE_INIT; + break; + + case 'O': + cdata->Gs = cdata->G3; + cdata->ss = 1; + cdata->state = STATE_INIT; + break; + + case 'P': + cdata->dcs_state = DCS_INIT; + cdata->state = STATE_DCS; + break; + + case 'Z': + vt_da ( vc ); + cdata->state = STATE_INIT; + break; + + case '~': + cdata->GR = cdata->G1; + cdata->state = STATE_INIT; + break; + + case '[': + clr_params ( cdata ); + cdata->state = STATE_CSI; + break; + + case '\\': + cdata->state = STATE_INIT; + break; + + case 'c': + vt_ris ( vc ); + cdata->state = STATE_CSI; + break; + + case 'n': + cdata->GL = cdata->G2; + cdata->state = STATE_INIT; + break; + + case 'o': + cdata->GL = cdata->G3; + cdata->state = STATE_INIT; + break; + + case '}': + cdata->GR = cdata->G2; + cdata->state = STATE_INIT; + break; + + case '|': + cdata->GR = cdata->G3; + cdata->state = STATE_INIT; + break; + + default: + do_render ( c, vc ); + cdata->state = STATE_INIT; + break; + } + break; + + case STATE_CSIQM: +#ifdef DEBUGTERM +{ + char buf[]="x"; + buf[0] = c; + dprintf ( buf ); +} +#endif + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': /* parameters */ + cdata->param[cdata->parami] *= 10; + cdata->param[cdata->parami] += (c-'0'); + break; + + case ';': /* next parameter */ + cdata->parami = + (cdata->parami+1 < MAXPARMS) ? + cdata->parami+1 : cdata->parami; + break; + + case 'h': + vt_set_dec_priv_qm ( vc ); + cdata->state = STATE_INIT; + break; + + case 'l': + vt_reset_dec_priv_qm ( vc ); + cdata->state = STATE_INIT; + break; + + case 'n': + vt_dsr ( vc ); + cdata->state = STATE_INIT; + break; + + case 'K': + vt_sel ( vc ); + cdata->state = STATE_INIT; + break; + + default: + do_render ( '[', vc ); + do_render ( c, vc ); + cdata->state = STATE_INIT; + { + register int counter; + for ( counter=0; counter<=cdata->parami; counter++ ) + { + do_render ( '@', vc ); + } + } + do_render ( c, vc ); + break; + } + + case STATE_CSI: +#ifdef DEBUGTERM +{ + char buf[]="x"; + buf[0] = c; + dprintf ( buf ); +} +#endif + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': /* parameters */ + cdata->param[cdata->parami] *= 10; + cdata->param[cdata->parami] += (c-'0'); + break; + + case ';': /* next parameter */ + cdata->parami = + (cdata->parami+1 < MAXPARMS) ? + cdata->parami+1 : cdata->parami; + break; + + case '?': /* ESC [ ? family */ + cdata->state = STATE_CSIQM; + break; + + case '@': /* insert char */ + vt_ic ( vc ); + cdata->state = STATE_INIT; + break; + + /* + case '!': + cdata->state = STATE_STR; + break; + */ + + case 'A': /* cursor up */ + vt_cuu ( vc ); + cdata->state = STATE_INIT; + break; + + case 'B': /* cursor down */ + vt_cud ( vc ); + cdata->state = STATE_INIT; + break; + + case 'C': + vt_cuf ( vc ); + cdata->state = STATE_INIT; + break; + + case 'D': /* cursor back */ + vt_cub ( vc ); + cdata->state = STATE_INIT; + break; + + case 'H': /* direct cursor addressing */ + vt_curadr ( vc ); + cdata->state = STATE_INIT; + break; + + case 'J': /* erase screen */ + vt_clreos ( vc ); + cdata->state = STATE_INIT; + break; + + cdata->state = STATE_INIT; + break; + + case 'K': /* erase line */ + vt_clreol ( vc ); + cdata->state = STATE_INIT; + break; + + case 'L': /* insert line */ + vt_il ( vc ); + cdata->state = STATE_INIT; + break; + + case 'M': /* delete line */ + vt_dl ( vc ); + cdata->state = STATE_INIT; + break; + + case 'P': /* Delete chars */ + vt_dch ( vc ); + cdata->state = STATE_INIT; + break; + + case 'S': /* scroll up */ + vt_su ( vc ); + cdata->state = STATE_INIT; + break; + + case 'c': + vt_da ( vc ); + cdata->state = STATE_INIT; + break; + + case 'f': + vt_curadr ( vc ); + cdata->state = STATE_INIT; + break; + + case 'h': + vt_set_ansi ( vc ); + cdata->state = STATE_INIT; + break; + + case 'l': + vt_reset_ansi ( vc ); + cdata->state = STATE_INIT; + break; + + case 'm': /* select graphic rendition */ + vt_sgr( vc ); + cdata->state = STATE_INIT; + break; + + case 'n': + vt_dsr ( vc ); + cdata->state = STATE_INIT; + break; + + case 'r': /* set scrolling region */ + vt_stbm ( vc ); + cdata->state = STATE_INIT; + break; + + case 'y': + vt_tst ( vc ); + cdata->state = STATE_INIT; + break; + + default: + do_render ( '[', vc ); + do_render ( c, vc ); + cdata->state = STATE_INIT; + { + register int counter; + for ( counter=0; counter<=cdata->parami; counter++ ) + { + do_render ( '@', vc ); + } + } + do_render ( c, vc ); + cdata->state = STATE_INIT; + break; + } + break; + + default: + cdata->state = STATE_INIT; + break; + } + } + } +#ifdef SIMPLE_CURSOR + if ( vc==vconsole_current ) + if ( vc->CURSORUPDATE(vc)==-1 ) + simple_cursor_on ( vc ); +#else + if ( vc==vconsole_current ) + vc->CURSORUPDATE (vc); +#endif + return 0; +} + +void +console_debug() +{ +} + +int +vt220_swapin(vc) + struct vconsole *vc; +{ +#ifdef SIMPLE_CURSOR + if ( vc==vconsole_current ) + if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_on ( vc ); +#else + if ( vc==vconsole_current ) + vc->CURSORUPDATE (vc); +#endif + return 0; +} + +int +vt220_swapout(vc) + struct vconsole *vc; +{ + return 0; +} + + +int +vt220_sleep(vc) + struct vconsole *vc; +{ +#ifdef SIMPLE_CURSOR + if ( vc==vconsole_current ) + if ( vc->CURSORUPDATE(vc)==-1 ) simple_cursor_off ( vc ); +#else + if ( vc==vconsole_current ) + vc->CURSORUPDATE (vc); +#endif + vc->FLASH ( vc, 0 ); + vc->CURSOR_FLASH ( vc, 0 ); + return 0; +} + +int +vt220_wake(vc) + struct vconsole *vc; +{ + vc->FLASH ( vc, 1 ); + vc->CURSOR_FLASH ( vc, 1 ); + +#ifdef SIMPLE_CURSOR + if ( vc==vconsole_current ) + if ( vc->CURSORUPDATE(vc)==-1 ) + simple_cursor_on ( vc ); +#else + if ( vc==vconsole_current ) + vc->CURSORUPDATE (vc); +#endif + return 0; +} + +int +vt220_scrollback(vc) + struct vconsole *vc; +{ + return -1; +} + +int +vt220_scrollforward(vc) + struct vconsole *vc; +{ + return -1; +} + +int +vt220_scrollbackend(vc) + struct vconsole *vc; +{ + return -1; +} + +int +vt220_debugprint(vc) + struct vconsole *vc; +{ + printf ( "VT220 TERMINAL EMULATOR\n\n" ); + printf ( "no information\n" ); + printf ( "\n" ); + return 0; +} + +int +vt220_modechange(vc) + struct vconsole *vc; +{ + if (vc->number >= 64) + return(0); + + if (vc == NULL) { + return(EINVAL); + } + vt_str ( vc ); + if (vc->charmap) + { + free ( vc->charmap, M_DEVBUF ); + + MALLOC (vc->charmap, int *, sizeof(int)*((vc->xchars)*(vc->ychars)), M_DEVBUF, M_NOWAIT ); + if ((vc->flags&LOSSY)==0) + mapped_cls(vc); + if (vc==vconsole_current) + vc->CLS(vc); + vc->xcur=0; + vc->ycur=0; + } + + return 0; +} + +int +vt220_attach(vc, a, b, aux) + struct vconsole *vc; + struct device *a; + struct device *b; + void *aux; +{ + return 0; +} + +struct terminal_emulator vt220 = { + vt220_name, + vt220_init, + vt220_putstring, + vt220_swapin, + vt220_swapout, + vt220_sleep, + vt220_wake, + vt220_scrollback, + vt220_scrollforward, + vt220_scrollbackend, + vt220_debugprint, + vt220_modechange, + vt220_attach +}; diff --git a/sys/arch/arm32/dev/console/vt220.h b/sys/arch/arm32/dev/console/vt220.h new file mode 100644 index 00000000000..ef877f0919d --- /dev/null +++ b/sys/arch/arm32/dev/console/vt220.h @@ -0,0 +1,117 @@ +/* $NetBSD: vt220.h,v 1.2 1996/03/18 19:33:12 mark Exp $ */ + +/* + * Copyright (c) 1994-1995 Melvyn Tang-Richardson + * Copyright (c) 1994-1995 RiscBSD kernel team + * 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 kernel team + * 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 RISCBSD TEAM ``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 AUTHORS 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 + * + * vt220.h + * + * VT220 emulation header file + * + * Created : 17/09/94 + */ + +#define MAXTABSTOPS 132 + +#define STATE_INIT 0 +#define STATE_HASH 1 +#define STATE_BROPN 2 +#define STATE_BRCLO 3 +#define STATE_STAR 4 +#define STATE_PLUS 5 +#define STATE_MINUS 6 +#define STATE_DOT 7 +#define STATE_SLASH 8 +#define STATE_AMPSND 9 +#define SHP_INIT 10 +#define STATE_ESC 11 +#define STATE_CSIQM 14 +#define STATE_CSI 15 +#define STATE_DCS 16 +#define STATE_SCA 17 +#define STATE_STR 18 + +/* sub-states for Device Control String processing */ + +#define DCS_INIT 0 /* got ESC P ... */ +#define DCS_AND_UDK 1 /* got ESC P ... | */ +#define DCS_UDK_DEF 2 /* got ESC P ... | fnckey / */ +#define DCS_UDK_ESC 3 /* got ESC P ... | fnckey / ... ESC */ +#define DCS_DLD_DSCS 4 /* got ESC P ... { */ +#define DCS_DLD_DEF 5 /* got ESC P ... { dscs */ +#define DCS_DLD_ESC 6 /* got ESC P ... { dscs ... / ... ESC */ + +#define F_AWM (1) +#define F_LASTCHAR (2) +#define F_IRM (3) + +#define MAXPARMS 10 + +struct vt220_info { + int tab_stops[MAXTABSTOPS]; + int state; + int hp_state; + int disable_function; + int lastchar; + int beepoff; + int param[MAXPARMS]; + int parami; + u_char m_om, sc_om; /* flag, vt100 mode, origin mode */ + u_char scrr_beg; + u_char scrr_len; + u_char scrr_end; + int simple_cursor_store; + int simple_cursor_on; + + int dcs_state; + + int G0, G1, G2, G3, GL, GR, sc_G0, sc_G1, sc_G2, sc_G3, sc_GL, sc_GR; + int Gs, ss; + int xcur, ycur, sc_xcur, sc_ycur; + int sc_flag; + + char *report_chars; + int report_count; + int cursor_on; + + int fgcol, bgcol; + int nfgcol, nbgcol; + + int attribs; + int flags; + int sflags; + + int lastpos; + int irm; +}; + diff --git a/sys/arch/arm32/dev/rd_hooks.c b/sys/arch/arm32/dev/rd_hooks.c new file mode 100644 index 00000000000..7aa97324645 --- /dev/null +++ b/sys/arch/arm32/dev/rd_hooks.c @@ -0,0 +1,98 @@ +/* $NetBSD: rd_hooks.c,v 1.5 1996/03/28 21:14:13 mark 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 +#include +#include + +#include +#include +#include + +#include + +#ifndef RAMDISK_SIZE +#define RAMDISK_SIZE 0 +#endif + +/*extern int boothowto;*/ +extern u_int ramdisc_size; +struct rd_conf *bootrd = NULL; + +int load_ramdisc_from_floppy __P((struct rd_conf *rd, dev_t dev)); + +/* + * This is called during autoconfig. + */ +int +rd_match_hook(parent, self, aux) + struct device *parent; + void *self; + void *aux; +{ + return (1); +} + +void +rd_attach_hook(unit, rd) + int unit; + struct rd_conf *rd; +{ + if (unit == 0) { + if (ramdisc_size == 0 && RAMDISK_SIZE) + ramdisc_size = (RAMDISK_SIZE * 1024); + + if (ramdisc_size != 0) { + rd->rd_size = round_page(ramdisc_size); + rd->rd_addr = (caddr_t)kmem_alloc(kernel_map, ramdisc_size); + rd->rd_type = RD_KMEM_FIXED; + bootrd = rd; + } + } + printf("rd%d: allocated %dK (%d blocks)\n", unit, rd->rd_size / 1024, rd->rd_size / DEV_BSIZE); +} + + +/* + * This is called during open (i.e. mountroot) + */ + +void +rd_open_hook(unit, rd) + int unit; + struct rd_conf *rd; +{ +/* I use the ramdisc for other testing ... */ +#if 0 + if (unit == 0) { + /* The root ramdisk only works single-user. */ + boothowto |= RB_SINGLE; + } +#endif +} diff --git a/sys/arch/arm32/doc/bootloader b/sys/arch/arm32/doc/bootloader new file mode 100644 index 00000000000..4bab605b630 --- /dev/null +++ b/sys/arch/arm32/doc/bootloader @@ -0,0 +1,12 @@ +Currently the bootloader can only be built under RiscOS as this +is the platform which it runs on. A spark file version of the +bootloader source code is also available + +[ From boot/README ] +Ok, this is the bootloader source that can be used to boot NetBSD/arm32 +from RISCOS. This code was written for use with Norcroft C and +objasm under RISCOS. It has been modified to compile under NetBSD/arm32 +but is as yet untested. + +It is provided here for the moment as example code for a boot loader +and will be updated shortly to compile under NetBSD/arm32 diff --git a/sys/arch/arm32/doc/history b/sys/arch/arm32/doc/history new file mode 100644 index 00000000000..5180a93e7b1 --- /dev/null +++ b/sys/arch/arm32/doc/history @@ -0,0 +1,451 @@ +3135 - fixed mode selection on boot + - page up/down, insert and delete now generate the correct codes in + the console + - the configured modesare now compiled in a separate file rather + than in vidcconsole.c + - The eb timeout reduced to 30 secs + + - clreos problems fixed + - / on the keypad generated the correct code + - the block cursor hove down 2 scan lines to align with characters + - extended irq renamed netslot + - extra double mapping of kstack removed + - kstack located at efbfe000 + - implementation of cpu_swapin() to remap the kstack + - patch to vm_glue to use kmem_alloc for the kstack + - extra pmap debugging code added with DEBUG669 + - the pventry tables can not be dumped from the kshell + or from a running system. + + - merged console code v133 into kernel + - the disklabel code no longer prints a warning if a HD is found + without a adfs partition + - the kbd driver now is capable of setting the keyboard leds. + - added ioctl to set the keyboard leds. + - added a routine to read the keyboard state. + - added a routine to set the keyboard state. + - added some prototypes to kbd.h + - implmented irq_setmasks() as an assembly function. + - added an extra disable irq mask + - the irq bits from IOMD reg A are cleared as soon as req A is read + - Debugged the plip driver. The ip packet is now word aligned when + passed to the upper network levels + +20/09/95 + - the cpu_switch routine checks the amount of stack space used when + swapping in a task and prints a warning when 6K has been used + - removed the remnants of the old kstack double mapping + - a separate message is printed for umounts during a halt. + - added extra validation in copyin() copyout() copyinstr() and + copyoutstr() + - podule irq handler no longer panics + - Lark A16 podule now recognised + - section permission faults now cause bus errors + - the syscall handler now correctly uses bcopy to copy the register + passed parameters + - the copyin() function now validates the uaddrs argumant + - the kstack is filled with a know pattern on a fork() + - the postmortem code will check the size of the kstack fill pattern + - the assembly bcopyinout() now returns EFAULT on error + - the copyin() copyout() copyinstr() copyoutstr() now return EFAULT + if the validation checks fail. +23/09/95 + - the fault handler will report faults from (fu/su)iwintr() + - added new pmap function to return the address of the next physical + page (pmap_next_phys_page). + - added code to machdep.c to compare the page number against + pmap_next_phys_page() to try and locate source to kernel size + limit + - added option to syscall_special (32) to return the address of the + next physical page. + - fixed the primary bootstrap to map more memory for the secondary + bootstrap to use. + - The 936K kernel size limit has been removed. + - Added support for KTRACE in syscall.c + - Seondary bootstrap now zeros down its memory + - cpu_switch now zeros curpcb while there is no valid process + - +1/10/95 + - cpuswitch now detects trahsed stacks. + - new compile option for generation of enhanced postmortem debugging + - merged console code 183b + - implemented a memcpy routine + - removed remnants of the kstackpte's + - cleaned old commented debugging code out of cpu_switch + - Added new comments in exception.S + - userret() check for a non-zero proc pointer + - extended postmortem debug for cpu_switch bug + - updated prototype declarations in machdep.c + - fixed passing of proc0 pointer into cpu_switch from switch_exit + - podulebus now recognised Lingenuity podules + - Lingenuity 16bit SCSI card recognised + +3/10/95 + - new compile option ROTTEN_INARDS to dump full debugging info on + postmortem + - Rewritten postmortem debug information printout + - Postmortem will now examine the IRQ stack for traceback info + - Fix cpu_exit() bug thus could result in the idle being entered at + splhigh() + - Added function prototypes for functions called in vm_machdep.c + - boot0() now makes sure IRQ's and FIQ's have been disabled + - The ARM700 FPA is now correctly turned off during boot + - A major has been allocated for the vidcaudio device (36) + - vidcaudio.c added to mainbus/ and associated support added in + conf/ and conf.c + - Patch to the console code to report the version number + - Latest version of dev/isa/com.c merged into mainbus/com.c + - Latest version of dev/isa/lpt.c merged into mainbus/lpt.c + - Latest version of dev/isa/wd.c merged into mainbus/wd.c + - new assembly version of copystr added + - buffer address for beep0 removed from attach message + - unrecognised undefined instructions are now logged as errors to + syslog + - fpe now attaches a coproc2 handler to stap coproc2 FP instructions + and report an error + - New compile option FPE_INLINE added to fpe.c to inline some of the + conversion functions + - Added new compile option FPE_PROF to fpe.c to compile in FP profiling + code + - + +14/10/95 + - added podule id for laser direct card + - added podule id for morley SCSI card + - added podule id for AXRE SCSI card + - added podule id for CC midi max card + - modified primary/secondary bootstraps to reserve special boot + - memory for hydra board + - added hydra device + - Added cpu identification for all hydra processors + - Private stacks are allocated to all slave processors + - All hydra processors are halted on reboot + - podule code checks for chunk directories but does not try to read + them yet. + - polling, immediate execution asc driver written for Acorn SCSI + card + - new special syscalls added to aid development of hydra software + +01/11/95 + - kernel built with new netbsd-current source tree + - arm32 source updated to conform to latest netbsd-current source + tree + +03/11/95 + - ALT-Cursor Left/Right now work the correct way round + - ALT-F6 now gernerates the correct code + - alpha version of the cumana SCSI II driver added + - alpha version of the ether1 driver added + - console code upgraded to V191 + - driver directory structure changed. + - ./src/patch directory updated + - alpha version of ATAPI CDROM driver added + - mainbus and podulebus directories split in to public and private + directories. + - warnings from validate_trapframe() are prefixed with "VTF" + - old rpc console stuff removed from files.arm32 and source moved to + arch/arm32/old/ + - the arch/arm32/pmap_stuff dir has been moved to arch/arm32/old/ + - the _mcount.S and belgium.S files have been moved to old and + removed from files.arm32 + - the device name to major code in autoconf.c now recognised /dev/cd + and /dev/wcd + - the mountroot code in stubs.c will call cd9660_mountroot() instead + of ffs_mountroot() is the root dev is a CDROM major. + - major 36 allocated to audio device + - major 37 allocated to vidcvideo device + - major 38 allocated to hydra device + + +07/11/95 + - cpu_fork() now maps in a page table for each process covering the + 0M-4M block of memory. + - VM_MIN_ADDRESS lowered to 0x1000 + - cpu_swapout() unmaps the system page at 0x00000000 from its page + table + - cpu_swapin() wires down the pagetable covering 0x00000000 and + maps in the system page at 0x00000000 + - cpu_swapin() and cpu_swapout() moved to vm_machdep.c + - pmap_enter_pv() no longer panics on duplicate mapping, it just + prints an warning. + - alpha version of the powertec SCSI driver + +15/11/95 + - switch_exit now unmaps the system page. + - added newline to printf in disksubr.c + - the console code has been moved to the dev directory + - cumana SCSI II driver upgraded to support interrupts + - powertec SCSI II driver upgraded to support interrupts + - the mount root code in stubs.c will attempt to mount + a hd partition as cd9660 if the ffs_mountroot() fails. + - added missing copyright notices + - updated some declarations in header files + - removed DEBUG669 code from pmap.c + - new syncing routine written for boot() + - syncing no longer requires kshell support + - Added extra comments to the boot() function + - Implemented cpu_sysctl() function (just returns not supported + error) + - The nosync kernel interrupt now correctly uses RB_NOSYNC + - + +20/11/95 + - restructure of directories contains device files + - fixed bug in pmap_pte() that could result in non-word + aligned pointers being returned in a off page boundry virtual + address was specified. + - + +24/11/95 + - merged in new netbsd-current source tree + - removed all the validate_trapframe() calls + - the ioctl CONSOLE_BLANKTIME now reloads the blank timer + - the ioctl CONSOLE_BLANKTIME uses the default blank time if a + negative time is specified. + - the machine id is now passed in the bootconfig structure + - the eb0 driver will set the MAC address from the machine id + if the address has not already been set. + +26/11/95 + - Fixed the definition of va_dcl in arm32/include/varargs.h + - + +02/12/95 + - Fixed the WriteShort() macro + - Removed some redundant code from machdep.c + - cpu_sysctl is now declared to return an int + - stubs.c now has prototypes for the floppy driver functions it + calls when loading the ramdisc. + - further debugging work on the ether3 driver + +10/12/95 + - Added uk device for unknown scsi devices to configuration files + and conf.c + - Alpha version of the ether3 ea device driver + +14/12/95 + - Merged in beta version of the ether1 (ie) device driver + - added ifdefs to stubs.c so the cd9660_mountroot() is only called + when the kernel is compiled with CD9660 + - created new text file to track all major and minor numbers + +16/12/95 + - define __FORK_BRAINDAMAGE for compilation with the latest NetBSD + sources + - boot() now calls doshutdownhooks() + - merged in frank's new debugger code (process_machdep.c, ptrace.h, + regs.h) + - patches stub.c to take account of frank's new code + - patch cpu.h to give more detail on the PSR bits + - fixed the setting of p->p_mdregs to point to the trapframe in + the kernel mapping of kstack rather than the current mapping. + - removed some redundant code from mem.c + - commented out all the trace_debug code + - cpu_coredump moved from stubs.c to vm_machdep.c + - implemented ptrace.S in libc + - boot() no longer sets the curproc to proc0 if it was zero. + - spl's added to the console locking code + - + +19/12/95 + - merged in new console code (V203) from Nut + - dosoftints() now calls pppintr() + +21/12/95 + - sys_sysarch() no longer panics but returns EINVAL instead. + - added 3 new debugging syscalls for tracing the vnode bug + - identified what goes wrong with vnodes resulting in a lockup + - fixed a number of source file headers + - Added new comments to a number of routines. + - readdisklabel() now sets the B_AGE flag on its buffer + - ether3 drive now reports the controller chip type + - removed all stand and glue code from kshell + - added a new debugging syscall to all wakeup() to be called + +24/12/95 + - removed redundant physconinit() call in initarm(). + - updated comments in machdep.c + - added support for mulitple swap devices to be specified at boot + time + - changed debugging output in userret() + - added extra debugging + - added new debugging syscalls for tracubg the vnode bug + - added new debugging commands to the kshell + - added a new insw16() function for faster block transfers + - created a patch to fix p_nice + - the wd driver now supports multisector transfers + - added a new outsw16() function for faster block transfers but is + currently untested + - the existing arm32/fpe directory has been renamed to + arm32/fpe-sp + - started work on integrating the ARM FPE + - a new fpe directory arm32/fpe-arm has been created for the new FPE + - file arm32/cpu.S renamed to arm32/cpuswitch.S + - created new mainbus device 'cpu' (mainbus/cpu.c) + - created new header file include/cpus.h to hold macros and + structure definitions for cpus. + - all identify functions for the processor and FPA have been moved + to mainbus/cpu.c + - FPE is now attached during the cpu attachment during + autoconfiguration + - Identification of CPU and FPU split into separate functions in + mainbus/cpu.c + - Added new function initialise_fpe() to fpe-sp/fpe.c This is the + new initialisation point for the FPE. All vector claiming is done + in this routine. Routine is also responcible for IDing the FPE. + - ramdisc memory allocation now only ever done in the ramdisc driver + - cpu_model now declared in mainbus/cpu.c + - rpc_configure() renamed to configure() + - added function need_proftick() to clock.c + - further development work ARM FPE driver + - glue code for ARM FPE written and tested. + - ARM FPE now gets first chance as being installed with + the existing FPE installed as a fallback if the ARM FPE + installation failed. + - Hooks for the ARM FPE added in cpu_fork() cpu_exit() and + cpu_switch() + - Recoding of ether3 driver started. + - More debugging code added to trace vnode bug + - macro added to syscall.c to handle exit from the syscall handler + for special development syscalls. + - Vnode bug idenitfied as a corruption of the first word (v_flag) + of certain vnodes. + - Ether3 driver rewritten and debugged. Now a beta stage driver + - Vnode corruption traced to console code. + - Ether3 drive now has interface buffer memory tests + - vnode corruption traced to do_scrolldown() routine in the + console driver. + - vnode corruption bug located and fixed. Incorrect loop start and + end points when scrolling the character map down (writing beyond + allocated memory). + - Started work on rewriting the etherB driver + - cleaned up various header files + - removed stub.c as it was no longer needed + - updated strstr.c + - hydra code hooks now only compiled in if hydra device is + configured + - EtherB driver rewritten to match recoding of ether3 driver + - EtherB driver now a beta stage driver + - Work started on generic driver code for SEEQ EDLC's + - vidcvideo device now supports multiple openings + - EtherB driver now puts the controller to sleep when not active + - strstr() replaced with version borrowed from libc/string/strstr.c + +05/01/96 + - Further development of ARM FPE + - generic fas216 code no longer experimental/NDA + - powertec scsi driver no longer experimental/NDA + - entry to undefined instruction handlers is now indirected in + exception.s + - entry to the undefined instruction handlers is made a trapframe + on the stack and r0-r12 preserved from exception. + - bounce code added so the existing undefined instuction handler + can be called with r0 pointing to the trapframe. + - new function arm_fpe_copycontext created + - fixed the use of FP instructions in sfas.c + - fixed errors in the softint code + - netns support can be be compiled in the kernel + - fixed warnings in fpe-sp/fpe.c and mainbus/cpu.c + +10/01/96 + - exception.S updated pending new undefined instruction handling + code + - merged in new wd driver from NetBSD-current + - merged in new com driver from NetBSD-current + - merged in new fd driver from NetBSD-current + - created new file sys_machdep.c for machine dependant syscall stuff + - moved sys_sysctl from machdep.c to sys_machdep.c + - fixed nested comments in iic.S + - removed old bug tracing code from cpuswitch.S + - debugged new fd driver + +13/01/96 + - undefined mode r13 added to the pcb structure + - new version of the ARM fpe built + - ARM FPE now has core deactivate routine accessable + - Call back from ARM FPE added on instruction completion + - cpu_switch() now switches UND32 mode r13 + - cpu_fork() now sets up UND32 mode r13 in pcb + - undefined vector now calls stub routine that indirects + via address held in data area. + - data abort handler address now held in data area rather + than text area. + - prefetch abort handler address now held in data area rather + than text area. + - disabled warnings about soft errors from the fd driver + +17/01/96 + - implemented pmap_resident_count() + - fixed the kernel avail_start and avail_end variable. This + fixes the divide by zero bug in /bin/ps + - ps now reports the correct resident size + +19/01/96 + - kernel now supports permission faults in UND32 mode. + - kernel shell now has kshell> prompt instead of # + - ramdisc loading code has been moved from stubs.c to fd.c + - ramdisc loading code now uses a rd_conf structure to + describe the ramdisc. + - rd_hooks.c file added to the arm32/dev directory in + order to support the generic ramdisk. + - patch to generic ramdisc driver to allow a device match hook + - mainbus/ramdisc.c removed. + - generic ramdisc has now replaces to mainbus/ramdisc. + - fault.c reformatted + - new compile symbols introduced to comile in debug code for + fault correction. + - all remnants of the trace_debug code removed. + - armfpe code moved from arm32/fpe-arm/arm32 to arm32/fpe-arm/ + - fu*() su*() functions moved from libkern into arm32/fusu.c + - added code to locore.S to traceback frames on the user process + stack + - added variable to enable / disable tracing back of user process + stacks + - added syscall to control user stack trackbacks. + - optimised ARM FPE exception delivery code + - implemented ARM FPE post processing callback glue + - ARM FPE post processor now calls user + - ARM FPE post processor optimised to recover some of the + performance lost by calling userret() + - integrated alpha version of the etherH driver + - updated ramdisc hooks to removed the need for a rd_match_hook() + function + - added Oak to the list of podule manufacturers + - kernel now reconised Oak SCSI I cards. + - Added generic NCR5380 SCSI driver code + - integrating in alpha version of the oak SCSI driver + +26/01/96 + - merged in latest updates from the NetBSD-current source tree + +29/01/96 + - code updated for merging into NetBSD source tree + +02/02/96 + - assembly symbol file now names assym.h instead of assym.s + - The symbol LOCORE has been replaced with _LOCORE + - ramdisc loading code in now compiled in conditionally on + RAMDISK_HOOKS + - Further development of hydrabus device. + - cpus can noe be attached to both the mainbus and the hydrabus + - hooks for hydrabus device updated in pmap.c syscall.c and + machdep.c + - Extra comments added in exception.S + - sizeof(struct trapframe) now defined in assym.h + - register fixup for data transfer instruction aborts now handles + LDC/STC instructions i.e. hardware executed LDF/STF + - configuration files updated for latest devices + - fixed use of mkdepend in makefile + - fixed the bug that caused panics when issuing the mode change + ioctl to the vidcvideo device + - console code version number updated + - Updated armfpe_post_proc() to take a trapframe pointer as the + second argument + - updated the armfpe_post_proc_glue() code to fake a trapframe + structure from the FPE frame before calling the post proc handler + so that sendsig has a valid trapframe in p->p_md.md_regs + - updated the armfpe_post_proc_glue() code to patch the FPE frame + with data from the trapframe on return from the post proc handler. + - signal delivery is now working during FP instructions. + - mondef code resurrected and renamed to setdisplay and moved to the + stand directory. diff --git a/sys/arch/arm32/doc/majors+minors b/sys/arch/arm32/doc/majors+minors new file mode 100644 index 00000000000..2b0463a09bd --- /dev/null +++ b/sys/arch/arm32/doc/majors+minors @@ -0,0 +1,246 @@ +/* $NetBSD: majors+minors,v 1.3 1996/04/19 20:04:29 mark Exp $ */ + +/* + * Copyright (c) 1994 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 + * + * majors + * + * list of all allocated major numbers + * + * Created : 17/09/94 + * Last updated : 30/12/95 + * + * $Id: majors+minors,v 1.1.1.1 1996/04/24 11:08:39 deraadt Exp $ + */ + +List of allocated and reserved major and minor numbers + +The block and character major numbers are ALWAYS allocated together to the +same device driver even if the driver does not require both. + + 0 B - reserved + 0 C - memory device + minor = 0 - /dev/mem + minor = 1 - /dev/kmem + minor = 2 - /dev/null + minor = 3 - /dev/zero + 1 B - swap device + 1 C - psuedo swap device + minor = 0 - /dev/drum + 2 B - reserved + 2 C - console device + minor = 0 - /dev/console + 3 B - reserved + 3 C - controlling terminal + minor = 0 - /dev/tty + 4 B - reserved + 4 C - virtual console + /dev/ttyv{unit} + unit = minor + 5 B - reserved + 5 C - kernel log device + minor = 0 - /dev/klog + 6 B - reserved + 6 C - psuedo tty master + /dev/pty{class}{unit} + unit = minor % 16 + minor / 16 = 0 - class = p + minor / 16 = 1 - class = q + minor / 16 = 2 - class = r + minor / 16 = 3 - class = s + minor / 16 = 4 - class = t + 7 B - reserved + 7 C - psuedo tty slave + /dev/tty{class}{unit} + unit = minor % 16 + minor / 16 = 0 - class = p + minor / 16 = 1 - class = q + minor / 16 = 2 - class = r + minor / 16 = 3 - class = s + minor / 16 = 4 - class = t + 8 B - reserved + 8 C - parallel printer + /dev/lp{class}{unit} + unit = minor & 0x1f + minor & 0x80 = 0x00 - class = t - interrupt driver + minor & 0x80 = 0x80 - class = a - polling driver + e.g. + 0 - /dev/lpt0 + 128 - /dev/lpa0 + 9 B - reserved + 9 C - quadrature mouse + minor = 0 - /dev/quadmouse +10 B - reserved +10 C - beep device + minor = 0 - /dev/beep +11 B - reserved +11 C - keyboard device + minor = 0 - /dev/kbd +12 B - reserved +12 C - serial port + /dev/tty0{unit} + unit = minor +13 B - reserver +13 C - reserved +14 B - reserved +14 C - reserved +15 B - reserved +15 C - reserved +16 B - ST506/ESDI/IDE disk + /dev/wd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +16 C - ST506/ESDI/IDE disk + /dev/rwd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +17 B - floppy disk + /dev/fd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +17 C - floppy disk + /dev/rfd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +18 B - ram disk + /dev/rd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +18 C - ram disk + /dev/rrd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +19 B - vnode disk driver + /dev/vnd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +19 C - vnode disk driver + /dev/rvnd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +20 B - reserved (ATAPI CDROM) + /dev/wcd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +20 C - reserved (ATAPI CDROM) + /dev/rwcd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +21 B - concatenated disk driver + /dev/ccd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +21 C - concatenated disk driver + /dev/rccd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +22 B - reserved +22 C - reserved +23 B - reserved +23 C - reserved +24 B - SCSI disk + /dev/sd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +24 C - SCSI disk + /dev/rsd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +25 B - SCSI tape +25 C - SCSI tape +26 B - SCSI cdrom + /dev/cd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +26 C - SCSI cdrom + /dev/rcd{unit}{partition} + partition = minor % 8 + unit = minor / 8 +27 B - reserved +27 C - SCSI autochanger + /dev/ch{unit} + unit = minor +28 B - reserved +28 C - SCSI unknown device + /dev/uk{unit} + unit = minor +29 B - reserved +29 C - SCSI scanner device + /dev/ss{unit} + unit = minor +30 B - reserved +30 C - reserved +31 B - reserved +31 C - reserved +32 B - reserved +32 C - Berkeley packet filter + /dev/bpf{unit} + unit = minor + minor = 0 - /dev/bpf0 + minor = 1 - /dev/bpf1 + minor = 2 - /dev/bpf2 + minor = 3 - /dev/bpf3 +33 B - reserved +33 C - network tunnel + /dev/tun{unit} + unit = minor + minor = 0 - /dev/tun0 + minor = 1 - /dev/tun1 + minor = 2 - /dev/tun2 +34 B - reserved +34 C - file descriptor pseudo-device + minor = 0 - /dev/stdin + minor = 1 - /dev/stdout + minor = 2 - /dev/stderr +35 B - reserved +35 C - loadable module driver + minor = 0 - /dev/lkm +36 B - reserved +36 C - generic audio device +37 B - reserved +37 C - vidcvideo device + minor = 0 - /dev/vidcvideo +38 B - reserved +38 C - cpu/hydra + minor = 0 - /dev/cpu0 +39 B - reserved +39 C - reserved +40 B - reserved +40 C - PS2 mouse + minor = 0 - /dev/pms +41 B - reserved +41 C - reserved +42 B - reserved +42 C - IIC device +43 B - reserved +43 C - RTC device diff --git a/sys/arch/arm32/doc/note.users b/sys/arch/arm32/doc/note.users new file mode 100644 index 00000000000..bfe56a9a2df --- /dev/null +++ b/sys/arch/arm32/doc/note.users @@ -0,0 +1,13 @@ +Ok there are a number of things that need to be done that I do not +have time to do and am unlikely to have time to do them in the near +future. +These are currently being left in the hope that users will do them +instead. + +1. replace netinet/in_cksum.c with an assembly version +2. replace netns/ns_chsum.c with an assembly version +3. drivers for currently unsupported podules +4. replacing the C string functions in libc with assembly ones (work + started but not finished) +5. porting libpthread to arm32 architecture + diff --git a/sys/arch/arm32/fpe-arm/armfpe.h b/sys/arch/arm32/fpe-arm/armfpe.h new file mode 100644 index 00000000000..fbcdaf46d10 --- /dev/null +++ b/sys/arch/arm32/fpe-arm/armfpe.h @@ -0,0 +1,137 @@ +/* + * $NetBSD: armfpe.h,v 1.3 1996/03/18 19:54:53 mark Exp $ + * + * Copyright (c) 1995 Neil A Carson. + * 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 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 + * + * armfpe.h + * + * Details of functions and structures needed for ARM FP cor + * support in RiscBSD + * + * Created : 04/01/96 + */ + +#ifndef __ARM32_ARM_FPE_H +#define __ARM32_ARM_FPE_H + +/************************************ Types ***********************************/ + +/* + * An extended precision floating point number + */ + +typedef struct { + u_int32_t exponent; + u_int32_t mantissa_hi; + u_int32_t mantissa_lo; +} fp_extended_precision_t; + +/* + * Type for a saved FP context, if we want to translate the context to a + * user-readable form + */ + +typedef struct fp_context_frame { + u_int32_t fpsr; + fp_extended_precision_t regs[8]; +} fp_context_frame_t; + +/************************************* Module *********************************/ + +typedef struct { + /* + * Addresses of procedures/functions + */ + + u_int32_t core_abort_addr; + u_int32_t core_initws_addr; + u_int32_t core_initcontext_addr; + u_int32_t core_changecontext_addr; + u_int32_t core_shutdown_addr; + u_int32_t core_activatecontext_addr; + u_int32_t core_deactivatecontext_addr; + u_int32_t core_savecontext_addr; + u_int32_t core_loadcontext_addr; + u_int32_t core_disable_addr; + u_int32_t core_enable_addr; + + /* + * Addresses of things that need to be filled in by the kernel on startup + */ + + u_int32_t *main_ws_ptr_addr; + u_int32_t *local_handler_ptr_addr; + u_int32_t *old_handler_ptr_addr; + u_int32_t *exc_handler_ptr_addr; + u_int32_t *fp_post_proc_addr; + + /* + * Numbers that the kernel needs - these are not pointers so do not need to + * be relocated! + */ + + u_int32_t WorkspaceLength; + u_int32_t ContextLength; +} arm_fpe_mod_hdr_t; + +/**************************** Procedures in arm_fpe.c *************************/ + +#ifdef _KERNEL + +/* macro to return the FP context for a process */ + +#define FP_CONTEXT(p) ((u_int)(((u_char *)(p)->p_addr) + sizeof(struct user))) + +/* Prototypes */ + +void arm_fpe_mod_reloc __P((void)); +int arm_fpe_boot __P((void)); +int initialise_arm_fpe __P((cpu_t *cpu)); +void arm_fpe_postproc __P((u_int fpframe, struct trapframe *frame)); +void arm_fpe_exception __P((int exception, u_int pc, u_int fpframe)); + +void arm_fpe_core_disable __P((void)); +void arm_fpe_core_enable __P((void)); +u_int arm_fpe_core_initws __P((u_int workspace, int handler1, int handler2)); +u_int arm_fpe_core_abort __P((u_int context, int r12, int pc)); +void arm_fpe_core_initcontext __P((u_int context)); +u_int arm_fpe_core_changecontext __P((u_int context)); +void arm_fpe_core_shutdown __P((void)); +void arm_fpe_core_activatecontext __P((u_int context)); +u_int arm_fpe_core_deactivatecontext __P((void)); +u_int arm_fpe_core_savecontext __P((u_int context, int *savearea, int pc)); +void arm_fpe_core_loadcontext __P((u_int context, int *loadarea)); +void arm_fpe_copycontext __P((u_int c1, u_int c2)); +#endif + +#endif diff --git a/sys/arch/arm32/fpe-arm/armfpe.s b/sys/arch/arm32/fpe-arm/armfpe.s new file mode 100644 index 00000000000..71066caa95e --- /dev/null +++ b/sys/arch/arm32/fpe-arm/armfpe.s @@ -0,0 +1,7459 @@ +/* $NetBSD: armfpe.s,v 1.2 1996/03/18 19:54:55 mark Exp $ */ + +/* + * Copyright (c) 1996 Neil A Carson. + * Copyright (c) 1996 Advanced Risc Machines Ltd. + * 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 kernel team. + * 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 + * + * armfpe.s + * + * ARM FPE core + * + * Created : 05/01/96 + */ + +/* DO NOT MODIFY - THIS FILE IS AUTOMATICALLY GENERATED. */ + +/* Generated from KernelFPE */ + +.text +.global _arm_fpe_mod +_arm_fpe_mod: + .word 0x00006cc0 + .word 0x00006e54 + .word 0x00006ebc + .word 0x00006f5c + .word 0x0000706c + .word 0x00006fd8 + .word 0x00006f64 + .word 0x00007140 + .word 0x0000722c + .word 0x0000707c + .word 0x000070d0 + .word 0x000072e4 + .word 0x000072fc + .word 0x00007314 + .word 0x00007364 + .word 0x000072e8 + .word 0x0000000c + .word 0x00000088 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0xe24dd040 + .word 0xe8cd7fff + .word 0xe58de03c + .word 0xe1a0c00d + .word 0xe10fa000 + .word 0xe14f9000 + .word 0xe92d0600 + .word 0xe319000f + .word 0xe24e9004 + .word 0x04b9b000 + .word 0x1599b000 + .word 0xe92d4000 + .word 0xeb001c90 + .word 0xe8bd0400 + .word 0xe8bd4000 + .word 0xe31b0302 + .word 0x0a000849 + .word 0xe20b9c0f + .word 0xe3590c01 + .word 0x1a000015 + .word 0xe59aa000 + .word 0xee509110 + .word 0xe2098c0f + .word 0xee307110 + .word 0xe08ff328 + .word 0x00000000 + .word 0xea001ca9 + .word 0xea001ca8 + .word 0xea001ca7 + .word 0xea001ca6 + .word 0xea000103 + .word 0xea0002b1 + .word 0xea00002e + .word 0xea0002af + .word 0xea00018f + .word 0xea0002b8 + .word 0xea00018d + .word 0xea0002b6 + .word 0xea0000fb + .word 0xea0002ad + .word 0xea000026 + .word 0xea0002ab + .word 0xe3590c02 + .word 0x1a00082e + .word 0xe59aa000 + .word 0xee509110 + .word 0xe2098c0f + .word 0xee307110 + .word 0xe08ff328 + .word 0x00000000 + .word 0xea001c91 + .word 0xea001c90 + .word 0xea001c8f + .word 0xea001c8e + .word 0xea0000e7 + .word 0xea000299 + .word 0xea000008 + .word 0xea000297 + .word 0xea00081b + .word 0xea0002a0 + .word 0xea000819 + .word 0xea00029e + .word 0xea0000df + .word 0xea000295 + .word 0xea000000 + .word 0xea000293 + .word 0xe3190010 + .word 0x13190601 + .word 0x0a00000d + .word 0xe59c803c + .word 0xe2488004 + .word 0xe58c803c + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe3190010 + .word 0x13190601 + .word 0x1a00011d + .word 0xe389b402 + .word 0xe3170b01 + .word 0x059c803c + .word 0x02488004 + .word 0x058c803c + .word 0xe10f8000 + .word 0xe3c88080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe31b0901 + .word 0x0d2d020c + .word 0x1d2d420c + .word 0xe20b8a03 + .word 0xe0888088 + .word 0xe08d8528 + .word 0xe8980007 + .word 0xe28dd030 + .word 0xe3c03103 + .word 0xe2000103 + .word 0xe20b8301 + .word 0xe18335a8 + .word 0xe3530903 + .word 0x22433801 + .word 0xe20b50e0 + .word 0xe20b8702 + .word 0xe18555a8 + .word 0xe20b4201 + .word 0xe31b0102 + .word 0x02644000 + .word 0xea00001e + .word 0x00003f81 + .word 0x0000407e + .word 0x00003f81 + .word 0x0000407e + .word 0x00003f81 + .word 0x0000407e + .word 0x00003f81 + .word 0x0000407e + .word 0x00003c01 + .word 0x000043fe + .word 0x00003c01 + .word 0x000043fe + .word 0x00003c01 + .word 0x000043fe + .word 0x00003c01 + .word 0x000043fe + .word 0x00000000 + .word 0x00007ffe + .word 0x00000000 + .word 0x00007ffe + .word 0x00000000 + .word 0x00007ffe + .word 0x00000000 + .word 0x00007ffe + .word 0xe3100101 + .word 0x1a00000f + .word 0xe20b50e0 + .word 0xe20b8702 + .word 0xe18555a8 + .word 0xe3a04000 + .word 0xeb000bbe + .word 0xe24f8084 + .word 0xe0888125 + .word 0xe8980300 + .word 0xe1530009 + .word 0xd1580003 + .word 0xca000015 + .word 0xe1800003 + .word 0xe3540000 + .word 0x11b08aa7 + .word 0x33877010 + .word 0x8b000d35 + .word 0xe92d0007 + .word 0xe20b8a07 + .word 0xe08f84a8 + .word 0xe1a0e00f + .word 0xe288f044 + .word 0xee207110 + .word 0xe92d4000 + .word 0xeb001c01 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe24fe05c + .word 0xe0588003 + .word 0xca000c8f + .word 0xea000c18 + .word 0xecbd8203 + .word 0xe1a0f00e + .word 0xecbd9203 + .word 0xe1a0f00e + .word 0xecbda203 + .word 0xe1a0f00e + .word 0xecbdb203 + .word 0xe1a0f00e + .word 0xecbdc203 + .word 0xe1a0f00e + .word 0xecbdd203 + .word 0xe1a0f00e + .word 0xecbde203 + .word 0xe1a0f00e + .word 0xecbdf203 + .word 0xe1a0f00e + .word 0xe20b3a0f + .word 0xe3530a0d + .word 0x2a000011 + .word 0xe79c6523 + .word 0xeb000f16 + .word 0xe20b50e0 + .word 0xe20b8702 + .word 0xe18555a8 + .word 0xe3a04000 + .word 0xeb000b84 + .word 0xe1800003 + .word 0xe3540000 + .word 0x11b08aa7 + .word 0x33877010 + .word 0x8b000d01 + .word 0xe92d0007 + .word 0xe20b8807 + .word 0xe08f86a8 + .word 0xe1a0e00f + .word 0xe248f08c + .word 0xeaffffca + .word 0xe3530a0f + .word 0x0a00000c + .word 0xe51c8008 + .word 0xe218800f + .word 0x0affffe8 + .word 0xe3888090 + .word 0xe10f9000 + .word 0xe3c9601f + .word 0xe1868008 + .word 0xe129f008 + .word 0xe3530a0d + .word 0x01a0600d + .word 0x11a0600e + .word 0xe129f009 + .word 0xeaffffdf + .word 0xe59c603c + .word 0xe2866008 + .word 0xeaffffdc + .word 0xe31b0702 + .word 0x131b0080 + .word 0x1a00076c + .word 0xe31b0010 + .word 0x0a000042 + .word 0xe20b860f + .word 0xe08ff928 + .word 0x00000000 + .word 0xeaffffcf + .word 0xea0000a0 + .word 0xea000764 + .word 0xea000763 + .word 0xea000762 + .word 0xea000761 + .word 0xea000760 + .word 0xea00075f + .word 0xea00075e + .word 0xea000081 + .word 0xea00075c + .word 0xea00007f + .word 0xea00075a + .word 0xea00007d + .word 0xea000758 + .word 0xea00007b + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00003fff + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004000 + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004000 + .word 0xc0000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004001 + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004001 + .word 0xa0000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00003ffe + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004002 + .word 0xa0000000 + .word 0x00000000 + .word 0x00000000 + .word 0xe3190010 + .word 0x13190601 + .word 0x0a000003 + .word 0xeaffff21 + .word 0xe3190010 + .word 0x13190601 + .word 0x1a00004a + .word 0xe389b402 + .word 0xe3170b01 + .word 0x059c803c + .word 0x02488004 + .word 0x058c803c + .word 0xe10f8000 + .word 0xe3c88080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe31b0902 + .word 0x1a000020 + .word 0xed2d420c + .word 0xed2d020c + .word 0xe20b8807 + .word 0xe0888088 + .word 0xe08d8728 + .word 0xe8980007 + .word 0xe1b09e8b + .word 0x208f8ca9 + .word 0x224880ec + .word 0x308d8da9 + .word 0x30888d29 + .word 0xe8980038 + .word 0xe28dd060 + .word 0xe24fefb7 + .word 0xe20b860f + .word 0xe08ff928 + .word 0x00000000 + .word 0xea0012b1 + .word 0xea0012e9 + .word 0xea0012af + .word 0xea0012ae + .word 0xea001327 + .word 0xea001326 + .word 0xea001616 + .word 0xea001615 + .word 0xea001120 + .word 0xea0012e1 + .word 0xea001321 + .word 0xea001320 + .word 0xea001912 + .word 0xea000706 + .word 0xea000705 + .word 0xea000704 + .word 0xe1b09e8b + .word 0x208f8ca9 + .word 0x22488f56 + .word 0x2a000004 + .word 0x5d2d020c + .word 0x4d2d420c + .word 0xe3c99102 + .word 0xe08d8da9 + .word 0xe0888d29 + .word 0xe8980007 + .word 0x328dd030 + .word 0xe24fefd6 + .word 0xe20b860f + .word 0xe08ff928 + .word 0x00000000 + .word 0xea0013d3 + .word 0xea0013d2 + .word 0xea0013d1 + .word 0xea0011f2 + .word 0xea00112c + .word 0xea0014cf + .word 0xea0014ce + .word 0xea001582 + .word 0xea001709 + .word 0xea001708 + .word 0xea001842 + .word 0xea001799 + .word 0xea001798 + .word 0xea001916 + .word 0xea0013f8 + .word 0xea0013ea + .word 0xe02b8009 + .word 0xe59f90f8 + .word 0xe1180009 + .word 0x1afffecf + .word 0xe10f8000 + .word 0xe3c88080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe31b0502 + .word 0x0a000016 + .word 0xed2d420c + .word 0xed2d020c + .word 0xe20b8807 + .word 0xe0888088 + .word 0xe08d8728 + .word 0xe8980007 + .word 0xe1b09e8b + .word 0x208f8ca9 + .word 0x22488f85 + .word 0x308d8da9 + .word 0x30888d29 + .word 0xe8980038 + .word 0xe28dd060 + .word 0xeb0013fb + .word 0xe20b3a0f + .word 0xe3330a0f + .word 0x1a000012 + .word 0xe51c8008 + .word 0xe3c8820f + .word 0xe206620f + .word 0xe1888006 + .word 0xe50c8008 + .word 0xeaffff0d + .word 0xe1b09e8b + .word 0x208f8ca9 + .word 0x22488f96 + .word 0x2a000004 + .word 0x5d2d020c + .word 0x4d2d420c + .word 0xe3c99102 + .word 0xe08d8da9 + .word 0xe0888d29 + .word 0xe8980007 + .word 0x328dd030 + .word 0xeb00141e + .word 0xe20b3a0f + .word 0xe3530a0d + .word 0x2a000001 + .word 0xe78c6523 + .word 0xeafffefc + .word 0xe3330a0f + .word 0x0affffe6 + .word 0xe51c8008 + .word 0xe218800f + .word 0x0afffff8 + .word 0xe3888090 + .word 0xe10f9000 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe3530a0d + .word 0x01a0d006 + .word 0x11a0e006 + .word 0xe129f009 + .word 0xeafffeed + .word 0x00ff00ff + .word 0xe10f8000 + .word 0xe3c88080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe31b0402 + .word 0x1affff2d + .word 0xe20b5501 + .word 0xe1a05725 + .word 0xe20b8902 + .word 0xe1855428 + .word 0xe3550d06 + .word 0x0a00005f + .word 0xe31b0901 + .word 0x0d2d020c + .word 0x1d2d420c + .word 0xe20b8a03 + .word 0xe0888088 + .word 0xe08d8528 + .word 0xe8980007 + .word 0xe28dd030 + .word 0xeb00069b + .word 0xe20b380f + .word 0xe51c8008 + .word 0xe218800f + .word 0x1a00001b + .word 0xe353080f + .word 0x2a00000d + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe3550080 + .word 0xe4a40004 + .word 0x24a41004 + .word 0x84a42000 + .word 0xeafffec3 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe3550080 + .word 0xe4a40004 + .word 0x24a41004 + .word 0x84a42000 + .word 0xeafffeb7 + .word 0xe353080d + .word 0x2a00000d + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe3550080 + .word 0x38840001 + .word 0x08840003 + .word 0x88840007 + .word 0xeafffea7 + .word 0xe353080f + .word 0x1a00000b + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe3550080 + .word 0x38840001 + .word 0x08840003 + .word 0x88840007 + .word 0xeafffe99 + .word 0xe3888090 + .word 0xe10f9000 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe129f009 + .word 0xe3550080 + .word 0x38840001 + .word 0x08840003 + .word 0x88840007 + .word 0xeafffe80 + .word 0xe31b0601 + .word 0x1a00005e + .word 0xe31b0901 + .word 0x0d2d020c + .word 0x1d2d420c + .word 0xe20b8a03 + .word 0xe0888088 + .word 0xe08d8528 + .word 0xe8980007 + .word 0xe28dd030 + .word 0xeb000775 + .word 0xe20b380f + .word 0xe51c8008 + .word 0xe218800f + .word 0x1a00001d + .word 0xe353080f + .word 0x2a00000e + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe3170b02 + .word 0xe4a40004 + .word 0xe4a41004 + .word 0xe4a42004 + .word 0x14a46000 + .word 0xeafffe60 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe3170b02 + .word 0xe4a40004 + .word 0xe4a41004 + .word 0xe4a42004 + .word 0x14a46000 + .word 0xeafffe53 + .word 0xe353080d + .word 0x2a00000c + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe3170b02 + .word 0x08840007 + .word 0x88840047 + .word 0xeafffe44 + .word 0xe353080f + .word 0x1a00000a + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe3170b02 + .word 0x08840007 + .word 0x88840047 + .word 0xeafffe37 + .word 0xe3888090 + .word 0xe10f9000 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe129f009 + .word 0xe3170b02 + .word 0x08840007 + .word 0x88840047 + .word 0xeafffe1f + .word 0xe20b380f + .word 0xe51c8008 + .word 0xe218800f + .word 0x1a00001f + .word 0xe353080f + .word 0x2a000015 + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe3170b02 + .word 0xe4b40004 + .word 0xe4b41004 + .word 0xe4b42004 + .word 0x14b46000 + .word 0xeb00085d + .word 0xe92d0007 + .word 0xe20b8a07 + .word 0xe08f84a8 + .word 0xe288805c + .word 0xe1a0e00f + .word 0xe248fb02 + .word 0xeafffe03 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffffea + .word 0xe353080d + .word 0x2a00000c + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe3170b02 + .word 0x08940007 + .word 0x88940047 + .word 0xeaffffe0 + .word 0xe353080f + .word 0x1a000007 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeafffff1 + .word 0xe3888090 + .word 0xe10f9000 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe129f009 + .word 0xeaffffdc + .word 0xe59a9084 + .word 0xe3190c02 + .word 0x1afffd6c + .word 0xeafffe48 + .word 0xee309110 + .word 0xe58a9080 + .word 0xed8a0200 + .word 0xed8a420c + .word 0xe59a9084 + .word 0xe3c99b02 + .word 0xe58a9084 + .word 0xe59c903c + .word 0xe2499004 + .word 0xe58c903c + .word 0xea0019cf + .word 0xe24dd040 + .word 0xe8cd7fff + .word 0xe58de03c + .word 0xe1a0c00d + .word 0xe10fa000 + .word 0xe14f9000 + .word 0xe92d0600 + .word 0xe319000f + .word 0xe24e9004 + .word 0x04b9b000 + .word 0x1599b000 + .word 0xe92d4000 + .word 0xeb0019af + .word 0xe8bd0400 + .word 0xe8bd4000 + .word 0xe31b0302 + .word 0x0a000568 + .word 0xe20b9c0f + .word 0xe3590c01 + .word 0x1a00048b + .word 0xe59aa000 + .word 0xe59a8084 + .word 0xe3380000 + .word 0x1a000481 + .word 0xe10f8000 + .word 0xe3c88080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe59a7080 + .word 0xe31b0402 + .word 0x1a0003bf + .word 0xe1a0948b + .word 0xe209920a + .word 0xe31b0902 + .word 0x13899101 + .word 0xe20b380f + .word 0xe353080f + .word 0x23899201 + .word 0xe51c8008 + .word 0xe218800f + .word 0x13899302 + .word 0xe2095103 + .word 0xe08ffca9 + .word 0x00000000 + .word 0xea00001e + .word 0xea000039 + .word 0xea000063 + .word 0xea000070 + .word 0xea0001ab + .word 0xea0001cc + .word 0xea000207 + .word 0xea00020e + .word 0xea000079 + .word 0xea000095 + .word 0xea0000bf + .word 0xea0000cd + .word 0xea000212 + .word 0xea000237 + .word 0xea000275 + .word 0xea00027c + .word 0xea0000d6 + .word 0xea0000f3 + .word 0xea00011d + .word 0xea00012c + .word 0xea000280 + .word 0xea0002a3 + .word 0xea0002de + .word 0xea0002e5 + .word 0xea000135 + .word 0xea000148 + .word 0xea000175 + .word 0xea000185 + .word 0xea0002e9 + .word 0xea0002fb + .word 0xea000323 + .word 0xea00032a + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb000535 + .word 0xe20b380f + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe4a40000 + .word 0xe58a7080 + .word 0xe92d4000 + .word 0xeb001964 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb000519 + .word 0xe20b380f + .word 0xe353080d + .word 0x2a00000a + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe8840001 + .word 0xea00031b + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xe8840001 + .word 0xea000303 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb0004ee + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe4a40000 + .word 0xea0002f5 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb0004e0 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe8840001 + .word 0xea0002e7 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb000527 + .word 0xe20b380f + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe4a40004 + .word 0xe4241004 + .word 0xe58a7080 + .word 0xe92d4000 + .word 0xeb001900 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb00050a + .word 0xe20b380f + .word 0xe353080d + .word 0x2a00000a + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe8840003 + .word 0xea0002b7 + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xe8840003 + .word 0xea00029f + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb0004df + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe4a40004 + .word 0xe4241004 + .word 0xea000290 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb0004d0 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe8840003 + .word 0xea000282 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb00051d + .word 0xe20b380f + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe4a40004 + .word 0xe4a41004 + .word 0xe4242008 + .word 0xe58a7080 + .word 0xe92d4000 + .word 0xeb00189a + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb0004ff + .word 0xe20b380f + .word 0xe353080d + .word 0x2a00000a + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe8840007 + .word 0xea000251 + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xe8840007 + .word 0xea000239 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb0004d4 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe4a40004 + .word 0xe4a41004 + .word 0xe4242008 + .word 0xea000229 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xe1a05ba5 + .word 0xeb0004c4 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe8840007 + .word 0xea00021b + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xeb00053f + .word 0xe20b380f + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe3170b02 + .word 0xe4a40004 + .word 0xe4a41004 + .word 0xe4a42004 + .word 0x14a46000 + .word 0xea000207 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xeb00052b + .word 0xe20b380f + .word 0xe353080d + .word 0x2a00000c + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe3170b02 + .word 0x08840007 + .word 0x18840047 + .word 0xea0001f3 + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xe3170b02 + .word 0x08840007 + .word 0x18840047 + .word 0xea0001d9 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xeb0004fd + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe3170b02 + .word 0xe4a40004 + .word 0xe4a41004 + .word 0xe4a42004 + .word 0x14a46000 + .word 0xea0001c8 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8980007 + .word 0xeb0004ec + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe3170b02 + .word 0x08840007 + .word 0x18840047 + .word 0xea0001b9 + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe4b40000 + .word 0xe1b00080 + .word 0xe1a01380 + .word 0xe1a00ba0 + .word 0x12800c7f + .word 0xe1a00060 + .word 0x13811102 + .word 0xe3a02000 + .word 0xe1b08c80 + .word 0x323884fe + .word 0x03800101 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8880007 + .word 0xe92d4000 + .word 0xeb0017cd + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe353080d + .word 0x2a000021 + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe8940001 + .word 0xe1b00080 + .word 0xe1a01380 + .word 0xe1a00ba0 + .word 0x12800c7f + .word 0xe1a00060 + .word 0x13811102 + .word 0xe3a02000 + .word 0xe1b08c80 + .word 0x323884fe + .word 0x03800101 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8880007 + .word 0xe92d4000 + .word 0xeb0017a9 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xe8940001 + .word 0xeaffffcf + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffffa2 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe8940001 + .word 0xeaffffbe + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe4b40004 + .word 0xe4342004 + .word 0xe1b00080 + .word 0x03320000 + .word 0xe1a01500 + .word 0xe1a00a20 + .word 0xe1811aa2 + .word 0xe1a02582 + .word 0x12800b1e + .word 0xe1a00060 + .word 0x13811102 + .word 0xe1b08b00 + .word 0x32288103 + .word 0x323885ff + .word 0x03800101 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8880007 + .word 0xe92d4000 + .word 0xeb00175a + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe353080d + .word 0x2a000024 + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe8940005 + .word 0xe1b00080 + .word 0x03320000 + .word 0xe1a01500 + .word 0xe1a00a20 + .word 0xe1811aa2 + .word 0xe1a02582 + .word 0x12800b1e + .word 0xe1a00060 + .word 0x13811102 + .word 0xe1b08b00 + .word 0x32288103 + .word 0x323885ff + .word 0x03800101 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8880007 + .word 0xe92d4000 + .word 0xeb001733 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xe8940005 + .word 0xeaffffcc + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffff9b + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe8940005 + .word 0xeaffffbb + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe4b40004 + .word 0xe4b41004 + .word 0xe4342008 + .word 0xe3c009fe + .word 0xe3c005ff + .word 0xe3110102 + .word 0x11e08000 + .word 0x11b08888 + .word 0x03800101 + .word 0x13c00101 + .word 0xe1818002 + .word 0xe1988880 + .word 0x03c00101 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8880007 + .word 0xe92d4000 + .word 0xeb0016e6 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe353080d + .word 0x2a000021 + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe8940007 + .word 0xe3c009fe + .word 0xe3c005ff + .word 0xe3110102 + .word 0x11e08000 + .word 0x11b08888 + .word 0x03800101 + .word 0x13c00101 + .word 0xe1818002 + .word 0xe1988880 + .word 0x03c00101 + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8880007 + .word 0xe92d4000 + .word 0xeb0016c2 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xe8940007 + .word 0xeaffffcf + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffffa0 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe8940007 + .word 0xeaffffbe + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe3170b02 + .word 0xe4b40004 + .word 0xe4b41004 + .word 0xe4b42004 + .word 0x14b46000 + .word 0xeb0004cf + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8880007 + .word 0xea000050 + .word 0xe353080d + .word 0x2a00000c + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe3170b02 + .word 0x08940007 + .word 0x18940047 + .word 0xeaffffeb + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xe3170b02 + .word 0x08940007 + .word 0x18940047 + .word 0xeaffffd1 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffffc4 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xe3170b02 + .word 0x08940007 + .word 0x18940047 + .word 0xeaffffbe + .word 0xe3100101 + .word 0x1a00000f + .word 0xe20b50e0 + .word 0xe20b8702 + .word 0xe18555a8 + .word 0xe3a04000 + .word 0xeb0005e4 + .word 0xe28f8070 + .word 0xe0888125 + .word 0xe8980300 + .word 0xe1530009 + .word 0xd1580003 + .word 0xca000013 + .word 0xe1800003 + .word 0xe3540000 + .word 0x11b08aa7 + .word 0x33877010 + .word 0x8b00075b + .word 0xe20b8a07 + .word 0xe08a8428 + .word 0xe8880007 + .word 0xe58a7080 + .word 0xe92d4000 + .word 0xeb001629 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe1a0d00c + .word 0xe8dc7fff + .word 0xe1a00000 + .word 0xe28dd03c + .word 0xe8fd8000 + .word 0xe24fe054 + .word 0xe0588003 + .word 0xca0006b7 + .word 0xea000640 + .word 0x00003f81 + .word 0x0000407e + .word 0x00003f81 + .word 0x0000407e + .word 0x00003f81 + .word 0x0000407e + .word 0x00003f81 + .word 0x0000407e + .word 0x00003c01 + .word 0x000043fe + .word 0x00003c01 + .word 0x000043fe + .word 0x00003c01 + .word 0x000043fe + .word 0x00003c01 + .word 0x000043fe + .word 0x00000000 + .word 0x00007ffe + .word 0x00000000 + .word 0x00007ffe + .word 0x00000000 + .word 0x00007ffe + .word 0x00000000 + .word 0x00007ffe + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00003fff + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004000 + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004000 + .word 0xc0000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004001 + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004001 + .word 0xa0000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00003ffe + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004002 + .word 0xa0000000 + .word 0x00000000 + .word 0x00000000 + .word 0xe31b0702 + .word 0x131b0080 + .word 0x1a000193 + .word 0xe31b0010 + .word 0x1a000036 + .word 0xe31b0902 + .word 0x1a00001b + .word 0xe20b8807 + .word 0xe08a8628 + .word 0xe8980007 + .word 0xe1b09e8b + .word 0x208f8ca9 + .word 0x224880b4 + .word 0x308a8ca9 + .word 0xe8980038 + .word 0xe20b860f + .word 0xe24fef6f + .word 0xe08ff928 + .word 0x00000000 + .word 0xea00095b + .word 0xea0009bf + .word 0xea000959 + .word 0xea000958 + .word 0xea000a5c + .word 0xea000a5b + .word 0xea001085 + .word 0xea001084 + .word 0xea000b8f + .word 0xea0009b7 + .word 0xea000a56 + .word 0xea000a55 + .word 0xea001381 + .word 0xea000175 + .word 0xea000174 + .word 0xea000173 + .word 0xe1b09e8b + .word 0x208f8ca9 + .word 0x22488f46 + .word 0x308a8ca9 + .word 0xe8980007 + .word 0xe20b860f + .word 0xe24fee22 + .word 0xe08ff928 + .word 0x00000000 + .word 0xea000c2b + .word 0xea000c2a + .word 0xea000c29 + .word 0xea000c67 + .word 0xea000ba1 + .word 0xea000f44 + .word 0xea000f43 + .word 0xea000ff7 + .word 0xea00117e + .word 0xea00117d + .word 0xea0012b7 + .word 0xea00120e + .word 0xea00120d + .word 0xea00138b + .word 0xea000c38 + .word 0xea000c26 + .word 0xe20b860f + .word 0xe08ff928 + .word 0x00000000 + .word 0xea000055 + .word 0xea00000d + .word 0xea00003a + .word 0xea000024 + .word 0xea000152 + .word 0xea000151 + .word 0xea000150 + .word 0xea00014f + .word 0xea00014e + .word 0xea00000c + .word 0xea00014c + .word 0xea00000a + .word 0xea00014a + .word 0xea000008 + .word 0xea000148 + .word 0xea000006 + .word 0xe1b09e8b + .word 0x208f8ca9 + .word 0x22488f72 + .word 0x308a8ca9 + .word 0xe8980007 + .word 0xe28fe04c + .word 0xea000cac + .word 0xe20b8807 + .word 0xe08a8628 + .word 0xe8980007 + .word 0xe1b09e8b + .word 0x208f8ca9 + .word 0x22488e1f + .word 0x308a8ca9 + .word 0xe8980038 + .word 0xeb000c8a + .word 0xe20b3a0f + .word 0xe3330a0f + .word 0x1a000007 + .word 0xe51c8008 + .word 0xe3c8820f + .word 0xe206620f + .word 0xe1888006 + .word 0xe50c8008 + .word 0xeaffff4f + .word 0xe1a06007 + .word 0xe20b3a0f + .word 0xe3530a0d + .word 0x2a000001 + .word 0xe78c6523 + .word 0xeaffff49 + .word 0xe3330a0f + .word 0x0afffff1 + .word 0xe51c8008 + .word 0xe218800f + .word 0x0afffff8 + .word 0xe3888090 + .word 0xe10f9000 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe3530a0d + .word 0x01a0d006 + .word 0x11a0e006 + .word 0xe129f009 + .word 0xeaffff3a + .word 0xe20b3a0f + .word 0xe3530a0d + .word 0x2a000003 + .word 0xe79c6523 + .word 0xe3c664ff + .word 0xe3867401 + .word 0xeaffff33 + .word 0xe3530a0f + .word 0x0a00000c + .word 0xe51c8008 + .word 0xe218800f + .word 0x0afffff6 + .word 0xe3888090 + .word 0xe10f9000 + .word 0xe3c9601f + .word 0xe1868008 + .word 0xe129f008 + .word 0xe3530a0d + .word 0x01a0600d + .word 0x11a0600e + .word 0xe129f009 + .word 0xeaffffed + .word 0xe59c603c + .word 0xe2866008 + .word 0xeaffffea + .word 0xe20b3a0f + .word 0xe3530a0d + .word 0x2a00000f + .word 0xe79c6523 + .word 0xeb000880 + .word 0xe20b50e0 + .word 0xe20b8702 + .word 0xe18555a8 + .word 0xe3a04000 + .word 0xeb0004ee + .word 0xe1800003 + .word 0xe3540000 + .word 0x11b08aa7 + .word 0x33877010 + .word 0x8b00066b + .word 0xe20b8807 + .word 0xe08a8628 + .word 0xe8880007 + .word 0xeaffff0e + .word 0xe3530a0f + .word 0x0a00000c + .word 0xe51c8008 + .word 0xe218800f + .word 0x0affffea + .word 0xe3888090 + .word 0xe10f9000 + .word 0xe3c9601f + .word 0xe1868008 + .word 0xe129f008 + .word 0xe3530a0d + .word 0x01a0600d + .word 0x11a0600e + .word 0xe129f009 + .word 0xeaffffe1 + .word 0xe59c603c + .word 0xe2866008 + .word 0xeaffffde + .word 0xe3a08000 + .word 0xe58a8084 + .word 0xe59c803c + .word 0xe2488004 + .word 0xe58c803c + .word 0xea00152f + .word 0xe3590c02 + .word 0x1a0000d7 + .word 0xe59aa000 + .word 0xe59a8084 + .word 0xe3380000 + .word 0x1afffff3 + .word 0xe10f8000 + .word 0xe3c88080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe31b0402 + .word 0x1a0000c9 + .word 0xe1a0958b + .word 0xe2099102 + .word 0xe20b380f + .word 0xe353080f + .word 0x23899101 + .word 0xe51c8008 + .word 0xe218800f + .word 0x13899202 + .word 0xe1a0548b + .word 0xe2055102 + .word 0xe31b0902 + .word 0x13855101 + .word 0xe08ffda9 + .word 0x00000000 + .word 0xea000006 + .word 0xea00001a + .word 0xea000045 + .word 0xea00004c + .word 0xea000053 + .word 0xea000070 + .word 0xea0000a4 + .word 0xea0000ab + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe20b3a07 + .word 0xe1a03883 + .word 0xe28a9000 + .word 0xe0898ca3 + .word 0xe8980007 + .word 0xe4a40004 + .word 0xe4a41004 + .word 0xe4a42004 + .word 0xe2833202 + .word 0xe2555101 + .word 0x1afffff7 + .word 0xeafffec0 + .word 0xe353080d + .word 0x2a000012 + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe20b3a07 + .word 0xe1a03883 + .word 0xe28a9000 + .word 0xe0898ca3 + .word 0xe8980007 + .word 0xe8a40007 + .word 0xe2833202 + .word 0xe2555101 + .word 0x1afffff9 + .word 0xeafffeab + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xeaffffde + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffffbf + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffffce + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe20b3a07 + .word 0xe1a03883 + .word 0xe28a9000 + .word 0xe4b40004 + .word 0xe4b41004 + .word 0xe4b42004 + .word 0xe3c009fe + .word 0xe3c005ff + .word 0xe3110102 + .word 0x11e08000 + .word 0x11b08888 + .word 0xe1818080 + .word 0x03800101 + .word 0xe1988002 + .word 0x03c00101 + .word 0xe0898ca3 + .word 0xe8880007 + .word 0xe2833202 + .word 0xe2555101 + .word 0x1affffee + .word 0xeafffe66 + .word 0xe353080d + .word 0x2a00001b + .word 0xe79c4723 + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x178c8723 + .word 0xe20b3a07 + .word 0xe1a03883 + .word 0xe28a9000 + .word 0xe8b40007 + .word 0xe3c009fe + .word 0xe3c005ff + .word 0xe3110102 + .word 0x11e08000 + .word 0x11b08888 + .word 0xe1818080 + .word 0x03800101 + .word 0xe1988002 + .word 0x03c00101 + .word 0xe0898ca3 + .word 0xe8880007 + .word 0xe2833202 + .word 0xe2555101 + .word 0x1afffff0 + .word 0xeafffe48 + .word 0xe51c8008 + .word 0xe218800f + .word 0xe10f9000 + .word 0xe3888090 + .word 0xe3c9401f + .word 0xe1848008 + .word 0xe129f008 + .word 0xe353080d + .word 0x01a0400d + .word 0x11a0400e + .word 0xe20b80ff + .word 0xe31b0502 + .word 0x10848108 + .word 0x00448108 + .word 0xe31b0401 + .word 0x11a04008 + .word 0xe31b0602 + .word 0x0a000002 + .word 0xe353080d + .word 0x01a0d008 + .word 0x11a0e008 + .word 0xe129f009 + .word 0xeaffffd5 + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffffad + .word 0xe59c403c + .word 0xe2844004 + .word 0xe31b0401 + .word 0x120b80ff + .word 0x10444108 + .word 0x131b0502 + .word 0x10844188 + .word 0xeaffffc5 + .word 0xe92d4000 + .word 0xeb001444 + .word 0xe8bd0400 + .word 0xe8bd4000 + .word 0xe91c0300 + .word 0xe129f009 + .word 0xe169f008 + .word 0xe59ab004 + .word 0xe59bb000 + .word 0xe59ca03c + .word 0xe28c9040 + .word 0xe9090e00 + .word 0xe919ffff + .word 0xe3550080 + .word 0x0a000093 + .word 0x8a0000b1 + .word 0xea000036 + .word 0xe3a05000 + .word 0xe3100101 + .word 0x1a000035 + .word 0xe3110102 + .word 0x01a0f00e + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe1924c01 + .word 0x1a00000a + .word 0xe28f8fc9 + .word 0xe8980300 + .word 0xe1530009 + .word 0xd1580003 + .word 0xc92d4000 + .word 0xca000023 + .word 0xe1800421 + .word 0xe3c00502 + .word 0xe2438dfe + .word 0xe1800b88 + .word 0xe1a0f00e + .word 0xe92d4000 + .word 0xe3a04000 + .word 0xe3a06000 + .word 0xeb0003e2 + .word 0xe28f8fba + .word 0xe8980300 + .word 0xe1530009 + .word 0xd1580003 + .word 0xca000015 + .word 0xe1800003 + .word 0xe3540000 + .word 0x11b08aa7 + .word 0x33877010 + .word 0x8b000540 + .word 0xe8bd4000 + .word 0xe1d18080 + .word 0x5a000006 + .word 0xe2300080 + .word 0xe1a08081 + .word 0xe1a084a8 + .word 0xe1880b80 + .word 0x53c00102 + .word 0x43800102 + .word 0xe1a0f00e + .word 0xe1b007c0 + .word 0x33c10102 + .word 0x23810102 + .word 0xe1a00440 + .word 0x53c00102 + .word 0x43800102 + .word 0xe1a0f00e + .word 0xe24fe05c + .word 0xe0588003 + .word 0xca000502 + .word 0xea000429 + .word 0xe3100101 + .word 0x0affffc9 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a00000e + .word 0xe1918002 + .word 0x02000102 + .word 0x01a0f00e + .word 0xe3c03103 + .word 0xe3110102 + .word 0x13530b0f + .word 0x1affffe6 + .word 0xe2000102 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12833001 + .word 0xe92d4000 + .word 0xeb000731 + .word 0xe8bd4000 + .word 0xeaffffb9 + .word 0xe1928081 + .word 0x0affffdc + .word 0xe92d4000 + .word 0xeb000559 + .word 0xe3360000 + .word 0x5b000595 + .word 0xe8bd4000 + .word 0xeaffffcd + .word 0xe3a05080 + .word 0xe3100101 + .word 0x1a00003b + .word 0xe3110102 + .word 0x01a0f00e + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe1b04a82 + .word 0x1a00000c + .word 0xe28f8f76 + .word 0xe8980300 + .word 0xe1530009 + .word 0xd1580003 + .word 0xc92d4000 + .word 0xca000029 + .word 0xe18005a1 + .word 0xe3c00601 + .word 0xe2438b0f + .word 0xe1800a08 + .word 0xe1a01a81 + .word 0xe18115a2 + .word 0xe1a0f00e + .word 0xe92d4000 + .word 0xe3a04000 + .word 0xe3a06000 + .word 0xeb00039e + .word 0xe28f8f65 + .word 0xe8980300 + .word 0xe1530009 + .word 0xd1580003 + .word 0xca000019 + .word 0xe1800003 + .word 0xe3540000 + .word 0x11b08aa7 + .word 0x33877010 + .word 0x8b0004eb + .word 0xe8bd4000 + .word 0xe1d18080 + .word 0x5a000008 + .word 0xe2300b01 + .word 0xe1a08081 + .word 0xe1a08628 + .word 0xe1880a00 + .word 0x53c00102 + .word 0x43800102 + .word 0xe1a01a81 + .word 0xe18115a2 + .word 0xe1a0f00e + .word 0xe1b007c0 + .word 0x33c10102 + .word 0x23810102 + .word 0xe1a005c0 + .word 0x53c00102 + .word 0x43800102 + .word 0xe1a01a81 + .word 0xe18115a2 + .word 0xe1a0f00e + .word 0xe24fe06c + .word 0xe0588003 + .word 0xca0004a7 + .word 0xea0003ce + .word 0xe3100101 + .word 0x0affffc3 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a00000e + .word 0xe1918002 + .word 0x02000102 + .word 0x01a0f00e + .word 0xe3c03103 + .word 0xe3110102 + .word 0x13530dfe + .word 0x1affffe4 + .word 0xe2000102 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12833001 + .word 0xe92d4000 + .word 0xeb0006d6 + .word 0xe8bd4000 + .word 0xeaffffb3 + .word 0xe1928081 + .word 0x0affffda + .word 0xe92d4000 + .word 0xeb0004fe + .word 0xe3360000 + .word 0x5b00053a + .word 0xe8bd4000 + .word 0xeaffffc9 + .word 0xe3a05c01 + .word 0xe3100101 + .word 0x01a0f00e + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a00000b + .word 0xe1918002 + .word 0x02000102 + .word 0x01a0f00e + .word 0xe1a06880 + .word 0xe2000102 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12866802 + .word 0xe3360000 + .word 0x1a00063d + .word 0xe2000102 + .word 0xe1a0f00e + .word 0xe1928081 + .word 0x0a000004 + .word 0xe92d4000 + .word 0xeb0004e2 + .word 0xe3360000 + .word 0x5b00051e + .word 0xe8bd4000 + .word 0xe1110080 + .word 0xe3c00101 + .word 0x51a0f00e + .word 0xe1928081 + .word 0x11a0f00e + .word 0xe38000ff + .word 0xe3800c7f + .word 0xe3c11102 + .word 0xe1a0f00e + .word 0x00003f81 + .word 0x0000407e + .word 0x00003c01 + .word 0x000043fe + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a00000d + .word 0xe1916002 + .word 0x02000102 + .word 0x01a0f00e + .word 0xe3c03103 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12833001 + .word 0xe92d4000 + .word 0xeb000696 + .word 0xe8bd4000 + .word 0xe3c00101 + .word 0xe3c04103 + .word 0xe0444003 + .word 0xea000053 + .word 0xe1918002 + .word 0x0a000003 + .word 0xe3100101 + .word 0x1a000001 + .word 0xe3170801 + .word 0x1a0005b6 + .word 0xe1a085a2 + .word 0xe1888a81 + .word 0xe3c8820e + .word 0xe3c15103 + .word 0xe1a05425 + .word 0xe1a04982 + .word 0xe3c44103 + .word 0xe1855b08 + .word 0xe1844528 + .word 0xe2000102 + .word 0xe38006ff + .word 0xe3800aff + .word 0xe1918002 + .word 0x13800b02 + .word 0xe3a06000 + .word 0xe3a02000 + .word 0xe3a01b02 + .word 0xe1a09005 + .word 0xe1a08125 + .word 0xe1888f04 + .word 0xe0555008 + .word 0xe0c44124 + .word 0xe1a08225 + .word 0xe1888e04 + .word 0xe0955008 + .word 0xe0a44224 + .word 0xe1a08425 + .word 0xe1888c04 + .word 0xe0955008 + .word 0xe0a44424 + .word 0xe1a08825 + .word 0xe1888804 + .word 0xe0955008 + .word 0xe0a44824 + .word 0xe0955004 + .word 0xe2a44000 + .word 0xe1a051a5 + .word 0xe1855e84 + .word 0xe1a041a4 + .word 0xe0858105 + .word 0xe0498088 + .word 0xe358000a + .word 0x2248800a + .word 0xe2b55000 + .word 0xe2a44000 + .word 0xe1b06226 + .word 0xe1866e02 + .word 0xe1a02222 + .word 0xe1822e01 + .word 0xe1a01221 + .word 0xe1811e08 + .word 0x3affffdc + .word 0xe3170b02 + .word 0x0a000008 + .word 0xe1a06a26 + .word 0xe1866602 + .word 0xe1a02a22 + .word 0xe1822601 + .word 0xe1a01a21 + .word 0xe1811a00 + .word 0xe3800eff + .word 0xe380000f + .word 0xe1a0f00e + .word 0xe1800a21 + .word 0xe1a01601 + .word 0xe1811a22 + .word 0xe1a02602 + .word 0xe1822a26 + .word 0xe1a0f00e + .word 0x00003ffe + .word 0x00013441 + .word 0xe3100101 + .word 0x1affff9d + .word 0xe3c03103 + .word 0xe1916002 + .word 0x02000102 + .word 0x01a0f00e + .word 0xe3a04000 + .word 0xe92d4000 + .word 0xe24f8030 + .word 0xe8980300 + .word 0xe0536008 + .word 0x82899001 + .word 0xe0090996 + .word 0xe1b06949 + .word 0x51a08006 + .word 0x0a000022 + .word 0x42668000 + .word 0xe24dd028 + .word 0xe1a09407 + .word 0xe3899003 + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d901c + .word 0xed490206 + .word 0xe8890007 + .word 0xed998200 + .word 0xe358001c + .word 0xaa0000a7 + .word 0xe28f9fae + .word 0xe0899208 + .word 0xedd91100 + .word 0xe3360000 + .word 0x5e480101 + .word 0x4e180101 + .word 0xee308110 + .word 0xe2088010 + .word 0xe28d901c + .word 0xed898200 + .word 0xe8990007 + .word 0xed590206 + .word 0xe28dd028 + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c03103 + .word 0xe0433004 + .word 0xe2000102 + .word 0xe3170b02 + .word 0x03a09011 + .word 0x13a09015 + .word 0xe2633002 + .word 0xe2833901 + .word 0xe263e020 + .word 0xe1a04e12 + .word 0xe1a02332 + .word 0xe1822e11 + .word 0xe1a01331 + .word 0xe3a03000 + .word 0xe311020f + .word 0x1a00000a + .word 0xe2466001 + .word 0xe0944004 + .word 0xe0b22002 + .word 0xe0a11001 + .word 0xe1a05f24 + .word 0xe0944104 + .word 0xe1a0ef22 + .word 0xe1855102 + .word 0xe0b22102 + .word 0xe18ee101 + .word 0xe0a1100e + .word 0xe1a03203 + .word 0xe1833e21 + .word 0xe3c1120f + .word 0xe2499001 + .word 0xe3340000 + .word 0x1affffef + .word 0xe3a05000 + .word 0xe0922002 + .word 0xe0a11001 + .word 0xe1a0ef22 + .word 0xe0922102 + .word 0xe18ee101 + .word 0xe0a1100e + .word 0xe1a04204 + .word 0xe1844e25 + .word 0xe1a05205 + .word 0xe1855e23 + .word 0xe1a03203 + .word 0xe1833e21 + .word 0xe3c1120f + .word 0xe2599001 + .word 0x1afffff0 + .word 0xe1889001 + .word 0xe1899002 + .word 0xe1921281 + .word 0x3a000005 + .word 0x02031001 + .word 0x0a000003 + .word 0xe2933001 + .word 0xe203800f + .word 0xe338000a + .word 0x0a00003e + .word 0xe3360000 + .word 0x43800101 + .word 0x42666000 + .word 0xe3a08000 + .word 0xe3560efa + .word 0x22466efa + .word 0x23888901 + .word 0xe3560e7d + .word 0x22466e7d + .word 0x23888a02 + .word 0xe3560ffa + .word 0x22466ffa + .word 0x23888a01 + .word 0xe3560e32 + .word 0x22466e32 + .word 0x23888b02 + .word 0xe3560e19 + .word 0x22466e19 + .word 0x23888b01 + .word 0xe35600c8 + .word 0x224660c8 + .word 0x23888c02 + .word 0xe3560064 + .word 0x22466064 + .word 0x23888c01 + .word 0xe3560050 + .word 0x22466050 + .word 0x23888080 + .word 0xe3560028 + .word 0x22466028 + .word 0x23888040 + .word 0xe3560014 + .word 0x22466014 + .word 0x23888020 + .word 0xe356000a + .word 0x22866006 + .word 0xe0888006 + .word 0xe3170b02 + .word 0x0a00000b + .word 0xe1800008 + .word 0xe1a01604 + .word 0xe1811a25 + .word 0xe1a02605 + .word 0xe1822a23 + .word 0xe1a06603 + .word 0xe3390000 + .word 0x08bd8000 + .word 0xe3170601 + .word 0x03877010 + .word 0x1b0003c6 + .word 0xe8bd8000 + .word 0xe1800608 + .word 0xe1800404 + .word 0xe1800c25 + .word 0xe1a01405 + .word 0xe1811c23 + .word 0xe1a02403 + .word 0xe3390000 + .word 0x08bd8000 + .word 0xe3170601 + .word 0x03877010 + .word 0x1b0003ad + .word 0xe8bd8000 + .word 0xe3a01011 + .word 0xe1811401 + .word 0xe1811801 + .word 0xe1812081 + .word 0xe0828063 + .word 0xe02880a3 + .word 0xe0188181 + .word 0xe08330a8 + .word 0xe0833128 + .word 0x5affffb6 + .word 0xe2955001 + .word 0xe0828065 + .word 0xe02880a5 + .word 0xe0188181 + .word 0xe08550a8 + .word 0xe0855128 + .word 0x5affffaf + .word 0xe2944001 + .word 0xe0828064 + .word 0xe02880a4 + .word 0xe0088181 + .word 0xe08440a8 + .word 0xe0844128 + .word 0xe1b08627 + .word 0x33140010 + .word 0x23140601 + .word 0x11a04224 + .word 0x12866001 + .word 0xeaffffa3 + .word 0xe1a090a8 + .word 0xeb000075 + .word 0xe3360000 + .word 0x5e480101 + .word 0x4e180101 + .word 0xe3180001 + .word 0x1e19110f + .word 0xeaffff52 + .word 0x00003fff + .word 0x80000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004002 + .word 0xa0000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004005 + .word 0xc8000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004008 + .word 0xfa000000 + .word 0x00000000 + .word 0x00000000 + .word 0x0000400c + .word 0x9c400000 + .word 0x00000000 + .word 0x00000000 + .word 0x0000400f + .word 0xc3500000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004012 + .word 0xf4240000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004016 + .word 0x98968000 + .word 0x00000000 + .word 0x00000000 + .word 0x00004019 + .word 0xbebc2000 + .word 0x00000000 + .word 0x00000000 + .word 0x0000401c + .word 0xee6b2800 + .word 0x00000000 + .word 0x00000000 + .word 0x00004020 + .word 0x9502f900 + .word 0x00000000 + .word 0x00000000 + .word 0x00004023 + .word 0xba43b740 + .word 0x00000000 + .word 0x00000000 + .word 0x00004026 + .word 0xe8d4a510 + .word 0x00000000 + .word 0x00000000 + .word 0x0000402a + .word 0x9184e72a + .word 0x00000000 + .word 0x00000000 + .word 0x0000402d + .word 0xb5e620f4 + .word 0x80000000 + .word 0x00000000 + .word 0x00004030 + .word 0xe35fa931 + .word 0xa0000000 + .word 0x00000000 + .word 0x00004034 + .word 0x8e1bc9bf + .word 0x04000000 + .word 0x00000000 + .word 0x00004037 + .word 0xb1a2bc2e + .word 0xc5000000 + .word 0x00000000 + .word 0x0000403a + .word 0xde0b6b3a + .word 0x76400000 + .word 0x00000000 + .word 0x0000403e + .word 0x8ac72304 + .word 0x89e80000 + .word 0x00000000 + .word 0x00004041 + .word 0xad78ebc5 + .word 0xac620000 + .word 0x00000000 + .word 0x00004044 + .word 0xd8d726b7 + .word 0x177a8000 + .word 0x00000000 + .word 0x00004048 + .word 0x87867832 + .word 0x6eac9000 + .word 0x00000000 + .word 0x0000404b + .word 0xa968163f + .word 0x0a57b400 + .word 0x00000000 + .word 0x0000404e + .word 0xd3c21bce + .word 0xcceda100 + .word 0x00000000 + .word 0x00004052 + .word 0x84595161 + .word 0x401484a0 + .word 0x00000000 + .word 0x00004055 + .word 0xa56fa5b9 + .word 0x9019a5c8 + .word 0x00000000 + .word 0x00004058 + .word 0xcecb8f27 + .word 0xf4200f3a + .word 0x00000000 + .word 0xe1a0000e + .word 0xe3a01000 + .word 0xe1a02009 + .word 0xe352001c + .word 0x21a020a2 + .word 0x22811001 + .word 0x2afffffb + .word 0xe24fef79 + .word 0xe08e2202 + .word 0xedd21100 + .word 0xe3510001 + .word 0x31a0f000 + .word 0xee191101 + .word 0xe1b02139 + .word 0xe2411001 + .word 0x2e19110f + .word 0xeafffff8 + .word 0xe92d4000 + .word 0xe1a08200 + .word 0xe3170b02 + .word 0x03a09004 + .word 0x13a09007 + .word 0xe3a05000 + .word 0xeb000141 + .word 0xe1b08627 + .word 0x23a09008 + .word 0x21b08001 + .word 0x21a01002 + .word 0x21a02006 + .word 0x33a09003 + .word 0x31b08a00 + .word 0xe1a06085 + .word 0x43866001 + .word 0xe3a05000 + .word 0xe3a04000 + .word 0xe3a03000 + .word 0xeb000134 + .word 0xe1a08001 + .word 0xe3a09008 + .word 0xeb000131 + .word 0xe1a08002 + .word 0xe3a09008 + .word 0xeb00012e + .word 0xe3170b02 + .word 0x03a08c41 + .word 0x13a088fe + .word 0xe15800a6 + .word 0x9a000111 + .word 0xe1a060a6 + .word 0xe1838004 + .word 0xe1988005 + .word 0x02000102 + .word 0x08bd8000 + .word 0xe3100101 + .word 0x12666000 + .word 0xe3170b02 + .word 0x02466012 + .word 0x12466017 + .word 0xe2000102 + .word 0xe2800901 + .word 0x0280003e + .word 0x03a08000 + .word 0x1280004e + .word 0x11a08805 + .word 0x11a05825 + .word 0x11855804 + .word 0x11a04824 + .word 0x11844803 + .word 0xe3340000 + .word 0x4a000004 + .word 0xe0988008 + .word 0xe0b55005 + .word 0xe0b44004 + .word 0xe2400001 + .word 0x5afffffa + .word 0xe3380102 + .word 0x01f08f85 + .word 0x4a000003 + .word 0xe2955001 + .word 0xe2b44000 + .word 0x21a04064 + .word 0x22800001 + .word 0xe24dd034 + .word 0xe1a09407 + .word 0xe3899007 + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9028 + .word 0xed498209 + .word 0xe8890031 + .word 0xed998200 + .word 0xe3380000 + .word 0x1e309110 + .word 0x13899010 + .word 0x1e209110 + .word 0xe1b09006 + .word 0x4a000009 + .word 0x0a000011 + .word 0xe3590a01 + .word 0x8a000020 + .word 0xe359001c + .word 0xb24f8fdd + .word 0xb0888209 + .word 0xbdd81100 + .word 0xabffff90 + .word 0xee180101 + .word 0xea000008 + .word 0xe2699000 + .word 0xe3590a01 + .word 0x8a00006c + .word 0xe359001c + .word 0xb24f8fe7 + .word 0xb0888209 + .word 0xbdd81100 + .word 0xabffff86 + .word 0xee480101 + .word 0xee308110 + .word 0xe3180010 + .word 0xe28d9028 + .word 0xed898200 + .word 0xe8990007 + .word 0xed598209 + .word 0xe28dd034 + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0x08bd8000 + .word 0xe3170601 + .word 0x03877010 + .word 0x13a04102 + .word 0x1b000262 + .word 0xe8bd8000 + .word 0xe3590a02 + .word 0x8a000028 + .word 0xe1a06009 + .word 0xe1a090a9 + .word 0xebffff6f + .word 0xe28f9fa6 + .word 0xed99a200 + .word 0xee180102 + .word 0xee180101 + .word 0xe3160001 + .word 0x1e19110f + .word 0xee181101 + .word 0xe28f9fa2 + .word 0xed998200 + .word 0xee190100 + .word 0xee309110 + .word 0xe3190004 + .word 0x0affffdc + .word 0xee190102 + .word 0xee308110 + .word 0xe3180010 + .word 0xe28d9028 + .word 0xed898200 + .word 0xe8990007 + .word 0xed598209 + .word 0xe28dd034 + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c03103 + .word 0xe2833a06 + .word 0xe2000102 + .word 0x03a04000 + .word 0x13a04102 + .word 0xe3a05002 + .word 0xeb000136 + .word 0xe3340000 + .word 0x08bd8000 + .word 0xe3170601 + .word 0x03877010 + .word 0x1b000237 + .word 0xe8bd8000 + .word 0xe3590901 + .word 0x2a000014 + .word 0xe1a06009 + .word 0xe1a09129 + .word 0xebffff44 + .word 0xe28f9f7b + .word 0xed99a200 + .word 0xee180102 + .word 0xee180101 + .word 0xee180101 + .word 0xee180102 + .word 0xe3160002 + .word 0x1e19110f + .word 0xee180101 + .word 0xe3160001 + .word 0x1e19110f + .word 0xee180101 + .word 0xee309110 + .word 0xe3190004 + .word 0x0affffd3 + .word 0xe28d9028 + .word 0xed898200 + .word 0xe8990007 + .word 0xe28d9028 + .word 0xed598209 + .word 0xe28dd034 + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe2000102 + .word 0xe3a01102 + .word 0xe3a02000 + .word 0xe3a03401 + .word 0xe3a04102 + .word 0xe3a05002 + .word 0xeb00010b + .word 0xe3340000 + .word 0x08bd8000 + .word 0xe3170601 + .word 0x03877010 + .word 0x1b00020c + .word 0xe8bd8000 + .word 0xe3590a02 + .word 0x8a000029 + .word 0xe1a06009 + .word 0xe1a090a9 + .word 0xebffff19 + .word 0xe28f9f53 + .word 0xed99a200 + .word 0xee180102 + .word 0xee480101 + .word 0xe3160001 + .word 0x1e19110f + .word 0xee481101 + .word 0xe28f9f49 + .word 0xed998200 + .word 0xee190100 + .word 0xee309110 + .word 0xe3190008 + .word 0x0affff86 + .word 0xee190102 + .word 0xee308110 + .word 0xe3180010 + .word 0xe28d9028 + .word 0xed898200 + .word 0xe8990007 + .word 0xed598209 + .word 0xe28dd034 + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c03103 + .word 0xe2433a06 + .word 0xe2000102 + .word 0x03a04000 + .word 0x13a04102 + .word 0xe3a05002 + .word 0xe2638000 + .word 0xeb000155 + .word 0xe3340000 + .word 0x08bd8000 + .word 0xe3170601 + .word 0x03877010 + .word 0x1b0001e0 + .word 0xe8bd8000 + .word 0xe3590901 + .word 0x2a000014 + .word 0xe1a06009 + .word 0xe1a09129 + .word 0xebfffeed + .word 0xe28f909c + .word 0xed99a200 + .word 0xee180102 + .word 0xee480101 + .word 0xee480101 + .word 0xee180102 + .word 0xe3160002 + .word 0x1e19110f + .word 0xee480101 + .word 0xe3160001 + .word 0x1e19110f + .word 0xee480101 + .word 0xee309110 + .word 0xe3190008 + .word 0x0affffd2 + .word 0xe28d9028 + .word 0xed898200 + .word 0xe8990007 + .word 0xe28d9028 + .word 0xed598209 + .word 0xe28dd034 + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe2000102 + .word 0xe3a01102 + .word 0xe3a02000 + .word 0xe3a034ff + .word 0xe3a04102 + .word 0xe3a05002 + .word 0xeb00012a + .word 0xe3340000 + .word 0x08bd8000 + .word 0xe3170601 + .word 0x03877010 + .word 0x1b0001b5 + .word 0xe8bd8000 + .word 0x00000fff + .word 0x80000000 + .word 0x00000000 + .word 0x00006fff + .word 0x80000000 + .word 0x00000000 + .word 0x6f05b59d + .word 0x3b200000 + .word 0x16ef0a57 + .word 0xb4000000 + .word 0xe3160001 + .word 0x0a000005 + .word 0xe3170b02 + .word 0x024f8024 + .word 0x124f8020 + .word 0xe8980006 + .word 0xe0555002 + .word 0xe0c44001 + .word 0xe1a08b25 + .word 0xe1888504 + .word 0xe3c8820e + .word 0xe3c42103 + .word 0xe1a029a2 + .word 0xe1a01405 + .word 0xe3c11103 + .word 0xe1822588 + .word 0xe1811aa8 + .word 0xe2000102 + .word 0xe3800101 + .word 0xe3800c7f + .word 0xe38000ff + .word 0xe3160001 + .word 0x13811101 + .word 0xe1a0f00e + .word 0xe1a03183 + .word 0xe1833ea4 + .word 0xe1a04184 + .word 0xe1844ea5 + .word 0xe1a05185 + .word 0xe0955125 + .word 0x20855f04 + .word 0x30955f04 + .word 0xe0b44124 + .word 0x20844f03 + .word 0x30944f03 + .word 0xe0a33123 + .word 0xe0955e28 + .word 0xe2b44000 + .word 0xe2a33000 + .word 0xe1a08208 + .word 0xe2599001 + .word 0x1affffed + .word 0xe1a0f00e + .word 0xe1b08425 + .word 0x2a000024 + .word 0x0a000010 + .word 0xe1b08086 + .word 0xe18082e5 + .word 0x23888101 + .word 0x13888202 + .word 0xe3340000 + .word 0x01b06f82 + .word 0x43888201 + .word 0xe28f6038 + .word 0xe7d66e68 + .word 0xe1b080a6 + .word 0x22922001 + .word 0x22911001 + .word 0x23a01102 + .word 0x22833001 + .word 0xe3160002 + .word 0x11a04c06 + .word 0xe1a0f00e + .word 0xe1868002 + .word 0xe1988c81 + .word 0xe18082e5 + .word 0x23888101 + .word 0x13888202 + .word 0xe3340000 + .word 0x01b06b81 + .word 0x43888201 + .word 0xe3a02000 + .word 0xe3c110ff + .word 0xe28f6068 + .word 0xe7d66e68 + .word 0xe1b080a6 + .word 0x22911c01 + .word 0x23a01102 + .word 0x22833001 + .word 0xe3160002 + .word 0x11a04c06 + .word 0xe1a0f00e + .word 0xe1968b02 + .word 0xe18082e5 + .word 0x23888101 + .word 0x13888202 + .word 0xe3340000 + .word 0x01b06a02 + .word 0x43888201 + .word 0xe3c220ff + .word 0xe3c22c07 + .word 0xe24f6020 + .word 0xe7d66e68 + .word 0xe1b080a6 + .word 0x22922b02 + .word 0x22911001 + .word 0x23a01102 + .word 0x22833001 + .word 0xe3160002 + .word 0x11a04c06 + .word 0xe1a0f00e + .word 0xfefe0000 + .word 0x030303fe + .word 0xfefe0000 + .word 0x030303fe + .word 0x03030000 + .word 0x03030303 + .word 0xfefe0000 + .word 0xfefefefe + .word 0xfefe0000 + .word 0xfefefefe + .word 0x03030000 + .word 0x03030303 + .word 0xfefe0000 + .word 0xfefefefe + .word 0xfefe0000 + .word 0xfefefefe + .word 0x40007fff + .word 0x00000000 + .word 0x00000000 + .word 0x0000407e + .word 0xffffff00 + .word 0x00000000 + .word 0x000043fe + .word 0xffffffff + .word 0xfffff800 + .word 0x00007ffe + .word 0xffffffff + .word 0xffffffff + .word 0xc0007fff + .word 0x00000000 + .word 0x00000000 + .word 0x8000407e + .word 0xffffff00 + .word 0x00000000 + .word 0x800043fe + .word 0xffffffff + .word 0xfffff800 + .word 0x80007ffe + .word 0xffffffff + .word 0xffffffff + .word 0x00000030 + .word 0x00000000 + .word 0x0000003c + .word 0x00000000 + .word 0x00000030 + .word 0x0000000c + .word 0x0000003c + .word 0x0000000c + .word 0x00000030 + .word 0x00000000 + .word 0x00000048 + .word 0x00000000 + .word 0x00000030 + .word 0x00000018 + .word 0x00000048 + .word 0x00000018 + .word 0x00000030 + .word 0x00000000 + .word 0x00000054 + .word 0x00000000 + .word 0x00000030 + .word 0x00000024 + .word 0x00000054 + .word 0x00000024 + .word 0xe3170701 + .word 0x1a00000c + .word 0xe3877004 + .word 0xe24f1074 + .word 0xe0811125 + .word 0xe8910006 + .word 0xe3100102 + .word 0xe24f00e4 + .word 0x10800001 + .word 0x00800002 + .word 0xe8900007 + .word 0xe3100101 + .word 0x13a04001 + .word 0x03e04000 + .word 0xe1a0f00e + .word 0xe92d4c28 + .word 0xe3540102 + .word 0x13540000 + .word 0xc3a04001 + .word 0xb3e04000 + .word 0xee207110 + .word 0xe24dd004 + .word 0xe28f8e17 + .word 0xe20b9010 + .word 0xe7989129 + .word 0xe31b0902 + .word 0x11a09829 + .word 0xe20b860f + .word 0xe1a08a28 + .word 0xe1a09839 + .word 0xe0099fa7 + .word 0xe1c99527 + .word 0xe0099cab + .word 0xe3150c01 + .word 0x1a00002b + .word 0xe3150080 + .word 0x1a000014 + .word 0xe24330c0 + .word 0xe59f8124 + .word 0xe1530008 + .word 0xd1800003 + .word 0xc28f0f43 + .word 0xc8900007 + .word 0xe92d0007 + .word 0xe1a03009 + .word 0xeb000fc2 + .word 0xe24dd010 + .word 0xe1a08407 + .word 0xe3888001 + .word 0xe58d8000 + .word 0xe10f8000 + .word 0xe3888080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe28d8010 + .word 0xed088203 + .word 0xed980100 + .word 0xea000028 + .word 0xe2433c06 + .word 0xe59f80d4 + .word 0xe1530008 + .word 0xd1800003 + .word 0xc28f00b8 + .word 0xc8900007 + .word 0xe92d0007 + .word 0xe1a03009 + .word 0xeb000fad + .word 0xe24dd010 + .word 0xe1a08407 + .word 0xe3888001 + .word 0xe58d8000 + .word 0xe10f8000 + .word 0xe3888080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe28d8010 + .word 0xed088203 + .word 0xed988100 + .word 0xea000013 + .word 0xe2433a06 + .word 0xe59f8084 + .word 0xe1530008 + .word 0xd1800003 + .word 0xc28f0064 + .word 0xc8900007 + .word 0xe92d0007 + .word 0xe1a03009 + .word 0xeb000f98 + .word 0xe24dd010 + .word 0xe1a08407 + .word 0xe3888001 + .word 0xe58d8000 + .word 0xe10f8000 + .word 0xe3888080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe28d8010 + .word 0xed088203 + .word 0xedd80100 + .word 0xee307110 + .word 0xe28d8010 + .word 0xed888200 + .word 0xe8980007 + .word 0xed188203 + .word 0xe28dd020 + .word 0xe10f8000 + .word 0xe3c88080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe8bd8c28 + .word 0x40007fff + .word 0x40000200 + .word 0x00000000 + .word 0x0000407e + .word 0x000043fe + .word 0x00007ffe + .word 0xc0070e3f + .word 0x00010001 + .word 0xe92d4000 + .word 0xe3170702 + .word 0x1a000025 + .word 0xe0833008 + .word 0xe1a092a8 + .word 0xe1c88289 + .word 0xe3590002 + .word 0x33390000 + .word 0xe2689020 + .word 0xe1a06912 + .word 0xe1a02832 + .word 0xe1822911 + .word 0xe1a01831 + .word 0x0a000003 + .word 0x11866106 + .word 0x11826126 + .word 0x11a02001 + .word 0x13a01000 + .word 0x3a000004 + .word 0x21866002 + .word 0x21866106 + .word 0x21816126 + .word 0x23a02000 + .word 0x23a01000 + .word 0xebfffef6 + .word 0xe3170c01 + .word 0x13310102 + .word 0x11918002 + .word 0x13a01000 + .word 0x13a02000 + .word 0x13e04000 + .word 0x03360000 + .word 0x13877008 + .word 0xe1916002 + .word 0x08bd8000 + .word 0xe3330000 + .word 0x1b000280 + .word 0x03110102 + .word 0x03800101 + .word 0xe1800003 + .word 0xe8bd8000 + .word 0xe92d4c28 + .word 0xe3540102 + .word 0x13540000 + .word 0xc3a04001 + .word 0xb3e04000 + .word 0xee207110 + .word 0xe24dd004 + .word 0xe24f80d0 + .word 0xe20b9010 + .word 0xe7989129 + .word 0xe31b0902 + .word 0x11a09829 + .word 0xe20b860f + .word 0xe1a08a28 + .word 0xe1a09839 + .word 0xe0099fa7 + .word 0xe1c99527 + .word 0xe0099cab + .word 0xe3150c01 + .word 0x1a000015 + .word 0xe3150080 + .word 0x1a000009 + .word 0xe28330c0 + .word 0xe59f8078 + .word 0xe1530008 + .word 0xa1800003 + .word 0xb28f0060 + .word 0xb8900007 + .word 0xe92d0007 + .word 0xe1a03009 + .word 0xeb000f34 + .word 0xeaffff6e + .word 0xe2833c06 + .word 0xe59f8054 + .word 0xe1530008 + .word 0xa1800003 + .word 0xb28f0038 + .word 0xb8900007 + .word 0xe92d0007 + .word 0xe1a03009 + .word 0xeb000f2a + .word 0xeaffff79 + .word 0xe2833a06 + .word 0xe3a08000 + .word 0xe1530008 + .word 0xa1800003 + .word 0xb28f0010 + .word 0xb8900007 + .word 0xe92d0007 + .word 0xe1a03009 + .word 0xeb000f20 + .word 0xeaffff84 + .word 0x40007fff + .word 0x40000300 + .word 0x00000000 + .word 0x00003f81 + .word 0x00003c01 + .word 0xe92d4000 + .word 0xe3170702 + .word 0x1affffc3 + .word 0xe0833008 + .word 0xe1a092a8 + .word 0xe1c88289 + .word 0xe3590002 + .word 0x33390000 + .word 0xe2689020 + .word 0xe1a06912 + .word 0xe1a02832 + .word 0xe1822911 + .word 0xe1a01831 + .word 0x0a000003 + .word 0x11866106 + .word 0x11826126 + .word 0x11a02001 + .word 0x13a01000 + .word 0x3a000004 + .word 0x21866002 + .word 0x21866106 + .word 0x21816126 + .word 0x23a02000 + .word 0x23a01000 + .word 0xebfffe94 + .word 0xe3170c01 + .word 0x13310102 + .word 0x11918002 + .word 0x13a01000 + .word 0x13a02000 + .word 0x13e04000 + .word 0x03360000 + .word 0x13877008 + .word 0xe1916002 + .word 0x08bd8000 + .word 0xe3310102 + .word 0x13800101 + .word 0x13330000 + .word 0x12433001 + .word 0x13811102 + .word 0xe1800003 + .word 0xe8bd8000 + .word 0xe3a08000 + .word 0xea000004 + .word 0xe3a08001 + .word 0xea000002 + .word 0xe3a08002 + .word 0xea000000 + .word 0xe1a083a5 + .word 0xe92d4c28 + .word 0xe3540102 + .word 0x13540000 + .word 0xc3a04001 + .word 0xb3e04000 + .word 0xee207110 + .word 0xe24dd004 + .word 0xe92d0007 + .word 0xe24f8f9f + .word 0xe20b3010 + .word 0xe7983123 + .word 0xe31b0902 + .word 0x11a03823 + .word 0xe20b860f + .word 0xe1a08a28 + .word 0xe1a03833 + .word 0xe0033fa7 + .word 0xe1c33527 + .word 0xe0033cab + .word 0xe3580001 + .word 0x8a000004 + .word 0x0a000001 + .word 0xeb000ed4 + .word 0xeaffff0c + .word 0xeb000ed2 + .word 0xeaffff1f + .word 0xeb000ed0 + .word 0xeaffff32 + .word 0xe92d4c28 + .word 0xe3540102 + .word 0x13540000 + .word 0xc3a04001 + .word 0xb3e04000 + .word 0xee207110 + .word 0xe24dd010 + .word 0xe3a03000 + .word 0xeb000ec6 + .word 0xee307110 + .word 0xe49d6010 + .word 0xe8bd8c28 + .word 0xe92d4c28 + .word 0xe3540102 + .word 0x13540000 + .word 0xc3a04001 + .word 0xb3e04000 + .word 0xee207110 + .word 0xe24dd010 + .word 0xe3a03000 + .word 0xeb000eba + .word 0xee307110 + .word 0xe89d0007 + .word 0xe28dd010 + .word 0xe8bd8c28 + .word 0xe92d4c28 + .word 0xe3540102 + .word 0x13540000 + .word 0xc3a04001 + .word 0xb3e04000 + .word 0xee207110 + .word 0xe24dd010 + .word 0xe3a03000 + .word 0xeb000ead + .word 0xee307110 + .word 0xe8bd0047 + .word 0xe8bd8c28 + .word 0xe3c08103 + .word 0xe3a090ff + .word 0xe3899c43 + .word 0xe1580009 + .word 0x81a0648b + .word 0x91e0648b + .word 0x0006680b + .word 0x11c6680b + .word 0xe3360000 + .word 0x52176c02 + .word 0x11a0f00e + .word 0xe1b06b08 + .word 0x31a06fa6 + .word 0x22026001 + .word 0xe31b0902 + .word 0x12266001 + .word 0xe31b0501 + .word 0x13a06000 + .word 0xe1a0f00e + .word 0xe3c08103 + .word 0xe3a090ff + .word 0xe3899c43 + .word 0xe1580009 + .word 0x81a0660b + .word 0x91e0660b + .word 0x00066c0b + .word 0x11c66c0b + .word 0xe3360000 + .word 0x52176c02 + .word 0x11a0f00e + .word 0xe1b06b08 + .word 0x31a06fa6 + .word 0x22026001 + .word 0xe31b0080 + .word 0x12266001 + .word 0xe31b0702 + .word 0x13a06000 + .word 0xe1a0f00e + .word 0xe1928081 + .word 0x0a000005 + .word 0xe3110101 + .word 0x0a000019 + .word 0xe1958084 + .word 0x0a000017 + .word 0xe3140101 + .word 0x1a000015 + .word 0xe2148101 + .word 0x1a000003 + .word 0xe3170801 + .word 0x1a00009b + .word 0xe3877001 + .word 0xe3844101 + .word 0xe1a00003 + .word 0xe1a01004 + .word 0xe1a02005 + .word 0xea000011 + .word 0x0a000010 + .word 0xe2118101 + .word 0x1a00000e + .word 0xe3170801 + .word 0x1a000053 + .word 0xea000009 + .word 0x0a00000a + .word 0xe2118101 + .word 0x1a000008 + .word 0xe3170801 + .word 0x1a00002d + .word 0xea000003 + .word 0xe2118101 + .word 0x1a000003 + .word 0xe3170801 + .word 0x1a000085 + .word 0xe3877001 + .word 0xe3811101 + .word 0xe31b0702 + .word 0x1a000010 + .word 0xe31b0080 + .word 0x1a000006 + .word 0xe2000103 + .word 0xe380007f + .word 0xe3800901 + .word 0xe3a02000 + .word 0xe3c110ff + .word 0xe3811102 + .word 0xe1a0f00e + .word 0xe2000103 + .word 0xe38000ff + .word 0xe3800c43 + .word 0xe1a025a2 + .word 0xe1a02582 + .word 0xe3811102 + .word 0xe1300000 + .word 0xe1a0f00e + .word 0xe31b0c02 + .word 0x1a000005 + .word 0xe3c08103 + .word 0xe3a090ff + .word 0xe3899c43 + .word 0xe1580009 + .word 0x33c22001 + .word 0x03822001 + .word 0xe2000103 + .word 0xe38000ff + .word 0xe3800c7f + .word 0xe1300000 + .word 0xe1a0f00e + .word 0xe3170801 + .word 0x1a000004 + .word 0xe3877001 + .word 0xe28f0d0a + .word 0xe8900007 + .word 0xe1811408 + .word 0xe1a0f00e + .word 0xe92d4c30 + .word 0xee207110 + .word 0xe24dd00c + .word 0xe92d0007 + .word 0xe28f8f9b + .word 0xe20b3010 + .word 0xe7983123 + .word 0xe31b0902 + .word 0x11a03823 + .word 0xe20b860f + .word 0xe1a08a28 + .word 0xe1a03833 + .word 0xe0033fa7 + .word 0xe1c33527 + .word 0xe0033cab + .word 0xe31b0702 + .word 0x1a00002e + .word 0xe31b0080 + .word 0x1a00001f + .word 0xeb000e1d + .word 0xe24dd010 + .word 0xe1a08407 + .word 0xe3888001 + .word 0xe58d8000 + .word 0xe10f8000 + .word 0xe3888080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe28d8010 + .word 0xed088203 + .word 0xed980100 + .word 0xea00002b + .word 0xe92d4c30 + .word 0xee207110 + .word 0xe24dd00c + .word 0xe92d0007 + .word 0xe28f8f7b + .word 0xe20b3010 + .word 0xe7983123 + .word 0xe31b0902 + .word 0x11a03823 + .word 0xe20b860f + .word 0xe1a08a28 + .word 0xe1a03833 + .word 0xe0033fa7 + .word 0xe1c33527 + .word 0xe0033cab + .word 0xe31b0501 + .word 0x1a00000e + .word 0xe31b0902 + .word 0x0affffdf + .word 0xeb000dfd + .word 0xe24dd010 + .word 0xe1a08407 + .word 0xe3888001 + .word 0xe58d8000 + .word 0xe10f8000 + .word 0xe3888080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe28d8010 + .word 0xed088203 + .word 0xed988100 + .word 0xea00000b + .word 0xeb000df0 + .word 0xe24dd010 + .word 0xe1a08407 + .word 0xe3888001 + .word 0xe58d8000 + .word 0xe10f8000 + .word 0xe3888080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe28d8010 + .word 0xed088203 + .word 0xedd80100 + .word 0xee307110 + .word 0xe28d8010 + .word 0xed888200 + .word 0xe8980007 + .word 0xed188203 + .word 0xe28dd028 + .word 0xe10f8000 + .word 0xe3c88080 + .word 0xe129f008 + .word 0xe1a00000 + .word 0xe2106101 + .word 0x03c03103 + .word 0x02000102 + .word 0xe3b08001 + .word 0xe8bd8c30 + .word 0xe3170801 + .word 0x0affff9d + .word 0xe92d4c30 + .word 0xee207110 + .word 0xe92d003f + .word 0xe28f80fc + .word 0xe20b3010 + .word 0xe7983123 + .word 0xe31b0902 + .word 0x11a03823 + .word 0xe20b860f + .word 0xe1a08a28 + .word 0xe1a03833 + .word 0xe0033fa7 + .word 0xe1c33527 + .word 0xe0033cab + .word 0xe31b0702 + .word 0x1a000005 + .word 0xe31b0080 + .word 0x1a000001 + .word 0xeb000dc1 + .word 0xeaffffa2 + .word 0xeb000dbf + .word 0xeaffffc0 + .word 0xeb000dbd + .word 0xeaffffcb + .word 0xe3170801 + .word 0x03877001 + .word 0x01a0f00e + .word 0xe92d4c00 + .word 0xee207110 + .word 0xe24dd004 + .word 0xe92d0007 + .word 0xe3a03000 + .word 0xeb000db3 + .word 0xee307110 + .word 0xe49d6010 + .word 0xe8bd8c00 + .word 0xe3170801 + .word 0x03877001 + .word 0x01a0f00e + .word 0xe92d4c00 + .word 0xee207110 + .word 0xe92d003f + .word 0xe3a03000 + .word 0xeb000da8 + .word 0xee307110 + .word 0xe49d6018 + .word 0xe8bd8c00 + .word 0xe92d4c00 + .word 0xee207110 + .word 0xe24dd004 + .word 0xe92d0007 + .word 0xe3a03000 + .word 0xe3170b02 + .word 0x1a000003 + .word 0xeb000d9d + .word 0xe8bd0007 + .word 0xe28dd004 + .word 0xea000001 + .word 0xeb000d99 + .word 0xe8bd0047 + .word 0xee307110 + .word 0xe8bd8c00 + .word 0x40007fff + .word 0x00000000 + .word 0x00000000 + .word 0x40007fff + .word 0x40000000 + .word 0x00000000 + .word 0xc0070e3f + .word 0x00010001 + .word 0xe3170802 + .word 0x1a000004 + .word 0xe3877002 + .word 0xe24f0034 + .word 0xe8900007 + .word 0xe3800102 + .word 0xe1a0f00e + .word 0xe92d4c30 + .word 0xee207110 + .word 0xe24dd00c + .word 0xe92d0007 + .word 0xe24f803c + .word 0xe20b3010 + .word 0xe7983123 + .word 0xe31b0902 + .word 0x11a03823 + .word 0xe20b860f + .word 0xe1a08a28 + .word 0xe1a03833 + .word 0xe0033fa7 + .word 0xe1c33527 + .word 0xe0033cab + .word 0xe31b0702 + .word 0x1a000005 + .word 0xe31b0080 + .word 0x1a000001 + .word 0xeb000d75 + .word 0xeaffff54 + .word 0xeb000d73 + .word 0xeaffff72 + .word 0xeb000d71 + .word 0xeaffff7d + .word 0xe3170802 + .word 0x1a000006 + .word 0xe3877002 + .word 0xe0208003 + .word 0xe2088102 + .word 0xe24f00bc + .word 0xe8900007 + .word 0xe1800008 + .word 0xe1a0f00e + .word 0xe92d4c30 + .word 0xee207110 + .word 0xe92d003f + .word 0xe24f80c0 + .word 0xe20b3010 + .word 0xe7983123 + .word 0xe31b0902 + .word 0x11a03823 + .word 0xe20b860f + .word 0xe1a08a28 + .word 0xe1a03833 + .word 0xe0033fa7 + .word 0xe1c33527 + .word 0xe0033cab + .word 0xe31b0702 + .word 0x1a000005 + .word 0xe31b0080 + .word 0x1a000001 + .word 0xeb000d54 + .word 0xeaffff33 + .word 0xeb000d52 + .word 0xeaffff51 + .word 0xeb000d50 + .word 0xeaffff5c + .word 0xe2000102 + .word 0xe3310000 + .word 0x0a000017 + .word 0xe3a08000 + .word 0xe1b09821 + .word 0x01a01801 + .word 0x02888010 + .word 0xe1b09c21 + .word 0x01a01401 + .word 0x02888008 + .word 0xe1b09e21 + .word 0x01a01201 + .word 0x02888004 + .word 0xe1b09f21 + .word 0x01a01101 + .word 0x02888002 + .word 0xe1b09fa1 + .word 0x01a01081 + .word 0x02888001 + .word 0xe05898a6 + .word 0x81a01931 + .word 0x81a088a6 + .word 0xe2686020 + .word 0xe1811632 + .word 0xe1a02812 + .word 0x30400009 + .word 0xe1a0f00e + .word 0xe3560501 + .word 0x3a000016 + .word 0xe1b01002 + .word 0x01a0f00e + .word 0xe3a02000 + .word 0xe3a08020 + .word 0xe1b09821 + .word 0x01a01801 + .word 0x02888010 + .word 0xe1b09c21 + .word 0x01a01401 + .word 0x02888008 + .word 0xe1b09e21 + .word 0x01a01201 + .word 0x02888004 + .word 0xe1b09f21 + .word 0x01a01101 + .word 0x02888002 + .word 0xe1b09fa1 + .word 0x01a01081 + .word 0x02888001 + .word 0xe05898a6 + .word 0x81a01931 + .word 0x30400009 + .word 0xe1a0f00e + .word 0xe1a088a6 + .word 0xe2689020 + .word 0xe1a01811 + .word 0xe1811932 + .word 0xe1a02812 + .word 0xe1a0f00e + .word 0xe2033102 + .word 0xe3340000 + .word 0x0a000017 + .word 0xe3a08000 + .word 0xe1b09824 + .word 0x01a04804 + .word 0x02888010 + .word 0xe1b09c24 + .word 0x01a04404 + .word 0x02888008 + .word 0xe1b09e24 + .word 0x01a04204 + .word 0x02888004 + .word 0xe1b09f24 + .word 0x01a04104 + .word 0x02888002 + .word 0xe1b09fa4 + .word 0x01a04084 + .word 0x02888001 + .word 0xe05898a6 + .word 0x81a04934 + .word 0x81a088a6 + .word 0xe2686020 + .word 0xe1844635 + .word 0xe1a05815 + .word 0x30433009 + .word 0xe1a0f00e + .word 0xe3560501 + .word 0x3a000016 + .word 0xe1b04005 + .word 0x01a0f00e + .word 0xe3a05000 + .word 0xe3a08020 + .word 0xe1b09824 + .word 0x01a04804 + .word 0x02888010 + .word 0xe1b09c24 + .word 0x01a04404 + .word 0x02888008 + .word 0xe1b09e24 + .word 0x01a04204 + .word 0x02888004 + .word 0xe1b09f24 + .word 0x01a04104 + .word 0x02888002 + .word 0xe1b09fa4 + .word 0x01a04084 + .word 0x02888001 + .word 0xe05898a6 + .word 0x81a04934 + .word 0x30433009 + .word 0xe1a0f00e + .word 0xe1a088a6 + .word 0xe2689020 + .word 0xe1a04814 + .word 0xe1844935 + .word 0xe1a05815 + .word 0xe1a0f00e + .word 0xe3a02000 + .word 0xe2160102 + .word 0x12661000 + .word 0x01b01006 + .word 0x03a03000 + .word 0x01a0f00e + .word 0xe3a03901 + .word 0xe383301e + .word 0xe3a06000 + .word 0xe3310000 + .word 0x01a01002 + .word 0x03a02000 + .word 0x02433020 + .word 0xe3a08000 + .word 0xe1b09821 + .word 0x01a01801 + .word 0x02888010 + .word 0xe1b09c21 + .word 0x01a01401 + .word 0x02888008 + .word 0xe1b09e21 + .word 0x01a01201 + .word 0x02888004 + .word 0xe1b09f21 + .word 0x01a01101 + .word 0x02888002 + .word 0xe1b09fa1 + .word 0x01a01081 + .word 0x02888001 + .word 0xe2789020 + .word 0xe1811932 + .word 0xe1a02812 + .word 0xe0433008 + .word 0xe1a0f00e + .word 0xe3340000 + .word 0x01a04005 + .word 0x03a05000 + .word 0x02433020 + .word 0xe3a08000 + .word 0xe1b09824 + .word 0x01a04804 + .word 0x02888010 + .word 0xe1b09c24 + .word 0x01a04404 + .word 0x02888008 + .word 0xe1b09e24 + .word 0x01a04204 + .word 0x02888004 + .word 0xe1b09f24 + .word 0x01a04104 + .word 0x02888002 + .word 0xe1b09fa4 + .word 0x01a04084 + .word 0x02888001 + .word 0xe2789020 + .word 0xe1844935 + .word 0xe1a05815 + .word 0xe0433008 + .word 0xe1a0f00e + .word 0xe3310000 + .word 0x01a01002 + .word 0x03a02000 + .word 0x02833020 + .word 0xe3a08000 + .word 0xe1b09821 + .word 0x01a01801 + .word 0x02888010 + .word 0xe1b09c21 + .word 0x01a01401 + .word 0x02888008 + .word 0xe1b09e21 + .word 0x01a01201 + .word 0x02888004 + .word 0xe1b09f21 + .word 0x01a01101 + .word 0x02888002 + .word 0xe1b09fa1 + .word 0x01a01081 + .word 0x02888001 + .word 0xe2789020 + .word 0xe1811932 + .word 0xe1a02812 + .word 0xe0833008 + .word 0xe1a0f00e + .word 0xe3100101 + .word 0x03130101 + .word 0x1a0003c1 + .word 0xe92d4000 + .word 0xe31b0602 + .word 0x12233102 + .word 0xe31b0601 + .word 0x12233102 + .word 0x12200102 + .word 0xe1a06880 + .word 0xe0568883 + .word 0xe020e003 + .word 0xe2000102 + .word 0xe1a038a6 + .word 0x8a00001a + .word 0x01a09008 + .word 0x0a00002e + .word 0xe2686000 + .word 0xe1a068a6 + .word 0xe0833006 + .word 0xe1a092a6 + .word 0xe1c66289 + .word 0xe3590002 + .word 0x33390000 + .word 0xe2669020 + .word 0xe1a08912 + .word 0xe1a02632 + .word 0xe1822911 + .word 0xe1a01631 + .word 0x0a000003 + .word 0x11888108 + .word 0x11828128 + .word 0x11a02001 + .word 0x13a01000 + .word 0x3a000004 + .word 0x21888002 + .word 0x21888108 + .word 0x21818128 + .word 0x23a02000 + .word 0x23a01000 + .word 0xe3a09000 + .word 0xea000015 + .word 0xe1a068a8 + .word 0xe1a082a6 + .word 0xe1c66288 + .word 0xe3580002 + .word 0x33380000 + .word 0xe2668020 + .word 0xe1a09815 + .word 0xe1a05635 + .word 0xe1855814 + .word 0xe1a04634 + .word 0x0a000003 + .word 0x11899109 + .word 0x11859129 + .word 0x11a05004 + .word 0x13a04000 + .word 0x3a000004 + .word 0x21899005 + .word 0x21899109 + .word 0x21849129 + .word 0x23a05000 + .word 0x23a04000 + .word 0xe3a08000 + .word 0xe31e0102 + .word 0x1a000009 + .word 0xe0986009 + .word 0xe0b22005 + .word 0xe0b11004 + .word 0x38bd8000 + .word 0xe2833001 + .word 0xe1b01061 + .word 0xe1b02062 + .word 0xe1866086 + .word 0xe1a06066 + .word 0xe8bd8000 + .word 0xe0586009 + .word 0xe0d22005 + .word 0xe0d11004 + .word 0x2a000003 + .word 0xe2200102 + .word 0xe2766000 + .word 0xe2f22000 + .word 0xe2e11000 + .word 0xe3110102 + .word 0x18bd8000 + .word 0xe0966006 + .word 0xe0b22002 + .word 0xe0a11001 + .word 0xe2433001 + .word 0xe3110102 + .word 0x18bd8000 + .word 0xe191e002 + .word 0x1bffff56 + .word 0x18bd8000 + .word 0xe20b8060 + .word 0xe3380040 + .word 0x03a00102 + .word 0x13a00000 + .word 0xe3a03000 + .word 0xe8bd8000 + .word 0xe3100101 + .word 0x03130101 + .word 0x1a000395 + .word 0xe0118004 + .word 0x5a0003b5 + .word 0xe3c08103 + .word 0xe3c39103 + .word 0xe0200003 + .word 0xe2000102 + .word 0xe0883009 + .word 0xe2433c3f + .word 0xe24330fe + .word 0xe31b0502 + .word 0x1a00007f + .word 0xe3320000 + .word 0x0a00005d + .word 0xe3350000 + .word 0x0a00003d + .word 0xe92d4881 + .word 0xe1a00821 + .word 0xe1c17800 + .word 0xe1a06824 + .word 0xe1c48806 + .word 0xe0090690 + .word 0xe0060697 + .word 0xe0070798 + .word 0xe0977806 + .word 0xe0a99826 + .word 0xe0080890 + .word 0xe0977808 + .word 0xe0a90828 + .word 0xe1a0b822 + .word 0xe1c2e80b + .word 0xe1a06825 + .word 0xe1c58806 + .word 0xe009069b + .word 0xe006069e + .word 0xe00e0e98 + .word 0xe09ee806 + .word 0xe0a99826 + .word 0xe008089b + .word 0xe09ee808 + .word 0xe0a9b828 + .word 0xe097700b + .word 0xe2a00000 + .word 0xe097b00e + .word 0xe0b77000 + .word 0xe2a00000 + .word 0xe0518002 + .word 0xe3a01000 + .word 0xe3a06000 + .word 0x31e01001 + .word 0x30446005 + .word 0x10559004 + .word 0x03a01000 + .word 0x31e01001 + .word 0x30466008 + .word 0xe1a04828 + .word 0xe1c85804 + .word 0xe1a08829 + .word 0xe1c99808 + .word 0xe0226894 + .word 0xe0080895 + .word 0xe0060599 + .word 0xe0966808 + .word 0xe0a22828 + .word 0xe0090994 + .word 0xe0966809 + .word 0xe0a22829 + .word 0xe09b6006 + .word 0xe0b72002 + .word 0xe0b01001 + .word 0xe18ee10e + .word 0xe186612e + .word 0x48bd8881 + .word 0xe0966006 + .word 0xe0b22002 + .word 0xe0a11001 + .word 0xe2433001 + .word 0xe8bd8881 + .word 0xe1a05824 + .word 0xe1c46805 + .word 0xe1a08821 + .word 0xe1c19808 + .word 0xe0040895 + .word 0xe0080896 + .word 0xe0010699 + .word 0xe0911808 + .word 0xe0a44828 + .word 0xe0090995 + .word 0xe0911809 + .word 0xe0a44829 + .word 0xe1a08822 + .word 0xe1c29808 + .word 0xe0020895 + .word 0xe0080896 + .word 0xe0060699 + .word 0xe0966808 + .word 0xe0a22828 + .word 0xe0090995 + .word 0xe0966809 + .word 0xe0a25829 + .word 0xe0952001 + .word 0xe2b41000 + .word 0x41a0f00e + .word 0xe0966006 + .word 0xe0b22002 + .word 0xe0a11001 + .word 0xe2433001 + .word 0xe1a0f00e + .word 0xe3350000 + .word 0x0a00001d + .word 0xe1a02821 + .word 0xe1c16802 + .word 0xe1a08824 + .word 0xe1c49808 + .word 0xe0010892 + .word 0xe0080896 + .word 0xe0040699 + .word 0xe0944808 + .word 0xe0a11828 + .word 0xe0090992 + .word 0xe0944809 + .word 0xe0a11829 + .word 0xe1a08825 + .word 0xe1c59808 + .word 0xe0050892 + .word 0xe0080896 + .word 0xe0060699 + .word 0xe0966808 + .word 0xe0a55828 + .word 0xe0090992 + .word 0xe0966809 + .word 0xe0a52829 + .word 0xe0922004 + .word 0xe2b11000 + .word 0x41a0f00e + .word 0xe0966006 + .word 0xe0b22002 + .word 0xe0a11001 + .word 0xe2433001 + .word 0xe1a0f00e + .word 0xe1a05824 + .word 0xe1c46805 + .word 0xe1a08821 + .word 0xe1c19808 + .word 0xe0010895 + .word 0xe0080896 + .word 0xe0020699 + .word 0xe0922808 + .word 0xe0a11828 + .word 0xe0090995 + .word 0xe0922809 + .word 0xe0b11829 + .word 0xe3a06000 + .word 0x41a0f00e + .word 0xe0922002 + .word 0xe0a11001 + .word 0xe2433001 + .word 0xe1a0f00e + .word 0xe3100101 + .word 0x03130101 + .word 0x1a000336 + .word 0xe0118004 + .word 0x5a000361 + .word 0xe31b0601 + .word 0x1a000008 + .word 0xe1a08000 + .word 0xe1a00003 + .word 0xe1a03008 + .word 0xe1a08001 + .word 0xe1a01004 + .word 0xe1a04008 + .word 0xe1a08002 + .word 0xe1a02005 + .word 0xe1a05008 + .word 0xe3c08103 + .word 0xe3c39103 + .word 0xe0200003 + .word 0xe2000102 + .word 0xe0493008 + .word 0xe2833c3f + .word 0xe28330ff + .word 0xe92d4889 + .word 0xe1a00821 + .word 0xe1c17800 + .word 0xe1a0b822 + .word 0xe1c2e80b + .word 0xe28f6fd9 + .word 0xe7d66420 + .word 0xe0286690 + .word 0xe2688502 + .word 0xe0060698 + .word 0xe1a069a6 + .word 0xe2866002 + .word 0xe1a086a1 + .word 0xe0296698 + .word 0xe2699202 + .word 0xe1a08829 + .word 0xe1c99808 + .word 0xe0020699 + .word 0xe0010698 + .word 0xe0816822 + .word 0xe1a06326 + .word 0xe1b040a4 + .word 0xe1b05065 + .word 0x33a03000 + .word 0x23a03102 + .word 0xe1a087a4 + .word 0xe0090896 + .word 0xe1a09829 + .word 0xe0080b99 + .word 0xe0555008 + .word 0xe0080990 + .word 0xe0c44008 + .word 0xe0080e99 + .word 0xe0533808 + .word 0xe0d55828 + .word 0xe0080799 + .word 0x30455808 + .word 0x20555808 + .word 0xe0c44828 + .word 0xe1a01809 + .word 0xe1a08124 + .word 0xe0090896 + .word 0xe1a09829 + .word 0xe0080b99 + .word 0xe0533988 + .word 0xe0d556a8 + .word 0xe0080990 + .word 0x30455988 + .word 0x20555988 + .word 0xe0c446a8 + .word 0xe0080e99 + .word 0xe0533188 + .word 0xe0d55ea8 + .word 0xe0080799 + .word 0x30455188 + .word 0x20555188 + .word 0xe0c44ea8 + .word 0xe1a04d04 + .word 0xe1844325 + .word 0xe1a05d05 + .word 0xe1855323 + .word 0xe1a03d03 + .word 0xe0811189 + .word 0xe59d800c + .word 0xe3180702 + .word 0x03180080 + .word 0x0a000094 + .word 0xe1a087a4 + .word 0xe0090896 + .word 0xe1a09829 + .word 0xe0080b99 + .word 0xe0555008 + .word 0xe0080990 + .word 0xe0c44008 + .word 0xe0080e99 + .word 0xe0533808 + .word 0xe0d55828 + .word 0xe0080799 + .word 0x30455808 + .word 0x20555808 + .word 0xe0c44828 + .word 0xe1a02b09 + .word 0xe0811529 + .word 0xe1a08124 + .word 0xe0090896 + .word 0xe1a09829 + .word 0xe0080b99 + .word 0xe0533988 + .word 0xe0d556a8 + .word 0xe0080990 + .word 0x30455988 + .word 0x20555988 + .word 0xe0c446a8 + .word 0xe0080e99 + .word 0xe0533188 + .word 0xe0d55ea8 + .word 0xe0080799 + .word 0x30455188 + .word 0x20555188 + .word 0xe0c44ea8 + .word 0xe1a04d04 + .word 0xe1844325 + .word 0xe1a05d05 + .word 0xe1855323 + .word 0xe1a03d03 + .word 0xe0922489 + .word 0xe2a11000 + .word 0xe59d800c + .word 0xe3180702 + .word 0x0a00003f + .word 0xe1a087a4 + .word 0xe0090896 + .word 0xe1a09829 + .word 0xe0080b99 + .word 0xe0555008 + .word 0xe0080990 + .word 0xe0c44008 + .word 0xe0080e99 + .word 0xe0533808 + .word 0xe0d55828 + .word 0xe0080799 + .word 0x30455808 + .word 0x20555808 + .word 0xe0c44828 + .word 0xe1a04704 + .word 0xe1844925 + .word 0xe1a05705 + .word 0xe1855923 + .word 0xe1a03703 + .word 0xe1a06e09 + .word 0xe0922229 + .word 0xe2a11000 + .word 0xe1870800 + .word 0xe18e780b + .word 0xe3a0e000 + .word 0xe0559007 + .word 0xe0d48000 + .word 0x21a05009 + .word 0x21a04008 + .word 0xe0aee00e + .word 0xe3a0b000 + .word 0xe0933003 + .word 0xe0b55005 + .word 0xe0b44004 + .word 0xe0abb00b + .word 0xe0559007 + .word 0xe0d48000 + .word 0xe2dbb000 + .word 0x21a05009 + .word 0x21a04008 + .word 0xe0aee00e + .word 0xe3a0b000 + .word 0xe0933003 + .word 0xe0b55005 + .word 0xe0b44004 + .word 0xe0abb00b + .word 0xe0559007 + .word 0xe0d48000 + .word 0xe2dbb000 + .word 0x21a05009 + .word 0x21a04008 + .word 0xe0aee00e + .word 0xe1948005 + .word 0x13866001 + .word 0xe0966e0e + .word 0xe2b22000 + .word 0xe2b11000 + .word 0x48bd8889 + .word 0xe8bd4889 + .word 0xe0966006 + .word 0xe0b22002 + .word 0xe0a11001 + .word 0xe2433001 + .word 0xe1a0f00e + .word 0xe1870800 + .word 0xe18e780b + .word 0xe3a0e000 + .word 0xe0933003 + .word 0xe0b55005 + .word 0xe0a44004 + .word 0xe0559007 + .word 0xe0d48000 + .word 0x21a05009 + .word 0x21a04008 + .word 0xe0aee00e + .word 0xe3a0b000 + .word 0xe0933003 + .word 0xe0b55005 + .word 0xe0b44004 + .word 0xe0abb00b + .word 0xe0559007 + .word 0xe0d48000 + .word 0xe2dbb000 + .word 0x21a05009 + .word 0x21a04008 + .word 0xe0aee00e + .word 0xe3a0b000 + .word 0xe0933003 + .word 0xe0b55005 + .word 0xe0b44004 + .word 0xe0abb00b + .word 0xe0559007 + .word 0xe0d48000 + .word 0xe2dbb000 + .word 0x21a05009 + .word 0x21a04008 + .word 0xe0aee00e + .word 0xe1846005 + .word 0xe092248e + .word 0xe2b11000 + .word 0x48bd8889 + .word 0xe8bd4889 + .word 0xe0922002 + .word 0xe0a11001 + .word 0xe2433001 + .word 0xe1a0f00e + .word 0xe1870800 + .word 0xe18e780b + .word 0xe0933003 + .word 0xe0b55005 + .word 0xe0a44004 + .word 0xe0559007 + .word 0xe0d48000 + .word 0x21a05009 + .word 0x21a04008 + .word 0x22811020 + .word 0xe3a0b000 + .word 0xe0933003 + .word 0xe0b55005 + .word 0xe0b44004 + .word 0xe0abb00b + .word 0xe0559007 + .word 0xe0d48000 + .word 0xe2dbb000 + .word 0x21a05009 + .word 0x21a04008 + .word 0x22811010 + .word 0xe3a0b000 + .word 0xe0933003 + .word 0xe0b55005 + .word 0xe0b44004 + .word 0xe0abb00b + .word 0xe0559007 + .word 0xe0d48000 + .word 0xe2dbb000 + .word 0x21a05009 + .word 0x21a04008 + .word 0x22811008 + .word 0xe1846005 + .word 0xe3a02000 + .word 0xe3310000 + .word 0x48bd8889 + .word 0xe8bd4889 + .word 0xe1a01081 + .word 0xe2433001 + .word 0xe1a0f00e + .word 0x7e7f8080 + .word 0x7a7b7c7d + .word 0x76777879 + .word 0x73747576 + .word 0x70717172 + .word 0x6d6e6e6f + .word 0x6a6b6c6c + .word 0x6868696a + .word 0x65666667 + .word 0x63636464 + .word 0x60616162 + .word 0x5e5f5f60 + .word 0x5c5d5d5e + .word 0x5a5b5b5c + .word 0x5859595a + .word 0x56575758 + .word 0x55555556 + .word 0x53535454 + .word 0x51525252 + .word 0x50505051 + .word 0x4e4f4f4f + .word 0x4d4d4d4e + .word 0x4b4c4c4c + .word 0x4a4a4b4b + .word 0x4949494a + .word 0x47484848 + .word 0x46474747 + .word 0x45454646 + .word 0x44444445 + .word 0x43434344 + .word 0x42424243 + .word 0x41414142 + .word 0xe3100101 + .word 0x03130101 + .word 0x1a00025f + .word 0xe1946005 + .word 0x03a0800a + .word 0x0afffc6c + .word 0xe1916002 + .word 0x0a000297 + .word 0xe92d4000 + .word 0xe3c33103 + .word 0xe2433001 + .word 0xe3c06103 + .word 0xe0566003 + .word 0xe2000102 + .word 0xb0863003 + .word 0xb3a06000 + .word 0xb1a0f00e + .word 0xe1a000c0 + .word 0xe3a0e000 + .word 0xea000002 + .word 0xe1a0efa1 + .word 0xe0922002 + .word 0xe0a11001 + .word 0xe0728005 + .word 0xe0f19004 + .word 0xe2fee000 + .word 0x2a000002 + .word 0xe0982005 + .word 0xe0a91004 + .word 0xe2200102 + .word 0xe2566001 + .word 0xaafffff3 + .word 0xe3a06000 + .word 0xe1918002 + .word 0x01a00080 + .word 0x03a03000 + .word 0x12000102 + .word 0x1bfffd52 + .word 0xe8bd8000 + .word 0xe3100101 + .word 0x1a00027f + .word 0xe3110102 + .word 0x0a000293 + .word 0xe3c03103 + .word 0xe2100102 + .word 0x13a0800b + .word 0x1afffbe1 + .word 0xe2833c3f + .word 0xe28330ff + .word 0xe1b030a3 + .word 0x32414102 + .word 0x22414101 + .word 0xe1a05002 + .word 0xe3a08202 + .word 0xe3a01102 + .word 0xe3a02000 + .word 0xe3a0928b + .word 0xe1a069ab + .word 0xe3160001 + .word 0x03a0926b + .word 0x031b0080 + .word 0x03a09103 + .word 0x3a000005 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe1816008 + .word 0x31540006 + .word 0x20444006 + .word 0x21811088 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe18160a8 + .word 0x31540006 + .word 0x20444006 + .word 0x21811008 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe1816128 + .word 0x31540006 + .word 0x20444006 + .word 0x218110a8 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe18161a8 + .word 0x31540006 + .word 0x20444006 + .word 0x21811128 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe1816228 + .word 0x31540006 + .word 0x20444006 + .word 0x218111a8 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe18162a8 + .word 0x31540006 + .word 0x20444006 + .word 0x21811228 + .word 0xe2999201 + .word 0xe1a08368 + .word 0xbaffffd8 + .word 0xe1946005 + .word 0x13580020 + .word 0x01a0f00e + .word 0xe92d4880 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe0aee00e + .word 0xe1826008 + .word 0xe055b006 + .word 0xe0d47001 + .word 0x31b0e0ae + .word 0x21a0500b + .word 0x21a04007 + .word 0x21822088 + .word 0x21811fa8 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe0aee00e + .word 0xe18260a8 + .word 0xe055b006 + .word 0xe0d47001 + .word 0x31b0e0ae + .word 0x21a0500b + .word 0x21a04007 + .word 0x21822008 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe0aee00e + .word 0xe1826128 + .word 0xe055b006 + .word 0xe0d47001 + .word 0x31b0e0ae + .word 0x21a0500b + .word 0x21a04007 + .word 0x218220a8 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe0aee00e + .word 0xe18261a8 + .word 0xe055b006 + .word 0xe0d47001 + .word 0x31b0e0ae + .word 0x21a0500b + .word 0x21a04007 + .word 0x21822128 + .word 0xe2599001 + .word 0xe1a08268 + .word 0x1affffd3 + .word 0xe1946005 + .word 0x13580080 + .word 0x08bd8880 + .word 0xe0955005 + .word 0xe0b44004 + .word 0xe0aee00e + .word 0xe2788000 + .word 0xe0f2b005 + .word 0xe0f17004 + .word 0x31b0e0ae + .word 0x21a0500b + .word 0x21a04007 + .word 0x33a08000 + .word 0x23822001 + .word 0xe3a06106 + .word 0xe0988008 + .word 0xe0b55005 + .word 0xe0b44004 + .word 0x28bd8880 + .word 0xe0d5b002 + .word 0xe0d4b001 + .word 0x33a06001 + .word 0xe8bd8880 + .word 0xe3100101 + .word 0x1a00021a + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe3a06000 + .word 0xe31b0601 + .word 0x12200102 + .word 0xe31b0602 + .word 0x13c00102 + .word 0xe1a0f00e + .word 0xe3100101 + .word 0x1a000236 + .word 0xe3c03103 + .word 0xe3110102 + .word 0x1a000008 + .word 0xe1918002 + .word 0x03a03000 + .word 0x0a000005 + .word 0xe92d4000 + .word 0xe0116080 + .word 0x43c11102 + .word 0x42833001 + .word 0xebfffcb4 + .word 0xe8bd4000 + .word 0xe2000102 + .word 0xe3a06000 + .word 0xe1a0f00e + .word 0xe3100101 + .word 0x1a000232 + .word 0xe3c06103 + .word 0xe2000102 + .word 0xe3a03016 + .word 0xe31b0080 + .word 0x13a03033 + .word 0xe31b0702 + .word 0x13a0303e + .word 0xe3833901 + .word 0xe0538006 + .word 0x9a000014 + .word 0xe1a092a8 + .word 0xe1c88289 + .word 0xe3590002 + .word 0x33390000 + .word 0xe2689020 + .word 0xe1a06912 + .word 0xe1a02832 + .word 0xe1822911 + .word 0xe1a01831 + .word 0x0a000003 + .word 0x11866106 + .word 0x11826126 + .word 0x11a02001 + .word 0x13a01000 + .word 0x3a000004 + .word 0x21866002 + .word 0x21866106 + .word 0x21816126 + .word 0x23a02000 + .word 0x23a01000 + .word 0xe1a0f00e + .word 0xe1a03006 + .word 0xe3a06000 + .word 0xe1a0f00e + .word 0xe3100101 + .word 0x1a000219 + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe3110102 + .word 0x0a000049 + .word 0x13a0603e + .word 0xe3866901 + .word 0xe0568003 + .word 0xda000045 + .word 0xe2789020 + .word 0xba000017 + .word 0xe1b08912 + .word 0x0a000041 + .word 0xe1b08080 + .word 0x231b0020 + .word 0x331b0040 + .word 0x1a000007 + .word 0xe31b0060 + .word 0x1a00000a + .word 0xe2898001 + .word 0xe1b08812 + .word 0x1a000001 + .word 0xe1b080a1 + .word 0xe1b08912 + .word 0x2a000004 + .word 0xe2699020 + .word 0xe1a02932 + .word 0xe1a02912 + .word 0xe3a06101 + .word 0xe1a0f00e + .word 0xe2699020 + .word 0xe1e02932 + .word 0xe1e02912 + .word 0xe3a06103 + .word 0xe1a0f00e + .word 0xe2789040 + .word 0xba00001a + .word 0xe1928911 + .word 0x0a000027 + .word 0xe1b08080 + .word 0x231b0020 + .word 0x331b0040 + .word 0x1a000007 + .word 0xe31b0060 + .word 0x1a00000c + .word 0xe2898001 + .word 0xe1928811 + .word 0x1a000001 + .word 0xe3590001 + .word 0x21b08911 + .word 0x2a000006 + .word 0xe2699020 + .word 0xe1a01931 + .word 0xe1b01911 + .word 0xe3a02000 + .word 0x03a03000 + .word 0xe3a06101 + .word 0xe1a0f00e + .word 0xe2699020 + .word 0xe1e01931 + .word 0xe1e01911 + .word 0xe3e02000 + .word 0xe3a06103 + .word 0xe1a0f00e + .word 0xe0208d0b + .word 0xe0209c8b + .word 0xe1d88009 + .word 0x4a000004 + .word 0xe3a01000 + .word 0xe3a02000 + .word 0xe3a03000 + .word 0xe3a06101 + .word 0xe1a0f00e + .word 0xe3e01000 + .word 0xe3e02000 + .word 0xe3a03c3f + .word 0xe38330fe + .word 0xe3a06103 + .word 0xe1a0f00e + .word 0xe3a06000 + .word 0xe1a0f00e + .word 0xe3100101 + .word 0x03130101 + .word 0x1a0001d7 + .word 0xe31b0602 + .word 0x02233102 + .word 0xe1a08880 + .word 0xe1580883 + .word 0x01510004 + .word 0x01520005 + .word 0x0a000004 + .word 0x23300000 + .word 0x33330000 + .word 0x53a06202 + .word 0x43a06102 + .word 0xe1a0f00e + .word 0xe0309003 + .word 0xe3a06206 + .word 0x41a0f00e + .word 0xe1888001 + .word 0xe1988002 + .word 0x01a0f00e + .word 0xe3100102 + .word 0x03a06202 + .word 0x13a06102 + .word 0xe1a0f00e + .word 0xe3100101 + .word 0x1a0001f9 + .word 0xe3c06103 + .word 0xe2000102 + .word 0xe92d4000 + .word 0xe3a03901 + .word 0xe383303e + .word 0xe0538006 + .word 0x9a000023 + .word 0xe1a092a8 + .word 0xe1c88289 + .word 0xe3590002 + .word 0x33390000 + .word 0xe2689020 + .word 0xe1a06912 + .word 0xe1a02832 + .word 0xe1822911 + .word 0xe1a01831 + .word 0x0a000003 + .word 0x11866106 + .word 0x11826126 + .word 0x11a02001 + .word 0x13a01000 + .word 0x3a000004 + .word 0x21866002 + .word 0x21866106 + .word 0x21816126 + .word 0x23a02000 + .word 0x23a01000 + .word 0xe20b5060 + .word 0xe3855c01 + .word 0xe3a04000 + .word 0xebfff86d + .word 0xe1b08080 + .word 0x21e01001 + .word 0x22722000 + .word 0x22811001 + .word 0xe1310fc2 + .word 0x1a000005 + .word 0xe1a06002 + .word 0xe3540000 + .word 0x11b08aa7 + .word 0x33877010 + .word 0x8bfff9fe + .word 0xe8bd8000 + .word 0xe8bd4000 + .word 0xe3e06102 + .word 0xe0266fc0 + .word 0xe3a0800e + .word 0xeafffb03 + .word 0xe1a09883 + .word 0xe3790802 + .word 0x30099004 + .word 0xe0199083 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a000014 + .word 0xe3190102 + .word 0x1a000022 + .word 0xe92d4000 + .word 0xe0116080 + .word 0x43c11102 + .word 0x42800001 + .word 0xe0146083 + .word 0x43c44102 + .word 0x42833001 + .word 0xe3100101 + .word 0x11b06880 + .word 0x1bfffb5d + .word 0xe3130101 + .word 0x11b06883 + .word 0x1bfffb94 + .word 0xebfffc24 + .word 0xe3110102 + .word 0x18bd8000 + .word 0xe191e002 + .word 0x1bfffbd2 + .word 0xe8bd8000 + .word 0xe3190102 + .word 0x0a000009 + .word 0xe1828081 + .word 0xe1888005 + .word 0xe1988084 + .word 0x1afffa1f + .word 0xe023850b + .word 0xe0388000 + .word 0x52008102 + .word 0x5a00000a + .word 0xe3a08004 + .word 0xeafffabf + .word 0xe1928081 + .word 0x1afffa35 + .word 0xe2008102 + .word 0xea000004 + .word 0xe1958084 + .word 0x1afffa1b + .word 0xe2038102 + .word 0xe31b0602 + .word 0x12288102 + .word 0xe31b0601 + .word 0x12288102 + .word 0xe28f0fe6 + .word 0xe8900007 + .word 0xe1800008 + .word 0xe1a0f00e + .word 0xe1a09883 + .word 0xe3790802 + .word 0x30099004 + .word 0xe0199083 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a00001f + .word 0xe3190102 + .word 0x1a00002f + .word 0xe1918002 + .word 0x11948005 + .word 0x0a000013 + .word 0xe0116080 + .word 0x43c11102 + .word 0x42800001 + .word 0xe0146083 + .word 0x43c44102 + .word 0x42833001 + .word 0xe3c08103 + .word 0xe3c39103 + .word 0xe0200003 + .word 0xe2000102 + .word 0xe0883009 + .word 0xe2433c3f + .word 0xe24330fe + .word 0xe92d4000 + .word 0xe3110102 + .word 0x0bfffb98 + .word 0xe3140102 + .word 0x0bfffbaf + .word 0xe8bd4000 + .word 0xeafffc50 + .word 0xe0200003 + .word 0xe2000102 + .word 0xe3a01000 + .word 0xe3a02000 + .word 0xe3a03000 + .word 0xe3a06000 + .word 0xe1a0f00e + .word 0xe3190102 + .word 0x0a000009 + .word 0xe1828081 + .word 0xe1888005 + .word 0xe1988084 + .word 0x1afff9db + .word 0xe0208003 + .word 0xe2088102 + .word 0xe28f0fb1 + .word 0xe8900007 + .word 0xe1800008 + .word 0xe1a0f00e + .word 0xe1928081 + .word 0x1afff9f1 + .word 0xe1948005 + .word 0x1afffff5 + .word 0xe3a08005 + .word 0xeafffa75 + .word 0xe1958084 + .word 0x1afff9d5 + .word 0xe1918002 + .word 0x1affffef + .word 0xe3a08006 + .word 0xeafffa6f + .word 0xe1a09883 + .word 0xe3790802 + .word 0x30099004 + .word 0xe0199083 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a000036 + .word 0xe3190102 + .word 0x1a000048 + .word 0xe1918002 + .word 0x11948005 + .word 0x0a00001e + .word 0xe31b0601 + .word 0x1a000008 + .word 0xe1a08000 + .word 0xe1a00003 + .word 0xe1a03008 + .word 0xe1a08001 + .word 0xe1a01004 + .word 0xe1a04008 + .word 0xe1a08002 + .word 0xe1a02005 + .word 0xe1a05008 + .word 0xe0116080 + .word 0x43c11102 + .word 0x42800001 + .word 0xe0146083 + .word 0x43c44102 + .word 0x42833001 + .word 0xe3c08103 + .word 0xe3c39103 + .word 0xe0200003 + .word 0xe2000102 + .word 0xe0493008 + .word 0xe2833c3f + .word 0xe28330ff + .word 0xe92d4000 + .word 0xe3110102 + .word 0x0bfffb7e + .word 0xe3140102 + .word 0x0bfffb63 + .word 0xe8bd4000 + .word 0xeafffcaf + .word 0xe3a08007 + .word 0xe31b0601 + .word 0x1a00000a + .word 0xe1919002 + .word 0x1afffaa5 + .word 0xe1949005 + .word 0x0afffa3b + .word 0xe0200003 + .word 0xe2000102 + .word 0xe3a01000 + .word 0xe3a02000 + .word 0xe3a03000 + .word 0xe3a06000 + .word 0xe1a0f00e + .word 0xe1919002 + .word 0x1afffff6 + .word 0xe1949005 + .word 0x1afffa98 + .word 0xeafffa2f + .word 0xe3190102 + .word 0x0a000005 + .word 0xe1828081 + .word 0xe1888005 + .word 0xe1988084 + .word 0x1afff983 + .word 0xe3a08008 + .word 0xeafffa27 + .word 0xe1928081 + .word 0x1afff99d + .word 0xe0208003 + .word 0xe2088102 + .word 0xe31b0601 + .word 0x028f0e15 + .word 0x128f0d05 + .word 0xe8900007 + .word 0xe1800008 + .word 0xe3a03000 + .word 0xe3a06000 + .word 0xe1a0f00e + .word 0xe1958084 + .word 0x1afff97b + .word 0xe0208003 + .word 0xe2088102 + .word 0xe31b0601 + .word 0x128f0e12 + .word 0x028f0e11 + .word 0xe8900007 + .word 0xe1800008 + .word 0xe3a03000 + .word 0xe3a06000 + .word 0xe1a0f00e + .word 0xe1a09883 + .word 0xe3790802 + .word 0x30099004 + .word 0xe0199083 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a000017 + .word 0xe3190102 + .word 0x1a000021 + .word 0xe1948005 + .word 0x03a0800a + .word 0x0afffa01 + .word 0xe1916002 + .word 0x0a00002c + .word 0xe0116080 + .word 0x43c11102 + .word 0x42800001 + .word 0xe0146083 + .word 0x43c44102 + .word 0x42833001 + .word 0xe92d4000 + .word 0xe3c33103 + .word 0xe3140102 + .word 0x0bfffb14 + .word 0xe2439001 + .word 0xe3c03103 + .word 0xe3140102 + .word 0x0bfffaf7 + .word 0xe0536009 + .word 0xe1a03009 + .word 0xeafffd88 + .word 0xe3190102 + .word 0x0a000005 + .word 0xe1828081 + .word 0xe1888005 + .word 0xe1988084 + .word 0x1afff942 + .word 0xe3a08009 + .word 0xeafff9e6 + .word 0xe1928081 + .word 0x1afff95c + .word 0xe3a08009 + .word 0xeafff9e2 + .word 0xe1958084 + .word 0x1afff942 + .word 0xe3100101 + .word 0x03c03103 + .word 0x02000102 + .word 0x03a06000 + .word 0x01a0f00e + .word 0xe1916002 + .word 0x0a000006 + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12833001 + .word 0xe3a06000 + .word 0xeafffad8 + .word 0xe2000102 + .word 0xe3a03000 + .word 0xe1a0f00e + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x40007fff + .word 0x00000000 + .word 0x00000000 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a000013 + .word 0xe1918002 + .word 0x02000102 + .word 0x0a00000d + .word 0xe3c03103 + .word 0xe2100102 + .word 0x13a0800b + .word 0x1afff95b + .word 0xe92d4000 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12833001 + .word 0xebfffabe + .word 0xe2833c3f + .word 0xe28330ff + .word 0xe1b030a3 + .word 0xe8bd4000 + .word 0xeafffd72 + .word 0xe3a03000 + .word 0xe3a06000 + .word 0xe1a0f00e + .word 0xe1928081 + .word 0x1afff921 + .word 0xe3100102 + .word 0x13a0800b + .word 0x1afff949 + .word 0xe24f008c + .word 0xe8900007 + .word 0xe1a0f00e + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a00000a + .word 0xe1918002 + .word 0x03a03000 + .word 0x0afffddd + .word 0xe3c03103 + .word 0xe92d4000 + .word 0xe0116080 + .word 0x43c11102 + .word 0x42833001 + .word 0xebfffaa0 + .word 0xe8bd4000 + .word 0xeafffdd5 + .word 0xe1928081 + .word 0x1a000008 + .word 0xe2008102 + .word 0xe31b0601 + .word 0x12288102 + .word 0xe31b0602 + .word 0x13c88102 + .word 0xe24f00f4 + .word 0xe8900007 + .word 0xe1800008 + .word 0xe1a0f00e + .word 0xe92d4000 + .word 0xebfff8d2 + .word 0xe3360000 + .word 0x4a000001 + .word 0xebfff8fa + .word 0x18bd8000 + .word 0xe31b0601 + .word 0x12200102 + .word 0xe31b0602 + .word 0x13c00102 + .word 0xe8bd8000 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x53c03103 + .word 0x5afffdc5 + .word 0xe1928081 + .word 0x1afff8ed + .word 0xe2008102 + .word 0xe24f0f55 + .word 0xe8900007 + .word 0xe1800008 + .word 0xe1a0f00e + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4afffff3 + .word 0xe3c06103 + .word 0xe2000102 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12866001 + .word 0xeafffdc3 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4affffe8 + .word 0xe1913002 + .word 0x02000102 + .word 0x0afffe2b + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe92d4000 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12833001 + .word 0xebfffa61 + .word 0xe8bd4000 + .word 0xeafffdd8 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0xe1a09883 + .word 0xe3790802 + .word 0x30099004 + .word 0xe0199083 + .word 0xe3180102 + .word 0x11926081 + .word 0x1a00001b + .word 0xe3190102 + .word 0x11956084 + .word 0x1a000018 + .word 0xe92d4000 + .word 0xe3180102 + .word 0x12000102 + .word 0x138000ff + .word 0x13800c7f + .word 0x13c11102 + .word 0xe3190102 + .word 0x12033102 + .word 0x138330ff + .word 0x13833c7f + .word 0x13c44102 + .word 0xe0116080 + .word 0x43c11102 + .word 0x42800001 + .word 0xe0146083 + .word 0x43c44102 + .word 0x42833001 + .word 0xe3100101 + .word 0x11b06880 + .word 0x1bfff9c0 + .word 0xe3130101 + .word 0x11b06883 + .word 0x1bfff9f7 + .word 0xe8bd4000 + .word 0xeafffe00 + .word 0xe3170a01 + .word 0x03a06201 + .word 0x13a06203 + .word 0xe3180102 + .word 0x11928081 + .word 0x0a000004 + .word 0xe2118101 + .word 0x0afff950 + .word 0xe3190102 + .word 0x11958084 + .word 0x0a000001 + .word 0xe2148101 + .word 0x0afff94b + .word 0xe31b0501 + .word 0x01a0f00e + .word 0xe3a0800f + .word 0xeafff947 + .word 0xe3100101 + .word 0x0afffe05 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a000005 + .word 0xe3c06103 + .word 0xe2000102 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12866001 + .word 0xeafffdfc + .word 0xe3110101 + .word 0x03a08000 + .word 0x13a0800c + .word 0xe1926081 + .word 0x03a0800d + .word 0xe3a06102 + .word 0xeafff927 + .word 0xedd8a200 + .word 0xee181102 + .word 0xee106111 + .word 0xee308110 + .word 0xe3180005 + .word 0x0e016110 + .word 0x0e192103 + .word 0x0e280102 + .word 0x0e192104 + .word 0x0e280102 + .word 0xe1a0f009 + .word 0xecb8a203 + .word 0xe2466001 + .word 0xecb8b203 + .word 0xee1a2101 + .word 0xee0a2103 + .word 0xe2566001 + .word 0x1afffffa + .word 0xee1a2101 + .word 0xe1a0f009 + .word 0xecb8b203 + .word 0xee094103 + .word 0xe2566001 + .word 0x01a0f009 + .word 0xecb8b203 + .word 0xee1c4101 + .word 0xee0c4103 + .word 0xe2566001 + .word 0x1afffffa + .word 0xe1a0f009 + .word 0xee08a109 + .word 0xee108111 + .word 0xe0389048 + .word 0xe2a99000 + .word 0xe3a06902 + .word 0xe1190006 + .word 0x01a060a6 + .word 0x0afffffc + .word 0xe3580000 + .word 0xba00000e + .word 0xea000002 + .word 0xee1a2102 + .word 0xe1190086 + .word 0x1e1a2100 + .word 0xe1b060a6 + .word 0x1afffffa + .word 0xee1a3102 + .word 0xe3190001 + .word 0x0e1a2162 + .word 0x1e1b2160 + .word 0x1e1b3100 + .word 0xea000009 + .word 0xee1a2102 + .word 0xe1190086 + .word 0x1e4a2100 + .word 0xe1b060a6 + .word 0x1afffffa + .word 0xee1a3102 + .word 0xe3190001 + .word 0x0e1a2162 + .word 0x1e4b2160 + .word 0x1e4b3100 + .word 0xee308110 + .word 0xe318000c + .word 0x1a0001b7 + .word 0xee92f113 + .word 0x03a06101 + .word 0x13a06103 + .word 0xe3180010 + .word 0x03a06000 + .word 0xee088102 + .word 0xea00010c + .word 0x80003ffe + .word 0xca20ad9a + .word 0xb5e946e9 + .word 0x00004003 + .word 0x83125100 + .word 0xb57f6509 + .word 0x80004005 + .word 0x803ff895 + .word 0x9dacd228 + .word 0x80004004 + .word 0x8eac025b + .word 0x3e7076bb + .word 0x00004007 + .word 0x9c041fd0 + .word 0xa933ef60 + .word 0x80004008 + .word 0xc05ff4e0 + .word 0x6c83bb96 + .word 0x00003ffe + .word 0xb17217f7 + .word 0xd1cf0000 + .word 0x00003fcd + .word 0xf35793c0 + .word 0x00000000 + .word 0x00003ffe + .word 0xb504f333 + .word 0xf9de6484 + .word 0x00003ffd + .word 0xde5bd8a9 + .word 0x37287195 + .word 0xe3100101 + .word 0x1a000079 + .word 0xe1918002 + .word 0x0afff8eb + .word 0xe3100102 + .word 0x13a08018 + .word 0x1afff83e + .word 0xe3c03103 + .word 0xe3a00c3f + .word 0xe38000fe + .word 0xe0433000 + .word 0xe92d4000 + .word 0xe24dd04c + .word 0xe1a09407 + .word 0xe389901f + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9040 + .word 0xed09020f + .word 0xed09c203 + .word 0xe8890007 + .word 0xed998200 + .word 0xe31b0601 + .word 0x0a000011 + .word 0xe2838001 + .word 0xe0889108 + .word 0xe0689109 + .word 0xe1a09349 + .word 0xe359001c + .word 0x2a000010 + .word 0xe24f8b0b + .word 0xe2488feb + .word 0xe0888209 + .word 0xe8980130 + .word 0xe1320008 + .word 0x01310005 + .word 0x00444003 + .word 0x01300004 + .word 0x1a000007 + .word 0xe3a06000 + .word 0xee019110 + .word 0xea00003e + .word 0xe3530001 + .word 0x0e90f11e + .word 0x03a06000 + .word 0x0e089108 + .word 0x0a000039 + .word 0xed5f113d + .word 0xee90f111 + .word 0xd2433001 + .word 0xde28010e + .word 0xee18110e + .word 0xee09110e + .word 0xce280109 + .word 0xee480101 + .word 0xee181100 + .word 0xe24f8f5e + .word 0xe3a06003 + .word 0xe1a0900f + .word 0xeaffff62 + .word 0xe24f8f59 + .word 0xe3a06003 + .word 0xe1a0900f + .word 0xeaffff67 + .word 0xee4a2104 + .word 0xee1a1100 + .word 0xee091100 + .word 0xe3330000 + .word 0x1a000008 + .word 0xe31b0601 + .word 0x1a000017 + .word 0xee1a2160 + .word 0xee0a0160 + .word 0xee91f110 + .word 0x03a06101 + .word 0x13a06103 + .word 0x1e089100 + .word 0xea00001a + .word 0xee083110 + .word 0xed5f2263 + .word 0xee1a2100 + .word 0xee1b3100 + .word 0xee090102 + .word 0xee282102 + .word 0xee2a2101 + .word 0xee0a2103 + .word 0xee081102 + .word 0xe31b0601 + .word 0x1a000005 + .word 0xee080162 + .word 0xee91f110 + .word 0x03a06101 + .word 0x13a06103 + .word 0x1e089100 + .word 0xea000009 + .word 0xee08a101 + .word 0xed5f016b + .word 0xee181162 + .word 0xe3a06101 + .word 0xe31b00e0 + .word 0x1a000003 + .word 0xe31b0702 + .word 0x1e180102 + .word 0x1e90f111 + .word 0x13a06103 + .word 0xe28d9040 + .word 0xed899200 + .word 0xe8990007 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe8bd8000 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a00000c + .word 0xe1918002 + .word 0x0afff86c + .word 0xe3c03103 + .word 0xe3100102 + .word 0x13a08018 + .word 0x1afff7be + .word 0xe92d4000 + .word 0xe3110102 + .word 0x13c11102 + .word 0x12833001 + .word 0xebfff921 + .word 0xe8bd4000 + .word 0xeaffff79 + .word 0xe1928081 + .word 0x1afff78a + .word 0xe3100102 + .word 0x13a08018 + .word 0x1afff7b2 + .word 0xe24f0b01 + .word 0xe2400fba + .word 0xe8900007 + .word 0xe1a0f00e + .word 0x00003fff + .word 0xb8aa3b29 + .word 0x5c17f0bc + .word 0x00003ffe + .word 0xb1800000 + .word 0x00000000 + .word 0x80003ff2 + .word 0xde8082e3 + .word 0x08654362 + .word 0x00003ff1 + .word 0x845a2157 + .word 0x3490f106 + .word 0x00003ff8 + .word 0xf83a5f91 + .word 0x50952c99 + .word 0x00003feb + .word 0xc99b1867 + .word 0x2822a93e + .word 0x00003ff5 + .word 0xa57862e1 + .word 0x46a6fb39 + .word 0x00003ffb + .word 0xe8b9428e + .word 0xfecff592 + .word 0x00003fbd + .word 0x80000000 + .word 0x00000000 + .word 0x00003ffd + .word 0xffffffff + .word 0xffffffff + .word 0xe3100101 + .word 0x1a00005f + .word 0xe1916002 + .word 0x0a00005a + .word 0xe1a05000 + .word 0xe92d4000 + .word 0xe24dd04c + .word 0xe1a09407 + .word 0xe389901f + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9040 + .word 0xed09020f + .word 0xed09c203 + .word 0xe8890007 + .word 0xed998200 + .word 0xe3a04000 + .word 0xe24f80dc + .word 0xe1a0900f + .word 0xeafffeca + .word 0x02868801 + .word 0x01b088a8 + .word 0x1a000030 + .word 0xe2866001 + .word 0xe1844086 + .word 0xed5f1127 + .word 0xee28a100 + .word 0xee92f111 + .word 0xba000024 + .word 0xee181100 + .word 0xe24f80d4 + .word 0xe3a06003 + .word 0xe1a0900f + .word 0xeafffec7 + .word 0xee0a4109 + .word 0xe24f8c01 + .word 0xe3a06002 + .word 0xe1a0900f + .word 0xeafffec2 + .word 0xee0a210e + .word 0xee1a2100 + .word 0xee2c4102 + .word 0xee4a1104 + .word 0xee09016e + .word 0xe3a06101 + .word 0xe31b00e0 + .word 0x1a000004 + .word 0xe31b0702 + .word 0x0a000002 + .word 0xee09110e + .word 0xee90f111 + .word 0x13a06103 + .word 0xe28d9040 + .word 0xed898200 + .word 0xe8990007 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c03103 + .word 0xe08330c4 + .word 0xe1a00f84 + .word 0xe8bd8000 + .word 0xee90f118 + .word 0xae08810e + .word 0xa3a06101 + .word 0xbd5f0150 + .word 0xb3a06103 + .word 0xeaffffeb + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe28f0b01 + .word 0xe2800f05 + .word 0xe8900007 + .word 0xe1800f84 + .word 0xe3a03601 + .word 0xe3150102 + .word 0x12633000 + .word 0xe3a06101 + .word 0xe8bd8000 + .word 0xe28f0e3f + .word 0xe890000f + .word 0xe1a0f00e + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x5affff9a + .word 0xe1928081 + .word 0x1afff6fc + .word 0xe3a04000 + .word 0xe3100102 + .word 0x024f0b02 + .word 0x02400f47 + .word 0x08900007 + .word 0x13a00000 + .word 0x13a01000 + .word 0x13a03000 + .word 0x13a06000 + .word 0xe1800f84 + .word 0xe1a0f00e + .word 0xe92d4000 + .word 0xe24dd04c + .word 0xe1a09407 + .word 0xe389901f + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9040 + .word 0xed09020f + .word 0xed09c203 + .word 0xe31b0601 + .word 0xe8890007 + .word 0x0d998200 + .word 0x1d999200 + .word 0xe8890038 + .word 0x0d999200 + .word 0x1d998200 + .word 0xe3100101 + .word 0x03130101 + .word 0x1a000096 + .word 0xeee8a101 + .word 0xeef8a102 + .word 0xee91f112 + .word 0x1a000044 + .word 0xe31b0601 + .word 0x01a08fa0 + .word 0x11a08fa3 + .word 0xe3180001 + .word 0x1e19210e + .word 0x1ee8b102 + .word 0x1ef8b103 + .word 0x1e92f113 + .word 0x03a08000 + .word 0xee91f118 + .word 0xca000002 + .word 0x0a000069 + .word 0xee90f118 + .word 0x0a000026 + .word 0xee90f118 + .word 0xbe188100 + .word 0x0a000015 + .word 0xee90f119 + .word 0x0a000006 + .word 0xe1a04008 + .word 0xe28f9fbd + .word 0xedd92100 + .word 0xee92f111 + .word 0xceb2f111 + .word 0xcafffe58 + .word 0xea000032 + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe28f0e2a + .word 0xe890000f + .word 0xe1800f88 + .word 0xe3a06000 + .word 0xe8bd8000 + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe1a00f88 + .word 0xe3a01000 + .word 0xe3a02000 + .word 0xe3a03000 + .word 0xe3a06000 + .word 0xe8bd8000 + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3170802 + .word 0x1afff793 + .word 0xe3877002 + .word 0xe24f0b02 + .word 0xe2400fad + .word 0xe8900007 + .word 0xe1800f88 + .word 0xe8bd8000 + .word 0xee90f118 + .word 0xb3a08019 + .word 0xba000107 + .word 0x0a000038 + .word 0xee90f119 + .word 0x1e91f118 + .word 0x0a000021 + .word 0xe3a04000 + .word 0xee688100 + .word 0xee180101 + .word 0xe28d8040 + .word 0xed888200 + .word 0xe5985000 + .word 0xee309110 + .word 0xe3190004 + .word 0x1affff67 + .word 0xee90f118 + .word 0x0a000010 + .word 0xe24f8b02 + .word 0xe2488e31 + .word 0xedd81100 + .word 0xee90f111 + .word 0x1eb0f111 + .word 0x1affff28 + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe8bd4000 + .word 0xe1a00005 + .word 0xeaffff70 + .word 0xe3150102 + .word 0x0e088109 + .word 0x03a06101 + .word 0x1ddf0163 + .word 0x13a06103 + .word 0xeaffff3a + .word 0xe24f8b02 + .word 0xe2488fdb + .word 0xedd82100 + .word 0xee90f112 + .word 0x1e91f112 + .word 0x1eb1f112 + .word 0x03a0801b + .word 0x0a0000d9 + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe28f0e13 + .word 0xe890000f + .word 0xe3a06000 + .word 0xe8bd8000 + .word 0xee91f118 + .word 0xd3a0801a + .word 0xda0000ca + .word 0xe28d9040 + .word 0xed898200 + .word 0xe8990007 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe2000102 + .word 0xe3a03000 + .word 0xe3a06000 + .word 0xe8bd8000 + .word 0xe1a09883 + .word 0xe3790802 + .word 0x30099004 + .word 0xe0199083 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a000010 + .word 0xe3190102 + .word 0x0affff5d + .word 0xe1958084 + .word 0x1a000002 + .word 0xe31b0601 + .word 0x0affffa2 + .word 0xeaffff58 + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe8bd4000 + .word 0xeafff616 + .word 0xe3190102 + .word 0x0a00000d + .word 0xe1828081 + .word 0xe1888005 + .word 0xe1988084 + .word 0x0affff91 + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe8bd4000 + .word 0xeafff5fe + .word 0xe1928081 + .word 0x1a000002 + .word 0xe31b0601 + .word 0x1affff83 + .word 0xeaffff39 + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe8bd4000 + .word 0xeafff60d + .word 0x00000000 + .word 0x80000000 + .word 0x00000000 + .word 0x00003fff + .word 0x00003ffe + .word 0xffffffff + .word 0xffffffff + .word 0x0000400f + .word 0x80000000 + .word 0x00000000 + .word 0x00003ffd + .word 0xa2f9836e + .word 0x4e44152a + .word 0x00004000 + .word 0xc9100000 + .word 0x00000000 + .word 0x80003fee + .word 0x95777a5c + .word 0xf72cece6 + .word 0x00003fce + .word 0xc407fb4c + .word 0x9efca5fe + .word 0x80003fd6 + .word 0xd72106e0 + .word 0x424cdf56 + .word 0x00003fde + .word 0xb091e343 + .word 0x56a17fa8 + .word 0x80003fe5 + .word 0xd7322a5a + .word 0xee055b44 + .word 0x00003fec + .word 0xb8ef1d29 + .word 0x27831824 + .word 0x80003ff2 + .word 0xd00d00d0 + .word 0x09f0d114 + .word 0x00003ff8 + .word 0x88888888 + .word 0x88858061 + .word 0x80003ffc + .word 0xaaaaaaaa + .word 0xaaaaa603 + .word 0xe3100101 + .word 0x1a00004d + .word 0xe1916002 + .word 0x0a000043 + .word 0xe92d4000 + .word 0xe24dd04c + .word 0xe1a09407 + .word 0xe389901f + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9040 + .word 0xed09020f + .word 0xed09c203 + .word 0xe8890007 + .word 0xed998200 + .word 0xee90f118 + .word 0xe0a44004 + .word 0xbe188100 + .word 0xe31b0601 + .word 0x1ddf1172 + .word 0x1e080101 + .word 0x13a04001 + .word 0xe24f80fc + .word 0xe1a0900f + .word 0xeafffd3d + .word 0x13a08010 + .word 0x1a000037 + .word 0xe0244006 + .word 0xee90f118 + .word 0xbe188100 + .word 0xa2244001 + .word 0xeddf1169 + .word 0xee90f111 + .word 0xba00001b + .word 0xee181100 + .word 0xe24f8f43 + .word 0xe3a06008 + .word 0xe1a0900f + .word 0xeafffd3a + .word 0xee1a1140 + .word 0xee091140 + .word 0xe3a06101 + .word 0xe31b00e0 + .word 0x1a000004 + .word 0xe31b0702 + .word 0x1e1a2100 + .word 0x1e0a0100 + .word 0x1e90f111 + .word 0x13a06103 + .word 0xe28d9040 + .word 0xed899200 + .word 0xe8990007 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe1a03000 + .word 0xe1a00f84 + .word 0xe8bd8000 + .word 0xed5f116d + .word 0xee181161 + .word 0xe3a06103 + .word 0xeaffffee + .word 0xe31b0601 + .word 0x1a000002 + .word 0xe2000102 + .word 0xe3a03000 + .word 0xe1a0f00e + .word 0xe24f0f7a + .word 0xe890000f + .word 0xe1a0f00e + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x5affffac + .word 0xe1928081 + .word 0x1afff586 + .word 0xe3a08011 + .word 0xeafff5af + .word 0xe28d9040 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe8bd4000 + .word 0xeafff5a5 + .word 0x80003ffe + .word 0xb25dedaf + .word 0x30f3242c + .word 0x00004002 + .word 0xa270bb27 + .word 0x61c93957 + .word 0x80004004 + .word 0x9ec1654d + .word 0x36d4f820 + .word 0x00004004 + .word 0xe4d539b0 + .word 0x56a451ad + .word 0x80004003 + .word 0xdaf2ad41 + .word 0xd05311c4 + .word 0x80004003 + .word 0xbe974377 + .word 0xcc30f9e6 + .word 0x00004006 + .word 0x96f3e4b2 + .word 0xc8e37cbc + .word 0x80004007 + .word 0xbeee77e2 + .word 0xb5423cf3 + .word 0x00004007 + .word 0xd0927880 + .word 0xf5c2170b + .word 0x80004006 + .word 0xa43601f1 + .word 0x5c3e6196 + .word 0x00003fff + .word 0xc90fdaa2 + .word 0x2168c234 + .word 0x00003fbf + .word 0xc4c68000 + .word 0x00000000 + .word 0x00004000 + .word 0xc90fdaa2 + .word 0x2168c234 + .word 0x00003fc0 + .word 0xc4c68000 + .word 0x00000000 + .word 0x00003fff + .word 0xc90fdaa2 + .word 0x2168c235 + .word 0x00003fdf + .word 0x80000000 + .word 0x00000000 + .word 0xe3100101 + .word 0x1a000075 + .word 0xe31b0501 + .word 0x01916002 + .word 0x0a00006f + .word 0xe92d4000 + .word 0xe24dd04c + .word 0xe1a09407 + .word 0xe389901f + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9040 + .word 0xed09020f + .word 0xed09c203 + .word 0xe8890007 + .word 0xed998200 + .word 0xee90f118 + .word 0xe0a44004 + .word 0xbe188100 + .word 0xee90f11e + .word 0xba000044 + .word 0xee90f119 + .word 0xba000004 + .word 0xc3a08014 + .word 0xcaffffa6 + .word 0xe31b0501 + .word 0x13140001 + .word 0x1a00004f + .word 0xe3a0520d + .word 0xe3140001 + .word 0x13a05103 + .word 0xe31b0501 + .word 0x13a0520e + .word 0x13140001 + .word 0x13a05000 + .word 0xee381109 + .word 0xee19110e + .word 0xee488101 + .word 0xee080100 + .word 0xe24f8f5f + .word 0xe3a06005 + .word 0xe1a0900f + .word 0xeafffca3 + .word 0xe24f8e15 + .word 0xe3a06005 + .word 0xe1a0900f + .word 0xeafffca8 + .word 0xee4a2104 + .word 0xe3150102 + .word 0x1e188100 + .word 0xee1a1100 + .word 0xee091100 + .word 0xe1b04105 + .word 0x2a000006 + .word 0xee1a2160 + .word 0xee0a0160 + .word 0xee91f110 + .word 0x03a06101 + .word 0x13a06103 + .word 0x1e089100 + .word 0xea00000d + .word 0x5d5f2257 + .word 0x4d5f2252 + .word 0xee090102 + .word 0xee282102 + .word 0xee2a2101 + .word 0xee0a2103 + .word 0xee081162 + .word 0xe3a06101 + .word 0xe31b00e0 + .word 0x1a000003 + .word 0xe31b0702 + .word 0x1e080102 + .word 0x1e90f111 + .word 0x13a06103 + .word 0xe3150201 + .word 0x1e189101 + .word 0xe28d9040 + .word 0xed899200 + .word 0xe8990007 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe8bd8000 + .word 0xe3a05201 + .word 0xe3140001 + .word 0x13a05000 + .word 0xe31b0501 + .word 0x13a05101 + .word 0x13140001 + .word 0x13a05103 + .word 0xed5f116c + .word 0xee90f111 + .word 0xae181100 + .word 0xaaffffc1 + .word 0xe3150102 + .word 0x1e188100 + .word 0xee089100 + .word 0xe1b04105 + .word 0x2affffd2 + .word 0xe3a06101 + .word 0xeaffffde + .word 0xee089108 + .word 0xe3a06000 + .word 0xeaffffdd + .word 0xe2000102 + .word 0xe3a03000 + .word 0xe1a0f00e + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x5affff84 + .word 0xe1928081 + .word 0x1afff4cb + .word 0xe3a08015 + .word 0xeafff4f4 + .word 0x00003ffe + .word 0xa2f9836e + .word 0x4e44152a + .word 0x00003fff + .word 0xc9100000 + .word 0x00000000 + .word 0x80003fed + .word 0x95777a5c + .word 0xf72cece6 + .word 0x80003fef + .word 0x95d5b975 + .word 0x16391da8 + .word 0x00003ff6 + .word 0xe0741531 + .word 0xdd56f650 + .word 0x80003ffc + .word 0x8895af2a + .word 0x6847fcd5 + .word 0x00003fea + .word 0x85bba783 + .word 0xb3c748a9 + .word 0x80003ff3 + .word 0xa37b24c8 + .word 0x4a42092e + .word 0x00003ff9 + .word 0xd23cf50b + .word 0xf10aca84 + .word 0x80003ffd + .word 0xeef5823f + .word 0xdecea969 + .word 0x00000000 + .word 0x80000000 + .word 0x00000000 + .word 0x00003ffe + .word 0xffffffff + .word 0xffffffff + .word 0x00005fff + .word 0x80000000 + .word 0x00000000 + .word 0xe3100101 + .word 0x1a00005c + .word 0xe1916002 + .word 0x0a000057 + .word 0xe92d4000 + .word 0xe24dd04c + .word 0xe1a09407 + .word 0xe389901f + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9040 + .word 0xed09020f + .word 0xed09c203 + .word 0xe8890007 + .word 0xed998200 + .word 0xe24f80f8 + .word 0xe1a0900f + .word 0xeafffc09 + .word 0x13a08012 + .word 0x1affff03 + .word 0xe1a04006 + .word 0xeddf1163 + .word 0xee28a100 + .word 0xee92f111 + .word 0xba000028 + .word 0xee181100 + .word 0xe24f8c01 + .word 0xe3a06003 + .word 0xe1a0900f + .word 0xeafffc08 + .word 0xee0a2109 + .word 0xee184102 + .word 0xe24f80f4 + .word 0xe3a06004 + .word 0xe1a0900f + .word 0xeafffc02 + .word 0xee0a2109 + .word 0xe3140001 + .word 0x0e4c0142 + .word 0x1e18c104 + .word 0x1e4a0144 + .word 0xe3a06101 + .word 0xe31b00e0 + .word 0x1a000006 + .word 0xe31b0702 + .word 0x0a000004 + .word 0xe3140001 + .word 0x0e4c1102 + .word 0x1e4a1104 + .word 0xee90f111 + .word 0x13a06103 + .word 0xe3a04000 + .word 0xe28d9040 + .word 0xed898200 + .word 0xe8990007 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd04c + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c03103 + .word 0xe0833004 + .word 0xe2000102 + .word 0xe8bd8000 + .word 0xed5fa253 + .word 0xee289100 + .word 0xe3140001 + .word 0x1a000006 + .word 0xe3a06101 + .word 0xee91f112 + .word 0xaaffffe9 + .word 0xee180104 + .word 0xe3a04a02 + .word 0xe2644000 + .word 0xeaffffe6 + .word 0xe3a06103 + .word 0xee91f112 + .word 0xbe180104 + .word 0xee188100 + .word 0xee580109 + .word 0xee180163 + .word 0xaaffffde + .word 0xe3a04a02 + .word 0xeaffffdd + .word 0xe2000102 + .word 0xe3a03000 + .word 0xe1a0f00e + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x5affff9d + .word 0xe1928081 + .word 0x1afff43c + .word 0xe3a08013 + .word 0xeafff465 + .word 0x80003ffe + .word 0xd66bd6cd + .word 0x8c3de934 + .word 0x80004002 + .word 0x87e9fae4 + .word 0x6b531a29 + .word 0x80004003 + .word 0xa40bfdcf + .word 0x15e65691 + .word 0x80004002 + .word 0xdb053288 + .word 0x30e70eb4 + .word 0x00004002 + .word 0xf0624f0a + .word 0x56388310 + .word 0x00004004 + .word 0xee505190 + .word 0x6d1eb4e8 + .word 0x00004005 + .word 0xac509020 + .word 0x5b6d243b + .word 0x00004004 + .word 0xa443e5e6 + .word 0x24ad4b90 + .word 0x00003fdf + .word 0x80000000 + .word 0x00000000 + .word 0x00003ffe + .word 0xffffffff + .word 0xffffffff + .word 0x00003ffd + .word 0x8930a2f4 + .word 0xf66ab18a + .word 0x00003ffe + .word 0x860a91c1 + .word 0x6b9b2c23 + .word 0x00003fbc + .word 0xb766aaaa + .word 0xaaaaaaab + .word 0x00003fff + .word 0x860a91c1 + .word 0x6b9b2c23 + .word 0x00003fbd + .word 0xb766aaaa + .word 0xaaaaaaab + .word 0x00003fff + .word 0xc90fdaa2 + .word 0x2168c234 + .word 0x00003fbf + .word 0xc4c68000 + .word 0x00000000 + .word 0x00003fff + .word 0xc90fdaa2 + .word 0x2168c234 + .word 0x00003fbf + .word 0xc4c68000 + .word 0x00000000 + .word 0x00004000 + .word 0x860a91c1 + .word 0x6b9b2c23 + .word 0x00003fbe + .word 0xb766aaaa + .word 0xaaaaaaab + .word 0x00004000 + .word 0xa78d3631 + .word 0xc681f72b + .word 0x00003fc0 + .word 0xd6ecd555 + .word 0x55555555 + .word 0x00004000 + .word 0xc90fdaa2 + .word 0x2168c234 + .word 0x00003fc0 + .word 0xc4c68000 + .word 0x00000000 + .word 0xe3100101 + .word 0x03130101 + .word 0x1a00008b + .word 0xe1946005 + .word 0x1a000005 + .word 0xe1918002 + .word 0x03a08016 + .word 0x0afff474 + .word 0xe3100102 + .word 0x01a00003 + .word 0x0a00007e + .word 0xe2036102 + .word 0xe3100102 + .word 0x12266007 + .word 0xe3c00102 + .word 0xe3c33102 + .word 0xe92d4000 + .word 0xe24dd058 + .word 0xe1a09407 + .word 0xe389901f + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9040 + .word 0xed09020f + .word 0xed09c203 + .word 0xe889003f + .word 0xedd90200 + .word 0xe1a05006 + .word 0xee490100 + .word 0xea000016 + .word 0xe3100101 + .word 0x1a000083 + .word 0xe1916002 + .word 0x0a000061 + .word 0xe2005102 + .word 0xe3c00102 + .word 0xe92d4000 + .word 0xe24dd058 + .word 0xe1a09407 + .word 0xe389901f + .word 0xe58d9000 + .word 0xe10f9000 + .word 0xe3899080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c7981f + .word 0xe3c9901f + .word 0xee209110 + .word 0xe28d9040 + .word 0xed09020f + .word 0xed09c203 + .word 0xe8890007 + .word 0xed998200 + .word 0xee90f119 + .word 0xce580109 + .word 0xc2255003 + .word 0xed5f116d + .word 0xee90f111 + .word 0xda000007 + .word 0xee393109 + .word 0xee182103 + .word 0xee2a2109 + .word 0xee0a2100 + .word 0xee39110a + .word 0xee091100 + .word 0xee4a0101 + .word 0xe2255001 + .word 0xed5f217e + .word 0xee289100 + .word 0xeed1f112 + .word 0xba000035 + .word 0xee181100 + .word 0xe24f8f9b + .word 0xe3a06004 + .word 0xe1a0900f + .word 0xeafffb27 + .word 0xe24f8f93 + .word 0xe3a06004 + .word 0xe1a0900f + .word 0xeafffb2c + .word 0xee4a2104 + .word 0xee1a1100 + .word 0xee091100 + .word 0xe3150002 + .word 0x1e189101 + .word 0xe3150007 + .word 0x1a000006 + .word 0xee1a2160 + .word 0xee0a0160 + .word 0xee91f110 + .word 0x03a06101 + .word 0x13a06103 + .word 0x1e089100 + .word 0xea00000f + .word 0xe24f8f96 + .word 0xe0859085 + .word 0xe0888189 + .word 0xedd82200 + .word 0xee090102 + .word 0xee282102 + .word 0xee2a2101 + .word 0xee0a2103 + .word 0xee081162 + .word 0xe3a06101 + .word 0xe31b00e0 + .word 0x1a000003 + .word 0xe31b0702 + .word 0x1e080102 + .word 0x1e90f111 + .word 0x13a06103 + .word 0xe3150102 + .word 0x1e189101 + .word 0xe28d9040 + .word 0xed899200 + .word 0xe8990007 + .word 0xed19020f + .word 0xed19c203 + .word 0xe28dd058 + .word 0xe10f9000 + .word 0xe3c99080 + .word 0xe129f009 + .word 0xe1a00000 + .word 0xe3c03103 + .word 0xe2000102 + .word 0xe8bd8000 + .word 0xe3150007 + .word 0x1e089100 + .word 0x1affffd2 + .word 0xed5f11b8 + .word 0xee191160 + .word 0xe3a06103 + .word 0xeaffffe9 + .word 0xe3a01000 + .word 0xe3a02000 + .word 0xe2000102 + .word 0xe3a03000 + .word 0xe1a0f00e + .word 0xe1a09883 + .word 0xe3790802 + .word 0x30099004 + .word 0xe0199083 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x4a000005 + .word 0xe3190102 + .word 0x0affff68 + .word 0xe1958084 + .word 0x1afff342 + .word 0xe3a04102 + .word 0xeaffff64 + .word 0xe3190102 + .word 0x0a000005 + .word 0xe1828081 + .word 0xe1888005 + .word 0xe1988084 + .word 0x1afff332 + .word 0xe3a08017 + .word 0xeafff3d6 + .word 0xe1928081 + .word 0x1afff34c + .word 0xe3a01102 + .word 0xeaffff58 + .word 0xe1a08880 + .word 0xe3780802 + .word 0x30088001 + .word 0xe0188080 + .word 0x5affff76 + .word 0xe1928081 + .word 0x1afff33e + .word 0xe3a01102 + .word 0xeaffff72 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0x00000000 + .word 0xe59a2080 + .word 0xe3320000 + .word 0x5a00002b + .word 0xe92d4000 + .word 0xeb00017d + .word 0xe8bd0004 + .word 0xe8bd4000 + .word 0xe5922000 + .word 0xe132000a + .word 0x0e502110 + .word 0xe59a2084 + .word 0xe3c22b01 + .word 0xe58a2084 + .word 0xe24f2b1b + .word 0xe2422f2a + .word 0xe24f3d01 + .word 0xe2433f05 + .word 0xe1510002 + .word 0xa1530001 + .word 0xb1a0f00e + .word 0xe590103c + .word 0xe1510002 + .word 0xa1530001 + .word 0xb1a0f00e + .word 0xe2804044 + .word 0xe5145004 + .word 0xe3150001 + .word 0x1cb48203 + .word 0xe3150002 + .word 0x1cb49203 + .word 0xe3150004 + .word 0x1cb4a203 + .word 0xe3150008 + .word 0x1cb4b203 + .word 0xe3150010 + .word 0x1cb4c203 + .word 0xe3150020 + .word 0x1cb4d203 + .word 0xe3150040 + .word 0x1cb4e203 + .word 0xe3150080 + .word 0x1cb4f203 + .word 0xe1a052a5 + .word 0xe3855481 + .word 0xee205110 + .word 0xe5900030 + .word 0xeaffffe4 + .word 0xe24f2a06 + .word 0xe2422ed3 + .word 0xe24f3d03 + .word 0xe2433f07 + .word 0xe1510002 + .word 0xa1530001 + .word 0xb1a0f00e + .word 0xe590103c + .word 0xe1510002 + .word 0xa1530001 + .word 0xb1a0f00e + .word 0xe28a3000 + .word 0xe2804044 + .word 0xe5145004 + .word 0xe3150001 + .word 0x18b400c2 + .word 0x188300c2 + .word 0xe2833010 + .word 0xe3150002 + .word 0x18b400c2 + .word 0x188300c2 + .word 0xe2833010 + .word 0xe3150004 + .word 0x18b400c2 + .word 0x188300c2 + .word 0xe2833010 + .word 0xe3150008 + .word 0x18b400c2 + .word 0x188300c2 + .word 0xe2833010 + .word 0xe3150010 + .word 0x18b400c2 + .word 0x188300c2 + .word 0xe2833010 + .word 0xe3150020 + .word 0x18b400c2 + .word 0x188300c2 + .word 0xe2833010 + .word 0xe3150040 + .word 0x18b400c2 + .word 0x188300c2 + .word 0xe2833010 + .word 0xe3150080 + .word 0x18b400c2 + .word 0x188300c2 + .word 0xe24f3c01 + .word 0xe2433f22 + .word 0xe1a052a5 + .word 0xe3855401 + .word 0xe58a5080 + .word 0xe5900030 + .word 0xeaffffd2 + .word 0xe3e00000 + .word 0xe1b0f00e + .word 0xe92d401e + .word 0xe58a1004 + .word 0xe3a0e000 + .word 0xe58ae000 + .word 0xe10f3000 + .word 0xe3830080 + .word 0xe129f000 + .word 0xe24f102c + .word 0xeb00011c + .word 0xe3a00000 + .word 0xee504110 + .word 0xe3300000 + .word 0x158a0008 + .word 0x1a000008 + .word 0xe3a02102 + .word 0xee302110 + .word 0xe1a00c22 + .word 0xe58a0008 + .word 0xe3300081 + .word 0x03a04c0d + .word 0x0e008109 + .word 0x0e100100 + .word 0xee404110 + .word 0xeb000112 + .word 0xe129f003 + .word 0xe8bd801e + .word 0xe92d400f + .word 0xe3a00000 + .word 0xe58a0084 + .word 0xe92d4000 + .word 0xeb0000fe + .word 0xe8bd0001 + .word 0xe8bd4000 + .word 0xe5900008 + .word 0xe3300081 + .word 0x1a00000d + .word 0xe24f0f8e + .word 0xe890000e + .word 0xe28a0000 + .word 0xe8a0000e + .word 0xe8a0000e + .word 0xe8a0000e + .word 0xe8a0000e + .word 0xe8a0000e + .word 0xe8a0000e + .word 0xe8a0000e + .word 0xe8a0000e + .word 0xe59f003c + .word 0xe58a0080 + .word 0xe8bd800f + .word 0xe24f0e27 + .word 0xe890000e + .word 0xe28a0000 + .word 0xe8a0001e + .word 0xe8a0001e + .word 0xe8a0001e + .word 0xe8a0001e + .word 0xe8a0001e + .word 0xe8a0001e + .word 0xe8a0001e + .word 0xe8a0001e + .word 0xe59f0008 + .word 0xe58a0080 + .word 0xe8bd800f + .word 0x81070000 + .word 0x01070000 + .word 0xe92d4007 + .word 0xe28fe074 + .word 0xe92d4000 + .word 0xeb0000d7 + .word 0xe8bd0001 + .word 0xe8bd4000 + .word 0xe5900000 + .word 0xe3300000 + .word 0x01a0f00e + .word 0xe5901080 + .word 0xe3310000 + .word 0x5a00000e + .word 0xe92d4002 + .word 0xee501110 + .word 0xe3110c01 + .word 0x01a0e001 + .word 0x1590e084 + .word 0xe3ceec0d + .word 0xe3110b01 + .word 0x138eec05 + .word 0xe580e084 + .word 0xee301110 + .word 0xe5801080 + .word 0xed800200 + .word 0xed80420c + .word 0xee40e110 + .word 0xe8bd8002 + .word 0xe92d4000 + .word 0xe3a0e000 + .word 0xe580e084 + .word 0xe8bd8000 + .word 0xe92d4007 + .word 0xe92d4000 + .word 0xeb0000b9 + .word 0xe8bd0001 + .word 0xe8bd4000 + .word 0xe580a000 + .word 0xe5900008 + .word 0xe3300081 + .word 0x0e501110 + .word 0xe33a0000 + .word 0x0a000014 + .word 0xe3300081 + .word 0x1a00000b + .word 0xe59a1080 + .word 0xee201110 + .word 0xed9a0200 + .word 0xed9a420c + .word 0xe24f1a06 + .word 0xe2411efd + .word 0xeb0000b0 + .word 0xe59a1084 + .word 0xe3110b01 + .word 0x13a01c05 + .word 0x1e401110 + .word 0xe8bd8007 + .word 0xe3300081 + .word 0x03a01c0d + .word 0x0e401110 + .word 0xe24f1b19 + .word 0xe2411f1e + .word 0xeb0000a5 + .word 0xe8bd8007 + .word 0xe3300081 + .word 0x03a01c0d + .word 0x0e401110 + .word 0xe8bd4007 + .word 0xea0000a4 + .word 0xe92d4400 + .word 0xe3a0a000 + .word 0xebffffd7 + .word 0xe8bd8400 + .word 0xe92d4000 + .word 0xeb000091 + .word 0xe8bd0001 + .word 0xe8bd4000 + .word 0xe5900000 + .word 0xe3300000 + .word 0x01a0f00e + .word 0xe5901080 + .word 0xe3310000 + .word 0x5a000007 + .word 0xee501110 + .word 0xe3110c01 + .word 0x01a02001 + .word 0x15902084 + .word 0xe3822c09 + .word 0xe5802084 + .word 0xee402110 + .word 0xe1a0f00e + .word 0xe3a01001 + .word 0xe5801084 + .word 0xe1a0f00e + .word 0xe92d4000 + .word 0xeb00007c + .word 0xe8bd0001 + .word 0xe8bd4000 + .word 0xe5900000 + .word 0xe3300000 + .word 0x01a0f00e + .word 0xe5901080 + .word 0xe3310000 + .word 0x5a00000e + .word 0xee501110 + .word 0xe3110b01 + .word 0x01a0f00e + .word 0xe3110c01 + .word 0x01a02001 + .word 0x15902084 + .word 0xe3822c01 + .word 0xe3c22b02 + .word 0xe5802084 + .word 0xee301110 + .word 0xe5801080 + .word 0xed800200 + .word 0xed80420c + .word 0xee402110 + .word 0xe1a0f00e + .word 0xe3a01000 + .word 0xe5801084 + .word 0xe1a0f00e + .word 0xe92d40fe + .word 0xe59a2080 + .word 0xe3320000 + .word 0x5a000010 + .word 0xe3a0700c + .word 0xe92d4000 + .word 0xeb00005b + .word 0xe8bd0004 + .word 0xe8bd4000 + .word 0xe5922000 + .word 0xe132000a + .word 0x159a6084 + .word 0x1a000005 + .word 0xee506110 + .word 0xee302110 + .word 0xe58a2080 + .word 0xed8a0200 + .word 0xed8a420c + .word 0xee406110 + .word 0xe2066b01 + .word 0xea000001 + .word 0xe3a07010 + .word 0xe3a06000 + .word 0xe59a2080 + .word 0xe4802004 + .word 0xe3a02008 + .word 0xe89a0038 + .word 0xe08aa007 + .word 0xe3130101 + .word 0x0a000009 + .word 0xe3c33101 + .word 0xe3140102 + .word 0x0a000008 + .word 0xe3c44102 + .word 0xe3130901 + .word 0x02833001 + .word 0x0a000004 + .word 0xe38330ff + .word 0xe3833c7f + .word 0xea000006 + .word 0xe3140102 + .word 0x1a000004 + .word 0xe92d0340 + .word 0xe1a06883 + .word 0xe2968802 + .word 0x1bfff338 + .word 0xe8bd0340 + .word 0xe8a00038 + .word 0xe2522001 + .word 0x1affffe7 + .word 0xe24f2a07 + .word 0xe2422f6f + .word 0xe24f3b01 + .word 0xe2433f5a + .word 0xe1510002 + .word 0xa1530001 + .word 0xa3a00001 + .word 0xb1a00006 + .word 0xe8bd80fe + .word 0xe92d40ff + .word 0xe59a1080 + .word 0xe3310000 + .word 0x53a07010 + .word 0x43a0700c + .word 0xe4902004 + .word 0xe3c224ff + .word 0x53822401 + .word 0x43822481 + .word 0xe58a2080 + .word 0xe3a02008 + .word 0xe8b00038 + .word 0xe1846005 + .word 0xe1966083 + .word 0x0a000003 + .word 0xe1a06883 + .word 0xe2966802 + .word 0x13140102 + .word 0x03833101 + .word 0xe88a0038 + .word 0xe08aa007 + .word 0xe2522001 + .word 0x1afffff3 + .word 0xe04aa187 + .word 0xe3310000 + .word 0x58bd80ff + .word 0xe92d4000 + .word 0xeb00000b + .word 0xe8bd0004 + .word 0xe8bd4000 + .word 0xe5922000 + .word 0xe132000a + .word 0x18bd80ff + .word 0xee506110 + .word 0xe59a2080 + .word 0xee202110 + .word 0xed9a0200 + .word 0xed9a420c + .word 0xee406110 + .word 0xe8bd80ff + .word 0xe24dd008 + .word 0xe58d0000 + .word 0xe59f0008 + .word 0xe58d0004 + .word 0xe49d0004 + .word 0xe1a0f00e + .word 0x00000000 + .word 0x00000000 + .word 0xe92d4003 + .word 0xe59f0004 + .word 0xe5801000 + .word 0xe8bd8003 + .word 0x00000000 + .word 0xe92d4007 + .word 0xe51f0010 + .word 0xe59f1004 + .word 0xe5801000 + .word 0xe8bd8007 + .word 0x00000000 + .word 0xe1a0d00c + .word 0xe8dd7fff + .word 0xe0000000 + .word 0xe28dd03c + .word 0xe8bd8000 + .word 0xe3a00000 + .word 0xea000009 + .word 0xe3a00001 + .word 0xea000007 + .word 0xe3a00002 + .word 0xea000005 + .word 0xe3a00003 + .word 0xea000003 + .word 0xe3a00004 + .word 0xea000001 + .word 0xe3e00000 + .word 0xeaffffff + .word 0xe59f1000 + .word 0xe1a0f001 + .word 0x00000000 + .word 0xe3a00005 + .word 0xeafffffa + .word 0xe1a00000 + .word 0xe59f1030 + .word 0xe24fb010 + .word 0xe05b1001 + .word 0x01a0f00e + .word 0xe59fb024 + .word 0xe08bb001 + .word 0xe28f2020 + .word 0xe4920004 + .word 0xe3700001 + .word 0xd1a0f00e + .word 0xe79b3000 + .word 0xe0833001 + .word 0xe78b3000 + .word 0xeafffff8 + .word 0x0000f370 + .word 0x00008000 + .word 0x000073ac + .word 0x000073b0 + .word 0xffffffff + diff --git a/sys/arch/arm32/fpe-arm/armfpe_glue.S b/sys/arch/arm32/fpe-arm/armfpe_glue.S new file mode 100644 index 00000000000..bd824f701b5 --- /dev/null +++ b/sys/arch/arm32/fpe-arm/armfpe_glue.S @@ -0,0 +1,411 @@ +/* $NetBSD: armfpe_glue.S,v 1.6 1996/03/18 19:54:59 mark 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 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 + * + * arm_fpe_glue.S + * + * Glue code for calling the ARM FPE core code + * + * Created : 21/12/95 + */ + +#include "assym.h" +#include + +sp .req r13 +lr .req r14 +pc .req r15 + +/* Offsets into fpe core for function addresses */ + +#define ARM_FPE_CORE_ABORT 0 +#define ARM_FPE_CORE_INITWS 4 +#define ARM_FPE_CORE_INITCONTEXT 8 +#define ARM_FPE_CORE_CHANGECONTEXT 12 +#define ARM_FPE_CORE_SHUTDOWN 16 +#define ARM_FPE_CORE_ACTIVATECONTEXT 20 +#define ARM_FPE_CORE_DEACTIVATECONTEXT 24 +#define ARM_FPE_CORE_SAVECONTEXT 28 +#define ARM_FPE_CORE_LOADCONTEXT 32 +#define ARM_FPE_CORE_DISABLE 36 +#define ARM_FPE_CORE_ENABLE 40 + +/* + * Ok Lots of little stubs for calling the fpe core + * routines from C + */ + + .text + .align + +arm_fpe_header: + .word _arm_fpe_mod + + .global _arm_fpe_core_disable +_arm_fpe_core_disable: + stmfd sp!, {r0-r7, lr} + ldr r0, [pc, #arm_fpe_header - . - 8] + ldr r0, [r0, #ARM_FPE_CORE_DISABLE] + + add lr, pc, #L1 - . - 8 + mov pc, r0 +L1: + ldmfd sp!, {r0-r7, pc} + + + .global _arm_fpe_core_enable +_arm_fpe_core_enable: + stmfd sp!, {r0-r7, lr} + ldr r0, [pc, #arm_fpe_header - . - 8] + ldr r0, [r0, #ARM_FPE_CORE_ENABLE] + + add lr, pc, #L2 - . - 8 + mov pc, r0 +L2: + ldmfd sp!, {r0-r7, pc} + + + .global _arm_fpe_core_initws +_arm_fpe_core_initws: + stmfd sp!, {r10, lr} + mov r10, r0 + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_INITWS] + + add lr, pc, #L3 - . - 8 + mov pc, r3 +L3: + ldmfd sp!, {r10, pc} + + + .global _arm_fpe_core_abort +_arm_fpe_core_abort: + stmfd sp!, {r1-r7, r10, lr} + mov r10, r0 + mov r0, r1 + mov r1, r2 + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_ABORT] + + add lr, pc, #L4 - . - 8 + mov pc, r3 +L4: + ldmfd sp!, {r1-r7, r10, pc} + + +/* Only needs to preserve r10 */ + + .global _arm_fpe_core_initcontext +_arm_fpe_core_initcontext: + stmfd sp!, {r0-r7, r10, lr} + mov r10, r0 + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_INITCONTEXT] + + add lr, pc, #L5 - . - 8 + mov pc, r3 +L5: + ldmfd sp!, {r0-r7, r10, pc} + + +/* Only needs to preserve r10 */ + + .global _arm_fpe_core_changecontext +_arm_fpe_core_changecontext: + stmfd sp!, {r1-r7, r10, lr} + mov r10, r0 + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_CHANGECONTEXT] + + add lr, pc, #L6 - . - 8 + mov pc, r3 +L6: + ldmfd sp!, {r1-r7, r10, pc} + + +/* All regs preerved */ + + .global _arm_fpe_core_shutdown +_arm_fpe_core_shutdown: + stmfd sp!, {r0-r7, r10, lr} + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_SHUTDOWN] + + add lr, pc, #L7 - . - 8 + mov pc, r3 +L7: + ldmfd sp!, {r0-r7, r10, pc} + + +/* Preserve r10 */ + .global _arm_fpe_core_savecontext +_arm_fpe_core_savecontext: + stmfd sp!, {r1-r7, r10, lr} + mov r10, r0 + mov r0, r1 + mov r1, r2 + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_SAVECONTEXT] + + add lr, pc, #L8 - . - 8 + mov pc, r3 +L8: + ldmfd sp!, {r1-r7, r10, pc} + + +/* Preserve r10 */ + + .global _arm_fpe_core_loadcontext +_arm_fpe_core_loadcontext: + stmfd sp!, {r0-r7, r10, lr} + mov r10, r0 + mov r0, r1 + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_LOADCONTEXT] + + add lr, pc, #L9 - . - 8 + mov pc, r3 +L9: + ldmfd sp!, {r0-r7, r10, pc} + + +/* Only needs to preserve r10 */ + + .global _arm_fpe_core_activatecontext +_arm_fpe_core_activatecontext: + stmfd sp!, {r0-r7, r10, lr} + mov r10, r0 + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_ACTIVATECONTEXT] + + add lr, pc, #L10 - . - 8 + mov pc, r3 +L10: + ldmfd sp!, {r0-r7, r10, pc} + + +/* Only needs to preserve r10 */ + + .global _arm_fpe_core_deactivatecontext +_arm_fpe_core_deactivatecontext: + stmfd sp!, {r1-r7, r10, lr} + ldr r3, [pc, #arm_fpe_header - . - 8] + ldr r3, [r3, #ARM_FPE_CORE_DEACTIVATECONTEXT] + + add lr, pc, #L11 - . - 8 + mov pc, r3 +L11: + ldmfd sp!, {r1-r7, r10, pc} + + +/* Simple call back function that panics */ + + .global _arm_fpe_panic +_arm_fpe_panic: + adr r0, fpe_panic_text + b _panic + +fpe_panic_text: + .asciz "armfpe: we are panicing" + .align 0 + + +/* + * Call back routine from FPE on completion of an instruction + */ + + .global _arm_fpe_post_proc_glue +_arm_fpe_post_proc_glue: + stmfd sp!, {r0-r6, r10-r12, lr} + +/* This could be optimised as we are going from UND32->SVC32 mode */ + + mrs r4, cpsr_all + bic r3, r4, #(PSR_MODE) + orr r3, r3, #(PSR_SVC32_MODE) + msr cpsr_all, r3 + + mov r0, r12 + +/* Reserve a trapframe on the SVC stack */ + + sub sp, sp, #(TRAPFRAMESIZE) + mov r1, sp + + ldr r2, [r0, #-0x0008] /* Copy spsr */ + str r2, [r1, #0x0000] + + ldr r2, [r0, #0x0000] /* Copy r0 */ + str r2, [r1, #0x0004] + ldr r2, [r0, #0x0004] + str r2, [r1, #0x0008] + ldr r2, [r0, #0x0008] + str r2, [r1, #0x000c] + ldr r2, [r0, #0x000c] + str r2, [r1, #0x0010] + ldr r2, [r0, #0x0010] + str r2, [r1, #0x0014] + ldr r2, [r0, #0x0014] + str r2, [r1, #0x0018] + ldr r2, [r0, #0x0018] + str r2, [r1, #0x001c] + ldr r2, [r0, #0x001c] + str r2, [r1, #0x0020] + ldr r2, [r0, #0x0020] + str r2, [r1, #0x0024] + ldr r2, [r0, #0x0024] + str r2, [r1, #0x0028] + ldr r2, [r0, #0x0028] + str r2, [r1, #0x002c] + ldr r2, [r0, #0x002c] + str r2, [r1, #0x0030] + ldr r2, [r0, #0x0030] /* Copy r12 */ + str r2, [r1, #0x0034] + ldr r2, [r0, #0x0034] /* Copy usr r13 */ + str r2, [r1, #0x0038] + ldr r2, [r0, #0x0038] /* Copy usr r14 */ + str r2, [r1, #0x003c] + ldr r2, [r0, #0x003c] /* Copy old pc */ + str r2, [r1, #0x0044] + + str r14, [r1, #0x0040] /* SVC r14 */ + +/* + * OK Question Time ... + * + * Do I need to save SVC r14 ? + * It only needs saving if this routine can interrupt something already + * running in SVC mode. Since FP is only valid from USR32 mode this + * should not happen. + */ + + mov r5, r14 + mov r6, r12 + +/* More optimisation ... Need to code a assembly version of userret() */ + + bl _arm_fpe_postproc + +/* Release the trapframe on the SVC stack */ + + ldr r2, [sp, #0x0000] /* Copy spsr */ + str r2, [r6, #-0x0008] + + ldr r2, [sp, #0x0004] /* Copy r0 */ + str r2, [r6, #0x0000] + ldr r2, [sp, #0x0008] /* Copy r1 */ + str r2, [r6, #0x0004] + ldr r2, [sp, #0x000c] /* Copy r2 */ + str r2, [r6, #0x0008] + ldr r2, [sp, #0x0010] /* Copy r3 */ + str r2, [r6, #0x000c] + ldr r2, [sp, #0x0014] /* Copy r4 */ + str r2, [r6, #0x0010] + ldr r2, [sp, #0x0018] /* Copy r5 */ + str r2, [r6, #0x0014] + ldr r2, [sp, #0x001c] /* Copy r6 */ + str r2, [r6, #0x0018] + ldr r2, [sp, #0x0020] /* Copy r7 */ + str r2, [r6, #0x001c] + ldr r2, [sp, #0x0024] /* Copy r8 */ + str r2, [r6, #0x0020] + ldr r2, [sp, #0x0028] /* Copy r9 */ + str r2, [r6, #0x0024] + ldr r2, [sp, #0x002c] /* Copy r10 */ + str r2, [r6, #0x0028] + ldr r2, [sp, #0x0030] /* Copy r11 */ + str r2, [r6, #0x002c] + ldr r2, [sp, #0x0034] /* Copy r12 */ + str r2, [r6, #0x0030] + ldr r2, [sp, #0x0038] /* Copy usr r13 */ + str r2, [r6, #0x0034] + ldr r2, [sp, #0x003c] /* Copy usr r14 */ + str r2, [r6, #0x0038] + ldr r2, [sp, #0x0044] /* Copy pc */ + str r2, [r6, #0x003c] + + add sp, sp, #(TRAPFRAMESIZE) + + mov r14, r5 + + msr cpsr_all, r4 + + ldmfd sp!, {r0-r6, r10-r12, pc} + + +/* + * Call back routine from FPE when the an exception occurs + */ + + .global _arm_fpe_exception_glue +_arm_fpe_exception_glue: + stmfd sp!, {r0-r5, r10-r12, lr} + +/* This could be optimised as we are going from UND32->SVC32 mode */ + + mrs r4, cpsr_all + bic r3, r4, #(PSR_MODE) + orr r3, r3, #(PSR_SVC32_MODE) + msr cpsr_all, r3 + + ldr r1, [r12, #15*4] + mov r2, r12 + + mov r5, r14 + + bl _arm_fpe_exception + + mov r14, r5 + + msr cpsr_all, r4 + + ldmfd sp!, {r0-r5, r10-r12, lr} + +/* Now pull the original trapframe that the FPE pushed off the stack */ + + ldmdb r12, {r0, r1} + + msr cpsr_all, r1 + msr spsr_all, r0 + + mov sp, r12 + + ldmia sp, {r0-r14}^ + mov r0, r0 + add sp, sp, #15*4 + ldmfd sp!, {pc}^ + + .global _fpe_nexthandler +_fpe_nexthandler: + .word _undefinedinstruction_bounce diff --git a/sys/arch/arm32/fpe-arm/armfpe_init.c b/sys/arch/arm32/fpe-arm/armfpe_init.c new file mode 100644 index 00000000000..05990d53fc2 --- /dev/null +++ b/sys/arch/arm32/fpe-arm/armfpe_init.c @@ -0,0 +1,332 @@ +/* $NetBSD: armfpe_init.c,v 1.6 1996/03/18 19:55:01 mark Exp $ */ + +/* + * Copyright (C) 1996 Mark Brinicombe + * Copyright (C) 1995 Neil A Carson. + * 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 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 + * + * arm_fpe.c + * + * Stuff needed to interface the ARM floating point emulator module to RiscBSD. + * + * Created : 22/10/95 + */ + +/*#define DEBUG*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "armfpe.h" /* Prototypes for things */ + +extern int want_resched; +extern u_int fpe_nexthandler; + +void undefinedinstruction_bounce __P(()); +void arm_fpe_exception_glue __P((int exception)); +void arm_fpe_panic __P(()); +void undefined_entry __P(()); +void arm_fpe_post_proc_glue __P(()); + +/* + * A module header, pointing into the module + */ + +extern u_int arm_fpe_mod[]; +extern u_int undefined_handler_address; + +/* + * Error messages for the various exceptions, numbered 0-5 + */ + +static char *exception_errors[] = { + "Floating point invalid operation", + "Floating point division by zero (0)", + "Floating point overflow", + "Floating point underflow", + "Floating point operation inexact", + "Floating point major faliure... core fault trapped... not good!" +}; + +/* + * Relocate the FPE. + */ + +void +arm_fpe_mod_reloc(void) +{ + int cnt; + arm_fpe_mod_hdr_t *arm_fpe_mod_hdr = (arm_fpe_mod_hdr_t *)arm_fpe_mod; + + /* Go through the module header, and convert all offsets into absolute + * addresses. Careful here - the last two fields of the header do _NOT_ + * want to be relocated! + */ + + for (cnt = 0; cnt < (sizeof(arm_fpe_mod_hdr_t) >> 2) - 2; cnt ++) { +#ifdef DEBUG + printf("FPE: entry %02x = %08x ", cnt, arm_fpe_mod[cnt]); +#endif + arm_fpe_mod[cnt] += (u_int) arm_fpe_mod; +#ifdef DEBUG + printf(" reloc=%08x\n", arm_fpe_mod[cnt]); +#endif + } + /* Print a startup message, and a couple of variables needed, these may need + * checking to make *sure* they are OK! + */ + +#ifdef DEBUG + printf("FPE: global workspace size = %d bytes, context size = %d bytes\n", + arm_fpe_mod_hdr->WorkspaceLength, arm_fpe_mod_hdr->ContextLength); + printf("FPE: base=%08x\n", (u_int)arm_fpe_mod); +#endif +} + +/* + * Initialisation point. The kernel calls this during the configuration of the cpu + * in order to install the FPE. + * The FPE specification needs to be filled in the specified cpu_t structure + * and the FPE needs to be installed on the CPU undefined instruction vector. + */ + +int +initialise_arm_fpe(cpu) + cpu_t *cpu; +{ + int error; + + cpu->fpu_class = FPU_CLASS_FPE; + cpu->fpu_type = FPU_TYPE_ARMLTD_FPE; + strcpy(cpu->fpu_model, "Advanced RISC Machines floating point emulator"); + error = arm_fpe_boot(); + if (error != 0) { + strcat(cpu->fpu_model, " - boot failed"); + return(1); + } + +/* Return with start failure so the old FPE is installed */ + +/* strcat(cpu->fpu_model, " - boot aborted");*/ + + return(0); +} + +/* + * The actual FPE boot routine. + * This has to do a number of things : + * 1. Relocate the FPE - Note this requires write access to the kernel text area + * 2. Allocated memory for the FPE + * 3. Initialise the FPE + */ + +int +arm_fpe_boot(void) +{ + u_int workspace; + int id; + arm_fpe_mod_hdr_t *arm_fpe_mod_hdr = (arm_fpe_mod_hdr_t *)arm_fpe_mod; + + /* First things first ... Relocate the FPE pointers */ + + arm_fpe_mod_reloc(); + + /* Now we must do some memory allocation */ + + workspace = (u_int)malloc(arm_fpe_mod_hdr->WorkspaceLength, M_DEVBUF, M_NOWAIT); +#ifdef DEBUG + printf("Gloabl workspace at 0x%08x\n", workspace); +#endif + + if (!workspace) + return(ENOMEM); + + *arm_fpe_mod_hdr->main_ws_ptr_addr = workspace; + + *arm_fpe_mod_hdr->local_handler_ptr_addr = (u_int)&undefined_handler_address; + *arm_fpe_mod_hdr->old_handler_ptr_addr = undefined_handler_address; + + /* Initialise out gloable workspace */ + +#ifdef DEBUG + printf("Initing workspace "); +#endif + + id = arm_fpe_core_initws(workspace, (u_int)&fpe_nexthandler, (u_int)&fpe_nexthandler); + +#ifdef DEBUG + printf("id=%08x\n", id); +#endif + + /* Set up an exception handler */ + + *arm_fpe_mod_hdr->exc_handler_ptr_addr = (u_int)arm_fpe_exception_glue; + + /* Set up post instruction handler */ +#if defined(CPU_ARM6) || defined(CPU_ARM7) + *arm_fpe_mod_hdr->fp_post_proc_addr = (((((u_int)arm_fpe_post_proc_glue - + (u_int)arm_fpe_mod_hdr->fp_post_proc_addr - 8)>>2) & 0x00ffffff) | 0xea000000); +#ifdef DEBUG + printf("arm_fpe_mod_hdr->fp_post_proc_addr = %08x (%08x)", + arm_fpe_mod_hdr->fp_post_proc_addr, + *arm_fpe_mod_hdr->fp_post_proc_addr); +#endif +#else +#error ARMFPE currently only supports ARM6 and ARM7 +#endif + +#ifdef DEBUG + printf("Initialising proc0 FPE context\n"); +#endif + + /* Initialise proc0's FPE context */ + + arm_fpe_core_initcontext(FP_CONTEXT(&proc0)); + arm_fpe_core_changecontext(FP_CONTEXT(&proc0)); + + return(0); +} + + +/* + * Callback routine from the FPE when instruction emulation completes + */ + +void +arm_fpe_postproc(fpframe, frame) + u_int fpframe; + struct trapframe *frame; +{ + register u_int s; + register int sig; + register struct proc *p; + + p = curproc; + p->p_md.md_regs = frame; + +/* take pending signals */ + + while ((sig = (CURSIG(p))) != 0) { + postsig(sig); + } + + p->p_priority = p->p_usrpri; + + if (want_resched) { + /* + * Since we are curproc, a clock interrupt could + * change our priority without changing run queues + * (the running process is not kept on a run queue). + * If this happened after we setrunqueue ourselves but + * before we switch()'ed, we might not be on the queue + * indicated by our priority + */ + + s = splstatclock(); + setrunqueue(p); + p->p_stats->p_ru.ru_nivcsw++; + + mi_switch(); + + (void)splx(s); + while ((sig = (CURSIG(p))) != 0) { + postsig(sig); + } + } + +/* Profiling. */ + + if (p->p_flag & P_PROFIL) { + extern int psratio; + u_int pc; + + pc = ReadWord(fpframe + 15*4); + + if (pc <0x1000 || pc > 0xefc00000) + printf("armfpe_postproc: pc=%08x\n", pc); + +/* addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);*/ + addupc_task(p, pc, (int)(p->p_sticks - p->p_sticks) * psratio); + } + + curpriority = p->p_priority; +} + + +/* + * Callback routine from the FPE when an exception occurs. + */ + +void +arm_fpe_exception(exception, pc, fpframe) + int exception; + u_int pc; + u_int fpframe; +{ + if (exception >= 0 && exception < 6) + printf("fpe exception: %d - %s\n", exception, exception_errors[exception]); + else + printf("fpe exception: %d - unknown\n", exception); + + trapsignal(curproc, SIGFPE, exception); + + printf("PC=%08x\n", ReadWord(fpframe + 60)); + + userret(curproc, pc, curproc->p_sticks); +} + + +void +arm_fpe_copycontext(c1, c2) + u_int c1; + u_int c2; +{ + fp_context_frame_t fpcontext; + + arm_fpe_core_savecontext(c1, (int *)&fpcontext, 0); + arm_fpe_core_loadcontext(c2, (int *)&fpcontext); +} + +/* End of armfpe_init.c */ diff --git a/sys/arch/arm32/fpe-sp/fpe.c b/sys/arch/arm32/fpe-sp/fpe.c new file mode 100644 index 00000000000..84b79dcc538 --- /dev/null +++ b/sys/arch/arm32/fpe-sp/fpe.c @@ -0,0 +1,1321 @@ +/* $NetBSD: fpe.c,v 1.2 1996/03/18 19:58:09 mark Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * Copyright (c) 1995 Neil Carson. + * 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 the RiscBSD kernel team. + * 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 AUTHORS ``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 AUTHORS 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 + * + * fpe.c + * + * Floating Point Emulator + * + * Currently calculations are only performed to single precision + * + * Created : 11/02/95 + */ + +/* FPE Compile options + * + * FPE_SPEEDUPS - use assembly speedups in place of C routines + * FPE_NODEBUG - don't compile in the debugging code + * FPE_PROF - compile in FPE profiling code + * FPE_INLINE - define this as inline to inline some functions + */ + +#define FPE_SPEEDUPS +#define FPE_NODEBUG +/*#define FPE_PROF*/ +#define FPE_INLINE __inline + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef struct { + int opcode; + int precision; + int rounding; + int fpregm; + int fpregn; + int fpregd; + int regd; +} fp_op_data_t; + +/* Types and stuctures used to hold floating point numbers */ + +typedef struct { + u_int32_t exponent; + u_int32_t mantissa_hi; + u_int32_t mantissa_lo; +} fpe_reg_t; + +typedef struct { + u_int mantissa:23; + u_int exponent:8; + u_int sign:1; +} fpe_sprec_t; + +typedef struct { + u_int mantissa_hi:20; + u_int exponent:11; + u_int sign:1; + u_int32_t mantissa_lo; +} fpe_dprec_t; + +typedef struct { + u_int32_t exponent; + u_int32_t mantissa_hi; + u_int32_t mantissa_lo; +} fpe_eprec_t; + +typedef struct { + u_int32_t word1; + u_int32_t word2; + u_int32_t word3; +} fpe_pprec_t; + +typedef struct { + u_int32_t exponent; + u_int64_t mantissa; +} fpe_qreg_t; + +/* FPE status and control registers */ + +u_int fpe_status = 0x02000000; +u_int fpe_control = 0x00000000; + +#define FPE_STATUS_MASK 0x001f1f1f +#define FPE_CONTROL_MASK 0x9cffffff + +/* Array containing the emulated registers */ + +fpe_reg_t fpe_registers[16] = { + { 0, 0, 0 }, /* f0 */ + { 0, 0, 0 }, /* f1 */ + { 0, 0, 0 }, /* f2 */ + { 0, 0, 0 }, /* f3 */ + { 0, 0, 0 }, /* f4 */ + { 0, 0, 0 }, /* f5 */ + { 0, 0, 0 }, /* f6 */ + { 0, 0, 0 }, /* f7 */ + { 0x0000, 0x00000000, 0x00000000 }, /* 0.0 */ + { 0x3fff, 0x80000000, 0x00000000 }, /* 1.0 */ + { 0x4000, 0x80000000, 0x00000000 }, /* 2.0 */ + { 0x4000, 0xc0000000, 0x00000000 }, /* 3.0 */ + { 0x4001, 0x80000000, 0x00000000 }, /* 4.0 */ + { 0x4001, 0xa0000000, 0x00000000 }, /* 5.0 */ + { 0x3ffe, 0x80000000, 0x00000000 }, /* 0.5 */ + { 0x4002, 0xa0000000, 0x00000000 }, /* 10.0 */ +}; + +fpe_reg_t *fpregs; + +/* Prototypes for instruction emulation functions */ + +typedef int (*fpe_handler_t) __P((unsigned int, trapframe_t *)); +typedef int (*fpe_dop_handler_t) __P((fp_op_data_t *, trapframe_t *)); + +int fpe_mvf __P((fp_op_data_t *, trapframe_t *)); +int fpe_mnf __P((fp_op_data_t *, trapframe_t *)); +int fpe_adf __P((fp_op_data_t *, trapframe_t *)); +int fpe_muf __P((fp_op_data_t *, trapframe_t *)); +int fpe_suf __P((fp_op_data_t *, trapframe_t *)); +int fpe_dvf __P((fp_op_data_t *, trapframe_t *)); +int fpe_muf __P((fp_op_data_t *, trapframe_t *)); +int fpe_rdf __P((fp_op_data_t *, trapframe_t *)); +int fpe_rsf __P((fp_op_data_t *, trapframe_t *)); +int fpe_abs __P((fp_op_data_t *, trapframe_t *)); + +/* Table of handler functions for register to registers operations */ + +fpe_dop_handler_t fpe_dops[32] = { + fpe_adf, /* 00000 ADF Add */ + fpe_mvf, /* 00001 MVF Move */ + fpe_muf, /* 00010 MUL Multiply */ + fpe_mnf, /* 00011 MNF Move negated */ + fpe_suf, /* 00100 SUF Subtract */ + fpe_abs, /* 00101 ABS Absolute value */ + fpe_rsf, /* 00110 RSF Reverse subtract */ + NULL, /* 00111 RND Round to integer */ + fpe_dvf, /* 01000 DVF Divide */ + NULL, /* 01001 SQT Square root */ + fpe_rdf, /* 01010 RDF Reverse divide */ + NULL, /* 01011 LOG Logarithm to base 10 */ + NULL, /* 01100 POW Power */ + NULL, /* 01101 LGN Logarithm to base e */ + NULL, /* 01110 RPW Reverse power */ + NULL, /* 01111 EXP Exponent */ + NULL, /* 10000 RMF Remainder */ + NULL, /* 10001 SIN Sine */ + fpe_muf, /* 10010 FML Fast multiply */ + NULL, /* 10011 COS Cosine */ + fpe_dvf, /* 10100 FDV Fast divide */ + NULL, /* 10101 TAN Tangent */ + fpe_rdf, /* 10110 FRD Fast reverse divide */ + NULL, /* 10111 ASN Arc sine */ + NULL, /* 11000 ROL Rolar angle */ + NULL, /* 11001 ACS Arc cosine */ + NULL, /* 11010 undefined */ + NULL, /* 11011 ATN Arc tangent */ + NULL, /* 11100 undefined */ + NULL, /* 11101 undefined */ + NULL, /* 11110 undefined */ + NULL, /* 11111 undefined */ +}; + +/* Prototypes for instruction emulation functions */ + +int fpe_flt __P((fp_op_data_t *, trapframe_t *)); +int fpe_fix __P((fp_op_data_t *, trapframe_t *)); +int fpe_wfs __P((fp_op_data_t *, trapframe_t *)); +int fpe_rfs __P((fp_op_data_t *, trapframe_t *)); +int fpe_wfc __P((fp_op_data_t *, trapframe_t *)); +int fpe_rfc __P((fp_op_data_t *, trapframe_t *)); +int fpe_cmf __P((fp_op_data_t *, trapframe_t *)); +int fpe_cnf __P((fp_op_data_t *, trapframe_t *)); + +/* Table of handler functions for fp register transfer operations */ + +fpe_dop_handler_t fpe_regtrans[16] = { + fpe_flt, /* 0000 FLT Integer to FP */ + fpe_fix, /* 0001 FIX FP to Integer */ + fpe_wfs, /* 0010 Write FP status */ + fpe_rfs, /* 0011 Read FP status */ + fpe_wfc, /* 0100 Write FP control */ + fpe_rfc, /* 0101 Read FP control */ + NULL, /* 0110 undefined */ + NULL, /* 0111 undefined */ + NULL, /* 1000 undefined */ + fpe_cmf, /* 1001 Compare FP */ + NULL, /* 1010 undefined */ + fpe_cnf, /* 1011 Compare negated FP */ + NULL, /* 1100 undefined */ + fpe_cmf, /* 1101 Compare FP with exception */ + NULL, /* 1110 undefined */ + fpe_cnf, /* 1111 Compare negated FP with exception */ +}; + +/* Prototypes for instruction emulation functions */ + +int fpe_ldfstf __P((unsigned int address, trapframe_t *)); + +FPE_INLINE int stofpe __P((u_int32_t */*address*/, fpe_reg_t */*fpreg*/)); +int dtofpe __P((u_int32_t *, fpe_reg_t *)); +int etofpe __P((u_int32_t *, fpe_reg_t *)); +int ptofpe __P((u_int32_t *, fpe_reg_t *)); +FPE_INLINE int fpetos __P((u_int32_t *, fpe_reg_t *)); +int fpetod __P((u_int32_t *, fpe_reg_t *)); +int fpetoe __P((u_int32_t *, fpe_reg_t *)); +int fpetop __P((u_int32_t *, fpe_reg_t *)); + +int fpe_dump(void); + +int coproc1_handler __P((unsigned int, unsigned int, trapframe_t *)); +int coproc2_handler __P((unsigned int, unsigned int, trapframe_t *)); + +/* Prototypes for assembly functions */ + +u_int32_t nc_fp_add __P((u_int32_t, u_int32_t)); +u_int32_t nc_fp_sub __P((u_int32_t, u_int32_t)); +u_int32_t nc_fp_mul __P((u_int32_t, u_int32_t)); +u_int32_t nc_fp_div __P((u_int32_t, u_int32_t)); +u_int32_t nc_fp_fix __P((u_int32_t)); +u_int32_t nc_fp_cmp __P((u_int32_t, u_int32_t)); + +#define FPP_ADD 0 +#define FPP_SUB 1 +#define FPP_MUL 2 +#define FPP_DIV 3 +#define FPP_CMF 4 +#define FPP_CNF 5 +#define FPP_FIX 6 +#define FPP_FLT 7 +#define FPP_ABS 8 +#define FPP_MOV 9 +#define FPP_MVN 10 +#define FPP_RDV 11 +#define FPP_RSB 12 +#define FPP_STRS 13 +#define FPP_STRD 14 +#define FPP_STRE 15 +#define FPP_STRP 16 +#define FPP_LDRS 17 +#define FPP_LDRD 18 +#define FPP_LDRE 19 +#define FPP_LDRP 20 +#define FPP_MAX 21 + +#ifdef FPE_PROF +u_int fp_profile[FPP_MAX]; + +#define FPP_INC(x) ++fp_profile[x] +#else +#define FPP_INC(x) +#endif + +/* +* If FPE is defined then we are being built into the kernel. +* If not then we are being built as a standalone loadable module. +*/ + +#ifdef FPE +#define PRINTF(x) ; +#define FPE_DUMP() ; +#else +#define PRINTF(x) (*printf_store)(x) +#define FPE_DUMP() fpe_dump() + +void (*printf_store)(); +void (*install_coproc_store)(); + +#ifdef NOTEXT +void +fpe_printf(char *a, ...) +{ +} +#endif + +/* Standalone initialisation point */ + +int +init_fpe(printf_handler, coproc_handler) + void (*printf_handler)(); + void (*coproc_handler)(); +{ + int loop; + + printf_store = printf_handler; + install_coproc_store = coproc_handler; +#ifdef NOTEXT + printf_store = fpe_printf; +#endif + (*install_coproc_store)(FP_COPROC, coproc1_handler); + (*install_coproc_store)(FP_COPROC2, coproc2_handler); + +#ifdef FPE_PROF + for (loop = 0; loop < FPP_MAX; ++loop) + fp_profile[loop] = 0; +#endif + + PRINTF(("FPE installed\n")); + return(0); +} +#endif + + +/* + * Main entry point after an undefined instruction. + * The instruction has been identified as a co-proc 2 instruction. + * We get the address of the instruction, the instruction itself and + * and pointer to the trap frame. + * Currently we do support this (LFM/SFM) so its gallows time + */ + +int +coproc2_handler(address, instruction, frame) + unsigned int address; + unsigned int instruction; + trapframe_t *frame; +{ + log(LOG_ERR, "Coprocessor 2 FP instruction 0x%08x not supported yet.", instruction); + return(1); +} + + +void +init_fpe_state(p) + struct proc *p; +{ + struct fp_state *fpstate; + int loop; + + fpstate = &p->p_addr->u_pcb.pcb_fpstate; + fpstate->fp_flags |= 1; + + for (loop = 8; loop < 16; ++loop) + fpstate->fp_registers[loop] = *((fp_reg_t *)&fpe_registers[loop]); +} + + +int +initialise_fpe(cpu) + cpu_t *cpu; +{ + cpu->fpu_class = FPU_CLASS_FPE; + cpu->fpu_type = FPU_TYPE_SP_FPE; + strcpy(cpu->fpu_model, "Single precision floating point emulator"); + install_coproc_handler(FP_COPROC, coproc1_handler); + install_coproc_handler(FP_COPROC2, coproc2_handler); + init_fpe_state(curproc); + return(0); +} + + +/* + * Main entry point after an undefined instruction. + * The instruction has been identified as a co-proc 1 instruction. + * We get the address of the instruction, the instruction itself and + * and pointer to the trap frame. + */ + +int +coproc1_handler(address, instruction, frame) + unsigned int address; + unsigned int instruction; + trapframe_t *frame; +{ + struct fp_state *fpstate; + PRINTF(("FPE instruction 0x%08x -> 0x%08x\n", + address, instruction)); + +/* Get the fp registers pointer */ + + fpstate = &curproc->p_addr->u_pcb.pcb_fpstate; + + fpstate->fp_flags |= 2; /* so statclock can tell if we are spending time in the fpe */ + + if (fpstate->fp_flags & 1) + fpregs = (fpe_reg_t *) &fpstate->fp_registers; + else + fpregs = fpe_registers; + +/* Test for a FP data transfer operation */ + + if ((instruction & (1 << 25)) == 0) { + int err; + + PRINTF(("FP data transfer\n")); + err = fpe_ldfstf(instruction, frame); + FPE_DUMP(); + fpstate->fp_flags &= ~2; + return(err); + } + +/* Test for a FP data operation */ + + else if ((instruction & (1 << 4)) == 0) { + fp_op_data_t op_data; + + op_data.opcode = (instruction >> 19) & 0x1e; + if (instruction & 0x00008000) + op_data.opcode |= 0x01; + + op_data.precision = ((instruction & (1<<19)) ? 2 : 0) + | ((instruction & (1<<7)) ? 1 : 0); + op_data.rounding = (instruction >> 5) & 3; + op_data.fpregm = (instruction) & 15; + op_data.fpregn = (instruction >> 16) & 7; + op_data.fpregd = (instruction >> 12) & 7; + + PRINTF(("FP data op = %d\n", op_data.opcode)); + if (fpe_dops[op_data.opcode]) { + int err; + err = (*fpe_dops[op_data.opcode])(&op_data, frame); +#ifndef FPE_NODEBUG + if (err == 0) + FPE_DUMP(); +#endif + fpstate->fp_flags &= ~2; + return(err); + } + else { + fpstate->fp_flags &= ~2; + return(1); + } + } + +/* Test for a FP register transfer operation */ + + else { + fp_op_data_t op_data; + + op_data.opcode = (instruction >> 20) & 0x0f; + + op_data.precision = ((instruction & (1<<19)) ? 2 : 0) + | ((instruction & (1<<7)) ? 1 : 0); + op_data.rounding = (instruction >> 5) & 3; + op_data.fpregm = (instruction) & 15; + op_data.fpregn = (instruction >> 16) & 7; + op_data.regd = (instruction >> 12) & 15; + + PRINTF(("FP reg trans = %d\n", op_data.opcode)); + if (fpe_regtrans[op_data.opcode]) { + int err; + + PRINTF(("FP reg trans op = %d\n", op_data.opcode)); + err = (*fpe_regtrans[op_data.opcode])(&op_data, frame); +#ifndef FPE_NODEBUG + if (err == 0 && (op_data.opcode == 0 || op_data.opcode == 2 + || op_data.opcode == 4)) + FPE_DUMP(); +#endif + fpstate->fp_flags &= ~2; + return(err); + } + else { + fpstate->fp_flags &= ~2; + return(1); + } + } + +/* Well if it gets here then it was not a decodable FP instruction */ + + fpstate->fp_flags &= ~2; + return(1); +} + + +/* Precision convertion routines */ + +FPE_INLINE int +stofpe(address, fpreg) + u_int32_t *address; + fpe_reg_t *fpreg; +{ + fpe_sprec_t real; + u_int32_t *words = (u_int32_t *)ℜ + + if ((address[0] & ~(1<<31)) == 0) { + PRINTF(("single=0\n")); + + fpreg->mantissa_hi = 0; + fpreg->mantissa_lo = 0; + fpreg->exponent = address[0] & (1<<31); + return(0); + } + + words[0] = address[0]; + PRINTF(("word=%08x\n", address[0])); + + PRINTF(("sign = %d exponent=%08x mantissa=%08x\n", real.sign, + real.exponent, real.mantissa)); + fpreg->mantissa_hi = real.mantissa << 8; + fpreg->mantissa_lo = 0; + fpreg->exponent = ((int)real.exponent - 0x80) + 0x4000; + fpreg->exponent |= (real.sign << 31); + return(0); +} + + +int +dtofpe(address, fpreg) + u_int32_t *address; + fpe_reg_t *fpreg; +{ + fpe_dprec_t real; + + if ((address[0] & ~(1<<31)) == 0 && address[1] == 0) { + PRINTF(("double=0\n")); + + fpreg->mantissa_hi = 0; + fpreg->mantissa_lo = 0; + fpreg->exponent = address[0] & (1<<31); + return(0); + } + + real = *(fpe_dprec_t *)address; + PRINTF(("sign = %d exponent=%08x mantissa=%08x %08x\n", real.sign, + real.exponent, real.mantissa_lo, real.mantissa_hi)); + fpreg->mantissa_hi = real.mantissa_hi << 11; + fpreg->mantissa_hi |= real.mantissa_lo >> 21; + fpreg->mantissa_lo = real.mantissa_lo << 11; + fpreg->exponent = (real.exponent - 0x400) + 0x4000; + fpreg->exponent |= (real.sign << 31); + + return(0); +} + + +#ifndef FPE_SPEEDUPS +int +etofpe(address, fpreg) + u_int32_t *address; + fpe_reg_t *fpreg; +{ + bcopy((char *)address, (char *)fpreg, 12); + return(0); +} +#endif + + +int +ptofpe(address, fpreg) + u_int32_t *address; + fpe_reg_t *fpreg; +{ + fpe_pprec_t real; + + real = *(fpe_pprec_t *)address; + return(1); +} + + +FPE_INLINE int +fpetos(address, fpreg) + u_int32_t *address; + fpe_reg_t *fpreg; +{ + fpe_sprec_t real; + int exp; + + if (fpreg->mantissa_hi == 0 && fpreg->mantissa_lo == 0 + && (fpreg->exponent & ~(1<<31)) == 0) { + PRINTF(("single=0\n")); + + address[0] = fpreg->exponent & (1<<31); + return(0); + } + + real.sign = (fpreg->exponent >> 31) & 1; + real.mantissa = (fpreg->mantissa_hi >> 8); + exp = ((int)(fpreg->exponent & 0x7fff) - 0x4000) + 0x80; + + if (exp < 0 || exp > 0xff) { + PRINTF(("ermm exponent out of range !\n")); + exp = 0x80; + } + + real.exponent = exp; + + PRINTF(("single=%08x\n", *((unsigned int *)&real))); + + *(fpe_sprec_t *)address = real; + if (real.sign == 1 && real.mantissa == 0 && real.exponent == 0) + printf("single result = %08x", *address); + return(0); +} + + +int +fpetod(address, fpreg) + u_int32_t *address; + fpe_reg_t *fpreg; +{ + fpe_dprec_t real; + u_int32_t *words = (u_int32_t *)ℜ + int exp; + + if (fpreg->mantissa_lo == 0 && (fpreg->exponent & ~(1<<31)) == 0) { + PRINTF(("double=0\n")); + + address[0] = fpreg->exponent & (1<<31); + address[1] = 0; + return(0); + } + + real.sign = (fpreg->exponent >> 31) & 1; + real.mantissa_hi = (fpreg->mantissa_hi >> 11); + real.mantissa_lo = (fpreg->mantissa_hi << 21) | (fpreg->mantissa_lo >> 11); + exp = ((int)(fpreg->exponent & 0x7fff) - 0x4000) + 0x400; + + if (exp < 0 || exp > 0x7ff) { + PRINTF(("ermm exponent out of range !\n")); + exp = 0x400; + } + + real.exponent = exp; + + PRINTF(("double=%08x%08x\n", words[0], words[1])); + + address[0] = words[0]; + address[1] = words[1]; + return(0); +} + +#ifndef FPE_SPEEDUPS +int +fpetoe(address, fpreg) + u_int32_t *address; + fpe_reg_t *fpreg; +{ + bcopy((char *)fpreg, (char *)address, 12); + return(0); +} +#endif + + +int +fpetop(address, fpreg) + u_int32_t *address; + fpe_reg_t *fpreg; +{ + return(1); +} + + +/* Unary fp data operations */ + +/* + * int fpe_mvf(fp_op_data_t *op, trapframe_t *frame) + * + * MVF - Move FP register to FP register + */ + +int +fpe_mvf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + FPP_INC(FPP_MOV); + PRINTF(("MVF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + fpregs[op->fpregd] = fpregs[op->fpregm]; + return(0); +} + + +/* +* int fpe_mnf(fp_op_data_t *op, trapframe_t *frame) +* +* MNF - Move FP register to FP register negated +*/ + +int +fpe_mnf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[8]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + fpe_qreg_t result; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_MVN); + PRINTF(("MNF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_sub(single_a, single_b); + stofpe(&single_result, (fpe_reg_t *) &result); + + fpregs[op->fpregd] = *(fpe_reg_t *) &result; + return(0); +} + + +/* +* int fpe_abs(fp_op_data_t *op, trapframe_t *frame) +* +* ABS - Absolute value of a FP register +*/ + +int +fpe_abs(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[8]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + fpe_qreg_t result; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_ABS); + PRINTF(("ABS prec=%d rnd=%d fd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real2); + fpetos(&single_b, (fpe_reg_t *) &real1); + single_result = nc_fp_cmp(single_a, single_b); + if (single_result & 0x80000000) { + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_sub(single_a, single_b); + stofpe(&single_result, (fpe_reg_t *) &result); + + fpregs[op->fpregd] = *(fpe_reg_t *) &result; + } else { + fpregs[op->fpregd] = fpregs[op->fpregm]; + } + + return(0); +} + + +/* Binary fp data operations */ + +/* + * int fpe_adf(fp_op_data_t *op, trapframe_t *frame) + * + * ADF - Floating point add + */ + +int +fpe_adf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + fpe_qreg_t result; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_ADD); + PRINTF(("ADF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_add(single_a, single_b); + stofpe(&single_result, (fpe_reg_t *) &result); + fpregs[op->fpregd] = *(fpe_reg_t *) &result; + return(0); +} + + +/* + * int fpe_suf(fp_op_data_t *op, trapframe_t *frame) + * + * SUF - Floating point subtract + */ + +int +fpe_suf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + fpe_qreg_t result; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_SUB); + PRINTF(("SUF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_sub(single_a, single_b); + stofpe(&single_result, (fpe_reg_t *) &result); + fpregs[op->fpregd] = *(fpe_reg_t *) &result; + return(0); +} + + +/* + * int fpe_muf(fp_op_data_t *op, trapframe_t *frame) + * + * MUF - Floating point multiply + */ + +int +fpe_muf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + fpe_qreg_t result; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_MUL); + PRINTF(("MUF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_mul(single_a, single_b); + stofpe(&single_result, (fpe_reg_t *) &result); + fpregs[op->fpregd] = *(fpe_reg_t *) &result; + return(0); +} + + +/* + * int fpe_dvf(fp_op_data_t *op, trapframe_t *frame) + * + * DVF - Floating point divide + */ + +int fpe_dvf(fp_op_data_t *op, trapframe_t *frame) +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + fpe_qreg_t result; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_DIV); + PRINTF(("DVF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_div(single_a, single_b); + stofpe(&single_result, (fpe_reg_t *) &result); + fpregs[op->fpregd] = *(fpe_reg_t *) &result; + return(0); +} + + +/* + * int fpe_rdf(fp_op_data_t *op, trapframe_t *frame) + * + * RDF - Floating point reverse divide + */ + +int +fpe_rdf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregn]; + fpe_qreg_t result; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_RDV); + PRINTF(("RDF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_div(single_a, single_b); + stofpe(&single_result, (fpe_reg_t *) &result); + fpregs[op->fpregd] = *(fpe_reg_t *) &result; + return(0); +} + + +/* + * int fpe_rsf(fp_op_data_t *op, trapframe_t *frame) + * + * RSF - Floating point reverse subtract + */ + +int +fpe_rsf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregn]; + fpe_qreg_t result; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_RSB); + PRINTF(("RSF prec=%d rnd=%d fd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->fpregd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_sub(single_a, single_b); + stofpe(&single_result, (fpe_reg_t *) &result); + fpregs[op->fpregd] = *(fpe_reg_t *) &result; + return(0); +} + + +/* FPE Register transfer instructions */ + +/* +* int fpe_flt(fp_op_data_t *op, trapframe_t *frame) +* +* FLT - Integer register to float register +*/ + +int +fpe_flt(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + int regd; + fpe_reg_t real; + int *regs = &frame->tf_r0; + + FPP_INC(FPP_FLT); + PRINTF(("FLT prec=%d rnd=%d rd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->regd, op->fpregn, op->fpregm)); + + regd = regs[op->regd]; + + if (regd > 0) + real.mantissa_lo = regd; + else + real.mantissa_lo = -regd; + real.mantissa_hi = 0; + + if (regd == 0) + real.exponent = 0; + else { + real.exponent = 16383 + 63; + + while ((real.mantissa_hi & (1 << 31)) == 0) { + --real.exponent; + real.mantissa_hi = real.mantissa_hi << 1; + if (real.mantissa_lo & (1 << 31)) + real.mantissa_hi |= 1; + real.mantissa_lo = real.mantissa_lo << 1; + } + } + + if (regd < 0) + real.exponent |= (1 <<31); + + fpregs[op->fpregn] = real; + + return(0); +} + + +/* + * int fpe_fix(fp_op_data_t *op, trapframe_t *frame) + * + * FIX - Float register to integer register + */ + +int +fpe_fix(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t src = *(fpe_qreg_t *) &fpregs[op->fpregm]; + u_int32_t single_argument; + unsigned int *regs = &frame->tf_r0; + + FPP_INC(FPP_FIX); + PRINTF(("FIX prec=%d rnd=%d rd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->regd, op->fpregn, op->fpregm)); + + fpetos(&single_argument, (fpe_reg_t *) &src); + +/* + * Call the assembler (32-bit) code for now + */ + regs[op->regd] = nc_fp_fix(single_argument); + return(0); +} + + +/* + * int fpe_wfs(fp_op_data_t *op, trapframe_t *frame) + * + * WFS - Write FP status register + */ + +int fpe_wfs(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + unsigned int *regs = &frame->tf_r0; + + PRINTF(("WFS rd=%d\n", op->regd)); + + fpe_status = (fpe_status & ~FPE_STATUS_MASK) + | (regs[op->regd] & FPE_STATUS_MASK); + + return(0); +} + + +/* +* int fpe_rfs(fp_op_data_t *op, trapframe_t *frame) +* +* RFS - Read FP status register +*/ + +int +fpe_rfs(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + unsigned int *regs = &frame->tf_r0; + + PRINTF(("RFS rd=%d\n", op->regd)); + + regs[op->regd] = fpe_status; + + return(0); +} + + +/* + * int fpe_wfc(fp_op_data_t *op, trapframe_t *frame) + * + * WFC - Write FP control register + */ + +int +fpe_wfc(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + unsigned int *regs = &frame->tf_r0; + + PRINTF(("WFC rd=%d\n", op->regd)); + + fpe_control = (fpe_control & ~FPE_CONTROL_MASK) + | (regs[op->regd] & FPE_CONTROL_MASK); + + return(0); +} + + +/* + * int fpe_rfc(fp_op_data_t *op, trapframe_t *frame) + * + * RFC - Read FP control register + */ + +int +fpe_rfc(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + unsigned int *regs = &frame->tf_r0; + + PRINTF(("RFC rd=%d\n", op->regd)); + + regs[op->regd] = fpe_control; + + return(0); +} + + +/* + * int fpe_cmf(fp_op_data_t *op, trapframe_t *frame) + * + * CMF - FP compare + */ + +int +fpe_cmf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_CMF); + PRINTF(("CMF prec=%d rnd=%d rd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->regd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real1); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_result = nc_fp_cmp(single_a, single_b); + frame->tf_spsr = (frame->tf_spsr & ~0xf0000000) | (single_result & 0xf0000000); + return(0); +} + + +/* + * int fpe_cnf(fp_op_data_t *op, trapframe_t *frame) + * + * CNF - FP compare negated + */ + +int +fpe_cnf(op, frame) + fp_op_data_t *op; + trapframe_t *frame; +{ + fpe_qreg_t real0 = *(fpe_qreg_t *)&fpregs[8]; + fpe_qreg_t real1 = *(fpe_qreg_t *)&fpregs[op->fpregn]; + fpe_qreg_t real2 = *(fpe_qreg_t *)&fpregs[op->fpregm]; + u_int32_t single_a, single_b, single_result; + + FPP_INC(FPP_CNF); + PRINTF(("CNF prec=%d rnd=%d rd=%d fn=%d fm=%d\n", + op->precision, op->rounding, op->regd, op->fpregn, op->fpregm)); + + fpetos(&single_a, (fpe_reg_t *) &real0); + fpetos(&single_b, (fpe_reg_t *) &real2); + single_b = nc_fp_sub(single_a, single_b); + + fpetos(&single_a, (fpe_reg_t *) &real1); + single_result = nc_fp_cmp(single_a, single_b); + frame->tf_spsr = (frame->tf_spsr & ~0xf0000000) | (single_result & 0xf0000000); + return(0); +} + + +/* + * int fpe_ldfstf(unsigned in instruction, trapframe_t *frame) + * + * LDF/STF - Load / store FP registers to / from memory + */ + + +int +fpe_ldfstf(instruction, frame) + unsigned int instruction; + trapframe_t *frame; +{ + unsigned int *regs = &frame->tf_r0; + int offset; + int fpreg; + int reg; + u_int32_t address; + int precision; + int error = 0; + + offset = (instruction & 0xff) << 2; + + fpreg = (instruction >> 12) & 0x07; + reg = (instruction >> 16) & 0x0f; + precision = ((instruction & (1<<22)) ? 2 : 0) + | ((instruction & (1<<15)) ? 1 : 0); + + if (!(instruction & (1<<23))) + offset = -offset; + + if (reg == 15) + printf("WARNING: LDF/STF using r15\n"); + + address = regs[reg]; + + if ((instruction & (1<<24))) + address += offset; + + if (!(instruction & (1 << 20))) { + PRINTF(("STF rd=%d fd=%d prec=%d offset=%d address = %08x\n", + reg, fpreg, precision, offset, address)); + + switch(precision) { + case 0 : + FPP_INC(FPP_STRS); + error = fpetos((u_int32_t *)address, &fpregs[fpreg]); + break; + case 1 : + FPP_INC(FPP_STRD); + error = fpetod((u_int32_t *)address, &fpregs[fpreg]); + break; + case 2 : + FPP_INC(FPP_STRE); + error = fpetoe((u_int32_t *)address, &fpregs[fpreg]); + break; + case 3 : + FPP_INC(FPP_STRP); + error = fpetop((u_int32_t *)address, &fpregs[fpreg]); + break; + } + } else { + PRINTF(("LDF rd=%d fd=%d prec=%d offset=%d address = %08x\n", + reg, fpreg, precision, offset, address)); + + switch(precision) { + case 0 : + FPP_INC(FPP_LDRS); + error = stofpe((u_int32_t *)address, &fpregs[fpreg]); + break; + case 1 : + FPP_INC(FPP_LDRD); + error = dtofpe((u_int32_t *)address, &fpregs[fpreg]); + break; + case 2 : + FPP_INC(FPP_LDRE); + error = etofpe((u_int32_t *)address, &fpregs[fpreg]); + break; + case 3 : + FPP_INC(FPP_LDRP); + error = ptofpe((u_int32_t *)address, &fpregs[fpreg]); + break; + } + } + + if (!(instruction & (1<<24))) + address += offset; + + if ((instruction & (1<<21))) + regs[reg] = address; + + return(error); +} + + +/* Debugging functions */ + +int +fpe_dump() +{ + int loop; + + for (loop = 0; loop < 8; loop+=2) { + PRINTF(("f%2d : %08x %08x %08x f%2d : %08x %08x %08x\n", + loop, fpregs[loop].mantissa_hi, + fpregs[loop].mantissa_lo, fpregs[loop].exponent, + loop+1, fpregs[loop+1].mantissa_hi, + fpregs[loop+1].mantissa_lo, fpregs[loop+1].exponent)); + } + PRINTF(("\x1b[0mFPSR=%08x FPCR=%08x\n", fpe_status, fpe_control)); + return(0); +} + + +#ifdef FPE_PROF +void +fpe_dump_prof() +{ + printf("adf : %6d\n", fp_profile[FPP_ADD]); + printf("suf : %6d\n", fp_profile[FPP_SUB]); + printf("muf : %6d\n", fp_profile[FPP_MUL]); + printf("dvf : %6d\n", fp_profile[FPP_DIV]); + printf("cmf : %6d\n", fp_profile[FPP_CMF]); + printf("cnf : %6d\n", fp_profile[FPP_CNF]); + printf("fix : %6d\n", fp_profile[FPP_FIX]); + printf("flt : %6d\n", fp_profile[FPP_FLT]); + printf("abs : %6d\n", fp_profile[FPP_ABS]); + printf("mvf : %6d\n", fp_profile[FPP_MOV]); + printf("mnf : %6d\n", fp_profile[FPP_MVN]); + printf("rdf : %6d\n", fp_profile[FPP_RDV]); + printf("rsf : %6d\n", fp_profile[FPP_RSB]); + printf("strs: %6d\n", fp_profile[FPP_STRS]); + printf("strd: %6d\n", fp_profile[FPP_STRD]); + printf("stre: %6d\n", fp_profile[FPP_STRE]); + printf("strp: %6d\n", fp_profile[FPP_STRP]); + printf("ldrs: %6d\n", fp_profile[FPP_LDRS]); + printf("ldrd: %6d\n", fp_profile[FPP_LDRD]); + printf("ldre: %6d\n", fp_profile[FPP_LDRE]); + printf("ldrp: %6d\n", fp_profile[FPP_LDRP]); +} +#else +void +fpe_dump_prof() +{ + printf("kernel not compiled with FPE profiling\n"); +} +#endif + +/* End of fpe.c */ diff --git a/sys/arch/arm32/fpe-sp/fpeadd.S b/sys/arch/arm32/fpe-sp/fpeadd.S new file mode 100644 index 00000000000..395c4419679 --- /dev/null +++ b/sys/arch/arm32/fpe-sp/fpeadd.S @@ -0,0 +1,121 @@ +/* $NetBSD: fpeadd.S,v 1.2 1996/03/18 19:58:12 mark Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * Copyright (c) 1995 Neil Carson. + * 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 kernel team. + * 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 AUTHORS ``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 AUTHORS 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 + * + * fpeadd.S + * + * FP addition + * + * Created : 11/02/95 + */ + +/* std. registers + */ +sp .req r13 +lr .req r14 +pc .req r15 + + +.global _nc_fp_add + +mant1 .req r2 +xp1 .req r3 +mant2 .req r4 +xp2 .req r5 +wrk1 .req r14 + +_nc_fp_add: + stmfd r13!,{r2-r5,r14} + mov xp1,r0,lsr #23 /* get exponent+sign */ + bic mant1,r0,xp1,lsl #23 /* get mantissa */ + cmp r0,#0 + orrne mant1,mant1,#1<<23 /* set on bit to left of point */ + and xp1,xp1,#255 /* remove sign */ + + mov xp2,r1,lsr #23 /* get exponent+sign */ + bic mant2,r1,xp2,lsl #23 /* get mantissa */ + cmp r1,#0 + orrne mant2,mant2,#1<<23 /* set on bit to left of point */ + and xp2,xp2,#255 /* remove sign */ + + eors wrk1,r0,r1 /* both +ve/-ve? */ + bmi fp_add_neg /* no, unequal signs */ + + subs wrk1,xp1,xp2 /* exp. difference */ + addpl mant1,mant1,mant2,lsr wrk1 /* xp1>exp2, round mant2 down */ + rsbmi wrk1,wrk1,#0 /* as +ve difference */ + addmi mant1,mant2,mant1,lsr wrk1 /* xp1xp2, round mant2 */ + rsbmi wrk1,wrk1,#0 /* as +ve difference */ + movmi mant1,mant1,lsr wrk1 /* exp1divisor? */ + orrcs q,q,p /* yes - set bit in binary place */ + subcs mant1,mant1,mant2 /* discard accounted value */ + movs mant1,mant1,lsl #1 /* shift up remainder, if any */ + movnes p,p,lsr#1 /* next binary place, if remainder */ + bne fp_divloop /* next place if any */ + + cmp q,#1<<23 /* normalise? */ + sublt xp1,xp1,#1 /* yes, adjust exponent */ + movlt q,q,lsl #1 /* & mantissa */ + /* combine result */ + orr r0,r0,xp1,lsl #23 /* set exponent */ + bic q,q,#1<<23 /* clear hi-order */ + orr r0,r0,q /* result */ +fp_div_exit: + ldmfd r13!,{r2-r4,pc} + diff --git a/sys/arch/arm32/fpe-sp/fpefix.S b/sys/arch/arm32/fpe-sp/fpefix.S new file mode 100644 index 00000000000..95c7c20f5ac --- /dev/null +++ b/sys/arch/arm32/fpe-sp/fpefix.S @@ -0,0 +1,72 @@ +/* $NetBSD: fpefix.S,v 1.2 1996/03/18 19:58:15 mark Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * Copyright (c) 1995 Neil Carson. + * 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 kernel team. + * 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 AUTHORS ``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 AUTHORS 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 + * + * fpefix.S + * + * FP register to integer + * + * Created : 11/02/95 + */ + +/* std. registers + */ +sp .req r13 +lr .req r14 +pc .req r15 + + +mant1 .req r0 +xp1 .req r1 + + .global _nc_fp_fix + +_nc_fp_fix: + cmp r0,#0 + moveq pc,r14 + mov xp1,r0,lsr #23 + bic mant1,r0,xp1,lsl #23 + orr mant1,mant1,#1<<23 + tst xp1,#1<<8 + rsbne mant1,mant1,#0 + bic xp1,xp1,#1<<8 + subs xp1,xp1,#127 + movmi r0,#0 + movmi pc,r14 + rsbs xp1,xp1,#23 + movpl mant1,mant1,asr xp1 + rsbmi xp1,xp1,#0 + movmi mant1,mant1,asl xp1 + mov pc,r14 diff --git a/sys/arch/arm32/fpe-sp/fpemul.S b/sys/arch/arm32/fpe-sp/fpemul.S new file mode 100644 index 00000000000..43c4f23365b --- /dev/null +++ b/sys/arch/arm32/fpe-sp/fpemul.S @@ -0,0 +1,99 @@ +/* $NetBSD: fpemul.S,v 1.2 1996/03/18 19:58:16 mark Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * Copyright (c) 1995 Neil Carson. + * 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 kernel team. + * 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 AUTHORS ``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 AUTHORS 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 + * + * fpemul.S + * + * FP multiply + * + * Created : 11/02/95 + */ + +.global _nc_fp_mul + +pc .req r15 + +mant1 .req r2 +xp1 .req r3 +mant2 .req r1 +xp2 .req r4 +wrk1 .req r14 +reshigh .req r4 + +_nc_fp_mul: + stmfd r13!,{r2-r4,r14} + /* check for null result - bloody lucky but you never know... */ + cmp r0,#0 + cmpne r1,#0 + moveq r0,#0 + beq fp_mul_exit + + mov xp1,r0,lsr #23 /* get exponent+sign */ + bic mant1,r0,xp1,lsl #23 /* get mantissa */ + orr mant1,mant1,#1<<23 /* set on bit to left of point */ + and xp1,xp1,#255 /* remove sign */ + + eor r0,r0,r1 /* sign of result */ + and r0,r0,#1<<31 /* clear rest of result */ + + mov xp2,r1,lsr #23 /* get exponent+sign */ + bic mant2,r1,xp2,lsl #23 /* get mantissa */ + orr mant2,mant2,#1<<23 /* set on bit to left of point */ + and xp2,xp2,#255 /* remove sign */ + + add xp1,xp1,xp2 + subs xp1,xp1,#127 /* exponent result */ + movmi r0,#0 /* underflow */ + bmi fp_mul_exit + /* do the multiply to 30 bits precision */ + mov wrk1,mant1,lsr#9 /* top 15 bits */ + mov reshigh,mant2,lsr#9 /* top 15 bits */ + bic mant1,mant1,wrk1,lsl#9 /* low 9 bits */ + bic mant2,mant2,reshigh,lsl#9 /* low 9 bits */ + mul mant2,wrk1,mant2 /* top*low */ + mul mant1,reshigh,mant1 /* low*top */ + mul reshigh,wrk1,reshigh /* top*top */ + add reshigh,reshigh,mant1,lsr#9 /* top + middle bit1 */ + add reshigh,reshigh,mant2,lsr#9 /* top + middle bit2 */ + /* adjust for carry */ + tst reshigh,#1<<29 + addne xp1,xp1,#1 /* adjust exponent */ + movne reshigh,reshigh,lsr#1 /* shift result right */ + /* combine result */ + orr r0,r0,xp1,lsl #23 /* set exponent */ + bic reshigh,reshigh,#1<<28 /* clear hi-order */ + orr r0,r0,reshigh,lsr #5 /* top 23 bits */ +fp_mul_exit: + ldmfd r13!,{r2-r4,pc} diff --git a/sys/arch/arm32/fpe-sp/fpesub.S b/sys/arch/arm32/fpe-sp/fpesub.S new file mode 100644 index 00000000000..c1f62b03703 --- /dev/null +++ b/sys/arch/arm32/fpe-sp/fpesub.S @@ -0,0 +1,113 @@ +/* $NetBSD: fpesub.S,v 1.2 1996/03/18 19:58:18 mark Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe. + * Copyright (c) 1995 Neil Carson. + * 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 kernel team. + * 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 AUTHORS ``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 AUTHORS 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 + * + * fpesub.S + * + * FP subtract + * + * Created : 11/02/95 + */ + +.global _nc_fp_sub + +pc .req r15 + +mant1 .req r2 +xp1 .req r3 +mant2 .req r4 +xp2 .req r5 +wrk1 .req r14 + +_nc_fp_sub: + stmfd r13!,{r2-r5,r14} + mov xp1,r0,lsr #23 /* get exponent+sign */ + bic mant1,r0,xp1,lsl #23 /* get mantissa */ + cmp r0,#0 + orrne mant1,mant1,#1<<23 /* set on bit to left of point */ + and xp1,xp1,#255 /* remove sign */ + + mov xp2,r1,lsr #23 /* get exponent+sign */ + bic mant2,r1,xp2,lsl #23 /* get mantissa */ + cmp r1,#0 + orrne mant2,mant2,#1<<23 /* set on bit to left of point */ + and xp2,xp2,#255 /* remove sign */ + + eors wrk1,r0,r1 /* both +ve/-ve? */ + bmi fp_sub_unequal /* no - special case */ + + subs wrk1,xp1,xp2 /* exp. difference */ + subpl mant1,mant1,mant2,lsr wrk1 /* exp1>exp2, round mant2 & subtract */ + rsbmi wrk1,wrk1,#0 /* as +ve difference */ + rsbmi mant1,mant2,mant1,lsr wrk1 /* exp1exp2, round mant2 & add */ + rsbmi wrk1,wrk1,#0 /* as +ve difference */ + addmi mant1,mant2,mant1,lsr wrk1 /* exp1 + +struct wavebuffer { + caddr_t addr; + int size; +}; + +#define BEEP_GENERATE _IO ( 'B', 100) +#define BEEP_SETRATE _IO ( 'B', 101) +#define BEEP_SET _IOW ( 'B', 102, struct wavebuffer ) + +/* End of beep.h */ diff --git a/sys/arch/arm32/include/bootconfig.h b/sys/arch/arm32/include/bootconfig.h new file mode 100644 index 00000000000..d7acfddc042 --- /dev/null +++ b/sys/arch/arm32/include/bootconfig.h @@ -0,0 +1,89 @@ +/* $NetBSD: bootconfig.h,v 1.2 1996/03/14 23:11:06 mark 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 + * + * bootconfig.h + * + * boot configuration structure + * + * Created : 12/09/94 + * + * Based on kate/boot/bootconfig.h + */ + +typedef struct _PhysMem { + u_int address; + u_int pages; +} PhysMem; + +typedef struct _BootConfig { + u_int kernvirtualbase; + u_int kernphysicalbase; + u_int kernsize; + u_int argvirtualbase; + u_int argphysicalbase; + u_int argsize; + u_int scratchvirtualbase; + u_int scratchphysicalbase; + u_int scratchsize; + + u_int display_start; + u_int display_size; + u_int width; + u_int height; + u_int bitsperpixel; + + PhysMem dram[4]; + PhysMem vram[1]; + + u_int dramblocks; + u_int vramblocks; + u_int pagesize; + u_int drampages; + u_int vrampages; + + char kernelname[80]; + + u_int framerate; + u_char machine_id[4]; +} BootConfig; + +#ifdef _KERNEL +extern BootConfig bootconfig; +#endif + +/* End of bootconfig.h */ diff --git a/sys/arch/arm32/include/cdefs.h b/sys/arch/arm32/include/cdefs.h new file mode 100644 index 00000000000..36ffac68bf3 --- /dev/null +++ b/sys/arch/arm32/include/cdefs.h @@ -0,0 +1,35 @@ +/* $NetBSD: cdefs.h,v 1.1 1996/01/31 23:21:36 mark Exp $ */ + +/* + * Written by J.T. Conklin 01/17/95. + * Public domain. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#ifdef __STDC__ +#define _C_LABEL(x) _STRING(_ ## x) +#else +#define _C_LABEL(x) _STRING(_/**/x) +#endif + +#ifdef __GNUC__ +#ifdef __STDC__ +#define __weak_reference(sym,alias) \ + __asm__(".stabs \"_" #alias "\",11,0,0,0"); \ + __asm__(".stabs \"_" #sym "\",1,0,0,0") +#define __warn_references(sym,msg) \ + __asm__(".stabs \"" msg "\",30,0,0,0"); \ + __asm__(".stabs \"_" #sym "\",1,0,0,0") +#else +#define __weak_reference(sym,alias) \ + __asm__(".stabs \"_/**/alias\",11,0,0,0"); \ + __asm__(".stabs \"_/**/sym\",1,0,0,0") +#define __warn_references(sym,msg) \ + __asm__(".stabs msg,30,0,0,0"); \ + __asm__(".stabs \"_/**/sym\",1,0,0,0") +#endif +#endif + +#endif /* !_MACHINE_CDEFS_H_ */ diff --git a/sys/arch/arm32/include/cpu.h b/sys/arch/arm32/include/cpu.h new file mode 100644 index 00000000000..3d79f4d7417 --- /dev/null +++ b/sys/arch/arm32/include/cpu.h @@ -0,0 +1,204 @@ +/* $NetBSD: cpu.h,v 1.6 1996/04/02 21:45:25 mark 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 + * + * cpu.h + * + * CPU specific symbols + * + * Created : 18/09/94 + * + * Based on kate/katelib/arm6.h + */ + +#ifndef _ARM32_CPU_H_ +#define _ARM32_CPU_H_ + +#ifndef _LOCORE +#include +#endif +#include + +/* + * If we are not an ARM6 then we MUST use late aborts as only the ARM6 + * supports early aborts. + * For the ARM6 we will use early abort unless otherwise configured + * This reduces the overheads of LDR/STR aborts and no correction is required. + */ + +#ifndef CPU_ARM6 +#define CPU_LATE_ABORTS +#endif + +#define COPY_SIGCODE /* copy sigcode above user stack in exec */ + +/* + * ARM Process Status Register + * + * The picture in the ARM manuals looks like this: + * 3 3 2 2 2 + * 1 0 9 8 7 8 7 6 5 4 0 + * +-------+---------------------------------------+-+-+-+---------+ + * | flags | reserved |I|F| |M M M M M| + * |n z c v| | | | |4 3 2 1 0| + * +-------+---------------------------------------+-+-+-+---------+ + */ + +#define PSR_FLAGS 0xf0000000 /* flags */ +#define PSR_N_bit (1 << 31) /* negative */ +#define PSR_Z_bit (1 << 30) /* zero */ +#define PSR_C_bit (1 << 29) /* carry */ +#define PSR_V_bit (1 << 28) /* overflow */ + +#define I32_bit (1 << 7) +#define F32_bit (1 << 6) + +#define PSR_MODE 0x0000001f +#define PSR_USR32_MODE 0x00000010 +#define PSR_FIQ32_MODE 0x00000011 +#define PSR_IRQ32_MODE 0x00000012 +#define PSR_SVC32_MODE 0x00000013 +#define PSR_ABT32_MODE 0x00000017 +#define PSR_UND32_MODE 0x0000001b + +#define CPU_ID_DESIGNER_MASK 0xff000000 +#define CPU_ID_ARM_LTD 0x41000000 +#define CPU_ID_DEC 0x44000000 +#define CPU_ID_MAKER_MASK 0x00ff0000 +#define CPU_ID_GPS 0x00560000 +#define CPU_ID_VLSI 0x00000000 +#define CPU_ID_CPU_MASK 0x0000fff0 +#define ID_ARM610 0x00000610 +#define ID_ARM700 0x00007000 +#define ID_ARM710 0x00007100 +#define ID_SARM110 0x0000a100 +#define CPU_ID_REVISION_MASK 0x0000000f + +#define CPU_CONTROL_MMU_ENABLE 0x0001 +#define CPU_CONTROL_AFLT_ENABLE 0x0002 +#define CPU_CONTROL_DC_ENABLE 0x0004 +#define CPU_CONTROL_WBUF_ENABLE 0x0008 +#define CPU_CONTROL_32BP_ENABLE 0x0010 +#define CPU_CONTROL_32BD_ENABLE 0x0020 +#define CPU_CONTROL_LABT_ENABLE 0x0040 +#define CPU_CONTROL_BEND_ENABLE 0x0080 +#define CPU_CONTROL_SYST_ENABLE 0x0100 +#define CPU_CONTROL_ROM_ENABLE 0x0200 +#define CPU_CONTROL_CPCLK 0x0400 +#define CPU_CONTROL_IC_ENABLE 0x1000 + +/* StrongARM has separate instruction and data caches */ + +#ifdef CPU_SA +#define CPU_CONTROL_IDC_ENABLE (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) +#else +#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE +#endif + +#define FAULT_TYPE_MASK 0x0f +#define FAULT_USER 0x10 + +#define FAULT_WRTBUF_0 0x00 +#define FAULT_WRTBUF_1 0x02 +#define FAULT_BUSERR_0 0x04 +#define FAULT_BUSERR_1 0x06 +#define FAULT_BUSERR_2 0x08 +#define FAULT_BUSERR_3 0x0a +#define FAULT_ALIGN_0 0x01 +#define FAULT_ALIGN_1 0x03 +#define FAULT_BUSTRNL1 0x0c +#define FAULT_BUSTRNL2 0x0e +#define FAULT_TRANS_S 0x05 +#define FAULT_TRANS_P 0x07 +#define FAULT_DOMAIN_S 0x09 +#define FAULT_DOMAIN_P 0x0b +#define FAULT_PERM_S 0x0d +#define FAULT_PERM_P 0x0f + +#ifdef _LOCORE +#define IRQdisable \ + stmfd sp!, {r0} ; \ + mrs r0, cpsr_all ; \ + orr r0, r0, #(I32_bit | F32_bit) ; \ + msr cpsr_all, r0 ; \ + ldmfd sp!, {r0} + +#define IRQenable \ + stmfd sp!, {r0} ; \ + mrs r0, cpsr_all ; \ + bic r0, r0, #(I32_bit | F32_bit) ; \ + msr cpsr_all, r0 ; \ + ldmfd sp!, {r0} + +#else +#define IRQdisable SetCPSR(I32_bit | F32_bit, I32_bit | F32_bit); +#define IRQenable SetCPSR(I32_bit | F32_bit, 0); +#endif /* _LOCORE */ + +/* + * Return TRUE/FALSE (1/0) depending on whether the frame came from USR + * mode or not. + */ + +#define CLKF_USERMODE(frame) ((frame->if_spsr & PSR_MODE) == PSR_USR32_MODE) + +#define CLKF_BASEPRI(frame) (1) + +#define CLKF_PC(frame) (frame->if_pc) + +/*#define CLKF_INTR(frame) ((frame->if_spsr & PSR_MODE) == PSR_IRQ32_MODE)*/ + +/* Hack to treat FPE time as interrupt time so we can measure it */ +#define CLKF_INTR(frame) ((frame->if_spsr & PSR_MODE) == PSR_UND32_MODE) + +/* + * definitions of cpu-dependent requirements + * referenced in generic code + */ + +#define cpu_wait(p) /* nothing */ + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ + +#define signotify(p) setsoftast() + +#endif /* _ARM32_CPU_H_ */ + +/* End of cpu.h */ diff --git a/sys/arch/arm32/include/cpus.h b/sys/arch/arm32/include/cpus.h new file mode 100644 index 00000000000..26ca72ce899 --- /dev/null +++ b/sys/arch/arm32/include/cpus.h @@ -0,0 +1,160 @@ +/* $NetBSD: cpus.h,v 1.3 1996/03/14 23:11:08 mark 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 + * + * cpus.h + * + * cpu device header file + * + * Created : 26/12/95 + */ + +#ifndef _LOCORE +#include +#endif + +/* If hydra is defined then we take into consideration the slave CPU's available */ + +#ifdef HYDRA +#define MAX_CPUS 6 +#define MAX_SLAVE_CPUS 4 +#define MAX_FOREIGN_CPUS 1 +#else +#define MAX_CPUS 2 +#define MAX_SLAVE_CPUS 0 +#define MAX_FOREIGN_CPUS 1 +#endif + +#define CPU_MASTER 0 +#define CPU_486 1 +#define CPU_SLAVE 2 + +#define CPU_CLASS_NONE 0 /* No CPU */ +#define CPU_CLASS_ARM 1 /* ARM 6/7/8 */ +#define CPU_CLASS_SARM 2 /* Guess */ +#define CPU_CLASS_I486 3 /* 486/586 */ + +#define CPU_HOST_NONE 0 /* No host */ +#define CPU_HOST_MAINBUS 1 /* Hosted via motherboard */ +#define CPU_HOST_HYDRA 2 /* Hosted via hydra multiprocessor board */ + +#define CPU_FLAG_PRESENT 0x01 +#define CPU_FLAG_HALTED 0x02 + +#define FPU_CLASS_NONE 0 /* no Floating point support */ +#define FPU_CLASS_FPE 1 /* Floating point emulator installed */ +#define FPU_CLASS_FPA 2 /* Floating point accelerator installed */ +#define FPU_CLASS_FPU 3 /* Floating point unit installed */ + +#define FPU_TYPE_SP_FPE 1 /* Single precision FPE */ +#define FPU_TYPE_ARMLTD_FPE 2 /* ARM Ltd FPE */ +#define FPU_TYPE_FPA11 0x81 /* ID of FPA11 */ + +#ifndef _LOCORE + +/* Define the structure used to describe a cpu */ + +typedef struct cpu_arm { + u_int cpu_id; /* The CPU id */ + u_int cpu_ctrl; /* The CPU control register */ + + u_int cpu_svc_r13; /* local data */ + u_int cpu_und_r13; /* local data */ + u_int cpu_abt_r13; /* local data */ + u_int cpu_irq_r13; /* local data */ +} cpu_arm_t; + +typedef struct cpu_sarm { + u_int cpu_id; /* The CPU id */ + u_int cpu_ctrl; /* The CPU control register */ +} cpu_sarm_t; + +typedef struct cpu_i486 { + u_int cpu_id; /* The CPU id */ + u_int cpu_ctrl; /* The CPU control register */ +} cpu_i486_t; + + +typedef struct _cpu { +/* These are generic CPU variables */ + + u_int cpu_class; /* The CPU class */ + u_int cpu_type; /* The CPU type */ + u_int cpu_host; /* The CPU host interface */ + u_int cpu_flags; /* The CPU flags */ + char cpu_model[256]; /* Text description of CPU */ + +/* These are generic FPU variables */ + + u_int fpu_class; /* The FPU class */ + u_int fpu_type; /* The FPU type */ + u_int fpu_flags; /* The FPU flags */ + char fpu_model[256]; /* Text description of FPU */ + +/* These are ARM specific variables */ + + u_int cpu_id; /* The CPU id */ + u_int cpu_ctrl; /* The CPU control register */ + + u_int cpu_svc_r13; /* local data */ + u_int cpu_und_r13; /* local data */ + u_int cpu_abt_r13; /* local data */ + u_int cpu_irq_r13; /* local data */ + +/* Not used yet */ + + union { + cpu_arm_t cpu_arm; + cpu_sarm_t cpu_sarm; + cpu_i486_t cpu_i486; + } cpu_local; +} cpu_t; + + +struct cpu_softc { + struct device sc_device; + int sc_open; +}; + +#ifdef _KERNEL + +/* Array of cpu structures, one per possible cpu */ + +extern cpu_t cpus[MAX_CPUS]; + +#endif /* _KERNEL */ +#endif /* _LOCORE */ + +/* End of hydra.h */ diff --git a/sys/arch/arm32/include/db_machdep.h b/sys/arch/arm32/include/db_machdep.h new file mode 100644 index 00000000000..2000290856f --- /dev/null +++ b/sys/arch/arm32/include/db_machdep.h @@ -0,0 +1,85 @@ +/* $NetBSD: db_machdep.h,v 1.2 1996/03/06 23:16:54 mark 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 _ARM32_DB_MACHDEP_H_ +#define _ARM32_DB_MACHDEP_H_ + +/* + * Machine-dependent defines for new kernel debugger. + */ + + +#include +#include +#include +#include + +/* end of mangling */ + +typedef vm_offset_t db_addr_t; /* address - unsigned */ +typedef int 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_pc) + +#define BKPT_INST (0xe7ffffff) /* breakpoint instruction */ +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +/*#define db_clear_single_step(regs) (0) +#define db_set_single_step(regs) (0)*/ + +#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 getreg_val (0) +#define next_instr_address(pc, bd) (pc + 4) + +#define DB_MACHINE_COMMANDS + +#define SOFTWARE_SSTEP + +#endif /* _ARM32_DB_MACHDEP_H_ */ diff --git a/sys/arch/arm32/include/disklabel.h b/sys/arch/arm32/include/disklabel.h new file mode 100644 index 00000000000..51789255abc --- /dev/null +++ b/sys/arch/arm32/include/disklabel.h @@ -0,0 +1,134 @@ +/* $NetBSD: disklabel.h,v 1.2 1996/03/06 23:17:51 mark 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 _ARM32_DISKLABEL_H_ +#define _ARM32_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 */ + +#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]; +}; + + +#include + +struct riscbsd_partition { + u_int rp_start; + u_int rp_length; + u_int rp_type; + char rp_name[16]; +}; + +struct cpu_disklabel { + u_int pad0; + u_int pad1; + struct riscbsd_partition partitions[NRISCBSD_PARTITIONS]; + struct dkbad bad; +}; + +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; +}; + +#ifdef _KERNEL +struct disklabel; +int bounds_check_with_label __P((struct buf *, struct disklabel *, int)); +#endif /* _KERNEL */ + +#endif /* _ARM32_DISKLABEL_H_ */ + +/* End of disklabel.h */ diff --git a/sys/arch/arm32/include/endian.h b/sys/arch/arm32/include/endian.h new file mode 100644 index 00000000000..a7eb2a40665 --- /dev/null +++ b/sys/arch/arm32/include/endian.h @@ -0,0 +1,78 @@ +/* $NetBSD: endian.h,v 1.2 1996/03/14 23:11:10 mark Exp $ */ + +/* + * Copyright (c) 1987, 1991 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: @(#)endian.h 7.8 (Berkeley) 4/3/91 + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +/* + * Define the order of 32-bit words in 64-bit words. + */ +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 + + +#ifndef _POSIX_SOURCE +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#define BYTE_ORDER LITTLE_ENDIAN + +#include + +__BEGIN_DECLS +unsigned long htonl __P((unsigned long)); +unsigned short htons __P((unsigned short)); +unsigned long ntohl __P((unsigned long)); +unsigned short ntohs __P((unsigned short)); +__END_DECLS + +/* + * Macros for network/external number representation conversion. + */ +#define NTOHL(x) (x) = ntohl((unsigned long)(x)) +#define NTOHS(x) (x) = ntohs((unsigned short)(x)) +#define HTONL(x) (x) = htonl((unsigned long)(x)) +#define HTONS(x) (x) = htons((unsigned short)(x)) + +#endif /* _POSIX_SOURCE */ + +#endif /* _MACHINE_ENDIAN_H_ */ diff --git a/sys/arch/arm32/include/exec.h b/sys/arch/arm32/include/exec.h new file mode 100644 index 00000000000..00cab9c6401 --- /dev/null +++ b/sys/arch/arm32/include/exec.h @@ -0,0 +1,59 @@ +/* $NetBSD: exec.h,v 1.2 1996/03/14 23:11:12 mark Exp $ */ + +/* + * Copyright (c) 1994 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 _ARM32_EXEC_H_ +#define _ARM32_EXEC_H_ + +#define __LDPGSZ 4096 + +/* Relocation format. */ + +struct relocation_info_arm6 { + int r_address; /* offset in text or data segment */ + unsigned int r_symbolnum : 24, /* ordinal number of add symbol */ + r_pcrel : 1, /* 1 if value should be pc-relative */ + r_length : 2, /* log base 2 of value's width */ + r_extern : 1, /* 1 if need to add symbol to value */ + r_baserel : 1, /* linkage table relative */ + r_jmptable : 1, /* relocate to jump table */ + r_relative : 1, /* load address relative */ + r_copy : 1; /* run time copy */ +}; + +#define relocation_info relocation_info_arm6 + +/* No special executable format */ +#define cpu_exec_aout_makecmds(a, b) ENOEXEC + +#endif /* _ARM_EXEC_H_ */ diff --git a/sys/arch/arm32/include/float.h b/sys/arch/arm32/include/float.h new file mode 100644 index 00000000000..c9fe666973c --- /dev/null +++ b/sys/arch/arm32/include/float.h @@ -0,0 +1,71 @@ +/* $NetBSD: float.h,v 1.2 1996/03/14 23:11:13 mark Exp $ */ + +/* + * Copyright (c) 1989 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. + * + * @(#)float.h 7.1 (Berkeley) 5/8/90 + */ + +/*extern int __flt_rounds();*/ +#define FLT_RADIX 2 /* b */ +/*#define FLT_ROUNDS __flt_rounds()*/ +#define FLT_ROUNDS 1 + +#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 diff --git a/sys/arch/arm32/include/fp.h b/sys/arch/arm32/include/fp.h new file mode 100644 index 00000000000..c32c9239c93 --- /dev/null +++ b/sys/arch/arm32/include/fp.h @@ -0,0 +1,64 @@ +/* $NetBSD: fp.h,v 1.2 1996/03/14 23:11:15 mark 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 + +typedef struct { + u_int32_t fp_exp; + u_int32_t fp_man_hi; + u_int32_t fp_man_lo; +} fp_reg_t; + +struct fp_state { + unsigned int fp_flags; + unsigned int fp_sr; + unsigned int fp_cr; + fp_reg_t fp_registers[16]; +}; + +#endif + +/* End of fp.h */ diff --git a/sys/arch/arm32/include/frame.h b/sys/arch/arm32/include/frame.h new file mode 100644 index 00000000000..60b06de6387 --- /dev/null +++ b/sys/arch/arm32/include/frame.h @@ -0,0 +1,140 @@ +/* $NetBSD: frame.h,v 1.3 1996/03/13 21:06:34 mark 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 + * + * frame.h + * + * Stack frames structures + * + * Created : 30/09/94 + */ + +#ifndef _ARM32_FRAME_H_ +#define _ARM32_FRAME_H_ + +#include + +/* + * System stack frames. + */ + +typedef struct irqframe { + unsigned int if_spsr; + unsigned int if_r0; + unsigned int if_r1; + unsigned int if_r2; + unsigned int if_r3; + unsigned int if_r4; + unsigned int if_r5; + unsigned int if_r6; + unsigned int if_r7; + unsigned int if_r8; + unsigned int if_r9; + unsigned int if_r10; + unsigned int if_r11; + unsigned int if_r12; + unsigned int if_usr_sp; + unsigned int if_usr_lr; + unsigned int if_svc_lr; + unsigned int if_pc; +} irqframe_t; + +#define clockframe irqframe + +typedef struct trapframe { + unsigned int tf_spsr; + unsigned int tf_r0; + unsigned int tf_r1; + unsigned int tf_r2; + unsigned int tf_r3; + unsigned int tf_r4; + unsigned int tf_r5; + unsigned int tf_r6; + unsigned int tf_r7; + unsigned int tf_r8; + unsigned int tf_r9; + unsigned int tf_r10; + unsigned int tf_r11; + unsigned int tf_r12; + unsigned int tf_usr_sp; + unsigned int tf_usr_lr; + unsigned int tf_svc_lr; + unsigned int tf_pc; +} 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 { + int sf_spl; + u_int sf_r4; + u_int sf_r5; + u_int sf_r6; + u_int sf_r7; + u_int sf_pc; +}; + +/* + * Stack frame. Used during stack traces (db_trace.c) + */ +struct frame { + u_int fr_fp; + u_int fr_sp; + u_int fr_lr; + u_int fr_pc; +}; + +#ifdef _KERNEL +void validate_trapframe __P((trapframe_t *, int)); +#endif /* _KERNEL */ + +#endif /* _ARM32_FRAME_H_ */ + +/* End of frame.h */ diff --git a/sys/arch/arm32/include/iic.h b/sys/arch/arm32/include/iic.h new file mode 100644 index 00000000000..837576f4c62 --- /dev/null +++ b/sys/arch/arm32/include/iic.h @@ -0,0 +1,71 @@ +/* $NetBSD: iic.h,v 1.1 1996/04/19 19:52:46 mark 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 { + u_int ib_addr; /* i/o address */ + void *ib_aux; /* driver specific */ +}; + +#define iic_bitdelay 10 + +#define IIC_WRITE 0x00 +#define IIC_READ 0x01 + +/* Prototypes for assembly functions */ + +void iic_set_state __P((int data, int clock)); +void iic_set_state_and_ack __P((int data, int clock)); +void iic_delay __P((int delay)); + +/* Prototype for kernel interface to IIC bus */ + +int iic_control __P((u_char address, u_char *buffer, int count)); + +#endif /* _KERNEL */ + +/* End of iic.h */ diff --git a/sys/arch/arm32/include/io.h b/sys/arch/arm32/include/io.h new file mode 100644 index 00000000000..6b8ed7c7a7e --- /dev/null +++ b/sys/arch/arm32/include/io.h @@ -0,0 +1,120 @@ +/* $NetBSD: io.h,v 1.3 1996/03/28 21:28:21 mark 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 + * + * io.h + * + * IO registers + * + * Created : 10/10/94 + */ + +/* Some of these addresses are frightening and need cleaning up */ + +/* + * The podule addresses should be removed and localised for the podules. + * This is difficuly as the podule addresses are interleaved with the + * other IO devices thus making it difficult to separate them. + */ + +#define IO_CONF_BASE 0xf6000000 + +#define IO_HW_BASE 0x03000000 + +#define IO_BASE 0xf6200000 + +#define COMBO_BASE 0xf6210000 + +#define IDE_CONTROLLER_BASE 0xf62107c0 + +#define FLOPPY_CONTROLLER_BASE 0xf6210fc0 + +#define FLOPPY_DACK 0x00002000 + +#define SERIAL0_CONTROLLER_BASE 0xf6210fe0 + +#define SERIAL1_CONTROLLER_BASE 0xf6210be0 + +#define PARALLEL_CONTROLLER_BASE 0xf62109e0 + +#define IO_MOUSE_BUTTONS 0xf6010000 + +#ifdef RC7500 + +#define IDE_CONTROLLER_BASE2 0xf622B000 + +/* + * a bit low turns attached LED on + */ +#define LEDPORT (IO_BASE + 0x0002B060) +#define LED0 0x01 +#define LED1 0x02 +#define LED2 0x04 +#define LED3 0x08 +#define LED4 0x10 +#define LED5 0x20 +#define LED6 0x40 +#define LED7 0x80 +#define LEDOFF 0x00 +#define LEDALL 0xFF +#endif + + +#define EASI_HW_BASE 0x08000000 +#define EASI_BASE 0xf8000000 +#define EASI_SIZE 0x01000000 + +#define SIMPLE_PODULE_SIZE 0x00004000 + +#define MOD_PODULE_BASE 0xf6200000 +#define SYNC_PODULE_BASE 0xf63c0000 +#define SYNC_PODULE_HW_BASE 0x033c0000 +#define FAST_PODULE_BASE 0xf6340000 +#define MEDIUM_PODULE_BASE 0xf60c0000 +#define SLOW_PODULE_BASE 0xf6040000 + +#define PODULE_GAP 0x00020000 +#define MAX_PODULES 8 + +#define NETSLOT_BASE 0xf622b000 +#define MAX_NETSLOTS 1 + +#define MOUSE_BUTTON_RIGHT 0x10 +#define MOUSE_BUTTON_MIDDLE 0x20 +#define MOUSE_BUTTON_LEFT 0x40 + +/* End of io.h */ diff --git a/sys/arch/arm32/include/iomd.h b/sys/arch/arm32/include/iomd.h new file mode 100644 index 00000000000..876c6df4749 --- /dev/null +++ b/sys/arch/arm32/include/iomd.h @@ -0,0 +1,159 @@ +/* $NetBSD: iomd.h,v 1.3 1996/03/28 21:26:05 mark 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 + * + * iomd.h + * + * IOMD registers + * + * Created : 18/09/94 + * + * Based on kate/display/iomd.h + */ + +#define IOMD_HW_BASE 0x03200000 + +#define IOMD_BASE 0xf6000000 + +#define IOMD_IOCR (IOMD_BASE + 0x00000000) +#define IOMD_KBDDAT (IOMD_BASE + 0x00000004) +#define IOMD_KBDCR (IOMD_BASE + 0x00000008) + +#define IOMD_IRQSTA (IOMD_BASE + 0x00000010) +#define IOMD_IRQRQA (IOMD_BASE + 0x00000014) +#define IOMD_IRQMSKA (IOMD_BASE + 0x00000018) +#define IOMD_SUSPEND (IOMD_BASE + 0x0000001C) /* ARM7500 */ + +#define IOMD_IRQSTB (IOMD_BASE + 0x00000020) +#define IOMD_IRQRQB (IOMD_BASE + 0x00000024) +#define IOMD_IRQMSKB (IOMD_BASE + 0x00000028) + +#define IOMD_FIQST (IOMD_BASE + 0x00000030) +#define IOMD_FIQRQ (IOMD_BASE + 0x00000034) +#define IOMD_FIQMSK (IOMD_BASE + 0x00000038) + +#define IOMD_T0LOW (IOMD_BASE + 0x00000040) +#define IOMD_T0HIGH (IOMD_BASE + 0x00000044) +#define IOMD_T0GO (IOMD_BASE + 0x00000048) +#define IOMD_T0LATCH (IOMD_BASE + 0x0000004c) + +#define IOMD_T1LOW (IOMD_BASE + 0x00000050) +#define IOMD_T1HIGH (IOMD_BASE + 0x00000054) +#define IOMD_T1GO (IOMD_BASE + 0x00000058) +#define IOMD_T1LATCH (IOMD_BASE + 0x0000005c) + +/* + * For RC7500, it's not really a IOMD device. + */ +#define IOMD_IRQSTC (IOMD_BASE + 0x00000060) /* ARM7500 */ +#define IOMD_IRQRQC (IOMD_BASE + 0x00000064) /* ARM7500 */ +#define IOMD_IRQMSKC (IOMD_BASE + 0x00000068) /* ARM7500 */ +#define IOMD_VIDMUX (IOMD_BASE + 0x0000006C) /* ARM7500 */ + +#define IOMD_IRQSTD (IOMD_BASE + 0x00000070) /* ARM7500 */ +#define IOMD_IRQRQD (IOMD_BASE + 0x00000074) /* ARM7500 */ +#define IOMD_IRQMSKD (IOMD_BASE + 0x00000078) /* ARM7500 */ + +#define IOMD_ROMCR0 (IOMD_BASE + 0x00000080) +#define IOMD_ROMCR1 (IOMD_BASE + 0x00000084) +#define IOMD_DRAMCR (IOMD_BASE + 0x00000088) +#define IOMD_VREFCR (IOMD_BASE + 0x0000008c) +#define IOMD_FSIZE (IOMD_BASE + 0x00000090) +#define IOMD_ID0 (IOMD_BASE + 0x00000094) +#define IOMD_ID1 (IOMD_BASE + 0x00000098) +#define IOMD_VERSION (IOMD_BASE + 0x0000009c) + +#define IOMD_MOUSEX (IOMD_BASE + 0x000000a0) +#define IOMD_MOUSEY (IOMD_BASE + 0x000000a4) + +#define IOMD_MSDATA (IOMD_BASE + 0x000000a8) /* ARM7500 */ +#define IOMD_MSCR (IOMD_BASE + 0x000000ac) /* ARM7500 */ + +#define IOMD_IOTCR (IOMD_BASE + 0x000000C4) /* ARM7500 */ +#define IOMD_ECTCR (IOMD_BASE + 0x000000C8) /* ARM7500 */ +#define IOMD_ASTCR (IOMD_BASE + 0x000000CC) /* ARM7500 */ + +#define IOMD_DRAMWID (IOMD_BASE + 0x000000D0) /* ARM7500 */ +#define IOMD_SELFREF (IOMD_BASE + 0x000000D4) /* ARM7500 */ + +#define IOMD_ATODICR (IOMD_BASE + 0x000000E0) /* ARM7500 */ +#define IOMD_ATODSR (IOMD_BASE + 0x000000E4) /* ARM7500 */ +#define IOMD_ATODCR (IOMD_BASE + 0x000000E8) /* ARM7500 */ +#define IOMD_ATODCNT1 (IOMD_BASE + 0x000000EC) /* ARM7500 */ +#define IOMD_ATODCNT2 (IOMD_BASE + 0x000000F0) /* ARM7500 */ +#define IOMD_ATODCNT3 (IOMD_BASE + 0x000000F4) /* ARM7500 */ +#define IOMD_ATODCNT4 (IOMD_BASE + 0x000000F8) /* ARM7500 */ + +#define IOMD_SD0CURA (IOMD_BASE + 0x00000180) +#define IOMD_SD0ENDA (IOMD_BASE + 0x00000184) +#define IOMD_SD0CURB (IOMD_BASE + 0x00000188) +#define IOMD_SD0ENDB (IOMD_BASE + 0x0000018c) +#define IOMD_SD0CR (IOMD_BASE + 0x00000190) +#define IOMD_SD0ST (IOMD_BASE + 0x00000194) + +#define IOMD_SD1CURA (IOMD_BASE + 0x000001a0) +#define IOMD_SD1ENDA (IOMD_BASE + 0x000001a4) +#define IOMD_SD1CURB (IOMD_BASE + 0x000001a8) +#define IOMD_SD1ENDB (IOMD_BASE + 0x000001ac) +#define IOMD_SD1CR (IOMD_BASE + 0x000001b0) +#define IOMD_SD1ST (IOMD_BASE + 0x000001b4) + +#define IOMD_CURSCUR (IOMD_BASE + 0x000001c0) +#define IOMD_CURSINIT (IOMD_BASE + 0x000001c4) + +#define IOMD_VIDCUR (IOMD_BASE + 0x000001d0) +#define IOMD_VIDEND (IOMD_BASE + 0x000001d4) +#define IOMD_VIDSTART (IOMD_BASE + 0x000001d8) +#define IOMD_VIDINIT (IOMD_BASE + 0x000001dc) +#define IOMD_VIDCR (IOMD_BASE + 0x000001e0) + +#define IOMD_DMAST (IOMD_BASE + 0x000001f0) +#define IOMD_DMARQ (IOMD_BASE + 0x000001f4) +#define IOMD_DMAMSK (IOMD_BASE + 0x000001f8) + +#define IO_MOUSE_BUTTONS 0xf6010000 + +#define MOUSE_BUTTON_RIGHT 0x10 +#define MOUSE_BUTTON_MIDDLE 0x20 +#define MOUSE_BUTTON_LEFT 0x40 + +#define RPC600_IOMD_ID 0xd4e7 +#define RC7500_IOC_ID 0x5B98 + +#define FREQCON (IOMD_BASE + 0x40000) + +/* End of iomd.h */ diff --git a/sys/arch/arm32/include/irqhandler.h b/sys/arch/arm32/include/irqhandler.h new file mode 100644 index 00000000000..3b506c9510a --- /dev/null +++ b/sys/arch/arm32/include/irqhandler.h @@ -0,0 +1,212 @@ +/* $NetBSD: irqhandler.h,v 1.4 1996/03/28 21:29:32 mark 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 + * + * irq.h + * + * IRQ related stuff + * + * Created : 30/09/94 + */ + +#include + +typedef struct irqhandler { + int (*ih_func)(); /* handler function */ + void *ih_arg; /* Argument to handler */ + int ih_level; /* Interrupt level */ + int ih_num; /* Interrupt number (for accounting) */ + char *ih_name; /* Name of interrupt (for vmstat -i) */ + unsigned int ih_flags; /* Interrupt flags */ + unsigned int *ih_irqmask; /* mask location for expansion cards */ + unsigned int ih_irqbit; /* interrupt bit for expansion cards */ + struct irqhandler *ih_next; /* next handler */ +} irqhandler_t; + +#define IRQ_FLAG_ACTIVE 0x00000001 /* This is the active handler in list */ + +/* Define the IRQ bits */ + + + +#ifdef RC7500 + +/*#define IRQ_PRINTER 0x00*/ +#define IRQ_RESERVED0 0x01 +#define IRQ_BUTTON 0x02 +#define IRQ_FLYBACK 0x03 +#define IRQ_POR 0x04 +#define IRQ_TIMER0 0x05 +#define IRQ_TIMER1 0x06 +#define IRQ_FIQDOWN 0x07 + +#define IRQ_DREQ3 0x08 +/*#define IRQ_HD1 0x09*/ +/*#define IRQ_HD IRQ_HD1*/ +#define IRQ_DREQ2 0x0A +#define IRQ_ETHERNET 0x0B +/*#define IRQ_FLOPPY 0x0C*/ +/*#define IRQ_SERIAL 0x0D*/ +#define IRQ_KBDTX 0x0E +#define IRQ_KBDRX 0x0F + +#define IRQ_IRQ3 0x10 +#define IRQ_IRQ4 0x11 +#define IRQ_IRQ5 0x12 +#define IRQ_IRQ6 0x13 +#define IRQ_IRQ7 0x14 +#define IRQ_IRQ9 0x15 +#define IRQ_IRQ10 0x16 +#define IRQ_HD2 0x17 + +#define IRQ_MSDRX 0x18 +#define IRQ_MSDTX 0x19 +#define IRQ_ATOD 0x1A +#define IRQ_CLOCK 0x1B +#define IRQ_PANIC 0x1C +#define IRQ_RESERVED2 0x1D +#define IRQ_RESERVED3 0x1E +#define IRQ_RESERVED1 IRQ_RESERVED2 + +/* + * Note that Sound DMA IRQ is on the 31st vector. + * It's not part of the IRQD. + */ +#define IRQ_SDMA 0x1F + +#else /* RC7500 */ + + + + +/*#define IRQ_PRINTER 0x00*/ +#define IRQ_RESERVED0 0x01 +/*#define IRQ_FLOPPYIDX 0x02*/ +#define IRQ_FLYBACK 0x03 +#define IRQ_POR 0x04 +#define IRQ_TIMER0 0x05 +#define IRQ_TIMER1 0x06 +#define IRQ_RESERVED1 0x07 + +#define IRQ_RESERVED2 0x08 +/*#define IRQ_HD 0x09*/ +/*#define IRQ_SERIAL 0x0A*/ +#define IRQ_EXTENDED 0x0B +/*#define IRQ_FLOPPY 0x0C*/ +#define IRQ_PODULE 0x0D +#define IRQ_KBDTX 0x0E +#define IRQ_KBDRX 0x0F + +#define IRQ_DMACH0 0x10 +#define IRQ_DMACH1 0x11 +#define IRQ_DMACH2 0x12 +#define IRQ_DMACH3 0x13 +#define IRQ_DMASCH0 0x14 +#define IRQ_DMASCH1 0x15 +#define IRQ_RESERVED3 0x16 +#define IRQ_RESERVED4 0x17 + +#define IRQ_EXPCARD0 0x18 +#define IRQ_EXPCARD1 0x19 +#define IRQ_EXPCARD2 0x1A +#define IRQ_EXPCARD3 0x1B +#define IRQ_EXPCARD4 0x1C +#define IRQ_EXPCARD5 0x1D +#define IRQ_EXPCARD6 0x1E +#define IRQ_EXPCARD7 0x1F + +#endif /* RC7500 */ + +#define IRQ_VSYNC IRQ_FLYBACK /* Aliased */ +#define IRQ_NETSLOT IRQ_EXTENDED + +#define IRQ_SOFTNET IRQ_RESERVED0 /* Emulated */ +#define IRQMASK_SOFTNET (1 << IRQ_SOFTNET) +#define IRQ_SOFTCLOCK IRQ_RESERVED1 /* Emulated */ +#define IRQMASK_SOFTCLOCK (1 << IRQ_SOFTCLOCK) + +#define IRQ_INSTRUCT -1 +#define NIRQS 0x20 + +/* Define the various Interrupt Priority Levels */ + +/* Interrupt Priority Levels are not mutually exclusive. */ + +#define IPL_NONE -1 +#define IPL_BIO 0 /* block I/O */ +#define IPL_NET 1 /* network */ +#define IPL_TTY 2 /* terminal */ +#define IPL_CLOCK 3 /* clock */ +#define IPL_IMP 4 /* memory allocation */ + +#define IRQ_LEVELS 5 + +#ifdef _KERNEL +extern u_int irqmasks[IRQ_LEVELS]; + +void irq_init __P(()); +int irq_claim __P((int, irqhandler_t *)); +int irq_release __P((int, irqhandler_t *)); +void irq_setmasks __P((void)); +void disable_irq __P((int)); +void enable_irq __P((int)); +u_int enable_interrupts __P((u_int)); +u_int disable_interrupts __P((u_int)); +u_int restore_interrupts __P((u_int)); +#endif + +typedef struct fiqhandler { + void (*fh_func)(); /* handler function */ + u_int fh_size; /* Size of handler function */ + u_int fh_mask; /* FIQ mask */ + u_int fh_r8; /* FIQ mode r8 */ + u_int fh_r9; /* FIQ mode r9 */ + u_int fh_r10; /* FIQ mode r10 */ + u_int fh_r11; /* FIQ mode r11 */ + u_int fh_r12; /* FIQ mode r12 */ + u_int fh_r13; /* FIQ mode r13 */ +} fiqhandler_t; + +#ifdef RC7500 +int fiq_claim __P((int, fiqhandler_t *)); +int fiq_release __P((int, fiqhandler_t *)); +#else +int fiq_claim __P((fiqhandler_t *)); +int fiq_release __P((fiqhandler_t *)); +#endif + +/* End of irqhandler.h */ diff --git a/sys/arch/arm32/include/katelib.h b/sys/arch/arm32/include/katelib.h new file mode 100644 index 00000000000..3fe6f061d42 --- /dev/null +++ b/sys/arch/arm32/include/katelib.h @@ -0,0 +1,132 @@ +/* $NetBSD: katelib.h,v 1.5 1996/03/28 21:35:51 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 + * + * katelib.h + * + * Prototypes for machine specific functions. Most of these + * could be inlined. + * + * This should not really be a separate header file. Eventually I will merge + * this into other header files once I have decided where the declarations + * should go. + * + * Created : 18/09/94 + * + * Based on kate/katelib/prototypes.h + */ + +#include + +#ifdef _KERNEL + +/* Assembly modules */ + +/* In setcpsr.S */ + +u_int SetCPSR __P((u_int, u_int)); +u_int GetCPSR __P((void)); + +/* In coproc15.S */ + +void tlbflush __P((void)); +void tlbpurge __P((u_int)); +void idcflush __P((void)); +void cpu_control __P((u_int)); +void cpu_domains __P((u_int)); +void setttb __P((u_int)); + +u_int cpu_id __P((void)); +u_int cpu_faultstatus __P((void)); +u_int cpu_faultaddress __P((void)); + +/* In setstack.S */ + +void set_stackptr __P((u_int, u_int)); +u_int get_stackptr __P((u_int)); + +/* In blockio.S */ + +void insw __P((u_int /*io*/, u_int /*dest*/, u_int /*size*/)); +void outsw __P((u_int /*io*/, u_int /*src*/, u_int /*size*/)); +void insw16 __P((u_int /*io*/, u_int /*dest*/, u_int /*size*/)); +void outsw16 __P((u_int /*io*/, u_int /*src*/, u_int /*size*/)); + +/* Macros for reading and writing words, shorts, bytes */ + +#define WriteWord(a, b) \ +*((volatile unsigned int *)(a)) = (b) + +#define ReadWord(a) \ +(*((volatile unsigned int *)(a))) + +#define WriteShort(a, b) \ +*((volatile unsigned int *)(a)) = ((b) | ((b) << 16)) + +#define ReadShort(a) \ +((*((volatile unsigned int *)(a))) & 0xffff) + +#define WriteByte(a, b) \ +*((volatile unsigned char *)(a)) = (b) + +#define ReadByte(a) \ +(*((volatile unsigned char *)(a))) + +/* Define in/out macros */ + +#define inb(port) ReadByte((port)) +#define outb(port, byte) WriteByte((port), (byte)) +#define inw(port) ReadShort((port)) +#define outw(port, word) WriteShort((port), (word)) +#define inl(port) ReadWord((port)) +#define outl(port, lword) WriteWord((port), (lword)) + +/* Prototypes that are wandering the streets */ + +#ifdef _ARM32_FRAME_H +void postmortem __P((trapframe_t */*frame*/)); +#endif +u_int traceback __P(()); +u_int simpletraceback __P(()); +u_int irqtraceback __P((u_int, u_int)); +int shell __P(()); +void kstack_stuff __P((struct proc */*p*/)); +void boot0 __P(()); +void bootsync __P((void)); +#endif + +/* End of katelib.h */ diff --git a/sys/arch/arm32/include/kbd.h b/sys/arch/arm32/include/kbd.h new file mode 100644 index 00000000000..a2023083785 --- /dev/null +++ b/sys/arch/arm32/include/kbd.h @@ -0,0 +1,66 @@ +/* $NetBSD: kbd.h,v 1.2 1996/03/14 23:11:21 mark Exp $ */ + +/* + * Copyright (c) 1995 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 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 + * + * kbd.h + * + * Keyboard ioctls + * + * Created : 21/07/95 + */ + +struct kbd_data { + int keycode; + struct timeval event_time; +}; + +struct kbd_autorepeat { + int ka_delay; + int ka_rate; +}; + +#define KBD_GETAUTOREPEAT _IOR( 'k', 100, struct kbd_autorepeat) +#define KBD_SETAUTOREPEAT _IOW( 'k', 101, struct kbd_autorepeat) +#define KBD_SETLEDS _IOW( 'k', 102, int) +#define KBD_XXX _IOW( 'k', 103, int) + +#define KBD_LED_SCROLL_LOCK 0x01 +#define KBD_LED_NUM_LOCK 0x02 +#define KBD_LED_CAPS_LOCK 0x04 + +#ifdef _KERNEL +void kbdsetstate __P((int /*state*/)); +int kbdgetstate __P(()); +#endif + +/* End of kbd.h */ diff --git a/sys/arch/arm32/include/kgdb.h b/sys/arch/arm32/include/kgdb.h new file mode 100644 index 00000000000..3f875e76bb5 --- /dev/null +++ b/sys/arch/arm32/include/kgdb.h @@ -0,0 +1,45 @@ +/* $NetBSD: kgdb.h,v 1.2 1996/03/14 23:11:23 mark 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 PSR 16 +#define SPSR 17 +#define NREG 18 + +extern int kgdbregs[NREG]; + +extern int *kgdb_find_stack(); +extern void kgdb_free_stack __P((int *)); diff --git a/sys/arch/arm32/include/limits.h b/sys/arch/arm32/include/limits.h new file mode 100644 index 00000000000..0eb98088cac --- /dev/null +++ b/sys/arch/arm32/include/limits.h @@ -0,0 +1,75 @@ +/* $NetBSD: limits.h,v 1.2 1996/03/14 23:11:25 mark 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 0x7f /* max value for a char */ +#define CHAR_MIN (-0x7f-1) /* 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_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_SOURCE */ +#endif /* !_ANSI_SOURCE */ +#endif /* _ARM_LIMITS_H_ */ diff --git a/sys/arch/arm32/include/mouse.h b/sys/arch/arm32/include/mouse.h new file mode 100644 index 00000000000..1187afffa05 --- /dev/null +++ b/sys/arch/arm32/include/mouse.h @@ -0,0 +1,111 @@ +/* $NetBSD: mouse.h,v 1.1 1996/03/27 20:57:18 mark Exp $ */ + +/* + * Copyright (c) Mark Brinicombe 1996 All rights reserved + * Copyright (c) Scott Stevens 1995 All rights reserved + * Copyright (c) Melvin Tang-Richardson 1995 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 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 MOUSE_BUTTON_RIGHT 0x10 +#define MOUSE_BUTTON_MIDDLE 0x20 +#define MOUSE_BUTTON_LEFT 0x40 +*/ + +/* Used in pms.c */ + +#define BUTSTATMASK 0x07 /* Any mouse button down if any bit set */ +#define BUTCHNGMASK 0x38 /* Any mouse button changed if any bit set */ + +#define BUT3STAT 0x01 /* Button 3 down if set */ +#define BUT2STAT 0x02 /* Button 2 down if set */ +#define BUT1STAT 0x04 /* Button 1 down if set */ +#define BUT3CHNG 0x08 /* Button 3 changed if set */ +#define BUT2CHNG 0x10 /* Button 2 changed if set */ +#define BUT1CHNG 0x20 /* Button 1 changed if set */ +#define MOVEMENT 0x40 /* Mouse movement detected */ + +/* Define user visible mouse structures */ + +struct mouseinfo { + u_int status; + int xmotion, ymotion; +}; + +struct mousebufrec { + int status; + int x,y; + struct timeval event_time; +}; + +struct mouse_state { + signed short x, y; + int buttons; +}; + +struct mouse_boundingbox { + int x, y, a, b; +}; + +struct mouse_origin { + int x, y; +}; + +/* Define mouse ioctls */ + +#define MOUSEIOC_WRITEX _IO ( 'M', 100 ) +#define MOUSEIOC_WRITEY _IO ( 'M', 101 ) + +#define MOUSEIOC_SETSTATE _IOW ( 'M', 102, struct mouse_state ) +#define MOUSEIOC_SETBOUNDS _IOW ( 'M', 103, struct mouse_boundingbox ) +#define MOUSEIOC_SETORIGIN _IOW ( 'M', 104, struct mouse_origin ) + +#define MOUSEIOC_GETSTATE _IOR ( 'M', 105, struct mouse_state ) +#define MOUSEIOC_READ MOUSEIOC_GETSTATE +#define MOUSEIOC_GETBOUNDS _IOR ( 'M', 106, struct mouse_boundingbox ) +#define MOUSEIOC_GETORIGIN _IOR ( 'M', 107, struct mouse_origin ) + +/* + * For backwards compatibility with the current Xserver. + * Eventually these will be removed. + */ + +#define QUADMOUSE_WRITEX MOUSEIOC_WRITEX +#define QUADMOUSE_WRITEY MOUSEIOC_WRITEY + +#define QUADMOUSE_SETSTATE MOUSEIOC_SETSTATE +#define QUADMOUSE_SETBOUNDS MOUSEIOC_SETBOUNDS +#define QUADMOUSE_SETORIGIN MOUSEIOC_SETORIGIN + +#define QUADMOUSE_GETSTATE MOUSEIOC_GETSTATE +#define QUADMOUSE_GETBOUNDS MOUSEIOC_GETBOUNDS +#define QUADMOUSE_GETORIGIN MOUSEIOC_GETORIGIN + +#define QUADMOUSE_SETFORMAT _IOW ( 'M', 108, char[20] ) + +/* End of mouse.h */ diff --git a/sys/arch/arm32/include/param.h b/sys/arch/arm32/include/param.h new file mode 100644 index 00000000000..5b737d6b53b --- /dev/null +++ b/sys/arch/arm32/include/param.h @@ -0,0 +1,184 @@ +/* $NetBSD: param.h,v 1.6 1996/03/14 23:11:27 mark 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 _ARM32_PARAM_H_ +#define _ARM32_PARAM_H_ + +#ifdef _KERNEL +# include +#endif + +/* + * Machine dependent constants for ARM6+ processors + */ +/*#define ovbcopy bcopy */ /* XXX should probably have long gone by now */ + +#define _MACHINE arm32 +#define MACHINE "arm32" +#define _MACHINE_ARCH arm32 +#define MACHINE_ARCH "arm32" +#define MID_MACHINE MID_ARM6 + +/* + * 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. + */ +#define ALIGNBYTES (sizeof(int) - 1) +#define ALIGN(p) (((u_int)(p) + ALIGNBYTES) &~ ALIGNBYTES) + +#define PGSHIFT 12 /* LOG2(NBPG) */ +#define NBPG (1 << PGSHIFT) /* bytes/page */ +#define PGOFSET (NBPG-1) /* byte offset into page */ +#define NPTEPG (NBPG/(sizeof (pt_entry_t))) + + +#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 2 /* pages of u-area */ +#define USPACE (UPAGES * NBPG) /* total size of u-area */ + +/* + * 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 + +/* + * Size of kernel malloc arena in CLBYTES-sized logical pages + */ +#ifndef NKMEMCLUSTERS +#define NKMEMCLUSTERS (6 * 1024 * 1024 / CLBYTES) +#endif + +/* pages ("clicks") (4096 bytes) 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) (((unsigned)(x) + PGOFSET) >> PGSHIFT) + +#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \ + ((unsigned)(bytes) >> DEV_BSHIFT) +#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \ + ((unsigned)(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)) + +/* Define various base addresses */ + +#define KERNEL_BASE 0xf0000000 +#define KERNEL_VM_BASE 0xf1000000 +#define PAGE_DIRS_BASE 0xf3000000 +#define ALT_PAGE_TBLS_BASE 0xf3c00000 +#define CURRENT_PAGEDIR_BASE 0xeffd4000 +#define PROCESS_PAGE_TBLS_BASE 0xefc00000 + +#define KERNBASE KERNEL_BASE + +/* Constants used to divide the USPACE area */ + +/* + * The USPACE area contains : + * 1. the user structure for the process + * 2. the fp context for FP emulation + * 3. the kernel (svc) stack + * 4. the undefined instruction stack + * + * The layout of the area looks like this + * + * | user area | FP context | undefined stack | kernel stack | + * + * The size of the user area is known. + * The size of the FP context is variable depending of the FP emulator + * in use and whether there is hardware FP support. However we can put + * an upper limit on it. + * The undefined stack needs to be at least 512 bytes. This is a requirement + * if the FP emulators + * The kernel stack should be at least 4K is size. + * + * The stack top addresses are used to set the stack pointers. The stack bottom + * addresses at the addresses monitored by the diagnostic code for stack overflows + * + */ + +#define FPCONTEXTSIZE (0x100) +#define USPACE_SVC_STACK_TOP (USPACE) +#define USPACE_SVC_STACK_BOTTOM (USPACE_SVC_STACK_TOP - 0x1000) +#define USPACE_UNDEF_STACK_TOP (USPACE_SVC_STACK_BOTTOM - 0x10) +#define USPACE_UNDEF_STACK_BOTTOM (sizeof(struct user) + FPCONTEXTSIZE + 10) + +#define arm_byte_to_page(x) (x >> PGSHIFT) +#define arm_page_to_byte(x) (x << PGSHIFT) + +#ifdef _KERNEL +#ifndef _LOCORE +void delay __P((unsigned)); +#define DELAY(x) delay(x) +#endif +#endif + +#endif /* _ARM_PARAM_H_ */ diff --git a/sys/arch/arm32/include/pcb.h b/sys/arch/arm32/include/pcb.h new file mode 100644 index 00000000000..00c04a84199 --- /dev/null +++ b/sys/arch/arm32/include/pcb.h @@ -0,0 +1,79 @@ +/* $NetBSD: pcb.h,v 1.2 1996/03/13 21:08:36 mark Exp $ */ + +/* + * Copyright (c) 1994 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 _ARM32_PCB_H_ +#define _ARM32_PCB_H_ + +#include +#include + +struct pcb { + pd_entry_t *pcb_pagedir; /* PT hooks */ + u_int pcb_flags; /* Flags */ + u_int pcb_spsr; + u_int pcb_r0; /* Space for register dump */ + u_int pcb_r1; + u_int pcb_r2; + u_int pcb_r3; + u_int pcb_r4; + u_int pcb_r5; + u_int pcb_r6; + u_int pcb_r7; + u_int pcb_r8; /* used */ + u_int pcb_r9; /* used */ + u_int pcb_r10; /* used */ + u_int pcb_r11; /* used */ + u_int pcb_r12; /* used */ + u_int pcb_sp; /* used */ + u_int pcb_lr; + u_int pcb_pc; + u_int pcb_und_sp; + caddr_t pcb_onfault; /* On fault handler */ + struct fp_state pcb_fpstate; /* Floating Point state */ +}; + +/* + * No additional data for core dumps. + */ +struct md_coredump { + int md_empty; +}; + +#ifdef _KERNEL +extern struct pcb *curpcb; +#endif /* _KERNEL */ + +#endif /* _ARM32_PCB_H_ */ + +/* End of pcb.h */ diff --git a/sys/arch/arm32/include/pmap.h b/sys/arch/arm32/include/pmap.h new file mode 100644 index 00000000000..888c7a2844a --- /dev/null +++ b/sys/arch/arm32/include/pmap.h @@ -0,0 +1,132 @@ +/* $NetBSD: pmap.h,v 1.3 1996/03/14 23:11:29 mark 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 _ARM32_PMAP_H_ +#define _ARM32_PMAP_H_ + +#include + +/* + * virtual address to page table entry and + * to physical address. + */ + +#define vtopte(va) \ + ((pt_entry_t *)(PROCESS_PAGE_TBLS_BASE + (arm_byte_to_page((unsigned int)(va)) << 2))) + + +#define vtophys(va) \ + ((*vtopte(va) & PG_FRAME) | ((unsigned int)(va) & ~PG_FRAME)) + +/* + * Pmap stuff + */ +struct pmap { + pd_entry_t *pm_pdir; /* KVA of page directory */ + vm_offset_t pm_pptpt; /* PA of pt's page table */ + vm_offset_t pm_vptpt; /* VA of pt's page table */ + boolean_t pm_pdchanged; /* pdir changed */ + short pm_dref; /* page directory ref count */ + short pm_count; /* pmap reference count */ + simple_lock_data_t pm_lock; /* lock on pmap */ + struct pmap_statistics pm_stats; /* pmap statistics */ +}; + +typedef struct pmap *pmap_t; + +/* + * For speed we store the both the virtual address and the page table + * entry address for each page hook. + */ + +typedef struct { + vm_offset_t va; + pt_entry_t *pte; +} pagehook_t; + +/* + * For each vm_page_t, there is a list of all currently valid virtual + * mappings of that page. An entry is a pv_entry_t, the list is pv_table. + */ + +typedef struct pv_entry { + struct pv_entry *pv_next; /* next pv_entry */ + pmap_t pv_pmap; /* pmap where mapping lies */ + vm_offset_t pv_va; /* virtual address for mapping */ + int pv_flags; /* flags */ +} *pv_entry_t; + +struct pv_page; + +struct pv_page_info { + TAILQ_ENTRY(pv_page) pgi_list; + struct pv_entry *pgi_freelist; + int pgi_nfree; +}; + +/* + * This is basically: + * ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry)) + */ + +#define NPVPPG ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry)) + +struct pv_page { + struct pv_page_info pvp_pgi; + struct pv_entry pvp_pv[NPVPPG]; +}; + +#ifdef _KERNEL +pv_entry_t pv_table; /* array of entries, one per page */ +extern pmap_t kernel_pmap; +extern struct pmap kernel_pmap_store; + +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_update() tlbflush() +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) + +boolean_t pmap_testbit __P((vm_offset_t, int)); +void pmap_changebit __P((vm_offset_t, int, int)); + +static __inline vm_offset_t +pmap_phys_address(int ppn) +{ + return(arm_page_to_byte(ppn)); +} + +#endif + +#endif + +/* End of pmap.h */ diff --git a/sys/arch/arm32/include/podule.h b/sys/arch/arm32/include/podule.h new file mode 100644 index 00000000000..5561d458868 --- /dev/null +++ b/sys/arch/arm32/include/podule.h @@ -0,0 +1,88 @@ +/* $NetBSD: podule.h,v 1.2 1996/03/14 23:11:31 mark Exp $ */ + +/* + * Copyright (C) 1994 Wolfgang Solfrank. + * Copyright (C) 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. + */ + +#ifndef _ARM32_PODULE_H_ +#define _ARM32_PODULE_H_ + +/* + * Generic defines for Acorn Podules + */ +#define IO_SPACE_PHYS 0x03000000 /* physical I/O space location */ +#define IO_SPACE_VIRT 0xf8000000 /* virtual I/O space location */ +#define IO_SPACE_SIZE 0x01000000 /* size of I/O space */ + +#define PODULE_SLOW_MEM ((volatile void *)(IO_SPACE_VIRT + 0x240000)) +#define PODULE_MED_MEM ((volatile void *)(IO_SPACE_VIRT + 0x2c0000)) +#define PODULE_FAST_MEM ((volatile void *)(IO_SPACE_VIRT + 0x340000)) +#define PODULE_SYNC_MEM ((volatile void *)(IO_SPACE_VIRT + 0x3c0000)) + +#define PODULE_SLOT2MEM(slot,mem) ((slot)*0x4000 + (mem)) + +/* + * Access 8 bit wide memory on podule + */ +#define PODULE_GET_BYTE(sp,off) (((volatile u_char *)(sp))[(off) * 4]) +#define PODULE_SET_BYTE(sp,off,byte) (((volatile u_int *)(sp))[(off)] \ + = ((u_char)(byte) << 24) \ + | ((u_char)(byte) << 16) \ + | ((u_char)(byte) << 8) \ + | (u_char)(byte)) +/* + * Access 16 bit wide memory on podule + */ +#define PODULE_GET_SHORT(sp,off) (((volatile u_short *)(sp))[(off)]) +#define PODULE_SET_SHORT(sp,off,word) (((volatile u_int *)(sp))[(off) / 2] \ + = ((u_short)(word) << 16) \ + | (u_short)(word)) + +/* + * Known offsets in any podule + */ +#define PODULE_IRQ_BYTE 0 +#define PODULE_IRQ_PEND 1 +#define PODULE_FIQ_PEND 2 + +#define PODULE_ID_BYTE 3 +#define PODULE_ID_SCSI 2 +#define PODULE_ID_ETHER 3 + +extern void podule_get_bytes __P((volatile void *sp, void *dp, int cnt)); +extern void podule_set_bytes __P((void *sp, volatile void *dp, int cnt)); + +extern void podule_get_shorts __P((volatile void *sp, void *dp, int cnt)); +extern void podule_set_shorts __P((void *sp, volatile void *dp, int cnt)); + +/* XXX Shouldn't this be somewhere else? */ +#define offsetof(type, member) ((size_t)&((type *)0)->member) + +#endif /* _ARM_PODULE_H_ */ diff --git a/sys/arch/arm32/include/proc.h b/sys/arch/arm32/include/proc.h new file mode 100644 index 00000000000..ff2531b168e --- /dev/null +++ b/sys/arch/arm32/include/proc.h @@ -0,0 +1,45 @@ +/* $NetBSD: proc.h,v 1.2 1996/03/14 23:11:33 mark Exp $ */ + +/* + * Copyright (c) 1994 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 _ARM32_PROC_H_ +#define _ARM32_PROC_H_ + +/* + * Machine-dependent part of the proc structure for arm. + */ +struct mdproc { + struct trapframe *md_regs; /* registers on current frame */ + int __spare; +}; +#endif diff --git a/sys/arch/arm32/include/profile.h b/sys/arch/arm32/include/profile.h new file mode 100644 index 00000000000..9d6a1327d26 --- /dev/null +++ b/sys/arch/arm32/include/profile.h @@ -0,0 +1,65 @@ +/* $NetBSD: profile.h,v 1.3 1996/03/14 23:11:34 mark 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 static inline void _mcount + +/* Cannot implement mcount in C as GCC uses the ip register to pass the + * frompcindex variable. GCC also uses ip during the register pushing + * at the beginning of any C function. + */ +#define MCOUNT \ +extern void mcount() asm("mcount"); \ +void \ +mcount() \ +{ \ + register int selfpc, frompcindex; \ + /* \ + * find the return address for mcount, \ + * and the return address for mcount's caller. \ + * \ + * selfpc = pc pushed by mcount call \ + */ \ + asm("mov %0, lr" : "=r" (selfpc)); \ + /* \ + * frompcindex = pc pushed by call into self. \ + */ \ + asm("mov %0, ip" : "=r" (frompcindex)); \ + _mcount(frompcindex, selfpc); \ +} + +#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/arm32/include/psl.h b/sys/arch/arm32/include/psl.h new file mode 100644 index 00000000000..b7ffcf17757 --- /dev/null +++ b/sys/arch/arm32/include/psl.h @@ -0,0 +1,84 @@ +/* $NetBSD: psl.h,v 1.2 1996/03/08 16:35:17 mark 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 + * + * psl.h + * + * spl prototypes. + * Eventually this will become a set of defines. + * + * Created : 21/07/95 + */ + +/* + * These are the different SPL states + * + * Each state has an interrupt mask associated with it which + * indicate which interrupts are allowed. + */ + +#define SPL_0 0 +#define SPL_SOFT 1 +#define SPL_BIO 2 +#define SPL_NET 3 +#define SPL_TTY 4 +#define SPL_CLOCK 5 +#define SPL_IMP 6 +#define SPL_HIGH 7 +#define SPL_LEVELS 8 + +#define spl0() splx(SPL_0) +#define splhigh() splx(SPL_HIGH) +#define splbio() raisespl(SPL_BIO) +#define splnet() raisespl(SPL_NET) +#define spltty() raisespl(SPL_TTY) +#define splimp() raisespl(SPL_IMP) +#define splclock() raisespl(SPL_CLOCK) +#define splstatclock() raisespl(SPL_CLOCK) +#define splsoftnet() raisespl(SPL_SOFT) + +#ifndef _LOCORE +int raisespl __P((int)); +int lowerspl __P((int)); +int splx __P((int)); +int splsoftclock __P(()); + +#ifdef _KERNEL +extern int current_spl_level; + +extern u_int spl_masks[SPL_LEVELS]; +#endif /* _KERNEL */ +#endif /* _LOCORE */ + +/* End of psl.h */ diff --git a/sys/arch/arm32/include/pte.h b/sys/arch/arm32/include/pte.h new file mode 100644 index 00000000000..73a087399ec --- /dev/null +++ b/sys/arch/arm32/include/pte.h @@ -0,0 +1,107 @@ +/* $NetBSD: pte.h,v 1.3 1996/03/14 23:11:36 mark Exp $ */ + +/* + * Copyright (c) 1994 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 _ARM32_PTE_H_ +#define _ARM32_PTE_H_ + +#define PDSHIFT 20 /* LOG2(NBPDR) */ +#define NBPD (1 << PDSHIFT) /* bytes/page dir */ +/*# define PDOFSET (NBPD-1)*/ /* byte offset into page dir */ +#define NPTEPD (NBPD / NBPG) + +#ifndef _LOCORE +typedef int pd_entry_t; /* page directory entry */ +typedef int pt_entry_t; /* page table entry */ +#endif + +#define PD_MASK 0xfff00000 /* page directory address bits */ +#define PT_MASK 0x000ff000 /* page table address bits */ + +#define PG_FRAME 0xfffff000 + +/* The PT_SIZE definition is misleading... A page table is only 0x400 + * bytes long. But since VM mapping can only be done to 0x1000 a single + * 1KB blocks cannot be steered to a va by itself. Therefore the + * pages tables are allocated in blocks of 4. i.e. if a 1 KB block + * was allocated for a PT then the other 3KB would also get mapped + * whenever the 1KB was mapped. + */ + +#define PT_SIZE 0x1000 +#define PD_SIZE 0x4000 + +#define AP_KR 0x00 +#define AP_KRW 0x01 +#define AP_KRWUR 0x02 +#define AP_KRWURW 0x03 + +#define AP_W 0x01 +#define AP_U 0x02 + +#define PT_B 0x04 /* Phys - Buffered (write) */ +#define PT_C 0x08 /* Phys - Cacheable */ +#define PT_U 0x10 /* Phys - Updateable */ + +#define PT_M 0x01 /* Virt - Modified */ +#define PT_H 0x02 /* Virt - Handled (Used) */ +#define PT_W 0x40 /* Virt - Wired */ +#define PT_Wr 0x10 /* Virt / Phys Write */ +#define PT_Us 0x20 /* Virt / Phys User */ + +#define PT_AP(x) ((x << 10) | (x << 8) | (x << 6) | (x << 4)) + +#define AP_SECTION_SHIFT 10 + +#define L1_PAGE 0x01 +#define L1_SECTION 0x02 +#define L2_LPAGE 0x01 +#define L2_SPAGE 0x02 +#define L2_MASK 0x03 +#define L2_INVAL 0x00 + +#define L2_PTE(p, a) ((p) | PT_AP(a) | L2_SPAGE | PT_C | PT_B) +#define L2_PTE_NC(p, a) ((p) | PT_AP(a) | L2_SPAGE | PT_B) + +#define L1_PTE(p) ((p) | 0x00 | PT_U | L1_PAGE) + +#define L1_SEC(p) ((p) | (AP_KRW << AP_SECTION_SHIFT) | PT_U | L1_SECTION) + +#define DOMAIN_FAULT 0x00 +#define DOMAIN_CLIENT 0x01 +#define DOMAIN_RESERVED 0x02 +#define DOMAIN_MANAGER 0x03 + +#endif + +/* End of pte.h */ diff --git a/sys/arch/arm32/include/ptrace.h b/sys/arch/arm32/include/ptrace.h new file mode 100644 index 00000000000..8eb446a943c --- /dev/null +++ b/sys/arch/arm32/include/ptrace.h @@ -0,0 +1,41 @@ +/* $NetBSD: ptrace.h,v 1.2 1996/03/14 23:11:38 mark 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/arm32/include/qmouse.h b/sys/arch/arm32/include/qmouse.h new file mode 100644 index 00000000000..1d776a55455 --- /dev/null +++ b/sys/arch/arm32/include/qmouse.h @@ -0,0 +1,75 @@ +/* $NetBSD: qmouse.h,v 1.2 1996/03/14 23:11:40 mark Exp $ */ + +/* + * Copyright (c) Scott Stevens 1995 All rights reserved + * Copyright (c) Melvin Tang-Richardson 1995 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 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 MOVEEVENT 0x40 +#define B1TRANS 0x20 +#define B2TRANS 0x10 +#define B3TRANS 0x08 +#define BTRANSMASK 0x38 +#define B1VAL 0x04 +#define B2VAL 0x02 +#define B3VAL 0x01 +#define BVALMASK 0x07 + +struct mousebufrec { + int status; + int x,y; + struct timeval event_time; +}; + +struct mouse_state { + signed short x, y; + int buttons; +}; + +struct mouse_boundingbox { + int x, y, a, b; +}; + +struct mouse_origin { + int x, y; +}; + +#define QUADMOUSE_WRITEX _IO ( 'M', 100 ) +#define QUADMOUSE_WRITEY _IO ( 'M', 101 ) + +#define QUADMOUSE_SETSTATE _IOW ( 'M', 102, struct mouse_state ) +#define QUADMOUSE_SETBOUNDS _IOW ( 'M', 103, struct mouse_boundingbox ) +#define QUADMOUSE_SETORIGIN _IOW ( 'M', 104, struct mouse_origin ) + +#define QUADMOUSE_GETSTATE _IOR ( 'M', 105, struct mouse_state ) +#define QUADMOUSE_GETBOUNDS _IOR ( 'M', 106, struct mouse_boundingbox ) +#define QUADMOUSE_GETORIGIN _IOR ( 'M', 107, struct mouse_origin ) + +#define QUADMOUSE_SETFORMAT _IOW ( 'M', 108, char[20] ) + +/* End of qmouse.h */ diff --git a/sys/arch/arm32/include/reg.h b/sys/arch/arm32/include/reg.h new file mode 100644 index 00000000000..840a9d6a453 --- /dev/null +++ b/sys/arch/arm32/include/reg.h @@ -0,0 +1,58 @@ +/* $NetBSD: reg.h,v 1.2 1996/03/14 23:11:41 mark 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 _ARM32_REG_H_ +#define _ARM32_REG_H_ + +#include + +struct reg { + unsigned int r[13]; + unsigned int r_sp; + unsigned int r_lr; + unsigned int r_pc; + unsigned int r_cpsr; +}; + +/* this is identical to fp_state */ +struct fpreg { + unsigned int fpr_flags; + unsigned int fpr_sr; + unsigned int fpr_cr; + fp_reg_t fpr[16]; +}; + +#endif /* !_ARM32_REG_H_ */ + diff --git a/sys/arch/arm32/include/rtc.h b/sys/arch/arm32/include/rtc.h new file mode 100644 index 00000000000..7f9e689a8ed --- /dev/null +++ b/sys/arch/arm32/include/rtc.h @@ -0,0 +1,83 @@ +/* $NetBSD: rtc.h,v 1.3 1996/04/19 19:51:48 mark 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 + * + * rtc.h + * + * Header file for RTC / CMOS stuff + * + * Created : 13/10/94 + * + * Based of kate/display/iiccontrol.c + */ + +/* + * IIC addresses for RTC chip + * Two PCF8583 chips are supported on the IIC bus + */ + +#define IIC_PCF8583_MASK 0xfc +#define IIC_PCF8583_ADDR 0xa0 + +#define RTC_Write (IIC_PCF8583_ADDR | IIC_WRITE) +#define RTC_Read (IIC_PCF8583_ADDR | IIC_READ) + +typedef struct { + u_char rtc_micro; + u_char rtc_centi; + u_char rtc_sec; + u_char rtc_min; + u_char rtc_hour; + u_char rtc_day; + u_char rtc_mon; + u_char rtc_year; + u_char rtc_cen; +} rtc_t; + +#define RTC_ADDR_BOOTOPTS 0x90 +#define RTC_ADDR_REBOOTCNT 0x91 +#define RTC_ADDR_YEAR 0xc0 +#define RTC_ADDR_CENT 0xc1 + +#ifdef _KERNEL +int cmos_read __P((int)); +int cmos_write __P((int, int)); +int rtc_read __P((rtc_t *)); +int rtc_write __P((rtc_t *)); +#endif /* _KERNEL */ + +/* End of rtc.h */ diff --git a/sys/arch/arm32/include/setjmp.h b/sys/arch/arm32/include/setjmp.h new file mode 100644 index 00000000000..bac98596c8f --- /dev/null +++ b/sys/arch/arm32/include/setjmp.h @@ -0,0 +1,7 @@ +/* $NetBSD: setjmp.h,v 1.2 1996/03/14 23:11:45 mark Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 26 /* size, in longs, of a jmp_buf */ diff --git a/sys/arch/arm32/include/signal.h b/sys/arch/arm32/include/signal.h new file mode 100644 index 00000000000..2cae693614d --- /dev/null +++ b/sys/arch/arm32/include/signal.h @@ -0,0 +1,89 @@ +/* $NetBSD: signal.h,v 1.3 1996/03/14 23:11:47 mark 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 _ARM32_SIGNAL_H_ +#define _ARM32_SIGNAL_H_ + +#ifndef _LOCORE + +typedef int sig_atomic_t; + +/* + * 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. + */ + +struct sigcontext { + int sc_onstack; /* sigstack state to restore */ + int sc_mask; /* signal mask to restore */ + + unsigned int sc_spsr; + 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_usr_sp; + unsigned int sc_usr_lr; + unsigned int sc_svc_lr; + unsigned int sc_pc; +}; + +#endif + +#endif /* _ARM_SIGNAL_H_ */ + +/* End of signal.h */ diff --git a/sys/arch/arm32/include/stdarg.h b/sys/arch/arm32/include/stdarg.h new file mode 100644 index 00000000000..b0c4350caaa --- /dev/null +++ b/sys/arch/arm32/include/stdarg.h @@ -0,0 +1,60 @@ +/* $NetBSD: stdarg.h,v 1.2 1996/03/14 23:11:49 mark 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/arm32/include/types.h b/sys/arch/arm32/include/types.h new file mode 100644 index 00000000000..4e841daa8e7 --- /dev/null +++ b/sys/arch/arm32/include/types.h @@ -0,0 +1,70 @@ +/* $NetBSD: types.h,v 1.2 1996/03/06 23:04:04 mark 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 + +typedef struct _physadr { + int r[1]; +} *physadr; + +typedef struct label_t { /* Used by setjmp & longjmp */ + int val[11]; +} label_t; + +typedef unsigned long vm_offset_t; +typedef unsigned long vm_size_t; + +/* + * 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; +typedef long long int64_t; +typedef unsigned long long u_int64_t; + +typedef int32_t register_t; + +#endif /* _ARM32_TYPES_H_ */ diff --git a/sys/arch/arm32/include/undefined.h b/sys/arch/arm32/include/undefined.h new file mode 100644 index 00000000000..c27b4c11cb2 --- /dev/null +++ b/sys/arch/arm32/include/undefined.h @@ -0,0 +1,63 @@ +/* $NetBSD: undefined.h,v 1.2 1996/03/14 23:11:51 mark 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 *)); + +#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/arm32/include/varargs.h b/sys/arch/arm32/include/varargs.h new file mode 100644 index 00000000000..7f0c6bc468b --- /dev/null +++ b/sys/arch/arm32/include/varargs.h @@ -0,0 +1,64 @@ +/* $NetBSD: varargs.h,v 1.2 1996/03/14 23:11:53 mark 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/arm32/include/vconsole.h b/sys/arch/arm32/include/vconsole.h new file mode 100644 index 00000000000..fd8dd37e94e --- /dev/null +++ b/sys/arch/arm32/include/vconsole.h @@ -0,0 +1,294 @@ +/* $NetBSD: vconsole.h,v 1.1 1996/01/31 23:23:29 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 Melvyn Tang-Richardson + * 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 the RiscBSD team + * 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 AUTHORS ``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 AUTHORS 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 + * + * vconsole.h + * + * Virtual console header + * + * Created : 18/09/94 + * Last updated : 10/01/96 + * + * $Id: vconsole.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $ + */ + +#ifdef _KERNEL +#define LOSSY 1 +#define FIXEDRES 2 + +#define BOLD (1<<15) +#define UNDERLINE (1<<16) +#define REVERSE (1<<17) +#define BLINKING (1<<18) + +#include + +struct vconsole; + +/* + * Render routines and terminal drivers which conform to version 1.00 + * of the spec should always be present. This is the lowest common + * denominator, which enables the driver to always find something that + * will work. + * + * Prefered drivers can be added required in the tables. + */ + +struct render_engine { + char * name; + int ( *init ) __P(( struct vconsole *vc )); + void ( *putchar ) __P(( dev_t dev, char c, struct vconsole *vc )); + int ( *spawn ) __P(( struct vconsole *vc )); + int ( *swapin ) __P(( struct vconsole *vc )); + int ( *mmap ) __P(( struct vconsole *vc, int offset, int nprot )); + void ( *render ) __P(( struct vconsole *vc, char c)); + void ( *scrollup ) __P(( struct vconsole *vc, int low, int high )); + void ( *scrolldown ) __P(( struct vconsole *vc, int low, int high )); + void ( *cls ) __P(( struct vconsole *vc )); + void ( *update ) __P(( struct vconsole *vc )); + int ( *scrollback ) __P(( struct vconsole *vc )); + int ( *scrollforward ) __P(( struct vconsole *vc )); + int ( *scrollbackend ) __P(( struct vconsole *vc )); + int ( *clreos ) __P(( struct vconsole *vc, int code )); + int ( *debugprint ) __P(( struct vconsole *vc )); + int ( *cursorupdate ) __P(( struct vconsole *vc )); + int ( *cursorflashrate ) __P(( struct vconsole *vc, int rate )); + int ( *setfgcol ) __P(( struct vconsole *vc, int col )); + int ( *setbgcol ) __P(( struct vconsole *vc, int col )); + int ( *textpalette ) __P(( struct vconsole *vc )); + int ( *sgr ) __P(( struct vconsole *vc, int type )); + int ( *blank ) __P(( struct vconsole *vc, int type )); + int ( *ioctl ) __P(( struct vconsole *vc, dev_t dev, int cmd, + caddr_t data, int flag, struct proc *p)); + int ( *redraw ) __P(( struct vconsole *vc, int x, int y, int a, int b )); + int ( *attach ) __P(( struct vconsole *vc, struct device *dev, struct device *dev1, void * arg)); + int ( *flash ) __P(( struct vconsole *vc, int flash )); + int ( *cursor_flash ) __P(( struct vconsole *vc, int flash )); +}; + +/* Blank types. VESA defined */ + +/* Blank type 3 is suported by default */ + +#define BLANK_NONE 0 /* Not really blanked */ +#define BLANK_IDLE 1 /* Vsync dropped for fast reactivation */ +#define BLANK_UNUSED 2 /* Hsync dropped for semi fast reactivation */ +#define BLANK_OFF 3 /* All signals removed slowest reactivation */ + +#define R_NAME render_engine->name +#define SPAWN render_engine->spawn +#define SCROLLUP render_engine->scrollup +#define SCROLLDOWN render_engine->scrolldown +#define RENDER render_engine->render +#define R_SWAPIN render_engine->swapin +#define CLS render_engine->cls +#define R_INIT render_engine->init +#define PUTCHAR render_engine->putchar +#define R_SWAPIN render_engine->swapin +#define MMAP render_engine->mmap +#define R_SCROLLBACK render_engine->scrollback +#define R_SCROLLFORWARD render_engine->scrollforward +#define R_SCROLLBACKEND render_engine->scrollbackend +#define R_CLREOS render_engine->clreos +#define R_DEBUGPRINT render_engine->debugprint +#define CURSORUPDATE render_engine->cursorupdate +#define CURSORFLASHRATE render_engine->cursorflashrate +#define SETFGCOL render_engine->setfgcol +#define SETBGCOL render_engine->setbgcol +#define TEXTPALETTE render_engine->textpalette +#define SGR render_engine->sgr +#define BLANK render_engine->blank +#define IOCTL render_engine->ioctl +#define REDRAW render_engine->redraw +#define R_ATTACH render_engine->attach +#define FLASH render_engine->flash +#define CURSOR_FLASH render_engine->cursor_flash + +/* + * The terminal emulator's scroll back is only used as a last resort for + * cases when a render engine can't scrollback. In most cases though, the + * terminal emulator won't allocate enough chapmap to perform scrollback. + */ + +struct terminal_emulator { + char *name; + /* Terminal emulation routines */ + int (*term_init) __P((struct vconsole *vc)); + int (*putstring) __P((char *string, int length, struct vconsole *vc)); + int (*swapin) __P((struct vconsole *vc)); + int (*swapout) __P((struct vconsole *vc)); + int (*sleep) __P((struct vconsole *vc)); + int (*wake) __P((struct vconsole *vc)); + int ( *scrollback) __P(( struct vconsole *vc )); + int ( *scrollforward) __P(( struct vconsole *vc )); + int ( *scrollbackend) __P(( struct vconsole *vc )); + int ( *debugprint) __P(( struct vconsole *vc )); + int ( *modechange) __P(( struct vconsole *vc )); + int ( *attach ) __P(( struct vconsole *vc, struct device *dev, struct device *dev1, void *arg )); +}; + +#define T_NAME terminal_emulator->name +#define TERM_INIT terminal_emulator->term_init +#define T_SWAPIN terminal_emulator->swapin +#define PUTSTRING terminal_emulator->putstring +#define SLEEP terminal_emulator->sleep +#define WAKE terminal_emulator->wake +#define T_SCROLLBACK terminal_emulator->scrollback +#define T_SCROLLFORWARD terminal_emulator->scrollforward +#define T_SCROLLBACKEND terminal_emulator->scrollbackend +#define T_DEBUGPRINT terminal_emulator->debugprint +#define MODECHANGE terminal_emulator->modechange +#define T_ATTACH terminal_emulator->attach + +struct vconsole { + /* Management of consoles */ + + struct vconsole *next; + int number; + int opened; + struct tty *tp; + struct proc *proc; + int flags; + + /* Data structures */ + char *data; + char *r_data; + + /* Structures required for the generic character map */ + int xchars, ychars; + int *charmap; + int xcur, ycur; + + /* This is the end of the old stuff */ + + struct render_engine *render_engine; + struct terminal_emulator *terminal_emulator; + + int t_scrolledback; + int r_scrolledback; + + int blanked; + + int vtty; +}; + +extern int vconsole_pending; +extern int vconsole_blankinit; +extern int vconsole_blankcounter; + +extern struct vconsole *vconsole_current; + +extern struct render_engine *render_engine_tab[]; +extern struct terminal_emulator *terminal_emulator_tab[]; + +#endif + +/* ioctls for switching between vconsoles */ + +#define CONSOLE_SWITCHUP _IO( 'n', 0 ) +#define CONSOLE_SWITCHDOWN _IO( 'n', 1 ) +#define CONSOLE_SWITCHTO _IOW( 'n', 2, int ) +#define CONSOLE_SWITCHPREV _IO( 'n', 3 ) + +/* ioctls for creating new virtual consoles */ + +#define CONSOLE_CREATE _IOW( 'n', 10, int ) +#define CONSOLE_RENDERTYPE _IOR( 'n', 11, 20 ) +#define CONSOLE_TERMTYPE _IOR( 'n', 12, 20 ) + +/* ioctls for locking in the current console. Kinky eh ? */ + +#define CONSOLE_LOCK _IO( 'n', 20 ) +#define CONSOLE_UNLOCK _IO( 'n', 21 ) + +/* ioctls for animation, multimedia and games */ + +#define CONSOLE_SWOP _IO( 'n', 30 ) /* Screen Banking */ + +#ifdef CONSOLEGFX +struct console_line { + int len; + char data[128]; +}; + +struct console_coords { + int x, y; +}; + +#define CONSOLE_DRAWGFX _IOW( 'n', 31, struct console_line ) /* Screen Banking */ +#define CONSOLE_MOVE _IOW( 'n', 32, struct console_coords ) +#endif + +/* ioctls for configuration and control */ + +#define CONSOLE_CURSORFLASHRATE _IOW ( 'n', 40, int ) +#define CONSOLE_MODE _IOW ( 'n', 41, struct vidc_mode ) +#define CONSOLE_MODE_ALL _IOW ( 'n', 42, struct vidc_mode ) + +#define CONSOLE_BLANKTIME _IOW ( 'n', 44, int ) + +/* ioctls for developers *DO NOT USE * */ + +#define CONSOLE_SPAWN_VIDC _IOW( 'n', 100, int ) +#define CONSOLE_DEBUGPRINT _IOW( 'n', 101, int ) + + +/* structures and ioctls added by mark for the Xserver development */ + +struct console_info { + videomemory_t videomemory; + int width; + int height; + int bpp; +}; + +struct console_palette { + int entry; + int red; + int green; + int blue; +}; + +#define CONSOLE_RESETSCREEN _IO( 'n', 102) +#define CONSOLE_RESTORESCREEN _IO( 'n', 103) +#define CONSOLE_GETINFO _IOR( 'n', 104, struct console_info ) +#define CONSOLE_PALETTE _IOW( 'n', 105, struct console_palette ) +#define CONSOLE_GETVC _IOR( 'n', 106, int ) + +#define CONSOLE_IOCTL_COMPAT_N _IO( 'n', 107 ) +#define CONSOLE_IOCTL_COMPAT_T _IO( 't', 107 ) + +/* End of vconsole.h */ diff --git a/sys/arch/arm32/include/vidc.h b/sys/arch/arm32/include/vidc.h new file mode 100644 index 00000000000..4c28277bd79 --- /dev/null +++ b/sys/arch/arm32/include/vidc.h @@ -0,0 +1,269 @@ +/* $NetBSD: vidc.h,v 1.2 1996/03/28 21:22:24 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 Mark Brinicombe. + * Copyright (c) 1994,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 + * + * vidc.h + * + * VIDC20 registers + * + * Created : 18/09/94 + * Last updated : 08/03/95 + * + * Based on kate/display/vidc.h + * + * $Id: vidc.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $ + */ + +#ifndef __vidc_h +#define __vidc_h + +/* VIDC20 Base addresses */ + +#define VIDC_HW_BASE 0x03400000 + +#define VIDC_BASE 0xf6100000 + +/* Video registers */ + +#define VIDC_PALETTE 0x00000000 +#define VIDC_PALREG 0x10000000 + +#define VIDC_BCOL 0x40000000 +#define VIDC_CP0 0x40000000 +#define VIDC_CP1 0x50000000 +#define VIDC_CP2 0x60000000 +#define VIDC_CP3 0x70000000 + +#define VIDC_HCR 0x80000000 +#define VIDC_HSWR 0x81000000 +#define VIDC_HBSR 0x82000000 +#define VIDC_HDSR 0x83000000 +#define VIDC_HDER 0x84000000 +#define VIDC_HBER 0x85000000 +#define VIDC_HCSR 0x86000000 +#define VIDC_HIR 0x87000000 + +#define VIDC_VCR 0x90000000 +#define VIDC_VSWR 0x91000000 +#define VIDC_VBSR 0x92000000 +#define VIDC_VDSR 0x93000000 +#define VIDC_VDER 0x94000000 +#define VIDC_VBER 0x95000000 +#define VIDC_VCSR 0x96000000 +#define VIDC_VCER 0x97000000 + +#define VIDC_EREG 0xc0000000 +#define VIDC_FSYNREG 0xd0000000 +#define VIDC_CONREG 0xe0000000 +#define VIDC_DCTL 0xf0000000 + +/* VIDC palette macros */ + +#define VIDC_RED(r) (r) +#define VIDC_GREEN(g) (g << 8) +#define VIDC_BLUE(b) (b << 16) +#define VIDC_COL(r, g, b) (VIDC_RED(r) | VIDC_GREEN(g) | VIDC_BLUE(b)) + +#ifdef RC7500 +/* + * Video frequency definitions + */ +#define VIDFREQ_25_18 0x00 +#define VIDFREQ_28_32 0x01 +#define VIDFREQ_40_00 0x02 +#define VIDFREQ_72_00 0x03 +#define VIDFREQ_50_00 0x04 +#define VIDFREQ_77_00 0x05 +#define VIDFREQ_36_00 0x06 +#define VIDFREQ_44_90 0x07 +#define VIDFREQ_130_0 0x08 +#define VIDFREQ_120_0 0x09 +#define VIDFREQ_80_00 0x0A +#define VIDFREQ_31_50 0x0B +#define VIDFREQ_110_0 0x0C +#define VIDFREQ_65_00 0x0D +#define VIDFREQ_75_00 0x0E +#define VIDFREQ_94_50 0x0F +#endif + + +/* Sound registers */ + +#define VIDC_SIR0 0xa0000000 +#define VIDC_SIR1 0xa1000000 +#define VIDC_SIR2 0xa2000000 +#define VIDC_SIR3 0xa3000000 +#define VIDC_SIR4 0xa4000000 +#define VIDC_SIR5 0xa5000000 +#define VIDC_SIR6 0xa6000000 +#define VIDC_SIR7 0xa7000000 + +#define VIDC_SFR 0xb0000000 +#define VIDC_SCR 0xb1000000 + +#define SIR_LEFT_100 0x01 +#define SIR_LEFT_83 0x02 +#define SIR_LEFT_67 0x03 +#define SIR_CENTRE 0x04 +#define SIR_RIGHT_67 0x05 +#define SIR_RIGHT_83 0x06 +#define SIR_RIGHT_100 0x07 + +/* Video display addresses */ + +/* Where the display memory is mapped */ + +#define VMEM_VBASE 0xf4000000 + +/* Where the VRAM will be found */ + +#define VRAM_BASE 0x02000000 + +/* Video memory descriptor */ + +typedef struct + { + u_int vidm_vbase; /* virtual base of video memory */ + u_int vidm_pbase; /* physical base of video memory */ + u_int vidm_size; /* video memory size */ + int vidm_type; /* video memory type */ + } videomemory_t; + +#define VIDEOMEM_TYPE_VRAM 0x01 +#define VIDEOMEM_TYPE_DRAM 0x02 + +/* Structures and prototypes for vidc handling functions */ + +struct vidc_state { + int palette[256]; + int palreg; + int bcol; + int cp1; + int cp2; + int cp3; + int hcr, hswr, hbsr, hdsr, hder, hber, hcsr; + int hir; + int vcr, vswr, vbsr, vdsr, vder, vber, vcsr, vcer; + int ereg; + int fsynreg; + int conreg; + int dctl; +}; + +#define VIDC_FREF 24000000 + +#ifdef _KERNEL +extern int vidc_write __P((u_int /*reg*/, int /*value*/)); +extern void vidc_setstate __P((struct vidc_state */*vidc*/)); +extern void vidc_setpalette __P((struct vidc_state */*vidc*/)); +extern void vidc_stdpalette __P(()); +extern int vidc_col __P((int /*red*/, int /*green*/, int /*blue*/)); +extern struct vidc_state vidc_current[]; +#endif + +struct vidc_mode { + int pixel_rate; + int hswr, hbsr, hdsr, hder, hber, hcr; + int vswr, vbsr, vdsr, vder, vber, vcr; + int bitsperpixel; + int sync_pol; + int frame_rate; +}; + +typedef struct + { + int chars; /* Number of characters defined in font */ + int width; /* Defined width of characters in bytes */ + int height; /* Defined height of characters in lines */ + int pixel_width; /* Width of characters in pixels */ + int pixel_height; /* Height of characters in pixels */ + int x_spacing; /* Spacing in pixels between chars */ + int y_spacing; /* Spacing in pixels between lines */ + int data_size; /* Allocated data size */ + unsigned char *data; /* Font data */ + } font_struct; + +#define XRES mode.hder +#define YRES mode.vder +#define BITSPERPIXEL mode.bitsperpixel + +struct vidc_info + { + struct vidc_mode mode; + struct vidc_state vidc; + font_struct *font; /* pointer to current font_struct */ + font_struct *normalfont; /* pointer to normal font struct */ + font_struct *italicfont; /* pointer to italic font struct */ + font_struct *boldfont; /* pointer to bold font struct */ + int xfontsize, yfontsize; + int text_width, text_height; + int bytes_per_line; + int bytes_per_scroll; + int pixelsperbyte; + int screensize; + int fast_render; + int forecolour, forefillcolour; + int backcolour, backfillcolour; + int text_colours; + int frontporch; + int topporch; /* ;) */ + int bold; + int reverse; + int n_forecolour; + int n_backcolour; + int blanked; + int scrollback_end; + int flash; + int cursor_flash; + }; + +#define COLOUR_BLACK_1 0x00 +#define COLOUR_WHITE_1 0x01 + +#define COLOUR_BLACK_2 0x00 +#define COLOUR_WHITE_2 0x03 + +#define COLOUR_BLACK_4 0x00 +#define COLOUR_WHITE_4 0x07 + +#define COLOUR_BLACK_8 0x00 +#define COLOUR_WHITE_8 0x07 + +#endif + +/* End of vidc.h */ + diff --git a/sys/arch/arm32/include/vmparam.h b/sys/arch/arm32/include/vmparam.h new file mode 100644 index 00000000000..d86654cc2f8 --- /dev/null +++ b/sys/arch/arm32/include/vmparam.h @@ -0,0 +1,116 @@ +/* $NetBSD: vmparam.h,v 1.1 1996/01/31 23:23:37 mark 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. + * + * $Id: vmparam.h,v 1.1.1.1 1996/04/24 11:08:46 deraadt Exp $ + */ + +#ifndef _ARM32_VMPARAM_H_ +#define _ARM32_VMPARAM_H_ + +#define USRTEXT VM_MIN_ADDRESS +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Note that MAXTSIZ mustn't be greater than 32M. Otherwise you'd have + * to change the compiler to not generate bl instructions + */ +#define MAXTSIZ (8*1024*1024) /* max text size */ +#ifndef DFLDSIZ +#define DFLDSIZ (16*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (256*1024*1024) /* max data size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (512*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (8*1024*1024) /* max stack size */ +#endif + +/* + * Default sizes of swap allocation chunks (see dmap.h). + * The actual values may be changed in vminit() based on MAXDSIZ. + * With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024. + */ +#define DMMIN 32 /* smallest swap allocation */ +#define DMMAX 4096 /* largest potential swap allocation */ +#define DMTEXT 1024 /* swap allocation for text */ + +/* + * 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 + */ + +/*#define VM_MIN_ADDRESS ((vm_offset_t)0x00400000)*/ +#define VM_MIN_ADDRESS ((vm_offset_t)0x00001000) +#define VM_MAXUSER_ADDRESS ((vm_offset_t)0xefc00000 - UPAGES * NBPG) +#define VM_MAX_ADDRESS ((vm_offset_t)0xeffc0000) + +#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xf0000000) +#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xffffffff) + +/* + * Size of User Raw I/O map + */ + +#define USRIOSIZE 300 + +/* virtual sizes (bytes) for various kernel submaps */ + +#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES) +#define VM_KMEM_SIZE (NKMEMCLUSTERS*CLBYTES) +#define VM_PHYS_SIZE (USRIOSIZE*CLBYTES) + +#endif + +/* End of vmparam.h */ + diff --git a/sys/arch/arm32/kshell/dumphex.c b/sys/arch/arm32/kshell/dumphex.c new file mode 100644 index 00000000000..d45947b627a --- /dev/null +++ b/sys/arch/arm32/kshell/dumphex.c @@ -0,0 +1,133 @@ +/* $NetBSD: dumphex.c,v 1.2 1996/03/18 20:32:31 mark 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 + * + * dumphex.c + * + * Hex memory dump routines + * + * Created : 17/09/94 + */ + +#include +#include +#include + +/* dumpb - dumps memory in bytes*/ + +void +dumpb(addr, count) + u_char *addr; + int count; +{ + u_int byte; + int loop; + + for (; count > 0; count -= 16) { + printf("%08x: ", (int)addr); + + for (loop = 0; loop < 16; ++loop) { + byte = addr[loop]; + printf("%02x ", byte); + } + + printf(" "); + + for (loop = 0; loop < 16; ++loop) { + byte = addr[loop]; + if (byte < 0x20) + printf("\x1b[31m%c\x1b[0m", byte + '@'); + else if (byte == 0x7f) + printf("\x1b[31m?\x1b[0m"); + else if (byte < 0x80) + printf("%c", byte); + else if (byte < 0xa0) + printf("\x1b[32m%c\x1b[0m", byte - '@'); + else if (byte == 0xff) + printf("\x1b[32m?\x1b[0m"); + else + printf("%c", byte & 0x7f); + } + + printf("\r\n"); + addr += 16; + } +} + + +/* dumpw - dumps memory in bytes*/ + +void +dumpw(addr, count) + u_char *addr; + int count; +{ + u_int byte; + int loop; + + for (; count > 0; count -= 32) { + printf("%08x: ", (int)addr); + + for (loop = 0; loop < 8; ++loop) { + byte = ((u_int *)addr)[loop]; + printf("%08x ", byte); + } + + printf(" "); + + for (loop = 0; loop < 32; ++loop) { + byte = addr[loop]; + if (byte < 0x20) + printf("\x1b[31m%c\x1b[0m", byte + '@'); + else if (byte == 0x7f) + printf("\x1b[31m?\x1b[0m"); + else if (byte < 0x80) + printf("%c", byte); + else if (byte < 0xa0) + printf("\x1b[32m%c\x1b[0m", byte - '@'); + else if (byte == 0xff) + printf("\x1b[32m?\x1b[0m"); + else + printf("%c", byte & 0x7f); + } + + printf("\r\n"); + addr += 32; + } +} + +/* End of dumphex.c */ diff --git a/sys/arch/arm32/kshell/shell_disassem.c b/sys/arch/arm32/kshell/shell_disassem.c new file mode 100644 index 00000000000..6de632e932c --- /dev/null +++ b/sys/arch/arm32/kshell/shell_disassem.c @@ -0,0 +1,186 @@ +/* $NetBSD: shell_disassem.c,v 1.2 1996/03/06 23:52:15 mark 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 + * + * shell_disassem.c + * + * Debug / Monitor shell disassembler + * + * Created : 09/10/94 + */ + +/* Include standard header files */ + +#include +#include + +/* Local header files */ + +#include + +/* Declare external variables */ + +/* Local function prototypes */ + +u_int disassemble __P((u_char *)); +u_int do_disassemble __P((u_char *)); + +/* Now for the main code */ + +/* dis - disassembles memory */ + +void +shell_disassem(argc, argv) + int argc; + char *argv[]; +{ + u_char *addr; + + if (argc < 2) { + printf("Syntax: dis \n\r"); + return; + } + +/* Decode the one argument */ + + addr = (u_char *)readhex(argv[1]); + + printf("Interactive disassembly\n\r"); + + do_disassemble(addr); +} + + +u_int +do_disassemble(addr) + u_char *addr; +{ + u_int result; + int quit = 0; + int key; + int count = 1; + + do { + result = disassemble(addr); + + --count; + + if (count == 0) { + count = 1; + + key = cngetc(); + + switch (key) { + case 'Q' : + case 'q' : + case 0x1b : + case 0x03 : + case 0x04 : + case 0x10b : + quit = 1; + break; + case 0x09 : + case 'r' : + case 'R' : + case 0x103 : + count = 16; + addr += 4; + break; + + case 0x102 : + count = 16; + addr -= 124; + break; + + case 0x0d : + case 0x101 : + addr = addr + 4; + break; + + case 'B' : + case 'b' : + case 0x100: + addr = addr - 4; + break; + + case '+' : + case '=' : + case 0x104 : + addr = addr + 0x80; + break; + + case '-' : + case '_' : + case 0x105 : + addr = addr - 0x80; + break; + + case ' ' : + quit = do_disassemble((u_char *)result); + break; + + case 'J' : + case 'j' : + addr = (u_char *)result; + break; + + case '/' : + case '?' : + printf("\'\xe3\' - Backwards 1 word\n\r"); + printf("\'\xe4\' - Forwards 1 word\n\r"); + printf("\'\xe5\' - Backwords 16 words\n\r"); + printf("\'\xe6\' - Forwards 16 words\n\r"); + printf("\'Q\' - Quit\n\r"); + printf("\'B\' - Back a word\n\r"); + printf("\'R\' - Disassemble 16 words\n\r"); + printf("\'J\' - Jump to address\n\r"); + printf("\' \' - Branch to address\n\r"); + printf(" - Return from branch\n\r"); + printf("\'-\' - Skip backwards 128 words\n\r"); + printf("\'+\' - Skip forwards 128 words\n\r"); + break; + + } + } else { + addr += 4; + } + } while (!quit && key != 0x08); + + return(quit); +} + +/* End of shell_disassem.c */ diff --git a/sys/arch/arm32/kshell/shell_input.c b/sys/arch/arm32/kshell/shell_input.c new file mode 100644 index 00000000000..07cbd576e3c --- /dev/null +++ b/sys/arch/arm32/kshell/shell_input.c @@ -0,0 +1,297 @@ +/* $NetBSD: shell_input.c,v 1.2 1996/03/06 23:44:07 mark 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 + * + * shell_input.c + * + * string input functions + * + * Created : 09/10/94 + */ + +#include +#include +#include + +/*#define SOFT_CURSOR*/ + +/* Declare global variables */ + +/* Prototype declarations */ + +char *strchr __P((const char *, int)); + +void deleteline __P((int, int)); + +/* + * Reads a line from the keyboard into an input buffer allowing + * cursor editing and input history. + */ + +int +readstring(string, length, valid_string, insert) + char *string; + int length; + char *valid_string; + char *insert; +{ + int key; + int loop; + int entered; + int insert_mode = 1; + +/* + * If we have text to preinsert into the buffer enter it and echo it + * to the display. + */ + + if (insert && insert[0] != 0) { + strcpy(string, insert); + loop = strlen(insert); + printf("%s", insert); + } else + loop = 0; + + entered = loop; + +/* + * The main loop. + * Keep looping until return or CTRL-D is pressed. + */ + + do { +#ifdef SOFT_CURSOR +/* + * Display the cursor depending on what mode we are in + */ + if (!insert_mode) + printf("\xe2"); + else + printf("\xe1"); +#endif + +/* + * Read the keyboard + */ + + key = cngetc(); + +#ifdef SOFT_CURSOR +/* + * Remove the cursor, restoring the text under it if necessary. + */ + + if (loop == entered || entered == 0) + printf("\x7f"); + else + printf("\x08%c\x08", string[loop]); +#endif + +/* + * Decode the key + */ + + switch (key) { +/* + * DELETE + */ + + case 0x109 : + case 0x7f : + { + int loop1; + + if (loop == entered) break; + for (loop1 = loop; loop1 < (entered - 1); ++loop1) { + string[loop1] = string[loop1+1]; + } + --entered; + string[entered] = 0; +/* printf("\x1b[s%s \x1b[u", &string[loop]);*/ + printf("\r%s \r", string); + for (loop1 = 0; loop1 <= loop; ++loop1) + printf("\x09"); + } + break; + +/* + * BACKSPACE + */ + + case 0x08 : + { + int loop1; + + if (loop == 0) { + printf("\x07"); + break; + } + for (loop1 = loop-1; loop1 < (entered - 1); ++loop1) { + string[loop1] = string[loop1+1]; + } + --loop; + --entered; + string[entered] = 0; +/* printf("\x1b[D\x1b[s%s \x1b[u", &string[loop]);*/ + printf("\r%s \r", string); + for (loop1 = 0; loop1 < loop; ++loop1) + printf("\x09"); + } + break; + +/* + * CTRL-U + */ + case 0x15 : + deleteline(loop, entered); + loop = 0; + entered = 0; + break; + +/* + * CTRL-A + */ + case 0x01 : + insert_mode = !insert_mode; + break; + +/* + * CTRL-D + */ + case 0x04 : + return(-1); + break; + +/* + * CURSOR LEFT + */ + + case 0x102 : + --loop; + if (loop < 0) + loop = 0; + else + printf("\x1b[D"); + break; + +/* + * CURSOR RIGHT + */ + + case 0x103 : + ++loop; + if (loop > entered) + loop = entered; + else + printf("\x1b[C"); + break; + +/* + * RETURN + */ + + case 0x0d : + case 0x0a : + break; + +/* + * Another key + */ + + default : + +/* + * Check for a valid key to enter + */ + + if (key < 0x100 && key > 0x1f + && (valid_string == NULL || strchr(valid_string, key))) { + if (!insert_mode && loop < length) { + string[loop] = key; + printf("%c", key); + ++loop; + if (loop > entered) entered = loop; + } + else if (entered < length) { + int loop1; + + for (loop1 = entered; loop1 >= loop; --loop1) { + string[loop1+1] = string[loop1]; + } + string[loop] = key; + ++loop; + ++entered; + string[entered] = 0; + if (loop != entered) printf("\x1b[s"); + printf("%s", &string[loop-1]); + if (loop != entered) printf("\x1b[u\x1b[C"); + } else { + printf("\x07"); + } + } + break; + } + } while (key != 0x0d && key != 0x0a); + + printf("\n\r"); + + string[entered] = 0; + + return(entered); +} + + +/* This erases a line of text */ + +void +deleteline(loop, entered) + int loop; + int entered; +{ + while (loop < entered) { + ++loop; + printf("\x1b[C"); + } + + while (loop > 0) { + --loop; + --entered; + printf("\x7f"); + } +} + +/* End of shell_input.c */ diff --git a/sys/arch/arm32/kshell/shell_shell.c b/sys/arch/arm32/kshell/shell_shell.c new file mode 100644 index 00000000000..870e4a1434a --- /dev/null +++ b/sys/arch/arm32/kshell/shell_shell.c @@ -0,0 +1,662 @@ +/* $NetBSD: shell_shell.c,v 1.5 1996/04/19 20:15:36 mark 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 + * + * shell_shell.c + * + * Debug / Monitor shell entry and commands + * + * Created : 09/10/94 + */ + +/* Include standard header files */ + +#include +#include +#include +#include +#include +#include +#include + +/* Local header files */ + +#include +#include +#include +#include + +/* Declare global variables */ + +/* Local function prototypes */ + +char *strchr __P((const char *, int)); + +void dumpb __P((u_char */*addr*/, int /*count*/)); +void dumpw __P((u_char */*addr*/, int /*count*/)); + +int readstring __P((char *, int, char *, char *)); + +void debug_show_q_details __P((void)); +void shell_disassem __P((int argc, char *argv[])); +void shell_devices __P((int argc, char *argv[])); +void shell_vmmap __P((int argc, char *argv[])); +void shell_flush __P((int argc, char *argv[])); +void shell_pextract __P((int argc, char *argv[])); +void shell_vnode __P((int argc, char *argv[])); +void debug_show_all_procs __P((int argc, char *argv[])); +void debug_show_callout __P((int argc, char *argv[])); +void debug_show_fs __P((int argc, char *argv[])); +void debug_show_vm_map __P((vm_map_t map, char *text)); +void debug_show_pmap __P((pmap_t pmap)); +void pmap_dump_pvs __P((void)); +void bootsync __P((void)); + +/* Now for the main code */ + +/* readhex + * + * This routine interprets the input string as a sequence of hex characters + * and returns it as an integer. + */ + +int +readhex(buf) + char *buf; +{ + int value; + int nibble; + + if (buf == NULL) + return(0); + +/* skip any spaces */ + + while (*buf == ' ') + ++buf; + +/* return 0 if a zero length string is passed */ + + if (*buf == 0) + return(0); + +/* Convert the characters */ + + value = 0; + + while (*buf != 0 && strchr("0123456789abcdefABCDEF", *buf) != 0) { + nibble = (*buf - '0'); + if (nibble > 9) nibble -= 7; + if (nibble > 15) nibble -= 32; + value = (value << 4) | nibble; + ++buf; + } + + return(value); +} + + +/* poke - writes a byte/word to memory */ + +void +shell_poke(argc, argv) + int argc; + char *argv[]; +{ + u_int addr; + u_int data; + + if (argc < 3) { + printf("Syntax: poke[bw] \n\r"); + return; + } + +/* Decode the two arguments */ + + addr = readhex(argv[1]); + data = readhex(argv[2]); + + if (argv[0][4] == 'b') + WriteByte(addr, data); + if (argv[0][4] == 'w') + WriteWord(addr, data); +} + + +/* peek - reads a byte/word from memory*/ + +void +shell_peek(argc, argv) + int argc; + char *argv[]; +{ + u_int addr; + u_int data; + + if (argc < 2) { + printf("Syntax: peek[bw] \n\r"); + return; + } + +/* Decode the one argument */ + + addr = readhex(argv[1]); + + if (argv[0][4] == 'b') + data = ReadByte(addr); + if (argv[0][4] == 'w') + data = ReadWord(addr); + + printf("%08x : %08x\n\r", addr, data); +} + + +/* dumpb - dumps memory in bytes*/ + +void +shell_dumpb(argc, argv) + int argc; + char *argv[]; +{ + u_char *addr; + int count; + + if (argc < 2) { + printf("Syntax: dumpb []\n\r"); + return; + } + +/* Decode the one argument */ + + addr = (u_char *)readhex(argv[1]); + + if (argc > 2) + count = readhex(argv[2]); + else + count = 0x80; + + dumpb(addr, count); +} + + +/* dumpw - dumps memory in bytes*/ + +void +shell_dumpw(argc, argv) + int argc; + char *argv[]; +{ + u_char *addr; + int count; + + if (argc < 2) { + printf("Syntax: dumpw []\n\r"); + return; + } + +/* Decode the one argument */ + + addr = (u_char *)readhex(argv[1]); + + if (argc > 2) + count = readhex(argv[2]); + else + count = 0x80; + + dumpw(addr, count); +} + + +/* vmmap - dumps the vmmap */ + +void +shell_vmmap(argc, argv) + int argc; + char *argv[]; +{ + u_char *addr; + + if (argc < 2) { + printf("Syntax: vmmap \n\r"); + return; + } + +/* Decode the one argument */ + + addr = (u_char *)readhex(argv[1]); + + debug_show_vm_map((vm_map_t)addr, argv[1]); +} + + +/* pmap - dumps the pmap */ + +void +shell_pmap(argc, argv) + int argc; + char *argv[]; +{ + u_char *addr; + + if (argc < 2) { + printf("Syntax: pmap \n\r"); + return; + } + +/* Decode the one argument */ + + addr = (u_char *)readhex(argv[1]); + + debug_show_pmap((pmap_t)addr); +} + + +/* + * void shell_devices(int argc, char *argv[]) + * + * Display all the devices + */ + +extern struct cfdata cfdata[]; + +void +shell_devices(argc, argv) + int argc; + char *argv[]; +{ + struct cfdata *cf; + struct cfdriver *cd; + struct device *dv; + int loop; + char *state; + + printf(" driver unit state name\n"); + for (cf = cfdata; cf->cf_driver; ++cf) { + cd = cf->cf_driver; + if (cf->cf_fstate & FSTATE_FOUND) + state = "FOUND "; + else + state = "NOT FOUND"; + + printf("%08x %2d %s %s\n", (u_int)cd, (u_int)cf->cf_unit, + state, cd->cd_name); + + if (cf->cf_fstate & FSTATE_FOUND) { + for (loop = 0; loop < cd->cd_ndevs; ++loop) { + dv = (struct device *)cd->cd_devs[loop]; + if (dv != 0) + printf(" %s (%08x)\n", + dv->dv_xname, (u_int) dv); + } + } + printf("\n"); + } +} + + +void +shell_reboot(argc, argv) + int argc; + char *argv[]; +{ + printf("Running shutdown hooks ...\n"); + doshutdownhooks(); + + IRQdisable; + boot0(); +} + +void +forceboot(argc, argv) + int argc; + char *argv[]; +{ + cmos_write(0x90, cmos_read(0x90) | 0x02); + shell_reboot(0, NULL); +} + + +void +shell_flush(argc, argv) + int argc; + char *argv[]; +{ + idcflush(); + tlbflush(); +} + + +void +shell_vmstat(argc, argv) + int argc; + char *argv[]; +{ + struct vmmeter sum; + + sum = cnt; + (void)printf("%9u cpu context switches\n", sum.v_swtch); + (void)printf("%9u device interrupts\n", sum.v_intr); + (void)printf("%9u software interrupts\n", sum.v_soft); + (void)printf("%9u traps\n", sum.v_trap); + (void)printf("%9u system calls\n", sum.v_syscall); + (void)printf("%9u total faults taken\n", sum.v_faults); + (void)printf("%9u swap ins\n", sum.v_swpin); + (void)printf("%9u swap outs\n", sum.v_swpout); + (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); + (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); + (void)printf("%9u page ins\n", sum.v_pageins); + (void)printf("%9u page outs\n", sum.v_pageouts); + (void)printf("%9u pages paged in\n", sum.v_pgpgin); + (void)printf("%9u pages paged out\n", sum.v_pgpgout); + (void)printf("%9u pages reactivated\n", sum.v_reactivated); + (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); + (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); + (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); + (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); + (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); + (void)printf("%9u VM object cache lookups\n", sum.v_lookups); + (void)printf("%9u VM object hits\n", sum.v_hits); + (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); + (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); + (void)printf("%9u pages freed by daemon\n", sum.v_dfree); + (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); + (void)printf("%9u pages free\n", sum.v_free_count); + (void)printf("%9u pages wired down\n", sum.v_wire_count); + (void)printf("%9u pages active\n", sum.v_active_count); + (void)printf("%9u pages inactive\n", sum.v_inactive_count); + (void)printf("%9u bytes per page\n", sum.v_page_size); +} + + +void +shell_pextract(argc, argv) + int argc; + char *argv[]; +{ + u_char *addr; + vm_offset_t pa; + int pind; + + if (argc < 2) { + printf("Syntax: pextract \n\r"); + return; + } + +/* Decode the one argument */ + + addr = (u_char *)readhex(argv[1]); + + pa = pmap_extract(kernel_pmap, (vm_offset_t)addr); + pind = pmap_page_index(pa); + + printf("va=%08x pa=%08x pind=%d\n", (u_int)addr, (u_int)pa, pind); +} + + +void +shell_vnode(argc, argv) + int argc; + char *argv[]; +{ + struct vnode *vp; + + if (argc < 2) { + printf("Syntax: vnode \n\r"); + return; + } + +/* Decode the one argument */ + + vp = (struct vnode *)readhex(argv[1]); + + printf("vp = %08x\n", (u_int)vp); + printf("vp->v_type = %d\n", vp->v_type); + printf("vp->v_flag = %ld\n", vp->v_flag); + printf("vp->v_usecount = %d\n", vp->v_usecount); + printf("vp->v_writecount = %d\n", vp->v_writecount); + printf("vp->v_numoutput = %ld\n", vp->v_numoutput); + + vprint("vnode:", vp); +} + +#if 0 +void +shell_vndbuf(argc, argv) + int argc; + char *argv[]; +{ + struct vnode *vp; + + if (argc < 2) { + printf("Syntax: vndbuf \n\r"); + return; + } + +/* Decode the one argument */ + + vp = (struct vnode *)readhex(argv[1]); + + dumpvndbuf(vp); +} + + +void +shell_vncbuf(argc, argv) + int argc; + char *argv[]; +{ + struct vnode *vp; + + if (argc < 2) { + printf("Syntax: vndbuf \n\r"); + return; + } + +/* Decode the one argument */ + + vp = (struct vnode *)readhex(argv[1]); + + dumpvncbuf(vp); +} +#endif + +/* shell - a crude shell */ + +int +shell() +{ + int quit = 0; + char buffer[200]; + char *ptr; + char *ptr1; + int args; + char *argv[20]; + + printf("\nRiscBSD debug/monitor shell\n"); + printf("CTRL-D, exit or reboot to terminate\n\n"); + + do { +/* print prompt */ + + printf("kshell> "); + +/* Read line from keyboard */ + + if (readstring(buffer, 200, NULL, NULL) == -1) + return(0); + + ptr = buffer; + +/* Slice leading spaces */ + + while (*ptr == ' ') + ++ptr; + +/* Loop back if zero length string */ + + if (*ptr == 0) + continue; + +/* Count the number of space separated args */ + + args = 0; + ptr1 = ptr; + + while (*ptr1 != 0) { + if (*ptr1 == ' ') { + ++args; + while (*ptr1 == ' ') + ++ptr1; + } else + ++ptr1; + } + +/* + * Construct the array of pointers to the args and terminate + * each argument with 0x00 + */ + + args = 0; + ptr1 = ptr; + + while (*ptr1 != 0) { + argv[args] = ptr1; + ++args; + while (*ptr1 != ' ' && *ptr1 != 0) + ++ptr1; + + while (*ptr1 == ' ') { + *ptr1 = 0; + ++ptr1; + } + } + + argv[args] = NULL; + +/* Interpret commands */ + + if (strcmp(argv[0], "exit") == 0) + quit = 1; +#ifdef DDB + else if (strcmp(argv[0], "deb") == 0) + Debugger(); +#endif + else if (strcmp(argv[0], "peekb") == 0) + shell_peek(args, argv); + else if (strcmp(argv[0], "pokeb") == 0) + shell_poke(args, argv); + else if (strcmp(argv[0], "peekw") == 0) + shell_peek(args, argv); + else if (strcmp(argv[0], "pokew") == 0) + shell_poke(args, argv); + else if (strcmp(argv[0], "dumpb") == 0) + shell_dumpb(args, argv); + else if (strcmp(argv[0], "reboot") == 0) + shell_reboot(args, argv); + else if (strcmp(argv[0], "dumpw") == 0) + shell_dumpw(args, argv); + else if (strcmp(argv[0], "dump") == 0) + shell_dumpw(args, argv); + else if (strcmp(argv[0], "dis") == 0) + shell_disassem(args, argv); + else if (strcmp(argv[0], "qs") == 0) + debug_show_q_details(); + else if (strcmp(argv[0], "ps") == 0) + debug_show_all_procs(args, argv); + else if (strcmp(argv[0], "callouts") == 0) + debug_show_callout(args, argv); + else if (strcmp(argv[0], "devices") == 0) + shell_devices(args, argv); + else if (strcmp(argv[0], "listfs") == 0) + debug_show_fs(args, argv); + else if (strcmp(argv[0], "vmmap") == 0) + shell_vmmap(args, argv); + else if (strcmp(argv[0], "pmap") == 0) + shell_pmap(args, argv); + else if (strcmp(argv[0], "flush") == 0) + shell_flush(args, argv); + else if (strcmp(argv[0], "vmstat") == 0) + shell_vmstat(args, argv); + else if (strcmp(argv[0], "pdstat") == 0) + pmap_pagedir_dump(); + else if (strcmp(argv[0], "traceback") == 0) + traceback(); + else if (strcmp(argv[0], "forceboot") == 0) + forceboot(args, argv); + else if (strcmp(argv[0], "dumppvs") == 0) + pmap_dump_pvs(); + else if (strcmp(argv[0], "pextract") == 0) + shell_pextract(args, argv); + else if (strcmp(argv[0], "vnode") == 0) + shell_vnode(args, argv); + else if (strcmp(argv[0], "ascdump") == 0) + asc_dump(); + else if (strcmp(argv[0], "help") == 0 + || strcmp(argv[0], "?") == 0) { + printf("peekb \r\n"); + printf("pokeb \r\n"); + printf("peekw \r\n"); + printf("pokew \r\n"); + printf("dis \r\n"); + printf("dumpb [length]\r\n"); + printf("dumpw [length]\r\n"); + printf("dump [length]\r\n"); + printf("reboot\r\n"); + printf("qs\r\n"); + printf("ps [m]\r\n"); + printf("vmstat\n"); + printf("listfs\n"); + printf("devices\n"); + printf("callouts\n"); + printf("prompt\r\n"); + printf("vmmap \r\n"); + printf("pmap \r\n"); + printf("pdstat\r\n"); + printf("flush\r\n"); + printf("exit\r\n"); + printf("forceboot\r\n"); + printf("dumppvs\r\n"); + printf("pextract \r\n"); + printf("vnode \r\n"); + printf("ascdump\r\n"); + } + } while (!quit); + + return(0); +} + +/* End of shell_shell.c */ diff --git a/sys/arch/arm32/kshell/strchr.c b/sys/arch/arm32/kshell/strchr.c new file mode 100644 index 00000000000..8caae137277 --- /dev/null +++ b/sys/arch/arm32/kshell/strchr.c @@ -0,0 +1,49 @@ +/* $NetBSD: strchr.c,v 1.2 1996/03/18 20:32:34 mark Exp $ */ + +/* + * Copyright (c) 1994 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 kernel team. + * 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 + +char * +strchr(s, c) + register char *s; + int c; +{ + do { + if (*s == c) { + return (s); + } + } while (*s++); + return (0); +} + +/* End of strchr.c */ diff --git a/sys/arch/arm32/mainbus/beep.c b/sys/arch/arm32/mainbus/beep.c new file mode 100644 index 00000000000..762830309f5 --- /dev/null +++ b/sys/arch/arm32/mainbus/beep.c @@ -0,0 +1,369 @@ +/* $NetBSD: beep.c,v 1.4 1996/03/27 22:08:36 mark Exp $ */ + +/* + * Copyright (c) 1995 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 RiscBSD team. + * 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. + */ + +/* + * Simple beep sounds using VIDC + */ + +/* + * To use the driver, open /dev/beep and write lines. + * Each write will generate a beep + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "beep.h" + +struct beep_softc { + struct device sc_device; + irqhandler_t sc_ih; + int sc_iobase; + int sc_open; + int sc_count; + u_int sc_sound_cur0; + u_int sc_sound_end0; + u_int sc_sound_cur1; + u_int sc_sound_end1; + vm_offset_t sc_buffer0; + vm_offset_t sc_buffer1; +}; + +int beepprobe __P((struct device *parent, void *match, void *aux)); +void beepattach __P((struct device *parent, struct device *self, void *aux)); +int beepopen __P((dev_t, int, int, struct proc *)); +int beepclose __P((dev_t, int, int, struct proc *)); +int beepintr __P((struct beep_softc *sc)); +void beepdma __P((struct beep_softc *sc, int buf)); + +struct cfattach beep_ca = { + sizeof(struct beep_softc), beepprobe, beepattach +}; + +struct cfdriver beep_cd = { + NULL, "beep", DV_TTY +}; + + +int +beepprobe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ +/* struct mainbus_attach_args *mb = aux;*/ + int id; + +/* Make sure we have an IOMD we understand */ + + id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8); + +/* So far I only know about this IOMD */ + + switch (id) { + case RPC600_IOMD_ID: + return(1); + break; + default: + printf("beep: Unknown IOMD id=%04x", id); + break; + } + return(0); +} + + +void +beepattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct beep_softc *sc = (void *)self; + struct mainbus_attach_args *mb = aux; + + sc->sc_iobase = mb->mb_iobase; + sc->sc_open = 0; + sc->sc_count = 0; + + sc->sc_buffer0 = kmem_alloc(kernel_map, NBPG); + if (sc->sc_buffer0 == 0) + panic("beep: Cannot allocate buffer memory\n"); + if ((sc->sc_buffer0 & (NBPG -1)) != 0) + panic("beep: Cannot allocate page aligned buffer\n"); + sc->sc_buffer1 = sc->sc_buffer0; + + sc->sc_sound_cur0 = pmap_extract(kernel_pmap, + (vm_offset_t)sc->sc_buffer0 & PG_FRAME); + sc->sc_sound_end0 = (sc->sc_sound_cur0 + NBPG - 16) | 0x00000000; + sc->sc_sound_cur1 = pmap_extract(kernel_pmap, + (vm_offset_t)sc->sc_buffer1 & PG_FRAME); + sc->sc_sound_end1 = (sc->sc_sound_cur1 + NBPG - 16) | 0x00000000; + + bcopy(beep_waveform, (void *)sc->sc_buffer0, sizeof(beep_waveform)); + +/* Reset the sound DMA channel */ + + WriteWord(IOMD_SD0CURA, sc->sc_sound_cur0); + WriteWord(IOMD_SD0ENDA, sc->sc_sound_end0 | 0xc0000000); + WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1); + WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | 0xc0000000); + + WriteByte(IOMD_SD0CR, 0x90); + +/* Install an IRQ handler */ + + sc->sc_ih.ih_func = beepintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_NONE; + sc->sc_ih.ih_name = "dma snd ch 0"; + + if (irq_claim(IRQ_DMASCH0, &sc->sc_ih)) + panic("Cannot claim DMASCH0 IRQ for beep%d\n", parent->dv_unit); + + disable_irq(IRQ_DMASCH0); + +/* + printf(" [ buf0=%08x:%08x->%08x buf1=%08x:%08x->%08x ]", + (u_int)sc->sc_buffer0, sc->sc_sound_cur0, sc->sc_sound_end0, + (u_int)sc->sc_buffer1, sc->sc_sound_cur1, sc->sc_sound_end1); +*/ + printf("\n"); + +/* Set sample rate to 32us */ + + WriteWord(VIDC_BASE, VIDC_SFR | 32); + +/* Set the stereo postions to centred for all channels */ + + WriteWord(VIDC_BASE, VIDC_SIR0 | SIR_CENTRE); + WriteWord(VIDC_BASE, VIDC_SIR1 | SIR_CENTRE); + WriteWord(VIDC_BASE, VIDC_SIR2 | SIR_CENTRE); + WriteWord(VIDC_BASE, VIDC_SIR3 | SIR_CENTRE); + WriteWord(VIDC_BASE, VIDC_SIR4 | SIR_CENTRE); + WriteWord(VIDC_BASE, VIDC_SIR5 | SIR_CENTRE); + WriteWord(VIDC_BASE, VIDC_SIR6 | SIR_CENTRE); + WriteWord(VIDC_BASE, VIDC_SIR7 | SIR_CENTRE); +} + + +int +beepopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct beep_softc *sc; + int unit = minor(dev); + int s; + + if (unit >= beep_cd.cd_ndevs) + return(ENXIO); + + sc = beep_cd.cd_devs[unit]; + if (!sc) return(ENXIO); + +/* HACK hack hack */ + + s = splhigh(); + if (sc->sc_open) { + (void)splx(s); + return(EBUSY); + } + + ++sc->sc_open; + (void)splx(s); + + return(0); +} + + +int +beepclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + int unit = minor(dev); + struct beep_softc *sc = beep_cd.cd_devs[unit]; + int s; + + if (sc->sc_open == 0) return(ENXIO); + +/* HACK hack hack */ + + s = splhigh(); + --sc->sc_open; + (void)splx(s); + + return(0); +} + + +void +beep_generate(void) +{ + struct beep_softc *sc = beep_cd.cd_devs[0]; +/* int status;*/ + + if (sc->sc_count > 0) { +/* printf("beep: active\n");*/ + return; + } +/* printf("beep: generate ");*/ + ++sc->sc_count; + +/* status = ReadByte(IOMD_SD0ST); + printf("st=%02x\n", status);*/ + WriteByte(IOMD_SD0CR, 0x90); + WriteByte(IOMD_SD0CR, 0x30); + beepdma(sc, 0); +} + + +int +beepioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct beep_softc *sc = beep_cd.cd_devs[minor(dev)]; + int rate; + struct wavebuffer *wave = (struct wavebuffer *)data; + + switch (cmd) { + case BEEP_GENERATE: + beep_generate(); + break; + + case BEEP_SETRATE: + rate = *(int *)data; + + if (rate < 3 || rate > 255) + return(EINVAL); + + WriteWord(VIDC_BASE, VIDC_SFR | rate); + break; + + case BEEP_SET: + printf("set %08x\n", (u_int)data); + printf("set %08x %08x\n", (u_int)wave->addr, wave->size); + if (wave->size < 16 || wave->size > NBPG) + return(ENXIO); + copyin(wave->addr, (char *)sc->sc_buffer0, wave->size); + sc->sc_sound_end0 = (sc->sc_sound_cur0 + wave->size - 16); + sc->sc_sound_end1 = (sc->sc_sound_cur1 + wave->size - 16); + break; + + default: + return(ENXIO); + break; + } + + return(0); +} + + +int +beepintr(sc) + struct beep_softc *sc; +{ +/* printf("beepintr: %02x,%02x,%02x,%d\n", ReadByte(IOMD_DMARQ), + ReadByte(IOMD_SD0CR), ReadByte(IOMD_SD0ST), sc->sc_count);*/ + WriteByte(IOMD_DMARQ, 0x10); + --sc->sc_count; + if (sc->sc_count <= 0) { + WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1); + WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30)); + disable_irq(IRQ_DMASCH0); +/* printf("stop:st=%02x\n", ReadByte(IOMD_SD0ST));*/ + return(1); + } + + beepdma(sc, sc->sc_count & 1); + return(1); +} + + +void +beepdma(sc, buf) + struct beep_softc *sc; + int buf; +{ + int status; +/* printf("beep:dma %d", buf); */ + status = ReadByte(IOMD_SD0ST); +/* printf("st=%02x\n", status);*/ + + if (buf == 0) { + WriteWord(IOMD_SD0CURA, sc->sc_sound_cur0); + WriteWord(IOMD_SD0ENDA, sc->sc_sound_end0); + WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1); + WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30)); + } + + if (buf == 1) { + WriteWord(IOMD_SD0CURB, sc->sc_sound_cur1); + WriteWord(IOMD_SD0ENDB, sc->sc_sound_end1 | (1 << 30)); + } + +/* status = ReadByte(IOMD_SD0ST); + printf("st=%02x\n", status);*/ + + enable_irq(IRQ_DMASCH0); +} + +/* End of beep.c */ diff --git a/sys/arch/arm32/mainbus/com.c b/sys/arch/arm32/mainbus/com.c new file mode 100644 index 00000000000..ee9b812f796 --- /dev/null +++ b/sys/arch/arm32/mainbus/com.c @@ -0,0 +1,1034 @@ +/* $NetBSD: com.c,v 1.5 1996/03/28 21:52:32 mark Exp $ */ + +/*- + * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1991 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. + * + * @(#)com.c 7.5 (Berkeley) 5/16/91 + */ + +/* + * COM driver, based on HP dca driver + * uses National Semiconductor NS16450/NS16550AF UART + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define com_lcr com_cfcr + +#define COM_IBUFSIZE (2 * 256) +#define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4) + +struct com_softc { + struct device sc_dev; + irqhandler_t sc_ih; + struct tty *sc_tty; + + int sc_overflows; + int sc_floods; + int sc_errors; + + int sc_iobase; + u_char sc_hwflags; +#define COM_HW_NOIEN 0x01 +#define COM_HW_FIFO 0x02 +#define COM_HW_CONSOLE 0x40 + u_char sc_swflags; +#define COM_SW_SOFTCAR 0x01 +#define COM_SW_CLOCAL 0x02 +#define COM_SW_CRTSCTS 0x04 +#define COM_SW_MDMBUF 0x08 + u_char sc_msr, sc_mcr, sc_lcr; + u_char sc_dtr; + + u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend; + u_char sc_ibufs[2][COM_IBUFSIZE]; +}; + +int comprobe __P((struct device *, void *, void *)); +void comattach __P((struct device *, struct device *, void *)); +int comopen __P((dev_t, int, int, struct proc *)); +int comclose __P((dev_t, int, int, struct proc *)); +void comdiag __P((void *)); +int comintr __P((void *)); +void compoll __P((void *)); +int comparam __P((struct tty *, struct termios *)); +void comstart __P((struct tty *)); + +struct cfattach com_ca = { + sizeof(struct com_softc), comprobe, comattach +}; + +struct cfdriver com_cd = { + NULL, "com", DV_TTY +}; + +int comdefaultrate = TTYDEF_SPEED; +#ifdef COMCONSOLE +int comconsole = COMCONSOLE; +#else +int comconsole = -1; +#endif +int comconsinit; +int commajor; +int comsopen = 0; +int comevents = 0; + +#ifdef KGDB +#include +extern int kgdb_dev; +extern int kgdb_rate; +extern int kgdb_debug_init; +#endif + +#define COMUNIT(x) (minor(x)) + +/* Macros to clear/set/test flags. */ +#define SET(t, f) (t) |= (f) +#define CLR(t, f) (t) &= ~(f) +#define ISSET(t, f) ((t) & (f)) + +int +comspeed(speed) + long speed; +{ +#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ + + int x, err; + + if (speed == 0) + return 0; + if (speed < 0) + return -1; + x = divrnd((COM_FREQ / 16), speed); + if (x <= 0) + return -1; + err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000; + if (err < 0) + err = -err; + if (err > COM_TOLERANCE) + return -1; + return x; + +#undef divrnd(n, q) +} + +int +comprobe1(iobase) + int iobase; +{ + + /* force access to id reg */ + outb(iobase + com_lcr, 0); + outb(iobase + com_iir, 0); + if (inb(iobase + com_iir) & 0x38) + return 0; + + return 1; +} + +int +comprobe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct mainbus_attach_args *mb = aux; + int iobase = mb->mb_iobase; + + if (!comprobe1(iobase)) + return 0; + + mb->mb_iosize = COM_NPORTS; + return 1; +} + +void +comattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct com_softc *sc = (void *)self; + struct mainbus_attach_args *mb = aux; + struct cfdata *cf = sc->sc_dev.dv_cfdata; + int iobase = mb->mb_iobase; + struct tty *tp; + + sc->sc_iobase = iobase; + sc->sc_hwflags = ISSET(cf->cf_flags, COM_HW_NOIEN); + sc->sc_swflags = 0; + + if (sc->sc_dev.dv_unit == comconsole) + delay(1000); + + /* look for a NS 16550AF UART with FIFOs */ + outb(iobase + com_fifo, + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14); + delay(100); + if (ISSET(inb(iobase + com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK) + if (ISSET(inb(iobase + com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) { + SET(sc->sc_hwflags, COM_HW_FIFO); + printf(": ns16550a, working fifo\n"); + } else + printf(": ns16550, broken fifo\n"); + else + printf(": ns8250 or ns16450, no fifo\n"); + outb(iobase + com_fifo, 0); + + /* disable interrupts */ + outb(iobase + com_ier, 0); + outb(iobase + com_mcr, 0); + + sc->sc_ih.ih_func = comintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_TTY; + sc->sc_ih.ih_name = "serial"; + if (mb->mb_irq != IRQUNK) + if (irq_claim(mb->mb_irq, &sc->sc_ih)) + panic("Cannot claim IRQ %d for com%d\n", mb->mb_irq, sc->sc_dev.dv_unit); + +#ifdef KGDB + if (kgdb_dev == makedev(commajor, unit)) { + if (comconsole == unit) + kgdb_dev = -1; /* can't debug over console port */ + else { + (void) cominit(unit, kgdb_rate); + if (kgdb_debug_init) { + /* + * Print prefix of device name, + * let kgdb_connect print the rest. + */ + printf("%s: ", sc->sc_dev.dv_xname); + kgdb_connect(1); + } else + printf("%s: kgdb enabled\n", + sc->sc_dev.dv_xname); + } + } +#endif + + if (sc->sc_dev.dv_unit == comconsole) { + /* + * Need to reset baud rate, etc. of next print so reset + * comconsinit. Also make sure console is always "hardwired". + */ + comconsinit = 0; + SET(sc->sc_hwflags, COM_HW_CONSOLE); + SET(sc->sc_swflags, COM_SW_SOFTCAR); + } +} + +int +comopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = COMUNIT(dev); + struct com_softc *sc; + int iobase; + struct tty *tp; + int s; + int error = 0; + + if (unit >= com_cd.cd_ndevs) + return ENXIO; + sc = com_cd.cd_devs[unit]; + if (!sc) + return ENXIO; + + if (!sc->sc_tty) + tp = sc->sc_tty = ttymalloc(); + else + tp = sc->sc_tty; + + tp->t_oproc = comstart; + tp->t_param = comparam; + tp->t_dev = dev; + if (!ISSET(tp->t_state, TS_ISOPEN)) { + SET(tp->t_state, TS_WOPEN); + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG; + if (ISSET(sc->sc_swflags, COM_SW_CLOCAL)) + SET(tp->t_cflag, CLOCAL); + if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS)) + SET(tp->t_cflag, CRTSCTS); + if (ISSET(sc->sc_swflags, COM_SW_MDMBUF)) + SET(tp->t_cflag, MDMBUF); + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = comdefaultrate; + + s = spltty(); + + comparam(tp, &tp->t_termios); + ttsetwater(tp); + + if (comsopen++ == 0) + timeout(compoll, NULL, 1); + + sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0]; + sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; + sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; + + iobase = sc->sc_iobase; + /* Set the FIFO threshold based on the receive speed. */ + if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) + outb(iobase + com_fifo, + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | + (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); + /* flush any pending I/O */ + while (ISSET(inb(iobase + com_lsr), LSR_RXRDY)) + (void) inb(iobase + com_data); + /* you turn me on, baby */ + sc->sc_mcr = MCR_DTR | MCR_RTS; + if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN)) + SET(sc->sc_mcr, MCR_IENABLE); + outb(iobase + com_mcr, sc->sc_mcr); + outb(iobase + com_ier, + IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC); + + sc->sc_msr = inb(iobase + com_msr); + if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || + ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF)) + SET(tp->t_state, TS_CARR_ON); + else + CLR(tp->t_state, TS_CARR_ON); + } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) + return EBUSY; + else + s = spltty(); + + /* wait for carrier if necessary */ + if (!ISSET(flag, O_NONBLOCK)) + while (!ISSET(tp->t_cflag, CLOCAL) && + !ISSET(tp->t_state, TS_CARR_ON)) { + SET(tp->t_state, TS_WOPEN); + error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, + ttopen, 0); + if (error) { + /* XXX should turn off chip if we're the + only waiter */ + splx(s); + return error; + } + } + splx(s); + + return (*linesw[tp->t_line].l_open)(dev, tp); +} + +int +comclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = COMUNIT(dev); + struct com_softc *sc = com_cd.cd_devs[unit]; + struct tty *tp = sc->sc_tty; + int iobase = sc->sc_iobase; + int s; + + /* XXX This is for cons.c. */ + if (!ISSET(tp->t_state, TS_ISOPEN)) + return 0; + + (*linesw[tp->t_line].l_close)(tp, flag); + s = spltty(); + CLR(sc->sc_lcr, LCR_SBREAK); + outb(iobase + com_lcr, sc->sc_lcr); + outb(iobase + com_ier, 0); + if (ISSET(tp->t_cflag, HUPCL) && + !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { + /* XXX perhaps only clear DTR */ + outb(iobase + com_mcr, 0); + } + CLR(tp->t_state, TS_BUSY | TS_FLUSH); + if (--comsopen == 0) + untimeout(compoll, NULL); + splx(s); + ttyclose(tp); +#ifdef notyet /* XXXX */ + if (unit != comconsole) { + ttyfree(tp); + sc->sc_tty = 0; + } +#endif + return 0; +} + +int +comread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +comwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +struct tty * +comtty(dev) + dev_t dev; +{ + struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)]; + struct tty *tp = sc->sc_tty; + + return (tp); +} + +static u_char +tiocm_xxx2mcr(data) + int data; +{ + u_char m = 0; + + if (ISSET(data, TIOCM_DTR)) + SET(m, MCR_DTR); + if (ISSET(data, TIOCM_RTS)) + SET(m, MCR_RTS); + return m; +} + +int +comioctl(dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + int unit = COMUNIT(dev); + struct com_softc *sc = com_cd.cd_devs[unit]; + struct tty *tp = sc->sc_tty; + int iobase = sc->sc_iobase; + int error; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return error; + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return error; + + switch (cmd) { + case TIOCSBRK: + SET(sc->sc_lcr, LCR_SBREAK); + outb(iobase + com_lcr, sc->sc_lcr); + break; + case TIOCCBRK: + CLR(sc->sc_lcr, LCR_SBREAK); + outb(iobase + com_lcr, sc->sc_lcr); + break; + case TIOCSDTR: + SET(sc->sc_mcr, sc->sc_dtr); + outb(iobase + com_mcr, sc->sc_mcr); + break; + case TIOCCDTR: + CLR(sc->sc_mcr, sc->sc_dtr); + outb(iobase + com_mcr, sc->sc_mcr); + break; + case TIOCMSET: + CLR(sc->sc_mcr, MCR_DTR | MCR_RTS); + case TIOCMBIS: + SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); + outb(iobase + com_mcr, sc->sc_mcr); + break; + case TIOCMBIC: + CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data)); + outb(iobase + com_mcr, sc->sc_mcr); + break; + case TIOCMGET: { + u_char m; + int bits = 0; + + m = sc->sc_mcr; + if (ISSET(m, MCR_DTR)) + SET(bits, TIOCM_DTR); + if (ISSET(m, MCR_RTS)) + SET(bits, TIOCM_RTS); + m = sc->sc_msr; + if (ISSET(m, MSR_DCD)) + SET(bits, TIOCM_CD); + if (ISSET(m, MSR_CTS)) + SET(bits, TIOCM_CTS); + if (ISSET(m, MSR_DSR)) + SET(bits, TIOCM_DSR); + if (ISSET(m, MSR_RI | MSR_TERI)) + SET(bits, TIOCM_RI); + if (inb(iobase + com_ier)) + SET(bits, TIOCM_LE); + *(int *)data = bits; + break; + } + case TIOCGFLAGS: { + int driverbits, userbits = 0; + + driverbits = sc->sc_swflags; + if (ISSET(driverbits, COM_SW_SOFTCAR)) + SET(userbits, TIOCFLAG_SOFTCAR); + if (ISSET(driverbits, COM_SW_CLOCAL)) + SET(userbits, TIOCFLAG_CLOCAL); + if (ISSET(driverbits, COM_SW_CRTSCTS)) + SET(userbits, TIOCFLAG_CRTSCTS); + if (ISSET(driverbits, COM_SW_MDMBUF)) + SET(userbits, TIOCFLAG_MDMBUF); + + *(int *)data = userbits; + break; + } + case TIOCSFLAGS: { + int userbits, driverbits = 0; + + error = suser(p->p_ucred, &p->p_acflag); + if (error != 0) + return(EPERM); + + userbits = *(int *)data; + if (ISSET(userbits, TIOCFLAG_SOFTCAR) || + ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) + SET(driverbits, COM_SW_SOFTCAR); + if (ISSET(userbits, TIOCFLAG_CLOCAL)) + SET(driverbits, COM_SW_CLOCAL); + if (ISSET(userbits, TIOCFLAG_CRTSCTS)) + SET(driverbits, COM_SW_CRTSCTS); + if (ISSET(userbits, TIOCFLAG_MDMBUF)) + SET(driverbits, COM_SW_MDMBUF); + + sc->sc_swflags = driverbits; + break; + } + default: + return ENOTTY; + } + + return 0; +} + +int +comparam(tp, t) + struct tty *tp; + struct termios *t; +{ + struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)]; + int iobase = sc->sc_iobase; + int ospeed = comspeed(t->c_ospeed); + u_char lcr; + tcflag_t oldcflag; + int s; + + /* check requested parameters */ + if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) + return EINVAL; + + lcr = sc->sc_lcr & LCR_SBREAK; + + switch (ISSET(t->c_cflag, CSIZE)) { + case CS5: + SET(lcr, LCR_5BITS); + break; + case CS6: + SET(lcr, LCR_6BITS); + break; + case CS7: + SET(lcr, LCR_7BITS); + break; + case CS8: + SET(lcr, LCR_8BITS); + break; + } + if (ISSET(t->c_cflag, PARENB)) { + SET(lcr, LCR_PENAB); + if (!ISSET(t->c_cflag, PARODD)) + SET(lcr, LCR_PEVEN); + } + if (ISSET(t->c_cflag, CSTOPB)) + SET(lcr, LCR_STOPB); + + sc->sc_lcr = lcr; + + s = spltty(); + + if (ospeed == 0) { + CLR(sc->sc_mcr, MCR_DTR); + outb(iobase + com_mcr, sc->sc_mcr); + } + + /* + * Set the FIFO threshold based on the receive speed, if we are + * changing it. + */ + if (tp->t_ispeed != t->c_ispeed) { + if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) + outb(iobase + com_fifo, + FIFO_ENABLE | + (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); + } + + if (ospeed != 0) { + outb(iobase + com_lcr, lcr | LCR_DLAB); + outb(iobase + com_dlbl, ospeed); + outb(iobase + com_dlbh, ospeed >> 8); + outb(iobase + com_lcr, lcr); + SET(sc->sc_mcr, MCR_DTR); + outb(iobase + com_mcr, sc->sc_mcr); + } else + outb(iobase + com_lcr, lcr); + + /* When not using CRTSCTS, RTS follows DTR. */ + if (!ISSET(t->c_cflag, CRTSCTS)) { + if (ISSET(sc->sc_mcr, MCR_DTR)) { + if (!ISSET(sc->sc_mcr, MCR_RTS)) { + SET(sc->sc_mcr, MCR_RTS); + outb(iobase + com_mcr, sc->sc_mcr); + } + } else { + if (ISSET(sc->sc_mcr, MCR_RTS)) { + CLR(sc->sc_mcr, MCR_RTS); + outb(iobase + com_mcr, sc->sc_mcr); + } + } + sc->sc_dtr = MCR_DTR | MCR_RTS; + } else + sc->sc_dtr = MCR_DTR; + + /* and copy to tty */ + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + oldcflag = tp->t_cflag; + tp->t_cflag = t->c_cflag; + + /* + * If DCD is off and MDMBUF is changed, ask the tty layer if we should + * stop the device. + */ + if (!ISSET(sc->sc_msr, MSR_DCD) && + !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && + ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) && + (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { + CLR(sc->sc_mcr, sc->sc_dtr); + outb(iobase + com_mcr, sc->sc_mcr); + } + + splx(s); + return 0; +} + +void +comstart(tp) + struct tty *tp; +{ + struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)]; + int iobase = sc->sc_iobase; + int s; + + s = spltty(); + if (ISSET(tp->t_state, TS_TTSTOP | TS_BUSY)) + goto out; + if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS)) + goto out; + if (tp->t_outq.c_cc <= tp->t_lowat) { + if (ISSET(tp->t_state, TS_ASLEEP)) { + CLR(tp->t_state, TS_ASLEEP); + wakeup(&tp->t_outq); + } + if (tp->t_outq.c_cc == 0) + goto out; + selwakeup(&tp->t_wsel); + } + SET(tp->t_state, TS_BUSY); + if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { + u_char buffer[16], *cp = buffer; + int n = q_to_b(&tp->t_outq, cp, sizeof buffer); + do { + outb(iobase + com_data, *cp++); + } while (--n); + } else + outb(iobase + com_data, getc(&tp->t_outq)); +out: + splx(s); +} + +/* + * Stop output on a line. + */ +void +comstop(tp, flag) + struct tty *tp; +{ + int s; + + s = spltty(); + if (ISSET(tp->t_state, TS_BUSY)) + if (!ISSET(tp->t_state, TS_TTSTOP)) + SET(tp->t_state, TS_FLUSH); + splx(s); +} + +void +comdiag(arg) + void *arg; +{ + struct com_softc *sc = arg; + int overflows, floods; + int s; + + s = spltty(); + sc->sc_errors = 0; + overflows = sc->sc_overflows; + sc->sc_overflows = 0; + floods = sc->sc_floods; + sc->sc_floods = 0; + splx(s); + + log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n", + sc->sc_dev.dv_xname, + overflows, overflows == 1 ? "" : "s", + floods, floods == 1 ? "" : "s"); +} + +void +compoll(arg) + void *arg; +{ + int unit; + struct com_softc *sc; + struct tty *tp; + register u_char *ibufp; + u_char *ibufend; + register int c; + int s; + static int lsrmap[8] = { + 0, TTY_PE, + TTY_FE, TTY_PE|TTY_FE, + TTY_FE, TTY_PE|TTY_FE, + TTY_FE, TTY_PE|TTY_FE + }; + + s = spltty(); + if (comevents == 0) { + splx(s); + goto out; + } + comevents = 0; + splx(s); + + for (unit = 0; unit < com_cd.cd_ndevs; unit++) { + sc = com_cd.cd_devs[unit]; + if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf) + continue; + + tp = sc->sc_tty; + + s = spltty(); + + ibufp = sc->sc_ibuf; + ibufend = sc->sc_ibufp; + + if (ibufp == ibufend) { + splx(s); + continue; + } + + sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ? + sc->sc_ibufs[1] : sc->sc_ibufs[0]; + sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER; + sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; + + if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) { + splx(s); + continue; + } + + if (ISSET(tp->t_cflag, CRTSCTS) && + !ISSET(sc->sc_mcr, MCR_RTS)) { + /* XXX */ + SET(sc->sc_mcr, MCR_RTS); + outb(sc->sc_iobase + com_mcr, sc->sc_mcr); + } + + splx(s); + + while (ibufp < ibufend) { + c = *ibufp++; + if (*ibufp & LSR_OE) { + sc->sc_overflows++; + if (sc->sc_errors++ == 0) + timeout(comdiag, sc, 60 * hz); + } + /* This is ugly, but fast. */ + c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2]; + (*linesw[tp->t_line].l_rint)(c, tp); + } + } + +out: + timeout(compoll, NULL, 1); +} + +int +comintr(arg) + void *arg; +{ + struct com_softc *sc = arg; + int iobase = sc->sc_iobase; + struct tty *tp; + u_char lsr, data, msr, delta; + + if (ISSET(inb(iobase + com_iir), IIR_NOPEND)) + return (0); + + tp = sc->sc_tty; + + for (;;) { + lsr = inb(iobase + com_lsr); + + if (ISSET(lsr, LSR_RCV_MASK)) { + register u_char *p = sc->sc_ibufp; + + comevents = 1; + do { + data = ISSET(lsr, LSR_RXRDY) ? + inb(iobase + com_data) : 0; + if (ISSET(lsr, LSR_BI)) { +#ifdef DDB + if (sc->sc_dev.dv_unit == comconsole) { + Debugger(); + goto next; + } +#endif + data = '\0'; + } + if (p >= sc->sc_ibufend) { + sc->sc_floods++; + if (sc->sc_errors++ == 0) + timeout(comdiag, sc, 60 * hz); + } else { + *p++ = data; + *p++ = lsr; + if (p == sc->sc_ibufhigh && + ISSET(tp->t_cflag, CRTSCTS)) { + /* XXX */ + CLR(sc->sc_mcr, MCR_RTS); + outb(iobase + com_mcr, + sc->sc_mcr); + } + } + next: + lsr = inb(iobase + com_lsr); + } while (ISSET(lsr, LSR_RCV_MASK)); + + sc->sc_ibufp = p; + } +#if 0 + else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE)) + printf("weird lsr %02x\n", lsr); +#endif + + msr = inb(iobase + com_msr); + + if (msr != sc->sc_msr) { + delta = msr ^ sc->sc_msr; + sc->sc_msr = msr; + if (ISSET(delta, MSR_DCD) && + !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) && + (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) { + CLR(sc->sc_mcr, sc->sc_dtr); + outb(iobase + com_mcr, sc->sc_mcr); + } + if (ISSET(delta & msr, MSR_CTS) && + ISSET(tp->t_cflag, CRTSCTS)) { + /* the line is up and we want to do rts/cts flow control */ + (*linesw[tp->t_line].l_start)(tp); + } + } + + if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) { + CLR(tp->t_state, TS_BUSY); + if (ISSET(tp->t_state, TS_FLUSH)) + CLR(tp->t_state, TS_FLUSH); + else + (*linesw[tp->t_line].l_start)(tp); + } + + if (ISSET(inb(iobase + com_iir), IIR_NOPEND)) + return (1); + } +} + +/* + * Following are all routines needed for COM to act as console + */ +#include + +void +comcnprobe(cp) + struct consdev *cp; +{ + + if (!comprobe1(CONADDR)) { + cp->cn_pri = CN_DEAD; + return; + } + + /* locate the major number */ + for (commajor = 0; commajor < nchrdev; commajor++) + if (cdevsw[commajor].d_open == comopen) + break; + + /* initialize required fields */ + cp->cn_dev = makedev(commajor, CONUNIT); +#ifdef COMCONSOLE + cp->cn_pri = CN_REMOTE; /* Force a serial port console */ +#else + cp->cn_pri = CN_NORMAL; +#endif +} + +void +comcninit(cp) + struct consdev *cp; +{ + + cominit(CONUNIT, comdefaultrate); + comconsole = CONUNIT; + comconsinit = 0; +} + +cominit(unit, rate) + int unit, rate; +{ + int s = splhigh(); + int iobase = CONADDR; + u_char stat; + + outb(iobase + com_lcr, LCR_DLAB); + rate = comspeed(comdefaultrate); + outb(iobase + com_dlbl, rate); + outb(iobase + com_dlbh, rate >> 8); + outb(iobase + com_lcr, LCR_8BITS); + outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY); + outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4); + stat = inb(iobase + com_iir); + splx(s); +} + +comcngetc(dev) + dev_t dev; +{ + int s = splhigh(); + int iobase = CONADDR; + u_char stat, c; + + while (!ISSET(stat = inb(iobase + com_lsr), LSR_RXRDY)) + ; + c = inb(iobase + com_data); + stat = inb(iobase + com_iir); + splx(s); + return c; +} + +/* + * Console kernel output character routine. + */ +void +comcnputc(dev, c) + dev_t dev; + int c; +{ + int s = splhigh(); + int iobase = CONADDR; + u_char stat; + register int timo; + +#ifdef KGDB + if (dev != kgdb_dev) +#endif + if (comconsinit == 0) { + (void) cominit(COMUNIT(dev), comdefaultrate); + comconsinit = 1; + } + /* wait for any pending transmission to finish */ + timo = 50000; + while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo) + ; + outb(iobase + com_data, c); + /* wait for this transmission to complete */ + timo = 1500000; + while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo) + ; + /* clear any interrupts generated by this transmission */ + stat = inb(iobase + com_iir); + splx(s); +} + +void +comcnpollc(dev, on) + dev_t dev; + int on; +{ + +} diff --git a/sys/arch/arm32/mainbus/comreg.h b/sys/arch/arm32/mainbus/comreg.h new file mode 100644 index 00000000000..7b1464d0a68 --- /dev/null +++ b/sys/arch/arm32/mainbus/comreg.h @@ -0,0 +1,133 @@ +/* $NetBSD: comreg.h,v 1.1 1996/01/31 23:24:29 mark Exp $ */ + +/*- + * Copyright (c) 1991 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. + * + * @(#)comreg.h 7.2 (Berkeley) 5/9/91 + */ + +/* + * NS16550 UART registers + */ + +#define com_data 0 /* data register (R/W) */ +#define com_dlbl 0 /* divisor latch low (W) */ +#define com_dlbh 4 /* divisor latch high (W) */ +#define com_ier 4 /* interrupt enable (W) */ +#define com_iir 8 /* interrupt identification (R) */ +#define com_fifo 8 /* FIFO control (W) */ +#define com_lctl 12 /* line control register (R/W) */ +#define com_cfcr 12 /* line control register (R/W) */ +#define com_mcr 16 /* modem control register (R/W) */ +#define com_lsr 20 /* line status register (R/W) */ +#define com_msr 24 /* modem status register (R/W) */ +#define com_scratch 28 /* scratch register (R/W) */ + +#define COM_FREQ 1843200 /* 16-bit baud rate divisor */ +#define COM_TOLERANCE 30 /* baud rate tolerance, in 0.1% units */ + +/* interrupt enable register */ +#define IER_ERXRDY 0x1 +#define IER_ETXRDY 0x2 +#define IER_ERLS 0x4 +#define IER_EMSC 0x8 + +/* interrupt identification register */ +#define IIR_IMASK 0xf +#define IIR_RXTOUT 0xc +#define IIR_RLS 0x6 +#define IIR_RXRDY 0x4 +#define IIR_TXRDY 0x2 +#define IIR_NOPEND 0x1 +#define IIR_MLSC 0x0 +#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ + +/* fifo control register */ +#define FIFO_ENABLE 0x01 +#define FIFO_RCV_RST 0x02 +#define FIFO_XMT_RST 0x04 +#define FIFO_DMA_MODE 0x08 +#define FIFO_TRIGGER_1 0x00 +#define FIFO_TRIGGER_4 0x40 +#define FIFO_TRIGGER_8 0x80 +#define FIFO_TRIGGER_14 0xc0 + +/* line control register */ +#define LCR_DLAB 0x80 +#define LCR_SBREAK 0x40 +#define LCR_PZERO 0x30 +#define LCR_PONE 0x20 +#define LCR_PEVEN 0x10 +#define LCR_PODD 0x00 +#define LCR_PENAB 0x08 +#define LCR_STOPB 0x04 +#define LCR_8BITS 0x03 +#define LCR_7BITS 0x02 +#define LCR_6BITS 0x01 +#define LCR_5BITS 0x00 + +/* modem control register */ +#define MCR_LOOPBACK 0x10 +#define MCR_IENABLE 0x08 +#define MCR_DRS 0x04 +#define MCR_RTS 0x02 +#define MCR_DTR 0x01 + +/* line status register */ +#define LSR_RCV_FIFO 0x80 +#define LSR_TSRE 0x40 +#define LSR_TXRDY 0x20 +#define LSR_BI 0x10 +#define LSR_FE 0x08 +#define LSR_PE 0x04 +#define LSR_OE 0x02 +#define LSR_RXRDY 0x01 +#define LSR_RCV_MASK 0x1f + +/* modem status register */ +#define MSR_DCD 0x80 +#define MSR_RI 0x40 +#define MSR_DSR 0x20 +#define MSR_CTS 0x10 +#define MSR_DDCD 0x08 +#define MSR_TERI 0x04 +#define MSR_DDSR 0x02 +#define MSR_DCTS 0x01 + +#define COM_NPORTS 32 + +/* + * WARNING: Serial console is assumed to be at COM1 address + * and CONUNIT must be 0. + */ +#define CONADDR (SERIAL0_CONTROLLER_BASE) +#define CONUNIT (0) diff --git a/sys/arch/arm32/mainbus/cpu.c b/sys/arch/arm32/mainbus/cpu.c new file mode 100644 index 00000000000..b5b8551dbdd --- /dev/null +++ b/sys/arch/arm32/mainbus/cpu.c @@ -0,0 +1,500 @@ +/* $NetBSD: cpu.c,v 1.4 1996/03/18 20:50:00 mark 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 + * + * cpu.c + * + * Probing and configuration for the master cpu + * + * Created : 10/10/95 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpu.h" +#if NCPU < 1 +#error Need at least 1 CPU configured +#endif + +/* Array of cpu structures, one per possible cpu */ + +cpu_t cpus[MAX_CPUS]; + +char cpu_model[48]; +extern int cpu_ctrl; /* Control bits for boot CPU */ +volatile int undefined_test; /* Used for FPA test */ + +extern char *boot_args; + +/* Declare prototypes */ + +/* Prototypes */ + +void identify_master_cpu __P((int /*cpu_number*/)); +void identify_arm_cpu __P((int /*cpu_number*/)); +void identify_arm_fpu __P((int /*cpu_number*/)); +char *strstr __P((char */*s1*/, char */*s2*/)); + + +/* + * int cpumatch(struct device *parent, void *match, void *aux) + * + * Probe for the main cpu. Currently all this does is return 1 to + * indicate that the cpu was found. + */ + +int +cpumatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct device *dev = match; + + if (dev->dv_unit == 0) + return(1); + return(0); +} + + +/* + * void cpusattach(struct device *parent, struct device *dev, void *aux) + * + * Attach the main cpu + */ + +void +cpuattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + int loop; + + for (loop = 0; loop < MAX_CPUS; ++loop) + bzero(&cpus[loop], sizeof(cpu_t)); + + identify_master_cpu(CPU_MASTER); +} + +struct cfattach cpu_ca = { + sizeof(struct cpu_softc), cpumatch, cpuattach +}; + +struct cfdriver cpu_cd = { + NULL, "cpu", DV_DULL, 1 +}; + + +/* + * Used to test for an FPA. The following function is installed as a coproc1 handler + * on the undefined instruction vector and then we issue a FPA instruction. + * If undefined_test is non zero then the FPA did not handle the instruction so + * must be absent. + */ + +int +fpa_test(address, instruction, frame) + u_int address; + u_int instruction; + trapframe_t *frame; +{ + ++undefined_test; + return(0); +} + +/* + * If an FPA was found then this function is installed as the coproc1 handler + * on the undefined instruction vector. Currently we don't support FPA's + * so this just triggers an exception. + */ + +int +fpa_handler(address, instruction, frame) + u_int address; + u_int instruction; + trapframe_t *frame; +{ + u_int fpsr; + + __asm __volatile("stmfd sp!, {r0}; .word 0xee300110; mov %0, r0; ldmfd sp!, {r0}" : "=r" (fpsr)); + + printf("FPA exception: fpsr = %08x\n", fpsr); + + return(1); +} + + +/* + * Identify the master (boot) CPU + * This also probes for an FPU and will install an FPE if necessary + */ + +void +identify_master_cpu(cpu_number) + int cpu_number; +{ + u_int fpsr; + + cpus[cpu_number].cpu_class = CPU_CLASS_ARM; + cpus[cpu_number].cpu_host = CPU_HOST_MAINBUS; + cpus[cpu_number].cpu_flags = CPU_FLAG_PRESENT; + cpus[cpu_number].cpu_ctrl = cpu_ctrl; + +/* Get the cpu ID from coprocessor 15 */ + + cpus[cpu_number].cpu_id = cpu_id(); + + identify_arm_cpu(cpu_number); + strcpy(cpu_model, cpus[cpu_number].cpu_model); + +/* + * Ok now we test for an FPA + * At this point no floating point emulator has been installed. + * This means any FP instruction will cause undefined exception. + * We install a temporay coproc 1 handler which will modify undefined_test + * if it is called. + * We then try to read the FP status register. If undefined_test has been + * decremented then the instruction was not handled by an FPA so we know + * the FPA is missing. If undefined_test is still 1 then we know the + * instruction was handled by an FPA. + * We then remove our test handler and look at the + * FP status register for identification. + */ + + install_coproc_handler(FP_COPROC, fpa_test); + + undefined_test = 0; + + __asm __volatile("stmfd sp!, {r0}; .word 0xee300110; mov %0, r0; ldmfd sp!, {r0}" : "=r" (fpsr)); + + if (undefined_test == 0) { + cpus[cpu_number].fpu_type = (fpsr >> 24); + switch (fpsr >> 24) { + case 0x81 : + cpus[cpu_number].fpu_class = FPU_CLASS_FPA; + +#if 0 +/* Experimental stuff used when playing with an ARM700+FPA11 */ + printf("FPA11: FPSR=%08x\n", fpsr); + fpsr=0x00070400; + __asm __volatile("wfs %0" : "=r" (fpsr)); + __asm __volatile("rfc %0" : "=r" (fpsr)); + printf("FPA11: FPCR=%08x", fpsr); + __asm __volatile("stmfd sp!, {r0}; mov r0, #0x00000e00 ; wfc r0; ldmfd sp!, {r0}"); + __asm __volatile("rfc %0" : "=r" (fpsr)); + printf("FPA11: FPCR=%08x", fpsr); +#endif + break; + + default : + cpus[cpu_number].fpu_class = FPU_CLASS_FPU; + break; + } + cpus[cpu_number].fpu_flags = 0; + install_coproc_handler(FP_COPROC, fpa_handler); + } else { + cpus[cpu_number].fpu_class = FPU_CLASS_NONE; + cpus[cpu_number].fpu_flags = 0; + +/* Ok if ARMFPE is defined and the boot options request the ARM FPE then it will + * be installed as the FPE. If the installation fails the existing FPE is used as + * a fall back. + * If either ARMFPE is not defined or the boot args did not request it the old FPE + * is installed. + * This is just while I work on integrating the new FPE. + * It means the new FPE gets installed if compiled int (ARMFPE defined) + * and also gives me a on/off option when I boot in case the new FPE is + * causing panics. + * In all cases it falls back on the existing FPE is the ARMFPE was not successfully + * installed. + */ + +#ifdef ARMFPE + if (boot_args) { + char *ptr; + + ptr = strstr(boot_args, "noarmfpe"); + if (!ptr) { + if (initialise_arm_fpe(&cpus[cpu_number]) != 0) { + identify_arm_fpu(cpu_number); +#ifdef FPE + initialise_fpe(&cpus[cpu_number]); +#endif + } +#ifdef FPE + } else + initialise_fpe(&cpus[cpu_number]); + + } else + initialise_fpe(&cpus[cpu_number]); +#else + } + } +#endif + +#else +#ifdef FPE + initialise_fpe(&cpus[cpu_number]); +#else +#error No FPE built in +#endif +#endif + } + + identify_arm_fpu(cpu_number); +} + + + +/* + * Report the type of the specifed arm processor. This uses the generic and arm specific + * information in the cpu structure to identify the processor. The remaining fields + * in the cpu structure are filled in appropriately. + */ + +void +identify_arm_cpu(cpu_number) + int cpu_number; +{ + cpu_t *cpu; + u_int cpuid; + + cpu = &cpus[cpu_number]; + if (cpu->cpu_host == CPU_HOST_NONE || cpu->cpu_class == CPU_CLASS_NONE) { + printf("No installed processor\n"); + return; + } + if (cpu->cpu_class != CPU_CLASS_ARM) { + printf("identify_arm_cpu: Can only identify ARM CPU's\n"); + return; + } + cpuid = cpu->cpu_id; + + if (cpuid == 0) { + printf("Processor failed probe - no CPU ID\n"); + return; + } + + if ((cpuid & CPU_ID_DESIGNER_MASK) != CPU_ID_ARM_LTD) + printf("Unrecognised designer ID = %08x\n", cpuid); + + switch (cpuid & CPU_ID_CPU_MASK) { + case ID_ARM610: + cpu->cpu_type = cpuid & CPU_ID_CPU_MASK; + break; + + case ID_ARM710 : + case ID_ARM700 : + cpu->cpu_type = (cpuid & CPU_ID_CPU_MASK) >> 4; + break; + + default : + printf("Unrecognised processor ID = %08x\n", cpuid); + cpu->cpu_type = cpuid & CPU_ID_CPU_MASK; + break; + } + + sprintf(cpu->cpu_model, "ARM%x rev %d", cpu->cpu_type, cpuid & CPU_ID_REVISION_MASK); + + if ((cpu->cpu_ctrl & CPU_CONTROL_IDC_ENABLE) == 0) + strcat(cpu->cpu_model, " IDC disabled"); + else + strcat(cpu->cpu_model, " IDC enabled"); + + if ((cpu->cpu_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0) + strcat(cpu->cpu_model, " WB disabled"); + else + strcat(cpu->cpu_model, " WB enabled"); + + if (cpu->cpu_ctrl & CPU_CONTROL_LABT_ENABLE) + strcat(cpu->cpu_model, " LABT"); + else + strcat(cpu->cpu_model, " EABT"); + +/* Print the info */ + + printf(": %s\n", cpu->cpu_model); +} + + +/* + * Report the type of the specifed arm fpu. This uses the generic and arm specific + * information in the cpu structure to identify the fpu. The remaining fields + * in the cpu structure are filled in appropriately. + */ + +void +identify_arm_fpu(cpu_number) + int cpu_number; +{ + cpu_t *cpu; + + cpu = &cpus[cpu_number]; + if (cpu->cpu_host == CPU_HOST_NONE || cpu->cpu_class == CPU_CLASS_NONE) { + printf("No installed processor\n"); + return; + } + + if (cpu->cpu_class != CPU_CLASS_ARM) { + printf("identify_arm_cpu: Can only identify ARM FPU's\n"); + return; + } + +/* Now for the FP info */ + + switch (cpu->fpu_class) { + case FPU_CLASS_NONE : + strcpy(cpu->fpu_model, "None"); + break; + case FPU_CLASS_FPE : + printf("fpe%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model); + printf("fpe%d: no hardware found\n", cpu_number); + break; + case FPU_CLASS_FPA : + printf("fpe%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model); + if (cpu->fpu_type == FPU_TYPE_FPA11) { + strcpy(cpu->fpu_model, "FPA11"); + printf("fpe%d: fpa11 found\n", cpu_number); + } else { + strcpy(cpu->fpu_model, "FPA"); + printf("fpe%d: fpa10 found\n", cpu_number); + } + if ((cpu->fpu_flags & 4) == 0) + strcat(cpu->fpu_model, ""); + else + strcat(cpu->fpu_model, " clk/2"); + break; + case FPU_CLASS_FPU : + sprintf(cpu->fpu_model, "Unknown FPU (ID=%02x)\n", cpu->fpu_type); + printf("fpu%d at cpu%d: %s\n", cpu_number, cpu_number, cpu->fpu_model); + break; + } +} + + +int +cpuopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct cpu_softc *sc; + int unit; + int s; + + unit = minor(dev); + if (unit >= cpu_cd.cd_ndevs) + return(ENXIO); + + sc = cpu_cd.cd_devs[unit]; + if (!sc) return(ENXIO); + + s = splhigh(); + if (sc->sc_open) { + (void)splx(s); + return(EBUSY); + } + + ++sc->sc_open; + (void)splx(s); + + return(0); +} + + +int +cpuclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct cpu_softc *sc; + int unit; + int s; + + unit = minor(dev); + sc = cpu_cd.cd_devs[unit]; + + if (sc->sc_open == 0) return(ENXIO); + + s = splhigh(); + --sc->sc_open; + (void)splx(s); + + return(0); +} + + +int +cpuioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct cpu_softc *sc; + int unit; + + unit = minor(dev); + sc = cpu_cd.cd_devs[unit]; + + switch (cmd) { + default: + return(ENXIO); + break; + } + + return(0); +} + +/* End of cpu.c */ diff --git a/sys/arch/arm32/mainbus/fd.c b/sys/arch/arm32/mainbus/fd.c new file mode 100644 index 00000000000..d12e73d46b9 --- /dev/null +++ b/sys/arch/arm32/mainbus/fd.c @@ -0,0 +1,1339 @@ +/* $NetBSD: fd.c,v 1.5 1996/03/28 21:52:41 mark Exp $ */ + +/*- + * Copyright (c) 1993, 1994, 1995 Charles Hannum. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Don Ahn. + * + * 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. + * + * @(#)fd.c 7.4 (Berkeley) 5/25/91 + */ + +/* The new config stuff do no use to use and need to be pulled out */ + +#undef NEWCONFIG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include +#include + +#define FDUNIT(dev) (minor(dev) / 8) +#define FDTYPE(dev) (minor(dev) % 8) + +#define b_cylin b_resid + +enum fdc_state { + DEVIDLE = 0, + MOTORWAIT, + DOSEEK, + SEEKWAIT, + SEEKTIMEDOUT, + SEEKCOMPLETE, + DOIO, + IOCOMPLETE, + IOTIMEDOUT, + DORESET, + RESETCOMPLETE, + RESETTIMEDOUT, + DORECAL, + RECALWAIT, + RECALTIMEDOUT, + RECALCOMPLETE, +}; + +/* software state, per controller */ +struct fdc_softc { + struct device sc_dev; /* boilerplate */ + irqhandler_t sc_ih; + + int sc_iobase; + int sc_drq; + + struct fd_softc *sc_fd[4]; /* pointers to children */ + TAILQ_HEAD(drivehead, fd_softc) sc_drives; + enum fdc_state sc_state; + int sc_errors; /* number of retries so far */ + u_char sc_status[7]; /* copy of registers */ +}; + +/* controller driver configuration */ +int fdcprobe __P((struct device *, void *, void *)); +#ifdef NEWCONFIG +void fdcforceintr __P((void *)); +#endif +void fdcattach __P((struct device *, struct device *, void *)); + +static fiqhandler_t fiqhandler; + +void floppy_read_fiq __P((void)); +void floppy_write_fiq __P((void)); + +struct cfattach fdc_ca = { + sizeof(struct fdc_softc), fdcprobe, fdcattach +}; + +struct cfdriver fdc_cd = { + NULL, "fdc", DV_DULL +}; + +/* + * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how + * we tell them apart. + */ +struct fd_type { + int sectrac; /* sectors per track */ + int heads; /* number of heads */ + int seccyl; /* sectors per cylinder */ + int secsize; /* size code for sectors */ + int datalen; /* data len when secsize = 0 */ + int steprate; /* step rate and head unload time */ + int gap1; /* gap len between sectors */ + int gap2; /* formatting gap */ + int tracks; /* total num of tracks */ + int size; /* size of disk in sectors */ + int step; /* steps per cylinder */ + int rate; /* transfer speed code */ + char *name; +}; + +/* The order of entries in the following table is important -- BEWARE! */ +struct fd_type fd_types[] = { + { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,"1.44MB" }, /* 1.44MB diskette */ + { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, "1.2MB" }, /* 1.2 MB AT-diskettes */ + { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, "360KB/AT" }, /* 360kB in 1.2MB drive */ + { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, "360KB/PC" }, /* 360kB PC diskettes */ + { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, "720KB" }, /* 3.5" 720kB diskette */ + { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, "720KB/x" }, /* 720kB in 1.2MB drive */ + { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, "360KB/x" }, /* 360kB in 720kB drive */ +}; + +/* software state, per disk (with up to 4 disks per ctlr) */ +struct fd_softc { + struct device sc_dev; + struct disk sc_dk; + + struct fd_type *sc_deftype; /* default type descriptor */ + struct fd_type *sc_type; /* current type descriptor */ + + daddr_t sc_blkno; /* starting block number */ + int sc_bcount; /* byte count left */ + int sc_skip; /* bytes already transferred */ + int sc_nblks; /* number of blocks currently tranferring */ + int sc_nbytes; /* number of bytes currently tranferring */ + + int sc_drive; /* physical unit number */ + int sc_flags; +#define FD_OPEN 0x01 /* it's open */ +#define FD_MOTOR 0x02 /* motor should be on */ +#define FD_MOTOR_WAIT 0x04 /* motor coming up */ + int sc_cylin; /* where we think the head is */ + + void *sc_sdhook; /* saved shutdown hook for drive. */ + + TAILQ_ENTRY(fd_softc) sc_drivechain; + int sc_ops; /* I/O ops since last switch */ + struct buf sc_q; /* head of buf chain */ +}; + +/* floppy driver configuration */ +int fdprobe __P((struct device *, void *, void *)); +void fdattach __P((struct device *, struct device *, void *)); + +struct cfattach fd_ca = { + sizeof(struct fd_softc), fdprobe, fdattach +}; + +struct cfdriver fd_cd = { + NULL, "fd", DV_DISK +}; + +void fdgetdisklabel __P((struct fd_softc *)); +int fd_get_parms __P((struct fd_softc *)); +void fdstrategy __P((struct buf *)); +void fdstart __P((struct fd_softc *)); + +struct dkdriver fddkdriver = { fdstrategy }; + +struct fd_type *fd_nvtotype __P((char *, int, int)); +void fd_set_motor __P((struct fdc_softc *fdc, int reset)); +void fd_motor_off __P((void *arg)); +void fd_motor_on __P((void *arg)); +int fdcresult __P((struct fdc_softc *fdc)); +int out_fdc __P((int iobase, u_char x)); +void fdcstart __P((struct fdc_softc *fdc)); +void fdcstatus __P((struct device *dv, int n, char *s)); +void fdctimeout __P((void *arg)); +void fdcpseudointr __P((void *arg)); +int fdcintr __P((void *)); +void fdcretry __P((struct fdc_softc *fdc)); +void fdfinish __P((struct fd_softc *fd, struct buf *bp)); + +int +fdcprobe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + register struct mainbus_attach_args *mb = aux; + int iobase = mb->mb_iobase; + + /* reset */ + outb(iobase + fdout, 0); + delay(100); + outb(iobase + fdout, FDO_FRST); + + /* see if it can handle a command */ + if (out_fdc(iobase, NE7CMD_SPECIFY) < 0) + return 0; + out_fdc(iobase, 0xdf); + out_fdc(iobase, 6/*2*/); /* Don't remember why - mark */ + +#ifdef NEWCONFIG + if (iobase == IOBASEUNK || ia->ia_drq == DRQUNK) + return 0; + + if (ia->ia_irq == IRQUNK) { + ia->ia_irq = isa_discoverintr(fdcforceintr, aux); + if (ia->ia_irq == IRQNONE) + return 0; + + /* reset it again */ + outb(iobase + fdout, 0); + delay(100); + outb(iobase + fdout, FDO_FRST); + } +#endif + + mb->mb_iosize = FDC_NPORT; + return 1; +} + +#ifdef NEWCONFIG +void +fdcforceintr(aux) + void *aux; +{ + struct mainbus_attach_args *mb = aux; + int iobase = mb->mb_iobase; + + /* the motor is off; this should generate an error with or + without a disk drive present */ + out_fdc(iobase, NE7CMD_SEEK); + out_fdc(iobase, 0); + out_fdc(iobase, 0); +} +#endif + +/* + * Arguments passed between fdcattach and fdprobe. + */ +struct fdc_attach_args { + int fa_drive; + struct fd_type *fa_deftype; +}; + +/* + * Print the location of a disk drive (called just before attaching the + * the drive). If `fdc' is not NULL, the drive was found but was not + * in the system config file; print the drive name as well. + * Return QUIET (config_find ignores this if the device was configured) to + * avoid printing `fdN not configured' messages. + */ +int +fdprint(aux, fdc) + void *aux; + char *fdc; +{ + register struct fdc_attach_args *fa = aux; + + if (!fdc) + printf(" drive %d", fa->fa_drive); + return QUIET; +} + +void +fdcattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct fdc_softc *fdc = (void *)self; + struct mainbus_attach_args *mb = aux; + struct fdc_attach_args fa; + int type; + + fdc->sc_iobase = mb->mb_iobase; + fdc->sc_drq = mb->mb_iobase + mb->mb_drq; + fdc->sc_state = DEVIDLE; + TAILQ_INIT(&fdc->sc_drives); + + printf("\n"); + +/*#ifdef NEWCONFIG + at_setup_dmachan(fdc->sc_drq, FDC_MAXIOSIZE); + isa_establish(&fdc->sc_id, &fdc->sc_dev); +#endif*/ + + fdc->sc_ih.ih_func = fdcintr; + fdc->sc_ih.ih_arg = fdc; + fdc->sc_ih.ih_level = IPL_BIO; + fdc->sc_ih.ih_name = "fdc"; + if (irq_claim(mb->mb_irq, &fdc->sc_ih)) + panic("Cannot claim IRQ %d for fdc%d\n", mb->mb_irq, parent->dv_unit); + + /* + * The NVRAM info only tells us about the first two disks on the + * `primary' floppy controller. + */ +/* if (fdc->sc_dev.dv_unit == 0) + type = mc146818_read(NULL, NVRAM_DISKETTE); + else + type = -1;*/ + + type = 0x10; + + /* physical limit: four drives per controller. */ + for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) { + if (type >= 0 && fa.fa_drive < 2) + fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname, + type, fa.fa_drive); + else + fa.fa_deftype = NULL; /* unknown */ + (void)config_found(self, (void *)&fa, fdprint); + } +} + +int +fdprobe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct fdc_softc *fdc = (void *)parent; + struct cfdata *cf = match; + struct fdc_attach_args *fa = aux; + int drive = fa->fa_drive; + int iobase = fdc->sc_iobase; + int n; + + if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive) + return 0; + /* + * XXX + * This is to work around some odd interactions between this driver + * and SMC Ethernet cards. + */ + + /* Don't need this for arm32 port but leave for the time being (it won't hurt) */ + + if (cf->cf_loc[0] == -1 && drive >= 2) + return 0; + + /* select drive and turn on motor */ + outb(iobase + fdout, drive | FDO_FRST | FDO_MOEN(drive)); + /* wait for motor to spin up */ + delay(250000); + out_fdc(iobase, NE7CMD_RECAL); + out_fdc(iobase, drive); + /* wait for recalibrate */ + delay(2000000); + out_fdc(iobase, NE7CMD_SENSEI); + n = fdcresult(fdc); +#ifdef FD_DEBUG + { + int i; + printf("fdprobe: status"); + for (i = 0; i < n; i++) + printf(" %x", fdc->sc_status[i]); + printf("\n"); + } +#endif + if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20) + return 0; + /* turn off motor */ + outb(iobase + fdout, FDO_FRST); + + return 1; +} + +/* + * Controller is working, and drive responded. Attach it. + */ +void +fdattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct fdc_softc *fdc = (void *)parent; + struct fd_softc *fd = (void *)self; + struct fdc_attach_args *fa = aux; + struct fd_type *type = fa->fa_deftype; + int drive = fa->fa_drive; + + /* XXX Allow `flags' to override device type? */ + + if (type) + printf(": %s %d cyl, %d head, %d sec\n", type->name, + type->tracks, type->heads, type->sectrac); + else + printf(": density unknown\n"); + + fd->sc_cylin = -1; + fd->sc_drive = drive; + fd->sc_deftype = type; + fdc->sc_fd[drive] = fd; + + /* + * Initialize and attach the disk structure. + */ + fd->sc_dk.dk_name = fd->sc_dev.dv_xname; + fd->sc_dk.dk_driver = &fddkdriver; + disk_attach(&fd->sc_dk); + +#ifdef NEWCONFIG + /* XXX Need to do some more fiddling with sc_dk. */ + dk_establish(&fd->sc_dk, &fd->sc_dev); +#endif + /* Needed to power off if the motor is on when we halt. */ + fd->sc_sdhook = shutdownhook_establish(fd_motor_off, fd); +} + +/* + * Translate nvram type into internal data structure. Return NULL for + * none/unknown/unusable. + */ +struct fd_type * +fd_nvtotype(fdc, nvraminfo, drive) + char *fdc; + int nvraminfo, drive; +{ + int type; + + type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0; + switch (type) { +/* case 0x00 : + return NULL;*/ + case 0x10 : + return &fd_types[0]; + default: + printf("%s: drive %d: unknown device type 0x%x\n", + fdc, drive, type); + return NULL; + } +} + +inline struct fd_type * +fd_dev_to_type(fd, dev) + struct fd_softc *fd; + dev_t dev; +{ + int type = FDTYPE(dev); + + if (type > (sizeof(fd_types) / sizeof(fd_types[0]))) + return NULL; + return type ? &fd_types[type - 1] : fd->sc_deftype; +} + +void +fdstrategy(bp) + register struct buf *bp; /* IO operation to perform */ +{ + struct fd_softc *fd; + int unit = FDUNIT(bp->b_dev); + int sz; + int s; + +/* printf("fdstrategy: bp=%08x\n", bp);*/ + + /* Valid unit, controller, and request? */ + if (unit >= fd_cd.cd_ndevs || + (fd = fd_cd.cd_devs[unit]) == 0 || + bp->b_blkno < 0 || + (bp->b_bcount % FDC_BSIZE) != 0) { + bp->b_error = EINVAL; + goto bad; + } + + /* If it's a null transfer, return immediately. */ + if (bp->b_bcount == 0) + goto done; + + sz = howmany(bp->b_bcount, FDC_BSIZE); + + if (bp->b_blkno + sz > fd->sc_type->size) { + sz = fd->sc_type->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; + } + + bp->b_cylin = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl; + +#ifdef FD_DEBUG + printf("fdstrategy: b_blkno %d b_bcount %d blkno %d cylin %d sz %d\n", + bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylin, sz); +#endif + + /* Queue transfer on drive, activate drive and controller if idle. */ + s = splbio(); + disksort(&fd->sc_q, bp); + untimeout(fd_motor_off, fd); /* a good idea */ + /* Instrumentation. */ + disk_busy(&fd->sc_dk); + if (!fd->sc_q.b_active) + fdstart(fd); +#ifdef DIAGNOSTIC + else { + struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; + if (fdc->sc_state == DEVIDLE) { + printf("fdstrategy: controller inactive\n"); + fdcstart(fdc); + } + } +#endif + splx(s); + return; + +bad: + bp->b_flags |= B_ERROR; +done: + /* Toss transfer; we're done early. */ + biodone(bp); +} + +void +fdstart(fd) + struct fd_softc *fd; +{ + struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; + int active = fdc->sc_drives.tqh_first != 0; + +/* printf("fdstart:\n");*/ + + /* Link into controller queue. */ + fd->sc_q.b_active = 1; + TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); + + /* Instrumentation. */ +/* disk_busy(&fd->sc_dk);*/ + + /* If controller not already active, start it. */ + if (!active) + fdcstart(fdc); +} + +void +fdfinish(fd, bp) + struct fd_softc *fd; + struct buf *bp; +{ + struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; + + /* + * Move this drive to the end of the queue to give others a `fair' + * chance. We only force a switch if N operations are completed while + * another drive is waiting to be serviced, since there is a long motor + * startup delay whenever we switch. + */ + if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) { + fd->sc_ops = 0; + TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); + if (bp->b_actf) { + TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain); + } else + fd->sc_q.b_active = 0; + } + bp->b_resid = fd->sc_bcount; + fd->sc_skip = 0; + fd->sc_q.b_actf = bp->b_actf; + +/* printf("fdfinish: fd=%08x buf=%08x busy=%d\n", (u_int)fd, (u_int)bp, fd->sc_dk.dk_busy);*/ + + disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid)); + + biodone(bp); + /* turn off motor 5s from now */ + timeout(fd_motor_off, fd, 5 * hz); + fdc->sc_state = DEVIDLE; +} + +int +fdread(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio)); +} + +int +fdwrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio)); +} + +void +fd_set_motor(fdc, reset) + struct fdc_softc *fdc; + int reset; +{ + struct fd_softc *fd; + u_char status; + int n; + + if (fd = fdc->sc_drives.tqh_first) + status = fd->sc_drive; + else + status = 0; + if (!reset) + status |= FDO_FRST | FDO_FDMAEN; + for (n = 0; n < 4; n++) + if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR)) + status |= FDO_MOEN(n); + outb(fdc->sc_iobase + fdout, status); +} + +void +fd_motor_off(arg) + void *arg; +{ + struct fd_softc *fd = arg; + int s; + + s = splbio(); + fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); + fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0); + splx(s); +} + +void +fd_motor_on(arg) + void *arg; +{ + struct fd_softc *fd = arg; + struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent; + int s; + + s = splbio(); + fd->sc_flags &= ~FD_MOTOR_WAIT; + if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT)) + (void) fdcintr(fdc); + splx(s); +} + +int +fdcresult(fdc) + struct fdc_softc *fdc; +{ + int iobase = fdc->sc_iobase; + u_char i; + int j = 100000, + n = 0; + + for (; j; j--) { + i = inb(iobase + fdsts) & (NE7_DIO | NE7_RQM | NE7_CB); + if (i == NE7_RQM) + return n; + if (i == (NE7_DIO | NE7_RQM | NE7_CB)) { + if (n >= sizeof(fdc->sc_status)) { + log(LOG_ERR, "fdcresult: overrun\n"); + return -1; + } + fdc->sc_status[n++] = inb(iobase + fddata); + } + } + log(LOG_ERR, "fdcresult: timeout\n"); + return -1; +} + +int +out_fdc(iobase, x) + int iobase; + u_char x; +{ + int i = 100000; + + while ((inb(iobase + fdsts) & NE7_DIO) && i-- > 0); + if (i <= 0) + return -1; + while ((inb(iobase + fdsts) & NE7_RQM) == 0 && i-- > 0); + if (i <= 0) + return -1; + outb(iobase + fddata, x); + return 0; +} + +int +fdopen(dev, flags) + dev_t dev; + int flags; +{ + int unit; + struct fd_softc *fd; + struct fd_type *type; + + unit = FDUNIT(dev); + if (unit >= fd_cd.cd_ndevs) + return ENXIO; + fd = fd_cd.cd_devs[unit]; + if (fd == 0) + return ENXIO; + type = fd_dev_to_type(fd, dev); + if (type == NULL) + return ENXIO; + + if ((fd->sc_flags & FD_OPEN) != 0 && + fd->sc_type != type) + return EBUSY; + + fd->sc_type = type; + fd->sc_cylin = -1; + fd->sc_flags |= FD_OPEN; + + return 0; +} + +int +fdclose(dev, flags) + dev_t dev; + int flags; +{ + struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)]; + + fd->sc_flags &= ~FD_OPEN; + return 0; +} + +void +fdcstart(fdc) + struct fdc_softc *fdc; +{ + +#ifdef DIAGNOSTIC + /* only got here if controller's drive queue was inactive; should + be in idle state */ + if (fdc->sc_state != DEVIDLE) { + printf("fdcstart: not idle\n"); + return; + } +#endif + (void) fdcintr(fdc); +} + +void +fdcstatus(dv, n, s) + struct device *dv; + int n; + char *s; +{ + struct fdc_softc *fdc = (void *)dv->dv_parent; + int iobase = fdc->sc_iobase; + + if (n == 0) { + out_fdc(fdc->sc_iobase, NE7CMD_SENSEI); + (void) fdcresult(fdc); + n = 2; + } + + printf("%s: %s", dv->dv_xname, s); + + switch (n) { + case 0: + printf("\n"); + break; + case 2: + printf(" (st0 %b cyl %d)\n", + fdc->sc_status[0], NE7_ST0BITS, + fdc->sc_status[1]); + break; + case 7: + printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n", + fdc->sc_status[0], NE7_ST0BITS, + fdc->sc_status[1], NE7_ST1BITS, + fdc->sc_status[2], NE7_ST2BITS, + fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]); + break; +#ifdef DIAGNOSTIC + default: + printf("\nfdcstatus: weird size"); + break; +#endif + } +} + +void +fdctimeout(arg) + void *arg; +{ + struct fdc_softc *fdc = arg; + struct fd_softc *fd = fdc->sc_drives.tqh_first; + int s; + + s = splbio(); + fdcstatus(&fd->sc_dev, 0, "timeout"); + + if (fd->sc_q.b_actf) + fdc->sc_state++; + else + fdc->sc_state = DEVIDLE; + + (void) fdcintr(fdc); + splx(s); +} + +void +fdcpseudointr(arg) + void *arg; +{ + int s; + + /* Just ensure it has the right spl. */ + s = splbio(); + (void) fdcintr(arg); + splx(s); +} + +int +fdcintr(arg) + void *arg; +{ + struct fdc_softc *fdc = arg; +#define st0 fdc->sc_status[0] +#define cyl fdc->sc_status[1] + struct fd_softc *fd; + struct buf *bp; + int iobase = fdc->sc_iobase; + int read, head, trac, sec, i, s, nblks; + struct fd_type *type; + +loop: + /* Is there a drive for the controller to do a transfer with? */ + fd = fdc->sc_drives.tqh_first; + if (fd == NULL) { + fdc->sc_state = DEVIDLE; + return 1; + } + + /* Is there a transfer to this drive? If not, deactivate drive. */ + bp = fd->sc_q.b_actf; + if (bp == NULL) { + fd->sc_ops = 0; + TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain); + fd->sc_q.b_active = 0; + goto loop; + } + + switch (fdc->sc_state) { + case DEVIDLE: + fdc->sc_errors = 0; + fd->sc_skip = 0; + fd->sc_bcount = bp->b_bcount; + fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE); + untimeout(fd_motor_off, fd); + if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) { + fdc->sc_state = MOTORWAIT; + return 1; + } + if ((fd->sc_flags & FD_MOTOR) == 0) { + /* Turn on the motor, being careful about pairing. */ + struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1]; + if (ofd && ofd->sc_flags & FD_MOTOR) { + untimeout(fd_motor_off, ofd); + ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT); + } + fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT; + fd_set_motor(fdc, 0); + fdc->sc_state = MOTORWAIT; + /* Allow .25s for motor to stabilize. */ + timeout(fd_motor_on, fd, hz / 4); + return 1; + } + /* Make sure the right drive is selected. */ + fd_set_motor(fdc, 0); + + /* fall through */ + case DOSEEK: + doseek: + if (fd->sc_cylin == bp->b_cylin) + goto doio; + + out_fdc(iobase, NE7CMD_CONFIGURE);/* configure command */ + out_fdc(iobase, 0); + out_fdc(iobase, 0x1a); + out_fdc(iobase, 0); + + out_fdc(iobase, NE7CMD_SPECIFY);/* specify command */ + out_fdc(iobase, fd->sc_type->steprate); + out_fdc(iobase, 6); /* XXX head load time == 6ms */ + + out_fdc(iobase, NE7CMD_SEEK); /* seek function */ + out_fdc(iobase, fd->sc_drive); /* drive number */ + out_fdc(iobase, bp->b_cylin * fd->sc_type->step); + + fd->sc_cylin = -1; + fdc->sc_state = SEEKWAIT; + timeout(fdctimeout, fdc, 4 * hz); + return 1; + + case DOIO: + doio: + type = fd->sc_type; + sec = fd->sc_blkno % type->seccyl; + nblks = type->seccyl - sec; + nblks = min(nblks, fd->sc_bcount / FDC_BSIZE); + nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE); + fd->sc_nblks = nblks; + fd->sc_nbytes = nblks * FDC_BSIZE; + head = sec / type->sectrac; + sec -= head * type->sectrac; +#ifdef DIAGNOSTIC + {int block; + block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec; + if (block != fd->sc_blkno) { + printf("fdcintr: block %d != blkno %d\n", block, fd->sc_blkno); +#ifdef DDB + Debugger(); +#endif + }} +#endif + read = bp->b_flags & B_READ; +/*#ifdef NEWCONFIG + at_dma(read, bp->b_data + fd->sc_skip, fd->sc_nbytes, + fdc->sc_drq); +#else + isa_dmastart(read, bp->b_data + fd->sc_skip, fd->sc_nbytes, + fdc->sc_drq); +#endif*/ + if (read) + fiqhandler.fh_func = floppy_read_fiq; + else + fiqhandler.fh_func = floppy_write_fiq; + fiqhandler.fh_r11 = nblks * FDC_BSIZE; + fiqhandler.fh_r12 = (int)bp->b_data + (int)fd->sc_skip; + fiqhandler.fh_r13 = fdc->sc_drq; + fiqhandler.fh_mask = 0x01; + if (fiq_claim(&fiqhandler) == -1) + panic("Cannot claim FIQ vector\n"); + + outb(iobase + fdctl, type->rate); +#ifdef FD_DEBUG + printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n", + read ? "read" : "write", fd->sc_drive, fd->sc_cylin, head, + sec, nblks); +#endif + if (read) + out_fdc(iobase, NE7CMD_READ); /* READ */ + else + out_fdc(iobase, NE7CMD_WRITE); /* WRITE */ + out_fdc(iobase, (head << 2) | fd->sc_drive); + out_fdc(iobase, fd->sc_cylin); /* track */ + out_fdc(iobase, head); + out_fdc(iobase, sec + 1); /* sector +1 */ + out_fdc(iobase, type->secsize); /* sector size */ + out_fdc(iobase, type->sectrac); /* sectors/track */ + out_fdc(iobase, type->gap1); /* gap1 size */ + out_fdc(iobase, type->datalen); /* data length */ + fdc->sc_state = IOCOMPLETE; + /* allow 2 seconds for operation */ + timeout(fdctimeout, fdc, 2 * hz); + return 1; /* will return later */ + + case SEEKWAIT: + untimeout(fdctimeout, fdc); + fdc->sc_state = SEEKCOMPLETE; + /* allow 1/50 second for heads to settle */ +/* timeout(fdcpseudointr, fdc, hz / 50);*/ + return 1; + + case SEEKCOMPLETE: + /* Make sure seek really happened. */ + out_fdc(iobase, NE7CMD_SENSEI); + if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || + cyl != bp->b_cylin * fd->sc_type->step) { +#ifdef FD_DEBUG + fdcstatus(&fd->sc_dev, 2, "seek failed"); +#endif + fdcretry(fdc); + goto loop; + } + fd->sc_cylin = bp->b_cylin; + goto doio; + + case IOTIMEDOUT: +/*#ifdef NEWCONFIG + at_dma_abort(fdc->sc_drq); +#else + isa_dmaabort(fdc->sc_drq); +#endif*/ + if (fiq_release(&fiqhandler) == -1) + panic("Cannot release FIQ vector\n"); + case SEEKTIMEDOUT: + case RECALTIMEDOUT: + case RESETTIMEDOUT: + fdcretry(fdc); + goto loop; + + case IOCOMPLETE: /* IO DONE, post-analyze */ + untimeout(fdctimeout, fdc); + if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) { +/*#ifdef NEWCONFIG + at_dma_abort(fdc->sc_drq); +#else + isa_dmaabort(fdc->sc_drq); +#endif*/ + if (fiq_release(&fiqhandler) == -1) + panic("Cannot release FIQ vector\n"); +#ifdef FD_DEBUG + fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ? + "read failed" : "write failed"); + printf("blkno %d nblks %d\n", + fd->sc_blkno, fd->sc_nblks); +#endif + fdcretry(fdc); + goto loop; + } +/*#ifdef NEWCONFIG + at_dma_terminate(fdc->sc_drq); +#else + read = bp->b_flags & B_READ; + isa_dmadone(read, bp->b_data + fd->sc_skip, fd->sc_nbytes, + fdc->sc_drq); +#endif*/ + if (fiq_release(&fiqhandler) == -1) + panic("Cannot release FIQ vector\n"); + + if (fdc->sc_errors) { +/* diskerr(bp, "fd", "soft error", LOG_PRINTF, + fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL); + printf("\n");*/ + fdc->sc_errors = 0; + } + fd->sc_blkno += fd->sc_nblks; + fd->sc_skip += fd->sc_nbytes; + fd->sc_bcount -= fd->sc_nbytes; + if (fd->sc_bcount > 0) { + bp->b_cylin = fd->sc_blkno / fd->sc_type->seccyl; + goto doseek; + } +/* printf("IOCOMPLETE:calling fdfinish fd=%08x bp=%08x blkno=%d\n", (u_int)fd, (u_int)bp, fd->sc_blkno);*/ + fdfinish(fd, bp); + goto loop; + + case DORESET: + /* try a reset, keep motor on */ + fd_set_motor(fdc, 1); + delay(100); + fd_set_motor(fdc, 0); + fdc->sc_state = RESETCOMPLETE; + timeout(fdctimeout, fdc, hz / 2); + return 1; /* will return later */ + + case RESETCOMPLETE: + untimeout(fdctimeout, fdc); + /* clear the controller output buffer */ + for (i = 0; i < 4; i++) { + out_fdc(iobase, NE7CMD_SENSEI); + (void) fdcresult(fdc); + } + + /* fall through */ + case DORECAL: + out_fdc(iobase, NE7CMD_RECAL); /* recalibrate function */ + out_fdc(iobase, fd->sc_drive); + fdc->sc_state = RECALWAIT; + timeout(fdctimeout, fdc, 5 * hz); + return 1; /* will return later */ + + case RECALWAIT: + untimeout(fdctimeout, fdc); + fdc->sc_state = RECALCOMPLETE; + /* allow 1/30 second for heads to settle */ +/* timeout(fdcpseudointr, fdc, hz / 30);*/ + return 1; /* will return later */ + + case RECALCOMPLETE: + out_fdc(iobase, NE7CMD_SENSEI); + if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) { +#ifdef FD_DEBUG + fdcstatus(&fd->sc_dev, 2, "recalibrate failed"); +#endif + fdcretry(fdc); + goto loop; + } + fd->sc_cylin = 0; + goto doseek; + + case MOTORWAIT: + if (fd->sc_flags & FD_MOTOR_WAIT) + return 1; /* time's not up yet */ + goto doseek; + + default: + fdcstatus(&fd->sc_dev, 0, "stray interrupt"); + return 1; + } +#ifdef DIAGNOSTIC + panic("fdcintr: impossible"); +#endif +#undef st0 +#undef cyl +} + +void +fdcretry(fdc) + struct fdc_softc *fdc; +{ + struct fd_softc *fd; + struct buf *bp; + + fd = fdc->sc_drives.tqh_first; + bp = fd->sc_q.b_actf; + + switch (fdc->sc_errors) { + case 0: + /* try again */ +/* fdc->sc_state = SEEKCOMPLETE;*/ + fdc->sc_state = DOSEEK; + break; + + case 1: case 2: case 3: + /* didn't work; try recalibrating */ + fdc->sc_state = DORECAL; + break; + + case 4: + /* still no go; reset the bastard */ + fdc->sc_state = DORESET; + break; + + default: + diskerr(bp, "fd", "hard error", LOG_PRINTF, + fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL); + printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n", + fdc->sc_status[0], NE7_ST0BITS, + fdc->sc_status[1], NE7_ST1BITS, + fdc->sc_status[2], NE7_ST2BITS, + fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]); + + bp->b_flags |= B_ERROR; + bp->b_error = EIO; + fdfinish(fd, bp); + } + fdc->sc_errors++; +} + +int +fdsize(dev) + dev_t dev; +{ + + /* Swapping to floppies would not make sense. */ + return -1; +} + +int +fddump(dev, blkno, va, size) + dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; +{ + + /* Not implemented. */ + return ENXIO; +} + +int +fdioctl(dev, cmd, addr, flag) + dev_t dev; + u_long cmd; + caddr_t addr; + int flag; +{ + struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)]; + struct disklabel buffer; + int error; + + switch (cmd) { + case DIOCGDINFO: + bzero(&buffer, sizeof(buffer)); + + buffer.d_secpercyl = fd->sc_type->seccyl; + buffer.d_type = DTYPE_FLOPPY; + buffer.d_secsize = FDC_BSIZE; + + if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL) + return EINVAL; + + *(struct disklabel *)addr = buffer; + return 0; + + case DIOCWLABEL: + if ((flag & FWRITE) == 0) + return EBADF; + /* XXX do something */ + return 0; + + case DIOCWDINFO: + if ((flag & FWRITE) == 0) + return EBADF; + + error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL); + if (error) + return error; + + error = writedisklabel(dev, fdstrategy, &buffer, NULL); + return error; + + default: + return ENOTTY; + } + +#ifdef DIAGNOSTIC + panic("fdioctl: impossible"); +#endif +} + + +#include "rd.h" +#if NRD > 0 + +#include + +int +load_ramdisc_from_floppy(rd, dev) + struct rd_conf *rd; + dev_t dev; +{ + struct buf *bp; + int loop; + int s; + int type; + int floppysize; + + if (major(dev) != 17) + return(EINVAL); + + if (rd->rd_type == RD_UNCONFIGURED || rd->rd_addr == 0) + return(EBUSY); + + type = FDTYPE(dev) - 1; + if (type < 0) type = 0; + floppysize = fd_types[type].size << (fd_types[type].secsize + 7); + + if (rd->rd_size < floppysize) { + printf("Ramdisc not big enough for floppy image\n"); + return(EINVAL); + } + +/* We have the ramdisk ! */ + + printf("Loading ramdisc : %4dK ", 0); + +/* obtain a buffer */ + + bp = geteblk(fd_types[type].sectrac * DEV_BSIZE); + +/* request no partition relocation by driver on I/O operations */ + + bp->b_dev = dev; + + s = spl0(); + + if (fdopen(bp->b_dev, 0) != 0) { + brelse(bp); + printf("Cannot open floppy device\n"); + return(EINVAL); + } + + for (loop = 0; + loop < (floppysize / DEV_BSIZE / fd_types[type].sectrac); + ++loop) { + printf("\x08\x08\x08\x08\x08\x08%4dK ", + loop * fd_types[type].sectrac * DEV_BSIZE / 1024); + bp->b_blkno = loop * fd_types[type].sectrac; + bp->b_bcount = fd_types[type].sectrac * DEV_BSIZE; + bp->b_flags = B_BUSY | B_READ; + bp->b_error = 0; + bp->b_resid = 0; + fdstrategy(bp); + + if (biowait(bp)) + panic("Cannot load floppy image\n"); + + bcopy((caddr_t)bp->b_data, (caddr_t)rd->rd_addr + + loop * fd_types[type].sectrac * DEV_BSIZE, + fd_types[type].sectrac * DEV_BSIZE); + } + printf("\x08\x08\x08\x08\x08\x08%4dK done\n", + loop * fd_types[type].sectrac * DEV_BSIZE / 1024); + + fdclose(bp->b_dev, 0); + + brelse(bp); + + splx(s); + return(0); +} + +#endif diff --git a/sys/arch/arm32/mainbus/fdreg.h b/sys/arch/arm32/mainbus/fdreg.h new file mode 100644 index 00000000000..bdfd8fe2760 --- /dev/null +++ b/sys/arch/arm32/mainbus/fdreg.h @@ -0,0 +1,102 @@ +/* $NetBSD: fdreg.h,v 1.2 1996/03/18 20:50:02 mark Exp $ */ + +/*- + * Copyright (c) 1991 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. + * + * @(#)fdreg.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * AT floppy controller registers and bitfields + */ + + +/* + * Nec 765 floppy disc controller definitions + */ + +/* Main status register */ +#define NE7_DAB 0x01 /* Diskette drive A is seeking, thus busy */ +#define NE7_DBB 0x02 /* Diskette drive B is seeking, thus busy */ +#define NE7_CB 0x10 /* Diskette Controller Busy */ +#define NE7_NDM 0x20 /* Diskette Controller in Non Dma Mode */ +#define NE7_DIO 0x40 /* Diskette Controller Data register I/O */ +#define NE7_RQM 0x80 /* Diskette Controller ReQuest for Master */ + +/* Status register ST0 */ +#define NE7_ST0BITS "\020\010invld\007abnrml\006seek_cmplt\005drv_chck\004drive_rdy\003top_head" + +/* Status register ST1 */ +#define NE7_ST1BITS "\020\010end_of_cyl\006bad_crc\005data_overrun\003sec_not_fnd\002write_protect\001no_am" + +/* Status register ST2 */ +#define NE7_ST2BITS "\020\007ctrl_mrk\006bad_crc\005wrong_cyl\004scn_eq\003scn_not_fnd\002bad_cyl\001no_dam" + +/* Status register ST3 */ +#define NE7_ST3BITS "\020\010fault\007write_protect\006drdy\005tk0\004two_side\003side_sel\002" + +/* Commands */ +#define NE7CMD_SPECIFY 3 /* specify drive parameters - requires unit + parameters byte */ +#define NE7CMD_SENSED 4 /* sense drive - requires unit select byte */ +#define NE7CMD_WRITE 0xc5 /* write - requires eight additional bytes */ +#define NE7CMD_READ 0xe6 /* read - requires eight additional bytes */ +#define NE7CMD_FORMAT 0x4c /* format - requires five additional bytes */ +#define NE7CMD_RECAL 7 /* recalibrate drive - requires + unit select byte */ +#define NE7CMD_SENSEI 8 /* sense controller interrupt status */ +#define NE7CMD_SEEK 15 /* seek drive - requires unit select byte + and new cyl byte */ +#define NE7CMD_CONFIGURE 0x13 + +/* registers */ +#define fdout 8 /* Digital Output Register (W) */ +#define FDO_FDSEL 0x03 /* floppy device select */ +#define FDO_FRST 0x04 /* floppy controller reset */ +#define FDO_FDMAEN 0x08 /* enable floppy DMA and Interrupt */ +#define FDO_MOEN(n) ((1 << n) * 0x10) /* motor enable */ + +#define fdsts 16 /* NEC 765 Main Status Register (R) */ +#define fddata 20 /* NEC 765 Data Register (R/W) */ + +#define fdctl 28 /* Control Register (W) */ +#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */ +#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */ +#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */ +#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */ + +#define fdin 28 /* Digital Input Register (R) */ +#define FDI_DCHG 0x80 /* diskette has been changed */ + +#define FDC_BSIZE 512 +#define FDC_NPORT 32 +#define FDC_MAXIOSIZE NBPG /* XXX should be MAXBSIZE */ diff --git a/sys/arch/arm32/mainbus/iic.c b/sys/arch/arm32/mainbus/iic.c new file mode 100644 index 00000000000..334b6030443 --- /dev/null +++ b/sys/arch/arm32/mainbus/iic.c @@ -0,0 +1,403 @@ +/* $NetBSD: iic.c,v 1.1 1996/04/19 19:49:03 mark 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Local function prototypes */ + +static int iic_getack __P((void)); +static void iic_write_bit __P((int bit)); +static int iic_write_byte __P((u_char value)); +static u_char iic_read_byte __P((void)); +static void iic_start_bit __P((void)); +static void iic_stop_bit __P((void)); + +struct iic_softc { + struct device sc_dev; + int sc_flags; +#define IIC_BROKEN 1 +#define IIC_OPEN 2 +#define IIC_BUSY 4 +}; + +void iicattach __P((struct device *parent, struct device *self, void *aux)); +int iicmatch __P((struct device *parent, void *match, void *aux)); + +/* + * Main entry to IIC driver. + */ + +int +iic_control(address, buffer, count) + u_char address; + u_char *buffer; + int count; +{ + int loop; + +/* Send the start bit */ + + iic_start_bit(); + +/* Send the address */ + + if (!iic_write_byte(address)) { + iic_stop_bit(); + 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(buffer[loop])) { + iic_stop_bit(); + return(-1); + } + } + } + else { +/* Read bytes */ + for (loop = 0; loop < count; ++loop) { + buffer[loop] = iic_read_byte(); + +/* Send final acknowledge */ + + if (loop == (count - 1)) + iic_write_bit(1); + else + iic_write_bit(0); + } + } + +/* Send stop bit */ + + iic_stop_bit(); + + return(0); +} + + +static int +iic_getack() +{ + u_int oldirqstate; + int ack; + + iic_set_state(1, 0); + oldirqstate = disable_interrupts(I32_bit); + iic_set_state_and_ack(1, 1); + ack = ReadByte(IOMD_IOCR); + iic_set_state(1, 0); + restore_interrupts(oldirqstate); + + return((ack & 1) == 0); +} + + +static void +iic_write_bit(bit) + int bit; +{ + u_int oldirqstate; + + iic_set_state(bit, 0); + oldirqstate = disable_interrupts(I32_bit); + iic_set_state_and_ack(bit, 1); + iic_set_state(bit, 0); + restore_interrupts(oldirqstate); +} + + +static int +iic_write_byte(value) + u_char value; +{ + int loop; + int bit; + + for (loop = 0x80; loop != 0; loop = loop >> 1) { + bit = ((value & loop) != 0); + iic_write_bit(bit); + } + + return(iic_getack()); +} + + +static u_char +iic_read_byte() +{ + int loop; + u_char byte; + u_int oldirqstate; + + iic_set_state(1,0); + + byte = 0; + + for (loop = 0; loop < 8; ++loop) { + oldirqstate = disable_interrupts(I32_bit); + iic_set_state_and_ack(1, 1); + byte = (byte << 1) + (ReadByte(IOMD_IOCR) & 1); + iic_set_state(1, 0); + restore_interrupts(oldirqstate); + } + + return(byte); +} + + +static void +iic_start_bit() +{ + iic_set_state(1, 1); + iic_set_state(0, 1); + iic_delay(10); + iic_set_state(0, 0); +} + + +static void +iic_stop_bit() +{ + iic_set_state(0, 1); + iic_set_state(1, 1); +} + + +struct cfattach iic_ca = { + sizeof(struct iic_softc), iicmatch, iicattach +}; + +struct cfdriver iic_cd = { + NULL, "iic", DV_DULL, 0 +}; + +int +iicmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + int id; + +/* Make sure we have an IOMD we understand */ + + id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8); + +/* So far I only know about this IOMD */ + + switch (id) { + case RPC600_IOMD_ID: + case RC7500_IOC_ID: + return(1); + break; + default: + printf("iic: Unknown IOMD id=%04x", id); + break; + } + + return(0); +} + +int +iicprint(aux, name) + void *aux; + char *name; +{ + struct iicbus_attach_args *ib = aux; + + if (!name) { + if (ib->ib_addr) + printf(" addr 0x%02x", ib->ib_addr); + } + +/* XXXX print flags */ + return (QUIET); +} + + +int +iicsubmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct cfdata *cf = match; + struct iicbus_attach_args *ib = aux; + + if (cf->cf_fstate == FSTATE_STAR) + panic("eekkk, I'm stuffed"); + + ib->ib_addr = cf->cf_loc[0]; + + if (ib->ib_addr == -1) + return(0); + + return((*cf->cf_attach->ca_match)(parent, match, aux)); +} + +void +iicattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct iicbus_attach_args iaa; + + printf("\n"); + + while (config_found_sm(self, &iaa, iicprint, iicsubmatch)); +} + + +int +iicopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct iic_softc *sc; + int unit = minor(dev); + + if (unit >= iic_cd.cd_ndevs) + return(ENXIO); + + sc = iic_cd.cd_devs[unit]; + + if (!sc) return(ENXIO); + + if (sc->sc_flags & IIC_OPEN) return(EBUSY); + + sc->sc_flags |= IIC_OPEN; + + return(0); +} + + +int +iicclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + int unit = minor(dev); + struct iic_softc *sc = iic_cd.cd_devs[unit]; + + sc->sc_flags &= ~IIC_OPEN; + + return(0); +} + + +int +iicread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct iic_softc *sc = iic_cd.cd_devs[unit]; + + return(ENXIO); +} + + +int +iicwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct iic_softc *sc = iic_cd.cd_devs[unit]; + + return(ENXIO); +} + + +int +iicioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct iic_softc *sc = iic_cd.cd_devs[minor(dev)]; + +/* + switch (cmd) { + case IICIOC_CONTROL: + if (iiccontrol() != 0) { + return(EIO); + } + return(0); + } +*/ + + return(EINVAL); +} + +/* End of iic.c */ diff --git a/sys/arch/arm32/mainbus/iic_asm.S b/sys/arch/arm32/mainbus/iic_asm.S new file mode 100644 index 00000000000..10ceb8a0238 --- /dev/null +++ b/sys/arch/arm32/mainbus/iic_asm.S @@ -0,0 +1,239 @@ +/* $NetBSD: iic_asm.S,v 1.1 1996/04/19 19:49:04 mark 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.s + * + * Low level routines to with IIC devices + * + * Created : 13/10/94 + * + * Based of kate/display/iic.s + */ + +#include +#include + +#define IIC_BITDELAY 10 + +sp .req r13 +lr .req r14 +pc .req r15 + +.text + + .global _iic_set_state + +_iic_set_state: +/* + * Parameters + * r0 - IIC data bit + * r1 - IIC clock bit + */ + +/* Store temporary register */ +/* stmfd sp!, {r4}*/ + +/* + * Mask the data and clock bits + * Since these routines are only called from iiccontrol.c this is not + * really needed + */ + and r0, r0, #0x00000001 + and r1, r1, #0x00000001 + +/* Get address of IOMD control register */ + + mov r2, #(IOMD_BASE) + +/* Get the current CPSR */ +/* mrs r4, cpsr_all + orr r3, r4, #(I32_bit | F32_bit) + msr cpsr_all, r3 +*/ + + IRQdisable + +/* Get current value of control register */ + + ldrb r3, [r2, #(IOMD_IOCR - IOMD_BASE)] + +/* Preserve non-IIC bits */ + + bic r3, r3, #0x00000003 + orr r3, r3, #0x000000c0 + +/* Set the IIC clock and data bits */ + + orr r3, r3, r0 + orr r3, r3, r1, lsl #1 + +/* Store the new value of control register */ + + strb r3, [r2, #(IOMD_IOCR - IOMD_BASE)] + +/* Restore CPSR state */ +/* msr cpsr_all, r4 */ + + IRQenable + +/* Restore temporary register */ +/* ldmfd sp!, {r4} */ + +/* Pause a bit */ + + mov r0, #(IIC_BITDELAY) + +/* Exit via iic_delay routine */ + b _iic_delay + + + .global _iic_set_state_and_ack + +_iic_set_state_and_ack: +/* + * Parameters + * r0 - IIC data bit + * r1 - IIC clock bit + */ +/* Store temporary register */ +/* stmfd sp!, {r4} */ + +/* + * Mask the data and clock bits + * Since these routines are only called from iiccontrol.c this is not + * really needed + */ + + and r0, r0, #0x00000001 + and r1, r1, #0x00000001 + +/* Get address of IOMD control register */ + + mov r2, #(IOMD_BASE) + +/* Get the current CPSR */ +/* mrs r4, cpsr_all + orr r3, r4, #(I32_bit | F32_bit) + msr cpsr_all, r3 +*/ + IRQdisable + +/* Get current value of control register */ + + ldrb r3, [r2, #(IOMD_IOCR - IOMD_BASE)] + +/* Preserve non-IIC bits */ + + bic r3, r3, #0x00000003 + orr r3, r3, #0x000000c0 + +/* Set the IIC clock and data bits */ + + orr r3, r3, r0 + orr r3, r3, r1, lsl #1 + +/* Store the new value of control register */ + + strb r3, [r2, #(IOMD_IOCR - IOMD_BASE)] + +iic_set_state_and_ack_loop: + ldrb r3, [r2, #(IOMD_IOCR - IOMD_BASE)] + tst r3, #0x00000002 + beq iic_set_state_and_ack_loop + +/* Restore CPSR state */ +/* msr cpsr_all, r4 */ + + IRQenable + +/* Restore temporary register */ +/* ldmfd sp!, {r4} */ + +/* Pause a bit */ + + mov r0, #(IIC_BITDELAY) + +/* Exit via iic_delay routine */ + b _iic_delay + + + .global _iic_delay + +_iic_delay: +/* + * Parameters + * r0 - time to wait + */ + +/* Load address of IOMD */ + + mov r2, #(IOMD_BASE) + +/* Latch current value of timer 1 */ + + strb r2, [r2, #(IOMD_T0LATCH - IOMD_BASE)] + +/* Get the latched value */ + + ldrb r1, [r2, #(IOMD_T0LOW - IOMD_BASE)] + +/* Loop until timer reaches end value */ + +iic_delay_loop: + +/* Latch the current value of timer1 */ + + strb r2, [r2, #(IOMD_T0LATCH - IOMD_BASE)] + +/* Get the latched value */ + + ldrb r3, [r2, #(IOMD_T0LOW - IOMD_BASE)] + +/* Loop until timer reached expected value */ + + teq r3, r1 + movne r1, r3 + beq iic_delay_loop + + subs r0, r0, #0x00000001 + bne iic_delay_loop + +/* Exit */ + mov pc, lr + +/* End of iic_asm.S */ diff --git a/sys/arch/arm32/mainbus/kbd.c b/sys/arch/arm32/mainbus/kbd.c new file mode 100644 index 00000000000..3b85bdba7e8 --- /dev/null +++ b/sys/arch/arm32/mainbus/kbd.c @@ -0,0 +1,1357 @@ +/* $NetBSD: kbd.c,v 1.7 1996/03/28 21:55:15 mark 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 + * + * kbd.c + * + * Keyboard driver functions + * + * Created : 09/10/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "vt.h" +#include "kbd.h" + +/* Declare global variables */ + +/* Declare external variables */ + +/* Local function prototypes */ + +/* Now for the main code */ + +/* Define the key_struct structure */ + +typedef struct { + int base_code; /* Base ASCII code */ + int shift_code; /* Shifted ASCII code */ + int ctrl_code; /* CTRL code */ + int alt_code; /* Alt code */ + int flags; /* Flags field */ +} key_struct; + +/* Define mappings for each possible code */ + +key_struct keys[256] = { +/* 0x00 - 0x0f */ + { 0x00, 0x00, 0x00, 0x00, 0x80 }, + { 0x89, 0x99, 0x00, 0x489, 0x00 }, + { 0x8a, 0x9a, 0x00, 0x00, 0x00 }, + { 0x85, 0x95, 0x00, 0x485, 0x00 }, + { 0x83, 0x93, 0x00, 0x483, 0x00 }, + { 0x81, 0x91, 0x00, 0x481, 0x00 }, + { 0x82, 0x92, 0x00, 0x482, 0x00 }, + { 0x8c, 0x9c, 0x00, 0x48c, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0x98, 0x00, 0x488, 0x00 }, + { 0x86, 0x96, 0x00, 0x486, 0x00 }, + { 0x84, 0x94, 0x00, 0x484, 0x00 }, + { 0x09, 0x09, 0x09, 0x09, 0x00 }, + { 0x60, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x10 - 0x1f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x84 }, + { 0x00, 0x00, 0x00, 0x00, 0x82 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x81 }, + { 0x71, 0x51, 0x11, 0x00, 0x40 }, + { 0x31, 0x21, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7a, 0x5a, 0x1a, 0x00, 0x40 }, + { 0x73, 0x53, 0x13, 0x00, 0x40 }, + { 0x61, 0x41, 0x01, 0x00, 0x40 }, + { 0x77, 0x57, 0x17, 0x00, 0x40 }, + { 0x32, 0x22, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x20 - 0x2f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x63, 0x43, 0x03, 0x00, 0x40 }, + { 0x78, 0x58, 0x18, 0x00, 0x40 }, + { 0x64, 0x44, 0x04, 0x00, 0x40 }, + { 0x65, 0x45, 0x05, 0x00, 0x40 }, + { 0x34, 0x24, 0x00, 0x00, 0x00 }, + { 0x33, 0x23, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x20, 0x20, 0x20, 0x20, 0x00 }, + { 0x76, 0x56, 0x16, 0x00, 0x40 }, + { 0x66, 0x46, 0x06, 0x00, 0x40 }, + { 0x74, 0x54, 0x14, 0x00, 0x40 }, + { 0x72, 0x52, 0x12, 0x00, 0x40 }, + { 0x35, 0x25, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x30 - 0x3f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6e, 0x4e, 0x0e, 0x00, 0x40 }, + { 0x62, 0x42, 0x02, 0x00, 0x40 }, + { 0x68, 0x48, 0x08, 0x00, 0x40 }, + { 0x67, 0x47, 0x07, 0x00, 0x40 }, + { 0x79, 0x59, 0x19, 0x00, 0x40 }, + { 0x36, 0x5e, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6d, 0x4d, 0x0d, 0x00, 0x40 }, + { 0x6a, 0x4a, 0x0a, 0x00, 0x40 }, + { 0x75, 0x55, 0x15, 0x00, 0x40 }, + { 0x37, 0x26, 0x00, 0x00, 0x00 }, + { 0x38, 0x2a, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x40 - 0x4f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2c, 0x3c, 0x00, 0x00, 0x00 }, + { 0x6b, 0x4b, 0x0b, 0x00, 0x40 }, + { 0x69, 0x49, 0x09, 0x00, 0x40 }, + { 0x6f, 0x4f, 0x0f, 0x00, 0x40 }, + { 0x30, 0x29, 0x00, 0x00, 0x00 }, + { 0x39, 0x28, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2e, 0x3e, 0x00, 0x00, 0x00 }, + { 0x2f, 0x3f, 0x00, 0x00, 0x00 }, + { 0x6c, 0x4c, 0x0c, 0x00, 0x40 }, + { 0x3b, 0x3a, 0x00, 0x00, 0x00 }, + { 0x70, 0x50, 0x10, 0x00, 0x40 }, + { 0x2d, 0x5f, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x50 - 0x5f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x27, 0x40, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x5b, 0x7b, 0x00, 0x00, 0x00 }, + { 0x3d, 0x2b, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0xa0 }, + { 0x00, 0x00, 0x00, 0x00, 0x82 }, + { 0x0d, 0x0d, 0x0d, 0x00, 0x00 }, + { 0x5d, 0x7d, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x23, 0x7e, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x60 - 0x6f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x5c, 0x7c, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x08, 0x7f, 0x08, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x31, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x34, 0x00, 0x00, 0x00, 0x00 }, + { 0x37, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x70 - 0x7f */ + { 0x30, 0x00, 0x00, 0x00, 0x00 }, + { 0x2e, 0x00, 0x00, 0x00, 0x00 }, + { 0x32, 0x00, 0x00, 0x00, 0x00 }, + { 0x35, 0x00, 0x00, 0x00, 0x00 }, + { 0x36, 0x00, 0x00, 0x00, 0x00 }, + { 0x38, 0x00, 0x00, 0x00, 0x00 }, + { 0x1b, 0x1b, 0x21b, 0x1b, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x90 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2b, 0x00, 0x00, 0x22b, 0x00 }, + { 0x33, 0x00, 0x00, 0x00, 0x00 }, + { 0x2d, 0x00, 0x00, 0x22d, 0x00 }, + { 0x2a, 0x00, 0x00, 0x00, 0x00 }, + { 0x39, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x88 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x80 - 0x8f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x87, 0x97, 0x00, 0x487, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x90 - 0x9f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0xa0 - 0xaf */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0xb0 - 0xbf */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0xc0 - 0xcf */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0xd0 - 0xdf */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0xe0 - 0xef */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0xf0 - 0xff */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +/* Define mappings for each possible code */ + +key_struct E0keys[128] = { + +/* 0x00 - 0x0f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x10 - 0x1f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x84 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x81 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x20 - 0x2f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x30 - 0x3f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x40 - 0x4f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2f, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x50 - 0x5f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0d, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x60 - 0x6f */ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x10b, 0x00, 0x00, 0x20b, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x102, 0x00, 0x00, 0x202, 0x00 }, + { 0x10a, 0x00, 0x00, 0x20a, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + +/* 0x70 - 0x7f */ + { 0x108, 0x00, 0x00, 0x208, 0x00 }, + { 0x109, 0x00, 0x00, 0x209, 0x00 }, + { 0x101, 0x105, 0x00, 0x201, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x103, 0x00, 0x00, 0x203, 0x00 }, + { 0x100, 0x104, 0x00, 0x200, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x104, 0x100, 0x00, 0x204, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x105, 0x101, 0x00, 0x205, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +/* Special keycodes */ + +#define KEYCODE_UP 0x100 +#define KEYCODE_DOWN 0x101 +#define KEYCODE_LEFT 0x102 +#define KEYCODE_RIGHT 0x103 +#define KEYCODE_PGUP 0x104 +#define KEYCODE_PGDN 0x105 +#define KEYCODE_INSERT 0x108 +#define KEYCODE_DELETE 0x109 +#define KEYCODE_HOME 0x10a +#define KEYCODE_END 0x10b + +/* Key modifiers flags */ + +#define MODIFIER_CTRL 0x01 +#define MODIFIER_SHIFT 0x02 +#define MODIFIER_ALT 0x04 +#define MODIFIER_MASK 0x07 + +#define MODIFIER_CAPS 0x20 +#define MODIFIER_NUM 0x10 +#define MODIFIER_SCROLL 0x08 +#define MODIFIER_LOCK_MASK 0x38 + +#define MODIFIER_CAPSLOCK 0x40 +#define MODIFIER_NORETURN 0x80 + +/* Keyboard buffer variables */ + +#define BUFFER_SIZE 32 +#define RAWKBD_BSIZE 128 + +static int autorepeatkey = -1; +static struct kbd_autorepeat kbdautorepeat = { 5, 20 }; +static int rawkbd_device = 0; +int modifiers = 0; +static int kbd_ack = 0; +static int kbd_resend = 0; + +extern int pmap_debug_level; + +struct kbd_softc { + struct device sc_device; + irqhandler_t sc_ih; + + int sc_state; +#define RAWKBD_OPEN 0x01 +#define KBD_OPEN 0x02 +#define RAWKBD_ASLEEP 0x04 + int sc_iobase; + struct clist sc_q; + struct selinfo sc_rsel; + struct proc *sc_proc; +}; + +#define KBDUNIT(u) (minor(u) / 2) +#define KBDFLAG(u) (minor(u) % 2) + +#define KBDFLAG_RAWUNIT 0 +#define KBDFLAG_CONUNIT 1 + +int kbdprobe __P((struct device *, void *, void *)); +void kbdattach __P((struct device *, struct device *, void *)); + +int kbdopen __P((dev_t, int, int, struct proc *)); +int kbdclose __P((dev_t, int, int, struct proc *)); +int kbdread __P((dev_t, struct uio *, int)); +int kbdselect __P((dev_t, int, struct proc *)); +int kbdioctl __P((dev_t, int, caddr_t, int, struct proc *)); + +void kbdinit __P((struct kbd_softc *sc)); +void kbdsetleds __P((int /*leds*/)); + +int PollKeyboard __P((int)); +int kbddecodekey __P((struct kbd_softc *, int)); +int kbdintr __P((struct kbd_softc *)); + +void autorepeatstart __P((void *)); +void autorepeat __P((void *)); + +struct cfattach kbd_ca = { + sizeof(struct kbd_softc), kbdprobe, kbdattach +}; + +struct cfdriver kbd_cd = { + NULL, "kbd", DV_TTY +}; + + +int +kbdprobe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ +/* struct mainbus_attach_args *mb = aux;*/ + int id; + +/* Make sure we have an IOMD we understand */ + + id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8); + +/* So far I only know about this IOMD */ + + switch (id) { + case RPC600_IOMD_ID: + case RC7500_IOC_ID: + return(1); + break; + default: + printf("kbd: Unknown IOMD id=%04x", id); + break; + } + + return(0); +} + + +void +kbdattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct kbd_softc *sc = (void *)self; + struct mainbus_attach_args *mb = aux; + + sc->sc_iobase = mb->mb_iobase; + + kbdinit(sc); + + printf("\n"); +} + + +int +kbdopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct kbd_softc *sc; + int unit = KBDUNIT(dev); + + if (unit >= kbd_cd.cd_ndevs) + return(ENXIO); + + sc = kbd_cd.cd_devs[unit]; + + if (!sc) return(ENXIO); + + switch (KBDFLAG(dev)) { + case KBDFLAG_RAWUNIT : + if (sc->sc_state & RAWKBD_OPEN) + return(EBUSY); + sc->sc_state |= RAWKBD_OPEN; + if (clalloc(&sc->sc_q, RAWKBD_BSIZE, 0) == -1) + return(ENOMEM); + sc->sc_proc = p; + rawkbd_device = 1; + break; + case KBDFLAG_CONUNIT : + if (sc->sc_state & KBD_OPEN) + return(EBUSY); + sc->sc_state |= KBD_OPEN; + break; + } + +/* Kill any active autorepeat */ + + untimeout(autorepeatstart, &autorepeatkey); + untimeout(autorepeat, &autorepeatkey); + + return(0); +} + + +int +kbdclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + int unit = KBDUNIT(dev); + struct kbd_softc *sc = kbd_cd.cd_devs[unit]; + + switch (KBDFLAG(dev)) { + case KBDFLAG_RAWUNIT : + if (!(sc->sc_state & RAWKBD_OPEN)) + return(EINVAL); + sc->sc_state &= ~RAWKBD_OPEN; + clfree(&sc->sc_q); + sc->sc_proc = NULL; + rawkbd_device = 0; + break; + case KBDFLAG_CONUNIT : + if (!(sc->sc_state & KBD_OPEN)) + return(EINVAL); + sc->sc_state &= ~KBD_OPEN; + break; + } + + return(0); +} + + +int +kbdread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)]; + int s; + int error = 0; + size_t length; + u_char buffer[128]; + + if (KBDFLAG(dev) == KBDFLAG_CONUNIT) + return(ENXIO); + + /* Block until keyboard activity occured. */ + + s = spltty(); + while (sc->sc_q.c_cc == 0) { + if (flag & IO_NDELAY) { + splx(s); + return EWOULDBLOCK; + } + sc->sc_state |= RAWKBD_ASLEEP; + if ((error = tsleep((caddr_t)sc, PZERO | PCATCH, "kbdread", 0))) { + sc->sc_state &= (~RAWKBD_ASLEEP); + splx(s); + return error; + } + } + splx(s); + + /* Transfer as many chunks as possible. */ + + while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) { + length = min(sc->sc_q.c_cc, uio->uio_resid); + if (length > sizeof(buffer)) + length = sizeof(buffer); + + /* Remove a small chunk from the input queue. */ + (void) q_to_b(&sc->sc_q, buffer, length); + + /* Copy the data to the user process. */ + if ((error = (uiomove(buffer, length, uio)))) + break; + } + return error; +} + +int +kbdselect(dev, rw, p) + dev_t dev; + int rw; + struct proc *p; +{ + struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)]; + int s; + int ret; + + if (KBDFLAG(dev) == KBDFLAG_CONUNIT) + return(ENXIO); + + if (rw == FWRITE) + return 0; + + s = spltty(); + if (!sc->sc_q.c_cc) { + selrecord(p, &sc->sc_rsel); + ret = 0; + } else + ret = 1; + splx(s); + return ret; +} + + +int +kbdioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ +/* struct kbd_softc *sc = kbd_cd.cd_devs[KBDUNIT(dev)];*/ + struct kbd_autorepeat *kbdar = (void *)data; + int *leds = (int *)data; + int s; + + switch (cmd) { + case KBD_GETAUTOREPEAT: +/* if (KBDFLAG(dev) == KBDFLAG_RAWUNIT) + return(EINVAL);*/ + + *kbdar = kbdautorepeat; + break; + case KBD_SETAUTOREPEAT: +/* if (KBDFLAG(dev) == KBDFLAG_RAWUNIT) + return(EINVAL);*/ + s = spltty(); + kbdautorepeat = *kbdar; + if (kbdautorepeat.ka_rate < 1) + kbdautorepeat.ka_rate = 1; + if (kbdautorepeat.ka_rate > 50) + kbdautorepeat.ka_rate = 50; + if (kbdautorepeat.ka_delay > 50) + kbdautorepeat.ka_delay = 50; + if (kbdautorepeat.ka_delay < 1) + kbdautorepeat.ka_delay = 1; + (void)splx(s); + break; + case KBD_SETLEDS: + kbdsetleds(*leds); + break; + default: + return(ENXIO); + } + return(0); +} + + +void +kbdsetleds(leds) + int leds; +{ + int loop; + + if ((ReadByte(IOMD_KBDCR) & 0x80)) { + WriteByte(IOMD_KBDDAT, 0xed); + loop = 10000; + while ((ReadByte(IOMD_KBDCR) & 0x40) && loop > 0) + --loop; + if ((ReadByte(IOMD_KBDCR) & 0x80)) { + WriteByte(IOMD_KBDDAT, leds); + loop = 10000; + while ((ReadByte(IOMD_KBDCR) & 0x40) && loop > 0) + --loop; + } + } +} + + +void +kbdsetstate(state) + int state; +{ + modifiers = state & MODIFIER_LOCK_MASK; +} + + +int +kdbgetstate() +{ + return(modifiers); +} + + +void +kbdinit(sc) + struct kbd_softc *sc; +{ + sc->sc_ih.ih_func = kbdintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_TTY; + sc->sc_ih.ih_name = "kbd rx"; + if (irq_claim(IRQ_KBDRX, &sc->sc_ih)) + panic("Cannot claim IRQ for kbd%d\n", sc->sc_device.dv_unit); + + modifiers = 0; + kbdsetleds((modifiers >> 3) & 7); +} + + +int +getkey_polled() +{ + int code; + int key; + int up; + key_struct *ks; + int s; + + s = splhigh(); + + key = 0; + + do { + while ((ReadByte(IOMD_KBDCR) & (1<<5)) == 0) ; + +/* Read the IOMD keyboard register and process the key */ + + code = PollKeyboard(ReadByte(IOMD_KBDDAT)); + + if (code != 0) { + up = (code & 0x100); + key = code & 0xff; + +/* printf("code=%04x mod=%04x\n", code, modifiers);*/ + +/* By default we use the main keycode lookup table */ + + ks = keys; + +/* If we have an E0 or E1 sqeuence we use the extended table */ + + if (code > 0x1ff) + ks = E0keys; + +/* Is the key a temporary modifier ? */ + + if (ks[key].flags & MODIFIER_MASK) { + if (up) + modifiers &= ~ks[key].flags; + else + modifiers |= ks[key].flags; + key = 0; + continue; + } + +/* Is the key a locking modifier ? */ + + if (ks[key].flags & MODIFIER_LOCK_MASK) { + if (!up) { + modifiers ^= ks[key].flags; + kbdsetleds((modifiers >> 3) & 7); + } + key = 0; + continue; + } + +/* Lookup the correct key code */ + + if (modifiers & 0x01) + key = ks[key].ctrl_code; + else if (modifiers & 0x02) + key = ks[key].shift_code; + else if (modifiers & 0x04) + key = ks[key].alt_code; + else + key = ks[key].base_code; + + if (modifiers & MODIFIER_CAPS) { + if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z')) + key ^= 0x20; + } + + if (up) + key = 0; + if (!up && key >= 0x200) { + +#if (NVT > 0) + if ((key & ~0x0f) == 0x480) + console_switch((key & 0x0f) - 1); + else +#endif + switch (key) { +#if (NVT > 0) + case 0x201: + console_scrollforward(); + break; + case 0x200: + console_scrollback(); + break; +#endif + default: + break; + } + key = 0; + } + } + } while (key == 0); + + if (key == '\r') + key = '\n'; + + splx(s); + return(key); +} + + +/* Keyboard IRQ handler */ + +int +kbdintr(sc) + struct kbd_softc *sc; +{ + int key; + +/* Read the IOMD keyboard register and process the key */ + + key = PollKeyboard(ReadByte(IOMD_KBDDAT)); + +/* If we have a raw keycode convert it to an ASCII code */ + + if (key != 0) + kbddecodekey(sc, key); + return(1); +} + + +/* Flags used to decode the raw keys */ + +#define FLAG_KEYUP 0x01 +#define FLAG_E0 0x02 +#define FLAG_E1 0x04 + +static int flags = 0; + +/* + * This function is now misnamed. + * It processes the raw key codes from the keyboard and generates + * a unique code that can be decoded with the key translation array. + */ + +int +PollKeyboard(code) + int code; +{ +/* printf("%02x.", code);*/ + +/* + * Set the keyup flag if this is the release code. + */ + + if (code == 0xf0) { + flags |= FLAG_KEYUP; + return(0); + } + +/* If it is a special code ignore it */ + + if (code == 0xff || code == 0x00) { + flags = 0; + return(0); + } + +/* If it is a resend code note it down */ + + if (code == 0xfe) { + printf("kbd:resend\n"); + kbd_resend = 1; + return(0); + } + +/* If it is an ack code note it down */ + + if (code == 0xfa) { +/* printf("kbd:ack\n");*/ + kbd_ack = 1; + return(0); + } + +/* Flag the start of an E0 sequence. */ + + if (code == 0xe0) { + flags |= FLAG_E0; + return(0); + } + +/* Flag the start of an E1 sequence. */ + + if (code == 0xe1) { + flags |= FLAG_E1; + return(0); + } + +/* Ignore any other invalid codes */ + + if (code > 0x8f) { + flags = 0; + return(0); + } + +/* printf("%02x:%02x.", code, flags);*/ + +/* Mark the code appropriately if it is part of an E0 sequence */ + + if (flags & FLAG_E0) { + flags &= ~FLAG_E0; + if (code == 0x12) { + flags &= ~FLAG_KEYUP; + return(0); + } + code |= 0x200; + } + +/* Mark the key if it is the upcode */ + + if (flags & FLAG_KEYUP) { + flags &= ~FLAG_KEYUP; + code |= 0x100; + } + +/* Mark the code appropriately if it is part of an E1 sequence */ + + if (flags & FLAG_E1) { + if ((code & 0xff) == 0x14) { + return(0); + } + flags &= ~FLAG_E1; + code |= 0x400; + flags &= ~FLAG_KEYUP; + } + + return(code); +} + + +/* + * This routine decodes the unique keycode and generates an ASCII code + * if necessary. + */ + +int +kbddecodekey(sc, code) + struct kbd_softc *sc; + int code; +{ + key_struct *ks; + int up; + int key; + + console_unblank(); + +/* Do we have the raw kbd device open ... */ + + if (rawkbd_device == 1 && code != 0) { + struct kbd_data buffer; + int s; + + /* Add this event to the queue. */ + + buffer.keycode = code; + microtime(&buffer.event_time); + s=spltty(); + (void) b_to_q((char *)&buffer, sizeof(buffer), &sc->sc_q); + splx(s); + selwakeup(&sc->sc_rsel); + + if (sc->sc_state & RAWKBD_ASLEEP) { + sc->sc_state &= ~RAWKBD_ASLEEP; + wakeup((caddr_t)sc); + } + + psignal(sc->sc_proc, SIGIO); + return(1); + } + + up = (code & 0x100); + key = code & 0xff; + +/* By default we use the main keycode lookup table */ + + ks = keys; + +/* If we have an E0 or E1 sqeuence we use the extended table */ + + if (code > 0x1ff) + ks = E0keys; + +/* Is the key a temporary modifier ? */ + + if (ks[key].flags & MODIFIER_MASK) { + if (up) + modifiers &= ~ks[key].flags; + else + modifiers |= ks[key].flags; + return(0); + } + +/* Is the key a locking modifier ? */ + + if (ks[key].flags & MODIFIER_LOCK_MASK) { + if (!up) { + modifiers ^= ks[key].flags; + kbdsetleds((modifiers >> 3) & 7); + } + return(0); + } + +/* Lookup the correct key code */ + + if (modifiers & 0x01) + key = ks[key].ctrl_code; + else if (modifiers & 0x02) + key = ks[key].shift_code; + else if (modifiers & 0x04) + key = ks[key].alt_code; + else + key = ks[key].base_code; + + if (modifiers & MODIFIER_CAPS) { + if ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z')) + key ^= 0x20; + } + +/* If no valid code the key is not yet mapped so report error */ + +#ifdef DEBUG_TERM +/* if (key == 0) { + char err[80]; + + sprintf(err, "\n\rUnknown keycode %04x\n\r", code); + dprintf(err); + + }*/ +#endif + +/* If we have an ASCII code insert it into the keyboard buffer */ + + if (!up && key != 0) { + if (key >= 0x200) { + + untimeout(autorepeatstart, &autorepeatkey); + untimeout(autorepeat, &autorepeatkey); + autorepeatkey = -1; +#if (NVT > 0) + if ((key & ~0x0f) == 0x480) + console_switch((key & 0x0f) - 1); + else +#endif + switch (key) { + case 0x22b: + pmap_debug(pmap_debug_level + 1); + break; + case 0x22d: + pmap_debug(pmap_debug_level - 1); + break; +#if (NVT > 0) + case 0x201: + console_scrollforward(); + break; + case 0x200: + console_scrollback(); + break; + case 0x202: + console_switchdown(); + break; + case 0x203: + console_switchup(); + break; +#endif + case 0x204: + --kbdautorepeat.ka_rate; + if (kbdautorepeat.ka_rate < 1) + kbdautorepeat.ka_rate = 1; + break; + case 0x205: + ++kbdautorepeat.ka_rate; + if (kbdautorepeat.ka_rate > 50) + kbdautorepeat.ka_rate = 50; + break; + case 0x20a: + ++kbdautorepeat.ka_delay; + if (kbdautorepeat.ka_delay > 50) + kbdautorepeat.ka_delay = 50; + break; + case 0x20b: + --kbdautorepeat.ka_delay; + if (kbdautorepeat.ka_delay < 1) + kbdautorepeat.ka_delay = 1; + break; +#ifdef DDB + case 0x208: + Debugger(); + break; +#endif + case 0x21b: + printf("Kernel interruption\n"); + boot(RB_HALT); + break; + case 0x209: + printf("Kernel interruption - nosync\n"); + boot(RB_NOSYNC | RB_HALT); + break; + + default: + printf("Special key %04x\n", key); + break; + } + } else { + if (physconkbd(key) == 0 && rawkbd_device == 0) { + if (autorepeatkey != key) { + untimeout(autorepeatstart, &autorepeatkey); + untimeout(autorepeat, &autorepeatkey); + autorepeatkey = key; + timeout(autorepeatstart, &autorepeatkey, hz/kbdautorepeat.ka_delay); + } + } + + return(1); + } + } else { + untimeout(autorepeatstart, &autorepeatkey); + untimeout(autorepeat, &autorepeatkey); + autorepeatkey = -1; + } + return(0); +} + + +void +autorepeatstart(key) + void *key; +{ + physconkbd(*((int *)key)); + timeout(autorepeat, key, hz/kbdautorepeat.ka_rate); +} + + +void +autorepeat(key) + void *key; +{ + physconkbd(*((int *)key)); + timeout(autorepeat, key, hz/kbdautorepeat.ka_rate); +} + +/* End of kbd.c */ diff --git a/sys/arch/arm32/mainbus/lpt.c b/sys/arch/arm32/mainbus/lpt.c new file mode 100644 index 00000000000..35ff77c3f0d --- /dev/null +++ b/sys/arch/arm32/mainbus/lpt.c @@ -0,0 +1,1314 @@ +/* $NetBSD: lpt.c,v 1.6 1996/03/28 21:52:47 mark Exp $ */ + +/* + * Copyright (c) 1995 Mark Brinicombe + * Copyright (c) 1993, 1994 Charles Hannum. + * Copyright (c) 1990 William F. Jolitz, TeleMuse + * 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 software is a component of "386BSD" developed by + * William F. Jolitz, TeleMuse. + * 4. Neither the name of the developer nor the name "386BSD" + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ + * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS + * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. + * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT + * NOT MAKE USE OF THIS WORK. + * + * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED + * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN + * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES + * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING + * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND + * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE + * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS + * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``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 DEVELOPER 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:$NetBSD: lpt.c,v 1.6 1996/03/28 21:52:47 mark Exp $ + */ + +/* + * Device Driver for AT parallel printer port + */ +/* + * PLIP driver code added by Mark Brinicombe + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(INET) && defined(PLIP) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bpfilter.h" +#if NBPFILTER > 0 +#include +#include +#endif +#endif + +#include +#include +#include +#include +#include +#include + +#define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */ +#define STEP hz/4 + +#define LPTPRI (PZERO+8) +#define LPT_BSIZE 1024 + +#if defined(INET) && defined(PLIP) +#ifndef PLIPMTU /* MTU for the plip# interfaces */ +#if defined(COMPAT_PLIP10) +#define PLIPMTU 1600 +#else +#define PLIPMTU (ETHERMTU - ifp->if_hdrlen) +#endif +#endif + +#ifndef PLIPMXSPIN1 /* DELAY factor for the plip# interfaces */ +#define PLIPMXSPIN1 2000 /* Spinning for remote intr to happen */ +#endif + +#ifndef PLIPMXSPIN2 /* DELAY factor for the plip# interfaces */ +#define PLIPMXSPIN2 6000 /* Spinning for remote handshake to happen */ +#endif + +#ifndef PLIPMXERRS /* Max errors before !RUNNING */ +#define PLIPMXERRS 100 +#endif +#ifndef PLIPMXRETRY +#define PLIPMXRETRY 10 /* Max number of retransmits */ +#endif +#ifndef PLIPRETRY +#define PLIPRETRY hz/10 /* Time between retransmits */ +#endif +#endif + +#if !defined(DEBUG) || !defined(notdef) +#define lprintf +#else +#define lprintf if (lptdebug) printf +int lptdebug = 1; +#endif + +struct lpt_softc { + struct device sc_dev; + irqhandler_t sc_ih; + + size_t sc_count; + struct buf *sc_inbuf; + u_char *sc_cp; + int sc_spinmax; + int sc_iobase; + int sc_irq; + u_char sc_state; +#define LPT_OPEN 0x01 /* device is open */ +#define LPT_OBUSY 0x02 /* printer is busy doing output */ +#define LPT_INIT 0x04 /* waiting to initialize for open */ +#define LPT_PLIP 0x08 /* busy with PLIP */ + u_char sc_flags; +#define LPT_AUTOLF 0x20 /* automatic LF on CR */ +#define LPT_NOPRIME 0x40 /* don't prime on open */ +#define LPT_NOINTR 0x80 /* do not use interrupt */ + u_char sc_control; + u_char sc_laststatus; +#if defined(INET) && defined(PLIP) + struct arpcom sc_arpcom; + u_char *sc_ifbuf; + int sc_iferrs; + int sc_ifretry; +#if defined(COMPAT_PLIP10) + u_char sc_adrcksum; +#endif +#endif +}; + +int lptprobe __P((struct device *, void *, void *)); +void lptattach __P((struct device *, struct device *, void *)); +int lptintr __P((void *)); + +#if defined(INET) && defined(PLIP) +/* Functions for the plip# interface */ +static void plipattach(struct lpt_softc *,int); +static int plipioctl(struct ifnet *, u_long, caddr_t); +static void plipstart(struct ifnet *); +static int plipintr(struct lpt_softc *); +#endif + +struct cfattach lpt_ca = { + sizeof(struct lpt_softc), lptprobe, lptattach +}; + +struct cfdriver lpt_cd = { + NULL, "lpt", DV_TTY +}; + +#define LPTUNIT(s) (minor(s) & 0x1f) +#define LPTFLAGS(s) (minor(s) & 0xe0) + +#define LPS_INVERT (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK) +#define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK|LPS_NOPAPER) +#define NOT_READY() ((inb(iobase + lpt_status) ^ LPS_INVERT) & LPS_MASK) +#define NOT_READY_ERR() not_ready(inb(iobase + lpt_status), sc) +static int not_ready __P((u_char, struct lpt_softc *)); + +static void lptwakeup __P((void *arg)); +static int pushbytes __P((struct lpt_softc *)); + +/* + * Internal routine to lptprobe to do port tests of one byte value. + */ +int +lpt_port_test(port, data, mask) + int port; + u_char data, mask; +{ + int timeout; + u_char temp; + + data &= mask; + outb(port, data); + timeout = 1000; + do { + delay(10); + temp = inb(port) & mask; + } while (temp != data && --timeout); + lprintf("lpt: port=0x%x out=0x%x in=0x%x timeout=%d\n", port, data, + temp, timeout); + return (temp == data); +} + +/* + * Logic: + * 1) You should be able to write to and read back the same value + * to the data port. Do an alternating zeros, alternating ones, + * walking zero, and walking one test to check for stuck bits. + * + * 2) You should be able to write to and read back the same value + * to the control port lower 5 bits, the upper 3 bits are reserved + * per the IBM PC technical reference manauls and different boards + * do different things with them. Do an alternating zeros, alternating + * ones, walking zero, and walking one test to check for stuck bits. + * + * Some printers drag the strobe line down when the are powered off + * so this bit has been masked out of the control port test. + * + * XXX Some printers may not like a fast pulse on init or strobe, I + * don't know at this point, if that becomes a problem these bits + * should be turned off in the mask byte for the control port test. + * + * 3) Set the data and control ports to a value of 0 + */ +int +lptprobe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct mainbus_attach_args *mb = aux; + int iobase = mb->mb_iobase; + int port; + u_char mask, data; + int i; + +#ifdef DEBUG +#define ABORT do {printf("lptprobe: mask %x data %x failed\n", mask, data); \ + return 0;} while (0) +#else +#define ABORT return 0 +#endif + + port = iobase + lpt_data; + mask = 0xff; + + data = 0x55; /* Alternating zeros */ + if (!lpt_port_test(port, data, mask)) + ABORT; + + data = 0xaa; /* Alternating ones */ + if (!lpt_port_test(port, data, mask)) + ABORT; + + for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */ + data = ~(1 << i); + if (!lpt_port_test(port, data, mask)) + ABORT; + } + + for (i = 0; i < CHAR_BIT; i++) { /* Walking one */ + data = (1 << i); + if (!lpt_port_test(port, data, mask)) + ABORT; + } + + outb(iobase + lpt_data, 0); + outb(iobase + lpt_control, 0); + + mb->mb_iosize = LPT_NPORTS; + return 1; +} + +void +lptattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct lpt_softc *sc = (void *)self; + struct mainbus_attach_args *mb = aux; + int iobase = mb->mb_iobase; + + if (mb->mb_irq != IRQUNK) + printf("\n"); + else + printf(": polled\n"); + + sc->sc_iobase = iobase; + sc->sc_irq = mb->mb_irq; + sc->sc_state = 0; + outb(iobase + lpt_control, LPC_NINIT); + + if (mb->mb_irq != IRQUNK) { + sc->sc_ih.ih_func = lptintr; + sc->sc_ih.ih_arg = sc; +#if defined(INET) && defined(PLIP) + sc->sc_ih.ih_level = IPL_NET; + sc->sc_ih.ih_name = "lpt/plip"; + plipattach(sc, self->dv_unit); +#else + sc->sc_ih.ih_level = IPL_NONE; + sc->sc_ih.ih_name = "lpt"; +#endif + if (irq_claim(mb->mb_irq, &sc->sc_ih)) + panic("Cannot claim IRQ %d for lpt%d\n", mb->mb_irq, sc->sc_dev.dv_unit); + + } +#if defined(INET) && defined(PLIP) + else { + printf("Warning PLIP device needs IRQ driven lpt driver\n"); + } +#endif +} + +/* + * Reset the printer, then wait until it's selected and not busy. + */ +int +lptopen(dev, flag) + dev_t dev; + int flag; +{ + int unit = LPTUNIT(dev); + u_char flags = LPTFLAGS(dev); + struct lpt_softc *sc; + int iobase; + u_char control; + int error; + int spin; + + if (unit >= lpt_cd.cd_ndevs) + return ENXIO; + sc = lpt_cd.cd_devs[unit]; + if (!sc) + return ENXIO; + + if (sc->sc_irq == IRQUNK && (flags & LPT_NOINTR) == 0) + return ENXIO; + +#ifdef DIAGNOSTIC + if (sc->sc_state) + printf("%s: stat=0x%x not zero\n", sc->sc_dev.dv_xname, + sc->sc_state); +#endif + + if (sc->sc_state) + return EBUSY; + + sc->sc_state = LPT_INIT; + sc->sc_flags = flags; + lprintf("%s: open: flags=0x%x\n", sc->sc_dev.dv_xname, flags); + iobase = sc->sc_iobase; + + if ((flags & LPT_NOPRIME) == 0) { + /* assert INIT for 100 usec to start up printer */ + outb(iobase + lpt_control, LPC_SELECT); + delay(100); + } + + control = LPC_SELECT | LPC_NINIT; + outb(iobase + lpt_control, control); + + /* wait till ready (printer running diagnostics) */ + for (spin = 0; NOT_READY_ERR(); spin += STEP) { + if (spin >= TIMEOUT) { + sc->sc_state = 0; + return EBUSY; + } + + /* wait 1/4 second, give up if we get a signal */ + if (error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptopen", + STEP) != EWOULDBLOCK) { + sc->sc_state = 0; + return error; + } + } + + if ((flags & LPT_NOINTR) == 0) + control |= LPC_IENABLE; + if (flags & LPT_AUTOLF) + control |= LPC_AUTOLF; + sc->sc_control = control; + outb(iobase + lpt_control, control); + + sc->sc_inbuf = geteblk(LPT_BSIZE); + sc->sc_count = 0; + sc->sc_state = LPT_OPEN; + + if ((sc->sc_flags & LPT_NOINTR) == 0) + lptwakeup(sc); + + lprintf("%s: opened\n", sc->sc_dev.dv_xname); + return 0; +} + +int +not_ready(status, sc) + u_char status; + struct lpt_softc *sc; +{ + u_char new; + + status = (status ^ LPS_INVERT) & LPS_MASK; + new = status & ~sc->sc_laststatus; + sc->sc_laststatus = status; + + if (new & LPS_SELECT) + log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname); + else if (new & LPS_NOPAPER) + log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname); + else if (new & LPS_NERR) + log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname); + + return status; +} + + +void +lptwakeup(arg) + void *arg; +{ + struct lpt_softc *sc = arg; + int s; + + s = spltty(); + lptintr(sc); + splx(s); + + timeout(lptwakeup, sc, STEP); +} + +/* + * Close the device, and free the local line buffer. + */ +lptclose(dev, flag) + dev_t dev; + int flag; +{ + int unit = LPTUNIT(dev); + struct lpt_softc *sc = lpt_cd.cd_devs[unit]; + int iobase = sc->sc_iobase; + + if (sc->sc_count) + (void) pushbytes(sc); + + if ((sc->sc_flags & LPT_NOINTR) == 0) + untimeout(lptwakeup, sc); + + outb(iobase + lpt_control, LPC_NINIT); + sc->sc_state = 0; + outb(iobase + lpt_control, LPC_NINIT); + brelse(sc->sc_inbuf); + + lprintf("%s: closed\n", sc->sc_dev.dv_xname); + return 0; +} + +int +pushbytes(sc) + struct lpt_softc *sc; +{ + int iobase = sc->sc_iobase; + int error; + + if (sc->sc_flags & LPT_NOINTR) { + int spin, tic; + u_char control = sc->sc_control; + + while (sc->sc_count > 0) { + spin = 0; + while (NOT_READY()) { + if (++spin < sc->sc_spinmax) + continue; + tic = 0; + /* adapt busy-wait algorithm */ + sc->sc_spinmax++; + while (NOT_READY_ERR()) { + /* exponential backoff */ + tic = tic + tic + 1; + if (tic > TIMEOUT) + tic = TIMEOUT; + error = tsleep((caddr_t)sc, + LPTPRI | PCATCH, "lptpsh", tic); + if (error != EWOULDBLOCK) + return error; + } + break; + } + + outb(iobase + lpt_data, *sc->sc_cp++); + outb(iobase + lpt_control, control | LPC_STROBE); + sc->sc_count--; + outb(iobase + lpt_control, control); + + /* adapt busy-wait algorithm */ + if (spin*2 + 16 < sc->sc_spinmax) + sc->sc_spinmax--; + } + } else { + int s; + + while (sc->sc_count > 0) { + /* if the printer is ready for a char, give it one */ + if ((sc->sc_state & LPT_OBUSY) == 0) { + lprintf("%s: write %d\n", sc->sc_dev.dv_xname, + sc->sc_count); + s = spltty(); + (void) lptintr(sc); + splx(s); + } + if (error = tsleep((caddr_t)sc, LPTPRI | PCATCH, + "lptwrite2", 0)) + return error; + } + } + return 0; +} + +/* + * Copy a line from user space to a local buffer, then call putc to get the + * chars moved to the output queue. + */ +lptwrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + struct lpt_softc *sc = lpt_cd.cd_devs[LPTUNIT(dev)]; + size_t n; + int error = 0; + + while (n = min(LPT_BSIZE, uio->uio_resid)) { + uiomove(sc->sc_cp = sc->sc_inbuf->b_data, n, uio); + sc->sc_count = n; + error = pushbytes(sc); + if (error) { + /* + * Return accurate residual if interrupted or timed + * out. + */ + uio->uio_resid += sc->sc_count; + sc->sc_count = 0; + return error; + } + } + return 0; +} + +/* + * Handle printer interrupts which occur when the printer is ready to accept + * another char. + */ +int +lptintr(arg) + void *arg; +{ + struct lpt_softc *sc = arg; + int iobase = sc->sc_iobase; + +/*printf("lptintr:\n");*/ + +#if defined(INET) && defined(PLIP) + if (sc->sc_arpcom.ac_if.if_flags & IFF_UP) { + return(plipintr(sc)); + } +#endif + +#if 0 + if ((sc->sc_state & LPT_OPEN) == 0) + return 0; +#endif + + /* is printer online and ready for output */ + if (NOT_READY() && NOT_READY_ERR()) + return 0; + + if (sc->sc_count) { + u_char control = sc->sc_control; + /* send char */ + outb(iobase + lpt_data, *sc->sc_cp++); + outb(iobase + lpt_control, control | LPC_STROBE); + sc->sc_count--; + outb(iobase + lpt_control, control); + sc->sc_state |= LPT_OBUSY; + } else + sc->sc_state &= ~LPT_OBUSY; + + if (sc->sc_count == 0) { + /* none, wake up the top half to get more */ + wakeup((caddr_t)sc); + } + + return(1); +} + +int +lptioctl(dev, cmd, data, flag) + dev_t dev; + u_long cmd; + caddr_t data; + int flag; +{ + int error = 0; + + switch (cmd) { + default: + error = ENODEV; + } + + return error; +} + + +#if defined(INET) && defined(PLIP) + +#define PLIP_INTR_ENABLE (LPC_NINIT | LPC_SELECT | LPC_IENABLE) +#define PLIP_INTR_DISABLE (LPC_NINIT | LPC_SELECT) +#define PLIP_DATA (iobase + lpt_data) +#define PLIP_STATUS (iobase + lpt_status) +#define PLIP_CONTROL (iobase + lpt_control) +#define PLIP_REMOTE_TRIGGER 0x08 +#define PLIP_DELAY_UNIT 50 +#if PLIP_DELAY_UNIT > 0 +#define PLIP_DELAY DELAY(PLIP_DELAY_UNIT) +#else +#define PLIP_DELAY +#endif +#define PLIP_DEBUG_RX 0x01 +#define PLIP_DEBUG_TX 0x02 +#define PLIP_DEBUG_IF 0x04 +#define PLIP_DEBUG 0x07 +#if PLIP_DEBUG != 0 +static int plip_debug = PLIP_DEBUG; +#endif + +static void +plipattach(struct lpt_softc *sc, int unit) +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + + sc->sc_ifbuf = NULL; + ifp->if_unit = unit; + ifp->if_name = "plip"; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; + ifp->if_output = ether_output; + ifp->if_start = plipstart; + ifp->if_ioctl = plipioctl; + ifp->if_watchdog = 0; + + ifp->if_type = IFT_ETHER; + ifp->if_addrlen = 6; + ifp->if_hdrlen = 14; + ifp->if_mtu = PLIPMTU; + + if_attach(ifp); + ether_ifattach(ifp); + + printf("plip%d at lpt%d: mtu=%d,%d,%d", unit, unit, (int) ifp->if_mtu, + ifp->if_hdrlen, ifp->if_addrlen); + if (sizeof(struct ether_header) != 14) + printf(" ethhdr super kludge mode enabled\n"); + else + printf("\n"); + +#if NBPFILTER > 0 + bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); +#endif +} + +/* + * Process an ioctl request. + */ +static int +plipioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct proc *p = curproc; + struct lpt_softc *sc = (struct lpt_softc *) lpt_cd.cd_devs[ifp->if_unit]; + unsigned int iobase = sc->sc_iobase; + struct ifaddr *ifa = (struct ifaddr *)data; + struct ifreq *ifr = (struct ifreq *)data; + int s; + int error = 0; + +#if PLIP_DEBUG > 0 + printf("plipioctl: cmd=%08x ifp=%08x data=%08x\n", cmd, ifp, data); + printf("plipioctl: ifp->flags=%08x\n", ifp->if_flags); +#endif + + switch (cmd) { + + case SIOCSIFFLAGS: + if (((ifp->if_flags & IFF_UP) == 0) && + (ifp->if_flags & IFF_RUNNING)) { + ifp->if_flags &= ~IFF_RUNNING; +/* Deactive the parallel port */ +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_IF) + printf("plip: Disabling lpt irqs\n"); +#endif + outb(PLIP_DATA, 0x00); + outb(PLIP_CONTROL, PLIP_INTR_DISABLE); + sc->sc_state = 0; + + if (sc->sc_ifbuf) + free(sc->sc_ifbuf, M_DEVBUF); + + sc->sc_ifbuf = NULL; + } + if (((ifp->if_flags & IFF_UP)) && + ((ifp->if_flags & IFF_RUNNING) == 0)) { + if (sc->sc_state) { + error = EBUSY; + break; + } +/* if (!(ifp->if_flags & IFF_DEBUG)) + plip_debug = PLIP_DEBUG; + else + plip_debug = 0;*/ + sc->sc_state = LPT_OPEN | LPT_PLIP; + if (!sc->sc_ifbuf) + sc->sc_ifbuf = + malloc(ifp->if_mtu + ifp->if_hdrlen, + M_DEVBUF, M_WAITOK); + ifp->if_flags |= IFF_RUNNING; +/* This starts it running */ +/* Enable lpt interrupts */ + +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_IF) + printf("plip: Enabling lpt irqs\n"); +#endif + outb(PLIP_CONTROL, PLIP_INTR_ENABLE); + outb(PLIP_DATA, 0x00); + } + break; + + case SIOCSIFADDR: + if (ifa->ifa_addr->sa_family == AF_INET) { + if (!sc->sc_ifbuf) + sc->sc_ifbuf = + malloc(PLIPMTU + ifp->if_hdrlen, + M_DEVBUF, M_WAITOK); + + sc->sc_arpcom.ac_enaddr[0] = 0xfc; + sc->sc_arpcom.ac_enaddr[1] = 0xfc; + bcopy((caddr_t)&IA_SIN(ifa)->sin_addr, + (caddr_t)&sc->sc_arpcom.ac_enaddr[2], 4); + sc->sc_arpcom.ac_ipaddr = IA_SIN(ifa)->sin_addr; +#if defined(COMPAT_PLIP10) + if (ifp->if_flags & IFF_LINK0) { + int i; + sc->sc_arpcom.ac_enaddr[0] = 0xfd; + sc->sc_arpcom.ac_enaddr[1] = 0xfd; + for (i = sc->sc_adrcksum = 0; i < 5; i++) + sc->sc_adrcksum += sc->sc_arpcom.ac_enaddr[i]; + sc->sc_adrcksum *= 2; + } +#endif + ifp->if_flags |= IFF_RUNNING | IFF_UP; +#if 0 + for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { + struct sockaddr_dl *sdl; + if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && + sdl->sdl_family == AF_LINK) { + sdl->sdl_type = IFT_ETHER; + sdl->sdl_alen = ifp->if_addrlen; + bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, + LLADDR(sdl), ifp->if_addrlen); + break; + } + } +#endif +/* Looks the same as the start condition above */ +/* Enable lpt interrupts */ + +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_IF) + printf("plip: Enabling lpt irqs\n"); +#endif + outb(PLIP_CONTROL, PLIP_INTR_ENABLE); + outb(PLIP_DATA, 0x00); + + arp_ifinit(&sc->sc_arpcom, ifa); + } else + error = EAFNOSUPPORT; + break; + + case SIOCAIFADDR: + case SIOCDIFADDR: + case SIOCSIFDSTADDR: + if (ifa->ifa_addr->sa_family != AF_INET) + error = EAFNOSUPPORT; + break; + + case SIOCSIFMTU: + if ((error = suser(p->p_ucred, &p->p_acflag))) + return(error); + if (ifp->if_mtu != ifr->ifr_metric) { + ifp->if_mtu = ifr->ifr_metric; + if (sc->sc_ifbuf) { + s = splimp(); + + free(sc->sc_ifbuf, M_DEVBUF); + sc->sc_ifbuf = + malloc(ifp->if_mtu + ifp->if_hdrlen, + M_DEVBUF, M_WAITOK); + splx(s); + } + } + break; + + case SIOCGIFMTU: + ifr->ifr_metric = ifp->if_mtu; + break; + + default: + error = EINVAL; + } + return (error); +} + +static int +plipreceive(unsigned int iobase, u_char *buf, int len) +{ + int i; + u_char cksum = 0, c; + u_char c0, c1; + +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_RX) + printf("Rx: "); +#endif + + while (len--) { + i = PLIPMXSPIN2; +/* Receive a byte */ + +/* Wait for a steady handshake */ + while (1) { + c0 = inb(PLIP_STATUS); + if ((c0 & LPS_NBSY) == 0) { + c1 = inb(PLIP_STATUS); + if (c0 == c1) break; +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_RX) + printf("rx: %02x-%02x ", c0, c1); +#endif + } + --i; + if (i < 0) { +#if PLIP_DEBUG > 0 + printf("timeout rx lsn %02x\n", c0); +#endif + return(-1); + } + PLIP_DELAY; + } + c = (c0 >> 3) & 0x0f; + +/* Acknowledge */ + outb(PLIP_DATA, 0x10); + +/* Another handshake */ + i = PLIPMXSPIN2; + while (1) { + c0 = inb(PLIP_STATUS); + if (c0 & LPS_NBSY) { + c1 = inb(PLIP_STATUS); + if (c0 == c1) break; +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_RX) + printf("rx: %02x-%02x ", c0, c1); +#endif + } + --i; + if (i < 0) { +#if PLIP_DEBUG > 0 + printf("timeout rx msn %02x\n", c0); +#endif + return(-1); + } + PLIP_DELAY; + } + c = c | ((c0 << 1) & 0xf0); +/* Acknowledge */ + outb(PLIP_DATA, 0x00); +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_RX) + printf("%02x ", c); +#endif + + cksum += (*buf++ = c); + } +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_RX) + printf("\n"); +#endif + return(cksum); +} + +static int +plipintr(struct lpt_softc *sc) +{ + extern struct mbuf *m_devget(char *, int, int, struct ifnet *, void (*)()); + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + unsigned int iobase = sc->sc_iobase; + struct mbuf *m; + struct ether_header *eh; + u_char *p = sc->sc_ifbuf, minibuf[4]; + int c, s, len, cksum; + u_char c0; + +printf("plipintr:\n"); + +/* Get the status */ + + c0 = inb(PLIP_STATUS); +#if PLIP_DEBUG > 0 + if ((c0 & 0xf8) != 0xc0) { + printf("st5=%02x ", c0); + } +#endif + +/* Don't want ints while receiving */ + + outb(PLIP_CONTROL, PLIP_INTR_DISABLE); + + outb(PLIP_DATA, 0x01); /* send ACK */ /* via NERR */ + +#if defined(COMPAT_PLIP10) + if (ifp->if_flags & IFF_LINK0) { + if (plipreceive(iobase, minibuf, 3) < 0) goto err; + len = (minibuf[1] << 8) | minibuf[2]; + if (len > (ifp->if_mtu + ifp->if_hdrlen)) goto err; + + switch (minibuf[0]) { + case 0xfc: + p[0] = p[ 6] = ifp->ac_enaddr[0]; + p[1] = p[ 7] = ifp->ac_enaddr[1]; + p[2] = p[ 8] = ifp->ac_enaddr[2]; + p[3] = p[ 9] = ifp->ac_enaddr[3]; + p[4] = p[10] = ifp->ac_enaddr[4]; + p += 5; + if ((cksum = plipreceive(iobase, p, 1)) < 0) goto err; + p += 6; + if ((c = plipreceive(iobase, p, len - 11)) < 0) goto err; + cksum += c + sc->sc_adrcksum; + c = p[1]; p[1] = p[2]; p[2] = c; + cksum &= 0xff; + break; + case 0xfd: + if ((cksum = plipreceive(iobase, p, len)) < 0) goto err; + break; + default: + goto err; + } + } else +#endif + { + if (plipreceive(iobase, minibuf, 2) < 0) goto err; + len = (minibuf[1] << 8) | minibuf[0]; + if (len > (ifp->if_mtu + ifp->if_hdrlen)) { + log(LOG_NOTICE, "plip%d: packet > MTU\n", ifp->if_unit); + goto err; + } +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_RX) + printf("len=%d ", len); +#endif + if (sizeof(struct ether_header) != 14) { + if ((cksum = plipreceive(iobase, p, 14)) < 0) goto err; + if ((c = plipreceive(iobase, p+16, len-14)) < 0) goto err; + cksum += c; + len += 2; + } + else + if ((cksum = plipreceive(iobase, p, len)) < 0) goto err; + } + + if (plipreceive(iobase, minibuf, 1) < 0) goto err; + if ((cksum & 0xff) != minibuf[0]) { + printf("cksum=%d, %d, %d\n", cksum, c, minibuf[0]); + log(LOG_NOTICE, "plip%d: checksum error\n", ifp->if_unit); + goto err; + } + + outb(PLIP_DATA, 0x00); /* clear ACK */ /* via NERR */ +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_RX) + printf("done\n"); +#endif + s = splimp(); + + eh = (struct ether_header *)sc->sc_ifbuf; + + if ((m = m_devget(sc->sc_ifbuf + sizeof(struct ether_header), len - sizeof(struct ether_header), 0, ifp, NULL))) { + /* We assume that the header fit entirely in one mbuf. */ +/* eh = mtod(m, struct ether_header *);*/ +/* m->m_pkthdr.len -= sizeof(*eh);*/ +/* m->m_len -= sizeof(*eh);*/ +/* m->m_data += sizeof(*eh);*/ +/* printf("m->m_data=%08x ifbuf=%08x eh=%08x\n", m->m_data, sc->sc_ifbuf, eh);*/ + +#if NBPFILTER > 0 +/* + * Check if there's a BPF listener on this interface. + * If so, hand off the raw packet to bpf. + */ + if (sc->sc_arpcom.ac_if.if_bpf) { + bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m); + } +#endif + ether_input(ifp, eh, m); + } + splx(s); + sc->sc_iferrs = 0; + ifp->if_ipackets++; + +/* Allow ints again */ + + outb(PLIP_CONTROL, PLIP_INTR_ENABLE); + return(1); + +err: + outb(PLIP_DATA, 0x00); /* clear ACK */ /* via NERR */ + + ifp->if_ierrors++; + sc->sc_iferrs++; + if (sc->sc_iferrs > PLIPMXERRS + || (sc->sc_iferrs > 5 && (inb(iobase + lpt_status) & LPS_NBSY))) { + /* We are not able to send receive anything for now, + * so stop wasting our time and leave the interrupt + * disabled. + */ + if (sc->sc_iferrs == PLIPMXERRS + 1) + log(LOG_NOTICE, "plip%d: rx hard error\n", ifp->if_unit); +/* xxx i8255->port_a |= LPA_ACTIVE;*/ + } else +; +/* xxx i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;*/ + +/* Allow ints again */ + + outb(PLIP_CONTROL, PLIP_INTR_ENABLE); + return(1); +} + +static int +pliptransmit(unsigned int iobase, u_char *buf, int len) +{ + int i; + u_char cksum = 0, c; + u_char c0; +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("tx: len=%d ", len); +#endif + + while (len--) { + i = PLIPMXSPIN2; + cksum += (c = *buf++); +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("%02x ", c); +#endif +/* xxx while ((i8255->port_c & LPC_NBUSY) == 0) + if (i-- < 0) return -1; + i8255->port_b = c & 0x0f; + i8255->port_b = c & 0x0f | 0x10; + c >>= 4; + while ((i8255->port_c & LPC_NBUSY) != 0) + if (i-- < 0) return -1; + i8255->port_b = c | 0x10; + i8255->port_b = c; +*/ + +/* Send the nibble + handshake */ + + outb(PLIP_DATA, 0x00 | (c & 0x0f)); + outb(PLIP_DATA, 0x10 | (c & 0x0f)); + + while (1) { + c0 = inb(PLIP_STATUS); + if ((c0 & LPS_NBSY) == 0) + break; + if (--i == 0) { /* time out */ +#if PLIP_DEBUG > 0 + printf("timeout tx lsn %02x ", c0); +#endif + return(-1); + } + PLIP_DELAY; + } + + outb(PLIP_DATA, 0x10 | (c >> 4)); + outb(PLIP_DATA, 0x00 | (c >> 4)); + i = PLIPMXSPIN2; + while (1) { + c0 = inb(PLIP_STATUS); + if ((c0 & LPS_NBSY) != 0) + break; + if (--i == 0) { /* time out */ +#if PLIP_DEBUG > 0 + printf("timeout tx msn %02x ", c0); +#endif + return(-1); + } + PLIP_DELAY; + } + } +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("done\n"); +#endif + return(cksum); +} + +/* + * Setup output on interface. + */ +static void +plipstart(struct ifnet *ifp) +{ + struct lpt_softc *sc = (struct lpt_softc *) lpt_cd.cd_devs[ifp->if_unit]; + unsigned int iobase = sc->sc_iobase; + struct mbuf *m0, *m; + u_char minibuf[4], cksum; + int len, i, s; + u_char *p; + +#if PLIP_DEBUG != 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("plipstart: "); +#endif + if (ifp->if_flags & IFF_OACTIVE) + return; + ifp->if_flags |= IFF_OACTIVE; + + if (sc->sc_ifretry) + untimeout((void (*)(void *))plipstart, ifp); + + for (;;) { + s = splimp(); + IF_DEQUEUE(&ifp->if_snd, m0); + splx(s); + if (!m0) + break; + + for (len = 0, m = m0; m; m = m->m_next) { +#if PLIP_DEBUG > 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("len=%d %d\n", m->m_len, len); +#endif + len += m->m_len; + } +#if NBPFILTER > 0 + p = sc->sc_ifbuf; + for (m = m0; m; m = m->m_next) { + if (m->m_len == 0) + continue; + bcopy(mtod(m, u_char *), p, m->m_len); + p += m->m_len; + } + if (sc->sc_arpcom.ac_if.if_bpf) + bpf_tap(sc->sc_arpcom.ac_if.if_bpf, sc->sc_ifbuf, len); +#endif + if (sizeof(struct ether_header) != 14) + len -= 2; +#if defined(COMPAT_PLIP10) + if (ifp->if_flags & IFF_LINK0) { + minibuf[0] = 3; + minibuf[1] = 0xfd; + minibuf[2] = len >> 8; + minibuf[3] = len; + } else +#endif + { + minibuf[0] = 2; + minibuf[1] = len; + minibuf[2] = len >> 8; + } + +/*yyy for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) != 0; i--) + if (i < 0) goto retry;*/ + + /* Trigger remote interrupt */ + +#if PLIP_DEBUG > 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("st=%02x ", inb(PLIP_STATUS)); +#endif + if (inb(PLIP_STATUS) & LPS_NERR) { + for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) != 0; i--) + PLIP_DELAY; +#if PLIP_DEBUG > 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("st1=%02x ", inb(PLIP_STATUS)); +#endif + } + + outb(PLIP_DATA, PLIP_REMOTE_TRIGGER); + for (i = PLIPMXSPIN1; (inb(PLIP_STATUS) & LPS_NERR) == 0; i--) { + if (i < 0 || (i > PLIPMXSPIN1/3 + && inb(PLIP_STATUS) & LPS_NACK)) { +#if PLIP_DEBUG > 0 + printf("trigger ack timeout\n"); +#endif + goto retry; + } + PLIP_DELAY; + } +#if PLIP_DEBUG > 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("st3=%02x ", inb(PLIP_STATUS)); +#endif + +/* Don't want ints while transmitting */ + + outb(PLIP_CONTROL, PLIP_INTR_DISABLE); + + if (pliptransmit(iobase, minibuf + 1, minibuf[0]) < 0) goto retry; + for (cksum = 0, m = m0; m; m = m->m_next) { + if (sizeof(struct ether_header) != 14 && m == m0) { + i = pliptransmit(iobase, mtod(m, u_char *), 14); + if (i < 0) goto retry; + cksum += i; + i = pliptransmit(iobase, mtod(m, u_char *)+16, m->m_len-16); + if (i < 0) goto retry; + } + else + i = pliptransmit(iobase, mtod(m, u_char *), m->m_len); + if (i < 0) goto retry; + cksum += i; + } + if (pliptransmit(iobase, &cksum, 1) < 0) goto retry; + i = PLIPMXSPIN2; + while ((inb(PLIP_STATUS) & LPS_NBSY) == 0) + if (i-- < 0) goto retry; + + outb(iobase + lpt_data, 0x00); +/* Re-enable ints */ + + outb(PLIP_CONTROL, PLIP_INTR_ENABLE); + + ifp->if_opackets++; + ifp->if_obytes += len + 4; + sc->sc_ifretry = 0; + s = splimp(); + m_freem(m0); + splx(s); + } + ifp->if_flags &= ~IFF_OACTIVE; + return; + +retry: +#if PLIP_DEBUG > 0 + if (plip_debug & PLIP_DEBUG_TX) + printf("retry: %02x", inb(iobase + lpt_status)); +#endif + if (inb(PLIP_STATUS & LPS_NACK)) + ifp->if_collisions++; + else + ifp->if_oerrors++; + if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == (IFF_RUNNING | IFF_UP) + && sc->sc_ifretry < PLIPMXRETRY) { + sc->sc_ifretry++; + s = splimp(); + IF_PREPEND(&ifp->if_snd, m0); + splx(s); + timeout((void (*)(void *))plipstart, ifp, PLIPRETRY); + } else { + if (sc->sc_ifretry == PLIPMXRETRY) { + sc->sc_ifretry++; + log(LOG_NOTICE, "plip%d: tx hard error\n", ifp->if_unit); + } + s = splimp(); + m_freem(m0); + splx(s); + } + ifp->if_flags &= ~IFF_OACTIVE; + outb(PLIP_DATA, 0x00); + +/* Re-enable ints */ + + outb(PLIP_CONTROL, PLIP_INTR_ENABLE); +/*xxx if (sc->sc_iferrs > PLIPMXERRS) + i8255->port_a |= LPA_ACTIVE; + else + i8255->port_a |= LPA_ACKENABLE | LPA_ACTIVE;*/ + return; +} + +#endif diff --git a/sys/arch/arm32/mainbus/lptreg.h b/sys/arch/arm32/mainbus/lptreg.h new file mode 100644 index 00000000000..f909794337d --- /dev/null +++ b/sys/arch/arm32/mainbus/lptreg.h @@ -0,0 +1,64 @@ +/* $NetBSD: lptreg.h,v 1.2 1996/03/18 20:50:03 mark 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. + * + * @(#)lptreg.h 1.1 (Berkeley) 12/19/90 + */ + +/* + * AT Parallel Port (for lineprinter) + * Interface port and bit definitions + * Written by William Jolitz 12/18/90 + * Copyright (C) William Jolitz 1990 + */ + +#define lpt_data 0 /* Data to/from printer (R/W) */ + +#define lpt_status 4 /* Status of printer (R) */ +#define LPS_NERR 0x08 /* printer no error */ +#define LPS_SELECT 0x10 /* printer selected */ +#define LPS_NOPAPER 0x20 /* printer out of paper */ +#define LPS_NACK 0x40 /* printer no ack of data */ +#define LPS_NBSY 0x80 /* printer no ack of data */ + +#define lpt_control 8 /* Control printer (R/W) */ +#define LPC_STROBE 0x01 /* strobe data to printer */ +#define LPC_AUTOLF 0x02 /* automatic linefeed */ +#define LPC_NINIT 0x04 /* initialize printer */ +#define LPC_SELECT 0x08 /* printer selected */ +#define LPC_IENABLE 0x10 /* printer out of paper */ + +#define LPT_NPORTS 32 diff --git a/sys/arch/arm32/mainbus/mainbus.c b/sys/arch/arm32/mainbus/mainbus.c new file mode 100644 index 00000000000..7caade580dd --- /dev/null +++ b/sys/arch/arm32/mainbus/mainbus.c @@ -0,0 +1,136 @@ +/* $NetBSD: mainbus.c,v 1.3 1996/03/20 18:38:00 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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 + * + * mainbus.c + * + * mainbus configuration + * + * Created : 15/12/94 + * Last updated : 03/07/95 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +int mainbusmatch __P((struct device *, void *, void *)); +void mainbusattach __P((struct device *, struct device *, void *)); + +struct cfattach mainbus_ca = { + sizeof(struct device), mainbusmatch, mainbusattach +}; + +struct cfdriver mainbus_cd = { + NULL, "mainbus", DV_DULL, 1 +}; + +int +mainbusmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + return (1); +} + +int +mainbusprint(aux, mainbus) + void *aux; + char *mainbus; +{ + struct mainbus_attach_args *mb = aux; + + if (mb->mb_iobase) + printf(" base 0x%x", mb->mb_iobase); + if (mb->mb_iosize > 1) + printf("-0x%x", mb->mb_iobase + mb->mb_iosize - 1); + if (mb->mb_irq != -1) + printf(" irq %d", mb->mb_irq); + if (mb->mb_drq != -1) + printf(" drq 0x%08x", mb->mb_drq); + +/* XXXX print flags */ + return (QUIET); +} + + +void +mainbusscan(parent, match) + struct device *parent; + void *match; +{ + struct device *dev = match; + struct cfdata *cf = dev->dv_cfdata; + struct mainbus_attach_args mb; + + if (cf->cf_fstate == FSTATE_STAR) + panic("eekkk, I'm stuffed"); + + if (cf->cf_loc[0] == -1) { + mb.mb_iobase = 0; + mb.mb_iosize = 0; + mb.mb_drq = -1; + mb.mb_irq = -1; + } else { + mb.mb_iobase = cf->cf_loc[0] + IO_CONF_BASE; + mb.mb_iosize = 0; + mb.mb_drq = cf->cf_loc[1]; + mb.mb_irq = cf->cf_loc[2]; + } + if ((*cf->cf_attach->ca_match)(parent, dev, &mb) > 0) + config_attach(parent, dev, &mb, mainbusprint); + else + free(dev, M_DEVBUF); +} + +void +mainbusattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + printf("\n"); + + config_scan(mainbusscan, self); +} + +/* End of mainbus.c */ diff --git a/sys/arch/arm32/mainbus/mainbus.h b/sys/arch/arm32/mainbus/mainbus.h new file mode 100644 index 00000000000..d0ae78e8c9b --- /dev/null +++ b/sys/arch/arm32/mainbus/mainbus.h @@ -0,0 +1,62 @@ +/* $NetBSD: mainbus.h,v 1.2 1996/03/18 20:50:05 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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 + * + * mainbus.c + * + * mainbus configuration + * + * Created : 15/12/94 + */ + +/* + * mainbus driver attach arguments + */ + +struct mainbus_attach_args { + u_int mb_iobase; /* base i/o address */ + int mb_iosize; /* span of ports used */ + int mb_irq; /* interrupt request */ + int mb_drq; /* DMA request */ + void *mb_aux; /* driver specific */ +}; + +#define DRQUNK -1 +#define INTUNK -1 +#define IRQUNK -1 + +/* End of mainbus.h */ + + diff --git a/sys/arch/arm32/mainbus/pms.c b/sys/arch/arm32/mainbus/pms.c new file mode 100644 index 00000000000..8339e1ab8a0 --- /dev/null +++ b/sys/arch/arm32/mainbus/pms.c @@ -0,0 +1,612 @@ +/* $NetBSD: pms.c,v 1.1 1996/03/28 21:50:19 mark Exp $ */ + +/*- + * Copyright (c) 1996 D.C. Tsen + * Copyright (c) 1994 Charles Hannum. + * Copyright (c) 1992, 1993 Erik Forsberg. + * 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 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 AUTHORS ``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 AUTHORS 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:pms.c,v 1.24 1995/12/24 02:30:28 mycroft Exp + */ + +/* + * Ported from 386 version of PS/2 mouse driver. + * D.C. Tsen + */ + +#include "pms.h" +#if NPMS > 1 +#error Only one PS/2 style mouse may be configured into your system. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* mouse commands */ +#define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */ +#define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */ +#define PMS_SET_RES 0xe8 /* set resolution */ +#define PMS_GET_SCALE 0xe9 /* get scaling factor */ +#define PMS_SET_STREAM 0xea /* set streaming mode */ +#define PMS_SET_SAMPLE 0xf3 /* set sampling rate */ +#define PMS_DEV_ENABLE 0xf4 /* mouse on */ +#define PMS_DEV_DISABLE 0xf5 /* mouse off */ +#define PMS_RESET 0xff /* reset */ + +#define PMS_CHUNK 128 /* chunk size for read */ +#define PMS_BSIZE (20*64) /* buffer size */ + +struct pms_softc { /* driver status information */ + struct device sc_dev; + irqhandler_t sc_ih; + + struct proc *proc; + struct clist sc_q; + struct selinfo sc_rsel; + u_int sc_state; /* mouse driver state */ +#define PMS_OPEN 0x01 /* device is open */ +#define PMS_ASLP 0x02 /* waiting for mouse data */ + u_int sc_status; /* mouse button status */ + int sc_x, sc_y; /* accumulated motion in the X,Y axis */ + int boundx, boundy, bounda, boundb; /* Bounding box. x,y is bottom left */ + int origx, origy; + int lastx, lasty, lastb; +}; + +int pmsprobe __P((struct device *, void *, void *)); +void pmsattach __P((struct device *, struct device *, void *)); +int pmsintr __P((void *)); + +struct cfattach pms_ca = { + sizeof(struct pms_softc), pmsprobe, pmsattach +}; + +struct cfdriver pms_cd = { + NULL, "pms", DV_DULL +}; + +#define PMSUNIT(dev) (minor(dev)) + +static inline void +pms_flush() +{ + while (inb(IOMD_MSCR) & 0x20) { + delay(6); + (void) inb(IOMD_MSDATA); + delay(6); + (void) inb(IOMD_MSDATA); + delay(6); + (void) inb(IOMD_MSDATA); + } +} + +static void +cmd_mouse(unsigned char cmd) +{ + unsigned char c; + int i = 0; + int retry = 10; + + for (i = 0; i < 1000; i++) { + if (inb(IOMD_MSCR) & 0x80) + break; + delay(2); + } + if (i == 1000) + printf("Mouse transmit not ready\n"); + +resend: + outb(IOMD_MSDATA, cmd); + delay(2); + c = inb(IOMD_MSCR) & (unsigned char) 0xff; + while (!(c & (unsigned char) 0x20)) { + delay(1); + c = inb(IOMD_MSCR); + } + + delay(10000); + + c = inb(IOMD_MSDATA) & 0xff; + if ((c == 0xFA) || (c == 0xEE)) + return; + + if (--retry) { + pms_flush(); + goto resend; + } + + printf("Mouse cmd failed, cmd = %x, status = %x\n", cmd, c); + return; +} + +int +pmsprobe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + /*struct mainbus_attach_args *mb = aux;*/ + int i, j; + int mid; + int id; + +/* Make sure we have an IOMD we understand */ + + id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8); + +/* So far I only know about this IOMD */ + + switch (id) { + case RPC600_IOMD_ID: + return(0); + break; + case RC7500_IOC_ID: + break; + default: + printf("pms: Unknown IOMD id=%04x", id); + return(0); + break; + } + + outb(IOMD_MSCR, 0x08); /* enable the mouse */ + + i = 0; + while ((inb(IOMD_MSCR) & 0x03) != 0x03) { + if (i++ > 10) { + printf("Mouse not found, status = <%x>.\n", inb(IOMD_MSCR)); + return(0); + } + pms_flush(); + delay(2); + outb(IOMD_MSCR, 0x08); + } + + pms_flush(); + + /* + * Disable, reset and enable the mouse. + */ + cmd_mouse(PMS_DEV_DISABLE); + cmd_mouse(PMS_RESET); + delay(300000); + j = 10; + i = 0; + while ((mid = inb(IOMD_MSDATA)) != 0xAA) { + if (++i > 500) { + if (--j < 0) { + printf("Mouse Reset failed, status = <%x>.\n", mid); + return(0); + } + pms_flush(); + cmd_mouse(PMS_RESET); + i = 0; + } + delay(100000); + } + mid = inb(IOMD_MSDATA); +#if 0 + cmd_mouse(PMS_SET_RES); + cmd_mouse(3); /* 8 counts/mm */ + cmd_mouse(PMS_SET_SCALE21); + cmd_mouse(PMS_SET_SAMPLE); + cmd_mouse(100); /* 100 samples/sec */ + cmd_mouse(PMS_SET_STREAM); +#endif + cmd_mouse(PMS_DEV_ENABLE); + return 1; +} + +void +pmsattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct pms_softc *sc = (void *)self; + struct mainbus_attach_args *mb = aux; + + printf("\n"); + + /* Other initialization was done by pmsprobe. */ + sc->sc_state = 0; + sc->origx = 0; + sc->origy = 0; + sc->boundx = -4095; + sc->boundy = -4095; + sc->bounda = 4096; + sc->boundb = 4096; + + sc->sc_ih.ih_func = pmsintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_TTY; + sc->sc_ih.ih_name = "pms"; + if (mb->mb_irq != IRQUNK) + sc->sc_ih.ih_num = mb->mb_irq; + else +#ifdef RC7500 + sc->sc_ih.ih_num = IRQ_MSDRX; +#else + panic("pms: No IRQ specified for pms interrupt handler\n"); +#endif +} + +int +pmsopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + int unit = PMSUNIT(dev); + struct pms_softc *sc; + + if (unit >= pms_cd.cd_ndevs) + return ENXIO; + sc = pms_cd.cd_devs[unit]; + if (!sc) + return ENXIO; + + if (sc->sc_state & PMS_OPEN) + return EBUSY; + + if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1) + return ENOMEM; + + sc->proc = p; + sc->sc_state |= PMS_OPEN; + sc->sc_status = 0; + sc->sc_x = sc->sc_y = 0; + sc->lastx = -1; + sc->lasty = -1; + sc->lastb = -1; + + if (irq_claim(IRQ_INSTRUCT, &sc->sc_ih) == -1) + panic("Cannot claim MOUSE IRQ\n"); + + return 0; +} + +int +pmsclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)]; + + if (irq_release(IRQ_INSTRUCT, &sc->sc_ih) != 0) + panic("Cannot release MOUSE IRQ\n"); + + sc->proc = NULL; + sc->sc_state &= ~PMS_OPEN; + sc->sc_x = sc->sc_y = 0; + + clfree(&sc->sc_q); + + return 0; +} + +int +pmsread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)]; + int s; + int error = 0; + size_t length; + u_char buffer[PMS_CHUNK]; + + /* Block until mouse activity occured. */ + + s = spltty(); + while (sc->sc_q.c_cc == 0) { + if (flag & IO_NDELAY) { + splx(s); + return EWOULDBLOCK; + } + sc->sc_state |= PMS_ASLP; + if (error = tsleep((caddr_t)sc, (PZERO | PCATCH), "pmsread", 0)) { + sc->sc_state &= ~PMS_ASLP; + splx(s); + return error; + } + } + + /* Transfer as many chunks as possible. */ + + while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) { + length = min(sc->sc_q.c_cc, uio->uio_resid); + if (length > sizeof(buffer)) + length = sizeof(buffer); + + /* Remove a small chunk from the input queue. */ + (void) q_to_b(&sc->sc_q, buffer, length); + + /* Copy the data to the user process. */ + if (error = uiomove(buffer, length, uio)) + break; + } + splx(s); + + return error; +} + +int +pmsioctl(dev, cmd, addr, flag, p) + dev_t dev; + u_long cmd; + caddr_t addr; + int flag; + struct proc *p; +{ + struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)]; + struct mouseinfo info; + int s; + int error = 0; + + s = spltty(); + + switch (cmd) { + case MOUSEIOC_SETSTATE: + printf("MOUSEIOC_SETSTATE called\n"); + break; + case MOUSEIOC_WRITEX: + sc->sc_x = *(int *) addr; + break; + case MOUSEIOC_WRITEY: + sc->sc_y = *(int *) addr; + break; + case MOUSEIOC_SETBOUNDS: + { + register struct mouse_boundingbox *bo = (void *) addr; + sc->boundx = bo->x; sc->boundy = bo->y; + sc->bounda = bo->a; sc->boundb = bo->b; + break; + } + case MOUSEIOC_SETORIGIN: + { + register struct mouse_origin *oo = (void *) addr; + sc->origx = oo->x; + sc->origy = oo->y; + break; + } + case MOUSEIOC_GETBOUNDS: + { + register struct mouse_boundingbox *bo = (void *) addr; + bo->x = sc->boundx; bo->y = sc->boundy; + bo->a = sc->bounda; bo->b = sc->boundb; + break; + } + case MOUSEIOC_GETORIGIN: + { + register struct mouse_origin *oo = (void *) addr; + oo->x = sc->origx; + oo->y = sc->origy; + break; + } + case MOUSEIOC_GETSTATE: + printf("MOUSEIOC_GETSTATE called\n"); + /* + * Fall through. + */ +/* case MOUSEIOCREAD:*/ + + info.status = sc->sc_status; + if (sc->sc_x || sc->sc_y) + info.status |= MOVEMENT; + +#if 1 + info.xmotion = sc->sc_x; + info.ymotion = sc->sc_y; +#else + if (sc->sc_x > sc->bounda) + info.xmotion = sc->bounda; + else if (sc->sc_x < sc->boundx) + info.xmotion = sc->boundx; + else + info.xmotion = sc->sc_x; + + if (sc->sc_y > sc->boundb) + info.ymotion = sc->boundb; + else if (sc->sc_y < sc->boundy) + info.ymotion = sc->boundy; + else + info.ymotion = sc->sc_y; +#endif + + /* Reset historical information. */ + sc->sc_x = sc->sc_y = 0; + sc->sc_status &= ~BUTCHNGMASK; + ndflush(&sc->sc_q, sc->sc_q.c_cc); + + error = copyout(&info, addr, sizeof(struct mouseinfo)); + break; + + default: + error = EINVAL; + break; + } + splx(s); + + return error; +} + +/* Masks for the first byte of a packet */ +#define PS2LBUTMASK 0x01 +#define PS2RBUTMASK 0x02 +#define PS2MBUTMASK 0x04 + +#define XNEG_MASK 0x10 +#define YNEG_MASK 0x20 + +int +pmsintr(arg) + void *arg; +{ + struct pms_softc *sc = arg; + static int state = 0; + static u_char buttons; + u_char changed; + static int dx, dy; + int dosignal = 0; + int s; + u_char b; + struct mousebufrec mbuffer; + + if ((sc->sc_state & PMS_OPEN) == 0) { + /* Interrupts are not expected. Discard the byte. */ + pms_flush(); + return(-1); + } + + switch (state) { + + case 0: + buttons = inb(IOMD_MSDATA); + if ((buttons & 0xc0) == 0) + ++state; + break; + + case 1: + dx = inb(IOMD_MSDATA); + dx = (buttons & XNEG_MASK) ? -dx : dx; + ++state; + break; + + case 2: + dy = inb(IOMD_MSDATA); + dy = (buttons & YNEG_MASK) ? -dy : dy; + state = 0; + + buttons = ((buttons & PS2LBUTMASK) << 2) | + ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1); + /* + * Ahhh, the Xarm server interrupt button bits reversed. + * If bit is set to 1, it means button is not pressed which is + * not what PS/2 mouse button bits said. Since we are simulating + * the quadmouse, that's not too picky about it. + */ + buttons ^= BUTSTATMASK; + changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3; + sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed; + + if (dx || dy || changed) { + if (dx < 0) + dx = -(256 + dx); + if (dy < 0) + dy = -(256 + dy); + + /* Update accumulated movements. */ + sc->sc_x += dx; + sc->sc_y += dy; + + if (sc->sc_x > sc->bounda) + sc->sc_x = sc->bounda; + else if (sc->sc_x < sc->boundx) + sc->sc_x = sc->boundx; + + if (sc->sc_y > sc->boundb) + sc->sc_y = sc->boundb; + else if (sc->sc_y < sc->boundy) + sc->sc_y = sc->boundy; + + if (sc->sc_q.c_cc == 0) { + dosignal = 1; + } + + /* Add this event to the queue. */ + b = buttons & BUTSTATMASK; + mbuffer.status = b | (b ^ sc->lastb) << 3 + | (((sc->sc_x==sc->lastx) && (sc->sc_y==sc->lasty))?0:0x40); + mbuffer.x = sc->sc_x * 2; + mbuffer.y = sc->sc_y * 2; + microtime(&mbuffer.event_time); + s = spltty(); + (void) b_to_q((char *)&mbuffer, sizeof(mbuffer), &sc->sc_q); + (void) splx(s); + sc->lastx = sc->sc_x; + sc->lasty = sc->sc_y; + sc->lastb = b; + + selwakeup(&sc->sc_rsel); + if (sc->sc_state & PMS_ASLP) { + sc->sc_state &= ~PMS_ASLP; + wakeup((caddr_t)sc); + } + if (dosignal) + psignal(sc->proc, SIGIO); + } + + break; + } + + return(0); +} + +int +pmsselect(dev, rw, p) + dev_t dev; + int rw; + struct proc *p; +{ + struct pms_softc *sc = pms_cd.cd_devs[PMSUNIT(dev)]; + int s; + int ret; + + if (rw == FWRITE) + return 0; + + s = spltty(); + if (!sc->sc_q.c_cc) { + selrecord(p, &sc->sc_rsel); + ret = 0; + } else + ret = 1; + splx(s); + + return ret; +} diff --git a/sys/arch/arm32/mainbus/qmouse.c b/sys/arch/arm32/mainbus/qmouse.c new file mode 100644 index 00000000000..b2a6447a073 --- /dev/null +++ b/sys/arch/arm32/mainbus/qmouse.c @@ -0,0 +1,440 @@ +/* $NetBSD: qmouse.c,v 1.5 1996/03/28 21:56:40 mark Exp $ */ + +/* + * Copyright (c) Scott Stevens 1995 All rights reserved + * Copyright (c) Melvin Tang-Richardson 1995 All rights reserved + * Copyright (c) Mark Brinicombe 1995 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 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. + */ + +/* + * Quadrature mouse driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "quadmouse.h" + +#define TIMER1_COUNT 40000 /* 50Hz */ + +#define QMOUSE_BSIZE 12*64 + +struct quadmouse_softc { + struct device sc_device; + irqhandler_t sc_ih; + int sc_iobase; + struct selinfo sc_rsel; +#define QMOUSE_OPEN 0x01 +#define QMOUSE_ASLEEP 0x02 + int sc_state; + int boundx, boundy, bounda, boundb; /* Bounding box. x,y is bottom left */ + int origx, origy; + int xmult, ymult; /* Multipliers */ + int lastx, lasty, lastb; + struct proc *proc; + struct clist buffer; +}; + +int quadmouseprobe __P((struct device *, void *, void *)); +void quadmouseattach __P((struct device *, struct device *, void *)); +int quadmouseopen __P((dev_t, int, int, struct proc *)); +int quadmouseclose __P((dev_t, int, int, struct proc *)); + +int strncmp __P((const char *, const char *, size_t)); + +int quadmouseintr (struct quadmouse_softc *); + +struct cfattach quadmouse_ca = { + sizeof(struct quadmouse_softc), quadmouseprobe, quadmouseattach +}; + +struct cfdriver quadmouse_cd = { + NULL, "quadmouse", DV_DULL +}; + + +int +quadmouseprobe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ +/* struct mainbus_attach_args *mb = aux;*/ + int id; + +/* Make sure we have an IOMD we understand */ + + id = ReadByte(IOMD_ID0) | (ReadByte(IOMD_ID1) << 8); + +/* So far I only know about this IOMD */ + + switch (id) { + case RPC600_IOMD_ID: + return(1); + break; + default: + printf("quadmouse: Unknown IOMD id=%04x", id); + break; + } + + return(0); +} + + +void +quadmouseattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct quadmouse_softc *sc = (void *)self; + struct mainbus_attach_args *mb = aux; + + sc->sc_iobase = mb->mb_iobase; + +/* Check for a known IOMD chip */ + + sc->sc_ih.ih_func = quadmouseintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_TTY; + sc->sc_ih.ih_name = "T1 quadmouse"; + +/* Set up origin and multipliers */ + + sc->origx = 0; + sc->origy = 0; + sc->xmult = 2; + sc->ymult = 2; + +/* Set up bounding box */ + + sc->boundx = -4095; + sc->boundy = -4095; + sc->bounda = 4096; + sc->boundb = 4096; + + sc->sc_state = 0; + + WriteWord(IOMD_MOUSEX, sc->origx); + WriteWord(IOMD_MOUSEY, sc->origy); + + printf("\n"); +} + + +int +quadmouseopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct quadmouse_softc *sc; + int unit = minor(dev); + + if (unit >= quadmouse_cd.cd_ndevs) + return(ENXIO); + + sc = quadmouse_cd.cd_devs[unit]; + + if (!sc) return(ENXIO); + + if (sc->sc_state & QMOUSE_OPEN) return(EBUSY); + + sc->proc = p; + + sc->lastx = -1; + sc->lasty = -1; + sc->lastb = -1; + + /* initialise buffer */ + if (clalloc(&sc->buffer, QMOUSE_BSIZE, 0) == -1) + return(ENOMEM); + + sc->sc_state |= QMOUSE_OPEN; + + WriteByte(IOMD_T1LOW, (TIMER1_COUNT >> 0) & 0xff); + WriteByte(IOMD_T1HIGH, (TIMER1_COUNT >> 8) & 0xff); + WriteByte(IOMD_T1GO, 0); + + if (irq_claim(IRQ_TIMER1, &sc->sc_ih)) + panic("Cannot claim TIMER1 IRQ for quadmouse%d\n", sc->sc_device.dv_unit); + + return(0); +} + + +int +quadmouseclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + int unit = minor (dev); + struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit]; + + if (irq_release(IRQ_TIMER1, &sc->sc_ih) != 0) + panic("Cannot release IRA\n"); + + sc->proc = NULL; + sc->sc_state = 0; + + clfree(&sc->buffer); + + return(0); +} + +int +quadmouseread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit]; + int error; + int s; + int length; + u_char buffer[128]; + + s=spltty(); + while(sc->buffer.c_cc==0) { + if(flag & IO_NDELAY) { + (void)splx(s); + return(EWOULDBLOCK); + } + sc->sc_state |= QMOUSE_ASLEEP; + if((error = tsleep((caddr_t)sc, PZERO | PCATCH, "quadmouseread", 0))) { + sc->sc_state &= ~QMOUSE_ASLEEP; + (void)splx(s); + return(error); + } + } + + while(sc->buffer.c_cc>0 && uio->uio_resid>0) { + length=min(sc->buffer.c_cc, uio->uio_resid); + if(length>sizeof(buffer)) + length=sizeof(buffer); + + (void) q_to_b(&sc->buffer, buffer, length); + + if(error = (uiomove(buffer, length, uio))) + break; + } + (void)splx(s); + return(error); +} + + +#define FMT_START int x = ReadWord(IOMD_MOUSEX)&0xffff; \ + int y = ReadWord(IOMD_MOUSEY)&0xffff; \ + int b = ReadByte(IO_MOUSE_BUTTONS)&0x70; \ + if(x&0x8000) x|=0xffff0000; \ + if(y&0x8000) y|=0xffff0000; \ + x = (x - sc->origx); \ + y = (y - sc->origy); \ + if (x<(sc->boundx)) x = sc->boundx; \ + WriteWord(IOMD_MOUSEX, x + sc->origx); \ + if (x>(sc->bounda)) x = sc->bounda; \ + WriteWord(IOMD_MOUSEX, x + sc->origx); \ + if (y<(sc->boundy)) y = sc->boundy; \ + WriteWord(IOMD_MOUSEY, y + sc->origy); \ + if (y>(sc->boundb)) y = sc->boundb; \ + WriteWord(IOMD_MOUSEY, y + sc->origy); \ + x=x*sc->xmult; \ + y=y*sc->ymult; + +#define FMT_END + + +int +quadmouseioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct quadmouse_softc *sc = quadmouse_cd.cd_devs[minor(dev)]; + + switch (cmd) { + case MOUSEIOC_WRITEX: + WriteWord(IOMD_MOUSEX, *(int *)data+sc->origx); + return 0; + case MOUSEIOC_WRITEY: + WriteWord(IOMD_MOUSEY, *(int *)data+sc->origy); + return 0; + case MOUSEIOC_SETSTATE: + { + register struct mouse_state *co = (void *)data; + WriteWord(IOMD_MOUSEX, co->x); + WriteWord(IOMD_MOUSEY, co->y); + + /* Silly, but here for completeness, just incase */ + /* the hardware supports it *giggle* */ + +/* This is not writable -- mark -- technically this should fault */ + +/* WriteWord ( IO_MOUSE_BUTTONS, co->buttons );*/ + return 0; + } + case MOUSEIOC_SETBOUNDS: + { + register struct mouse_boundingbox *bo = (void *)data; + sc->boundx = bo->x; sc->boundy = bo->y; + sc->bounda = bo->a; sc->boundb = bo->b; + return 0; + } + case MOUSEIOC_SETORIGIN: + { + register struct mouse_origin *oo = (void *)data; +/* int oldx, oldy;*/ + /* Need to fix up! */ + sc->origx = oo->x; + sc->origy = oo->y; + return 0; + } + case MOUSEIOC_GETSTATE: + { + register struct mouse_state *co = (void *)data; + FMT_START + co->x = x; + co->y = y; + co->buttons = b ^ 0x70; + FMT_END + return 0; + } + case MOUSEIOC_GETBOUNDS: + { + register struct mouse_boundingbox *bo = (void *)data; + bo->x = sc->boundx; bo->y = sc->boundy; + bo->a = sc->bounda; bo->b = sc->boundb; + return 0; + } + case MOUSEIOC_GETORIGIN: + { + register struct mouse_origin *oo = (void *)data; + oo->x = sc->origx; + oo->y = sc->origy; + return 0; + } + } + + return (EINVAL); +} + + +int +quadmouseintr(sc) + struct quadmouse_softc *sc; +{ + int s; + struct mousebufrec buffer; + int dosignal=0; + + FMT_START + + b &= 0x70; + b >>= 4; + if (x != sc->lastx || y != sc->lasty || b != sc->lastb) { + /* Mouse state changed */ + buffer.status = b | ( b ^ sc->lastb) << 3 | (((x==sc->lastx) && (y==sc->lasty))?0:0x40); + buffer.x = x; + buffer.y = y; + microtime(&buffer.event_time); + + if(sc->buffer.c_cc==0) + dosignal=1; + + s=spltty(); + (void) b_to_q((char *)&buffer, sizeof(buffer), &sc->buffer); + (void)splx(s); + selwakeup(&sc->sc_rsel); + + if(sc->sc_state & QMOUSE_ASLEEP) { + sc->sc_state &= ~QMOUSE_ASLEEP; + wakeup((caddr_t)sc); + } + + if(dosignal) + psignal(sc->proc, SIGIO); + + sc->lastx = x; + sc->lasty = y; + sc->lastb = b; + } + + FMT_END + return(0); +} + +int +quadmouseselect(dev, rw, p) + dev_t dev; + int rw; + struct proc *p; +{ + int unit = minor(dev); + struct quadmouse_softc *sc = quadmouse_cd.cd_devs[unit]; + int s; + + if(rw == FWRITE) + return 0; + + s=spltty(); + if(sc->buffer.c_cc > 0) { + selrecord(p, &sc->sc_rsel); + (void)splx(s); + return 0; + } + (void)splx(s); + return 1; +} + +/* End of quadmouse.c */ diff --git a/sys/arch/arm32/mainbus/rtc.c b/sys/arch/arm32/mainbus/rtc.c new file mode 100644 index 00000000000..d759294324c --- /dev/null +++ b/sys/arch/arm32/mainbus/rtc.c @@ -0,0 +1,384 @@ +/* $NetBSD: rtc.c,v 1.1 1996/04/19 19:49:06 mark 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 + * + * rtc.c + * + * Routines to read and write the RTC and CMOS RAM + * + * Created : 13/10/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct rtc_softc { + struct device sc_dev; + int sc_flags; +#define RTC_BROKEN 1 +#define RTC_OPEN 2 +}; + +void rtcattach __P((struct device *parent, struct device *self, void *aux)); +int rtcmatch __P((struct device *parent, void *match, void *aux)); + +/* Read a byte from CMOS RAM */ + +int +cmos_read(location) + int location; +{ + u_char buff; + +/* + * This commented code dates from when I was translating CMOS address + * from the RISCOS addresses. Now all addresses are specifed as + * actual addresses in the CMOS RAM + */ + +/* + if (location > 0xF0) + return(-1); + + if (location < 0xC0) + buff = location + 0x40; + else + buff = location - 0xB0; +*/ + buff = location; + + if (iic_control(RTC_Write, &buff, 1)) + return(-1); + if (iic_control(RTC_Read, &buff, 1)) + return(-1); + + return(buff); +} + + +/* Write a byte to CMOS RAM */ + +int +cmos_write(location, value) + int location; + int value; +{ + u_char buff[2]; + +/* + * This commented code dates from when I was translating CMOS address + * from the RISCOS addresses. Now all addresses are specifed as + * actual addresses in the CMOS RAM + */ + +/* if (location > 0xF0) + return(-1); + + if (location < 0xC0) + buff = location + 0x40; + else + buff = location - 0xB0; +*/ + buff[0] = location; + buff[1] = value; + + if (iic_control(RTC_Write, buff, 2)) + return(-1); + + return(0); +} + + +/* Hex to BCD and BCD to hex conversion routines */ + +static inline int +hexdectodec(n) + u_char n; +{ + return(((n >> 4) & 0x0F) * 10 + (n & 0x0F)); +} + +static inline int +dectohexdec(n) + u_char n; +{ + return(((n / 10) << 4) + (n % 10)); +} + + +/* Write the RTC data from an 8 byte buffer */ + +int +rtc_write(rtc) + rtc_t *rtc; +{ + u_char buff[8]; + + buff[0] = 1; + + buff[1] = dectohexdec(rtc->rtc_centi); + buff[2] = dectohexdec(rtc->rtc_sec); + buff[3] = dectohexdec(rtc->rtc_min); + buff[4] = dectohexdec(rtc->rtc_hour) & 0x3f; + buff[5] = dectohexdec(rtc->rtc_day); + buff[6] = dectohexdec(rtc->rtc_mon); + + if (iic_control(RTC_Write, buff, 7)) + return(0); + + cmos_write(RTC_ADDR_YEAR, rtc->rtc_year); + cmos_write(RTC_ADDR_CENT, rtc->rtc_cen); + + return(1); +} + + +/* Read the RTC data into a 8 byte buffer */ + +int +rtc_read(rtc) + rtc_t *rtc; +{ + u_char buff[8]; + int byte; + + buff[0] = 0; + + if (iic_control(RTC_Write, buff, 1)) + return(0); + + if (iic_control(RTC_Read, buff, 8)) + return(0); + + rtc->rtc_micro = 0; + rtc->rtc_centi = hexdectodec(buff[1] & 0xff); + rtc->rtc_sec = hexdectodec(buff[2] & 0x7f); + rtc->rtc_min = hexdectodec(buff[3] & 0x7f); + rtc->rtc_hour = hexdectodec(buff[4] & 0x3f); + + /* If in 12 hour mode need to look at the AM/PM flag */ + + if (buff[4] & 0x80) + rtc->rtc_hour += (buff[4] & 0x40) ? 12 : 0; + + rtc->rtc_day = hexdectodec(buff[5] & 0x3f); + rtc->rtc_mon = hexdectodec(buff[6] & 0x1f); + + byte = cmos_read(RTC_ADDR_YEAR); + if (byte == -1) + return(0); + rtc->rtc_year = byte; + + byte = cmos_read(RTC_ADDR_CENT); + if (byte == -1) + return(0); + rtc->rtc_cen = byte; + + return(1); +} + + +struct cfattach rtc_ca = { + sizeof(struct rtc_softc), rtcmatch, rtcattach +}; + +struct cfdriver rtc_cd = { + NULL, "rtc", DV_DULL, 0 +}; + +int +rtcmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ +/* struct iicbus_attach_args *ib = aux;*/ + + return(1); +} + + +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; + if ((ib->ib_addr & IIC_PCF8583_MASK) == IIC_PCF8583_ADDR) { + printf(": PCF8583"); + + buff[0] = 0; + + if (iic_control(RTC_Write, buff, 1)) + return; + + if (iic_control(RTC_Read, buff, 1)) + return; + + printf(" clock base "); + switch (buff[0] & 0x30) { + case 0x00: + printf("32.768KHz"); + break; + case 0x10: + printf("50Hz"); + break; + case 0x20: + printf("event"); + break; + case 0x30: + printf("test mode"); + break; + } + + if (buff[0] & 0x80) + printf(" stopped"); + if (buff[0] & 0x04) + printf(" alarm enabled"); + sc->sc_flags &= ~RTC_BROKEN; + } + + +/* + * Initialise the time of day register. + * This is normally left to the filing system to do but not all + * filing systems call it e.g. cd9660 + */ + + inittodr(0); + + printf("\n"); +} + + +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_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; +{ + int unit = minor(dev); + struct rtc_softc *sc = rtc_cd.cd_devs[unit]; + + return(ENXIO); +} + + +int +rtcwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct rtc_softc *sc = rtc_cd.cd_devs[unit]; + + return(ENXIO); +} + + +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); +} + +/* End of rtc.c */ diff --git a/sys/arch/arm32/mainbus/vidcaudio.c b/sys/arch/arm32/mainbus/vidcaudio.c new file mode 100644 index 00000000000..0529519a9b4 --- /dev/null +++ b/sys/arch/arm32/mainbus/vidcaudio.c @@ -0,0 +1,870 @@ +/* $NetBSD: vidcaudio.c,v 1.3 1996/03/17 01:24:37 thorpej Exp $ */ + +/* + * Copyright (c) 1995 Melvin Tang-Richardson + * + * 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 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. + */ + +/* + * Yikes just had a look at this and realised that it does not conform + * to Kernel Normal Form at all. I have fixed the first few functions + * but there are a lot more still to do - mark + */ + +/* + * vidcaudio driver for RiscBSD by Melvin Tang-Richardson (c) 1995 + * + * Interfaces with the NetBSD generic audio driver to provide SUN + * /dev/audio (partial) compatibility. + * + * Do not include me in conf.c. My interface is done by the generic + * audio driver. Put me in config file and files.arm32. Do not put + * the audio.c generic driver in them. I do the autoconfig for it. + * + * The following files need to be altered + * + * [files.arm32] + * device vidcaudio at mainbus :audio + * file arch/arm32/mainbus/vidcaudio.c vidcaudio needs-flag + * major { audio=36 } + * + * [conf.c] + * #include "audio.h" + * cdev_decl(audio) + * + * cdev_audio_init(NAUDIO,audio) /* 36: generic audio I/O */ + * + * [GENERIC] + * vidcaudio0 at mainbus? base 0x00000000 + * + */ + +#include /* proc.h */ +#include /* dunno */ +#include /* autoconfig functions */ +#include /* device calls */ +#include /* device calls */ +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include /* ReadByte etc. */ + +#include +#include "waveform.h" +#include "vidcaudio.h" + +#undef DEBUG + +struct audio_general { + int in_sr; + int out_sr; + vm_offset_t silence; + irqhandler_t ih; + + void (*intr) (); + void *arg; + + vm_offset_t next_cur; + vm_offset_t next_end; + void (*next_intr) (); + void *next_arg; + + int buffer; + int in_progress; + + int open; +} ag; + +struct vidcaudio_softc { + struct device device; + int iobase; + + int open; + + u_int encoding; + int inport; + int outport; +}; + +int vidcaudio_probe __P((struct device *parent, struct device *match, void *aux)); +void vidcaudio_attach __P((struct device *parent, struct device *self, void *aux)); +int vidcaudio_open __P((dev_t dev, int flags)); +void vidcaudio_close __P((void *addr)); + +int vidcaudio_intr __P((void *arg)); +int vidcaudio_dma_program __P((vm_offset_t cur, vm_offset_t end, void (*intr)(), void *arg)); +void vidcaudio_dummy_routine __P((void *arg)); +int vidcaudio_stereo __P((int channel, int position)); +int vidcaudio_rate __P((int rate)); +void vidcaudio_shutdown __P((void)); +int vidcaudio_hw_attach __P((struct vidcaudio_softc *sc)); + +struct cfattach vidcaudio_ca = { + sizeof(struct vidcaudio_softc), vidcaudio_probe, vidcaudio_attach +}; + +struct cfdriver vidcaudio_cd = { + NULL, "vidcaudio", DV_DULL +}; + + +void +vidcaudio_beep_generate() +{ + vidcaudio_dma_program ( ag.silence, ag.silence+sizeof(beep_waveform)-16, + vidcaudio_dummy_routine, NULL ); +} + + +int +vidcaudio_probe(parent, match, aux) + struct device *parent; + struct device *match; + void *aux; +{ + int id; + + id = ReadByte(IOMD_ID0) | ReadByte(IOMD_ID1) << 8; + +/* So far I only know about this IOMD */ + + switch (id) { + case RPC600_IOMD_ID: + return(1); + break; + default: + printf("vidcaudio: Unknown IOMD id=%04x", id); + break; + } + + return (0); +} + + +void +vidcaudio_attach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct mainbus_attach_args *mb = aux; + struct vidcaudio_softc *sc = (void *)self; + + sc->iobase = mb->mb_iobase; + + sc->open = 0; + sc->encoding = 0; + sc->inport = 0; + sc->outport = 0; + ag.in_sr = 24*1024; + ag.out_sr = 24*1024; + ag.in_progress = 0; + + ag.next_cur = 0; + ag.next_end = 0; + ag.next_intr = NULL; + ag.next_arg = NULL; + + vidcaudio_rate(32); + +/* Program the silence buffer and reset the DMA channel */ + + ag.silence = kmem_alloc(kernel_map, NBPG); + if (ag.silence == NULL) + panic("vidcaudio: Cannot allocate memory\n"); + + bzero((char *)ag.silence, NBPG); + bcopy((char *)beep_waveform, (char *)ag.silence, sizeof(beep_waveform)); + + ag.buffer = 0; + + /* Install the irq handler for the DMA interrupt */ + ag.ih.ih_func = vidcaudio_intr; + ag.ih.ih_arg = NULL; + ag.ih.ih_level = IPL_NONE; + + ag.intr = NULL; + ag.nextintr = NULL; + + disable_irq(IRQ_DMASCH0); + + if (irq_claim(IRQ_DMASCH0, &(ag.ih))) + panic("vidcaudio: couldn't claim IRQ_DMASCH0"); + + disable_irq(IRQ_DMASCH0); + + vidcaudio_dma_program(ag.silence, ag.silence+NBPG-16, + vidcaudio_dummy_routine, NULL); + + vidcaudio_hw_attach(sc); + +#ifdef DEBUG + printf(" UNDER DEVELOPMENT (nuts)\n"); +#endif +} + +int +vidcaudio_open(dev, flags) + dev_t dev; + int flags; +{ + struct vidcaudio_softc *sc; + int unit = AUDIOUNIT (dev); + int s; + +#ifdef DEBUG + printf("DEBUG: vidcaudio_open called\n"); +#endif + + if (unit >= vidcaudio_cd.cd_ndevs) + return ENODEV; + + sc = vidcaudio_cd.cd_devs[unit]; + + if (!sc) + return ENXIO; + + s = splhigh(); + + if (sc->open != 0) { + (void)splx(s); + return EBUSY; + } + + sc->open=1; + ag.open=1; + + (void)splx(s); + return 0; +} + +void +vidcaudio_close(addr) + void *addr; +{ + struct vidcaudio_softc *sc = addr; + + vidcaudio_shutdown (); + +#ifdef DEBUG + printf("DEBUG: vidcaudio_close called\n"); +#endif + + sc->open = 0; + ag.open = 0; +} + +/* ************************************************************************* * + | Interface to the generic audio driver | + * ************************************************************************* */ + +int vidcaudio_set_in_sr __P((void *, u_long)); +u_long vidcaudio_get_in_sr __P((void *)); +int vidcaudio_set_out_sr __P((void *, u_long)); +u_long vidcaudio_get_out_sr __P((void *)); +int vidcaudio_query_encoding __P((void *, struct audio_encoding *)); +int vidcaudio_set_encoding __P((void *, u_int)); +int vidcaudio_get_encoding __P((void *)); +int vidcaudio_set_precision __P((void *, u_int)); +int vidcaudio_getprecision __P((void *)); +int vidcaudio_set_channels __P((void *, int)); +int vidcaudio_get_channels __P((void *)); +int vidcaudio_round_blocksize __P((void *, int)); +int vidcaudio_set_out_port __P((void *, int)); +int vidcaudio_get_out_port __P((void *)); +int vidcaudio_set_in_port __P((void *, int)); +int vidcaudio_get_in_port __P((void *)); +int vidcaudio_commit_settings __P((void *)); +u_int vidcaudio_get_silence __P((int)); +void vidcaudio_sw_encode __P((int, u_char *, int)); +void vidcaudio_sw_decode __P((int, u_char *, int)); +int vidcaudio_start_output __P((void *, void *, int, void (*)(), void *)); +int vidcaudio_start_input __P((void *, void *, int, void (*)(), void *)); +int vidcaudio_halt_output __P((void *)); +int vidcaudio_halt_input __P((void *)); +int vidcaudio_cont_output __P((void *)); +int vidcaudio_cont_input __P((void *)); +int vidcaudio_speaker_ctl __P((void *, int)); +int vidcaudio_getdev __P((void *, struct audio_device *)); +int vidcaudio_setfd __P((void *, int)); +int vidcaudio_set_port __P((void *, mixer_ctrl_t *)); +int vidcaudio_get_port __P((void *, mixer_ctrl_t *)); +int vidcaudio_query_devinfo __P((void *, mixer_devinfo_t *)); + +struct audio_device vidcaudio_device = { + "VidcAudio 8-bit", + "x", + "vidcaudio" +}; + +int +vidcaudio_set_in_sr(addr, sr) + void *addr; + u_long sr; +{ + ag.in_sr = sr; + return 0; +} + +u_long +vidcaudio_get_in_sr(addr) + void *addr; +{ + return ag.in_sr; +} + +int +vidcaudio_set_out_sr(addr, sr) + void *addr; + u_long sr; +{ + ag.out_sr = sr; + return 0; +} + +u_long +vidcaudio_get_out_sr(addr) + void *addr; +{ + return(ag.out_sr); +} + +int vidcaudio_query_encoding ( void *addr, struct audio_encoding *fp ) +{ + switch ( fp->index ) + { + case 0: + strcpy (fp->name, "vidc" ); + fp->format_id = AUDIO_ENCODING_ULAW; + break; + + default: + return (EINVAL); + } + return 0; +} + +int vidcaudio_set_encoding ( void *addr, u_int enc ) +{ + struct vidcaudio_softc *sc = addr; + + switch (enc) + { + case AUDIO_ENCODING_ULAW: +#ifdef DEBUG + printf ( "DEBUG: Set ulaw encoding\n" ); +#endif + sc->encoding = enc; + break; + + default: + return (EINVAL); + } + return 0; +} + +int vidcaudio_get_encoding ( void *addr ) +{ + struct vidcaudio_softc *sc = addr; + return sc->encoding; +} + +int vidcaudio_set_precision ( void *addr, u_int prec ) +{ + if (prec != 8) + return EINVAL; + return 0; +} + +int vidcaudio_get_precision ( void *addr ) +{ + return (8); +} + +int vidcaudio_set_channels ( void *addr, int chans ) +{ + if ( chans!=1 ) + return EINVAL; + + return 0; +} + +int vidcaudio_get_channels ( void *addr ) +{ + return 1; +} + +int vidcaudio_round_blocksize ( void *addr, int blk ) +{ + if (blk>NBPG) blk=NBPG; + return blk; +} + +int vidcaudio_set_out_port ( void *addr, int port ) +{ + struct vidcaudio_softc *sc = addr; + sc->outport = port; + return 0; +} + +int vidcaudio_get_out_port ( void *addr ) +{ + struct vidcaudio_softc *sc = addr; + return sc->outport; +} + +int vidcaudio_set_in_port ( void *addr, int port ) +{ + struct vidcaudio_softc *sc = addr; + sc->inport = port; + return 0; +} + +int vidcaudio_get_in_port ( void *addr ) +{ + struct vidcaudio_softc *sc = addr; + return sc->inport; +} + +int vidcaudio_commit_settings ( void *addr ) +{ +#ifdef DEBUG +printf ( "DEBUG: committ_settings\n" ); +#endif + return 0; +} + +u_int vidcaudio_get_silence ( int enc ) +{ + switch (enc) + { + case AUDIO_ENCODING_ULAW: + return 0x7f; + + default: + return 0; + } + return 0; +} + +void vidcaudio_sw_encode ( int e, u_char *p, int cc ) +{ +#ifdef DEBUG + printf ( "DEBUG: sw_encode\n" ); +#endif + return; +} + +void vidcaudio_sw_decode ( int e, u_char *p, int cc ) +{ +#ifdef DEBUG + printf ( "DEBUG: sw_decode\n" ); +#endif +} + +#define ROUND(s) ( ((int)s) & (~(NBPG-1)) ) + +int vidcaudio_start_output ( void *addr, void *p, int cc, + void (*intr)(), void *arg ) +{ + /* I can only DMA inside 1 page */ + +#ifdef DEBUG + printf ( "vidcaudio_start_output (%d) %08x %08x\n", cc, intr, arg ); +#endif + + if ( ROUND(p) != ROUND(p+cc) ) + { + /* If it's over a page I can fix it up by copying it into my buffer */ + +#ifdef DEBUG + printf ( "vidcaudio: DMA over page boundary requested. Fixing up\n" ); +#endif + bcopy ( (char *)ag.silence, p, cc>NBPG ? NBPG : cc ); + p=(void *)ag.silence; + + /* I can't DMA any more than that, but it is possible to fix it up */ + /* by handling multiple buffers and only interrupting the audio */ + /* driver after sending out all the stuff it gave me. That it more */ + /* than I can be bothered to do right now and it probablly wont */ + /* happen so I'll just truncate the buffer and tell the user */ + + if ( cc>NBPG ) + { + printf ( "vidcaudio: DMA buffer truncated. I could fix this up\n" ); + cc=NBPG; + } + } + vidcaudio_dma_program ( (vm_offset_t)p, (vm_offset_t)(p+cc), intr, arg ); + return 0; +} + +int vidcaudio_start_input ( void *addr, void *p, int cc, + void (*intr)(), void *arg ) +{ + return EIO; +} + +int vidcaudio_halt_output ( void *addr ) +{ +#ifdef DEBUG + printf ( "DEBUG: vidcaudio_halt_output\n" ); +#endif + return EIO; +} + +int vidcaudio_halt_input ( void *addr ) +{ +#ifdef DEBUG + printf ( "DEBUG: vidcaudio_halt_output\n" ); +#endif + return EIO; +} + +int vidcaudio_cont_output ( void *addr ) +{ +#ifdef DEBUG + printf ( "DEBUG: vidcaudio_halt_output\n" ); +#endif + return EIO; +} + +int vidcaudio_cont_input ( void *addr ) +{ +#ifdef DEBUG + printf ( "DEBUG: vidcaudio_halt_output\n" ); +#endif + return EIO; +} + +int vidcaudio_speaker_ctl ( void *addr, int newstate ) +{ +#ifdef DEBUG + printf ( "DEBUG: vidcaudio_speaker_ctl\n" ); +#endif + return 0; +} + +int vidcaudio_getdev ( void *addr, struct audio_device *retp ) +{ + *retp = vidcaudio_device; + return 0; +} + + +int vidcaudio_setfd ( void *addr, int flag ) +{ + return ENOTTY; +} + +int vidcaudio_set_port ( void *addr, mixer_ctrl_t *cp ) +{ + return EINVAL; +} + +int vidcaudio_get_port ( void *addr, mixer_ctrl_t *cp ) +{ + return EINVAL; +} + +int vidcaudio_query_devinfo ( void *addr, mixer_devinfo_t *dip ) +{ + return 0; +} + +struct audio_hw_if vidcaudio_hw_if = { + vidcaudio_open, + vidcaudio_close, + NULL, + vidcaudio_set_in_sr, + vidcaudio_get_in_sr, + vidcaudio_set_out_sr, + vidcaudio_get_out_sr, + vidcaudio_query_encoding, + vidcaudio_set_encoding, + vidcaudio_get_encoding, + vidcaudio_set_precision, + vidcaudio_get_precision, + vidcaudio_set_channels, + vidcaudio_get_channels, + vidcaudio_round_blocksize, + vidcaudio_set_out_port, + vidcaudio_get_out_port, + vidcaudio_set_in_port, + vidcaudio_get_in_port, + vidcaudio_commit_settings, + vidcaudio_get_silence, + vidcaudio_sw_encode, + vidcaudio_sw_decode, + vidcaudio_start_output, + vidcaudio_start_input, + vidcaudio_halt_output, + vidcaudio_halt_input, + vidcaudio_cont_output, + vidcaudio_cont_input, + vidcaudio_speaker_ctl, + vidcaudio_getdev, + vidcaudio_setfd, + vidcaudio_set_port, + vidcaudio_get_port, + vidcaudio_query_devinfo, + 0, /* not full duplex */ + 0 +}; + +void vidcaudio_dummy_routine ( void *arg ) +{ +#ifdef DEBUG + printf ( "vidcaudio_dummy_routine\n" ); +#endif +} + +int vidcaudio_hw_attach ( struct vidcaudio_softc *sc ) +{ + return ( audio_hardware_attach ( &vidcaudio_hw_if, sc ) ); +} + +int vidcaudio_rate ( int rate ) +{ + WriteWord ( VIDC_BASE, VIDC_SFR | rate ); + return 0; +} + +int vidcaudio_stereo ( int channel, int position ) +{ + if ( channel<0 ) return EINVAL; + if ( channel>7 ) return EINVAL; + channel = channel<<24 | VIDC_SIR0; + WriteWord ( VIDC_BASE, channel|position ); + return 0; +} + +#define PHYS(x) (pmap_extract( kernel_pmap, ((x)&PG_FRAME) )) + +/* + * Program the next buffer to be used + * This function must be re-entrant, maximum re-entrancy of 2 + */ + +#define FLAGS (0) + +int vidcaudio_dma_program ( vm_offset_t cur, vm_offset_t end, + void (*intr)(), void *arg ) +{ + /* If there isn't a transfer in progress then start a new one */ + if ( ag.in_progress==0 ) + { + ag.buffer = 0; + WriteWord ( IOMD_SD0CR, 0x90 ); /* Reset State Machine */ + WriteWord ( IOMD_SD0CR, 0x30 ); /* Reset State Machine */ + + WriteWord ( IOMD_SD0CURB, PHYS(cur) ); + WriteWord ( IOMD_SD0ENDB, PHYS(end-16)|FLAGS ); + WriteWord ( IOMD_SD0CURA, PHYS(cur) ); + WriteWord ( IOMD_SD0ENDA, PHYS(end-16)|FLAGS ); + + ag.in_progress = 1; + + ag.next_cur = ag.next_end = 0; + ag.next_intr = ag.next_arg = 0; + + ag.intr = intr; + ag.arg = arg; + + /* The driver 'clicks' between buffer swaps, leading me to think */ + /* that the fifo is much small than on other sound cards. So */ + /* so I'm going to have to do some tricks here */ + + (*ag.intr)(ag.arg); /* Schedule the next buffer */ + ag.intr = vidcaudio_dummy_routine; /* Already done this */ + ag.arg = NULL; + +#ifdef PRINT +printf ( "vidcaudio: start output\n" ); +#endif +#ifdef DEBUG + printf ( "SE" ); +#endif + enable_irq ( IRQ_DMASCH0 ); + } + else + { + /* Otherwise schedule the next one */ + if ( ag.next_cur!=0 ) + { + /* If there's one scheduled then complain */ + printf ( "vidcaudio: Buffer already Q'ed\n" ); + return EIO; + } + else + { + /* We're OK to schedule it now */ + ag.buffer = (++ag.buffer) & 1; + ag.next_cur = PHYS(cur); + ag.next_end = PHYS(end-16); + ag.next_intr = intr; + ag.next_arg = arg; +#ifdef DEBUG +printf ( "s" ); +#endif + } + } + return 0; +} + +void vidcaudio_shutdown ( void ) +{ + /* Shut down the channel */ + ag.intr = NULL; + ag.in_progress = 0; +#ifdef PRINT +printf ( "vidcaudio: stop output\n" ); +#endif + WriteWord ( IOMD_SD0CURB, ag.silence ); + WriteWord ( IOMD_SD0ENDB, (ag.silence + NBPG - 16) | (1<<30) ); + disable_irq ( IRQ_DMASCH0 ); +} + +int vidcaudio_intr ( void *arg ) +{ + int status = ReadByte(IOMD_SD0ST); + void (*nintr)(); + void *narg; + void (*xintr)(); + void *xarg; + int xcur, xend; + WriteWord ( IOMD_DMARQ, 0x10 ); + +#ifdef PRINT + printf ( "I" ); +#endif + + if ( ag.open==0 ) + { + vidcaudio_shutdown (); + return 0; + } + + /* Have I got the generic audio device attached */ + +#ifdef DEBUG + printf ( "[B%01x]", status ); +#endif + + nintr=ag.intr; + narg=ag.arg; + ag.intr = NULL; + + xintr=ag.next_intr; + xarg=ag.next_arg; + xcur=ag.next_cur; + xend=ag.next_end; + ag.next_cur = 0; + ag.intr = xintr; + ag.arg = xarg; + + if ( nintr ) + { +#ifdef DEBUG + printf ( "i" ); +#endif + (*nintr)(narg); + } + + if ( xcur==0 ) + { + vidcaudio_shutdown (); + } + else + { +#define OVERRUN (0x04) +#define INTERRUPT (0x02) +#define BANK_A (0x00) +#define BANK_B (0x01) + switch ( status&0x7 ) + { + case (INTERRUPT|BANK_A): +#ifdef PRINT +printf( "B" ); +#endif + WriteWord ( IOMD_SD0CURB, xcur ); + WriteWord ( IOMD_SD0ENDB, xend|FLAGS ); + break; + + case (INTERRUPT|BANK_B): +#ifdef PRINT +printf( "A" ); +#endif + WriteWord ( IOMD_SD0CURA, xcur ); + WriteWord ( IOMD_SD0ENDA, xend|FLAGS ); + break; + + case (OVERRUN|INTERRUPT|BANK_A): +#ifdef PRINT +printf( "A" ); +#endif + WriteWord ( IOMD_SD0CURA, xcur ); + WriteWord ( IOMD_SD0ENDA, xend|FLAGS ); + break; + + case (OVERRUN|INTERRUPT|BANK_B): +#ifdef PRINT +printf( "B" ); +#endif + WriteWord ( IOMD_SD0CURB, xcur ); + WriteWord ( IOMD_SD0ENDB, xend|FLAGS ); + break; + } +/* + ag.next_cur = 0; + ag.intr = xintr; + ag.arg = xarg; +*/ + } +#ifdef PRINT +printf ( "i" ); +#endif + + if ( ag.next_cur==0 ) + { + (*ag.intr)(ag.arg); /* Schedule the next buffer */ + ag.intr = vidcaudio_dummy_routine; /* Already done this */ + ag.arg = NULL; + } + return 0; +} + + diff --git a/sys/arch/arm32/mainbus/waveform.h b/sys/arch/arm32/mainbus/waveform.h new file mode 100644 index 00000000000..1508a71d2e3 --- /dev/null +++ b/sys/arch/arm32/mainbus/waveform.h @@ -0,0 +1,551 @@ +/* $NetBSD: waveform.h,v 1.2 1996/03/18 20:50:06 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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. + */ + +static unsigned char beep_waveform[] = { + 0x00, 0x06, 0x18, 0x2a, 0x3e, 0x4a, 0x54, 0x60, + 0x64, 0x68, 0x6a, 0x6a, 0x66, 0x62, 0x54, 0x3e, + 0x00, 0x45, 0x61, 0x6f, 0x7f, 0x87, 0x8d, 0x91, + 0x93, 0x95, 0x93, 0x91, 0x8b, 0x85, 0x73, 0x59, + 0x00, 0x5c, 0x78, 0x8a, 0x96, 0xa0, 0xa6, 0xa8, + 0xaa, 0xaa, 0xa8, 0xa6, 0xa2, 0x94, 0x86, 0x6a, + 0x00, 0x6b, 0x8b, 0x9d, 0xa7, 0xaf, 0xb5, 0xb9, + 0xbb, 0xbb, 0xb9, 0xb3, 0xad, 0xa5, 0x93, 0x77, + 0x00, 0x78, 0x96, 0xa8, 0xb2, 0xbc, 0xc2, 0xc4, + 0xc6, 0xc6, 0xc4, 0xc0, 0xb8, 0xac, 0x9e, 0x82, + 0x00, 0x83, 0xa3, 0xb1, 0xbf, 0xc5, 0xcb, 0xcd, + 0xcf, 0xcf, 0xcd, 0xc9, 0xc3, 0xb7, 0xa7, 0x89, + 0x00, 0x88, 0xa8, 0xb8, 0xc4, 0xcc, 0xd0, 0xd4, + 0xd6, 0xd4, 0xd2, 0xce, 0xc8, 0xbe, 0xac, 0x8e, + 0x00, 0x8f, 0xaf, 0xc3, 0xcb, 0xd3, 0xd9, 0xdd, + 0xdf, 0xdd, 0xdb, 0xd5, 0xcf, 0xc5, 0xb3, 0x95, + 0x00, 0x96, 0xb4, 0xc6, 0xd0, 0xd8, 0xe0, 0xe2, + 0xe4, 0xe2, 0xe2, 0xdc, 0xd2, 0xc8, 0xb8, 0x9a, + 0x00, 0x9d, 0xbb, 0xcb, 0xd7, 0xe1, 0xe5, 0xe7, + 0xe9, 0xe7, 0xe5, 0xe3, 0xd9, 0xcf, 0xbf, 0xa1, + 0x00, 0xa2, 0xc0, 0xce, 0xdc, 0xe4, 0xe8, 0xea, + 0xec, 0xea, 0xe8, 0xe4, 0xde, 0xd2, 0xc2, 0xa4, + 0x00, 0xa5, 0xc5, 0xd5, 0xe3, 0xe7, 0xed, 0xef, + 0xf1, 0xef, 0xed, 0xe9, 0xe3, 0xd7, 0xc7, 0xa9, + 0x00, 0xa8, 0xc6, 0xd8, 0xe4, 0xea, 0xee, 0xf2, + 0xf4, 0xf2, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa, + 0x00, 0xab, 0xcb, 0xdd, 0xe7, 0xef, 0xf3, 0xf7, + 0xf9, 0xf7, 0xf5, 0xef, 0xe9, 0xdf, 0xcd, 0xaf, + 0x00, 0xae, 0xcc, 0xe0, 0xea, 0xf0, 0xf6, 0xfa, + 0xfc, 0xfa, 0xf8, 0xf2, 0xea, 0xe2, 0xd0, 0xb0, + 0x00, 0xb1, 0xd1, 0xe3, 0xed, 0xf5, 0xfb, 0xff, + 0xff, 0xff, 0xfb, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb4, + 0x00, 0xb5, 0xd3, 0xe5, 0xef, 0xf7, 0xfd, 0xff, + 0xff, 0xff, 0xfd, 0xf7, 0xef, 0xe5, 0xd3, 0xb5, + 0x00, 0xb4, 0xd2, 0xe4, 0xee, 0xf6, 0xfc, 0xfe, + 0xfe, 0xfe, 0xfc, 0xf6, 0xee, 0xe4, 0xd2, 0xb2, + 0x00, 0xb3, 0xd3, 0xe5, 0xef, 0xf7, 0xfb, 0xff, + 0xff, 0xff, 0xfb, 0xf5, 0xef, 0xe5, 0xd1, 0xb3, + 0x00, 0xb2, 0xd0, 0xe4, 0xec, 0xf4, 0xfa, 0xfe, + 0xfe, 0xfe, 0xfa, 0xf4, 0xec, 0xe4, 0xd0, 0xb2, + 0x00, 0xb3, 0xd1, 0xe5, 0xed, 0xf5, 0xfb, 0xff, + 0xff, 0xff, 0xfb, 0xf5, 0xed, 0xe5, 0xd1, 0xb3, + 0x00, 0xb2, 0xd0, 0xe4, 0xec, 0xf4, 0xfa, 0xfc, + 0xfe, 0xfc, 0xfa, 0xf4, 0xec, 0xe2, 0xd0, 0xb2, + 0x00, 0xb3, 0xd1, 0xe3, 0xed, 0xf5, 0xf9, 0xfd, + 0xff, 0xfd, 0xf9, 0xf5, 0xed, 0xe3, 0xd1, 0xb1, + 0x00, 0xb0, 0xd0, 0xe2, 0xec, 0xf2, 0xf8, 0xfc, + 0xfc, 0xfc, 0xf8, 0xf2, 0xec, 0xe2, 0xd0, 0xb0, + 0x00, 0xb1, 0xcf, 0xe3, 0xed, 0xf3, 0xf9, 0xfd, + 0xfd, 0xfd, 0xf9, 0xf3, 0xed, 0xe3, 0xcf, 0xb1, + 0x00, 0xb0, 0xce, 0xe2, 0xea, 0xf2, 0xf8, 0xfa, + 0xfc, 0xfa, 0xf8, 0xf2, 0xea, 0xe2, 0xce, 0xb0, + 0x00, 0xb1, 0xcf, 0xe3, 0xeb, 0xf3, 0xf9, 0xfb, + 0xfd, 0xfb, 0xf7, 0xf3, 0xeb, 0xe3, 0xcf, 0xb1, + 0x00, 0xb0, 0xce, 0xe2, 0xea, 0xf2, 0xf6, 0xfa, + 0xfa, 0xfa, 0xf6, 0xf2, 0xea, 0xe2, 0xce, 0xae, + 0x00, 0xaf, 0xcf, 0xe3, 0xeb, 0xf1, 0xf7, 0xfb, + 0xfb, 0xfb, 0xf7, 0xf1, 0xeb, 0xe1, 0xcf, 0xaf, + 0x00, 0xae, 0xce, 0xe0, 0xea, 0xf0, 0xf6, 0xf8, + 0xfa, 0xf8, 0xf6, 0xf0, 0xea, 0xe0, 0xcc, 0xae, + 0x00, 0xaf, 0xcd, 0xe1, 0xeb, 0xf1, 0xf7, 0xf9, + 0xfb, 0xf9, 0xf7, 0xf1, 0xe9, 0xe1, 0xcd, 0xaf, + 0x00, 0xae, 0xcc, 0xe0, 0xe8, 0xf0, 0xf4, 0xf8, + 0xf8, 0xf8, 0xf4, 0xf0, 0xe8, 0xe0, 0xcc, 0xae, + 0x00, 0xaf, 0xcd, 0xe1, 0xe9, 0xf1, 0xf5, 0xf9, + 0xf9, 0xf9, 0xf5, 0xf1, 0xe9, 0xdf, 0xcd, 0xad, + 0x00, 0xac, 0xcc, 0xde, 0xe8, 0xee, 0xf4, 0xf6, + 0xf8, 0xf6, 0xf4, 0xee, 0xe8, 0xde, 0xcc, 0xac, + 0x00, 0xad, 0xcd, 0xdf, 0xe9, 0xef, 0xf5, 0xf7, + 0xf9, 0xf7, 0xf5, 0xef, 0xe9, 0xdf, 0xcb, 0xad, + 0x00, 0xac, 0xca, 0xde, 0xe8, 0xee, 0xf2, 0xf6, + 0xf6, 0xf6, 0xf2, 0xee, 0xe8, 0xde, 0xca, 0xac, + 0x00, 0xad, 0xcb, 0xdd, 0xe7, 0xef, 0xf3, 0xf7, + 0xf7, 0xf7, 0xf3, 0xef, 0xe7, 0xdd, 0xcb, 0xad, + 0x00, 0xac, 0xca, 0xdc, 0xe6, 0xee, 0xf2, 0xf4, + 0xf6, 0xf4, 0xf2, 0xee, 0xe6, 0xdc, 0xca, 0xaa, + 0x00, 0xab, 0xcb, 0xdd, 0xe7, 0xed, 0xf3, 0xf5, + 0xf7, 0xf5, 0xf3, 0xed, 0xe7, 0xdd, 0xcb, 0xab, + 0x00, 0xaa, 0xca, 0xdc, 0xe6, 0xec, 0xf2, 0xf4, + 0xf4, 0xf4, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa, + 0x00, 0xab, 0xc9, 0xdb, 0xe7, 0xed, 0xf1, 0xf5, + 0xf5, 0xf5, 0xf1, 0xed, 0xe7, 0xdb, 0xc9, 0xab, + 0x00, 0xaa, 0xc8, 0xda, 0xe6, 0xec, 0xf0, 0xf4, + 0xf4, 0xf2, 0xf0, 0xec, 0xe6, 0xda, 0xc8, 0xaa, + 0x00, 0xab, 0xc9, 0xdb, 0xe5, 0xed, 0xf1, 0xf3, + 0xf5, 0xf3, 0xf1, 0xeb, 0xe5, 0xdb, 0xc9, 0xa9, + 0x00, 0xa8, 0xc8, 0xd8, 0xe4, 0xea, 0xf0, 0xf2, + 0xf2, 0xf2, 0xf0, 0xea, 0xe4, 0xd8, 0xc8, 0xa8, + 0x00, 0xa9, 0xc9, 0xd9, 0xe5, 0xeb, 0xef, 0xf3, + 0xf3, 0xf3, 0xef, 0xeb, 0xe5, 0xd9, 0xc9, 0xa9, + 0x00, 0xa8, 0xc6, 0xd8, 0xe4, 0xea, 0xee, 0xf2, + 0xf2, 0xf2, 0xee, 0xea, 0xe4, 0xd8, 0xc6, 0xa8, + 0x00, 0xa9, 0xc7, 0xd9, 0xe5, 0xeb, 0xef, 0xf1, + 0xf3, 0xf1, 0xef, 0xeb, 0xe5, 0xd7, 0xc7, 0xa9, + 0x00, 0xa8, 0xc6, 0xd6, 0xe4, 0xea, 0xee, 0xf0, + 0xf0, 0xf0, 0xee, 0xe8, 0xe2, 0xd6, 0xc6, 0xa8, + 0x00, 0xa7, 0xc7, 0xd7, 0xe3, 0xe9, 0xed, 0xf1, + 0xf1, 0xf1, 0xed, 0xe9, 0xe3, 0xd7, 0xc7, 0xa7, + 0x00, 0xa6, 0xc6, 0xd6, 0xe2, 0xe8, 0xec, 0xf0, + 0xf0, 0xf0, 0xec, 0xe8, 0xe2, 0xd6, 0xc6, 0xa6, + 0x00, 0xa7, 0xc5, 0xd7, 0xe3, 0xe9, 0xed, 0xef, + 0xf1, 0xef, 0xed, 0xe9, 0xe3, 0xd5, 0xc5, 0xa7, + 0x00, 0xa6, 0xc4, 0xd4, 0xe2, 0xe8, 0xec, 0xee, + 0xee, 0xee, 0xec, 0xe8, 0xe2, 0xd4, 0xc4, 0xa6, + 0x00, 0xa7, 0xc5, 0xd5, 0xe3, 0xe7, 0xed, 0xef, + 0xef, 0xef, 0xeb, 0xe7, 0xe3, 0xd5, 0xc5, 0xa7, + 0x00, 0xa6, 0xc4, 0xd4, 0xe0, 0xe6, 0xea, 0xee, + 0xee, 0xee, 0xea, 0xe6, 0xe0, 0xd4, 0xc4, 0xa4, + 0x00, 0xa5, 0xc5, 0xd3, 0xe1, 0xe7, 0xeb, 0xed, + 0xef, 0xed, 0xeb, 0xe7, 0xe1, 0xd3, 0xc5, 0xa5, + 0x00, 0xa4, 0xc4, 0xd2, 0xe0, 0xe6, 0xea, 0xec, + 0xec, 0xec, 0xea, 0xe6, 0xe0, 0xd2, 0xc2, 0xa4, + 0x00, 0xa5, 0xc3, 0xd3, 0xdf, 0xe7, 0xeb, 0xed, + 0xed, 0xed, 0xeb, 0xe7, 0xdf, 0xd3, 0xc3, 0xa5, + 0x00, 0xa4, 0xc2, 0xd2, 0xde, 0xe4, 0xe8, 0xec, + 0xec, 0xec, 0xe8, 0xe4, 0xde, 0xd0, 0xc2, 0xa4, + 0x00, 0xa5, 0xc3, 0xd1, 0xdf, 0xe5, 0xe9, 0xeb, + 0xed, 0xeb, 0xe9, 0xe5, 0xdf, 0xd1, 0xc3, 0xa3, + 0x00, 0xa2, 0xc2, 0xd0, 0xdc, 0xe4, 0xe8, 0xea, + 0xea, 0xea, 0xe8, 0xe4, 0xdc, 0xd0, 0xc2, 0xa2, + 0x00, 0xa3, 0xc3, 0xd1, 0xdd, 0xe5, 0xe9, 0xeb, + 0xeb, 0xeb, 0xe9, 0xe5, 0xdd, 0xd1, 0xc1, 0xa3, + 0x00, 0xa2, 0xc0, 0xce, 0xdc, 0xe4, 0xe6, 0xea, + 0xea, 0xea, 0xe6, 0xe4, 0xda, 0xce, 0xc0, 0xa2, + 0x00, 0xa3, 0xc1, 0xcf, 0xdb, 0xe3, 0xe7, 0xe9, + 0xeb, 0xe9, 0xe7, 0xe3, 0xdb, 0xcf, 0xc1, 0xa3, + 0x00, 0xa2, 0xc0, 0xce, 0xda, 0xe2, 0xe6, 0xe8, + 0xe8, 0xe8, 0xe6, 0xe2, 0xda, 0xce, 0xbe, 0xa0, + 0x00, 0xa1, 0xbf, 0xcf, 0xdb, 0xe3, 0xe7, 0xe9, + 0xe9, 0xe9, 0xe7, 0xe3, 0xd9, 0xcd, 0xbf, 0xa1, + 0x00, 0xa0, 0xbe, 0xcc, 0xd8, 0xe2, 0xe6, 0xe8, + 0xe8, 0xe8, 0xe4, 0xe2, 0xd8, 0xcc, 0xbc, 0x9e, + 0x00, 0x9f, 0xbd, 0xcd, 0xd9, 0xe3, 0xe5, 0xe7, + 0xe9, 0xe7, 0xe5, 0xe1, 0xd9, 0xcd, 0xbd, 0x9f, + 0x00, 0x9e, 0xbc, 0xcc, 0xd8, 0xe0, 0xe4, 0xe6, + 0xe6, 0xe6, 0xe4, 0xe0, 0xd6, 0xcc, 0xbc, 0x9e, + 0x00, 0x9f, 0xbd, 0xcd, 0xd7, 0xe1, 0xe5, 0xe7, + 0xe7, 0xe7, 0xe5, 0xe1, 0xd7, 0xcb, 0xbb, 0x9d, + 0x00, 0x9c, 0xba, 0xca, 0xd6, 0xde, 0xe4, 0xe6, + 0xe6, 0xe6, 0xe4, 0xde, 0xd6, 0xca, 0xba, 0x9c, + 0x00, 0x9d, 0xbb, 0xcb, 0xd5, 0xdf, 0xe3, 0xe5, + 0xe7, 0xe5, 0xe3, 0xdf, 0xd5, 0xcb, 0xbb, 0x9d, + 0x00, 0x9a, 0xb8, 0xca, 0xd4, 0xde, 0xe2, 0xe4, + 0xe4, 0xe4, 0xe2, 0xdc, 0xd4, 0xca, 0xb8, 0x9a, + 0x00, 0x9b, 0xb9, 0xc9, 0xd5, 0xdd, 0xe3, 0xe5, + 0xe5, 0xe5, 0xe3, 0xdd, 0xd5, 0xc9, 0xb9, 0x9b, + 0x00, 0x9a, 0xb8, 0xc8, 0xd2, 0xdc, 0xe2, 0xe4, + 0xe4, 0xe4, 0xe2, 0xdc, 0xd2, 0xc8, 0xb6, 0x98, + 0x00, 0x99, 0xb7, 0xc9, 0xd3, 0xdb, 0xe1, 0xe3, + 0xe5, 0xe3, 0xe1, 0xdb, 0xd3, 0xc9, 0xb7, 0x99, + 0x00, 0x98, 0xb6, 0xc8, 0xd2, 0xda, 0xe0, 0xe2, + 0xe2, 0xe2, 0xe0, 0xda, 0xd2, 0xc6, 0xb6, 0x98, + 0x00, 0x99, 0xb7, 0xc7, 0xd1, 0xd9, 0xdf, 0xe3, + 0xe3, 0xe3, 0xdf, 0xd9, 0xd1, 0xc7, 0xb5, 0x97, + 0x00, 0x96, 0xb4, 0xc6, 0xd0, 0xd8, 0xde, 0xe2, + 0xe2, 0xe2, 0xde, 0xd8, 0xd0, 0xc6, 0xb4, 0x96, + 0x00, 0x97, 0xb5, 0xc7, 0xd1, 0xd9, 0xdf, 0xe1, + 0xe3, 0xe1, 0xdd, 0xd7, 0xcf, 0xc7, 0xb3, 0x95, + 0x00, 0x94, 0xb2, 0xc4, 0xce, 0xd6, 0xdc, 0xe0, + 0xe0, 0xe0, 0xdc, 0xd6, 0xce, 0xc4, 0xb2, 0x94, + 0x00, 0x95, 0xb3, 0xc5, 0xcf, 0xd7, 0xdd, 0xdf, + 0xe1, 0xdf, 0xdd, 0xd7, 0xcf, 0xc5, 0xb3, 0x95, + 0x00, 0x94, 0xb2, 0xc4, 0xce, 0xd4, 0xda, 0xde, + 0xde, 0xde, 0xda, 0xd4, 0xcc, 0xc4, 0xb0, 0x92, + 0x00, 0x93, 0xb1, 0xc5, 0xcd, 0xd5, 0xdb, 0xdd, + 0xdf, 0xdd, 0xdb, 0xd5, 0xcd, 0xc3, 0xb1, 0x93, + 0x00, 0x92, 0xb0, 0xc2, 0xcc, 0xd4, 0xd8, 0xdc, + 0xdc, 0xdc, 0xd8, 0xd2, 0xcc, 0xc2, 0xb0, 0x90, + 0x00, 0x91, 0xaf, 0xc3, 0xcb, 0xd3, 0xd9, 0xdb, + 0xdd, 0xdb, 0xd9, 0xd3, 0xcb, 0xc3, 0xaf, 0x91, + 0x00, 0x90, 0xae, 0xc2, 0xca, 0xd2, 0xd6, 0xda, + 0xda, 0xda, 0xd6, 0xd2, 0xca, 0xc2, 0xae, 0x90, + 0x00, 0x91, 0xaf, 0xc3, 0xcb, 0xd1, 0xd7, 0xd9, + 0xdb, 0xd9, 0xd7, 0xd1, 0xcb, 0xc1, 0xad, 0x8f, + 0x00, 0x8e, 0xac, 0xc0, 0xc8, 0xd0, 0xd4, 0xd8, + 0xd8, 0xd8, 0xd4, 0xd0, 0xc8, 0xc0, 0xac, 0x8e, + 0x00, 0x8f, 0xad, 0xbf, 0xc9, 0xcf, 0xd5, 0xd7, + 0xd9, 0xd7, 0xd5, 0xcf, 0xc9, 0xbf, 0xad, 0x8f, + 0x00, 0x8c, 0xac, 0xbe, 0xc8, 0xce, 0xd2, 0xd6, + 0xd6, 0xd6, 0xd2, 0xce, 0xc8, 0xbe, 0xaa, 0x8c, + 0x00, 0x8d, 0xab, 0xbd, 0xc7, 0xcf, 0xd3, 0xd5, + 0xd7, 0xd5, 0xd3, 0xcd, 0xc7, 0xbd, 0xab, 0x8d, + 0x00, 0x8c, 0xaa, 0xbc, 0xc6, 0xcc, 0xd2, 0xd4, + 0xd4, 0xd4, 0xd0, 0xcc, 0xc6, 0xba, 0xaa, 0x8a, + 0x00, 0x8b, 0xa9, 0xbb, 0xc7, 0xcd, 0xd1, 0xd5, + 0xd5, 0xd3, 0xd1, 0xcd, 0xc5, 0xbb, 0xa9, 0x8b, + 0x00, 0x8a, 0xa8, 0xba, 0xc4, 0xca, 0xd0, 0xd2, + 0xd2, 0xd2, 0xd0, 0xca, 0xc4, 0xb8, 0xa8, 0x8a, + 0x00, 0x8b, 0xa9, 0xb9, 0xc5, 0xcb, 0xcf, 0xd3, + 0xd3, 0xd1, 0xcf, 0xcb, 0xc5, 0xb9, 0xa7, 0x89, + 0x00, 0x88, 0xa6, 0xb8, 0xc4, 0xca, 0xce, 0xd0, + 0xd0, 0xd0, 0xce, 0xc8, 0xc2, 0xb6, 0xa6, 0x88, + 0x00, 0x89, 0xa7, 0xb7, 0xc3, 0xc9, 0xcd, 0xd1, + 0xd1, 0xcf, 0xcd, 0xc9, 0xc3, 0xb7, 0xa7, 0x87, + 0x00, 0x86, 0xa6, 0xb4, 0xc2, 0xc8, 0xcc, 0xce, + 0xce, 0xce, 0xcc, 0xc8, 0xc2, 0xb4, 0xa4, 0x86, + 0x00, 0x87, 0xa5, 0xb5, 0xc3, 0xc7, 0xcb, 0xcf, + 0xcf, 0xcf, 0xcb, 0xc7, 0xc1, 0xb5, 0xa5, 0x87, + 0x00, 0x86, 0xa4, 0xb2, 0xc0, 0xc6, 0xca, 0xcc, + 0xcc, 0xcc, 0xca, 0xc6, 0xc0, 0xb2, 0xa2, 0x84, + 0x00, 0x85, 0xa3, 0xb3, 0xbf, 0xc5, 0xc9, 0xcd, + 0xcd, 0xcd, 0xc9, 0xc5, 0xbf, 0xb1, 0xa3, 0x85, + 0x00, 0x84, 0xa2, 0xb0, 0xbc, 0xc4, 0xc8, 0xca, + 0xca, 0xca, 0xc8, 0xc4, 0xbc, 0xb0, 0xa2, 0x82, + 0x00, 0x83, 0xa3, 0xb1, 0xbd, 0xc5, 0xc7, 0xcb, + 0xcb, 0xcb, 0xc7, 0xc3, 0xbb, 0xaf, 0xa1, 0x83, + 0x00, 0x82, 0xa0, 0xae, 0xba, 0xc2, 0xc6, 0xc8, + 0xc8, 0xc8, 0xc6, 0xc2, 0xba, 0xae, 0x9e, 0x82, + 0x00, 0x83, 0x9f, 0xaf, 0xb9, 0xc3, 0xc7, 0xc9, + 0xc9, 0xc9, 0xc5, 0xc3, 0xb9, 0xad, 0x9f, 0x81, + 0x00, 0x80, 0x9c, 0xac, 0xb8, 0xc0, 0xc4, 0xc6, + 0xc6, 0xc6, 0xc4, 0xc0, 0xb6, 0xac, 0x9c, 0x7e, + 0x00, 0x7f, 0x9d, 0xab, 0xb7, 0xbf, 0xc5, 0xc7, + 0xc7, 0xc7, 0xc5, 0xbf, 0xb7, 0xab, 0x9b, 0x7d, + 0x00, 0x7c, 0x9a, 0xaa, 0xb4, 0xbe, 0xc2, 0xc4, + 0xc4, 0xc4, 0xc2, 0xbc, 0xb4, 0xaa, 0x98, 0x7c, + 0x00, 0x7d, 0x99, 0xa9, 0xb5, 0xbd, 0xc3, 0xc5, + 0xc5, 0xc5, 0xc3, 0xbb, 0xb3, 0xa9, 0x99, 0x7b, + 0x00, 0x7a, 0x96, 0xa8, 0xb2, 0xba, 0xc0, 0xc2, + 0xc2, 0xc2, 0xc0, 0xba, 0xb0, 0xa6, 0x96, 0x78, + 0x00, 0x79, 0x97, 0xa7, 0xb1, 0xb9, 0xbf, 0xc3, + 0xc3, 0xc3, 0xbf, 0xb9, 0xb1, 0xa7, 0x95, 0x77, + 0x00, 0x76, 0x94, 0xa6, 0xae, 0xb6, 0xbc, 0xc0, + 0xc0, 0xc0, 0xbc, 0xb6, 0xae, 0xa4, 0x92, 0x76, + 0x00, 0x75, 0x93, 0xa5, 0xaf, 0xb5, 0xbb, 0xbf, + 0xbf, 0xbf, 0xbb, 0xb5, 0xad, 0xa5, 0x91, 0x75, + 0x00, 0x74, 0x90, 0xa4, 0xac, 0xb4, 0xb8, 0xbc, + 0xbc, 0xbc, 0xb8, 0xb2, 0xac, 0xa2, 0x90, 0x72, + 0x00, 0x73, 0x91, 0xa3, 0xab, 0xb3, 0xb7, 0xbb, + 0xbb, 0xbb, 0xb7, 0xb1, 0xab, 0xa3, 0x8f, 0x71, + 0x00, 0x70, 0x8e, 0xa0, 0xaa, 0xb0, 0xb4, 0xb8, + 0xb8, 0xb8, 0xb4, 0xb0, 0xa8, 0xa0, 0x8c, 0x6e, + 0x00, 0x6f, 0x8d, 0x9f, 0xa9, 0xaf, 0xb5, 0xb7, + 0xb7, 0xb7, 0xb3, 0xaf, 0xa9, 0x9f, 0x8b, 0x6f, + 0x00, 0x6e, 0x8a, 0x9c, 0xa6, 0xac, 0xb2, 0xb4, + 0xb4, 0xb4, 0xb0, 0xac, 0xa6, 0x9a, 0x8a, 0x6c, + 0x00, 0x6d, 0x89, 0x9b, 0xa5, 0xab, 0xb1, 0xb3, + 0xb3, 0xb3, 0xaf, 0xab, 0xa5, 0x99, 0x89, 0x6b, + 0x00, 0x6a, 0x88, 0x98, 0xa4, 0xaa, 0xae, 0xb0, + 0xb0, 0xb0, 0xae, 0xa8, 0xa2, 0x96, 0x86, 0x68, + 0x00, 0x69, 0x87, 0x97, 0xa3, 0xa9, 0xad, 0xaf, + 0xaf, 0xaf, 0xad, 0xa7, 0xa3, 0x95, 0x85, 0x69, + 0x00, 0x66, 0x84, 0x94, 0xa0, 0xa6, 0xaa, 0xac, + 0xac, 0xac, 0xaa, 0xa6, 0x9e, 0x92, 0x84, 0x66, + 0x00, 0x67, 0x83, 0x93, 0x9f, 0xa5, 0xa9, 0xab, + 0xab, 0xab, 0xa9, 0xa5, 0x9d, 0x91, 0x83, 0x65, + 0x00, 0x64, 0x82, 0x8e, 0x9a, 0xa2, 0xa6, 0xa8, + 0xa8, 0xa8, 0xa6, 0xa2, 0x9a, 0x8e, 0x80, 0x62, + 0x00, 0x63, 0x7f, 0x8d, 0x99, 0xa1, 0xa5, 0xa7, + 0xa7, 0xa7, 0xa5, 0xa1, 0x97, 0x8d, 0x7d, 0x61, + 0x00, 0x60, 0x7c, 0x8a, 0x94, 0x9e, 0xa2, 0xa4, + 0xa4, 0xa4, 0xa2, 0x9c, 0x94, 0x8a, 0x7a, 0x5e, + 0x00, 0x5f, 0x79, 0x89, 0x93, 0x9b, 0xa1, 0xa3, + 0xa3, 0xa3, 0xa1, 0x9b, 0x91, 0x87, 0x77, 0x5b, + 0x00, 0x5a, 0x76, 0x86, 0x90, 0x96, 0x9c, 0xa0, + 0xa0, 0xa0, 0x9c, 0x96, 0x8e, 0x84, 0x72, 0x58, + 0x00, 0x59, 0x73, 0x85, 0x8d, 0x95, 0x99, 0x9d, + 0x9d, 0x9d, 0x99, 0x93, 0x8d, 0x83, 0x71, 0x55, + 0x00, 0x54, 0x70, 0x82, 0x8a, 0x90, 0x96, 0x98, + 0x98, 0x98, 0x94, 0x90, 0x88, 0x80, 0x6c, 0x52, + 0x00, 0x51, 0x6d, 0x7f, 0x87, 0x8d, 0x93, 0x95, + 0x95, 0x95, 0x91, 0x8d, 0x87, 0x7b, 0x6b, 0x4f, + 0x00, 0x4e, 0x6a, 0x7a, 0x84, 0x8a, 0x8e, 0x90, + 0x90, 0x90, 0x8c, 0x88, 0x82, 0x76, 0x66, 0x4a, + 0x00, 0x4b, 0x67, 0x75, 0x83, 0x87, 0x8b, 0x8d, + 0x8d, 0x8d, 0x8b, 0x87, 0x7f, 0x73, 0x65, 0x49, + 0x00, 0x48, 0x62, 0x70, 0x7c, 0x82, 0x86, 0x88, + 0x88, 0x88, 0x86, 0x82, 0x78, 0x6e, 0x60, 0x44, + 0x00, 0x45, 0x5f, 0x6d, 0x77, 0x7f, 0x83, 0x85, + 0x85, 0x85, 0x83, 0x7d, 0x75, 0x6b, 0x5b, 0x43, + 0x00, 0x42, 0x58, 0x68, 0x70, 0x78, 0x7c, 0x80, + 0x80, 0x7e, 0x7c, 0x76, 0x6e, 0x64, 0x54, 0x3c, + 0x00, 0x3d, 0x53, 0x63, 0x6b, 0x73, 0x77, 0x79, + 0x79, 0x79, 0x75, 0x6f, 0x69, 0x61, 0x4f, 0x37, + 0x00, 0x34, 0x4c, 0x5c, 0x66, 0x6a, 0x6e, 0x70, + 0x70, 0x70, 0x6c, 0x68, 0x62, 0x56, 0x48, 0x30, + 0x00, 0x2f, 0x47, 0x55, 0x5f, 0x65, 0x67, 0x69, + 0x69, 0x69, 0x65, 0x63, 0x59, 0x4f, 0x43, 0x2b, + 0x00, 0x28, 0x40, 0x4a, 0x52, 0x5a, 0x5e, 0x60, + 0x60, 0x5e, 0x5a, 0x54, 0x4c, 0x44, 0x36, 0x22, + 0x00, 0x23, 0x33, 0x43, 0x49, 0x4d, 0x4f, 0x51, + 0x51, 0x4f, 0x4d, 0x47, 0x43, 0x37, 0x2b, 0x19, + 0x00, 0x16, 0x26, 0x30, 0x36, 0x3c, 0x40, 0x40, + 0x40, 0x3c, 0x38, 0x32, 0x2c, 0x24, 0x1a, 0x0c, + 0x00, 0x0b, 0x15, 0x1b, 0x21, 0x23, 0x23, 0x21, + 0x1f, 0x19, 0x15, 0x0f, 0x09, 0x05, 0x03, 0x00, +}; + +/* End of waveform.h */ diff --git a/sys/arch/arm32/mainbus/wd.c b/sys/arch/arm32/mainbus/wd.c new file mode 100644 index 00000000000..e54e2e2a127 --- /dev/null +++ b/sys/arch/arm32/mainbus/wd.c @@ -0,0 +1,1764 @@ +/* $NetBSD: wd.c,v 1.6 1996/03/28 21:52:52 mark Exp $ */ + +/* + * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. + * + * DMA and multi-sector PIO handling are derived from code contributed by + * Onno van der Linden. + * + * 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 Charles M. Hannum. + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +extern int wdresethack; + +#define WAITTIME (4 * hz) /* time to wait for a completion */ +#define RECOVERYTIME (hz / 2) /* time to recover from an error */ + +#define WDCDELAY 100 +#define WDCNDELAY 100000 /* delay = 100us; so 10s for a controller state change */ +#if 0 +/* If you enable this, it will report any delays more than 100us * N long. */ +#define WDCNDELAY_DEBUG 10 +#endif + +#define WDIORETRIES 5 /* number of retries before giving up */ + +#define WDUNIT(dev) DISKUNIT(dev) +#define WDPART(dev) DISKPART(dev) +#define MAKEWDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) + +#define WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART)) + +struct wd_softc { + struct device sc_dev; + struct disk sc_dk; + + /* Information about the current transfer: */ + daddr_t sc_blkno; /* starting block number */ + int sc_bcount; /* byte count left */ + int sc_skip; /* bytes already transferred */ + int sc_nblks; /* number of blocks currently transferring */ + int sc_nbytes; /* number of bytes currently transferring */ + + /* Long-term state: */ + int sc_drive; /* physical unit number */ + int sc_state; /* control state */ +#define RECAL 0 /* recalibrate */ +#define RECAL_WAIT 1 /* done recalibrating */ +#define GEOMETRY 2 /* upload geometry */ +#define GEOMETRY_WAIT 3 /* done uploading geometry */ +#define MULTIMODE 4 /* set multiple mode */ +#define MULTIMODE_WAIT 5 /* done setting multiple mode */ +#define OPEN 6 /* done with open */ + int sc_mode; /* transfer mode */ +#define WDM_PIOSINGLE 0 /* single-sector PIO */ +#define WDM_PIOMULTI 1 /* multi-sector PIO */ +#define WDM_DMA 2 /* DMA */ + int sc_multiple; /* multiple for WDM_PIOMULTI */ + int sc_flags; /* drive characteistics found */ +#define WDF_LOCKED 0x01 +#define WDF_WANTED 0x02 +#define WDF_WLABEL 0x04 /* label is writable */ +#define WDF_LABELLING 0x08 /* writing label */ +/* XXX Nothing resets this yet, but disk change sensing will when ATAPI is + implemented. */ +#define WDF_LOADED 0x10 /* parameters loaded */ +#define WDF_32BIT 0x20 /* can do 32-bit transfer */ + + struct wdparams sc_params; /* ESDI/ATA drive parameters */ + daddr_t sc_badsect[127]; /* 126 plus trailing -1 marker */ + + TAILQ_ENTRY(wd_softc) sc_drivechain; + struct buf sc_q; +}; + +struct wdc_softc { + struct device sc_dev; + irqhandler_t sc_ih; + + int sc_iobase; /* I/O port base */ + int sc_drq; /* DMA channel */ + + TAILQ_HEAD(drivehead, wd_softc) sc_drives; + int sc_flags; +#define WDCF_ACTIVE 0x01 /* controller is active */ +#define WDCF_SINGLE 0x02 /* sector at a time mode */ +#define WDCF_ERROR 0x04 /* processing a disk error */ +#define WDCF_WANTED 0x08 /* XXX locking for wd_get_parms() */ + int sc_errors; /* errors during current transfer */ + u_char sc_status; /* copy of status register */ + u_char sc_error; /* copy of error register */ +}; + +int wdcprobe __P((struct device *, void *, void *)); +void wdcattach __P((struct device *, struct device *, void *)); + +struct cfattach wdc_ca = { + sizeof(struct wdc_softc), wdcprobe, wdcattach +}; + +struct cfdriver wdc_cd = { + NULL, "wdc", DV_DULL +}; + +int wdprobe __P((struct device *, void *, void *)); +void wdattach __P((struct device *, struct device *, void *)); + +struct cfattach wd_ca = { + sizeof(struct wd_softc), wdprobe, wdattach +}; + +struct cfdriver wd_cd = { + NULL, "wd", DV_DISK +}; + +void wdgetdisklabel __P((struct wd_softc *)); +int wd_get_parms __P((struct wd_softc *)); +void wdstrategy __P((struct buf *)); +void wdstart __P((struct wd_softc *)); + +struct dkdriver wddkdriver = { wdstrategy }; + +void wdfinish __P((struct wd_softc *, struct buf *)); +int wdcintr __P((void *)); +void wdcstart __P((struct wdc_softc *)); +int wdcommand __P((struct wd_softc *, int, int, int, int, int)); +int wdcommandshort __P((struct wdc_softc *, int, int)); +int wdcontrol __P((struct wd_softc *)); +int wdsetctlr __P((struct wd_softc *)); +static void bad144intern __P((struct wd_softc *)); +int wdcreset __P((struct wdc_softc *)); +void wdcrestart __P((void *arg)); +void wdcunwedge __P((struct wdc_softc *)); +void wdctimeout __P((void *arg)); +void wderror __P((void *, struct buf *, char *)); +int wdcwait __P((struct wdc_softc *, int)); +/* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write + command is aborted. */ +#define wait_for_drq(d) wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ) +#define wait_for_ready(d) wdcwait(d, WDCS_DRDY | WDCS_DSC) +#define wait_for_unbusy(d) wdcwait(d, 0) + +int +wdcprobe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct wdc_softc *wdc = match; + struct mainbus_attach_args *mb = aux; + int iobase; + + wdc->sc_iobase = iobase = mb->mb_iobase; + + /* Check if we have registers that work. */ + outb(iobase+wd_error, 0x5a); /* Error register not writable, */ + outb(iobase+wd_cyl_lo, 0xa5); /* but all of cyllo are. */ + if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5) + return 0; + + if (wdcreset(wdc) != 0) { + delay(500000); + if (wdcreset(wdc) != 0) + return 0; + } + + /* Select drive 0. */ + outb(iobase+wd_sdh, WDSD_IBM | 0); + + /* Wait for controller to become ready. */ + if (wait_for_unbusy(wdc) < 0) + return 0; + + /* Start drive diagnostics. */ + outb(iobase+wd_command, WDCC_DIAGNOSE); + + /* Wait for command to complete. */ + if (wait_for_unbusy(wdc) < 0) + return 0; + + mb->mb_iosize = 32; + return 1; +} + +struct wdc_attach_args { + int wa_drive; +}; + +int +wdprint(aux, wdc) + void *aux; + char *wdc; +{ + struct wdc_attach_args *wa = aux; + + if (!wdc) + printf(" drive %d", wa->wa_drive); + return QUIET; +} + +void +wdcattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct wdc_softc *wdc = (void *)self; + struct mainbus_attach_args *mb = aux; + struct wdc_attach_args wa; + + TAILQ_INIT(&wdc->sc_drives); + wdc->sc_drq = mb->mb_drq; + + printf("\n"); + + wdc->sc_ih.ih_func = wdcintr; + wdc->sc_ih.ih_arg = wdc; + wdc->sc_ih.ih_level = IPL_BIO; + wdc->sc_ih.ih_name = "wdc"; + if (irq_claim(mb->mb_irq, &wdc->sc_ih)) + panic("Cannot claim IRQ %d for wdc%d\n", mb->mb_irq, parent->dv_unit); + + for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++) + (void)config_found(self, (void *)&wa, wdprint); +} + +int +wdprobe(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct wdc_softc *wdc = (void *)parent; + struct cfdata *cf = match; + struct wdc_attach_args *wa = aux; + int drive = wa->wa_drive; + + if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive) + return 0; + + if (wdcommandshort(wdc, drive, WDCC_RECAL) != 0 || + wait_for_ready(wdc) != 0) + return 0; + + return 1; +} + +void +wdattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct wd_softc *wd = (void *)self; + struct wdc_softc *wdc = (void *)parent; + struct wdc_attach_args *wa = aux; + int i, blank; + char buf[41], c, *p, *q; + + wd->sc_drive = wa->wa_drive; + + /* + * Initialize and attach the disk structure. + */ + wd->sc_dk.dk_driver = &wddkdriver; + wd->sc_dk.dk_name = wd->sc_dev.dv_xname; + disk_attach(&wd->sc_dk); + + wd_get_parms(wd); + for (blank = 0, p = wd->sc_params.wdp_model, q = buf, i = 0; + i < sizeof(wd->sc_params.wdp_model); i++) { + c = *p++; + if (c == '\0') + break; + if (c != ' ') { + if (blank) { + *q++ = ' '; + blank = 0; + } + *q++ = c; + } else + blank = 1; + } + *q++ = '\0'; + + printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec <%s>\n", + wd->sc_params.wdp_cylinders * + (wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) / + (1048576 / DEV_BSIZE), + wd->sc_params.wdp_cylinders, + wd->sc_params.wdp_heads, + wd->sc_params.wdp_sectors, + DEV_BSIZE, + buf); + + if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 && + wdc->sc_drq != DRQUNK) { + wd->sc_mode = WDM_DMA; + } else if (wd->sc_params.wdp_maxmulti > 1) { + wd->sc_mode = WDM_PIOMULTI; + wd->sc_multiple = min(wd->sc_params.wdp_maxmulti, 16); + } else { + wd->sc_mode = WDM_PIOSINGLE; + wd->sc_multiple = 1; + } + + printf("%s: using", wd->sc_dev.dv_xname); + if (wd->sc_mode == WDM_DMA) + printf(" dma transfers,"); + else + printf(" %d-sector %d-bit pio transfers,", + wd->sc_multiple, (wd->sc_flags & WDF_32BIT) == 0 ? 16 : 32); + if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) + printf(" lba addressing\n"); + else + printf(" chs addressing\n"); +} + +/* + * Read/write routine for a buffer. Validates the arguments and schedules the + * transfer. Does not wait for the transfer to complete. + */ +void +wdstrategy(bp) + struct buf *bp; +{ + struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)]; + int s; + + /* Valid request? */ + if (bp->b_blkno < 0 || + (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 || + (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) { + bp->b_error = EINVAL; + goto bad; + } + + /* If device invalidated (e.g. media change, door open), error. */ + if ((wd->sc_flags & WDF_LOADED) == 0) { + bp->b_error = EIO; + goto bad; + } + + /* If it's a null transfer, return immediately. */ + if (bp->b_bcount == 0) + goto done; + + /* + * Do bounds checking, adjust transfer. if error, process. + * If end of partition, just return. + */ + if (WDPART(bp->b_dev) != RAW_PART && + bounds_check_with_label(bp, wd->sc_dk.dk_label, + (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0) + goto done; + + /* Queue transfer on drive, activate drive and controller if idle. */ + s = splbio(); + disksort(&wd->sc_q, bp); + if (!wd->sc_q.b_active) + wdstart(wd); +#if 0 + else { + struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent; + if ((wdc->sc_flags & (WDCF_ACTIVE|WDCF_ERROR)) == 0) { + printf("wdstrategy: controller inactive\n"); + wdcstart(wdc); + } + } +#endif + splx(s); + return; + +bad: + bp->b_flags |= B_ERROR; +done: + /* Toss transfer; we're done early. */ + bp->b_resid = bp->b_bcount; + biodone(bp); +} + +/* + * Queue a drive for I/O. + */ +void +wdstart(wd) + struct wd_softc *wd; +{ + struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent; + int active = wdc->sc_drives.tqh_first != 0; + + /* Link onto controller queue. */ + wd->sc_q.b_active = 1; + TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain); + + disk_busy(&wd->sc_dk); + + /* If controller not already active, start it. */ + if (!active) + wdcstart(wdc); +} + +/* + * Finish an I/O operation. Clean up the drive and controller state, set the + * residual count, and inform the upper layers that the operation is complete. + */ +void +wdfinish(wd, bp) + struct wd_softc *wd; + struct buf *bp; +{ + struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent; + + wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR); + wdc->sc_errors = 0; + /* + * Move this drive to the end of the queue to give others a `fair' + * chance. + */ + if (wd->sc_drivechain.tqe_next) { + TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain); + if (bp->b_actf) { + TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain); + } else + wd->sc_q.b_active = 0; + } + bp->b_resid = wd->sc_bcount; + wd->sc_skip = 0; + wd->sc_q.b_actf = bp->b_actf; + + disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid)); + + if (!wd->sc_q.b_actf) { + TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain); + wd->sc_q.b_active = 0; + } else + disk_busy(&wd->sc_dk); + + biodone(bp); +} + +int +wdread(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio)); +} + +int +wdwrite(dev, uio) + dev_t dev; + struct uio *uio; +{ + + return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio)); +} + +/* + * Start I/O on a controller. This does the calculation, and starts a read or + * write operation. Called to from wdstart() to start a transfer, from + * wdcintr() to continue a multi-sector transfer or start the next transfer, or + * wdcrestart() after recovering from an error. + */ +void +wdcstart(wdc) + struct wdc_softc *wdc; +{ + struct wd_softc *wd; + struct buf *bp; + struct disklabel *lp; + int nblks; + +#ifdef DIAGNOSTIC + if ((wdc->sc_flags & WDCF_ACTIVE) != 0) + panic("wdcstart: controller still active"); +#endif + + /* + * XXX + * This is a kluge. See comments in wd_get_parms(). + */ + if ((wdc->sc_flags & WDCF_WANTED) != 0) { + wdc->sc_flags &= ~WDCF_WANTED; + wakeup(wdc); + return; + } + +loop: + /* Is there a drive for the controller to do a transfer with? */ + wd = wdc->sc_drives.tqh_first; + if (wd == NULL) + return; + + /* Is there a transfer to this drive? If not, deactivate drive. */ + bp = wd->sc_q.b_actf; + + if (wdc->sc_errors >= WDIORETRIES) { + wderror(wd, bp, "hard error"); + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + wdfinish(wd, bp); + goto loop; + } + + /* Do control operations specially. */ + if (wd->sc_state < OPEN) { + /* + * Actually, we want to be careful not to mess with the control + * state if the device is currently busy, but we can assume + * that we never get to this point if that's the case. + */ + if (wdcontrol(wd) == 0) { + /* The drive is busy. Wait. */ + return; + } + } + + /* + * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is + * encountered. If we are in multi-sector mode, then we switch to + * single-sector mode and retry the operation from the start. + */ + if (wdc->sc_flags & WDCF_ERROR) { + wdc->sc_flags &= ~WDCF_ERROR; + if ((wdc->sc_flags & WDCF_SINGLE) == 0) { + wdc->sc_flags |= WDCF_SINGLE; + wd->sc_skip = 0; + } + } + + lp = wd->sc_dk.dk_label; + + /* When starting a transfer... */ + if (wd->sc_skip == 0) { + int part = WDPART(bp->b_dev); + daddr_t blkno; + +#ifdef WDDEBUG + printf("\n%s: wdcstart %s %d@%d; map ", wd->sc_dev.dv_xname, + (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount, + bp->b_blkno); +#endif + wd->sc_bcount = bp->b_bcount; + blkno = bp->b_blkno; + if (part != RAW_PART) + blkno += lp->d_partitions[part].p_offset; + wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE); + } else { +#ifdef WDDEBUG + printf(" %d)%x", wd->sc_skip, inb(wd->sc_iobase+wd_altsts)); +#endif + } + + /* When starting a multi-sector transfer, or doing single-sector + transfers... */ + if (wd->sc_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 || + wd->sc_mode == WDM_DMA) { + daddr_t blkno = wd->sc_blkno; + long cylin, head, sector; + int command; + + if ((wdc->sc_flags & WDCF_SINGLE) != 0) + nblks = 1; + else if (wd->sc_mode != WDM_DMA) + nblks = wd->sc_bcount / lp->d_secsize; + else + nblks = min(wd->sc_bcount / lp->d_secsize, 8); + + /* Check for bad sectors and adjust transfer, if necessary. */ + if ((lp->d_flags & D_BADSECT) != 0 +#ifdef B_FORMAT + && (bp->b_flags & B_FORMAT) == 0 +#endif + ) { + long blkdiff; + int i; + + for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) { + blkdiff -= blkno; + if (blkdiff < 0) + continue; + if (blkdiff == 0) { + /* Replace current block of transfer. */ + blkno = + lp->d_secperunit - lp->d_nsectors - i - 1; + } + if (blkdiff < nblks) { + /* Bad block inside transfer. */ + wdc->sc_flags |= WDCF_SINGLE; + nblks = 1; + } + break; + } + /* Tranfer is okay now. */ + } + + if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) { + sector = (blkno >> 0) & 0xff; + cylin = (blkno >> 8) & 0xffff; + head = (blkno >> 24) & 0xf; + head |= WDSD_LBA; + } else { + sector = blkno % lp->d_nsectors; + sector++; /* Sectors begin with 1, not 0. */ + blkno /= lp->d_nsectors; + head = blkno % lp->d_ntracks; + blkno /= lp->d_ntracks; + cylin = blkno; + head |= WDSD_CHS; + } + + if (wd->sc_mode == WDM_PIOSINGLE || + (wdc->sc_flags & WDCF_SINGLE) != 0) + wd->sc_nblks = 1; + else if (wd->sc_mode == WDM_PIOMULTI) + wd->sc_nblks = min(nblks, wd->sc_multiple); + else + wd->sc_nblks = nblks; + wd->sc_nbytes = wd->sc_nblks * lp->d_secsize; + +#ifdef B_FORMAT + if (bp->b_flags & B_FORMAT) { + sector = lp->d_gap3; + nblks = lp->d_nsectors; + command = WDCC_FORMAT; + } else +#endif + switch (wd->sc_mode) { + case WDM_DMA: + command = (bp->b_flags & B_READ) ? + WDCC_READDMA : WDCC_WRITEDMA; + /* Start the DMA channel and bounce the buffer if + necessary. */ +/* isa_dmastart(bp->b_flags & B_READ, + bp->b_data + wd->sc_skip, + wd->sc_nbytes, wdc->sc_drq);*/ + panic("wd cannot do DMA yet\n"); + break; + case WDM_PIOMULTI: + command = (bp->b_flags & B_READ) ? + WDCC_READMULTI : WDCC_WRITEMULTI; + break; + case WDM_PIOSINGLE: + command = (bp->b_flags & B_READ) ? + WDCC_READ : WDCC_WRITE; + break; + } + + /* Initiate command! */ + if (wdcommand(wd, command, cylin, head, sector, nblks) != 0) { + wderror(wd, NULL, + "wdcstart: timeout waiting for unbusy"); + wdcunwedge(wdc); + return; + } + +#ifdef WDDEBUG + printf("sector %d cylin %d head %d addr %x sts %x\n", sector, + cylin, head, bp->b_data, 0/*inb(wd->sc_iobase+wd_altsts)*/); +#endif + } else if (wd->sc_nblks > 1) { + /* The number of blocks in the last stretch may be smaller. */ + nblks = wd->sc_bcount / lp->d_secsize; + if (wd->sc_nblks > nblks) { + wd->sc_nblks = nblks; + wd->sc_nbytes = wd->sc_bcount; + } + } + + /* If this was a write and not using DMA, push the data. */ + if (wd->sc_mode != WDM_DMA && + (bp->b_flags & (B_READ|B_WRITE)) == B_WRITE) { + if (wait_for_drq(wdc) < 0) { + wderror(wd, NULL, "wdcstart: timeout waiting for drq"); + wdcunwedge(wdc); + return; + } + + /* Push out data. */ + if ((wd->sc_flags & WDF_32BIT) == 0) + outsw(wdc->sc_iobase+wd_data, (u_int) bp->b_data + wd->sc_skip, + wd->sc_nbytes >> 1); + else + panic("wd cannot do 32 bit transfers\n"); +/* outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip, + wd->sc_nbytes >> 2);*/ + } + + wdc->sc_flags |= WDCF_ACTIVE; + timeout(wdctimeout, wdc, WAITTIME); +} + +/* + * Interrupt routine for the controller. Acknowledge the interrupt, check for + * errors on the current operation, mark it done if necessary, and start the + * next request. Also check for a partially done transfer, and continue with + * the next chunk if so. + */ +int +wdcintr(arg) + void *arg; +{ + struct wdc_softc *wdc = arg; + struct wd_softc *wd; + struct buf *bp; + + if ((wdc->sc_flags & WDCF_ACTIVE) == 0) { + /* Clear the pending interrupt and abort. */ + (void) inb(wdc->sc_iobase+wd_status); + return 0; + } + + wdc->sc_flags &= ~WDCF_ACTIVE; + untimeout(wdctimeout, wdc); + + wd = wdc->sc_drives.tqh_first; + bp = wd->sc_q.b_actf; + +#ifdef WDDEBUG + printf("I%d ", ctrlr); +#endif + + if (wait_for_unbusy(wdc) < 0) { + wderror(wd, NULL, "wdcintr: timeout waiting for unbusy"); + wdc->sc_status |= WDCS_ERR; /* XXX */ + } + + /* Is it not a transfer, but a control operation? */ + if (wd->sc_state < OPEN) { + if (wdcontrol(wd) == 0) { + /* The drive is busy. Wait. */ + return 1; + } + wdcstart(wdc); + return 1; + } + + /* Turn off the DMA channel and unbounce the buffer. */ + if (wd->sc_mode == WDM_DMA) + panic("wd cannot do DMA\n"); +/* isa_dmadone(bp->b_flags & B_READ, bp->b_data + wd->sc_skip, + wd->sc_nbytes, wdc->sc_drq);*/ + + /* Have we an error? */ + if (wdc->sc_status & WDCS_ERR) { + lose: +#ifdef WDDEBUG + wderror(wd, NULL, "wdcintr"); +#endif + if ((wdc->sc_flags & WDCF_SINGLE) == 0) { + wdc->sc_flags |= WDCF_ERROR; + goto restart; + } + +#ifdef B_FORMAT + if (bp->b_flags & B_FORMAT) + goto bad; +#endif + + if (++wdc->sc_errors < WDIORETRIES) + goto restart; + wderror(wd, bp, "hard error"); + + bad: + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + goto done; + } + + /* If this was a read and not using DMA, fetch the data. */ + if (wd->sc_mode != WDM_DMA && + (bp->b_flags & (B_READ|B_WRITE)) == B_READ) { + if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) + != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) { + wderror(wd, NULL, "wdcintr: read intr before drq"); + wdcunwedge(wdc); + return 1; + } + + /* Pull in data. */ + if ((wd->sc_flags & WDF_32BIT) == 0) + insw(wdc->sc_iobase+wd_data, (u_int) bp->b_data + wd->sc_skip, + wd->sc_nbytes >> 1); + else + panic("wd cannot do 32 bit transfers\n"); +/* insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip, + wd->sc_nbytes >> 2);*/ + } + + /* If we encountered any abnormalities, flag it as a soft error. */ + if (wdc->sc_errors > 0 || + (wdc->sc_status & WDCS_CORR) != 0) { + wderror(wd, bp, "soft error (corrected)"); + wdc->sc_errors = 0; + } + + /* Adjust pointers for the next block, if any. */ + wd->sc_blkno += wd->sc_nblks; + wd->sc_skip += wd->sc_nbytes; + wd->sc_bcount -= wd->sc_nbytes; + + /* See if this transfer is complete. */ + if (wd->sc_bcount > 0) + goto restart; + +done: + /* Done with this transfer, with or without error. */ + wdfinish(wd, bp); + +restart: + /* Start the next operation, if any. */ + wdcstart(wdc); + + return 1; +} + +/* + * Wait interruptibly for an exclusive lock. + * + * XXX + * Several drivers do this; it should be abstracted and made MP-safe. + */ +int +wdlock(wd) + struct wd_softc *wd; +{ + int error; + + while ((wd->sc_flags & WDF_LOCKED) != 0) { + wd->sc_flags |= WDF_WANTED; + if ((error = tsleep(wd, PRIBIO | PCATCH, "wdlck", 0)) != 0) + return error; + } + wd->sc_flags |= WDF_LOCKED; + return 0; +} + +/* + * Unlock and wake up any waiters. + */ +void +wdunlock(wd) + struct wd_softc *wd; +{ + + wd->sc_flags &= ~WDF_LOCKED; + if ((wd->sc_flags & WDF_WANTED) != 0) { + wd->sc_flags &= ~WDF_WANTED; + wakeup(wd); + } +} + +int +wdopen(dev, flag, fmt) + dev_t dev; + int flag, fmt; +{ + struct wd_softc *wd; + int unit, part; + int error; + + unit = WDUNIT(dev); + if (unit >= wd_cd.cd_ndevs) + return ENXIO; + wd = wd_cd.cd_devs[unit]; + if (wd == 0) + return ENXIO; + + if (error = wdlock(wd)) + return error; + + if (wd->sc_dk.dk_openmask != 0) { + /* + * If any partition is open, but the disk has been invalidated, + * disallow further opens. + */ + if ((wd->sc_flags & WDF_LOADED) == 0) { + error = EIO; + goto bad3; + } + } else { + if ((wd->sc_flags & WDF_LOADED) == 0) { + wd->sc_flags |= WDF_LOADED; + + /* Load the physical device parameters. */ + if (wd_get_parms(wd) != 0) { + error = ENXIO; + goto bad2; + } + + /* Load the partition info if not already loaded. */ + wdgetdisklabel(wd); + } + } + + part = WDPART(dev); + + /* Check that the partition exists. */ + if (part != RAW_PART && + (part >= wd->sc_dk.dk_label->d_npartitions || + wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { + error = ENXIO; + goto bad; + } + + /* Insure only one open at a time. */ + switch (fmt) { + case S_IFCHR: + wd->sc_dk.dk_copenmask |= (1 << part); + break; + case S_IFBLK: + wd->sc_dk.dk_bopenmask |= (1 << part); + break; + } + wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; + + wdunlock(wd); + return 0; + +bad2: + wd->sc_flags &= ~WDF_LOADED; + +bad: + if (wd->sc_dk.dk_openmask == 0) { + } + +bad3: + wdunlock(wd); + return error; +} + +int +wdclose(dev, flag, fmt) + dev_t dev; + int flag, fmt; +{ + struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)]; + int part = WDPART(dev); + int error; + + if (error = wdlock(wd)) + return error; + + switch (fmt) { + case S_IFCHR: + wd->sc_dk.dk_copenmask &= ~(1 << part); + break; + case S_IFBLK: + wd->sc_dk.dk_bopenmask &= ~(1 << part); + break; + } + wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; + + if (wd->sc_dk.dk_openmask == 0) { + /* XXXX Must wait for I/O to complete! */ + } + + wdunlock(wd); + return 0; +} + +/* + * Fabricate a default disk label, and try to read the correct one. + */ +void +wdgetdisklabel(wd) + struct wd_softc *wd; +{ + struct disklabel *lp = wd->sc_dk.dk_label; + char *errstring; + + bzero(lp, sizeof(struct disklabel)); + bzero(wd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel)); + + lp->d_secsize = DEV_BSIZE; + lp->d_ntracks = wd->sc_params.wdp_heads; + lp->d_nsectors = wd->sc_params.wdp_sectors; + lp->d_ncylinders = wd->sc_params.wdp_cylinders; + lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; + +#if 0 + strncpy(lp->d_typename, "ST506 disk", 16); + lp->d_type = DTYPE_ST506; +#endif + strncpy(lp->d_packname, wd->sc_params.wdp_model, 16); + lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; + lp->d_rpm = 3600; + lp->d_interleave = 1; + lp->d_flags = 0; + + lp->d_partitions[RAW_PART].p_offset = 0; + lp->d_partitions[RAW_PART].p_size = + lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); + lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; + lp->d_npartitions = RAW_PART + 1; + + lp->d_magic = DISKMAGIC; + lp->d_magic2 = DISKMAGIC; + lp->d_checksum = dkcksum(lp); + + wd->sc_badsect[0] = -1; + + if (wd->sc_state > RECAL) + wd->sc_state = RECAL; + errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART), + wdstrategy, lp, wd->sc_dk.dk_cpulabel); + if (errstring) { + /* + * This probably happened because the drive's default + * geometry doesn't match the DOS geometry. We + * assume the DOS geometry is now in the label and try + * again. XXX This is a kluge. + */ + if (wd->sc_state > GEOMETRY) + wd->sc_state = GEOMETRY; + errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART), + wdstrategy, lp, wd->sc_dk.dk_cpulabel); + } + if (errstring) { + printf("%s: %s\n", wd->sc_dev.dv_xname, errstring); + return; + } + + if (wd->sc_state > GEOMETRY) + wd->sc_state = GEOMETRY; + if ((lp->d_flags & D_BADSECT) != 0) + bad144intern(wd); +} + +/* + * Implement operations needed before read/write. + * Returns 0 if operation still in progress, 1 if completed. + */ +int +wdcontrol(wd) + struct wd_softc *wd; +{ + struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent; + + switch (wd->sc_state) { + case RECAL: /* Set SDH, step rate, do recal. */ + if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0) { + wderror(wd, NULL, "wdcontrol: recal failed (1)"); + goto bad; + } + wd->sc_state = RECAL_WAIT; + break; + + case RECAL_WAIT: + if (wdc->sc_status & WDCS_ERR) { + wderror(wd, NULL, "wdcontrol: recal failed (2)"); + goto bad; + } + /* fall through */ + case GEOMETRY: + if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) + goto multimode; + if (wdsetctlr(wd) != 0) { + /* Already printed a message. */ + goto bad; + } + wd->sc_state = GEOMETRY_WAIT; + break; + + case GEOMETRY_WAIT: + if (wdc->sc_status & WDCS_ERR) { + wderror(wd, NULL, "wdcontrol: geometry failed"); + goto bad; + } + /* fall through */ + case MULTIMODE: + multimode: + if (wd->sc_mode != WDM_PIOMULTI) + goto open; + outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple); + if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) { + wderror(wd, NULL, "wdcontrol: setmulti failed (1)"); + goto bad; + } + wd->sc_state = MULTIMODE_WAIT; + break; + + case MULTIMODE_WAIT: + if (wdc->sc_status & WDCS_ERR) { + wderror(wd, NULL, "wdcontrol: setmulti failed (2)"); + goto bad; + } + /* fall through */ + case OPEN: + open: + wdc->sc_errors = 0; + wd->sc_state = OPEN; + /* + * The rest of the initialization can be done by normal means. + */ + return 1; + + bad: + wdcunwedge(wdc); + return 0; + } + + wdc->sc_flags |= WDCF_ACTIVE; + timeout(wdctimeout, wdc, WAITTIME); + return 0; +} + +/* + * Wait for the drive to become ready and send a command. + * Return -1 if busy for too long or 0 otherwise. + * Assumes interrupts are blocked. + */ +int +wdcommand(wd, command, cylin, head, sector, count) + struct wd_softc *wd; + int command; + int cylin, head, sector, count; +{ + struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent; + int iobase = wdc->sc_iobase; + int stat; + + /* Select drive, head, and addressing mode. */ + outb(iobase+wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head); + + /* Wait for it to become ready to accept a command. */ + if (command == WDCC_IDP) + stat = wait_for_unbusy(wdc); + else + stat = wdcwait(wdc, WDCS_DRDY); + if (stat < 0) + return -1; + + /* Load parameters. */ + if (wd->sc_dk.dk_label->d_type == DTYPE_ST506) + outb(iobase+wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4); + else + outb(iobase+wd_features, 0); + outb(iobase+wd_cyl_lo, cylin); + outb(iobase+wd_cyl_hi, cylin >> 8); + outb(iobase+wd_sector, sector); + outb(iobase+wd_seccnt, count); + + /* Send command. */ + outb(iobase+wd_command, command); + + return 0; +} + +/* + * Simplified version of wdcommand(). + */ +int +wdcommandshort(wdc, drive, command) + struct wdc_softc *wdc; + int drive; + int command; +{ + int iobase = wdc->sc_iobase; + + /* Select drive. */ + outb(iobase+wd_sdh, WDSD_IBM | (drive << 4)); + + if (wdcwait(wdc, WDCS_DRDY) < 0) + return -1; + + outb(iobase+wd_command, command); + + return 0; +} + +/* + * Tell the drive what geometry to use. + */ +int +wdsetctlr(wd) + struct wd_softc *wd; +{ + struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent; + +#ifdef WDDEBUG + printf("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit, wd->sc_drive, + wd->sc_dk.dk_label->d_ncylinders, wd->sc_dk.dk_label->d_ntracks, + wd->sc_dk.dk_label->d_nsectors); +#endif + + if (wdcommand(wd, WDCC_IDP, wd->sc_dk.dk_label->d_ncylinders, + wd->sc_dk.dk_label->d_ntracks - 1, 0, + wd->sc_dk.dk_label->d_nsectors) != 0) { + wderror(wd, NULL, "wdsetctlr: geometry upload failed"); + return -1; + } + + return 0; +} + +/* + * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506. + */ +int +wd_get_parms(wd) + struct wd_softc *wd; +{ + struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent; + int i; + char tb[DEV_BSIZE]; + int s, error; + + /* + * XXX + * The locking done here, and the length of time this may keep the rest + * of the system suspended, is a kluge. This should be rewritten to + * set up a transfer and queue it through wdstart(), but it's called + * infrequently enough that this isn't a pressing matter. + */ + + s = splbio(); + + while ((wdc->sc_flags & WDCF_ACTIVE) != 0) { + wdc->sc_flags |= WDCF_WANTED; + if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) { + splx(s); + return error; + } + } + + if (wdcommandshort(wdc, wd->sc_drive, WDCC_IDENTIFY) != 0 || + wait_for_drq(wdc) != 0) { + /* + * We `know' there's a drive here; just assume it's old. + * This geometry is only used to read the MBR and print a + * (false) attach message. + */ + strncpy(wd->sc_dk.dk_label->d_typename, "ST506", + sizeof wd->sc_dk.dk_label->d_typename); + wd->sc_dk.dk_label->d_type = DTYPE_ST506; + + strncpy(wd->sc_params.wdp_model, "unknown", + sizeof wd->sc_params.wdp_model); + wd->sc_params.wdp_config = WD_CFG_FIXED; + wd->sc_params.wdp_cylinders = 1024; + wd->sc_params.wdp_heads = 8; + wd->sc_params.wdp_sectors = 17; + wd->sc_params.wdp_maxmulti = 0; + wd->sc_params.wdp_usedmovsd = 0; + wd->sc_params.wdp_capabilities = 0; + } else { + strncpy(wd->sc_dk.dk_label->d_typename, "ESDI/IDE", + sizeof wd->sc_dk.dk_label->d_typename); + wd->sc_dk.dk_label->d_type = DTYPE_ESDI; + + /* Read in parameter block. */ + insw(wdc->sc_iobase+wd_data, (u_int)tb, sizeof(tb) / sizeof(short)); + bcopy(tb, &wd->sc_params, sizeof(struct wdparams)); + + /* Shuffle string byte order. */ + for (i = 0; i < sizeof(wd->sc_params.wdp_model); i += 2) { + u_short *p; + p = (u_short *)(wd->sc_params.wdp_model + i); + *p = ntohs(*p); + } + } + + /* Clear any leftover interrupt. */ + (void) inb(wdc->sc_iobase+wd_status); + + /* Restart the queue. */ + wdcstart(wdc); + + splx(s); + return 0; +} + +int +wdioctl(dev, cmd, addr, flag, p) + dev_t dev; + u_long cmd; + caddr_t addr; + int flag; + struct proc *p; +{ + struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)]; + int error; + + if ((wd->sc_flags & WDF_LOADED) == 0) + return EIO; + + switch (cmd) { + case DIOCSBAD: + if ((flag & FWRITE) == 0) + return EBADF; + wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr; + wd->sc_dk.dk_label->d_flags |= D_BADSECT; + bad144intern(wd); + return 0; + + case DIOCGDINFO: + *(struct disklabel *)addr = *(wd->sc_dk.dk_label); + return 0; + + case DIOCGPART: + ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label; + ((struct partinfo *)addr)->part = + &wd->sc_dk.dk_label->d_partitions[WDPART(dev)]; + return 0; + + case DIOCWDINFO: + case DIOCSDINFO: + if ((flag & FWRITE) == 0) + return EBADF; + + if (error = wdlock(wd)) + return error; + wd->sc_flags |= WDF_LABELLING; + + error = setdisklabel(wd->sc_dk.dk_label, + (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0, + wd->sc_dk.dk_cpulabel); + if (error == 0) { + if (wd->sc_state > GEOMETRY) + wd->sc_state = GEOMETRY; + if (cmd == DIOCWDINFO) + error = writedisklabel(WDLABELDEV(dev), + wdstrategy, wd->sc_dk.dk_label, + wd->sc_dk.dk_cpulabel); + } + + wd->sc_flags &= ~WDF_LABELLING; + wdunlock(wd); + return error; + + case DIOCWLABEL: + if ((flag & FWRITE) == 0) + return EBADF; + if (*(int *)addr) + wd->sc_flags |= WDF_WLABEL; + else + wd->sc_flags &= ~WDF_WLABEL; + return 0; + +#ifdef notyet + case DIOCWFORMAT: + if ((flag & FWRITE) == 0) + return EBADF; + { + register struct format_op *fop; + struct iovec aiov; + struct uio auio; + + fop = (struct format_op *)addr; + aiov.iov_base = fop->df_buf; + aiov.iov_len = fop->df_count; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_resid = fop->df_count; + auio.uio_segflg = 0; + auio.uio_offset = + fop->df_startblk * wd->sc_dk.dk_label->d_secsize; + auio.uio_procp = p; + error = physio(wdformat, NULL, dev, B_WRITE, minphys, + &auio); + fop->df_count -= auio.uio_resid; + fop->df_reg[0] = wdc->sc_status; + fop->df_reg[1] = wdc->sc_error; + return error; + } +#endif + + default: + return ENOTTY; + } + +#ifdef DIAGNOSTIC + panic("wdioctl: impossible"); +#endif +} + +#ifdef B_FORMAT +int +wdformat(struct buf *bp) +{ + + bp->b_flags |= B_FORMAT; + return wdstrategy(bp); +} +#endif + +int +wdsize(dev) + dev_t dev; +{ + struct wd_softc *wd; + int part; + int size; + + if (wdopen(dev, 0, S_IFBLK) != 0) + return -1; + wd = wd_cd.cd_devs[WDUNIT(dev)]; + part = WDPART(dev); + if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) + size = -1; + else + size = wd->sc_dk.dk_label->d_partitions[part].p_size; + if (wdclose(dev, 0, S_IFBLK) != 0) + return -1; + return size; +} + + +#ifndef __BDEVSW_DUMP_OLD_TYPE +/* #define WD_DUMP_NOT_TRUSTED if you just want to watch */ +static int wddoingadump; +static int wddumprecalibrated; + +/* + * Dump core after a system crash. + */ +int +wddump(dev, blkno, va, size) + dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; +{ + struct wd_softc *wd; /* disk unit to do the I/O */ + struct wdc_softc *wdc; /* disk controller to do the I/O */ + struct disklabel *lp; /* disk's disklabel */ + int unit, part; + int nblks; /* total number of sectors left to write */ + + /* Check if recursive dump; if so, punt. */ + if (wddoingadump) + return EFAULT; + wddoingadump = 1; + + unit = WDUNIT(dev); + if (unit >= wd_cd.cd_ndevs) + return ENXIO; + wd = wd_cd.cd_devs[unit]; + if (wd == 0) + return ENXIO; + + part = WDPART(dev); + + /* Make sure it was initialized. */ + if (wd->sc_state < OPEN) + return ENXIO; + + wdc = (void *)wd->sc_dev.dv_parent; + + /* Convert to disk sectors. Request must be a multiple of size. */ + lp = wd->sc_dk.dk_label; + if ((size % lp->d_secsize) != 0) + return EFAULT; + nblks = size / lp->d_secsize; + blkno = blkno / (lp->d_secsize / DEV_BSIZE); + + /* Check transfer bounds against partition size. */ + if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size)) + return EINVAL; + + /* Offset block number to start of partition. */ + blkno += lp->d_partitions[part].p_offset; + + /* Recalibrate, if first dump transfer. */ + if (wddumprecalibrated == 0) { + wddumprecalibrated = 1; + if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0 || + wait_for_ready(wdc) != 0 || wdsetctlr(wd) != 0 || + wait_for_ready(wdc) != 0) { + wderror(wd, NULL, "wddump: recal failed"); + return EIO; + } + } + + while (nblks > 0) { + daddr_t xlt_blkno = blkno; + long cylin, head, sector; + + if ((lp->d_flags & D_BADSECT) != 0) { + long blkdiff; + int i; + + for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) { + blkdiff -= xlt_blkno; + if (blkdiff < 0) + continue; + if (blkdiff == 0) { + /* Replace current block of transfer. */ + xlt_blkno = lp->d_secperunit - + lp->d_nsectors - i - 1; + } + break; + } + /* Tranfer is okay now. */ + } + + if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) { + sector = (xlt_blkno >> 0) & 0xff; + cylin = (xlt_blkno >> 8) & 0xffff; + head = (xlt_blkno >> 24) & 0xf; + head |= WDSD_LBA; + } else { + sector = xlt_blkno % lp->d_nsectors; + sector++; /* Sectors begin with 1, not 0. */ + xlt_blkno /= lp->d_nsectors; + head = xlt_blkno % lp->d_ntracks; + xlt_blkno /= lp->d_ntracks; + cylin = xlt_blkno; + head |= WDSD_CHS; + } + +#ifndef WD_DUMP_NOT_TRUSTED + if (wdcommand(wd, WDCC_WRITE, cylin, head, sector, 1) != 0 || + wait_for_drq(wdc) != 0) { + wderror(wd, NULL, "wddump: write failed"); + return EIO; + } + + outsw(wdc->sc_iobase+wd_data, (u_int)va, lp->d_secsize >> 1); + + /* Check data request (should be done). */ + if (wait_for_ready(wdc) != 0) { + wderror(wd, NULL, "wddump: timeout waiting for ready"); + return EIO; + } +#else /* WD_DUMP_NOT_TRUSTED */ + /* Let's just talk about this first... */ + printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n", + unit, va, cylin, head, sector); + delay(500 * 1000); /* half a second */ +#endif + + /* update block count */ + nblks -= 1; + blkno += 1; + va += lp->d_secsize; + } + + wddoingadump = 0; + return 0; +} +#else /* __BDEVSW_DUMP_NEW_TYPE */ +int +wddump(dev, blkno, va, size) + dev_t dev; + daddr_t blkno; + caddr_t va; + size_t size; +{ + + /* Not implemented. */ + return ENXIO; +} +#endif /* __BDEVSW_DUMP_NEW_TYPE */ + +/* + * Internalize the bad sector table. + */ +void +bad144intern(wd) + struct wd_softc *wd; +{ + struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad; + struct disklabel *lp = wd->sc_dk.dk_label; + int i = 0; + + for (; i < 126; i++) { + if (bt->bt_bad[i].bt_cyl == 0xffff) + break; + wd->sc_badsect[i] = + bt->bt_bad[i].bt_cyl * lp->d_secpercyl + + (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors + + (bt->bt_bad[i].bt_trksec & 0xff); + } + for (; i < 127; i++) + wd->sc_badsect[i] = -1; +} + +int +wdcreset(wdc) + struct wdc_softc *wdc; +{ + int iobase = wdc->sc_iobase; + + /* Reset the device. */ + if (wdresethack) { + outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS); + delay(1000); + outb(iobase+wd_ctlr, WDCTL_IDS); + delay(1000); + (void) inb(iobase+wd_error); + outb(iobase+wd_ctlr, WDCTL_4BIT); + } + + if (wait_for_unbusy(wdc) < 0) { + printf("%s: reset failed\n", wdc->sc_dev.dv_xname); + return 1; + } + + return 0; +} + +void +wdcrestart(arg) + void *arg; +{ + struct wdc_softc *wdc = arg; + int s; + + s = splbio(); + wdcstart(wdc); + splx(s); +} + +/* + * Unwedge the controller after an unexpected error. We do this by resetting + * it, marking all drives for recalibration, and stalling the queue for a short + * period to give the reset time to finish. + * NOTE: We use a timeout here, so this routine must not be called during + * autoconfig or dump. + */ +void +wdcunwedge(wdc) + struct wdc_softc *wdc; +{ + int unit; + + untimeout(wdctimeout, wdc); + (void) wdcreset(wdc); + + /* Schedule recalibrate for all drives on this controller. */ + for (unit = 0; unit < wd_cd.cd_ndevs; unit++) { + struct wd_softc *wd = wd_cd.cd_devs[unit]; + if (!wd || (void *)wd->sc_dev.dv_parent != wdc) + continue; + if (wd->sc_state > RECAL) + wd->sc_state = RECAL; + } + + wdc->sc_flags |= WDCF_ERROR; + ++wdc->sc_errors; + + /* Wake up in a little bit and restart the operation. */ + timeout(wdcrestart, wdc, RECOVERYTIME); +} + +int +wdcwait(wdc, mask) + struct wdc_softc *wdc; + int mask; +{ + int iobase = wdc->sc_iobase; + int timeout = 0; + u_char status; + extern int cold; + + for (;;) { + wdc->sc_status = status = inb(iobase+wd_status); + if ((status & WDCS_BSY) == 0 && (status & mask) == mask) + break; + if (++timeout > WDCNDELAY) + return -1; + delay(WDCDELAY); + } + if (status & WDCS_ERR) { + wdc->sc_error = inb(iobase+wd_error); + return WDCS_ERR; + } +#ifdef WDCNDELAY_DEBUG + /* After autoconfig, there should be no long delays. */ + if (!cold && timeout > WDCNDELAY_DEBUG) + printf("%s: warning: busy-wait took %dus\n", + wdc->sc_dev.dv_xname, WDCDELAY * timeout); +#endif + return 0; +} + +void +wdctimeout(arg) + void *arg; +{ + struct wdc_softc *wdc = (struct wdc_softc *)arg; + int s; + + s = splbio(); + if ((wdc->sc_flags & WDCF_ACTIVE) != 0) { + struct wd_softc *wd = wdc->sc_drives.tqh_first; + struct buf *bp = wd->sc_q.b_actf; + + wdc->sc_flags &= ~WDCF_ACTIVE; + wderror(wdc, NULL, "lost interrupt"); + printf("%s: lost interrupt: %sing %d@%s:%d\n", + wdc->sc_dev.dv_xname, + (bp->b_flags & B_READ) ? "read" : "writ", + wd->sc_nblks, wd->sc_dev.dv_xname, wd->sc_blkno); + wdcunwedge(wdc); + } else + wderror(wdc, NULL, "missing untimeout"); + splx(s); +} + +void +wderror(dev, bp, msg) + void *dev; + struct buf *bp; + char *msg; +{ + struct wd_softc *wd = dev; + struct wdc_softc *wdc = dev; + + if (bp) { + diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE, + wd->sc_dk.dk_label); + printf("\n"); + } else + printf("%s: %s: status %b error %b\n", wdc->sc_dev.dv_xname, + msg, wdc->sc_status, WDCS_BITS, wdc->sc_error, WDERR_BITS); +} diff --git a/sys/arch/arm32/mainbus/wdreg.h b/sys/arch/arm32/mainbus/wdreg.h new file mode 100644 index 00000000000..12311b76e60 --- /dev/null +++ b/sys/arch/arm32/mainbus/wdreg.h @@ -0,0 +1,161 @@ +/* $NetBSD: wdreg.h,v 1.1 1996/01/31 23:25:18 mark Exp $ */ + +/*- + * Copyright (c) 1991 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. + * + * @(#)wdreg.h 7.1 (Berkeley) 5/9/91 + */ + +/* + * Disk Controller register definitions. + */ +#define wd_data 0x000 /* data register (R/W - 16 bits) */ +#define wd_error 0x004 /* error register (R) */ +#define wd_precomp 0x004 /* write precompensation (W) */ +#define wd_features 0x004 /* features (W) */ +#define wd_seccnt 0x008 /* sector count (R/W) */ +#define wd_sector 0x00c /* first sector number (R/W) */ +#define wd_cyl_lo 0x010 /* cylinder address, low byte (R/W) */ +#define wd_cyl_hi 0x014 /* cylinder address, high byte (R/W) */ +#define wd_sdh 0x018 /* sector size/drive/head (R/W) */ +#define wd_command 0x01c /* command register (W) */ +#define wd_status 0x01c /* immediate status (R) */ + +#define wd_altsts 0x818 /* alternate fixed disk status (via 1015) (R) */ +#define wd_ctlr 0x818 /* fixed disk controller control (via 1015) (W) */ +#define WDCTL_4BIT 0x08 /* use four head bits (wd1003) */ +#define WDCTL_RST 0x04 /* reset the controller */ +#define WDCTL_IDS 0x02 /* disable controller interrupts */ +#define wd_digin 0x81c /* disk controller input (via 1015) (R) */ + +/* + * Status bits. + */ +#define WDCS_BSY 0x80 /* busy */ +#define WDCS_DRDY 0x40 /* drive ready */ +#define WDCS_DWF 0x20 /* drive write fault */ +#define WDCS_DSC 0x10 /* drive seek complete */ +#define WDCS_DRQ 0x08 /* data request */ +#define WDCS_CORR 0x04 /* corrected data */ +#define WDCS_IDX 0x02 /* index */ +#define WDCS_ERR 0x01 /* error */ +#define WDCS_BITS "\020\010bsy\007drdy\006dwf\005dsc\004drq\003corr\002idx\001err" + +/* + * Error bits. + */ +#define WDCE_BBK 0x80 /* bad block detected */ +#define WDCE_UNC 0x40 /* uncorrectable data error */ +#define WDCE_MC 0x20 /* media changed */ +#define WDCE_IDNF 0x10 /* id not found */ +#define WDCE_ABRT 0x08 /* aborted command */ +#define WDCE_MCR 0x04 /* media change requested */ +#define WDCE_TK0NF 0x02 /* track 0 not found */ +#define WDCE_AMNF 0x01 /* address mark not found */ +#define WDERR_BITS "\020\010bbk\007unc\006mc\005idnf\004mcr\003abrt\002tk0nf\001amnf" + +/* + * Commands for Disk Controller. + */ +#define WDCC_RECAL 0x10 /* disk restore code -- resets cntlr */ + +#define WDCC_READ 0x20 /* disk read code */ +#define WDCC_WRITE 0x30 /* disk write code */ +#define WDCC__LONG 0x02 /* modifier -- access ecc bytes */ +#define WDCC__NORETRY 0x01 /* modifier -- no retrys */ + +#define WDCC_FORMAT 0x50 /* disk format code */ +#define WDCC_DIAGNOSE 0x90 /* controller diagnostic */ +#define WDCC_IDP 0x91 /* initialize drive parameters */ + +#define WDCC_READMULTI 0xc4 /* read multiple */ +#define WDCC_WRITEMULTI 0xc5 /* write multiple */ +#define WDCC_SETMULTI 0xc6 /* set multiple mode */ + +#define WDCC_READDMA 0xc8 /* read with DMA */ +#define WDCC_WRITEDMA 0xca /* write with DMA */ + +#define WDCC_ACKMC 0xdb /* acknowledge media change */ +#define WDCC_LOCK 0xde /* lock drawer */ +#define WDCC_UNLOCK 0xdf /* unlock drawer */ + +#define WDCC_IDENTIFY 0xec /* read parameters from controller */ +#define WDCC_CACHEC 0xef /* cache control */ + +#define WDSD_IBM 0xa0 /* forced to 512 byte sector, ecc */ +#define WDSD_CHS 0x00 /* cylinder/head/sector addressing */ +#define WDSD_LBA 0x40 /* logical block addressing */ + + +#ifdef _KERNEL +/* + * read parameters command returns this: + */ +struct wdparams { + /* drive info */ + short wdp_config; /* general configuration */ +#define WD_CFG_REMOVABLE 0x0080 +#define WD_CFG_FIXED 0x0040 + short wdp_cylinders; /* number of non-removable cylinders */ + char __reserved1[2]; + short wdp_heads; /* number of heads */ + short wdp_unfbytespertrk; /* number of unformatted bytes/track */ + short wdp_unfbytespersec; /* number of unformatted bytes/sector */ + short wdp_sectors; /* number of sectors */ + char wdp_vendor1[6]; + /* controller info */ + char wdp_serial[20]; /* serial number */ + short wdp_buftype; /* buffer type */ +#define WD_BUF_SINGLEPORTSECTOR 1 /* single port, single sector buffer */ +#define WD_BUF_DUALPORTMULTI 2 /* dual port, multiple sector buffer */ +#define WD_BUF_DUALPORTMULTICACHE 3 /* above plus track cache */ + short wdp_bufsize; /* buffer size, in 512-byte units */ + short wdp_eccbytes; /* ecc bytes appended */ + char wdp_revision[8]; /* firmware revision */ + char wdp_model[40]; /* model name */ + u_char wdp_maxmulti; /* maximum sectors per interrupt */ + char wdp_vendor2[1]; + short wdp_usedmovsd; /* can use double word read/write? */ + char wdp_vendor3[1]; + char wdp_capabilities; /* capability flags */ +#define WD_CAP_LBA 0x02 +#define WD_CAP_DMA 0x01 + char __reserved2[2]; + char wdp_vendor4[1]; + char wdp_piotiming; /* PIO timing mode */ + char wdp_vendor5[1]; + char wdp_dmatiming; /* DMA timing mode */ +}; +#endif /* _KERNEL */ diff --git a/sys/arch/arm32/podulebus/asc.c b/sys/arch/arm32/podulebus/asc.c new file mode 100644 index 00000000000..80f64e32d69 --- /dev/null +++ b/sys/arch/arm32/podulebus/asc.c @@ -0,0 +1,483 @@ +/* $NetBSD: asc.c,v 1.5 1996/04/19 20:13:56 mark 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 + */ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int ascprint __P((void *auxp, char *)); +void ascattach __P((struct device *, struct device *, void *)); +int ascmatch __P((struct device *, void *, 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 scsi_xfer *xs)); +int asc_intr __P((struct asc_softc *)); + +char *strstr __P((char */*s1*/, char */*s2*/)); + +struct scsi_adapter asc_scsiswitch = { + asc_scsicmd, + sbic_minphys, + 0, /* no lun support */ + 0, /* no lun support */ +}; + +struct scsi_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 +}; + +struct cfdriver asc_cd = { + NULL, "asc", DV_DULL, NULL, 0 +}; + +u_long scsi_nosync; +int shift_nosync; + +#if ASC_POLL > 0 +int asc_poll = 1; + +extern char *boot_args; +#endif + +int +ascmatch(pdp, match, auxp) + struct device *pdp; + void *match, *auxp; +{ + struct podule_attach_args *pa = (struct podule_attach_args *)auxp; + int podule; + + podule = findpodule(0x00, 0x02, pa->pa_podule_number); + + if (podule == -1) + return(0); + + pa->pa_podule_number = podule; + pa->pa_podule = &podules[podule]; + + 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 podule_attach_args *pa; + + sc = (struct asc_softc *)dp; + + pa = (struct podule_attach_args *)auxp; + sc->sc_podule_number = pa->pa_podule_number; + if (sc->sc_podule_number == -1) + panic("Podule has disappeared !"); + + sc->sc_podule = &podules[sc->sc_podule_number]; + podules[sc->sc_podule_number].attached = 1; + +#if ASC_POLL > 0 + if (boot_args) { + char *ptr; + + ptr = strstr(boot_args, "noascpoll"); + if (ptr) + asc_poll = 0; + } + + if (asc_poll) + printf(" polling"); + else + printf(" using interrupts"); +#endif + printf("\n"); + + 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) (sc->sc_podule->mod_base + ASC_SBIC); + sbic->sc_clkfreq = sbic_clock_override ? sbic_clock_override : 143; + + sbic->sc_link.adapter_softc = sbic; + sbic->sc_link.adapter_target = 7; + sbic->sc_link.adapter = &asc_scsiswitch; + sbic->sc_link.device = &asc_scsidev; + sbic->sc_link.openings = 1; /* was 2 */ + + sc->sc_pagereg = sc->sc_podule->fast_base + ASC_PAGEREG; + sc->sc_intstat = sc->sc_podule->fast_base + ASC_INTSTATUS; + + /* Reset the card */ + + WriteByte(sc->sc_pagereg, 0x80); + DELAY(500000); + WriteByte(sc->sc_pagereg, 0x00); + DELAY(250000); + + sbicinit(sbic); + +/* If we are polling only then we don't need a interrupt handler */ + + sc->sc_ih.ih_func = asc_intr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_BIO; + sc->sc_ih.ih_name = "asc"; + +#ifdef ASC_POLL + if (!asc_poll) +#endif + if (irq_claim(IRQ_PODULE, &sc->sc_ih)) + panic("asc: Cannot claim podule IRQ\n"); + + /* + * attach all scsi units on us + */ + config_found(dp, &sbic->sc_link, ascprint); +} + +/* + * print diag if pnp is NULL else just extra + */ +int +ascprint(auxp, pnp) + void *auxp; + char *pnp; +{ + if (pnp == NULL) + return(UNCONF); + return(QUIET); +} + + +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\n"); +#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 +} + +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 +} + + +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 +} + +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 scsi_xfer *xs; +{ + struct scsi_link *sc_link = xs->sc_link; + + /* ensure command is polling for the moment */ +#if ASC_POLL > 0 + if (asc_poll) + xs->flags |= SCSI_POLL; +#endif + +/* printf("id=%d lun=%dcmdlen=%d datalen=%d opcode=%02x flags=%08x status=%02x blk=%02x %02x\n", + sc_link->target, sc_link->lun, xs->cmdlen, xs->datalen, xs->cmd->opcode, + xs->flags, xs->status, xs->cmd->bytes[0], xs->cmd->bytes[1]);*/ + + return(sbic_scsicmd(xs)); +} + + +int +asc_intr(sc) + struct asc_softc *sc; +{ + int intr; + +/* printf("ascintr:");*/ + intr = ReadByte(sc->sc_intstat); +/* printf("%02x\n", intr);*/ + + if (intr & IS_SBIC_IRQ) + sbicintr((struct sbic_softc *)sc); + return(0); +} + + +int kvtop() +{ + printf("kvtop\n"); +#ifdef DDB + Debugger(); +#else + panic("Hit a brick wall\n"); +#endif + return(0); +} + +void alloc_z2mem() +{ + panic("allocz2mem"); +} + +void isztwomem() +{ + panic("isz2mem"); +} + +void PREP_DMA_MEM() +{ + panic("PREP_DMA_MEM"); +} diff --git a/sys/arch/arm32/podulebus/ascreg.h b/sys/arch/arm32/podulebus/ascreg.h new file mode 100644 index 00000000000..dba455eb84a --- /dev/null +++ b/sys/arch/arm32/podulebus/ascreg.h @@ -0,0 +1,279 @@ +/* $NetBSD: ascreg.h,v 1.4 1996/03/07 23:54:29 mark 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/arm32/podulebus/ascvar.h b/sys/arch/arm32/podulebus/ascvar.h new file mode 100644 index 00000000000..a722f2f05dc --- /dev/null +++ b/sys/arch/arm32/podulebus/ascvar.h @@ -0,0 +1,52 @@ +/* $NetBSD: ascvar.h,v 1.1 1996/03/07 23:54:31 mark 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 +#include + +#define ASC_POLL 1 + +struct asc_softc { + struct sbic_softc sc_softc; + + podule_t *sc_podule; + int sc_podule_number; + irqhandler_t sc_ih; + + vu_int sc_pagereg; + vu_int sc_intstat; + }; + +#endif /* _ASCVAR_H_ */ diff --git a/sys/arch/arm32/podulebus/if_ea.c b/sys/arch/arm32/podulebus/if_ea.c new file mode 100644 index 00000000000..1104d512f7f --- /dev/null +++ b/sys/arch/arm32/podulebus/if_ea.c @@ -0,0 +1,1557 @@ +/* $NetBSD: if_ea.c,v 1.4 1996/03/27 21:49:26 mark 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef INET +#include +#include +#include +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +#include "bpfilter.h" +#if NBPFILTER > 0 +#include +#include +#endif + +#include +#include +#include +#include + +#include +#include + +#define ETHER_MIN_LEN 64 +#define ETHER_MAX_LEN 1514 +#define ETHER_ADDR_LEN 6 + +#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 + +#define MY_MANUFACTURER 0x11 +#define MY_PODULE 0xa4 + +/* + * per-line info and status + */ + +struct ea_softc { + struct device sc_dev; + irqhandler_t sc_ih; + int sc_irq; /* IRQ number */ + podule_t *sc_podule; /* Our podule */ + int sc_podule_number; /* Our podule number */ + u_int sc_iobase; /* base I/O addr */ + struct arpcom sc_arpcom; /* 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 + */ + +static 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((int)); +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 *, void *, void *)); +void eaattach __P((struct device *, struct device *, void *)); + +/* driver structure for autoconf */ + +struct cfattach ea_ca = { + sizeof(struct ea_softc), eaprobe, eaattach +}; + +struct cfdriver ea_cd = { + NULL, "ea", DV_IFNET +}; + +#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, void *match, void *aux) + * + * Probe for the ether3 podule. + */ + +int +eaprobe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct podule_attach_args *pa = (void *)aux; + int podule; + u_int iobase; + +/* dprintf(("Probing for SEEQ 8005... \n"));*/ + +/* Look for a network slot interface */ + + podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number); + +/* Fail if we did not find it */ + + if (podule == -1) + return(0); + + iobase = podules[podule].mod_base + EA_8005_BASE; + +/* Reset it - Why here ? */ + + WriteShort(iobase + EA_8005_CONFIG2, EA_CFG2_RESET); + delay(100); + +/* We found it */ + + pa->pa_podule_number = podule; + pa->pa_podule = &podules[podule]; + + 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 podule_attach_args *pa = (void *)aux; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + int loop; + int sum; + +/* dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));*/ + +/* Note the podule number and validate */ + + sc->sc_podule_number = pa->pa_podule_number; + if (sc->sc_podule_number == -1) + panic("Podule has disappeared !"); + + sc->sc_podule = &podules[sc->sc_podule_number]; + podules[sc->sc_podule_number].attached = 1; + +/* Set the address of the controller for easy access */ + + sc->sc_iobase = sc->sc_podule->mod_base + EA_8005_BASE; + + sc->sc_irqclaimed = 0; + +/* Set up the interrupt structure */ + + sc->sc_ih.ih_func = eaintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_NET; + sc->sc_ih.ih_name = "net: ea"; + +/* Claim either a network slot interrupt or a podule interrupt */ + + if (sc->sc_podule_number >= MAX_PODULES) + sc->sc_irq = IRQ_NETSLOT; + else + sc->sc_irq = IRQ_PODULE /*+ sc->sc_podule_number*/; + + /* Stop the board. */ + + ea_chipreset(sc); + ea_stoptx(sc); + ea_stoprx(sc); + + /* Initialise ifnet structure. */ + + ifp->if_unit = sc->sc_dev.dv_unit; + ifp->if_name = ea_cd.cd_name; + 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); + +/* 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) { + sc->sc_arpcom.ac_enaddr[loop] = + ReadByte(sc->sc_iobase + EA_8005_BUFWIN); + sum += sc->sc_arpcom.ac_enaddr[loop]; + } + +/* + * Hard code the ether address if we don't have one. + * Need to work out how I get the real address + */ + + if (sum == 0) { + sc->sc_arpcom.ac_enaddr[0] = 0x00; + sc->sc_arpcom.ac_enaddr[1] = 0x00; + sc->sc_arpcom.ac_enaddr[2] = 0xa4; + sc->sc_arpcom.ac_enaddr[3] = 0x10; + sc->sc_arpcom.ac_enaddr[4] = 0x02; + sc->sc_arpcom.ac_enaddr[5] = 0x87; + } + + /* Print out some information for the user. */ + + printf(" SEEQ8005 address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr)); + + /* 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 */ + + dprintf(("ea_claimirq(%d)\n", sc->sc_irq)); + if (irq_claim(sc->sc_irq, &sc->sc_ih)) + panic("Cannot install IRQ handler for IRQ %d\n", sc->sc_irq); + + sc->sc_irqclaimed = 1; +} + + +/* Release an irq */ + +void +ea_releaseirq(sc) + struct ea_softc *sc; +{ +/* Have we claimed one ? */ + + if (!sc->sc_irqclaimed) return; + + dprintf(("ea_releaseirq(%d)\n", sc->sc_irq)); + if (irq_release(sc->sc_irq, &sc->sc_ih)) + panic("Cannot release IRQ handler for IRQ %d\n", sc->sc_irq); + + 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 = splimp(); + 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_arpcom.ac_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; + 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, sc->sc_arpcom.ac_enaddr[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_arpcom.ac_if; + u_int iobase = sc->sc_iobase; + int s; + + dprintf(("ea_init()\n")); + + s = splimp(); + +/* 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 splimp or + * interrupt level! + */ + +static void +ea_start(ifp) + struct ifnet *ifp; +{ + struct ea_softc *sc = ea_cd.cd_devs[ifp->if_unit]; + int s; + + s = splimp(); +#ifdef EA_TX_DEBUG + dprintf(("ea_start()...\n")); +#endif + + /* Don't do anything if output is active. */ + + if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE) + return; + + /* Mark interface as output active */ + + sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE; + + /* tx packets */ + + eatxpacket(sc); + (void)splx(s); +} + + +/* + * Transfer a packet to the interface buffer and start transmission + * + * Called at splimp() + */ + +void +eatxpacket(sc) + struct ea_softc *sc; +{ + u_int iobase = sc->sc_iobase; + struct mbuf *m, *m0; + int len; + +/* Dequeue the next datagram. */ + + IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0); + +/* If there's nothing to send, return. */ + + if (!m0) { + sc->sc_arpcom.ac_if.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 (sc->sc_arpcom.ac_if.if_bpf) + bpf_mtap(sc->sc_arpcom.ac_if.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) + 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; + int status, s; + u_int txstatus; + + 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 ")); + +/* 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) { + sc->sc_arpcom.ac_if.if_collisions++; + } else if (txstatus & EA_TXHDR_ERROR_MASK) { + sc->sc_arpcom.ac_if.if_oerrors++; + } + +/* if (txstatus & EA_TXHDR_ERROR_MASK) { + log(LOG_WARNING, "tx packet error =%02x\n", txstatus); + }*/ + + if (txstatus & EA_PKTHDR_DONE) { + sc->sc_arpcom.ac_if.if_opackets++; + + /* Tx next packet */ + + s = splimp(); + eatxpacket(sc); + (void)splx(s); + } + } + +/* Rx interrupt ? */ + + if (status & EA_STATUS_RX_INT) { + dprintf(("rxint ")); + +/* 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 */ + + sc->sc_arpcom.ac_if.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(0); +} + +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; + +/* 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) { + ++sc->sc_arpcom.ac_if.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; */ + addr = ptr; + continue; + } + +/* Is the packet too big ? - this will probably be trapped above as a receive error */ + + if (len > ETHER_MAX_LEN) { + ++sc->sc_arpcom.ac_if.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;*/ + addr = ptr; + continue; + } + + 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 + sc->sc_arpcom.ac_if.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; + + eh = (struct ether_header *)buf; + len -= sizeof(struct ether_header); + if (len <= 0) + return; + + /* Pull packet off interface. */ + m = eaget(buf, len, &sc->sc_arpcom.ac_if); + 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 (sc->sc_arpcom.ac_if.if_bpf) { + bpf_tap(sc->sc_arpcom.ac_if.if_bpf, buf, len + sizeof(struct ether_header)); +/* bpf_mtap(sc->sc_arpcom.ac_if.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 ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) && + (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ + bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, + sizeof(eh->ether_dhost)) != 0) { + m_freem(m); + return; + } + } +#endif + + ether_input(&sc->sc_arpcom.ac_if, eh, 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; + + buf += sizeof(struct ether_header); + 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 = ea_cd.cd_devs[ifp->if_unit]; + struct ifaddr *ifa = (struct ifaddr *)data; +/* struct ifreq *ifr = (struct ifreq *)data;*/ + int s, error = 0; + + s = splimp(); + + 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(&sc->sc_arpcom, 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 *)(sc->sc_arpcom.ac_enaddr); + else + bcopy(ina->x_host.c_host, + sc->sc_arpcom.ac_enaddr, + sizeof(sc->sc_arpcom.ac_enaddr)); + /* 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(unit) + int unit; +{ + struct ea_softc *sc = ea_cd.cd_devs[unit]; + + log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); + sc->sc_arpcom.ac_if.if_oerrors++; + dprintf(("ea_watchdog: ")); + dprintf(("st=%04x\n", ReadShort(sc->sc_iobase + EA_8005_STATUS))); + + /* Kick the interface */ + + ea_reinit(sc); + +/* sc->sc_arpcom.ac_if.if_timer = EA_TIMEOUT;*/ + sc->sc_arpcom.ac_if.if_timer = 0; +} + +/* End of if_ea.c */ diff --git a/sys/arch/arm32/podulebus/if_eareg.h b/sys/arch/arm32/podulebus/if_eareg.h new file mode 100644 index 00000000000..7d069da6440 --- /dev/null +++ b/sys/arch/arm32/podulebus/if_eareg.h @@ -0,0 +1,168 @@ +/* $NetBSD: if_eareg.h,v 1.2 1996/03/18 21:23:09 mark 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/arm32/podulebus/if_eb.c b/sys/arch/arm32/podulebus/if_eb.c new file mode 100644 index 00000000000..a433d38bbf7 --- /dev/null +++ b/sys/arch/arm32/podulebus/if_eb.c @@ -0,0 +1,1575 @@ +/* $NetBSD: if_eb.c,v 1.4 1996/03/27 21:49:31 mark 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_eb.c + * + * EtherB device driver + * + * Created : 08/07/95 + */ + +/* + * SEEQ 80C04 device driver + */ + +/* + * Bugs/possible improvements: + * - Does not currently support DMA + * - Does not currently support multicasts + * - Does not transmit multiple packets in one go + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef INET +#include +#include +#include +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +#include "bpfilter.h" +#if NBPFILTER > 0 +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#define ETHER_MIN_LEN 64 +#define ETHER_MAX_LEN 1514 +#define ETHER_ADDR_LEN 6 + +#ifndef EB_TIMEOUT +#define EB_TIMEOUT 60 +#endif + +/*#define EB_TX_DEBUG*/ +/*#define EB_RX_DEBUG*/ +/*#define EB_DEBUG*/ +/*#define EB_PACKET_DEBUG*/ + +/* for debugging convenience */ +#ifdef EB_DEBUG +#define dprintf(x) printf x +#else +#define dprintf(x) +#endif + +#define MY_MANUFACTURER 0x53 +#define MY_PODULE 0xe4 + +/* + * per-line info and status + */ + +struct eb_softc { + struct device sc_dev; + irqhandler_t sc_ih; + int sc_irq; /* IRQ number */ + podule_t *sc_podule; /* Our podule */ + int sc_podule_number; /* Our podule number */ + u_int sc_iobase; /* base I/O addr */ + struct arpcom sc_arpcom; /* ethernet common */ + char sc_pktbuf[EB_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 + */ + +static int ebintr __P((void *)); +static int eb_init __P((struct eb_softc *)); +static int eb_ioctl __P((struct ifnet *, u_long, caddr_t)); +static void eb_start __P((struct ifnet *)); +static void eb_watchdog __P((int)); +static void eb_reinit __P((struct eb_softc *)); +static void eb_chipreset __P((struct eb_softc *)); +static void eb_ramtest __P((struct eb_softc *)); +static int eb_stoptx __P((struct eb_softc *)); +static int eb_stoprx __P((struct eb_softc *)); +static void eb_stop __P((struct eb_softc *)); +static void eb_writebuf __P((struct eb_softc *, u_char *, int, int)); +static void eb_readbuf __P((struct eb_softc *, u_char *, int, int)); +static void ebread __P((struct eb_softc *, caddr_t, int)); +static struct mbuf *ebget __P((caddr_t, int, struct ifnet *)); +static void eb_hardreset __P((struct eb_softc *)); +static void ebgetpackets __P((struct eb_softc *)); +static void ebtxpacket __P((struct eb_softc *)); + +int ebprobe __P((struct device *, void *, void *)); +void ebattach __P((struct device *, struct device *, void *)); + +/* driver structure for autoconf */ + +struct cfattach eb_ca = { + sizeof(struct eb_softc), ebprobe, ebattach +}; + +struct cfdriver eb_cd = { + NULL, "eb", DV_IFNET +}; + +#if 0 + +/* + * Dump the chip registers + */ + +void +ebdump(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 +eb_dump_buffer(sc, offset) + struct eb_softc *sc; + int offset; +{ +#ifdef EB_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 + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_READ); + WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM); + WriteShort(iobase + EB_8004_DMA_ADDR, addr); + + ptr = ReadShort(iobase + EB_8004_BUFWIN); + ctrl = ReadShort(iobase + EB_8004_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 + EB_8004_BUFWIN)); + printf("\n"); + addr = ptr; + } while (size != 0); +#endif +} + +/* + * Probe routine. + */ + +/* + * int ebprobe(struct device *parent, void *match, void *aux) + * + * Probe for the ether3 podule. + */ + +int +ebprobe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct podule_attach_args *pa = (void *)aux; + int podule; + u_int iobase; + +/* dprintf(("Probing for SEEQ 8004... \n"));*/ + +/* Look for a network slot interface */ + + podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number); + +/* Fail if we did not find it */ + + if (podule == -1) + return(0); + + iobase = podules[podule].mod_base + EB_8004_BASE; + +/* Reset it - Why here ? */ + + WriteShort(iobase + EB_8004_CONFIG2, EB_CFG2_RESET); + delay(100); + +/* We found it */ + + pa->pa_podule_number = podule; + pa->pa_podule = &podules[podule]; + + return(1); +} + + +/* + * void ebattach(struct device *parent, struct device *dev, void *aux) + * + * Attach podule. + */ + +void +ebattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct eb_softc *sc = (void *)self; + struct podule_attach_args *pa = (void *)aux; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + int loop; + int sum; + int id; + +/* dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));*/ + +/* Note the podule number and validate */ + + sc->sc_podule_number = pa->pa_podule_number; + if (sc->sc_podule_number == -1) + panic("Podule has disappeared !"); + + sc->sc_podule = &podules[sc->sc_podule_number]; + podules[sc->sc_podule_number].attached = 1; + +/* Set the address of the controller for easy access */ + + sc->sc_iobase = sc->sc_podule->mod_base + EB_8004_BASE; + + sc->sc_irqclaimed = 0; + +/* Set up the interrupt structure */ + + sc->sc_ih.ih_func = ebintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_NET; + sc->sc_ih.ih_name = "net: eb"; + +/* Claim either a network slot interrupt or a podule interrupt */ + + if (sc->sc_podule_number >= MAX_PODULES) + sc->sc_irq = IRQ_NETSLOT; + else + sc->sc_irq = IRQ_PODULE /*+ sc->sc_podule_number*/; + + /* Stop the board. */ + + eb_chipreset(sc); + eb_stoptx(sc); + eb_stoprx(sc); + + /* Initialise ifnet structure. */ + + ifp->if_unit = sc->sc_dev.dv_unit; + ifp->if_name = eb_cd.cd_name; + ifp->if_start = eb_start; + ifp->if_ioctl = eb_ioctl; + ifp->if_watchdog = eb_watchdog; + ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS; + + /* Now we can attach the interface. */ + +/* dprintf(("Attaching interface...\n"));*/ + if_attach(ifp); + ether_ifattach(ifp); + +/* Read the station address - the receiver must be off */ + + WriteShort(sc->sc_iobase + EB_8004_CONFIG1, EB_BUFCODE_STATION_ADDR); + + for (sum = 0, loop = 0; loop < ETHER_ADDR_LEN; ++loop) { + sc->sc_arpcom.ac_enaddr[loop] = + ReadByte(sc->sc_iobase + EB_8004_BUFWIN); + sum += sc->sc_arpcom.ac_enaddr[loop]; + } + +/* + * Hard code the ether address if we don't have one. + * Build the address from the machine id. + */ + + if (sum == 0) { + sc->sc_arpcom.ac_enaddr[0] = 0x00; + sc->sc_arpcom.ac_enaddr[1] = 0x00; + sc->sc_arpcom.ac_enaddr[2] = bootconfig.machine_id[3]; + sc->sc_arpcom.ac_enaddr[3] = bootconfig.machine_id[2]; + sc->sc_arpcom.ac_enaddr[4] = bootconfig.machine_id[1]; + sc->sc_arpcom.ac_enaddr[5] = bootconfig.machine_id[0]; + } + + /* Get the product ID */ + + WriteShort(sc->sc_iobase + EB_8004_CONFIG1, EB_BUFCODE_PRODUCTID); + id = ReadByte(sc->sc_iobase + EB_8004_BUFWIN); + + /* Print out some information for the user. */ + + if ((id & 0xf0) == 0xa0) + printf(" SEEQ80C04 rev %x address %s", id & 0x0f, ether_sprintf(sc->sc_arpcom.ac_enaddr)); + else + printf(" SEEQ???? rev %02x address %s", id, ether_sprintf(sc->sc_arpcom.ac_enaddr)); + + /* 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 */ + + eb_ramtest(sc); + +/* dprintf(("ebattach() finished.\n"));*/ +} + + +/* + * Test the RAM on the ethernet card. This does not work yet + */ + +void +eb_ramtest(sc) + struct eb_softc *sc; +{ + register u_int iobase = sc->sc_iobase; + register int loop; + register u_int sum = 0; + +/* dprintf(("eb_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 + EB_8004_CONFIG1, EB_BUFCODE_TX_EAP); + WriteShort(iobase + EB_8004_BUFWIN, ((EB_BUFFER_SIZE >> 8) - 1)); + WriteShort(iobase + EB_8004_TX_PTR, 0x0000); + WriteShort(iobase + EB_8004_RX_PTR, EB_BUFFER_SIZE - 2); + + /* Set the write start address and write a pattern */ + + eb_writebuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2) + WriteShort(iobase + EB_8004_BUFWIN, loop); + + /* Set the read start address and verify the pattern */ + + eb_readbuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2) + if (ReadShort(iobase + EB_8004_BUFWIN) != loop) + ++sum; + + if (sum != 0) + dprintf(("sum=%d\n", sum)); + + /* Set the write start address and write a pattern */ + + eb_writebuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2) + WriteShort(iobase + EB_8004_BUFWIN, loop ^ (EB_BUFFER_SIZE - 1)); + + /* Set the read start address and verify the pattern */ + + eb_readbuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2) + if (ReadShort(iobase + EB_8004_BUFWIN) != (loop ^ (EB_BUFFER_SIZE - 1))) + ++sum; + + if (sum != 0) + dprintf(("sum=%d\n", sum)); + + /* Set the write start address and write a pattern */ + + eb_writebuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2) + WriteShort(iobase + EB_8004_BUFWIN, 0xaa55); + + /* Set the read start address and verify the pattern */ + + eb_readbuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2) + if (ReadShort(iobase + EB_8004_BUFWIN) != 0xaa55) + ++sum; + + if (sum != 0) + dprintf(("sum=%d\n", sum)); + + /* Set the write start address and write a pattern */ + + eb_writebuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2) + WriteShort(iobase + EB_8004_BUFWIN, 0x55aa); + + /* Set the read start address and verify the pattern */ + + eb_readbuf(sc, NULL, 0x0000, 0); + + for (loop = 0; loop < EB_BUFFER_SIZE; loop += 2) + if (ReadShort(iobase + EB_8004_BUFWIN) != 0x55aa) + ++sum; + + if (sum != 0) + dprintf(("sum=%d\n", sum)); + + /* Report */ + + if (sum == 0) + printf(" %dK buffer RAM\n", EB_BUFFER_SIZE / 1024); + else + printf(" buffer RAM failed self test, %d faults\n", sum); +} + + +/* Claim an irq for the board */ + +void +eb_claimirq(sc) + struct eb_softc *sc; +{ +/* Have we claimed one already ? */ + + if (sc->sc_irqclaimed) return; + +/* Claim it */ + + dprintf(("eb_claimirq(%d)\n", sc->sc_irq)); + if (irq_claim(sc->sc_irq, &sc->sc_ih)) + panic("Cannot install IRQ handler for IRQ %d\n", sc->sc_irq); + + sc->sc_irqclaimed = 1; +} + + +/* Release an irq */ + +void +eb_releaseirq(sc) + struct eb_softc *sc; +{ +/* Have we claimed one ? */ + + if (!sc->sc_irqclaimed) return; + + dprintf(("eb_releaseirq(%d)\n", sc->sc_irq)); + if (irq_release(sc->sc_irq, &sc->sc_ih)) + panic("Cannot release IRQ handler for IRQ %d\n", sc->sc_irq); + + sc->sc_irqclaimed = 0; +} + + +/* + * Stop and reinitialise the interface. + */ + +static void +eb_reinit(sc) + struct eb_softc *sc; +{ + int s; + + dprintf(("eb_reinit()\n")); + +/* Stop and reinitialise the interface */ + + s = splimp(); + eb_stop(sc); + eb_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 +eb_stoptx(sc) + struct eb_softc *sc; +{ + u_int iobase = sc->sc_iobase; + int timeout; + int status; + + dprintf(("eb_stoptx()\n")); + + status = ReadShort(iobase + EB_8004_STATUS); + if (!(status & EB_STATUS_TX_ON)) + return(0); + +/* Stop any tx and wait for confirmation */ + + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_TX_OFF); + + timeout = 20000; + do { + status = ReadShort(iobase + EB_8004_STATUS); + } while ((status & EB_STATUS_TX_ON) && --timeout > 0); + if (timeout == 0) + dprintf(("eb_stoptx: timeout waiting for tx termination\n")); + +/* Clear any pending tx interrupt */ + + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_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 +eb_stoprx(sc) + struct eb_softc *sc; +{ + u_int iobase = sc->sc_iobase; + int timeout; + int status; + + dprintf(("eb_stoprx()\n")); + + status = ReadShort(iobase + EB_8004_STATUS); + if (!(status & EB_STATUS_RX_ON)) + return(0); + +/* Stop any rx and wait for confirmation */ + + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_OFF); + + timeout = 20000; + do { + status = ReadShort(iobase + EB_8004_STATUS); + } while ((status & EB_STATUS_RX_ON) && --timeout > 0); + if (timeout == 0) + dprintf(("eb_stoprx: timeout waiting for rx termination\n")); + +/* Clear any pending rx interrupt */ + + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_INTACK); + return(1); +} + + +/* + * Stop interface. + * Stop all IO and shut the interface down + */ + +static void +eb_stop(sc) + struct eb_softc *sc; +{ + u_int iobase = sc->sc_iobase; + + dprintf(("eb_stop()\n")); + +/* Stop all IO */ + + eb_stoptx(sc); + eb_stoprx(sc); + + /* Disable rx and tx interrupts */ + + sc->sc_command &= (EB_CMD_RX_INTEN | EB_CMD_TX_INTEN); + + /* Clear any pending interrupts */ + + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command + | EB_CMD_RX_INTACK | EB_CMD_TX_INTACK | EB_CMD_TEST_INTACK + | EB_CMD_BW_INTACK); + dprintf(("st=%08x", ReadShort(iobase + EB_8004_STATUS))); + + /* Release the irq */ + + eb_releaseirq(sc); + + /* Put the chip to sleep */ + + WriteShort(iobase + EB_8004_CONFIG1, EB_BUFCODE_CONFIG3); + WriteShort(iobase + EB_8004_BUFWIN, EB_CFG3_SLEEP); + + /* Cancel any watchdog timer */ + + sc->sc_arpcom.ac_if.if_timer = 0; +} + + +/* + * Reset the chip + * Following this the software registers are reset + */ + +static void +eb_chipreset(sc) + struct eb_softc *sc; +{ + u_int iobase = sc->sc_iobase; + + dprintf(("eb_chipreset()\n")); + +/* Reset the controller. Min of 4us delay here */ + + WriteShort(iobase + EB_8004_CONFIG2, EB_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 +eb_hardreset(sc) + struct eb_softc *sc; +{ + u_int iobase = sc->sc_iobase; + int loop; + + dprintf(("eb_hardreset()\n")); + +/* Stop any activity */ + + eb_stoptx(sc); + eb_stoprx(sc); + + eb_chipreset(sc); + +/* Set up defaults for the registers */ + + sc->sc_config2 = 0; + WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2); + sc->sc_command = 0x00; + sc->sc_config1 = 0; + WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1); + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command); + + WriteShort(iobase + EB_8004_CONFIG1, EB_BUFCODE_TX_EAP); + WriteShort(iobase + EB_8004_BUFWIN, ((EB_TX_BUFFER_SIZE >> 8) - 1)); + +/* Write the station address - the receiver must be off */ + + WriteShort(sc->sc_iobase + EB_8004_CONFIG1, + sc->sc_config1 | EB_BUFCODE_STATION_ADDR); + for (loop = 0; loop < ETHER_ADDR_LEN; ++loop) { + WriteByte(sc->sc_iobase + EB_8004_BUFWIN, sc->sc_arpcom.ac_enaddr[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 +eb_writebuf(sc, buf, addr, len) + struct eb_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 + EB_8004_STATUS))); + +/* If we have a valid buffer address set the buffer pointer and direction */ + + if (addr >= 0 && addr < EB_BUFFER_SIZE) { + WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM); + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_WRITE); + + /* Should wait here of FIFO empty flag */ + + timeout = 20000; + while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0); + + + WriteShort(iobase + EB_8004_DMA_ADDR, addr); + } + + for (loop = 0; loop < len; loop += 2) + WriteShort(iobase + EB_8004_BUFWIN, buf[loop] | buf[loop + 1] << 8); + + +/* if (len > 0) + outsw(iobase + EB_8004_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 +eb_readbuf(sc, buf, addr, len) + struct eb_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 + EB_8004_STATUS), addr, len)); + +/* If we have a valid buffer address set the buffer pointer and direction */ + + if (addr >= 0 && addr < EB_BUFFER_SIZE) { + if ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_DIR) == 0) { + /* Should wait here of FIFO empty flag */ + + timeout = 20000; + while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0); + } + WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_LOCAL_MEM); + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_WRITE); + + /* Should wait here of FIFO empty flag */ + + timeout = 20000; + while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_EMPTY) == 0 && --timeout > 0); + + WriteShort(iobase + EB_8004_DMA_ADDR, addr); + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_FIFO_READ); + + /* Should wait here of FIFO full flag */ + + timeout = 20000; + while ((ReadShort(iobase + EB_8004_STATUS) & EB_STATUS_FIFO_FULL) == 0 && --timeout > 0); + + + } + + for (loop = 0; loop < len; loop += 2) { + word = ReadShort(iobase + EB_8004_BUFWIN); + buf[loop] = word & 0xff; + buf[loop + 1] = word >> 8; + } + +/* if (len > 0) + insw(iobase + EB_8004_BUFWIN, buf, len / 2);*/ +} + + +/* + * Initialize interface. + * + * This should leave the interface in a state for packet reception and transmission + */ + +static int +eb_init(sc) + struct eb_softc *sc; +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + u_int iobase = sc->sc_iobase; + int s; + + dprintf(("eb_init()\n")); + + s = splimp(); + +/* Grab an irq */ + + eb_claimirq(sc); + + /* First, reset the board. */ + + eb_hardreset(sc); + +/* Configure rx. */ + + dprintf(("Configuring rx...\n")); + if (ifp->if_flags & IFF_PROMISC) + sc->sc_config1 = EB_CFG1_PROMISCUOUS; + else + sc->sc_config1 = EB_CFG1_BROADCAST; + + sc->sc_config1 |= 0; + WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1); + +/* Configure TX. */ + + dprintf(("Configuring tx...\n")); + + WriteShort(iobase + EB_8004_CONFIG1, sc->sc_config1 | EB_BUFCODE_TX_EAP); + WriteShort(iobase + EB_8004_BUFWIN, ((EB_TX_BUFFER_SIZE >> 8) - 1)); + WriteShort(iobase + EB_8004_TX_PTR, 0x0000); + + sc->sc_config2 |= (EB_CFG2_OUTPUT | EB_CFG2_RX_TX_DISABLE); + WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2); + +/* Place a NULL header at the beginning of the transmit area */ + + eb_writebuf(sc, NULL, 0x0000, 0); + + WriteShort(iobase + EB_8004_BUFWIN, 0x0000); + WriteShort(iobase + EB_8004_BUFWIN, 0x0000); + + sc->sc_command |= EB_CMD_TX_INTEN; + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command); + +/* Setup the Rx pointers */ + + sc->sc_rx_ptr = EB_TX_BUFFER_SIZE; + + WriteShort(iobase + EB_8004_RX_PTR, sc->sc_rx_ptr); + WriteShort(iobase + EB_8004_RX_END, (sc->sc_rx_ptr >> 8)); + +/* Place a NULL header at the beginning of the receive area */ + + eb_writebuf(sc, NULL, sc->sc_rx_ptr, 0); + + WriteShort(iobase + EB_8004_BUFWIN, 0x0000); + WriteShort(iobase + EB_8004_BUFWIN, 0x0000); + +/* Turn on Rx */ + + sc->sc_command |= EB_CMD_RX_INTEN; + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_RX_ON); + + /* Set flags appropriately. */ + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + + dprintf(("init: st=%04x\n", ReadShort(iobase + EB_8004_STATUS))); + + /* And start output. */ + eb_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 splimp or + * interrupt level! + */ + +static void +eb_start(ifp) + struct ifnet *ifp; +{ + struct eb_softc *sc = eb_cd.cd_devs[ifp->if_unit]; + int s; + + s = splimp(); +#ifdef EB_TX_DEBUG + dprintf(("eb_start()...\n")); +#endif + + /* Don't do anything if output is active. */ + + if (sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE) + return; + + /* Mark interface as output active */ + + sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE; + + /* tx packets */ + + ebtxpacket(sc); + (void)splx(s); +} + + +/* + * Transfer a packet to the interface buffer and start transmission + * + * Called at splimp() + */ + +void +ebtxpacket(sc) + struct eb_softc *sc; +{ + u_int iobase = sc->sc_iobase; + struct mbuf *m, *m0; + int len; + +/* Dequeue the next datagram. */ + + IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m0); + +/* If there's nothing to send, return. */ + + if (!m0) { + sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + sc->sc_config2 |= EB_CFG2_OUTPUT; + WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2); +#ifdef EB_TX_DEBUG + dprintf(("tx finished\n")); +#endif + return; + } + + /* Give the packet to the bpf, if any. */ +#if NBPFILTER > 0 + if (sc->sc_arpcom.ac_if.if_bpf) + bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0); +#endif + +#ifdef EB_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) + 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 EB_TX_DEBUG + dprintf(("eb: 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 &= ~EB_CFG2_OUTPUT; + WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2); + +/* dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/ + +/* Write the packet to the interface buffer, skipping the packet header */ + + eb_writebuf(sc, sc->sc_pktbuf, 0x0004, len); + +/* Follow it with a NULL packet header */ + + WriteShort(iobase + EB_8004_BUFWIN, 0x00); + WriteShort(iobase + EB_8004_BUFWIN, 0x00); + +/* Write the packet header */ + + eb_writebuf(sc, NULL, 0x0000, 0); + + WriteShort(iobase + EB_8004_BUFWIN, (((len+4) & 0xff00) >> 8) | (((len+4) & 0xff) << 8)); + WriteShort(iobase + EB_8004_BUFWIN, 0x00aa); + + WriteShort(iobase + EB_8004_TX_PTR, 0x0000); + +/* dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/ + +#ifdef EB_DEBUG + eb_dump_buffer(sc, 0); +#endif + +/* Now transmit the datagram. */ + +/* dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS)));*/ + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command | EB_CMD_TX_ON); +#ifdef EB_TX_DEBUG + dprintf(("st=%04x\n", ReadShort(iobase + EB_8004_STATUS))); + dprintf(("tx: queued\n")); +#endif +} + + +/* + * Ethernet controller interrupt. + */ + +int +ebintr(arg) + void *arg; +{ + register struct eb_softc *sc = arg; + u_int iobase = sc->sc_iobase; + int status, s; + u_int txstatus; + + dprintf(("ebintr: ")); + +/* Get the controller status */ + + status = ReadShort(iobase + EB_8004_STATUS); + dprintf(("st=%04x ", status)); + +/* Tx interrupt ? */ + + if (status & EB_STATUS_TX_INT) { + dprintf(("txint ")); + +/* Acknowledge the interrupt */ + + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command + | EB_CMD_TX_INTACK); + + eb_readbuf(sc, (u_char *)&txstatus, 0x0000, 4); + +#ifdef EB_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 & EB_TXHDR_COLLISION) { + sc->sc_arpcom.ac_if.if_collisions++; + } else if (txstatus & EB_TXHDR_ERROR_MASK) { + sc->sc_arpcom.ac_if.if_oerrors++; + } + +/* if (txstatus & EB_TXHDR_ERROR_MASK) { + log(LOG_WARNING, "tx packet error =%02x\n", txstatus); + }*/ + + if (txstatus & EB_PKTHDR_DONE) { + sc->sc_arpcom.ac_if.if_opackets++; + + /* Tx next packet */ + + s = splimp(); + ebtxpacket(sc); + (void)splx(s); + } + } + +/* Rx interrupt ? */ + + if (status & EB_STATUS_RX_INT) { + dprintf(("rxint ")); + +/* Acknowledge the interrupt */ + + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command + | EB_CMD_RX_INTACK); + +/* Install a watchdog timer needed atm to fixed rx lockups */ + + sc->sc_arpcom.ac_if.if_timer = EB_TIMEOUT; + +/* Processes the received packets */ + ebgetpackets(sc); + +/* Make sure the receiver is on */ + +/* if ((status & EB_STATUS_RX_ON) == 0) { + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command + | EB_CMD_RX_ON); + printf("rxintr: rx is off st=%04x\n",status); + }*/ + } + +#ifdef EB_DEBUG + status = ReadShort(iobase + EB_8004_STATUS); + dprintf(("st=%04x\n", status)); +#endif + return(0); +} + +void +ebgetpackets(sc) + struct eb_softc *sc; +{ + u_int iobase = sc->sc_iobase; + int addr; + int len; + int ctrl; + int ptr; + int pack; + int status; + u_int rxstatus; + +/* We start from the last rx pointer position */ + + addr = sc->sc_rx_ptr; + sc->sc_config2 &= ~EB_CFG2_OUTPUT; + WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2); + + do { +/* Read rx header */ + + eb_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 EB_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 += EB_RX_BUFFER_SIZE; + } + +#ifdef EB_RX_DEBUG + dprintf(("len=%04x\n", len)); +#endif + +/* Has the packet rx completed ? if not then exit */ + + if ((status & EB_PKTHDR_DONE) == 0) + break; + +/* Did we have any errors ? then note error and go to next packet */ + + if (status & 0x0f) { + ++sc->sc_arpcom.ac_if.if_ierrors; + printf("rx packet error (%02x) - dropping packet\n", status & 0x0f); +/* sc->sc_config2 |= EB_CFG2_OUTPUT; + WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2); + eb_reinit(sc); + return; */ + addr = ptr; + continue; + } + +/* Is the packet too big ? - this will probably be trapped above as a receive error */ + + if (len > ETHER_MAX_LEN) { + ++sc->sc_arpcom.ac_if.if_ierrors; + printf("rx packet size error len=%d\n", len); +/* sc->sc_config2 |= EB_CFG2_OUTPUT; + WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2); + eb_reinit(sc); + return;*/ + addr = ptr; + continue; + } + + eb_readbuf(sc, sc->sc_pktbuf, addr + 4, len); + +#ifdef EB_RX_DEBUG + dprintf(("%s-->", ether_sprintf(sc->sc_pktbuf+6))); + dprintf(("%s\n", ether_sprintf(sc->sc_pktbuf))); +#endif + sc->sc_arpcom.ac_if.if_ipackets++; + /* Pass data up to upper levels. */ + ebread(sc, (caddr_t)sc->sc_pktbuf, len); + + addr = ptr; + ++pack; + } while (len != 0); + + sc->sc_config2 |= EB_CFG2_OUTPUT; + WriteShort(iobase + EB_8004_CONFIG2, sc->sc_config2); + +#ifdef EB_RX_DEBUG + dprintf(("new rx ptr=%04x\n", addr)); +#endif + +/* Store new rx pointer */ + + sc->sc_rx_ptr = addr; + WriteShort(iobase + EB_8004_RX_END, (sc->sc_rx_ptr >> 8)); + +/* Make sure the receiver is on */ + + WriteShort(iobase + EB_8004_COMMAND, sc->sc_command + | EB_CMD_RX_ON); + +} + + +/* + * Pass a packet up to the higher levels. + */ + +static void +ebread(sc, buf, len) + struct eb_softc *sc; + caddr_t buf; + int len; +{ + register struct ether_header *eh; + struct mbuf *m; + + eh = (struct ether_header *)buf; + len -= sizeof(struct ether_header); + if (len <= 0) + return; + + /* Pull packet off interface. */ + m = ebget(buf, len, &sc->sc_arpcom.ac_if); + 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 (sc->sc_arpcom.ac_if.if_bpf) { + bpf_tap(sc->sc_arpcom.ac_if.if_bpf, buf, len + sizeof(struct ether_header)); +/* bpf_mtap(sc->sc_arpcom.ac_if.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 ((sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC) && + (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ + bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, + sizeof(eh->ether_dhost)) != 0) { + m_freem(m); + return; + } + } +#endif + + ether_input(&sc->sc_arpcom.ac_if, eh, 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 * +ebget(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; + + buf += sizeof(struct ether_header); + 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 +eb_ioctl(ifp, cmd, data) + register struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + struct eb_softc *sc = eb_cd.cd_devs[ifp->if_unit]; + struct ifaddr *ifa = (struct ifaddr *)data; +/* struct ifreq *ifr = (struct ifreq *)data;*/ + int s, error = 0; + + s = splimp(); + + 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(&sc->sc_arpcom, ifa); + dprintf(("Interface eb is coming up (AF_INET)\n")); + eb_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 *)(sc->sc_arpcom.ac_enaddr); + else + bcopy(ina->x_host.c_host, + sc->sc_arpcom.ac_enaddr, + sizeof(sc->sc_arpcom.ac_enaddr)); + /* Set new address. */ + dprintf(("Interface eb is coming up (AF_NS)\n")); + eb_init(sc); + break; + } +#endif + default: + dprintf(("Interface eb is coming up (default)\n")); + eb_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")); + eb_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 eb is restarting(1)\n")); + eb_init(sc); + } else { + /* + * Some other important flag might have changed, so + * reset. + */ + dprintf(("Interface eb is reinitialising\n")); + eb_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 +eb_watchdog(unit) + int unit; +{ + struct eb_softc *sc = eb_cd.cd_devs[unit]; + + log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); + sc->sc_arpcom.ac_if.if_oerrors++; + dprintf(("eb_watchdog: ")); + dprintf(("st=%04x\n", ReadShort(sc->sc_iobase + EB_8004_STATUS))); + + /* Kick the interface */ + + eb_reinit(sc); + + sc->sc_arpcom.ac_if.if_timer = 0; +} + +/* End of if_ea.c */ diff --git a/sys/arch/arm32/podulebus/if_ebreg.h b/sys/arch/arm32/podulebus/if_ebreg.h new file mode 100644 index 00000000000..b14bea7a503 --- /dev/null +++ b/sys/arch/arm32/podulebus/if_ebreg.h @@ -0,0 +1,154 @@ +/* $NetBSD: if_ebreg.h,v 1.2 1996/03/18 21:23:12 mark 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_ebreg.h + * + * EtherB device driver + * + * Created : 08/07/95 + */ + +/* + * SEEQ 80C04 Register Definitions + */ + +#define EB_8004_BASE 0x800 + +/* + * SEEQ 80C04 registers + */ + +#define EB_8004_COMMAND 0x000 +#define EB_8004_STATUS 0x000 +#define EB_8004_CONFIG1 0x040 +#define EB_8004_CONFIG2 0x080 +#define EB_8004_RX_END 0x0c0 +#define EB_8004_BUFWIN 0x100 +#define EB_8004_RX_PTR 0x140 +#define EB_8004_TX_PTR 0x180 +#define EB_8004_DMA_ADDR 0x1c0 + +/* */ + +#define EB_CMD_TEST_INTEN (1 << 0) +#define EB_CMD_RX_INTEN (1 << 1) +#define EB_CMD_TX_INTEN (1 << 2) +#define EB_CMD_TEST_INTACK (1 << 4) +#define EB_CMD_RX_INTACK (1 << 5) +#define EB_CMD_TX_INTACK (1 << 6) +#define EB_CMD_BW_INTACK (1 << 7) +#define EB_CMD_TEST_INT1 (1 << 8) +#define EB_CMD_RX_ON (1 << 9) +#define EB_CMD_TX_ON (1 << 10) +#define EB_CMD_TEST_INT2 (1 << 11) +#define EB_CMD_RX_OFF (1 << 12) +#define EB_CMD_TX_OFF (1 << 13) +#define EB_CMD_FIFO_READ (1 << 14) +#define EB_CMD_FIFO_WRITE (1 << 15) + +#define EB_STATUS_TEST_INT (1 << 4) +#define EB_STATUS_RX_INT (1 << 5) +#define EB_STATUS_TX_INT (1 << 6) +#define EB_STATUS_RX_ON (1 << 9) +#define EB_STATUS_TX_ON (1 << 10) +#define EB_STATUS_TX_NOFAIL (1 << 12) +#define EB_STATUS_FIFO_FULL (1 << 13) +#define EB_STATUS_FIFO_EMPTY (1 << 14) +#define EB_STATUS_FIFO_DIR (1 << 15) +#define EB_STATUS_FIFO_READ (1 << 15) + +#define EB_CFG1_SPECIFIC ((0 << 15) | (0 << 14)) +#define EB_CFG1_BROADCAST ((0 << 15) | (1 << 14)) +#define EB_CFG1_MULTICAST ((1 << 15) | (0 << 14)) +#define EB_CFG1_PROMISCUOUS ((1 << 15) | (1 << 14)) + +#define EB_CFG2_BYTESWAP (1 << 0) +#define EB_CFG2_REA_AUTOUPDATE (1 << 1) +#define EB_CFG2_RX_TX_DISABLE (1 << 2) +#define EB_CFG2_CRC_ERR_ENABLE (1 << 3) +#define EB_CFG2_DRIB_ERR_ENABLE (1 << 4) +#define EB_CFG2_PASS_LONGSHORT (1 << 5) +#define EB_CFG2_PREAM_SELECT (1 << 7) +#define EB_CFG2_RX_CRC (1 << 9) +#define EB_CFG2_NO_TX_CRC (1 << 10) +#define EB_CFG2_LOOPBACK (1 << 11) +#define EB_CFG2_OUTPUT (1 << 12) +#define EB_CFG2_RESET (1 << 15) + +#define EB_CFG3_SLEEP (1 << 3) + +#define EB_BUFCODE_STATION_ADDR 0x00 +#define EB_BUFCODE_ADDRESS_PROM 0x06 +#define EB_BUFCODE_TX_EAP 0x07 +#define EB_BUFCODE_LOCAL_MEM 0x08 +#define EB_BUFCODE_TX_COLLS 0x0b +#define EB_BUFCODE_CONFIG3 0x0c +#define EB_BUFCODE_PRODUCTID 0x0d +#define EB_BUFCODE_TESTENABLE 0x0e +#define EB_BUFCODE_MULTICAST 0x0f + +#define EB_PKTHDR_TX (1 << 7) +#define EB_PKTHDR_RX (0 << 7) +#define EB_PKTHDR_CHAIN_CONT (1 << 6) +#define EB_PKTHDR_DATA_FOLLOWS (1 << 5) + +#define EB_PKTHDR_DONE (1 << 7) + +#define EB_TXHDR_BABBLE (1 << 0) +#define EB_TXHDR_COLLISION (1 << 1) +#define EB_TXHDR_COLLISION16 (1 << 2) +#define EB_TXHDR_COLLISIONMASK (0x78) +#define EB_TXHDR_ERROR_MASK (0x07) + +#define EB_TXHDR_BABBLE_INT (1 << 0) +#define EB_TXHDR_COLLISION_INT (1 << 1) +#define EB_TXHDR_COLLISION16_INT (1 << 2) +#define EB_TXHDR_XMIT_SUCCESS_INT (1 << 3) +#define EB_TXHDR_SQET_TEST_INT (1 << 3) + +#define EB_RXHDR_OVERSIZE (1 << 0) +#define EB_RXHDR_CRC_ERROR (1 << 1) +#define EB_RXHDR_DRIBBLE_ERROR (1 << 2) +#define EB_RXHDR_SHORT_FRAME (1 << 3) + +#define EB_BUFFER_SIZE 0x10000 +#define EB_TX_BUFFER_SIZE 0x4000 +#define EB_RX_BUFFER_SIZE 0xC000 + +/* Packet buffer size */ + +#define EB_BUFSIZ 2048 + +/* End of if_ebreg.h */ diff --git a/sys/arch/arm32/podulebus/if_eh.c b/sys/arch/arm32/podulebus/if_eh.c new file mode 100644 index 00000000000..ab476637091 --- /dev/null +++ b/sys/arch/arm32/podulebus/if_eh.c @@ -0,0 +1,1213 @@ +/* $NetBSD: if_eh.c,v 1.6 1996/03/27 21:49:34 mark Exp $ */ + +/* + * Copyright (c) 1995 Melvin Tang-Richardson. + * All rights reserved. + * + * Essential things to do + * - BPF and multicast support + * - Testing + * - 16-bit dma's + * - Buffer overflow handling (This must be done a certain way) [Nuts] + * - Enabling card interrupts (Need i cubed info) + * + * Other things to do + * - Pipelined transmitts + * - Dynamic buffer allocation + * - Shared RAM if I cubed give me info + * + * 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 RiscBSD. + * 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 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. + * + * if_eh.c + * + * Ether H driver. + */ + +/* Some system includes *****************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Hardware related include chip/card/bus ***********************************/ + +#include +#include +#include +#include +#include + +/* Includes for interfacing with the network subsystem **********************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef INET +#include +#include +#include +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +/****************************************************************************/ +/* Some useful definitions **************************************************/ +/****************************************************************************/ + +#define MY_MANUFACTURER (0x46) +#define MY_PODULE (0xec) + +#define TXBUF_SIZE (1522) +#define NTXBUF (1) + +#define RXBUF_SIZE (256) +#define NRXBUF (26) + +#define ETHER_MIN_LEN (64) +#define ETHER_MAX_LEN (1522) + +#define PRINTF printf + +/****************************************************************************/ +/* Prototype internal data structures ***************************************/ +/****************************************************************************/ + +struct eh_softc { + /* Kernel interface variables */ + struct device sc_dev; + int sc_podule_number; + podule_t *sc_podule; + irqhandler_t sc_ih; + + /* Network subsystem interface */ + struct arpcom sc_arpcom; + int promisc; + + /* Driver defined state variables */ + int sc_flags; + + /* Hardware defined state */ + int sc_base; + int sc_reg; + int sc_nxtpkt; + + /* Card memory map */ + int sc_physstart; + int sc_physend; + int sc_tbs[NTXBUF]; /* Transmit buffer start */ + int sc_rbs; + int sc_rbd; + + /* Txrx parameters */ + int sc_txcur; /* Fill this buffer next */ + int sc_txlst; /* Buffer in use */ +}; + +/* sc_flags */ + +#define MODE_MASK (3) +#define MODE_DEAD (0) +#define MODE_PIO (1) +#define MODE_SHRAM (2) + +/****************************************************************************/ +/* Function and data prototypes *********************************************/ +/****************************************************************************/ + +int ehprobe __P((struct device *parent, void *match, void *aux)); +void ehattach __P((struct device *parent, struct device *self, void *aux)); +void ehstart __P((struct ifnet *ifp)); +int ehioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data)); +void ehwatchdog __P((int unit)); +void eh_stop_controller __P((struct eh_softc *sc)); +void eh_start_controller __P((struct eh_softc *sc)); +void eh_transmit_command __P((struct eh_softc *sc)); +int eh_copyin __P((struct eh_softc *sc, int src, char *dest, int len)); +int eh_copyout __P((struct eh_softc *sc, char *src, int dest, int len)); +void ehinit __P((struct eh_softc *sc)); +int ehstop __P((struct eh_softc *sc)); +int ehintr __P((void *arg)); +void eh_shutdown __P((void *arg)); + +struct cfattach eh_ca = { + sizeof(struct eh_softc), ehprobe, ehattach +}; + +struct cfdriver eh_cd = { + NULL, "eh", DV_DULL, NULL, 0 +}; + +/****************************************************************************/ +/* Some useful macros *******************************************************/ +/****************************************************************************/ + +#define SetReg(r,v) WriteWord ( sc->sc_reg+(r), (v)|((v)<<16) ) + +#define GetReg(r) ReadByte ( sc->sc_reg+(r) ) + +#define PAGE(n) SetReg ( EH_COMMAND, \ + ((GetReg(EH_COMMAND)&COM_MASK_PAGE)|(n<<6)) ) + +/* When initiating a remote dma, reset the TXP bit. This Does Not abort */ +/* the transmit, but allows us overlap this remote dma */ + +#define REMOTE_DMA(n) SetReg ( EH_COMMAND, \ + ((GetReg(EH_COMMAND)&(COM_MASK_DMA))|n) ) + +extern char *boot_args; +char *strstr __P((char */*s1*/, char */*s2*/)); + +/****************************************************************************/ +/* Bus attachment code ******************************************************/ +/****************************************************************************/ + +int +ehprobe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct eh_softc *sc = (void *) match; + struct podule_attach_args *pa = (void *) aux; + int counter; + int temp; + int podule; + + podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number); + + if (podule == -1) + return 0; + + /* Start to fill in the softc with the trivial variables */ + + sc->sc_flags = MODE_PIO; /* Select pio mode until I get info from i^3 */ + sc->sc_base = podules[podule].fast_base; + sc->sc_reg = sc->sc_base + 0x800; + + /* The probe could be tidied up a little */ + + /* Reset the card */ + SetReg(EH_RESET, 0xff); + delay(10000); + + /* Explicitly abort remote DMA, mainly to set a legal state */ + PAGE(0); + eh_stop_controller(sc); + SetReg(EH_COMMAND, 0x20); /* This is wrong */ + + SetReg(EH_ISR, 0xf ); /* Clear any previous work */ + + temp = GetReg(EH_CONFIGA); + temp = GetReg(EH_CONFIGA); + temp &= ~0x38; + SetReg(EH_CONFIGA, temp | 3<<3); + + temp = GetReg(EH_CONFIGA); + temp = GetReg(EH_CONFIGA); + + /* Make the thing interrupt and test it */ + + eh_start_controller(sc); + + /* Temporary initialisation, to allow a transmit test */ + + SetReg(EH_PSTART, 16384 >> 8); + SetReg(EH_PSTOP, 16896 >> 8); + SetReg(EH_BNRY, 16384 >> 8); + + SetReg(EH_TCR, TCR_NORMALLOOP); /* Erk!! No, put us in loopback */ + SetReg(EH_DCR, DCR_WTS|DCR_LS|DCR_LAS); + SetReg(EH_RCR, 0); + + /* Transmit some garbage into the loopback */ + + SetReg(EH_TPSR, 0x5000); + SetReg(EH_TBCR0, 0); + SetReg(EH_TBCR1, 3); + + eh_transmit_command(sc); + + /* The card shouldn't be this quick, so use it as a test */ + + if ((GetReg(EH_TSR)&TSR_DONE) != 0) + PRINTF("eh: Card responded rather quickly %02x\n", GetReg(EH_TSR)); + + for (counter=500; counter>0; counter--) { + if ((GetReg(EH_TSR)&TSR_DONE) != 0) + break; + + delay(500); + } + + if (counter == 0) { + PRINTF("eh: card did not respond\n"); + return 0; + } + + /* Let it sleep since we're not doing anything with it for now */ + + SetReg(EH_ISR, 0); + SetReg(EH_DCR, DCR_WTS|DCR_LS|DCR_LAS); + + + /* Test the board ram. This code will change */ + + /* + * Due to problems with some ether H cards the boot option ehbug + * can be used to skip this test. + * If you system hangs during the eh probe try this option. + */ + + #define NLEN (0x2000) + #define NBASE (0x4000) + + if (boot_args) { + char *ptr; + + ptr = strstr(boot_args, "ehbug"); + if (!ptr) { + char *test_data; + char *read_buffer; + MALLOC(test_data, char *, NLEN, M_TEMP, M_NOWAIT); + if (test_data == NULL) + panic("Cannot allocate temporary memory for buffer test (1)\n"); + MALLOC(read_buffer, char *, NLEN, M_TEMP, M_NOWAIT); + if (read_buffer == NULL) + panic("Cannot allocate temporary memory for buffer test (1)\n"); + + printf("1."); + + /* Fill the test_data block */ + + for (counter=0; countersc_physstart = 0x4000; + sc->sc_physend = 0x6000; + + /* Get out ethernet address */ + sc->sc_arpcom.ac_enaddr[0] = 0x00; + sc->sc_arpcom.ac_enaddr[1] = 0x00; + sc->sc_arpcom.ac_enaddr[2] = 0xc0; + sc->sc_arpcom.ac_enaddr[3] = 0x41; + sc->sc_arpcom.ac_enaddr[4] = bootconfig.machine_id[1]; + sc->sc_arpcom.ac_enaddr[5] = bootconfig.machine_id[0]; + + /* Copy the ether addr cards filter */ + + PAGE(1); + for (counter=0; counter<6; counter++) + SetReg(((counter+1)<<2), sc->sc_arpcom.ac_enaddr[counter]); + PAGE(0); + + /* Tell the podule system about our successful probe */ + pa->pa_podule_number = podule; + pa->pa_podule = &podules[podule]; + + return 1; +} + +void +ehattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct eh_softc *sc = (void *) self; + struct podule_attach_args *pa = (void *)aux; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + int irq; + int temp; + + /* Check a few things about the attach args */ + sc->sc_podule_number = pa->pa_podule_number; + if (sc->sc_podule_number == -1) + panic("Podule has disappeared !"); + + sc->sc_podule = &podules[sc->sc_podule_number]; + podules[sc->sc_podule_number].attached = 1; + + /* Fill in my application form to attach to the networking system */ + + ifp->if_unit = sc->sc_dev.dv_unit; + ifp->if_name = eh_cd.cd_name; + ifp->if_start = ehstart; + ifp->if_ioctl = ehioctl; + ifp->if_watchdog = ehwatchdog; + ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS; + + /* Signed, dated then sent */ + + if_attach(ifp); + ether_ifattach(ifp); + + /* Not print some stuff for the attach line, starting with the address */ + + PRINTF(" address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr)); + + /* Now the transfer mode we're operating in */ + + switch (sc->sc_flags & MODE_MASK) { + case MODE_PIO: + PRINTF(" pio mode"); + break; + case MODE_SHRAM: + PRINTF(" ram mode"); + break; + default: + panic("Ether H probe set an unknown mode"); + } + + /* Get an irq handler installed */ + + SetReg(EH_IMR, 0); + SetReg(EH_ISR, 0xff); + + sc->sc_ih.ih_func = ehintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_NET; + sc->sc_ih.ih_name = "net: eh"; + + irq = (sc->sc_podule_number>=MAX_PODULES) ? IRQ_NETSLOT : IRQ_PODULE; + + if (irq_claim(irq, &sc->sc_ih)) + panic("Cannot install IRQ handler"); + + /* This loopbacks the card on reset, and stops riscos locking */ + + if (shutdownhook_establish(eh_shutdown, (void *)sc)==NULL) + panic("Cannot install shutdown handler"); + + /* Reprogram CONFIGA. I dont think we should do this any more */ + + temp = GetReg(EH_CONFIGA); + temp = GetReg(EH_CONFIGA); + temp &= ~0x38; + SetReg(EH_CONFIGA, temp | (3<<3)); + + /* And that's it */ + + PRINTF("\n"); +} + +/****************************************************************************/ +/* Net subsystem interface **************************************************/ +/****************************************************************************/ + +#define NEXT_TXBUF (((sc->sc_txcur+1)>=NTXBUF) ? 0 : (sc->sc_txcur+1)) + +void +ehstart(ifp) + struct ifnet *ifp; +{ + struct eh_softc *sc = eh_cd.cd_devs[ifp->if_unit]; + int cur; + struct mbuf *m0, *m; + int nextbuf; + char *buffer; + char txbuf[TXBUF_SIZE]; + int len = 0; + + PAGE(0); + + if ((ifp->if_flags & IFF_OACTIVE) != 0) + return; + +/* This is for pipelined transmit. At present just use 1 buffer */ + + for (;;) { + +/* The #ifdef PIPELINE_TRANSMIT code is total screwed */ + +#ifdef PIPELINE_TRANSMIT + nextbuf = NEXT_TXBUF; + if ( nextbuf == sc->sc_txlst ) + ifp->if_flags |= IFF_OACTIVE; + break; + } +#else + nextbuf = 0; +#endif + + /*** Speed up - In future, copy the bufs direct to the card ***/ + + /* Copy a frame out of the mbufs */ + + IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m); + if ( !m ) + break; + + buffer = txbuf; + + len = 0; + for ( m0=m; m && (len + m->m_len) < TXBUF_SIZE; m=m->m_next ) { + bcopy(mtod(m,caddr_t), buffer, m->m_len); + buffer+=m->m_len; + len+=m->m_len; + } + + m_freem(m0); + len = max ( len, ETHER_MIN_LEN ); + + /* And blat it to the card */ + + eh_copyout ( sc, txbuf, sc->sc_tbs[nextbuf], len ); + +#ifdef PIPELINE_TRANSMIT + sc->sc_txlst = nextbuf; +#endif + PAGE(0); + + SetReg ( EH_TPSR, sc->sc_tbs[nextbuf]>>8 ); + SetReg ( EH_TBCR0, len&0xff ); + SetReg ( EH_TBCR1, (len>>8) & 0xff ); + + cur = GetReg(EH_COMMAND); + + eh_transmit_command (sc ); + + ifp->if_flags |= IFF_OACTIVE; + ifp->if_timer = 30; + +#ifndef PIPELINE_TRANSMIT + break; +#endif + } +} + +#define IZSET(a,b) ((a->if_flags&b)!=0) +#define IZCLR(a,b) ((a->if_flags&b)==0) +#define DOSET(a,b) (a->if_flags|=b) +#define DOCLR(a,b) (a->if_flags&=~b) + +int +ehioctl(ifp, cmd, data) + struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + struct eh_softc *sc = eh_cd.cd_devs[ifp->if_unit]; + struct ifaddr *ifa = (struct ifaddr *)data; + int s = splimp (); + int error = 0; + + switch (cmd) { + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + switch ( ifa->ifa_addr->sa_family ) { +#ifdef INET + case AF_INET: + ehinit(sc); + arp_ifinit(&sc->sc_arpcom, ifa); + break; +#endif + default: + ehinit(sc); + break; + } + break; + + case SIOCSIFFLAGS: + sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI ); + + if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) ) { + /* Interface marked down, but still running */ + ehstop(sc); + DOCLR(ifp,IFF_RUNNING); + } else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) ) { + /* Just marked up, not running yet */ + ehinit(sc); + } else { + /* Reset to invoke changes in other registers */ + ehstop(sc); + ehinit(sc); + } + + default: + error = EINVAL; + } + + splx (s); + return error; +} + +void +ehwatchdog(unit) + int unit; +{ + struct eh_softc *sc = eh_cd.cd_devs[unit]; + + log (LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname ); + sc->sc_arpcom.ac_if.if_oerrors++; + + ehinit (sc); +} + +/* + * void eh_stop_controller ( struct eh_softc *sc ) + * + * Software reset command, takes the controller offline, no packets will be + * received or transmitted. Any reception or transmission inprogres will + * continue to completion before entering the reset state. + */ + +void +eh_stop_controller(sc) + struct eh_softc *sc; +{ + SetReg ( EH_COMMAND, ((GetReg(EH_COMMAND)&0xfc)|1) ); + delay ( 10000 ); /* Change this to wait on the ISR bit */ +} + +/* + * void eh_start_controller ( struct eh_softc *sc ) + * + * Activte the NIC core after either power up or when the NIC Core has + * been placed in a reset mode by eh_stop_controller or an error. + */ + +void +eh_start_controller(sc) + struct eh_softc *sc; +{ + int temp = GetReg(EH_COMMAND); + SetReg ( EH_COMMAND, ( (temp&0xfc)|2) ); +} + +void +eh_transmit_command(sc) + struct eh_softc *sc; +{ + /* Explicit set here. There is no other reasonable combination */ + SetReg ( EH_COMMAND, COM_ABORT|COM_STA|COM_TXP); +} + +/****************************************************************************/ +/* Remote DMA handling ******************************************************/ +/****************************************************************************/ + +/* Remote DMA handling is going to undergo a major overhaul real soon now */ + +/* We musn't fail */ + +inline void +eh_ensure_dma_ok(sc) + struct eh_softc *sc; +{ + register int isr = GetReg ( EH_ISR ); + register int status = GetReg ( EH_COMMAND ); + int dummy; + + if ((status&COM_ABORT)==0) { + SetReg ( EH_COMMAND, status|COM_ABORT ); + while ((isr&ISR_RDC)==0) { + dummy = GetReg ( EH_DATA_PORT ); + delay(50); + } + } + + /* Reset the COM_TXP bit. This does not abort transmission */ + + SetReg(EH_COMMAND, 0x22); +} + +inline int +eh_ensure_dma_competed(sc, type) + struct eh_softc *sc; + int type; +{ + register int status = GetReg ( EH_COMMAND ); + + if ( (status&COM_ABORT)==0 ) { + int dummy=0; + printf ( "EHDEBUG: Remote %d wasn't finished\n", type ); + SetReg ( EH_COMMAND, status|COM_ABORT ); + switch ( type ) { + case COM_READ: + dummy = GetReg ( EH_DATA_PORT ); + break; + case COM_WRITE: + SetReg ( EH_DATA_PORT, dummy ); + break; + } + ehinit (sc); + return 1; + } + return 0; +} + +/* Do an eh_copyin, but take into consideration ring wrap */ + +int +eh_copyring(sc, src, dest, len) + struct eh_softc *sc; + int src; + char *dest; + int len; +{ + if ( (src+len)>sc->sc_rbd ) { + register int in = sc->sc_rbd - src; + if ( eh_copyin ( sc, src, dest, in )==0 ) { + printf ( "copyring failed pass 1\n" ); + return 0; + } + if ( eh_copyin ( sc, sc->sc_rbs, dest+in, len-in )==0 ) { + printf ( "copyring failed pass 2\n" ); + return 0; + } + } else { + if ( eh_copyin ( sc, src, dest, len )==0 ) { + printf ( "copyring faild on 1 pass copy\n" ); + return 0; + } + } + return len; +} + +int +eh_copyin(sc, src, dest, len) + struct eh_softc *sc; + int src; + char *dest; + int len; +{ + int counter; + int s; + short *dst = (short *)dest; + + s = splhigh(); /* Erm, maybe not needed now */ + + if (len & 1) + len++; + if (src & 1) { + printf ( "EHDEBUG: Copying from odd address\n" ); + src++; + } + + /* Remote DMA to the DP83905 must be done with care. If we dont */ + /* do it exactly right, it punishes us by locking the bus. */ + + eh_ensure_dma_ok (sc); + + /* Set up the DMA */ + + SetReg ( EH_RSAR0, src & 0xff ); + SetReg ( EH_RSAR1, (src>>8) & 0xff ); + SetReg ( EH_RBCR0, len & 0xff ); + SetReg ( EH_RBCR1, (len>>8) & 0xff ); + + /* Set the DMA running */ + /* REMOTE_DMA ( COM_READ ); */ /* SetReg ( EH_COMMAND, 0x0a ); */ + SetReg ( EH_COMMAND, COM_READ|COM_STA ); + + for ( counter=0; countersc_reg + EH_DATA_PORT ); + + splx(s); + + if ( eh_ensure_dma_competed ( sc, COM_READ ) ) + return 0; + + return len; +} + +int +eh_copyout(sc, src, dest, len) + struct eh_softc *sc; + char *src; + int dest; + int len; +{ + int counter; + int s; + short *sr = (short *)src; + + if (len & 1) + len++; + if (dest & 1) { + printf ( "EHDEBUG: Copying to odd address\n" ); + dest++; + } + + s = splhigh(); /* Erm, maybe not needed now */ + + /* Remote DMA to the DP83905 must be done with care. If we dont */ + /* do it exactly right, it punishes us by locking the bus. */ + + eh_ensure_dma_ok (sc); + + /* Set up the DMA */ + + SetReg ( EH_RSAR0, dest & 0xff ); + SetReg ( EH_RSAR1, (dest>>8) & 0xff ); + SetReg ( EH_RBCR0, len & 0xff ); + SetReg ( EH_RBCR1, (len>>8) & 0xff ); + + /* Set the DMA running */ + /*REMOTE_DMA ( COM_WRITE );*/ /* SetReg ( EH_COMMAND, 0x0a ); */ + SetReg ( EH_COMMAND, COM_WRITE|COM_STA ); + + for ( counter=0; countersc_reg + EH_DATA_PORT, *(sr) ); + sr++; + } + + splx(s); + + if ( eh_ensure_dma_competed ( sc, COM_WRITE ) ) + return 0; + + return len; +} + +#define ALLOCBLK(v,s) (v)=card_freestart; \ + card_freestart+=((s)+0xff)&(~0xff) + +void +ehinit(sc) + struct eh_softc *sc; +{ + int card_freestart; + int counter; + + PAGE(0); + + /* Lay out the cards ram */ + card_freestart = sc->sc_physstart; + + /* Allocate receive buffers */ + + ALLOCBLK ( sc->sc_rbs, (RXBUF_SIZE*NRXBUF) ); + sc->sc_rbd = card_freestart; + sc->sc_nxtpkt = sc->sc_rbs + 0x100; + + /* Allocate transmit buffers */ + for ( counter=0; countersc_tbs[counter], TXBUF_SIZE ); + } + + if ( card_freestart > sc->sc_physend ) { + printf ( "eh: card short of ram %02x required %02x present\n", + card_freestart, sc->sc_physstart ); + sc->sc_arpcom.ac_if.if_flags &= ~IFF_RUNNING; + sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE; + return; + } + + /* + * Bring the controller up + * + * The ordering here is critical. Dont change unless you know what + * you're doing + */ + + /* Reset the card */ + + SetReg ( EH_RESET, 0xff ); + delay (50000); + SetReg ( EH_RESET, 0x00 ); + delay (50000); + + /* 1. Program the command register for page 0 */ + + SetReg ( EH_COMMAND, 0x21 ); + + /* 2. Initialize the Data configuration register */ + + SetReg ( EH_DCR, DCR_WTS|DCR_LS|(0<<5) ); + + /* 3. Clear RBCR if using remote DMA */ + + SetReg ( EH_RBCR0, 0 ); + SetReg ( EH_RBCR1, 0 ); + + /* 4. Initialise RCR */ + + SetReg ( EH_RCR, 0x04 ); + + /* 5. Place the controller in loopback mode 1 or 2 TCR=02H or 04H */ + + SetReg ( EH_TCR, 0x02 ); + + /* 6. Initiliase Receive ring buffer BNDRY PSTART PSTOP */ + + SetReg ( EH_BNRY, sc->sc_rbs >> 8 ); + SetReg ( EH_PSTART, sc->sc_rbs >> 8 ); + SetReg ( EH_PSTOP, sc->sc_rbd >> 8 ); + + /* 7. Clear ISR */ + + SetReg ( EH_ISR, 0xff ); + + /* 8. Initialise IMR */ + + SetReg ( EH_IMR, ISR_PRX|ISR_PTX|ISR_RXE|ISR_TXE|ISR_OVW|ISR_CNT ); + + /* 9. Program command register for page 1 COM=0x61 */ + /* Initialise PAR MAR and CURR */ + + PAGE(1); + + SetReg ( EH_CURR, sc->sc_nxtpkt >> 8 ); + + for ( counter=0; counter<6; counter++ ) + SetReg ( ((counter+1)<<2), sc->sc_arpcom.ac_enaddr[counter] ); + + /* Put controller into start mode COM = 0x22 */ + + SetReg ( EH_COMMAND, 0x22 ); + + /* Initialise the TCR */ + + SetReg ( EH_TCR, TCR_NORMALLOOP ); + + /* Interface is up */ + + sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING; + sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + + ehstart(&sc->sc_arpcom.ac_if); +} + +int +ehstop(sc) + struct eh_softc *sc; +{ + int s = splimp(); + eh_stop_controller(sc); + SetReg(EH_DCR, DCR_LS|DCR_LAS); + splx(s); + return 0; +} + +#define INTR_ACK(s) SetReg ( EH_ISR, s ) + +/* In need of tidying */ + +#undef MYTEST + +void +eh_rint(sc) + struct eh_softc *sc; +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + struct mbuf *top, **mp, *m; + struct ether_header eh; + struct eh_rxhdr hdr; + int status = GetReg(EH_RSR); + int rxstatus=0; + int totlen, len; + int ptr; + int rbend; + int thispacket; + int bnry; + +#ifdef MYTEST + int old; +#endif + + /* Get the end of the ring buffer */ + + PAGE(1); + rbend = GetReg ( EH_CURR ) << 8; + PAGE(0); + + /* If we have something to receive then receive it */ + + if ( status&RSR_PRX ) { + /* Remove all the packets from the ring buffer */ + for ( ptr=sc->sc_nxtpkt; ptr!=rbend ; ptr = sc->sc_nxtpkt ) { + + thispacket = ptr; + /* Copy the ether h receive header */ + + if ( eh_copyring ( sc, ptr, (char *)&hdr, 4 ) != 4 ) { + printf ( "eh: Failed copying in header\n" ); + printf ( "eh: thispacket %02x\n", thispacket ); + ehinit (sc); + return; + } + + rxstatus = hdr.rx_status; + totlen = (hdr.rx_rbc1<<8) + hdr.rx_rbc0; + + ptr+=4; + + /* Check the packet's status */ + if ( hdr.rx_status&(RSR_CRC|RSR_FAE|RSR_FO|RSR_MPA) ) { + printf ( "eh: intact packet is corrupt %02x %04x\n", + hdr.rx_status, ptr ); + } + + if (((hdr.rx_nxtpkt<<8)>sc->sc_rbd) || ((hdr.rx_nxtpkt<<8)sc_rbs)) { + printf ( "eh: ring buffer empty %04x %04x\n", + hdr.rx_nxtpkt, ptr ); + ehinit (sc); + return; + } + + if (0) + printf ( "pulling packet at %08x, next at %08x\n", thispacket, sc->sc_nxtpkt ); + + if ( totlen>ETHER_MAX_LEN ) { + printf ( "eh: giant packet received %04x\n", totlen ); + totlen = ETHER_MAX_LEN; + } + + /* Copy the ether header */ + + if ((eh_copyring ( sc, ptr, (char *)&eh, sizeof (eh)))!=sizeof(eh)) { + printf ( "eh: Failed copying in ethenet header\n" ); + return; + } + ptr+=sizeof(eh); + totlen-=sizeof(eh); + + /* Copy the packet into mbufs */ + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if ( m==0 ) + return; + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = totlen; + len = MHLEN; + top = 0; + mp = ⊤ + + while ( totlen > 0 ) { + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if ( m==0 ) { + m_freem(top); + goto skip; + } + len = MLEN; + } + if ( totlen >= MINCLSIZE ) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + len = MCLBYTES; + } + m->m_len = len = min ( totlen, len ); + + if ((eh_copyring ( sc, ptr, mtod(m, caddr_t), len))!=len) + printf ( "eh: failed copying in buffer %d\n", len ); + + ptr += len; + totlen -= len; + *mp = m; + mp = &m->m_next; + } + + m = top; + ifp->if_ipackets++; + ether_input(ifp, &eh, m ); +skip: + + /* Ok, I'm done with this packet */ + + sc->sc_nxtpkt = hdr.rx_nxtpkt << 8; + + /* Set the boundary pointer on the ring buffer */ + + bnry = (sc->sc_nxtpkt>>8)-1; + if ( bnry < (sc->sc_rbs>>8) ) + bnry = (sc->sc_rbd>>8)-1; + SetReg ( EH_BNRY, bnry ); + + PAGE(1); + rbend = GetReg ( EH_CURR ) << 8; + PAGE(0); + } + } +} + +int +ehintr(arg) + void *arg; +{ + struct eh_softc *sc = arg; + register int isr = GetReg ( EH_ISR ); /* Is char of int faster ? */ + register int times = 0; + + PAGE(0); + + if ( isr & ISR_RXE ) { + int status = GetReg ( EH_RSR ); + PRINTF ( "eh: Receive Error:" ); + if ( status&RSR_PRX ) + PRINTF ( " packet received intact (this should happen)" ); + if ( status&RSR_CRC ) + PRINTF ( " crc error" ); + if ( status&RSR_FAE ) + PRINTF ( " frame alignment error" ); + if ( status&RSR_FO ) + PRINTF ( " fifo overrun" ); + if ( status&RSR_MPA ) + PRINTF ( " missed packet" ); + if ( status&RSR_DIS ) + PRINTF ( " receiver disabled" ); + printf ( "\n" ); + INTR_ACK ( ISR_RXE ); + ehinit (sc); + return 0; + } + + if ( isr & ISR_PRX ) { + eh_rint (sc); + INTR_ACK ( ISR_PRX ); + } + + if ( isr & ISR_PTX ) { + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + int status; + INTR_ACK ( ISR_PTX ); + ifp->if_timer=0; + ifp->if_flags &= ~IFF_OACTIVE; + + status = GetReg ( EH_TSR ); + + if ( status&TSR_PTX ) + ifp->if_opackets++; + + if ( status&TSR_COL ) + ifp->if_collisions+=GetReg(EH_NCR); + + if ( status&TSR_ABT ) + PRINTF ( "eh: too many collisions\n" ); + + if ( status&TSR_CRS ) + PRINTF ( "eh: no carrier\n" ); + + if ( status&TSR_CDH ) + PRINTF ( "eh: tranceiver failure, no heartbeat \n" ); + + if ( status&TSR_OWC ) + PRINTF ( "eh: out of window \n" ); + + if ( status&(TSR_ABT|TSR_CRS|TSR_FU|TSR_CDH|TSR_OWC) ) + ifp->if_oerrors++; + + ehstart(ifp); + } + + if ( isr & ISR_TXE ) { + INTR_ACK ( ISR_TXE ); + PRINTF ( "ehintr: Transmit error\n" ); + } + + if ( isr & ISR_OVW ) { + INTR_ACK ( ISR_OVW ); + PRINTF ( "ehintr: Counter overflow\n" ); + } + + if ( isr & ISR_RST ) { + INTR_ACK ( ISR_RST ); + PRINTF ( "ehintr: Reset status\n" ); + } + + if ((times++)>16) { + PRINTF ( "eh: possible interrupt jammed on." ); + SetReg ( EH_IMR, 0x0 ); + } + + /* Dont do this for the mo until I'm sure. + + isr = GetReg ( EH_ISR ); + + if ( (isr&GetReg(EH_IMR))!=0 ) + goto more; + */ + + if ( (isr&GetReg(EH_IMR))!=0 ) + printf ( "eh: Interrupt not serviced\n" ); + + return 0; +} + +/****************************************************************************/ +/* Auxilary routines ********************************************************/ +/****************************************************************************/ + +void +eh_shutdown(arg) + void *arg; +{ + struct eh_softc *sc = (struct eh_softc *)arg; + + /* On shutdown put us in loopback */ + + SetReg(EH_DCR, DCR_LAS); + SetReg(EH_TCR, TCR_NICMOD); + + /* and program remote dma so riscos doesnt lock */ + + SetReg(EH_RSAR0, 0); + SetReg(EH_RSAR1, 1); + SetReg(EH_RBCR0, 0); + SetReg(EH_RBCR1, 1); +} diff --git a/sys/arch/arm32/podulebus/if_ehreg.h b/sys/arch/arm32/podulebus/if_ehreg.h new file mode 100644 index 00000000000..8fbb18e964e --- /dev/null +++ b/sys/arch/arm32/podulebus/if_ehreg.h @@ -0,0 +1,151 @@ +/* $NetBSD: if_ehreg.h,v 1.2 1996/03/08 16:24:51 mark Exp $ */ + +/* + * Copyright (c) 1995 Melvin Tang-Richardson. + * 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 RiscBSD. + * 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 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. + * + * if_ehreg.h + * + * Ether H register definitions. + */ + +#define EH_RESET (0x18<<2) + +#define EH_DATA_PORT (0x10<<2) + +/* Special registers */ + +#define EH_CONFIGA (0x0a<<2) + +/* Page 0 read registers */ + +#define EH_COMMAND (0x00<<2) +#define EH_CLAD0 (0x01<<2) +#define EH_CLDA1 (0x02<<2) +#define EH_BNRY (0x03<<2) +#define EH_TSR (0x04<<2) +#define EH_NCR (0x05<<2) +#define EH_FIFO (0x06<<2) +#define EH_ISR (0x07<<2) +#define EH_CRDA0 (0x08<<2) +#define EH_CRDA1 (0x09<<2) +#define EH_RSR (0x0c<<2) + +/* Page 0 write registers */ + +#define EH_PSTART (0x01<<2) +#define EH_PSTOP (0x02<<2) +#define EH_TPSR (0x04<<2) +#define EH_TBCR0 (0x05<<2) +#define EH_TBCR1 (0x06<<2) +#define EH_RSAR0 (0x08<<2) +#define EH_RSAR1 (0x09<<2) +#define EH_RBCR0 (0x0a<<2) +#define EH_RBCR1 (0x0b<<2) +#define EH_RCR (0x0c<<2) +#define EH_TCR (0x0d<<2) +#define EH_DCR (0x0e<<2) +#define EH_IMR (0x0f<<2) + +/* Page 1 write registers */ + +#define EH_CURR (0x07<<2) + +/* Command bits */ + +#define COM_STP (0x01) +#define COM_STA (0x02) +#define COM_TXP (0x04) +#define COM_MASK_PAGE (0x3f) +#define COM_READ (0x08) +#define COM_WRITE (0x10) +#define COM_SEND (0x18) +#define COM_ABORT (0x20) +#define COM_MASK_DMA (0xc7) +#define COM_DMA_MASK (0x38) + +/* DCR bits */ + +#define DCR_WTS (0x01) +#define DCR_BOS (0x02) +#define DCR_LAS (0x04) +#define DCR_LS (0x08) +#define DCR_ARM (0x10) + +/* TSR bits */ + +#define TSR_PTX (0x01) +#define TSR_COL (0x04) +#define TSR_ABT (0x08) +#define TSR_CRS (0x10) +#define TSR_FU (0x20) +#define TSR_CDH (0x40) +#define TSR_OWC (0x80) +#define TSR_DONE ((TSR_PTX)|(TSR_ABT)) + +/* TCR bits */ + +#define TCR_CRC (0x01) +#define TCR_NORMALLOOP (0x00) +#define TCR_NICMOD (0x02) +#define TCR_ENDECMOD (0x04) +#define TCR_EXTLOOP (0x06) +#define TCR_ATD (0x08) +#define TCR_OFST (0x10) + +/* ISR bits */ + +#define ISR_PRX (0x01) +#define ISR_PTX (0x02) +#define ISR_RXE (0x04) +#define ISR_TXE (0x08) +#define ISR_OVW (0x10) +#define ISR_CNT (0x20) +#define ISR_RDC (0x40) +#define ISR_RST (0x80) + +/* RSR bits */ + +#define RSR_PRX (0x01) +#define RSR_CRC (0x02) +#define RSR_FAE (0x04) +#define RSR_FO (0x08) +#define RSR_MPA (0x10) +#define RSR_PHY (0x20) +#define RSR_DIS (0x40) +#define RSR_DFR (0x80) + +struct eh_rxhdr { + char rx_status; + char rx_nxtpkt; + char rx_rbc0; + char rx_rbc1; +}; + diff --git a/sys/arch/arm32/podulebus/if_ie.c b/sys/arch/arm32/podulebus/if_ie.c new file mode 100644 index 00000000000..ecc8269445d --- /dev/null +++ b/sys/arch/arm32/podulebus/if_ie.c @@ -0,0 +1,1524 @@ +/* $NetBSD: if_ie.c,v 1.5 1996/03/27 21:49:36 mark Exp $ */ + +/* + * Copyright (c) 1995 Melvin Tang-Richardson. + * All rights reserved. + * + * This driver is a major hash up of src/sys/dev/isa/if_ie.c and + * src/sys/arch/arm32/podule/kgdb_ie.c Please refer to copyright + * notices from them too. + * + * 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 RiscBSD. + * 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 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. + * + * RiscBSD kernel project + * + * if_ie.c + * + * Ether 1 podule driver + * + * Created : 26/06/95 + */ + +/* + * This driver is at it's last beta release. It should not cause + * any problems (Touch wood) + * + * If it passes field tests again. This will constitute the realse + * version. + */ + +#define IGNORE_ETHER1_IDROM_CHECKSUM + +/* Standard podule includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Include for interface to the net and ethernet subsystems */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef INET +#include +#include +#include +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +/* Import our data structres */ + +#include "if_iereg.h" + +/* BPF support */ + +#include "bpfilter.h" +#if NBPFILTER > 0 +#include +#include +#endif + +/* Some useful defines and macros */ + +#define MY_MANUFACTURER 0x00 +#define MY_PODULE 0x03 +#define PODULE_IRQ_PENDING (1) +#define NFRAMES (16) /* number of frame to allow for receive */ +#define NRXBUF (48) /* number of receive buffers to allocate */ +#define IE_RXBUF_SIZE (256) /* receive buf size */ +#define NTXBUF (2) /* number of transmit buffers to allocate */ +#define IE_TXBUF_SIZE (1522) /* size of tx buffer */ + +#define ETHER_MIN_LEN (64) +#define ETHER_MAX_LEN (1518) + +#define PWriteShort(a,b) WriteWord(a,(b)<<16|(b)) + +#define offsetof(type, member) (((size_t)&((type *)0)->member)<<1) + +/* Some data structres local to this file */ + +struct ie_softc { + struct device sc_dev; + int sc_podule_number; + podule_t *sc_podule; + irqhandler_t sc_ih; + int sc_iobase; + int sc_fastbase; + int sc_rom; + int sc_ram; + int sc_control; + struct arpcom sc_arpcom; + int promisc; + int sc_irqmode; + + u_long rframes[NFRAMES]; + u_long rbuffs[NRXBUF]; + u_long cbuffs[NRXBUF]; + int rfhead, rftail, rbhead, rbtail; + + u_long xmit_cmds[NTXBUF]; + u_long xmit_buffs[NTXBUF]; + u_long xmit_cbuffs[NTXBUF]; + int xmit_count; + int xmit_free; + int xchead; + int xctail; +}; + +/* Function and data prototypes */ + +static void host2ie ( struct ie_softc *sc, void *src, u_long dest, int size ); +static void ie2host ( struct ie_softc *sc, u_long src, void *dest, int size ); +static void iezero ( struct ie_softc *sc, u_long p, int size ); +void iereset ( struct ie_softc *sc ); +void iewatchdog ( int unit ); +int ieioctl ( struct ifnet *ifp, u_long cmd, caddr_t data ); +void iestart ( struct ifnet *ifp ); +int iestop ( struct ie_softc *sc ); +int ieinit ( struct ie_softc *sc ); +int ieintr ( void *arg ); +void ietint ( struct ie_softc *sc ); + +/* A whopper of a function */ +static int command_and_wait ( struct ie_softc *sc, u_short cmd, + struct ie_sys_ctl_block *pscb, + void *pcmd, int ocmd, int scmd, int mask ); + +struct cfattach ie_ca; + +struct cfdriver ie_cd; + +/* Let's go! */ + +/* + * Clear all pending interrupts from the i82586 chip + */ + +static __inline void ie_cli ( struct ie_softc *sc ) +{ + WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_CLI ); +} + +/* + * Cool down the i82586, like its namesake, it gets very hot + */ + +static __inline void ie_cooldown ( int temperature ) +{ +} + +/* + * Wake the i82586 chip up and get it to do something + */ + +static __inline void ieattn ( struct ie_softc *sc ) +{ + WriteByte ( sc->sc_control + (IE_CONTROL<<2), IE_CONT_ATTN ); +} + +/* + * Set the podule page register to bring a given address into view + */ + +static __inline void setpage ( struct ie_softc *sc, u_long off ) +{ + WriteByte ( sc->sc_control + (IE_PAGE<<2), IE_COFF2PAGE(off) ); +} + +/* + * Ack the i82586 + */ + +static void ie_ack ( struct ie_softc *sc, u_short mask ) +{ + u_short stat; + int i; + setpage(sc, IE_IBASE + IE_SCB_OFF ); + + stat = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + + (offsetof(struct ie_sys_ctl_block, ie_status)) ); + + PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + + (offsetof(struct ie_sys_ctl_block, ie_command)), + stat & mask ); + + ieattn(sc); + + for ( i=4000; --i>=0; ) { + if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + + (offsetof(struct ie_sys_ctl_block, ie_command))) ) + break; + delay(100); + } + + if ( i<=0 ) + { + printf ( "ie: command timed out\n" ); + } + ie_cli(sc); +} + +/* + * This routine does the checksumming for the idrom + */ + +static u_long crc32(u_char *p, int l) +{ + u_long crc=-1; + int i, b; + while ( --l >= 0 ) { + b = *p++; + for ( i=8; --i >= 0; b>>=1 ) + if ((b&1)^(crc>>31)) + crc=(crc<<1)^0x4c11db7; + else + crc<<=1; + } + return crc; +} + +/* + * Probe for the ether1 card. return 1 on success 0 on failure + */ + +int ieprobe ( struct device *parent, void *match, void *aux ) +{ + struct ie_softc *sc = (void *)match; + struct podule_attach_args *pa = (void *)aux; + int podule, i; + char idrom[32]; + u_char *hwaddr = sc->sc_arpcom.ac_enaddr; + + /* Get the nice podulebus podule to find my podule in its table */ + podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number); + + if (podule == -1) + return(0); + + /* Index some podule areas */ + sc->sc_iobase = podules[podule].sync_base; /* OBSOLETE */ + sc->sc_fastbase = podules[podule].fast_base; /* OBSOLETE */ + sc->sc_rom = podules[podule].sync_base; + sc->sc_control = podules[podule].fast_base; + sc->sc_ram = podules[podule].fast_base + IE_MEMOFF; + + /* Set the page mask to something know and neutral */ + setpage(sc, IE_SCB_OFF); + + /* Fetch the first part of the idrom */ + for ( i=0; i<16; i++ ) { + idrom[i] = ReadByte ( sc->sc_rom + (i<<2) ); + }; + + /* Verify the podulebus probe incase RiscOS lied */ + if ( ReadByte ( sc->sc_rom + (3<<2) ) != 0x03 ) { + panic ( "ie: Ether1 ROM probablly broken. ECID corrupt" ); + return 0; + } + + /* Reset the 82586 */ + WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_RESET ); + delay(1000); + WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), 0 ); + delay(10000); + + /* Clear pending interrupts */ + ie_cli (sc); + + /* Setup SCP */ + { + struct ie_sys_conf_ptr scp; + bzero (&scp, sizeof(scp) ); + scp.ie_iscp_ptr = (caddr_t)IE_ISCP_ADDR; + host2ie(sc, &scp, IE_SCP_ADDR, sizeof (scp) ); + } + + /* Setup ISCP */ + { + struct ie_int_sys_conf_ptr iscp; + bzero ( &iscp, sizeof(iscp) ); + iscp.ie_busy = 1; + iscp.ie_base = (caddr_t)IE_IBASE; + iscp.ie_scb_offset = IE_SCB_OFF; + host2ie(sc, &iscp, IE_ISCP_ADDR, sizeof(iscp) ); + } + + /* Initialise the control block */ + iezero ( sc, IE_IBASE + IE_SCB_OFF, sizeof(struct ie_sys_ctl_block) ); + ieattn(sc); + + /* Wait for not busy */ + setpage ( sc, IE_ISCP_ADDR ); + for ( i=10000; --i>=0; ) { + if ( !ReadShort( sc->sc_ram + IE_COFF2POFF(IE_ISCP_ADDR) + + ( offsetof(struct ie_int_sys_conf_ptr, ie_busy)) ) ) + break; + delay (10); + } + + /* If the busy didn't go low, the i82586 is broken or too slow */ + if ( i<=0 ) + { + printf ( "ie: ether1 chipset didn't respond\n" ); + return 0; + } + + /* Ensure that the podule sends interrupts */ + for ( i=1000; --i>=0 ; ) { + if ( ReadByte(sc->sc_rom + 0) & PODULE_IRQ_PENDING ) + break; + delay (10); + } + + /* If we didn't see the interrupt then the IRQ line is broken */ + if ( i<=0 ) + { + printf ( "ie: interrupt from chipset didn't reach host\n" ); + return 0; + } + + /* Ack our little test operation */ + ie_ack(sc,IE_ST_WHENCE); + ie_cli (sc); + + /* Get second part of idrom */ + for ( i=16; i<32; i++ ) { + idrom[i] = ReadByte ( sc->sc_rom + (i<<2) ); + }; + + /* This checksum always fails. For some reason the first 16 */ + /* bytes are duplicated in the second 16 bytes, the checksum */ + /* should be at location 28 it is clearly not */ + + /* It is possible that this ether1 card is buggered */ + +#ifndef IGNORE_ETHER1_IDROM_CHECKSUM + if ( crc32(idrom,28) != *(u_long *)(idrom+28) ) + { + printf ( "ie: ether1 idrom failed checksum %08x!=%08x\n", + crc32(idrom,28), *(u_long *)(idrom+28)); + for ( i=0; i<32; i+=8 ) { + printf ( "IDROM: %02x %02x %02x %02x %02x %02x %02x %02x\n", + idrom[0+i], idrom[1+i], idrom[2+i], idrom[3+i], + idrom[4+i], idrom[5+i], idrom[6+i], idrom[7+i] ); + } + printf ( "ie: I'll ignore this fact for now!\n" ); + } +#endif + + /* Get our ethernet address. Do explicit copy */ + for ( i=0; ipa_podule_number = podule; + pa->pa_podule = &podules[podule]; + + return(1); +} + +/* + * Attach our driver to the interfaces it uses + */ + +void ieattach ( struct device *parent, struct device *self, void *aux ) +{ + struct ie_softc *sc = (void *)self; + struct podule_attach_args *pa = (void *)aux; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + + /* Check a few things about the attach args */ + sc->sc_podule_number = pa->pa_podule_number; + if (sc->sc_podule_number == -1) + panic("Podule has disappeared !"); + + sc->sc_podule = &podules[sc->sc_podule_number]; + podules[sc->sc_podule_number].attached = 1; + + /* Fill in my application form to attach to the inet system */ + + ifp->if_unit = sc->sc_dev.dv_unit; + ifp->if_name = ie_cd.cd_name; + ifp->if_start = iestart; + ifp->if_ioctl = ieioctl; + ifp->if_watchdog = iewatchdog; + ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS; + + /* Signed, dated then sent */ + if_attach (ifp); + ether_ifattach(ifp); + + /* "Hmm," said nuts, "what if the attach fails" */ + + /* Write some pretty things on the annoucement line */ + printf ( " %s using %dk card ram", + ether_sprintf(sc->sc_arpcom.ac_enaddr), + ((NRXBUF*IE_RXBUF_SIZE)+(NTXBUF*IE_TXBUF_SIZE))/1024 ); + +#if NBPFILTER > 0 + printf ( " BPF" ); + bpfattach ( &ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); +#endif + + sc->sc_ih.ih_func = ieintr; + sc->sc_ih.ih_arg = sc; + sc->sc_ih.ih_level = IPL_NET; + sc->sc_ih.ih_name = "net: ie"; + + if (irq_claim(IRQ_PODULE, &sc->sc_ih)) + { + sc->sc_irqmode = 0; + printf ( " POLLED" ); + panic("Cannot install IRQ handler\n"); + } + else + { + sc->sc_irqmode = 1; + printf ( " IRQ" ); + } + + printf ( "\n" ); +} + + +/* + * Our cfdriver structure for the autoconfig system to chew on + */ + +struct cfattach ie_ca = { + sizeof(struct ie_softc), ieprobe, ieattach +}; + +struct cfdriver ie_cd = { + NULL, "ie", DV_IFNET +}; + +/* + * Oh no!! Where's my shorts!!! I'm sure I put them on this morning + */ + +void PWriteShorts ( char *src, char *dest, int cnt ) +{ + for ( cnt/=2; --cnt>=0; ) { + PWriteShort ( dest, *(u_short *)src ); + src+=2; + dest+=4; + } +} + +void ReadShorts ( char *src, char *dest, int cnt ) +{ + for ( cnt/=2; --cnt>=0; ) { + *(u_short *)dest = ReadShort ( src ); + src+=4; + dest+=2; + } +} + +/* + * A bcopy or memcpy to adapter ram. It handles the page register for you + * so you dont have to worry about the ram windowing + */ + +static void host2ie ( struct ie_softc *sc, void *src, u_long dest, int size ) +{ + int cnt; + + if (size&1) + panic ( "host2ie" ); + + while ( size>0 ) { + cnt = IE_PAGESIZE - dest % IE_PAGESIZE; + if ( cnt > size ) + cnt = size; + setpage ( sc, dest ); + PWriteShorts ( src, (char *)sc->sc_ram + IE_COFF2POFF(dest), cnt ); + src+=cnt; + dest+=cnt; + size-=cnt; + } +} + +static void ie2host ( struct ie_softc *sc, u_long src, void *dest, int size ) +{ + int cnt; + + if (size&1) + panic ( "ie2host" ); + + while ( size>0 ) { + cnt = IE_PAGESIZE - src % IE_PAGESIZE; + if ( cnt > size ) + cnt = size; + setpage ( sc, src ); + ReadShorts ( (char *)sc->sc_ram + IE_COFF2POFF(src), dest, cnt ); + src+=cnt; + dest+=cnt; + size-=cnt; + } +} + +/* + * Like a bzero or memset 0 for adapter memory. It handles the page + * register so you dont have to worry about it + */ + +static void iezero ( struct ie_softc *sc, u_long p, int size ) +{ + int cnt; + while ( size > 0 ) { + cnt = IE_PAGESIZE - p % IE_PAGESIZE; + if ( cnt>size ) + cnt=size; + setpage(sc, p); + bzero((char *)sc->sc_ram + IE_COFF2POFF(p), 2*cnt ); + p += cnt; + size -= cnt; + } +} + +/* + * I/O Control interface to the kernel, entry point here + */ + +int ieioctl ( struct ifnet *ifp, u_long cmd, caddr_t data ) +{ + struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit]; + struct ifaddr *ifa = (struct ifaddr *)data; +/* struct ifreq *ifr = (struct ifreq *)data;*/ + int s; + int error=0; + + s=splimp(); + + switch ( cmd ) + { + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + switch ( ifa->ifa_addr->sa_family ) { +#ifdef INET + case AF_INET: + ieinit(sc); + arp_ifinit(&sc->sc_arpcom, ifa ); + break; +#endif + default: + ieinit(sc); + break; + } + break; + +#define IZSET(a,b) ((a->if_flags&b)!=0) +#define IZCLR(a,b) ((a->if_flags&b)==0) +#define DOSET(a,b) (a->if_flags|=b) +#define DOCLR(a,b) (a->if_flags&=~b) + + case SIOCSIFFLAGS: + sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI ); + + if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) ) + { + /* Interface was marked down and its running so stop it */ + iestop(sc); + DOCLR(ifp,IFF_RUNNING); + } + else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) ) + { + /* Just marked up and we're not running so start it */ + ieinit(sc); + } + else + { + /* else reset to invoke changes in other registers */ + iestop(sc); + ieinit(sc); + } + + default: + error = EINVAL; + } + (void)splx(s); + return error; +} + +/* + * Reset the card. Completely. + */ + +void iereset( struct ie_softc *sc ) +{ + struct ie_sys_ctl_block scb; + int s = splimp(); + + iestop(sc); + + ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); + + if ( command_and_wait(sc, IE_RU_ABORT|IE_CU_ABORT, 0, 0, 0, 0, 0) ) + printf ( "ie0: abort commands timed out\n" ); + + if ( command_and_wait(sc, IE_RU_DISABLE|IE_CU_STOP, 0, 0, 0, 0, 0) ) + printf ( "ie0: abort commands timed out\n" ); + + ieinit(sc); + + (void)splx(s); +} + +/* + * Watchdog entry point. This is the entry for the kernel to call us + */ + +void iewatchdog ( int unit ) +{ + struct ie_softc *sc = ie_cd.cd_devs[unit]; + + /* WOOF WOOF */ + log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname ); + ++sc->sc_arpcom.ac_if.if_oerrors; + iereset(sc); +} + +/* + * Start the time-domain-refloctometer running + */ + +static void run_tdr ( struct ie_softc *sc ) +{ + struct ie_sys_ctl_block scb; + u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb; + struct ie_tdr_cmd cmd; + int result; + + bzero ( &scb, sizeof(scb) ); + bzero ( &cmd, sizeof(cmd) ); + + cmd.com.ie_cmd_status = 0; + cmd.com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST; + cmd.com.ie_cmd_link = 0xffff; + cmd.ie_tdr_time = 0; + + scb.ie_command_list = (u_short)ptr; + + result=0; + if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd, + IE_STAT_COMPL) ) + { + result = 0x10000; + } + else if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) + { + result = 0x10000; + } + + if ( result==0 ) + result = cmd.ie_tdr_time; + + ie_ack ( sc, IE_ST_WHENCE ); + + if (result & IE_TDR_SUCCESS ) + return; + + /* Very messy. I'll tidy it later */ + + if ( result & 0x10000 ) + { + printf ( "ie: TDR command failed\n" ); + } + else if ( result & IE_TDR_XCVR ) + { + printf ( "ie: tranceiver problem. Is it plugged in?\n" ); + } + else if ( result & IE_TDR_OPEN ) + { + if ((result & IE_TDR_TIME)>0) + printf ( "ie: TDR detected an open %d clocks away.\n", + result & IE_TDR_TIME ); + } + else if ( result & IE_TDR_SHORT ) + { + if ((result & IE_TDR_TIME)>0) + printf ( "ie: TDR detected a short %d clock away.\n", + result & IE_TDR_TIME ); + } + else + { + printf ( "ie: TDR returned unknown status %x\n", result ); + } +} + +u_long setup_rfa ( struct ie_softc *sc, u_long ptr ) +{ + int i; + { + /* Receive frame descriptors */ + struct ie_recv_frame_desc rfd; + bzero( &rfd, sizeof rfd ); + for ( i=0; irframes[i] = ptr; + rfd.ie_fd_next = ptr + sizeof rfd; + host2ie(sc, (char *)&rfd, ptr, sizeof rfd); + ptr += sizeof rfd; + } + rfd.ie_fd_next = sc->rframes[0]; + rfd.ie_fd_last |= IE_FD_LAST; + host2ie(sc, (char *)&rfd, sc->rframes[NFRAMES-1], sizeof rfd ); + + ie2host(sc, sc->rframes[0], (char *)&rfd, sizeof rfd ); + rfd.ie_fd_buf_desc = (u_short) ptr; + host2ie(sc, (char *)&rfd, sc->rframes[0], sizeof rfd ); + } + + { + /* Receive frame descriptors */ + struct ie_recv_buf_desc rbd; + bzero(&rbd, sizeof rbd); + for ( i=0; irbuffs[i] = ptr; + rbd.ie_rbd_length = IE_RXBUF_SIZE; + rbd.ie_rbd_buffer = (caddr_t)(ptr + sizeof rbd); + rbd.ie_rbd_next = (u_short)(ptr + sizeof rbd + IE_RXBUF_SIZE); + host2ie(sc, &rbd, ptr, sizeof rbd); + ptr+=sizeof rbd; + + sc->cbuffs[i] = ptr; + ptr+=IE_RXBUF_SIZE; + } + rbd.ie_rbd_next = sc->rbuffs[0]; + rbd.ie_rbd_length |= IE_RBD_LAST; + host2ie(sc, &rbd, sc->rbuffs[NRXBUF-1], sizeof rbd); + } + + sc->rfhead = 0; + sc->rftail = NFRAMES-1; + sc->rbhead = 0; + sc->rbtail = NRXBUF-1; + + { + struct ie_sys_ctl_block scb; + bzero ( &scb, sizeof scb ); + scb.ie_recv_list = (u_short)sc->rframes[0]; + host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb ); + } + return ptr; +} + +static void start_receiver ( struct ie_softc *sc ) +{ + struct ie_sys_ctl_block scb; + ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); + scb.ie_recv_list = (u_short)sc->rframes[0]; + command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0); + ie_ack(sc, IE_ST_WHENCE ); +} + +/* + * Take our configuration and update all the other data structures that + * require information from the driver. + * + * CALL AT SPLIMP OR HIGHER + */ + +int ieinit ( struct ie_softc *sc ) +{ + struct ie_sys_ctl_block scb; + struct ie_config_cmd cmd; + struct ie_iasetup_cmd iasetup_cmd; + u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb; + int n; + + bzero ( &scb, sizeof(scb) ); + + /* Send the configure command */ + + cmd.com.ie_cmd_status = 0; + cmd.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST; + cmd.com.ie_cmd_link = 0xffff; + + cmd.ie_config_count = 0x0c; + cmd.ie_fifo = 8; + cmd.ie_save_bad = 0x40; + cmd.ie_addr_len = 0x2e; + cmd.ie_priority = 0; + cmd.ie_ifs = 0x60; + cmd.ie_slot_low = 0; + cmd.ie_slot_high = 0xf2; + cmd.ie_promisc = 0; /* Hey nuts, look at this! */ + cmd.ie_crs_cdt = 0; + cmd.ie_min_len = 64; + cmd.ie_junk = 0xff; + + scb.ie_command_list = (u_short)ptr; + + if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd, + IE_STAT_COMPL) ) + { + printf ( "%s: command failed: timeout\n", sc->sc_dev.dv_xname ); + return 0; + } + + if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) + { + printf ( "%s: command failed: !IE_STAT_OK\n", sc->sc_dev.dv_xname ); + return 0; + } + + /* Individual address setup command */ + + iasetup_cmd.com.ie_cmd_status = 0; + iasetup_cmd.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST; + iasetup_cmd.com.ie_cmd_link = 0xffff; + + bcopy ( sc->sc_arpcom.ac_enaddr, (caddr_t) &iasetup_cmd.ie_address, + sizeof (iasetup_cmd.ie_address) ); + + if ( command_and_wait(sc, IE_CU_START, &scb, &iasetup_cmd, ptr, sizeof cmd, + IE_STAT_COMPL) ) + { + printf ( "%s: iasetup failed : timeout\n", sc->sc_dev.dv_xname ); + return 0; + } + + if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) + { + printf ( "%s: iasetup failed : !IE_STAT_OK\n", sc->sc_dev.dv_xname ); + return 0; + } + + ie_ack ( sc, IE_ST_WHENCE ); + + /* Run the time-domain refloctometer */ + run_tdr ( sc ); + + ie_ack ( sc, IE_ST_WHENCE ); + + /* meminit */ + ptr = setup_rfa(sc, ptr); + + sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING; + sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; + + /* Setup transmit buffers */ + + for ( n=0; nxmit_cmds[n] = ptr; + iezero(sc, ptr, sizeof(struct ie_xmit_cmd) ); + ptr += sizeof(struct ie_xmit_cmd); + + sc->xmit_buffs[n] = ptr; + iezero(sc, ptr, sizeof(struct ie_xmit_buf)); + ptr += sizeof(struct ie_xmit_buf); + } + + for ( n=0; nxmit_cbuffs[n] = ptr; + ptr += IE_TXBUF_SIZE; + } + + sc->xmit_free = NTXBUF; + sc->xchead = sc->xctail = 0; + + { + struct ie_xmit_cmd xmcmd; + bzero ( &xmcmd, sizeof xmcmd ); + xmcmd.ie_xmit_status = IE_STAT_COMPL; + host2ie(sc, &xmcmd, sc->xmit_cmds[0], sizeof xmcmd); + } + + start_receiver (sc); + + return 0; +} + +int iestop ( struct ie_softc *sc ) +{ + struct ie_sys_ctl_block scb; + int s = splimp(); + + ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); + + if ( command_and_wait(sc, IE_RU_DISABLE, &scb, 0, 0, 0, 0) ) + printf ( "ie0: abort commands timed out\n" ); + + (void)splx(s); + return(0); +} + +/* + * Send a command to the card and awaits it's completion. + * Timeout if it's taking too long + */ + +/*CAW*/ + +static int command_and_wait ( struct ie_softc *sc, u_short cmd, + struct ie_sys_ctl_block *pscb, + void *pcmd, int ocmd, int scmd, int mask ) +{ + int i=0; + + /* Copy the command to the card */ + + if ( pcmd ) + host2ie(sc, pcmd, ocmd, scmd); /* transfer the command to the card */ + + /* Copy the scb to the card */ + + if ( pscb ) { + pscb->ie_command = cmd; + host2ie(sc, pscb, IE_IBASE + IE_SCB_OFF, sizeof *pscb); + } + else + { + setpage ( sc, IE_IBASE + IE_SCB_OFF ); + PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + + (offsetof(struct ie_sys_ctl_block, ie_command)), cmd ); + } + + /* Prod the card to act on the newly loaded command */ + ieattn(sc); + + /* Wait for the command to complete */ + if ( IE_ACTION_COMMAND(cmd) && pcmd ) + { + setpage(sc,ocmd); + for ( i=4000; --i>=0; ) { + if ( ReadShort(sc->sc_ram + IE_COFF2POFF(ocmd) + + (offsetof(struct ie_config_cmd, ie_config_status))) & mask) + break; + delay(100); + } + } + else + { + for ( i=4000; --i>=0; ) { + if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + + (offsetof(struct ie_sys_ctl_block, ie_command))) ) + break; + delay(100); + } + } + + /* Update the host structures to reflect the state on the card */ + if ( pscb ) + ie2host(sc, IE_IBASE + IE_SCB_OFF, pscb, sizeof *pscb ); + if ( pcmd ) + ie2host(sc, ocmd, pcmd, scmd); + + return i < 0; +} + +#define READ_MEMBER(sc,type,member,ptr,dest) \ + setpage(sc, ptr); \ + dest = ReadShort(sc->sc_ram + IE_COFF2POFF(ptr) + \ + (offsetof(type, member)) ); + +#define WRITE_MEMBER(sc,type,member,ptr,dest) \ + setpage(sc, ptr); \ + PWriteShort(sc->sc_ram + IE_COFF2POFF(ptr) + \ + (offsetof(type, member)), dest ); + +static inline int ie_buflen ( struct ie_softc *sc, int head ) +{ + int actual; + READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, + sc->rbuffs[head], actual ); + + return ( actual & ( IE_RXBUF_SIZE | ( IE_RXBUF_SIZE-1 ) ) ) ; +} + +static inline int ie_packet_len ( struct ie_softc *sc ) +{ + int i; + int actual; + int head = sc->rbhead; + int acc=0; + + do { + READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, + sc->rbuffs[sc->rbhead], actual ); + if (!(actual&IE_RBD_USED)) + { + return (-1); + } + + READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, + sc->rbuffs[head], i ); + i = i & IE_RBD_LAST; + + acc += ie_buflen(sc, head); + head = (head+1) % NRXBUF; + } while (!i); + + return acc; +} + +struct mbuf *ieget(struct ie_softc *sc, struct ether_header *ehp, int *to_bpf ) +{ + struct mbuf *top, **mp, *m; + int head; + int resid, totlen, thisrboff, thismboff; + int len; + + totlen = ie_packet_len(sc); + + if ( totlen > ETHER_MAX_LEN ) + { + printf ( "ie: Gosh that packet was s-o-o-o big.\n" ); + return 0; + } + + if ( totlen<=0 ) + return 0; + + head = sc->rbhead; + + /* Read the ethernet header */ + ie2host ( sc, sc->cbuffs[head], (caddr_t)ehp, sizeof *ehp ); + + /* Check if the packet is for us */ + + resid = totlen -= (thisrboff = sizeof *ehp); + + MGETHDR ( m, M_DONTWAIT, MT_DATA ); + if ( m==0 ) + return 0; + + m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if; + m->m_pkthdr.len = totlen; + len = MHLEN; + top = 0; + mp = ⊤ + + /* + * This loop goes through and allocates mbufs for all the data we will + * be copying in. It does not actually do the copying yet. + */ + while (totlen > 0) { + if (top) { + MGET(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + m_freem(top); + return 0; + } + len = MLEN; + } + if (totlen >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if (m->m_flags & M_EXT) + len = MCLBYTES; + } + m->m_len = len = min(totlen, len); + totlen -= len; + *mp = m; + mp = &m->m_next; + } + + m = top; + thismboff = 0; + + /* + * Now we take the mbuf chain (hopefully only one mbuf most of the + * time) and stuff the data into it. There are no possible failures at + * or after this point. + */ + while (resid > 0) { + int thisrblen = ie_buflen(sc, head) - thisrboff, + thismblen = m->m_len - thismboff; + len = min(thisrblen, thismblen); + +/* bcopy((caddr_t)(sc->cbuffs[head] + thisrboff), + mtod(m, caddr_t) + thismboff, (u_int)len); */ + + + if ( len&1 ) + { + ie2host(sc, sc->cbuffs[head]+thisrboff, + mtod(m, caddr_t) + thismboff, (u_int)len+1); + } + else + { + ie2host(sc, sc->cbuffs[head]+thisrboff, + mtod(m, caddr_t) + thismboff, (u_int)len); + } + + resid -= len; + + if (len == thismblen) { + m = m->m_next; + thismboff = 0; + } else + thismboff += len; + + if (len == thisrblen) { + head = (head + 1) % NRXBUF; + thisrboff = 0; + } else + thisrboff += len; + } + + + return top; +} + +void ie_drop_packet_buffer ( struct ie_softc *sc ) +{ + int i, actual, last; + + do { + READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, + sc->rbuffs[sc->rbhead], actual ); + if (!(actual&IE_RBD_USED)) + { + iereset(sc); + return; + } + + i = actual & IE_RBD_LAST; + + READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, + sc->rbuffs[sc->rbhead], last ); + last |= IE_RBD_LAST; + WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, + sc->rbuffs[sc->rbhead], last ); + + WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_actual, + sc->rbuffs[sc->rbhead], 0 ); + + sc->rbhead = ( sc->rbhead + 1 ) % NRXBUF; + + READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, + sc->rbuffs[sc->rbtail], last ); + last &= ~IE_RBD_LAST; + WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, + sc->rbuffs[sc->rbtail], last ); + + sc->rbtail = ( sc->rbtail + 1 ) % NRXBUF; + } while (!i); +} + +void ie_read_frame ( struct ie_softc *sc, int num ) +{ + int status; + struct ie_recv_frame_desc rfd; + struct mbuf *m=0; + struct ether_header eh; + int last; + + ie2host(sc, sc->rframes[num], &rfd, sizeof rfd ); + status = rfd.ie_fd_status; + + /* Advance the RFD list, since we're done with this descriptor */ + + WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status, + sc->rframes[num], 0 ); + + READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, + sc->rframes[num], last ); + last |= IE_FD_LAST; + WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, + sc->rframes[num], last ); + + READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, + sc->rframes[sc->rftail], last ); + last &= ~IE_FD_LAST; + WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, + sc->rframes[sc->rftail], last ); + + sc->rftail = ( sc->rftail + 1 ) % NFRAMES; + sc->rfhead = ( sc->rfhead + 1 ) % NFRAMES; + + if ( status & IE_FD_OK ) { + m = ieget(sc, &eh, 0); + ie_drop_packet_buffer(sc); + } + + if ( m==0 ) { + sc->sc_arpcom.ac_if.if_ierrors++; + return; + } + +/* + printf ( "%s: frame from ether %s type %x\n", sc->sc_dev.dv_xname, + ether_sprintf(eh.ether_shost), (u_int)eh.ether_type ); +*/ + +#if NBFILTER > 0 + if ( sc->sc_arpcom.ac_if.if_bpf ) { + bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m ); + }; +#endif + + ether_input ( &sc->sc_arpcom.ac_if, &eh, m ); + sc->sc_arpcom.ac_if.if_ipackets++; +} + +void ierint ( struct ie_softc *sc ) +{ + int i; + int times_thru = 1024; + struct ie_sys_ctl_block scb; + int status; + int saftey_catch = 0; + + i = sc->rfhead; + for (;;) { + + if ( (saftey_catch++)>100 ) + { + printf ( "ie: ierint saftey catch tripped\n" ); + iereset(sc); + return; + } + + READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status, + sc->rframes[i],status); + + if ((status&IE_FD_COMPLETE)&&(status&IE_FD_OK)) { + if ( !--times_thru ) { + printf ( "IERINT: Uh oh. Nuts, look at this bit!!!\n" ); + ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); + sc->sc_arpcom.ac_if.if_ierrors += scb.ie_err_crc + + scb.ie_err_align + + scb.ie_err_resource + + scb.ie_err_overrun; + scb.ie_err_crc = scb.ie_err_align = 0; + scb.ie_err_resource = scb.ie_err_overrun = 0; + host2ie(sc, &scb, IE_SCP_ADDR, sizeof (scb) ); + } + ie_read_frame(sc, i); + } else { + ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); + + if ( ((status&IE_FD_RNR)!=0) && ((scb.ie_status&IE_RU_READY)==0) ) + { + WRITE_MEMBER(sc,struct ie_recv_frame_desc, ie_fd_buf_desc, + sc->rframes[0], sc->rbuffs[0] ); + + scb.ie_recv_list = sc->rframes[0]; + host2ie(sc, (char *)&scb, IE_IBASE + IE_SCB_OFF, sizeof (scb) ); + command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0); + } + break; + } + i = (i + 1) % NFRAMES; + } +} + +static int in_intr = 0; + +int ieintr ( void *arg ) +{ + struct ie_softc *sc = arg; + u_short status; + int saftey_catch = 0; + static saftey_net = 0; + + if ( in_intr==1 ) + { + panic ( "ie: INTERRUPT REENTERED\n" ); + } + + /* Clear the interrrupt */ + ie_cli (sc); + + setpage(sc, IE_IBASE + IE_SCB_OFF ); + status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + + (offsetof(struct ie_sys_ctl_block, ie_status)) ); + + status = status & IE_ST_WHENCE; + + if ( status==0 ) + { + in_intr = 0; + return 0; + } + +loop: + + ie_ack(sc, status); + + if (status & (IE_ST_FR | IE_ST_RNR)) { + ierint(sc); + } + + if (status & IE_ST_CX) { + ietint(sc); + } + + if (status & IE_ST_RNR) { + printf ( "ie: receiver not ready\n" ); + sc->sc_arpcom.ac_if.if_ierrors++; + iereset(sc); + } + + setpage(sc, IE_IBASE + IE_SCB_OFF ); + status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + + (offsetof(struct ie_sys_ctl_block, ie_status)) ); + status = status & IE_ST_WHENCE; + + ie_cli(sc); + + if ( status==0 ) + { + in_intr = 0; + return 1; + } + + /* This is prehaps a little over cautious */ + if ( saftey_catch++ > 10 ) + { + printf ( "ie: Interrupt couldn't be cleared\n" ); + delay ( 1000 ); + ie_cli(sc); + if ( saftey_net++ > 50 ) + { + printf ( "ie: saftey net catches driver, shutting down\n" ); + disable_irq ( IRQ_PODULE ); + } + in_intr = 0; + return 1; + } + + goto loop; +} + +void iexmit ( struct ie_softc *sc ) +{ +/* int actual;*/ + struct ie_sys_ctl_block scb; + + struct ie_xmit_cmd xc; + struct ie_xmit_buf xb; + + ie2host(sc, sc->xmit_buffs[sc->xctail], (char *)&xb, sizeof xb ); + xb.ie_xmit_flags |= IE_XMIT_LAST; + xb.ie_xmit_next = 0xffff; + xb.ie_xmit_buf = (caddr_t)sc->xmit_cbuffs[sc->xctail]; + host2ie(sc, &xb, sc->xmit_buffs[sc->xctail], sizeof xb ); + + bzero ( &xc, sizeof xc ); + xc.com.ie_cmd_link = 0xffff; + xc.com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST; + xc.ie_xmit_status = 0x0000; + xc.ie_xmit_desc = sc->xmit_buffs[sc->xctail]; + host2ie(sc, (char *)&xc, sc->xmit_cmds[sc->xctail], sizeof xc ); + + ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); + scb.ie_command_list = sc->xmit_cmds[sc->xctail]; + host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb ); + + command_and_wait(sc, IE_CU_START, &scb, &xc, sc->xmit_cmds[sc->xctail] + , sizeof xc, IE_STAT_COMPL); + + sc->sc_arpcom.ac_if.if_timer = 5; +} +/* + * Start sending all the queued buffers. + */ + +void iestart( struct ifnet *ifp ) +{ + struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit]; + struct mbuf *m0, *m; + u_char *buffer; + u_short len; + char txbuf[IE_TXBUF_SIZE]; + int saftey_catch = 0; + + if ((ifp->if_flags & IFF_OACTIVE) != 0) + return; + + for (;;) { + if ( (saftey_catch++)>100 ) + { + printf ( "ie: iestart saftey catch tripped\n" ); + iereset(sc); + return; + } + if (sc->xmit_free == 0) { + ifp->if_flags |= IFF_OACTIVE; + break; + } + + IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m); + if (!m) + break; + + /* TODO: Write directly to the card */ + len = 0; + /* buffer = sc->xmit_cbuffs[sc->xchead]; */ + buffer = txbuf; + + for (m0 = m; m && (len + m->m_len) < IE_TXBUF_SIZE; + m = m->m_next) { + bcopy(mtod(m, caddr_t), buffer, m->m_len); + buffer += m->m_len; + len += m->m_len; + } + + m_freem(m0); + len = max(len, ETHER_MIN_LEN); + +#if NBPFILTER > 0 + if ( sc->sc_arpcom.ac_if.if_bpf ) + bpf_tap(sc->sc_arpcom.ac_if.if_bpf, txbuf, len); +#endif + + /* When we write directly to the card we dont need this */ + if (len&1) + host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len+1 ); + else + host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len ); + + /* sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len; */ + + WRITE_MEMBER(sc,struct ie_xmit_buf, ie_xmit_flags, + sc->xmit_buffs[sc->xchead], len) + + /* Start the first packet transmitting. */ + if (sc->xmit_free == NTXBUF) + iexmit(sc); + + sc->xchead = (sc->xchead + 1) % NTXBUF; + sc->xmit_free--; + } +} + +void ietint ( struct ie_softc *sc ) +{ + struct ifnet *ifp = &sc->sc_arpcom.ac_if; + + int status; + + ifp->if_timer=0; + ifp->if_flags &= ~IFF_OACTIVE; + + READ_MEMBER(sc,struct ie_xmit_cmd, ie_xmit_status, + sc->xmit_cmds[sc->xctail], status ); + + if (!(status&IE_STAT_COMPL) || (status & IE_STAT_BUSY) ) + printf ( "ietint: command still busy!\n" ); + + if ( status & IE_STAT_OK ) { + ifp->if_opackets++; + ifp->if_collisions += status & IE_XS_MAXCOLL; + } else { + ifp->if_oerrors++; + if ( status & IE_STAT_ABORT ) + printf ( "ie: send aborted\n" ); + if ( status & IE_XS_LATECOLL ) + printf ( "ie: late collision\n" ); + if ( status & IE_XS_NOCARRIER ) + printf ( "ie: no carrier\n" ); + if ( status & IE_XS_LOSTCTS ) + printf ( "ie: lost CTS\n" ); + if ( status & IE_XS_UNDERRUN ) + printf ( "ie: DMA underrun\n" ); + if ( status & IE_XS_EXCMAX ) + printf ( "ie: too many collisions\n" ); + ifp->if_collisions+=16; + } + /* Done with the buffer */ + sc->xmit_free++; + sc->xctail = (sc->xctail + 1 ) % NTXBUF; + + /* Start the next packet transmitting, if any */ + if ( sc->xmit_free diff --git a/sys/arch/arm32/podulebus/ncr5380reg.h b/sys/arch/arm32/podulebus/ncr5380reg.h new file mode 100644 index 00000000000..04b181d0db5 --- /dev/null +++ b/sys/arch/arm32/podulebus/ncr5380reg.h @@ -0,0 +1,160 @@ +/* $NetBSD: ncr5380reg.h,v 1.1 1996/01/31 23:26:04 mark Exp $ */ + +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989 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 + * 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. + */ +/* + * HISTORY (mach3) + * Revision 2.3 91/08/24 12:25:10 af + * Moved padding of regmap in impl file. + * [91/08/02 04:22:39 af] + * + * Revision 2.2 91/06/19 16:28:35 rvb + * From the NCR data sheets + * "NCR 5380 Family, SCSI Protocol Controller Data Manual" + * NCR Microelectronics Division, Colorado Spring, 6/98 T01891L + * [91/04/21 af] + * + */ + +/* + * File: scsi_5380.h + * Author: Alessandro Forin, Carnegie Mellon University + * Date: 5/91 + * + * Defines for the NCR 5380 (SCSI chip), aka Am5380 + */ + +/* + * Register map: Note not declared here anymore! + * All the 5380 registers are accessed through individual + * pointers initialized by MD code. This allows the 5380 + * MI functions to be shared between MD drivers that have + * different padding between the registers (i.e. amiga). + */ +#if 0 /* example only */ +struct ncr5380regs { + volatile u_char sci_r0; + volatile u_char sci_r1; + volatile u_char sci_r2; + volatile u_char sci_r3; + volatile u_char sci_r4; + volatile u_char sci_r5; + volatile u_char sci_r6; + volatile u_char sci_r7; +}; +#endif + +/* + * Machine-independent code uses these names: + */ +#define sci_data sci_r0 /* r: Current data */ +#define sci_odata sci_r0 /* w: Out data */ + +#define sci_icmd sci_r1 /* rw: Initiator command */ +#define sci_mode sci_r2 /* rw: Mode */ +#define sci_tcmd sci_r3 /* rw: Target command */ + +#define sci_bus_csr sci_r4 /* r: Bus Status */ +#define sci_sel_enb sci_r4 /* w: Select enable */ + +#define sci_csr sci_r5 /* r: Status */ +#define sci_dma_send sci_r5 /* w: Start dma send data */ + +#define sci_idata sci_r6 /* r: Input data */ +#define sci_trecv sci_r6 /* w: Start dma receive, target */ + +#define sci_iack sci_r7 /* r: Interrupt Acknowledge */ +#define sci_irecv sci_r7 /* w: Start dma receive, initiator */ + + +/* + * R1: Initiator command register + */ +#define SCI_ICMD_DATA 0x01 /* rw: Assert data bus */ +#define SCI_ICMD_ATN 0x02 /* rw: Assert ATN signal */ +#define SCI_ICMD_SEL 0x04 /* rw: Assert SEL signal */ +#define SCI_ICMD_BSY 0x08 /* rw: Assert BSY signal */ +#define SCI_ICMD_ACK 0x10 /* rw: Assert ACK signal */ +#define SCI_ICMD_LST 0x20 /* r: Lost arbitration */ +#define SCI_ICMD_DIFF SCI_ICMD_LST /* w: Differential cable */ +#define SCI_ICMD_AIP 0x40 /* r: Arbitration in progress */ +#define SCI_ICMD_TEST SCI_ICMD_AIP /* w: Test mode */ +#define SCI_ICMD_RST 0x80 /* rw: Assert RST signal */ +/* Bits to keep when doing read/modify/write (leave out RST) */ +#define SCI_ICMD_RMASK 0x1F + + +/* + * R2: Mode register + */ +#define SCI_MODE_ARB 0x01 /* rw: Start arbitration */ +#define SCI_MODE_DMA 0x02 /* rw: Enable DMA xfers */ +#define SCI_MODE_MONBSY 0x04 /* rw: Monitor BSY signal */ +#define SCI_MODE_DMA_IE 0x08 /* rw: Enable DMA complete interrupt */ +#define SCI_MODE_PERR_IE 0x10 /* rw: Interrupt on parity errors */ +#define SCI_MODE_PAR_CHK 0x20 /* rw: Check parity */ +#define SCI_MODE_TARGET 0x40 /* rw: Target mode (Initiator if 0) */ +#define SCI_MODE_BLOCKDMA 0x80 /* rw: Block-mode DMA handshake */ + + +/* + * R3: Target command register + */ +#define SCI_TCMD_IO 0x01 /* rw: Assert I/O signal */ +#define SCI_TCMD_CD 0x02 /* rw: Assert C/D signal */ +#define SCI_TCMD_MSG 0x04 /* rw: Assert MSG signal */ +#define SCI_TCMD_PHASE_MASK 0x07 /* r: Mask for current bus phase */ +#define SCI_TCMD_REQ 0x08 /* rw: Assert REQ signal */ +#define SCI_TCMD_LAST_SENT 0x80 /* ro: Last byte was xferred + * (not on 5380/1) */ + +#define SCI_TCMD_PHASE(x) ((x) & 0x7) + +/* + * R4: Current (SCSI) Bus status (.sci_bus_csr) + */ +#define SCI_BUS_DBP 0x01 /* r: Data Bus parity */ +#define SCI_BUS_SEL 0x02 /* r: SEL signal */ +#define SCI_BUS_IO 0x04 /* r: I/O signal */ +#define SCI_BUS_CD 0x08 /* r: C/D signal */ +#define SCI_BUS_MSG 0x10 /* r: MSG signal */ +#define SCI_BUS_REQ 0x20 /* r: REQ signal */ +#define SCI_BUS_BSY 0x40 /* r: BSY signal */ +#define SCI_BUS_RST 0x80 /* r: RST signal */ + +#define SCI_BUS_PHASE(x) (((x) >> 2) & 7) + +/* + * R5: Bus and Status register (.sci_csr) + */ +#define SCI_CSR_ACK 0x01 /* r: ACK signal */ +#define SCI_CSR_ATN 0x02 /* r: ATN signal */ +#define SCI_CSR_DISC 0x04 /* r: Disconnected (BSY==0) */ +#define SCI_CSR_PHASE_MATCH 0x08 /* r: Bus and SCI_TCMD match */ +#define SCI_CSR_INT 0x10 /* r: Interrupt request */ +#define SCI_CSR_PERR 0x20 /* r: Parity error */ +#define SCI_CSR_DREQ 0x40 /* r: DMA request */ +#define SCI_CSR_DONE 0x80 /* r: DMA count is zero */ diff --git a/sys/arch/arm32/podulebus/ncr5380sbc.c b/sys/arch/arm32/podulebus/ncr5380sbc.c new file mode 100644 index 00000000000..9758419156e --- /dev/null +++ b/sys/arch/arm32/podulebus/ncr5380sbc.c @@ -0,0 +1,2591 @@ +/* $NetBSD: ncr5380sbc.c,v 1.2 1996/03/27 22:05:19 mark Exp $ */ + +/* + * Copyright (c) 1996 Melvin Tang-Richardson (Modified for weird regs) + * Copyright (c) 1995 David Jones, Gordon W. Ross + * Copyright (c) 1994 Jarle Greipsland + * 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 authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 4. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by + * David Jones and Gordon Ross + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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. + */ + +#undef DIAGNOSTIC + +/* + * This is a machine-independent driver for the NCR5380 + * SCSI Bus Controller (SBC), also known as the Am5380. + * + * This code should work with any memory-mapped 5380, + * and can be shared by multiple adapters that address + * the 5380 with different register offset spacings. + * (This can happen on the atari, for example.) + * For porting/design info. see: ncr5380.doc + * + * Credits, history: + * + * David Jones is the author of most of the code that now + * appears in this file, and was the architect of the + * current overall structure (MI/MD code separation, etc.) + * + * Gordon Ross integrated the message phase code, added lots of + * comments about what happens when and why (re. SCSI spec.), + * debugged some reentrance problems, and added several new + * "hooks" needed for the Sun3 "si" adapters. + * + * The message in/out code was taken nearly verbatim from + * the aic6360 driver by Jarle Greipsland. + * + * Several other NCR5380 drivers were used for reference + * while developing this driver, including work by: + * The Alice Group (mac68k port) namely: + * Allen K. Briggs, Chris P. Caputo, Michael L. Finch, + * Bradley A. Grantham, and Lawrence A. Kesteloot + * Michael L. Hitch (amiga drivers: sci.c) + * Leo Weppelman (atari driver: ncr5380.c) + * There are others too. Thanks, everyone. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DEBUG XXX + +#define SetReg(l,d) *((volatile unsigned int *)((void *)l))=((d)|(((d)<<16))) + +#if 0 /* XXX - not yet... */ +#include +#include +#else +#include "ncr5380reg.h" +#include "ncr5380var.h" +#endif + +static int ncr5380_wait_req __P((struct ncr5380_softc *)); +static int ncr5380_wait_not_req __P((struct ncr5380_softc *)); + +static void ncr5380_sched __P((struct ncr5380_softc *)); +static void ncr5380_done __P((struct ncr5380_softc *)); + +static int ncr5380_select + __P((struct ncr5380_softc *, struct sci_req *)); +static void ncr5380_reselect __P((struct ncr5380_softc *)); + +static int ncr5380_msg_in __P((struct ncr5380_softc *)); +static int ncr5380_msg_out __P((struct ncr5380_softc *)); +static int ncr5380_data_xfer __P((struct ncr5380_softc *, int)); +static int ncr5380_command __P((struct ncr5380_softc *)); +static int ncr5380_status __P((struct ncr5380_softc *)); +static void ncr5380_machine __P((struct ncr5380_softc *)); + +/* + * Action flags returned by the info_tranfer functions: + * (These determine what happens next.) + */ +#define ACT_CONTINUE 0x00 /* No flags: expect another phase */ +#define ACT_DISCONNECT 0x01 /* Target is disconnecting */ +#define ACT_CMD_DONE 0x02 /* Need to call scsi_done() */ +#define ACT_RESET_BUS 0x04 /* Need bus reset (cmd timeout) */ +#define ACT_WAIT_DMA 0x10 /* Wait for DMA to complete */ + +/***************************************************************** + * Debugging stuff + *****************************************************************/ + +#ifndef DDB +/* This is used only in recoverable places. */ +#define Debugger() printf("Debug: ncr5380.c:%d\n", __LINE__) +#endif + +#ifdef DEBUG + +#define NCR_DBG_BREAK 1 +#define NCR_DBG_CMDS 2 +int ncr5380_debug = NCR_DBG_BREAK; +#define NCR_BREAK() \ + do { if (ncr5380_debug & NCR_DBG_BREAK) Debugger(); } while (0) +static void ncr5380_show_scsi_cmd __P((struct scsi_xfer *)); +static void ncr5380_show_sense __P((struct scsi_xfer *)); +#else /* DEBUG */ +#define NCR_BREAK() /* nada */ +#define ncr5380_show_scsi_cmd(xs) /* nada */ +#define ncr5380_show_sense(xs) /* nada */ +#endif /* DEBUG */ + +static char * +phase_names[8] = { + "DATA_OUT", + "DATA_IN", + "COMMAND", + "STATUS", + "UNSPEC1", + "UNSPEC2", + "MSG_OUT", + "MSG_IN", +}; + +/***************************************************************** + * Actual chip control + *****************************************************************/ + +/* + * XXX: These timeouts might need to be tuned... + */ + +/* This one is used when waiting for a phase change. (X100uS.) */ +int ncr5380_wait_phase_timo = 1000 * 10 * 300; /* 5 min. */ + +/* These are used in the following inline functions. */ +int ncr5380_wait_req_timo = 1000 * 50; /* X2 = 100 mS. */ +int ncr5380_wait_nrq_timo = 1000 * 25; /* X2 = 50 mS. */ + +/* Return zero on success. */ +static __inline__ int ncr5380_wait_req(sc) + struct ncr5380_softc *sc; +{ + register int timo = ncr5380_wait_req_timo; + for (;;) { + if (*sc->sci_bus_csr & SCI_BUS_REQ) { + timo = 0; /* return 0 */ + break; + } + if (--timo < 0) + break; /* return -1 */ + delay(2); + } + return (timo); +} + +/* Return zero on success. */ +static __inline__ int ncr5380_wait_not_req(sc) + struct ncr5380_softc *sc; +{ + register int timo = ncr5380_wait_nrq_timo; + for (;;) { + if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) { + timo = 0; /* return 0 */ + break; + } + if (--timo < 0) + break; /* return -1 */ + delay(2); + } + return (timo); +} + +/* Ask the target for a MSG_OUT phase. */ +static __inline__ void +ncr_sched_msgout(sc, msg_code) + struct ncr5380_softc *sc; + int msg_code; +{ + /* First time, raise ATN line. */ + if (sc->sc_msgpriq == 0) { + register u_char icmd; + icmd = *sc->sci_icmd & SCI_ICMD_RMASK; + SetReg ( sc->sci_icmd, icmd | SCI_ICMD_ATN ); +/* *sc->sci_icmd = icmd | SCI_ICMD_ATN; */ + delay(2); + } + sc->sc_msgpriq |= msg_code; +} + + +int +ncr5380_pio_out(sc, phase, count, data) + struct ncr5380_softc *sc; + int phase, count; + unsigned char *data; +{ + register u_char icmd; + register int resid; + register int error; + + icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK; + + icmd |= SCI_ICMD_DATA; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + resid = count; + while (resid > 0) { + if (!SCI_BUSY(sc)) { + NCR_TRACE("pio_out: lost BSY, resid=%d\n", resid); + break; + } + if (ncr5380_wait_req(sc)) { + NCR_TRACE("pio_out: no REQ, resid=%d\n", resid); + break; + } + if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase) + break; + + /* Put the data on the bus. */ + SetReg ( sc->sci_odata, *data ); data++; +/* *sc->sci_odata = *data++; */ + + /* Tell the target it's there. */ + icmd |= SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + /* Wait for target to get it. */ + error = ncr5380_wait_not_req(sc); + + /* OK, it's got it (or we gave up waiting). */ + icmd &= ~SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + if (error) { + NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid); + break; + } + + --resid; + } + + /* Stop driving the data bus. */ + icmd &= ~SCI_ICMD_DATA; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + return (count - resid); +} + + +int +ncr5380_pio_in(sc, phase, count, data) + struct ncr5380_softc *sc; + int phase, count; + unsigned char *data; +{ + register u_char icmd; + register int resid; + register int error; + + icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK; + + resid = count; + while (resid > 0) { + if (!SCI_BUSY(sc)) { + NCR_TRACE("pio_in: lost BSY, resid=%d\n", resid); + break; + } + if (ncr5380_wait_req(sc)) { + NCR_TRACE("pio_in: no REQ, resid=%d\n", resid); + break; + } + /* A phase change is not valid until AFTER REQ rises! */ + if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase) + break; + + /* Read the data bus. */ + *data++ = *sc->sci_data; + + /* Tell target we got it. */ + icmd |= SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + /* Wait for target to drop REQ... */ + error = ncr5380_wait_not_req(sc); + + /* OK, we can drop ACK. */ + icmd &= ~SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + if (error) { + NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid); + break; + } + + --resid; + } + + return (count - resid); +} + + +void +ncr5380_init(sc) + struct ncr5380_softc *sc; +{ + int i, j; + +#ifdef DEBUG + ncr5380_debug_sc = sc; +#endif + + for (i = 0; i < SCI_OPENINGS; i++) + sc->sc_ring[i].sr_xs = NULL; + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + sc->sc_matrix[i][j] = NULL; + + sc->sc_link.openings = 2; /* XXX - Not SCI_OPENINGS */ + sc->sc_prevphase = PHASE_INVALID; + sc->sc_state = NCR_IDLE; + + SetReg ( sc->sci_tcmd, PHASE_INVALID ); + SetReg ( sc->sci_icmd, 0 ); + SetReg ( sc->sci_mode, 0 ); + SetReg ( sc->sci_sel_enb, 0 ); + +/* *sc->sci_tcmd = PHASE_INVALID; + *sc->sci_icmd = 0; + *sc->sci_mode = 0; + *sc->sci_sel_enb = 0; */ + SCI_CLR_INTR(sc); + + /* XXX: Enable reselect interrupts... */ + SetReg ( sc->sci_sel_enb, 0x80 ); +/* *sc->sci_sel_enb = 0x80; */ + + /* Another hack (Er.. hook!) for the sun3 si: */ + if (sc->sc_intr_on) { + NCR_TRACE("init: intr ON\n", 0); + sc->sc_intr_on(sc); + } +} + + +void +ncr5380_reset_scsibus(sc) + struct ncr5380_softc *sc; +{ + + NCR_TRACE("reset_scsibus, cur=0x%x\n", + (long) sc->sc_current); + + SetReg ( sc->sci_icmd, SCI_ICMD_RST ); +/* *sc->sci_icmd = SCI_ICMD_RST; */ + delay(500); + SetReg ( sc->sci_icmd, 0 ); +/* *sc->sci_icmd = 0; */ + + SetReg ( sc->sci_mode, 0 ); + SetReg ( sc->sci_tcmd, PHASE_INVALID ); + +/* *sc->sci_mode = 0; + *sc->sci_tcmd = PHASE_INVALID; */ + + SCI_CLR_INTR(sc); + /* XXX - Need long delay here! */ + delay(100000); + + /* XXX - Need to cancel disconnected requests. */ +} + + +/* + * Interrupt handler for the SCSI Bus Controller (SBC) + * This may also called for a DMA timeout (at splbio). + */ +int +ncr5380_intr(sc) + struct ncr5380_softc *sc; +{ + int claimed = 0; + + /* + * Do not touch SBC regs here unless sc_current == NULL + * or it will complain about "register conflict" errors. + * Instead, just let ncr5380_machine() deal with it. + */ + NCR_TRACE("intr: top, state=%d\n", sc->sc_state); + + if (sc->sc_state == NCR_IDLE) { + /* + * Might be reselect. ncr5380_reselect() will check, + * and set up the connection if so. This will verify + * that sc_current == NULL at the beginning... + */ + + /* Another hack (Er.. hook!) for the sun3 si: */ + if (sc->sc_intr_off) { + NCR_TRACE("intr: for reselect, intr off\n", 0); + sc->sc_intr_off(sc); + } + + ncr5380_reselect(sc); + } + + /* + * The remaining documented interrupt causes are phase mismatch and + * disconnect. In addition, the sunsi controller may produce a state + * where SCI_CSR_DONE is false, yet DMA is complete. + * + * The procedure in all these cases is to let ncr5380_machine() + * figure out what to do next. + */ + if (sc->sc_state & NCR_WORKING) { + NCR_TRACE("intr: call machine, cur=0x%x\n", + (long) sc->sc_current); + /* This will usually free-up the nexus. */ + ncr5380_machine(sc); + NCR_TRACE("intr: machine done, cur=0x%x\n", + (long) sc->sc_current); + claimed = 1; + } + + /* Maybe we can run some commands now... */ + if (sc->sc_state == NCR_IDLE) { + NCR_TRACE("intr: call sched, cur=0x%x\n", + (long) sc->sc_current); + ncr5380_sched(sc); + NCR_TRACE("intr: sched done, cur=0x%x\n", + (long) sc->sc_current); + } + + return claimed; +} + + +/* + * Abort the current command (i.e. due to timeout) + */ +void +ncr5380_abort(sc) + struct ncr5380_softc *sc; +{ + + /* + * Finish it now. If DMA is in progress, we + * can not call ncr_sched_msgout() because + * that hits the SBC (avoid DMA conflict). + */ + + /* Another hack (Er.. hook!) for the sun3 si: */ + if (sc->sc_intr_off) { + NCR_TRACE("abort: intr off\n", 0); + sc->sc_intr_off(sc); + } + + sc->sc_state |= NCR_ABORTING; + if ((sc->sc_state & NCR_DOINGDMA) == 0) { + ncr_sched_msgout(sc, SEND_ABORT); + } + NCR_TRACE("abort: call machine, cur=0x%x\n", + (long) sc->sc_current); + ncr5380_machine(sc); + NCR_TRACE("abort: machine done, cur=0x%x\n", + (long) sc->sc_current); + + /* Another hack (Er.. hook!) for the sun3 si: */ + if (sc->sc_intr_on) { + NCR_TRACE("abort: intr ON\n", 0); + sc->sc_intr_on(sc); + } +} + +/* + * Timeout handler, scheduled for each SCSI command. + */ +void +ncr5380_cmd_timeout(arg) + void *arg; +{ + struct sci_req *sr = arg; + struct scsi_xfer *xs; + struct scsi_link *sc_link; + struct ncr5380_softc *sc; + int s; + + s = splbio(); + + /* Get all our variables... */ + xs = sr->sr_xs; + if (xs == NULL) { + printf("ncr5380_cmd_timeout: no scsi_xfer\n"); + goto out; + } + sc_link = xs->sc_link; + sc = sc_link->adapter_softc; + + printf("%s: cmd timeout, targ=%d, lun=%d\n", + sc->sc_dev.dv_xname, + sr->sr_target, sr->sr_lun); + + /* + * Mark the overdue job as failed, and arrange for + * ncr5380_machine to terminate it. If the victim + * is the current job, call ncr5380_machine() now. + * Otherwise arrange for ncr5380_sched() to do it. + */ + sr->sr_flags |= SR_OVERDUE; + if (sc->sc_current == sr) { + NCR_TRACE("cmd_tmo: call abort, sr=0x%x\n", (long) sr); + ncr5380_abort(sc); + } else { + /* + * The driver may be idle, or busy with another job. + * Arrange for ncr5380_sched() to do the deed. + */ + NCR_TRACE("cmd_tmo: clear matrix, t/l=0x%02x\n", + (sr->sr_target << 4) | sr->sr_lun); + sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL; + } + + /* + * We may have aborted the current job, or may have + * already been idle. In either case, we should now + * be idle, so try to start another job. + */ + if (sc->sc_state == NCR_IDLE) { + NCR_TRACE("cmd_tmo: call sched, cur=0x%x\n", + (long) sc->sc_current); + ncr5380_sched(sc); + NCR_TRACE("cmd_tmo: sched done, cur=0x%x\n", + (long) sc->sc_current); + } + +out: + splx(s); +} + + +/***************************************************************** + * Interface to higher level + *****************************************************************/ + + +/* + * Enter a new SCSI command into the "issue" queue, and + * if there is work to do, start it going. + * + * WARNING: This can be called recursively! + * (see comment in ncr5380_done) + */ +int +ncr5380_scsi_cmd(xs) + struct scsi_xfer *xs; +{ + struct ncr5380_softc *sc; + struct sci_req *sr; + int s, rv, i, flags; + extern int cold; /* XXX */ + + sc = xs->sc_link->adapter_softc; + + flags = xs->flags; + /* + * XXX: Hack: During autoconfig, force polling mode. + * Needed as long as sdsize() can be called while cold, + * otherwise timeouts will never call back (grumble). + */ + if (cold) + flags |= SCSI_POLL; + + if (sc->sc_flags & NCR5380_FORCE_POLLING) + flags |= SCSI_POLL; + + if (flags & SCSI_DATA_UIO) + panic("ncr5380: scsi data uio requested"); + + s = splbio(); + + if (flags & SCSI_POLL) { + /* Terminate any current command. */ + sr = sc->sc_current; + if (sr) { + printf("%s: polled request aborting %d/%d\n", + sc->sc_dev.dv_xname, + sr->sr_target, sr->sr_lun); + ncr5380_abort(sc); + } + if (sc->sc_state != NCR_IDLE) { + panic("ncr5380_scsi_cmd: polled request, abort failed"); + } + } + + /* + * Find lowest empty slot in ring buffer. + * XXX: What about "fairness" and cmd order? + */ + for (i = 0; i < SCI_OPENINGS; i++) + if (sc->sc_ring[i].sr_xs == NULL) + goto new; + + rv = TRY_AGAIN_LATER; + NCR_TRACE("scsi_cmd: no openings, rv=%d\n", rv); + goto out; + +new: + /* Create queue entry */ + sr = &sc->sc_ring[i]; + sr->sr_xs = xs; + sr->sr_target = xs->sc_link->target; + sr->sr_lun = xs->sc_link->lun; + sr->sr_dma_hand = NULL; + sr->sr_dataptr = xs->data; + sr->sr_datalen = xs->datalen; + sr->sr_flags = (flags & SCSI_POLL) ? SR_IMMED : 0; + sr->sr_status = -1; /* no value */ + sc->sc_ncmds++; + rv = SUCCESSFULLY_QUEUED; + + NCR_TRACE("scsi_cmd: new sr=0x%x\n", (long)sr); + + if (flags & SCSI_POLL) { + /* Force this new command to be next. */ + sc->sc_rr = i; + } + + /* + * If we were idle, run some commands... + */ + if (sc->sc_state == NCR_IDLE) { + NCR_TRACE("scsi_cmd: call sched, cur=0x%x\n", + (long) sc->sc_current); + ncr5380_sched(sc); + NCR_TRACE("scsi_cmd: sched done, cur=0x%x\n", + (long) sc->sc_current); + } + + if (flags & SCSI_POLL) { + /* Make sure ncr5380_sched() finished it. */ + if ((xs->flags & ITSDONE) == 0) + panic("ncr5380_scsi_cmd: poll didn't finish"); + rv = COMPLETE; + } + +out: + splx(s); + return (rv); +} + + +/* + * POST PROCESSING OF SCSI_CMD (usually current) + * Called by ncr5380_sched(), ncr5380_machine() + */ +static void +ncr5380_done(sc) + struct ncr5380_softc *sc; +{ + struct sci_req *sr; + struct scsi_xfer *xs; + +#ifdef DIAGNOSTIC + if ((getsr() & PSL_IPL) < PSL_IPL2) + panic("ncr5380_done: bad spl"); + if (sc->sc_state == NCR_IDLE) + panic("ncr5380_done: state=idle"); + if (sc->sc_current == NULL) + panic("ncr5380_done: current=0"); +#endif + + sr = sc->sc_current; + xs = sr->sr_xs; + + NCR_TRACE("done: top, cur=0x%x\n", (long) sc->sc_current); + + /* + * Clean up DMA resources for this command. + */ + if (sr->sr_dma_hand) { + NCR_TRACE("done: dma_free, dh=0x%x\n", + (long) sr->sr_dma_hand); + (*sc->sc_dma_free)(sc); + } +#ifdef DIAGNOSTIC + if (sr->sr_dma_hand) + panic("ncr5380_done: dma free did not"); +#endif + + if (sc->sc_state & NCR_ABORTING) { + NCR_TRACE("done: aborting, error=%d\n", xs->error); + if (xs->error == XS_NOERROR) + xs->error = XS_TIMEOUT; + } + + NCR_TRACE("done: check error=%d\n", (long) xs->error); + + /* If error is already set, ignore sr_status value. */ + if (xs->error != XS_NOERROR) + goto finish; + + NCR_TRACE("done: check status=%d\n", sr->sr_status); + + switch (sr->sr_status) { + case SCSI_OK: /* 0 */ + if (sr->sr_flags & SR_SENSE) { + if (ncr5380_debug & NCR_DBG_CMDS) { + ncr5380_show_sense(xs); + } + xs->error = XS_SENSE; + } + break; + + case SCSI_CHECK: + if (sr->sr_flags & SR_SENSE) { + /* Sense command also asked for sense? */ + printf("ncr5380_done: sense asked for sense\n"); + NCR_BREAK(); + xs->error = XS_DRIVER_STUFFUP; + break; + } + sr->sr_flags |= SR_SENSE; + NCR_TRACE("done: get sense, sr=0x%x\n", (long) sr); + /* + * Leave queued, but clear sc_current so we start over + * with selection. Guaranteed to get the same request. + */ + sc->sc_state = NCR_IDLE; + sc->sc_current = NULL; + sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL; + return; /* XXX */ + + case SCSI_BUSY: + xs->error = XS_BUSY; + break; + + case -1: + /* This is our "impossible" initial value. */ + /* fallthrough */ + default: + printf("%s: target %d, bad status=%d\n", + sc->sc_dev.dv_xname, sr->sr_target, sr->sr_status); + xs->error = XS_DRIVER_STUFFUP; + break; + } + +finish: + + NCR_TRACE("done: finish, error=%d\n", xs->error); + + /* + * Dequeue the finished command, but don't clear sc_state until + * after the call to scsi_done(), because that may call back to + * ncr5380_scsi_cmd() - unwanted recursion! + * + * Keeping sc->sc_state != idle terminates the recursion. + */ +#ifdef DIAGNOSTIC + if ((sc->sc_state & NCR_WORKING) == 0) + panic("ncr5380_done: bad state"); +#endif + + /* Clear our pointers to the request. */ + sc->sc_current = NULL; + sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL; + untimeout(ncr5380_cmd_timeout, sr); + + /* Make the request free. */ + sr->sr_xs = NULL; + sc->sc_ncmds--; + + /* Tell common SCSI code it is done. */ + xs->flags |= ITSDONE; + scsi_done(xs); + + sc->sc_state = NCR_IDLE; + /* Now ncr5380_sched() may be called again. */ +} + + +/* + * Schedule a SCSI operation. This routine should return + * only after it achieves one of the following conditions: + * Busy (sc->sc_state != NCR_IDLE) + * No more work can be started. + */ +static void +ncr5380_sched(sc) + struct ncr5380_softc *sc; +{ + struct sci_req *sr; + struct scsi_xfer *xs; + int target, lun; + int error, i; + +#ifdef DIAGNOSTIC + if ((getsr() & PSL_IPL) < PSL_IPL2) + panic("ncr5380_sched: bad spl"); +#endif + + /* Another hack (Er.. hook!) for the sun3 si: */ + if (sc->sc_intr_off) { + NCR_TRACE("sched: top, intr off\n", 0); + sc->sc_intr_off(sc); + } + +next_job: + /* + * Grab the next job from queue. Must be idle. + */ +#ifdef DIAGNOSTIC + if (sc->sc_state != NCR_IDLE) + panic("ncr5380_sched: not idle"); + if (sc->sc_current) + panic("ncr5380_sched: current set"); +#endif + + /* + * Always start the search where we last looked. + * The REQUEST_SENSE logic depends on this to + * choose the same job as was last picked, so it + * can just clear sc_current and reschedule. + * (Avoids loss of "contingent allegiance".) + */ + i = sc->sc_rr; + sr = NULL; + do { + if (sc->sc_ring[i].sr_xs) { + target = sc->sc_ring[i].sr_target; + lun = sc->sc_ring[i].sr_lun; + if (sc->sc_matrix[target][lun] == NULL) { + sc->sc_matrix[target][lun] = + sr = &sc->sc_ring[i]; + sc->sc_rr = i; + break; + } + } + i++; + if (i == SCI_OPENINGS) + i = 0; + } while (i != sc->sc_rr); + + if (sr == NULL) { + NCR_TRACE("sched: no work, cur=0x%x\n", + (long) sc->sc_current); + + /* Another hack (Er.. hook!) for the sun3 si: */ + if (sc->sc_intr_on) { + NCR_TRACE("sched: ret, intr ON\n", 0); + sc->sc_intr_on(sc); + } + + return; /* No more work to do. */ + } + + NCR_TRACE("sched: select for t/l=0x%02x\n", + (sr->sr_target << 4) | sr->sr_lun); + + sc->sc_state = NCR_WORKING; + error = ncr5380_select(sc, sr); + if (sc->sc_current) { + /* Lost the race! reselected out from under us! */ + /* Work with the reselected job. */ + if (sr->sr_flags & SR_IMMED) { + printf("%s: reselected while polling (abort)\n", + sc->sc_dev.dv_xname); + /* Abort the reselected job. */ + sc->sc_state |= NCR_ABORTING; + sc->sc_msgpriq |= SEND_ABORT; + } + sr = sc->sc_current; + xs = sr->sr_xs; + NCR_TRACE("sched: reselect, new sr=0x%x\n", (long)sr); + goto have_nexus; + } + + /* Normal selection result */ + sc->sc_current = sr; /* connected */ + xs = sr->sr_xs; + + /* + * Initialize pointers, etc. for this job + */ + sc->sc_dataptr = sr->sr_dataptr; + sc->sc_datalen = sr->sr_datalen; + sc->sc_prevphase = PHASE_INVALID; + sc->sc_msgpriq = SEND_IDENTIFY; + sc->sc_msgoutq = 0; + sc->sc_msgout = 0; + + NCR_TRACE("sched: select rv=%d\n", error); + + switch (error) { + case XS_NOERROR: + break; + + case XS_BUSY: + /* XXX - Reset and try again. */ + printf("%s: SCSI bus busy, resetting...\n", + sc->sc_dev.dv_xname); + ncr5380_reset_scsibus(sc); + /* fallthrough */ + case XS_SELTIMEOUT: + default: + xs->error = error; /* from select */ + NCR_TRACE("sched: call done, sr=0x%x\n", (long)sr); + ncr5380_done(sc); + + /* Paranoia: clear everything. */ + sc->sc_dataptr = NULL; + sc->sc_datalen = 0; + sc->sc_prevphase = PHASE_INVALID; + sc->sc_msgpriq = 0; + sc->sc_msgoutq = 0; + sc->sc_msgout = 0; + + goto next_job; + } + + /* + * Selection was successful. Normally, this means + * we are starting a new command. However, this + * might be the termination of an overdue job. + */ + if (sr->sr_flags & SR_OVERDUE) { + NCR_TRACE("sched: overdue, sr=0x%x\n", (long)sr); + sc->sc_state |= NCR_ABORTING; + sc->sc_msgpriq |= SEND_ABORT; + goto have_nexus; + } + + /* + * This may be the continuation of some job that + * completed with a "check condition" code. + */ + if (sr->sr_flags & SR_SENSE) { + NCR_TRACE("sched: get sense, sr=0x%x\n", (long)sr); + /* Do not allocate DMA, nor set timeout. */ + goto have_nexus; + } + + /* + * OK, we are starting a new command. + * Initialize and allocate resources for the new command. + * Device reset is special (only uses MSG_OUT phase). + * Normal commands start in MSG_OUT phase where we will + * send and IDENDIFY message, and then expect CMD phase. + */ + if (ncr5380_debug & NCR_DBG_CMDS) { + printf("ncr5380_sched: begin, target=%d, LUN=%d\n", + xs->sc_link->target, xs->sc_link->lun); + ncr5380_show_scsi_cmd(xs); + } + if (xs->flags & SCSI_RESET) { + NCR_TRACE("sched: cmd=reset, sr=0x%x\n", (long)sr); + /* Not an error, so do not set NCR_ABORTING */ + sc->sc_msgpriq |= SEND_DEV_RESET; + goto have_nexus; + } + +#ifdef DIAGNOSTIC + if ((xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) == 0) { + if (sc->sc_dataptr) { + printf("%s: ptr but no data in/out flags?\n"); + NCR_BREAK(); + sc->sc_dataptr = NULL; + } + } +#endif + + /* Allocate DMA space (maybe) */ + if (sc->sc_dataptr && sc->sc_dma_alloc && + (sc->sc_datalen >= sc->sc_min_dma_len)) + { + NCR_TRACE("sched: dma_alloc, len=%d\n", sc->sc_datalen); + (*sc->sc_dma_alloc)(sc); + } + + /* + * Initialization hook called just after select, + * at the beginning of COMMAND phase. + * (but AFTER the DMA allocation is done) + * + * The evil Sun "si" adapter (OBIO variant) needs some + * setup done to the DMA engine BEFORE the target puts + * the SCSI bus into any DATA phase. + */ + if (sr->sr_dma_hand && sc->sc_dma_setup) { + NCR_TRACE("sched: dma_setup, dh=0x%x\n", + (long) sr->sr_dma_hand); + sc->sc_dma_setup(sc); + } + + /* + * Schedule a timeout for the job we are starting. + */ + if ((sr->sr_flags & SR_IMMED) == 0) { + i = (xs->timeout * hz) / 1000; + NCR_TRACE("sched: set timeout=%d\n", i); + timeout(ncr5380_cmd_timeout, sr, i); + } + +have_nexus: + NCR_TRACE("sched: call machine, cur=0x%x\n", + (long) sc->sc_current); + ncr5380_machine(sc); + NCR_TRACE("sched: machine done, cur=0x%x\n", + (long) sc->sc_current); + + /* + * What state did ncr5380_machine() leave us in? + * Hopefully it sometimes completes a job... + */ + if (sc->sc_state == NCR_IDLE) + goto next_job; + + return; /* Have work in progress. */ +} + + +/* + * Reselect handler: checks for reselection, and if we are being + * reselected, it sets up sc->sc_current. + * + * We are reselected when: + * SEL is TRUE + * IO is TRUE + * BSY is FALSE + */ +void +ncr5380_reselect(sc) + struct ncr5380_softc *sc; +{ + struct sci_req *sr; + int target, lun, phase, timo; + u_char bus, data, icmd, msg; + +#ifdef DIAGNOSTIC + /* + * Note: sc_state will be "idle" when ncr5380_intr() + * calls, or "working" when ncr5380_select() calls. + * (So don't test that in this DIAGNOSTIC) + */ + if (sc->sc_current) + panic("ncr5380_reselect: current set"); +#endif + + /* + * First, check the select line. + * (That has to be set first.) + */ + bus = *(sc->sci_bus_csr); + if ((bus & SCI_BUS_SEL) == 0) { + /* Not a selection or reselection. */ + return; + } + + /* + * The target will assert BSY first (for bus arbitration), + * then raise SEL, and finally drop BSY. Only then is the + * data bus required to have valid selection ID bits set. + * Wait for: SEL==1, BSY==0 before reading the data bus. + */ + timo = ncr5380_wait_nrq_timo; + for (;;) { + if ((bus & SCI_BUS_BSY) == 0) + break; + /* Probably never get here... */ + if (--timo <= 0) { + printf("%s: reselect, BSY stuck, bus=0x%x\n", + sc->sc_dev.dv_xname, bus); + /* Not much we can do. Reset the bus. */ + ncr5380_reset_scsibus(sc); + return; + } + delay(10); + bus = *(sc->sci_bus_csr); + /* If SEL went away, forget it. */ + if ((bus & SCI_BUS_SEL) == 0) + return; + /* Still have SEL, check BSY. */ + } + NCR_TRACE("reselect, valid data after %d loops\n", + ncr5380_wait_nrq_timo - timo); + + /* + * Good. We have SEL=1 and BSY=0. Now wait for a + * "bus settle delay" before we sample the data bus + */ + delay(2); + data = *(sc->sci_data) & 0xFF; + /* XXX - Should check parity... */ + + /* + * Is this a reselect (I/O == 1) or have we been + * selected as a target? (I/O == 0) + */ + if ((bus & SCI_BUS_IO) == 0) { + printf("%s: selected as target, data=0x%x\n", + sc->sc_dev.dv_xname, data); + /* Not much we can do. Reset the bus. */ + ncr5380_reset_scsibus(sc); + return; + } + + /* + * OK, this is a reselection. + */ + for (target = 0; target < 7; target++) + if (data & (1 << target)) + break; + + if ((data & 0x7F) != (1 << target)) { + /* No selecting ID? or >2 IDs on bus? */ + printf("%s: bad reselect, data=0x%x\n", + sc->sc_dev.dv_xname, data); + return; + } + + NCR_TRACE("reselect: target=0x%x\n", target); + + /* Raise BSY to acknowledge target reselection. */ + SetReg ( sc->sci_icmd, SCI_ICMD_BSY ); +/* *(sc->sci_icmd) = SCI_ICMD_BSY; */ + + /* Wait for target to drop SEL. */ + timo = ncr5380_wait_nrq_timo; + for (;;) { + bus = *(sc->sci_bus_csr); + if ((bus & SCI_BUS_SEL) == 0) + break; /* success */ + if (--timo <= 0) { + printf("%s: reselect, SEL stuck, bus=0x%x\n", + sc->sc_dev.dv_xname, bus); + NCR_BREAK(); + /* assume connected (fail later if not) */ + break; + } + delay(2); + } + + /* Now we drop BSY, and we are connected. */ + SetReg ( sc->sci_icmd, 0 ); + SetReg ( sc->sci_sel_enb, 0 ); +/* *(sc->sci_icmd) = 0; + *sc->sci_sel_enb = 0; */ + SCI_CLR_INTR(sc); + + /* + * At this point the target should send an IDENTIFY message, + * which will permit us to determine the reselecting LUN. + * If not, we assume LUN 0. + */ + lun = 0; + /* Wait for REQ before reading bus phase. */ + if (ncr5380_wait_req(sc)) { + printf("%s: reselect, no REQ\n", + sc->sc_dev.dv_xname); + /* Try to send an ABORT message. */ + goto abort; + } + phase = SCI_BUS_PHASE(*sc->sci_bus_csr); + if (phase != PHASE_MSG_IN) { + printf("%s: reselect, phase=%d\n", + sc->sc_dev.dv_xname, phase); + goto abort; + } + + /* Ack. the change to PHASE_MSG_IN */ + SetReg ( sc->sci_tcmd, PHASE_MSG_IN ); +/* *(sc->sci_tcmd) = PHASE_MSG_IN; */ + + /* Peek at the message byte without consuming it! */ + msg = *(sc->sci_data); + if ((msg & 0x80) == 0) { + printf("%s: reselect, not identify, msg=%d\n", + sc->sc_dev.dv_xname, msg); + goto abort; + } + lun = msg & 7; + + /* We now know target/LUN. Do we have the request? */ + sr = sc->sc_matrix[target][lun]; + if (sr) { + /* We now have a nexus. */ + sc->sc_state |= NCR_WORKING; + sc->sc_current = sr; + NCR_TRACE("reselect: resume sr=0x%x\n", (long)sr); + + /* Implicit restore pointers message */ + sc->sc_dataptr = sr->sr_dataptr; + sc->sc_datalen = sr->sr_datalen; + + sc->sc_prevphase = PHASE_INVALID; + sc->sc_msgpriq = 0; + sc->sc_msgoutq = 0; + sc->sc_msgout = 0; + + /* + * Another hack for the Sun3 "si", which needs + * some setup done to its DMA engine before the + * target puts the SCSI bus into any DATA phase. + */ + if (sr->sr_dma_hand && sc->sc_dma_setup) { + NCR_TRACE("reselect: call DMA setup, dh=0x%x\n", + (long) sr->sr_dma_hand); + sc->sc_dma_setup(sc); + } + + /* Now consume the IDENTIFY message. */ + ncr5380_pio_in(sc, PHASE_MSG_IN, 1, &msg); + return; + } + + printf("%s: phantom reselect: target=%d, LUN=%d\n", + sc->sc_dev.dv_xname, target, lun); +abort: + /* + * Try to send an ABORT message. This makes us + * temporarily busy, but no current command... + */ + sc->sc_state |= NCR_ABORTING; + + /* Raise ATN, delay, raise ACK... */ + icmd = SCI_ICMD_ATN; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + delay(2); + + /* Now consume the IDENTIFY message. */ + ncr5380_pio_in(sc, PHASE_MSG_IN, 1, &msg); + + /* Finally try to send the ABORT. */ + sc->sc_prevphase = PHASE_INVALID; + sc->sc_msgpriq = SEND_ABORT; + ncr5380_msg_out(sc); + + SetReg ( sc->sci_tcmd, PHASE_INVALID ); + SetReg ( sc->sci_sel_enb, 0 ); +/* *(sc->sci_tcmd) = PHASE_INVALID; + *sc->sci_sel_enb = 0; */ + SCI_CLR_INTR(sc); + SetReg ( sc->sci_sel_enb, 0x80 ); +/* *sc->sci_sel_enb = 0x80; */ + + sc->sc_state &= ~NCR_ABORTING; +} + + +/* + * Select target: xs is the transfer that we are selecting for. + * sc->sc_current should be NULL. + * + * Returns: + * sc->sc_current != NULL ==> we were reselected (race!) + * XS_NOERROR ==> selection worked + * XS_BUSY ==> lost arbitration + * XS_SELTIMEOUT ==> no response to selection + */ +static int +ncr5380_select(sc, sr) + struct ncr5380_softc *sc; + struct sci_req *sr; +{ + int timo; + u_char bus, data, icmd; + + /* Check for reselect */ + ncr5380_reselect(sc); + if (sc->sc_current) { + NCR_TRACE("select: reselect, cur=0x%x\n", + (long) sc->sc_current); + return XS_BUSY; /* reselected */ + } + + /* + * Set phase bits to 0, otherwise the 5380 won't drive the bus during + * selection. + */ + + SetReg ( sc->sci_tcmd, PHASE_DATA_OUT ); + SetReg ( sc->sci_icmd, 0 ); + SetReg ( sc->sci_mode, 0 ); + +/* *sc->sci_tcmd = PHASE_DATA_OUT; + *sc->sci_icmd = icmd = 0; + *sc->sci_mode = 0; */ + + /* + * Arbitrate for the bus. The 5380 takes care of the + * time-critical bus interactions. We set our ID bit + * in the output data register and set MODE_ARB. The + * 5380 watches for the required "bus free" period. + * If and when the "bus free" period is detected, the + * 5380 then drives BSY, drives the data bus, and sets + * the "arbitration in progress" (AIP) bit to let us + * know arbitration has started. We then wait for one + * arbitration delay (2.2uS) and check the ICMD_LST bit, + * which will be set if someone else drives SEL. + */ + + SetReg ( sc->sci_odata, 0x80 ); + SetReg ( sc->sci_mode, SCI_MODE_ARB ); + +/* *(sc->sci_odata) = 0x80; */ /* OUR_ID */ +/* *(sc->sci_mode) = SCI_MODE_ARB; */ + + /* Wait for ICMD_AIP. */ + timo = ncr5380_wait_req_timo; + for (;;) { + if (*(sc->sci_icmd) & SCI_ICMD_AIP) + break; + if (--timo <= 0) { + /* Did not see any "bus free" period. */ + SetReg ( sc->sci_mode, 0 ); +/* *sc->sci_mode = 0; */ + NCR_TRACE("select: bus busy, rc=%d\n", XS_BUSY); + return XS_BUSY; + } + delay(2); + } + NCR_TRACE("select: have AIP after %d loops\n", + ncr5380_wait_req_timo - timo); + + /* Got AIP. Wait one arbitration delay (2.2 uS.) */ + delay(3); + + /* Check for ICMD_LST */ + if (*(sc->sci_icmd) & SCI_ICMD_LST) { + /* Some other target asserted SEL. */ + SetReg ( sc->sci_mode, 0 ); +/* *sc->sci_mode = 0; */ + NCR_TRACE("select: lost one, rc=%d\n", XS_BUSY); + ncr5380_reselect(sc); /* XXX */ + return XS_BUSY; + } + + /* + * No other device has declared itself the winner. + * The spec. says to check for higher IDs, but we + * are always the highest (ID=7) so don't bother. + * We can now declare victory by asserting SEL. + * + * Note that the 5380 is asserting BSY because we + * asked it to do arbitration. We will now hold + * BSY directly so we can turn off ARB mode. + */ + icmd = (SCI_ICMD_BSY | SCI_ICMD_SEL); + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + /* + * "The SCSI device that wins arbitration shall wait + * at least a bus clear delay plus a bus settle delay + * after asserting the SEL signal before changing + * any [other] signal." (1.2uS. total) + */ + delay(2); + +#if 1 + /* + * XXX: Check one last time to see if we really + * XXX: did win arbitration. (too paranoid?) + */ + if (*(sc->sci_icmd) & SCI_ICMD_LST) { + SetReg ( sc->sci_icmd, 0 ); + SetReg ( sc->sci_mode, 0 ); +/* *sc->sci_icmd = 0; + *sc->sci_mode = 0; */ + NCR_TRACE("select: lost two, rc=%d\n", XS_BUSY); + return XS_BUSY; + } +#endif + /* Leave ARB mode Now that we drive BSY+SEL */ + SetReg ( sc->sci_mode, 0 ); + SetReg ( sc->sci_sel_enb, 0 ); +/* *sc->sci_mode = 0; + *sc->sci_sel_enb = 0; */ + + /* + * Arbitration is complete. Now do selection: + * Drive the data bus with the ID bits for both + * the host and target. Also set ATN now, to + * ask the target for a messgae out phase. + */ + data = 0x80 | (1 << sr->sr_target); + SetReg ( sc->sci_odata, data ); +/* *(sc->sci_odata) = data; */ + icmd |= (SCI_ICMD_DATA | SCI_ICMD_ATN); + SetReg ( sc->sci_icmd, icmd ); + *(sc->sci_icmd) = icmd; + delay(2); /* two deskew delays. */ + + /* De-assert BSY (targets sample the data now). */ + icmd &= ~SCI_ICMD_BSY; + SetReg ( sc->sci_icmd, icmd ); +/* *(sc->sci_icmd) = icmd; */ + delay(3); /* Bus settle delay. */ + + /* + * Wait for the target to assert BSY. + * SCSI spec. says wait for 250 mS. + */ + for (timo = 25000;;) { + if (*sc->sci_bus_csr & SCI_BUS_BSY) + goto success; + if (--timo <= 0) + break; + delay(10); + } + + /* + * There is no reaction from the target. Start the selection + * timeout procedure. We release the databus but keep SEL+ATN + * asserted. After that we wait a 'selection abort time' (200 + * usecs) and 2 deskew delays (90 ns) and check BSY again. + * When BSY is asserted, we assume the selection succeeded, + * otherwise we release the bus. + */ + icmd &= ~SCI_ICMD_DATA; + SetReg ( sc->sci_icmd, icmd ); +/* *(sc->sci_icmd) = icmd; */ + delay(201); + if ((*sc->sci_bus_csr & SCI_BUS_BSY) == 0) { + /* Really no device on bus */ + SetReg ( sc->sci_tcmd, PHASE_INVALID ); + SetReg ( sc->sci_icmd, 0 ); + SetReg ( sc->sci_mode, 0 ); + SetReg ( sc->sci_sel_enb, 0 ); +/* *sc->sci_tcmd = PHASE_INVALID; + *sc->sci_icmd = 0; + *sc->sci_mode = 0; + *sc->sci_sel_enb = 0; */ + SCI_CLR_INTR(sc); + SetReg ( sc->sci_sel_enb, 0x80 ); + *sc->sci_sel_enb = 0x80; + NCR_TRACE("select: device down, rc=%d\n", XS_SELTIMEOUT); + return XS_SELTIMEOUT; + } + +success: + /* + * The target is now driving BSY, so we can stop + * driving SEL and the data bus (keep ATN true). + * Configure the ncr5380 to monitor BSY, parity. + */ + icmd &= ~(SCI_ICMD_DATA | SCI_ICMD_SEL); + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + /* XXX - Make parity checking optional? */ + SetReg ( sc->sci_mode, (SCI_MODE_MONBSY) ); +/* SetReg ( sc->sci_mode, (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK) ); */ +/* *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK); */ + + return XS_NOERROR; +} + + +/***************************************************************** + * Functions to handle each info. transfer phase: + *****************************************************************/ + +/* + * The message system: + * + * This is a revamped message system that now should easier accomodate + * new messages, if necessary. + * + * Currently we accept these messages: + * IDENTIFY (when reselecting) + * COMMAND COMPLETE # (expect bus free after messages marked #) + * NOOP + * MESSAGE REJECT + * SYNCHRONOUS DATA TRANSFER REQUEST + * SAVE DATA POINTER + * RESTORE POINTERS + * DISCONNECT # + * + * We may send these messages in prioritized order: + * BUS DEVICE RESET # if SCSI_RESET & xs->flags (or in weird sits.) + * MESSAGE PARITY ERROR par. err. during MSGI + * MESSAGE REJECT If we get a message we don't know how to handle + * ABORT # send on errors + * INITIATOR DETECTED ERROR also on errors (SCSI2) (during info xfer) + * IDENTIFY At the start of each transfer + * SYNCHRONOUS DATA TRANSFER REQUEST if appropriate + * NOOP if nothing else fits the bill ... + */ + +#define IS1BYTEMSG(m) (((m) != 0x01 && (m) < 0x20) || (m) >= 0x80) +#define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20) +#define ISEXTMSG(m) ((m) == 0x01) + +/* + * Precondition: + * The SCSI bus is already in the MSGI phase and there is a message byte + * on the bus, along with an asserted REQ signal. + * + * Our return value determines whether our caller, ncr5380_machine() + * will expect to see another REQ (and possibly phase change). + */ +static int +ncr5380_msg_in(sc) + register struct ncr5380_softc *sc; +{ + struct sci_req *sr = sc->sc_current; + int n, phase, timo; + int act_flags; + register u_char icmd; + + /* acknowledge phase change */ + SetReg ( sc->sci_tcmd, PHASE_MSG_IN ); +/* *sc->sci_tcmd = PHASE_MSG_IN; */ + + act_flags = ACT_CONTINUE; + icmd = *sc->sci_icmd & SCI_ICMD_RMASK; + + if (sc->sc_prevphase == PHASE_MSG_IN) { + /* This is a continuation of the previous message. */ + n = sc->sc_imp - sc->sc_imess; + NCR_TRACE("msg_in: continuation, n=%d\n", n); + goto nextbyte; + } + + /* This is a new MESSAGE IN phase. Clean up our state. */ + sc->sc_state &= ~NCR_DROP_MSGIN; + +nextmsg: + n = 0; + sc->sc_imp = &sc->sc_imess[n]; + +nextbyte: + /* + * Read a whole message, but don't ack the last byte. If we reject the + * message, we have to assert ATN during the message transfer phase + * itself. + */ + for (;;) { + /* + * Read a message byte. + * First, check BSY, REQ, phase... + */ + if (!SCI_BUSY(sc)) { + NCR_TRACE("msg_in: lost BSY, n=%d\n", n); + /* XXX - Assume the command completed? */ + act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE); + return (act_flags); + } + if (ncr5380_wait_req(sc)) { + NCR_TRACE("msg_in: BSY but no REQ, n=%d\n", n); + /* Just let ncr5380_machine() handle it... */ + return (act_flags); + } + phase = SCI_BUS_PHASE(*sc->sci_bus_csr); + if (phase != PHASE_MSG_IN) { + /* + * Target left MESSAGE IN, probably because it + * a) noticed our ATN signal, or + * b) ran out of messages. + */ + return (act_flags); + } + /* Still in MESSAGE IN phase, and REQ is asserted. */ + if (*sc->sci_csr & SCI_CSR_PERR) { + ncr_sched_msgout(sc, SEND_PARITY_ERROR); + sc->sc_state |= NCR_DROP_MSGIN; + } + + /* Gather incoming message bytes if needed. */ + if ((sc->sc_state & NCR_DROP_MSGIN) == 0) { + if (n >= NCR_MAX_MSG_LEN) { + ncr_sched_msgout(sc, SEND_REJECT); + sc->sc_state |= NCR_DROP_MSGIN; + } else { + *sc->sc_imp++ = *sc->sci_data; + n++; + /* + * This testing is suboptimal, but most + * messages will be of the one byte variety, so + * it should not affect performance + * significantly. + */ + if (n == 1 && IS1BYTEMSG(sc->sc_imess[0])) + goto have_msg; + if (n == 2 && IS2BYTEMSG(sc->sc_imess[0])) + goto have_msg; + if (n >= 3 && ISEXTMSG(sc->sc_imess[0]) && + n == sc->sc_imess[1] + 2) + goto have_msg; + } + } + + /* + * If we reach this spot we're either: + * a) in the middle of a multi-byte message, or + * b) dropping bytes. + */ + + /* Ack the last byte read. */ + icmd |= SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + if (ncr5380_wait_not_req(sc)) { + NCR_TRACE("msg_in: drop, stuck REQ, n=%d\n", n); + act_flags |= ACT_RESET_BUS; + } + + icmd &= ~SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + if (act_flags != ACT_CONTINUE) + return (act_flags); + + /* back to nextbyte */ + } + +have_msg: + /* We now have a complete message. Parse it. */ + + switch (sc->sc_imess[0]) { + case MSG_CMDCOMPLETE: + NCR_TRACE("msg_in: CMDCOMPLETE\n", 0); + /* Target is about to disconnect. */ + act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE); + break; + + case MSG_DISCONNECT: + NCR_TRACE("msg_in: DISCONNECT\n", 0); + /* Target is about to disconnect. */ + act_flags |= ACT_DISCONNECT; + break; + + case MSG_PARITY_ERROR: + NCR_TRACE("msg_in: PARITY_ERROR\n", 0); + /* Resend the last message. */ + ncr_sched_msgout(sc, sc->sc_msgout); + break; + + case MSG_MESSAGE_REJECT: + /* The target rejects the last message we sent. */ + NCR_TRACE("msg_in: got reject for 0x%x\n", sc->sc_msgout); + switch (sc->sc_msgout) { + case SEND_IDENTIFY: + /* Really old target controller? */ + /* XXX ... */ + break; + case SEND_INIT_DET_ERR: + goto abort; + } + break; + + case MSG_NOOP: + NCR_TRACE("msg_in: NOOP\n", 0); + break; + + case MSG_SAVEDATAPOINTER: + NCR_TRACE("msg_in: SAVE_PTRS\n", 0); + sr->sr_dataptr = sc->sc_dataptr; + sr->sr_datalen = sc->sc_datalen; + break; + + case MSG_RESTOREPOINTERS: + NCR_TRACE("msg_in: RESTORE_PTRS\n", 0); + sc->sc_dataptr = sr->sr_dataptr; + sc->sc_datalen = sr->sr_datalen; + break; + + case MSG_EXTENDED: + switch (sc->sc_imess[2]) { + case MSG_EXT_SDTR: + case MSG_EXT_WDTR: + /* The ncr5380 can not do synchronous mode. */ + goto reject; + default: + printf("%s: unrecognized MESSAGE EXTENDED; sending REJECT\n", + sc->sc_dev.dv_xname); + NCR_BREAK(); + goto reject; + } + break; + + default: + NCR_TRACE("msg_in: eh? imsg=0x%x\n", sc->sc_imess[0]); + printf("%s: unrecognized MESSAGE; sending REJECT\n", + sc->sc_dev.dv_xname); + NCR_BREAK(); + /* fallthrough */ + reject: + ncr_sched_msgout(sc, SEND_REJECT); + break; + + abort: + sc->sc_state |= NCR_ABORTING; + ncr_sched_msgout(sc, SEND_ABORT); + break; + } + + /* Ack the last byte read. */ + icmd |= SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + if (ncr5380_wait_not_req(sc)) { + NCR_TRACE("msg_in: last, stuck REQ, n=%d\n", n); + act_flags |= ACT_RESET_BUS; + } + + icmd &= ~SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + /* Go get the next message, if any. */ + if (act_flags == ACT_CONTINUE) + goto nextmsg; + + return (act_flags); +} + + +/* + * The message out (and in) stuff is a bit complicated: + * If the target requests another message (sequence) without + * having changed phase in between it really asks for a + * retransmit, probably due to parity error(s). + * The following messages can be sent: + * IDENTIFY @ These 4 stem from SCSI command activity + * SDTR @ + * WDTR @ + * DEV_RESET @ + * REJECT if MSGI doesn't make sense + * PARITY_ERROR if parity error while in MSGI + * INIT_DET_ERR if parity error while not in MSGI + * ABORT if INIT_DET_ERR rejected + * NOOP if asked for a message and there's nothing to send + * + * Note that we call this one with (sc_current == NULL) + * when sending ABORT for unwanted reselections. + */ +static int +ncr5380_msg_out(sc) + register struct ncr5380_softc *sc; +{ + struct sci_req *sr = sc->sc_current; + int n, phase, resel; + int progress, act_flags; + register u_char icmd; + + /* acknowledge phase change */ + SetReg ( sc->sci_tcmd, PHASE_MSG_OUT ); +/* *sc->sci_tcmd = PHASE_MSG_OUT; */ + + progress = 0; /* did we send any messages? */ + act_flags = ACT_CONTINUE; + + /* + * Set ATN. If we're just sending a trivial 1-byte message, + * we'll clear ATN later on anyway. Also drive the data bus. + */ + icmd = *sc->sci_icmd & SCI_ICMD_RMASK; + icmd |= (SCI_ICMD_ATN | SCI_ICMD_DATA); + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + if (sc->sc_prevphase == PHASE_MSG_OUT) { + if (sc->sc_omp == sc->sc_omess) { + /* + * This is a retransmission. + * + * We get here if the target stayed in MESSAGE OUT + * phase. Section 5.1.9.2 of the SCSI 2 spec indicates + * that all of the previously transmitted messages must + * be sent again, in the same order. Therefore, we + * requeue all the previously transmitted messages, and + * start again from the top. Our simple priority + * scheme keeps the messages in the right order. + */ + sc->sc_msgpriq |= sc->sc_msgoutq; + NCR_TRACE("msg_out: retrans priq=0x%x\n", sc->sc_msgpriq); + } else { + /* This is a continuation of the previous message. */ + n = sc->sc_omp - sc->sc_omess; + NCR_TRACE("msg_out: continuation, n=%d\n", n); + goto nextbyte; + } + } + + /* No messages transmitted so far. */ + sc->sc_msgoutq = 0; + +nextmsg: + /* Pick up highest priority message. */ + sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq; + sc->sc_msgpriq &= ~sc->sc_msgout; + sc->sc_msgoutq |= sc->sc_msgout; + + /* Build the outgoing message data. */ + switch (sc->sc_msgout) { + case SEND_IDENTIFY: + NCR_TRACE("msg_out: SEND_IDENTIFY\n", 0); + if (sr == NULL) { + printf("%s: SEND_IDENTIFY while not connected; sending NOOP\n", + sc->sc_dev.dv_xname); + NCR_BREAK(); + goto noop; + } + resel = (sc->sc_flags & NCR5380_PERMIT_RESELECT) ? 1 : 0; + resel &= (sr->sr_flags & (SR_IMMED | SR_SENSE)) ? 0 : 1; + sc->sc_omess[0] = MSG_IDENTIFY(sr->sr_lun, resel); + n = 1; + break; + + case SEND_DEV_RESET: + NCR_TRACE("msg_out: SEND_DEV_RESET\n", 0); + /* Expect disconnect after this! */ + /* XXX: Kill jobs for this target? */ + act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE); + sc->sc_omess[0] = MSG_BUS_DEV_RESET; + n = 1; + break; + + case SEND_REJECT: + NCR_TRACE("msg_out: SEND_REJECT\n", 0); + sc->sc_omess[0] = MSG_MESSAGE_REJECT; + n = 1; + break; + + case SEND_PARITY_ERROR: + NCR_TRACE("msg_out: SEND_PARITY_ERROR\n", 0); + sc->sc_omess[0] = MSG_PARITY_ERROR; + n = 1; + break; + + case SEND_INIT_DET_ERR: + NCR_TRACE("msg_out: SEND_INIT_DET_ERR\n", 0); + sc->sc_omess[0] = MSG_INITIATOR_DET_ERR; + n = 1; + break; + + case SEND_ABORT: + NCR_TRACE("msg_out: SEND_ABORT\n", 0); + /* Expect disconnect after this! */ + /* XXX: Set error flag? */ + act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE); + sc->sc_omess[0] = MSG_ABORT; + n = 1; + break; + + case 0: + printf("%s: unexpected MESSAGE OUT; sending NOOP\n", + sc->sc_dev.dv_xname); + NCR_BREAK(); + noop: + NCR_TRACE("msg_out: send NOOP\n", 0); + sc->sc_omess[0] = MSG_NOOP; + n = 1; + break; + + default: + printf("%s: weird MESSAGE OUT; sending NOOP\n", + sc->sc_dev.dv_xname); + NCR_BREAK(); + goto noop; + } + sc->sc_omp = &sc->sc_omess[n]; + +nextbyte: + /* Send message bytes. */ + while (n > 0) { + /* + * Send a message byte. + * First check BSY, REQ, phase... + */ + if (!SCI_BUSY(sc)) { + NCR_TRACE("msg_out: lost BSY, n=%d\n", n); + goto out; + } + if (ncr5380_wait_req(sc)) { + NCR_TRACE("msg_out: no REQ, n=%d\n", n); + goto out; + } + phase = SCI_BUS_PHASE(*sc->sci_bus_csr); + if (phase != PHASE_MSG_OUT) { + /* + * Target left MESSAGE OUT, possibly to reject + * our message. + */ + NCR_TRACE("msg_out: new phase=%d\n", phase); + goto out; + } + + /* Yes, we can send this message byte. */ + --n; + + /* Clear ATN before last byte if this is the last message. */ + if (n == 0 && sc->sc_msgpriq == 0) { + icmd &= ~SCI_ICMD_ATN; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + /* 2 deskew delays */ + delay(2); /* XXX */ + } + + /* Put data on the bus. */ + sc->sc_omp--; + SetReg ( sc->sci_odata, *sc->sc_omp ); +/* *sc->sci_odata = *--sc->sc_omp; */ + + /* Raise ACK to tell target data is on the bus. */ + icmd |= SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + /* Wait for REQ to be negated. */ + if (ncr5380_wait_not_req(sc)) { + NCR_TRACE("msg_out: stuck REQ, n=%d\n", n); + act_flags |= ACT_RESET_BUS; + } + + /* Finally, drop ACK. */ + icmd &= ~SCI_ICMD_ACK; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + /* Stuck bus or something... */ + if (act_flags & ACT_RESET_BUS) + goto out; + + } + progress++; + + /* We get here only if the entire message has been transmitted. */ + if (sc->sc_msgpriq != 0) { + /* There are more outgoing messages. */ + goto nextmsg; + } + + /* + * The last message has been transmitted. We need to remember the last + * message transmitted (in case the target switches to MESSAGE IN phase + * and sends a MESSAGE REJECT), and the list of messages transmitted + * this time around (in case the target stays in MESSAGE OUT phase to + * request a retransmit). + */ + +out: + /* Stop driving the data bus. */ + icmd &= ~SCI_ICMD_DATA; + SetReg ( sc->sci_icmd, icmd ); +/* *sc->sci_icmd = icmd; */ + + if (!progress) + act_flags |= ACT_RESET_BUS; + + return (act_flags); +} + + +/* + * Handle command phase. + */ +static int +ncr5380_command(sc) + struct ncr5380_softc *sc; +{ + struct sci_req *sr = sc->sc_current; + struct scsi_xfer *xs = sr->sr_xs; + struct scsi_sense rqs; + int len; + + /* acknowledge phase change */ + SetReg ( sc->sci_tcmd, PHASE_COMMAND ); +/* *sc->sci_tcmd = PHASE_COMMAND; */ + + if (sr->sr_flags & SR_SENSE) { + rqs.opcode = REQUEST_SENSE; + rqs.byte2 = xs->sc_link->lun << 5; + rqs.length = sizeof(xs->sense); + + rqs.unused[0] = rqs.unused[1] = rqs.control = 0; + len = ncr5380_pio_out(sc, PHASE_COMMAND, sizeof(rqs), + (u_char *)&rqs); + } + else { + /* Assume command can be sent in one go. */ + /* XXX: Do this using DMA, and get a phase change intr? */ + len = ncr5380_pio_out(sc, PHASE_COMMAND, xs->cmdlen, + (u_char *)xs->cmd); + } + + if (len != xs->cmdlen) { +#ifdef DEBUG + printf("ncr5380_command: short transfer: wanted %d got %d.\n", + xs->cmdlen, len); + ncr5380_show_scsi_cmd(xs); + NCR_BREAK(); +#endif + if (len < 6) { + xs->error = XS_DRIVER_STUFFUP; + sc->sc_state |= NCR_ABORTING; + ncr_sched_msgout(sc, SEND_ABORT); + } + + } + + return ACT_CONTINUE; +} + + +/* + * Handle either data_in or data_out + */ +static int +ncr5380_data_xfer(sc, phase) + struct ncr5380_softc *sc; + int phase; +{ + struct sci_req *sr = sc->sc_current; + struct scsi_xfer *xs = sr->sr_xs; + int expected_phase; + int i, len; + + if (sr->sr_flags & SR_SENSE) { + NCR_TRACE("data_xfer: get sense, sr=0x%x\n", (long)sr); + if (phase != PHASE_DATA_IN) { + printf("%s: sense phase error\n", sc->sc_dev.dv_xname); + goto abort; + } + /* acknowledge phase change */ + SetReg ( sc->sci_tcmd, PHASE_DATA_IN ); +/* *sc->sci_tcmd = PHASE_DATA_IN; */ + len = ncr5380_pio_in(sc, phase, sizeof(xs->sense), + (u_char *)&xs->sense); + return ACT_CONTINUE; + } + + /* + * When aborting a command, disallow any data phase. + */ + if (sc->sc_state & NCR_ABORTING) { + printf("%s: aborting, but phase=%s (reset)\n", + sc->sc_dev.dv_xname, + phase_names[phase & 7]); + return ACT_RESET_BUS; /* XXX */ + } + + /* Validate expected phase (data_in or data_out) */ + expected_phase = (xs->flags & SCSI_DATA_OUT) ? + PHASE_DATA_OUT : PHASE_DATA_IN; + if (phase != expected_phase) { + printf("%s: data phase error\n", + sc->sc_dev.dv_xname); + goto abort; + } + + /* Make sure we have some data to move. */ + if (sc->sc_datalen <= 0) { + printf("%s: can not transfer more data\n", + sc->sc_dev.dv_xname); + goto abort; + } + + /* + * Attempt DMA only if dma_alloc gave us a DMA handle AND + * there is enough left to transfer so DMA is worth while. + */ + if (sr->sr_dma_hand && + (sc->sc_datalen >= sc->sc_min_dma_len)) + { + /* + * OK, really start DMA. Note, the MI start function + * is responsible for setting the TCMD register, etc. + * (Acknowledge the phase change there, not here.) + */ + NCR_TRACE("data_xfer: dma_start, dh=0x%x\n", + (long) sr->sr_dma_hand); + (*sc->sc_dma_start)(sc); + return ACT_WAIT_DMA; + } + + NCR_TRACE("data_xfer: doing PIO, len=%d\n", sc->sc_datalen); + + /* acknowledge phase change */ + SetReg ( sc->sci_tcmd, phase ); +/* *sc->sci_tcmd = phase; */ + if (phase == PHASE_DATA_OUT) { + len = ncr5380_pio_out(sc, phase, sc->sc_datalen, sc->sc_dataptr); + } else { + len = ncr5380_pio_in (sc, phase, sc->sc_datalen, sc->sc_dataptr); + } + sc->sc_dataptr += len; + sc->sc_datalen -= len; + + NCR_TRACE("data_xfer: did PIO, resid=%d\n", sc->sc_datalen); + return (ACT_CONTINUE); + +abort: + sc->sc_state |= NCR_ABORTING; + ncr_sched_msgout(sc, SEND_ABORT); + return (ACT_CONTINUE); +} + + +static int +ncr5380_status(sc) + struct ncr5380_softc *sc; +{ + int len; + u_char status; + struct sci_req *sr = sc->sc_current; + struct scsi_xfer *xs = sr->sr_xs; + + /* acknowledge phase change */ + SetReg ( sc->sci_tcmd, PHASE_STATUS ); +/* *sc->sci_tcmd = PHASE_STATUS; */ + + len = ncr5380_pio_in(sc, PHASE_STATUS, 1, &status); + if (len) { + sr->sr_status = status; + } else { + printf("ncr5380_status: none?\n"); + } + + return ACT_CONTINUE; +} + + +/* + * This is the big state machine that follows SCSI phase changes. + * This is somewhat like a co-routine. It will do a SCSI command, + * and exit if the command is complete, or if it must wait, i.e. + * for DMA to complete or for reselect to resume the job. + * + * The bus must be selected, and we need to know which command is + * being undertaken. + */ +static void +ncr5380_machine(sc) + struct ncr5380_softc *sc; +{ + struct sci_req *sr; + struct scsi_xfer *xs; + int act_flags, phase, timo; + +#ifdef DIAGNOSTIC + if ((getsr() & PSL_IPL) < PSL_IPL2) + panic("ncr5380_machine: bad spl"); + if (sc->sc_state == NCR_IDLE) + panic("ncr5380_machine: state=idle"); + if (sc->sc_current == NULL) + panic("ncr5380_machine: no current cmd"); +#endif + + sr = sc->sc_current; + xs = sr->sr_xs; + act_flags = ACT_CONTINUE; + + /* + * This will be called by ncr5380_intr() when DMA is + * complete. Must stop DMA before touching the 5380 or + * there will be "register conflict" errors. + */ + if (sc->sc_state & NCR_DOINGDMA) { + /* Pick-up where where we left off... */ + goto dma_done; + } + +next_phase: + + if (!SCI_BUSY(sc)) { + /* Unexpected disconnect */ + printf("ncr5380_machine: unexpected disconnect.\n"); + xs->error = XS_DRIVER_STUFFUP; + act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE); + goto do_actions; + } + + /* + * Wait for REQ before reading the phase. + * Need to wait longer than usual here, because + * some devices are just plain slow... + */ + timo = ncr5380_wait_phase_timo; + for (;;) { + if (*sc->sci_bus_csr & SCI_BUS_REQ) + break; + if (--timo <= 0) { + if (sc->sc_state & NCR_ABORTING) { + printf("%s: no REQ while aborting, reset\n", + sc->sc_dev.dv_xname); + act_flags |= ACT_RESET_BUS; + goto do_actions; + } + printf("%s: no REQ for next phase, abort\n", + sc->sc_dev.dv_xname); + sc->sc_state |= NCR_ABORTING; + ncr_sched_msgout(sc, SEND_ABORT); + goto next_phase; + } + delay(100); + } + + phase = SCI_BUS_PHASE(*sc->sci_bus_csr); + NCR_TRACE("machine: phase=%s\n", + (long) phase_names[phase & 7]); + + /* + * We assume that the device knows what it's doing, + * so any phase is good. + */ + +#if 0 + /* + * XXX: Do not ACK the phase yet! do it later... + * XXX: ... each phase routine does that itself. + * In particular, DMA needs it done LATER. + */ + SetReg ( sc->sci_tcmd, phase ); +/* *sc->sci_tcmd = phase; */ /* acknowledge phase change */ +#endif + + switch (phase) { + + case PHASE_DATA_OUT: + case PHASE_DATA_IN: + act_flags = ncr5380_data_xfer(sc, phase); + break; + + case PHASE_COMMAND: + act_flags = ncr5380_command(sc); + break; + + case PHASE_STATUS: + act_flags = ncr5380_status(sc); + break; + + case PHASE_MSG_OUT: + act_flags = ncr5380_msg_out(sc); + break; + + case PHASE_MSG_IN: + act_flags = ncr5380_msg_in(sc); + break; + + default: + printf("ncr5380_machine: Unexpected phase 0x%x\n", phase); + sc->sc_state |= NCR_ABORTING; + ncr_sched_msgout(sc, SEND_ABORT); + goto next_phase; + + } /* switch */ + sc->sc_prevphase = phase; + +do_actions: + __asm("_ncr5380_actions:"); + + if (act_flags & ACT_WAIT_DMA) { + act_flags &= ~ACT_WAIT_DMA; + /* Wait for DMA to complete (polling, or interrupt). */ + if ((sr->sr_flags & SR_IMMED) == 0) { + NCR_TRACE("machine: wait for DMA intr.\n", 0); + return; /* will resume at dma_done */ + } + /* Busy-wait for it to finish. */ + NCR_TRACE("machine: dma_poll, dh=0x%x\n", + (long) sr->sr_dma_hand); + (*sc->sc_dma_poll)(sc); + dma_done: + /* Return here after interrupt. */ + if (sr->sr_flags & SR_OVERDUE) + sc->sc_state |= NCR_ABORTING; + NCR_TRACE("machine: dma_stop, dh=0x%x\n", + (long) sr->sr_dma_hand); + (*sc->sc_dma_stop)(sc); + SCI_CLR_INTR(sc); /* XXX */ + /* + * While DMA is running we can not touch the SBC, + * so various places just set NCR_ABORTING and + * expect us the "kick it" when DMA is done. + */ + if (sc->sc_state & NCR_ABORTING) { + ncr_sched_msgout(sc, SEND_ABORT); + } + } + + /* + * Check for parity error. + * XXX - better place to check? + */ + if (*(sc->sci_csr) & SCI_CSR_PERR) { + printf("%s: parity error csr = %02x!\n", + sc->sc_dev.dv_xname, *(sc->sci_csr) ); + /* XXX: sc->sc_state |= NCR_ABORTING; */ + ncr_sched_msgout(sc, SEND_PARITY_ERROR); + } + + if (act_flags == ACT_CONTINUE) + goto next_phase; + /* All other actions "break" from the loop. */ + + NCR_TRACE("machine: act_flags=0x%x\n", act_flags); + + if (act_flags & ACT_RESET_BUS) { + act_flags |= ACT_CMD_DONE; + /* + * Reset the SCSI bus, usually due to a timeout. + * The error code XS_TIMEOUT allows retries. + */ + sc->sc_state |= NCR_ABORTING; + printf("%s: reset SCSI bus for TID=%d LUN=%d\n", + sc->sc_dev.dv_xname, + sr->sr_target, sr->sr_lun); + ncr5380_reset_scsibus(sc); + } + + if (act_flags & ACT_CMD_DONE) { + act_flags |= ACT_DISCONNECT; + /* Need to call scsi_done() */ + /* XXX: from the aic6360 driver, but why? */ + if (sc->sc_datalen < 0) { + printf("%s: %d extra bytes from %d:%d\n", + sc->sc_dev.dv_xname, -sc->sc_datalen, + sr->sr_target, sr->sr_lun); + sc->sc_datalen = 0; + } + xs->resid = sc->sc_datalen; + /* Note: this will clear sc_current */ + NCR_TRACE("machine: call done, cur=0x%x\n", (long)sr); + ncr5380_done(sc); + } + + if (act_flags & ACT_DISCONNECT) { + /* + * The device has dropped BSY (or will soon). + * Return and let ncr5380_sched() do its thing. + */ + SetReg ( sc->sci_icmd, 0 ); + SetReg ( sc->sci_mode, 0 ); + SetReg ( sc->sci_tcmd, PHASE_INVALID ); + SetReg ( sc->sci_sel_enb, 0 ); + +/* *sc->sci_icmd = 0; + *sc->sci_mode = 0; + *sc->sci_tcmd = PHASE_INVALID; + *sc->sci_sel_enb = 0; */ + + SCI_CLR_INTR(sc); + SetReg ( sc->sci_sel_enb, 0x80 ); + *sc->sci_sel_enb = 0x80; + + if ((act_flags & ACT_CMD_DONE) == 0) { + __asm("_ncr5380_disconnected:"); + NCR_TRACE("machine: discon, cur=0x%x\n", (long)sr); + } + + /* + * We may be here due to a disconnect message, + * in which case we did NOT call ncr5380_done, + * and we need to clear sc_current. + */ + sc->sc_state = NCR_IDLE; + sc->sc_current = NULL; + + /* Paranoia: clear everything. */ + sc->sc_dataptr = NULL; + sc->sc_datalen = 0; + sc->sc_prevphase = PHASE_INVALID; + sc->sc_msgpriq = 0; + sc->sc_msgoutq = 0; + sc->sc_msgout = 0; + + /* Our caller will re-enable interrupts. */ + } +} + + +#ifdef DEBUG + +static void +ncr5380_show_scsi_cmd(xs) + struct scsi_xfer *xs; +{ + u_char *b = (u_char *) xs->cmd; + int i = 0; + + if ( ! ( xs->flags & SCSI_RESET ) ) { + printf("si(%d:%d:%d)-", + xs->sc_link->scsibus, + xs->sc_link->target, + xs->sc_link->lun); + while (i < xs->cmdlen) { + if (i) printf(","); + printf("%x",b[i++]); + } + printf("-\n"); + } else { + printf("si(%d:%d:%d)-RESET-\n", + xs->sc_link->scsibus, + xs->sc_link->target, + xs->sc_link->lun); + } +} + + +static void +ncr5380_show_sense(xs) + struct scsi_xfer *xs; +{ + u_char *b = (u_char *)&xs->sense; + int i; + + printf("sense:"); + for (i = 0; i < sizeof(xs->sense); i++) + printf(" %02x", b[i]); + printf("\n"); +} + +int ncr5380_traceidx = 0; + +#define TRACE_MAX 1024 +struct trace_ent { + char *msg; + long val; +} ncr5380_tracebuf[TRACE_MAX]; + +void +ncr5380_trace(msg, val) + char *msg; + long val; +{ + register struct trace_ent *tr; + register int s; + + s = splhigh(); + + tr = &ncr5380_tracebuf[ncr5380_traceidx]; + + ncr5380_traceidx++; + if (ncr5380_traceidx >= TRACE_MAX) + ncr5380_traceidx = 0; + + tr->msg = msg; + tr->val = val; + + splx(s); +} + +#ifdef DDB +void +ncr5380_clear_trace() +{ + ncr5380_traceidx = 0; + bzero((char*) ncr5380_tracebuf, sizeof(ncr5380_tracebuf)); +} + +void +ncr5380_show_trace() +{ + struct trace_ent *tr; + int idx; + + idx = ncr5380_traceidx; + do { + tr = &ncr5380_tracebuf[idx]; + idx++; + if (idx >= TRACE_MAX) + idx = 0; + if (tr->msg) + db_printf(tr->msg, tr->val); + } while (idx != ncr5380_traceidx); +} + +void +ncr5380_show_req(sr) + struct sci_req *sr; +{ + struct scsi_xfer *xs = sr->sr_xs; + + db_printf("TID=%d ", sr->sr_target); + db_printf("LUN=%d ", sr->sr_lun); + db_printf("dh=0x%x ", sr->sr_dma_hand); + db_printf("dptr=0x%x ", sr->sr_dataptr); + db_printf("dlen=0x%x ", sr->sr_datalen); + db_printf("flags=%d ", sr->sr_flags); + db_printf("stat=%d ", sr->sr_status); + + if (xs == NULL) { + db_printf("(xs=NULL)\n"); + return; + } + db_printf("\n"); +#ifdef SCSIDEBUG + show_scsi_xs(xs); +#else + db_printf("xs=0x%x\n", xs); +#endif +} + +void +ncr5380_show_state() +{ + struct ncr5380_softc *sc; + struct sci_req *sr; + int i, j, k; + + sc = ncr5380_debug_sc; + + if (sc == NULL) { + db_printf("ncr5380_debug_sc == NULL\n"); + return; + } + + db_printf("sc_ncmds=%d\n", sc->sc_ncmds); + k = -1; /* which is current? */ + for (i = 0; i < SCI_OPENINGS; i++) { + sr = &sc->sc_ring[i]; + if (sr->sr_xs) { + if (sr == sc->sc_current) + k = i; + db_printf("req %d: (sr=0x%x)", i, (long)sr); + ncr5380_show_req(sr); + } + } + db_printf("sc_rr=%d, current=%d\n", sc->sc_rr, k); + + db_printf("Active request matrix:\n"); + for(i = 0; i < 8; i++) { /* targets */ + for (j = 0; j < 8; j++) { /* LUN */ + sr = sc->sc_matrix[i][j]; + if (sr) { + db_printf("TID=%d LUN=%d sr=0x%x\n", i, j, (long)sr); + } + } + } + + db_printf("sc_state=0x%x\n", sc->sc_state); + db_printf("sc_current=0x%x\n", sc->sc_current); + db_printf("sc_dataptr=0x%x\n", sc->sc_dataptr); + db_printf("sc_datalen=0x%x\n", sc->sc_datalen); + + db_printf("sc_prevphase=%d\n", sc->sc_prevphase); + db_printf("sc_msgpriq=0x%x\n", sc->sc_msgpriq); +} + +#endif /* DDB */ +#endif /* DEBUG */ diff --git a/sys/arch/arm32/podulebus/ncr5380var.h b/sys/arch/arm32/podulebus/ncr5380var.h new file mode 100644 index 00000000000..0ad0637e1a0 --- /dev/null +++ b/sys/arch/arm32/podulebus/ncr5380var.h @@ -0,0 +1,178 @@ +/* $NetBSD: ncr5380var.h,v 1.1 1996/01/31 23:26:12 mark Exp $ */ + +/* + * Copyright (c) 1995 David Jones, Gordon W. Ross + * Copyright (c) 1994 Jarle Greipsland + * 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 authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 4. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by + * David Jones and Gordon Ross + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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 defines the interface between the machine-dependent + * module and the machine-indepenedent ncr5380sbc.c module. + */ + +#define SCI_CLR_INTR(sc) (*(sc)->sci_iack) +#define SCI_BUSY(sc) (*sc->sci_bus_csr & SCI_BUS_BSY) + +/* These are NOT artibtrary, but map to bits in sci_tcmd */ +#define PHASE_DATA_OUT 0x0 +#define PHASE_DATA_IN 0x1 +#define PHASE_COMMAND 0x2 +#define PHASE_STATUS 0x3 +#define PHASE_UNSPEC1 0x4 +#define PHASE_UNSPEC2 0x5 +#define PHASE_MSG_OUT 0x6 +#define PHASE_MSG_IN 0x7 + +/* + * This illegal phase is used to prevent the 5380 from having + * a phase-match condition when we don't want one, such as + * when setting up the DMA engine or whatever... + */ +#define PHASE_INVALID PHASE_UNSPEC1 + + +/* Per-request state. This is required in order to support reselection. */ +struct sci_req { + struct scsi_xfer *sr_xs; /* Pointer to xfer struct, NULL=unused */ + int sr_target, sr_lun; /* For fast access */ + void *sr_dma_hand; /* Current DMA hnadle */ + u_char *sr_dataptr; /* Saved data pointer */ + int sr_datalen; + int sr_flags; /* Internal error code */ +#define SR_IMMED 1 /* Immediate command */ +#define SR_SENSE 2 /* We are getting sense */ +#define SR_OVERDUE 4 /* Timeout while not current */ +#define SR_ERROR 8 /* Error occurred */ + int sr_status; /* Status code from last cmd */ +}; +#define SCI_OPENINGS 16 /* How many commands we can enqueue. */ + + +struct ncr5380_softc { + struct device sc_dev; + struct scsi_link sc_link; + + /* Pointers to 5380 registers. See ncr5380reg.h */ + volatile u_char *sci_r0; + volatile u_char *sci_r1; + volatile u_char *sci_r2; + volatile u_char *sci_r3; + volatile u_char *sci_r4; + volatile u_char *sci_r5; + volatile u_char *sci_r6; + volatile u_char *sci_r7; + + /* Functions set from MD code */ + int (*sc_pio_out) __P((struct ncr5380_softc *, + int, int, u_char *)); + int (*sc_pio_in) __P((struct ncr5380_softc *, + int, int, u_char *)); + void (*sc_dma_alloc) __P((struct ncr5380_softc *)); + void (*sc_dma_free) __P((struct ncr5380_softc *)); + + void (*sc_dma_setup) __P((struct ncr5380_softc *)); + void (*sc_dma_start) __P((struct ncr5380_softc *)); + void (*sc_dma_poll) __P((struct ncr5380_softc *)); + void (*sc_dma_eop) __P((struct ncr5380_softc *)); + void (*sc_dma_stop) __P((struct ncr5380_softc *)); + + void (*sc_intr_on) __P((struct ncr5380_softc *)); + void (*sc_intr_off) __P((struct ncr5380_softc *)); + + int sc_flags; /* Misc. flags and capabilities */ +#define NCR5380_PERMIT_RESELECT 1 /* Allow disconnect/reselect */ +#define NCR5380_FORCE_POLLING 2 /* Do not use interrupts. */ + + int sc_min_dma_len; /* Smaller than this is done with PIO */ + + /* Begin MI shared data */ + + int sc_state; +#define NCR_IDLE 0 /* Ready for new work. */ +#define NCR_WORKING 0x01 /* Some command is in progress. */ +#define NCR_ABORTING 0x02 /* Bailing out */ +#define NCR_DOINGDMA 0x04 /* The FIFO data path is active! */ +#define NCR_DROP_MSGIN 0x10 /* Discard all msgs (parity err detected) */ + + /* The request that has the bus now. */ + struct sci_req *sc_current; + + /* Active data pointer for current SCSI command. */ + u_char *sc_dataptr; + int sc_datalen; + + /* Begin MI private data */ + + /* The number of operations in progress on the bus */ + volatile int sc_ncmds; + + /* Ring buffer of pending/active requests */ + struct sci_req sc_ring[SCI_OPENINGS]; + int sc_rr; /* Round-robin scan pointer */ + + /* Active requests, by target/LUN */ + struct sci_req *sc_matrix[8][8]; + + /* Message stuff */ + int sc_prevphase; + + u_int sc_msgpriq; /* Messages we want to send */ + u_int sc_msgoutq; /* Messages sent during last MESSAGE OUT */ + u_int sc_msgout; /* Message last transmitted */ +#define SEND_DEV_RESET 0x01 +#define SEND_PARITY_ERROR 0x02 +#define SEND_ABORT 0x04 +#define SEND_REJECT 0x08 +#define SEND_INIT_DET_ERR 0x10 +#define SEND_IDENTIFY 0x20 +#define SEND_SDTR 0x40 +#define SEND_WDTR 0x80 +#define NCR_MAX_MSG_LEN 8 + u_char sc_omess[NCR_MAX_MSG_LEN]; + u_char *sc_omp; /* Outgoing message pointer */ + u_char sc_imess[NCR_MAX_MSG_LEN]; + u_char *sc_imp; /* Incoming message pointer */ + +}; + +void ncr5380_init __P((struct ncr5380_softc *)); +void ncr5380_reset_scsibus __P((struct ncr5380_softc *)); +int ncr5380_intr __P((struct ncr5380_softc *)); +int ncr5380_scsi_cmd __P((struct scsi_xfer *)); +int ncr5380_pio_in __P((struct ncr5380_softc *, int, int, u_char *)); +int ncr5380_pio_out __P((struct ncr5380_softc *, int, int, u_char *)); + +#ifdef DEBUG +struct ncr5380_softc *ncr5380_debug_sc; +void ncr5380_trace __P((char *msg, long val)); +#define NCR_TRACE(msg, val) ncr5380_trace(msg, val) +#else +#define NCR_TRACE(msg, val) /* nada */ +#endif diff --git a/sys/arch/arm32/podulebus/oak.c b/sys/arch/arm32/podulebus/oak.c new file mode 100644 index 00000000000..48922d6159e --- /dev/null +++ b/sys/arch/arm32/podulebus/oak.c @@ -0,0 +1,381 @@ +/* $NetBSD: oak.c,v 1.3 1996/03/17 01:24:51 thorpej Exp $ */ + +/* + * Copyright (c) 1995 Melvin Tang-Richardson 1996. + * 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 RiscBSD. + * 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 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. + * + * oak.c + * + * Oak SCSI Driver. + */ + +#undef USE_OWN_PIO_ROUTINES + +/* Some system includes *****************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ + +/* SCSI bus includes */ + +#include +#include + +/* Hardware related include chip/card/bus ***********************************/ + +#include +#include +#include +#include +#include +#include + +/****************************************************************************/ +/* Some useful definitions **************************************************/ +/****************************************************************************/ + +#define MY_MANUFACTURER (0x21) +#define MY_PODULE (0x58) +#define MAX_DMA_LEN (0xe000) + +/****************************************************************************/ +/* Prototype internal data structures ***************************************/ +/****************************************************************************/ + +struct oak_softc { + struct ncr5380_softc ncr_sc; + int sc_podule; + int sc_base; +}; + +/****************************************************************************/ +/* Function and data prototypes *********************************************/ +/****************************************************************************/ + +int oakprobe __P(( struct device *, void *, void * )); +void oakattach __P(( struct device *, struct device *, void * )); +int oakprint __P(( void *, char * )); +void oakminphys __P(( struct buf * )); + +#ifdef USE_OWN_PIO_ROUTINES +int oak_pio_in __P(( struct ncr5380_softc *, int, int, unsigned char * )); +int oak_pio_out __P(( struct ncr5380_softc *, int, int, unsigned char * )); +#endif + +struct scsi_adapter oak_adapter = { + ncr5380_scsi_cmd, + oakminphys, + NULL, + NULL, +}; + +struct scsi_device oak_device = { + NULL, + NULL, + NULL, + NULL, +}; + +int +oakprobe(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct oak_softc *sc = (void *) match; + struct podule_attach_args *pa = (void *) aux; + int podule; + + podule = findpodule(MY_MANUFACTURER, MY_PODULE, pa->pa_podule_number); + + if (podule == -1) + return 0; + + sc->sc_podule = podule; + sc->sc_base = podules[podule].mod_base; + + return 1; +} + +void +oakattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct oak_softc *sc = (void *) self; + struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)sc; + struct podule_attach_args *pa = (void *)aux; + + printf(" 16-bit"); + + ncr_sc->sc_link.adapter_softc = sc; + ncr_sc->sc_link.adapter_target = 7; + ncr_sc->sc_link.adapter = &oak_adapter; + ncr_sc->sc_link.device = &oak_device; + + ncr_sc->sci_r0 = (volatile u_char *)sc->sc_base + 0x00; + ncr_sc->sci_r1 = (volatile u_char *)sc->sc_base + 0x04; + ncr_sc->sci_r2 = (volatile u_char *)sc->sc_base + 0x08; + ncr_sc->sci_r3 = (volatile u_char *)sc->sc_base + 0x0c; + ncr_sc->sci_r4 = (volatile u_char *)sc->sc_base + 0x10; + ncr_sc->sci_r5 = (volatile u_char *)sc->sc_base + 0x14; + ncr_sc->sci_r6 = (volatile u_char *)sc->sc_base + 0x18; + ncr_sc->sci_r7 = (volatile u_char *)sc->sc_base + 0x1c; + +#ifdef USE_OWN_PIO_ROUTINES + printf ( ", my pio" ); + ncr_sc->sc_pio_out = oak_pio_out; + ncr_sc->sc_pio_in = oak_pio_in; +#else + printf ( ", normal pio" ); + ncr_sc->sc_pio_out = ncr5380_pio_out; + ncr_sc->sc_pio_in = ncr5380_pio_in; +#endif + + ncr_sc->sc_dma_alloc = NULL; + ncr_sc->sc_dma_free = NULL; + ncr_sc->sc_dma_poll = NULL; + ncr_sc->sc_dma_setup = NULL; + ncr_sc->sc_dma_start = NULL; + ncr_sc->sc_dma_eop = NULL; + ncr_sc->sc_dma_stop = NULL; + + printf(", polling"); + ncr_sc->sc_intr_on = NULL; + ncr_sc->sc_intr_off = NULL; + + ncr_sc->sc_flags = NCR5380_FORCE_POLLING; + + ncr5380_init(ncr_sc); + ncr5380_reset_scsibus(ncr_sc); + + printf(" UNDER DEVELOPMENT\n"); + + config_found(self, &(ncr_sc->sc_link), oakprint); +} + +int +oakprint(aux, name) + void *aux; + char *name; +{ + if (name != NULL) + printf("%s: scsibus ", name); + return UNCONF; +} + +void +oakminphys(bp) + struct buf *bp; +{ + if (bp->b_bcount > MAX_DMA_LEN) { + printf("oak: DEBUG reducing dma length\n"); + bp->b_bcount = MAX_DMA_LEN; + } + return (minphys(bp)); +} + +struct cfattach oak_ca = { + sizeof(struct oak_softc), oakprobe, oakattach +}; + +struct cfdriver oak_cd = { + NULL, "oak", DV_DISK, NULL, 0, +}; + +#ifdef USE_OWN_PIO_ROUTINES + +/****************************************************************************/ +/* Copyright (c) 1996 Melvin Tang-Richardson */ +/* Copyright (c) 1995 David Jones, Gordon W. Rose */ +/* Copyright (c) 1994 Jarle Greipsland */ +/****************************************************************************/ + +static ncr5380_wait_req_timo = 1000 * 50; /* X2 = 100 mS */ +static ncr5380_wait_nrq_timo = 1000 * 25; /* X2 = 50 mS */ + +/* Return zero on success. */ +static __inline__ int ncr5380_wait_req(sc) + struct ncr5380_softc *sc; +{ + register int timo = ncr5380_wait_req_timo; + for (;;) { + if (*sc->sci_bus_csr & SCI_BUS_REQ) { + timo = 0; /* return 0 */ + break; + } + if (--timo < 0) + break; /* return -1 */ + delay(2); + } + return (timo); +} + +/* Return zero on success. */ +static __inline__ int ncr5380_wait_not_req(sc) + struct ncr5380_softc *sc; +{ + register int timo = ncr5380_wait_nrq_timo; + for (;;) { + if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) { + timo = 0; /* return 0 */ + break; + } + if (--timo < 0) + break; /* return -1 */ + delay(2); + } + return (timo); +} + +int +oak_pio_out(sc, phase, count, data) + struct ncr5380_softc *sc; + int phase, count; + unsigned char *data; +{ + register u_char icmd; + register int resid; + register int error; + + printf("oak: pio_out %d %d\n", phase, count); + + icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK; + + icmd |= SCI_ICMD_DATA; + *sc->sci_icmd = icmd; + + resid = count; + while (resid > 0) { + if (!SCI_BUSY(sc)) { + NCR_TRACE("pio_out: lost BSY, resid=%d\n", resid); + break; + } + if (ncr5380_wait_req(sc)) { + NCR_TRACE("pio_out: no REQ, resid=%d\n", resid); + break; + } + if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase) + break; + + /* Put the data on the bus. */ + *sc->sci_odata = *data++; + + /* Tell the target it's there. */ + icmd |= SCI_ICMD_ACK; + *sc->sci_icmd = icmd; + + /* Wait for target to get it. */ + error = ncr5380_wait_not_req(sc); + + /* OK, it's got it (or we gave up waiting). */ + icmd &= ~SCI_ICMD_ACK; + *sc->sci_icmd = icmd; + + if (error) { + NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid); + break; + } + + --resid; + } + + /* Stop driving the data bus. */ + icmd &= ~SCI_ICMD_DATA; + *sc->sci_icmd = icmd; + + return (count - resid); +} + +int +oak_pio_in(sc, phase, count, data) + struct ncr5380_softc *sc; + int phase, count; + unsigned char *data; +{ + register u_char icmd; + register int resid; + register int error; + + printf("oak: pio_in %d %d\n", phase, count); + + icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK; + + resid = count; + while (resid > 0) { + if (!SCI_BUSY(sc)) { + NCR_TRACE("pio_in: lost BSY, resid=%d\n", resid); + break; + } + if (ncr5380_wait_req(sc)) { + NCR_TRACE("pio_in: no REQ, resid=%d\n", resid); + break; + } + /* A phase change is not valid until AFTER REQ rises! */ + if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase) + break; + + /* Read the data bus. */ + *data++ = *sc->sci_data; + + /* Tell target we got it. */ + icmd |= SCI_ICMD_ACK; + *sc->sci_icmd = icmd; + + /* Wait for target to drop REQ... */ + error = ncr5380_wait_not_req(sc); + + /* OK, we can drop ACK. */ + icmd &= ~SCI_ICMD_ACK; + *sc->sci_icmd = icmd; + + if (error) { + NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid); + break; + } + + --resid; + } + + return (count - resid); +} + +#endif /* USE_OWN_PIO_ROUTINES */ + diff --git a/sys/arch/arm32/podulebus/podulebus.c b/sys/arch/arm32/podulebus/podulebus.c new file mode 100644 index 00000000000..4ca0e18aa2b --- /dev/null +++ b/sys/arch/arm32/podulebus/podulebus.c @@ -0,0 +1,627 @@ +/* $NetBSD: podulebus.c,v 1.5 1996/03/27 22:07:26 mark Exp $ */ + +/* + * Copyright (c) 1994,1995 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 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.c + * + * Podule probe and configuration routines + * + * Created : 07/11/94 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Now construct the table of know podules. + * A podule description array is setup for each manufacturer id + */ + +struct podule_description podules_0000[] = { + { 0x02, "SCSI interface" }, + { 0x03, "ether 1 interface" }, + { 0x61, "ether 2 interface" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0004[] = { + { 0x14, "laser direct (Canon LBP-4)" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0009[] = { + { 0x52, "hawk V9 mark2" }, + { 0xcb, "scanlight Video256" }, + { 0xcc, "eagle M2" }, + { 0xce, "lark A16" }, + { 0x200, "MIDI max" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0011[] = { + { 0xa4, "ether 3 interface" }, + { 0x00, NULL }, +}; + +struct podule_description podules_001a[] = { + { 0x95, "16 bit SCSI interface" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0021[] = { + { 0x58, "16 bit SCSI interface" }, + { 0x00, NULL }, +}; + +struct podule_description podules_002b[] = { + { 0x67, "SCSI interface" }, + { 0x00, NULL }, +}; + +struct podule_description podules_003a[] = { + { 0x3a, "SCSI II interface" }, + { 0xdd, "CDFS & SLCD expansion card" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0041[] = { + { 0x41, "16 bit SCSI interface" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0042[] = { + { 0xea, "PC card" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0046[] = { + { 0xec, "etherlan 600 network slot interface" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0050[] = { + { 0x00, "BriniPort intelligent I/O interface" }, + { 0xdf, "BriniLink transputer link adapter" }, + { 0x00, NULL }, +}; + +struct podule_description podules_0053[] = { + { 0xe4, "ether B network slot interface" }, + { 0x00, NULL }, +}; + +struct podule_description podules_005b[] = { + { 0x107, "SCSI 1 / SCSI 2 host adapter" }, + { 0x00, NULL }, +}; + +/* A podule list if setup for all the manufacturers */ + +struct podule_list known_podules[] = { + { 0x00, "Acorn", podules_0000 }, + { 0x04, "CConcepts", podules_0004 }, /* Two codes ??? */ + { 0x09, "CConcepts", podules_0009 }, + { 0x11, "Atomwide", podules_0011 }, + { 0x1a, "Lingenuity", podules_001a }, + { 0x21, "Oak", podules_0021 }, + { 0x2b, "Morley", podules_002b }, + { 0x3a, "Cumana", podules_003a }, + { 0x41, "ARXE", podules_0041 }, + { 0x42, "Aleph1", podules_0042 }, + { 0x46, "I-Cubed", podules_0046 }, + { 0x50, "Brini", podules_0050 }, + { 0x53, "ANT", podules_0053 }, + { 0x5b, "Power-tec", podules_005b }, +}; + +/* Array of podule structures, one per possible podule */ + +podule_t podules[MAX_PODULES + MAX_NETSLOTS]; +irqhandler_t poduleirq; +extern u_int actual_mask; +extern irqhandler_t *irqhandlers[NIRQS]; + +/* Declare prototypes */ + +void map_section __P((vm_offset_t, vm_offset_t, vm_offset_t)); +int poduleirqhandler __P((void)); +u_int poduleread __P((u_int /*address*/, int /*offset*/, int /*slottype*/)); + + +/* + * int podulebusmatch(struct device *parent, void *match, void *aux) + * + * Probe for the podule bus. Currently all this does is return 1 to + * indicate that the podule bus was found. + */ + +int +podulebusmatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + return (1); +} + + +int +podulebusprint(aux, podulebus) + void *aux; + char *podulebus; +{ + struct podule_attach_args *pa = aux; + + if (pa->pa_podule != NULL) { + if (pa->pa_podule->slottype == SLOT_POD) + printf(" [ podule %d ]:", pa->pa_podule_number); + else if (pa->pa_podule->slottype == SLOT_NET) + printf(" [ netslot %d ]:", pa->pa_podule_number - MAX_PODULES); + else + panic("Invalid slot type\n"); + } + +/* XXXX print flags */ + return (QUIET); +} + + +void +podulebusscan(parent, match) + struct device *parent; + void *match; +{ + struct device *dev = match; + struct cfdata *cf = dev->dv_cfdata; + struct podule_attach_args pa; + + if (cf->cf_fstate == FSTATE_STAR) + panic("nope cannot handle this"); + + pa.pa_podule = NULL; + pa.pa_podule_number = -1; + + if (cf->cf_loc[0] != -1) { + pa.pa_podule_number = cf->cf_loc[0]; + } + + if ((*cf->cf_attach->ca_match)(parent, dev, &pa) > 0) + config_attach(parent, dev, &pa, podulebusprint); + else + free(dev, M_DEVBUF); +} + + +void +dump_podule(podule) + podule_t *podule; +{ + printf("podule%d: ", podule->podulenum); + printf("flags0=%02x ", podule->flags0); + printf("flags1=%02x ", podule->flags1); + printf("reserved=%02x ", podule->reserved); + printf("product=%02x ", podule->product); + printf("manufacturer=%02x ", podule->manufacturer); + printf("country=%02x ", podule->country); + printf("irq_addr=%08x ", podule->irq_addr); + printf("irq_mask=%02x ", podule->irq_mask); + printf("fiq_addr=%08x ", podule->fiq_addr); + printf("fiq_mask=%02x ", podule->fiq_mask); + printf("fast_base=%08x ", podule->fast_base); + printf("medium_base=%08x ", podule->medium_base); + printf("slow_base=%08x ", podule->slow_base); + printf("sync_base=%08x ", podule->sync_base); + printf("mod_base=%08x ", podule->mod_base); + printf("easi_base=%08x ", podule->easi_base); + printf("attached=%d ", podule->attached); + printf("slottype=%d ", podule->slottype); + printf("podulenum=%d ", podule->podulenum); + printf("\n"); +} + + +void +podulechunkdirectory(podule) + podule_t *podule; +{ + u_int address; + u_int id; + u_int size; + u_int addr; + int loop; + + address = 0x40; + + do { + id = poduleread(podule->slow_base, address, podule->slottype); + size = poduleread(podule->slow_base, address + 4, podule->slottype); + size |= (poduleread(podule->slow_base, address + 8, podule->slottype) << 8); + size |= (poduleread(podule->slow_base, address + 12, podule->slottype) << 16); + if (id == 0xf5) { + addr = poduleread(podule->slow_base, address + 16, podule->slottype); + addr |= (poduleread(podule->slow_base, address + 20, podule->slottype) << 8); + addr |= (poduleread(podule->slow_base, address + 24, podule->slottype) << 16); + addr |= (poduleread(podule->slow_base, address + 28, podule->slottype) << 24); + if (addr < 0x800) { + for (loop = 0; loop < size; ++loop) + printf("%c", poduleread(podule->slow_base, (addr + loop)*4, podule->slottype)); + printf("\n"); + } + } + address += 32; + } while (id != 0 && address < 0x800); +} + + +void +poduleexamine(podule, dev, slottype) + podule_t *podule; + struct device *dev; + int slottype; +{ + struct podule_list *pod_list; + struct podule_description *pod_desc; + +/* Test to see if the podule is present */ + + if ((podule->flags0 & 0x02) == 0x00) { + podule->slottype = slottype; + if (slottype == SLOT_NET) + printf("netslot%d at %s : ", podule->podulenum - MAX_PODULES, + dev->dv_xname); + else + printf("podule%d at %s : ", podule->podulenum, + dev->dv_xname); + +/* Is it Acorn conformant ? */ + + if (podule->flags0 & 0x80) + printf("Non-Acorn conformant expansion card\n"); + else { + int id; + +/* Is it a simple podule ? */ + + id = (podule->flags0 >> 3) & 0x0f; + if (id != 0) + printf("Simple expansion card <%x>\n", id); + else { +/* Do we know this manufacturer ? */ + pod_list = known_podules; + while (pod_list->description) { + if (pod_list->manufacturer_id == podule->manufacturer) + break; + ++pod_list; + } + if (!pod_list->description) + printf("man=%04x : ", podule->manufacturer); + else + printf("%10s : ", pod_list->description); + +/* Do we know this product ? */ + + pod_desc = pod_list->products; + while (pod_desc->description) { + if (pod_desc->product_id == podule->product) + break; + ++pod_desc; + } + if (!pod_desc->description) + printf("prod=%04x\n", podule->product); + else + printf("%s\n", pod_desc->description); + + if (pod_desc->description == NULL + && podule->flags1 & PODULE_FLAGS_CD) + podulechunkdirectory(podule); + } + } + } +} + + +u_int +poduleread(address, offset, slottype) + u_int address; + int offset; + int slottype; +{ + static u_int netslotoffset; + + if (slottype == SLOT_NET) { + offset = offset >> 2; + if (offset < netslotoffset) { + WriteWord(address, 0); + netslotoffset = 0; + } + while (netslotoffset < offset) { + slottype = ReadWord(address); + ++netslotoffset; + } + ++netslotoffset; + return(ReadByte(address)); + } + return(ReadByte(address + offset)); +} + + +void +podulescan(dev) + struct device *dev; +{ + int loop; + podule_t *podule; + u_char *address; + u_int offset = 0; + +/* Loop round all the podules */ + + for (loop = 0; loop < MAX_PODULES; ++loop, offset += SIMPLE_PODULE_SIZE) { + if (loop == 4) offset += PODULE_GAP; + address = ((u_char *)SLOW_PODULE_BASE) + offset; + + podule = &podules[loop]; + +/* Get information from the podule header */ + + podule->flags0 = address[0]; + podule->flags1 = address[4]; + podule->reserved = address[8]; + podule->product = address[12] + (address[16] << 8); + podule->manufacturer = address[20] + (address[24] << 8); + podule->country = address[28]; + if (podule->flags1 & PODULE_FLAGS_IS) { + podule->irq_addr = address[52] + (address[56] << 8) + (address[60] << 16); + podule->irq_mask = address[48]; + podule->fiq_addr = address[36] + (address[40] << 8) + (address[44] << 16); + podule->fiq_mask = address[32]; + } else { + podule->irq_addr = 0; + podule->irq_mask = 0; + podule->fiq_addr = 0; + podule->fiq_mask = 0; + } + podule->fast_base = FAST_PODULE_BASE + offset; + podule->medium_base = MEDIUM_PODULE_BASE + offset; + podule->slow_base = SLOW_PODULE_BASE + offset; + podule->sync_base = SYNC_PODULE_BASE + offset; + podule->mod_base = MOD_PODULE_BASE + offset; + podule->easi_base = EASI_BASE + loop * EASI_SIZE; + podule->attached = 0; + podule->slottype = SLOT_NONE; + podule->podulenum = loop; + + poduleexamine(podule, dev, SLOT_POD); + } +} + + +void +netslotscan(dev) + struct device *dev; +{ + podule_t *podule; + volatile u_char *address; + +/* Only one netslot atm */ + +/* Reset the address counter */ + + WriteByte(NETSLOT_BASE, 0x00); + + address = (u_char *)NETSLOT_BASE; + + podule = &podules[MAX_PODULES]; + +/* Get information from the podule header */ + + podule->flags0 = *address; + podule->flags1 = *address; + podule->reserved = *address; + podule->product = *address + (*address << 8); + podule->manufacturer = *address + (*address << 8); + podule->country = *address; + if (podule->flags1 & PODULE_FLAGS_IS) { + podule->irq_mask = *address; + podule->irq_addr = *address + (*address << 8) + (*address << 16); + podule->fiq_mask = *address; + podule->fiq_addr = *address + (*address << 8) + (*address << 16); + } else { + podule->irq_addr = 0; + podule->irq_mask = 0; + podule->fiq_addr = 0; + podule->fiq_mask = 0; + } + podule->fast_base = NETSLOT_BASE; + podule->medium_base = NETSLOT_BASE; + podule->slow_base = NETSLOT_BASE; + podule->sync_base = NETSLOT_BASE; + podule->mod_base = NETSLOT_BASE; + podule->easi_base = 0; + podule->attached = 0; + podule->slottype = SLOT_NONE; + podule->podulenum = MAX_PODULES; + + poduleexamine(podule, dev, SLOT_NET); +} + + +/* + * void podulebusattach(struct device *parent, struct device *dev, void *aux) + * + * Attach podulebus. + * This probes all the podules and sets up the podules array with + * information found in the podule headers. + * After identifing all the podules, all the children of the podulebus + * are probed and attached. + */ + +void +podulebusattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + int loop; + + printf("\n"); + +/* Ok we need to map in the podulebus */ + +/* Map the FAST and SYNC simple podules */ + + map_section(PAGE_DIRS_BASE, SYNC_PODULE_BASE & 0xfff00000, + SYNC_PODULE_HW_BASE & 0xfff00000); + +/* Now map the EASI space */ + + for (loop = 0; loop < MAX_PODULES; ++loop) { + int loop1; + + for (loop1 = loop * EASI_SIZE; loop1 < ((loop + 1) * EASI_SIZE); loop1 += (1 << 20)) + map_section(PAGE_DIRS_BASE, EASI_BASE + loop1, EASI_HW_BASE + loop1); + } + +/* + * The MEDIUM and SLOW simple podules and the module space will have been + * mapped when the IOMD and COMBO we mapped in for the RPC + */ + +/* Install an podule IRQ handler */ + + poduleirq.ih_func = poduleirqhandler; + poduleirq.ih_arg = NULL; + poduleirq.ih_level = IPL_NONE; + poduleirq.ih_name = "podulebus"; + + if (irq_claim(IRQ_PODULE, &poduleirq)) + panic("Cannot claim IRQ for podulebus%d\n", IRQ_PODULE, parent->dv_unit); + +/* Find out what hardware is bolted on */ + + podulescan(self); + netslotscan(self); + +/* Look for drivers */ + + config_scan(podulebusscan, self); +} + + +/* + * int podule_irqhandler(void *arg) + * + * text irq handler to service expansion card IRQ's + * + * There is currently a problem here. + * The spl_mask may mask out certain expansion card IRQ's e.g. SCSI + * but allow others e.g. Ethernet. + */ + +int +poduleirqhandler() +{ + int loop; + irqhandler_t *handler; + + printf("eek ! Unknown podule IRQ received - Blocking all podule interrupts\n"); + disable_irq(IRQ_PODULE); + return(1); + +/* Loop round the expansion card handlers */ + + for (loop = IRQ_EXPCARD0; loop <= IRQ_EXPCARD7; ++loop) { + +/* Is the IRQ currently allowable */ + + if (actual_mask & (1 << loop)) { + handler = irqhandlers[loop]; + + if (handler && handler->ih_irqmask) { + if ((*handler->ih_irqmask) & handler->ih_irqbit) + handler->ih_func(handler->ih_arg); + } + } + } + return(1); +} + +struct cfattach podulebus_ca = { + sizeof(struct device), podulebusmatch, podulebusattach +}; + +struct cfdriver podulebus_cd = { + NULL, "podulebus", DV_DULL, 1 +}; + + +/* Useful functions that drivers may share */ + +/* + * Search the podule list for the specified manufacturer and product. + * Return the podule number if the podule is not already attach and + * the podule was in the required slot. + * A required slot of -1 means any slot. + */ + +int +findpodule(manufacturer, product, required_slot) + int manufacturer; + int product; + int required_slot; +{ + int loop; + + for (loop = 0; loop < MAX_PODULES+MAX_NETSLOTS; ++loop) { + if (podules[loop].slottype != SLOT_NONE + && !podules[loop].attached + && podules[loop].manufacturer == manufacturer + && podules[loop].product == product + && (required_slot == -1 || required_slot == loop)) + return(loop); + } + + return(-1); +} + +/* End of podulebus.c */ diff --git a/sys/arch/arm32/podulebus/podulebus.h b/sys/arch/arm32/podulebus/podulebus.h new file mode 100644 index 00000000000..0b0c6384ad9 --- /dev/null +++ b/sys/arch/arm32/podulebus/podulebus.h @@ -0,0 +1,114 @@ +/* $NetBSD: podulebus.h,v 1.2 1996/03/18 21:23:18 mark 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 + +/* Define the structures used to describe the "known" podules */ + +struct podule_description { + int product_id; + char *description; +}; + +struct podule_list { + int manufacturer_id; + char *description; + struct podule_description *products; +}; + +/* Define the structure used to describe a podule */ + +typedef struct { +/* The podule header, read from the on board ROM */ + + u_char flags0; + u_char flags1; + u_char reserved; + u_short product; + u_short manufacturer; + u_char country; + u_int irq_addr; + u_int irq_mask; + u_int fiq_addr; + u_int fiq_mask; + +/* The base addresses for this podule */ + + u_int fast_base; + u_int medium_base; + u_int slow_base; + u_int sync_base; + u_int mod_base; + u_int easi_base; + +/* Flags */ + + int podulenum; + int slottype; + int attached; +} podule_t; + +#define PODULE_FLAGS_CD 0x01 +#define PODULE_FLAGS_IS 0x02 + +#define SLOT_NONE 0x00 +#define SLOT_POD 0x01 +#define SLOT_NET 0x02 + +struct podule_attach_args { + podule_t *pa_podule; + int pa_podule_number; + int pa_slottype; +}; + +#ifdef _KERNEL + +/* Array of podule structures, one per possible podule */ + +extern podule_t podules[MAX_PODULES + MAX_NETSLOTS]; + +int findpodule __P((int, int, int)); + +#endif + +/* End of podulebus.h */ diff --git a/sys/arch/arm32/podulebus/ptsc.c b/sys/arch/arm32/podulebus/ptsc.c new file mode 100644 index 00000000000..f13c928aada --- /dev/null +++ b/sys/arch/arm32/podulebus/ptsc.c @@ -0,0 +1,485 @@ +/* $NetBSD: ptsc.c,v 1.2 1996/03/17 01:24:54 thorpej Exp $ */ + +/* + * Copyright (c) 1995 Scott Stevens + * Copyright (c) 1995 Daniel Widenfalk + * 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. + * + * @(#)ptsc.c + */ +/* + * Power-tec SCSI-2 driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int ptscprint __P((void *auxp, char *)); +void ptscattach __P((struct device *, struct device *, void *)); +int ptscmatch __P((struct device *, void *, void *)); +int ptsc_scsicmd __P((struct scsi_xfer *)); + +struct scsi_adapter ptsc_scsiswitch = { + ptsc_scsicmd, + sfas_minphys, + 0, /* no lun support */ + 0, /* no lun support */ +}; + +struct scsi_device ptsc_scsidev = { + NULL, /* use default error handler */ + NULL, /* do not have a start functio */ + NULL, /* have no async handler */ + NULL, /* Use default done routine */ +}; + +struct cfattach ptsc_ca = { + sizeof(struct ptsc_softc), ptscmatch, ptscattach +}; + +struct cfdriver ptsc_cd = { + NULL, "ptsc", DV_DULL, NULL, 0 +}; + +int ptsc_intr __P((struct sfas_softc *dev)); +int ptsc_setup_dma __P((struct sfas_softc *sc, void *ptr, int len, + int mode)); +int ptsc_build_dma_chain __P((struct sfas_softc *sc, + struct sfas_dma_chain *chain, void *p, int l)); +int ptsc_need_bump __P((struct sfas_softc *sc, void *ptr, int len)); +void ptsc_led __P((struct sfas_softc *sc, int mode)); + +/* + * if we are a Power-tec SCSI-2 card + */ +int +ptscmatch(pdp, match, auxp) + struct device *pdp; + void *match, *auxp; +{ + struct podule_attach_args *pa = (struct podule_attach_args *)auxp; + int podule; + + podule = findpodule(0x5b, 0x107, pa->pa_podule_number); + + if (podule == -1) + return(0); + + pa->pa_podule_number = podule; + pa->pa_podule = &podules[podule]; + + return(1); +} + +void +ptscattach(pdp, dp, auxp) + struct device *pdp; + struct device *dp; + void *auxp; +{ + struct ptsc_softc *sc = (struct ptsc_softc *)dp; + struct podule_attach_args *pa; + ptsc_regmap_p rp = &sc->sc_regmap; + vu_char *fas; + + pa = (struct podule_attach_args *)auxp; + sc->sc_specific.sc_podule_number = pa->pa_podule_number; + if (sc->sc_specific.sc_podule_number == -1) + panic("Podule has disappeared !"); + + sc->sc_specific.sc_podule = &podules[sc->sc_specific.sc_podule_number]; + sc->sc_specific.sc_iobase = + (vu_char *)sc->sc_specific.sc_podule->fast_base; + + rp->chipreset = &sc->sc_specific.sc_iobase[PTSC_CONTROL_CHIPRESET]; + rp->inten = &sc->sc_specific.sc_iobase[PTSC_CONTROL_INTEN]; + rp->status = &sc->sc_specific.sc_iobase[PTSC_STATUS]; + rp->term = &sc->sc_specific.sc_iobase[PTSC_CONTROL_TERM]; + rp->led = &sc->sc_specific.sc_iobase[PTSC_CONTROL_LED]; + fas = &sc->sc_specific.sc_iobase[PTSC_FASOFFSET_BASE]; + + rp->FAS216.sfas_tc_low = &fas[PTSC_FASOFFSET_TCL]; + rp->FAS216.sfas_tc_mid = &fas[PTSC_FASOFFSET_TCM]; + rp->FAS216.sfas_fifo = &fas[PTSC_FASOFFSET_FIFO]; + rp->FAS216.sfas_command = &fas[PTSC_FASOFFSET_COMMAND]; + rp->FAS216.sfas_dest_id = &fas[PTSC_FASOFFSET_DESTID]; + rp->FAS216.sfas_timeout = &fas[PTSC_FASOFFSET_TIMEOUT]; + rp->FAS216.sfas_syncper = &fas[PTSC_FASOFFSET_PERIOD]; + rp->FAS216.sfas_syncoff = &fas[PTSC_FASOFFSET_OFFSET]; + rp->FAS216.sfas_config1 = &fas[PTSC_FASOFFSET_CONFIG1]; + rp->FAS216.sfas_clkconv = &fas[PTSC_FASOFFSET_CLOCKCONV]; + rp->FAS216.sfas_test = &fas[PTSC_FASOFFSET_TEST]; + rp->FAS216.sfas_config2 = &fas[PTSC_FASOFFSET_CONFIG2]; + rp->FAS216.sfas_config3 = &fas[PTSC_FASOFFSET_CONFIG3]; + rp->FAS216.sfas_tc_high = &fas[PTSC_FASOFFSET_TCH]; + rp->FAS216.sfas_fifo_bot = &fas[PTSC_FASOFFSET_FIFOBOTTOM]; + + sc->sc_softc.sc_fas = (sfas_regmap_p)rp; + sc->sc_softc.sc_spec = &sc->sc_specific; + + sc->sc_softc.sc_led = ptsc_led; + + sc->sc_softc.sc_setup_dma = ptsc_setup_dma; + sc->sc_softc.sc_build_dma_chain = ptsc_build_dma_chain; + sc->sc_softc.sc_need_bump = ptsc_need_bump; + + sc->sc_softc.sc_clock_freq = 8; /* Power-Tec runs at 8MHz */ + sc->sc_softc.sc_timeout = 250; /* Set default timeout to 250ms */ + sc->sc_softc.sc_config_flags = SFAS_NO_DMA /*| SFAS_NF_DEBUG*/; + sc->sc_softc.sc_host_id = 7; /* Should check the jumpers */ + + sc->sc_softc.sc_bump_sz = NBPG; + sc->sc_softc.sc_bump_pa = 0x0; + + sfasinitialize((struct sfas_softc *)sc); + + sc->sc_softc.sc_link.adapter_softc = sc; + sc->sc_softc.sc_link.adapter_target = sc->sc_softc.sc_host_id; + sc->sc_softc.sc_link.adapter = &ptsc_scsiswitch; + sc->sc_softc.sc_link.device = &ptsc_scsidev; + sc->sc_softc.sc_link.openings = 1; + + sc->sc_softc.sc_ih.ih_func = ptsc_intr; + sc->sc_softc.sc_ih.ih_arg = &sc->sc_softc; + sc->sc_softc.sc_ih.ih_level = IPL_BIO; + +/* initialise the card */ + *rp->term = 0; + *rp->inten = (PTSC_POLL?0:1); + *rp->led = 0; + +#if PTSC_POLL == 0 + if (irq_claim(IRQ_PODULE /*IRQ_EXPCARD0 + sc->sc_specific.sc_podule_number */, + &sc->sc_softc.sc_ih)) + panic("ptsc: Cannot install IRQ handler\n"); +#endif + + printf("\n"); + +/* attach all scsi units on us */ + config_found(dp, &sc->sc_softc.sc_link, ptscprint); +} + +/* print diag if pnp is NULL else just extra */ +int +ptscprint(auxp, pnp) + void *auxp; + char *pnp; +{ + if (pnp == NULL) + return(UNCONF); + + return(QUIET); +} + +int +ptsc_intr(dev) + struct sfas_softc *dev; +{ + ptsc_regmap_p rp; + int quickints; + + rp = (ptsc_regmap_p)dev->sc_fas; + + if (*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) { + quickints = 16; + do { + dev->sc_status = *rp->FAS216.sfas_status; + dev->sc_interrupt = *rp->FAS216.sfas_interrupt; + + if (dev->sc_interrupt & SFAS_INT_RESELECTED) { + dev->sc_resel[0] = *rp->FAS216.sfas_fifo; + dev->sc_resel[1] = *rp->FAS216.sfas_fifo; + } + + sfasintr(dev); + + } while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) + && --quickints); + } + + return(1); +} + +/* Load transfer address into dma register */ +void +ptsc_set_dma_adr(sc, ptr) + struct sfas_softc *sc; + void *ptr; +{ + ptsc_regmap_p rp; + unsigned int *p; + unsigned int d; + +#if 0 + printf("ptsc_set_dma_adr(sc = 0x%08x, ptr = 0x%08x)\n", (u_int)sc, (u_int)ptr); +#endif + return; +#if 0 + rp = (ptsc_regmap_p)sc->sc_fas; + + d = (unsigned int)ptr; + p = (unsigned int *)((d & 0xFFFFFF) + (int)rp->dmabase); + + *rp->clear=0; + *p = d; +#endif +} + +/* Set DMA transfer counter */ +void +ptsc_set_dma_tc(sc, len) + struct sfas_softc *sc; + unsigned int len; +{ + printf("ptsc_set_dma_tc(sc, len = 0x%08x)", len); + + *sc->sc_fas->sfas_tc_low = len; len >>= 8; + *sc->sc_fas->sfas_tc_mid = len; len >>= 8; + *sc->sc_fas->sfas_tc_high = len; +} + +/* Set DMA mode */ +void +ptsc_set_dma_mode(sc, mode) + struct sfas_softc *sc; + int mode; +{ + struct csc_specific *spec; + +#if 0 + spec = sc->sc_spec; + + spec->portbits = (spec->portbits & ~FLSC_PB_DMA_BITS) | mode; + *((flsc_regmap_p)sc->sc_fas)->hardbits = spec->portbits; +#endif +} + +/* Initialize DMA for transfer */ +int +ptsc_setup_dma(sc, ptr, len, mode) + struct sfas_softc *sc; + void *ptr; + int len; + int mode; +{ + int retval; + + retval = 0; + +#if 0 + printf("ptsc_setup_dma(sc, ptr = 0x%08x, len = 0x%08x, mode = 0x%08x)\n", (u_int)ptr, len, mode); +#endif + return(0); + +#if 0 + switch(mode) { + case SFAS_DMA_READ: + case SFAS_DMA_WRITE: + flsc_set_dma_adr(sc, ptr); + if (mode == SFAS_DMA_READ) + flsc_set_dma_mode(sc,FLSC_PB_ENABLE_DMA | FLSC_PB_DMA_READ); + else + flsc_set_dma_mode(sc,FLSC_PB_ENABLE_DMA | FLSC_PB_DMA_WRITE); + + flsc_set_dma_tc(sc, len); + break; + + case SFAS_DMA_CLEAR: + default: + flsc_set_dma_mode(sc, FLSC_PB_DISABLE_DMA); + flsc_set_dma_adr(sc, 0); + + retval = (*sc->sc_fas->sfas_tc_high << 16) | + (*sc->sc_fas->sfas_tc_mid << 8) | + *sc->sc_fas->sfas_tc_low; + + flsc_set_dma_tc(sc, 0); + break; + } + + return(retval); +#endif +} + +/* Check if address and len is ok for DMA transfer */ +int +ptsc_need_bump(sc, ptr, len) + struct sfas_softc *sc; + void *ptr; + int len; +{ + int p; + + p = (int)ptr & 0x03; + + if (p) { + p = 4-p; + + if (len < 256) + p = len; + } + + return(p); +} + +/* Interrupt driven routines */ +int +ptsc_build_dma_chain(sc, chain, p, l) + struct sfas_softc *sc; + struct sfas_dma_chain *chain; + void *p; + int l; +{ + vm_offset_t pa, lastpa; + char *ptr; + int len, prelen, postlen, max_t, n; + +#if 0 + printf("ptsc_build_dma_chain()\n"); +#endif + return(0); + +#if 0 + if (l == 0) + return(0); + +#define set_link(n, p, l, f)\ +do { chain[n].ptr = (p); chain[n].len = (l); chain[n++].flg = (f); } while(0) + + n = 0; + + if (l < 512) + set_link(n, (vm_offset_t)p, l, SFAS_CHAIN_BUMP); + else if ((p >= (void *)0xFF000000) +#if M68040 + && ((mmutype == MMU_68040) && (p >= (void *)0xFFFC0000)) +#endif + ) { + while(l != 0) { + len = ((l > sc->sc_bump_sz) ? sc->sc_bump_sz : l); + + set_link(n, (vm_offset_t)p, len, SFAS_CHAIN_BUMP); + + p += len; + l -= len; + } + } else { + ptr = p; + len = l; + + pa = kvtop(ptr); + prelen = ((int)ptr & 0x03); + + if (prelen) { + prelen = 4-prelen; + set_link(n, (vm_offset_t)ptr, prelen, SFAS_CHAIN_BUMP); + ptr += prelen; + len -= prelen; + } + + lastpa = 0; + while(len > 3) { + pa = kvtop(ptr); + max_t = NBPG - (pa & PGOFSET); + if (max_t > len) + max_t = len; + + max_t &= ~3; + + if (lastpa == pa) + sc->sc_chain[n-1].len += max_t; + else + set_link(n, pa, max_t, SFAS_CHAIN_DMA); + + lastpa = pa+max_t; + + ptr += max_t; + len -= max_t; + } + + if (len) + set_link(n, (vm_offset_t)ptr, len, SFAS_CHAIN_BUMP); + } + + return(n); +#endif +} + +/* Turn on/off led */ +void +ptsc_led(sc, mode) + struct sfas_softc *sc; + int mode; +{ + ptsc_regmap_p rp; + + rp = (ptsc_regmap_p)sc->sc_fas; + + if (mode) { + sc->sc_led_status++; + } else { + if (sc->sc_led_status) + sc->sc_led_status--; + } + *rp->led = (sc->sc_led_status?1:0); +} + +int +ptsc_scsicmd(xs) + struct scsi_xfer *xs; +{ + /* ensure command is polling for the moment */ +#if PTSC_POLL > 0 + xs->flags |= SCSI_POLL; +#endif +#if 0 + printf("Opcode %d\n", (int)(xs->cmd->opcode)); +#endif + return(sfas_scsicmd(xs)); +} diff --git a/sys/arch/arm32/podulebus/ptscreg.h b/sys/arch/arm32/podulebus/ptscreg.h new file mode 100644 index 00000000000..81f01b710e3 --- /dev/null +++ b/sys/arch/arm32/podulebus/ptscreg.h @@ -0,0 +1,77 @@ +/* $NetBSD: ptscreg.h,v 1.1 1996/01/31 23:26:35 mark Exp $ */ + +/* + * Copyright (c) 1995 Scott Stevens + * Copyright (c) 1995 Daniel Widenfalk + * + * 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 Daniel Widenfalk + * 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. + */ +/* + * Power-tec SCSI-2 with FAS216 SCSI interface hardware description. + */ + +#ifndef _PTSCREG_H_ +#define _PTSCREG_H_ + +#include + +typedef volatile unsigned short vu_short; + +typedef struct ptsc_regmap { + sfas_regmap_t FAS216; + vu_char *chipreset; + vu_char *inten; + vu_char *status; + vu_char *term; + vu_char *led; +} ptsc_regmap_t; +typedef ptsc_regmap_t *ptsc_regmap_p; + +/* NDA Information */ +#define PTSC_CONTROL_CHIPRESET 0x1018 +#define PTSC_CONTROL_INTEN 0x101c +#define PTSC_STATUS 0x2000 +#define PTSC_CONTROL_TERM 0x2018 +#define PTSC_CONTROL_LED 0x201c +#define PTSC_FASOFFSET_BASE 0x3000 +#define PTSC_FASOFFSET_TCL 0x0000 +#define PTSC_FASOFFSET_TCM 0x0040 +#define PTSC_FASOFFSET_FIFO 0x0080 +#define PTSC_FASOFFSET_COMMAND 0x00c0 +#define PTSC_FASOFFSET_DESTID 0x0100 +#define PTSC_FASOFFSET_TIMEOUT 0x0140 +#define PTSC_FASOFFSET_PERIOD 0x0180 +#define PTSC_FASOFFSET_OFFSET 0x01c0 +#define PTSC_FASOFFSET_CONFIG1 0x0200 +#define PTSC_FASOFFSET_CLOCKCONV 0x0240 +#define PTSC_FASOFFSET_TEST 0x0280 +#define PTSC_FASOFFSET_CONFIG2 0x02c0 +#define PTSC_FASOFFSET_CONFIG3 0x0300 +#define PTSC_FASOFFSET_TCH 0x0380 +#define PTSC_FASOFFSET_FIFOBOTTOM 0x03c0 +/* NDA Info end */ +#endif diff --git a/sys/arch/arm32/podulebus/ptscvar.h b/sys/arch/arm32/podulebus/ptscvar.h new file mode 100644 index 00000000000..6608eaf2635 --- /dev/null +++ b/sys/arch/arm32/podulebus/ptscvar.h @@ -0,0 +1,52 @@ +/* $NetBSD: ptscvar.h,v 1.1 1996/01/31 23:26:38 mark Exp $ */ + +/* + * Copyright (c) 1995 Scott Stevens + * + * 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 Daniel Widenfalk + * 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 _PTSCVAR_H_ +#define _PTSCVAR_H_ + +#include +#include + +#define PTSC_POLL 1 + +struct ptsc_specific { + vu_char *sc_iobase; + int sc_podule_number; + podule_t *sc_podule; +}; + +struct ptsc_softc { + struct sfas_softc sc_softc; + ptsc_regmap_t sc_regmap; + struct ptsc_specific sc_specific; +}; + +#endif /* _PTSCVAR_H_ */ diff --git a/sys/arch/arm32/podulebus/sbic.c b/sys/arch/arm32/podulebus/sbic.c new file mode 100644 index 00000000000..b4d5b097f81 --- /dev/null +++ b/sys/arch/arm32/podulebus/sbic.c @@ -0,0 +1,2947 @@ +/* $NetBSD: sbic.c,v 1.2 1996/04/19 20:09:50 mark 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 DEBUG +/*#define SBIC_DEBUG*/ +/* + * AMIGA AMD 33C93 scsi adaptor driver + */ + +#include +#include +#include +#include /* For hz */ +#include +#include +#include +#include +#include +#include +#include +#include +/*#include +#include */ +#include +#include +#include +#include +#include +#include + +/* These are for bounce buffers */ + +/*#include */ + +/* 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 b_cylin b_resid +#define SBIC_WAIT(regs, until, timeo) sbicwait(regs, until, timeo, __LINE__) + +extern u_int kvtop(); + +int sbicicmd __P((struct sbic_softc *, int, int, void *, int, void *, int)); +int sbicgo __P((struct sbic_softc *, struct scsi_xfer *)); +int sbicdmaok __P((struct sbic_softc *, struct scsi_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)); + +/* + * 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 +#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, csr, s; + 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 (%x,%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 (%x,%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 i, s, asr, count; + char* vaddr, * 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(%x,%x)pa(%x,%x)\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 (%x,%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 scsi_xfer *xs; +{ + struct sbic_acb *acb; + struct sbic_softc *dev; + struct scsi_link *slp; + int flags, s, stat; + + slp = xs->sc_link; + dev = slp->adapter_softc; + SBIC_TRACE(dev); + flags = xs->flags; + + if (flags & SCSI_DATA_UIO) + panic("sbic: scsi data uio requested"); + + if (dev->sc_nexus && flags & SCSI_POLL) + panic("sbic_scsicmd: busy"); + + if (slp->target == slp->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->target); +#ifdef DDB + Debugger(); +#endif +#endif + xs->error = XS_DRIVER_STUFFUP; + SBIC_TRACE(dev); + return(TRY_AGAIN_LATER); + } + + acb->flags = ACB_ACTIVE; + if (flags & SCSI_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 & SCSI_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->target; + dev->lun = slp->lun; + stat = sbicicmd(dev, slp->target, slp->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 SCSI_POLL operations */ +#if 0 + if (flags & SCSI_POLL) + return(COMPLETE); +#endif + return(SUCCESSFULLY_QUEUED); +} + +/* + * attempt to start the next available command + */ +void +sbic_sched(dev) + struct sbic_softc *dev; +{ + struct scsi_xfer *xs; + struct scsi_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->target; + if (!(dev->sc_tinfo[i].lubusy & (1 << slp->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->target]; + ti->lubusy |= (1 << slp->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->flags; + + if (flags & SCSI_RESET) + sbicreset(dev); + +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("sbic_sched(%d,%d)\n",slp->target,slp->lun); +#endif + dev->sc_stat[0] = -1; + dev->target = slp->target; + dev->lun = slp->lun; + if ( flags & SCSI_POLL || ( !sbic_parallel_operations + && (/*phase == STATUS_PHASE ||*/ + sbicdmaok(dev, xs) == 0) ) ) + stat = sbicicmd(dev, slp->target, slp->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 scsi_xfer *xs; + struct scsi_link *slp; + struct sbic_softc *dev; + int s, 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 scsi_xfer\n", + dev->target, dev->lun); +#ifdef DDB + Debugger(); +#endif + return; + } +#endif + /* + * XXX Support old-style instrumentation for now. + * IS THIS REALLY THE RIGHT PLACE FOR THIS? --thorpej + */ + if (slp->device_softc && + ((struct device *)(slp->device_softc))->dv_unit < dk_ndrive) + ++dk_xfer[((struct device *)(slp->device_softc))->dv_unit]; + /* + * is this right? + */ + xs->status = stat; + +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("scsidone: (%d,%d)->(%d,%d)%02x\n", + slp->target, slp->lun, + dev->target, dev->lun, stat); + if( xs->sc_link->target == dev->sc_link.adapter_target ) + panic("target == hostid"); +#endif + + if (xs->error == XS_NOERROR && !(acb->flags & ACB_CHKSENSE)) { + if (stat == SCSI_CHECK) { + /* Schedule a REQUEST SENSE */ + struct scsi_sense *ss = (void *)&acb->cmd; +#ifdef DEBUG + if (report_sense) + printf("sbic_scsidone: autosense %02x targ %d lun %d", + acb->cmd.opcode, slp->target, slp->lun); +#endif + bzero(ss, sizeof(*ss)); + ss->opcode = REQUEST_SENSE; + ss->byte2 = slp->lun << 5; + ss->length = sizeof(struct scsi_sense_data); + acb->clen = sizeof(*ss); + acb->sc_kv.dc_addr = (char *)&xs->sense; + acb->sc_kv.dc_count = sizeof(struct scsi_sense_data); +#if 0 + acb->pa_addr = (char *)kvtop(&xs->sense); /* XXX check */ +#endif + acb->flags = ACB_ACTIVE | ACB_CHKSENSE | ACB_DATAIN; + TAILQ_INSERT_HEAD(&dev->ready_list, acb, chain); + dev->sc_tinfo[slp->target].lubusy &= + ~(1 << slp->lun); + dev->sc_tinfo[slp->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)) { + xs->error = XS_SENSE; +#ifdef DEBUG + if (report_sense) + printf(" => %02x %02x\n", xs->sense.flags, + xs->sense.extra_bytes[3]); +#endif + } else { + xs->resid = 0; /* XXXX */ + } +#if whataboutthisone + case SCSI_BUSY: + xs->error = XS_BUSY; + break; +#endif + xs->flags |= ITSDONE; + + /* + * 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->target].lubusy &= ~(1<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->target].lubusy + &= ~(1<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->target].cmds++; + + scsi_done(xs); + + if (dosched) + sbic_sched(dev); + SBIC_TRACE(dev); +} + +int +sbicdmaok(dev, xs) + struct sbic_softc *dev; + struct scsi_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->target].bounce) + return(1); + /* + * try to get one + */ + else if (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->target].bounce)); + else if (dev->sc_tinfo[xs->sc_link->target].bounce) + printf("alloc CHIP target %d bounce pa 0x%x\n", + xs->sc_link->target, + PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->target].bounce)); + return(1); + } + + 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 my_id, i, 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); + 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 */ + timeout((void *)sbictimeout, dev, 30 * hz); +#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, i, s; + 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.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 scsi_xfer *xs; + + xs = dev->sc_xs; + +#ifdef DIAGNOSTIC + if (xs == NULL) + panic("sbicerror"); +#endif + if (xs->flags & SCSI_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->flags & SCSI_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, csr, asr, *buf; + 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])); + + GET_SBIC_csr (regs, orig_csr); + CSR_TRACE('>',orig_csr,0,0); + + /* + * 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, read; + u_char *obp, *buf; + u_char orig_csr, csr, asr; + + wait = sbic_data_wait; + obp = bp; + buf = bp; + + GET_SBIC_csr (regs, orig_csr); + CSR_TRACE('<',orig_csr,0,0); + + QPRINTF(("sbicxfin %d, csr=%02x\n", len, orig_csr)); + + 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; + } + + if( ! asr & SBIC_ASR_BSY ) { + GET_SBIC_csr(regs, csr); + CSR_TRACE('<',csr,asr,len); + QPRINTF(("[CSR%02xASR%02x]", csr, asr)); + } + +/* 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, 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 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 scsi_xfer *xs; +{ + int i, dmaflags, count, wait, usedma; + u_char csr, asr, cmd, *addr; + sbic_regmap_p regs; + struct sbic_acb *acb; + + SBIC_TRACE(dev); + dev->target = xs->sc_link->target; + dev->lun = xs->sc_link->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 (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: (%x->%x,%x)\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->target].bounce)); + else if (dev->sc_tinfo[xs->sc_link->target].bounce) + printf("alloc CHIP target %d bounce pa 0x%x\n", + xs->sc_link->target, + PREP_DMA_MEM(dev->sc_tinfo[xs->sc_link->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 + } + + /* + * 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); + + /* + * push the data cache ( I think this won't work (EH)) + */ +#if defined(M68040) + if (mmutype == MMU_68040 && 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(%x:%x)\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, *tmpaddr; + struct sbic_acb *acb; + int i, 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, 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 + */ +#ifdef M68040 + if (dev->sc_flags & SBICF_DCFLUSH) { +#if 0 + printf("sbic: 68040 DMA cache flush needs fixing? %x:%x\n", + dev->sc_xs->data, dev->sc_xs->datalen); +#endif + } +#endif +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("next dmastop: %d(%x:%x)\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 %x->%x\n", + dev->sc_dev.dv_xname, acb->sc_usrbufpa, + kvtop(acb->sc_dmausrbuf)); +#ifdef DEBUG + if(data_pointer_debug) + printf("sbicgo:copying %x 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: + if( dev->sc_xs->flags & SCSI_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(%x:%x)\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->flags & SCSI_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->target != newtarget || + acb->xs->sc_link->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 %x\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(%x:%x)\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 + */ +#ifdef M68040 + if (dev->sc_flags & SBICF_DCFLUSH) { +#if 0 + printf("sibc: 68040 DMA cache flush needs fixing? %x:%x\n", + dev->sc_xs->data, dev->sc_xs->datalen); +#endif + } +#endif + dev->sc_flags &= + ~(SBICF_INDMA | SBICF_DCFLUSH); +#ifdef DEBUG + if( data_pointer_debug > 1 ) + printf("next dmastop: %d(%x:%x)\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); + timeout((void *)sbictimeout, dev, 30 * hz); +} + +void +sbic_dump_acb(acb) + struct sbic_acb *acb; +{ + u_char *b = (u_char *) &acb->cmd; + int i; + + printf("acb@%x ", acb); + if (acb->xs == NULL) { + printf("\n"); + return; + } + printf("(%d:%d) flags %2x clen %2d cmd ", acb->xs->sc_link->target, + acb->xs->sc_link->lun, acb->flags, acb->clen); + for (i = acb->clen; i; --i) + printf(" %02x", *b++); + printf("\n"); + printf(" xs: %08x data %8x:%04x ", acb->xs, acb->xs->data, + acb->xs->datalen); + printf("va %8x:%04x ", acb->sc_kv.dc_addr, acb->sc_kv.dc_count); + printf("pa %8x:%04x tcnt %x\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@%x regs %x 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 %x targ %d lun %d flags %x tcnt %x dmacmd %x mask %x\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/arm32/podulebus/sbicreg.h b/sys/arch/arm32/podulebus/sbicreg.h new file mode 100644 index 00000000000..0b43c60c419 --- /dev/null +++ b/sys/arch/arm32/podulebus/sbicreg.h @@ -0,0 +1,426 @@ +/* $NetBSD: sbicreg.h,v 1.1 1996/03/06 23:44:09 mark 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/arm32/podulebus/sbicvar.h b/sys/arch/arm32/podulebus/sbicvar.h new file mode 100644 index 00000000000..3e17ecc7ff7 --- /dev/null +++ b/sys/arch/arm32/podulebus/sbicvar.h @@ -0,0 +1,230 @@ +/* $NetBSD: sbicvar.h,v 1.1 1996/03/06 23:44:10 mark 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 + +/* + * 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 scsi_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 target_sync { + u_char state; + u_char period; + u_char offset; + } sc_sync[8]; + u_char target; /* Currently active target */ + u_char lun; + struct scsi_link sc_link; /* proto for sub devices */ + 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 scsi_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 scsi_xfer; + +void sbic_minphys __P((struct buf *bp)); +int sbic_scsicmd __P((struct scsi_xfer *)); + +#endif /* _SBICVAR_H_ */ diff --git a/sys/arch/arm32/podulebus/sfas.c b/sys/arch/arm32/podulebus/sfas.c new file mode 100644 index 00000000000..f605486391d --- /dev/null +++ b/sys/arch/arm32/podulebus/sfas.c @@ -0,0 +1,1621 @@ +/* $NetBSD: sfas.c,v 1.4 1996/03/18 21:23:20 mark Exp $ */ + +/* + * Copyright (c) 1995 Scott Stevens + * Copyright (c) 1995 Daniel Widenfalk + * 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. + * + * @(#)scsi.c 7.5 (Berkeley) 5/4/91 + */ + +/* + * Emulex FAS216 scsi adaptor driver + */ + +/* + * Modified for NetBSD/arm32 by Scott Stevens + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Externs */ +extern pt_entry_t *pmap_pte __P((pmap_t, vm_offset_t)); + +void sfasinitialize __P((struct sfas_softc *)); +void sfas_minphys __P((struct buf *bp)); +int sfas_scsicmd __P((struct scsi_xfer *xs)); +void sfas_donextcmd __P((struct sfas_softc *dev, struct sfas_pending *pendp)); +void sfas_scsidone __P((struct sfas_softc *dev, struct scsi_xfer *xs, + int stat)); +void sfasintr __P((struct sfas_softc *dev)); +void sfasiwait __P((struct sfas_softc *dev)); +void sfasreset __P((struct sfas_softc *dev, int how)); +int sfasselect __P((struct sfas_softc *dev, struct sfas_pending *pendp, + unsigned char *cbuf, int clen, + unsigned char *buf, int len, int mode)); +void sfasicmd __P((struct sfas_softc *dev, struct sfas_pending *pendp)); +void sfasgo __P((struct sfas_softc *dev, struct sfas_pending *pendp)); + +/* + * Initialize these to make 'em patchable. Defaults to enable sync and discon. + */ +u_char sfas_inhibit_sync[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +u_char sfas_inhibit_disc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +#define DEBUG +#ifdef DEBUG +#define QPRINTF(a) if (sfas_debug > 1) printf a +int sfas_debug = 2; +#else +#define QPRINTF +#endif + +/* + * default minphys routine for sfas based controllers + */ +void +sfas_minphys(bp) + struct buf *bp; +{ + + /* + * No max transfer at this level. + */ + minphys(bp); +} + +/* + * Initialize the nexus structs. + */ +void +sfas_init_nexus(dev, nexus) + struct sfas_softc *dev; + struct nexus *nexus; +{ + bzero(nexus, sizeof(struct nexus)); + + nexus->state = SFAS_NS_IDLE; + nexus->period = 200; + nexus->offset = 0; + nexus->syncper = 5; + nexus->syncoff = 0; + nexus->config3 = dev->sc_config3 & ~SFAS_CFG3_FASTSCSI; +} + +void +sfasinitialize(dev) + struct sfas_softc *dev; +{ + u_int *pte; + int i; + + dev->sc_led_status = 0; + + TAILQ_INIT(&dev->sc_xs_pending); + TAILQ_INIT(&dev->sc_xs_free); + +/* + * Initialize the sfas_pending structs and link them into the free list. We + * have to set vm_link_data.pages to 0 or the vm FIX won't work. + */ + for(i=0; isc_xs_free, &dev->sc_xs_store[i], + link); + } + +/* + * Calculate the correct clock conversion factor 2 <= factor <= 8, i.e. set + * the factor to clock_freq / 5 (int). + */ + if (dev->sc_clock_freq <= 10) + dev->sc_clock_conv_fact = 2; + if (dev->sc_clock_freq <= 40) + dev->sc_clock_conv_fact = 2+((dev->sc_clock_freq-10)/5); + else + panic("sfasinitialize: Clock frequence too high"); + +/* Setup and save the basic configuration registers */ + dev->sc_config1 = (dev->sc_host_id & SFAS_CFG1_BUS_ID_MASK); + dev->sc_config2 = SFAS_CFG2_FEATURES_ENABLE; + dev->sc_config3 = (dev->sc_clock_freq > 25 ? SFAS_CFG3_FASTCLK : 0); + +/* Precalculate timeout value and clock period. */ +/* Ekkk ... floating point in the kernel !!!! */ +/* dev->sc_timeout_val = 1+dev->sc_timeout*dev->sc_clock_freq/ + (7.682*dev->sc_clock_conv_fact);*/ + dev->sc_timeout_val = 1+dev->sc_timeout*dev->sc_clock_freq/ + ((7682*dev->sc_clock_conv_fact)/1000); + dev->sc_clock_period = 1000/dev->sc_clock_freq; + + sfasreset(dev, 1 | 2); /* Reset Chip and Bus */ + + dev->sc_units_disconnected = 0; + dev->sc_msg_in_len = 0; + dev->sc_msg_out_len = 0; + + dev->sc_flags = 0; + + for(i=0; i<8; i++) + sfas_init_nexus(dev, &dev->sc_nexus[i]); + +/* + * Setup bump buffer. + */ + dev->sc_bump_va = (u_char *)kmem_alloc(kernel_map, dev->sc_bump_sz); + dev->sc_bump_pa = pmap_extract(kernel_pmap, (vm_offset_t)dev->sc_bump_va); + +/* + * Setup pages to noncachable, that way we don't have to flush the cache + * every time we need "bumped" transfer. + */ + pte = pmap_pte(kernel_pmap, (vm_offset_t)dev->sc_bump_va); + *pte &= ~PT_C; + tlbflush(); + + printf(" dmabuf V0x%08x P0x%08x", (u_int)dev->sc_bump_va, (u_int)dev->sc_bump_pa); +} + + +/* + * used by specific sfas controller + */ +int +sfas_scsicmd(struct scsi_xfer *xs) +{ + struct sfas_softc *dev; + struct scsi_link *slp; + struct sfas_pending *pendp; + int flags, s, target; + + slp = xs->sc_link; + dev = slp->adapter_softc; + flags = xs->flags; + target = slp->target; + + if (flags & SCSI_DATA_UIO) + panic("sfas: scsi data uio requested"); + + if ((flags & SCSI_POLL) && (dev->sc_flags & SFAS_ACTIVE)) + panic("sfas_scsicmd: busy"); + +/* Get hold of a sfas_pending block. */ + s = splbio(); + pendp = dev->sc_xs_free.tqh_first; + if (pendp == NULL) { + splx(s); + return(TRY_AGAIN_LATER); + } + TAILQ_REMOVE(&dev->sc_xs_free, pendp, link); + pendp->xs = xs; + splx(s); + + +/* If the chip if busy OR the unit is busy, we have to wait for out turn. */ + if ((dev->sc_flags & SFAS_ACTIVE) || + (dev->sc_nexus[target].flags & SFAS_NF_UNIT_BUSY)) { + s = splbio(); + TAILQ_INSERT_TAIL(&dev->sc_xs_pending, pendp, link); + splx(s); + } else + sfas_donextcmd(dev, pendp); + + return((flags & SCSI_POLL) ? COMPLETE : SUCCESSFULLY_QUEUED); +} + +/* + * Actually select the unit, whereby the whole scsi-process is started. + */ +void +sfas_donextcmd(dev, pendp) + struct sfas_softc *dev; + struct sfas_pending *pendp; +{ + int s; + +/* + * Special case for scsi unit reset. I think this is waterproof. We first + * select the unit during splbio. We then cycle through the generated + * interrupts until the interrupt routine signals that the unit has + * acknowledged the reset. After that we have to wait a reset to select + * delay before anything else can happend. + */ + if (pendp->xs->flags & SCSI_RESET) { + struct nexus *nexus; + + s = splbio(); + while(!sfasselect(dev, pendp, 0, 0, 0, 0, SFAS_SELECT_K)) { + splx(s); + delay(10); + s = splbio(); + } + + nexus = dev->sc_cur_nexus; + while(nexus->flags & SFAS_NF_UNIT_BUSY) { + sfasiwait(dev); + sfasintr(dev); + } + + nexus->flags |= SFAS_NF_UNIT_BUSY; + splx(s); + + sfasreset(dev, 0); + + s = splbio(); + nexus->flags &= ~SFAS_NF_UNIT_BUSY; + splx(s); + } + +/* + * If we are polling, go to splbio and perform the command, else we poke + * the scsi-bus via sfasgo to get the interrupt machine going. + */ + if (pendp->xs->flags & SCSI_POLL) { + s = splbio(); + sfasicmd(dev, pendp); + TAILQ_INSERT_TAIL(&dev->sc_xs_free, pendp, link); + splx(s); + } else { + sfasgo(dev, pendp); + } +} + +void +sfas_scsidone(dev, xs, stat) + struct sfas_softc *dev; + struct scsi_xfer *xs; + int stat; +{ + struct sfas_pending *pendp; + int s; + + xs->status = stat; + + if (stat == 0) + xs->resid = 0; + else { + switch(stat) { + case SCSI_CHECK: + /* If we get here we have valid sense data. Faults during + * sense is handeled elsewhere and will generate a + * XS_DRIVER_STUFFUP. */ + xs->error = XS_SENSE; + break; + case SCSI_BUSY: + xs->error = XS_BUSY; + break; + case -1: + xs->error = XS_DRIVER_STUFFUP; + QPRINTF(("sfas_scsicmd() bad %x\n", stat)); + break; + default: + xs->error = XS_TIMEOUT; + break; + } + } + + xs->flags |= ITSDONE; + +/* Steal the next command from the queue so that one unit can't hog the bus. */ + s = splbio(); + pendp = dev->sc_xs_pending.tqh_first; + while(pendp) { + if (!(dev->sc_nexus[pendp->xs->sc_link->target].flags & + SFAS_NF_UNIT_BUSY)) + break; + pendp = pendp->link.tqe_next; + } + + if (pendp != NULL) { + TAILQ_REMOVE(&dev->sc_xs_pending, pendp, link); + } + + splx(s); + scsi_done(xs); + + if (pendp) + sfas_donextcmd(dev, pendp); +} + +/* + * There are two kinds of reset: + * 1) CHIP-bus reset. This also implies a SCSI-bus reset. + * 2) SCSI-bus reset. + * After the appropriate resets have been performed we wait a reset to select + * delay time. + */ +void +sfasreset(dev, how) + struct sfas_softc *dev; + int how; +{ + sfas_regmap_p rp; + int i, s; + + rp = dev->sc_fas; + + if (how & 1) { + for(i=0; i<8; i++) + sfas_init_nexus(dev, &dev->sc_nexus[i]); + + *rp->sfas_command = SFAS_CMD_RESET_CHIP; + delay(1); + *rp->sfas_command = SFAS_CMD_NOP; + + *rp->sfas_config1 = dev->sc_config1; + *rp->sfas_config2 = dev->sc_config2; + *rp->sfas_config3 = dev->sc_config3; + *rp->sfas_timeout = dev->sc_timeout_val; + *rp->sfas_clkconv = dev->sc_clock_conv_fact & + SFAS_CLOCK_CONVERSION_MASK; + } + + if (how & 2) { + for(i=0; i<8; i++) + sfas_init_nexus(dev, &dev->sc_nexus[i]); + + s = splbio(); + + *rp->sfas_command = SFAS_CMD_RESET_SCSI_BUS; + delay(100); + +/* Skip interrupt generated by RESET_SCSI_BUS */ + while(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING) { + dev->sc_status = *rp->sfas_status; + dev->sc_interrupt = *rp->sfas_interrupt; + + delay(100); + } + + dev->sc_status = *rp->sfas_status; + dev->sc_interrupt = *rp->sfas_interrupt; + + splx(s); + } + + if (dev->sc_config_flags & SFAS_SLOW_START) + delay(4*250000); /* RESET to SELECT DELAY*4 for slow devices */ + else + delay(250000); /* RESET to SELECT DELAY */ +} + +/* + * Save active data pointers to the nexus block currently active. + */ +void +sfas_save_pointers(dev) + struct sfas_softc *dev; +{ + struct nexus *nx; + + nx = dev->sc_cur_nexus; + if (nx) { + nx->cur_link = dev->sc_cur_link; + nx->max_link = dev->sc_max_link; + nx->buf = dev->sc_buf; + nx->len = dev->sc_len; + nx->dma_len = dev->sc_dma_len; + nx->dma_buf = dev->sc_dma_buf; + nx->dma_blk_flg = dev->sc_dma_blk_flg; + nx->dma_blk_len = dev->sc_dma_blk_len; + nx->dma_blk_ptr = dev->sc_dma_blk_ptr; + } +} + +/* + * Restore data pointers from the currently active nexus block. + */ +void +sfas_restore_pointers(dev) + struct sfas_softc *dev; +{ + struct nexus *nx; + + nx = dev->sc_cur_nexus; + if (nx) { + dev->sc_cur_link = nx->cur_link; + dev->sc_max_link = nx->max_link; + dev->sc_buf = nx->buf; + dev->sc_len = nx->len; + dev->sc_dma_len = nx->dma_len; + dev->sc_dma_buf = nx->dma_buf; + dev->sc_dma_blk_flg = nx->dma_blk_flg; + dev->sc_dma_blk_len = nx->dma_blk_len; + dev->sc_dma_blk_ptr = nx->dma_blk_ptr; + dev->sc_chain = nx->dma; + dev->sc_unit = (nx->lun_unit & 0x0F); + dev->sc_lun = (nx->lun_unit & 0xF0) >> 4; + } +} + +/* + * sfasiwait is used during interrupt and polled IO to wait for an event from + * the FAS chip. This function MUST NOT BE CALLED without interrupt disabled. + */ +void +sfasiwait(dev) + struct sfas_softc *dev; +{ + sfas_regmap_p rp; + +/* + * If SFAS_DONT_WAIT is set, we have already grabbed the interrupt info + * elsewhere. So we don't have to wait for it. + */ + if (dev->sc_flags & SFAS_DONT_WAIT) { + dev->sc_flags &= ~SFAS_DONT_WAIT; + return; + } + + rp = dev->sc_fas; + +/* Wait for FAS chip to signal an interrupt. */ + while(!(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING)) + delay(1); + +/* Grab interrupt info from chip. */ + dev->sc_status = *rp->sfas_status; + dev->sc_interrupt = *rp->sfas_interrupt; + if (dev->sc_interrupt & SFAS_INT_RESELECTED) { + dev->sc_resel[0] = *rp->sfas_fifo; + dev->sc_resel[1] = *rp->sfas_fifo; + } +} + +/* + * Transfer info to/from device. sfas_ixfer uses polled IO+sfasiwait so the + * rules that apply to sfasiwait also applies here. + */ +void +sfas_ixfer(dev, polling) + struct sfas_softc *dev; + int polling; +{ + sfas_regmap_p rp; + u_char *buf; + int len, mode, phase; + + rp = dev->sc_fas; + buf = dev->sc_buf; + len = dev->sc_len; + +/* + * Decode the scsi phase to determine whether we are reading or writing. + * mode == 1 => READ, mode == 0 => WRITE + */ + phase = dev->sc_status & SFAS_STAT_PHASE_MASK; + mode = (phase == SFAS_PHASE_DATA_IN); + + while(len && ((dev->sc_status & SFAS_STAT_PHASE_MASK) == phase)) + if (mode) { + *rp->sfas_command = SFAS_CMD_TRANSFER_INFO; + + sfasiwait(dev); + + *buf++ = *rp->sfas_fifo; + len--; + } else { + len--; + *rp->sfas_fifo = *buf++; + *rp->sfas_command = SFAS_CMD_TRANSFER_INFO; + + sfasiwait(dev); + } + +/* Update buffer pointers to reflect the sent/recieved data. */ + dev->sc_buf = buf; + dev->sc_len = len; + +/* + * Since the last sfasiwait will be a phase-change, we can't wait for it + * again later, so we have to signal that. + * Since this may be called from an interrupt initiated routine then we + * must call sfasintr again to avoid losing an interrupt. Phew! + */ + if(polling) + dev->sc_flags |= SFAS_DONT_WAIT; + else + sfasintr(dev); +} + +/* + * Build a Synchronous Data Transfer Request message + */ +void +sfas_build_sdtrm(dev, period, offset) + struct sfas_softc *dev; + int period; + int offset; +{ + dev->sc_msg_out[0] = 0x01; + dev->sc_msg_out[1] = 0x03; + dev->sc_msg_out[2] = 0x01; + dev->sc_msg_out[3] = period/4; + dev->sc_msg_out[4] = offset; + dev->sc_msg_out_len= 5; +} + +/* + * Arbitate the scsi bus and select the unit + */ +int +sfas_select_unit(dev, target) + struct sfas_softc *dev; + short target; +{ + sfas_regmap_p rp; + struct nexus *nexus; + int s, retcode, i; + u_char cmd; + + s = splbio(); /* Do this at splbio so that we won't be disturbed. */ + + retcode = 0; + + nexus = &dev->sc_nexus[target]; + +/* + * Check if the chip is busy. If not the we mark it as so and hope that nobody + * reselects us until we have grabbed the bus. + */ + if (!(dev->sc_flags & SFAS_ACTIVE) && !dev->sc_sel_nexus) { + dev->sc_flags |= SFAS_ACTIVE; + + rp = dev->sc_fas; + + *rp->sfas_syncper = nexus->syncper; + *rp->sfas_syncoff = nexus->syncoff; + *rp->sfas_config3 = nexus->config3; + + *rp->sfas_config1 = dev->sc_config1; + *rp->sfas_timeout = dev->sc_timeout_val; + *rp->sfas_dest_id = target; + +/* If nobody has stolen the bus, we can send a select command to the chip. */ + if (!(*rp->sfas_status & SFAS_STAT_INTERRUPT_PENDING)) { + *rp->sfas_fifo = nexus->ID; + if ((nexus->flags & (SFAS_NF_DO_SDTR | SFAS_NF_RESET)) + || (dev->sc_msg_out_len != 0)) + cmd = SFAS_CMD_SEL_ATN_STOP; + else { + for(i=0; iclen; i++) + *rp->sfas_fifo = nexus->cbuf[i]; + + cmd = SFAS_CMD_SEL_ATN; + } + + dev->sc_sel_nexus = nexus; + + *rp->sfas_command = cmd; + retcode = 1; + } + } + + splx(s); + return(retcode); +} + +/* + * Grab the nexus if available else return 0. + */ +struct nexus * +sfas_arbitate_target(dev, target) + struct sfas_softc *dev; + int target; +{ + struct nexus *nexus; + int s; + +/* + * This is realy simple. Raise interrupt level to splbio. Grab the nexus and + * leave. + */ + nexus = &dev->sc_nexus[target]; + + s = splbio(); + + if (nexus->flags & SFAS_NF_UNIT_BUSY) + nexus = 0; + else + nexus->flags |= SFAS_NF_UNIT_BUSY; + + splx(s); + return(nexus); +} + +/* + * Setup a nexus for use. Initializes command, buffer pointers and dma chain. + */ +void +sfas_setup_nexus(dev, nexus, pendp, cbuf, clen, buf, len, mode) + struct sfas_softc *dev; + struct nexus *nexus; + struct sfas_pending *pendp; + unsigned char *cbuf; + int clen; + unsigned char *buf; + int len; + int mode; +{ + char sync, target, lun; + + target = pendp->xs->sc_link->target; + lun = pendp->xs->sc_link->lun; + +/* + * Adopt mode to reflect the config flags. + * If we can't use DMA we can't use synch transfer. Also check the + * sfas_inhibit_xxx[target] flags. + */ + if ((dev->sc_config_flags & (SFAS_NO_SYNCH | SFAS_NO_DMA)) || + sfas_inhibit_sync[(int)target]) + mode &= ~SFAS_SELECT_S; + + if ((dev->sc_config_flags & SFAS_NO_RESELECT) || + sfas_inhibit_disc[(int)target]) + mode &= ~SFAS_SELECT_R; + + nexus->xs = pendp->xs; + +/* Setup the nexus struct. */ + nexus->ID = ((mode & SFAS_SELECT_R) ? 0xC0 : 0x80) | lun; + nexus->clen = clen; + bcopy(cbuf, nexus->cbuf, nexus->clen); + nexus->cbuf[1] |= lun << 5; /* Fix the lun bits */ + nexus->cur_link = 0; + nexus->dma_len = 0; + nexus->dma_buf = 0; + nexus->dma_blk_len = 0; + nexus->dma_blk_ptr = 0; + nexus->len = len; + nexus->buf = buf; + nexus->lun_unit = (lun << 4) | target; + nexus->state = SFAS_NS_SELECTED; + +/* We must keep these flags. All else must be zero. */ + nexus->flags &= SFAS_NF_UNIT_BUSY | SFAS_NF_REQUEST_SENSE + | SFAS_NF_SYNC_TESTED | SFAS_NF_SELECT_ME; + +/* + * If we are requesting sense, reflect that in the flags so that we can handle + * error in sense data correctly + */ + if (nexus->flags & SFAS_NF_REQUEST_SENSE) { + nexus->flags &= ~SFAS_NF_REQUEST_SENSE; + nexus->flags |= SFAS_NF_SENSING; + } + + if (mode & SFAS_SELECT_I) + nexus->flags |= SFAS_NF_IMMEDIATE; + if (mode & SFAS_SELECT_K) + nexus->flags |= SFAS_NF_RESET; + + sync = ((mode & SFAS_SELECT_S) ? 1 : 0); + +/* We can't use sync during polled IO. */ + if (sync && (mode & SFAS_SELECT_I)) + sync = 0; + + if (!sync && + ((nexus->flags & SFAS_NF_SYNC_TESTED) && (nexus->offset != 0))) { + /* + * If the scsi unit is set to synch transfer and we don't want + * that, we have to renegotiate. + */ + + nexus->flags |= SFAS_NF_DO_SDTR; + nexus->period = 200; + nexus->offset = 0; + } else if (sync && !(nexus->flags & SFAS_NF_SYNC_TESTED)) { + /* + * If the scsi unit is not set to synch transfer and we want + * that, we have to negotiate. This should realy base the + * period on the clock frequence rather than just check if + * >25Mhz + */ + + nexus->flags |= SFAS_NF_DO_SDTR; + nexus->period = ((dev->sc_clock_freq>25) ? 100 : 200); + nexus->offset = 8; + + /* If the user has a long cable, we want to limit the period */ + if ((nexus->period == 100) && + (dev->sc_config_flags & SFAS_SLOW_CABLE)) + nexus->period = 200; + } + +/* + * Fake a dma-block for polled IO. This way we can use the same code to handle + * reselection. Much nicer this way. + */ + if ((mode & SFAS_SELECT_I) || (dev->sc_config_flags & SFAS_NO_DMA)) { + nexus->dma[0].ptr = (vm_offset_t)buf; + nexus->dma[0].len = len; + nexus->dma[0].flg = SFAS_CHAIN_PRG; + nexus->max_link = 1; + } else { + nexus->max_link = dev->sc_build_dma_chain(dev, nexus->dma, + buf, len); + } + +/* Flush the caches. (If needed) */ +/* Do I need to ? */ +/* + if ((mmutype == MMU_68040) && len && !(mode & SFAS_SELECT_I)) + dma_cachectl(buf, len); +*/ +} + +int +sfasselect(dev, pendp, cbuf, clen, buf, len, mode) + struct sfas_softc *dev; + struct sfas_pending *pendp; + unsigned char *cbuf; + int clen; + unsigned char *buf; + int len; + int mode; +{ + struct nexus *nexus; + +/* Get the nexus struct. */ + nexus = sfas_arbitate_target(dev, pendp->xs->sc_link->target); + if (nexus == NULL) + return(0); + +/* Setup the nexus struct. */ + sfas_setup_nexus(dev, nexus, pendp, cbuf, clen, buf, len, mode); + +/* Post it to the interrupt machine. */ + sfas_select_unit(dev, pendp->xs->sc_link->target); + + return(1); +} + +void +sfas_request_sense(dev, nexus) + struct sfas_softc *dev; + struct nexus *nexus; +{ + struct scsi_xfer *xs; + struct sfas_pending pend; + struct scsi_sense rqs; + int mode; + + xs = nexus->xs; + +/* Fake a sfas_pending structure. */ + pend.xs = xs; + + rqs.opcode = REQUEST_SENSE; + rqs.byte2 = xs->sc_link->lun << 5; +#ifdef not_yet + rqs.length=xs->req_sense_length?xs->req_sense_length:sizeof(xs->sense); +#else + rqs.length=sizeof(xs->sense); +#endif + + rqs.unused[0] = rqs.unused[1] = rqs.control = 0; + +/* + * If we are requesting sense during polled IO, we have to sense with polled + * IO too. + */ + mode = SFAS_SELECT_RS; + if (nexus->flags & SFAS_NF_IMMEDIATE) + mode = SFAS_SELECT_I; + +/* Setup the nexus struct for sensing. */ + sfas_setup_nexus(dev, nexus, &pend, (char *)&rqs, sizeof(rqs), + (char *)&xs->sense, rqs.length, mode); + +/* Post it to the interrupt machine. */ + sfas_select_unit(dev, xs->sc_link->target); +} + +void +sfasgo(dev, pendp) + struct sfas_softc *dev; + struct sfas_pending *pendp; +{ + int s; + char *buf; + + buf = pendp->xs->data; + + if (sfasselect(dev, pendp, (char *)pendp->xs->cmd, pendp->xs->cmdlen, + buf, pendp->xs->datalen, SFAS_SELECT_RS)) { + /* + * We got the command going so the sfas_pending struct is now + * free to reuse. + */ + + s = splbio(); + TAILQ_INSERT_TAIL(&dev->sc_xs_free, pendp, link); + splx(s); + } else { + /* + * We couldn't make the command fly so we have to wait. The + * struct MUST be inserted at the head to keep the order of + * the commands. + */ + + s = splbio(); + TAILQ_INSERT_HEAD(&dev->sc_xs_pending, pendp, link); + splx(s); + } + + return; +} + +/* + * Part one of the interrupt machine. Error checks and reselection test. + * We don't know if we have an active nexus here! + */ +int +sfas_pretests(dev, rp) + struct sfas_softc *dev; + sfas_regmap_p rp; +{ + struct nexus *nexus; + int i, s; + + if (dev->sc_interrupt & SFAS_INT_SCSI_RESET_DETECTED) { + /* + * Cleanup and notify user. Lets hope that this is all we + * have to do + */ + + for(i=0; i<8; i++) { + if (dev->sc_nexus[i].xs) + sfas_scsidone(dev, dev->sc_nexus[i].xs, -2); + + sfas_init_nexus(dev, &dev->sc_nexus[i]); + } + printf("sfasintr: SCSI-RESET detected!"); + return(-1); + } + + if (dev->sc_interrupt & SFAS_INT_ILLEGAL_COMMAND) { + /* Something went terrible wrong! Dump some data and panic! */ + + printf("FIFO:"); + while(*rp->sfas_fifo_flags & SFAS_FIFO_COUNT_MASK) + printf(" %x", *rp->sfas_fifo); + printf("\n"); + + printf("CMD: %x\n", *rp->sfas_command); + panic("sfasintr: ILLEGAL COMMAND!"); + } + + if (dev->sc_interrupt & SFAS_INT_RESELECTED) { + /* We were reselected. Set the chip as busy */ + + s = splbio(); + dev->sc_flags |= SFAS_ACTIVE; + if (dev->sc_sel_nexus) { + dev->sc_sel_nexus->flags |= SFAS_NF_SELECT_ME; + dev->sc_sel_nexus = 0; + } + splx(s); + + if (dev->sc_units_disconnected) { + /* Find out who reselected us. */ + + dev->sc_resel[0] &= ~(1<sc_host_id); + + for(i=0; i<8; i++) + if (dev->sc_resel[0] & (1<sc_nexus[i].state == SFAS_NS_DISCONNECTED) { + /* + * This unit had disconnected, so we reconnect + * it. + */ + + dev->sc_cur_nexus = &dev->sc_nexus[i]; + nexus = dev->sc_cur_nexus; + + *rp->sfas_syncper = nexus->syncper; + *rp->sfas_syncoff = nexus->syncoff; + *rp->sfas_config3 = nexus->config3; + + *rp->sfas_dest_id = i & 7; + + dev->sc_units_disconnected--; + dev->sc_msg_in_len= 0; + + /* Restore active pointers. */ + sfas_restore_pointers(dev); + + nexus->state = SFAS_NS_RESELECTED; + + *rp->sfas_command = SFAS_CMD_MESSAGE_ACCEPTED; + + return(1); + } + } + + /* Somehow we got an illegal reselection. Dump and panic. */ + printf("sfasintr: resel[0] %x resel[1] %x disconnected %d\n", + dev->sc_resel[0], dev->sc_resel[1], + dev->sc_units_disconnected); + panic("sfasintr: Unexpected reselection!"); + } + + return(0); +} + +/* + * Part two of the interrupt machine. Handle disconnection and post command + * processing. We know that we have an active nexus here. + */ +int +sfas_midaction(dev, rp, nexus) + struct sfas_softc *dev; + sfas_regmap_p rp; + struct nexus *nexus; +{ + int i, left, len, s; + u_char status, msg; + + if (dev->sc_interrupt & SFAS_INT_DISCONNECT) { + s = splbio(); + dev->sc_cur_nexus = 0; + + /* Mark chip as busy and clean up the chip FIFO. */ + dev->sc_flags &= ~SFAS_ACTIVE; + *rp->sfas_command = SFAS_CMD_FLUSH_FIFO; + + /* Let the nexus state reflect what we have to do. */ + switch(nexus->state) { + case SFAS_NS_SELECTED: + dev->sc_sel_nexus = 0; + nexus->flags &= ~SFAS_NF_SELECT_ME; + + /* + * We were trying to select the unit. Probably no unit + * at this ID. + */ + nexus->xs->resid = dev->sc_len; + + nexus->status = -2; + nexus->flags &= ~SFAS_NF_UNIT_BUSY; + nexus->state = SFAS_NS_FINISHED; + break; + + case SFAS_NS_SENSE: + /* + * Oops! We have to request sense data from this unit. + * Do so. + */ + dev->sc_led(dev, 0); + nexus->flags |= SFAS_NF_REQUEST_SENSE; + sfas_request_sense(dev, nexus); + break; + + case SFAS_NS_DONE: + /* All done. */ + nexus->xs->resid = dev->sc_len; + + nexus->flags &= ~SFAS_NF_UNIT_BUSY; + nexus->state = SFAS_NS_FINISHED; + dev->sc_led(dev, 0); + break; + + case SFAS_NS_DISCONNECTING: + /* + * We have recieved a DISCONNECT message, so we are + * doing a normal disconnection. + */ + nexus->state = SFAS_NS_DISCONNECTED; + + dev->sc_units_disconnected++; + break; + + case SFAS_NS_RESET: + /* + * We were reseting this SCSI-unit. Clean up the + * nexus struct. + */ + dev->sc_led(dev, 0); + sfas_init_nexus(dev, nexus); + break; + + default: + /* + * Unexpected disconnection! Cleanup and exit. This + * shouldn't cause any problems. + */ + printf("sfasintr: Unexpected disconnection\n"); + printf("sfasintr: u %x s %d p %d f %x c %x\n", + nexus->lun_unit, nexus->state, + dev->sc_status & SFAS_STAT_PHASE_MASK, + nexus->flags, nexus->cbuf[0]); + + nexus->xs->resid = dev->sc_len; + + nexus->flags &= ~SFAS_NF_UNIT_BUSY; + nexus->state = SFAS_NS_FINISHED; + nexus->status = -3; + + dev->sc_led(dev, 0); + break; + } + + /* + * If we have disconnected units, we MUST enable reselection + * within 250ms. + */ + if (dev->sc_units_disconnected && + !(dev->sc_flags & SFAS_ACTIVE)) + *rp->sfas_command = SFAS_CMD_ENABLE_RESEL; + + splx(s); + + /* Select the first pre-initialized nexus we find. */ + for(i=0; i<8; i++) + if (dev->sc_nexus[i].flags & SFAS_NF_SELECT_ME) + if (sfas_select_unit(dev, i) == 2) + break; + + /* Does any unit need sense data? */ + for(i=0; i<8; i++) + if (dev->sc_nexus[i].flags & SFAS_NF_REQUEST_SENSE) { + sfas_request_sense(dev, &dev->sc_nexus[i]); + break; + } + + /* We are done with this nexus! */ + if (nexus->state == SFAS_NS_FINISHED) + sfas_scsidone(dev, nexus->xs, nexus->status); + + return(1); + } + + switch(nexus->state) { + case SFAS_NS_SELECTED: + dev->sc_cur_nexus = nexus; + dev->sc_sel_nexus = 0; + + nexus->flags &= ~SFAS_NF_SELECT_ME; + + /* + * We have selected a unit. Setup chip, restore pointers and + * light the led. + */ + *rp->sfas_syncper = nexus->syncper; + *rp->sfas_syncoff = nexus->syncoff; + *rp->sfas_config3 = nexus->config3; + + sfas_restore_pointers(dev); + + if (!(nexus->flags & SFAS_NF_SENSING)) + nexus->status = 0xFF; + dev->sc_msg_in[0] = 0xFF; + dev->sc_msg_in_len= 0; + + dev->sc_led(dev, 1); + + break; + + case SFAS_NS_DATA_IN: + case SFAS_NS_DATA_OUT: + /* We have transfered data. */ + if (dev->sc_dma_len) + if (dev->sc_cur_link < dev->sc_max_link) { + /* + * Clean up dma and at the same time get how + * many bytes that were NOT transfered. + */ + left = dev->sc_setup_dma(dev, 0, 0, SFAS_DMA_CLEAR); + len = dev->sc_dma_len; + + if (nexus->state == SFAS_NS_DATA_IN) { + /* + * If we were bumping we may have had an odd length + * which means that there may be bytes left in the + * fifo. We also need to move the data from the + * bump buffer to the actual memory. + */ + if (dev->sc_dma_buf == dev->sc_bump_pa) + { + while((*rp->sfas_fifo_flags&SFAS_FIFO_COUNT_MASK) + && left) + dev->sc_bump_va[len-(left--)] = *rp->sfas_fifo; + + bcopy(dev->sc_bump_va, dev->sc_buf, len-left); + } + } else { + /* Count any unsent bytes and flush them. */ + left+= *rp->sfas_fifo_flags & SFAS_FIFO_COUNT_MASK; + *rp->sfas_command = SFAS_CMD_FLUSH_FIFO; + } + + /* + * Update pointers/length to reflect the transfered + * data. + */ + dev->sc_len -= len-left; + dev->sc_buf += len-left; + + dev->sc_dma_buf += len-left; + dev->sc_dma_len = left; + + dev->sc_dma_blk_ptr += len-left; + dev->sc_dma_blk_len -= len-left; + + /* + * If it was the end of a dma block, we select the + * next to begin with. + */ + if (!dev->sc_dma_blk_len) + dev->sc_cur_link++; + } + break; + + case SFAS_NS_STATUS: + /* + * If we were not sensing, grab the status byte. If we were + * sensing and we got a bad status, let the user know. + */ + + status = *rp->sfas_fifo; + msg = *rp->sfas_fifo; + + if (!(nexus->flags & SFAS_NF_SENSING)) + nexus->status = status; + else if (status != 0) + nexus->status = -1; + + /* + * Preload the command complete message. Handeled in + * sfas_postaction. + */ + dev->sc_msg_in[0] = msg; + dev->sc_msg_in_len = 1; + nexus->flags |= SFAS_NF_HAS_MSG; + break; + + default: + break; + } + + return(0); +} + +/* + * Part three of the interrupt machine. Handle phase changes (and repeated + * phase passes). We know that we have an active nexus here. + */ +int +sfas_postaction(dev, rp, nexus) + struct sfas_softc *dev; + sfas_regmap_p rp; + struct nexus *nexus; +{ + int i, len; + u_char cmd; + short offset, period; + + cmd = 0; + + switch(dev->sc_status & SFAS_STAT_PHASE_MASK) { + case SFAS_PHASE_DATA_OUT: + case SFAS_PHASE_DATA_IN: + if ((dev->sc_status & SFAS_STAT_PHASE_MASK) == + SFAS_PHASE_DATA_OUT) + nexus->state = SFAS_NS_DATA_OUT; + else + nexus->state = SFAS_NS_DATA_IN; + + /* Make DMA ready to accept new data. Load active pointers + * from the DMA block. */ + dev->sc_setup_dma(dev, 0, 0, SFAS_DMA_CLEAR); + if (dev->sc_cur_link < dev->sc_max_link) { + if (!dev->sc_dma_blk_len) { + dev->sc_dma_blk_ptr = dev->sc_chain[dev->sc_cur_link].ptr; + dev->sc_dma_blk_len = dev->sc_chain[dev->sc_cur_link].len; + dev->sc_dma_blk_flg = dev->sc_chain[dev->sc_cur_link].flg; + } + + /* We should use polled IO here. */ + if (dev->sc_dma_blk_flg == SFAS_CHAIN_PRG) { + sfas_ixfer(dev, nexus->xs->flags & SCSI_POLL); + dev->sc_cur_link++; + dev->sc_dma_len = 0; + break; + } + else if (dev->sc_dma_blk_flg == SFAS_CHAIN_BUMP) + len = dev->sc_dma_blk_len; + else + len = dev->sc_need_bump(dev, dev->sc_dma_blk_ptr, + dev->sc_dma_blk_len); + + /* + * If len != 0 we must bump the data, else we just DMA it + * straight into memory. + */ + if (len) { + dev->sc_dma_buf = dev->sc_bump_pa; + dev->sc_dma_len = len; + + if (nexus->state == SFAS_NS_DATA_OUT) + bcopy(dev->sc_buf, dev->sc_bump_va, dev->sc_dma_len); + } else { + dev->sc_dma_buf = dev->sc_dma_blk_ptr; + dev->sc_dma_len = dev->sc_dma_blk_len; + } + + /* Load DMA with adress and length of transfer. */ + dev->sc_setup_dma(dev, dev->sc_dma_buf, dev->sc_dma_len, + ((nexus->state == SFAS_NS_DATA_OUT) ? + SFAS_DMA_WRITE : SFAS_DMA_READ)); + + printf("Using DMA !!!!\n"); + cmd = SFAS_CMD_TRANSFER_INFO | SFAS_CMD_DMA; + } else { + /* + * Hmmm, the unit wants more info than we have or has + * more than we want. Let the chip handle that. + */ + + *rp->sfas_tc_low = 0; /* was 256 but this does not make sense */ + *rp->sfas_tc_mid = 1; + *rp->sfas_tc_high = 0; + cmd = SFAS_CMD_TRANSFER_PAD; + } + break; + + case SFAS_PHASE_COMMAND: + /* The scsi unit wants the command, send it. */ + nexus->state = SFAS_NS_SVC; + + *rp->sfas_command = SFAS_CMD_FLUSH_FIFO; + for(i=0; i<5; i++); + + for(i=0; iclen; i++) + *rp->sfas_fifo = nexus->cbuf[i]; + cmd = SFAS_CMD_TRANSFER_INFO; + break; + + case SFAS_PHASE_STATUS: + /* + * We've got status phase. Request status and command + * complete message. + */ + nexus->state = SFAS_NS_STATUS; + cmd = SFAS_CMD_COMMAND_COMPLETE; + break; + + case SFAS_PHASE_MESSAGE_OUT: + /* + * Either the scsi unit wants us to send a message or we have + * asked for it by seting the ATN bit. + */ + nexus->state = SFAS_NS_MSG_OUT; + + *rp->sfas_command = SFAS_CMD_FLUSH_FIFO; + + if (nexus->flags & SFAS_NF_DO_SDTR) { + /* Send a Synchronous Data Transfer Request. */ + + sfas_build_sdtrm(dev, nexus->period, nexus->offset); + nexus->flags |= SFAS_NF_SDTR_SENT; + nexus->flags &= ~SFAS_NF_DO_SDTR; + } else if (nexus->flags & SFAS_NF_RESET) { + /* Send a reset scsi unit message. */ + + dev->sc_msg_out[0] = 0x0C; + dev->sc_msg_out_len = 1; + nexus->state = SFAS_NS_RESET; + nexus->flags &= ~SFAS_NF_RESET; + } else if (dev->sc_msg_out_len == 0) { + /* Don't know what to send so we send a NOP message. */ + + dev->sc_msg_out[0] = 0x08; + dev->sc_msg_out_len = 1; + } + + cmd = SFAS_CMD_TRANSFER_INFO; + + for(i=0; isc_msg_out_len; i++) + *rp->sfas_fifo = dev->sc_msg_out[i]; + dev->sc_msg_out_len = 0; + + break; + + case SFAS_PHASE_MESSAGE_IN: + /* Receive a message from the scsi unit. */ + nexus->state = SFAS_NS_MSG_IN; + + while(!(nexus->flags & SFAS_NF_HAS_MSG)) { + *rp->sfas_command = SFAS_CMD_TRANSFER_INFO; + sfasiwait(dev); + + dev->sc_msg_in[dev->sc_msg_in_len++] = *rp->sfas_fifo; + + /* Check if we got all the bytes in the message. */ + if (dev->sc_msg_in[0] >= 0x80) ; + else if (dev->sc_msg_in[0] >= 0x30) ; + else if (((dev->sc_msg_in[0] >= 0x20) && + (dev->sc_msg_in_len == 2)) || + ((dev->sc_msg_in[0] != 0x01) && + (dev->sc_msg_in_len == 1))) { + nexus->flags |= SFAS_NF_HAS_MSG; + break; + } else { + if (dev->sc_msg_in_len >= 2) + if ((dev->sc_msg_in[1]+2) == dev->sc_msg_in_len) { + nexus->flags |= SFAS_NF_HAS_MSG; + break; + } + } + + *rp->sfas_command = SFAS_CMD_MESSAGE_ACCEPTED; + sfasiwait(dev); + + if ((dev->sc_status & SFAS_STAT_PHASE_MASK) != + SFAS_PHASE_MESSAGE_IN) + break; + } + + cmd = SFAS_CMD_MESSAGE_ACCEPTED; + if (nexus->flags & SFAS_NF_HAS_MSG) { + /* We have a message. Decode it. */ + + switch(dev->sc_msg_in[0]) { + case 0x00: /* COMMAND COMPLETE */ + if ((nexus->status == SCSI_CHECK) && + !(nexus->flags & SFAS_NF_SENSING)) + nexus->state = SFAS_NS_SENSE; + else + nexus->state = SFAS_NS_DONE; + break; + case 0x04: /* DISCONNECT */ + nexus->state = SFAS_NS_DISCONNECTING; + break; + case 0x02: /* SAVE DATA POINTER */ + sfas_save_pointers(dev); + break; + case 0x03: /* RESTORE DATA POINTERS */ + sfas_restore_pointers(dev); + break; + case 0x07: /* MESSAGE REJECT */ + /* + * If we had sent a SDTR and we got a message + * reject, the scsi docs say that we must go + * to async transfer. + */ + if (nexus->flags & SFAS_NF_SDTR_SENT) { + nexus->flags &= ~SFAS_NF_SDTR_SENT; + + nexus->config3 &= ~SFAS_CFG3_FASTSCSI; + nexus->syncper = 5; + nexus->syncoff = 0; + + *rp->sfas_syncper = nexus->syncper; + *rp->sfas_syncoff = nexus->syncoff; + *rp->sfas_config3 = nexus->config3; + } else + /* + * Something was rejected but we don't know + * what! PANIC! + */ + panic("sfasintr: Unknown message rejected!"); + break; + case 0x08: /* MO OPERATION */ + break; + case 0x01: /* EXTENDED MESSAGE */ + switch(dev->sc_msg_in[2]) { + case 0x01:/* SYNC. DATA TRANSFER REQUEST */ + /* Decode the SDTR message. */ + period = 4*dev->sc_msg_in[3]; + offset = dev->sc_msg_in[4]; + + /* + * Make sure that the specs are within + * chip limits. Note that if we + * initiated the negotiation the specs + * WILL be withing chip limits. If it + * was the scsi unit that initiated + * the negotiation, the specs may be + * to high. + */ + if (offset > 16) + offset = 16; + if ((period < 200) && + (dev->sc_clock_freq <= 25)) + period = 200; + + if (offset == 0) + period = 5*dev->sc_clock_period; + + nexus->syncper = period/ + dev->sc_clock_period; + nexus->syncoff = offset; + + if (period < 200) + nexus->config3 |= SFAS_CFG3_FASTSCSI; + else + nexus->config3 &=~SFAS_CFG3_FASTSCSI; + + nexus->flags |= SFAS_NF_SYNC_TESTED; + + *rp->sfas_syncper = nexus->syncper; + *rp->sfas_syncoff = nexus->syncoff; + *rp->sfas_config3 = nexus->config3; + + /* + * Hmmm, it seems that the scsi unit + * initiated sync negotiation, so lets + * reply acording to scsi-2 standard. + */ + if (!(nexus->flags& SFAS_NF_SDTR_SENT)) + { + if ((dev->sc_config_flags & + SFAS_NO_SYNCH) || + (dev->sc_config_flags & + SFAS_NO_DMA) || + sfas_inhibit_sync[ + nexus->lun_unit & 7]) { + period = 200; + offset = 0; + } + + nexus->offset = offset; + nexus->period = period; + nexus->flags |= SFAS_NF_DO_SDTR; + *rp->sfas_command = SFAS_CMD_SET_ATN; + } + + nexus->flags &= ~SFAS_NF_SDTR_SENT; + break; + + case 0x00: /* MODIFY DATA POINTERS */ + case 0x02: /* EXTENDED IDENTIFY (SCSI-1) */ + case 0x03: /* WIDE DATA TRANSFER REQUEST */ + default: + /* Reject any unhandeled messages. */ + + dev->sc_msg_out[0] = 0x07; + dev->sc_msg_out_len = 1; + *rp->sfas_command = SFAS_CMD_SET_ATN; + cmd = SFAS_CMD_MESSAGE_ACCEPTED; + break; + } + break; + + default: + /* Reject any unhandeled messages. */ + + dev->sc_msg_out[0] = 0x07; + dev->sc_msg_out_len = 1; + *rp->sfas_command = SFAS_CMD_SET_ATN; + cmd = SFAS_CMD_MESSAGE_ACCEPTED; + break; + } + nexus->flags &= ~SFAS_NF_HAS_MSG; + dev->sc_msg_in_len = 0; + } + break; + default: + printf("SFASINTR: UNKNOWN PHASE! phase: %d\n", + dev->sc_status & SFAS_STAT_PHASE_MASK); + dev->sc_led(dev, 0); + sfas_scsidone(dev, nexus->xs, -4); + + return(-1); + } + + if (cmd) + *rp->sfas_command = cmd; + + return(0); +} + +/* + * Stub for interrupt machine. + */ +void +sfasintr(dev) + struct sfas_softc *dev; +{ + sfas_regmap_p rp; + struct nexus *nexus; + + rp = dev->sc_fas; + + if (!sfas_pretests(dev, rp)) { + + nexus = dev->sc_cur_nexus; + if (nexus == NULL) + nexus = dev->sc_sel_nexus; + + if (nexus) + if (!sfas_midaction(dev, rp, nexus)) + sfas_postaction(dev, rp, nexus); + } +} + +/* + * sfasicmd is used to perform IO when we can't use interrupts. sfasicmd + * emulates the normal environment by waiting for the chip and calling + * sfasintr. + */ +void +sfasicmd(dev, pendp) + struct sfas_softc *dev; + struct sfas_pending *pendp; +{ + sfas_regmap_p rp; + struct nexus *nexus; + + nexus = &dev->sc_nexus[pendp->xs->sc_link->target]; + rp = dev->sc_fas; + + if (!sfasselect(dev, pendp, (char *)pendp->xs->cmd, pendp->xs->cmdlen, + (char *)pendp->xs->data, pendp->xs->datalen, + SFAS_SELECT_I)) + panic("sfasicmd: Couldn't select unit"); + + while(nexus->state != SFAS_NS_FINISHED) { + sfasiwait(dev); + sfasintr(dev); + } + + nexus->flags &= ~SFAS_NF_SYNC_TESTED; +} diff --git a/sys/arch/arm32/podulebus/sfasreg.h b/sys/arch/arm32/podulebus/sfasreg.h new file mode 100644 index 00000000000..9c4020ae7f6 --- /dev/null +++ b/sys/arch/arm32/podulebus/sfasreg.h @@ -0,0 +1,158 @@ +/* $NetBSD: sfasreg.h,v 1.1 1996/01/31 23:26:45 mark Exp $ */ + +/* + * Copyright (c) 1995 Daniel Widenfalk + * + * 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 Daniel Widenfalk + * 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 _SFASREG_H_ +#define _SFASREG_H_ + +/* + * Emulex FAS216 SCSI interface hardware description. + */ + +typedef volatile unsigned char vu_char; + +typedef struct { + vu_char *sfas_tc_low; /* rw: Transfer count low */ + vu_char *sfas_tc_mid; /* rw: Transfer count mid */ + vu_char *sfas_fifo; /* rw: Data FIFO */ + vu_char *sfas_command; /* rw: Chip command reg */ + vu_char *sfas_dest_id; /* w: (Re)select bus ID */ +#define sfas_status sfas_dest_id /* r: Status */ + vu_char *sfas_timeout; /* w: (Re)select timeout */ +#define sfas_interrupt sfas_timeout /* r: Interrupt */ + vu_char *sfas_syncper; /* w: Synch. transfer period */ +#define sfas_seqstep sfas_syncper /* r: Sequence step */ + vu_char *sfas_syncoff; /* w: Synch. transfer offset */ +#define sfas_fifo_flags sfas_syncoff /* r: FIFO flags */ + vu_char *sfas_config1; /* rw: Config register #1 */ + vu_char *sfas_clkconv; /* w: Clock conv. factor */ + vu_char *sfas_test; /* w: Test register */ + vu_char *sfas_config2; /* rw: Config register #2 */ + vu_char *sfas_config3; /* rw: Config register #3 */ + vu_char *sfas_tc_high; /* rw: Transfer count high */ + vu_char *sfas_fifo_bot; /* w: FIFO bottom register */ +} sfas_regmap_t; +typedef sfas_regmap_t *sfas_regmap_p; + +/* Commands for the FAS216 */ +#define SFAS_CMD_DMA 0x80 + +#define SFAS_CMD_SEL_NO_ATN 0x41 +#define SFAS_CMD_SEL_ATN 0x42 +#define SFAS_CMD_SEL_ATN3 0x46 +#define SFAS_CMD_SEL_ATN_STOP 0x43 + +#define SFAS_CMD_ENABLE_RESEL 0x44 +#define SFAS_CMD_DISABLE_RESEL 0x45 + +#define SFAS_CMD_TRANSFER_INFO 0x10 +#define SFAS_CMD_TRANSFER_PAD 0x98 + +#define SFAS_CMD_COMMAND_COMPLETE 0x11 +#define SFAS_CMD_MESSAGE_ACCEPTED 0x12 + +#define SFAS_CMD_SET_ATN 0x1A +#define SFAS_CMD_RESET_ATN 0x1B + +#define SFAS_CMD_NOP 0x00 +#define SFAS_CMD_FLUSH_FIFO 0x01 +#define SFAS_CMD_RESET_CHIP 0x02 +#define SFAS_CMD_RESET_SCSI_BUS 0x03 + +#define SFAS_STAT_PHASE_MASK 0x07 +#define SFAS_STAT_PHASE_TRANS_CPLT 0x08 +#define SFAS_STAT_TRANSFER_COUNT_ZERO 0x10 +#define SFAS_STAT_PARITY_ERROR 0x20 +#define SFAS_STAT_GROSS_ERROR 0x40 +#define SFAS_STAT_INTERRUPT_PENDING 0x80 + +#define SFAS_PHASE_DATA_OUT 0 +#define SFAS_PHASE_DATA_IN 1 +#define SFAS_PHASE_COMMAND 2 +#define SFAS_PHASE_STATUS 3 +#define SFAS_PHASE_MESSAGE_OUT 6 +#define SFAS_PHASE_MESSAGE_IN 7 + +#define SFAS_DEST_ID_MASK 0x07 + +#define SFAS_INT_SELECTED 0x01 +#define SFAS_INT_SELECTED_WITH_ATN 0x02 +#define SFAS_INT_RESELECTED 0x04 +#define SFAS_INT_FUNCTION_COMPLETE 0x08 +#define SFAS_INT_BUS_SERVICE 0x10 +#define SFAS_INT_DISCONNECT 0x20 +#define SFAS_INT_ILLEGAL_COMMAND 0x40 +#define SFAS_INT_SCSI_RESET_DETECTED 0x80 + +#define SFAS_SYNCHRON_PERIOD_MASK 0x1F + +#define SFAS_FIFO_COUNT_MASK 0x1F +#define SFAS_FIFO_SEQUENCE_STEP_MASK 0xE0 +#define SFAS_FIFO_SEQUENCE_SHIFT 5 + +#define SFAS_SYNCHRON_OFFSET_MASK 0x0F +#define SFAS_SYNC_ASSERT_MASK 0x30 +#define SFAS_SYNC_ASSERT_SHIFT 4 +#define SFAS_SYNC_DEASSERT_MASK 0x30 +#define SFAS_SYNC_DEASSERT_SHIFT 6 + +#define SFAS_CFG1_BUS_ID_MASK 0x07 +#define SFAS_CFG1_CHIP_TEST_MODE 0x08 +#define SFAS_CFG1_SCSI_PARITY_ENABLE 0x10 +#define SFAS_CFG1_PARITY_TEST_MODE 0x20 +#define SFAS_CFG1_SCSI_RES_INT_DIS 0x40 +#define SFAS_CFG1_SLOW_CABLE_MODE 0x80 + +#define SFAS_CLOCK_CONVERSION_MASK 0x07 + +#define SFAS_TEST_TARGET_TEST_MODE 0x01 +#define SFAS_TEST_INITIATOR_TEST_MODE 0x02 +#define SFAS_TEST_TRISTATE_TEST_MODE 0x04 + +#define SFAS_CFG2_DMA_PARITY_ENABLE 0x01 +#define SFAS_CFG2_REG_PARITY_ENABLE 0x02 +#define SFAS_CFG2_TARG_BAD_PARITY_ABORT 0x04 +#define SFAS_CFG2_SCSI_2_MODE 0x08 +#define SFAS_CFG2_TRISTATE_DMA_REQ 0x10 +#define SFAS_CFG2_BYTE_CONTROL_MODE 0x20 +#define SFAS_CFG2_FEATURES_ENABLE 0x40 +#define SFAS_CFG2_RESERVE_FIFO_BYTE 0x80 + +#define SFAS_CFG3_THRESHOLD_8_MODE 0x01 +#define SFAS_CFG3_ALTERNATE_DMA_MODE 0x02 +#define SFAS_CFG3_SAVE_RESIDUAL_BYTE 0x04 +#define SFAS_CFG3_FASTCLK 0x08 +#define SFAS_CFG3_FASTSCSI 0x10 +#define SFAS_CFG3_CDB10 0x20 +#define SFAS_CFG3_QENB 0x40 +#define SFAS_CFG3_IDRESCHK 0x80 + +#endif diff --git a/sys/arch/arm32/podulebus/sfasvar.h b/sys/arch/arm32/podulebus/sfasvar.h new file mode 100644 index 00000000000..04dc68d70f8 --- /dev/null +++ b/sys/arch/arm32/podulebus/sfasvar.h @@ -0,0 +1,263 @@ +/* $NetBSD: sfasvar.h,v 1.1 1996/01/31 23:26:49 mark Exp $ */ + +/* + * Copyright (c) 1995 Daniel Widenfalk + * + * 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 Daniel Widenfalk + * 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 _SFASVAR_H_ +#define _SFASVAR_H_ + +#ifndef _SFASREG_H_ +#include +#endif + +/* + * MAXCHAIN is the anticipated maximum number of chain blocks needed. This + * assumes that we are NEVER requested to transfer more than MAXPHYS bytes. + */ +#define MAXCHAIN (MAXPHYS/NBPG+2) + +/* + * Maximum number of requests standing by. Could be anything, but I think 9 + * looks nice :-) NOTE: This does NOT include requests already started! + */ +#define MAXPENDING 9 /* 7 IDs + 2 extra */ + +/* + * DMA chain block. If flg == SFAS_CHAIN_PRG or flg == SFAS_CHAIN_BUMP then + * ptr is a VIRTUAL adress. If flg == SFAS_CHAIN_DMA then ptr is a PHYSICAL + * adress. + */ +struct sfas_dma_chain { + vm_offset_t ptr; + u_short len; + short flg; +}; +#define SFAS_CHAIN_DMA 0x00 +#define SFAS_CHAIN_BUMP 0x01 +#define SFAS_CHAIN_PRG 0x02 + + +/* + * This struct contains the necessary info for a pending request. Pointer to + * a scsi_xfer struct. + */ +struct sfas_pending { + TAILQ_ENTRY(sfas_pending) link; + struct scsi_xfer *xs; +}; + +/* + * nexus contains all active data for one SCSI unit. Parts of the info in this + * struct survives between scsi commands. + */ +struct nexus { + struct scsi_xfer *xs; /* Pointer to request */ + + u_char ID; /* ID message to be sent */ + u_char clen; /* scsi command length + */ + u_char cbuf[14]; /* the actual command bytes */ + + struct sfas_dma_chain dma[MAXCHAIN]; /* DMA chain blocks */ + short max_link; /* Maximum used of above */ + short cur_link; /* Currently handled block */ + + u_char *buf; /* Virtual adress of data */ + int len; /* Bytes left to transfer */ + + vm_offset_t dma_buf; /* Current DMA adress */ + int dma_len; /* Current DMA length */ + + vm_offset_t dma_blk_ptr; /* Current chain adress */ + int dma_blk_len; /* Current chain length */ + u_char dma_blk_flg; /* Current chain flags */ + + u_char state; /* Nexus state, see below */ + u_short flags; /* Nexus flags, see below */ + + short period; /* Sync period to request */ + u_char offset; /* Sync offset to request */ + + u_char syncper; /* FAS216 variable storage */ + u_char syncoff; /* FAS216 variable storage */ + u_char config3; /* FAS216 variable storage */ + + u_char lun_unit; /* (Lun<<4) | Unit of nexus */ + u_char status; /* Status byte from unit*/ + +}; + +/* SCSI nexus_states */ +#define SFAS_NS_IDLE 0 /* Nexus idle */ +#define SFAS_NS_SELECTED 1 /* Last command was a SELECT command */ +#define SFAS_NS_DATA_IN 2 /* Last command was a TRANSFER_INFO */ + /* command during a data in phase */ +#define SFAS_NS_DATA_OUT 3 /* Last command was a TRANSFER_INFO */ + /* command during a data out phase */ +#define SFAS_NS_STATUS 4 /* We have send a COMMAND_COMPLETE */ + /* command and are awaiting status */ +#define SFAS_NS_MSG_IN 5 /* Last phase was MESSAGE IN */ +#define SFAS_NS_MSG_OUT 6 /* Last phase was MESSAGE OUT */ +#define SFAS_NS_SVC 7 /* We have sent the command */ +#define SFAS_NS_DISCONNECTING 8 /* We have recieved a disconnect msg */ +#define SFAS_NS_DISCONNECTED 9 /* We are disconnected */ +#define SFAS_NS_RESELECTED 10 /* We was reselected */ +#define SFAS_NS_DONE 11 /* Done. Prephsase to FINISHED */ +#define SFAS_NS_FINISHED 12 /* Realy done. Call scsi_done */ +#define SFAS_NS_SENSE 13 /* We are requesting sense */ +#define SFAS_NS_RESET 14 /* We are reseting this unit */ + +/* SCSI nexus flags */ +#define SFAS_NF_UNIT_BUSY 0x0001 /* Unit is not available */ + +#define SFAS_NF_SELECT_ME 0x0002 /* Nexus is set up, waiting for bus */ + +#define SFAS_NF_REQUEST_SENSE 0x0004 /* We should request sense */ +#define SFAS_NF_SENSING 0x0008 /* We are sensing */ + +#define SFAS_NF_HAS_MSG 0x0010 /* We have recieved a complete msg */ + +#define SFAS_NF_DO_SDTR 0x0020 /* We should send a SDTR */ +#define SFAS_NF_SDTR_SENT 0x0040 /* We have sent a SDTR */ +#define SFAS_NF_SYNC_TESTED 0x0080 /* We have negotiated sync */ + +#define SFAS_NF_RESET 0x0100 /* Reset this nexus */ +#define SFAS_NF_IMMEDIATE 0x0200 /* We are operating from sfasicmd */ + +#define SFAS_NF_DEBUG 0x8000 /* As it says: DEBUG */ + +struct sfas_softc { + struct device sc_dev; /* System required struct */ + struct scsi_link sc_link; /* For sub devices */ + irqhandler_t sc_ih; /* Interrupt chain struct */ + + TAILQ_HEAD(,sfas_pending) sc_xs_pending; + TAILQ_HEAD(,sfas_pending) sc_xs_free; + struct sfas_pending sc_xs_store[MAXPENDING]; + + sfas_regmap_p sc_fas; /* FAS216 Address */ + void *sc_spec; /* Board-specific data */ + + u_char *sc_bump_va; /* Bumpbuf virtual adr */ + vm_offset_t sc_bump_pa; /* Bumpbuf physical adr */ + int sc_bump_sz; /* Bumpbuf size */ + +/* Configuration registers, must be set BEFORE sfasinitialize */ + u_char sc_clock_freq; + u_short sc_timeout; + u_char sc_host_id; + u_char sc_config_flags; + +/* Generic DMA functions */ + int (*sc_setup_dma)(); + int (*sc_build_dma_chain)(); + int (*sc_need_bump)(); + +/* Generic Led data */ + int sc_led_status; + void (*sc_led)(); + +/* Nexus list */ + struct nexus sc_nexus[8]; + struct nexus *sc_cur_nexus; + struct nexus *sc_sel_nexus; + +/* Current transfer data */ + u_char *sc_buf; /* va */ + int sc_len; + + vm_offset_t sc_dma_buf; /* pa */ + int sc_dma_len; + vm_offset_t sc_dma_blk_ptr; + int sc_dma_blk_len; + short sc_dma_blk_flg; + + struct sfas_dma_chain *sc_chain; /* Current DMA chain */ + short sc_max_link; + short sc_cur_link; + +/* Interrupt registers */ + u_char sc_status; + u_char sc_interrupt; + u_char sc_resel[2]; + + u_char sc_units_disconnected; + +/* Storage for FAS216 config registers (current values) */ + u_char sc_config1; + u_char sc_config2; + u_char sc_config3; + u_char sc_clock_conv_fact; + u_char sc_timeout_val; + u_char sc_clock_period; + + u_char sc_msg_in[7]; + u_char sc_msg_in_len; + + u_char sc_msg_out[7]; + u_char sc_msg_out_len; + + u_char sc_unit; + u_char sc_lun; + u_char sc_flags; +}; + +#define SFAS_DMA_READ 0 +#define SFAS_DMA_WRITE 1 +#define SFAS_DMA_CLEAR 2 + +/* sc_flags */ +#define SFAS_ACTIVE 0x01 +#define SFAS_DONT_WAIT 0x02 + +/* SCSI Selection modes */ +#define SFAS_SELECT 0x00 /* Normal selection: No sync, no resel */ +#define SFAS_SELECT_R 0x01 /* Reselection allowed */ +#define SFAS_SELECT_S 0x02 /* Synchronous transfer allowed */ +#define SFAS_SELECT_I 0x04 /* Selection for sfasicmd */ +#define SFAS_SELECT_K 0x08 /* Send a BUS DEVICE RESET message (Kill) */ + +/* Nice abbreviations of the above */ +#define SFAS_SELECT_RS (SFAS_SELECT_R|SFAS_SELECT_S) +#define SFAS_SELECT_RI (SFAS_SELECT_R|SFAS_SELECT_I) +#define SFAS_SELECT_SI (SFAS_SELECT_S|SFAS_SELECT_I) +#define SFAS_SELECT_RSI (SFAS_SELECT_R|SFAS_SELECT_S|SFAS_SELECT_I) + +/* sc_config_flags */ +#define SFAS_NO_SYNCH 0x01 /* Disable synchronous transfer */ +#define SFAS_NO_DMA 0x02 /* Do not use DMA! EVER! */ +#define SFAS_NO_RESELECT 0x04 /* Do not allow relesection */ +#define SFAS_SLOW_CABLE 0x08 /* Cable is "unsafe" for fast scsi-2 */ +#define SFAS_SLOW_START 0x10 /* There are slow starters on the bus */ + +void sfasinitialize __P((struct sfas_softc *sc)); +void sfas_minphys __P((struct buf *bp)); +int sfas_scsicmd __P((struct scsi_xfer *)); + +#endif /* _SFASVAR_H_ */