summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorleo <leo@NetBSD.org>1995-03-26 07:12:03 +0000
committerleo <leo@NetBSD.org>1995-03-26 07:12:03 +0000
commit8b0113cfceadf3ee3bc427c4680b6b46bb57ceea (patch)
tree2a5b7db0400149a733175c4b1a56774b2d4c1eb7 /sys
parent282052c7a8346370f47965457329f3b0b3fa01b7 (diff)
NetBSD/Atari, port by Leo Weppelman.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/atari/Makefile45
-rw-r--r--sys/arch/atari/atari/Locore.c350
-rw-r--r--sys/arch/atari/atari/atari_init.c603
-rw-r--r--sys/arch/atari/atari/autoconf.c275
-rw-r--r--sys/arch/atari/atari/conf.c701
-rw-r--r--sys/arch/atari/atari/device.h55
-rw-r--r--sys/arch/atari/atari/disksubr.c370
-rw-r--r--sys/arch/atari/atari/dkbad.c65
-rw-r--r--sys/arch/atari/atari/genassym.c166
-rw-r--r--sys/arch/atari/atari/kdassert.h56
-rw-r--r--sys/arch/atari/atari/locore.s2141
-rw-r--r--sys/arch/atari/atari/machdep.c1470
-rw-r--r--sys/arch/atari/atari/mem.c180
-rw-r--r--sys/arch/atari/atari/misc.c217
-rw-r--r--sys/arch/atari/atari/misc.h55
-rw-r--r--sys/arch/atari/atari/pmap.c2128
-rw-r--r--sys/arch/atari/atari/stalloc.c217
-rw-r--r--sys/arch/atari/atari/stalloc.h55
-rw-r--r--sys/arch/atari/atari/swapgeneric.c303
-rw-r--r--sys/arch/atari/atari/sys_machdep.c283
-rw-r--r--sys/arch/atari/atari/trap.c968
-rw-r--r--sys/arch/atari/atari/vectors.s201
-rw-r--r--sys/arch/atari/atari/vm_machdep.c318
-rw-r--r--sys/arch/atari/compile/.keep_me3
-rw-r--r--sys/arch/atari/conf/ATARITT90
-rw-r--r--sys/arch/atari/conf/GENERIC90
-rw-r--r--sys/arch/atari/conf/Makefile.atari161
-rw-r--r--sys/arch/atari/conf/files.atari102
-rw-r--r--sys/arch/atari/conf/files.atari.newconf102
-rw-r--r--sys/arch/atari/conf/std.atari22
-rw-r--r--sys/arch/atari/dev/clock.c697
-rw-r--r--sys/arch/atari/dev/clockioctl.h47
-rw-r--r--sys/arch/atari/dev/clockreg.h114
-rw-r--r--sys/arch/atari/dev/dma.c202
-rw-r--r--sys/arch/atari/dev/event.c173
-rw-r--r--sys/arch/atari/dev/event_var.h89
-rw-r--r--sys/arch/atari/dev/fd.c1061
-rw-r--r--sys/arch/atari/dev/fdreg.h93
-rw-r--r--sys/arch/atari/dev/font.h48
-rw-r--r--sys/arch/atari/dev/font_8x16.c562
-rw-r--r--sys/arch/atari/dev/font_8x8.c304
-rw-r--r--sys/arch/atari/dev/grf.c559
-rw-r--r--sys/arch/atari/dev/grfabs.c449
-rw-r--r--sys/arch/atari/dev/grfabs_reg.h140
-rw-r--r--sys/arch/atari/dev/grfioctl.h212
-rw-r--r--sys/arch/atari/dev/grfvar.h98
-rw-r--r--sys/arch/atari/dev/ite.c2327
-rw-r--r--sys/arch/atari/dev/ite_cc.c578
-rw-r--r--sys/arch/atari/dev/iteioctl.h82
-rw-r--r--sys/arch/atari/dev/itevar.h199
-rw-r--r--sys/arch/atari/dev/kbd.c353
-rw-r--r--sys/arch/atari/dev/kbdmap.c208
-rw-r--r--sys/arch/atari/dev/kbdmap.h144
-rw-r--r--sys/arch/atari/dev/kbdreg.h54
-rw-r--r--sys/arch/atari/dev/ncr5380.c1936
-rw-r--r--sys/arch/atari/dev/ncr5380reg.h182
-rw-r--r--sys/arch/atari/dev/ramd.c492
-rw-r--r--sys/arch/atari/dev/view.c407
-rw-r--r--sys/arch/atari/dev/viewioctl.h57
-rw-r--r--sys/arch/atari/dev/viewvar.h60
-rw-r--r--sys/arch/atari/dev/vuid_event.h87
-rw-r--r--sys/arch/atari/dev/zs.c1016
-rw-r--r--sys/arch/atari/dev/zsreg.h428
-rw-r--r--sys/arch/atari/dev/zsvar.h144
-rw-r--r--sys/arch/atari/include/acia.h86
-rw-r--r--sys/arch/atari/include/ansi.h8
-rw-r--r--sys/arch/atari/include/aout_machdep.h49
-rw-r--r--sys/arch/atari/include/asm.h8
-rw-r--r--sys/arch/atari/include/cdefs.h8
-rw-r--r--sys/arch/atari/include/cpu.h219
-rw-r--r--sys/arch/atari/include/cpufunc.h8
-rw-r--r--sys/arch/atari/include/db_machdep.h8
-rw-r--r--sys/arch/atari/include/disklabel.h45
-rw-r--r--sys/arch/atari/include/dma.h88
-rw-r--r--sys/arch/atari/include/endian.h8
-rw-r--r--sys/arch/atari/include/exec.h49
-rw-r--r--sys/arch/atari/include/float.h8
-rw-r--r--sys/arch/atari/include/frame.h8
-rw-r--r--sys/arch/atari/include/iomap.h63
-rw-r--r--sys/arch/atari/include/limits.h8
-rw-r--r--sys/arch/atari/include/mfp.h177
-rw-r--r--sys/arch/atari/include/mtpr.h61
-rw-r--r--sys/arch/atari/include/param.h220
-rw-r--r--sys/arch/atari/include/pcb.h77
-rw-r--r--sys/arch/atari/include/pmap.h105
-rw-r--r--sys/arch/atari/include/proc.h52
-rw-r--r--sys/arch/atari/include/profile.h8
-rw-r--r--sys/arch/atari/include/psl.h8
-rw-r--r--sys/arch/atari/include/pte.h143
-rw-r--r--sys/arch/atari/include/ptrace.h8
-rw-r--r--sys/arch/atari/include/reg.h8
-rw-r--r--sys/arch/atari/include/scu.h106
-rw-r--r--sys/arch/atari/include/setjmp.h3
-rw-r--r--sys/arch/atari/include/signal.h8
-rw-r--r--sys/arch/atari/include/stdarg.h4
-rw-r--r--sys/arch/atari/include/tospart.h59
-rw-r--r--sys/arch/atari/include/trap.h8
-rw-r--r--sys/arch/atari/include/types.h8
-rw-r--r--sys/arch/atari/include/varargs.h4
-rw-r--r--sys/arch/atari/include/video.h162
-rw-r--r--sys/arch/atari/include/vmparam.h168
-rw-r--r--sys/arch/atari/stand/binpatch/Makefile9
-rw-r--r--sys/arch/atari/stand/binpatch/binpatch.896
-rw-r--r--sys/arch/atari/stand/binpatch/binpatch.c241
-rw-r--r--sys/arch/atari/stand/chg_pid/chg_pid.c240
-rw-r--r--sys/arch/atari/stand/loadbsd/loadbsd.c383
-rw-r--r--sys/arch/atari/stand/loadbsd/loader.h75
-rw-r--r--sys/arch/atari/stand/tostools/chg_pid/chg_pid.c240
-rw-r--r--sys/arch/atari/stand/tostools/loadbsd/loadbsd.c383
-rw-r--r--sys/arch/atari/stand/tostools/loadbsd/loader.h75
110 files changed, 29204 insertions, 0 deletions
diff --git a/sys/arch/atari/Makefile b/sys/arch/atari/Makefile
new file mode 100644
index 00000000000..d8c45becb98
--- /dev/null
+++ b/sys/arch/atari/Makefile
@@ -0,0 +1,45 @@
+# $NetBSD: Makefile,v 1.1.1.1 1995/03/26 07:12:03 leo Exp $
+#
+# from: @(#)Makefile 7.3 (Berkeley) 6/9/91
+#
+S=${BSDSRCDIR}/sys
+COMM= $S/vm/*.[ch] $S/ufs/*.[ch] $S/sys/*.h $S/compat/sunos/*.[ch] \
+ $S/nfs/*.[ch] $S/netns/*.[ch] $S/netiso/*.[ch] \
+ $S/netiso/xebec/*.[ch] $S/netinet/*.[ch] $S/netccitt/*.[ch] \
+ $S/net/*.[ch] $S/miscfs/*/*.[ch] $S/kern/*.[ch] $S/dev/*.[ch] \
+ $S/scsi/*.[ch] $S/lib/libkern/m68k/*.[ch] $S/lib/libkern/*.[ch]
+
+# Makefile for atari tags file
+
+all:
+ @echo "make tags or links only"
+
+TATARI= $S/arch/atari/tags
+SATARI= $S/arch/m68k/m68k/*.c $S/arch/m68k/include/*.h \
+ $S/arch/atari/atari/*.[ch] $S/arch/atari/include/*.h \
+ $S/arch/atari/dev/*.[ch]
+AATARI= $S/arch/m68k/m68k/*.s $S/arch/atari/atari/*.s
+
+# Directories in which to place atari tags links
+DATARI= atari dev include
+
+TAGS:
+ -etags -dt ${COMM} ${SATARI} ${AATARI}
+ egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AATARI} | \
+ sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+ >> ${TATARI}/tags
+
+tags:
+ -ctags -dtf ${TATARI} ${COMM} ${SATARI}
+ egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AATARI} | \
+ sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
+ >> ${TATARI}
+ sort -o ${TATARI} ${TATARI}
+
+links:
+ -for i in ${DATARI}; do \
+ rm -f $$i/tags; rm -f $$i/TAGS ; \
+ ln -s ../tags $$i/tags; ln -s ../TAGS $$i/TAGS; done
+
+.include <bsd.prog.mk>
+
diff --git a/sys/arch/atari/atari/Locore.c b/sys/arch/atari/atari/Locore.c
new file mode 100644
index 00000000000..22d76494907
--- /dev/null
+++ b/sys/arch/atari/atari/Locore.c
@@ -0,0 +1,350 @@
+/* $NetBSD: Locore.c,v 1.1.1.1 1995/03/26 07:12:17 leo Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 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.
+ *
+ * @(#)Locore.c 7.4 (Berkeley) 5/7/91
+ */
+
+#include <machine/pte.h>
+#include <machine/cpu.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/user.h>
+#include <sys/vm.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/msgbuf.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/domain.h>
+#include <sys/map.h>
+#include <sys/dkbad.h>
+
+/*
+ * Pseudo file for lint to show what is used/defined in locore.s.
+ */
+
+int machineid;
+int mmutype;
+int ectype;
+struct user u;
+int icode[8];
+int szicode = sizeof (icode);
+u_int lowram;
+u_char ssir;
+int Usrptsize;
+
+/*
+ * Variables declared for savecore, or
+ * implicitly, such as by config or the loader.
+ */
+char version[] = "4.3 BSD UNIX ....";
+int etext;
+
+doadump() { dumpsys(); doboot(); }
+
+lowinit()
+{
+#if !defined(GPROF)
+ caddr_t cp;
+#endif
+ struct frame frame;
+ extern int dumpmag;
+ extern int rthashsize;
+ extern int arptab_size;
+ extern int dk_ndrive;
+ extern struct domain unixdomain;
+#ifdef INET
+ extern struct domain inetdomain;
+#endif
+#include "imp.h"
+#if NIMP > 0
+ extern struct domain impdomain;
+#endif
+#ifdef NS
+ extern struct domain nsdomain;
+#endif
+
+ /* cpp messes these up for lint so put them here */
+ unixdomain.dom_next = domains;
+ domains = &unixdomain;
+#ifdef INET
+ inetdomain.dom_next = domains;
+ domains = &inetdomain;
+#endif
+#if NIMP > 0
+ impdomain.dom_next = domains;
+ domains = &impdomain;
+#endif
+#ifdef NS
+ nsdomain.dom_next = domains;
+ domains = &nsdomain;
+#endif
+ dumpmag = 0; /* used only by savecore */
+ rthashsize = rthashsize; /* used by netstat, etc. */
+ arptab_size = arptab_size; /* used by arp command */
+ dk_ndrive = dk_ndrive; /* used by vmstat, iostat, etc. */
+
+ /*
+ * Pseudo-uses of globals.
+ */
+ lowinit();
+ machineid = machineid;
+ mmutype = mmutype;
+ ectype = ectype;
+ lowram = lowram;
+ ssir = ssir;
+ maxmem = physmem = freemem = 0;
+ u = u;
+ Usrptsize = Usrptsize;
+ main(0);
+
+ /*
+ * Routines called from interrupt vectors.
+ */
+ panic("Machine check");
+ printf("Write timeout");
+ hilint();
+ if (dmaintr())
+ return;
+ intrhand(0);
+ regdump((int *)0, 0);
+ hardclock((caddr_t)0, 0);
+ nmihand(frame);
+ softclock((caddr_t)0, 0);
+ trap(0, (unsigned)0, (unsigned)0, frame);
+ syscall(0, frame);
+ straytrap(0);
+
+ /*
+ * Miscellaneous routines called from configurable
+ * drivers.
+ */
+ disksort((struct buf *)0, (struct buf *)0);
+ if (vmemall((struct pte *)0, 0, (struct proc *)0, 0))
+ return; /* use value */
+ boothowto = 0;
+/* dumpflag = 0; dumpflag = dumpflag; */
+#if !defined(GPROF)
+ cp = (caddr_t)&etext;
+ cp = cp;
+#endif
+}
+
+int cold = 1;
+
+struct pte Sysmap[SYSPTSIZE];
+struct pte Usrptmap[USRPTSIZE];
+int Usrptsize;
+struct pte usrpt[USRPTSIZE*NPTEPG];
+struct pte Forkmap[UPAGES];
+struct user forkutl;
+struct pte Xswapmap[UPAGES];
+struct user xswaputl;
+struct pte Xswap2map[UPAGES];
+struct user xswap2utl;
+struct pte Swapmap[UPAGES];
+struct user swaputl;
+struct pte Pushmap[UPAGES];
+struct user pushutl;
+struct pte Vfmap[UPAGES];
+struct user vfutl;
+struct pte CMAP1;
+char CADDR1[NBPG];
+struct pte CMAP2;
+char CADDR2[NBPG];
+struct pte vmpte[1];
+char vmmap[NBPG];
+struct pte Mbmap[NMBCLUSTERS/CLSIZE];
+char mbutl[NMBCLUSTERS][MCLBYTES];
+struct pte msgbufmap[CLSIZE];
+struct msgbuf msgbuf;
+struct pte kmempt[200], ekmempt[1];
+struct pte Intiomap[IIOMAPSIZE], Extiomap[EIOMAPSIZE];
+char intiobase[IIOMAPSIZE*NBPG], extiobase[EIOMAPSIZE*NBPG];
+struct pte Usriomap[USRIOSIZE];
+char usrio[USRIOSIZE*NBPG];
+struct ste Sysseg[NPTEPG];
+
+/*ARGSUSED*/
+ovbcopy(from, to, len) caddr_t from, to; unsigned len; { }
+copyinstr(udaddr, kaddr, maxlength, lencopied)
+ caddr_t udaddr, kaddr; u_int maxlength, *lencopied;
+{ *kaddr = *udaddr; *lencopied = maxlength; return (0); }
+copyoutstr(kaddr, udaddr, maxlength, lencopied)
+ caddr_t kaddr, udaddr; u_int maxlength, *lencopied;
+{ *udaddr = *kaddr; *lencopied = maxlength; return (0); }
+copystr(kfaddr, kdaddr, maxlength, lencopied)
+ caddr_t kfaddr, kdaddr; u_int maxlength, *lencopied;
+{ *kdaddr = *kfaddr; *lencopied = maxlength; return (0); }
+
+/*ARGSUSED*/
+copyin(udaddr, kaddr, n) caddr_t udaddr, kaddr; u_int n; { return (0); }
+/*ARGSUSED*/
+copyout(kaddr, udaddr, n) caddr_t kaddr, udaddr; u_int n; { return (0); }
+
+/*ARGSUSED*/
+longjmp(lp) label_t *lp; { /*NOTREACHED*/ }
+
+/*ARGSUSED*/
+savectx(pcbp, ar) struct pcb *pcbp; { return (0); }
+
+/*ARGSUSED*/
+setrunqueue(p) struct proc *p; { }
+
+/*ARGSUSED*/
+remrq(p) struct proc *p; { }
+
+swtch() { if (whichqs) whichqs = 0; }
+
+/*ARGSUSED*/
+fubyte(base) caddr_t base; { return (0); }
+#ifdef notdef
+/*ARGSUSED*/
+fuibyte(base) caddr_t base; { return (0); }
+#endif
+/*ARGSUSED*/
+subyte(base, i) caddr_t base; { return (0); }
+/*ARGSUSED*/
+suibyte(base, i) caddr_t base; { return (0); }
+/*ARGSUSED*/
+fuword(base) caddr_t base; { return (0); }
+/*ARGSUSED*/
+fuiword(base) caddr_t base; { return (0); }
+/*ARGSUSED*/
+suword(base, i) caddr_t base; { return (0); }
+/*ARGSUSED*/
+suiword(base, i) caddr_t base; { return (0); }
+
+/*ARGSUSED*/
+copyseg(udaddr, pf)
+ caddr_t udaddr; unsigned pf;
+{ CMAP1 = CMAP1; CADDR1[0] = CADDR1[0]; }
+
+/*ARGSUSED*/
+clearseg(pf) unsigned pf; { CMAP2 = CMAP2; CADDR2[0] = CADDR2[0]; }
+
+TBIA() { }
+/*ARGSUSED*/
+TBIS(addr) caddr_t addr; { }
+TBIAS() { }
+TBIAU() { }
+ICIA() { }
+DCIA() { }
+DCIS() { }
+DCIU() { }
+PCIA() { }
+ecacheon() { }
+ecacheoff() { }
+
+getsfc() { return (0); }
+getdfc() { return (0); }
+
+/*ARGSUSED*/
+loadustp(ustp) int ustp; { }
+/*ARGSUSED*/
+flushustp(ustp) int ustp; { }
+
+/*ARGSUSED*/
+ploadw(addr) caddr_t addr; { }
+
+/*ARGSUSED*/
+addupc(pc, prof, counts) int pc; struct uprof *prof; int counts; { }
+
+spl0() { }
+splsoftclock() { return (0); }
+splnet() { return (0); }
+spl1() { return (0); }
+spl2() { return (0); }
+spl3() { return (0); }
+spl4() { return (0); }
+splimp() { return (0); }
+splbio() { return (0); }
+spltty() { return (0); }
+spl5() { return (0); }
+splclock() { return (0); }
+spl6() { return (0); }
+splhigh() { return (0); }
+spl7() { return (0); }
+
+/*ARGSUSED*/
+splx(s) int s; { }
+
+/*ARGSUSED*/
+_insque(p, q) caddr_t p, q; { }
+/*ARGSUSED*/
+_remque(p) caddr_t p; { }
+
+/*ARGSUSED*/
+bcopy(from, to, len) caddr_t from, to; unsigned len; { }
+/*ARGSUSED*/
+bzero(base, count) caddr_t base; unsigned count; { }
+/*ARGSUSED*/
+blkclr(base, count) caddr_t base; unsigned count; { }
+/*ARGSUSED*/
+bcmp(str1, str2, count) caddr_t str1, str2; unsigned count; { return (0); }
+
+/*ARGSUSED*/
+strlen(str) caddr_t str; { return (0); }
+
+/*ARGSUSED*/
+setjmp(lp) label_t *lp; { return (0); }
+
+/*ARGSUSED*/
+qsetjmp(lp) label_t *lp; { return (0); }
+
+/*ARGSUSED*/
+scanc(size, cp, table, mask)
+ unsigned size; u_char *cp, table[]; int mask;
+{ return (0); }
+
+/*ARGSUSED*/
+skpc(mask, size, cp) int mask; int size; char *cp; { return (0); }
+
+/*ARGSUSED*/
+locc(mask, size, cp) int mask; char *cp; unsigned size; { return (0); }
+
+/*ARGSUSED*/
+ffs(v) long v; { return (0); }
+
+#ifdef FPCOPROC
+/*ARGSUSED*/
+m68881_save(fpframep) struct fpframe *fpframep; { }
+/*ARGSUSED*/
+m68881_restore(fpframep) struct fpframe *fpframep; { }
+#endif
+
+doboot() { /*NOTREACHED*/ }
diff --git a/sys/arch/atari/atari/atari_init.c b/sys/arch/atari/atari/atari_init.c
new file mode 100644
index 00000000000..22c481845c7
--- /dev/null
+++ b/sys/arch/atari/atari/atari_init.c
@@ -0,0 +1,603 @@
+/* $NetBSD: atari_init.c,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1994 Michael L. Hitch
+ * Copyright (c) 1993 Markus Wild
+ * 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 Markus Wild.
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <vm/vm.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/msgbuf.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/domain.h>
+#include <sys/dkbad.h>
+#include <sys/reboot.h>
+#include <sys/exec.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/pte.h>
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+#include <machine/scu.h>
+#include <atari/atari/misc.h>
+
+extern u_int lowram;
+extern u_int Sysptmap, Sysptsize, Sysseg, Umap, proc0paddr;
+u_int *Sysmap;
+int machineid, mmutype, cpu040, astpending, cpuspeed;
+char *vmmap;
+pv_entry_t pv_table;
+
+/*
+ * Need-to-know for kernel reload code.
+ */
+static u_long boot_ttphystart, boot_ttphysize, boot_stphysize;
+
+extern char *esym;
+
+/*
+ * The following vars become valid just before pmap_bootstrap is called.
+ * They give info about free memory with the kernel and the tables allocated
+ * in 'start_c' excluded.
+ */
+extern vm_offset_t st_ramstart; /* First available ST RAM address */
+extern vm_offset_t st_ramend; /* First ST RAM address not available */
+extern vm_offset_t tt_ramstart; /* First available TT RAM address */
+extern vm_offset_t tt_ramend; /* First TT RAM address not available */
+
+
+/*
+ * This is the virtual address of physical page 0. Used by 'do_boot()'.
+ */
+vm_offset_t page_zero;
+
+/*
+ * Crude support for allocation in ST-ram. Currently only used to allocate
+ * video ram.
+ * The physical address is also returned because the video init needs it to
+ * setup the controller at the time the vm-system is not yet operational so
+ * 'kvtop()' cannot be used.
+ */
+#define ST_POOL_SIZE (40*NBPG) /* XXX: enough? */
+
+u_long st_pool_size = ST_POOL_SIZE; /* Patchable */
+u_long st_pool_virt, st_pool_phys;
+
+#if 0
+void
+*stmem_steal(amount, phys)
+long amount;
+vm_offset_t *phys;
+{
+ /*
+ * steal from top of st-memory, so we don't collide with
+ * the kernel loaded into st-memory in the not-yet-mapped state.
+ */
+ vm_offset_t p = st_pool_virt;
+
+ if(amount & 1)
+ amount++;
+ if(amount > st_pool_size)
+ panic("not enough ST memory");
+ *phys = st_pool_phys;
+
+ st_pool_virt += amount;
+ st_pool_phys += amount;
+ st_pool_size -= amount;
+
+ return((void *)p);
+}
+#endif
+
+/*
+ * this is the C-level entry function, it's called from locore.s.
+ * Preconditions:
+ * Interrupts are disabled
+ * PA == VA, we don't have to relocate addresses before enabling
+ * the MMU
+ * Exec is no longer available (because we're loaded all over
+ * low memory, no ExecBase is available anymore)
+ *
+ * It's purpose is:
+ * Do the things that are done in locore.s in the hp300 version,
+ * this includes allocation of kernel maps and enabling the MMU.
+ *
+ * Some of the code in here is `stolen' from Amiga MACH, and was
+ * written by Bryan Ford and Niklas Hallqvist.
+ *
+ * Very crude 68040 support by Michael L. Hitch.
+ */
+
+void
+start_c(id, ttphystart, ttphysize, stphysize, esym_addr)
+int id; /* Machine id */
+u_int ttphystart, ttphysize; /* Start address and size of TT-ram */
+u_int stphysize; /* Size of ST-ram */
+char *esym_addr; /* Address of kernel '_esym' symbol */
+{
+ extern char end[];
+ extern void etext();
+ extern u_long protorp[2];
+ u_int pstart; /* Next available physical address*/
+ u_int vstart; /* Next available virtual address */
+ u_int avail;
+ u_int pt, ptsize;
+ u_int tc, i;
+ u_int *sg, *pg, *pg2;
+ u_int sg_proto, pg_proto;
+ u_int umap;
+ u_int p0_pt, p0_u_area, end_loaded;
+ u_int ptextra;
+ u_long kbase;
+
+ boot_ttphystart = ttphystart;
+ boot_ttphysize = ttphysize;
+ boot_stphysize = stphysize;
+
+ /*
+ * The following is a hack. We do not know how much ST memory we
+ * really need until after configuration has finished. At this
+ * time I have no idea how to grab ST memory at that time.
+ */
+ st_pool_phys = stphysize - st_pool_size;
+ stphysize = st_pool_phys;
+
+ machineid = id;
+ esym = esym_addr;
+
+ /*
+ * the kernel ends at end() or esym.
+ */
+ if(esym == NULL)
+ end_loaded = (u_int)end;
+ else end_loaded = (u_int)esym;
+
+
+ /*
+ * If we have enough fast-memory to put the kernel in, do it!
+ */
+ if(ttphysize >= end_loaded)
+ kbase = ttphystart;
+ else kbase = 0;
+
+ /*
+ * update these as soon as possible!
+ */
+ PAGE_SIZE = NBPG;
+ PAGE_MASK = NBPG-1;
+ PAGE_SHIFT = PG_SHIFT;
+
+ /*
+ * We run the kernel from ST memory at the moment.
+ * The kernel segment table is put just behind the loaded image.
+ * pstart: start of usable ST memory
+ * avail : size of ST memory available.
+ */
+ pstart = (u_int)end_loaded;
+ pstart = atari_round_page(pstart);
+ avail = stphysize - pstart;
+
+ /*
+ * allocate the kernel segment table
+ */
+ Sysseg = pstart;
+ pstart += NBPG;
+ avail -= NBPG;
+
+ /*
+ * We only allocate 1 extra pagetable. it currently only contains
+ * entries for Sysmap.
+ */
+ ptextra = 0;
+
+ /*
+ * allocate initial page table pages
+ */
+ pt = pstart;
+ ptsize = (Sysptsize + howmany(ptextra, NPTEPG)) << PGSHIFT;
+ pstart += ptsize;
+ avail -= ptsize;
+
+ /*
+ * allocate kernel page table map
+ */
+ Sysptmap = pstart;
+ pstart += NBPG;
+ avail -= NBPG;
+
+ /*
+ * Set Sysmap; mapped after page table pages. Because I too (LWP)
+ * didn't understand the reason for this, I borrowed the following
+ * (sligthly modified) comment from mac68k/locore.s:
+ * LAK: There seems to be some confusion here about the next line,
+ * so I'll explain. The kernel needs some way of dynamically modifying
+ * the page tables for its own virtual memory. What it does is that it
+ * has a page table map. This page table map is mapped right after the
+ * kernel itself (in our implementation; in HP's it was after the I/O
+ * space). Therefore, the first three (or so) entries in the segment
+ * table point to the first three pages of the page tables (which
+ * point to the kernel) and the next entry in the segment table points
+ * to the page table map (this is done later). Therefore, the value
+ * of the pointer "Sysmap" will be something like 16M*3 = 48M. When
+ * the kernel addresses this pointer (e.g., Sysmap[0]), it will get
+ * the first longword of the first page map (== pt[0]). Since the
+ * page map mirrors the segment table, addressing any index of Sysmap
+ * will give you a PTE of the page maps which map the kernel.
+ */
+ Sysmap = (u_int *)(ptsize << (SEGSHIFT - PGSHIFT));
+
+ /*
+ * Initialize segment table and page table map.
+ */
+ sg_proto = (pt + kbase) | SG_RW | SG_V;
+ pg_proto = (pt + kbase) | PG_RW | PG_CI | PG_V;
+ /*
+ * map so many segs
+ */
+ sg = (u_int *)Sysseg;
+ pg = (u_int *)Sysptmap;
+ while(sg_proto < (pstart + kbase)) {
+ *sg++ = sg_proto;
+ *pg++ = pg_proto;
+ sg_proto += NBPG;
+ pg_proto += NBPG;
+ }
+ /*
+ * invalidate the remainder of the tables
+ * (except last entry)
+ */
+ do {
+ *sg++ = SG_NV;
+ *pg++ = PG_NV;
+ } while(sg < (u_int *)(Sysseg + ATARI_STSIZE - 4));
+
+ /*
+ * the end of the last segment (0xFF000000)
+ * of KVA space is used to map the u-area of
+ * the current process (u + kernel stack).
+ */
+ sg_proto = (pstart + kbase) | SG_RW | SG_V; /* use next availabe PA */
+ pg_proto = (pstart + kbase) | PG_RW | PG_CI | PG_V;
+ umap = pstart; /* remember for later map entry */
+
+ /*
+ * enter the page into the segment table
+ * (and page table map)
+ */
+ *sg++ = sg_proto;
+ *pg++ = pg_proto;
+
+ /*
+ * invalidate all pte's (will validate u-area afterwards)
+ */
+ for(pg = (u_int *) pstart; pg < (u_int *) (pstart + NBPG); )
+ *pg++ = PG_NV;
+
+ /*
+ * account for the allocated page
+ */
+ pstart += NBPG;
+ avail -= NBPG;
+
+ /*
+ * record KVA at which to access current u-area PTE(s)
+ */
+ Umap = (u_int)Sysmap + ATARI_MAX_PTSIZE - UPAGES * 4;
+
+ /*
+ * initialize kernel page table page(s).
+ * Assume load at VA 0.
+ * - Text pages are RO
+ */
+ pg_proto = (0 + kbase) | PG_RO | PG_V;
+ pg = (u_int *) pt;
+ for(i = 0; i < (u_int)etext; i += NBPG, pg_proto += NBPG)
+ *pg++ = pg_proto;
+
+ /*
+ * data, bss and dynamic tables are read/write
+ */
+ pg_proto = (pg_proto & PG_FRAME) | PG_RW | PG_V;
+
+ /*
+ * go till end of data allocated so far
+ * plus proc0 PT/u-area (to be allocated)
+ */
+ for(; i < pstart + (UPAGES + 1)*NBPG; i += NBPG, pg_proto += NBPG)
+ *pg++ = pg_proto;
+
+ /*
+ * invalidate remainder of kernel PT
+ */
+ while(pg < (u_int *)(pt + ptsize))
+ *pg++ = PG_NV;
+
+ /*
+ * Go back and validate internal IO PTEs. They MUST be Cache inhibited!
+ */
+ pg = (u_int *) pt + (AD_IO / NBPG);
+ pg_proto = AD_IO | PG_RW | PG_CI | PG_V;
+ while(pg_proto < AD_EIO) {
+ *pg++ = pg_proto;
+ pg_proto += NBPG;
+ }
+
+ /*
+ * Setup page table for process 0.
+ * We set up page table access for the kernel via Usrptmap (usrpt)
+ * [no longer used?] and access to the u-area itself via Umap (u).
+ * First available page (pstart) is used for proc0 page table.
+ * Next UPAGES page(s) following are for u-area.
+ */
+
+ p0_pt = pstart;
+ pstart += NBPG;
+ avail -= NBPG;
+
+ p0_u_area = pstart; /* base of u-area and end of PT */
+
+ /*
+ * invalidate entire page table
+ */
+ for(pg = (u_int *)p0_pt; pg < (u_int *) p0_u_area; )
+ *pg++ = PG_NV;
+
+ /*
+ * now go back and validate u-area PTE(s) in PT and in Umap
+ */
+ pg -= UPAGES;
+ pg2 = (u_int *) (umap + 4*(NPTEPG - UPAGES));
+ pg_proto = (p0_u_area + kbase) | PG_RW | PG_V;
+ for(i = 0; i < UPAGES; i++, pg_proto += NBPG) {
+ *pg++ = pg_proto;
+ *pg2++ = pg_proto;
+ }
+ bzero((u_char *)p0_u_area, UPAGES * NBPG);
+
+ /*
+ * save KVA of proc0 u-area
+ */
+ proc0paddr = pstart;
+ pstart += UPAGES * NBPG;
+ avail -= UPAGES * NBPG;
+
+ /*
+ * At this point, virtual and physical allocation starts to divert.
+ */
+ vstart = pstart;
+
+ /*
+ * Map the allocated space in ST-ram now. In the contig-case, there
+ * is no need to make a distinction between virtual and physical
+ * adresses. But I make it anyway to be prepared.
+ * Physcal space is already reserved!
+ */
+ st_pool_virt = vstart;
+ pg = (u_int *) pt + (vstart / NBPG);
+ pg_proto = st_pool_phys | PG_RW | PG_CI | PG_V;
+ vstart += st_pool_size;
+ while(pg_proto < (st_pool_phys + st_pool_size)) {
+ *pg++ = pg_proto;
+ pg_proto += NBPG;
+ }
+
+ /*
+ * Map physical page zero (First ST-ram page)
+ */
+ page_zero = vstart;
+ pg = (u_int *) pt + (vstart / NBPG);
+ *pg = PG_RW | PG_CI | PG_V;
+ vstart += NBPG;
+
+ lowram = 0 >> PGSHIFT; /* XXX */
+
+ /*
+ * Initialize memory sizes
+ */
+ st_ramstart = 0;
+ st_ramend = stphysize;
+ tt_ramstart = ttphystart;
+ tt_ramend = ttphystart + ttphysize;
+ if(kbase) {
+ /*
+ * First page of ST-ram is unusable.
+ */
+ st_ramstart = NBPG;
+ tt_ramstart += pstart;
+ }
+ else {
+ /*
+ * Because the first 8 addresses of ST-memory are mapped to
+ * ROM, we remap them. This makes the debugger stack-trace
+ * work.
+ */
+ extern u_long first_8_bytes[];
+ u_long *sp, *dp;
+
+ /*
+ * Copy page zero and set first 8 bytes.
+ */
+ sp = (u_long *)0;
+ dp = (u_long *)pstart;
+ while(dp < (u_long *)(pstart+NBPG))
+ *dp++ = *sp++;
+ dp = (u_long *)pstart;
+ *dp++ = first_8_bytes[0];
+ *dp = first_8_bytes[1];
+
+ /*
+ * Enter into the page-table
+ */
+ pg = (u_int *)pt;
+ *pg = pstart | PG_RO | PG_V;
+
+
+ /*
+ * Reserve space for page 0
+ */
+ pstart += NBPG;
+
+ st_ramstart += pstart;
+ }
+
+ physmem = ((st_ramend-st_ramstart)+(tt_ramend-tt_ramstart)) >> PGSHIFT;
+
+ /*
+ * get the pmap module in sync with reality.
+ */
+ pmap_bootstrap(vstart);
+
+
+ /*
+ * Prepare to enable the MMU.
+ * Setup and load SRP nolimit, share global, 4 byte PTE's
+ */
+ protorp[0] = 0x80000202;
+ protorp[1] = Sysseg + kbase; /* + segtable address */
+
+ /*
+ * copy over the kernel (and all now initialized variables)
+ * to fastram. DONT use bcopy(), this beast is much larger
+ * than 128k !
+ */
+ if(kbase) {
+ register u_long *lp, *le, *fp;
+ extern u_long first_8_bytes[];
+
+ lp = (u_long *)0;
+ le = (u_long *)pstart;
+ fp = (u_long *)kbase;
+ while(lp < le)
+ *fp++ = *lp++;
+
+ /*
+ * Fill in reset stuff
+ */
+ fp = (u_long *)kbase;
+ *fp++ = first_8_bytes[0];
+ *fp = first_8_bytes[1];
+ }
+
+ asm volatile ("pmove %0@,srp" : : "a" (&protorp[0]));
+ /*
+ * setup and load TC register.
+ * enable_cpr, enable_srp, pagesize=8k,
+ * A = 8 bits, B = 11 bits
+ */
+ tc = 0x82d08b00;
+ asm volatile ("pmove %0@,tc" : : "a" (&tc));
+
+ /* Is this to fool the optimizer?? */
+ i = *(int *)proc0paddr;
+ *(volatile int *)proc0paddr = i;
+
+ /*
+ * Initialize both MFP chips to generate auto-vectored interrupts
+ * with EOI. The active-edge registers are set up. The interrupt
+ * enable registers are set to disable all interrupts.
+ */
+ MFP->mf_iera = MFP->mf_ierb = 0;
+ MFP->mf_imra = MFP->mf_imrb = 0;
+ MFP->mf_aer = 0;
+ MFP->mf_vr = 0x40;
+ MFP2->mf_iera = MFP2->mf_ierb = 0;
+ MFP2->mf_imra = MFP2->mf_imrb = 0;
+ MFP2->mf_aer = 0x80;
+ MFP2->mf_vr = 0x50;
+
+ /*
+ * Initialize the SCU, to enable interrupts on the SCC (ipl5),
+ * MFP (ipl6) and softints (ipl1).
+ */
+ SCU->sys_mask = SCU_MFP | SCU_SCC | SCU_SYS_SOFT;
+
+ /*
+ * Initialize stmem allocator
+ */
+ init_stmem();
+}
+
+#ifdef DEBUG
+void
+dump_segtable(stp)
+ u_int *stp;
+{
+ u_int *s, *es;
+ int shift, i;
+
+ s = stp;
+ {
+ es = s + (ATARI_STSIZE >> 2);
+ shift = SG_ISHIFT;
+ }
+
+ /*
+ * XXX need changes for 68040
+ */
+ for (i = 0; s < es; s++, i++)
+ if (*s & SG_V)
+ printf("$%08lx: $%08lx\t", i << shift, *s & SG_FRAME);
+ printf("\n");
+}
+
+void
+dump_pagetable(ptp, i, n)
+ u_int *ptp, i, n;
+{
+ u_int *p, *ep;
+
+ p = ptp + i;
+ ep = p + n;
+ for (; p < ep; p++, i++)
+ if (*p & PG_V)
+ printf("$%08lx -> $%08lx\t", i, *p & PG_FRAME);
+ printf("\n");
+}
+
+u_int
+vmtophys(ste, vm)
+ u_int *ste, vm;
+{
+ ste = (u_int *) (*(ste + (vm >> SEGSHIFT)) & SG_FRAME);
+ ste += (vm & SG_PMASK) >> PGSHIFT;
+ return((*ste & -NBPG) | (vm & (NBPG - 1)));
+}
+
+#endif
diff --git a/sys/arch/atari/atari/autoconf.c b/sys/arch/atari/atari/autoconf.c
new file mode 100644
index 00000000000..da8ccc3ef4b
--- /dev/null
+++ b/sys/arch/atari/atari/autoconf.c
@@ -0,0 +1,275 @@
+/* $NetBSD: autoconf.c,v 1.1.1.1 1995/03/26 07:12:18 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1994 Christian E. Hopps
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce 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 Christian E. Hopps.
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <machine/disklabel.h>
+#include <machine/cpu.h>
+
+void configure __P((void));
+static void setroot __P((void));
+void swapconf __P((void));
+void mbattach __P((struct device *, struct device *, void *));
+int mbprint __P((void *, char *));
+int mbmatch __P((struct device *, struct cfdata *, void *));
+
+extern int cold; /* 1 if still booting (locore.s) */
+int atari_realconfig;
+#include <sys/kernel.h>
+
+/*
+ * called at boot time, configure all devices on system
+ */
+void
+configure()
+{
+ extern int atari_realconfig;
+
+ atari_realconfig = 1;
+
+ if (config_rootfound("mainbus", "mainbus") == 0)
+ panic("no mainbus found");
+
+#ifdef GENERIC
+ if((boothowto & RB_ASKNAME) == 0)
+ setroot();
+ setconf();
+#else
+ setroot();
+#endif
+ swapconf();
+ cold = 0;
+}
+
+/*ARGSUSED*/
+int
+simple_devprint(auxp, pnp)
+ void *auxp;
+ char *pnp;
+{
+ return(QUIET);
+}
+
+/*
+ * use config_search to find appropriate device, then call that device
+ * directly with NULL device variable storage. A device can then
+ * always tell the difference between the real and console init
+ * by checking for NULL.
+ */
+int
+atari_config_found(pcfp, pdp, auxp, pfn)
+ struct cfdata *pcfp;
+ struct device *pdp;
+ void *auxp;
+ cfprint_t pfn;
+{
+ struct device temp;
+ struct cfdata *cf;
+ extern int atari_realconfig;
+
+ if (atari_realconfig)
+ return(config_found(pdp, auxp, pfn));
+
+ if (pdp == NULL)
+ pdp = &temp;
+
+ pdp->dv_cfdata = pcfp;
+ if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) {
+ cf->cf_driver->cd_attach(pdp, NULL, auxp);
+ pdp->dv_cfdata = NULL;
+ return(1);
+ }
+ pdp->dv_cfdata = NULL;
+ return(0);
+}
+
+/*
+ * this function needs to get enough configured to do a console
+ * basically this means start attaching the grfxx's that support
+ * the console. Kinda hacky but it works.
+ */
+int
+config_console()
+{
+ struct cfdata *cf;
+
+ /*
+ * we need mainbus' cfdata.
+ */
+ cf = config_rootsearch(NULL, "mainbus", "mainbus");
+ if(cf == NULL)
+ panic("no mainbus");
+ atari_config_found(cf, NULL, "grfbus", NULL);
+}
+
+void
+swapconf()
+{
+ struct swdevt *swp;
+ u_int maj;
+ int nb;
+
+ for(swp = swdevt; swp->sw_dev > 0; swp++) {
+ maj = major(swp->sw_dev);
+
+ if(maj > nblkdev)
+ break;
+
+ if(bdevsw[maj].d_psize) {
+ nb = bdevsw[maj].d_psize(swp->sw_dev);
+ if(nb > 0 &&
+ (swp->sw_nblks == 0 || swp->sw_nblks > nb))
+ swp->sw_nblks = nb;
+ else swp->sw_nblks = 0;
+ }
+ swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
+ }
+ if(dumplo == 0 && bdevsw[major(dumpdev)].d_psize)
+ dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) -
+ ctob(physmem)/DEV_BSIZE;
+ if(dumplo < 0)
+ dumplo = 0;
+
+}
+
+#define DOSWAP /* change swdevt and dumpdev */
+dev_t bootdev = 0;
+
+static char devname[][2] = {
+ 0,0,
+ 0,0,
+ 'f','d', /* 2 = fd */
+ 0,0,
+ 's','d', /* 4 = sd -- SCSI system */
+};
+
+static void
+setroot()
+{
+ int majdev, mindev, unit, part, adaptor;
+ dev_t temp, orootdev;
+ struct swdevt *swp;
+
+ if(boothowto & RB_DFLTROOT
+ || (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
+ return;
+ majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
+ if(majdev > sizeof(devname) / sizeof(devname[0]))
+ return;
+ adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
+ part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
+ unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
+ orootdev = rootdev;
+ rootdev = MAKEDISKDEV(majdev, unit, part);
+ /*
+ * If the original rootdev is the same as the one
+ * just calculated, don't need to adjust the swap configuration.
+ */
+ if(rootdev == orootdev)
+ return;
+ printf("changing root device to %c%c%d%c\n",
+ devname[majdev][0], devname[majdev][1],
+ unit, part + 'a');
+#ifdef DOSWAP
+ mindev = DISKUNIT(rootdev);
+ for(swp = swdevt; swp->sw_dev; swp++) {
+ if(majdev == major(swp->sw_dev)
+ && mindev == DISKUNIT(swp->sw_dev)) {
+ temp = swdevt[0].sw_dev;
+ swdevt[0].sw_dev = swp->sw_dev;
+ swp->sw_dev = temp;
+ break;
+ }
+ }
+ if(swp->sw_dev == 0)
+ return;
+ /*
+ * If dumpdev was the same as the old primary swap
+ * device, move it to the new primary swap device.
+ */
+ if(temp == dumpdev)
+ dumpdev = swdevt[0].sw_dev;
+#endif
+}
+
+/*
+ * mainbus driver
+ */
+struct cfdriver mainbuscd = {
+ NULL, "mainbus", (cfmatch_t)mbmatch, mbattach,
+ DV_DULL, sizeof(struct device), NULL, 0
+};
+
+int
+mbmatch(pdp, cfp, auxp)
+ struct device *pdp;
+ struct cfdata *cfp;
+ void *auxp;
+{
+ if(cfp->cf_unit > 0)
+ return(0);
+ /*
+ * We are always here
+ */
+ return(1);
+}
+
+/*
+ * "find" all the things that should be there.
+ */
+void
+mbattach(pdp, dp, auxp)
+ struct device *pdp, *dp;
+ void *auxp;
+{
+ printf ("\n");
+ config_found(dp, "clock" , simple_devprint);
+ config_found(dp, "grfbus" , simple_devprint);
+ config_found(dp, "kbd" , simple_devprint);
+ config_found(dp, "fdc" , simple_devprint);
+ config_found(dp, "zs" , simple_devprint);
+ config_found(dp, "ncrscsi", simple_devprint);
+}
+
+int
+mbprint(auxp, pnp)
+ void *auxp;
+ char *pnp;
+{
+ if (pnp)
+ printf("%s at %s", (char *)auxp, pnp);
+ return(UNCONF);
+}
diff --git a/sys/arch/atari/atari/conf.c b/sys/arch/atari/atari/conf.c
new file mode 100644
index 00000000000..5904143effe
--- /dev/null
+++ b/sys/arch/atari/atari/conf.c
@@ -0,0 +1,701 @@
+/* $NetBSD: conf.c,v 1.1.1.1 1995/03/26 07:12:20 leo 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.
+ *
+ * @(#)conf.c 7.9 (Berkeley) 5/28/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+#include <sys/vnode.h>
+#include <dev/cons.h>
+
+#ifdef BANKEDDEVPAGER
+#include <sys/bankeddev.h>
+#endif
+
+int rawread __P((dev_t, struct uio *, int));
+int rawwrite __P((dev_t, struct uio *, int));
+void swstrategy __P((struct buf *));
+int ttselect __P((dev_t, int, struct proc *));
+
+#define dev_type_open(n) int n __P((dev_t, int, int, struct proc *))
+#define dev_type_close(n) int n __P((dev_t, int, int, struct proc *))
+#define dev_type_strategy(n) void n __P((struct buf *))
+#define dev_type_ioctl(n) \
+ int n __P((dev_t, u_long, caddr_t, int, struct proc *))
+
+/* bdevsw-specific types */
+#define dev_type_dump(n) int n ()
+#define dev_type_size(n) int n __P((dev_t))
+
+#define dev_decl(n,t) __CONCAT(dev_type_,t)(__CONCAT(n,t))
+#define dev_init(c,n,t) \
+ (c > 0 ? __CONCAT(n,t) : (__CONCAT(dev_type_,t)((*))) enxio)
+
+/* bdevsw-specific initializations */
+#define dev_size_init(c,n) (c > 0 ? __CONCAT(n,size) : 0)
+
+#define bdev_decl(n) \
+ dev_decl(n,open); dev_decl(n,close); dev_decl(n,strategy); \
+ dev_decl(n,ioctl); dev_decl(n,dump); dev_decl(n,size)
+
+
+#include "vnd.h"
+#include "sd.h"
+#include "cd.h"
+bdev_decl(vnd);
+bdev_decl(sd);
+bdev_decl(cd);
+#define bdev_disk_init(c,n) { \
+ dev_init(c,n,open), \
+ dev_init(c,n,close), \
+ dev_init(c,n,strategy), \
+ dev_init(c,n,ioctl), \
+ dev_init(c,n,dump), \
+ dev_size_init(c,n), \
+ 0 \
+}
+
+#include "st.h"
+bdev_decl(st);
+#define bdev_tape_init(c,n) { \
+ dev_init(c,n,open), \
+ dev_init(c,n,close), \
+ dev_init(c,n,strategy), \
+ dev_init(c,n,ioctl), \
+ dev_init(c,n,dump), \
+ 0, \
+ B_TAPE \
+}
+
+#include "ch.h"
+bdev_decl(ch); /* XXX not used yet */
+#define bdev_ch_init(c) { \
+ dev_init(c,ch,open), \
+ dev_init(c,ch,close), \
+ (dev_type_strategy((*))) xxx, \
+ dev_init(c,ch,ioctl), \
+ (dev_type_dump((*))) enxio, \
+ (dev_type_size((*))) xxx, \
+ 0 \
+}
+
+#include "fd.h"
+bdev_decl(fd);
+dev_decl(Fd,open);
+dev_decl(Fd,close);
+#define bdev_floppy_init(c) { \
+ dev_init(c,Fd,open), \
+ dev_init(c,Fd,close), \
+ dev_init(c,fd,strategy), \
+ dev_init(c,fd,ioctl), \
+ (dev_type_dump((*))) enxio, \
+ dev_size_init(c,fd), \
+ 0 \
+}
+
+#include "ramd.h"
+bdev_decl(rd);
+dev_decl(rd,open);
+#define bdev_ramd_init(c) { \
+ dev_init(c,rd,open), \
+ dev_init(c,rd,close), \
+ dev_init(c,rd,strategy), \
+ dev_init(c,rd,ioctl), \
+ (dev_type_dump((*))) enxio, \
+ dev_size_init(c,rd), \
+ 0 \
+}
+
+#define bdev_swap_init() { \
+ (dev_type_open((*))) enodev, \
+ (dev_type_close((*))) enodev, \
+ swstrategy, \
+ (dev_type_ioctl((*))) enodev, \
+ (dev_type_dump((*))) enodev, \
+ 0, \
+ 0 \
+}
+
+#define bdev_notdef() bdev_tape_init(0,no)
+bdev_decl(no); /* dummy declarations */
+
+#ifdef LKM
+int lkmenodev();
+#else
+#define lkmenodev enodev
+#endif
+
+#define LKM_BDEV() { \
+ (dev_type_open((*))) lkmenodev, (dev_type_close((*))) lkmenodev, \
+ (dev_type_strategy((*))) lkmenodev, (dev_type_ioctl((*))) lkmenodev, \
+ (dev_type_dump((*))) lkmenodev, 0, 0 }
+
+struct bdevsw bdevsw[] =
+{
+ bdev_disk_init(NVND,vnd), /* 0 : vnode disk (swap to files) */
+ bdev_ramd_init(NRAMD), /* 1 : ramdisk (for floppy boot */
+ bdev_floppy_init(NFD), /* 2 : floppy */
+ bdev_swap_init(), /* 3 : swap pseudo-device */
+ bdev_disk_init(NSD,sd), /* 4 : scsi disk */
+ bdev_tape_init(NST,st), /* 5 : exabyte tape */
+ bdev_disk_init(NCD,cd), /* 6 : scsi cd. */
+ LKM_BDEV(), /* 7 : Empty slot for LKM */
+ LKM_BDEV(), /* 8 : Empty slot for LKM */
+ LKM_BDEV(), /* 9 : Empty slot for LKM */
+ LKM_BDEV(), /* 10: Empty slot for LKM */
+ LKM_BDEV(), /* 11: Empty slot for LKM */
+ LKM_BDEV(), /* 12: Empty slot for LKM */
+};
+
+int nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
+
+/* cdevsw-specific types */
+#define dev_type_read(n) int n __P((dev_t, struct uio *, int))
+#define dev_type_write(n) int n __P((dev_t, struct uio *, int))
+#define dev_type_stop(n) int n __P((struct tty *, int))
+#define dev_type_reset(n) int n __P((int))
+#define dev_type_select(n) int n __P((dev_t, int, struct proc *))
+#define dev_type_map(n) int n __P(())
+
+#define cdev_decl(n) \
+ dev_decl(n,open); dev_decl(n,close); dev_decl(n,read); \
+ dev_decl(n,write); dev_decl(n,ioctl); dev_decl(n,stop); \
+ dev_decl(n,reset); dev_decl(n,select); dev_decl(n,map); \
+ dev_decl(n,strategy); extern struct tty *__CONCAT(n,_tty)[]
+
+#define dev_tty_init(c,n) (c > 0 ? __CONCAT(n,_tty) : 0)
+
+
+/* open, close, read, write, ioctl, stop, tty */
+#define cdev_tty_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_type_reset((*))) nullop, \
+ dev_tty_init(c,n), \
+ ttselect, \
+ (dev_type_map((*))) enodev, \
+ 0 \
+}
+
+cdev_decl(no); /* dummy declarations */
+#define cdev_notdef() { \
+ (dev_type_open((*))) enodev, \
+ (dev_type_close((*))) enodev, \
+ (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, \
+ (dev_type_ioctl((*))) enodev, \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ (dev_type_select((*))) seltrue, \
+ (dev_type_map((*))) enodev, \
+ 0 \
+}
+
+/* disks */
+cdev_decl(vnd);
+cdev_decl(sd);
+#define cdev_disk_init(c,n) { \
+ dev_init(c,n,open), \
+ dev_init(c,n,close), \
+ rawread, \
+ rawwrite, \
+ dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ (dev_type_select((*))) seltrue, \
+ (dev_type_map((*))) enodev, \
+ dev_init(c,n,strategy) \
+}
+
+/* scsi tape */
+cdev_decl(st);
+#define cdev_st_init(c) { \
+ dev_init(c,st,open), \
+ dev_init(c,st,close), \
+ (dev_type_read((*))) rawread, \
+ (dev_type_write((*))) rawwrite, \
+ dev_init(c,st,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ (dev_type_select((*))) seltrue, \
+ (dev_type_map((*))) enodev, \
+ dev_init(c,st,strategy) \
+}
+
+
+/* floppy disk */
+cdev_decl(fd);
+dev_decl(Fd, open);
+dev_decl(Fd, close);
+#define cdev_floppy_init(c) { \
+ dev_init(c,Fd,open), \
+ dev_init(c,Fd,close), \
+ dev_init(c,fd,read), \
+ dev_init(c,fd,write), \
+ dev_init(c,fd,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ seltrue, \
+ (dev_type_map((*))) enodev, \
+ dev_init(c,fd,strategy) \
+}
+
+cdev_decl(cn);
+/* console */
+#define cdev_cn_init(c) { \
+ dev_init(c,cn,open), \
+ dev_init(c,cn,close), \
+ dev_init(c,cn,read), \
+ dev_init(c,cn,write), \
+ dev_init(c,cn,ioctl), \
+ (dev_type_stop((*))) nullop, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ dev_init(c,cn,select), \
+ (dev_type_map((*))) enodev, \
+ 0 \
+}
+
+cdev_decl(ctty);
+/* open, read, write, ioctl, select -- XXX should be a tty */
+#define cdev_ctty_init(c) { \
+ dev_init(c,ctty,open), \
+ (dev_type_close((*))) nullop, \
+ dev_init(c,ctty,read), \
+ dev_init(c,ctty,write), \
+ dev_init(c,ctty,ioctl), \
+ (dev_type_stop((*))) nullop, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ dev_init(c,ctty,select), \
+ (dev_type_map((*))) enodev, \
+ 0 \
+}
+
+dev_type_read(mmrw);
+/* read/write */
+#define cdev_mm_init(c) { \
+ (dev_type_open((*))) nullop, \
+ (dev_type_close((*))) nullop, \
+ mmrw, \
+ mmrw, \
+ (dev_type_ioctl((*))) enodev, \
+ (dev_type_stop((*))) nullop, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ (dev_type_select((*)))seltrue, \
+ (dev_type_map((*))) enodev, \
+ 0 \
+}
+
+/* read, write, strategy */
+#define cdev_swap_init(c) { \
+ (dev_type_open((*))) nullop, \
+ (dev_type_close((*))) nullop, \
+ rawread, \
+ rawwrite, \
+ (dev_type_ioctl((*))) enodev, \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ (dev_type_select((*))) enodev, \
+ (dev_type_map((*))) enodev, \
+ dev_init(c,sw,strategy) \
+}
+
+#include "pty.h"
+#define pts_tty pt_tty
+#define ptsioctl ptyioctl
+cdev_decl(pts);
+#define ptc_tty pt_tty
+#define ptcioctl ptyioctl
+cdev_decl(ptc);
+
+/* open, close, read, write, ioctl, tty, select */
+#define cdev_ptc_init(c) { \
+ dev_init(c,ptc,open), \
+ dev_init(c,ptc,close), \
+ dev_init(c,ptc,read), \
+ dev_init(c,ptc,write), \
+ dev_init(c,ptc,ioctl), \
+ (dev_type_stop((*))) nullop, \
+ (dev_type_reset((*))) nullop, \
+ dev_tty_init(c,ptc), \
+ dev_init(c,ptc,select), \
+ (dev_type_map((*))) enodev, \
+ 0 \
+}
+
+cdev_decl(log);
+/* open, close, read, ioctl, select -- XXX should be a generic device */
+#define cdev_log_init(c) { \
+ dev_init(c,log,open), \
+ dev_init(c,log,close), \
+ dev_init(c,log,read), \
+ (dev_type_write((*))) enodev, \
+ dev_init(c,log,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ dev_init(c,log,select), \
+ (dev_type_map((*))) enodev, \
+ 0 \
+}
+
+
+#include "grf.h"
+cdev_decl(grf);
+/* open, close, ioctl, select, map -- XXX should be a map device */
+#define cdev_grf_init(c) { \
+ dev_init(c,grf,open), \
+ dev_init(c,grf,close), \
+ (dev_type_read((*))) nullop, \
+ (dev_type_write((*))) nullop, \
+ dev_init(c,grf,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ dev_init(c,grf,select), \
+ dev_init(c,grf,map), \
+ 0 \
+}
+
+#include "view.h"
+cdev_decl(view);
+/* open, close, ioctl, select, map -- XXX should be a map device */
+#define cdev_view_init(c) { \
+ dev_init(c,view,open), \
+ dev_init(c,view,close), \
+ (dev_type_read((*))) nullop, \
+ (dev_type_write((*))) nullop, \
+ dev_init(c,view,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ 0, \
+ dev_init(c,view,select), \
+ dev_init(c,view,map), \
+ 0 \
+}
+
+#include "ite.h"
+cdev_decl(ite);
+/* open, close, read, write, ioctl, tty -- XXX should be a tty! */
+#define cdev_ite_init(c) { \
+ dev_init(c,ite,open), \
+ dev_init(c,ite,close), \
+ dev_init(c,ite,read), \
+ dev_init(c,ite,write), \
+ dev_init(c,ite,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ dev_tty_init(c,ite), \
+ ttselect, \
+ (dev_type_map((*))) enodev, \
+ 0 \
+}
+
+#include "kbd.h"
+cdev_decl(kbd);
+/* open, close, read, write, ioctl, select */
+#define cdev_kbd_init(c) { \
+ dev_init(c,kbd,open), \
+ dev_init(c,kbd,close), \
+ dev_init(c,kbd,read), \
+ dev_init(c,kbd,write), \
+ dev_init(c,kbd,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) nullop, \
+ (struct tty **) NULL, \
+ dev_init(c,kbd,select), \
+ (dev_type_map((*))) enodev, \
+ (dev_type_strategy((*))) 0 \
+}
+
+dev_type_open(fdopen);
+/* open */
+#define cdev_fd_init(c) { \
+ dev_init(c,fd,open), \
+ (dev_type_close((*))) enodev, \
+ (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, \
+ (dev_type_ioctl((*))) enodev, \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) enodev, \
+ (struct tty **) NULL, \
+ (dev_type_select((*))) enodev, \
+ (dev_type_map((*))) enodev, \
+ (dev_type_strategy((*))) NULL \
+}
+
+#include "bpfilter.h"
+cdev_decl(bpf);
+/* open, close, read, write, ioctl, select -- XXX should be generic device */
+#define cdev_bpf_init(c) { \
+ dev_init(c,bpf,open), \
+ dev_init(c,bpf,close), \
+ dev_init(c,bpf,read), \
+ dev_init(c,bpf,write), \
+ dev_init(c,bpf,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) enodev, \
+ (struct tty **) NULL, \
+ dev_init(c,bpf,select), \
+ (dev_type_map((*))) enodev, \
+ (dev_type_strategy((*))) NULL \
+}
+
+
+#ifdef LKM
+#define NLKM 1
+#else
+#define NLKM 0
+#endif
+
+dev_type_open(lkmopen);
+dev_type_close(lkmclose);
+dev_type_ioctl(lkmioctl);
+
+#define cdev_lkm_init(c) { \
+ dev_init(c,lkm,open), \
+ dev_init(c,lkm,close), \
+ (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, \
+ dev_init(c,lkm,ioctl), \
+ (dev_type_stop((*))) enodev, \
+ (dev_type_reset((*))) enodev, \
+ (struct tty **) NULL, \
+ (dev_type_select((*))) enodev,\
+ (dev_type_map((*))) enodev, \
+ (dev_type_strategy((*))) NULL \
+}
+
+#define LKM_CDEV() { \
+ (dev_type_open((*))) lkmenodev, \
+ (dev_type_close((*))) lkmenodev, \
+ (dev_type_read((*))) lkmenodev, \
+ (dev_type_write((*))) lkmenodev, \
+ (dev_type_ioctl((*))) lkmenodev, \
+ (dev_type_stop((*))) lkmenodev, \
+ (dev_type_reset((*))) nullop, \
+ (struct tty **) NULL, \
+ (dev_type_select((*))) seltrue, \
+ (dev_type_map((*))) lkmenodev, \
+ (dev_type_strategy((*))) NULL \
+}
+
+#include "zs.h"
+cdev_decl(zs);
+
+struct cdevsw cdevsw[] =
+{
+ cdev_cn_init(1), /* 0 : virtual console */
+ cdev_ctty_init(1), /* 1 : controlling terminal */
+ cdev_mm_init(1), /* 2 : /dev/{null,mem,kmem,...} */
+ cdev_swap_init(1), /* 3 : /dev/drum (swap pseudo-device) */
+ cdev_tty_init(NPTY,pts), /* 4 : pseudo-tty slave */
+ cdev_ptc_init(NPTY), /* 5 : pseudo-tty master */
+ cdev_log_init(1), /* 6 : /dev/klog */
+ cdev_tty_init(NZS,zs), /* 7 : 8530 SCC */
+ cdev_disk_init(NSD,sd), /* 8 : scsi disk */
+ cdev_disk_init(NCD,cd), /* 9 : scsi cdrom */
+ cdev_st_init(NST), /* 10: scsi tape */
+ cdev_grf_init(NGRF), /* 11: frame buffer */
+ cdev_ite_init(NITE), /* 12: console terminal emulator */
+ cdev_view_init(NVIEW), /* 13: /dev/view00 /dev/view01 ... */
+ cdev_kbd_init(NKBD), /* 14: /dev/kbd */
+ cdev_notdef(), /* 15: /dev/mouse0 /dev/mouse1 */
+ cdev_floppy_init(NFD), /* 16: floppy */
+ cdev_disk_init(NVND,vnd), /* 17: vnode disk */
+ cdev_fd_init(1), /* 18: file descriptor pseudo-dev */
+ cdev_bpf_init(NBPFILTER), /* 19: berkeley packet filter */
+ cdev_lkm_init(NLKM), /* 20: loadable kernel modules pdev */
+ LKM_CDEV(), /* 21: Empty slot for LKM */
+ LKM_CDEV(), /* 22: Empty slot for LKM */
+ LKM_CDEV(), /* 23: Empty slot for LKM */
+ LKM_CDEV(), /* 24: Empty slot for LKM */
+ LKM_CDEV(), /* 25: Empty slot for LKM */
+ LKM_CDEV(), /* 26: Empty slot for LKM */
+};
+
+int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
+
+#ifdef BANKEDDEVPAGER
+extern int grfbanked_get __P((int, int, int));
+extern int grfbanked_set __P((int, int));
+extern int grfbanked_cur __P((int));
+
+struct bankeddevsw bankeddevsw[sizeof (cdevsw) / sizeof (cdevsw[0])] = {
+ { 0, 0, 0 }, /* 0 */
+ { 0, 0, 0 }, /* 1 */
+ { 0, 0, 0 }, /* 2 */
+ { 0, 0, 0 }, /* 3 */
+ { 0, 0, 0 }, /* 4 */
+ { 0, 0, 0 }, /* 5 */
+ { 0, 0, 0 }, /* 6 */
+ { 0, 0, 0 }, /* 7 */
+ { 0, 0, 0 }, /* 8 */
+ { 0, 0, 0 }, /* 9 */
+ { grfbanked_get, grfbanked_cur, grfbanked_set }, /* 10 */
+ /* rest { 0, 0, 0 } */
+};
+#endif
+
+int mem_no = 2; /* major device number of memory special file */
+
+/*
+ * Swapdev is a fake device implemented
+ * in sw.c used only internally to get to swstrategy.
+ * It cannot be provided to the users, because the
+ * swstrategy routine munches the b_dev and b_blkno entries
+ * before calling the appropriate driver. This would horribly
+ * confuse, e.g. the hashing routines. Instead, /dev/drum is
+ * provided as a character (raw) device.
+ */
+dev_t swapdev = makedev(3, 0);
+
+/*
+ * return true if memory device (kmem or mem)
+ */
+int
+iskmemdev(dev)
+dev_t dev;
+{
+ if (major(dev) == mem_no && minor(dev) < 2)
+ return(1);
+ return(0);
+}
+
+/*
+ * return true if /dev/zero
+ */
+int
+iszerodev(dev)
+ dev_t dev;
+{
+ if (major(dev) == mem_no && minor(dev) == 12)
+ return(1);
+ return(0);
+}
+
+/*
+ * return true if a disk
+ */
+int
+isdisk(dev, type)
+ dev_t dev;
+ int type;
+{
+ switch (major(dev)) {
+ case 2: /* fd: floppy */
+ case 4: /* sd: scsi disk */
+ case 7: /* cd: scsi cd-rom */
+ if (type == VBLK)
+ return(1);
+ break;
+ case 8: /* sd: scsi disk */
+ case 9: /* cd: scsi cdrom */
+ case 18: /* fd: floppy */
+ if (type == VCHR)
+ return(1);
+ break;
+ }
+ return(0);
+}
+
+static int chrtoblktab[] = {
+ /* CHR*/ /* BLK*/ /* CHR*/ /* BLK*/
+ /* 0 */ NODEV, /* 1 */ NODEV,
+ /* 2 */ NODEV, /* 3 */ 3,
+ /* 4 */ NODEV, /* 5 */ NODEV,
+ /* 6 */ NODEV, /* 7 */ NODEV,
+ /* 8 */ 4, /* 9 */ 7,
+ /* 10 */ NODEV, /* 11 */ NODEV,
+ /* 12 */ NODEV, /* 13 */ NODEV,
+ /* 14 */ NODEV, /* 15 */ NODEV,
+ /* 16 */ NODEV, /* 17 */ NODEV,
+ /* 18 */ 2, /* 19 */ 6,
+ /* 20 */ 5, /* 21 */ NODEV,
+ /* 22 */ NODEV, /* 23 */ NODEV,
+ /* 24 */ NODEV, /* 25 */ NODEV,
+ /* 26 */ NODEV, /* 27 */ NODEV,
+ /* 28 */ NODEV, /* 29 */ NODEV,
+ /* 30 */ NODEV,
+};
+
+/*
+ * convert chr dev to blk dev
+ */
+dev_t
+chrtoblk(dev)
+ dev_t dev;
+{
+ int blkmaj;
+
+ if (major(dev) >= nchrdev)
+ return(NODEV);
+ blkmaj = chrtoblktab[major(dev)];
+ if (blkmaj == NODEV)
+ return(NODEV);
+ return(makedev(blkmaj, minor(dev)));
+}
+
+
+/*
+ * console capable devices entry points.
+ */
+int sercnprobe(), sercninit(), sercngetc(), sercnputc();
+int ite_cnprobe(), ite_cninit(), ite_cngetc(), ite_cnputc();
+
+struct consdev constab[] = {
+#if NSER > 0
+ { sercnprobe, sercninit, sercngetc, sercnputc, (void(*))nullop },
+#endif
+#if NITE > 0
+ { ite_cnprobe, ite_cninit, ite_cngetc, ite_cnputc, (void(*))nullop },
+#endif
+ { 0 },
+};
diff --git a/sys/arch/atari/atari/device.h b/sys/arch/atari/atari/device.h
new file mode 100644
index 00000000000..209c2205df4
--- /dev/null
+++ b/sys/arch/atari/atari/device.h
@@ -0,0 +1,55 @@
+/* $NetBSD: device.h,v 1.1.1.1 1995/03/26 07:12:18 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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 _ATARI_DEVICE_H_
+#define _ATARI_DEVICE_H_
+
+/*
+ * devices that need to configure before console use this
+ * *and know it* (i.e. everything is really tight certain params won't be
+ * passed in some cases and the devices will deal with it)
+ */
+int atari_config_found __P((struct cfdata *, struct device *,
+ void *, cfprint_t ));
+int simple_devprint __P((void *, char *));
+int matchname __P((char *, char *));
+/*
+ * false when initing for the console.
+ */
+extern int atari_realconfig;
+
+
+#define getsoftc(cdnam, unit) \
+ ((unit) >= (cdnam).cd_ndevs ? NULL : (cdnam).cd_devs[unit])
+
+#endif /* _ATARI_DEVICE_H_ */
diff --git a/sys/arch/atari/atari/disksubr.c b/sys/arch/atari/atari/disksubr.c
new file mode 100644
index 00000000000..69eb9ff28ca
--- /dev/null
+++ b/sys/arch/atari/atari/disksubr.c
@@ -0,0 +1,370 @@
+/* $NetBSD: disksubr.c,v 1.1.1.1 1995/03/26 07:12:18 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 <sys/param.h>
+#include <sys/buf.h>
+#include <sys/disklabel.h>
+#include <machine/tospart.h>
+
+#define b_cylin b_resid
+#define baddr(bp) (void *)((bp)->b_un.b_addr)
+
+/*
+ * Stash TOS partition info in here before handling.
+ */
+typedef struct {
+ u_long nblocks;
+ u_long blkoff;
+ u_long type;
+} TMP_PART;
+
+#define ROOT_FLAG 0x8000 /* Added in TMP_PART.type when NBR */
+
+static char *rd_tosparts __P((TMP_PART *,dev_t,void (*)(),struct disklabel *));
+static int get_type __P((u_char *));
+
+/* XXX unknown function but needed for /sys/scsi to link */
+int
+dk_establish()
+{
+ return(-1);
+}
+
+/*
+ * Attempt to read a disk label from a device
+ * using the indicated stategy routine.
+ * The label must be partly set up before this:
+ * secpercyl and anything required in the strategy routine
+ * (e.g., sector size) must be filled in before calling us.
+ * Returns null on success and an error string on failure.
+ */
+char *
+readdisklabel(dev, strat, lp, clp)
+dev_t dev;
+void (*strat)();
+struct disklabel *lp;
+struct cpu_disklabel *clp;
+{
+ TMP_PART sizes[TOS_MAXPART];
+ char *msg;
+ int i;
+ int usr_part = RAW_PART;
+
+ bzero(sizes, sizeof(sizes));
+ if((msg = rd_tosparts(sizes, dev, strat, lp)) != NULL)
+ return(msg);
+
+ /*
+ * give some guarnteed validity to
+ * the disklabel
+ */
+ if(lp->d_secperunit == 0)
+ lp->d_secperunit = 0x1fffffff;
+ if(lp->d_secpercyl == 0)
+ return("Zero secpercyl");
+ lp->d_npartitions = RAW_PART + 1;
+
+ for(i = 0; i < MAXPARTITIONS; i++) {
+ if(i == RAW_PART)
+ continue;
+ lp->d_partitions[i].p_size = 0;
+ lp->d_partitions[i].p_offset = 0;
+ }
+
+ /*
+ * Now map the partition table from TOS to the NetBSD table.
+ *
+ * This means:
+ * Part 0 : Root
+ * Part 1 : Swap
+ * Part 2 : Whole disk
+ * Part 3.. : User partitions
+ *
+ * When more than one root partition is found, the only the first one
+ * will be recognized as such. The others are mapped as user partitions.
+ */
+ lp->d_partitions[RAW_PART].p_size = sizes[0].nblocks;
+ lp->d_partitions[RAW_PART].p_offset = sizes[0].blkoff;
+
+ for(i = 0; sizes[i].nblocks; i++) {
+ int have_root = 0;
+ int pno;
+
+ if(!have_root && (sizes[i].type & ROOT_FLAG)) {
+ lp->d_partitions[0].p_size = sizes[i].nblocks;
+ lp->d_partitions[0].p_offset = sizes[i].blkoff;
+ lp->d_partitions[0].p_fstype = FS_BSDFFS;
+ have_root++;
+ continue;
+ }
+ switch(sizes[i].type &= ~ROOT_FLAG) {
+ case FS_SWAP:
+ pno = 1;
+ break;
+ case FS_BSDFFS:
+ case FS_MSDOS:
+ pno = ++usr_part;
+ break;
+ default:
+ continue;
+ }
+ if(pno >= MAXPARTITIONS)
+ break; /* XXX */
+ lp->d_partitions[pno].p_size = sizes[i].nblocks;
+ lp->d_partitions[pno].p_offset = sizes[i].blkoff;
+ lp->d_partitions[pno].p_fstype = sizes[i].type;
+ }
+ lp->d_npartitions = usr_part + 1;
+ lp->d_secperunit = sizes[0].nblocks;
+
+ /*
+ * calulate new checksum.
+ */
+ lp->d_magic = lp->d_magic2 = DISKMAGIC;
+ lp->d_checksum = 0;
+ lp->d_checksum = dkcksum(lp);
+
+ return(NULL);
+}
+
+/*
+ * Check new disk label for sensibility
+ * before setting it.
+ */
+int
+setdisklabel(olp, nlp, openmask, clp)
+register struct disklabel *olp, *nlp;
+u_long openmask;
+struct cpu_disklabel *clp;
+{
+ return (EINVAL);
+}
+
+/*
+ * Write disk label back to device after modification.
+ */
+int
+writedisklabel(dev, strat, lp, clp)
+ dev_t dev;
+ void (*strat)();
+ register struct disklabel *lp;
+ struct cpu_disklabel *clp;
+{
+ return(EINVAL);
+}
+
+
+int
+bounds_check_with_label(bp, lp, wlabel)
+struct buf *bp;
+struct disklabel *lp;
+int wlabel;
+{
+ struct partition *pp;
+ long maxsz, sz;
+
+ pp = &lp->d_partitions[DISKPART(bp->b_dev)];
+ if(bp->b_flags & B_RAW) {
+ maxsz = pp->p_size * (lp->d_secsize / DEV_BSIZE);
+ sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
+ }
+ else {
+ maxsz = pp->p_size;
+ sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
+ }
+
+ if(bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+ if(bp->b_blkno == maxsz) {
+ /*
+ * trying to get one block beyond return EOF.
+ */
+ bp->b_resid = bp->b_bcount;
+ return(0);
+ }
+ sz = maxsz - bp->b_blkno;
+ if(sz <= 0 || bp->b_blkno < 0) {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR;
+ return(-1);
+ }
+ /*
+ * adjust count down
+ */
+ if(bp->b_flags & B_RAW)
+ bp->b_bcount = sz << DEV_BSHIFT;
+ else bp->b_bcount = sz * lp->d_secsize;
+ }
+
+ /*
+ * calc cylinder for disksort to order transfers with
+ */
+ bp->b_cylin = (bp->b_blkno + pp->p_offset) / lp->d_secpercyl;
+ return(1);
+}
+
+/*
+ * Read a GEM-partition info and translate it to our temporary partitions array.
+ * Returns 0 if an error occured, 1 if all went ok.
+ */
+#define BP_SETUP(bp, block) { \
+ bp->b_blkno = block; \
+ bp->b_cylin = block / lp->d_secpercyl; \
+ bp->b_bcount = TOS_BSIZE; \
+ bp->b_flags = B_BUSY | B_READ; \
+ }
+
+static char *
+rd_tosparts(sizes, dev, strat, lp)
+TMP_PART *sizes;
+dev_t dev;
+void (*strat)();
+struct disklabel *lp;
+{
+ GEM_ROOT *g_root;
+ GEM_PART g_local[NGEM_PARTS];
+ struct buf *bp;
+ int pno = 1;
+ char *msg = NULL;
+ int i;
+
+ /*
+ * Get a buffer first, so we can read the disk.
+ */
+ bp = (void*)geteblk(TOS_BSIZE);
+ bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART);
+
+ /*
+ * Read root sector
+ */
+ BP_SETUP(bp, TOS_BBLOCK);
+ strat(bp);
+ if(biowait(bp)) {
+ msg = "I/O error";
+ goto done;
+ }
+
+ /*
+ * Make local copy of partition info, we may need to re-use
+ * the buffer in case of 'XGM' partitions.
+ */
+ g_root = (GEM_ROOT*)baddr(bp);
+ bcopy(g_root->parts, g_local, NGEM_PARTS*sizeof(GEM_PART));
+
+ /*
+ * Partition 0 contains whole disk!
+ */
+ sizes[0].nblocks = g_root->hd_siz;
+ sizes[0].blkoff = 0;
+ sizes[0].type = FS_UNUSED;
+
+ for(i = 0; i < NGEM_PARTS; i++) {
+ if(!(g_local[i].p_flg & 1))
+ continue;
+ if(!strncmp(g_local[i].p_id, "XGM", 3)) {
+ int j;
+ daddr_t new_root = g_local[i].p_st;
+
+ /*
+ * Loop through extended partition list
+ */
+ for(;;) {
+ BP_SETUP(bp, new_root);
+ strat(bp);
+ if(biowait(bp)) {
+ msg = "I/O error";
+ goto done;
+ }
+ for(j = 0; j < NGEM_PARTS; j++) {
+ if(!(g_root->parts[j].p_flg & 1))
+ continue;
+ if(!strncmp(g_root->parts[j].p_id, "XGM", 3)) {
+ new_root = g_local[i].p_st + g_root->parts[j].p_st;
+ break;
+ }
+ else {
+ sizes[pno].nblocks=g_root->parts[j].p_size;
+ sizes[pno].blkoff =g_root->parts[j].p_st+new_root;
+ sizes[pno].type =get_type(g_root->parts[j].p_id);
+ pno++;
+ if(pno >= TOS_MAXPART)
+ break;
+ }
+ }
+ if(j == NGEM_PARTS)
+ break;
+ }
+ }
+ else {
+ sizes[pno].nblocks = g_local[i].p_size;
+ sizes[pno].blkoff = g_local[i].p_st;
+ sizes[pno].type = get_type(g_local[i].p_id);
+ pno++;
+ }
+ }
+ /*
+ * Check sensibility of partition info
+ */
+ for(i = 2; i < pno; i++) {
+ if(sizes[i].blkoff < (sizes[i-1].blkoff + sizes[i-1].nblocks)) {
+ msg = "Partion table bad (overlap)";
+ goto done;
+ }
+ if((sizes[i].blkoff + sizes[i].nblocks) > sizes[0].nblocks) {
+ msg = "Partion table bad (extends beyond disk)";
+ goto done;
+ }
+ }
+done:
+ bp->b_flags = B_INVAL | B_AGE | B_READ;
+ brelse(bp);
+ return(msg);
+}
+
+/*
+ * Translate a TOS partition type to a NetBSD partition type.
+ */
+#define ID_CMP(a,b) ((a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]))
+
+static int
+get_type(p_id)
+u_char *p_id;
+{
+ if(ID_CMP(p_id, "GEM") || ID_CMP(p_id, "BGM"))
+ return(FS_MSDOS); /* XXX - should be compatible */
+ if(ID_CMP(p_id, "NBU"))
+ return(FS_BSDFFS);
+ if(ID_CMP(p_id, "NBR"))
+ return(FS_BSDFFS|ROOT_FLAG);
+ if(ID_CMP(p_id, "NBS"))
+ return(FS_SWAP);
+ return(FS_OTHER);
+}
diff --git a/sys/arch/atari/atari/dkbad.c b/sys/arch/atari/atari/dkbad.c
new file mode 100644
index 00000000000..d426a362e83
--- /dev/null
+++ b/sys/arch/atari/atari/dkbad.c
@@ -0,0 +1,65 @@
+/* $NetBSD: dkbad.c,v 1.1.1.1 1995/03/26 07:12:19 leo Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 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.
+ *
+ * @(#)dkbad.c 7.2 (Berkeley) 12/16/90
+ */
+
+#ifndef NOBADSECT
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/dkbad.h>
+
+/*
+ * Search the bad sector table looking for
+ * the specified sector. Return index if found.
+ * Return -1 if not found.
+ */
+
+isbad(bt, cyl, trk, sec)
+ register struct dkbad *bt;
+{
+ register int i;
+ register long blk, bblk;
+
+ blk = ((long)cyl << 16) + (trk << 8) + sec;
+ for (i = 0; i < 126; i++) {
+ bblk = ((long)bt->bt_bad[i].bt_cyl << 16) + bt->bt_bad[i].bt_trksec;
+ if (blk == bblk)
+ return (i);
+ if (blk < bblk || bblk < 0)
+ break;
+ }
+ return (-1);
+}
+#endif
diff --git a/sys/arch/atari/atari/genassym.c b/sys/arch/atari/atari/genassym.c
new file mode 100644
index 00000000000..ad793301cfe
--- /dev/null
+++ b/sys/arch/atari/atari/genassym.c
@@ -0,0 +1,166 @@
+/* $NetBSD: genassym.c,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $ */
+
+/*
+ * 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.
+ *
+ * @(#)genassym.c 7.8 (Berkeley) 5/7/91
+ */
+
+#define KERNEL
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <machine/cpu.h>
+#include <machine/trap.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/vmparam.h>
+#include <sys/syscall.h>
+#include <vm/vm.h>
+#include <sys/user.h>
+#include <machine/pte.h>
+#include <machine/iomap.h>
+#include <machine/scu.h>
+
+main()
+{
+ register struct proc *p = (struct proc *)0;
+ register struct vmmeter *vm = (struct vmmeter *)0;
+ register struct user *up = (struct user *)0;
+ register struct rusage *rup = (struct rusage *)0;
+ struct frame *frame = NULL;
+ struct vmspace *vms = (struct vmspace *)0;
+ pmap_t pmap = (pmap_t)0;
+ struct pcb *pcb = (struct pcb *)0;
+ register unsigned i;
+
+ printf("#define\tP_FORW %d\n", &p->p_forw);
+ printf("#define\tP_BACK %d\n", &p->p_back);
+ printf("#define\tP_VMSPACE %d\n", &p->p_vmspace);
+ printf("#define\tP_ADDR %d\n", &p->p_addr);
+ printf("#define\tP_PRIORITY %d\n", &p->p_priority);
+ printf("#define\tP_STAT %d\n", &p->p_stat);
+ printf("#define\tP_WCHAN %d\n", &p->p_wchan);
+ printf("#define\tSRUN %d\n", SRUN);
+
+ printf("#define\tPM_STCHG %d\n", &pmap->pm_stchanged);
+
+ printf("#define\tVM_PMAP %d\n", &vms->vm_pmap);
+ printf("#define\tV_INTR %d\n", &vm->v_intr);
+
+ printf("#define\tUPAGES %d\n", UPAGES);
+ printf("#define\tNBPG %d\n", NBPG);
+ printf("#define\tPGSHIFT %d\n", PGSHIFT);
+ printf("#define\tUSRSTACK %d\n", USRSTACK);
+
+ printf("#define\tU_PROF %d\n", &up->u_stats.p_prof);
+ printf("#define\tU_PROFSCALE %d\n", &up->u_stats.p_prof.pr_scale);
+ printf("#define\tT_BUSERR %d\n", T_BUSERR);
+ printf("#define\tT_ADDRERR %d\n", T_ADDRERR);
+ printf("#define\tT_ILLINST %d\n", T_ILLINST);
+ printf("#define\tT_ZERODIV %d\n", T_ZERODIV);
+ printf("#define\tT_CHKINST %d\n", T_CHKINST);
+ printf("#define\tT_TRAPVINST %d\n", T_TRAPVINST);
+ printf("#define\tT_PRIVINST %d\n", T_PRIVINST);
+ printf("#define\tT_TRACE %d\n", T_TRACE);
+ printf("#define\tT_MMUFLT %d\n", T_MMUFLT);
+ printf("#define\tT_SSIR %d\n", T_SSIR);
+ printf("#define\tT_FMTERR %d\n", T_FMTERR);
+ printf("#define\tT_COPERR %d\n", T_COPERR);
+ printf("#define\tT_FPERR %d\n", T_FPERR);
+ printf("#define\tT_ASTFLT %d\n", T_ASTFLT);
+ printf("#define\tT_TRAP15 %d\n", T_TRAP15);
+ printf("#define\tPSL_S %d\n", PSL_S);
+ printf("#define\tPSL_IPL7 %d\n", PSL_IPL7);
+ printf("#define\tPSL_LOWIPL %d\n", PSL_LOWIPL);
+ printf("#define\tPSL_HIGHIPL %d\n", PSL_HIGHIPL);
+ printf("#define\tPSL_USER %d\n", PSL_USER);
+ printf("#define\tSPL1 %d\n", PSL_S | PSL_IPL1);
+ printf("#define\tSPL2 %d\n", PSL_S | PSL_IPL2);
+ printf("#define\tSPL3 %d\n", PSL_S | PSL_IPL3);
+ printf("#define\tSPL4 %d\n", PSL_S | PSL_IPL4);
+ printf("#define\tSPL5 %d\n", PSL_S | PSL_IPL5);
+ printf("#define\tSPL6 %d\n", PSL_S | PSL_IPL6);
+ printf("#define\tFC_USERD %d\n", FC_USERD);
+ printf("#define\tFC_SUPERD %d\n", FC_SUPERD);
+ printf("#define\tCACHE_ON %d\n", CACHE_ON);
+ printf("#define\tCACHE_OFF %d\n", CACHE_OFF);
+ printf("#define\tCACHE_CLR %d\n", CACHE_CLR);
+ printf("#define\tIC_CLEAR %d\n", IC_CLEAR);
+ printf("#define\tDC_CLEAR %d\n", DC_CLEAR);
+ printf("#define\tCACHE40_ON %d\n", CACHE40_ON);
+ printf("#define\tCACHE40_OFF %d\n", CACHE40_OFF);
+ printf("#define\tPG_V %d\n", PG_V);
+ printf("#define\tPG_NV %d\n", PG_NV);
+ printf("#define\tPG_RO %d\n", PG_RO);
+ printf("#define\tPG_RW %d\n", PG_RW);
+ printf("#define\tPG_CI %d\n", PG_CI);
+ printf("#define\tPG_PROT %d\n", PG_PROT);
+ printf("#define\tPG_FRAME %d\n", PG_FRAME);
+ printf("#define\tSG_V %d\n", SG_V);
+ printf("#define\tSG_NV %d\n", SG_NV);
+ printf("#define\tSG_RW %d\n", SG_RW);
+ printf("#define\tSG_FRAME %d\n", SG_FRAME);
+ printf("#define\tSG_ISHIFT %d\n", SG_ISHIFT);
+ printf("#define\tSG4_ISHIFT %d\n", SG4_ISHIFT);
+ printf("#define\tPCB_FLAGS %d\n", &pcb->pcb_flags);
+ printf("#define\tPCB_PS %d\n", &pcb->pcb_ps);
+ printf("#define\tPCB_USTP %d\n", &pcb->pcb_ustp);
+ printf("#define\tPCB_USP %d\n", &pcb->pcb_usp);
+ printf("#define\tPCB_REGS %d\n", pcb->pcb_regs);
+ printf("#define\tPCB_CMAP2 %d\n", &pcb->pcb_cmap2);
+ printf("#define\tPCB_ONFAULT %d\n", &pcb->pcb_onfault);
+ printf("#define\tPCB_FPCTX %d\n", &pcb->pcb_fpregs);
+ printf("#define\tSIZEOF_PCB %d\n", sizeof(struct pcb));
+
+ printf("#define\tFR_SP %d\n", &frame->f_regs[15]);
+ printf("#define\tFR_HW %d\n", &frame->f_sr);
+ printf("#define\tFR_ADJ %d\n", &frame->f_stackadj);
+
+ printf("#define\tSP %d\n", SP);
+ printf("#define\tSYS_exit %d\n", SYS_exit);
+ printf("#define\tSYS_execve %d\n", SYS_execve);
+ printf("#define\tSYS_sigreturn %d\n", SYS_sigreturn);
+ printf("#define\tATARI_68020 %d\n", ATARI_68020);
+ printf("#define\tATARI_68030 %d\n", ATARI_68030);
+ printf("#define\tATARI_68040 %d\n", ATARI_68040);
+ printf("#define\tMMU_68030 %d\n", MMU_68030);
+ printf("#define\tMMU_68851 %d\n", MMU_68851);
+ printf("#define\tMMU_68040 %d\n", MMU_68040);
+
+ printf("#define\tSOFTINT_ADDR %d\n", &SCU->sys_int);
+
+ exit(0);
+}
diff --git a/sys/arch/atari/atari/kdassert.h b/sys/arch/atari/atari/kdassert.h
new file mode 100644
index 00000000000..2b4ac37a3b9
--- /dev/null
+++ b/sys/arch/atari/atari/kdassert.h
@@ -0,0 +1,56 @@
+/* $NetBSD: kdassert.h,v 1.1.1.1 1995/03/26 07:12:18 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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.
+ */
+
+#if ! defined (_KDASSERT_H)
+#define _KDASSERT_H
+#if defined (DEBUG)
+#if defined (__STDC__)
+#if defined (__GNUC__)
+#define KDASSERT(x) if (!(x)) panic ("kernel assertion:\"%s\" failed\nfile: %s\n" \
+ "func: %s\nline: %d\n", #x , __FILE__, __FUNCTION__, __LINE__)
+#else /* !__GNUC__ */
+#define KDASSERT(x) if (!(x)) panic ("kernel assertion:\"%s\" failed\nfile: %s\n" \
+ "line: %d\n", #x, __FILE__, __LINE__)
+#endif /* !__GNUC__ */
+#else /* !__STDC__ */
+#if defined (__GNUC__)
+#define KDASSERT(x) if (!(x)) panic ("kernel assertion:\"%s\" failed\nfile: %s\n" \
+ "func: %s\nline: %d\n", "x", __FILE__, __FUNCTION__, __LINE__)
+#else /* !__GNUC__ */
+#define KDASSERT(x) if (!(x)) panic ("kernel assertion:\"%s\" failed\nfile: %s\n" \
+ "line: %d\n", "x", __FILE__, __LINE__)
+#endif /* !__GNUC__ */
+#endif /* !__STDC__ */
+#else /* !DEBUG */
+#define KDASSERT(x)
+#endif /* !DEBUG */
+#endif /* _KDASSERT_H
diff --git a/sys/arch/atari/atari/locore.s b/sys/arch/atari/atari/locore.s
new file mode 100644
index 00000000000..51a9c3bc1d7
--- /dev/null
+++ b/sys/arch/atari/atari/locore.s
@@ -0,0 +1,2141 @@
+/* $NetBSD: locore.s,v 1.1.1.1 1995/03/26 07:12:19 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1980, 1990 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.
+ *
+ * from: Utah $Hdr: locore.s 1.58 91/04/22$
+ *
+ * @(#)locore.s 7.11 (Berkeley) 5/9/91
+ */
+
+/*
+ *
+ * Original (hp300) Author: unknown, maybe Mike Hibler?
+ * Amiga author: Markus Wild
+ * Atari Modifications: Leo Weppelman
+ */
+
+#include "assym.s"
+#include <atari/atari/vectors.s>
+
+ .text
+/*
+ * This is where we wind up if the kernel jumps to location 0.
+ * (i.e. a bogus PC) This is known to immediately follow the vector
+ * table and is hence at 0x400 (see reset vector in vectors.s).
+ */
+ .globl _panic
+ pea Ljmp0panic
+ jbsr _panic
+ /* NOTREACHED */
+Ljmp0panic:
+ .asciz "kernel jump to zero"
+ .even
+
+/*
+ * Do a dump.
+ * Called by auto-restart.
+ */
+ .globl _dumpsys
+ .globl _doadump
+_doadump:
+ jbsr _dumpsys
+ jbsr _doboot
+ /*NOTREACHED*/
+
+/*
+ * Trap/interrupt vector routines
+ */
+
+ .globl _trap, _nofault, _longjmp
+_buserr:
+ tstl _nofault | device probe?
+ jeq _addrerr | no, handle as usual
+ movl _nofault,sp@- | yes,
+ jbsr _longjmp | longjmp(nofault)
+_addrerr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ lea sp@(FR_HW),a1 | grab base of HW berr frame
+ tstl _cpu040
+ jeq Lbe030
+ movl a1@(8),sp@- | V = exception address
+ clrl sp@- | dummy code
+ moveq #0,d0
+ movw a1@(6),d0 | get vector offset
+ andw #0x0fff,d0
+ cmpw #12,d0 | is it address error
+ jeq Lisaerr
+ movl a1@(20),d1 | get fault address
+ moveq #0,d0
+ movw a1@(12),d0 | get SSW
+ btst #11,d0 | check for mis-aligned
+ jeq Lbe1stpg | no skip
+ addl #3,d1 | get into next page
+ andl #PG_FRAME,d1 | and truncate
+Lbe1stpg:
+ movl d1,sp@(4) | pass fault address.
+ movl d0,sp@ | pass SSW as code
+ btst #10,d0 | test ATC
+ jeq Lisberr | it's a bus error
+ jra Lismerr
+Lbe030:
+ moveq #0,d0
+ movw a1@(10),d0 | grab SSW for fault processing
+ btst #12,d0 | RB set?
+ jeq LbeX0 | no, test RC
+ bset #14,d0 | yes, must set FB
+ movw d0,a1@(10) | for hardware too
+LbeX0:
+ btst #13,d0 | RC set?
+ jeq LbeX1 | no, skip
+ bset #15,d0 | yes, must set FC
+ movw d0,a1@(10) | for hardware too
+LbeX1:
+ btst #8,d0 | data fault?
+ jeq Lbe0 | no, check for hard cases
+ movl a1@(16),d1 | fault address is as given in frame
+ jra Lbe10 | thats it
+Lbe0:
+ btst #4,a1@(6) | long (type B) stack frame?
+ jne Lbe4 | yes, go handle
+ movl a1@(2),d1 | no, can use save PC
+ btst #14,d0 | FB set?
+ jeq Lbe3 | no, try FC
+ addql #4,d1 | yes, adjust address
+ jra Lbe10 | done
+Lbe3:
+ btst #15,d0 | FC set?
+ jeq Lbe10 | no, done
+ addql #2,d1 | yes, adjust address
+ jra Lbe10 | done
+Lbe4:
+ movl a1@(36),d1 | long format, use stage B address
+ btst #15,d0 | FC set?
+ jeq Lbe10 | no, all done
+ subql #2,d1 | yes, adjust address
+Lbe10:
+ movl d1,sp@- | push fault VA
+ movl d0,sp@- | and padded SSW
+ movw a1@(6),d0 | get frame format/vector offset
+ andw #0x0FFF,d0 | clear out frame format
+ cmpw #12,d0 | address error vector?
+ jeq Lisaerr | yes, go to it
+ movl d1,a0 | fault address
+ ptestr #1,a0@,#7 | do a table search
+ pmove psr,sp@ | save result
+ btst #7,sp@ | bus error bit set?
+ jeq Lismerr | no, must be MMU fault
+ clrw sp@ | yes, re-clear pad word
+ jra Lisberr | and process as normal bus error
+Lismerr:
+ movl #T_MMUFLT,sp@- | show that we are an MMU fault
+ jra Ltrapnstkadj | and deal with it
+Lisaerr:
+ movl #T_ADDRERR,sp@- | mark address error
+ jra Ltrapnstkadj | and deal with it
+Lisberr:
+ movl #T_BUSERR,sp@- | mark bus error
+Ltrapnstkadj:
+ jbsr _trap | handle the error
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore user SP
+ movl a0,usp | from save area
+ movw sp@(FR_ADJ),d0 | need to adjust stack?
+ jne Lstkadj | yes, go to it
+ moveml sp@+,#0x7FFF | no, restore most user regs
+ addql #8,sp | toss SSP and stkadj
+ jra rei | all done
+Lstkadj:
+ lea sp@(FR_HW),a1 | pointer to HW frame
+ addql #8,a1 | source pointer
+ movl a1,a0 | source
+ addw d0,a0 | + hole size = dest pointer
+ movl a1@-,a0@- | copy
+ movl a1@-,a0@- | 8 bytes
+ movl a0,sp@(FR_SP) | new SSP
+ moveml sp@+,#0x7FFF | restore user registers
+ movl sp@,sp | and our SP
+ jra rei | all done
+
+/*
+ * FP exceptions.
+ */
+_fpfline:
+#if defined(M68040)
+ cmpw #0x202c,sp@(6) | format type 2?
+ jne _illinst | no, not an FP emulation
+#ifdef FPSP
+ .globl fpsp_unimp
+ jmp fpsp_unimp | yes, go handle it
+#else
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save registers
+ moveq #T_FPEMULI,d0 | denote as FP emulation trap
+ jra fault | do it
+#endif
+#else
+ jra _illinst
+#endif
+
+_fpunsupp:
+#if defined(M68040)
+ cmpl #-2,_mmutype | 68040?
+ jne _illinst | no, treat as illinst
+#ifdef FPSP
+ .globl fpsp_unsupp
+ jmp fpsp_unsupp | yes, go handle it
+#else
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save registers
+ moveq #T_FPEMULD,d0 | denote as FP emulation trap
+ jra fault | do it
+#endif
+#else
+ jra _illinst
+#endif
+/*
+ * Handles all other FP coprocessor exceptions.
+ * Note that since some FP exceptions generate mid-instruction frames
+ * and may cause signal delivery, we need to test for stack adjustment
+ * after the trap call.
+ */
+ .globl _fpfault
+_fpfault:
+#ifdef FPCOPROC
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ movl _curpcb,a0 | current pcb
+ lea a0@(PCB_FPCTX),a0 | address of FP savearea
+ fsave a0@ | save state
+ tstb a0@ | null state frame?
+ jeq Lfptnull | yes, safe
+ clrw d0 | no, need to tweak BIU
+ movb a0@(1),d0 | get frame size
+ bset #3,a0@(0,d0:w) | set exc_pend bit of BIU
+Lfptnull:
+ fmovem fpsr,sp@- | push fpsr as code argument
+ frestore a0@ | restore state
+ movl #T_FPERR,sp@- | push type arg
+ jra Ltrapnstkadj | call trap and deal with stack cleanup
+#else
+ jra _badtrap | treat as an unexpected trap
+#endif
+
+/*
+ * Coprocessor and format errors can generate mid-instruction stack
+ * frames and cause signal delivery hence we need to check for potential
+ * stack adjustment.
+ */
+_coperr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@-
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl #T_COPERR,sp@- | push trap type
+ jra Ltrapnstkadj | call trap and deal with stack adjust
+
+_fmterr:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@-
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl #T_FMTERR,sp@- | push trap type
+ jra Ltrapnstkadj | call trap and deal with stack adjust
+
+/*
+ * Other exceptions only cause four and six word stack frame and require
+ * no post-trap stack adjustment.
+ */
+_illinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_ILLINST,d0
+ jra fault
+
+_zerodiv:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_ZERODIV,d0
+ jra fault
+
+_chkinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_CHKINST,d0
+ jra fault
+
+_trapvinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_TRAPVINST,d0
+ jra fault
+
+_privinst:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+ moveq #T_PRIVINST,d0
+ jra fault
+
+ .globl fault
+fault:
+ movl usp,a0 | get and save
+ movl a0,sp@(FR_SP) | the user stack pointer
+ clrl sp@- | no VA arg
+ clrl sp@- | or code arg
+ movl d0,sp@- | push trap type
+ jbsr _trap | handle trap
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | restore most user regs
+ addql #8,sp | pop SP and stack adjust
+ jra rei | all done
+
+ .globl _straytrap
+_lev2intr:
+_lev3intr:
+_lev4intr:
+_lev5intr:
+_lev6intr:
+_badtrap:
+ moveml #0xC0C0,sp@- | save scratch regs
+ movw sp@(22),sp@- | push exception vector info
+ clrw sp@-
+ movl sp@(22),sp@- | and PC
+ jbsr _straytrap | report
+ addql #8,sp | pop args
+ moveml sp@+,#0x0303 | restore regs
+ jra rei | all done
+
+ .globl _straymfpint
+_badmfpint:
+ moveml #0xC0C0,sp@- | save scratch regs
+ movw sp@(22),sp@- | push exception vector info
+ clrw sp@-
+ movl sp@(22),sp@- | and PC
+ jbsr _straymfpint | report
+ addql #8,sp | pop args
+ moveml sp@+,#0x0303 | restore regs
+ jra rei | all done
+
+ .globl _syscall
+_trap0:
+ clrl sp@- | stack adjust count
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ movl d0,sp@- | push syscall number
+ jbsr _syscall | handle it
+ addql #4,sp | pop syscall arg
+ movl sp@(FR_SP),a0 | grab and restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | restore most registers
+ addql #8,sp | pop SP and stack adjust
+ jra rei | all done
+
+/*
+ * Our native 4.3 implementation uses trap 1 as sigreturn() and trap 2
+ * as a breakpoint trap.
+ */
+_trap1:
+ jra sigreturn
+
+_trap2:
+ jra _trace
+
+/*
+ * Trap 12 is the entry point for the cachectl "syscall"
+ * cachectl(command, addr, length)
+ * command in d0, addr in a1, length in d1
+ */
+ .globl _cachectl
+_trap12:
+ movl d1,sp@- | push length
+ movl a1,sp@- | push addr
+ movl d0,sp@- | push command
+ jbsr _cachectl | do it
+ lea sp@(12),sp | pop args
+ jra rei | all done
+
+/*
+ * Trap 15 is used for:
+ * - KGDB traps
+ * - trace traps for SUN binaries (not fully supported yet)
+ * We just pass it on and let trap() sort it all out
+ */
+_trap15:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+#ifdef KGDB
+ moveq #T_TRAP15,d0
+ movw sp@(FR_HW),d1 | get PSW
+ andw #PSL_S,d1 | from user mode?
+ jeq fault | yes, just a regular fault
+ movl d0,sp@-
+ .globl _kgdb_trap_glue
+ jbsr _kgdb_trap_glue | returns if no debugger
+ addl #4,sp
+#endif
+ moveq #T_TRAP15,d0
+ jra fault
+
+/*
+ * Hit a breakpoint (trap 1 or 2) instruction.
+ * Push the code and treat as a normal fault.
+ */
+_trace:
+ clrl sp@-
+ moveml #0xFFFF,sp@-
+#ifdef KGDB
+ moveq #T_TRACE,d0
+ movw sp@(FR_HW),d1 | get SSW
+ andw #PSL_S,d1 | from user mode?
+ jeq fault | no, regular fault
+ movl d0,sp@-
+ jbsr _kgdb_trap_glue | returns if no debugger
+ addl #4,sp
+#endif
+ moveq #T_TRACE,d0
+ jra fault
+
+/*
+ * The sigreturn() syscall comes here. It requires special handling
+ * because we must open a hole in the stack to fill in the (possibly much
+ * larger) original stack frame.
+ */
+sigreturn:
+ lea sp@(-84),sp | leave enough space for largest frame
+ movl sp@(84),sp@ | move up current 8 byte frame
+ movl sp@(88),sp@(4)
+ movl #84,sp@- | default: adjust by 84 bytes
+ moveml #0xFFFF,sp@- | save user registers
+ movl usp,a0 | save the user SP
+ movl a0,sp@(FR_SP) | in the savearea
+ movl #SYS_sigreturn,sp@- | push syscall number
+ jbsr _syscall | handle it
+ addql #4,sp | pop syscall#
+ movl sp@(FR_SP),a0 | grab and restore
+ movl a0,usp | user SP
+ lea sp@(FR_HW),a1 | pointer to HW frame
+ movw sp@(FR_ADJ),d0 | do we need to adjust the stack?
+ jeq Lsigr1 | no, just continue
+ moveq #92,d1 | total size
+ subw d0,d1 | - hole size = frame size
+ lea a1@(92),a0 | destination
+ addw d1,a1 | source
+ lsrw #1,d1 | convert to word count
+ subqw #1,d1 | minus 1 for dbf
+Lsigrlp:
+ movw a1@-,a0@- | copy a word
+ dbf d1,Lsigrlp | continue
+ movl a0,a1 | new HW frame base
+Lsigr1:
+ movl a1,sp@(FR_SP) | new SP value
+ moveml sp@+,#0x7FFF | restore user registers
+ movl sp@,sp | and our SP
+ jra rei | all done
+
+/*
+ * Interrupt handlers.
+ *
+ * Level 0: Spurious: ignored.
+ * Level 1: softint
+ * Level 2: HBL
+ * Level 3: not used
+ * Level 4: not used
+ * Level 5: SCC (not used)
+ * Level 6: MFP1/MFP2 (not used -> autovectored)
+ * Level 7: Non-maskable: shouldn't be possible. ignore.
+ */
+
+/* Provide a generic interrupt dispatcher, only handle hardclock (int6)
+ * specially, to improve performance
+ */
+
+ .globl _hardclock
+
+_spurintr:
+ addql #1,_intrcnt+0
+ addql #1,_cnt+V_INTR
+ jra rei
+
+ /* MFP2 timer A handler --- System clock --- */
+ /* Note: Reduce by factor 4 before handling */
+mfp2_tima:
+ subqw #1,_clk_div | time for another clock tick?
+ jgt clk_ret | no, return
+ movw #4,_clk_div | reset divide counter
+ moveml d0-d1/a0-a1,sp@- | save scratch registers
+ lea sp@(16),a1 | get pointer to PS
+ movl a1,sp@- | push pointer to PS, PC
+ jbsr _hardclock | call generic clock int routine
+ addql #4,sp | pop params
+ addql #1,_intrcnt+4 | add another system clock interrupt
+ moveml sp@+,d0-d1/a0-a1 | restore scratch regs
+ addql #1,_cnt+V_INTR | chalk up another interrupt
+ jra rei | all done
+clk_ret:
+ rte
+
+
+ /* MFP ACIA handler --- keyboard/midi --- */
+mfp_kbd:
+ addql #1,_intrcnt+8 | add another kbd/mouse interrupt
+
+ moveml d0-d1/a0-a1,sp@- | Save scratch registers
+ movw sp@(16),sp@- | push previous SR value
+ clrw sp@- | padded to longword
+ jbsr _kbdintr | handle interrupt
+ addql #4,sp | pop SR
+ moveml sp@+,d0-d1/a0-a1
+ addql #1,_cnt+V_INTR | chalk up another interrupt
+ jra rei
+
+ /* MFP2 SCSI DMA handler --- NCR5380 --- */
+mfp2_5380dm:
+ addql #1,_intrcnt+24 | add another 5380-DMA interrupt
+
+ moveml d0-d1/a0-a1,sp@- | Save scratch registers
+ movw sp@(16),sp@- | push previous SR value
+ clrw sp@- | padded to longword
+ jbsr _scsi_dma | handle interrupt
+ addql #4,sp | pop SR
+ moveml sp@+,d0-d1/a0-a1
+ addql #1,_cnt+V_INTR | chalk up another interrupt
+ jra rei
+
+ /* MFP2 SCSI handler --- NCR5380 --- */
+mfp2_5380:
+ addql #1,_intrcnt+20 | add another 5380-SCSI interrupt
+
+ moveml d0-d1/a0-a1,sp@- | Save scratch registers
+ movw sp@(16),sp@- | push previous SR value
+ clrw sp@- | padded to longword
+ jbsr _scsi_ctrl | handle interrupt
+ addql #4,sp | pop SR
+ moveml sp@+,d0-d1/a0-a1
+ addql #1,_cnt+V_INTR | chalk up another interrupt
+ jra rei
+
+ /* MFP DMA handler --- fdc/acsi --- */
+mfp_fd_acsi:
+ addql #1,_intrcnt+12 | add another fdc/acsi interrupt
+
+ moveml d0-d1/a0-a1,sp@- | Save scratch registers
+ movw sp@(16),sp@- | push previous SR value
+ clrw sp@- | padded to longword
+ jbsr _cdmaint | handle interrupt
+ addql #4,sp | pop SR
+ moveml sp@+,d0-d1/a0-a1
+ addql #1,_cnt+V_INTR | chalk up another interrupt
+ jra rei
+
+ /* SCC Interrupt --- modem2/serial2 --- */
+sccint:
+ addql #1,_intrcnt+32 | add another SCC interrupt
+
+ moveml d0-d1/a0-a1,sp@- | Save scratch registers
+ movw sp@(16),sp@- | push previous SR value
+ clrw sp@- | padded to longword
+ jbsr _zshard | handle interrupt
+ addql #4,sp | pop SR
+ moveml sp@+,d0-d1/a0-a1
+ addql #1,_cnt+V_INTR | chalk up another interrupt
+ jra rei
+
+ /* Level 1 (Software) interrupt handler */
+_lev1intr:
+ moveb #0, SOFTINT_ADDR | Turn off software interrupt
+ moveml d0-d1/a0-a1,sp@-
+ addql #1,_intrcnt+16 | add another software interrupt
+ jbsr _call_sicallbacks | handle call-backs
+ moveml sp@+,d0-d1/a0-a1
+ addql #1,_cnt+V_INTR | chalk up another interrupt
+ jra rei
+
+_lev7intr: /* Should never occur */
+ addql #1,_intrcnt+28 | add another nmi interrupt
+ rte | all done
+
+
+/*
+ * Emulation of VAX REI instruction.
+ *
+ * This code deals with checking for and servicing ASTs
+ * (profiling, scheduling) and software interrupts (network, softclock).
+ * We check for ASTs first, just like the VAX. To avoid excess overhead
+ * the T_ASTFLT handling code will also check for software interrupts so we
+ * do not have to do it here. After identifing that we need an AST we
+ * drop the IPL to allow device interrupts.
+ *
+ * This code is complicated by the fact that sendsig may have been called
+ * necessitating a stack cleanup. A cleanup should only be needed at this
+ * point for coprocessor mid-instruction frames (type 9), but we also test
+ * for bus error frames (type 10 and 11).
+ */
+ .comm _ssir,1
+ .globl _astpending
+ .globl rei
+rei:
+#ifdef DEBUG
+ tstl _panicstr | have we paniced?
+ jne Ldorte | yes, do not make matters worse
+#endif
+ tstl _astpending | AST pending?
+ jeq Lchksir | no, go check for SIR
+Lrei1:
+ btst #5,sp@ | yes, are we returning to user mode?
+ jne Lchksir | no, go check for SIR
+ movw #PSL_LOWIPL,sr | lower SPL
+ clrl sp@- | stack adjust
+ moveml #0xFFFF,sp@- | save all registers
+ movl usp,a1 | including
+ movl a1,sp@(FR_SP) | the users SP
+ clrl sp@- | VA == none
+ clrl sp@- | code == none
+ movl #T_ASTFLT,sp@- | type == async system trap
+ jbsr _trap | go handle it
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore user SP
+ movl a0,usp | from save area
+ movw sp@(FR_ADJ),d0 | need to adjust stack?
+ jne Laststkadj | yes, go to it
+ moveml sp@+,#0x7FFF | no, restore most user regs
+ addql #8,sp | toss SP and stack adjust
+ rte | and do real RTE
+Laststkadj:
+ lea sp@(FR_HW),a1 | pointer to HW frame
+ addql #8,a1 | source pointer
+ movl a1,a0 | source
+ addw d0,a0 | + hole size = dest pointer
+ movl a1@-,a0@- | copy
+ movl a1@-,a0@- | 8 bytes
+ movl a0,sp@(FR_SP) | new SSP
+ moveml sp@+,#0x7FFF | restore user registers
+ movl sp@,sp | and our SP
+ rte | and do real RTE
+Lchksir:
+ tstb _ssir | SIR pending?
+ jeq Ldorte | no, all done
+ movl d0,sp@- | need a scratch register
+ movw sp@(4),d0 | get SR
+ andw #PSL_IPL7,d0 | mask all but IPL
+ jne Lnosir | came from interrupt, no can do
+ movl sp@+,d0 | restore scratch register
+Lgotsir:
+ movw #SPL1,sr | prevent others from servicing int
+ tstb _ssir | too late?
+ jeq Ldorte | yes, oh well...
+ clrl sp@- | stack adjust
+ moveml #0xFFFF,sp@- | save all registers
+ movl usp,a1 | including
+ movl a1,sp@(FR_SP) | the users SP
+ clrl sp@- | VA == none
+ clrl sp@- | code == none
+ movl #T_SSIR,sp@- | type == software interrupt
+ jbsr _trap | go handle it
+ lea sp@(12),sp | pop value args
+ movl sp@(FR_SP),a0 | restore
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | and all remaining registers
+ addql #8,sp | pop SP and stack adjust
+ rte
+Lnosir:
+ movl sp@+,d0 | restore scratch register
+Ldorte:
+ rte | real return
+
+/*
+ * Kernel access to the current processes kernel stack is via a fixed
+ * virtual address. It is at the same address as in the users VA space.
+ * Umap contains the KVA of the first of UPAGES PTEs mapping VA _kstack.
+ */
+ .data
+ .set _kstack,-(UPAGES*NBPG)
+_Umap: .long 0
+_esym: .long 0
+ .globl _kstack, _Umap, _esym
+
+
+/*
+ * Initialization
+ *
+ * A5 contains physical load point from boot
+ * exceptions vector thru our table, that's bad.. just hope nothing exceptional
+ * happens till we had time to initialize ourselves..
+ */
+ .comm _lowram,4
+
+ .text
+ .globl _edata
+ .globl _etext,_end
+ .globl start
+ .globl _first_8_bytes
+_first_8_bytes: | Save first 8 bytes here
+ .long 0
+ .long 0
+
+ .word 0x0002 | XXX: loadbsd version required
+ | 2: needs a4 = esym
+ | XXX should be a symbol?
+start:
+ movw #PSL_HIGHIPL,sr | No interrupts
+
+ /*
+ * a0 = start of loaded kernel
+ * a1 = value of esym
+ * d0 = fastmem size
+ * d1 = stmem size
+ * d2 = cputype
+ * d3 = boothowto
+ * d4 = size of loaded kernel
+ */
+ movl a0, a6 | Save load address in a6
+ movl #8, a5 | Addresses 0-8 are mapped to ROM on the
+ addql #8, a0 | atari ST. We cannot set these.
+ subl #8, d4
+
+ /*
+ * Copy until end of kernel relocation code.
+ */
+Lstart0:
+ movl a0@+,a5@+
+ subl #4, d4
+ cmpl #Lstart3,a5
+ jle Lstart0
+ /*
+ * Enter kernel at destination address and continue copy
+ */
+ jmp Lstart1
+Lstart1:
+ movl a6@+,_first_8_bytes | copy first 8 bytes
+ movl a6@,_first_8_bytes+4
+Lstart2:
+ movl a0@+,a5@+ | copy the rest of the kernel
+ subl #4, d4
+ jcc Lstart2
+Lstart3:
+
+ lea tmpstk,sp | give ourselves a temporary stack
+
+ /*
+ * save the passed parameters. `prepass' them on the stack for
+ * later catch by _start_c
+ */
+ movl a1,sp@- | pass address of _esym
+ movl d1,sp@- | pass stmem-size
+ movl d0,sp@- | pass fastmem-size
+ movl d5,sp@- | pass fastmem_start
+ movl d2,sp@- | pass machine id
+ movl d3,_boothowto | save reboot flags
+
+ movl #ATARI_68030,d1 | 68030 type from loader
+ andl d2,d1
+ jeq Ltestfor020 | Not an 68030, try 68020
+ movl #MMU_68030,_mmutype | Use 68030 MMU
+ jra Lsetcpu040 | skip to init.
+Ltestfor020:
+ movl #ATARI_68020,d1 | 68020 type from loader
+ andl d2,d1
+ jeq Lsetcpu040
+ movl #MMU_68851,_mmutype | Assume 68851 with 68020
+Lsetcpu040:
+ movl #CACHE_OFF,d0 | 68020/030 cache
+ movl #ATARI_68040,d1
+ andl d1,d2
+ movl d2,_cpu040 | set 68040 CPU flag
+ jeq Lstartnot040 | it's not 68040
+ movl #MMU_68040,_mmutype | same as hp300 for compat
+ .word 0xf4f8 | cpusha bc - push and inval caches
+ movl #CACHE40_OFF,d0 | 68040 cache disable
+Lstartnot040:
+ movc d0,cacr | clear and disable on-chip cache(s)
+ moveq #0,d0 | This assumes load-address 0!!
+ movc d0,vbr
+
+ /*
+ * Initialize source/destination control registers for movs
+ */
+ moveq #FC_USERD,d0 | user space
+ movc d0,sfc | as source
+ movc d0,dfc | and destination of transfers
+
+ /*
+ * let the C function initialize everything and enable the MMU
+ */
+ jsr _start_c
+
+ /*
+ * set kernel stack, user SP, and initial pcb
+ */
+ lea _kstack,a1 | proc0 kernel stack
+ lea a1@(UPAGES*NBPG-4),sp | set kernel stack to end of area
+ movl #USRSTACK-4,a2
+ movl a2,usp | init user SP
+ movl _proc0paddr,a1 | get proc0 pcb addr
+ movl a1,_curpcb | proc0 is running
+ clrw a1@(PCB_FLAGS) | clear flags
+#ifdef FPCOPROC
+ clrl a1@(PCB_FPCTX) | ensure null FP context
+ pea a1@(PCB_FPCTX)
+ jbsr _m68881_restore | restore it (does not kill a1)
+ addql #4,sp
+#endif
+ /* flush TLB and turn on caches */
+ jbsr _TBIA | invalidate TLB
+ movl #CACHE_ON,d0
+ tstl _cpu040
+ jeq Lcacheon
+ /* is this needed? MLH */
+ .word 0xf4f8 | cpusha bc - push & invalidate caches
+ movl #CACHE40_ON,d0
+Lcacheon:
+ movc d0,cacr | clear cache(s)
+
+ /*
+ * Final setup for C code
+ */
+ movw #PSL_LOWIPL,sr | lower SPL
+
+#ifdef notdef
+ movl d6,_bootdev | and boot device
+#endif
+
+ /*
+ * Create a fake exception frame that returns to user mode,
+ * make space for the rest of a fake saved register set, and
+ * pass a pointer to the register set to "main()".
+ * "main()" will call "icode()", which fakes
+ * an "execve()" system call, which is why we need to do that
+ * ("main()" sets "u.u_ar0" to point to the register set).
+ * When "main()" returns, we're running in process 1 and have
+ * successfully faked the "execve()". We load up the registers from
+ * that set; the "rte" loads the PC and PSR, which jumps to "init".
+ */
+ movl #0,a6 | make DDB stack_trace() work
+ clrw sp@- | vector offset/frame type
+ clrl sp@- | PC - filled in by "execve"
+ movw #PSL_USER,sp@- | in user mode
+ clrl sp@- | stack adjust count
+ lea sp@(-64),sp | construct space for D0-D7/A0-A7
+ pea sp@ | addr of space for D0
+ jbsr _main | main(r0)
+ addql #4,sp | pop args
+ tstl _cpu040 | 68040?
+ jeq Lnoflush | no, skip
+ .word 0xf478 | cpusha dc
+ .word 0xf498 | cinva ic
+Lnoflush:
+ movl sp@(FR_SP),a0 | grab and load
+ movl a0,usp | user SP
+ moveml sp@+,#0x7FFF | load most registers (all but SSP)
+ addql #8,sp | pop SSP and stack adjust count
+ rte
+
+/*
+ * Signal "trampoline" code (18 bytes). Invoked from RTE setup by sendsig().
+ *
+ * Stack looks like:
+ *
+ * sp+0 -> signal number
+ * sp+4 signal specific code
+ * sp+8 pointer to signal context frame (scp)
+ * sp+12 address of handler
+ * sp+16 saved hardware state
+ * .
+ * .
+ * scp+0-> beginning of signal context frame
+ */
+ .globl _sigcode, _esigcode
+ .data
+_sigcode:
+ movl sp@(12),a0 | signal handler addr (4 bytes)
+ jsr a0@ | call signal handler (2 bytes)
+ addql #4,sp | pop signo (2 bytes)
+ trap #1 | special syscall entry (2 bytes)
+ movl d0,sp@(4) | save errno (4 bytes)
+ moveq #1,d0 | syscall == exit (2 bytes)
+ trap #0 | exit(errno) (2 bytes)
+ .align 2
+_esigcode:
+
+/*
+ * Icode is copied out to process 1 to exec init.
+ * If the exec fails, process 1 exits.
+ */
+ .globl _icode,_szicode
+ .text
+_icode:
+ jra st1
+init:
+ .asciz "/sbin/init"
+ .byte 0 | GNU ``as'' bug won't
+ | allow an .even directive
+ | here, says something about
+ | non constant, which is crap.
+argv:
+ .long init+6-_icode | argv[0] = "init" ("/sbin/init" + 6)
+ .long eicode-_icode | argv[1] follows icode after copyout
+ .long 0
+
+st1:
+ clrl sp@-
+ .set argvrpc,argv-.-2 | avoids PCREL bugs in ``as''
+ | otherwise it assebles different
+ | depending on your version of
+ | GNU ``as''. Markus' as has a
+ | nice one:
+ | a: pea pc@(0)
+ | is equivelent to:
+ | a: pea pc@(a-.)
+ | is equivelent to!:
+ | a: pea pc@(b-.)
+ | b: ....
+ | ---
+ | Mine (2.2.1) doesn't work right
+ | for #3 mine puts out
+ | a: pea pc@(2)
+ | and it should be pc@(4).
+ | cest la vie.
+ pea pc@(argvrpc)
+ .set initrpc,init-.-2 | avoids PCREL bugs in ``as''
+ | see above comment
+ pea pc@(initrpc)
+ clrl sp@-
+ moveq #SYS_execve,d0
+ trap #0
+ moveq #SYS_exit,d0
+ trap #0
+eicode:
+
+_szicode:
+ .long _szicode-_icode
+
+/*
+ * Primitives
+ */
+#include <m68k/asm.h>
+
+/*
+ * copypage(fromaddr, toaddr)
+ *
+ * Optimized version of bcopy for a single page-aligned NBPG byte copy.
+ * dbra will work better perhaps.
+ */
+ENTRY(copypage)
+ movl sp@(4),a0 | source address
+ movl sp@(8),a1 | destination address
+ movl #NBPG/32,d0 | number of 32 byte chunks
+ tstl _cpu040
+ jeq Lmlloop | no, use movl
+Lm16loop:
+ .long 0xf6209000 | move16 a0@+,a1@+
+ .long 0xf6209000 | move16 a0@+,a1@+
+ subql #1,d0
+ jne Lm16loop
+ rts
+Lmlloop:
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ movl a0@+,a1@+
+ subql #1,d0
+ jne Lmlloop
+ rts
+/*
+ * update profiling information for the user
+ * addupc(pc, &u.u_prof, ticks)
+ */
+ENTRY(addupc)
+ movl a2,sp@- | scratch register
+ movl sp@(12),a2 | get &u.u_prof
+ movl sp@(8),d0 | get user pc
+ subl a2@(8),d0 | pc -= pr->pr_off
+ jlt Lauexit | less than 0, skip it
+ movl a2@(12),d1 | get pr->pr_scale
+ lsrl #1,d0 | pc /= 2
+ lsrl #1,d1 | scale /= 2
+ mulul d1,d0 | pc /= scale
+ moveq #14,d1
+ lsrl d1,d0 | pc >>= 14
+ bclr #0,d0 | pc &= ~1
+ cmpl a2@(4),d0 | too big for buffer?
+ jge Lauexit | yes, screw it
+ addl a2@,d0 | no, add base
+ movl d0,sp@- | push address
+ jbsr _fusword | grab old value
+ movl sp@+,a0 | grab address back
+ cmpl #-1,d0 | access ok
+ jeq Lauerror | no, skip out
+ addw sp@(18),d0 | add tick to current value
+ movl d0,sp@- | push value
+ movl a0,sp@- | push address
+ jbsr _susword | write back new value
+ addql #8,sp | pop params
+ tstl d0 | fault?
+ jeq Lauexit | no, all done
+Lauerror:
+ clrl a2@(12) | clear scale (turn off prof)
+Lauexit:
+ movl sp@+,a2 | restore scratch reg
+ rts
+
+/*
+ * non-local gotos
+ */
+ENTRY(setjmp)
+ movl sp@(4),a0 | savearea pointer
+ moveml #0xFCFC,a0@ | save d2-d7/a2-a7
+ movl sp@,a0@(48) | and return address
+ moveq #0,d0 | return 0
+ rts
+
+ENTRY(qsetjmp)
+ movl sp@(4),a0 | savearea pointer
+ lea a0@(40),a0 | skip regs we do not save
+ movl a6,a0@+ | save FP
+ movl sp,a0@+ | save SP
+ movl sp@,a0@ | and return address
+ moveq #0,d0 | return 0
+ rts
+
+ENTRY(longjmp)
+ movl sp@(4),a0
+ moveml a0@+,#0xFCFC
+ movl a0@,sp@
+ moveq #1,d0
+ rts
+
+/*
+ * The following primitives manipulate the run queues.
+ * _whichqs tells which of the 32 queues _qs
+ * have processes in them. Setrunqueue puts processes into queues, Remrq
+ * removes them from queues. The running process is on no queue,
+ * other processes are on a queue related to p->p_priority, divided by 4
+ * actually to shrink the 0-127 range of priorities into the 32 available
+ * queues.
+ */
+
+ .globl _whichqs,_qs,_cnt,_panic
+ .globl _curproc
+ .comm _want_resched,4
+
+/*
+ * Setrunqueue(p)
+ *
+ * Call should be made at spl6(), and p->p_stat should be SRUN
+ */
+ENTRY(setrunqueue)
+ movl sp@(4),a0
+ tstl a0@(P_BACK)
+ jeq Lset1
+ movl #Lset2,sp@-
+ jbsr _panic
+Lset1:
+ clrl d0
+ movb a0@(P_PRIORITY),d0
+ lsrb #2,d0
+ movl _whichqs,d1
+ bset d0,d1
+ movl d1,_whichqs
+ lslb #3,d0
+ addl #_qs,d0
+ movl d0,a0@(P_FORW)
+ movl d0,a1
+ movl a1@(P_BACK),a0@(P_BACK)
+ movl a0,a1@(P_BACK)
+ movl a0@(P_BACK),a1
+ movl a0,a1@(P_FORW)
+ rts
+
+Lset2:
+ .asciz "setrunqueue"
+ .even
+
+/*
+ * Remrq(p)
+ *
+ * Call should be made at spl6().
+ */
+ENTRY(remrq)
+ movl sp@(4),a0
+ clrl d0
+ movb a0@(P_PRIORITY),d0
+ lsrb #2,d0
+ movl _whichqs,d1
+ bclr d0,d1
+ jne Lrem1
+ movl #Lrem3,sp@-
+ jbsr _panic
+Lrem1:
+ movl d1,_whichqs
+ movl a0@(P_FORW),a1
+ movl a0@(P_BACK),a1@(P_BACK)
+ movl a0@(P_BACK),a1
+ movl a0@(P_FORW),a1@(P_FORW)
+ movl #_qs,a1
+ movl d0,d1
+ lslb #3,d1
+ addl d1,a1
+ cmpl a1@(P_FORW),a1
+ jeq Lrem2
+ movl _whichqs,d1
+ bset d0,d1
+ movl d1,_whichqs
+Lrem2:
+ clrl a0@(P_BACK)
+ rts
+
+Lrem3:
+ .asciz "remrq"
+Lsw0:
+ .asciz "cpu_switch"
+ .even
+
+ .globl _curpcb
+ .globl _masterpaddr | XXX compatibility (debuggers)
+ .data
+_masterpaddr: | XXX compatibility (debuggers)
+_curpcb:
+ .long 0
+pcbflag:
+ .byte 0 | copy of pcb_flags low byte
+ .align 2
+ .comm nullpcb,SIZEOF_PCB
+ .text
+
+/*
+ * At exit of a process, do a cpu_switch for the last time.
+ * The mapping of the pcb at p->p_addr has already been deleted,
+ * and the memory for the pcb+stack has been freed.
+ * The ipl is high enough to prevent the memory from being reallocated.
+ */
+ENTRY(switch_exit)
+ movl #nullpcb,_curpcb | save state into garbage pcb
+ lea tmpstk,sp | goto a tmp stack
+ jra _cpu_switch
+
+/*
+ * When no processes are on the runq, Swtch branches to idle
+ * to wait for something to come ready.
+ */
+ .globl Idle
+Lidle:
+ stop #PSL_LOWIPL
+Idle:
+idle:
+ movw #PSL_HIGHIPL,sr
+ tstl _whichqs
+ jeq Lidle
+ movw #PSL_LOWIPL,sr
+ jra Lsw1
+
+Lbadsw:
+ movl #Lsw0,sp@-
+ jbsr _panic
+ /*NOTREACHED*/
+
+/*
+ * Cpu_switch()
+ *
+ * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the
+ * entire ATC. The effort involved in selective flushing may not be
+ * worth it, maybe we should just flush the whole thing?
+ *
+ * NOTE 2: With the new VM layout we now no longer know if an inactive
+ * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
+ * bit). For now, we just always flush the full ATC.
+ */
+ENTRY(cpu_switch)
+ movl _curpcb,a0 | current pcb
+ movw sr,a0@(PCB_PS) | save sr before changing ipl
+#ifdef notyet
+ movl _curproc,sp@- | remember last proc running
+#endif
+ clrl _curproc
+Lsw1:
+ /*
+ * Find the highest-priority queue that isn't empty,
+ * then take the first proc from that queue.
+ */
+ clrl d0
+ lea _whichqs,a0
+ movl a0@,d1
+Lswchk:
+ btst d0,d1
+ jne Lswfnd
+ addqb #1,d0
+ cmpb #32,d0
+ jne Lswchk
+ jra idle
+Lswfnd:
+ movw #PSL_HIGHIPL,sr | lock out interrupts
+ movl a0@,d1 | and check again...
+ bclr d0,d1
+ jeq Lsw1 | proc moved, rescan
+ movl d1,a0@ | update whichqs
+ moveq #1,d1 | double check for higher priority
+ lsll d0,d1 | process (which may have snuck in
+ subql #1,d1 | while we were finding this one)
+ andl a0@,d1
+ jeq Lswok | no one got in, continue
+ movl a0@,d1
+ bset d0,d1 | otherwise put this one back
+ movl d1,a0@
+ jra Lsw1 | and rescan
+Lswok:
+ movl d0,d1
+ lslb #3,d1 | convert queue number to index
+ addl #_qs,d1 | locate queue (q)
+ movl d1,a1
+ cmpl a1@(P_FORW),a1 | anyone on queue?
+ jeq Lbadsw | no, panic
+ movl a1@(P_FORW),a0 | p = q->p_forw
+ movl a0@(P_FORW),a1@(P_FORW) | q->p_forw = p->p_forw
+ movl a0@(P_FORW),a1 | q = p->p_forw
+ movl a0@(P_BACK),a1@(P_BACK) | q->p_back = p->p_back
+ cmpl a0@(P_FORW),d1 | anyone left on queue?
+ jeq Lsw2 | no, skip
+ movl _whichqs,d1
+ bset d0,d1 | yes, reset bit
+ movl d1,_whichqs
+Lsw2:
+ movl a0,_curproc
+ clrl _want_resched
+#ifdef notyet
+ movl sp@+,a1
+ cmpl a0,a1 | switching to same proc?
+ jeq Lswdone | yes, skip save and restore
+#endif
+
+ /*
+ * Save state of previous process in its pcb.
+ */
+ movl _curpcb,a1
+ moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers
+ movl usp,a2 | grab USP (a2 has been saved)
+ movl a2,a1@(PCB_USP) | and save it
+ movl _CMAP2,a1@(PCB_CMAP2) | save temporary map PTE
+#ifdef FPCOPROC
+ lea a1@(PCB_FPCTX),a2 | pointer to FP save area
+ fsave a2@ | save FP state
+ tstb a2@ | null state frame?
+ jeq Lswnofpsave | yes, all done
+ fmovem fp0-fp7,a2@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a2@(312) | save FP control registers
+Lswnofpsave:
+#endif
+
+#ifdef DIAGNOSTIC
+ tstl a0@(P_WCHAN)
+ jne Lbadsw
+ cmpb #SRUN,a0@(P_STAT)
+ jne Lbadsw
+#endif
+ clrl a0@(P_BACK) | clear back link
+ movl a0@(P_ADDR),a1 | get p_addr
+ movl a1,_curpcb
+ movb a1@(PCB_FLAGS+1),pcbflag | copy of pcb_flags low byte
+
+ /* see if pmap_activate needs to be called; should remove this */
+ movl a0@(P_VMSPACE),a0 | vmspace = p->p_vmspace
+#ifdef DIAGNOSTIC
+ tstl a0 | map == VM_MAP_NULL?
+ jeq Lbadsw | panic
+#endif
+ lea a0@(VM_PMAP),a0 | pmap = &vmspace.vm_pmap
+ tstl a0@(PM_STCHG) | pmap->st_changed?
+ jeq Lswnochg | no, skip
+ pea a1@ | push pcb (at p_addr)
+ pea a0@ | push pmap
+ jbsr _pmap_activate | pmap_activate(pmap, pcb)
+ addql #8,sp
+ movl _curpcb,a1 | restore p_addr
+Lswnochg:
+ movl #PGSHIFT,d1
+ movl a1,d0
+ lsrl d1,d0 | convert p_addr to page number
+ lsll #2,d0 | and now to Systab offset
+ addl _Sysmap,d0 | add Systab base to get PTE addr
+#ifdef notdef
+ movw #PSL_HIGHIPL,sr | go crit while changing PTEs
+#endif
+ lea tmpstk,sp | now goto a tmp stack for NMI
+ movl d0,a0 | address of new context
+ movl _Umap,a2 | address of PTEs for kstack
+ moveq #UPAGES-1,d0 | sizeof kstack
+Lres1:
+ movl a0@+,d1 | get PTE
+ andl #~PG_PROT,d1 | mask out old protection
+ orl #PG_RW+PG_V,d1 | ensure valid and writable
+ movl d1,a2@+ | load it up
+ dbf d0,Lres1 | til done
+ tstl _cpu040
+ jne Lres2
+ movl #CACHE_CLR,d0
+ movc d0,cacr | invalidate cache(s)
+ pflusha | flush entire TLB
+ jra Lres3
+Lres2:
+ .word 0xf518 | pflusha (68040)
+ movl #CACHE40_ON,d0
+ movc d0,cacr | invalidate cache(s)
+Lres3:
+ movl a1@(PCB_USTP),d0 | get USTP
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to addr
+ tstl _cpu040
+ jne Lres4
+ lea _protorp,a0 | CRP prototype
+ movl d0,a0@(4) | stash USTP
+ pmove a0@,crp | load new user root pointer
+ jra Lres5
+Lres4:
+ .word 0x4e7b,0x0806 | movc d0,URP
+Lres5:
+ movl a1@(PCB_CMAP2),_CMAP2 | reload tmp map
+ moveml a1@(PCB_REGS),#0xFCFC | and registers
+ movl a1@(PCB_USP),a0
+ movl a0,usp | and USP
+#ifdef FPCOPROC
+ lea a1@(PCB_FPCTX),a0 | pointer to FP save area
+ tstb a0@ | null state frame?
+ jeq Lresfprest | yes, easy
+ fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers
+ fmovem a0@(216),fp0-fp7 | restore FP general registers
+Lresfprest:
+ frestore a0@ | restore state
+#endif
+ movw a1@(PCB_PS),sr | no, restore PS
+ moveq #1,d0 | return 1 (for alternate returns)
+ rts
+
+/*
+ * savectx(pcb, altreturn)
+ * Update pcb, saving current processor state and arranging
+ * for alternate return ala longjmp in cpu_switch() if altreturn is true.
+ */
+ENTRY(savectx)
+ movl sp@(4),a1
+ movw sr,a1@(PCB_PS)
+ movl usp,a0 | grab USP
+ movl a0,a1@(PCB_USP) | and save it
+ moveml #0xFCFC,a1@(PCB_REGS) | save non-scratch registers
+ movl _CMAP2,a1@(PCB_CMAP2) | save temporary map PTE
+#ifdef FPCOPROC
+ lea a1@(PCB_FPCTX),a0 | pointer to FP save area
+ fsave a0@ | save FP state
+ tstb a0@ | null state frame?
+ jeq Lsvnofpsave | yes, all done
+ fmovem fp0-fp7,a0@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers
+Lsvnofpsave:
+#endif
+ tstl sp@(8) | altreturn?
+ jeq Lsavedone
+ movl sp,d0 | relocate current sp relative to a1
+ subl #_kstack,d0 | (sp is relative to kstack):
+ addl d0,a1 | a1 += sp - kstack;
+ movl sp@,a1@ | write return pc at (relocated) sp@
+Lsavedone:
+ moveq #0,d0 | return 0
+ rts
+
+/*
+ * Copy 1 relocation unit (NBPG bytes)
+ * from user virtual address to physical address
+ */
+ENTRY(copyseg)
+ movl _curpcb,a1 | current pcb
+ movl #Lcpydone,a1@(PCB_ONFAULT) | where to return to on a fault
+ movl sp@(8),d0 | destination page number
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to address
+ orl #PG_CI+PG_RW+PG_V,d0 | make sure valid and writable
+ movl _CMAP2,a0
+ movl _CADDR2,sp@- | destination kernel VA
+ movl d0,a0@ | load in page table
+ jbsr _TBIS | invalidate any old mapping
+ addql #4,sp
+ movl _CADDR2,a1 | destination addr
+ movl sp@(4),a0 | source addr
+ movl #NBPG/4-1,d0 | count
+Lcpyloop:
+ movsl a0@+,d1 | read longword
+ movl d1,a1@+ | write longword
+ dbf d0,Lcpyloop | continue until done
+Lcpydone:
+ movl _curpcb,a1 | current pcb
+ clrl a1@(PCB_ONFAULT) | clear error catch
+ rts
+
+/*
+ * Copy 1 relocation unit (NBPG bytes)
+ * from physical address to physical address
+ */
+ENTRY(physcopyseg)
+ movl sp@(4),d0 | source page number
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to address
+ orl #PG_CI+PG_RW+PG_V,d0 | make sure valid and writable
+ movl _CMAP1,a0
+ movl d0,a0@ | load in page table
+ movl _CADDR1,sp@- | destination kernel VA
+ jbsr _TBIS | invalidate any old mapping
+ addql #4,sp
+
+ movl sp@(8),d0 | destination page number
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to address
+ orl #PG_CI+PG_RW+PG_V,d0 | make sure valid and writable
+ movl _CMAP2,a0
+ movl d0,a0@ | load in page table
+ movl _CADDR2,sp@- | destination kernel VA
+ jbsr _TBIS | invalidate any old mapping
+ addql #4,sp
+
+ movl _CADDR1,a0 | source addr
+ movl _CADDR2,a1 | destination addr
+ movl #NBPG/4-1,d0 | count
+Lpcpy:
+ movl a0@+,a1@+ | copy longword
+ dbf d0,Lpcpy | continue until done
+ rts
+
+/*
+ * zero out physical memory
+ * specified in relocation units (NBPG bytes)
+ */
+ENTRY(clearseg)
+ movl sp@(4),d0 | destination page number
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to address
+ orl #PG_CI+PG_RW+PG_V,d0 | make sure valid and writable
+ movl _CMAP1,a0
+ movl _CADDR1,sp@- | destination kernel VA
+ movl d0,a0@ | load in page map
+ jbsr _TBIS | invalidate any old mapping
+ addql #4,sp
+ movl _CADDR1,a1 | destination addr
+ movl #NBPG/4-1,d0 | count
+ /* simple clear loop is fastest on 68020 */
+Lclrloop:
+ clrl a1@+ | clear a longword
+ dbf d0,Lclrloop | continue til done
+ rts
+
+/*
+ * Invalidate entire TLB.
+ */
+ENTRY(TBIA)
+__TBIA:
+ tstl _cpu040
+ jne Ltbia040
+ pflusha | flush entire TLB
+ tstl _mmutype
+ jpl Lmc68851a | 68851 implies no d-cache
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+Lmc68851a:
+ rts
+Ltbia040:
+ .word 0xf518 | pflusha
+ rts
+
+/*
+ * Invalidate any TLB entry for given VA (TB Invalidate Single)
+ */
+ENTRY(TBIS)
+#ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush entire TLB
+#endif
+ movl sp@(4),a0 | get addr to flush
+ tstl _cpu040
+ jne Ltbis040
+ tstl _mmutype
+ jpl Lmc68851b | is 68851?
+ pflush #0,#0,a0@ | flush address from both sides
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip data cache
+ rts
+Lmc68851b:
+ pflushs #0,#0,a0@ | flush address from both sides
+ rts
+Ltbis040:
+ moveq #FC_SUPERD,d0 | select supervisor
+ movc d0,dfc
+ .word 0xf508 | pflush a0@
+ moveq #FC_USERD,d0 | select user
+ movc d0,dfc
+ .word 0xf508 | pflush a0@
+ rts
+
+/*
+ * Invalidate supervisor side of TLB
+ */
+ENTRY(TBIAS)
+#ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush everything
+#endif
+ tstl _cpu040
+ jne Ltbias040
+ tstl _mmutype
+ jpl Lmc68851c | 68851?
+ pflush #4,#4 | flush supervisor TLB entries
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts
+Lmc68851c:
+ pflushs #4,#4 | flush supervisor TLB entries
+ rts
+Ltbias040:
+/* 68040 can't specify supervisor/user on pflusha, so we flush all */
+ .word 0xf518 | pflusha
+ rts
+
+/*
+ * Invalidate user side of TLB
+ */
+ENTRY(TBIAU)
+#ifdef DEBUG
+ tstl fulltflush | being conservative?
+ jne __TBIA | yes, flush everything
+#endif
+ tstl _cpu040
+ jne Ltbiau040
+ tstl _mmutype
+ jpl Lmc68851d | 68851?
+ pflush #0,#4 | flush user TLB entries
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts
+Lmc68851d:
+ pflushs #0,#4 | flush user TLB entries
+ rts
+Ltbiau040:
+ /* 68040 can't specify supervisor/user on pflusha, so we flush all */
+ .word 0xf518 | pflusha
+ rts
+
+/*
+ * Invalidate instruction cache
+ */
+ENTRY(ICIA)
+ENTRY(ICPA)
+#if defined(M68030) || defined(M68020)
+#if defined(M68040)
+ tstl _cpu040
+ jne Licia040
+#endif
+ movl #IC_CLEAR,d0
+ movc d0,cacr | invalidate i-cache
+ rts
+Licia040:
+#endif
+#if defined(M68040)
+ .word 0xf498 | cinva ic
+ rts
+#endif
+
+/*
+ * Invalidate data cache.
+ * NOTE: we do not flush 68030 on-chip cache as there are no aliasing
+ * problems with DC_WA. The only cases we have to worry about are context
+ * switch and TLB changes, both of which are handled "in-line" in resume
+ * and TBI*.
+ */
+ENTRY(DCIA)
+__DCIA:
+ tstl _cpu040
+ jeq Ldciax
+ .word 0xf478 | cpusha dc
+Ldciax:
+ rts
+
+ENTRY(DCIS)
+__DCIS:
+ tstl _cpu040
+ jeq Ldcisx
+ .word 0xf478 | cpusha dc
+ nop
+Ldcisx:
+ rts
+
+ENTRY(DCIU)
+__DCIU:
+ tstl _cpu040
+ jeq Ldciux
+ .word 0xf478 | cpusha dc
+Ldciux:
+ rts
+
+/* Invalid single cache line */
+ENTRY(DCIAS)
+__DCIAS:
+ tstl _cpu040
+ jeq Ldciasx
+ movl sp@(4),a0
+ .word 0xf468 | cpushl dc,a0@
+Ldciasx:
+ rts
+#ifdef M68040
+ENTRY(ICPL) /* invalidate instruction physical cache line */
+ movl sp@(4),a0 | address
+ .word 0xf488 | cinvl ic,a0@
+ rts
+ENTRY(ICPP) /* invalidate instruction physical cache page */
+ movl sp@(4),a0 | address
+ .word 0xf490 | cinvp ic,a0@
+ rts
+ENTRY(DCPL) /* invalidate data physical cache line */
+ movl sp@(4),a0 | address
+ .word 0xf448 | cinvl dc,a0@
+ rts
+ENTRY(DCPP) /* invalidate data physical cache page */
+ movl sp@(4),a0 | address
+ .word 0xf450 | cinvp dc,a0@
+ rts
+ENTRY(DCPA) /* invalidate data physical all */
+ .word 0xf458 | cinva dc
+ rts
+ENTRY(DCFL) /* data cache flush line */
+ movl sp@(4),a0 | address
+ .word 0xf468 | cpushl dc,a0@
+ rts
+ENTRY(DCFP) /* data cache flush page */
+ movl sp@(4),a0 | address
+ .word 0xf470 | cpushp dc,a0@
+ rts
+#endif /* M68040 */
+
+ENTRY(PCIA)
+#if defined(M68030) || defined(M68030)
+#if defined(M68040)
+ tstl _cpu040
+ jne Lpcia040
+#endif
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts
+#endif
+#if defined(M68040)
+ENTRY(DCFA)
+Lpcia040:
+ .word 0xf478 | cpusha dc
+ rts
+#endif
+
+ENTRY(ecacheon)
+ rts
+
+ENTRY(ecacheoff)
+ rts
+
+/*
+ * Get callers current SP value.
+ * Note that simply taking the address of a local variable in a C function
+ * doesn't work because callee saved registers may be outside the stack frame
+ * defined by A6 (e.g. GCC generated code).
+ */
+ .globl _getsp
+_getsp:
+ movl sp,d0 | get current SP
+ addql #4,d0 | compensate for return address
+ rts
+
+ .globl _getsfc, _getdfc
+_getsfc:
+ movc sfc,d0
+ rts
+_getdfc:
+ movc dfc,d0
+ rts
+
+/*
+ * Check out a virtual address to see if it's okay to write to.
+ *
+ * probeva(va, fc)
+ *
+ */
+ENTRY(probeva)
+ movl sp@(8),d0
+ movec d0,dfc
+ movl sp@(4),a0
+ .word 0xf548 | ptestw (a0)
+ moveq #FC_USERD,d0 | restore DFC to user space
+ movc d0,dfc
+ .word 0x4e7a,0x0805 | movec MMUSR,d0
+ rts
+
+/*
+ * Load a new user segment table pointer.
+ */
+ENTRY(loadustp)
+ movl sp@(4),d0 | new USTP
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to addr
+ tstl _cpu040
+ jne Lldustp040
+ lea _protorp,a0 | CRP prototype
+ movl d0,a0@(4) | stash USTP
+ pmove a0@,crp | load root pointer
+ movl #DC_CLEAR,d0
+ movc d0,cacr | invalidate on-chip d-cache
+ rts | since pmove flushes TLB
+Lldustp040:
+ .word 0x4e7b,0x0806 | movec d0,URP
+ rts
+
+/*
+ * Flush any hardware context associated with given USTP.
+ * Only does something for HP330 where we must flush RPT
+ * and ATC entries in PMMU.
+ */
+ENTRY(flushustp)
+ tstl _cpu040
+ jne Lnot68851
+ tstl _mmutype | 68851 PMMU?
+ jle Lnot68851 | no, nothing to do
+ movl sp@(4),d0 | get USTP to flush
+ moveq #PGSHIFT,d1
+ lsll d1,d0 | convert to address
+ movl d0,_protorp+4 | stash USTP
+ pflushr _protorp | flush RPT/TLB entries
+Lnot68851:
+ rts
+
+ENTRY(ploadw)
+ movl sp@(4),a0 | address to load
+ tstl _cpu040
+ jne Lploadw040
+ ploadw #1,a0@ | pre-load translation
+Lploadw040: | should 68040 do a ptest?
+ rts
+
+/*
+ * Set processor priority level calls. Most are implemented with
+ * inline asm expansions. However, spl0 requires special handling
+ * as we need to check for our emulated software interrupts.
+ */
+
+ENTRY(spl0)
+ moveq #0,d0
+ movw sr,d0 | get old SR for return
+ movw #PSL_LOWIPL,sr | restore new SR
+ tstb _ssir | software interrupt pending?
+ jeq Lspldone | no, all done
+ subql #4,sp | make room for RTE frame
+ movl sp@(4),sp@(2) | position return address
+ clrw sp@(6) | set frame type 0
+ movw #PSL_LOWIPL,sp@ | and new SR
+ jra Lgotsir | go handle it
+Lspldone:
+ rts
+
+ENTRY(_insque)
+ movw sr,d0
+ movw #PSL_HIGHIPL,sr | atomic
+ movl sp@(8),a0 | where to insert (after)
+ movl sp@(4),a1 | element to insert (e)
+ movl a0@,a1@ | e->next = after->next
+ movl a0,a1@(4) | e->prev = after
+ movl a1,a0@ | after->next = e
+ movl a1@,a0
+ movl a1,a0@(4) | e->next->prev = e
+ movw d0,sr
+ rts
+
+ENTRY(_remque)
+ movw sr,d0
+ movw #PSL_HIGHIPL,sr | atomic
+ movl sp@(4),a0 | element to remove (e)
+ movl a0@,a1
+ movl a0@(4),a0
+ movl a0,a1@(4) | e->next->prev = e->prev
+ movl a1,a0@ | e->prev->next = e->next
+ movw d0,sr
+ rts
+
+/*
+ * bzero(addr, count)
+ */
+ALTENTRY(blkclr, _bzero)
+ENTRY(bzero)
+ movl sp@(4),a0 | address
+ movl sp@(8),d0 | count
+ jeq Lbzdone | if zero, nothing to do
+ movl a0,d1
+ btst #0,d1 | address odd?
+ jeq Lbzeven | no, can copy words
+ clrb a0@+ | yes, zero byte to get to even boundary
+ subql #1,d0 | decrement count
+ jeq Lbzdone | none left, all done
+Lbzeven:
+ movl d0,d1
+ andl #31,d0
+ lsrl #5,d1 | convert count to 8*longword count
+ jeq Lbzbyte | no such blocks, zero byte at a time
+Lbzloop:
+ clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+;
+ clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+;
+ subql #1,d1 | one more block zeroed
+ jne Lbzloop | more to go, do it
+ tstl d0 | partial block left?
+ jeq Lbzdone | no, all done
+Lbzbyte:
+ clrb a0@+
+ subql #1,d0 | one more byte cleared
+ jne Lbzbyte | more to go, do it
+Lbzdone:
+ rts
+
+/*
+ * strlen(str)
+ */
+ENTRY(strlen)
+ moveq #-1,d0
+ movl sp@(4),a0 | string
+Lslloop:
+ addql #1,d0 | increment count
+ tstb a0@+ | null?
+ jne Lslloop | no, keep going
+ rts
+
+/*
+ * bcmp(s1, s2, len)
+ *
+ * WARNING! This guy only works with counts up to 64K
+ */
+ENTRY(bcmp)
+ movl sp@(4),a0 | string 1
+ movl sp@(8),a1 | string 2
+ moveq #0,d0
+ movw sp@(14),d0 | length
+ jeq Lcmpdone | if zero, nothing to do
+ subqw #1,d0 | set up for DBcc loop
+Lcmploop:
+ cmpmb a0@+,a1@+ | equal?
+ dbne d0,Lcmploop | yes, keep going
+ addqw #1,d0 | +1 gives zero on match
+Lcmpdone:
+ rts
+
+/*
+ * {ov}bcopy(from, to, len)
+ *
+ * Works for counts up to 128K.
+ */
+ALTENTRY(ovbcopy, _bcopy)
+ENTRY(bcopy)
+ movl sp@(12),d0 | get count
+ jeq Lcpyexit | if zero, return
+ movl sp@(4),a0 | src address
+ movl sp@(8),a1 | dest address
+ cmpl a1,a0 | src before dest?
+ jlt Lcpyback | yes, copy backwards (avoids overlap)
+ movl a0,d1
+ btst #0,d1 | src address odd?
+ jeq Lcfeven | no, go check dest
+ movb a0@+,a1@+ | yes, copy a byte
+ subql #1,d0 | update count
+ jeq Lcpyexit | exit if done
+Lcfeven:
+ movl a1,d1
+ btst #0,d1 | dest address odd?
+ jne Lcfbyte | yes, must copy by bytes
+ movl d0,d1 | no, get count
+ lsrl #2,d1 | convert to longwords
+ jeq Lcfbyte | no longwords, copy bytes
+ subql #1,d1 | set up for dbf
+Lcflloop:
+ movl a0@+,a1@+ | copy longwords
+ dbf d1,Lcflloop | til done
+ andl #3,d0 | get remaining count
+ jeq Lcpyexit | done if none
+Lcfbyte:
+ subql #1,d0 | set up for dbf
+Lcfbloop:
+ movb a0@+,a1@+ | copy bytes
+ dbf d0,Lcfbloop | til done
+Lcpyexit:
+ rts
+Lcpyback:
+ addl d0,a0 | add count to src
+ addl d0,a1 | add count to dest
+ movl a0,d1
+ btst #0,d1 | src address odd?
+ jeq Lcbeven | no, go check dest
+ movb a0@-,a1@- | yes, copy a byte
+ subql #1,d0 | update count
+ jeq Lcpyexit | exit if done
+Lcbeven:
+ movl a1,d1
+ btst #0,d1 | dest address odd?
+ jne Lcbbyte | yes, must copy by bytes
+ movl d0,d1 | no, get count
+ lsrl #2,d1 | convert to longwords
+ jeq Lcbbyte | no longwords, copy bytes
+ subql #1,d1 | set up for dbf
+Lcblloop:
+ movl a0@-,a1@- | copy longwords
+ dbf d1,Lcblloop | til done
+ andl #3,d0 | get remaining count
+ jeq Lcpyexit | done if none
+Lcbbyte:
+ subql #1,d0 | set up for dbf
+Lcbbloop:
+ movb a0@-,a1@- | copy bytes
+ dbf d0,Lcbbloop | til done
+ rts
+
+/*
+ * Emulate fancy VAX string operations:
+ * scanc(count, startc, table, mask)
+ * skpc(mask, count, startc)
+ * locc(mask, count, startc)
+ */
+ENTRY(scanc)
+ movl sp@(4),d0 | get length
+ jeq Lscdone | nothing to do, return
+ movl sp@(8),a0 | start of scan
+ movl sp@(12),a1 | table to compare with
+ movb sp@(19),d1 | and mask to use
+ movw d2,sp@- | need a scratch register
+ clrw d2 | clear it out
+ subqw #1,d0 | adjust for dbra
+Lscloop:
+ movb a0@+,d2 | get character
+ movb a1@(0,d2:w),d2 | get table entry
+ andb d1,d2 | mask it
+ dbne d0,Lscloop | keep going til no more or non-zero
+ addqw #1,d0 | overshot by one
+ movw sp@+,d2 | restore scratch
+Lscdone:
+ rts
+
+ENTRY(skpc)
+ movl sp@(8),d0 | get length
+ jeq Lskdone | nothing to do, return
+ movb sp@(7),d1 | mask to use
+ movl sp@(12),a0 | where to start
+ subqw #1,d0 | adjust for dbcc
+Lskloop:
+ cmpb a0@+,d1 | compate with mask
+ dbne d0,Lskloop | keep going til no more or zero
+ addqw #1,d0 | overshot by one
+Lskdone:
+ rts
+
+ENTRY(locc)
+ movl sp@(8),d0 | get length
+ jeq Llcdone | nothing to do, return
+ movb sp@(7),d1 | mask to use
+ movl sp@(12),a0 | where to start
+ subqw #1,d0 | adjust for dbcc
+Llcloop:
+ cmpb a0@+,d1 | compate with mask
+ dbeq d0,Llcloop | keep going til no more or non-zero
+ addqw #1,d0 | overshot by one
+Llcdone:
+ rts
+
+/*
+ * Emulate VAX FFS (find first set) instruction.
+ */
+ENTRY(ffs)
+ moveq #-1,d0
+ movl sp@(4),d1
+ jeq Lffsdone
+Lffsloop:
+ addql #1,d0
+ btst d0,d1
+ jeq Lffsloop
+Lffsdone:
+ addql #1,d0
+ rts
+
+#ifdef FPCOPROC
+/*
+ * Save and restore 68881 state.
+ * Pretty awful looking since our assembler does not
+ * recognize FP mnemonics.
+ */
+ENTRY(m68881_save)
+ movl sp@(4),a0 | save area pointer
+ fsave a0@ | save state
+ tstb a0@ | null state frame?
+ jeq Lm68881sdone | yes, all done
+ fmovem fp0-fp7,a0@(216) | save FP general registers
+ fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registers
+Lm68881sdone:
+ rts
+
+ENTRY(m68881_restore)
+ movl sp@(4),a0 | save area pointer
+ tstb a0@ | null state frame?
+ jeq Lm68881rdone | yes, easy
+ fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers
+ fmovem a0@(216),fp0-fp7 | restore FP general registers
+Lm68881rdone:
+ frestore a0@ | restore state
+ rts
+#endif
+
+/*
+ * Handle the nitty-gritty of rebooting the machine.
+ *
+ */
+ .globl _doboot
+_doboot:
+ movl #CACHE_OFF,d0
+ movl _cpu040,d1 | load 68040 flag
+ jeq Ldoboot0
+ .word 0xf4f8 | cpusha bc - push and inval caches
+ nop
+ movl #CACHE40_OFF,d0
+Ldoboot0:
+ movc d0,cacr | disable on-chip cache(s)
+
+ movw #0x2700,sr | cut off any interrupts
+
+ /*
+ * Clear first 2k of ST-memory. We start clearing at address 0x8
+ * because the lower 8 bytes are mapped to ROM.
+ * This makes sure that the machine will 'cold-boot'.
+ */
+ movl _page_zero,a0
+ addl #0x8,a0
+ movl #512,d0
+Ldb1:
+ clrl a0@+
+ dbra d0,Ldb1
+
+ lea Ldoreboot,a1 | a1 = start of copy range
+ lea Ldorebootend,a2 | a2 = end of copy range
+ movl _page_zero,a0 | a0 = virtual base for page zero
+ addl a1,a0 | + offset of Ldoreboot
+Ldb2: | Do the copy
+ movel a1@+,a0@+
+ cmpl a1,a2
+ jle Ldb2
+
+ /*
+ * Ok, turn off MMU..
+ */
+Ldoreboot:
+ tstl d1 | We saved cpu040 here
+ jne Lmmuoff040 | Go turn off 68040 MMU
+ lea zero,a0
+ pmove a0@,tc | Turn off MMU
+ lea nullrp,a0
+ pmove a0@,crp | Invalidate Cpu root pointer
+ pmove a0@,srp | and the Supervisor root pointer
+ jra Ldoboot1 | Ok, continue with actual reboot
+Lmmuoff040:
+ movl #0,d0
+ .word 0x4e7b,0x0003 | movc d0,TC
+ .word 0x4e7b,0x0806 | movc d0,URP
+ .word 0x4e7b,0x0807 | movc d0,SRP
+Ldoboot1:
+ movl 0x4,a0 | fetch reset-vector
+ jmp a0@ | jump through it
+ /* NOT REACHED */
+
+/* A do-nothing MMU root pointer (includes the following long as well) */
+
+nullrp: .long 0x7fff0001
+zero: .long 0
+Ldorebootend:
+
+ .data
+ .space NBPG
+tmpstk:
+ .globl _mmutype,_protorp
+_protorp:
+ .long 0x80000002,0 | prototype root pointer
+ .globl _cold
+_cold:
+ .long 1 | cold start flag
+ .globl _proc0paddr
+_proc0paddr:
+ .long 0 | KVA of proc0 u-area
+ .globl _clk_div
+_clk_div:
+ .word 4 | Clock divisor
+#ifdef DEBUG
+ .globl fulltflush, fullcflush
+fulltflush:
+ .long 0
+fullcflush:
+ .long 0
+ .globl timebomb
+timebomb:
+ .long 0
+#endif
+/* interrupt counters */
+ .globl _intrcnt,_eintrcnt,_intrnames,_eintrnames
+_intrnames:
+ .asciz "spur"
+ .asciz "clock"
+ .asciz "kbd/mouse"
+ .asciz "fdc/acsi"
+ .asciz "soft"
+ .asciz "5380-SCSI"
+ .asciz "5380-DMA"
+ .asciz "nmi"
+ .asciz "8530-SCC"
+_eintrnames:
+ .even
+_intrcnt:
+ .long 0,0,0,0,0,0,0,0,0
+_eintrcnt:
diff --git a/sys/arch/atari/atari/machdep.c b/sys/arch/atari/atari/machdep.c
new file mode 100644
index 00000000000..66b33410680
--- /dev/null
+++ b/sys/arch/atari/atari/machdep.c
@@ -0,0 +1,1470 @@
+/* $NetBSD: machdep.c,v 1.1.1.1 1995/03/26 07:12:19 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * from: Utah $Hdr: machdep.c 1.63 91/04/24$
+ *
+ * @(#)machdep.c 7.16 (Berkeley) 6/3/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/kernel.h>
+#include <sys/map.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/clist.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/user.h>
+#include <sys/exec.h> /* for PS_STRINGS */
+#include <sys/vnode.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+#ifdef SYSVSHM
+#include <sys/shm.h>
+#endif
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+#ifdef SYSVSEM
+#include <sys/sem.h>
+#endif
+#include <net/netisr.h>
+#define MAXMEM 64*1024*CLSIZE /* XXX - from cmap.h */
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/psl.h>
+#include <machine/pte.h>
+#include <machine/iomap.h>
+#include <machine/scu.h>
+#include <dev/cons.h>
+
+/* vm_map_t buffer_map; */
+extern vm_offset_t avail_end;
+
+/*
+ * Declare these as initialized data so we can patch them.
+ */
+#ifdef BUFPAGES
+int bufpages = BUFPAGES;
+#else
+int bufpages = 0;
+#endif
+int msgbufmapped; /* set when safe to use msgbuf */
+int physmem = MAXMEM; /* max supported memory, changes to actual */
+/*
+ * safepri is a safe priority for sleep to set for a spin-wait
+ * during autoconfiguration or after a panic.
+ */
+int safepri = PSL_LOWIPL;
+extern int freebufspace;
+extern u_int lowram;
+
+/* used in init_main.c */
+char *cpu_type = "m68k";
+/* the following is used externally (sysctl_hw) */
+char machine[] = "atari";
+
+#ifdef COMPAT_SUNOS
+void sunos_sendsig ();
+#endif
+
+ /*
+ * Console initialization: called early on from main,
+ * before vm init or startup. Do enough configuration
+ * to choose and initialize a console.
+ */
+void
+consinit()
+{
+
+ /*
+ * Set cpuspeed immediately since cninit() called routines
+ * might use delay.[
+ */
+
+ cpuspeed = MHZ_33; /* XXX */
+
+ /*
+ * Initialize the console before we print anything out.
+ */
+ cninit();
+
+#if defined (DDB)
+ ddb_init();
+ if(boothowto & RB_KDB)
+ Debugger();
+#endif
+}
+
+/*
+ * cpu_startup: allocate memory for variable-sized tables,
+ * initialize cpu, and do autoconfiguration.
+ */
+void
+cpu_startup()
+{
+ extern long Usrptsize;
+ extern struct map *useriomap;
+ register unsigned i;
+ register caddr_t v, firstaddr;
+ int base, residual;
+
+#ifdef DEBUG
+ extern int pmapdebug;
+ int opmapdebug = pmapdebug;
+#endif
+ vm_offset_t minaddr, maxaddr;
+ vm_size_t size;
+
+ /*
+ * Initialize error message buffer (at end of core).
+ */
+#ifdef DEBUG
+ pmapdebug = 0;
+#endif
+ /* avail_end was pre-decremented in pmap_bootstrap to compensate */
+ for(i = 0; i < btoc(sizeof (struct msgbuf)); i++)
+ pmap_enter(kernel_pmap, (vm_offset_t)msgbufp,
+ avail_end + i * NBPG, VM_PROT_ALL, TRUE);
+ msgbufmapped = 1;
+
+ /*
+ * Good {morning,afternoon,evening,night}.
+ */
+ printf(version);
+ identifycpu();
+ printf("real mem = %d (%d pages)\n",ctob(physmem),ctob(physmem)/NBPG);
+
+ /*
+ * Allocate space for system data structures.
+ * The first available real memory address is in "firstaddr".
+ * The first available kernel virtual address is in "v".
+ * As pages of kernel virtual memory are allocated, "v" is incremented.
+ * As pages of memory are allocated and cleared,
+ * "firstaddr" is incremented.
+ * An index into the kernel page table corresponding to the
+ * virtual memory address maintained in "v" is kept in "mapaddr".
+ */
+ /*
+ * Make two passes. The first pass calculates how much memory is
+ * needed and allocates it. The second pass assigns virtual
+ * addresses to the various data structures.
+ */
+ firstaddr = 0;
+again:
+ v = (caddr_t)firstaddr;
+
+#define valloc(name, type, num) \
+ (name) = (type *)v; v = (caddr_t)((name)+(num))
+#define valloclim(name, type, num, lim) \
+ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
+/* valloc(cfree, struct cblock, nclist); */
+ 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 allocate
+ * the BSD standard of use 10% of memory for the first 2 Meg,
+ * 5% of remaining. Insure a minimum of 16 buffers.
+ * We allocate 3/4 as many swap buffer headers as file i/o buffers.
+ */
+ if (bufpages == 0)
+ if (physmem < btoc(2 * 1024 * 1024))
+ bufpages = physmem / (10 * CLSIZE);
+ else
+ bufpages = (btoc(2 * 1024 * 1024) + physmem) /
+ (20 * CLSIZE);
+
+ if (nbuf == 0) {
+ nbuf = bufpages;
+ if (nbuf < 16)
+ nbuf = 16;
+ }
+
+ if (nswbuf == 0) {
+ nswbuf = (nbuf * 3 / 4) &~ 1; /* force even */
+ if (nswbuf > 256)
+ nswbuf = 256; /* sanity */
+ }
+ valloc(swbuf, struct buf, nswbuf);
+ valloc(buf, struct buf, nbuf);
+ /*
+ * End of first pass, size has been calculated so allocate memory
+ */
+ if (firstaddr == 0) {
+ size = (vm_size_t)(v - firstaddr);
+ firstaddr = (caddr_t) kmem_alloc(kernel_map, round_page(size));
+ if (firstaddr == 0)
+ panic("startup: no room for tables");
+ goto again;
+ }
+ /*
+ * End of second pass, addresses have been assigned
+ */
+ if ((vm_size_t)(v - firstaddr) != size)
+ panic("startup: table size inconsistency");
+
+ /*
+ * Now allocate buffers proper. They are different than the above
+ * in that they usually occupy more virtual memory than physical.
+ */
+ size = MAXBSIZE * nbuf;
+ buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
+ &maxaddr, size, TRUE);
+ minaddr = (vm_offset_t)buffers;
+ if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
+ &minaddr, size, 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 (i = 0; i < nbuf; i++) {
+ vm_size_t curbufsize;
+ vm_offset_t curbuf;
+
+ /*
+ * First <residual> 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 + i * MAXBSIZE;
+ curbufsize = CLBYTES * (i < 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);
+
+ /*
+ * Initialize callouts
+ */
+ callfree = callout;
+ for (i = 1; i < ncallout; i++)
+ callout[i-1].c_next = &callout[i];
+
+#ifdef DEBUG
+ pmapdebug = opmapdebug;
+#endif
+ printf("avail mem = %d (%d pages)\n", ptoa(cnt.v_free_count),
+ ptoa(cnt.v_free_count)/NBPG);
+ printf("using %d buffers containing %d bytes of memory\n",
+ nbuf, bufpages * CLBYTES);
+
+ /*
+ * Set up CPU-specific registers, cache, etc.
+ */
+ initcpu();
+
+ /*
+ * Set up buffers, so they can be used to read disk labels.
+ */
+ bufinit();
+
+ /*
+ * Configure the system.
+ */
+ configure();
+}
+
+/*
+ * Set registers on exec.
+ * XXX Should clear registers except sp, pc,
+ * but would break init; should be fixed soon.
+ */
+void
+setregs(p, entry, stack, retval)
+ register struct proc *p;
+ u_long entry;
+ u_long stack;
+ register_t *retval;
+{
+ struct frame *frame = (struct frame *)p->p_md.md_regs;
+
+ frame->f_pc = entry & ~1;
+ frame->f_regs[SP] = stack;
+#ifdef FPCOPROC
+ /* restore a null state frame */
+ p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0;
+ m68881_restore(&p->p_addr->u_pcb.pcb_fpregs);
+#endif
+}
+
+/*
+ * Info for CTL_HW
+ */
+char cpu_model[120];
+extern char version[];
+
+identifycpu()
+{
+ /* there's alot of XXX in here... */
+ char *mach, *mmu, *fpu;
+
+ mach = "Atari TT";
+
+ fpu = NULL;
+ if (machineid & ATARI_68040) {
+ cpu_type = "m68040";
+ mmu = "/MMU";
+ fpu = "/FPU";
+ } else if (machineid & ATARI_68030) {
+ cpu_type = "m68030"; /* XXX */
+ mmu = "/MMU";
+ } else {
+ cpu_type = "m68020";
+ mmu = " m68851 MMU";
+ }
+ if (fpu == NULL) {
+ if (machineid & ATARI_68882)
+ fpu = " m68882 FPU";
+ else if (machineid & ATARI_68881)
+ fpu = " m68881 FPU";
+ else
+ fpu = " no FPU";
+ }
+ sprintf(cpu_model, "%s (%s CPU%s%s)", mach, cpu_type, mmu, fpu);
+ printf("%s\n", cpu_model);
+}
+
+/*
+ * machine dependent system variables.
+ */
+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;
+{
+ dev_t consdev;
+
+ /* all sysctl names at this level are terminal */
+ if (namelen != 1)
+ return(ENOTDIR); /* overloaded */
+
+ switch (name[0]) {
+ case CPU_CONSDEV:
+ if (cn_tab != NULL)
+ consdev = cn_tab->cn_dev;
+ else
+ consdev = NODEV;
+ return(sysctl_rdstruct(oldp, oldlenp, newp, &consdev, sizeof(consdev)));
+ default:
+ return(EOPNOTSUPP);
+ }
+ /* NOTREACHED */
+}
+
+#define SS_RTEFRAME 1
+#define SS_FPSTATE 2
+#define SS_USERREGS 4
+
+struct sigstate {
+ int ss_flags; /* which of the following are valid */
+ struct frame ss_frame; /* original exception frame */
+ struct fpframe ss_fpstate; /* 68881/68882 state info */
+};
+
+/*
+ * WARNING: code in locore.s assumes the layout shown for sf_signum
+ * thru sf_handler so... don't screw with them!
+ */
+struct sigframe {
+ int sf_signum; /* signo for handler */
+ int sf_code; /* additional info for handler */
+ struct sigcontext *sf_scp; /* context ptr for handler */
+ sig_t sf_handler; /* handler addr for u_sigc */
+ struct sigstate sf_state; /* state of the hardware */
+ struct sigcontext sf_sc; /* actual context */
+};
+
+#ifdef COMPAT_SUNOS
+/* sigh.. I guess it's too late to change now, but "our" sigcontext
+ is plain vax, not very 68000 (ap, for example..) */
+struct sunos_sigcontext {
+ int sc_onstack; /* sigstack state to restore */
+ int sc_mask; /* signal mask to restore */
+ int sc_sp; /* sp to restore */
+ int sc_pc; /* pc to restore */
+ int sc_ps; /* psl to restore */
+};
+struct sunos_sigframe {
+ int ssf_signum; /* signo for handler */
+ int ssf_code; /* additional info for handler */
+ struct sunos_sigcontext *ssf_scp; /* context pointer for handler */
+ u_int ssf_addr; /* even more info for handler */
+ struct sunos_sigcontext ssf_sc; /* I don't know if that's what
+ comes here */
+};
+#endif
+
+#ifdef DEBUG
+int sigdebug = 0x0;
+int sigpid = 0;
+#define SDB_FOLLOW 0x01
+#define SDB_KSTACK 0x02
+#define SDB_FPSTATE 0x04
+#endif
+
+/*
+ * Send an interrupt to process.
+ */
+void
+sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig, mask;
+ u_long code;
+{
+ register struct proc *p = curproc;
+ register struct sigframe *fp, *kfp;
+ register struct frame *frame;
+ register struct sigacts *psp = p->p_sigacts;
+ register short ft;
+ int oonstack;
+ extern short exframesize[];
+ extern char sigcode[], esigcode[];
+
+
+/*printf("sendsig %d %d %x %x %x\n", p->p_pid, sig, mask, code, catcher);*/
+
+ frame = (struct frame *)p->p_md.md_regs;
+ ft = frame->f_format;
+ oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+
+#ifdef COMPAT_SUNOS
+ if (p->p_emul == EMUL_SUNOS) {
+ /*
+ * build the short SunOS frame instead
+ */
+ sunos_sendsig(catcher, sig, mask, code);
+ return;
+ }
+#endif
+ /*
+ * Allocate and validate space for the signal handler
+ * context. Note that if the stack is in P0 space, the
+ * call to grow() is a nop, and the useracc() check
+ * will fail if the process has not already allocated
+ * the space with a `brk'.
+ */
+ if ((psp->ps_flags & SAS_ALTSTACK) && oonstack == 0 &&
+ (psp->ps_sigonstack & sigmask(sig))) {
+ fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
+ psp->ps_sigstk.ss_size - sizeof(struct sigframe));
+ psp->ps_sigstk.ss_flags |= SA_ONSTACK;
+ } else
+ fp = (struct sigframe *)frame->f_regs[SP] - 1;
+ if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
+ (void)grow(p, (unsigned)fp);
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): sig %d ssp %x usp %x scp %x ft %d\n",
+ p->p_pid, sig, &oonstack, fp, &fp->sf_sc, ft);
+#endif
+ if (useracc((caddr_t)fp, sizeof(struct sigframe), B_WRITE) == 0) {
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): useracc failed on sig %d\n",
+ p->p_pid, sig);
+#endif
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+ SIGACTION(p, SIGILL) = SIG_DFL;
+ sig = sigmask(SIGILL);
+ p->p_sigignore &= ~sig;
+ p->p_sigcatch &= ~sig;
+ p->p_sigmask &= ~sig;
+ psignal(p, SIGILL);
+ return;
+ }
+ kfp = malloc(sizeof(struct sigframe), M_TEMP, M_WAITOK);
+ /*
+ * Build the argument list for the signal handler.
+ */
+ kfp->sf_signum = sig;
+ kfp->sf_code = code;
+ kfp->sf_scp = &fp->sf_sc;
+ kfp->sf_handler = catcher;
+ /*
+ * Save necessary hardware state. Currently this includes:
+ * - general registers
+ * - original exception frame (if not a "normal" frame)
+ * - FP coprocessor state
+ */
+ kfp->sf_state.ss_flags = SS_USERREGS;
+ bcopy((caddr_t)frame->f_regs,
+ (caddr_t)kfp->sf_state.ss_frame.f_regs, sizeof frame->f_regs);
+ if (ft >= FMT9) {
+#ifdef DEBUG
+ if (ft != FMT9 && ft != FMTA && ft != FMTB)
+ panic("sendsig: bogus frame type");
+#endif
+ kfp->sf_state.ss_flags |= SS_RTEFRAME;
+ kfp->sf_state.ss_frame.f_format = frame->f_format;
+ kfp->sf_state.ss_frame.f_vector = frame->f_vector;
+ bcopy((caddr_t)&frame->F_u,
+ (caddr_t)&kfp->sf_state.ss_frame.F_u, exframesize[ft]);
+ /*
+ * Leave an indicator that we need to clean up the kernel
+ * stack. We do this by setting the "pad word" above the
+ * hardware stack frame to the amount the stack must be
+ * adjusted by.
+ *
+ * N.B. we increment rather than just set f_stackadj in
+ * case we are called from syscall when processing a
+ * sigreturn. In that case, f_stackadj may be non-zero.
+ */
+ frame->f_stackadj += exframesize[ft];
+ frame->f_format = frame->f_vector = 0;
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sendsig(%d): copy out %d of frame %d\n",
+ p->p_pid, exframesize[ft], ft);
+#endif
+ }
+#ifdef FPCOPROC
+ kfp->sf_state.ss_flags |= SS_FPSTATE;
+ m68881_save(&kfp->sf_state.ss_fpstate);
+#ifdef DEBUG
+ if ((sigdebug & SDB_FPSTATE) && *(char *)&kfp->sf_state.ss_fpstate)
+ printf("sendsig(%d): copy out FP state (%x) to %x\n",
+ p->p_pid, *(u_int *)&kfp->sf_state.ss_fpstate,
+ &kfp->sf_state.ss_fpstate);
+#endif
+#endif
+ /*
+ * Build the signal context to be used by sigreturn.
+ */
+ kfp->sf_sc.sc_onstack = oonstack;
+ kfp->sf_sc.sc_mask = mask;
+ kfp->sf_sc.sc_sp = frame->f_regs[SP];
+ kfp->sf_sc.sc_fp = frame->f_regs[A6];
+ kfp->sf_sc.sc_ap = (int)&fp->sf_state;
+ kfp->sf_sc.sc_pc = frame->f_pc;
+ kfp->sf_sc.sc_ps = frame->f_sr;
+ (void) copyout((caddr_t)kfp, (caddr_t)fp, sizeof(struct sigframe));
+ frame->f_regs[SP] = (int)fp;
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sendsig(%d): sig %d scp %x fp %x sc_sp %x sc_ap %x\n",
+ p->p_pid, sig, kfp->sf_scp, fp,
+ kfp->sf_sc.sc_sp, kfp->sf_sc.sc_ap);
+#endif
+ /*
+ * Signal trampoline code is at base of user stack.
+ */
+ frame->f_pc = (int)(((char *)PS_STRINGS) - (esigcode - sigcode));
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sendsig(%d): sig %d returns\n",
+ p->p_pid, sig);
+#endif
+ free((caddr_t)kfp, M_TEMP);
+}
+
+#ifdef COMPAT_SUNOS
+/*
+ * much simpler sendsig() for SunOS processes, as SunOS does the whole
+ * context-saving in usermode. For now, no hardware information (ie.
+ * frames for buserror etc) is saved. This could be fatal, so I take
+ * SIG_DFL for "dangerous" signals.
+ */
+void
+sunos_sendsig(catcher, sig, mask, code)
+ sig_t catcher;
+ int sig, mask;
+ unsigned code;
+{
+ register struct proc *p = curproc;
+ register struct sunos_sigframe *fp;
+ struct sunos_sigframe kfp;
+ register struct frame *frame;
+ register struct sigacts *psp = p->p_sigacts;
+ register short ft;
+ int oonstack, fsize;
+
+ frame = (struct frame *)p->p_md.md_regs;
+ ft = frame->f_format;
+ oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+ /*
+ * Allocate and validate space for the signal handler
+ * context. Note that if the stack is in P0 space, the
+ * call to grow() is a nop, and the useracc() check
+ * will fail if the process has not already allocated
+ * the space with a `brk'.
+ */
+ fsize = sizeof(struct sunos_sigframe);
+ if ((psp->ps_flags & SAS_ALTSTACK) && oonstack == 0 &&
+ (psp->ps_sigonstack & sigmask(sig))) {
+ fp = (struct sunos_sigframe *)(psp->ps_sigstk.ss_base +
+ psp->ps_sigstk.ss_size - sizeof(struct sunos_sigframe));
+ psp->ps_sigstk.ss_flags |= SA_ONSTACK;
+ } else
+ fp = (struct sunos_sigframe *)frame->f_regs[SP] - 1;
+ if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
+ (void)grow(p, (unsigned)fp);
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sunos_sendsig(%d): sig %d ssp %x usp %x scp %x ft %d\n",
+ p->p_pid, sig, &oonstack, fp, &fp->ssf_sc, ft);
+#endif
+ if (useracc((caddr_t)fp, fsize, B_WRITE) == 0) {
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sunos_sendsig(%d): useracc failed on sig %d\n",
+ p->p_pid, sig);
+#endif
+ /*
+ * Process has trashed its stack; give it an illegal
+ * instruction to halt it in its tracks.
+ */
+ SIGACTION(p, SIGILL) = SIG_DFL;
+ sig = sigmask(SIGILL);
+ p->p_sigignore &= ~sig;
+ p->p_sigcatch &= ~sig;
+ p->p_sigmask &= ~sig;
+ psignal(p, SIGILL);
+ return;
+ }
+ /*
+ * Build the argument list for the signal handler.
+ */
+ kfp.ssf_signum = sig;
+ kfp.ssf_code = code;
+ kfp.ssf_scp = &fp->ssf_sc;
+ kfp.ssf_addr = ~0; /* means: not computable */
+
+ /*
+ * Build the signal context to be used by sigreturn.
+ */
+ kfp.ssf_sc.sc_onstack = oonstack;
+ kfp.ssf_sc.sc_mask = mask;
+ kfp.ssf_sc.sc_sp = frame->f_regs[SP];
+ kfp.ssf_sc.sc_pc = frame->f_pc;
+ kfp.ssf_sc.sc_ps = frame->f_sr;
+ (void) copyout(&kfp, fp, fsize);
+ frame->f_regs[SP] = (int)fp;
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sunos_sendsig(%d): sig %d scp %x sc_sp %x\n",
+ p->p_pid, sig, kfp.ssf_sc.sc_sp);
+#endif
+
+ /* have the user-level trampoline code sort out what registers it
+ has to preserve. */
+ frame->f_pc = (u_int) catcher;
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sunos_sendsig(%d): sig %d returns\n",
+ p->p_pid, sig);
+#endif
+}
+
+#endif /* COMPAT_SUNOS */
+
+
+/*
+ * 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
+ * psl to gain improper priviledges or to cause
+ * a machine fault.
+ */
+/* ARGSUSED */
+sigreturn(p, uap, retval)
+ struct proc *p;
+ struct sigreturn_args /* {
+ syscallarg(struct sigcontext *)sigcntxp;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sigcontext *scp, context;
+ struct frame *frame;
+ int rf, flags;
+ struct sigstate tstate;
+ extern short exframesize[];
+
+#ifdef COMPAT_SUNOS
+ if (p->p_emul == EMUL_SUNOS)
+ return(sunos_sigreturn(p, uap, retval));
+#endif
+
+ scp = SCARG(uap, sigcntxp);
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+#endif
+ if ((int)scp & 1)
+ return(EINVAL);
+ /*
+ * Test and fetch the context structure.
+ * We grab it all at once for speed.
+ */
+ if (useracc((caddr_t)scp, sizeof(*scp), B_WRITE) == 0 ||
+ copyin(scp, &context, sizeof(context)))
+ return(EINVAL);
+ scp = &context;
+ if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0)
+ return(EINVAL);
+ /*
+ * Restore the user supplied information
+ */
+ if (scp->sc_onstack & 1)
+ p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+ p->p_sigmask = scp->sc_mask &~ sigcantmask;
+ frame = (struct frame *) p->p_md.md_regs;
+ frame->f_regs[SP] = scp->sc_sp;
+ frame->f_regs[A6] = scp->sc_fp;
+ frame->f_pc = scp->sc_pc;
+ frame->f_sr = scp->sc_ps;
+ /*
+ * Grab pointer to hardware state information.
+ * If zero, the user is probably doing a longjmp.
+ */
+ if ((rf = scp->sc_ap) == 0)
+ return (EJUSTRETURN);
+ /*
+ * See if there is anything to do before we go to the
+ * expense of copying in close to 1/2K of data
+ */
+ flags = fuword((caddr_t)rf);
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sigreturn(%d): sc_ap %x flags %x\n",
+ p->p_pid, rf, flags);
+#endif
+ /*
+ * fuword failed (bogus sc_ap value).
+ */
+ if (flags == -1)
+ return (EINVAL);
+ if (flags == 0 || copyin((caddr_t)rf, (caddr_t)&tstate, sizeof tstate))
+ return (EJUSTRETURN);
+#ifdef DEBUG
+ if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+ printf("sigreturn(%d): ssp %x usp %x scp %x ft %d\n",
+ p->p_pid, &flags, scp->sc_sp, SCARG(uap,sigcntxp),
+ (flags&SS_RTEFRAME) ? tstate.ss_frame.f_format : -1);
+#endif
+ /*
+ * Restore most of the users registers except for A6 and SP
+ * which were handled above.
+ */
+ if (flags & SS_USERREGS)
+ bcopy((caddr_t)tstate.ss_frame.f_regs,
+ (caddr_t)frame->f_regs, sizeof(frame->f_regs)-2*NBPW);
+ /*
+ * Restore long stack frames. Note that we do not copy
+ * back the saved SR or PC, they were picked up above from
+ * the sigcontext structure.
+ */
+ if (flags & SS_RTEFRAME) {
+ register int sz;
+
+ /* grab frame type and validate */
+ sz = tstate.ss_frame.f_format;
+ if (sz > 15 || (sz = exframesize[sz]) < 0)
+ return (EINVAL);
+ frame->f_stackadj -= sz;
+ frame->f_format = tstate.ss_frame.f_format;
+ frame->f_vector = tstate.ss_frame.f_vector;
+ bcopy((caddr_t)&tstate.ss_frame.F_u, (caddr_t)&frame->F_u, sz);
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sigreturn(%d): copy in %d of frame type %d\n",
+ p->p_pid, sz, tstate.ss_frame.f_format);
+#endif
+ }
+#ifdef FPCOPROC
+ /*
+ * Finally we restore the original FP context
+ */
+ if (flags & SS_FPSTATE)
+ m68881_restore(&tstate.ss_fpstate);
+#ifdef DEBUG
+ if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate)
+ printf("sigreturn(%d): copied in FP state (%x) at %x\n",
+ p->p_pid, *(u_int *)&tstate.ss_fpstate,
+ &tstate.ss_fpstate);
+#endif
+#endif
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) ||
+ ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
+ printf("sigreturn(%d): returns\n", p->p_pid);
+#endif
+ return (EJUSTRETURN);
+}
+
+#ifdef COMPAT_SUNOS
+/*
+ * this is a "light weight" version of the NetBSD sigreturn, just for
+ * SunOS processes. We don't have to restore any hardware frames,
+ * registers, fpu stuff, that's all done in user space.
+ */
+struct sunos_sigreturn_args {
+ struct sunos_sigcontext *sigcntxp;
+};
+
+int
+sunos_sigreturn(p, uap, retval)
+ struct proc *p;
+ struct sunos_sigreturn_args *uap;
+ register_t *retval;
+{
+ register struct sunos_sigcontext *scp;
+ register struct frame *frame;
+ register int rf;
+ struct sunos_sigcontext tsigc;
+ int flags;
+
+ scp = uap->sigcntxp;
+#ifdef DEBUG
+ if (sigdebug & SDB_FOLLOW)
+ printf("sunos_sigreturn: pid %d, scp %x\n", p->p_pid, scp);
+#endif
+ if ((int)scp & 1)
+ return (EINVAL);
+ /*
+ * Test and fetch the context structure.
+ * We grab it all at once for speed.
+ */
+ if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
+ copyin((caddr_t)scp, (caddr_t)&tsigc, sizeof tsigc))
+ return (EINVAL);
+ scp = &tsigc;
+ if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0)
+ return (EINVAL);
+ /*
+ * Restore the user supplied information
+ */
+ if (scp->sc_onstack & 1)
+ p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+ p->p_sigmask = scp->sc_mask &~ sigcantmask;
+ frame = (struct frame *) p->p_md.md_regs;
+ frame->f_regs[SP] = scp->sc_sp;
+ frame->f_pc = scp->sc_pc;
+ frame->f_sr = scp->sc_ps;
+
+ return EJUSTRETURN;
+}
+#endif /* COMPAT_SUNOS */
+
+static int waittime = -1;
+
+void
+bootsync(void)
+{
+ if (waittime < 0) {
+ register struct buf *bp;
+ int iter, nbusy;
+
+ waittime = 0;
+ (void) spl0();
+ printf("syncing disks... ");
+ /*
+ * Release vnodes held by texts before sync.
+ */
+ if (panicstr == 0)
+ vnode_pager_umount(NULL);
+ sync(&proc0, (void *)NULL, (int *)NULL);
+
+ for (iter = 0; iter < 20; iter++) {
+ nbusy = 0;
+ for (bp = &buf[nbuf]; --bp >= buf; )
+ if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
+ nbusy++;
+ if (nbusy == 0)
+ break;
+ printf("%d ", nbusy);
+ delay(40000 * iter);
+ }
+ if (nbusy)
+ printf("giving up\n");
+ else
+ printf("done\n");
+ /*
+ * If we've been adjusting the clock, the todr
+ * will be out of synch; adjust it now.
+ */
+ resettodr();
+ }
+}
+
+void
+boot(howto)
+ register int howto;
+{
+ /* take a snap shot before clobbering any registers */
+ if (curproc)
+ savectx(curproc->p_addr, 0);
+
+ boothowto = howto;
+ if((howto&RB_NOSYNC) == 0)
+ bootsync();
+ splhigh(); /* extreme priority */
+ if(howto & RB_HALT) {
+ printf("halted\n\n");
+ asm(" stop #0x2700");
+ }
+ else {
+ if(howto & RB_DUMP)
+ dumpsys();
+ doboot();
+ /*NOTREACHED*/
+ }
+ /*NOTREACHED*/
+}
+
+unsigned dumpmag = 0x8fca0101; /* magic number for savecore */
+int dumpsize = 0; /* also for savecore */
+long dumplo = 0;
+
+dumpconf()
+{
+ int nblks;
+
+ dumpsize = physmem;
+ if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
+ nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+ if (dumpsize > btoc(dbtob(nblks - dumplo)))
+ dumpsize = btoc(dbtob(nblks - dumplo));
+ else if (dumplo == 0)
+ dumplo = nblks - btodb(ctob(physmem));
+ }
+ /*
+ * Don't dump on the first CLBYTES (why CLBYTES?)
+ * in case the dump device includes a disk label.
+ */
+ if (dumplo < btodb(CLBYTES))
+ dumplo = btodb(CLBYTES);
+}
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+dumpsys()
+{
+
+ msgbufmapped = 0;
+ if (dumpdev == NODEV)
+ return;
+ /*
+ * For dumps during autoconfiguration,
+ * if dump device has already configured...
+ */
+ if (dumpsize == 0)
+ dumpconf();
+ if (dumplo < 0)
+ return;
+ printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
+ printf("dump ");
+ switch ((*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
+
+ 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;
+
+ default:
+ printf("succeeded\n");
+ break;
+ }
+}
+
+/*
+ * Return the best possible estimate of the time in the timeval
+ * to which tvp points. We do this by returning the current time
+ * plus the amount of time since the last clock interrupt (clock.c:clkread).
+ *
+ * Check that this time is no less than any previously-reported time,
+ * which could happen around the time of a clock adjustment. Just for fun,
+ * we guarantee that the time will be greater than the value obtained by a
+ * previous call.
+ */
+void microtime(tvp)
+ register struct timeval *tvp;
+{
+ int s = splhigh();
+ static struct timeval lasttime;
+
+ *tvp = time;
+ tvp->tv_usec += clkread();
+ while (tvp->tv_usec > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ if (tvp->tv_sec == lasttime.tv_sec &&
+ tvp->tv_usec <= lasttime.tv_usec &&
+ (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
+ tvp->tv_sec++;
+ tvp->tv_usec -= 1000000;
+ }
+ lasttime = *tvp;
+ splx(s);
+}
+
+initcpu()
+{
+}
+
+straytrap(pc, evec)
+int pc;
+u_short evec;
+{
+ static int prev_evec;
+
+ printf("unexpected trap (vector offset %x) from %x\n",evec & 0xFFF, pc);
+
+ if(prev_evec == evec) {
+ delay(1000000);
+ prev_evec = 0;
+ }
+}
+
+straymfpint(pc, evec)
+int pc;
+u_short evec;
+{
+ printf("unexpected mfp-interrupt (vector offset %x) from %x\n",
+ evec & 0xFFF, pc);
+}
+
+int *nofault;
+
+badbaddr(addr)
+ register caddr_t addr;
+{
+ register int i;
+ label_t faultbuf;
+
+#ifdef lint
+ i = *addr; if (i) return(0);
+#endif
+ nofault = (int *) &faultbuf;
+ if (setjmp((label_t *)nofault)) {
+ nofault = (int *) 0;
+ return(1);
+ }
+ i = *(volatile char *)addr;
+ nofault = (int *) 0;
+ return(0);
+}
+
+netintr()
+{
+#ifdef INET
+#if NETHER > 0
+ if (netisr & (1 << NETISR_ARP)) {
+ netisr &= ~(1 << NETISR_ARP);
+ arpintr();
+ }
+#endif
+ if (netisr & (1 << NETISR_IP)) {
+ netisr &= ~(1 << NETISR_IP);
+ ipintr();
+ }
+#endif
+#ifdef NS
+ if (netisr & (1 << NETISR_NS)) {
+ netisr &= ~(1 << NETISR_NS);
+ nsintr();
+ }
+#endif
+#ifdef ISO
+ if (netisr & (1 << NETISR_ISO)) {
+ netisr &= ~(1 << NETISR_ISO);
+ clnlintr();
+ }
+#endif
+}
+
+
+/*
+ * this is a handy package to have asynchronously executed
+ * function calls executed at very low interrupt priority.
+ * Example for use is keyboard repeat, where the repeat
+ * handler running at splclock() triggers such a (hardware
+ * aided) software interrupt.
+ * Note: the installed functions are currently called in a
+ * LIFO fashion, might want to change this to FIFO
+ * later.
+ */
+struct si_callback {
+ struct si_callback *next;
+ void (*function) __P((void *rock1, void *rock2));
+ void *rock1, *rock2;
+};
+static struct si_callback *si_callbacks;
+static struct si_callback *si_free;
+#ifdef DIAGNOSTIC
+static int ncb; /* number of callback blocks allocated */
+static int ncbd; /* number of callback blocks dynamically allocated */
+#endif
+
+void alloc_sicallback()
+{
+ struct si_callback *si;
+ int s;
+
+ si = (struct si_callback *)malloc(sizeof(*si), M_TEMP, M_NOWAIT);
+ if(si == NULL)
+ return;
+ s = splhigh();
+ si->next = si_free;
+ si_free = si;
+ splx(s);
+#ifdef DIAGNOSTIC
+ ++ncb;
+#endif
+}
+
+void add_sicallback (function, rock1, rock2)
+void (*function) __P((void *rock1, void *rock2));
+void *rock1, *rock2;
+{
+ struct si_callback *si;
+ int s;
+
+ /*
+ * this function may be called from high-priority interrupt handlers.
+ * We may NOT block for memory-allocation in here!.
+ */
+ s = splhigh();
+ if((si = si_free) != NULL)
+ si_free = si->next;
+ splx(s);
+
+ if(si == NULL) {
+ si = (struct si_callback *)malloc(sizeof(*si), M_TEMP, M_NOWAIT);
+#ifdef DIAGNOSTIC
+ if(si)
+ ++ncbd; /* count # dynamically allocated */
+#endif
+
+ if(!si)
+ return;
+ }
+
+ si->function = function;
+ si->rock1 = rock1;
+ si->rock2 = rock2;
+
+ s = splhigh();
+ si->next = si_callbacks;
+ si_callbacks = si;
+ splx(s);
+
+ /*
+ * and cause a software interrupt (spl1). This interrupt might
+ * happen immediately, or after returning to a safe enough level.
+ */
+ SCU->sys_int = 1;
+}
+
+void rem_sicallback(function)
+void (*function) __P((void *rock1, void *rock2));
+{
+ struct si_callback *si, *psi, *nsi;
+ int s;
+
+ s = splhigh();
+ for(psi = 0, si = si_callbacks; si; ) {
+ nsi = si->next;
+
+ if(si->function != function)
+ psi = si;
+ else {
+ si->next = si_free;
+ si_free = si;
+ if(psi)
+ psi->next = nsi;
+ else si_callbacks = nsi;
+ }
+ si = nsi;
+ }
+ splx(s);
+}
+
+/* purge the list */
+void call_sicallbacks()
+{
+ struct si_callback *si;
+ int s;
+ void *rock1, *rock2;
+ void (*function) __P((void *, void *));
+
+ do {
+ s = splhigh ();
+ if(si = si_callbacks)
+ si_callbacks = si->next;
+ splx(s);
+
+ if(si) {
+ function = si->function;
+ rock1 = si->rock1;
+ rock2 = si->rock2;
+ s = splhigh ();
+ si->next = si_free;
+ si_free = si;
+ splx(s);
+ function(rock1, rock2);
+ }
+ } while(si);
+#ifdef DIAGNOSTIC
+ if(ncbd) {
+#ifdef DEBUG
+ printf("call_sicallback: %d more dynamic structures %d total\n",
+ ncbd, ncb);
+#endif
+ ncbd = 0;
+ }
+#endif
+}
+
+#if defined(DEBUG) && !defined(PANICBUTTON)
+#define PANICBUTTON
+#endif
+
+#ifdef PANICBUTTON
+int panicbutton = 1; /* non-zero if panic buttons are enabled */
+int crashandburn = 0;
+int candbdelay = 50; /* give em half a second */
+
+candbtimer()
+{
+ crashandburn = 0;
+}
+#endif
+
+regdump(fp, sbytes)
+ struct frame *fp; /* must not be register */
+ int sbytes;
+{
+ static int doingdump = 0;
+ register int i;
+ int s;
+ extern char *hexstr();
+
+ if (doingdump)
+ return;
+ s = splhigh();
+ doingdump = 1;
+ printf("pid = %d, pc = %s, ", curproc->p_pid, hexstr(fp->f_pc, 8));
+ printf("ps = %s, ", hexstr(fp->f_sr, 4));
+ printf("sfc = %s, ", hexstr(getsfc(), 4));
+ printf("dfc = %s\n", hexstr(getdfc(), 4));
+ printf("Registers:\n ");
+ for (i = 0; i < 8; i++)
+ printf(" %d", i);
+ printf("\ndreg:");
+ for (i = 0; i < 8; i++)
+ printf(" %s", hexstr(fp->f_regs[i], 8));
+ printf("\nareg:");
+ for (i = 0; i < 8; i++)
+ printf(" %s", hexstr(fp->f_regs[i+8], 8));
+ if (sbytes > 0) {
+ if (fp->f_sr & PSL_S) {
+ printf("\n\nKernel stack (%s):",
+ hexstr((int)(((int *)&fp)-1), 8));
+ dumpmem(((int *)&fp)-1, sbytes, 0);
+ } else {
+ printf("\n\nUser stack (%s):", hexstr(fp->f_regs[SP], 8));
+ dumpmem((int *)fp->f_regs[SP], sbytes, 1);
+ }
+ }
+ doingdump = 0;
+ splx(s);
+}
+
+extern char kstack[];
+#define KSADDR ((int *)&(kstack[(UPAGES-1)*NBPG]))
+
+dumpmem(ptr, sz, ustack)
+ register int *ptr;
+ int sz;
+{
+ register int i, val;
+ extern char *hexstr();
+
+ for (i = 0; i < sz; i++) {
+ if ((i & 7) == 0)
+ printf("\n%s: ", hexstr((int)ptr, 6));
+ else
+ printf(" ");
+ if (ustack == 1) {
+ if ((val = fuword(ptr++)) == -1)
+ break;
+ } else {
+ if (ustack == 0 &&
+ (ptr < KSADDR || ptr > KSADDR+(NBPG/4-1)))
+ break;
+ val = *ptr++;
+ }
+ printf("%s", hexstr(val, 8));
+ }
+ printf("\n");
+}
+
+char *
+hexstr(val, len)
+ register int val;
+{
+ static char nbuf[9];
+ register int x, i;
+
+ if (len > 8)
+ return("");
+ nbuf[len] = '\0';
+ for (i = len-1; i >= 0; --i) {
+ x = val & 0xF;
+ if (x > 9)
+ nbuf[i] = x - 10 + 'A';
+ else
+ nbuf[i] = x + '0';
+ val >>= 4;
+ }
+ return(nbuf);
+}
+
+/*
+ * should only get here, if no standard executable. This can currently
+ * only mean, we're reading an old ZMAGIC file without MID, but since Atari
+ * ZMAGIC always worked the `right' way (;-)) just ignore the missing
+ * MID and proceed to new zmagic code ;-)
+ */
+cpu_exec_aout_makecmds(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ int error = ENOEXEC;
+ struct exec *execp = epp->ep_hdr;
+
+#ifdef COMPAT_NOMID
+ if (!((execp->a_midmag >> 16) & 0x0fff)
+ && execp->a_midmag == ZMAGIC)
+ return(exec_aout_prep_zmagic(p, epp));
+#endif
+#ifdef COMPAT_SUNOS
+ {
+ extern sunos_exec_aout_makecmds
+ __P((struct proc *, struct exec_package *));
+ if ((error = sunos_exec_aout_makecmds(p, epp)) == 0)
+ return(0);
+ }
+#endif
+ return(error);
+}
diff --git a/sys/arch/atari/atari/mem.c b/sys/arch/atari/atari/mem.c
new file mode 100644
index 00000000000..26d6d69508a
--- /dev/null
+++ b/sys/arch/atari/atari/mem.c
@@ -0,0 +1,180 @@
+/* $NetBSD: mem.c,v 1.1.1.1 1995/03/26 07:12:18 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * from: Utah $Hdr: mem.c 1.14 90/10/12$
+ *
+ * @(#)mem.c 7.5 (Berkeley) 5/7/91
+ */
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <machine/cpu.h>
+
+#include <vm/vm_param.h>
+#include <vm/vm_prot.h>
+#include <vm/lock.h>
+#include <vm/pmap.h>
+
+
+/*ARGSUSED*/
+int
+mmrw(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ extern u_int lowram;
+ register int o;
+ register u_int c, v;
+ register struct iovec *iov;
+ int error;
+ caddr_t zbuf;
+
+ zbuf = NULL;
+ error = 0;
+
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("mmrw");
+ continue;
+ }
+ switch (minor(dev)) {
+
+ /*
+ * minor device 0 is physical memory
+ */
+ case 0:
+ v = uio->uio_offset;
+#ifndef DEBUG
+ /* allow reads only in RAM (except for DEBUG) */
+ if (v >= 0xFFFFFFFC || v < lowram)
+ return (EFAULT);
+#endif
+ pmap_enter(kernel_pmap, (vm_offset_t) vmmap,
+ trunc_page(v), uio->uio_rw == UIO_READ
+ ? VM_PROT_READ : VM_PROT_WRITE, TRUE);
+ o = (int)uio->uio_offset & PGOFSET;
+ c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET));
+ c = min(c, (u_int)(NBPG - o));
+ c = min(c, (u_int)iov->iov_len);
+ error = uiomove((caddr_t)&vmmap[o], (int)c, uio);
+ pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
+ (vm_offset_t)&vmmap[NBPG]);
+ continue;
+
+ /*
+ * minor device 1 is kernel memory
+ */
+ case 1:
+ c = min(iov->iov_len, MAXPHYS);
+ if (!kernacc((caddr_t)(vm_offset_t)uio->uio_offset, c,
+ uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
+ return (EFAULT);
+ error = uiomove((caddr_t)(vm_offset_t)uio->uio_offset,
+ (int)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 12 (/dev/zero) is source of nulls on
+ * read, rathole on write
+ */
+ case 12:
+ if (uio->uio_rw == UIO_WRITE) {
+ c = iov->iov_len;
+ break;
+ }
+ if (zbuf == NULL) {
+ zbuf = (caddr_t)
+ malloc(CLBYTES, M_TEMP, M_WAITOK);
+ bzero(zbuf, CLBYTES);
+ }
+ c = min(iov->iov_len, CLBYTES);
+ error = uiomove(zbuf, (int)c, uio);
+ continue;
+
+#ifdef notyet /* LWP */
+ /*
+ * minor device 20 (/dev/reload) represents
+ * magic memory which you can write a kernel
+ * image to, causing a reboot into that
+ * kernel.
+ */
+ case 20:
+ /* Reads simply get EOF. */
+ if (uio->uio_rw == UIO_READ)
+ return 0;
+
+ error = kernel_reload_write(uio);
+ continue;
+#endif /* notyet */
+
+ default:
+ return (ENXIO);
+ }
+ if (error)
+ break;
+ iov->iov_base += c;
+ iov->iov_len -= c;
+ uio->uio_offset += c;
+ uio->uio_resid -= c;
+ }
+ if (zbuf)
+ free(zbuf, M_TEMP);
+ return (error);
+}
diff --git a/sys/arch/atari/atari/misc.c b/sys/arch/atari/atari/misc.c
new file mode 100644
index 00000000000..7e332f09303
--- /dev/null
+++ b/sys/arch/atari/atari/misc.c
@@ -0,0 +1,217 @@
+/* $NetBSD: misc.c,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman (Atari modifications)
+ * Copyright (c) 1994 Christian E. Hopps (allocator stuff)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <atari/atari/misc.h>
+
+/*
+ * St-mem allocator.
+ */
+/*
+ * From atari_init.c
+ */
+extern u_long st_pool_size, st_pool_virt, st_pool_phys;
+
+#define PHYS_ADDR(virt) ((u_long)(virt) - st_pool_virt + st_pool_phys)
+
+static CIRCLEQ_HEAD(stlist, mem_node) st_list;
+static CIRCLEQ_HEAD(freelist, mem_node) free_list;
+static u_long stmem_total; /* total free. */
+
+void
+init_stmem()
+{
+ int s = splhigh ();
+ struct mem_node *mem;
+
+ stmem_total = st_pool_size - sizeof(*mem);
+
+ mem = (struct mem_node *)st_pool_virt;
+ mem->size = st_pool_size - sizeof(*mem);
+
+ CIRCLEQ_INIT(&st_list);
+ CIRCLEQ_INIT(&free_list);
+
+ CIRCLEQ_INSERT_HEAD(&st_list, mem, link);
+ CIRCLEQ_INSERT_HEAD(&free_list, mem, free_link);
+ splx(s);
+}
+
+void *
+alloc_stmem(size, phys_addr)
+u_long size;
+void **phys_addr;
+{
+ struct mem_node *mn, *new;
+ void *mem;
+ int s;
+
+ if (size == 0)
+ return NULL;
+
+ s = splhigh();
+
+ if (size & ~(ST_BLOCKMASK))
+ size = (size & ST_BLOCKMASK) + ST_BLOCKSIZE;
+
+ /*
+ * walk list of available nodes.
+ */
+ mn = free_list.cqh_first;
+ while (size > mn->size && mn != (void *)&free_list)
+ mn = mn->free_link.cqe_next;
+
+ if (mn == (void *)&free_list) {
+ printf("St-mem pool exhausted, binpatch 'st_pool_size'"
+ "to get more\n");
+ return(NULL);
+ }
+
+ if ((mn->size - size) <= sizeof (*mn)) {
+ /*
+ * our allocation would not leave room
+ * for a new node in between.
+ */
+ CIRCLEQ_REMOVE(&free_list, mn, free_link);
+ mn->free_link.cqe_next = NULL;
+ size = mn->size; /* increase size. (or same) */
+ stmem_total -= mn->size;
+ splx(s);
+ *phys_addr = (void*)PHYS_ADDR(&mn[1]);
+ return ((void *)&mn[1]);
+ }
+
+ /*
+ * split the node's memory.
+ */
+ new = mn;
+ new->size -= size + sizeof(struct mem_node);
+ mn = (struct mem_node *)(MNODES_MEM(new) + new->size);
+ mn->size = size;
+
+ /*
+ * add split node to node list
+ * and mark as not on free list
+ */
+ CIRCLEQ_INSERT_AFTER(&st_list, new, mn, link);
+ mn->free_link.cqe_next = NULL;
+
+ stmem_total -= size + sizeof(struct mem_node);
+ splx(s);
+ *phys_addr = (void*)PHYS_ADDR(&mn[1]);
+ return ((void *)&mn[1]);
+}
+
+void
+free_stmem(mem)
+void *mem;
+{
+ struct mem_node *mn, *next, *prev;
+ int s;
+
+ if (mem == NULL)
+ return;
+
+ s = splhigh();
+ mn = (struct mem_node *)mem - 1;
+ next = mn->link.cqe_next;
+ prev = mn->link.cqe_prev;
+
+ /*
+ * check ahead of us.
+ */
+ if (next->link.cqe_next != (void *)&st_list &&
+ next->free_link.cqe_next) {
+ /*
+ * if next is: a valid node and a free node. ==> merge
+ */
+ CIRCLEQ_INSERT_BEFORE(&free_list, next, mn, free_link);
+ CIRCLEQ_REMOVE(&st_list, next, link);
+ CIRCLEQ_REMOVE(&st_list, next, free_link);
+ stmem_total += mn->size + sizeof(struct mem_node);
+ mn->size += next->size + sizeof(struct mem_node);
+ }
+ if (prev->link.cqe_prev != (void *)&st_list &&
+ prev->free_link.cqe_prev) {
+ /*
+ * if prev is: a valid node and a free node. ==> merge
+ */
+ if (mn->free_link.cqe_next == NULL)
+ stmem_total += mn->size + sizeof(struct mem_node);
+ else {
+ /* already on free list */
+ CIRCLEQ_REMOVE(&free_list, mn, free_link);
+ stmem_total += sizeof(struct mem_node);
+ }
+ CIRCLEQ_REMOVE(&st_list, mn, link);
+ prev->size += mn->size + sizeof(struct mem_node);
+ } else if (mn->free_link.cqe_next == NULL) {
+ /*
+ * we still are not on free list and we need to be.
+ * <-- | -->
+ */
+ while (next->link.cqe_next != (void *)&st_list &&
+ prev->link.cqe_prev != (void *)&st_list) {
+ if (next->free_link.cqe_next) {
+ CIRCLEQ_INSERT_BEFORE(&free_list, next, mn,
+ free_link);
+ break;
+ }
+ if (prev->free_link.cqe_next) {
+ CIRCLEQ_INSERT_AFTER(&free_list, prev, mn,
+ free_link);
+ break;
+ }
+ prev = prev->link.cqe_prev;
+ next = next->link.cqe_next;
+ }
+ if (mn->free_link.cqe_next == NULL) {
+ if (next->link.cqe_next == (void *)&st_list) {
+ /*
+ * we are not on list so we can add
+ * ourselves to the tail. (we walked to it.)
+ */
+ CIRCLEQ_INSERT_TAIL(&free_list,mn,free_link);
+ } else {
+ CIRCLEQ_INSERT_HEAD(&free_list,mn,free_link);
+ }
+ }
+ stmem_total += mn->size;/* add our helpings to the pool. */
+ }
+ splx(s);
+}
diff --git a/sys/arch/atari/atari/misc.h b/sys/arch/atari/atari/misc.h
new file mode 100644
index 00000000000..477f4535e47
--- /dev/null
+++ b/sys/arch/atari/atari/misc.h
@@ -0,0 +1,55 @@
+/* $NetBSD: misc.h,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps (allocator stuff)
+ * Copyright (c) 1995 Leo Weppelman (Atari modifications)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ATARI_MISC_H
+#define _ATARI_MISC_H
+/*
+ * St-mem allocator stuff.
+ */
+struct mem_node {
+ CIRCLEQ_ENTRY(mem_node) link;
+ CIRCLEQ_ENTRY(mem_node) free_link;
+ u_long size; /* size of memory following node. */
+};
+
+#define ST_BLOCKSIZE (sizeof(long))
+#define ST_BLOCKMASK (~(ST_BLOCKSIZE - 1))
+#define MNODES_MEM(mn) ((u_char *)(&mn[1]))
+
+void init_stmem __P((void));
+void *alloc_stmem __P((u_long, void **));
+void free_stmem __P((void *));
+
+#endif /* _ATARI_MISC_H */
diff --git a/sys/arch/atari/atari/pmap.c b/sys/arch/atari/atari/pmap.c
new file mode 100644
index 00000000000..f8166f00d99
--- /dev/null
+++ b/sys/arch/atari/atari/pmap.c
@@ -0,0 +1,2128 @@
+/* $NetBSD: pmap.c,v 1.1.1.1 1995/03/26 07:12:20 leo Exp $ */
+
+/*
+ * Copyright (c) 1991 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.
+ *
+ * @(#)pmap.c 7.5 (Berkeley) 5/10/91
+ */
+
+/*
+ * ATARI physical map management code.
+ * For 68020/68030 machines with 68551, or 68030 MMUs
+ * Don't even pay lip service to multiprocessor support.
+ *
+ * will only work for PAGE_SIZE == NBPG
+ * right now because of the assumed one-to-one relationship of PT
+ * pages to STEs.
+ */
+
+/*
+ * Manages physical address maps.
+ *
+ * In addition to hardware address maps, this
+ * module is called upon to provide software-use-only
+ * maps which may or may not be stored in the same
+ * form as hardware maps. These pseudo-maps are
+ * used to store intermediate results from copy
+ * operations to and from address spaces.
+ *
+ * Since the information managed by this module is
+ * also stored by the logical address mapping module,
+ * this module may throw away valid virtual-to-physical
+ * mappings at almost any time. However, invalidations
+ * of virtual-to-physical mappings must be done as
+ * requested.
+ *
+ * In order to cope with hardware architectures which
+ * make virtual-to-physical map invalidates expensive,
+ * this module may delay invalidate or reduced protection
+ * operations until such time as they are actually
+ * necessary. This module is given full information as
+ * to which processors are currently using which maps,
+ * and to when physical maps must be made correct.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/msgbuf.h>
+#include <vm/vm.h>
+#include <sys/user.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <machine/pte.h>
+#include <machine/cpu.h>
+#include <machine/vmparam.h>
+/*
+ * Allocate various and sundry SYSMAPs used in the days of old VM
+ * and not yet converted. XXX.
+ */
+
+#ifdef DEBUG
+struct kpt_stats {
+ int collectscans;
+ int collectpages;
+ int kpttotal;
+ int kptinuse;
+ int kptmaxuse;
+};
+struct enter_stats {
+ int kernel; /* entering kernel mapping */
+ int user; /* entering user mapping */
+ int ptpneeded; /* needed to allocate a PT page */
+ int pwchange; /* no mapping change, just wiring or protection */
+ int wchange; /* no mapping change, just wiring */
+ int mchange; /* was mapped but mapping to different page */
+ int managed; /* a managed page */
+ int firstpv; /* first mapping for this PA */
+ int secondpv; /* second mapping for this PA */
+ int ci; /* cache inhibited */
+ int unmanaged; /* not a managed page */
+ int flushes; /* cache flushes */
+};
+struct remove_stats {
+ int calls;
+ int removes;
+ int pvfirst;
+ int pvsearch;
+ int ptinvalid;
+ int uflushes;
+ int sflushes;
+};
+
+struct remove_stats remove_stats;
+struct enter_stats enter_stats;
+struct kpt_stats kpt_stats;
+
+#define PDB_FOLLOW 0x0001
+#define PDB_INIT 0x0002
+#define PDB_ENTER 0x0004
+#define PDB_REMOVE 0x0008
+#define PDB_CREATE 0x0010
+#define PDB_PTPAGE 0x0020
+#define PDB_CACHE 0x0040
+#define PDB_BITS 0x0080
+#define PDB_COLLECT 0x0100
+#define PDB_PROTECT 0x0200
+#define PDB_SEGTAB 0x0400
+#define PDB_PARANOIA 0x2000
+#define PDB_WIRING 0x4000
+#define PDB_PVDUMP 0x8000
+int debugmap = 0;
+int pmapdebug = PDB_PARANOIA;
+#endif
+
+/*
+ * Get STEs and PTEs for user/kernel address space
+ */
+#define pmap_ste(m, v) (&((m)->pm_stab[(vm_offset_t)(v) >> pmap_ishift]))
+#define pmap_pte(m, v) (&((m)->pm_ptab[(vm_offset_t)(v) >> PG_SHIFT]))
+
+#define pmap_pte_pa(pte) (*(u_int *)(pte) & PG_FRAME)
+
+#define pmap_ste_v(ste) (*(u_int *)(ste) & SG_V)
+#define pmap_pte_w(pte) (*(u_int *)(pte) & PG_W)
+#define pmap_pte_ci(pte) (*(u_int *)(pte) & PG_CI)
+#define pmap_pte_m(pte) (*(u_int *)(pte) & PG_M)
+#define pmap_pte_u(pte) (*(u_int *)(pte) & PG_U)
+#define pmap_pte_prot(pte) (*(u_int *)(pte) & PG_PROT)
+#define pmap_pte_v(pte) (*(u_int *)(pte) & PG_V)
+
+#define pmap_pte_set_w(pte, v) \
+ do { if (v) *(u_int *)(pte) |= PG_W; else *(u_int *)(pte) &= ~PG_W; \
+ } while (0)
+#define pmap_pte_set_prot(pte, v) \
+ do { if (v) *(u_int *)(pte) |= PG_PROT; else *(u_int *)(pte) &= ~PG_PROT; \
+ } while (0)
+#define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte))
+#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte))
+
+#define active_pmap(pm) \
+ ((pm) == kernel_pmap || (pm) == curproc->p_vmspace->vm_map.pmap)
+
+/*
+ * Given a map and a machine independent protection code,
+ * convert to a vax protection code.
+ */
+#define pte_prot(m, p) (protection_codes[p])
+int protection_codes[8];
+
+/*
+ * Kernel page table page management.
+ */
+struct kpt_page {
+ struct kpt_page *kpt_next; /* link on either used or free list */
+ vm_offset_t kpt_va; /* always valid kernel VA */
+ vm_offset_t kpt_pa; /* PA of this page (for speed) */
+};
+struct kpt_page *kpt_free_list, *kpt_used_list;
+struct kpt_page *kpt_pages;
+
+/*
+ * Kernel segment/page table and page table map.
+ * The page table map gives us a level of indirection we need to dynamically
+ * expand the page table. It is essentially a copy of the segment table
+ * with PTEs instead of STEs. All are initialized in locore at boot time.
+ * Sysmap will initially contain VM_KERNEL_PT_PAGES pages of PTEs.
+ * Segtabzero is an empty segment table which all processes share til they
+ * reference something.
+ */
+u_int *Sysseg1; /* root segment for 68040 */
+u_int *Sysseg;
+u_int *Sysptmap;
+u_int *Segtabzero;
+vm_size_t Sysptsize = VM_KERNEL_PT_PAGES + 4 / NPTEPG;
+
+struct pmap kernel_pmap_store;
+pmap_t kernel_pmap;
+vm_map_t pt_map;
+
+vm_offset_t avail_start; /* PA of first available physical page */
+vm_offset_t avail_end; /* PA of last available physical page */
+vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/
+vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */
+vm_offset_t vm_first_phys; /* PA of first managed page */
+vm_offset_t vm_last_phys; /* PA just past last managed page */
+boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */
+char *pmap_attributes; /* reference and modify bits */
+static int pmap_ishift; /* segment table index shift */
+
+boolean_t pmap_testbit();
+void pmap_enter_ptpage();
+
+/*
+ * The following vars become valid just before pmap_bootstrap is called.
+ * They give info about free memory with the kernel and the tables allocated
+ * in 'start_c' excluded.
+ */
+vm_offset_t st_ramstart; /* First available ST RAM address */
+vm_offset_t st_ramend; /* First ST RAM address not available */
+vm_offset_t tt_ramstart; /* First available TT RAM address */
+vm_offset_t tt_ramend; /* First TT RAM address not available */
+
+
+/*
+ * All those kernel PT submaps that BSD is so fond of
+ */
+caddr_t CADDR1, CADDR2;
+u_int *CMAP1, *CMAP2, *vmpte, *msgbufmap;
+
+/*
+ * Bootstrap the system enough to run with virtual memory.
+ * Map the kernel's code and data, and allocate the system page table.
+ *
+ * On the HP this is called after mapping has already been enabled
+ * and just syncs the pmap module with what has already been done.
+ * [We can't call it easily with mapping off since the kernel is not
+ * mapped with PA == VA, hence we would have to relocate every address
+ * from the linked base (virtual) address 0 to the actual (physical)
+ * address of 0xFFxxxxxx.]
+ */
+void pmap_bootstrap(kernel_size)
+vm_offset_t kernel_size;
+{
+ vm_offset_t va;
+ u_int *pte;
+
+ /*
+ * Setup physical address ranges
+ */
+ avail_start = st_ramstart;
+ avail_end = tt_ramend ? tt_ramend : st_ramend;
+
+ /* XXX: allow for msgbuf */
+ avail_end -= atari_round_page(sizeof(struct msgbuf));
+
+ /*
+ * Setup virtual address ranges
+ */
+ virtual_avail = VM_MIN_KERNEL_ADDRESS + kernel_size;
+ virtual_end = VM_MAX_KERNEL_ADDRESS;
+
+ /*
+ * Initialize protection array.
+ */
+ atari_protection_init();
+
+ /*
+ * The kernel's pmap is statically allocated so we don't
+ * have to use pmap_create, which is unlikely to work
+ * correctly at this part of the boot sequence.
+ */
+ kernel_pmap = &kernel_pmap_store;
+
+ /*
+ * Kernel page/segment table allocated in locore,
+ * just initialize pointers.
+ */
+ kernel_pmap->pm_stab = Sysseg;
+ kernel_pmap->pm_ptab = Sysmap;
+#ifdef M68040
+ if (cpu040) {
+ kernel_pmap->pm_rtab = Sysseg1;
+ pmap_ishift = SG4_ISHIFT;
+ } else
+#endif
+ pmap_ishift = SG_ISHIFT;
+
+ simple_lock_init(&kernel_pmap->pm_lock);
+ kernel_pmap->pm_count = 1;
+
+ /*
+ * Allocate all the submaps we need
+ */
+#define SYSMAP(c, p, v, n) \
+ v = (c)va; va += ((n)*NBPG); p = pte; pte += (n);
+
+ va = virtual_avail;
+ pte = pmap_pte(kernel_pmap, va);
+
+ SYSMAP(caddr_t ,CMAP1 ,CADDR1 ,1 )
+ SYSMAP(caddr_t ,CMAP2 ,CADDR2 ,1 )
+ SYSMAP(caddr_t ,vmpte ,vmmap ,1 )
+ SYSMAP(struct msgbuf * ,msgbufmap ,msgbufp ,1 )
+
+ virtual_avail = va;
+}
+
+/*
+ * Bootstrap memory allocator. This function allows for early dynamic
+ * memory allocation until the virtual memory system has been bootstrapped.
+ * After that point, either kmem_alloc or malloc should be used. This
+ * function works by stealing pages from the (to be) managed page pool,
+ * stealing virtual address space, then mapping the pages and zeroing them.
+ *
+ * It should be used from pmap_bootstrap till vm_page_startup, afterwards
+ * it cannot be used, and will generate a panic if tried. Note that this
+ * memory will never be freed, and in essence it is wired down.
+ */
+void *
+pmap_bootstrap_alloc(size)
+ int size;
+{
+ extern boolean_t vm_page_startup_initialized;
+ vm_offset_t val;
+
+ if (vm_page_startup_initialized)
+ panic("pmap_bootstrap_alloc: called after startup initialized");
+ size = round_page(size);
+ val = virtual_avail;
+
+ virtual_avail = pmap_map(virtual_avail, avail_start,
+ avail_start + size, VM_PROT_READ|VM_PROT_WRITE);
+ avail_start += size;
+
+ blkclr((caddr_t) val, size);
+ return((void *) val);
+}
+
+
+/*
+ * Initialize the pmap module.
+ * Called by vm_init, to initialize any structures that the pmap
+ * system needs to map virtual memory.
+ */
+void
+pmap_init(phys_start, phys_end)
+ vm_offset_t phys_start, phys_end;
+{
+ extern char kstack[];
+ vm_offset_t addr, addr2;
+ vm_size_t npg, s;
+ int rv;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_init(%x, %x)\n", phys_start, phys_end);
+#endif
+ addr = (vm_offset_t) Sysmap;
+ vm_object_reference(kernel_object);
+ (void) vm_map_find(kernel_map, kernel_object, addr, &addr,
+ ATARI_KPTSIZE, FALSE);
+ /*
+ * If this fails it is probably because the static portion of
+ * the kernel page table isn't big enough and we overran the
+ * page table map. Need to adjust pmap_size() in atari_init.c.
+ */
+ if (addr != (vm_offset_t)Sysmap)
+ goto bogons;
+
+ addr = (vm_offset_t) kstack;
+ vm_object_reference(kernel_object);
+ (void) vm_map_find(kernel_map, kernel_object, addr,
+ &addr, atari_ptob(UPAGES), FALSE);
+ if (addr != (vm_offset_t)kstack)
+bogons:
+ panic("pmap_init: bogons in the VM system!\n");
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_INIT) {
+ printf("pmap_init: Sysseg %x, Sysmap %x, Sysptmap %x\n",
+ Sysseg, Sysmap, Sysptmap);
+ printf(" pstart %x, pend %x, vstart %x, vend %x\n",
+ avail_start, avail_end, virtual_avail, virtual_end);
+ }
+#endif
+
+ /*
+ * Allocate memory for random pmap data structures. Includes the
+ * initial segment table, pv_head_table and pmap_attributes.
+ */
+ npg = atop(phys_end - phys_start);
+#ifdef M68040
+ if (cpu040)
+ s = (vm_size_t)ATARI_040STSIZE * 128 +
+ sizeof(struct pv_entry) * npg + npg;
+ else
+#endif
+ s = (vm_size_t)ATARI_STSIZE +
+ sizeof(struct pv_entry) * npg + npg;
+
+ s = round_page(s);
+ addr = (vm_offset_t) kmem_alloc(kernel_map, s);
+ Segtabzero = (u_int *) addr;
+#ifdef M68040
+ if (cpu040)
+ addr += ATARI_040STSIZE * 128;
+ else
+#endif
+ addr += ATARI_STSIZE;
+ pv_table = (pv_entry_t) addr;
+ addr += sizeof(struct pv_entry) * npg;
+ pmap_attributes = (char *) addr;
+#ifdef DEBUG
+ if (pmapdebug & PDB_INIT)
+ printf("pmap_init: %x bytes (%x pgs): seg %x tbl %x attr %x\n",
+ s, npg, Segtabzero, pv_table, pmap_attributes);
+#endif
+
+ /*
+ * Allocate physical memory for kernel PT pages and their management.
+ * we need enough pages to map the page tables for each process
+ * plus some slop.
+ */
+ npg = howmany(((maxproc + 16) * ATARI_UPTSIZE / NPTEPG), NBPG);
+ npg = min(atop(ATARI_MAX_KPTSIZE), npg);
+ s = ptoa(npg) + round_page(npg * sizeof(struct kpt_page));
+
+ /*
+ * Verify that space will be allocated in region for which
+ * we already have kernel PT pages.
+ */
+ addr = 0;
+ rv = vm_map_find(kernel_map, NULL, 0, &addr, s, TRUE);
+ if (rv != KERN_SUCCESS || addr + s >= (vm_offset_t)Sysmap)
+ panic("pmap_init: kernel PT too small");
+ vm_map_remove(kernel_map, addr, addr + s);
+
+ /*
+ * Now allocate the space and link the pages together to
+ * form the KPT free list.
+ */
+ addr = (vm_offset_t) kmem_alloc(kernel_map, s);
+ s = ptoa(npg);
+ addr2 = addr + s;
+ kpt_pages = &((struct kpt_page *)addr2)[npg];
+ kpt_free_list = (struct kpt_page *) 0;
+ do {
+ addr2 -= NBPG;
+ (--kpt_pages)->kpt_next = kpt_free_list;
+ kpt_free_list = kpt_pages;
+ kpt_pages->kpt_va = addr2;
+ kpt_pages->kpt_pa = pmap_extract(kernel_pmap, addr2);
+ } while (addr != addr2);
+#ifdef DEBUG
+ kpt_stats.kpttotal = atop(s);
+ if (pmapdebug & PDB_INIT)
+ printf("pmap_init: KPT: %d pages from %x to %x\n",
+ atop(s), addr, addr + s);
+#endif
+
+ /*
+ * Slightly modified version of kmem_suballoc() to get page table
+ * map where we want it.
+ */
+ addr = ATARI_UPTBASE;
+ s = min(ATARI_UPTMAXSIZE, maxproc * ATARI_UPTSIZE);
+ addr2 = addr + s;
+ rv = vm_map_find(kernel_map, NULL, 0, &addr, s, TRUE);
+ if (rv != KERN_SUCCESS)
+ panic("pmap_init: cannot allocate space for PT map");
+ pmap_reference(vm_map_pmap(kernel_map));
+ pt_map = vm_map_create(vm_map_pmap(kernel_map), addr, addr2, TRUE);
+ if (pt_map == NULL)
+ panic("pmap_init: cannot create pt_map");
+ rv = vm_map_submap(kernel_map, addr, addr2, pt_map);
+ if (rv != KERN_SUCCESS)
+ panic("pmap_init: cannot map range to pt_map");
+#ifdef DEBUG
+ if (pmapdebug & PDB_INIT)
+ printf("pmap_init: pt_map [%x - %x)\n", addr, addr2);
+#endif
+
+ /*
+ * Now it is safe to enable pv_table recording.
+ */
+ vm_first_phys = phys_start;
+ vm_last_phys = phys_end;
+ pmap_initialized = TRUE;
+}
+
+/*
+ * 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(virt, start, end, prot)
+ vm_offset_t virt;
+ vm_offset_t start;
+ vm_offset_t end;
+ int prot;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_map(%x, %x, %x, %x)\n", virt, start, end, prot);
+#endif
+ while (start < end) {
+ pmap_enter(kernel_pmap, virt, start, prot, FALSE);
+ virt += PAGE_SIZE;
+ start += PAGE_SIZE;
+ }
+ return(virt);
+}
+
+/*
+ * 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;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_create(%x)\n", size);
+#endif
+ /*
+ * Software use map does not need a pmap
+ */
+ if (size)
+ return(NULL);
+
+ /* XXX: is it ok to wait here? */
+ pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
+#ifdef notifwewait
+ if (pmap == NULL)
+ panic("pmap_create: cannot allocate a pmap");
+#endif
+ bzero(pmap, sizeof(*pmap));
+ pmap_pinit(pmap);
+ return (pmap);
+}
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+void
+pmap_pinit(pmap)
+ register struct pmap *pmap;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+ printf("pmap_pinit(%x)\n", pmap);
+#endif
+ /*
+ * No need to allocate page table space yet but we do need a
+ * valid segment table. Initially, we point everyone at the
+ * "null" segment table. On the first pmap_enter, a real
+ * segment table will be allocated.
+ */
+#ifdef M68040
+ if (cpu040)
+ pmap->pm_rtab = Segtabzero;
+#endif
+ pmap->pm_stab = Segtabzero;
+ pmap->pm_stchanged = TRUE;
+ pmap->pm_count = 1;
+ simple_lock_init(&pmap->pm_lock);
+}
+
+/*
+ * Retire the given physical map from service.
+ * Should only be called if the map contains
+ * no valid mappings.
+ */
+void
+pmap_destroy(pmap)
+ register pmap_t pmap;
+{
+ int count;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_destroy(%x)\n", pmap);
+#endif
+ 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);
+ }
+}
+
+/*
+ * 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 struct pmap *pmap;
+{
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_release(%x)\n", pmap);
+#endif
+#ifdef notdef /* DIAGNOSTIC */
+ /* count would be 0 from pmap_destroy... */
+ simple_lock(&pmap->pm_lock);
+ if (pmap->pm_count != 1)
+ panic("pmap_release count");
+#endif
+ if (pmap->pm_ptab)
+ kmem_free_wakeup(pt_map, (vm_offset_t)pmap->pm_ptab,
+ ATARI_UPTSIZE);
+ if (pmap->pm_stab != Segtabzero)
+#ifdef M68040
+ if (cpu040) {
+ kmem_free(kernel_map, (vm_offset_t)pmap->pm_rtab,
+ ATARI_040RTSIZE);
+ kmem_free(kernel_map, (vm_offset_t)pmap->pm_stab,
+ ATARI_040STSIZE*128);
+ }
+ else
+#endif
+ kmem_free(kernel_map, (vm_offset_t)pmap->pm_stab, ATARI_STSIZE);
+}
+
+/*
+ * Add a reference to the specified pmap.
+ */
+void
+pmap_reference(pmap)
+ pmap_t pmap;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_reference(%x)\n", pmap);
+#endif
+ if (pmap != NULL) {
+ simple_lock(&pmap->pm_lock);
+ pmap->pm_count++;
+ simple_unlock(&pmap->pm_lock);
+ }
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ *
+ * It is assumed that the start and end are properly
+ * rounded to the page size.
+ */
+void
+pmap_remove(pmap, sva, eva)
+ register pmap_t pmap;
+ vm_offset_t sva, eva;
+{
+ register vm_offset_t pa, va;
+ register u_int *pte;
+ register pv_entry_t pv, npv;
+ pmap_t ptpmap;
+ int *ste, i, s, bits;
+ boolean_t flushcache = FALSE;
+#ifdef DEBUG
+ u_int opte;
+
+ if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
+ printf("pmap_remove(%x, %x, %x)\n", pmap, sva, eva);
+#endif
+
+ if (pmap == NULL)
+ return;
+
+#ifdef DEBUG
+ remove_stats.calls++;
+#endif
+ for (va = sva; va < eva; va += PAGE_SIZE) {
+ /*
+ * Weed out invalid mappings.
+ * Note: we assume that the segment table is always allocated.
+ */
+ if (!pmap_ste_v(pmap_ste(pmap, va))) {
+ /* XXX: avoid address wrap around */
+ if (va >= atari_trunc_seg((vm_offset_t)-1))
+ break;
+ va = atari_round_seg(va + PAGE_SIZE) - PAGE_SIZE;
+ continue;
+ }
+ pte = pmap_pte(pmap, va);
+ pa = pmap_pte_pa(pte);
+ if (pa == 0)
+ continue;
+#ifdef DEBUG
+ opte = *pte;
+ remove_stats.removes++;
+#endif
+ /*
+ * Update statistics
+ */
+ if (pmap_pte_w(pte))
+ pmap->pm_stats.wired_count--;
+ pmap->pm_stats.resident_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: invalidating %x\n", pte);
+#endif
+ bits = *(int *)pte & (PG_U|PG_M);
+ *(int *)pte = PG_NV;
+ if (active_pmap(pmap))
+ TBIS(va);
+
+ /*
+ * For user mappings decrement the wiring count on
+ * the PT page. We do this after the PTE has been
+ * invalidated because vm_map_pageable winds up in
+ * pmap_pageable which clears the modify bit for the
+ * PT page.
+ */
+ if (pmap != kernel_pmap) {
+ pte = pmap_pte(pmap, va);
+ vm_map_pageable(pt_map, trunc_page(pte),
+ round_page(pte+1), TRUE);
+#ifdef DEBUG
+ if (pmapdebug & PDB_WIRING)
+ pmap_check_wiring("remove", trunc_page(pte));
+#endif
+ }
+ /*
+ * Remove from the PV table (raise IPL since we
+ * may be called at interrupt time).
+ */
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ continue;
+ pv = pa_to_pvh(pa);
+ ste = (int *)0;
+ s = splimp();
+ /*
+ * 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) {
+ ste = (int *)pv->pv_ptste;
+ ptpmap = pv->pv_ptpmap;
+ npv = pv->pv_next;
+ if (npv) {
+ *pv = *npv;
+ free((caddr_t)npv, M_VMPVENT);
+ } else
+ pv->pv_pmap = NULL;
+#ifdef DEBUG
+ remove_stats.pvfirst++;
+#endif
+ } else {
+ for (npv = pv->pv_next; npv; npv = npv->pv_next) {
+#ifdef DEBUG
+ remove_stats.pvsearch++;
+#endif
+ if (pmap == npv->pv_pmap && va == npv->pv_va)
+ break;
+ pv = npv;
+ }
+#ifdef DEBUG
+ if (npv == NULL)
+ panic("pmap_remove: PA not in pv_tab");
+#endif
+ ste = (int *)npv->pv_ptste;
+ ptpmap = npv->pv_ptpmap;
+ pv->pv_next = npv->pv_next;
+ free((caddr_t)npv, M_VMPVENT);
+ pv = pa_to_pvh(pa);
+ }
+ /*
+ * If this was a PT page we must also remove the
+ * mapping from the associated segment table.
+ */
+ if (ste) {
+#ifdef DEBUG
+ remove_stats.ptinvalid++;
+ if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE)) {
+ printf("remove: ste was %x@%x pte was %x@%x\n",
+ *ste, ste,
+ *(int *)&opte, pmap_pte(pmap, va));
+ }
+#endif
+#ifdef M68040
+ if (cpu040) {
+ /*
+ * On the 68040, the PT page contains 64 page tables,
+ * so we need to remove all the associated segment
+ * table entries
+ * (This may be incorrect: if a single page table is
+ * being removed, the whole page should not be
+ * removed.)
+ */
+ for (i = 0; i < 64; ++i)
+ *ste++ = SG_NV;
+ ste -= 64;
+#ifdef DEBUG
+ if (pmapdebug &(PDB_REMOVE|PDB_SEGTAB|0x10000))
+ printf("pmap_remove:PT at %x remved\n",
+ va);
+#endif
+ }
+ else
+#endif /* M68040 */
+ *ste = SG_NV;
+ /*
+ * If it was a user PT page, we decrement the
+ * reference count on the segment table as well,
+ * freeing it if it is now empty.
+ */
+ if (ptpmap != kernel_pmap) {
+#ifdef DEBUG
+ if (pmapdebug & (PDB_REMOVE|PDB_SEGTAB))
+ printf("remove: stab %x, refcnt %d\n",
+ ptpmap->pm_stab,
+ ptpmap->pm_sref - 1);
+ if ((pmapdebug & PDB_PARANOIA) &&
+ ptpmap->pm_stab != (u_int *)trunc_page(ste))
+ panic("remove: bogus ste");
+#endif
+ if (--(ptpmap->pm_sref) == 0) {
+#ifdef DEBUG
+ if (pmapdebug&(PDB_REMOVE|PDB_SEGTAB))
+ printf("remove: free stab %x\n",
+ ptpmap->pm_stab);
+#endif
+#ifdef M68040
+ if (cpu040) {
+ kmem_free(kernel_map,
+ (vm_offset_t)ptpmap->pm_rtab,
+ ATARI_040RTSIZE);
+ kmem_free(kernel_map,
+ (vm_offset_t)ptpmap->pm_stab,
+ ATARI_040STSIZE*128);
+ ptpmap->pm_rtab = Segtabzero;
+ }
+ else
+#endif
+ kmem_free(kernel_map,
+ (vm_offset_t)ptpmap->pm_stab,
+ ATARI_STSIZE);
+ ptpmap->pm_stab = Segtabzero;
+ ptpmap->pm_stchanged = TRUE;
+ /*
+ * XXX may have changed segment table
+ * pointer for current process so
+ * update now to reload hardware.
+ */
+ if (ptpmap == curproc->p_vmspace->vm_map.pmap)
+ PMAP_ACTIVATE(ptpmap,
+ (struct pcb *)curproc->p_addr, 1);
+ }
+ }
+ if (ptpmap == kernel_pmap)
+ TBIAS();
+ else
+ TBIAU();
+ pv->pv_flags &= ~PV_PTPAGE;
+ ptpmap->pm_ptpages--;
+ }
+ /*
+ * Update saved attributes for managed page
+ */
+ pmap_attributes[pa_index(pa)] |= bits;
+ splx(s);
+ }
+ if (flushcache) {
+ if (pmap == kernel_pmap) {
+ DCIS();
+#ifdef DEBUG
+ remove_stats.sflushes++;
+#endif
+ } else {
+ DCIU();
+#ifdef DEBUG
+ remove_stats.uflushes++;
+#endif
+ }
+ }
+}
+
+/*
+ * pmap_page_protect:
+ *
+ * Lower the permission for all mappings to a given page.
+ */
+void
+pmap_page_protect(pa, prot)
+ vm_offset_t pa;
+ vm_prot_t prot;
+{
+ register pv_entry_t pv;
+ int s;
+
+#ifdef DEBUG
+ if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) ||
+ prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE))
+ printf("pmap_page_protect(%x, %x)\n", pa, prot);
+#endif
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+
+ switch (prot) {
+ case VM_PROT_ALL:
+ break;
+ /* copy_on_write */
+ case VM_PROT_READ:
+ case VM_PROT_READ|VM_PROT_EXECUTE:
+ pmap_changebit(pa, PG_RO, TRUE);
+ break;
+ /* remove_all */
+ default:
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ while (pv->pv_pmap != NULL) {
+#ifdef DEBUG
+ if (!pmap_ste_v(pmap_ste(pv->pv_pmap,pv->pv_va)) ||
+ pmap_pte_pa(pmap_pte(pv->pv_pmap,pv->pv_va)) != pa)
+ panic("pmap_page_protect: bad mapping");
+#endif
+ pmap_remove(pv->pv_pmap, pv->pv_va,
+ pv->pv_va + PAGE_SIZE);
+ }
+ splx(s);
+ break;
+ }
+}
+
+/*
+ * Set the physical protection on the
+ * specified range of this map as requested.
+ */
+void
+pmap_protect(pmap, sva, eva, prot)
+ register pmap_t pmap;
+ vm_offset_t sva, eva;
+ vm_prot_t prot;
+{
+ register u_int *pte;
+ register vm_offset_t va;
+ boolean_t needtflush;
+ int isro;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
+ printf("pmap_protect(%x, %x, %x, %x)\n", pmap, sva, eva, prot);
+#endif
+ if (pmap == NULL)
+ return;
+
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ pmap_remove(pmap, sva, eva);
+ return;
+ }
+ if (prot & VM_PROT_WRITE)
+ return;
+
+ pte = pmap_pte(pmap, sva);
+ isro = pte_prot(pmap, prot) == PG_RO ? 1 : 0;
+ needtflush = active_pmap(pmap);
+ for (va = sva; va < eva; va += PAGE_SIZE) {
+ /*
+ * Page table page is not allocated.
+ * Skip it, we don't want to force allocation
+ * of unnecessary PTE pages just to set the protection.
+ */
+ if (!pmap_ste_v(pmap_ste(pmap, va))) {
+ /* XXX: avoid address wrap around */
+ if (va >= atari_trunc_seg((vm_offset_t)-1))
+ break;
+ va = atari_round_seg(va + PAGE_SIZE) - PAGE_SIZE;
+ pte = pmap_pte(pmap, va);
+ pte++;
+ continue;
+ }
+ /*
+ * skip if page not valid or protection is same
+ */
+ if (!pmap_pte_v(pte) || !pmap_pte_prot_chg(pte, isro)) {
+ pte++;
+ continue;
+ }
+#ifdef M68040
+ /*
+ * Clear caches if making RO (see section
+ * "7.3 Cache Coherency" in the manual).
+ */
+ if (isro && cpu040) {
+ vm_offset_t pa = pmap_pte_pa(pte);
+
+ DCFP(pa);
+ ICPP(pa);
+ }
+#endif
+ pmap_pte_set_prot(pte, isro);
+ if (needtflush)
+ TBIS(va);
+ pte++;
+ }
+}
+
+/*
+ * 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)
+ register pmap_t pmap;
+ vm_offset_t va;
+ register vm_offset_t pa;
+ vm_prot_t prot;
+ boolean_t wired;
+{
+ register u_int *pte;
+ register int npte;
+ vm_offset_t opa;
+ boolean_t cacheable = TRUE;
+ boolean_t checkpv = TRUE;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_ENTER))
+ printf("pmap_enter(%x, %x, %x, %x, %x)\n",
+ pmap, va, pa, prot, wired);
+#endif
+ if (pmap == NULL)
+ return;
+
+#ifdef DEBUG
+ if (pmap == kernel_pmap)
+ enter_stats.kernel++;
+ else
+ enter_stats.user++;
+#endif
+ /*
+ * For user mapping, allocate kernel VM resources if necessary.
+ */
+ if (pmap->pm_ptab == NULL)
+ pmap->pm_ptab = (u_int *)
+ kmem_alloc_wait(pt_map, ATARI_UPTSIZE);
+
+ /*
+ * Segment table entry not valid, we need a new PT page
+ */
+ if (!pmap_ste_v(pmap_ste(pmap, va)))
+ pmap_enter_ptpage(pmap, va);
+
+ pte = pmap_pte(pmap, va);
+ opa = pmap_pte_pa(pte);
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: pte %x, *pte %x, opa: %x\n", pte, *(int *)pte, opa);
+#endif
+
+ /*
+ * Mapping has not changed, must be protection or wiring change.
+ */
+ if (opa == pa) {
+#ifdef DEBUG
+ enter_stats.pwchange++;
+#endif
+ /*
+ * Wiring change, just update stats.
+ * We don't worry about wiring PT pages as they remain
+ * resident as long as there are valid mappings in them.
+ * Hence, if a user page is wired, the PT page will be also.
+ */
+ if (wired && !pmap_pte_w(pte) || !wired && pmap_pte_w(pte)) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: wiring change -> %x\n", wired);
+#endif
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ else
+ pmap->pm_stats.wired_count--;
+#ifdef DEBUG
+ enter_stats.wchange++;
+#endif
+ }
+ /*
+ * Retain cache inhibition status
+ */
+ checkpv = FALSE;
+ if (pmap_pte_ci(pte))
+ cacheable = FALSE;
+ goto validate;
+ }
+
+ /*
+ * Mapping has changed, invalidate old range and fall through to
+ * handle validating new mapping.
+ */
+ if (opa) {
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: removing old mapping %x\n", va);
+#endif
+ pmap_remove(pmap, va, va + PAGE_SIZE);
+#ifdef DEBUG
+ enter_stats.mchange++;
+#endif
+ }
+
+ /*
+ * If this is a new user mapping, increment the wiring count
+ * on this PT page. PT pages are wired down as long as there
+ * is a valid mapping in the page.
+ */
+ if (pmap != kernel_pmap)
+ vm_map_pageable(pt_map, trunc_page(pte),
+ round_page(pte+1), FALSE);
+
+ /*
+ * Enter on the PV list if part of our managed memory
+ * Note that we raise IPL while manipulating pv_table
+ * since pmap_enter can be called at interrupt time.
+ */
+ if (pa >= vm_first_phys && pa < vm_last_phys) {
+ register pv_entry_t pv, npv;
+ int s;
+
+#ifdef DEBUG
+ enter_stats.managed++;
+#endif
+ pv = pa_to_pvh(pa);
+ s = splimp();
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: pv at %x: %x/%x/%x\n",
+ pv, pv->pv_va, pv->pv_pmap, pv->pv_next);
+#endif
+ /*
+ * No entries yet, use header as the first entry
+ */
+ if (pv->pv_pmap == NULL) {
+#ifdef DEBUG
+ enter_stats.firstpv++;
+#endif
+ pv->pv_va = va;
+ pv->pv_pmap = pmap;
+ pv->pv_next = NULL;
+ pv->pv_ptste = NULL;
+ pv->pv_ptpmap = NULL;
+ pv->pv_flags = 0;
+ }
+ /*
+ * There is at least one other VA mapping this page.
+ * Place this entry after the header.
+ */
+ else {
+#ifdef DEBUG
+ for (npv = pv; npv; npv = npv->pv_next)
+ if (pmap == npv->pv_pmap && va == npv->pv_va)
+ panic("pmap_enter: already in pv_tab");
+#endif
+ npv = (pv_entry_t)
+ malloc(sizeof *npv, M_VMPVENT, M_NOWAIT);
+ npv->pv_va = va;
+ npv->pv_pmap = pmap;
+ npv->pv_next = pv->pv_next;
+ npv->pv_ptste = NULL;
+ npv->pv_ptpmap = NULL;
+ pv->pv_next = npv;
+#ifdef DEBUG
+ if (!npv->pv_next)
+ enter_stats.secondpv++;
+#endif
+ }
+ splx(s);
+ }
+ /*
+ * Assumption: if it is not part of our managed memory
+ * then it must be device memory which may be volitile.
+ */
+ else if (pmap_initialized) {
+ checkpv = cacheable = FALSE;
+#ifdef DEBUG
+ enter_stats.unmanaged++;
+#endif
+ }
+
+ /*
+ * Increment counters
+ */
+ pmap->pm_stats.resident_count++;
+ if (wired)
+ pmap->pm_stats.wired_count++;
+
+validate:
+ /*
+ * Now validate mapping with desired protection/wiring.
+ * Assume uniform modified and referenced status for all
+ * ATARI pages in a MACH page.
+ */
+#ifdef M68040
+ if (cpu040 && pmap == kernel_pmap && va >= ATARI_UPTBASE &&
+ va < (ATARI_UPTBASE + ATARI_UPTMAXSIZE))
+ cacheable = FALSE; /* don't cache user page tables */
+#endif
+ npte = (pa & PG_FRAME) | pte_prot(pmap, prot) | PG_V;
+ npte |= (*(int *)pte & (PG_M|PG_U));
+ if (wired)
+ npte |= PG_W;
+ if (!checkpv && !cacheable)
+ npte |= PG_CI;
+#ifdef M68040
+ else if (cpu040 && (npte & PG_PROT) == PG_RW)
+ npte |= PG_CCB; /* cache copyback */
+#endif
+ /*
+ * Remember if this was a wiring-only change.
+ * If so, we need not flush the TLB and caches.
+ */
+ wired = ((*(int *)pte ^ npte) == PG_W);
+#ifdef M68040
+ if (cpu040 && !wired) {
+ DCFP(pa);
+ ICPP(pa);
+ }
+#endif
+#ifdef DEBUG
+ if (pmapdebug & PDB_ENTER)
+ printf("enter: new pte value %x\n", npte);
+#endif
+ *(int *)pte++ = npte;
+ if (!wired && active_pmap(pmap))
+ TBIS(va);
+#ifdef DEBUG
+ if ((pmapdebug & PDB_WIRING) && pmap != kernel_pmap) {
+ va -= PAGE_SIZE;
+ pmap_check_wiring("enter", trunc_page(pmap_pte(pmap, va)));
+ }
+#endif
+}
+
+/*
+ * 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)
+ register pmap_t pmap;
+ vm_offset_t va;
+ boolean_t wired;
+{
+ register u_int *pte;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_change_wiring(%x, %x, %x)\n", pmap, va, wired);
+#endif
+ if (pmap == NULL)
+ return;
+
+ pte = pmap_pte(pmap, va);
+#ifdef DEBUG
+ /*
+ * Page table page is not allocated.
+ * Should this ever happen? Ignore it for now,
+ * we don't want to force allocation of unnecessary PTE pages.
+ */
+ if (!pmap_ste_v(pmap_ste(pmap, va))) {
+ if (pmapdebug & PDB_PARANOIA)
+ printf("pmap_change_wiring: invalid STE for %x\n", va);
+ return;
+ }
+ /*
+ * Page not valid. Should this ever happen?
+ * Just continue and change wiring anyway.
+ */
+ if (!pmap_pte_v(pte)) {
+ if (pmapdebug & PDB_PARANOIA)
+ printf("pmap_change_wiring: invalid PTE for %x\n", va);
+ }
+#endif
+ if (wired && !pmap_pte_w(pte) || !wired && pmap_pte_w(pte)) {
+ if (wired)
+ pmap->pm_stats.wired_count++;
+ else
+ pmap->pm_stats.wired_count--;
+ }
+ /*
+ * Wiring is not a hardware characteristic so there is no need
+ * to invalidate TLB.
+ */
+ pmap_pte_set_w(pte, wired);
+}
+
+/*
+ * Routine: pmap_extract
+ * Function:
+ * Extract the physical page address associated
+ * with the given map/virtual_address pair.
+ */
+
+vm_offset_t
+pmap_extract(pmap, va)
+ register pmap_t pmap;
+ vm_offset_t va;
+{
+ register vm_offset_t pa;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_extract(%x, %x) -> ", pmap, va);
+#endif
+ pa = 0;
+ if (pmap && pmap_ste_v(pmap_ste(pmap, va)))
+ pa = *(int *)pmap_pte(pmap, va);
+ if (pa)
+ pa = (pa & PG_FRAME) | (va & ~PG_FRAME);
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("%x\n", pa);
+#endif
+ return(pa);
+}
+
+/*
+ * 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;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_copy(%x, %x, %x, %x, %x)\n",
+ dst_pmap, src_pmap, dst_addr, len, src_addr);
+#endif
+}
+
+/*
+ * Require that all active physical maps contain no
+ * incorrect entries NOW. [This update includes
+ * forcing updates of any address map caching.]
+ *
+ * Generally used to insure that a thread about
+ * to run will see a semantically correct world.
+ */
+void pmap_update()
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_update()\n");
+#endif
+ TBIA();
+}
+
+/*
+ * Routine: pmap_collect
+ * Function:
+ * Garbage collects the physical map system for
+ * pages which are no longer used.
+ * Success need not be guaranteed -- that is, there
+ * may well be pages which are not referenced, but
+ * others may be collected.
+ * Usage:
+ * Called by the pageout daemon when pages are scarce.
+ */
+void
+pmap_collect(pmap)
+ pmap_t pmap;
+{
+ register vm_offset_t pa;
+ register pv_entry_t pv;
+ register int *pte;
+ vm_offset_t kpa;
+ int s;
+
+#ifdef DEBUG
+ int *ste;
+ int opmapdebug;
+#endif
+ if (pmap != kernel_pmap)
+ return;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_collect(%x)\n", pmap);
+ kpt_stats.collectscans++;
+#endif
+ s = splimp();
+ for (pa = vm_first_phys; pa < vm_last_phys; pa += PAGE_SIZE) {
+ register struct kpt_page *kpt, **pkpt;
+
+ /*
+ * Locate physical pages which are being used as kernel
+ * page table pages.
+ */
+ pv = pa_to_pvh(pa);
+ if (pv->pv_pmap != kernel_pmap || !(pv->pv_flags & PV_PTPAGE))
+ continue;
+ do {
+ if (pv->pv_ptste && pv->pv_ptpmap == kernel_pmap)
+ break;
+ } while (pv = pv->pv_next);
+ if (pv == NULL)
+ continue;
+#ifdef DEBUG
+ if (pv->pv_va < (vm_offset_t)Sysmap ||
+ pv->pv_va >= (vm_offset_t)Sysmap + ATARI_KPTSIZE)
+ printf("collect: kernel PT VA out of range\n");
+ else
+ goto ok;
+ pmap_pvdump(pa);
+ continue;
+ok:
+#endif
+ pte = (int *)(pv->pv_va + NBPG);
+ while (--pte >= (int *)pv->pv_va && *pte == PG_NV)
+ ;
+ if (pte >= (int *)pv->pv_va)
+ continue;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) {
+ printf("collect: freeing KPT page at %x (ste %x@%x)\n",
+ pv->pv_va, *(int *)pv->pv_ptste, pv->pv_ptste);
+ opmapdebug = pmapdebug;
+ pmapdebug |= PDB_PTPAGE;
+ }
+
+ ste = (int *)pv->pv_ptste;
+#endif
+ /*
+ * If all entries were invalid we can remove the page.
+ * We call pmap_remove to take care of invalidating ST
+ * and Sysptmap entries.
+ */
+ kpa = pmap_extract(pmap, pv->pv_va);
+ pmap_remove(pmap, pv->pv_va, pv->pv_va + NBPG);
+ /*
+ * Use the physical address to locate the original
+ * (kmem_alloc assigned) address for the page and put
+ * that page back on the free list.
+ */
+ for (pkpt = &kpt_used_list, kpt = *pkpt;
+ kpt != (struct kpt_page *)0;
+ pkpt = &kpt->kpt_next, kpt = *pkpt)
+ if (kpt->kpt_pa == kpa)
+ break;
+#ifdef DEBUG
+ if (kpt == (struct kpt_page *)0)
+ panic("pmap_collect: lost a KPT page");
+ if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT))
+ printf("collect: %x (%x) to free list\n",
+ kpt->kpt_va, kpa);
+#endif
+ *pkpt = kpt->kpt_next;
+ kpt->kpt_next = kpt_free_list;
+ kpt_free_list = kpt;
+#ifdef DEBUG
+ kpt_stats.kptinuse--;
+ kpt_stats.collectpages++;
+ if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT))
+ pmapdebug = opmapdebug;
+
+ if (*ste)
+ printf("collect: kernel STE at %x still valid (%x)\n",
+ ste, *ste);
+ ste = (int *)&Sysptmap[(u_int *)ste-pmap_ste(kernel_pmap, 0)];
+ if (*ste)
+ printf("collect: kernel PTmap at %x still valid (%x)\n",
+ ste, *ste);
+#endif
+ }
+ splx(s);
+}
+
+void
+pmap_activate(pmap, pcbp)
+ register pmap_t pmap;
+ struct pcb *pcbp;
+{
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_SEGTAB))
+ printf("pmap_activate(%x, %x)\n", pmap, pcbp);
+#endif
+ PMAP_ACTIVATE(pmap, pcbp, pmap == curproc->p_vmspace->vm_map.pmap);
+}
+
+/*
+ * pmap_zero_page zeros the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bzero to clear its contents, one machine dependent page
+ * at a time.
+ */
+void
+pmap_zero_page(phys)
+ register vm_offset_t phys;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_zero_page(%x)\n", phys);
+#endif
+ phys >>= PG_SHIFT;
+ clearseg(phys);
+}
+
+/*
+ * pmap_copy_page copies the specified (machine independent)
+ * page by mapping the page into virtual memory and using
+ * bcopy to copy the page, one machine dependent page at a
+ * time.
+ */
+void
+pmap_copy_page(src, dst)
+ register vm_offset_t src, dst;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_copy_page(%x, %x)\n", src, dst);
+#endif
+ src >>= PG_SHIFT;
+ dst >>= PG_SHIFT;
+ physcopyseg(src, dst);
+}
+
+
+/*
+ * Routine: pmap_pageable
+ * Function:
+ * 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, eva;
+ boolean_t pageable;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_pageable(%x, %x, %x, %x)\n",
+ pmap, sva, eva, pageable);
+#endif
+ /*
+ * If we are making a PT page pageable then all valid
+ * mappings must be gone from that page. Hence it should
+ * be all zeros and there is no need to clean it.
+ * Assumptions:
+ * - we are called with only one page at a time
+ * - PT pages have only one pv_table entry
+ */
+ if (pmap == kernel_pmap && pageable && sva + PAGE_SIZE == eva) {
+ register pv_entry_t pv;
+ register vm_offset_t pa;
+
+#ifdef DEBUG
+ if ((pmapdebug & (PDB_FOLLOW|PDB_PTPAGE)) == PDB_PTPAGE)
+ printf("pmap_pageable(%x, %x, %x, %x)\n",
+ pmap, sva, eva, pageable);
+#endif
+ if (!pmap_ste_v(pmap_ste(pmap, sva)))
+ return;
+ pa = pmap_pte_pa(pmap_pte(pmap, sva));
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+ pv = pa_to_pvh(pa);
+ if (pv->pv_ptste == NULL)
+ return;
+#ifdef DEBUG
+ if (pv->pv_va != sva || pv->pv_next) {
+ printf("pmap_pageable: bad PT page va %x next %x\n",
+ pv->pv_va, pv->pv_next);
+ return;
+ }
+#endif
+ /*
+ * Mark it unmodified to avoid pageout
+ */
+ pmap_changebit(pa, PG_M, FALSE);
+#ifdef DEBUG
+ if (pmapdebug & PDB_PTPAGE)
+ printf("pmap_pageable: PT page %x(%x) unmodified\n",
+ sva, *(int *)pmap_pte(pmap, sva));
+ if (pmapdebug & PDB_WIRING)
+ pmap_check_wiring("pageable", sva);
+#endif
+ }
+}
+
+/*
+ * Clear the modify bits on the specified physical page.
+ */
+
+void
+pmap_clear_modify(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_clear_modify(%x)\n", pa);
+#endif
+ pmap_changebit(pa, PG_M, FALSE);
+}
+
+/*
+ * pmap_clear_reference:
+ *
+ * Clear the reference bit on the specified physical page.
+ */
+
+void pmap_clear_reference(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW)
+ printf("pmap_clear_reference(%x)\n", pa);
+#endif
+ pmap_changebit(pa, PG_U, FALSE);
+}
+
+/*
+ * pmap_is_referenced:
+ *
+ * Return whether or not the specified physical page is referenced
+ * by any physical maps.
+ */
+
+boolean_t
+pmap_is_referenced(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW) {
+ boolean_t rv = pmap_testbit(pa, PG_U);
+ printf("pmap_is_referenced(%x) -> %c\n", pa, "FT"[rv]);
+ return(rv);
+ }
+#endif
+ return(pmap_testbit(pa, PG_U));
+}
+
+/*
+ * pmap_is_modified:
+ *
+ * Return whether or not the specified physical page is modified
+ * by any physical maps.
+ */
+
+boolean_t
+pmap_is_modified(pa)
+ vm_offset_t pa;
+{
+#ifdef DEBUG
+ if (pmapdebug & PDB_FOLLOW) {
+ boolean_t rv = pmap_testbit(pa, PG_M);
+ printf("pmap_is_modified(%x) -> %c\n", pa, "FT"[rv]);
+ return(rv);
+ }
+#endif
+ return(pmap_testbit(pa, PG_M));
+}
+
+vm_offset_t
+pmap_phys_address(ppn)
+ int ppn;
+{
+ return(atari_ptob(ppn));
+}
+
+/*
+ * Miscellaneous support routines follow
+ */
+
+/* static */
+atari_protection_init()
+{
+ register int *kp, prot;
+
+ kp = protection_codes;
+ for (prot = 0; prot < 8; prot++) {
+ switch (prot) {
+ case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
+ *kp++ = 0;
+ break;
+ case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
+ case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
+ case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
+ *kp++ = PG_RO;
+ break;
+ case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
+ case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
+ case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
+ case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
+ *kp++ = PG_RW;
+ break;
+ }
+ }
+}
+
+/* static */
+boolean_t
+pmap_testbit(pa, bit)
+ register vm_offset_t pa;
+ int bit;
+{
+ register pv_entry_t pv;
+ register int *pte;
+ int s;
+
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return(FALSE);
+
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * Check saved info first
+ */
+ if (pmap_attributes[pa_index(pa)] & bit) {
+ 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 = (int *) pmap_pte(pv->pv_pmap, pv->pv_va);
+ if (*pte & bit) {
+ splx(s);
+ return(TRUE);
+ }
+ }
+ }
+ splx(s);
+ return(FALSE);
+}
+
+/* static */
+pmap_changebit(pa, bit, setem)
+ register vm_offset_t pa;
+ int bit;
+ boolean_t setem;
+{
+ register pv_entry_t pv;
+ register int *pte, npte;
+ vm_offset_t va;
+ boolean_t firstpage;
+ int s;
+
+ firstpage = TRUE;
+
+#ifdef DEBUG
+ if (pmapdebug & PDB_BITS)
+ printf("pmap_changebit(%x, %x, %s)\n",
+ pa, bit, setem ? "set" : "clear");
+#endif
+ if (pa < vm_first_phys || pa >= vm_last_phys)
+ return;
+
+ pv = pa_to_pvh(pa);
+ s = splimp();
+ /*
+ * Clear saved attributes (modify, reference)
+ */
+ if (!setem)
+ pmap_attributes[pa_index(pa)] &= ~bit;
+ /*
+ * Loop over all current mappings setting/clearing as appropos
+ * If setting RO do we need to clear the VAC?
+ */
+ if (pv->pv_pmap == NULL) {
+ splx(s);
+ return;
+ }
+ for (; pv; pv = pv->pv_next) {
+ va = pv->pv_va;
+
+ /*
+ * XXX don't write protect pager mappings
+ */
+ if (bit == PG_RO) {
+ extern vm_offset_t pager_sva, pager_eva;
+
+ if (va >= pager_sva && va < pager_eva)
+ continue;
+ }
+
+ pte = (int *) pmap_pte(pv->pv_pmap, va);
+ if (setem)
+ npte = *pte | bit;
+ else
+ npte = *pte & ~bit;
+ if (*pte != npte) {
+ /*
+ * If we are changing caching status or
+ * protection make sure the caches are
+ * flushed (but only once).
+ */
+#ifdef M68040
+ if (firstpage && cpu040 &&
+ (bit == PG_RO && setem || (bit & PG_CMASK))) {
+ firstpage = FALSE;
+ DCFP(pa);
+ ICPP(pa);
+ }
+#endif
+ *pte = npte;
+ if (active_pmap(pv->pv_pmap))
+ TBIS(va);
+ }
+ }
+ splx(s);
+}
+
+/* static */
+void
+pmap_enter_ptpage(pmap, va)
+ register pmap_t pmap;
+ register vm_offset_t va;
+{
+ register vm_offset_t ptpa;
+ register pv_entry_t pv;
+ u_int *ste;
+ int s;
+ u_int sg_proto, *sg;
+
+#ifdef DEBUG
+ if (pmapdebug & (PDB_FOLLOW|PDB_ENTER|PDB_PTPAGE))
+ printf("pmap_enter_ptpage: pmap %x, va %x\n", pmap, va);
+ enter_stats.ptpneeded++;
+#endif
+ /*
+ * Allocate a segment table if necessary. Note that it is allocated
+ * from kernel_map and not pt_map. This keeps user page tables
+ * aligned on segment boundaries in the kernel address space.
+ * The segment table is wired down. It will be freed whenever the
+ * reference count drops to zero.
+ */
+ if (pmap->pm_stab == Segtabzero) {
+#ifdef M68040
+ if (cpu040) {
+ pmap->pm_rtab = (u_int *)
+ kmem_alloc(kernel_map, ATARI_040RTSIZE);
+ pmap->pm_stab = (u_int *)
+ kmem_alloc(kernel_map, ATARI_040STSIZE*128);
+ /* intialize root table entries */
+ sg = (u_int *) pmap->pm_rtab;
+ sg_proto = pmap_extract(kernel_pmap,
+ (vm_offset_t) pmap->pm_stab) | SG_RW | SG_V;
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
+ printf ("pmap_enter_ptpage: ROOT TABLE SETUP %x %x\n",
+ pmap->pm_rtab, sg_proto);
+#endif
+ while (sg < (u_int *) ((u_int) pmap->pm_rtab + ATARI_040RTSIZE)) {
+ *sg++ = sg_proto;
+ sg_proto += ATARI_040STSIZE;
+ }
+ }
+ else
+#endif
+ pmap->pm_stab = (u_int *)
+ kmem_alloc(kernel_map, ATARI_STSIZE);
+ pmap->pm_stchanged = TRUE;
+ /*
+ * XXX may have changed segment table pointer for current
+ * process so update now to reload hardware.
+ */
+ if (pmap == curproc->p_vmspace->vm_map.pmap)
+ PMAP_ACTIVATE(pmap, (struct pcb *)curproc->p_addr, 1);
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
+ printf("enter: pmap %x stab %x\n",
+ pmap, pmap->pm_stab);
+#endif
+ }
+
+ /*
+ * On the 68040, a page will hold 64 page tables, so the segment
+ * table will have to have 64 entries set up. First get the ste
+ * for the page mapped by the first PT entry.
+ */
+#ifdef M68040
+ if (cpu040) {
+ ste = pmap_ste(pmap, va & (SG4_IMASK << 6));
+ va = trunc_page((vm_offset_t)pmap_pte(pmap, va & (SG4_IMASK << 6)));
+ } else
+#endif
+ {
+ ste = pmap_ste(pmap, va);
+ va = trunc_page((vm_offset_t)pmap_pte(pmap, va));
+ }
+
+ /*
+ * In the kernel we allocate a page from the kernel PT page
+ * free list and map it into the kernel page table map (via
+ * pmap_enter).
+ */
+ if (pmap == kernel_pmap) {
+ register struct kpt_page *kpt;
+
+ s = splimp();
+ if ((kpt = kpt_free_list) == (struct kpt_page *)0) {
+ /*
+ * No PT pages available.
+ * Try once to free up unused ones.
+ */
+#ifdef DEBUG
+ if (pmapdebug & PDB_COLLECT)
+ printf("enter: no KPT pages, collecting...\n");
+#endif
+ pmap_collect(kernel_pmap);
+ if ((kpt = kpt_free_list) == (struct kpt_page *)0)
+ panic("pmap_enter_ptpage: can't get KPT page");
+ }
+#ifdef DEBUG
+ if (++kpt_stats.kptinuse > kpt_stats.kptmaxuse)
+ kpt_stats.kptmaxuse = kpt_stats.kptinuse;
+#endif
+ kpt_free_list = kpt->kpt_next;
+ kpt->kpt_next = kpt_used_list;
+ kpt_used_list = kpt;
+ ptpa = kpt->kpt_pa;
+ bzero(kpt->kpt_va, NBPG);
+ pmap_enter(pmap, va, ptpa, VM_PROT_DEFAULT, TRUE);
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
+ printf("enter: add &Sysptmap[%d]: %x (KPT page %x)\n",
+ ste - pmap_ste(pmap, 0),
+ *(int *)&Sysptmap[ste - pmap_ste(pmap, 0)],
+ kpt->kpt_va);
+#endif
+ splx(s);
+ }
+ /*
+ * For user processes we just simulate a fault on that location
+ * letting the VM system allocate a zero-filled page.
+ */
+ else {
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
+ printf("enter: about to fault UPT pg at %x\n", va);
+#endif
+ if (vm_fault(pt_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE)
+ != KERN_SUCCESS)
+ panic("pmap_enter: vm_fault failed");
+ ptpa = pmap_extract(kernel_pmap, va);
+#ifdef DEBUG
+ PHYS_TO_VM_PAGE(ptpa)->flags |= PG_PTPAGE;
+#endif
+ }
+
+ /*
+ * Locate the PV entry in the kernel for this PT page and
+ * record the STE address. This is so that we can invalidate
+ * the STE when we remove the mapping for the page.
+ */
+ pv = pa_to_pvh(ptpa);
+ s = splimp();
+ if (pv) {
+ pv->pv_flags |= PV_PTPAGE;
+ do {
+ if (pv->pv_pmap == kernel_pmap && pv->pv_va == va)
+ break;
+ } while (pv = pv->pv_next);
+ }
+#ifdef DEBUG
+ if (pv == NULL)
+ panic("pmap_enter_ptpage: PT page not entered");
+#endif
+ pv->pv_ptste = ste;
+ pv->pv_ptpmap = pmap;
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE))
+ printf("enter: new PT page at PA %x, ste at %x\n", ptpa, ste);
+#endif
+
+ /*
+ * Map the new PT page into the segment table.
+ * Also increment the reference count on the segment table if this
+ * was a user page table page. Note that we don't use vm_map_pageable
+ * to keep the count like we do for PT pages, this is mostly because
+ * it would be difficult to identify ST pages in pmap_pageable to
+ * release them. We also avoid the overhead of vm_map_pageable.
+ */
+#ifdef M68040
+ if (cpu040) {
+ /* 68040 has 64 page tables, so we have to map all 64 */
+ sg = (u_int *) ste;
+ sg_proto = (ptpa & SG_FRAME) | SG_RW | SG_V;
+ while (sg < (u_int *) (ste + 64)) {
+ *sg++ = sg_proto;
+ sg_proto += ATARI_040PTSIZE;
+ }
+ }
+ else
+#endif
+ *(int *)ste = (ptpa & SG_FRAME) | SG_RW | SG_V;
+ if (pmap != kernel_pmap) {
+ pmap->pm_sref++;
+#ifdef DEBUG
+ if (pmapdebug & (PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB))
+ printf("enter: stab %x refcnt %d\n",
+ pmap->pm_stab, pmap->pm_sref);
+#endif
+ }
+ /*
+ * Flush stale TLB info.
+ */
+ if (pmap == kernel_pmap)
+ TBIAS();
+ else
+ TBIAU();
+ pmap->pm_ptpages++;
+ splx(s);
+}
+
+int pmap_isvalidphys(pa)
+vm_offset_t pa;
+{
+ if((pa >= st_ramstart) && (pa < st_ramend))
+ return(TRUE);
+ if((pa >= tt_ramstart) && (pa < tt_ramend))
+ return(TRUE);
+ return(FALSE);
+}
+
+#ifdef DEBUG
+pmap_pvdump(pa)
+ vm_offset_t pa;
+{
+ register pv_entry_t pv;
+
+ printf("pa %x", pa);
+ for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next)
+ printf(" -> pmap %x, va %x, ptste %x, ptpmap %x, flags %x",
+ pv->pv_pmap, pv->pv_va, pv->pv_ptste, pv->pv_ptpmap,
+ pv->pv_flags);
+ printf("\n");
+}
+
+pmap_check_wiring(str, va)
+ char *str;
+ vm_offset_t va;
+{
+ vm_map_entry_t entry;
+ register int count, *pte;
+
+ va = trunc_page(va);
+ if (!pmap_ste_v(pmap_ste(kernel_pmap, va)) ||
+ !pmap_pte_v(pmap_pte(kernel_pmap, va)))
+ return;
+
+ if (!vm_map_lookup_entry(pt_map, va, &entry)) {
+ printf("wired_check: entry for %x not found\n", va);
+ return;
+ }
+ count = 0;
+ for (pte = (int *)va; pte < (int *)(va+PAGE_SIZE); pte++)
+ if (*pte)
+ count++;
+ if (entry->wired_count != count)
+ printf("*%s*: %x: w%d/a%d\n",
+ str, va, entry->wired_count, count);
+}
+#endif
diff --git a/sys/arch/atari/atari/stalloc.c b/sys/arch/atari/atari/stalloc.c
new file mode 100644
index 00000000000..7d06439c6aa
--- /dev/null
+++ b/sys/arch/atari/atari/stalloc.c
@@ -0,0 +1,217 @@
+/* $NetBSD: stalloc.c,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman (Atari modifications)
+ * Copyright (c) 1994 Christian E. Hopps (allocator stuff)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+
+#include <atari/atari/misc.h>
+
+/*
+ * St-mem allocator.
+ */
+/*
+ * From atari_init.c
+ */
+extern u_long st_pool_size, st_pool_virt, st_pool_phys;
+
+#define PHYS_ADDR(virt) ((u_long)(virt) - st_pool_virt + st_pool_phys)
+
+static CIRCLEQ_HEAD(stlist, mem_node) st_list;
+static CIRCLEQ_HEAD(freelist, mem_node) free_list;
+static u_long stmem_total; /* total free. */
+
+void
+init_stmem()
+{
+ int s = splhigh ();
+ struct mem_node *mem;
+
+ stmem_total = st_pool_size - sizeof(*mem);
+
+ mem = (struct mem_node *)st_pool_virt;
+ mem->size = st_pool_size - sizeof(*mem);
+
+ CIRCLEQ_INIT(&st_list);
+ CIRCLEQ_INIT(&free_list);
+
+ CIRCLEQ_INSERT_HEAD(&st_list, mem, link);
+ CIRCLEQ_INSERT_HEAD(&free_list, mem, free_link);
+ splx(s);
+}
+
+void *
+alloc_stmem(size, phys_addr)
+u_long size;
+void **phys_addr;
+{
+ struct mem_node *mn, *new;
+ void *mem;
+ int s;
+
+ if (size == 0)
+ return NULL;
+
+ s = splhigh();
+
+ if (size & ~(ST_BLOCKMASK))
+ size = (size & ST_BLOCKMASK) + ST_BLOCKSIZE;
+
+ /*
+ * walk list of available nodes.
+ */
+ mn = free_list.cqh_first;
+ while (size > mn->size && mn != (void *)&free_list)
+ mn = mn->free_link.cqe_next;
+
+ if (mn == (void *)&free_list) {
+ printf("St-mem pool exhausted, binpatch 'st_pool_size'"
+ "to get more\n");
+ return(NULL);
+ }
+
+ if ((mn->size - size) <= sizeof (*mn)) {
+ /*
+ * our allocation would not leave room
+ * for a new node in between.
+ */
+ CIRCLEQ_REMOVE(&free_list, mn, free_link);
+ mn->free_link.cqe_next = NULL;
+ size = mn->size; /* increase size. (or same) */
+ stmem_total -= mn->size;
+ splx(s);
+ *phys_addr = (void*)PHYS_ADDR(&mn[1]);
+ return ((void *)&mn[1]);
+ }
+
+ /*
+ * split the node's memory.
+ */
+ new = mn;
+ new->size -= size + sizeof(struct mem_node);
+ mn = (struct mem_node *)(MNODES_MEM(new) + new->size);
+ mn->size = size;
+
+ /*
+ * add split node to node list
+ * and mark as not on free list
+ */
+ CIRCLEQ_INSERT_AFTER(&st_list, new, mn, link);
+ mn->free_link.cqe_next = NULL;
+
+ stmem_total -= size + sizeof(struct mem_node);
+ splx(s);
+ *phys_addr = (void*)PHYS_ADDR(&mn[1]);
+ return ((void *)&mn[1]);
+}
+
+void
+free_stmem(mem)
+void *mem;
+{
+ struct mem_node *mn, *next, *prev;
+ int s;
+
+ if (mem == NULL)
+ return;
+
+ s = splhigh();
+ mn = (struct mem_node *)mem - 1;
+ next = mn->link.cqe_next;
+ prev = mn->link.cqe_prev;
+
+ /*
+ * check ahead of us.
+ */
+ if (next->link.cqe_next != (void *)&st_list &&
+ next->free_link.cqe_next) {
+ /*
+ * if next is: a valid node and a free node. ==> merge
+ */
+ CIRCLEQ_INSERT_BEFORE(&free_list, next, mn, free_link);
+ CIRCLEQ_REMOVE(&st_list, next, link);
+ CIRCLEQ_REMOVE(&st_list, next, free_link);
+ stmem_total += mn->size + sizeof(struct mem_node);
+ mn->size += next->size + sizeof(struct mem_node);
+ }
+ if (prev->link.cqe_prev != (void *)&st_list &&
+ prev->free_link.cqe_prev) {
+ /*
+ * if prev is: a valid node and a free node. ==> merge
+ */
+ if (mn->free_link.cqe_next == NULL)
+ stmem_total += mn->size + sizeof(struct mem_node);
+ else {
+ /* already on free list */
+ CIRCLEQ_REMOVE(&free_list, mn, free_link);
+ stmem_total += sizeof(struct mem_node);
+ }
+ CIRCLEQ_REMOVE(&st_list, mn, link);
+ prev->size += mn->size + sizeof(struct mem_node);
+ } else if (mn->free_link.cqe_next == NULL) {
+ /*
+ * we still are not on free list and we need to be.
+ * <-- | -->
+ */
+ while (next->link.cqe_next != (void *)&st_list &&
+ prev->link.cqe_prev != (void *)&st_list) {
+ if (next->free_link.cqe_next) {
+ CIRCLEQ_INSERT_BEFORE(&free_list, next, mn,
+ free_link);
+ break;
+ }
+ if (prev->free_link.cqe_next) {
+ CIRCLEQ_INSERT_AFTER(&free_list, prev, mn,
+ free_link);
+ break;
+ }
+ prev = prev->link.cqe_prev;
+ next = next->link.cqe_next;
+ }
+ if (mn->free_link.cqe_next == NULL) {
+ if (next->link.cqe_next == (void *)&st_list) {
+ /*
+ * we are not on list so we can add
+ * ourselves to the tail. (we walked to it.)
+ */
+ CIRCLEQ_INSERT_TAIL(&free_list,mn,free_link);
+ } else {
+ CIRCLEQ_INSERT_HEAD(&free_list,mn,free_link);
+ }
+ }
+ stmem_total += mn->size;/* add our helpings to the pool. */
+ }
+ splx(s);
+}
diff --git a/sys/arch/atari/atari/stalloc.h b/sys/arch/atari/atari/stalloc.h
new file mode 100644
index 00000000000..9257d00c99d
--- /dev/null
+++ b/sys/arch/atari/atari/stalloc.h
@@ -0,0 +1,55 @@
+/* $NetBSD: stalloc.h,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps (allocator stuff)
+ * Copyright (c) 1995 Leo Weppelman (Atari modifications)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ATARI_MISC_H
+#define _ATARI_MISC_H
+/*
+ * St-mem allocator stuff.
+ */
+struct mem_node {
+ CIRCLEQ_ENTRY(mem_node) link;
+ CIRCLEQ_ENTRY(mem_node) free_link;
+ u_long size; /* size of memory following node. */
+};
+
+#define ST_BLOCKSIZE (sizeof(long))
+#define ST_BLOCKMASK (~(ST_BLOCKSIZE - 1))
+#define MNODES_MEM(mn) ((u_char *)(&mn[1]))
+
+void init_stmem __P((void));
+void *alloc_stmem __P((u_long, void **));
+void free_stmem __P((void *));
+
+#endif /* _ATARI_MISC_H */
diff --git a/sys/arch/atari/atari/swapgeneric.c b/sys/arch/atari/atari/swapgeneric.c
new file mode 100644
index 00000000000..42bd4b6d5b3
--- /dev/null
+++ b/sys/arch/atari/atari/swapgeneric.c
@@ -0,0 +1,303 @@
+/* $NetBSD: swapgeneric.c,v 1.1.1.1 1995/03/26 07:12:19 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1982, 1986 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/device.h>
+#include <machine/disklabel.h>
+#include <sys/disklabel.h>
+#include <sys/fcntl.h> /* XXXX and all that uses it */
+#include <sys/proc.h> /* XXXX and all that uses it */
+#include <sys/disk.h>
+
+#include "ramd.h"
+#include "fd.h"
+#include "sd.h"
+#include "cd.h"
+
+/*
+ * Only boot on ufs. (XXX?)
+ */
+int ffs_mountroot();
+int (*mountroot)() = ffs_mountroot;
+
+/*
+ * Generic configuration; all in one
+ */
+dev_t rootdev = NODEV;
+dev_t dumpdev = NODEV;
+
+struct swdevt swdevt[] = {
+ { NODEV, 1, 0 },
+ { NODEV, 0, 0 },
+};
+
+#if NFD > 0
+extern struct cfdriver fdcd;
+#endif
+#if NRAMD > 0
+extern struct cfdriver ramdcd;
+#endif
+#if NSD > 0
+extern struct cfdriver sdcd;
+#endif
+#if NCD > 0
+extern struct cfdriver cdcd;
+#endif
+
+struct genericconf {
+ struct cfdriver *gc_driver;
+ dev_t gc_root;
+};
+
+/*
+ * the system will assign rootdev to the first partition 'a'
+ * found with FS_BSDFFS fstype. so these should be ordered
+ * in preference of boot.
+ */
+static struct genericconf genericconf[] = {
+#if NRAMD > 0
+ {&ramdcd,makedev(1, 0)},
+#endif
+#if NFD > 0
+ {&fdcd, makedev(2, 0)},
+#endif
+#if NSD > 0
+ {&sdcd, makedev(4, 0)},
+#endif
+#if NCD > 0
+ {&cdcd, makedev(6, 0)},
+#endif
+ { 0 },
+};
+
+static void gets __P((char *));
+static struct genericconf *getgenconf __P((char *));
+static struct genericconf *guess_gc __P((int, int *));
+
+
+static struct genericconf *
+getgenconf(bp)
+char *bp;
+{
+ char *cp;
+ struct genericconf *gc;
+
+ for(;;) {
+ printf("format: <dev-name><unit> [ ':'<part> ] [ * ]\n");
+ printf("root device> ");
+ gets(bp);
+ for(gc = genericconf; gc->gc_driver; gc++)
+ if(gc->gc_driver->cd_name[0] == bp[0] &&
+ gc->gc_driver->cd_name[1] == bp[1])
+ break;
+ if(gc->gc_driver == NULL) {
+ printf("use one of:");
+ for(gc = genericconf; gc->gc_driver; gc++)
+ printf(" %s%%d", gc->gc_driver->cd_name);
+ printf("\n");
+ continue;
+ }
+ cp = bp + 2;
+ if(*cp >= '0' && *cp <= '9')
+ break;
+ printf("bad/missing unit number\n");
+ }
+ return(gc);
+}
+
+setconf()
+{
+ struct genericconf *gc;
+ int unit, swaponroot, part;
+ char name[128];
+ char *cp;
+
+ swaponroot = 0;
+ part = 0;
+ unit = 0;
+
+ if(rootdev != NODEV)
+ goto justdoswap;
+
+ if(boothowto & RB_ASKNAME) {
+ gc = getgenconf(name);
+ cp = name + 2;
+
+ /*
+ * Get unit number
+ */
+ while(*cp >= '0' && *cp <= '9')
+ unit = 10 * unit + *cp++ - '0';
+
+ /*
+ * And maybe partition...
+ * This is only usefull when booting from floppy. So it is
+ * possible to select the correct density.
+ */
+ if(*cp == ':') {
+ cp++;
+ while(*cp >= '0' && *cp <= '9')
+ part = 10 * part + *cp++ - '0';
+ }
+
+ if(*cp == '*')
+ swaponroot = 1;
+ unit &= 0x7;
+ }
+ else {
+ gc = guess_gc(1, &unit);
+
+ if(gc == NULL) {
+ printf("no suitable root\n");
+ asm("stop #0x2700");
+ }
+ /*NOTREACHED*/
+ }
+
+ gc->gc_root = MAKEDISKDEV(major(gc->gc_root), unit, part);
+ rootdev = gc->gc_root;
+
+
+justdoswap:
+ if(!swaponroot) {
+ /* Find a suitable swap device */
+ if((gc = guess_gc(0, &unit)) == NULL) {
+ swdevt[0].sw_dev = dumpdev =
+ MAKEDISKDEV(major(rootdev),DISKUNIT(rootdev),1);
+ }
+ else {
+ swdevt[0].sw_dev = dumpdev =
+ MAKEDISKDEV(major(gc->gc_root),unit,1);
+ }
+ }
+
+ /* swap size and dumplo set during autoconfigure */
+ if (swaponroot)
+ rootdev = dumpdev;
+}
+
+static void
+gets(cp)
+char *cp;
+{
+ register char *lp;
+ register int c;
+
+ lp = cp;
+ for (;;) {
+ cnputc(c = cngetc());
+ switch (c) {
+ case '\n':
+ case '\r':
+ *lp = 0;
+ return;
+ case '\b':
+ case '\177':
+ if (lp > cp) {
+ lp--;
+ cnputc(' ');
+ cnputc('\b');
+ }
+ continue;
+ case '#':
+ lp--;
+ if (lp < cp)
+ lp = cp;
+ continue;
+ case '@':
+ case 'u'&037:
+ lp = cp;
+ cnputc('\n');
+ continue;
+ default:
+ *lp++ = c;
+ }
+ }
+}
+
+static struct genericconf *
+guess_gc(search_root, rv_unit)
+int search_root;
+int *rv_unit;
+{
+ struct genericconf *gc;
+ struct partition *pp;
+ struct dkdevice *dkp;
+ struct bdevsw *bdp;
+ int unit;
+
+ for(gc = genericconf; gc->gc_driver; gc++) {
+ for(unit = 0; unit < gc->gc_driver->cd_ndevs; unit++) {
+ if(gc->gc_driver->cd_devs[unit] == NULL)
+ continue;
+ /*
+ * this is a hack these drivers should use
+ * dk_dev and not another instance directly above.
+ */
+ dkp = (struct dkdevice *)
+ ((struct device *)gc->gc_driver->cd_devs[unit] + 1);
+ if(dkp->dk_driver == NULL || dkp->dk_driver->d_strategy == NULL)
+ continue;
+ for(bdp = bdevsw; bdp < (bdevsw + nblkdev); bdp++)
+ if(bdp->d_strategy == dkp->dk_driver->d_strategy)
+ break;
+ if(bdp->d_open(MAKEDISKDEV(major(gc->gc_root),
+ unit, 3), FREAD | FNONBLOCK, 0, curproc))
+ continue;
+ bdp->d_close(MAKEDISKDEV(major(gc->gc_root), unit, 3),
+ FREAD | FNONBLOCK, 0, curproc);
+ if(search_root) {
+ pp = &dkp->dk_label.d_partitions[0];
+ if(pp->p_size == 0 || pp->p_fstype != FS_BSDFFS)
+ continue;
+ }
+ else { /* must be swap */
+ pp = &dkp->dk_label.d_partitions[1];
+ if(pp->p_size == 0 || pp->p_fstype != FS_SWAP)
+ continue;
+ }
+ goto found;
+ }
+ }
+ return(NULL);
+found:
+ *rv_unit = unit;
+ return(gc);
+}
diff --git a/sys/arch/atari/atari/sys_machdep.c b/sys/arch/atari/atari/sys_machdep.c
new file mode 100644
index 00000000000..785b4cf5e05
--- /dev/null
+++ b/sys/arch/atari/atari/sys_machdep.c
@@ -0,0 +1,283 @@
+/* $NetBSD: sys_machdep.c,v 1.1.1.1 1995/03/26 07:12:18 leo Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986 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.
+ *
+ * @(#)sys_machdep.c 7.7 (Berkeley) 5/7/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/mtio.h>
+#include <sys/buf.h>
+#include <sys/trace.h>
+
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+#include <vm/vm.h>
+
+#ifdef TRACE
+int nvualarm;
+
+vtrace(p, uap, retval)
+ struct proc *p;
+ register struct vtrace_args /* {
+ syscallarg(int) request;
+ syscallarg(int) value;
+ } */ *uap;
+ register_t *retval;
+{
+ int vdoualarm();
+
+ switch(SCARG(uap, request)) {
+
+ case VTR_DISABLE: /* disable a trace point */
+ case VTR_ENABLE: /* enable a trace point */
+ if(SCARG(uap, value) < 0 || SCARG(uap,value) >= TR_NFLAGS)
+ return (EINVAL);
+ *retval = traceflags[SCARG(uap,value)];
+ traceflags[SCARG(uap, value)] = SCARG(uap, request);
+ break;
+
+ case VTR_VALUE: /* return a trace point setting */
+ if(SCARG(uap, value) < 0 || SCARG(uap, value) >= TR_NFLAGS)
+ return (EINVAL);
+ *retval = traceflags[SCARG(uap, value)];
+ break;
+
+ case VTR_UALARM: /* set a real-time ualarm, less than 1 min */
+ if(SCARG(uap, value) <= 0 || SCARG(uap, value) > 60 * hz
+ || nvualarm > 5)
+ return (EINVAL);
+ nvualarm++;
+ timeout(vdoualarm, (caddr_t)p->p_pid, SCARG(uap, value));
+ break;
+
+ case VTR_STAMP:
+ trace(TR_STAMP, SCARG(uap, value), p->p_pid);
+ break;
+ }
+ return (0);
+}
+
+vdoualarm(arg)
+ int arg;
+{
+ register struct proc *p;
+
+ p = pfind(arg);
+ if (p)
+ psignal(p, 16);
+ nvualarm--;
+}
+#endif
+
+#include <machine/cpu.h>
+
+/* XXX should be in an include file somewhere */
+#define CC_PURGE 1
+#define CC_FLUSH 2
+#define CC_IPURGE 4
+#define CC_EXTPURGE 0x80000000
+/* XXX end should be */
+
+/*ARGSUSED1*/
+cachectl(req, addr, len)
+ int req;
+ caddr_t addr;
+ int len;
+{
+ int error = 0;
+#ifdef M68040
+ if (cpu040) {
+ register int inc = 0;
+ int pa = 0, doall = 0;
+ caddr_t end;
+
+ if (addr == 0 ||
+ (req & ~CC_EXTPURGE) != CC_PURGE && len > 2*NBPG)
+ doall = 1;
+ if (!doall) {
+ end = addr + len;
+ if (len <= 1024) {
+ addr = (caddr_t)((int)addr & ~0xF);
+ inc = 16;
+ } else {
+ addr = (caddr_t)((int)addr & ~PGOFSET);
+ inc = NBPG;
+ }
+ }
+ do {
+ /*
+ * Convert to physical address if needed.
+ * If translation fails, we perform operation on
+ * entire cache (XXX is this a rational thing to do?)
+ */
+ if (!doall &&
+ (pa == 0 || ((int)addr & PGOFSET) == 0)) {
+ pa = pmap_extract(&curproc->p_vmspace->vm_pmap,
+ (vm_offset_t)addr);
+ if (pa == 0)
+ doall = 1;
+ }
+ switch (req) {
+ case CC_EXTPURGE|CC_IPURGE:
+ case CC_IPURGE:
+ if (doall) {
+ DCFA();
+ ICPA();
+ } else if (inc == 16) {
+ DCFL(pa);
+ ICPL(pa);
+ } else if (inc == NBPG) {
+ DCFP(pa);
+ ICPP(pa);
+ }
+ break;
+
+ case CC_EXTPURGE|CC_PURGE:
+ case CC_PURGE:
+ if (doall)
+ DCFA(); /* note: flush not purge */
+ else if (inc == 16)
+ DCPL(pa);
+ else if (inc == NBPG)
+ DCPP(pa);
+ break;
+
+ case CC_EXTPURGE|CC_FLUSH:
+ case CC_FLUSH:
+ if (doall)
+ DCFA();
+ else if (inc == 16)
+ DCFL(pa);
+ else if (inc == NBPG)
+ DCFP(pa);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ if (doall)
+ break;
+ pa += inc;
+ addr += inc;
+ } while (addr < end);
+ return(error);
+ }
+#endif /* M68040 */
+
+ switch (req) {
+ case CC_EXTPURGE|CC_PURGE:
+ case CC_EXTPURGE|CC_FLUSH:
+ case CC_PURGE:
+ case CC_FLUSH:
+ DCIU();
+ break;
+ case CC_EXTPURGE|CC_IPURGE:
+ DCIU();
+ /*FALLTHROUGH*/
+ case CC_IPURGE:
+ ICIA();
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return(error);
+}
+
+/*
+ * DMA cache control
+ */
+
+/*ARGSUSED1*/
+dma_cachectl(addr, len)
+ caddr_t addr;
+ int len;
+{
+#ifdef M68040
+ if (cpu040) {
+ register int inc = 0;
+ int pa = 0;
+ caddr_t end;
+
+ end = addr + len;
+ if (len <= 1024) {
+ addr = (caddr_t)((int)addr & ~0xF);
+ inc = 16;
+ } else {
+ addr = (caddr_t)((int)addr & ~PGOFSET);
+ inc = NBPG;
+ }
+ do {
+ /*
+ * Convert to physical address.
+ */
+ if (pa == 0 || ((int)addr & PGOFSET) == 0) {
+ pa = kvtop ((vm_offset_t)addr);
+ }
+ if (inc == 16) {
+ DCFL(pa);
+ ICPL(pa);
+ } else {
+ DCFP(pa);
+ ICPP(pa);
+ }
+ pa += inc;
+ addr += inc;
+ } while (addr < end);
+ }
+#endif /* M68040 */
+ return(0);
+}
+
+int
+sysarch(p, uap, retval)
+ struct proc *p;
+ struct sysarch_args /* {
+ syscallarg(int) op;
+ syscallarg(char*)parms;
+ } */ *uap;
+ register_t *retval;
+{
+ return ENOSYS;
+}
+
diff --git a/sys/arch/atari/atari/trap.c b/sys/arch/atari/atari/trap.c
new file mode 100644
index 00000000000..3b62631d4d4
--- /dev/null
+++ b/sys/arch/atari/atari/trap.c
@@ -0,0 +1,968 @@
+/* $NetBSD: trap.c,v 1.1.1.1 1995/03/26 07:12:18 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * from: Utah $Hdr: trap.c 1.32 91/04/06$
+ *
+ * @(#)trap.c 7.15 (Berkeley) 8/2/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/acct.h>
+#include <sys/kernel.h>
+#include <sys/signalvar.h>
+#include <sys/resourcevar.h>
+#include <sys/syslog.h>
+#include <sys/syscall.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+
+#include <vm/vm.h>
+#include <sys/user.h>
+#include <vm/pmap.h>
+
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/mtpr.h>
+#include <machine/pte.h>
+
+#ifdef COMPAT_SUNOS
+#include <compat/sunos/sunos_syscall.h>
+struct sysent sunos_sysent[];
+int nsunos_sysent;
+#endif
+
+/*
+ * XXX Hack until I can figure out what to do about this code's removal
+ * from m68k/include/frame.h
+ */
+
+/* 68040 fault frame */
+#define SSW_CP 0x8000 /* Continuation - Floating-Point Post*/
+#define SSW_CU 0x4000 /* Continuation - Unimpl. FP */
+#define SSW_CT 0x2000 /* Continuation - Trace */
+#define SSW_CM 0x1000 /* Continuation - MOVEM */
+#define SSW_MA 0x0800 /* Misaligned access */
+#define SSW_ATC 0x0400 /* ATC fault */
+#define SSW_LK 0x0200 /* Locked transfer */
+#define SSW_RW040 0x0100 /* Read/Write */
+#define SSW_SZMASK 0x0060 /* Transfer size */
+#define SSW_TTMASK 0x0018 /* Transfer type */
+#define SSW_TMMASK 0x0007 /* Transfer modifier */
+
+#define WBS_TMMASK 0x0007
+#define WBS_TTMASK 0x0018
+#define WBS_SZMASK 0x0060
+#define WBS_VALID 0x0080
+
+#define WBS_SIZE_BYTE 0x0020
+#define WBS_SIZE_WORD 0x0040
+#define WBS_SIZE_LONG 0x0000
+#define WBS_SIZE_LINE 0x0060
+
+#define WBS_TT_NORMAL 0x0000
+#define WBS_TT_MOVE16 0x0008
+#define WBS_TT_ALTFC 0x0010
+#define WBS_TT_ACK 0x0018
+
+#define WBS_TM_PUSH 0x0000
+#define WBS_TM_UDATA 0x0001
+#define WBS_TM_UCODE 0x0002
+#define WBS_TM_MMUTD 0x0003
+#define WBS_TM_MMUTC 0x0004
+#define WBS_TM_SDATA 0x0005
+#define WBS_TM_SCODE 0x0006
+#define WBS_TM_RESV 0x0007
+
+#define MMUSR_PA_MASK 0xfffff000
+#define MMUSR_B 0x00000800
+#define MMUSR_G 0x00000400
+#define MMUSR_U1 0x00000200
+#define MMUSR_U0 0x00000100
+#define MMUSR_S 0x00000080
+#define MMUSR_CM 0x00000060
+#define MMUSR_M 0x00000010
+#define MMUSR_0 0x00000008
+#define MMUSR_W 0x00000004
+#define MMUSR_T 0x00000002
+#define MMUSR_R 0x00000001
+/*
+ * XXX End hack
+ */
+char *trap_type[] = {
+ "Bus error",
+ "Address error",
+ "Illegal instruction",
+ "Zero divide",
+ "CHK instruction",
+ "TRAPV instruction",
+ "Privilege violation",
+ "Trace trap",
+ "MMU fault",
+ "SSIR trap",
+ "Format error",
+ "68881 exception",
+ "Coprocessor violation",
+ "Async system trap"
+};
+int trap_types = sizeof trap_type / sizeof trap_type[0];
+
+/*
+ * Size of various exception stack frames (minus the standard 8 bytes)
+ */
+short exframesize[] = {
+ FMT0SIZE, /* type 0 - normal (68020/030/040) */
+ FMT1SIZE, /* type 1 - throwaway (68020/030/040) */
+ FMT2SIZE, /* type 2 - normal 6-word (68020/030/040) */
+ FMT3SIZE, /* type 3 - FP post-instruction (68040) */
+ -1, -1, -1, /* type 4-6 - undefined */
+ FMT7SIZE, /* type 7 - access error (68040) */
+ 58, /* type 8 - bus fault (68010) */
+ FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */
+ FMTASIZE, /* type A - short bus fault (68020/030) */
+ FMTBSIZE, /* type B - long bus fault (68020/030) */
+ -1, -1, -1, -1 /* type C-F - undefined */
+};
+
+#ifdef DEBUG
+int mmudebug = 0;
+#endif
+
+extern struct pcb *curpcb;
+int fubail();
+int subail();
+
+static void
+userret(p, pc, oticks)
+ struct proc *p;
+ int pc;
+ u_quad_t oticks;
+{
+ int sig, s;
+
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+
+ p->p_priority = p->p_usrpri;
+
+ if (want_resched) {
+ /*
+ * Since we are curproc, clock will normally just change
+ * our priority without moving us from one queue to another
+ * (since the running process is not on a queue.)
+ * If that 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();
+ splx(s);
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+ }
+ /*
+ * If profiling, charge recent system time.
+ */
+ if (p->p_flag & P_PROFIL) {
+ extern int psratio;
+
+ addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
+ }
+ curpriority = p->p_priority;
+}
+
+void
+panictrap(type, code, v, fp)
+ int type;
+ u_int code, v;
+ struct frame *fp;
+{
+ static int panicing = 0;
+ if (panicing++ == 0) {
+ printf("trap type %d, code = %x, v = %x\n", type, code, v);
+ regdump(fp, 128);
+ }
+ type &= ~T_USER;
+ DCIS(); /* XXX? push cache */
+ if ((u_int)type < trap_types)
+ panic(trap_type[type]);
+ panic("trap");
+ /*NOTREACHED*/
+}
+
+/*
+ * return to fault handler
+ */
+void
+trapcpfault(p, fp)
+ struct proc *p;
+ struct frame *fp;
+{
+ /*
+ * We have arranged to catch this fault in one of the
+ * copy to/from user space routines, set PC to return to
+ * indicated location and set flag informing buserror code
+ * that it may need to clean up stack frame.
+ */
+ fp->f_stackadj = exframesize[fp->f_format];
+ fp->f_format = fp->f_vector = 0;
+ fp->f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
+}
+
+void
+trapmmufault(type, code, v, fp, p, sticks)
+ int type;
+ u_int code, v;
+ struct frame *fp;
+ struct proc *p;
+ u_quad_t sticks;
+{
+ extern vm_map_t kernel_map;
+ struct vmspace *vm;
+ vm_prot_t ftype;
+ vm_offset_t va;
+ vm_map_t map;
+ u_int nss;
+ int rv;
+
+ vm = p->p_vmspace;
+
+ /*
+ * It is only a kernel address space fault iff:
+ * 1. (type & T_USER) == 0 and
+ * 2. pcb_onfault not set or
+ * 3. pcb_onfault set but supervisor space data fault
+ * The last can occur during an exec() copyin where the
+ * argument space is lazy-allocated.
+ */
+#ifdef DEBUG
+ /*
+ * Print out some data about the fault
+ */
+ if (mmudebug && cpu040) {
+ printf ("68040 access error: pc %x, code %x,"
+ " ea %x, fa %x\n", fp->f_pc, code, fp->f_fmt7.f_ea, v);
+ if (curpcb)
+ printf (" curpcb %x ->pcb_ustp %x / %x\n",
+ curpcb, curpcb->pcb_ustp,
+ curpcb->pcb_ustp << PG_SHIFT);
+ }
+#endif
+ if (type == T_MMUFLT &&
+ (p->p_addr->u_pcb.pcb_onfault == 0 ||
+ (cpu040 && (code & SSW_TMMASK) == FC_SUPERD) ||
+ (!cpu040 && (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))))
+ map = kernel_map;
+ else
+ map = &vm->vm_map;
+ if (
+ (cpu040 && (code & SSW_RW040) == 0) ||
+ (!cpu040 && (code & (SSW_DF|SSW_RW)) ==
+ SSW_DF)) /* what about RMW? */
+ ftype = VM_PROT_READ | VM_PROT_WRITE;
+ else
+ ftype = VM_PROT_READ;
+ va = trunc_page((vm_offset_t)v);
+#ifdef DEBUG
+ if (map == kernel_map && va == 0) {
+ printf("trap: bad kernel access at %x\n", v);
+ panictrap(type, code, v, fp);
+ }
+#endif
+#ifndef no_386bsd_code
+ /*
+ * XXX: rude hack to make stack limits "work"
+ */
+ nss = 0;
+ if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
+ nss = clrnd(btoc(USRSTACK - (unsigned)va));
+ if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
+ rv = KERN_FAILURE;
+ goto nogo;
+ }
+ }
+#endif
+
+#ifdef DEBUG
+ if (mmudebug)
+ printf("vm_fault(%x,%x,%d,0)\n", map, va, ftype);
+#endif
+
+ rv = vm_fault(map, va, ftype, FALSE);
+
+#ifdef DEBUG
+ if (mmudebug)
+ printf("vmfault %s %x returned %d\n",
+ map == kernel_map ? "kernel" : "user", va, rv);
+#endif
+ if (cpu040) {
+ if(rv != KERN_SUCCESS) {
+ goto nogo;
+ }
+
+ /*
+ * The 68040 doesn't re-run instructions that cause
+ * write page faults (unless due to a move16 isntruction).
+ * So once the page is repaired, we have to write the
+ * value of WB2D out to memory ourselves. Because
+ * the writeback could possibly span two pages in
+ * memory, so we need to check both "ends" of the
+ * address to see if they are in the same page or not.
+ * If not, then we need to make sure the second page
+ * is valid, and bring it into memory if it's not.
+ *
+ * This whole process needs to be repeated for WB3 as well.
+ * <sigh>
+ */
+
+ /* Check WB1 */
+ if (fp->f_fmt7.f_wb1s & WBS_VALID) {
+ printf ("trap: wb1 was valid, not handled yet\n");
+ panictrap(type, code, v, fp);
+ }
+
+ /*
+ * Check WB2
+ * skip if it's for a move16 instruction
+ */
+ if(fp->f_fmt7.f_wb2s & WBS_VALID &&
+ ((fp->f_fmt7.f_wb2s & WBS_TTMASK)==WBS_TT_MOVE16) == 0) {
+ if (_write_back(2, fp->f_fmt7.f_wb2s,
+ fp->f_fmt7.f_wb2d, fp->f_fmt7.f_wb2a, map)
+ != KERN_SUCCESS)
+ goto nogo;
+ if ((fp->f_fmt7.f_wb2s & WBS_TMMASK)
+ != (code & SSW_TMMASK))
+ panictrap(type, code, v, fp);
+ }
+
+ /* Check WB3 */
+ if(fp->f_fmt7.f_wb3s & WBS_VALID) {
+ vm_map_t wb3_map;
+
+ if ((fp->f_fmt7.f_wb3s & WBS_TMMASK) == WBS_TM_SDATA)
+ wb3_map = kernel_map;
+ else
+ wb3_map = &vm->vm_map;
+ if (_write_back(3, fp->f_fmt7.f_wb3s,
+ fp->f_fmt7.f_wb3d, fp->f_fmt7.f_wb3a, wb3_map)
+ != KERN_SUCCESS)
+ goto nogo;
+ }
+ }
+
+#ifdef no_386bsd_code
+ /*
+ * If this was a stack access we keep track of the maximum
+ * accessed stack size. Also, if vm_fault gets a protection
+ * failure it is due to accessing the stack region outside
+ * the current limit and we need to reflect that as an access
+ * error.
+ */
+ if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
+ if (rv == KERN_SUCCESS) {
+ nss = clrnd(btoc(USRSTACK-(unsigned)va));
+ if (nss > vm->vm_ssize)
+ vm->vm_ssize = nss;
+ } else if (rv == KERN_PROTECTION_FAILURE)
+ rv = KERN_INVALID_ADDRESS;
+ }
+
+ if (rv == KERN_SUCCESS) {
+ if (type == T_MMUFLT)
+ return;
+ userret(p, fp->f_pc, sticks);
+ reutrn;
+ }
+#else /* use hacky 386bsd_code */
+ if (rv == KERN_SUCCESS) {
+ /*
+ * XXX: continuation of rude stack hack
+ */
+ if (nss > vm->vm_ssize)
+ vm->vm_ssize = nss;
+ if (type == T_MMUFLT)
+ return;
+ userret(p, fp->f_pc, sticks);
+ return;
+ }
+nogo:
+#endif
+ if (type == T_MMUFLT) {
+ if (p->p_addr->u_pcb.pcb_onfault) {
+ trapcpfault(p, fp);
+ return;
+ }
+ printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+ map, va, ftype, rv);
+ printf(" type %x, code [mmu,,ssw]: %x\n",
+ type, code);
+ panictrap(type, code, v, fp);
+ }
+ trapsignal(p, (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV, v);
+ if ((type & T_USER) == 0)
+ return;
+ userret(p, fp->f_pc, sticks);
+}
+/*
+ * Trap is called from locore to handle most types of processor traps,
+ * including events such as simulated software interrupts/AST's.
+ * System calls are broken out for efficiency.
+ */
+/*ARGSUSED*/
+trap(type, code, v, frame)
+ int type;
+ u_int code, v;
+ struct frame frame;
+{
+ struct proc *p;
+ u_int ncode, ucode;
+ u_quad_t sticks;
+ int i, s;
+
+ p = curproc;
+ ucode = 0;
+ cnt.v_trap++;
+
+ if (USERMODE(frame.f_sr)) {
+ type |= T_USER;
+ sticks = p->p_sticks;
+ p->p_md.md_regs = frame.f_regs;
+ }
+
+#ifdef DDB
+ if (type == T_TRACE || type == T_BREAKPOINT) {
+ if (kdb_trap(type, &frame))
+ return;
+ }
+#endif
+
+ switch (type) {
+ default:
+ panictrap(type, code, v, &frame);
+ /*
+ * Kernel Bus error
+ */
+ case T_BUSERR:
+ if (!p->p_addr->u_pcb.pcb_onfault)
+ panictrap(type, code, v, &frame);
+ trapcpfault(p, &frame);
+ return;
+ /*
+ * User Bus/Addr error.
+ */
+ case T_BUSERR|T_USER:
+ case T_ADDRERR|T_USER:
+ i = SIGBUS;
+ break;
+ /*
+ * User illegal/privleged inst fault
+ */
+ case T_ILLINST|T_USER:
+ case T_PRIVINST|T_USER:
+ ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
+ i = SIGILL;
+ break;
+ /*
+ * divde by zero, CHK/TRAPV inst
+ */
+ case T_ZERODIV|T_USER:
+ case T_CHKINST|T_USER:
+ case T_TRAPVINST|T_USER:
+ ucode = frame.f_format;
+ i = SIGFPE;
+ break;
+#ifdef FPCOPROC
+ /*
+ * User coprocessor violation
+ */
+ case T_COPERR|T_USER:
+ ucode = 0;
+ i = SIGFPE; /* XXX What is a proper response here? */
+ break;
+ /*
+ * 6888x exceptions
+ */
+ case T_FPERR|T_USER:
+ /*
+ * We pass along the 68881 status register which locore
+ * stashed in code for us. Note that there is a
+ * possibility that the bit pattern of this register
+ * will conflict with one of the FPE_* codes defined
+ * in signal.h. Fortunately for us, the only such
+ * codes we use are all in the range 1-7 and the low
+ * 3 bits of the status register are defined as 0 so
+ * there is no clash.
+ */
+ ucode = code;
+ i = SIGFPE;
+ break;
+ /*
+ * Kernel coprocessor violation
+ */
+ case T_COPERR:
+ /*FALLTHROUGH*/
+#endif
+ /*
+ * Kernel format error
+ */
+ case T_FMTERR:
+ /*
+ * The user has most likely trashed the RTE or FP state info
+ * in the stack frame of a signal handler.
+ */
+ type |= T_USER;
+#ifdef DEBUG
+ printf("pid %d: kernel %s exception\n", p->p_pid,
+ type==T_COPERR ? "coprocessor" : "format");
+#endif
+ p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
+ i = sigmask(SIGILL);
+ p->p_sigignore &= ~i;
+ p->p_sigcatch &= ~i;
+ p->p_sigmask &= ~i;
+ i = SIGILL;
+ ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
+ break;
+ /*
+ * Trace traps.
+ *
+ * M68k NetBSD uses trap #2,
+ * SUN 3.x uses trap #15,
+ * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
+ *
+ * Atari traps get mapped by locore.s into T_TRACE.
+ * SUN 3.x traps get passed through as T_TRAP15 and are not really
+ * supported yet.
+ */
+ case T_TRACE:
+ case T_TRAP15:
+ frame.f_sr &= ~PSL_T;
+ i = SIGTRAP;
+ break;
+ case T_TRACE|T_USER:
+ case T_TRAP15|T_USER:
+#ifdef COMPAT_SUNOS
+ /*
+ * XXX This comment/code is not consistent XXX
+ * SunOS seems to use Trap #2 for some obscure
+ * fpu operations. So far, just ignore it, but
+ * DONT trap on it..
+ */
+ if (p->p_emul == EMUL_SUNOS) {
+ userret(p, frame.f_pc, sticks);
+ return;
+ }
+#endif
+ frame.f_sr &= ~PSL_T;
+ i = SIGTRAP;
+ break;
+ /*
+ * Kernel AST (should not happen)
+ */
+ case T_ASTFLT:
+ panictrap(type, code, v, &frame);
+ /*
+ * User AST
+ */
+ case T_ASTFLT|T_USER:
+ astpending = 0;
+ /*
+ * We check for software interrupts first. This is because
+ * they are at a higher level than ASTs, and on a VAX would
+ * interrupt the AST. We assume that if we are processing
+ * an AST that we must be at IPL0 so we don't bother to
+ * check. Note that we ensure that we are at least at SIR
+ * IPL while processing the SIR.
+ */
+ spl1();
+ /*FALLTHROUGH*/
+ /*
+ * Software interrupt
+ */
+ case T_SSIR:
+ case T_SSIR|T_USER:
+ if (ssir & SIR_NET) {
+ siroff(SIR_NET);
+ cnt.v_soft++;
+ netintr();
+ }
+ if (ssir & SIR_CLOCK) {
+ siroff(SIR_CLOCK);
+ cnt.v_soft++;
+ /* XXXX softclock(&frame.f_stackadj); */
+ softclock();
+ }
+ /*
+ * If this was not an AST trap, we are all done.
+ */
+ if (type != (T_ASTFLT|T_USER)) {
+ cnt.v_trap--;
+ return;
+ }
+ spl0();
+ if (p->p_flag & P_OWEUPC) {
+ p->p_flag &= ~P_OWEUPC;
+ ADDUPROF(p);
+ }
+ userret(p, frame.f_pc, sticks);
+ return;
+ /*
+ * Kernel/User page fault
+ */
+ case T_MMUFLT:
+ if (p->p_addr->u_pcb.pcb_onfault == (caddr_t)fubail ||
+ p->p_addr->u_pcb.pcb_onfault == (caddr_t)subail) {
+ trapcpfault(p, &frame);
+ return;
+ }
+ /*FALLTHROUGH*/
+ case T_MMUFLT|T_USER: /* page fault */
+ trapmmufault(type, code, v, &frame, p, sticks);
+ return;
+ }
+
+ trapsignal(p, i, ucode);
+ if ((type & T_USER) == 0)
+ return;
+ userret(p, frame.f_pc, sticks);
+}
+
+/*
+ * Proces a system call.
+ */
+syscall(code, frame)
+ u_int code;
+ struct frame frame;
+{
+ struct sysent *callp;
+ struct sysent *systab;
+ int rval[2], args[8], error, opc, numsys, s, i;
+ caddr_t params;
+ u_quad_t sticks;
+ struct proc *p;
+
+ if (USERMODE(frame.f_sr) == 0)
+ panic("syscall");
+
+ cnt.v_syscall++;
+
+ p = curproc;
+ p->p_md.md_regs = frame.f_regs;
+ p->p_md.md_flags &= ~MDP_STACKADJ;
+ sticks = p->p_sticks;
+ opc = frame.f_pc - 2;
+ error = 0;
+
+ switch (p->p_emul) {
+#ifdef COMPAT_SUNOS
+ case EMUL_SUNOS:
+ systab = sunos_sysent;
+ numsys = nsunos_sysent;
+
+ /*
+ * SunOS passes the syscall-number on the stack, whereas
+ * BSD passes it in D0. So, we have to get the real "code"
+ * from the stack, and clean up the stack, as SunOS glue
+ * code assumes the kernel pops the syscall argument the
+ * glue pushed on the stack. Sigh...
+ */
+ code = fuword ((caddr_t) frame.f_regs[SP]);
+
+ /*
+ * XXX don't do this for sunos_sigreturn, as there's no
+ * XXX stored pc on the stack to skip, the argument follows
+ * XXX the syscall number without a gap.
+ */
+ if (code != SUNOS_SYS_sigreturn) {
+ frame.f_regs[SP] += sizeof (int);
+ /*
+ * remember that we adjusted the SP,
+ * might have to undo this if the system call
+ * returns ERESTART.
+ */
+ p->p_md.md_flags |= MDP_STACKADJ;
+ }
+ break;
+#endif
+ case EMUL_NETBSD:
+ default:
+ systab = sysent;
+ numsys = nsysent;
+ break;
+ }
+
+ params = (caddr_t)frame.f_regs[SP] + sizeof(int);
+
+ switch (code) {
+ case SYS_syscall:
+ /*
+ * Code is first argument, followed by actual args.
+ */
+ code = fuword(params);
+ params += sizeof(int);
+ /*
+ * XXX sigreturn requires special stack manipulation
+ * that is only done if entered via the sigreturn
+ * trap. Cannot allow it here so make sure we fail.
+ */
+ if (code == SYS_sigreturn)
+ code = numsys;
+ break;
+ case SYS___syscall:
+ /*
+ * Like syscall, but code is a quad, so as to maintain
+ * quad alignment for the rest of the arguments.
+ */
+ if (systab != sysent)
+ break;
+ code = fuword(params + _QUAD_LOWWORD * sizeof(int));
+ params += sizeof(quad_t);
+ break;
+ default:
+ break;
+ }
+
+ callp = systab;
+ if (code < numsys)
+ callp += code;
+ else
+ callp += SYS_syscall; /* => nosys */
+
+ i = callp->sy_argsize;
+ if (i != 0)
+ error = copyin(params, (caddr_t)args, (u_int)i);
+
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p->p_tracep, code, callp->sy_narg, i, args);
+#endif
+#ifdef SYSCALL_DEBUG
+ if (p->p_emul == EMUL_NETBSD) /* XXX */
+ scdebug_call(p, code, callp->sy_narg, i, args);
+#endif
+ if (error == 0) {
+ rval[0] = 0;
+ rval[1] = frame.f_regs[D1];
+ error = (*callp->sy_call)(p, &args, rval);
+ }
+
+ switch (error) {
+ case 0:
+ frame.f_regs[D0] = rval[0];
+ frame.f_regs[D1] = rval[1];
+ frame.f_sr &= ~PSL_C;
+ break;
+ case ERESTART:
+ frame.f_pc = opc;
+ break;
+ case EJUSTRETURN:
+ break;
+ default:
+ frame.f_regs[D0] = error;
+ frame.f_sr |= PSL_C; /* carry bit */
+ break;
+ }
+ /*
+ * Reinitialize proc pointer `p' as it may be different
+ * if this is a child returning from fork syscall.
+ */
+ p = curproc;
+#ifdef SYSCALL_DEBUG
+ if (p->p_emul == EMUL_NETBSD) /* XXX */
+ scdebug_ret(p, code, error, rval[0]);
+#endif
+#ifdef COMPAT_SUNOS
+ /* need new p-value for this */
+ if (error == ERESTART && (p->p_md.md_flags & MDP_STACKADJ)) {
+ frame.f_regs[SP] -= sizeof (int);
+ p->p_md.md_flags &= ~MDP_STACKADJ;
+ }
+#endif
+ userret(p, frame.f_pc, sticks);
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET))
+ ktrsysret(p->p_tracep, code, error, rval[0]);
+#endif
+}
+
+/*
+ * Process a pending write back
+ */
+_write_back (wb, wb_sts, wb_data, wb_addr, wb_map)
+ u_int wb; /* writeback type: 1, 2, or 3 */
+ u_int wb_sts; /* writeback status information */
+ u_int wb_data; /* data to writeback */
+ u_int wb_addr; /* address to writeback to */
+ vm_map_t wb_map;
+{
+ u_int wb_extra_page = 0;
+ u_int wb_rc, mmusr;
+ void _wb_fault (); /* fault handler for write back */
+
+#ifdef DEBUG
+ if (mmudebug)
+ printf("wb%d valid: %x %x %x\n",wb,wb_sts,wb_addr,wb_data);
+#endif
+
+ /* See if we're going to span two pages (for word or long transfers) */
+
+ if((wb_sts & WBS_SZMASK) == WBS_SIZE_WORD)
+ if(trunc_page((vm_offset_t)wb_addr) !=
+ trunc_page((vm_offset_t)wb_addr+1))
+ wb_extra_page = 1;
+
+ if((wb_sts & WBS_SZMASK) == WBS_SIZE_LONG)
+ if(trunc_page((vm_offset_t)wb_addr) !=
+ trunc_page((vm_offset_t)wb_addr+3))
+ wb_extra_page = 3;
+
+ /*
+ * if it's writeback 3, we need to check the first page
+ */
+ if (wb == 3) {
+ mmusr = probeva(wb_addr, wb_sts & WBS_TMMASK);
+#ifdef DEBUG
+ if (mmudebug)
+ printf("wb3: probeva(%x,%x) = %x\n",
+ wb_addr + wb_extra_page, wb_sts & WBS_TMMASK, mmusr);
+#endif
+
+ if((mmusr & (MMUSR_R | MMUSR_W)) != MMUSR_R) {
+#ifdef DEBUG
+ if (mmudebug)
+ printf("wb3: need to bring in first page\n");
+#endif
+ wb_rc = vm_fault(wb_map,
+ trunc_page((vm_offset_t)wb_addr),
+ VM_PROT_READ | VM_PROT_WRITE, FALSE);
+
+ if(wb_rc != KERN_SUCCESS)
+ return (wb_rc);
+#ifdef DEBUG
+ if (mmudebug)
+ printf("wb3: first page brought in.\n");
+#endif
+ }
+ }
+
+ /*
+ * now check to see if a second page is required
+ */
+ if(wb_extra_page) {
+
+ mmusr = probeva(wb_addr+wb_extra_page, wb_sts & WBS_TMMASK);
+#ifdef DEBUG
+ if (mmudebug)
+ printf("wb%d: probeva %x %x = %x\n",
+ wb, wb_addr + wb_extra_page,
+ wb_sts & WBS_TMMASK,mmusr);
+#endif
+
+ if((mmusr & (MMUSR_R | MMUSR_W)) != MMUSR_R) {
+#ifdef DEBUG
+ if (mmudebug)
+ printf("wb%d: page boundary crossed."
+ " Bringing in extra page.\n",wb);
+#endif
+
+ wb_rc = vm_fault(wb_map,
+ trunc_page((vm_offset_t)wb_addr + wb_extra_page),
+ VM_PROT_READ | VM_PROT_WRITE,FALSE);
+
+ if(wb_rc != KERN_SUCCESS)
+ return (wb_rc);
+ }
+#ifdef DEBUG
+ if (mmudebug)
+ printf("wb%d: extra page brought in okay.\n", wb);
+#endif
+ }
+
+ /* Actually do the write now */
+
+ if ((wb_sts & WBS_TMMASK) == FC_USERD &&
+ !curpcb->pcb_onfault) {
+ curpcb->pcb_onfault = (caddr_t) _wb_fault;
+ }
+
+ switch(wb_sts & WBS_SZMASK) {
+
+ case WBS_SIZE_BYTE :
+ asm volatile ("movec %0,dfc ; movesb %1,%2@" : : "d" (wb_sts & WBS_TMMASK),
+ "d" (wb_data),
+ "a" (wb_addr));
+ break;
+
+ case WBS_SIZE_WORD :
+ asm volatile ("movec %0,dfc ; movesw %1,%2@" : : "d" (wb_sts & WBS_TMMASK),
+ "d" (wb_data),
+ "a" (wb_addr));
+ break;
+
+ case WBS_SIZE_LONG :
+ asm volatile ("movec %0,dfc ; movesl %1,%2@" : : "d" (wb_sts & WBS_TMMASK),
+ "d" (wb_data),
+ "a" (wb_addr));
+ break;
+
+ }
+ if (curpcb->pcb_onfault == (caddr_t) _wb_fault)
+ curpcb->pcb_onfault = NULL;
+ if ((wb_sts & WBS_TMMASK) != FC_USERD)
+ asm volatile ("movec %0,dfc\n" : : "d" (FC_USERD));
+ return (KERN_SUCCESS);
+}
+
+/*
+ * fault handler for write back
+ */
+void _wb_fault()
+{
+#ifdef DEBUG
+ printf ("trap: writeback fault\n");
+#endif
+ return;
+}
diff --git a/sys/arch/atari/atari/vectors.s b/sys/arch/atari/atari/vectors.s
new file mode 100644
index 00000000000..5d8f742adac
--- /dev/null
+++ b/sys/arch/atari/atari/vectors.s
@@ -0,0 +1,201 @@
+/* $NetBSD: vectors.s,v 1.1.1.1 1995/03/26 07:12:19 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah
+ * Copyright (c) 1990 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.
+ *
+ * @(#)vectors.s 7.2 (Berkeley) 5/7/91
+ */
+ .text
+ .globl _buserr,_addrerr
+ .globl _illinst,_zerodiv,_chkinst,_trapvinst,_privinst,_trace
+ .globl _badtrap
+ .globl _spurintr,_lev1intr,_lev2intr,_lev3intr
+ .globl _lev4intr,_lev5intr,_lev6intr,_lev7intr
+ .globl _trap0,_trap1,_trap2,_trap15
+ .globl _fpfline, _fpunsupp, _fpfault
+ .globl _trap12, _badmfpint
+
+Lvectab:
+ .long 0x4ef80400 | 0: jmp 0x400:w (unused reset SSP)
+ .long 0 | 1: NOT USED (reset PC)
+ .long _buserr | 2: bus error
+ .long _addrerr | 3: address error
+ .long _illinst | 4: illegal instruction
+ .long _zerodiv | 5: zero divide
+ .long _chkinst | 6: CHK instruction
+ .long _trapvinst | 7: TRAPV instruction
+ .long _privinst | 8: privilege violation
+ .long _trace | 9: trace
+ .long _illinst | 10: line 1010 emulator
+ .long _fpfline | 11: line 1111 emulator
+ .long _badtrap | 12: unassigned, reserved
+ .long _coperr | 13: coprocessor protocol violation
+ .long _fmterr | 14: format error
+ .long _badtrap | 15: uninitialized interrupt vector
+ .long _badtrap | 16: unassigned, reserved
+ .long _badtrap | 17: unassigned, reserved
+ .long _badtrap | 18: unassigned, reserved
+ .long _badtrap | 19: unassigned, reserved
+ .long _badtrap | 20: unassigned, reserved
+ .long _badtrap | 21: unassigned, reserved
+ .long _badtrap | 22: unassigned, reserved
+ .long _badtrap | 23: unassigned, reserved
+ .long _spurintr | 24: spurious interrupt
+ .long _lev1intr | 25: level 1 interrupt autovector
+ .long _lev2intr | 26: level 2 interrupt autovector
+ .long _lev3intr | 27: level 3 interrupt autovector
+ .long _lev4intr | 28: level 4 interrupt autovector
+ .long _lev5intr | 29: level 5 interrupt autovector
+ .long _lev6intr | 30: level 6 interrupt autovector
+ .long _lev7intr | 31: level 7 interrupt autovector
+ .long _trap0 | 32: syscalls
+ .long _trap1 | 33: sigreturn syscall or breakpoint
+ .long _trap2 | 34: breakpoint or sigreturn syscall
+ .long _illinst | 35: TRAP instruction vector
+ .long _illinst | 36: TRAP instruction vector
+ .long _illinst | 37: TRAP instruction vector
+ .long _illinst | 38: TRAP instruction vector
+ .long _illinst | 39: TRAP instruction vector
+ .long _illinst | 40: TRAP instruction vector
+ .long _illinst | 41: TRAP instruction vector
+ .long _illinst | 42: TRAP instruction vector
+ .long _illinst | 43: TRAP instruction vector
+ .long _trap12 | 44: TRAP instruction vector
+ .long _illinst | 45: TRAP instruction vector
+ .long _illinst | 46: TRAP instruction vector
+ .long _trap15 | 47: TRAP instruction vector
+#ifdef FPSP
+ .globl bsun, inex, dz, unfl, operr, ovfl, snan
+ .long bsun | 48: FPCP branch/set on unordered cond
+ .long inex | 49: FPCP inexact result
+ .long dz | 50: FPCP divide by zero
+ .long unfl | 51: FPCP underflow
+ .long operr | 52: FPCP operand error
+ .long ovfl | 53: FPCP overflow
+ .long snan | 54: FPCP signalling NAN
+#else
+ .globl _fpfault
+ .long _fpfault | 48: FPCP branch/set on unordered cond
+ .long _fpfault | 49: FPCP inexact result
+ .long _fpfault | 50: FPCP divide by zero
+ .long _fpfault | 51: FPCP underflow
+ .long _fpfault | 52: FPCP operand error
+ .long _fpfault | 53: FPCP overflow
+ .long _fpfault | 54: FPCP signalling NAN
+#endif
+
+
+ .long _fpunsupp | 55: FPCP unimplemented data type
+ .long _badtrap | 56: unassigned, reserved
+ .long _badtrap | 57: unassigned, reserved
+ .long _badtrap | 58: unassigned, reserved
+ .long _badtrap | 59: unassigned, reserved
+ .long _badtrap | 60: unassigned, reserved
+ .long _badtrap | 61: unassigned, reserved
+ .long _badtrap | 62: unassigned, reserved
+ .long _badtrap | 63: unassigned, reserved
+
+ /*
+ * MFP 1 auto vectors (ipl 6)
+ */
+ .long _badmfpint | 64: parallel port - BUSY
+ .long _badmfpint | 65: modem port 1 - DCD
+ .long _badmfpint | 66: modem port 1 - CTS
+ .long _badmfpint | 67: unassigned
+ .long _badmfpint | 68: modem port 1 baudgen (Timer D)
+ .long _badmfpint | 69: Timer C
+ .long mfp_kbd | 70: KBD/MIDI IRQ
+ .long mfp_fd_acsi | 71: FDC/ACSI DMA
+ .long _badmfpint | 72: Display enable counter
+ .long _badmfpint | 73: modem port 1 - XMIT error
+ .long _badmfpint | 74: modem port 1 - XMIT buffer empty
+ .long _badmfpint | 75: modem port 1 - RCV error
+ .long _badmfpint | 76: modem port 1 - RCV buffer full
+ .long _badmfpint | 77: Timer A
+ .long _badmfpint | 78: modem port 1 - RI
+ .long _badmfpint | 79: Monochrome detect
+
+ /*
+ * MFP 2 auto vectors (ipl 6)
+ */
+ .long _badmfpint | 80: I/O pin 1 J602
+ .long _badmfpint | 81: I/O pin 3 J602
+ .long _badmfpint | 82: SCC-DMA
+ .long _badmfpint | 83: modem port 2 - RI
+ .long _badmfpint | 84: serial port 1 baudgen (Timer D)
+ .long _badmfpint | 85: TCCLC SCC (Timer C)
+ .long _badmfpint | 86: FDC Drive Ready
+ .long mfp2_5380dm | 87: SCSI DMA
+ .long _badmfpint | 88: Display enable (Timer B)
+ .long _badmfpint | 89: serial port 1 - XMIT error
+ .long _badmfpint | 90: serial port 1 - XMIT buffer empty
+ .long _badmfpint | 91: serial port 1 - RCV error
+ .long _badmfpint | 92: serial port 1 - RCV buffer full
+ .long mfp2_tima | 93: Timer A (System clock)
+ .long _badmfpint | 94: RTC
+ .long mfp2_5380 | 95: SCSI 5380
+
+ /*
+ * Interrupts from the 8530 SCC
+ */
+ .long sccint | 96: SCC Tx empty channel B
+ .long _badtrap | 97: Not used
+ .long sccint | 98: SCC Ext./Status Channel B
+ .long _badtrap | 99: Not used
+ .long sccint | 100: SCC Rx Channel B
+ .long _badtrap | 101: Not used
+ .long sccint | 102: SCC Special Rx cond. Channel B
+ .long _badtrap | 103: Not used
+ .long sccint | 104: SCC Tx empty channel A
+ .long _badtrap | 105: Not used
+ .long sccint | 106: SCC Ext./Status Channel A
+ .long _badtrap | 107: Not used
+ .long sccint | 108: SCC Rx Channel A
+ .long _badtrap | 109: Not used
+ .long sccint | 110: SCC Special Rx cond. Channel A
+ .long _badtrap | 111: Not used
+
+#define BADTRAP16 .long _badtrap,_badtrap,_badtrap,_badtrap,\
+ _badtrap,_badtrap,_badtrap,_badtrap,\
+ _badtrap,_badtrap,_badtrap,_badtrap,\
+ _badtrap,_badtrap,_badtrap,_badtrap
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
+ BADTRAP16 | 112-255: user interrupt vectors
diff --git a/sys/arch/atari/atari/vm_machdep.c b/sys/arch/atari/atari/vm_machdep.c
new file mode 100644
index 00000000000..836d4697990
--- /dev/null
+++ b/sys/arch/atari/atari/vm_machdep.c
@@ -0,0 +1,318 @@
+/* $NetBSD: vm_machdep.c,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * from: Utah $Hdr: vm_machdep.c 1.21 91/04/06$
+ *
+ * @(#)vm_machdep.c 7.10 (Berkeley) 5/7/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/buf.h>
+
+#include <machine/cpu.h>
+
+#include <vm/vm.h>
+#include <sys/user.h>
+#include <vm/vm_kern.h>
+#include <machine/pte.h>
+
+/*
+ * 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.
+ */
+cpu_fork(p1, p2)
+ register struct proc *p1, *p2;
+{
+ register struct user *up = p2->p_addr;
+ int offset;
+ extern caddr_t getsp();
+ extern char kstack[];
+
+ /* copy over the machdep part of struct proc, so we don't lose
+ any emulator-properties of processes. */
+ bcopy (&p1->p_md, &p2->p_md, sizeof (struct mdproc));
+
+ /* need to copy current frame pointer */
+ p2->p_md.md_regs = p1->p_md.md_regs;
+
+ /*
+ * Copy pcb and stack from proc p1 to p2.
+ * We do this as cheaply as possible, copying only the active
+ * part of the stack. The stack and pcb need to agree;
+ * this is tricky, as the final pcb is constructed by savectx,
+ * but its frame isn't yet on the stack when the stack is copied.
+ * cpu_switch compensates for this when the child eventually runs.
+ * This should be done differently, with a single call
+ * that copies and updates the pcb+stack,
+ * replacing the bcopy and savectx.
+ */
+ p2->p_addr->u_pcb = p1->p_addr->u_pcb;
+ offset = getsp() - kstack;
+ bcopy((caddr_t)kstack + offset, (caddr_t)p2->p_addr + offset,
+ (unsigned) ctob(UPAGES) - offset);
+
+ PMAP_ACTIVATE(&p2->p_vmspace->vm_pmap, &up->u_pcb, 0);
+
+ /*
+ * Arrange for a non-local goto when the new process
+ * is started, to resume here, returning nonzero from setjmp.
+ */
+ if (savectx(up, 1)) {
+ /*
+ * Return 1 in child.
+ */
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * cpu_exit is called as the last action during exit.
+ * We release the address space and machine-dependent resources,
+ * including the memory for the user structure and kernel stack.
+ * Once finished, we call switch_exit, which switches to a temporary
+ * pcb and stack and never returns. We block memory allocation
+ * until switch_exit has made things safe again.
+ */
+void
+cpu_exit(p)
+ struct proc *p;
+{
+
+ vmspace_free(p->p_vmspace);
+
+ (void) splimp();
+ cnt.v_swtch++;
+ kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
+ switch_exit();
+ /* NOTREACHED */
+}
+
+/*
+ * 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.
+ */
+pagemove(from, to, size)
+ register caddr_t from, to;
+ int size;
+{
+ register vm_offset_t pa;
+
+#ifdef DEBUG
+ if (size & CLOFSET)
+ panic("pagemove");
+#endif
+ while (size > 0) {
+ pa = pmap_extract(kernel_pmap, (vm_offset_t)from);
+#ifdef DEBUG
+ if (pa == 0)
+ panic("pagemove 2");
+ if (pmap_extract(kernel_pmap, (vm_offset_t)to) != 0)
+ panic("pagemove 3");
+#endif
+ pmap_remove(kernel_pmap,
+ (vm_offset_t)from, (vm_offset_t)from + PAGE_SIZE);
+ pmap_enter(kernel_pmap,
+ (vm_offset_t)to, pa, VM_PROT_READ|VM_PROT_WRITE, 1);
+ from += PAGE_SIZE;
+ to += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+}
+
+/*
+ * Map `size' bytes of physical memory starting at `paddr' into
+ * kernel VA space at `vaddr'. Read/write and cache-inhibit status
+ * are specified by `prot'.
+ */
+physaccess(vaddr, paddr, size, prot)
+ caddr_t vaddr, paddr;
+ register int size, prot;
+{
+ u_int *pte;
+ register u_int page;
+
+ if (cpu040 && (prot & PG_CI) == 0) /* if cache not inhibited */
+ prot |= PG_CCB; /* set cacheable, copyback */
+ pte = kvtopte(vaddr);
+ page = (u_int)paddr & PG_FRAME;
+ for (size = btoc(size); size; size--) {
+ *pte++ = PG_V | prot | page;
+ page += NBPG;
+ }
+ TBIAS();
+}
+
+physunaccess(vaddr, size)
+ caddr_t vaddr;
+ register int size;
+{
+ u_int *pte;
+
+ pte = kvtopte(vaddr);
+ for (size = btoc(size); size; size--)
+ *pte++ = PG_NV;
+ TBIAS();
+}
+
+/*
+ * Dump the machine specific header information at the start of a core dump.
+ */
+cpu_coredump(p, vp, cred)
+ struct proc *p;
+ struct vnode *vp;
+ struct ucred *cred;
+{
+ return(vn_rdwr(UIO_WRITE, vp, (caddr_t) p->p_addr, ctob(UPAGES),
+ (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL,
+ p));
+}
+
+/*
+ * Set a red zone in the kernel stack after the u. area.
+ * We don't support a redzone right now. It really isn't clear
+ * that it is a good idea since, if the kernel stack were to roll
+ * into a write protected page, the processor would lock up (since
+ * it cannot create an exception frame) and we would get no useful
+ * post-mortem info. Currently, under the DEBUG option, we just
+ * check at every clock interrupt to see if the current k-stack has
+ * gone too far (i.e. into the "redzone" page) and if so, panic.
+ * Look at _lev6intr in locore.s for more details.
+ */
+/*ARGSUSED*/
+setredzone(pte, vaddr)
+ u_int *pte;
+ caddr_t vaddr;
+{
+}
+
+/*
+ * Convert kernel VA to physical address
+ */
+kvtop(addr)
+ register caddr_t addr;
+{
+ vm_offset_t va;
+
+ va = pmap_extract(kernel_pmap, (vm_offset_t)addr);
+ if (va == 0)
+ panic("kvtop: zero page frame");
+ return((int)va);
+}
+
+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")
+ */
+vmapbuf(bp)
+ register struct buf *bp;
+{
+ register int npf;
+ register caddr_t addr;
+ register long flags = bp->b_flags;
+ struct proc *p;
+ int off;
+ vm_offset_t kva;
+ register vm_offset_t pa;
+
+ if ((flags & B_PHYS) == 0)
+ panic("vmapbuf");
+ addr = bp->b_saveaddr = bp->b_un.b_addr;
+ off = (int)addr & PGOFSET;
+ p = bp->b_proc;
+ npf = btoc(round_page(bp->b_bcount + off));
+ kva = kmem_alloc_wait(phys_map, ctob(npf));
+ bp->b_un.b_addr = (caddr_t) (kva + off);
+ while (npf--) {
+ pa = pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),
+ (vm_offset_t)addr);
+ if (pa == 0)
+ panic("vmapbuf: null page frame");
+ pmap_enter(vm_map_pmap(phys_map), kva, trunc_page(pa),
+ VM_PROT_READ|VM_PROT_WRITE, TRUE);
+ addr += PAGE_SIZE;
+ kva += PAGE_SIZE;
+ }
+}
+
+/*
+ * Free the io map PTEs associated with this IO operation.
+ * We also invalidate the TLB entries and restore the original b_addr.
+ */
+vunmapbuf(bp)
+ register struct buf *bp;
+{
+ register int npf;
+ register caddr_t addr = bp->b_un.b_addr;
+ vm_offset_t kva;
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vunmapbuf");
+ npf = btoc(round_page(bp->b_bcount + ((int)addr & PGOFSET)));
+ kva = (vm_offset_t)((int)addr & ~PGOFSET);
+ kmem_free_wakeup(phys_map, kva, ctob(npf));
+ bp->b_un.b_addr = bp->b_saveaddr;
+ bp->b_saveaddr = NULL;
+}
diff --git a/sys/arch/atari/compile/.keep_me b/sys/arch/atari/compile/.keep_me
new file mode 100644
index 00000000000..05ddb1317d3
--- /dev/null
+++ b/sys/arch/atari/compile/.keep_me
@@ -0,0 +1,3 @@
+ $NetBSD: .keep_me,v 1.1.1.1 1995/03/26 07:12:17 leo Exp $
+
+This normally empty directory needs to be kept in the distribution.
diff --git a/sys/arch/atari/conf/ATARITT b/sys/arch/atari/conf/ATARITT
new file mode 100644
index 00000000000..904d42258cd
--- /dev/null
+++ b/sys/arch/atari/conf/ATARITT
@@ -0,0 +1,90 @@
+#
+# $NetBSD: ATARITT,v 1.1.1.1 1995/03/26 07:12:16 leo Exp $
+#
+# ATARI-TT
+#
+# This configuration file is for a multiple disk/multiple tape ATARI-TT
+#
+
+include "std.atari"
+#
+# Add support for about 16 users. This variable is used to size
+# various kernel structures.
+#
+maxusers 16
+
+#
+# processors this kernel should support
+#
+options "M68030" # support for 030
+
+options TIMEZONE=300 # Set the timezone that the kernel will use
+options DST=1 # Set the timezone that the kernel will use
+
+options FPCOPROC # Support for MC68881/MC68882
+#options FPSP
+
+#
+# Networking options
+#
+options INET # Basic networking support
+
+options FFS # Berkeley fast file system
+options MFS # Memory based filesystem
+options PROCFS # Process filesystem
+options KERNFS # Kernel parameter filesystem
+options NULLFS # Loopback filesystem
+options MSDOSFS # MSDOS filesystem
+
+options FIFO # FIFO operations on vnodes
+
+options SWAPPAGER # Pager for swap device
+options VNODEPAGER # Pager for vnodes
+options DEVPAGER # Pager
+
+
+#
+# Misc. debuging options
+#
+options PANICWAIT # Require keystroke to dump/reboot
+options DDB # Kernel debugger
+
+#
+# Compatability options for various existing systems
+#
+options "COMPAT_43" # 4.3 BSD compatible system calls (required)
+
+#
+# Support for System V IPC facilities.
+#
+#options SYSVSHM # System V shared memory
+#options SYSVMSG # System V messages
+#options SYSVSEM # System V semaphores
+
+#
+# Support for various kernel options
+#
+options KTRACE # Add kernel tracing system call
+options DIAGNOSTIC # Add additional error checking code
+options "NKMEMCLUSTERS=256" # Size of kernel malloc area
+options GENERIC # Mini-root boot support
+#options KFONT_8x8 # Use 8x8 font instead of 8x16
+
+#
+# Build one kernel that can boot from any disk.
+#
+config netbsd swap on generic
+
+pseudo-device view 2 # View (graphics mapping)
+pseudo-device sl # Slip
+pseudo-device ppp # ppp
+pseudo-device pty 16 # Pseudo-tty support
+pseudo-device loop # Loopback network
+pseudo-device vnd 3 # 3 pseudo disks (see vnconfig)
+
+#
+#The following sections describe various hardware options.
+#
+zs0 at mainbus0 # Serial support through 8530
+grf1 at grfbus0 # second graphics driver
+ite1 at grf1 # second tty
diff --git a/sys/arch/atari/conf/GENERIC b/sys/arch/atari/conf/GENERIC
new file mode 100644
index 00000000000..743a0f0c5e9
--- /dev/null
+++ b/sys/arch/atari/conf/GENERIC
@@ -0,0 +1,90 @@
+#
+# $NetBSD: GENERIC,v 1.1.1.1 1995/03/26 07:12:16 leo Exp $
+#
+# Maximal ATARI-TT
+#
+# This configuration file is for a multiple disk/multiple tape ATARI-TT
+# with network (through ppp or slip).
+
+include "std.atari"
+#
+# Add support for about 16 users. This variable is used to size
+# various kernel structures.
+#
+maxusers 16
+
+#
+# processors this kernel should support
+#
+options "M68030" # support for 030
+
+options TIMEZONE=300 # Set the timezone that the kernel will use
+options DST=1 # Set the timezone that the kernel will use
+options FPCOPROC # Support for MC68881/MC68882
+
+#
+# Networking options
+#
+options INET # Basic networking support
+
+options FFS # Berkeley fast file system
+options MFS # Memory based filesystem
+options PROCFS # Process filesystem
+options KERNFS # Kernel parameter filesystem
+options NULLFS # Loopback filesystem
+options MSDOSFS # MSDOS filesystem
+
+options FIFO # FIFO operations on vnodes
+
+options SWAPPAGER # Pager for swap device
+options VNODEPAGER # Pager for vnodes
+options DEVPAGER # Pager
+
+
+#
+# Misc. debuging options
+#
+options PANICWAIT # Require keystroke to dump/reboot
+options DDB # Kernel debugger
+
+#
+# Compatability options for various existing systems
+#
+options "COMPAT_43" # 4.3 BSD compatible system calls (required)
+#options "COMPAT_09" # has no meaning on the atari
+#options COMPAT_SUNOS # Support to run Sun-3 executables
+#options "TCP_COMPAT_42" # Disable UDP checksums (not needed)
+
+#
+# Support for System V IPC facilities.
+#
+options SYSVSHM # System V shared memory
+options SYSVMSG # System V messages
+options SYSVSEM # System V semaphores
+
+#
+# Support for various kernel options
+#
+options KTRACE # Add kernel tracing system call
+options DIAGNOSTIC # Add additional error checking code
+options "NKMEMCLUSTERS=256" # Size of kernel malloc area
+options GENERIC # Mini-root boot support
+#options KFONT_8x8 # Use 8x8 font instead of 8x16
+
+#
+# Build one kernel that can boot from any disk.
+#
+config netbsd swap on generic
+
+pseudo-device view 2 # View (graphics mapping)
+pseudo-device sl # Slip
+pseudo-device ppp # ppp
+pseudo-device pty 16 # Pseudo-tty support
+pseudo-device loop # Loopback network
+pseudo-device vnd 3 # 3 pseudo disks (see vnconfig)
+
+#
+#The following sections describe various hardware options.
+#
+zs0 at mainbus0 # Serial support through 8530
+
diff --git a/sys/arch/atari/conf/Makefile.atari b/sys/arch/atari/conf/Makefile.atari
new file mode 100644
index 00000000000..519355aa93d
--- /dev/null
+++ b/sys/arch/atari/conf/Makefile.atari
@@ -0,0 +1,161 @@
+# $NetBSD: Makefile.atari,v 1.1.1.1 1995/03/26 07:12:16 leo Exp $
+#
+# Makefile for NetBSD Atari-TT
+#
+# This makefile is constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/conf/``machineid''
+# after which you should do
+# config machineid
+# Machine generic makefile changes should be made in
+# /sys/conf/Makefile.``machinetype''
+# 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 by config if debugging is requested (config -g).
+# PROF is set to -pg by config if profiling is requested (config -p).
+AS= as ${DEBUG}
+CC= cc ${DEBUG}
+CPP= cpp
+LD= ld
+TOUCH= touch -f -c
+
+# source tree is located via $S relative to the compilation directory
+S= ../../../..
+ATARI= ../..
+
+INCLUDES= -I. -I$S/arch -I$S -I$S/sys
+COPTS= ${INCLUDES} ${IDENT} -DKERNEL -Dmc68020 -Datari
+CFLAGS= -O -mc68020 -m68881 ${COPTS}
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+.ifndef PROF
+LIBKERN= ${KERNLIB}
+.else
+LIBKERN= ${KERNLIB_PROF}
+.endif
+
+### for the Motorola 68040 Floating Point Software Product
+.include "$S/arch/m68k/fpsp/Makefile.inc"
+
+# 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} -c ${CFLAGS} ${PROF} $<
+NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
+
+DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $<
+DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
+
+PROFILE_C= ${CC} -S -c ${COPTS} $<; \
+ sed -e s/_mcount/mcount/ -e s/subrmcount/subr_mcount/ <$*.s | \
+ ${AS} -o $@; \
+ rm -f $*.s
+
+NORMAL_S= ${CPP} ${COPTS} $< | ${AS} -o $@
+NORMAL_S_C= ${CPP} ${COPTS} ${PARAM} $< | ${AS} -o $@
+
+%OBJS
+
+%CFILES
+
+# 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 ${FPSP} vnode_if.o ${OBJS} param.o ioconf.o ${LIBKERN}
+SYSTEM_DEP= Makefile ${SYSTEM_OBJ}
+SYSTEM_LD_HEAD= rm -f $@
+SYSTEM_LD= -@if [ X${DEBUG} = X-g ]; \
+ then strip=-X; \
+ else strip=-x; \
+ fi; \
+ echo ${LD} $$strip -n -T 0 -o $@ -e start '$${SYSTEM_OBJ}' vers.o; \
+ ${LD} $$strip -n -T 0 -o $@ -e start ${SYSTEM_OBJ} vers.o
+SYSTEM_LD_TAIL= @size $@; chmod 755 $@; \
+ [ X${DEBUG} = X-g ] && { \
+ echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \
+ echo strip -d $@; strip -d $@; } || true
+
+%LOAD
+
+vers.o: newvers
+
+newvers:
+ sh $S/conf/newvers.sh ${KERN_IDENT}
+ ${CC} $(CFLAGS) -c vers.c
+
+clean:
+ rm -f eddep *netbsd netbsd.gdb tags *.o locore.i [a-z]*.s \
+ Errs errs linterrs makelinks
+
+lint: /tmp param.c
+ @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} -UKGDB \
+ ${ATARI}/atari/Locore.c ${CFILES} ${ATARI}/atari/swapgeneric.c \
+ ioconf.c param.c| \
+ grep -v 'struct/union .* never defined' | \
+ grep -v 'possible pointer alignment problem'
+
+locore.o: assym.s ${ATARI}/atari/vectors.s ${ATARI}/atari/locore.s
+locore.o: machine/trap.h machine/psl.h machine/pte.h machine/cpu.h
+ ${CPP} -DLOCORE ${COPTS} ${ATARI}/atari/locore.s | ${AS} -o locore.o
+
+# the following is necessary because autoconf.o depends on #if GENERIC
+autoconf.o: Makefile
+
+# the following are necessary because the files depend on the types of
+# hp cpu's included in the system configuration
+machdep.o sys_machdep.o pmap.o pmap_bootstrap.o trap.o dma.o: Makefile
+
+# depend on network or filesystem configuration
+uipc_proto.o vfs_conf.o locore.o: Makefile
+
+# depend on maxusers
+assym.s: Makefile
+
+assym.s: genassym
+ ./genassym >assym.s
+
+genassym:
+ ${CC} -static ${INCLUDES} ${IDENT} ${PARAM} -Dmc68020 -Datari \
+ -o genassym ${ATARI}/atari/genassym.c
+
+depend: assym.s param.c vnode_if.h
+ mkdep ${COPTS} ${CFILES} ioconf.c param.c
+ mkdep -a -p ${INCLUDES} ${IDENT} ${PARAM} ${ATARI}/atari/genassym.c
+
+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
+
+tags:
+ @echo "see $S/kern/Makefile for tags"
+
+ioconf.o: ioconf.c
+ ${CC} -c ${CFLAGS} ioconf.c
+
+param.c: $S/conf/param.c
+ rm -f param.c
+ cp $S/conf/param.c .
+
+param.o: param.c Makefile
+ ${CC} -c ${CFLAGS} ${PARAM} param.c
+vnode_if.c vnode_if.h: $S/kern/vnode_if.sh $S/kern/vnode_if.src
+ AWK="${AWK}" sh $S/kern/vnode_if.sh $S/kern/vnode_if.src
+
+%RULES
diff --git a/sys/arch/atari/conf/files.atari b/sys/arch/atari/conf/files.atari
new file mode 100644
index 00000000000..67b1f4edecf
--- /dev/null
+++ b/sys/arch/atari/conf/files.atari
@@ -0,0 +1,102 @@
+#
+# $NetBSD: files.atari,v 1.1.1.1 1995/03/26 07:12:16 leo Exp $
+#
+
+maxusers 2 8 64
+
+device mainbus at root {}
+
+device cpu at mainbus
+
+define event {}
+file arch/atari/dev/event.c event
+
+device clock at mainbus
+file arch/atari/dev/clock.c
+
+# keyboard
+device kbd at mainbus: event
+file arch/atari/dev/kbd.c kbd needs-count
+
+# serial port via 85C30 (modem2/serial2)
+device zs at mainbus: tty
+file arch/atari/dev/zs.c zs needs-count
+
+#ramdisk
+device ramd at mainbus
+file arch/atari/dev/ramd.c ramd needs-flag
+
+device fdc at mainbus { unit = -1 }
+
+device fd at fdc
+file arch/atari/dev/fd.c fd needs-flag
+file arch/atari/dev/dma.c
+major {fd = 2}
+
+# graphic devices
+define grfb {}
+
+device grfbus at mainbus: grfb
+
+device grf at grfb {}
+file arch/atari/dev/grf.c grf needs-count
+file arch/atari/dev/ite_cc.c grf ite
+file arch/atari/dev/grfabs.c grf ite
+
+device ite at grf
+file arch/atari/dev/ite.c ite needs-flag
+file arch/atari/dev/kbdmap.c ite
+file arch/atari/dev/font_8x8.c ite
+file arch/atari/dev/font_8x16.c ite
+
+
+pseudo-device view
+file arch/atari/dev/view.c view grf needs-count
+
+define scsi {}
+
+# ncr 5380 controller
+device ncrscsi at mainbus: scsi
+file arch/atari/dev/ncr5380.c ncrscsi
+
+device scsibus at scsi {target = -1, lun = -1}
+
+device cd at scsibus: disk
+file scsi/cd.c cd needs-flag
+major {cd = 6}
+device sd at scsibus: disk
+file scsi/sd.c sd needs-flag
+major {sd = 4}
+device st at scsibus: tape
+file scsi/st.c st needs-flag
+major {st = 5}
+device ch at scsibus: disk
+file scsi/ch.c ch needs-flag
+device uk at scsibus: disk
+file scsi/uk.c uk needs-flag
+device su at scsibus: disk
+file scsi/su.c su needs-flag
+
+
+# list of standard files...
+file dev/cons.c ite
+file scsi/scsi_base.c scsi
+file scsi/scsi_ioctl.c scsi
+file scsi/scsiconf.c scsi
+file arch/atari/atari/atari_init.c
+file arch/atari/atari/autoconf.c
+file arch/atari/atari/conf.c
+file arch/atari/atari/disksubr.c
+file arch/atari/atari/dkbad.c
+file arch/atari/atari/machdep.c
+file arch/atari/atari/mem.c
+file arch/atari/atari/pmap.c
+file arch/atari/atari/sys_machdep.c
+file arch/atari/atari/trap.c
+file arch/atari/atari/misc.c
+file arch/atari/atari/vm_machdep.c
+file arch/m68k/m68k/copy.s
+file compat/sunos/sun_misc.c compat_sunos
+file compat/sunos/sun_sysent.c compat_sunos
+file compat/sunos/sun_ioctl.c compat_sunos
+file compat/sunos/sun_exec.c compat_sunos
diff --git a/sys/arch/atari/conf/files.atari.newconf b/sys/arch/atari/conf/files.atari.newconf
new file mode 100644
index 00000000000..a5d37ca92df
--- /dev/null
+++ b/sys/arch/atari/conf/files.atari.newconf
@@ -0,0 +1,102 @@
+#
+# $NetBSD: files.atari.newconf,v 1.1.1.1 1995/03/26 07:12:16 leo Exp $
+#
+
+maxusers 2 8 64
+
+device mainbus at root {}
+
+device cpu at mainbus
+
+define event {}
+file arch/atari/dev/event.c event
+
+device clock at mainbus
+file arch/atari/dev/clock.c
+
+# keyboard
+device kbd at mainbus: event
+file arch/atari/dev/kbd.c kbd needs-count
+
+# serial port via 85C30 (modem2/serial2)
+device zs at mainbus: tty
+file arch/atari/dev/zs.c zs needs-count
+
+#ramdisk
+device ramd at mainbus
+file arch/atari/dev/ramd.c ramd needs-flag
+
+device fdc at mainbus { unit = -1 }
+
+device fd at fdc
+file arch/atari/dev/fd.c fd needs-flag
+file arch/atari/dev/dma.c
+major {fd = 2}
+
+# graphic devices
+define grfb {}
+
+device grfbus at mainbus: grfb
+
+device grf at grfb {}
+file arch/atari/dev/grf.c grf needs-count
+file arch/atari/dev/ite_cc.c grf ite
+file arch/atari/dev/grfabs.c grf ite
+
+device ite at grf
+file arch/atari/dev/ite.c ite needs-flag
+file arch/atari/dev/kbdmap.c ite
+file arch/atari/dev/font_8x8.c ite
+file arch/atari/dev/font_8x16.c ite
+
+
+pseudo-device view
+file arch/atari/dev/view.c view grf needs-count
+
+define scsi {}
+
+# ncr 5380 controller
+device ncrscsi at mainbus: scsi
+file arch/atari/dev/ncr5380.c ncrscsi
+
+device scsibus at scsi {target = -1, lun = -1}
+
+device cd at scsibus: disk
+file scsi/cd.c cd needs-flag
+major {cd = 6}
+device sd at scsibus: disk
+file scsi/sd.c sd needs-flag
+major {sd = 4}
+device st at scsibus: tape
+file scsi/st.c st needs-flag
+major {st = 5}
+device ch at scsibus: disk
+file scsi/ch.c ch needs-flag
+device uk at scsibus: disk
+file scsi/uk.c uk needs-flag
+device su at scsibus: disk
+file scsi/su.c su needs-flag
+
+
+# list of standard files...
+file dev/cons.c ite
+file scsi/scsi_base.c scsi
+file scsi/scsi_ioctl.c scsi
+file scsi/scsiconf.c scsi
+file arch/atari/atari/atari_init.c
+file arch/atari/atari/autoconf.c
+file arch/atari/atari/conf.c
+file arch/atari/atari/disksubr.c
+file arch/atari/atari/dkbad.c
+file arch/atari/atari/machdep.c
+file arch/atari/atari/mem.c
+file arch/atari/atari/pmap.c
+file arch/atari/atari/sys_machdep.c
+file arch/atari/atari/trap.c
+file arch/atari/atari/misc.c
+file arch/atari/atari/vm_machdep.c
+file arch/m68k/m68k/copy.s
+file compat/sunos/sun_misc.c compat_sunos
+file compat/sunos/sun_sysent.c compat_sunos
+file compat/sunos/sun_ioctl.c compat_sunos
+file compat/sunos/sun_exec.c compat_sunos
diff --git a/sys/arch/atari/conf/std.atari b/sys/arch/atari/conf/std.atari
new file mode 100644
index 00000000000..ff486076172
--- /dev/null
+++ b/sys/arch/atari/conf/std.atari
@@ -0,0 +1,22 @@
+# $NetBSD: std.atari,v 1.1.1.1 1995/03/26 07:12:16 leo Exp $
+#
+# standard atari information
+#
+machine atari m68k
+
+mainbus0 at root
+
+clock0 at mainbus0 # system clock
+ramd0 at mainbus0 # ramdisk for install-fs
+kbd0 at mainbus0 # standard keyboard
+fdc0 at mainbus0 # floppy controller
+fd0 at fdc0 unit 0 # buildin floppy drive
+grfbus0 at mainbus0 # bitmapped display's
+ncrscsi0 at mainbus0 # SCSI driver
+scsibus0 at ncrscsi0 # SCSI bus
+grf0 at grfbus0 # graphics driver
+ite0 at grf0 # console
+
+# any disk/tape drives on configured controllers.
+sd* at scsibus? target ? lun ?
+st0 at scsibus? target ? lun 0
diff --git a/sys/arch/atari/dev/clock.c b/sys/arch/atari/dev/clock.c
new file mode 100644
index 00000000000..10661c42d83
--- /dev/null
+++ b/sys/arch/atari/dev/clock.c
@@ -0,0 +1,697 @@
+/* $NetBSD: clock.c,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990 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.
+ *
+ * from: Utah $Hdr: clock.c 1.18 91/01/21$
+ *
+ * @(#)clock.c 7.6 (Berkeley) 5/7/91
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <machine/psl.h>
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+#include <atari/dev/clockreg.h>
+
+#if defined(PROF) && defined(PROFTIMER)
+#include <sys/PROF.h>
+#endif
+
+
+/*
+ * Machine-dependent clock routines.
+ *
+ * Startrtclock restarts the real-time clock, which provides
+ * hardclock interrupts to kern_clock.c.
+ *
+ * Inittodr initializes the time of day hardware which provides
+ * date functions.
+ *
+ * Resettodr restores the time of day hardware after a time change.
+ *
+ * A note on the real-time clock:
+ * We actually load the clock with CLK_INTERVAL-1 instead of CLK_INTERVAL.
+ * This is because the counter decrements to zero after N+1 enabled clock
+ * periods where N is the value loaded into the counter.
+ */
+
+int clockmatch __P((struct device *, struct cfdata *, void *));
+void clockattach __P((struct device *, struct device *, void *));
+
+struct cfdriver clockcd = {
+ NULL, "clock", (cfmatch_t)clockmatch, clockattach,
+ DV_DULL, sizeof(struct device), NULL, 0
+};
+
+static u_long gettod __P((void));
+static int settod __P((u_long));
+
+static int divisor;
+
+int
+clockmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(!strcmp("clock", auxp))
+ return(1);
+ return(0);
+}
+
+/*
+ * Start the real-time clock.
+ */
+void clockattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ /*
+ * Initialize Timer-A in the TT-MFP. An exact reduce to HZ is not
+ * possible by hardware. We use a divisor of 64 and reduce by software
+ * with a factor of 4. The MFP clock runs at 2457600Hz. Therefore the
+ * timer runs at an effective rate of: 2457600/(64*4) = 9600Hz. The
+ * following expression works for all 'normal' values of hz.
+ */
+ divisor = 9600/hz;
+ MFP2->mf_tacr = 0; /* Stop timer */
+ MFP2->mf_iera &= ~IA_TIMA2; /* Disable timer interrupts */
+ MFP2->mf_tadr = divisor; /* Set divisor */
+
+ printf(": system hz %d timer-A divisor %d\n", hz, divisor);
+
+ /*
+ * Initialize Timer-B in the TT-MFP. This timer is used by the 'delay'
+ * function below. This time is setup to be continueously counting from
+ * 255 back to zero at a frequency of 614400Hz.
+ */
+ MFP2->mf_tbcr = 0; /* Stop timer */
+ MFP2->mf_iera &= ~IA_TIMB2; /* Disable timer interrupts */
+ MFP2->mf_tbdr = 0;
+ MFP2->mf_tbcr = T_Q004; /* Start timer */
+
+}
+
+void cpu_initclocks()
+{
+ MFP2->mf_tacr = T_Q064; /* Start timer */
+ MFP2->mf_ipra &= ~IA_TIMA2; /* Clear pending interrupts */
+ MFP2->mf_iera |= IA_TIMA2; /* Enable timer interrupts */
+ MFP2->mf_imra |= IA_TIMA2; /* ..... */
+}
+
+setstatclockrate(hz)
+ int hz;
+{
+}
+
+/*
+ * Returns number of usec since last recorded clock "tick"
+ * (i.e. clock interrupt).
+ */
+clkread()
+{
+ extern short clk_div;
+ u_int delta, elapsed;
+
+ elapsed = (divisor - MFP2->mf_tadr) + ((4 - clk_div) * divisor);
+ delta = (elapsed * tick) / (divisor << 2);
+
+ /*
+ * Account for pending clock interrupts
+ */
+ if(MFP2->mf_iera & IA_TIMA2)
+ return(delta + tick);
+ return(delta);
+}
+
+#define TIMB2_FREQ 614400
+#define TIMB2_LIMIT 256
+
+/*
+ * Wait "n" microseconds.
+ * Relies on MFP2-Timer B counting down from TIMB2_LIMIT at TIMB2_FREQ Hz.
+ * Note: timer had better have been programmed before this is first used!
+ */
+void delay(n)
+int n;
+{
+ int tick, otick;
+
+ /*
+ * Read the counter first, so that the rest of the setup overhead is
+ * counted.
+ */
+ otick = MFP2->mf_tbdr;
+
+ /*
+ * Calculate ((n * TIMER_FREQ) / 1e6) using explicit assembler code so
+ * we can take advantage of the intermediate 64-bit quantity to prevent
+ * loss of significance.
+ */
+ n -= 5;
+ if(n < 0)
+ return;
+ {
+ u_int temp;
+
+ __asm __volatile ("mulul %2,%1:%0" : "=d" (n), "=d" (temp)
+ : "d" (TIMB2_FREQ));
+ __asm __volatile ("divul %1,%2:%0" : "=d" (n)
+ : "d"(1000000),"d"(temp),"0"(n));
+ }
+
+ while(n > 0) {
+ tick = MFP2->mf_tbdr;
+ if(tick > otick)
+ n -= TIMB2_LIMIT - (tick - otick);
+ else n -= otick - tick;
+ otick = tick;
+ }
+}
+
+#ifdef notyet
+/*
+ * Needs to be calibrated for use, its way off most of the time
+ */
+void
+DELAY(mic)
+ int mic;
+{
+ u_long n;
+ short hpos;
+
+ /*
+ * this function uses HSync pulses as base units. The custom chips
+ * display only deals with 31.6kHz/2 refresh, this gives us a
+ * resolution of 1/15800 s, which is ~63us (add some fuzz so we really
+ * wait awhile, even if using small timeouts)
+ */
+ n = mic/63 + 2;
+ do {
+ hpos = custom.vhposr & 0xff00;
+ while (hpos == (custom.vhposr & 0xff00))
+ ;
+ } while (n--);
+}
+#endif /* notyet */
+
+#if notyet
+
+/* implement this later. I'd suggest using both timers in CIA-A, they're
+ not yet used. */
+
+#include "clock.h"
+#if NCLOCK > 0
+/*
+ * /dev/clock: mappable high resolution timer.
+ *
+ * This code implements a 32-bit recycling counter (with a 4 usec period)
+ * using timers 2 & 3 on the 6840 clock chip. The counter can be mapped
+ * RO into a user's address space to achieve low overhead (no system calls),
+ * high-precision timing.
+ *
+ * Note that timer 3 is also used for the high precision profiling timer
+ * (PROFTIMER code above). Care should be taken when both uses are
+ * configured as only a token effort is made to avoid conflicting use.
+ */
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/ioctl.h>
+#include <sys/malloc.h>
+#include <vm/vm.h>
+#include <amiga/amiga/clockioctl.h>
+#include <sys/specdev.h>
+#include <sys/vnode.h>
+#include <sys/mman.h>
+
+int clockon = 0; /* non-zero if high-res timer enabled */
+#ifdef PROFTIMER
+int profprocs = 0; /* # of procs using profiling timer */
+#endif
+#ifdef DEBUG
+int clockdebug = 0;
+#endif
+
+/*ARGSUSED*/
+clockopen(dev, flags)
+ dev_t dev;
+{
+#ifdef PROFTIMER
+#ifdef PROF
+ /*
+ * Kernel profiling enabled, give up.
+ */
+ if (profiling)
+ return(EBUSY);
+#endif
+ /*
+ * If any user processes are profiling, give up.
+ */
+ if (profprocs)
+ return(EBUSY);
+#endif
+ if (!clockon) {
+ startclock();
+ clockon++;
+ }
+ return(0);
+}
+
+/*ARGSUSED*/
+clockclose(dev, flags)
+ dev_t dev;
+{
+ (void) clockunmmap(dev, (caddr_t)0, curproc); /* XXX */
+ stopclock();
+ clockon = 0;
+ return(0);
+}
+
+/*ARGSUSED*/
+clockioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ struct proc *p;
+{
+ int error = 0;
+
+ switch (cmd) {
+
+ case CLOCKMAP:
+ error = clockmmap(dev, (caddr_t *)data, p);
+ break;
+
+ case CLOCKUNMAP:
+ error = clockunmmap(dev, *(caddr_t *)data, p);
+ break;
+
+ case CLOCKGETRES:
+ *(int *)data = CLK_RESOLUTION;
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ return(error);
+}
+
+/*ARGSUSED*/
+clockmap(dev, off, prot)
+ dev_t dev;
+{
+ return((off + (INTIOBASE+CLKBASE+CLKSR-1)) >> PGSHIFT);
+}
+
+clockmmap(dev, addrp, p)
+ dev_t dev;
+ caddr_t *addrp;
+ struct proc *p;
+{
+ int error;
+ struct vnode vn;
+ struct specinfo si;
+ int flags;
+
+ flags = MAP_FILE|MAP_SHARED;
+ if (*addrp)
+ flags |= MAP_FIXED;
+ else
+ *addrp = (caddr_t)0x1000000; /* XXX */
+ vn.v_type = VCHR; /* XXX */
+ vn.v_specinfo = &si; /* XXX */
+ vn.v_rdev = dev; /* XXX */
+ error = vm_mmap(&p->p_vmspace->vm_map, (vm_offset_t *)addrp,
+ PAGE_SIZE, VM_PROT_ALL, flags, (caddr_t)&vn, 0);
+ return(error);
+}
+
+clockunmmap(dev, addr, p)
+ dev_t dev;
+ caddr_t addr;
+ struct proc *p;
+{
+ int rv;
+
+ if (addr == 0)
+ return(EINVAL); /* XXX: how do we deal with this? */
+ rv = vm_deallocate(p->p_vmspace->vm_map, (vm_offset_t)addr, PAGE_SIZE);
+ return(rv == KERN_SUCCESS ? 0 : EINVAL);
+}
+
+startclock()
+{
+ register struct clkreg *clk = (struct clkreg *)clkstd[0];
+
+ clk->clk_msb2 = -1; clk->clk_lsb2 = -1;
+ clk->clk_msb3 = -1; clk->clk_lsb3 = -1;
+
+ clk->clk_cr2 = CLK_CR3;
+ clk->clk_cr3 = CLK_OENAB|CLK_8BIT;
+ clk->clk_cr2 = CLK_CR1;
+ clk->clk_cr1 = CLK_IENAB;
+}
+
+stopclock()
+{
+ register struct clkreg *clk = (struct clkreg *)clkstd[0];
+
+ clk->clk_cr2 = CLK_CR3;
+ clk->clk_cr3 = 0;
+ clk->clk_cr2 = CLK_CR1;
+ clk->clk_cr1 = CLK_IENAB;
+}
+#endif
+
+#endif
+
+
+#ifdef PROFTIMER
+/*
+ * This code allows the amiga kernel to use one of the extra timers on
+ * the clock chip for profiling, instead of the regular system timer.
+ * The advantage of this is that the profiling timer can be turned up to
+ * a higher interrupt rate, giving finer resolution timing. The profclock
+ * routine is called from the lev6intr in locore, and is a specialized
+ * routine that calls addupc. The overhead then is far less than if
+ * hardclock/softclock was called. Further, the context switch code in
+ * locore has been changed to turn the profile clock on/off when switching
+ * into/out of a process that is profiling (startprofclock/stopprofclock).
+ * This reduces the impact of the profiling clock on other users, and might
+ * possibly increase the accuracy of the profiling.
+ */
+int profint = PRF_INTERVAL; /* Clock ticks between interrupts */
+int profscale = 0; /* Scale factor from sys clock to prof clock */
+char profon = 0; /* Is profiling clock on? */
+
+/* profon values - do not change, locore.s assumes these values */
+#define PRF_NONE 0x00
+#define PRF_USER 0x01
+#define PRF_KERNEL 0x80
+
+initprofclock()
+{
+#if NCLOCK > 0
+ struct proc *p = curproc; /* XXX */
+
+ /*
+ * If the high-res timer is running, force profiling off.
+ * Unfortunately, this gets reflected back to the user not as
+ * an error but as a lack of results.
+ */
+ if (clockon) {
+ p->p_stats->p_prof.pr_scale = 0;
+ return;
+ }
+ /*
+ * Keep track of the number of user processes that are profiling
+ * by checking the scale value.
+ *
+ * XXX: this all assumes that the profiling code is well behaved;
+ * i.e. profil() is called once per process with pcscale non-zero
+ * to turn it on, and once with pcscale zero to turn it off.
+ * Also assumes you don't do any forks or execs. Oh well, there
+ * is always adb...
+ */
+ if (p->p_stats->p_prof.pr_scale)
+ profprocs++;
+ else
+ profprocs--;
+#endif
+ /*
+ * The profile interrupt interval must be an even divisor
+ * of the CLK_INTERVAL so that scaling from a system clock
+ * tick to a profile clock tick is possible using integer math.
+ */
+ if (profint > CLK_INTERVAL || (CLK_INTERVAL % profint) != 0)
+ profint = CLK_INTERVAL;
+ profscale = CLK_INTERVAL / profint;
+}
+
+startprofclock()
+{
+ unsigned short interval;
+
+ /* stop timer B */
+ ciab.crb = ciab.crb & 0xc0;
+
+ /* load interval into registers.
+ the clocks run at NTSC: 715.909kHz or PAL: 709.379kHz */
+
+ interval = profint - 1;
+
+ /* order of setting is important ! */
+ ciab.tblo = interval & 0xff;
+ ciab.tbhi = interval >> 8;
+
+ /* enable interrupts for timer B */
+ ciab.icr = (1<<7) | (1<<1);
+
+ /* start timer B in continuous shot mode */
+ ciab.crb = (ciab.crb & 0xc0) | 1;
+}
+
+stopprofclock()
+{
+ /* stop timer B */
+ ciab.crb = ciab.crb & 0xc0;
+}
+
+#ifdef PROF
+/*
+ * profclock() is expanded in line in lev6intr() unless profiling kernel.
+ * Assumes it is called with clock interrupts blocked.
+ */
+profclock(pc, ps)
+ caddr_t pc;
+ int ps;
+{
+ /*
+ * Came from user mode.
+ * If this process is being profiled record the tick.
+ */
+ if (USERMODE(ps)) {
+ if (p->p_stats.p_prof.pr_scale)
+ addupc(pc, &curproc->p_stats.p_prof, 1);
+ }
+ /*
+ * Came from kernel (supervisor) mode.
+ * If we are profiling the kernel, record the tick.
+ */
+ else if (profiling < 2) {
+ register int s = pc - s_lowpc;
+
+ if (s < s_textsize)
+ kcount[s / (HISTFRACTION * sizeof (*kcount))]++;
+ }
+ /*
+ * Kernel profiling was on but has been disabled.
+ * Mark as no longer profiling kernel and if all profiling done,
+ * disable the clock.
+ */
+ if (profiling && (profon & PRF_KERNEL)) {
+ profon &= ~PRF_KERNEL;
+ if (profon == PRF_NONE)
+ stopprofclock();
+ }
+}
+#endif
+#endif
+
+/*
+ * Initialize the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+inittodr(base)
+time_t base;
+{
+ u_long timbuf = base; /* assume no battery clock exists */
+
+ timbuf = gettod();
+
+ if(timbuf < base) {
+ printf("WARNING: bad date in battery clock\n");
+ timbuf = base;
+ }
+
+ /* Battery clock does not store usec's, so forget about it. */
+ time.tv_sec = timbuf;
+}
+
+resettodr()
+{
+ if(settod(time.tv_sec) == 1)
+ return;
+ printf("Cannot set battery backed clock\n");
+}
+
+static char dmsize[12] =
+{
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static char ldmsize[12] =
+{
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static __inline__ int rtc_getclkreg(regno)
+int regno;
+{
+ RTC->rtc_regno = RTC_REGA;
+ RTC->rtc_regno = regno;
+ return(RTC->rtc_data & 0377);
+}
+
+static __inline__ void rtc_setclkreg(regno, value)
+int regno, value;
+{
+ RTC->rtc_regno = regno;
+ RTC->rtc_data = value;
+}
+
+static u_long
+gettod()
+{
+ int i, year, mon, day, hour, min, sec;
+ u_long new_time = 0;
+ char *msize;
+
+ /*
+ * Hold clock
+ */
+ rtc_setclkreg(RTC_REGB, rtc_getclkreg(RTC_REGB) | RTC_B_SET);
+
+ /*
+ * Read clock
+ */
+ sec = rtc_getclkreg(RTC_SEC);
+ min = rtc_getclkreg(RTC_MIN);
+ hour = rtc_getclkreg(RTC_HOUR);
+ day = rtc_getclkreg(RTC_DAY) - 1;
+ mon = rtc_getclkreg(RTC_MONTH) - 1;
+ year = rtc_getclkreg(RTC_YEAR) + STARTOFTIME;
+
+ /*
+ * Let it run again..
+ */
+ rtc_setclkreg(RTC_REGB, rtc_getclkreg(RTC_REGB) & ~RTC_B_SET);
+
+ if(range_test(hour, 0, 23))
+ return(0);
+ if(range_test(day, 0, 30))
+ return(0);
+ if (range_test(mon, 0, 11))
+ return(0);
+ if(range_test(year, STARTOFTIME, 2000))
+ return(0);
+
+ for(i = STARTOFTIME; i < year; i++) {
+ if(is_leap(i))
+ new_time += 366;
+ else new_time += 365;
+ }
+
+ msize = is_leap(year) ? ldmsize : dmsize;
+ for(i = 0; i < mon; i++)
+ new_time += msize[i];
+ new_time += day;
+ return((new_time * SECS_DAY) + (hour * 3600) + (min * 60) + sec);
+}
+
+static int
+settod(newtime)
+u_long newtime;
+{
+ register long days, rem, year;
+ register char *ml;
+ int sec, min, hour, month;
+
+ /* Number of days since Jan. 1 1970 */
+ days = newtime / SECS_DAY;
+ rem = newtime % SECS_DAY;
+
+ /*
+ * Calculate sec, min, hour
+ */
+ hour = rem / SECS_HOUR;
+ rem %= SECS_HOUR;
+ min = rem / 60;
+ sec = rem % 60;
+
+ /*
+ * Figure out the year. Day in year is left in 'days'.
+ */
+ year = STARTOFTIME;
+ while(days >= (rem = is_leap(year) ? 366 : 365)) {
+ ++year;
+ days -= rem;
+ }
+ while(days < 0) {
+ --year;
+ days += is_leap(year) ? 366 : 365;
+ }
+
+ /*
+ * Determine the month
+ */
+ ml = is_leap(year) ? ldmsize : dmsize;
+ for(month = 0; days >= ml[month]; ++month)
+ days -= ml[month];
+
+ /*
+ * Now that everything is calculated, program the RTC
+ */
+ rtc_setclkreg(RTC_REGB, RTC_B_SET);
+ rtc_setclkreg(RTC_REGA, RTC_A_DV1|RTC_A_RS2|RTC_A_RS3);
+ rtc_setclkreg(RTC_REGB, RTC_B_SET|RTC_B_SQWE|RTC_B_DM|RTC_B_24_12);
+ rtc_setclkreg(RTC_SEC, sec);
+ rtc_setclkreg(RTC_MIN, min);
+ rtc_setclkreg(RTC_HOUR, hour);
+ rtc_setclkreg(RTC_DAY, days+1);
+ rtc_setclkreg(RTC_MONTH, month+1);
+ rtc_setclkreg(RTC_YEAR, year-1970);
+ rtc_setclkreg(RTC_REGB, RTC_B_SQWE|RTC_B_DM|RTC_B_24_12);
+
+ return(1);
+}
diff --git a/sys/arch/atari/dev/clockioctl.h b/sys/arch/atari/dev/clockioctl.h
new file mode 100644
index 00000000000..03f16574b05
--- /dev/null
+++ b/sys/arch/atari/dev/clockioctl.h
@@ -0,0 +1,47 @@
+/* $NetBSD: clockioctl.h,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1989 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * from: Utah $Hdr: clockioctl.h 1.1 90/07/09$
+ *
+ * @(#)clockioctl.h 7.2 (Berkeley) 11/2/90
+ */
+
+#define CLOCKMAP _IOWR('C', 1, int)
+#define CLOCKUNMAP _IOW('C', 2, int)
+#define CLOCKGETRES _IOR('C', 3, int)
diff --git a/sys/arch/atari/dev/clockreg.h b/sys/arch/atari/dev/clockreg.h
new file mode 100644
index 00000000000..dc6fb1548a3
--- /dev/null
+++ b/sys/arch/atari/dev/clockreg.h
@@ -0,0 +1,114 @@
+/* $NetBSD: clockreg.h,v 1.1.1.1 1995/03/26 07:12:15 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _CLOCKREG_H
+#define _CLOCKREG_H
+/*
+ * Atari TT hardware:
+ * Motorola MC146818A RealTimeClock
+ */
+
+#define RTC ((struct rtc *)AD_RTC)
+
+struct rtc {
+ volatile u_char rtc_dat[4];
+};
+
+#define rtc_regno rtc_dat[1] /* register nr. select */
+#define rtc_data rtc_dat[3] /* data register */
+
+/*
+ * Register number definitions
+ */
+#define RTC_SEC 0
+#define RTC_ASEC 1
+#define RTC_MIN 2
+#define RTC_A_MIN 3
+#define RTC_HOUR 4
+#define RTC_A_HOUR 5
+#define RTC_WDAY 6
+#define RTC_DAY 7
+#define RTC_MONTH 8
+#define RTC_YEAR 9
+#define RTC_REGA 10
+#define RTC_REGB 11
+#define RTC_REGC 12
+#define RTC_REGD 13
+#define RTC_RAMBOT 14 /* Reg. offset of nv-RAM */
+#define RTC_RAMSIZ 50 /* #bytes of nv-RAM available */
+
+/*
+ * Define fields for register A
+ */
+#define RTC_A_UIP 0x80 /* Update In Progress */
+#define RTC_A_DV2 0x40 /* Divider select */
+#define RTC_A_DV1 0x20 /* Divider select */
+#define RTC_A_DV0 0x10 /* Divider select */
+#define RTC_A_RS3 0x08 /* Rate Select */
+#define RTC_A_RS2 0x04 /* Rate Select */
+#define RTC_A_RS1 0x02 /* Rate Select */
+#define RTC_A_RS0 0x01 /* Rate Select */
+
+/*
+ * Define fields for register B
+ */
+#define RTC_B_SET 0x80 /* SET date/time */
+#define RTC_B_PIE 0x40 /* Periodic Int. Enable */
+#define RTC_B_AIE 0x20 /* Alarm Int. Enable */
+#define RTC_B_UIE 0x10 /* Update Ended Int. Enable */
+#define RTC_B_SQWE 0x08 /* Square Wave Output Enable */
+#define RTC_B_DM 0x04 /* Binary Data mode */
+#define RTC_B_24_12 0x02 /* 24 Hour mode */
+#define RTC_B_DSE 0x01 /* DST Enable */
+
+/*
+ * Define fields for register C
+ */
+#define RTC_C_IRQF 0x80 /* IRQ flag */
+#define RTC_C_PF 0x40 /* Periodic Int. flag */
+#define RTC_C_AF 0x20 /* Alarm Int. flag */
+#define RTC_C_UF 0x10 /* Update Ended Int. flag */
+
+/*
+ * Define fields for register D
+ */
+#define RTC_D_VRT 0x80 /* Valid Ram and Time */
+
+/*
+ * Some useful constants/macros
+ */
+#define is_leap(x) (!(x % 4) && ((x % 100) || !(x % 1000)))
+#define range_test(n, l, h) ((n) < (l) || (n) > (h))
+#define SECS_DAY 86400L
+#define SECS_HOUR 3600L
+#define STARTOFTIME 1970
+#endif /* _CLOCKREG_H */
diff --git a/sys/arch/atari/dev/dma.c b/sys/arch/atari/dev/dma.c
new file mode 100644
index 00000000000..bca7297ac12
--- /dev/null
+++ b/sys/arch/atari/dev/dma.c
@@ -0,0 +1,202 @@
+/* $NetBSD: dma.c,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file contains special code dealing with the DMA interface
+ * on the Atari ST.
+ *
+ * The DMA circuitry requires some special treatment for the peripheral
+ * devices which make use of the ST's DMA feature (the hard disk and the
+ * floppy drive).
+ * All devices using DMA need mutually exclusive access and can follow some
+ * standard pattern which will be provided in this file.
+ *
+ * The file contains the following entry points:
+ *
+ * dmagrab: ensure exclusive access to the DMA circuitry
+ * dmafree: free exclusive access to the DMA circuitry
+ * dmaint: DMA interrupt routine, switches to the current driver
+ * dmaaddr: specify 24 bit RAM address
+ * dmardat: set dma_mode and read word from dma_data
+ * dmawdat: set dma_mode and write word to dma_data
+ * dmacomm: like dmawdat, but first toggle WRBIT
+ *
+ * FIXME: The delay-loops should be done otherwise!
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/dma.h>
+
+#define NDMA_DEV 10 /* Max 2 floppy's, 8 hard-disks */
+typedef struct {
+ int (*call_func)();
+ int (*int_func)();
+ void *softc;
+} DMA_DISP;
+
+static DMA_DISP dispatch[NDMA_DEV]; /* dispatch table */
+static int dma_free = 0; /* next free entry in dispatch table */
+static int dma_curr = 0; /* current entry in dispatch table */
+static int dmalock = 0; /* if != 0, dma is not free */
+static int (*xxxint)(); /* current interrupt function */
+static void *dma_softc; /* Device currently owning DMA-intr */
+static int sched_soft = 0; /* Software interrupt scheduled */
+
+static void cdmasoft __P((void));
+
+dmagrab(int_func, call_func, softc)
+int (*int_func)();
+int (*call_func)();
+void *softc;
+{
+ int sps;
+ DMA_DISP *disp;
+
+ sps = splbio();
+
+ if(dmalock) {
+ disp = &dispatch[dma_free++];
+ if(dma_free >= NDMA_DEV)
+ dma_free = 0;
+ if(disp->call_func != NULL)
+ panic("dma dispatch table overflow");
+ disp->call_func = call_func;
+ disp->int_func = int_func;
+ disp->softc = softc;
+ splx(sps);
+ return;
+ }
+ dmalock++;
+ xxxint = int_func; /* Grab DMA interrupts */
+ dma_softc = softc; /* Identify device which got DMA */
+ (*call_func)(softc); /* Call followup function */
+ splx(sps);
+
+}
+
+dmafree()
+{
+ int sps;
+ DMA_DISP *disp;
+
+ sps = splbio();
+ disp = &dispatch[dma_curr];
+ if(disp->call_func != NULL) {
+ xxxint = disp->int_func;
+ dma_softc = disp->softc;
+ (*disp->call_func)(dma_softc);
+ disp->call_func = NULL;
+ if(++dma_curr >= NDMA_DEV)
+ dma_curr = 0;
+ splx(sps);
+ return;
+ }
+ dmalock = 0;
+ xxxint = NULL; /* no more DMA interrupts */
+ splx(sps);
+}
+
+cdmaint(sr)
+long sr; /* sr at time of interrupt */
+{
+ if(xxxint != NULL) {
+ if(!BASEPRI(sr)) {
+ if(!sched_soft++)
+ add_sicallback(cdmasoft, 0, 0);
+ }
+ else {
+ spl1();
+ cdmasoft();
+ }
+ }
+ else printf("DMA interrupt discarded\r\n");
+}
+
+static void cdmasoft()
+{
+ sched_soft = 0;
+ (*xxxint)(dma_softc);
+}
+
+dmaaddr(address)
+caddr_t address;
+{
+ register u_long ad = (u_long)address;
+
+ DMA->dma_addr[AD_LOW ] = (ad ) & 0xff;
+ DMA->dma_addr[AD_MID ] = (ad >> 8) & 0xff;
+ DMA->dma_addr[AD_HIGH] = (ad >>16) & 0xff;
+}
+
+int
+dmardat(mode, delay)
+int mode, delay;
+{
+ while(--delay >= 0);
+ DMA->dma_mode = mode;
+ while(--delay >= 0);
+ return(DMA->dma_data);
+}
+
+dmawdat(mode, data, delay)
+int mode, data, delay;
+{
+ DMA->dma_mode = mode;
+ while(--delay >= 0);
+ DMA->dma_data = data;
+ while(--delay >= 0);
+}
+
+dmacomm(mode, data, delay)
+int mode, data, delay;
+{
+ DMA->dma_mode = mode;
+ DMA->dma_mode = mode ^ WRBIT;
+ DMA->dma_mode = mode;
+ while(--delay >= 0);
+ DMA->dma_data = data;
+ while(--delay >= 0);
+}
+
+int
+dmastat(mode, delay)
+int mode, delay;
+{
+ while(--delay >= 0);
+ DMA->dma_mode = mode;
+ while(--delay >= 0);
+ return(DMA->dma_stat);
+}
diff --git a/sys/arch/atari/dev/event.c b/sys/arch/atari/dev/event.c
new file mode 100644
index 00000000000..df1126652cd
--- /dev/null
+++ b/sys/arch/atari/dev/event.c
@@ -0,0 +1,173 @@
+/* $NetBSD: event.c,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)event.c 8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: event.c,v 1.5 92/11/26 01:10:44 torek Exp (LBL)
+ */
+
+/*
+ * Internal `Firm_event' interface for the keyboard and mouse drivers.
+ */
+
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+
+#include <amiga/dev/vuid_event.h>
+#include <amiga/dev/event_var.h>
+
+/*
+ * Initialize a firm_event queue.
+ */
+void
+ev_init(ev)
+ register struct evvar *ev;
+{
+
+ ev->ev_get = ev->ev_put = 0;
+ ev->ev_q = malloc((u_long)EV_QSIZE * sizeof(struct firm_event),
+ M_DEVBUF, M_WAITOK);
+ bzero((caddr_t)ev->ev_q, EV_QSIZE * sizeof(struct firm_event));
+}
+
+/*
+ * Tear down a firm_event queue.
+ */
+void
+ev_fini(ev)
+ register struct evvar *ev;
+{
+
+ free(ev->ev_q, M_DEVBUF);
+}
+
+/*
+ * User-level interface: read, select.
+ * (User cannot write an event queue.)
+ */
+int
+ev_read(ev, uio, flags)
+ register struct evvar *ev;
+ struct uio *uio;
+ int flags;
+{
+ int s, n, cnt, error;
+
+ /*
+ * Make sure we can return at least 1.
+ */
+ if (uio->uio_resid < sizeof(struct firm_event))
+ return (EMSGSIZE); /* ??? */
+ s = splev();
+ while (ev->ev_get == ev->ev_put) {
+ if (flags & IO_NDELAY) {
+ splx(s);
+ return (EWOULDBLOCK);
+ }
+ ev->ev_wanted = 1;
+ error = tsleep((caddr_t)ev, PEVENT | PCATCH, "firm_event", 0);
+ if (error) {
+ splx(s);
+ return (error);
+ }
+ }
+ /*
+ * Move firm_events from tail end of queue (there is at least one
+ * there).
+ */
+ if (ev->ev_put < ev->ev_get)
+ cnt = EV_QSIZE - ev->ev_get; /* events in [get..QSIZE) */
+ else
+ cnt = ev->ev_put - ev->ev_get; /* events in [get..put) */
+ splx(s);
+ n = howmany(uio->uio_resid, sizeof(struct firm_event));
+ if (cnt > n)
+ cnt = n;
+ error = uiomove((caddr_t)&ev->ev_q[ev->ev_get],
+ cnt * sizeof(struct firm_event), uio);
+ n -= cnt;
+ /*
+ * If we do not wrap to 0, used up all our space, or had an error,
+ * stop. Otherwise move from front of queue to put index, if there
+ * is anything there to move.
+ */
+ if ((ev->ev_get = (ev->ev_get + cnt) % EV_QSIZE) != 0 ||
+ n == 0 || error || (cnt = ev->ev_put) == 0)
+ return (error);
+ if (cnt > n)
+ cnt = n;
+ error = uiomove((caddr_t)&ev->ev_q[0],
+ cnt * sizeof(struct firm_event), uio);
+ ev->ev_get = cnt;
+ return (error);
+}
+
+int
+ev_select(ev, rw, p)
+ register struct evvar *ev;
+ int rw;
+ struct proc *p;
+{
+ int s = splev();
+
+ switch (rw) {
+
+ case FREAD:
+ /* succeed if there is something to read */
+ if (ev->ev_get != ev->ev_put) {
+ splx(s);
+ return (1);
+ }
+ selrecord(p, &ev->ev_sel);
+ break;
+
+ case FWRITE:
+ return (1); /* always fails => never blocks */
+ }
+ splx(s);
+ return (0);
+}
diff --git a/sys/arch/atari/dev/event_var.h b/sys/arch/atari/dev/event_var.h
new file mode 100644
index 00000000000..766bc2632fa
--- /dev/null
+++ b/sys/arch/atari/dev/event_var.h
@@ -0,0 +1,89 @@
+/* $NetBSD: event_var.h,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)event_var.h 8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: event_var.h,v 1.5 92/11/26 01:11:51 torek Exp (LBL)
+ */
+
+/*
+ * Internal `Firm_event' interface for the keyboard and mouse drivers.
+ * The drivers are expected not to place events in the queue above spltty(),
+ * i.e., are expected to run off serial ports.
+ */
+
+/* EV_QSIZE should be a power of two so that `%' is fast */
+#define EV_QSIZE 256 /* may need tuning; this uses 2k */
+
+struct evvar {
+ u_int ev_get; /* get (read) index (modified synchronously) */
+ volatile u_int ev_put; /* put (write) index (modified by interrupt) */
+ struct selinfo ev_sel; /* process selecting */
+ struct proc *ev_io; /* process that opened queue (can get SIGIO) */
+ char ev_wanted; /* wake up on input ready */
+ char ev_async; /* send SIGIO on input ready */
+ struct firm_event *ev_q;/* circular buffer (queue) of events */
+};
+
+#define splev() spltty()
+
+#define EV_WAKEUP(ev) { \
+ selwakeup(&(ev)->ev_sel); \
+ if ((ev)->ev_wanted) { \
+ (ev)->ev_wanted = 0; \
+ wakeup((caddr_t)(ev)); \
+ } \
+ if ((ev)->ev_async) \
+ psignal((ev)->ev_io, SIGIO); \
+}
+
+void ev_init __P((struct evvar *));
+void ev_fini __P((struct evvar *));
+int ev_read __P((struct evvar *, struct uio *, int));
+int ev_select __P((struct evvar *, int, struct proc *));
+
+/*
+ * PEVENT is set just above PSOCK, which is just above TTIPRI, on the
+ * theory that mouse and keyboard `user' input should be quick.
+ */
+#define PEVENT 23
diff --git a/sys/arch/atari/dev/fd.c b/sys/arch/atari/dev/fd.c
new file mode 100644
index 00000000000..708b905dd0d
--- /dev/null
+++ b/sys/arch/atari/dev/fd.c
@@ -0,0 +1,1061 @@
+/* $NetBSD: fd.c,v 1.1.1.1 1995/03/26 07:12:11 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file contains a driver for the Floppy Disk Controller (FDC)
+ * on the Atari TT. It uses the WD 1772 chip, modified for steprates.
+ *
+ * The ST floppy disk controller shares the access to the DMA circuitry
+ * with other devices. For this reason the floppy disk controller makes
+ * use of some special DMA accessing code.
+ *
+ * Interrupts from the FDC are in fact DMA interrupts which get their
+ * first level handling in 'dma.c' . If the floppy driver is currently
+ * using DMA the interrupt is signalled to 'fdcint'.
+ *
+ * TODO:
+ * - Test it with 2 drives (I don't have them)
+ * - Test it with an HD-drive (Don't have that either)
+ * - Finish ioctl's
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/conf.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/dkbad.h>
+#include <atari/atari/device.h>
+#include <machine/disklabel.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+#include <machine/dma.h>
+#include <machine/video.h>
+#include <atari/dev/fdreg.h>
+
+/*
+ * Be verbose for debugging
+ */
+/*#define FLP_DEBUG 1 */
+
+#define FDC_DELAY 64 /* for dma[rw]dat() */
+#define FDC_MAX_DMA_AD 0x1000000 /* No DMA possible beyond */
+
+/* Parameters for the disk drive. */
+#define SECTOR_SIZE 512 /* physical sector size in bytes */
+#define NR_DRIVES 2 /* maximum number of drives */
+#define NR_TYPES 3 /* number of diskette/drive combinations*/
+#define MAX_ERRORS 10 /* how often to try rd/wt before quitting*/
+#define STEP_DELAY 6000 /* 6ms (6000us) delay after stepping */
+
+
+#define INV_TRK 32000 /* Should fit in unsigned short */
+#define INV_PART NR_TYPES
+
+/*
+ * Driver states
+ */
+#define FLP_IDLE 0x00 /* floppy is idle */
+#define FLP_MON 0x01 /* idle with motor on */
+#define FLP_STAT 0x02 /* determine floppy status */
+#define FLP_XFER 0x04 /* read/write data from floppy */
+
+/*
+ * Timer delay's
+ */
+#define FLP_MONDELAY (3 * hz) /* motor-on delay */
+#define FLP_XFERDELAY (2 * hz) /* timeout on transfer */
+
+
+#define b_block b_resid /* FIXME: this is not the place */
+
+/*
+ * Global data for all physical floppy devices
+ */
+static short selected = 0; /* drive/head currently selected*/
+static short motoron = 0; /* motor is spinning */
+static short nopens = 0; /* Number of opens executed */
+
+static short fd_state = FLP_IDLE;/* Current driver state */
+static short fd_in_dma= 0; /* 1: dmagrab() called */
+static short fd_cmd = 0; /* command being executed */
+static char *fd_error= NULL; /* error from fd_xfer_ok() */
+
+/*
+ * Private per device data
+ */
+struct fd_softc {
+ struct dkdevice dkdev;
+ struct buf bufq; /* queue of buf's */
+ int unit; /* unit for atari controlling hw*/
+ int nheads; /* number of heads in use */
+ int nsectors; /* number of sectors/track */
+ int nblocks; /* number of blocks on disk */
+ int curtrk; /* track head positioned on */
+ short flags; /* misc flags */
+ short part; /* Current open partition */
+ int sector; /* logical sector for I/O */
+ caddr_t io_data; /* KVA for data transfer */
+ int io_bytes; /* bytes left for I/O */
+ int io_dir; /* B_READ/B_WRITE */
+ int errcnt; /* current error count */
+ u_char *bounceb; /* Bounce buffer */
+
+};
+
+/*
+ * Flags in fd_softc:
+ */
+#define FLPF_NOTRESP 0x01 /* Unit not responding */
+#define FLPF_ISOPEN 0x02 /* Unit is open */
+#define FLPF_ISHD 0x04 /* Use High Density */
+#define FLPF_HAVELAB 0x08 /* We have a valid label */
+#define FLPF_BOUNCE 0x10 /* Now using the bounce buffer */
+
+struct fd_types {
+ int nheads; /* Heads in use */
+ int nsectors; /* sectors per track */
+ int nblocks; /* number of blocks */
+} fdtypes[NR_TYPES] = {
+ { 1, 9, 720 }, /* 360 Kb */
+ { 2, 9, 1440 }, /* 720 Kb */
+ { 1, 18, 2880 }, /* 1.44 Mb */
+};
+
+typedef void (*FPV)();
+
+/*
+ * Private drive functions....
+ */
+static void fdstart __P((struct fd_softc *));
+static void fddone __P((struct fd_softc *));
+static void fd_xfer __P((struct fd_softc *));
+static int fdcint __P((struct fd_softc *));
+static int fd_xfer_ok __P((struct fd_softc *));
+static void fdmotoroff __P((struct fd_softc *));
+static int fdminphys __P((struct buf *));
+static void fdtestdrv __P((struct fd_softc *));
+static int fdgetdisklabel __P((struct fd_softc *, dev_t));
+
+/*
+ * Autoconfig stuff....
+ */
+static int fdcmatch __P((struct device *, struct cfdata *, void *));
+static int fdcprint __P((void *, char *));
+static void fdcattach __P((struct device *, struct device *, void *));
+
+struct cfdriver fdccd = {
+ NULL, "fdc", (cfmatch_t)fdcmatch, fdcattach, DV_DULL,
+ sizeof(struct device), NULL, 0 };
+
+static int
+fdcmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp("fdc", auxp) || cfp->cf_unit != 0)
+ return(0);
+ return(1);
+}
+
+static void
+fdcattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ struct fd_softc fdsoftc;
+ int i, nfound = 0;
+
+ printf("\n");
+ for(i = 0; i < NR_DRIVES; i++) {
+
+ /*
+ * Test if unit is present
+ */
+ fdsoftc.unit = i;
+ fdsoftc.flags = 0;
+ dmagrab(fdcint, fdtestdrv, &fdsoftc);
+ dmafree();
+
+ if(!(fdsoftc.flags & FLPF_NOTRESP)) {
+ nfound++;
+ config_found(dp, (void*)i, fdcprint);
+ }
+ }
+
+ if(nfound) {
+ /*
+ * enable disk related interrupts
+ */
+ MFP->mf_ierb |= IB_DINT;
+ MFP->mf_iprb &= ~IB_DINT;
+ MFP->mf_imrb |= IB_DINT;
+ }
+}
+
+static int
+fdcprint(auxp, pnp)
+void *auxp;
+char *pnp;
+{
+ return(UNCONF);
+}
+
+static int fdmatch __P((struct device *, struct cfdata *, void *));
+static void fdattach __P((struct device *, struct device *, void *));
+ void fdstrategy __P((struct buf *));
+struct dkdriver fddkdriver = { fdstrategy };
+
+struct cfdriver fdcd = {
+ NULL, "fd", (cfmatch_t)fdmatch, fdattach, DV_DISK,
+ sizeof(struct fd_softc), NULL, 0 };
+
+static int
+fdmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ int unit = (int)auxp;
+ return(1);
+}
+
+static void
+fdattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ struct fd_softc *sc;
+
+ sc = (struct fd_softc *)dp;
+
+ printf("\n");
+
+ sc->dkdev.dk_driver = &fddkdriver;
+}
+
+fdioctl(dev, cmd, addr, flag, p)
+dev_t dev;
+u_long cmd;
+int flag;
+caddr_t addr;
+struct proc *p;
+{
+ struct fd_softc *sc;
+ void *data;
+
+ sc = getsoftc(fdcd, DISKUNIT(dev));
+
+ if((sc->flags & FLPF_HAVELAB) == 0)
+ return(EBADF);
+
+ switch(cmd) {
+ case DIOCSBAD:
+ return(EINVAL);
+ case DIOCGDINFO:
+ *(struct disklabel *)addr = sc->dkdev.dk_label;
+ return(0);
+ case DIOCGPART:
+ ((struct partinfo *)addr)->disklab =
+ &sc->dkdev.dk_label;
+ ((struct partinfo *)addr)->part =
+ &sc->dkdev.dk_label.d_partitions[DISKPART(dev)];
+ return(0);
+#ifdef notyet /* XXX LWP */
+ case DIOCSRETRIES:
+ case DIOCSSTEP:
+ case DIOCSDINFO:
+ case DIOCWDINFO:
+ case DIOCWLABEL:
+#endif /* notyet */
+ default:
+ return(ENOTTY);
+ }
+}
+
+/*
+ * Open the device. If this is the first open on both the floppy devices,
+ * intialize the controller.
+ * Note that partition info on the floppy device is used to distinguise
+ * between 780Kb and 360Kb floppy's.
+ * partition 0: 360Kb
+ * partition 1: 780Kb
+ */
+Fdopen(dev, flags, devtype, proc)
+dev_t dev;
+int flags, devtype;
+struct proc *proc;
+{
+ struct fd_softc *sc;
+ int sps;
+
+#ifdef FLP_DEBUG
+ printf("Fdopen dev=0x%x\n", dev);
+#endif
+
+ if(DISKPART(dev) >= NR_TYPES)
+ return(ENXIO);
+
+ if((sc = getsoftc(fdcd, DISKUNIT(dev))) == NULL)
+ return(ENXIO);
+
+ /*
+ * If no floppy currently open, reset the controller and select
+ * floppy type.
+ */
+ if(!nopens) {
+
+#ifdef FLP_DEBUG
+ printf("Fdopen device not yet open\n");
+#endif
+ nopens++;
+ dmawdat(FDC_CS, IRUPT, FDC_DELAY);
+ }
+
+ if(!(sc->flags & FLPF_ISOPEN)) {
+ /*
+ * Initialise some driver values.
+ */
+ int part = DISKPART(dev);
+ void *addr;
+
+ sc->bufq.b_actf = NULL;
+ sc->unit = DISKUNIT(dev);
+ sc->part = part;
+ sc->nheads = fdtypes[part].nheads;
+ sc->nsectors = fdtypes[part].nsectors;
+ sc->nblocks = fdtypes[part].nblocks;
+ sc->curtrk = INV_TRK;
+ sc->sector = 0;
+ sc->errcnt = 0;
+ sc->bounceb = (u_char*)alloc_stmem(SECTOR_SIZE, &addr);
+ if(sc->bounceb == NULL)
+ return(ENOMEM); /* XXX */
+ if(sc->nsectors > 9) /* XXX */
+ sc->flags |= FLPF_ISHD;
+
+ sc->flags = FLPF_ISOPEN;
+ }
+ else {
+ /*
+ * Multiply opens are granted when accessing the same type of
+ * floppy (eq. the same partition).
+ */
+ if(sc->part != DISKPART(dev))
+ return(ENXIO); /* XXX temporarely out of business */
+ }
+ fdgetdisklabel(sc, dev);
+#ifdef FLP_DEBUG
+ printf("Fdopen open succeeded on type %d\n", sc->part);
+#endif
+}
+
+Fdclose(dev, flags, devtype, proc)
+dev_t dev;
+int flags, devtype;
+struct proc *proc;
+{
+ struct fd_softc *sc;
+
+ sc = getsoftc(fdcd, DISKUNIT(dev));
+ free_stmem(sc->bounceb);
+ sc->flags = 0;
+ nopens--;
+
+#ifdef FLP_DEBUG
+ printf("Closed floppy device -- nopens: %d\n", nopens);
+#endif
+}
+
+void
+fdstrategy(bp)
+struct buf *bp;
+{
+ struct fd_softc *sc;
+ int sps, nblocks;
+
+ sc = getsoftc(fdcd, DISKUNIT(bp->b_dev));
+
+#ifdef FLP_DEBUG
+ printf("fdstrategy: 0x%x\n", bp);
+#endif
+
+ /*
+ * check for valid partition and bounds
+ */
+ nblocks = (bp->b_bcount + SECTOR_SIZE - 1) / SECTOR_SIZE;
+ if((bp->b_blkno < 0) || ((bp->b_blkno + nblocks) >= sc->nblocks)) {
+ if((bp->b_blkno == sc->nblocks) && (bp->b_flags & B_READ)) {
+ /*
+ * Read 1 block beyond, return EOF
+ */
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ /*
+ * Try to limit the size of the transaction, adjust count
+ * if we succeed.
+ */
+ nblocks = sc->nblocks - bp->b_blkno;
+ if((nblocks <= 0) || (bp->b_blkno < 0)) {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR;
+ goto done;
+ }
+ bp->b_bcount = nblocks * SECTOR_SIZE;
+ }
+ if(bp->b_bcount == 0)
+ goto done;
+
+ /*
+ * Set order info for disksort
+ */
+ bp->b_block = bp->b_blkno / (sc->nsectors * sc->nheads);
+
+ /*
+ * queue the buf and kick the low level code
+ */
+ sps = splbio();
+ disksort(&sc->bufq, bp);
+ if(!fd_in_dma) {
+ if(fd_state & FLP_MON)
+ untimeout((FPV)fdmotoroff, (void*)sc);
+ fd_state = FLP_IDLE;
+ fd_in_dma = 1; dmagrab(fdcint, fdstart, sc);
+ }
+ splx(sps);
+
+ return;
+done:
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+}
+
+/*
+ * no dumps to floppy disks thank you.
+ */
+int
+fdsize(dev)
+dev_t dev;
+{
+ return(-1);
+}
+
+int
+fdread(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return(physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
+ dev, B_READ, fdminphys, uio));
+}
+
+int
+fdwrite(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return(physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
+ dev, B_WRITE, fdminphys, uio));
+}
+
+/*
+ * Called through the dma-dispatcher. So we know we are the only ones
+ * messing with the floppy-controler.
+ * Initialize some fields in the fdsoftc for the state-machine and get
+ * it going.
+ */
+static void
+fdstart(sc)
+struct fd_softc *sc;
+{
+ struct buf *bp;
+
+ bp = sc->bufq.b_actf;
+ sc->sector = bp->b_blkno; /* Start sector for I/O */
+ sc->io_data = bp->b_data; /* KVA base for I/O */
+ sc->io_bytes = bp->b_bcount; /* Transfer size in bytes */
+ sc->io_dir = bp->b_flags & B_READ;/* Direction of transfer */
+ sc->errcnt = 0; /* No errors yet */
+ fd_state = FLP_XFER; /* Yes, we're going to transfer */
+
+ /*
+ * Make sure the floppy controller is the correct density mode
+ */
+ if(sc->flags & FLPF_ISHD)
+ DMA->dma_drvmode |= (FDC_HDSET|FDC_HDSIG);
+ else DMA->dma_drvmode &= ~(FDC_HDSET|FDC_HDSIG);
+ fd_xfer(sc);
+}
+
+/*
+ * The current transaction is finished (for good or bad). Let go of
+ * the the dma-resources. Call biodone() to finish the transaction.
+ * Find a new transaction to work on.
+ */
+static void
+fddone(sc)
+register struct fd_softc *sc;
+{
+ struct buf *bp, *dp;
+ struct fd_softc *sc1;
+ int i;
+
+ /*
+ * Lower clock frequency of FDC (better for some old ones).
+ */
+ DMA->dma_drvmode &= ~(FDC_HDSET|FDC_HDSIG);
+
+ dp = &sc->bufq;
+ bp = dp->b_actf;
+ if(bp == NULL)
+ panic("fddone");
+ dp->b_actf = bp->b_actf;
+
+#ifdef FLP_DEBUG
+ printf("fddone: unit: %d, buf: %x, resid: %d\n",sc->unit,bp,
+ sc->io_bytes);
+#endif
+ /*
+ * Give others a chance to use the dma.
+ */
+ fd_in_dma = 0; dmafree();
+
+ /*
+ * Finish current transaction.
+ */
+ bp->b_resid = sc->io_bytes;
+ biodone(bp);
+
+ if(fd_in_dma)
+ return; /* XXX Is this possible? */
+
+ /*
+ * Find a new transaction on round-robin basis.
+ */
+ for(i = sc->unit + 1; ;i++) {
+ if(i >= fdcd.cd_ndevs)
+ i = 0;
+ if((sc1 = fdcd.cd_devs[i]) == NULL)
+ continue;
+ if(sc1->bufq.b_actf)
+ break;
+ if(i == sc->unit) {
+ timeout((FPV)fdmotoroff, (void*)sc, FLP_MONDELAY);
+#ifdef FLP_DEBUG
+ printf("fddone: Nothing to do\n");
+#endif
+ return; /* No work */
+ }
+ }
+ fd_state = FLP_IDLE;
+#ifdef FLP_DEBUG
+ printf("fddone: Staring job on unit %d\n", sc1->unit);
+#endif
+ fd_in_dma = 1; dmagrab(fdcint, fdstart, sc1);
+}
+
+/****************************************************************************
+ * The following functions assume to be running as a result of a *
+ * disk-interrupt (e.q. spl = splbio). *
+ * They form the finit-state machine, the actual driver. *
+ * *
+ * fdstart()/ --> fd_xfer() -> activate hardware *
+ * fdopen() ^ *
+ * | *
+ * +-- not ready -<------------+ *
+ * | *
+ * fdmotoroff()/ --> fdcint() -> fd_xfer_ok() ---+ *
+ * h/w interrupt | *
+ * \|/ *
+ * finished ---> fdone() *
+ * *
+ ****************************************************************************/
+static void
+fd_xfer(sc)
+struct fd_softc *sc;
+{
+ register int head = 0;
+ register int track, sector, hbit;
+ int i;
+ u_long phys_addr;
+
+ if(fd_state != FLP_XFER)
+ panic("fd_xfer: wrong state (0x%x)", fd_state);
+
+ /*
+ * Calculate head/track values
+ */
+ track = sc->sector / sc->nsectors;
+ head = track % sc->nheads;
+ track = track / sc->nheads;
+#ifdef FLP_DEBUG
+ printf("fd_xfer: sector:%d,head:%d,track:%d\n", sc->sector,head,track);
+#endif
+
+ /*
+ * Determine if the controller should check spin-up.
+ */
+ hbit = motoron ? HBIT : 0;
+ motoron = 1;
+
+ /*
+ * Select the right unit and head.
+ */
+ i = (sc->unit ? PA_FLOP1 : PA_FLOP0) | head;
+ if(i != selected) {
+ selected = i;
+ SOUND->sd_selr = YM_IOA;
+ SOUND->sd_wdat = (SOUND->sd_rdat & 0xF8) | (i ^ 0x07);
+ }
+
+ if(sc->curtrk == INV_TRK) {
+ /*
+ * Recalibrate, since we lost track of head positioning.
+ * The floppy disk controller has no way of determining its
+ * absolute arm position (track). Instead, it steps the
+ * arm a track at a time and keeps track of where it
+ * thinks it is (in software). However, after a SEEK, the
+ * hardware reads information from the diskette telling
+ * where the arm actually is. If the arm is in the wrong place,
+ * a recalibration is done, which forces the arm to track 0.
+ * This way the controller can get back into sync with reality.
+ */
+ dmawdat(FDC_CS, RESTORE|VBIT|hbit, FDC_DELAY);
+ fd_cmd = RESTORE;
+ timeout((FPV)fdmotoroff, (void*)sc, FLP_XFERDELAY);
+
+#ifdef FLP_DEBUG
+ printf("fd_xfer:Recalibrating drive %d\n", sc->unit);
+#endif
+ return;
+ }
+
+ dmawdat(FDC_TR, sc->curtrk, FDC_DELAY);
+
+ /*
+ * Issue a SEEK command on the indicated drive unless the arm is
+ * already positioned on the correct track.
+ */
+ if(track != sc->curtrk) {
+ sc->curtrk = track; /* be optimistic */
+ dmawdat(FDC_DR, track, FDC_DELAY);
+ dmawdat(FDC_CS, SEEK|RATE6|VBIT|hbit, FDC_DELAY);
+ timeout((FPV)fdmotoroff, (void*)sc, FLP_XFERDELAY);
+ fd_cmd = SEEK;
+#ifdef FLP_DEBUG
+ printf("fd_xfer:Seek to track %d on drive %d\n",track,sc->unit);
+#endif
+ return;
+ }
+
+ /*
+ * The drive is now on the proper track. Read or write 1 block.
+ */
+ sector = sc->sector % sc->nsectors;
+ sector++; /* start numbering at 1 */
+
+ dmawdat(FDC_SR, sector, FDC_DELAY);
+
+ phys_addr = (u_long)kvtop(sc->io_data);
+ if(phys_addr >= FDC_MAX_DMA_AD) {
+ /*
+ * We _must_ bounce this address
+ */
+ phys_addr = (u_long)kvtop(sc->bounceb);
+ if(sc->io_dir == B_WRITE)
+ bcopy(sc->io_data, sc->bounceb, SECTOR_SIZE);
+ sc->flags |= FLPF_BOUNCE;
+ }
+ dmaaddr(phys_addr); /* DMA address setup */
+
+#ifdef FLP_DEBUG
+ printf("fd_xfer:Start io (io_addr:%x)\n", kvtop(sc->io_data));
+#endif
+
+ if(sc->io_dir == B_READ) {
+ /* Issue the command */
+ dmacomm(FDC | SCREG, 1, 0);
+ dmawdat(FDC_CS, F_READ|hbit, FDC_DELAY);
+ fd_cmd = F_READ;
+ }
+ else {
+ /* Issue the command */
+ dmacomm(WRBIT | FDC | SCREG, 1, FDC_DELAY);
+ dmawdat(WRBIT | FDC_CS, F_WRITE|hbit|EBIT|PBIT, FDC_DELAY);
+ fd_cmd = F_WRITE;
+ }
+ timeout((FPV)fdmotoroff, (void*)sc, FLP_XFERDELAY);
+}
+
+/* return values of fd_xfer_ok(): */
+#define X_OK 0
+#define X_AGAIN 1
+#define X_ERROR 2
+#define X_FAIL 3
+
+/*
+ * Hardware interrupt function.
+ */
+static int
+fdcint(sc)
+struct fd_softc *sc;
+{
+ struct buf *bp;
+
+#ifdef FLP_DEBUG
+ printf("fdcint: unit = %d\n", sc->unit);
+#endif
+
+ /*
+ * Cancel timeout (we made it, didn't we)
+ */
+ untimeout((FPV)fdmotoroff, (void*)sc);
+
+ switch(fd_xfer_ok(sc)) {
+ case X_ERROR :
+ if(++(sc->errcnt) < MAX_ERRORS) {
+ /*
+ * Command failed but still retries left.
+ */
+ break;
+ }
+ /* FALL THROUGH */
+ case X_FAIL :
+ /*
+ * Non recoverable error. Fall back to motor-on
+ * idle-state.
+ */
+ bp = sc->bufq.b_actf;
+
+ bp->b_error = EIO;
+ bp->b_flags |= B_ERROR;
+ fd_state = FLP_MON;
+ if(fd_error != NULL) {
+ printf("Floppy error: %s\n", fd_error);
+ fd_error = NULL;
+ }
+
+ break;
+ case X_AGAIN:
+ /*
+ * Start next part of state machine.
+ */
+ break;
+ case X_OK:
+ /*
+ * Command ok and finished. Reset error-counter.
+ * If there are no more bytes to transfer fall back
+ * to motor-on idle state.
+ */
+ sc->errcnt = 0;
+ if((sc->flags & FLPF_BOUNCE) && (sc->io_dir == B_READ))
+ bcopy(sc->bounceb, sc->io_data, SECTOR_SIZE);
+ sc->flags &= ~FLPF_BOUNCE;
+
+ sc->sector++;
+ sc->io_data += SECTOR_SIZE;
+ sc->io_bytes -= SECTOR_SIZE;
+ if(sc->io_bytes <= 0)
+ fd_state = FLP_MON;
+ }
+ if(fd_state == FLP_MON)
+ fddone(sc);
+ else fd_xfer(sc);
+}
+
+/*
+ * Determine status of last command. Should only be called through
+ * 'fdcint()'.
+ * Returns:
+ * X_ERROR : Error on command; might succeed next time.
+ * X_FAIL : Error on command; will never succeed.
+ * X_AGAIN : Part of a command succeeded, call 'fd_xfer()' to complete.
+ * X_OK : Command succeeded and is complete.
+ *
+ * This function only affects sc->curtrk.
+ */
+static int
+fd_xfer_ok(sc)
+register struct fd_softc *sc;
+{
+ register int status;
+
+ switch(fd_cmd) {
+ case IRUPT:
+ /*
+ * Timeout. Force a recalibrate before we try again.
+ */
+ fd_error = "Timeout";
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ case F_READ:
+ /*
+ * Test for DMA error
+ */
+ status = dmastat(FDC_CS | SCREG, 0);
+ if(!(status & DMAOK)) {
+ fd_error = "Dma error";
+ return(X_ERROR);
+ }
+ /*
+ * Get controller status and check for errors.
+ */
+ status = dmardat(FDC_CS, FDC_DELAY);
+ if(status & (RNF | CRCERR | LD_T00)) {
+ fd_error = "Read error";
+ if(status & RNF)
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ }
+ break;
+ case F_WRITE:
+ /*
+ * Get controller status and check for errors.
+ */
+ status = dmardat(WRBIT | FDC_CS, FDC_DELAY);
+ if(status & WRI_PRO) {
+ fd_error = "Write protected";
+ return(X_FAIL);
+ }
+ if(status & (RNF | CRCERR | LD_T00)) {
+ fd_error = "Write error";
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ }
+ break;
+ case SEEK:
+ status = dmardat(FDC_CS, FDC_DELAY);
+ if(status & (RNF | CRCERR)) {
+ fd_error = "Seek error";
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ }
+ return(X_AGAIN);
+ case RESTORE:
+ /*
+ * Determine if the recalibration succeeded.
+ */
+ status = dmardat(FDC_CS, FDC_DELAY);
+ if(status & RNF) {
+ fd_error = "Recalibrate error";
+ /* reset controller */
+ dmawdat(FDC_CS, IRUPT, FDC_DELAY);
+ sc->curtrk = INV_TRK;
+ return(X_ERROR);
+ }
+ sc->curtrk = 0;
+ return(X_AGAIN);
+ default:
+ fd_error = "Driver error: fd_xfer_ok : Unknown state";
+ return(X_FAIL);
+ }
+ return(X_OK);
+}
+
+/*
+ * All timeouts will call this function.
+ */
+static void
+fdmotoroff(sc)
+struct fd_softc *sc;
+{
+ int sps, wrbit;
+
+ /*
+ * Get at harware interrupt level
+ */
+ sps = splbio();
+
+#if FLP_DEBUG
+ printf("fdmotoroff, state = 0x%x\n", fd_state);
+#endif
+
+ switch(fd_state) {
+ case FLP_XFER :
+ /*
+ * Timeout during a transfer; cancel transaction
+ * set command to 'IRUPT'.
+ * A drive-interrupt is simulated to trigger the state
+ * machine.
+ */
+ /*
+ * Cancel current transaction
+ */
+ wrbit = (fd_cmd == F_WRITE) ? WRBIT : 0;
+ fd_cmd = IRUPT;
+ dmawdat(FDC_CS, wrbit|IRUPT, FDC_DELAY);
+
+ /*
+ * Simulate floppy interrupt.
+ */
+ fdcint(sc);
+ return;
+ case FLP_MON :
+ /*
+ * Turn motor off.
+ */
+ if(selected) {
+ SOUND->sd_selr = YM_IOA;
+ SOUND->sd_wdat = SOUND->sd_rdat | 0x07;
+ motoron = selected = 0;
+ }
+ fd_state = FLP_IDLE;
+ break;
+ }
+ splx(sps);
+}
+
+/*
+ * min byte count to whats left of the track in question
+ */
+static int
+fdminphys(bp)
+struct buf *bp;
+{
+ struct fd_softc *sc;
+ int sec, toff, tsz;
+
+ if((sc = getsoftc(fdcd, DISKUNIT(bp->b_dev))) == NULL)
+ return(ENXIO);
+
+ sec = bp->b_blkno % (sc->nsectors * sc->nheads);
+ toff = sec * SECTOR_SIZE;
+ tsz = sc->nsectors * sc->nheads * SECTOR_SIZE;
+
+#ifdef FLP_DEBUG
+ printf("fdminphys: before %d", bp->b_bcount);
+#endif
+
+ bp->b_bcount = min(bp->b_bcount, tsz - toff);
+
+#ifdef FLP_DEBUG
+ printf(" after %d\n", bp->b_bcount);
+#endif
+
+ return(bp->b_bcount);
+}
+
+/*
+ * Used to find out wich drives are actually connected. We do this by issueing
+ * is 'RESTORE' command and check if the 'track-0' bit is set. This also works
+ * if the drive is present but no floppy is inserted.
+ */
+static void
+fdtestdrv(fdsoftc)
+struct fd_softc *fdsoftc;
+{
+ int i, status;
+
+ /*
+ * Select the right unit and head.
+ */
+ i = fdsoftc->unit ? PA_FLOP1 : PA_FLOP0;
+ if(i != selected) {
+ selected = i;
+ SOUND->sd_selr = YM_IOA;
+ SOUND->sd_wdat = (SOUND->sd_rdat & 0xF8) | (i ^ 0x07);
+ }
+
+ dmawdat(FDC_CS, RESTORE|VBIT|HBIT, FDC_DELAY);
+
+ /*
+ * Wait for about 2 seconds.
+ */
+ delay(2000000);
+
+ status = dmardat(FDC_CS, FDC_DELAY);
+ if(status & (RNF|BUSY))
+ dmawdat(FDC_CS, IRUPT, FDC_DELAY); /* reset controller */
+
+ if(!(status & LD_T00))
+ fdsoftc->flags |= FLPF_NOTRESP;
+}
+
+/*
+ * Build disk label. For now we only create a label from what we know
+ * from 'sc'.
+ */
+static int
+fdgetdisklabel(sc, dev)
+struct fd_softc *sc;
+dev_t dev;
+{
+ struct disklabel *lp, *dlp;
+ int part;
+
+ /*
+ * If we already got one, get out.
+ */
+ if(sc->flags & FLPF_HAVELAB)
+ return(0);
+
+#ifdef FLP_DEBUG
+ printf("fdgetdisklabel()\n");
+#endif
+
+ part = DISKPART(dev);
+ lp = &sc->dkdev.dk_label;
+ bzero(lp, sizeof(struct disklabel));
+
+ lp->d_secsize = SECTOR_SIZE;
+ lp->d_ntracks = sc->nheads;
+ lp->d_nsectors = sc->nsectors;
+ lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
+ lp->d_ncylinders = sc->nblocks / lp->d_secpercyl;
+ lp->d_secperunit = sc->nblocks;
+
+ lp->d_type = DTYPE_FLOPPY;
+ lp->d_rpm = 300; /* good guess I suppose. */
+ lp->d_interleave = 1; /* FIXME: is this OK? */
+ lp->d_bbsize = 0;
+ lp->d_sbsize = 0;
+ lp->d_npartitions = part + 1;
+ lp->d_trkseek = STEP_DELAY;
+ lp->d_magic = DISKMAGIC;
+ lp->d_magic2 = DISKMAGIC;
+ lp->d_checksum = dkcksum(lp);
+ lp->d_partitions[part].p_size = lp->d_secperunit;
+ lp->d_partitions[part].p_fstype = FS_UNUSED;
+ lp->d_partitions[part].p_fsize = 1024;
+ lp->d_partitions[part].p_frag = 8;
+ sc->flags |= FLPF_HAVELAB;
+
+ return(0);
+}
diff --git a/sys/arch/atari/dev/fdreg.h b/sys/arch/atari/dev/fdreg.h
new file mode 100644
index 00000000000..656c8fbc1cc
--- /dev/null
+++ b/sys/arch/atari/dev/fdreg.h
@@ -0,0 +1,93 @@
+/* $NetBSD: fdreg.h,v 1.1.1.1 1995/03/26 07:12:15 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _FDREG_H
+#define _FDREG_H
+/*
+ * Atari TT hardware:
+ * Western Digital 1772 Floppy Disk Controller.
+ */
+
+/*
+ * Accessing the FDC registers is indirect through ST-specific
+ * DMA circuitry. See also dma.h.
+ */
+#define FDC_CS (FDC ) /* command/status */
+#define FDC_TR (FDC| A0) /* track register */
+#define FDC_SR (FDC|A1 ) /* sector register */
+#define FDC_DR (FDC|A1|A0) /* data register */
+
+/*
+ * commands (relevant bits/fields indicated)
+ */
+#define RESTORE 0x00 /* ( HVRR) seek to track 0 */
+#define SEEK 0x10 /* ( HVRR) seek to track */
+#define STEP 0x20 /* (UHVRR) step in same direction */
+#define STEPI 0x40 /* (UHVRR) step in */
+#define STEPO 0x60 /* (UHVRR) step out */
+#define F_READ 0x80 /* (MHE00) read sector */
+#define F_WRITE 0xA0 /* (MHEPA) write sector */
+#define READID 0xC0 /* ( HE00) read sector ID */
+#define READTR 0xE0 /* ( HE00) read track */
+#define WRITETR 0xF0 /* ( HEP0) write track */
+#define IRUPT 0xD0 /* ( IIII) force interrupt */
+
+/*
+ * other bits/fields in command register
+ */
+#define RATE6 0x00 /* not 2, but 6 msec steprate */
+#define RATE12 0x01 /* not 3, but 12 msec steprate */
+#define RATE2 0x02 /* not 5, but 2 msec steprate */
+#define RATE3 0x03 /* not 6, but 3 msec steprate */
+#define VBIT 0x04 /* verify sector ID */
+#define HBIT 0x08 /* suppress motor on sequence */
+#define UBIT 0x10 /* update track register */
+#define EBIT 0x04 /* wait 30 msec to settle */
+#define MBIT 0x10 /* multi-sector */
+#define PBIT 0x02 /* write precompensate */
+#define A0BIT 0x01 /* suppress (?) data address mark */
+#define IINDEX 0x04 /* interrupt on each index pulse */
+#define IFORCE 0x08 /* force interrupt */
+
+/*
+ * status register
+ */
+#define BUSY 0x01 /* set if command under execution */
+#define DRQ 0x02 /* Data Register status (pin c1) */
+#define LD_T00 0x04 /* lost data; track 00 */
+#define CRCERR 0x08 /* CRC error */
+#define RNF 0x10 /* Record Not Found */
+#define RT_SU 0x20 /* Record Type; Spin Up completed */
+#define WRI_PRO 0x40 /* Write Protected */
+#define MOTORON 0x80 /* Motor On */
+
+#endif /* _FDREG_H */
diff --git a/sys/arch/atari/dev/font.h b/sys/arch/atari/dev/font.h
new file mode 100644
index 00000000000..c96b55a429e
--- /dev/null
+++ b/sys/arch/atari/dev/font.h
@@ -0,0 +1,48 @@
+/* $NetBSD: font.h,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _FONT_H
+#define _FONT_H
+/*
+ * What we like to know about fonts...
+ */
+typedef struct {
+ short boldsmear;
+ unsigned char width;
+ unsigned char height;
+ unsigned char baseline;
+ unsigned char font_lo;
+ unsigned char font_hi;
+ unsigned char *font_p;
+} font_info;
+
+#endif /* _FONT_H */
diff --git a/sys/arch/atari/dev/font_8x16.c b/sys/arch/atari/dev/font_8x16.c
new file mode 100644
index 00000000000..d6e6ba87f2f
--- /dev/null
+++ b/sys/arch/atari/dev/font_8x16.c
@@ -0,0 +1,562 @@
+/* $NetBSD: font_8x16.c,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993, 1994 Hellmuth Michaelis and Joerg Wunsch
+ *
+ * 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
+ * Hellmuth Michaelis and Joerg Wunsch
+ * 4. The name authors 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.
+ */
+
+/*
+ * Translated into compiler and human readable for for the Atari-TT port of
+ * NetBSD by Leo Weppelman.
+ */
+#include <atari/dev/font.h>
+
+char fontname_8x16[64] = "vt220l.816";
+
+extern unsigned char fontdata_8x16[];
+font_info font_info_8x16 = { 1, 8, 16, 14, 0, 255, &fontdata_8x16[0] };
+
+int fontheight_8x16 = 16;
+int fontwidth_8x16 = 8;
+
+unsigned char fontdata_8x16[] = {
+/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x01 */ 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
+ 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
+/* 0x02 */ 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3,
+ 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
+/* 0x03 */ 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe,
+ 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+/* 0x04 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
+ 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x05 */ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7,
+ 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0x06 */ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff,
+ 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0x07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+ 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x08 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3,
+ 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+/* 0x09 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42,
+ 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x0a */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
+ 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
+/* 0x0b */ 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+/* 0x0c */ 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c,
+ 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0x0d */ 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
+ 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00,
+/* 0x0e */ 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63,
+ 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
+/* 0x0f */ 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7,
+ 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0x10 */ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
+ 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+/* 0x11 */ 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e,
+ 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+/* 0x12 */ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18,
+ 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x13 */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+/* 0x14 */ 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b,
+ 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+/* 0x15 */ 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6,
+ 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
+/* 0x16 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 0x17 */ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18,
+ 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+/* 0x18 */ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0x19 */ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0x1a */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe,
+ 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x1b */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe,
+ 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x1c */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+ 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x1d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe,
+ 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x1e */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c,
+ 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x1f */ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
+ 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '!' */ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18,
+ 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* '"' */ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '#' */ 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c,
+ 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+/* '$' */ 0x00, 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c,
+ 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
+/* '%' */ 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
+ 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
+/* '&' */ 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* ''' */ 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '(' */ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
+/* ')' */ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+/* '*' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff,
+ 0x3c, 0x66, 0x00, 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, 0x18, 0x18, 0x18, 0x30, 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, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* '/' */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18,
+ 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+/* '0' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6,
+ 0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '1' */ 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+/* '2' */ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30,
+ 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* '3' */ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06,
+ 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '4' */ 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
+ 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
+/* '5' */ 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06,
+ 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '6' */ 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '7' */ 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
+ 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+/* '8' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* '9' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06,
+ 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
+/* ':' */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* ';' */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+/* '<' */ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60,
+ 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
+/* '=' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '>' */ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06,
+ 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+/* '?' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18,
+ 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* '@' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
+ 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'A' */ 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'B' */ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66,
+ 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+/* 'C' */ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
+ 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'D' */ 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+/* 'E' */ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
+ 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 'F' */ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 'G' */ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde,
+ 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+/* 'H' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'I' */ 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'J' */ 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+/* 'K' */ 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78,
+ 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+/* 'L' */ 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
+ 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 'M' */ 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'N' */ 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'O' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'P' */ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 'Q' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
+/* 'R' */ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
+ 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+/* 'S' */ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c,
+ 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'T' */ 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'U' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'V' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+/* 'W' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6,
+ 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00,
+/* 'X' */ 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38,
+ 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'Y' */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'Z' */ 0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30,
+ 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* '[' */ 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* '\' */ 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38,
+ 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+/* ']' */ 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+ 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* '^' */ 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '_' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+/* '`' */ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 'a' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 'b' */ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66,
+ 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'c' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'd' */ 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 'e' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'f' */ 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 'g' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
+/* 'h' */ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66,
+ 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+/* 'i' */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'j' */ 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
+/* 'k' */ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78,
+ 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+/* 'l' */ 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 'm' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6,
+ 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'n' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+/* 'o' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 'p' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+/* 'q' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+/* 'r' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66,
+ 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+/* 's' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
+ 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 't' */ 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30,
+ 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+/* 'u' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 'v' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+/* 'w' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6,
+ 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
+/* 'x' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38,
+ 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 'y' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
+/* 'z' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18,
+ 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* '{' */ 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18,
+ 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
+/* '|' */ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* '}' */ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18,
+ 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+/* '~' */ 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x7f */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
+ 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x80 */ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
+ 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
+/* 0x81 */ 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0x82 */ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x83 */ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0x84 */ 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0x85 */ 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0x86 */ 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0x87 */ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60,
+ 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00,
+/* 0x88 */ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x89 */ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x8a */ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe,
+ 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x8b */ 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0x8c */ 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0x8d */ 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0x8e */ 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0x8f */ 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6,
+ 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0x90 */ 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c,
+ 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 0x91 */ 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xb2, 0x32,
+ 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00,
+/* 0x92 */ 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+/* 0x93 */ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x94 */ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x95 */ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x96 */ 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0x97 */ 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0x98 */ 0x00, 0xc6, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+/* 0x99 */ 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x9a */ 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0x9b */ 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60,
+ 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0x9c */ 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60,
+ 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
+/* 0x9d */ 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
+ 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0x9e */ 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde,
+ 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0x9f */ 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00,
+/* 0xa0 */ 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xa1 */ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xa2 */ 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xa3 */ 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
+ 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xa4 */ 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+/* 0xa5 */ 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde,
+ 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xa6 */ 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa7 */ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xa8 */ 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60,
+ 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+/* 0xa9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+ 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xaa */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06,
+ 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xab */ 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
+ 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00,
+/* 0xac */ 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
+ 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00,
+/* 0xad */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18,
+ 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0xae */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8,
+ 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xaf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
+ 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xb0 */ 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+ 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+/* 0xb1 */ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+/* 0xb2 */ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+/* 0xb3 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xb4 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xb5 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xb6 */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xb7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xb8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xb9 */ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xba */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xbb */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xbc */ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xbd */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xbe */ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xbf */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xc0 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xc1 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xc2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xc3 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xc4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xc5 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xc6 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xc7 */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xc8 */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xc9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xca */ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xcb */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xcc */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xcd */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xce */ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xcf */ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xd0 */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xd1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xd2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xd3 */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xd4 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xd5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xd6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xd7 */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xd8 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xd9 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xda */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xdb */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+/* 0xdc */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+/* 0xdd */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+/* 0xde */ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+/* 0xdf */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xe0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8,
+ 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
+/* 0xe1 */ 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc,
+ 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
+/* 0xe2 */ 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
+ 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
+/* 0xe3 */ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c,
+ 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+/* 0xe4 */ 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18,
+ 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+/* 0xe5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
+ 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+/* 0xe6 */ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
+/* 0xe7 */ 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+/* 0xe8 */ 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
+ 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+/* 0xe9 */ 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe,
+ 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+/* 0xea */ 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c,
+ 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00,
+/* 0xeb */ 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
+ 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+/* 0xec */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb,
+ 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xed */ 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb,
+ 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
+/* 0xee */ 0x00, 0x00, 0x1e, 0x30, 0x60, 0x60, 0x7e, 0x60,
+ 0x60, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00,
+/* 0xef */ 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6,
+ 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* 0xf0 */ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe,
+ 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xf1 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
+ 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+/* 0xf2 */ 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c,
+ 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+/* 0xf3 */ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30,
+ 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+/* 0xf4 */ 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xf5 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+/* 0xf6 */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xf7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
+ 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xf8 */ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xf9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xfa */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xfb */ 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec,
+ 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+/* 0xfc */ 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xfd */ 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xfe */ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c,
+ 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0xff */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
diff --git a/sys/arch/atari/dev/font_8x8.c b/sys/arch/atari/dev/font_8x8.c
new file mode 100644
index 00000000000..d5776bf6fff
--- /dev/null
+++ b/sys/arch/atari/dev/font_8x8.c
@@ -0,0 +1,304 @@
+/* $NetBSD: font_8x8.c,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993, 1994 Hellmuth Michaelis and Joerg Wunsch
+ *
+ * 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
+ * Hellmuth Michaelis and Joerg Wunsch
+ * 4. The name authors 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.
+ */
+
+/*
+ * Translated into compiler and human readable for for the Atari-TT port of
+ * NetBSD by Leo Weppelman.
+ */
+#include <atari/dev/font.h>
+
+char fontname_8x8[64] = "vt220l.808";
+
+extern unsigned char fontdata_8x8[];
+
+font_info font_info_8x8 = { 1, 8, 8, 6, 0, 255, &fontdata_8x8[0] };
+
+unsigned char fontdata_8x8[] = {
+/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
+/* 0x02 */ 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
+/* 0x03 */ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
+/* 0x04 */ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
+/* 0x05 */ 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0xd6, 0x10, 0x38,
+/* 0x06 */ 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x7c, 0x10, 0x38,
+/* 0x07 */ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
+/* 0x08 */ 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
+/* 0x09 */ 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c,
+/* 0x0a */ 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
+/* 0x0b */ 0x1f, 0x07, 0x0d, 0x79, 0xcd, 0xcc, 0xcc, 0x78,
+/* 0x0c */ 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
+/* 0x0d */ 0x38, 0x3c, 0x36, 0x32, 0x34, 0x70, 0xf0, 0xe0,
+/* 0x0e */ 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
+/* 0x0f */ 0x18, 0xdb, 0x3c, 0xe7, 0xe7, 0x3c, 0xdb, 0x18,
+/* 0x10 */ 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
+/* 0x11 */ 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
+/* 0x12 */ 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
+/* 0x13 */ 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
+/* 0x14 */ 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
+/* 0x15 */ 0x7e, 0xc3, 0xfc, 0x66, 0x66, 0x3f, 0xc3, 0x7e,
+/* 0x16 */ 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00,
+/* 0x17 */ 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
+/* 0x18 */ 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
+/* 0x19 */ 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
+/* 0x1a */ 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
+/* 0x1b */ 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
+/* 0x1c */ 0x00, 0x00, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x00,
+/* 0x1d */ 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
+/* 0x1e */ 0x00, 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x00, 0x00,
+/* 0x1f */ 0x00, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00,
+/* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '!' */ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00,
+/* '"' */ 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '#' */ 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
+/* '$' */ 0x30, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x30, 0x00,
+/* '%' */ 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
+/* '&' */ 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xce, 0x7b, 0x00,
+/* ''' */ 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* '(' */ 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
+/* ')' */ 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00,
+/* '*' */ 0x00, 0x6c, 0x38, 0xfe, 0x38, 0x6c, 0x00, 0x00,
+/* '+' */ 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
+/* ',' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
+/* '-' */ 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
+/* '.' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
+/* '/' */ 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
+/* '0' */ 0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0x7c, 0x00,
+/* '1' */ 0x30, 0x70, 0xb0, 0x30, 0x30, 0x30, 0xfc, 0x00,
+/* '2' */ 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xc0, 0xfc, 0x00,
+/* '3' */ 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
+/* '4' */ 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
+/* '5' */ 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
+/* '6' */ 0x78, 0xcc, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
+/* '7' */ 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
+/* '8' */ 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* '9' */ 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
+/* ':' */ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
+/* ';' */ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
+/* '<' */ 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
+/* '=' */ 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00,
+/* '>' */ 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00,
+/* '?' */ 0x3c, 0x66, 0x06, 0x0c, 0x18, 0x00, 0x18, 0x00,
+/* '@' */ 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x7e, 0x00,
+/* 'A' */ 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00,
+/* 'B' */ 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00,
+/* 'C' */ 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00,
+/* 'D' */ 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00,
+/* 'E' */ 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
+/* 'F' */ 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
+/* 'G' */ 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
+/* 'H' */ 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
+/* 'I' */ 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 'J' */ 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
+/* 'K' */ 0xe6, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0xe6, 0x00,
+/* 'L' */ 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
+/* 'M' */ 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00,
+/* 'N' */ 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
+/* 'O' */ 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
+/* 'P' */ 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+/* 'Q' */ 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
+/* 'R' */ 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
+/* 'S' */ 0x78, 0xcc, 0xc0, 0x78, 0x0c, 0xcc, 0x78, 0x00,
+/* 'T' */ 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 'U' */ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 'V' */ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
+/* 'W' */ 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xfe, 0xc6, 0x00,
+/* 'X' */ 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
+/* 'Y' */ 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
+/* 'Z' */ 0xfc, 0xcc, 0x98, 0x30, 0x64, 0xcc, 0xfc, 0x00,
+/* '[' */ 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
+/* '\' */ 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
+/* ']' */ 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+/* '^' */ 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+/* '_' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+/* '`' */ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 'a' */ 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
+/* 'b' */ 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xfc, 0x00,
+/* 'c' */ 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
+/* 'd' */ 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x7e, 0x00,
+/* 'e' */ 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+/* 'f' */ 0x38, 0x6c, 0x60, 0xf8, 0x60, 0x60, 0xf0, 0x00,
+/* 'g' */ 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+/* 'h' */ 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
+/* 'i' */ 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 'j' */ 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
+/* 'k' */ 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
+/* 'l' */ 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 'm' */ 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
+/* 'n' */ 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+/* 'o' */ 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 'p' */ 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
+/* 'q' */ 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
+/* 'r' */ 0x00, 0x00, 0xdc, 0x76, 0x60, 0x60, 0xf0, 0x00,
+/* 's' */ 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x00,
+/* 't' */ 0x10, 0x30, 0x7c, 0x30, 0x30, 0x36, 0x1c, 0x00,
+/* 'u' */ 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
+/* 'v' */ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7c, 0x38, 0x00,
+/* 'w' */ 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
+/* 'x' */ 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
+/* 'y' */ 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+/* 'z' */ 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
+/* '{' */ 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
+/* '|' */ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
+/* '}' */ 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
+/* '~' */ 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 0x7f */ 0x10, 0x38, 0x6c, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
+/* 0x80 */ 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78,
+/* 0x81 */ 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+/* 0x82 */ 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+/* 0x83 */ 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00,
+/* 0x84 */ 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0x85 */ 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0x86 */ 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0x87 */ 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38,
+/* 0x88 */ 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
+/* 0x89 */ 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+/* 0x8a */ 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+/* 0x8b */ 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 0x8c */ 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
+/* 0x8d */ 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 0x8e */ 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
+/* 0x8f */ 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00,
+/* 0x90 */ 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00,
+/* 0x91 */ 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00,
+/* 0x92 */ 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00,
+/* 0x93 */ 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0x94 */ 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0x95 */ 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0x96 */ 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+/* 0x97 */ 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+/* 0x98 */ 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+/* 0x99 */ 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00,
+/* 0x9a */ 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+/* 0x9b */ 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18,
+/* 0x9c */ 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00,
+/* 0x9d */ 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30,
+/* 0x9e */ 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7,
+/* 0x9f */ 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70,
+/* 0xa0 */ 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+/* 0xa1 */ 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+/* 0xa2 */ 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xa3 */ 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+/* 0xa4 */ 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00,
+/* 0xa5 */ 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00,
+/* 0xa6 */ 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00,
+/* 0xa7 */ 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
+/* 0xa8 */ 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00,
+/* 0xa9 */ 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00,
+/* 0xaa */ 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
+/* 0xab */ 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f,
+/* 0xac */ 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03,
+/* 0xad */ 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
+/* 0xae */ 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00,
+/* 0xaf */ 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00,
+/* 0xb0 */ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
+/* 0xb1 */ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+/* 0xb2 */ 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee,
+/* 0xb3 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xb4 */ 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18,
+/* 0xb5 */ 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
+/* 0xb6 */ 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
+/* 0xb7 */ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
+/* 0xb8 */ 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
+/* 0xb9 */ 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
+/* 0xba */ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+/* 0xbb */ 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
+/* 0xbc */ 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
+/* 0xbd */ 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
+/* 0xbe */ 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00,
+/* 0xbf */ 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
+/* 0xc0 */ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00,
+/* 0xc1 */ 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
+/* 0xc2 */ 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
+/* 0xc3 */ 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
+/* 0xc4 */ 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+/* 0xc5 */ 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
+/* 0xc6 */ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
+/* 0xc7 */ 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
+/* 0xc8 */ 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
+/* 0xc9 */ 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
+/* 0xca */ 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00,
+/* 0xcb */ 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
+/* 0xcc */ 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
+/* 0xcd */ 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+/* 0xce */ 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
+/* 0xcf */ 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+/* 0xd0 */ 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00,
+/* 0xd1 */ 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
+/* 0xd2 */ 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36,
+/* 0xd3 */ 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
+/* 0xd4 */ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
+/* 0xd5 */ 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
+/* 0xd6 */ 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36,
+/* 0xd7 */ 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
+/* 0xd8 */ 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18,
+/* 0xd9 */ 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
+/* 0xda */ 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
+/* 0xdb */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+/* 0xdc */ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+/* 0xdd */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+/* 0xde */ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+/* 0xdf */ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+/* 0xe0 */ 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00,
+/* 0xe1 */ 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
+/* 0xe2 */ 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
+/* 0xe3 */ 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
+/* 0xe4 */ 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00,
+/* 0xe5 */ 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00,
+/* 0xe6 */ 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0,
+/* 0xe7 */ 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00,
+/* 0xe8 */ 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
+/* 0xe9 */ 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00,
+/* 0xea */ 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00,
+/* 0xeb */ 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
+/* 0xec */ 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00,
+/* 0xed */ 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0,
+/* 0xee */ 0x3c, 0x60, 0xc0, 0xfc, 0xc0, 0x60, 0x3c, 0x00,
+/* 0xef */ 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+/* 0xf0 */ 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00,
+/* 0xf1 */ 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
+/* 0xf2 */ 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00,
+/* 0xf3 */ 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00,
+/* 0xf4 */ 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18,
+/* 0xf5 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
+/* 0xf6 */ 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
+/* 0xf7 */ 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
+/* 0xf8 */ 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+/* 0xf9 */ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+/* 0xfa */ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+/* 0xfb */ 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c,
+/* 0xfc */ 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
+/* 0xfd */ 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
+/* 0xfe */ 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
+/* 0xff */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
diff --git a/sys/arch/atari/dev/grf.c b/sys/arch/atari/dev/grf.c
new file mode 100644
index 00000000000..0feec1999da
--- /dev/null
+++ b/sys/arch/atari/dev/grf.c
@@ -0,0 +1,559 @@
+/* $NetBSD: grf.c,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * from: Utah $Hdr: grf.c 1.31 91/01/21$
+ *
+ * @(#)grf.c 7.8 (Berkeley) 5/7/91
+ */
+
+/*
+ * Graphics display driver for the Atari
+ * This is the hardware-independent portion of the driver.
+ * Hardware access is through the grf_softc->g_mode routine.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/file.h>
+#include <sys/malloc.h>
+#include <sys/conf.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+#include <sys/mman.h>
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
+#include <machine/cpu.h>
+#include <atari/atari/device.h>
+#include <atari/dev/grfioctl.h>
+#include <atari/dev/grfabs_reg.h>
+#include <atari/dev/grfvar.h>
+#include <atari/dev/itevar.h>
+#include <atari/dev/viewioctl.h>
+#include <atari/dev/viewvar.h>
+
+#include "grf.h"
+#if NGRF > 0
+
+#include "ite.h"
+#if NITE == 0
+#define ite_on(u,f)
+#define ite_off(u,f)
+#define ite_reinit(d)
+#endif
+
+int grfopen __P((dev_t, int, int, struct proc *));
+int grfclose __P((dev_t, int));
+int grfioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+int grfselect __P((dev_t, int));
+int grfmap __P((dev_t, int, int));
+
+int grfon __P((dev_t));
+int grfoff __P((dev_t));
+int grfsinfo __P((dev_t, struct grfdyninfo *));
+#ifdef BANKEDDEVPAGER
+int grfbanked_get __P((dev_t, off_t, int));
+int grfbanked_cur __P((dev_t));
+int grfbanked_set __P((dev_t, int));
+#endif
+static void grf_viewsync __P((struct grf_softc *));
+static int grf_mode __P((struct grf_softc *, int, void *, int, int));
+
+int grfbusprint __P((void *auxp, char *));
+int grfbusmatch __P((struct device *, struct cfdata *, void *));
+void grfbusattach __P((struct device *, struct device *, void *));
+
+void grfattach __P((struct device *, struct device *, void *));
+int grfmatch __P((struct device *, struct cfdata *, void *));
+int grfprint __P((void *, char *));
+/*
+ * pointers to grf drivers device structs
+ */
+struct grf_softc *grfsp[NGRF];
+
+
+struct cfdriver grfbuscd = {
+ NULL, "grfbus", (cfmatch_t)grfbusmatch, grfbusattach, DV_DULL,
+ sizeof(struct device)
+};
+
+struct cfdriver grfcd = {
+ NULL, "grf", (cfmatch_t)grfmatch, grfattach, DV_DULL,
+ sizeof(struct grf_softc), NULL, 0
+};
+
+/*
+ * only used in console init.
+ */
+static struct cfdata *cfdata_gbus = NULL;
+static struct cfdata *cfdata_grf = NULL;
+
+int
+grfbusmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp(auxp, grfbuscd.cd_name))
+ return(0);
+
+ if((atari_realconfig == 0) || (cfdata_gbus == NULL)) {
+ /*
+ * Probe layers we depend on
+ */
+ if(grfabs_probe() == 0)
+ return(0);
+ viewprobe();
+
+ if(atari_realconfig == 0) {
+ /*
+ * XXX: console init opens view 0
+ */
+ if(viewopen(0, 0))
+ return(0);
+ cfdata_gbus = cfp;
+ }
+ }
+ return(1); /* Always there */
+}
+
+void
+grfbusattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ static int did_cons = 0;
+ int i;
+
+ if(dp == NULL) { /* Console init */
+ did_cons = 1;
+ i = 0;
+ atari_config_found(cfdata_gbus, NULL, (void*)&i, grfbusprint);
+ }
+ else {
+ printf("\n");
+ for(i = 0; i < NGRF; i++) {
+ /*
+ * Skip opening view[0] when we this is the console.
+ */
+ if(!did_cons || (i > 0))
+ if(viewopen(i, 0))
+ break;
+ config_found(dp, (void*)&i, grfbusprint);
+ }
+ }
+}
+
+int
+grfbusprint(auxp, name)
+void *auxp;
+char *name;
+{
+ if(name == NULL)
+ return(UNCONF);
+ return(QUIET);
+}
+
+
+int
+grfmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ int unit = *(int*)auxp;
+
+ /*
+ * Match only on unit indicated by grfbus attach.
+ */
+ if(cfp->cf_unit != unit)
+ return(0);
+
+ cfdata_grf = cfp;
+ return(1);
+}
+
+/*
+ * attach: initialize the grf-structure and try to attach an ite to us.
+ * note : dp is NULL during early console init.
+ */
+void
+grfattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ extern struct view_softc views[];
+ static struct grf_softc congrf;
+ struct grf_softc *gp;
+ int maj;
+
+ /*
+ * find our major device number
+ */
+ for(maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == grfopen)
+ break;
+
+ /*
+ * Handle exeption case: early console init
+ */
+ if(dp == NULL) {
+ congrf.g_unit = 0;
+ congrf.g_grfdev = makedev(maj, 0);
+ congrf.g_flags = GF_ALIVE;
+ congrf.g_mode = grf_mode;
+ congrf.g_conpri = grfcc_cnprobe();
+ congrf.g_view = views[0].view; /* XXX */
+ congrf.g_viewdev = congrf.g_unit;
+ grfcc_iteinit(&congrf);
+ grf_viewsync(&congrf);
+
+ /* Attach console ite */
+ atari_config_found(cfdata_grf, NULL, &congrf, grfprint);
+ return;
+ }
+
+ gp = (struct grf_softc *)dp;
+ gp->g_unit = gp->g_device.dv_unit;
+ grfsp[gp->g_unit] = gp;
+
+ if((cfdata_grf != NULL) && (gp->g_unit == 0)) {
+ /*
+ * We inited earlier just copy the info, take care
+ * not to copy the device struct though.
+ */
+ bcopy(&congrf.g_display, &gp->g_display,
+ (char *)&gp[1] - (char *)&gp->g_display);
+ }
+ else {
+ gp->g_grfdev = makedev(maj, gp->g_unit);
+ gp->g_flags = GF_ALIVE;
+ gp->g_mode = grf_mode;
+ gp->g_conpri = 0;
+ gp->g_view = views[gp->g_unit].view; /* XXX */
+ gp->g_viewdev = gp->g_unit;
+ grfcc_iteinit(gp);
+ grf_viewsync(gp);
+ }
+
+ printf(": width %d height %d", gp->g_display.gd_dwidth,
+ gp->g_display.gd_dheight);
+ if(gp->g_display.gd_colors == 2)
+ printf(" monochrome\n");
+ else printf(" colors %d\n", gp->g_display.gd_colors);
+
+ /*
+ * try and attach an ite
+ */
+ config_found(dp, gp, grfprint);
+}
+
+int
+grfprint(auxp, pnp)
+void *auxp;
+char *pnp;
+{
+ if(pnp)
+ printf("ite at %s", pnp);
+ return(UNCONF);
+}
+
+/*ARGSUSED*/
+int
+grfopen(dev, flags, devtype, p)
+ dev_t dev;
+ int flags, devtype;
+ struct proc *p;
+{
+ struct grf_softc *gp;
+
+ if (GRFUNIT(dev) >= NGRF)
+ return(ENXIO);
+
+ gp = grfsp[GRFUNIT(dev)];
+
+ if ((gp->g_flags & GF_ALIVE) == 0)
+ return(ENXIO);
+
+ if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
+ return(EBUSY);
+
+ return(0);
+}
+
+/*ARGSUSED*/
+int
+grfclose(dev, flags)
+ dev_t dev;
+ int flags;
+{
+ struct grf_softc *gp;
+
+ gp = grfsp[GRFUNIT(dev)];
+ (void)grfoff(dev);
+ gp->g_flags &= GF_ALIVE;
+ return(0);
+}
+
+/*ARGSUSED*/
+int
+grfioctl(dev, cmd, data, flag, p)
+dev_t dev;
+u_long cmd;
+int flag;
+caddr_t data;
+struct proc *p;
+{
+ struct grf_softc *gp;
+ int error;
+
+ gp = grfsp[GRFUNIT(dev)];
+ error = 0;
+
+ switch (cmd) {
+ case OGRFIOCGINFO:
+ /* argl.. no bank-member.. */
+ bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)-4);
+ break;
+ case GRFIOCGINFO:
+ bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
+ break;
+ case GRFIOCON:
+ error = grfon(dev);
+ break;
+ case GRFIOCOFF:
+ error = grfoff(dev);
+ break;
+ case GRFIOCSINFO:
+ error = grfsinfo(dev, (struct grfdyninfo *) data);
+ break;
+ case GRFGETVMODE:
+ return(gp->g_mode(gp, GM_GRFGETVMODE, data));
+ case GRFSETVMODE:
+ error = gp->g_mode(gp, GM_GRFSETVMODE, data);
+ if (error == 0 && gp->g_itedev)
+ ite_reinit(gp->g_itedev);
+ break;
+ case GRFGETNUMVM:
+ return(gp->g_mode(gp, GM_GRFGETNUMVM, data));
+ /*
+ * these are all hardware dependant, and have to be resolved
+ * in the respective driver.
+ */
+ case GRFIOCPUTCMAP:
+ case GRFIOCGETCMAP:
+ case GRFIOCSSPRITEPOS:
+ case GRFIOCGSPRITEPOS:
+ case GRFIOCSSPRITEINF:
+ case GRFIOCGSPRITEINF:
+ case GRFIOCGSPRITEMAX:
+ default:
+ /*
+ * check to see whether it's a command recognized by the
+ * view code.
+ */
+ if(gp->g_view != NULL)
+ return(viewioctl(gp->g_viewdev, cmd, data, flag, p));
+ error = EINVAL;
+ break;
+
+ }
+ return(error);
+}
+
+/*ARGSUSED*/
+int
+grfselect(dev, rw)
+ dev_t dev;
+ int rw;
+{
+ if (rw == FREAD)
+ return(0);
+ return(1);
+}
+
+/*
+ * map the contents of a graphics display card into process'
+ * memory space.
+ */
+int
+grfmap(dev, off, prot)
+dev_t dev;
+int off, prot;
+{
+panic("No grfmap\n"); /* LWP */
+}
+
+int
+grfon(dev)
+ dev_t dev;
+{
+ struct grf_softc *gp;
+
+ gp = grfsp[GRFUNIT(dev)];
+
+ if (gp->g_flags & GF_GRFON)
+ return(0);
+
+ gp->g_flags |= GF_GRFON;
+ if (gp->g_itedev != NODEV)
+ ite_off(gp->g_itedev, 3);
+
+ return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON));
+}
+
+int
+grfoff(dev)
+ dev_t dev;
+{
+ struct grf_softc *gp;
+ int error;
+
+ gp = grfsp[GRFUNIT(dev)];
+
+ if ((gp->g_flags & GF_GRFON) == 0)
+ return(0);
+
+ gp->g_flags &= ~GF_GRFON;
+ error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF);
+
+ /*
+ * Closely tied together no X's
+ */
+ if (gp->g_itedev != NODEV)
+ ite_on(gp->g_itedev, 2);
+
+ return(error);
+}
+
+int
+grfsinfo(dev, dyninfo)
+ dev_t dev;
+ struct grfdyninfo *dyninfo;
+{
+ struct grf_softc *gp;
+ int error;
+
+ gp = grfsp[GRFUNIT(dev)];
+ error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo);
+
+ /*
+ * Closely tied together no X's
+ */
+ if (gp->g_itedev != NODEV)
+ ite_reinit(gp->g_itedev);
+ return(error);
+}
+
+/*
+ * Get the grf-info in sync with underlying view.
+ */
+static void
+grf_viewsync(gp)
+struct grf_softc *gp;
+{
+ struct view_size vs;
+ bmap_t bm;
+ struct grfinfo *gi;
+
+ gi = &gp->g_display;
+
+ viewioctl(gp->g_viewdev, VIOCGBMAP, &bm, 0, -1);
+
+ gp->g_data = (caddr_t) 0xDeadBeaf; /* not particularly clean.. */
+
+ gi->gd_fbaddr = bm.hw_address;
+ gi->gd_fbsize = bm.depth*bm.bytes_per_row*bm.rows;
+
+ if(viewioctl(gp->g_viewdev, VIOCGSIZE, &vs, 0, -1)) {
+ /*
+ * fill in some default values...
+ * XXX: Should _never_ happen
+ */
+ vs.width = 640;
+ vs.height = 400;
+ vs.depth = 2;
+ }
+ gi->gd_colors = 1 << vs.depth;
+ gi->gd_planes = vs.depth;
+
+ gi->gd_fbwidth = vs.width;
+ gi->gd_fbheight = vs.height;
+ gi->gd_dyn.gdi_fbx = 0;
+ gi->gd_dyn.gdi_fby = 0;
+ gi->gd_dyn.gdi_dwidth = vs.width;
+ gi->gd_dyn.gdi_dheight = vs.height;
+ gi->gd_dyn.gdi_dx = 0;
+ gi->gd_dyn.gdi_dy = 0;
+}
+
+/*
+ * Change the mode of the display.
+ * Right now all we can do is grfon/grfoff.
+ * Return a UNIX error number or 0 for success.
+ */
+/*ARGSUSED*/
+static int
+grf_mode(gp, cmd, arg, a2, a3)
+struct grf_softc *gp;
+int cmd, a2, a3;
+void *arg;
+{
+ switch (cmd) {
+ case GM_GRFON:
+ /*
+ * Get in sync with view, ite might have changed it.
+ */
+ grf_viewsync(gp);
+ viewioctl(gp->g_viewdev, VIOCDISPLAY, NULL, 0, -1);
+ return(0);
+ case GM_GRFOFF:
+ viewioctl(gp->g_viewdev, VIOCREMOVE, NULL, 0, -1);
+ return(0);
+ case GM_GRFCONFIG:
+ default:
+ break;
+ }
+ return(EINVAL);
+}
+#endif /* NGRF > 0 */
diff --git a/sys/arch/atari/dev/grfabs.c b/sys/arch/atari/dev/grfabs.c
new file mode 100644
index 00000000000..df8c34c663a
--- /dev/null
+++ b/sys/arch/atari/dev/grfabs.c
@@ -0,0 +1,449 @@
+/* $NetBSD: grfabs.c,v 1.1.1.1 1995/03/26 07:12:15 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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.
+ */
+
+/*
+ * atari abstract graphics driver.
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+
+#include <machine/iomap.h>
+#include <machine/video.h>
+#include <machine/mfp.h>
+#include <atari/dev/grfabs_reg.h>
+
+/*
+ * Function decls
+ */
+static dmode_t *get_best_display_mode __P((int, int, int));
+static view_t *alloc_view __P((dmode_t *, dimen_t *, u_char));
+static void init_view __P((view_t *, bmap_t *, dmode_t *, box_t *));
+static bmap_t *alloc_bitmap __P((u_long, u_long, u_char, int));
+static void free_bitmap __P((bmap_t *));
+static colormap_t *alloc_colormap __P((dmode_t *));
+
+/*
+ * Ugh.. Stuff needed to allocate console structures before the VM-system
+ * is running. There is no malloc() available at that time.
+ */
+extern int atari_realconfig; /* 0 -> no malloc */
+static view_t con_view;
+static colormap_t con_cmap;
+static u_short con_colors[MAX_CENTRIES];
+
+/*
+ * List of available graphic modes
+ */
+static LIST_HEAD(modelist, display_mode) modes;
+
+static dmode_t vid_modes[] = {
+ { { NULL, NULL }, "stlow", { 320, 200 }, 1, RES_STLOW },
+ { { NULL, NULL }, "stmid", { 640, 200 }, 2, RES_STMID },
+ { { NULL, NULL }, "sthigh", { 640, 400 }, 1, RES_STHIGH },
+ { { NULL, NULL }, "ttlow", { 320, 480 }, 8, RES_TTLOW },
+ { { NULL, NULL }, "ttmid", { 640, 480 }, 4, RES_TTMID },
+ { { NULL, NULL }, "tthigh", { 1280, 960 }, 1, RES_TTHIGH },
+ { { NULL, NULL }, NULL, }
+};
+
+/*
+ * Default colors.....
+ * Currently the TT-low (256 colors) just uses 16 time the 16-color default.
+ * If you have a sensible 256 scale, feel free to add.....
+ * The first 2 colors in all maps are {black,white}, so ite (text) displays
+ * are initially readable. Also, this enables me to supply only 1 map. The
+ * 4 color mode uses the first four entries of the 16 color mode thus giving
+ * a gray scale display. (Maybe we can add an intensity bit to the ite...)
+ */
+static u_short def_color16[16] = {
+ 0x000, /* black */
+ 0xfff, /* white */
+ 0xccc, /* light gray */
+ 0x888, /* gray */
+ 0x00c, /* blue */
+ 0x0c0, /* green */
+ 0x0cc, /* cyan */
+ 0xc00, /* red */
+ 0xc0c, /* magenta */
+ 0xcc0, /* brown */
+ 0x00f, /* light blue */
+ 0x0f0, /* light green */
+ 0x0ff, /* light cyan */
+ 0xf00, /* light red */
+ 0xf0f, /* light magenta */
+ 0xff0 /* light brown */
+};
+
+/*
+ * XXX: called from ite console init routine.
+ * Initialize list of posible video modes.
+ */
+int
+grfabs_probe()
+{
+ dmode_t *dm;
+ int i;
+ int has_mono;
+ static int inited = 0;
+
+ if(inited)
+ return; /* Has to be done only once */
+ inited++;
+
+ /*
+ * First find out what kind of monitor is attached. Dma-sound
+ * should be off because the 'sound-done' and 'monochrome-detect'
+ * are xor-ed together. I think that shutting it down here is the
+ * wrong place.
+ */
+ has_mono = (MFP->mf_gpip & IA_MONO) == 0;
+
+ LIST_INIT(&modes);
+ for(i = 0; (dm = &vid_modes[i])->name != NULL; i++) {
+ if(has_mono && (dm->vm_reg != RES_TTHIGH))
+ continue;
+ if(!has_mono && (dm->vm_reg == RES_TTHIGH))
+ continue;
+ LIST_INSERT_HEAD(&modes, dm, link);
+ }
+ return(1);
+}
+
+view_t *
+grf_alloc_view(d, dim, depth)
+dmode_t *d;
+dimen_t *dim;
+u_char depth;
+{
+ if(!d)
+ d = get_best_display_mode(dim->width, dim->height, depth);
+ if(d)
+ return(alloc_view(d, dim, depth));
+ return(NULL);
+}
+
+void grf_display_view(v)
+view_t *v;
+{
+ dmode_t *dm = v->mode;
+ bmap_t *bm = v->bitmap;
+
+ if(dm->current_view) {
+ /*
+ * Mark current view for this mode as no longer displayed
+ */
+ dm->current_view->flags &= ~VF_DISPLAY;
+ }
+ dm->current_view = v;
+ v->flags |= VF_DISPLAY;
+
+ grf_use_colormap(v, v->colormap);
+
+ /* XXX: should use vbl for this */
+ VIDEO->vd_tt_res = dm->vm_reg;
+ VIDEO->vd_raml = (u_long)bm->hw_address & 0xff;
+ VIDEO->vd_ramm = ((u_long)bm->hw_address >> 8) & 0xff;
+ VIDEO->vd_ramh = ((u_long)bm->hw_address >> 16) & 0xff;
+}
+
+void grf_remove_view(v)
+view_t *v;
+{
+ dmode_t *mode = v->mode;
+
+ if(mode->current_view == v) {
+#if 0
+ if(v->flags & VF_DISPLAY)
+ panic("Cannot shutdown display\n"); /* XXX */
+#endif
+ mode->current_view = NULL;
+ }
+ v->flags &= ~VF_DISPLAY;
+}
+
+void grf_free_view(v)
+view_t *v;
+{
+ if(v) {
+ dmode_t *md = v->mode;
+
+ grf_remove_view(v);
+ if(v->colormap != &con_cmap)
+ free(v->colormap, M_DEVBUF);
+ free_bitmap(v->bitmap);
+ if(v != &con_view)
+ free(v, M_DEVBUF);
+ }
+}
+
+int
+grf_get_colormap(v, cm)
+view_t *v;
+colormap_t *cm;
+{
+ colormap_t *gcm;
+ int i, n;
+
+ bzero(cm->centry, cm->nentries * sizeof(u_short));
+
+ gcm = v->colormap;
+ n = cm->nentries < gcm->nentries ? cm->nentries : gcm->nentries;
+ for(i = 0; i < n; i++)
+ cm->centry[i] = gcm->centry[i];
+ return(0);
+}
+
+int
+grf_use_colormap(v, cm)
+view_t *v;
+colormap_t *cm;
+{
+ dmode_t *dm;
+ volatile u_short *creg;
+ u_short *src;
+ u_short ncreg;
+ int i;
+
+ dm = v->mode;
+
+ switch(dm->vm_reg) {
+ case RES_STLOW:
+ creg = &VIDEO->vd_tt_rgb[0];
+ ncreg = 16;
+ break;
+ case RES_STMID:
+ creg = &VIDEO->vd_tt_rgb[0];
+ ncreg = 4;
+ break;
+ case RES_STHIGH:
+ creg = &VIDEO->vd_tt_rgb[254];
+ ncreg = 2;
+ break;
+ case RES_TTLOW:
+ creg = &VIDEO->vd_tt_rgb[0];
+ ncreg = 256;
+ break;
+ case RES_TTMID:
+ creg = &VIDEO->vd_tt_rgb[0];
+ ncreg = 16;
+ break;
+ case RES_TTHIGH:
+ return(0); /* No colors */
+ default:
+ panic("grf_get_colormap: wrong mode!?");
+ }
+ if(cm->nentries < ncreg)
+ ncreg = cm->nentries;
+
+ for(i = 0, src = cm->centry; i < ncreg; i++)
+ *creg++ = *src++;
+ return(0);
+}
+
+static dmode_t *
+get_best_display_mode(width, height, depth)
+int width, height, depth;
+{
+ dmode_t *save;
+ dmode_t *dm;
+ long dt, dx, dy, ct;
+
+ save = NULL;
+ dm = modes.lh_first;
+ while(dm != NULL) {
+ if(depth > dm->depth) {
+ dm = dm->link.le_next;
+ continue;
+ }
+ else if(width > dm->size.width || height > dm->size.height) {
+ dm = dm->link.le_next;
+ continue;
+ }
+ else if (width < dm->size.width || height < dm->size.height) {
+ dm = dm->link.le_next;
+ continue;
+ }
+ dx = abs(dm->size.width - width);
+ dy = abs(dm->size.height - height);
+ ct = dx + dy;
+
+ if (ct < dt || save == NULL) {
+ save = dm;
+ dt = ct;
+ }
+ dm = dm->link.le_next;
+ }
+ return (save);
+}
+
+static view_t *
+alloc_view(mode, dim, depth)
+dmode_t *mode;
+dimen_t *dim;
+u_char depth;
+{
+ view_t *v;
+ bmap_t *bm;
+
+ if(!atari_realconfig)
+ v = &con_view;
+ else v = malloc(sizeof(*v), M_DEVBUF, M_WAITOK);
+
+ bm = alloc_bitmap(mode->size.width, mode->size.height, mode->depth, 1);
+ if(bm) {
+ int i;
+ box_t box;
+
+ v->colormap = alloc_colormap(mode);
+ if(v->colormap) {
+ INIT_BOX(&box,0,0,mode->size.width,mode->size.height);
+ init_view(v, bm, mode, &box);
+ return(v);
+ }
+ free_bitmap(bm);
+ }
+ if(v != &con_view)
+ free(v, M_DEVBUF);
+ return (NULL);
+}
+
+static void
+init_view(v, bm, mode, dbox)
+view_t *v;
+bmap_t *bm;
+dmode_t *mode;
+box_t *dbox;
+{
+ v->bitmap = bm;
+ v->mode = mode;
+ bcopy(dbox, &v->display, sizeof(box_t));
+}
+
+/* bitmap functions */
+
+static bmap_t *
+alloc_bitmap(width, height, depth, clear)
+u_long width, height;
+u_char depth;
+int clear;
+{
+ int i;
+ u_long total_size, bm_size;
+ void *hw_address;
+ bmap_t *bm;
+
+ /*
+ * Sigh, it seems for mapping to work we need the bitplane data to
+ * 1: be aligned on a page boundry.
+ * 2: be n pages large.
+ *
+ * why? because the user gets a page aligned address, if this is before
+ * your allocation, too bad. Also it seems that the mapping routines
+ * do not watch to closely to the allowable length. so if you go over
+ * n pages by less than another page, the user gets to write all over
+ * the entire page. Since you did not allocate up to a page boundry
+ * (or more) the user writes into someone elses memory. -ch
+ */
+ bm_size = atari_round_page((width * height * depth) / NBBY);
+ total_size = bm_size + sizeof(bmap_t) + NBPG;
+
+ if((bm = (bmap_t*)alloc_stmem(total_size, &hw_address)) == NULL)
+ return(NULL);
+
+ bm->plane = (u_char*)bm + sizeof(bmap_t);
+ bm->plane = (u_char*)atari_round_page(bm->plane);
+ bm->hw_address = (u_char*)hw_address + sizeof(bmap_t);
+ bm->hw_address = (u_char*)atari_round_page(bm->hw_address);
+ bm->bytes_per_row = (width * depth) / NBBY;
+ bm->rows = height;
+ bm->depth = depth;
+
+ if(clear)
+ bzero(bm->plane, bm_size);
+ return(bm);
+}
+
+static void
+free_bitmap(bm)
+bmap_t *bm;
+{
+ if(bm)
+ free_stmem(bm);
+}
+
+static colormap_t *
+alloc_colormap(dm)
+dmode_t *dm;
+{
+ int nentries, i;
+ colormap_t *cm;
+
+ switch(dm->vm_reg) {
+ case RES_STLOW:
+ case RES_TTMID:
+ nentries = 16;
+ break;
+ case RES_STMID:
+ nentries = 4;
+ break;
+ case RES_STHIGH:
+ nentries = 2;
+ break;
+ case RES_TTLOW:
+ nentries = 256;
+ break;
+ case RES_TTHIGH:
+ nentries = 0;
+ default:
+ panic("grf:alloc_colormap: wrong mode!?");
+ }
+ if(!atari_realconfig) {
+ cm = &con_cmap;
+ cm->centry = con_colors;
+ }
+ else {
+ int size;
+
+ size = sizeof(*cm) + (nentries * sizeof(u_short));
+ cm = malloc(size, M_DEVBUF, M_WAITOK);
+ if(cm == NULL)
+ return(NULL);
+ cm->centry = (u_short *)&cm[1];
+
+ }
+ cm->nentries = nentries;
+
+ for(i = 0; i < nentries; i++)
+ cm->centry[i] = def_color16[i % 16];
+ return(cm);
+}
diff --git a/sys/arch/atari/dev/grfabs_reg.h b/sys/arch/atari/dev/grfabs_reg.h
new file mode 100644
index 00000000000..f9a3107daf2
--- /dev/null
+++ b/sys/arch/atari/dev/grfabs_reg.h
@@ -0,0 +1,140 @@
+/* $NetBSD: grfabs_reg.h,v 1.1.1.1 1995/03/26 07:12:15 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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 _GRFABS_REG_H
+#define _GRFABS_REG_H
+
+struct point {
+ long x;
+ long y;
+};
+typedef struct point point_t;
+
+struct dimension {
+ u_long width;
+ u_long height;
+};
+typedef struct dimension dimen_t;
+
+struct box {
+ long x;
+ long y;
+ u_long width;
+ u_long height;
+};
+typedef struct box box_t;
+
+struct rectangle {
+ long left;
+ long top;
+ long right;
+ long bottom;
+};
+typedef struct rectangle rect_t;
+
+typedef struct bitmap bmap_t;
+typedef struct colormap colormap_t;
+typedef struct display_mode dmode_t;
+
+/*
+ * View stuff.
+ */
+
+struct view {
+ bmap_t *bitmap; /* bitmap. */
+ box_t display; /* viewable area. */
+ dmode_t *mode; /* the mode for this view */
+ colormap_t *colormap; /* the colormap for this view */
+ int flags;
+};
+typedef struct view view_t;
+
+/* View-flags: */
+#define VF_DISPLAY 1 /* view is on the air now */
+
+/*
+ * Bitmap stuff.
+ */
+struct bitmap {
+ u_short bytes_per_row; /* number of bytes per display row. */
+ u_short rows; /* number of display rows. */
+ u_short depth; /* depth of bitmap. */
+ u_char *plane; /* plane data for bitmap. */
+ u_char *hw_address; /* mappable bitplane pointer. */
+};
+
+/*
+ * Colormap stuff.
+ */
+struct colormap {
+ u_short nentries; /* number of entries in the map */
+ u_short *centry; /* actual colormap */
+};
+
+/*
+ * Create a colormap entry
+ */
+#define MAKE_CENTRY(r,g,b) (((r & 0xf)<<8)|((g & 0xf)<<4)|(b & 0xf))
+#define MAX_CENTRIES 256 /* that all there is */
+
+/* display mode */
+struct display_mode {
+ LIST_ENTRY(display_mode) link;
+ u_char *name; /* logical name for mode. */
+ dimen_t size; /* screen size */
+ u_char depth; /* screen depth */
+ u_short vm_reg; /* video mode register */
+ view_t *current_view; /* view displaying me */
+};
+
+/*
+ * Misc draw related macros.
+ */
+#define INIT_BOX(b,xx,yy,ww,hh) \
+ do { \
+ (b)->x = xx; \
+ (b)->y = yy; \
+ (b)->width = ww; \
+ (b)->height = hh; \
+ } while(0)
+
+/*
+ * Prototypes:
+ */
+view_t *grf_alloc_view __P((dmode_t *d, dimen_t *dim, u_char depth));
+void grf_display_view __P((view_t *v));
+void grf_remove_view __P((view_t *v));
+void grf_free_view __P((view_t *v));
+int grf_get_colormap __P((view_t *, colormap_t *));
+int grf_use_colormap __P((view_t *, colormap_t *));
+
+#endif /* _GRFABS_REG_H */
diff --git a/sys/arch/atari/dev/grfioctl.h b/sys/arch/atari/dev/grfioctl.h
new file mode 100644
index 00000000000..fb5b32571c3
--- /dev/null
+++ b/sys/arch/atari/dev/grfioctl.h
@@ -0,0 +1,212 @@
+/* $NetBSD: grfioctl.h,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * from: Utah $Hdr: grfioctl.h 1.1 90/07/09$
+ *
+ * @(#)grfioctl.h 7.2 (Berkeley) 11/4/90
+ */
+
+
+/* these are changeable values, encapsulated in their own structure, so
+ no the whole thing has to be copied when setting parameters. */
+struct grfdyninfo {
+ int gdi_fbx; /* frame buffer x offset */
+ int gdi_fby; /* frame buffer y offset */
+ int gdi_dwidth; /* displayed part width */
+ int gdi_dheight; /* displayed part height */
+ int gdi_dx; /* displayed part x offset */
+ int gdi_dy; /* displayed part y offset */
+};
+
+struct grfinfo {
+ caddr_t gd_fbaddr; /* frame buffer physaddr */
+ int gd_fbsize; /* frame buffer size */
+ short gd_colors; /* number of colors */
+ short gd_planes; /* number of planes */
+
+ int gd_fbwidth; /* frame buffer width */
+ int gd_fbheight; /* frame buffer height */
+
+ struct grfdyninfo gd_dyn; /* everything changable by GRFIOCSINFO */
+/* compatibility... */
+#define gd_fbx gd_dyn.gdi_fbx
+#define gd_fby gd_dyn.gdi_fby
+#define gd_dwidth gd_dyn.gdi_dwidth
+#define gd_dheight gd_dyn.gdi_dheight
+#define gd_dx gd_dyn.gdi_dx
+#define gd_dy gd_dyn.gdi_dy
+
+ /* new for banked pager support */
+ int gd_bank_size; /* size of a bank (or 0) */
+};
+
+
+/* video mode, should be display-independant, but it might need
+ modifications in the future to really become hardware-independant. */
+
+struct grfvideo_mode {
+ u_char mode_num; /* index in mode table */
+ char mode_descr[80]; /* description of mode */
+ u_long pixel_clock; /* in Hz. */
+ u_short disp_width; /* width of displayed video (incl overscan) */
+ u_short disp_height; /* height "" */
+ u_short depth; /* number of bitplanes resp. bits per pixel */
+ u_short hblank_start;
+ u_short hblank_stop;
+ u_short hsync_start; /* video-parameters, take care not to */
+ u_short hsync_stop; /* use parameters that violete specs of */
+ u_short htotal; /* your monitor ! */
+ u_short vblank_start;
+ u_short vblank_stop;
+ u_short vsync_start;
+ u_short vsync_stop;
+ u_short vtotal;
+};
+
+
+/*
+ * BSD ioctls
+ */
+#define OGRFIOCGINFO 0x40344700 /* to keep compat for a while... */
+#define GRFIOCGINFO _IOR('G', 0, struct grfinfo) /* get info on device */
+#define GRFIOCON _IO('G', 1) /* turn graphics on */
+#define GRFIOCOFF _IO('G', 2) /* turn graphics off */
+#define GRFIOCMAP _IOWR('G', 5, int) /* map in regs+framebuffer */
+#define GRFIOCUNMAP _IOW('G', 6, int) /* unmap regs+framebuffer */
+
+/* amiga addons */
+ /* set info on device */
+#define GRFIOCSINFO _IOW('G', 40, struct grfdyninfo)
+ /* get video_mode. mode_num==0 gets current mode. */
+#define GRFGETVMODE _IOWR('G', 41, struct grfvideo_mode)
+ /* set video_mode. */
+#define GRFSETVMODE _IOW('G', 42, int)
+ /* get number of configured video modes */
+#define GRFGETNUMVM _IOR('G', 43, int)
+
+
+/*
+ * generic framebuffer-related ioctls. These are somewhat
+ * similar to SunOS fb-ioctls since I liked them reading
+ * thru the X11-server code.
+ */
+
+/*
+ * colormap related information. Every grf has an associated
+ * colormap. Depending on the capabilities of the hardware, more
+ * or less of the information provided may be used.
+ * Maxium value of "index" can be deduced from grfinfo->gd_colors.
+ */
+struct grf_colormap {
+ int index; /* start at red[index],green[index],blue[index] */
+ int count; /* till < red[index+count],... */
+ u_char *red;
+ u_char *green;
+ u_char *blue;
+};
+
+/* write the selected slots into the active colormap */
+#define GRFIOCPUTCMAP _IOW('G', 50, struct grf_colormap)
+
+/* retrieve the selected slots from the active colormap */
+#define GRFIOCGETCMAP _IOWR('G', 51, struct grf_colormap)
+
+
+/*
+ * support a possibly available hardware sprite. calls just fail
+ * if a given grf doesn't implement hardware sprites.
+ */
+struct grf_position {
+ u_short x, y; /* 0,0 is upper left corner */
+};
+#define GRFIOCSSPRITEPOS _IOW('G', 52, struct grf_position)
+#define GRFIOCGSPRITEPOS _IOR('G', 53, struct grf_position)
+
+struct grf_spriteinfo {
+ u_short set;
+#define GRFSPRSET_ENABLE (1<<0)
+#define GRFSPRSET_POS (1<<1)
+#define GRFSPRSET_HOT (1<<2)
+#define GRFSPRSET_CMAP (1<<3)
+#define GRFSPRSET_SHAPE (1<<4)
+#define GRFSPRSET_ALL 0x1f
+ u_short enable; /* sprite is displayed if == 1 */
+ struct grf_position pos; /* sprite location */
+ struct grf_position hot; /* sprite hot spot */
+ struct grf_colormap cmap; /* colormap for the sprite. */
+ struct grf_position size; /* x == width, y == height */
+ u_char *image, *mask; /* sprite bitmap and mask */
+};
+
+#define GRFIOCSSPRITEINF _IOW('G', 54, struct grf_spriteinfo)
+#define GRFIOCGSPRITEINF _IOR('G', 55, struct grf_spriteinfo)
+
+/* get maximum sprite size hardware can display */
+#define GRFIOCGSPRITEMAX _IOR('G', 56, struct grf_position)
+
+
+/* support for a BitBlt operation. The op-codes are identical
+ to X11 GCs */
+#define GRFBBOPclear 0x0 /* 0 */
+#define GRFBBOPand 0x1 /* src AND dst */
+#define GRFBBOPandReverse 0x2 /* src AND NOT dst */
+#define GRFBBOPcopy 0x3 /* src */
+#define GRFBBOPandInverted 0x4 /* NOT src AND dst */
+#define GRFBBOPnoop 0x5 /* dst */
+#define GRFBBOPxor 0x6 /* src XOR dst */
+#define GRFBBOPor 0x7 /* src OR dst */
+#define GRFBBOPnor 0x8 /* NOT src AND NOT dst */
+#define GRFBBOPequiv 0x9 /* NOT src XOR dst */
+#define GRFBBOPinvert 0xa /* NOT dst */
+#define GRFBBOPorReverse 0xb /* src OR NOT dst */
+#define GRFBBOPcopyInverted 0xc /* NOT src */
+#define GRFBBOPorInverted 0xd /* NOT src OR dst */
+#define GRFBBOPnand 0xe /* NOT src OR NOT dst */
+#define GRFBBOPset 0xf /* 1 */
+
+struct grf_bitblt {
+ u_short op; /* see above */
+ u_short src_x, src_y; /* upper left corner of source-region */
+ u_short dst_x, dst_y; /* upper left corner of dest-region */
+ u_short w, h; /* width, height of region */
+ u_short mask; /* bitmask to apply */
+};
+
+#define GRFIOCBITBLT _IOR('G', 57, struct grf_bitblt)
+
diff --git a/sys/arch/atari/dev/grfvar.h b/sys/arch/atari/dev/grfvar.h
new file mode 100644
index 00000000000..7f4fed36166
--- /dev/null
+++ b/sys/arch/atari/dev/grfvar.h
@@ -0,0 +1,98 @@
+/* $NetBSD: grfvar.h,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * from: Utah $Hdr: grfvar.h 1.9 91/01/21$
+ *
+ * @(#)grfvar.h 7.3 (Berkeley) 5/7/91
+ */
+
+struct ite_softc;
+
+/*
+ * this struct is owned by the driver (grfcc)
+ * and is passed to grf when grf is configed. The ite also
+ * uses it...
+ */
+struct grf_softc {
+ struct device g_device; /* config sets this up. */
+ struct grfinfo g_display; /* hardware descr. (for ioctl) */
+ int g_flags; /* software flags */
+ int g_unit; /* grf unit we want/have */
+ dev_t g_itedev; /* ite device number */
+ dev_t g_grfdev; /* grf device number */
+ view_t *g_view; /* the view we're acting on */
+ dev_t g_viewdev; /* view device number */
+ caddr_t g_data; /* device dependent data */
+ int (*g_mode)();
+ int g_conpri; /* priority of ite as console */
+ void (*g_iteinit)();
+ void (*g_itedeinit)();
+ void (*g_iteclear)();
+ void (*g_iteputc)();
+ void (*g_itecursor)();
+ void (*g_itescroll)();
+};
+
+/* flags */
+#define GF_ALIVE 0x01
+#define GF_OPEN 0x02
+#define GF_EXCLUDE 0x04
+#define GF_WANTED 0x08
+#define GF_GRFON 0x10
+
+/* software ids defined in grfioctl.h */
+
+/* requests to mode routine (g_mode())*/
+#define GM_GRFON 1
+#define GM_GRFOFF 2
+#define GM_GRFOVON 3
+#define GM_GRFOVOFF 4
+#define GM_GRFCONFIG 5
+#define GM_GRFGETVMODE 6
+#define GM_GRFSETVMODE 7
+#define GM_GRFGETNUMVM 8
+#define GM_GRFGETBANK 9
+#define GM_GRFSETBANK 10
+#define GM_GRFGETCURBANK 11
+#define GM_GRFIOCTL 12
+
+/* minor device interpretation */
+#define GRFOVDEV 0x10 /* XXX no driver uses yet, overlay planes */
+#define GRFIMDEV 0x20 /* XXX no driver uses yet, images planes */
+#define GRFUNIT(d) ((d) & 0x7)
diff --git a/sys/arch/atari/dev/ite.c b/sys/arch/atari/dev/ite.c
new file mode 100644
index 00000000000..dcf511152c3
--- /dev/null
+++ b/sys/arch/atari/dev/ite.c
@@ -0,0 +1,2327 @@
+/* $NetBSD: ite.c,v 1.1.1.1 1995/03/26 07:12:10 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * from: Utah Hdr: ite.c 1.1 90/07/09
+ * from: @(#)ite.c 7.6 (Berkeley) 5/16/91
+ */
+
+/*
+ * ite - bitmapped terminal.
+ * Supports VT200, a few terminal features will be unavailable until
+ * the system actually probes the device (i.e. not after consinit())
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/termios.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <dev/cons.h>
+
+#include <atari/atari/kdassert.h>
+#include <atari/dev/iteioctl.h>
+#include <atari/dev/itevar.h>
+#include <atari/dev/grfioctl.h>
+#include <atari/dev/grfabs_reg.h>
+#include <atari/dev/grfvar.h>
+#include <atari/dev/viewioctl.h>
+#include <atari/dev/viewvar.h>
+#include <atari/dev/kbdmap.h>
+
+/*
+ * XXX go ask sys/kern/tty.c:ttselect()
+ */
+#include "grf.h" /* Get definition of NGRF */
+struct tty *ite_tty[NGRF];
+
+#define ITEUNIT(dev) (minor(dev))
+
+#define SUBR_INIT(ip) (ip)->grf->g_iteinit(ip)
+#define SUBR_DEINIT(ip) (ip)->grf->g_itedeinit(ip)
+#define SUBR_PUTC(ip,c,dy,dx,m) (ip)->grf->g_iteputc(ip,c,dy,dx,m)
+#define SUBR_CURSOR(ip,flg) (ip)->grf->g_itecursor(ip,flg)
+#define SUBR_CLEAR(ip,sy,sx,h,w) (ip)->grf->g_iteclear(ip,sy,sx,h,w)
+#define SUBR_SCROLL(ip,sy,sx,cnt,dir) (ip)->grf->g_itescroll(ip,sy,sx,cnt,dir)
+
+u_int ite_confunits; /* configured units */
+
+int start_repeat_timeo = 30; /* first repeat after x s/100 */
+int next_repeat_timeo = 10; /* next repeat after x s/100 */
+
+int ite_default_wrap = 1; /* you want vtxxx-nam, binpatch */
+
+struct ite_softc con_itesoftc;
+u_char cons_tabs[MAX_TABS];
+
+struct ite_softc *kbd_ite;
+int kbd_init;
+
+static char *index __P((const char *, int));
+static int inline atoi __P((const char *));
+static void ite_switch __P((int));
+void iteputchar __P((int c, struct ite_softc *ip));
+void ite_putstr __P((const char * s, int len, dev_t dev));
+void iteattach __P((struct device *, struct device *, void *));
+int itematch __P((struct device *, struct cfdata *, void *));
+
+struct cfdriver itecd = {
+ NULL, "ite", (cfmatch_t)itematch, iteattach, DV_DULL,
+ sizeof(struct ite_softc), NULL, 0 };
+
+int
+itematch(pdp, cdp, auxp)
+ struct device *pdp;
+ struct cfdata *cdp;
+ void *auxp;
+{
+ struct grf_softc *gp;
+ int maj;
+
+ gp = auxp;
+
+ /* ite0 should be at grf0 */
+ if(cdp->cf_unit != gp->g_unit)
+ return(0);
+
+ /*
+ * all that our mask allows (more than enough no one
+ * has > 32 monitors for text consoles on one machine)
+ */
+ if (cdp->cf_unit >= sizeof(ite_confunits) * NBBY)
+ return(0);
+ /*
+ * XXX
+ * normally this would be done in attach, however
+ * during early init we do not have a device pointer
+ * and thus no unit number.
+ */
+ for(maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == iteopen)
+ break;
+ gp->g_itedev = makedev(maj, cdp->cf_unit);
+ return(1);
+}
+
+void
+iteattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ extern int hz;
+ struct grf_softc *gp;
+ struct ite_softc *ip;
+ int s;
+
+ gp = (struct grf_softc *)auxp;
+
+ /*
+ * mark unit as attached (XXX see itematch)
+ */
+ ite_confunits |= 1 << ITEUNIT(gp->g_itedev);
+
+ if(dp) {
+ ip = (struct ite_softc *)dp;
+
+ s = spltty();
+ if(con_itesoftc.grf != NULL
+ && con_itesoftc.grf->g_unit == gp->g_unit) {
+ /*
+ * console reinit copy params over.
+ * and console always gets keyboard
+ */
+ bcopy(&con_itesoftc.grf, &ip->grf,
+ (char *)&ip[1] - (char *)&ip->grf);
+ con_itesoftc.grf = NULL;
+ kbd_ite = ip;
+ }
+ ip->grf = gp;
+ splx(s);
+
+ iteinit(gp->g_itedev);
+ printf(": rows %d cols %d", ip->rows, ip->cols);
+ printf(" repeat at (%d/100)s next at (%d/100)s",
+ start_repeat_timeo, next_repeat_timeo);
+
+ if (kbd_ite == NULL)
+ kbd_ite = ip;
+ if (kbd_ite == ip)
+ printf(" has keyboard");
+ printf("\n");
+ } else {
+ if (con_itesoftc.grf != NULL &&
+ con_itesoftc.grf->g_conpri > gp->g_conpri)
+ return;
+ con_itesoftc.grf = gp;
+ con_itesoftc.tabs = cons_tabs;
+ }
+}
+
+struct ite_softc *
+getitesp(dev)
+ dev_t dev;
+{
+ extern int atari_realconfig;
+
+ if(atari_realconfig && (con_itesoftc.grf == NULL))
+ return(itecd.cd_devs[ITEUNIT(dev)]);
+
+ if(con_itesoftc.grf == NULL)
+ panic("no ite_softc for console");
+ return(&con_itesoftc);
+}
+
+/*
+ * cons.c entry points into ite device.
+ */
+
+/*
+ * Return a priority in consdev->cn_pri field highest wins. This function
+ * is called before any devices have been probed.
+ */
+void
+ite_cnprobe(cd)
+ struct consdev *cd;
+{
+ /*
+ * bring graphics layer up.
+ */
+ config_console();
+
+ /*
+ * return priority of the best ite (already picked from attach)
+ * or CN_DEAD.
+ */
+ if (con_itesoftc.grf == NULL)
+ cd->cn_pri = CN_DEAD;
+ else {
+ cd->cn_pri = con_itesoftc.grf->g_conpri;
+ cd->cn_dev = con_itesoftc.grf->g_itedev;
+ }
+}
+
+void
+ite_cninit(cd)
+ struct consdev *cd;
+{
+ struct ite_softc *ip;
+
+ ip = getitesp(cd->cn_dev);
+ ip->flags |= ITE_ISCONS;
+ iteinit(cd->cn_dev);
+ ip->flags |= ITE_ACTIVE | ITE_ISCONS;
+}
+
+/*
+ * ite_cnfinish() is called in ite_init() when the device is
+ * being probed in the normal fasion, thus we can finish setting
+ * up this ite now that the system is more functional.
+ */
+void
+ite_cnfinish(ip)
+ struct ite_softc *ip;
+{
+ static int done;
+
+ if (done)
+ return;
+ done = 1;
+}
+
+int
+ite_cngetc(dev)
+ dev_t dev;
+{
+ int c;
+
+ /* XXX this should be moved */
+ if (!kbd_init) {
+ kbd_init = 1;
+ kbdenable();
+ }
+ do {
+ c = kbdgetcn();
+ c = ite_cnfilter(c, ITEFILT_CONSOLE);
+ } while (c == -1);
+ return (c);
+}
+
+void
+ite_cnputc(dev, c)
+ dev_t dev;
+ int c;
+{
+ static int paniced;
+ struct ite_softc *ip;
+ char ch;
+
+ ip = getitesp(dev);
+ ch = c;
+
+ if (panicstr && !paniced &&
+ (ip->flags & (ITE_ACTIVE | ITE_INGRF)) != ITE_ACTIVE) {
+ (void)ite_on(dev, 3);
+ paniced = 1;
+ }
+ iteputchar(ch, ip);
+}
+
+/*
+ * standard entry points to the device.
+ */
+
+/*
+ * iteinit() is the standard entry point for initialization of
+ * an ite device, it is also called from ite_cninit().
+ *
+ */
+void
+iteinit(dev)
+ dev_t dev;
+{
+ struct ite_softc *ip;
+
+ ip = getitesp(dev);
+ if(ip->flags & ITE_INITED)
+ return;
+ bcopy(&ascii_kbdmap, &kbdmap, sizeof(struct kbdmap));
+
+ ip->cursorx = 0;
+ ip->cursory = 0;
+ SUBR_INIT(ip);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ if (ip->tabs == NULL)
+ ip->tabs = malloc(MAX_TABS * sizeof(u_char),M_DEVBUF,M_WAITOK);
+ ite_reset(ip);
+ ip->flags |= ITE_INITED;
+}
+
+int
+iteopen(dev, mode, devtype, p)
+ dev_t dev;
+ int mode, devtype;
+ struct proc *p;
+{
+ struct ite_softc *ip;
+ struct tty *tp;
+ int error, first, unit;
+
+ unit = ITEUNIT(dev);
+ first = 0;
+
+ if (((1 << unit) & ite_confunits) == 0)
+ return (ENXIO);
+
+ ip = getitesp(dev);
+
+ if (ip->tp == NULL)
+ tp = ite_tty[unit] = ip->tp = ttymalloc();
+ else
+ tp = ip->tp;
+ if ((tp->t_state & (TS_ISOPEN | TS_XCLUDE)) == (TS_ISOPEN | TS_XCLUDE)
+ && p->p_ucred->cr_uid != 0)
+ return (EBUSY);
+ if ((ip->flags & ITE_ACTIVE) == 0) {
+ error = ite_on(dev, 0);
+ if (error)
+ return (error);
+ first = 1;
+ }
+ tp->t_oproc = itestart;
+ tp->t_param = ite_param;
+ tp->t_dev = dev;
+ if ((tp->t_state & TS_ISOPEN) == 0) {
+ 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;
+ tp->t_state = TS_WOPEN | TS_CARR_ON;
+ ttsetwater(tp);
+ }
+ error = (*linesw[tp->t_line].l_open) (dev, tp);
+ if (error == 0) {
+ tp->t_winsize.ws_row = ip->rows;
+ tp->t_winsize.ws_col = ip->cols;
+ if (!kbd_init) {
+ kbd_init = 1;
+ kbdenable();
+ }
+ } else if (first)
+ ite_off(dev, 0);
+ return (error);
+}
+
+int
+iteclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ struct tty *tp;
+
+ tp = getitesp(dev)->tp;
+
+ KDASSERT(tp);
+ (*linesw[tp->t_line].l_close) (tp, flag);
+ ttyclose(tp);
+ ite_off(dev, 0);
+ return (0);
+}
+
+int
+iteread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct tty *tp;
+
+ tp = getitesp(dev)->tp;
+
+ KDASSERT(tp);
+ return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
+}
+
+int
+itewrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct tty *tp;
+
+ tp = getitesp(dev)->tp;
+
+ KDASSERT(tp);
+ return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
+}
+
+int
+iteioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ u_long cmd;
+ int flag;
+ caddr_t addr;
+ struct proc *p;
+{
+ struct iterepeat *irp;
+ struct ite_softc *ip;
+ struct tty *tp;
+ int error;
+
+ ip = getitesp(dev);
+ tp = ip->tp;
+
+ KDASSERT(tp);
+
+ error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, addr, flag, p);
+ if (error >= 0)
+ return (error);
+ error = ttioctl(tp, cmd, addr, flag, p);
+ if (error >= 0)
+ return (error);
+
+ switch (cmd) {
+ case ITEIOCSKMAP:
+ if (addr == 0)
+ return(EFAULT);
+ bcopy(addr, &kbdmap, sizeof(struct kbdmap));
+ return(0);
+ case ITEIOCGKMAP:
+ if (addr == NULL)
+ return(EFAULT);
+ bcopy(&kbdmap, addr, sizeof(struct kbdmap));
+ return(0);
+ case ITEIOCGREPT:
+ irp = (struct iterepeat *)addr;
+ irp->start = start_repeat_timeo;
+ irp->next = next_repeat_timeo;
+ case ITEIOCSREPT:
+ irp = (struct iterepeat *)addr;
+ if (irp->start < ITEMINREPEAT && irp->next < ITEMINREPEAT)
+ return(EINVAL);
+ start_repeat_timeo = irp->start;
+ next_repeat_timeo = irp->next;
+ return(0);
+ }
+#ifdef notyet /* LWP */
+ /* XXX */
+ if (minor(dev) == 0) {
+ error = ite_grf_ioctl(ip, cmd, addr, flag, p);
+ if (error >= 0)
+ return (error);
+ }
+#endif
+ return (ENOTTY);
+}
+
+void
+itestart(tp)
+ struct tty *tp;
+{
+ struct clist *rbp;
+ struct ite_softc *ip;
+ u_char buf[ITEBURST];
+ int s, len, n;
+
+ ip = getitesp(tp->t_dev);
+
+ KDASSERT(tp);
+
+ s = spltty(); {
+ if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
+ goto out;
+
+ tp->t_state |= TS_BUSY;
+ rbp = &tp->t_outq;
+
+ len = q_to_b(rbp, buf, ITEBURST);
+ } splx(s);
+
+ /* Here is a really good place to implement pre/jumpscroll() */
+ ite_putstr((char *)buf, len, tp->t_dev);
+
+ s = spltty(); {
+ tp->t_state &= ~TS_BUSY;
+ /* we have characters remaining. */
+ if (rbp->c_cc) {
+ tp->t_state |= TS_TIMEOUT;
+ timeout(ttrstrt, tp, 1);
+ }
+ /* wakeup we are below */
+ if (rbp->c_cc <= tp->t_lowat) {
+ if (tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t) rbp);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+ out: ;
+ } splx(s);
+}
+
+int
+ite_on(dev, flag)
+ dev_t dev;
+ int flag;
+{
+ struct ite_softc *ip;
+ int unit;
+
+ unit = ITEUNIT(dev);
+ if (((1 << unit) & ite_confunits) == 0)
+ return (ENXIO);
+
+ ip = getitesp(dev);
+
+ /* force ite active, overriding graphics mode */
+ if (flag & 1) {
+ ip->flags |= ITE_ACTIVE;
+ ip->flags &= ~(ITE_INGRF | ITE_INITED);
+ }
+ /* leave graphics mode */
+ if (flag & 2) {
+ ip->flags &= ~ITE_INGRF;
+ if ((ip->flags & ITE_ACTIVE) == 0)
+ return (0);
+ }
+ ip->flags |= ITE_ACTIVE;
+ if (ip->flags & ITE_INGRF)
+ return (0);
+ iteinit(dev);
+ return (0);
+}
+
+int
+ite_off(dev, flag)
+dev_t dev;
+int flag;
+{
+ struct ite_softc *ip;
+
+ ip = getitesp(dev);
+ if (flag & 2)
+ ip->flags |= ITE_INGRF;
+ if ((ip->flags & ITE_ACTIVE) == 0)
+ return;
+ if ((flag & 1) ||
+ (ip->flags & (ITE_INGRF | ITE_ISCONS | ITE_INITED)) == ITE_INITED)
+ SUBR_DEINIT(ip);
+ if ((flag & 2) == 0) /* XXX hmm grfon() I think wants this to go inactive. */
+ ip->flags &= ~ITE_ACTIVE;
+}
+
+static void
+ite_switch(unit)
+int unit;
+{
+ struct ite_softc *ip;
+
+ if(!(ite_confunits & (1 << unit)))
+ return; /* Don't try unconfigured units */
+ ip = getitesp(unit);
+ if(!(ip->flags & ITE_INITED))
+ return;
+
+ /*
+ * If switching to an active ite, also switch the keyboard.
+ */
+ if(ip->flags & ITE_ACTIVE)
+ kbd_ite = ip;
+
+ /*
+ * Now make it visible
+ */
+ viewioctl(ip->grf->g_viewdev, VIOCDISPLAY, NULL, 0, -1);
+}
+
+/* XXX called after changes made in underlying grf layer. */
+/* I want to nuke this */
+void
+ite_reinit(dev)
+ dev_t dev;
+{
+ struct ite_softc *ip;
+
+ ip = getitesp(dev);
+ ip->flags &= ~ITE_INITED;
+ iteinit(dev);
+}
+
+int
+ite_param(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
+ite_reset(ip)
+ struct ite_softc *ip;
+{
+ int i;
+
+ ip->curx = 0;
+ ip->cury = 0;
+ ip->attribute = ATTR_NOR;
+ ip->save_curx = 0;
+ ip->save_cury = 0;
+ ip->save_attribute = ATTR_NOR;
+ ip->ap = ip->argbuf;
+ ip->emul_level = 0;
+ ip->eightbit_C1 = 0;
+ ip->top_margin = 0;
+ ip->bottom_margin = ip->rows - 1;
+ ip->inside_margins = 0;
+ ip->linefeed_newline = 0;
+ ip->auto_wrap = ite_default_wrap;
+ ip->cursor_appmode = 0;
+ ip->keypad_appmode = 0;
+ ip->imode = 0;
+ ip->key_repeat = 1;
+ bzero(ip->tabs, ip->cols);
+ for (i = 0; i < ip->cols; i++)
+ ip->tabs[i] = ((i & 7) == 0);
+}
+
+/*
+ * has to be global becuase of the shared filters.
+ */
+static u_char key_mod;
+static u_char last_dead;
+
+/* Used in console at startup only */
+int
+ite_cnfilter(c, caller)
+u_int c;
+enum caller caller;
+{
+ struct key key;
+ u_char code, up, mask;
+ int s;
+
+ up = KBD_RELEASED(c);
+ c = KBD_SCANCODE(c);
+ code = 0;
+ mask = 0;
+
+ s = spltty();
+
+ /*
+ * Handle special keys
+ */
+ switch(c) {
+ case KBD_LEFT_SHIFT:
+ mask = KBD_MOD_LSHIFT;
+ break;
+ case KBD_RIGHT_SHIFT:
+ mask = KBD_MOD_RSHIFT;
+ break;
+ case KBD_CTRL:
+ mask = KBD_MOD_CTRL;
+ break;
+ case KBD_ALT:
+ mask = KBD_MOD_ALT;
+ break;
+ case KBD_CAPS_LOCK:
+ /* CAPSLOCK is a toggle */
+ if(!up)
+ key_mod ^= KBD_MOD_CAPS;
+ splx(s);
+ return;
+ break;
+ }
+ if(mask) {
+ if(up)
+ key_mod &= ~mask;
+ else
+ key_mod |= mask;
+ splx(s);
+ return -1;
+ }
+
+ /*
+ * No special action if key released
+ */
+ if(up) {
+ splx(s);
+ return -1;
+ }
+
+ /* translate modifiers */
+ if(key_mod & KBD_MOD_SHIFT) {
+ if(key_mod & KBD_MOD_ALT)
+ key = kbdmap.alt_shift_keys[c];
+ else key = kbdmap.shift_keys[c];
+ }
+ else if(key_mod & KBD_MOD_ALT)
+ key = kbdmap.alt_keys[c];
+ else {
+ key = kbdmap.keys[c];
+ /*
+ * If CAPS and key is CAPable (no pun intended)
+ */
+ if((key_mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
+ key = kbdmap.shift_keys[c];
+ }
+ code = key.code;
+
+#ifdef notyet /* LWP: Didn't have time to look at this yet */
+ /*
+ * If string return simple console filter
+ */
+ if(key->mode & (KBD_MODE_STRING | KBD_MODE_KPAD)) {
+ splx(s);
+ return -1;
+ }
+ /* handle dead keys */
+ if(key->mode & KBD_MODE_DEAD) {
+ /* if entered twice, send accent itself */
+ if (last_dead == key->mode & KBD_MODE_ACCMASK)
+ last_dead = 0;
+ else {
+ last_dead = key->mode & KBD_MODE_ACCMASK;
+ splx(s);
+ return -1;
+ }
+ }
+ if(last_dead) {
+ /* can't apply dead flag to string-keys */
+ if (code >= '@' && code < 0x7f)
+ code =
+ acctable[KBD_MODE_ACCENT(last_dead)][code - '@'];
+ last_dead = 0;
+ }
+#endif
+ if(key_mod & KBD_MOD_CTRL)
+ code &= 0x1f;
+
+ /*
+ * Do console mapping.
+ */
+ code = code == '\r' ? '\n' : code;
+
+ splx(s);
+ return (code);
+}
+
+/* And now the old stuff. */
+
+/* these are used to implement repeating keys.. */
+static u_char last_char;
+static u_char tout_pending;
+
+/*ARGSUSED*/
+static void
+
+repeat_handler(arg)
+void *arg;
+{
+ tout_pending = 0;
+ if(last_char)
+ add_sicallback(ite_filter, last_char, ITEFILT_REPEATER);
+}
+
+void
+ite_filter(c, caller)
+u_int c;
+enum caller caller;
+{
+ struct tty *kbd_tty;
+ u_char code, *str, up, mask;
+ struct key key;
+ int s, i;
+
+ if(kbd_ite == NULL)
+ return;
+
+ kbd_tty = kbd_ite->tp;
+
+ up = KBD_RELEASED(c);
+ c = KBD_SCANCODE(c);
+ code = 0;
+ mask = 0;
+
+ /* have to make sure we're at spltty in here */
+ s = spltty();
+
+ /*
+ * keyboard interrupts come at priority 2, while softint
+ * generated keyboard-repeat interrupts come at level 1. So,
+ * to not allow a key-up event to get thru before a repeat for
+ * the key-down, we remove any outstanding callout requests..
+ */
+ rem_sicallback(ite_filter);
+
+
+ /*
+ * Handle special keys
+ */
+ switch(c) {
+ case KBD_LEFT_SHIFT:
+ mask = KBD_MOD_LSHIFT;
+ break;
+ case KBD_RIGHT_SHIFT:
+ mask = KBD_MOD_RSHIFT;
+ break;
+ case KBD_CTRL:
+ mask = KBD_MOD_CTRL;
+ break;
+ case KBD_ALT:
+ mask = KBD_MOD_ALT;
+ break;
+ case KBD_CAPS_LOCK:
+ /* CAPSLOCK is a toggle */
+ if(!up)
+ key_mod ^= KBD_MOD_CAPS;
+ splx(s);
+ return;
+ break;
+ }
+ if(mask) {
+ if(up)
+ key_mod &= ~mask;
+ else
+ key_mod |= mask;
+ splx(s);
+ return;
+ }
+
+ /*
+ * Stop repeating on up event
+ */
+ if (up) {
+ if(tout_pending) {
+ untimeout(repeat_handler, 0);
+ tout_pending = 0;
+ last_char = 0;
+ }
+ splx(s);
+ return;
+ }
+ else if(tout_pending && last_char != c) {
+ /*
+ * Different character, stop also
+ */
+ untimeout(repeat_handler, 0);
+ tout_pending = 0;
+ last_char = 0;
+ }
+
+ /*
+ * Handle ite-switching ALT + Fx
+ */
+ if((key_mod == KBD_MOD_ALT) && (c >= 0x3b) && (c <= 0x44)) {
+ ite_switch(c - 0x3b);
+ splx(s);
+ return;
+ }
+ /*
+ * Safety button, switch back to ascii keymap.
+ */
+ if(key_mod == (KBD_MOD_ALT | KBD_MOD_LSHIFT) && c == 0x3b) {
+ /* ALT + LSHIFT + F1 */
+ bcopy(&ascii_kbdmap, &kbdmap, sizeof(struct kbdmap));
+ splx(s);
+ return;
+#ifdef DDB
+ }
+ else if(key_mod == (KBD_MOD_ALT | KBD_MOD_LSHIFT) && c == 0x43) {
+ /* ALT + LSHIFT + F9 */
+ extern int Debugger();
+ Debugger();
+ splx(s);
+ return;
+#endif
+ }
+
+ /*
+ * The rest of the code is senseless when the device is not open.
+ */
+ if(kbd_tty == NULL) {
+ splx(s);
+ return;
+ }
+
+ /*
+ * Translate modifiers
+ */
+ if(key_mod & KBD_MOD_SHIFT) {
+ if(key_mod & KBD_MOD_ALT)
+ key = kbdmap.alt_shift_keys[c];
+ else key = kbdmap.shift_keys[c];
+ }
+ else if(key_mod & KBD_MOD_ALT)
+ key = kbdmap.alt_keys[c];
+ else {
+ key = kbdmap.keys[c];
+ /*
+ * If CAPS and key is CAPable (no pun intended)
+ */
+ if((key_mod & KBD_MOD_CAPS) && (key.mode & KBD_MODE_CAPS))
+ key = kbdmap.shift_keys[c];
+ }
+ code = key.code;
+
+ /*
+ * Arrange to repeat the keystroke. By doing this at the level
+ * of scan-codes, we can have function keys, and keys that
+ * send strings, repeat too. This also entitles an additional
+ * overhead, since we have to do the conversion each time, but
+ * I guess that's ok.
+ */
+ if(!tout_pending && caller == ITEFILT_TTY && kbd_ite->key_repeat) {
+ tout_pending = 1;
+ last_char = c;
+ timeout(repeat_handler, 0, start_repeat_timeo * hz / 100);
+ }
+ else if(!tout_pending && caller==ITEFILT_REPEATER
+ && kbd_ite->key_repeat) {
+ tout_pending = 1;
+ last_char = c;
+ timeout(repeat_handler, 0, next_repeat_timeo * hz / 100);
+ }
+ /* handle dead keys */
+ if (key.mode & KBD_MODE_DEAD) {
+ /* if entered twice, send accent itself */
+ if (last_dead == key.mode & KBD_MODE_ACCMASK)
+ last_dead = 0;
+ else {
+ last_dead = key.mode & KBD_MODE_ACCMASK;
+ splx(s);
+ return;
+ }
+ }
+ if (last_dead) {
+ /* can't apply dead flag to string-keys */
+ if (!(key.mode & KBD_MODE_STRING) && code >= '@' &&
+ code < 0x7f)
+ code = acctable[KBD_MODE_ACCENT(last_dead)][code - '@'];
+ last_dead = 0;
+ }
+
+ /*
+ * If not string, apply CTRL modifiers
+ */
+ if(!(key.mode & KBD_MODE_STRING)
+ && (!(key.mode & KBD_MODE_KPAD)
+ || (kbd_ite && !kbd_ite->keypad_appmode))) {
+ if(key_mod & KBD_MOD_CTRL)
+ code &= 0x1f;
+ }
+ else if((key.mode & KBD_MODE_KPAD)
+ && (kbd_ite && kbd_ite->keypad_appmode)) {
+ static char *in = "0123456789-+.\r()/*";
+ static char *out = "pqrstuvwxymlnMPQRS";
+ char *cp = index(in, code);
+
+ /*
+ * keypad-appmode sends SS3 followed by the above
+ * translated character
+ */
+ (*linesw[kbd_tty->t_line].l_rint) (27, kbd_tty);
+ (*linesw[kbd_tty->t_line].l_rint) ('O', kbd_tty);
+ (*linesw[kbd_tty->t_line].l_rint) (out[cp - in], kbd_tty);
+ splx(s);
+ return;
+ } else {
+ /* *NO* I don't like this.... */
+ static u_char app_cursor[] =
+ {
+ 3, 27, 'O', 'A',
+ 3, 27, 'O', 'B',
+ 3, 27, 'O', 'C',
+ 3, 27, 'O', 'D'};
+
+ str = kbdmap.strings + code;
+ /*
+ * if this is a cursor key, AND it has the default
+ * keymap setting, AND we're in app-cursor mode, switch
+ * to the above table. This is *nasty* !
+ */
+ if(((c == 0x48) || (c == 0x4b) || (c == 0x4d) || (c == 0x50))
+ && kbd_ite->cursor_appmode
+ && !bcmp(str, "\x03\x1b[", 3) &&
+ index("ABCD", str[3]))
+ str = app_cursor + 4 * (str[3] - 'A');
+
+ /*
+ * using a length-byte instead of 0-termination allows
+ * to embed \0 into strings, although this is not used
+ * in the default keymap
+ */
+ for (i = *str++; i; i--)
+ (*linesw[kbd_tty->t_line].l_rint) (*str++, kbd_tty);
+ splx(s);
+ return;
+ }
+ (*linesw[kbd_tty->t_line].l_rint) (code, kbd_tty);
+
+ splx(s);
+ return;
+}
+
+/* helper functions, makes the code below more readable */
+static void inline
+ite_sendstr(str)
+ char *str;
+{
+ struct tty *kbd_tty;
+
+ kbd_tty = kbd_ite->tp;
+ KDASSERT(kbd_tty);
+ while (*str)
+ (*linesw[kbd_tty->t_line].l_rint) (*str++, kbd_tty);
+}
+
+static void
+alignment_display(ip)
+ struct ite_softc *ip;
+{
+ int i, j;
+
+ for (j = 0; j < ip->rows; j++)
+ for (i = 0; i < ip->cols; i++)
+ SUBR_PUTC(ip, 'E', j, i, ATTR_NOR);
+ attrclr(ip, 0, 0, ip->rows, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+snap_cury(ip)
+ struct ite_softc *ip;
+{
+ if (ip->inside_margins)
+ {
+ if (ip->cury < ip->top_margin)
+ ip->cury = ip->top_margin;
+ if (ip->cury > ip->bottom_margin)
+ ip->cury = ip->bottom_margin;
+ }
+}
+
+static void inline
+ite_dnchar(ip, n)
+ struct ite_softc *ip;
+ int n;
+{
+ n = min(n, ip->cols - ip->curx);
+ if (n < ip->cols - ip->curx)
+ {
+ SUBR_SCROLL(ip, ip->cury, ip->curx + n, n, SCROLL_LEFT);
+ attrmov(ip, ip->cury, ip->curx + n, ip->cury, ip->curx,
+ 1, ip->cols - ip->curx - n);
+ attrclr(ip, ip->cury, ip->cols - n, 1, n);
+ }
+ while (n-- > 0)
+ SUBR_PUTC(ip, ' ', ip->cury, ip->cols - n - 1, ATTR_NOR);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_inchar(ip, n)
+ struct ite_softc *ip;
+ int n;
+{
+ n = min(n, ip->cols - ip->curx);
+ if (n < ip->cols - ip->curx)
+ {
+ SUBR_SCROLL(ip, ip->cury, ip->curx, n, SCROLL_RIGHT);
+ attrmov(ip, ip->cury, ip->curx, ip->cury, ip->curx + n,
+ 1, ip->cols - ip->curx - n);
+ attrclr(ip, ip->cury, ip->curx, 1, n);
+ }
+ while (n--)
+ SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_clrtoeol(ip)
+ struct ite_softc *ip;
+{
+ int y = ip->cury, x = ip->curx;
+ if (ip->cols - x > 0)
+ {
+ SUBR_CLEAR(ip, y, x, 1, ip->cols - x);
+ attrclr(ip, y, x, 1, ip->cols - x);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ }
+}
+
+static void inline
+ite_clrtobol(ip)
+ struct ite_softc *ip;
+{
+ int y = ip->cury, x = min(ip->curx + 1, ip->cols);
+ SUBR_CLEAR(ip, y, 0, 1, x);
+ attrclr(ip, y, 0, 1, x);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_clrline(ip)
+ struct ite_softc *ip;
+{
+ int y = ip->cury;
+ SUBR_CLEAR(ip, y, 0, 1, ip->cols);
+ attrclr(ip, y, 0, 1, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+
+
+static void inline
+ite_clrtoeos(ip)
+ struct ite_softc *ip;
+{
+ ite_clrtoeol(ip);
+ if (ip->cury < ip->rows - 1)
+ {
+ SUBR_CLEAR(ip, ip->cury + 1, 0, ip->rows - 1 - ip->cury, ip->cols);
+ attrclr(ip, ip->cury, 0, ip->rows - ip->cury, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ }
+}
+
+static void inline
+ite_clrtobos(ip)
+ struct ite_softc *ip;
+{
+ ite_clrtobol(ip);
+ if (ip->cury > 0)
+ {
+ SUBR_CLEAR(ip, 0, 0, ip->cury, ip->cols);
+ attrclr(ip, 0, 0, ip->cury, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ }
+}
+
+static void inline
+ite_clrscreen(ip)
+ struct ite_softc *ip;
+{
+ SUBR_CLEAR(ip, 0, 0, ip->rows, ip->cols);
+ attrclr(ip, 0, 0, ip->rows, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+
+
+static void inline
+ite_dnline(ip, n)
+ struct ite_softc *ip;
+ int n;
+{
+ /* interesting.. if the cursor is outside the scrolling
+ region, this command is simply ignored.. */
+ if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
+ return;
+
+ n = min(n, ip->bottom_margin + 1 - ip->cury);
+ if (n <= ip->bottom_margin - ip->cury)
+ {
+ SUBR_SCROLL(ip, ip->cury + n, 0, n, SCROLL_UP);
+ attrmov(ip, ip->cury + n, 0, ip->cury, 0,
+ ip->bottom_margin + 1 - ip->cury - n, ip->cols);
+ }
+ SUBR_CLEAR(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
+ attrclr(ip, ip->bottom_margin - n + 1, 0, n, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_inline(ip, n)
+ struct ite_softc *ip;
+ int n;
+{
+ /* interesting.. if the cursor is outside the scrolling
+ region, this command is simply ignored.. */
+ if (ip->cury < ip->top_margin || ip->cury > ip->bottom_margin)
+ return;
+
+ n = min(n, ip->bottom_margin + 1 - ip->cury);
+ if (n <= ip->bottom_margin - ip->cury)
+ {
+ SUBR_SCROLL(ip, ip->cury, 0, n, SCROLL_DOWN);
+ attrmov(ip, ip->cury, 0, ip->cury + n, 0,
+ ip->bottom_margin + 1 - ip->cury - n, ip->cols);
+ }
+ SUBR_CLEAR(ip, ip->cury, 0, n, ip->cols);
+ attrclr(ip, ip->cury, 0, n, ip->cols);
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+}
+
+static void inline
+ite_lf (ip)
+ struct ite_softc *ip;
+{
+ ++ip->cury;
+ if ((ip->cury == ip->bottom_margin+1) || (ip->cury == ip->rows))
+ {
+ ip->cury--;
+ SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
+ ite_clrline(ip);
+ }
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr(ip, ATTR_INV);
+}
+
+static void inline
+ite_crlf (ip)
+ struct ite_softc *ip;
+{
+ ip->curx = 0;
+ ite_lf (ip);
+}
+
+static void inline
+ite_cr (ip)
+ struct ite_softc *ip;
+{
+ if (ip->curx)
+ {
+ ip->curx = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ }
+}
+
+static void inline
+ite_rlf (ip)
+ struct ite_softc *ip;
+{
+ ip->cury--;
+ if ((ip->cury < 0) || (ip->cury == ip->top_margin - 1))
+ {
+ ip->cury++;
+ SUBR_SCROLL(ip, ip->top_margin, 0, 1, SCROLL_DOWN);
+ ite_clrline(ip);
+ }
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr(ip, ATTR_INV);
+}
+
+static int inline
+atoi (cp)
+ const char *cp;
+{
+ int n;
+
+ for (n = 0; *cp && *cp >= '0' && *cp <= '9'; cp++)
+ n = n * 10 + *cp - '0';
+
+ return n;
+}
+
+static char *
+index (cp, ch)
+ const char *cp;
+ int ch;
+{
+ while (*cp && *cp != ch) cp++;
+ return *cp ? (char *) cp : 0;
+}
+
+
+
+static int inline
+ite_argnum (ip)
+ struct ite_softc *ip;
+{
+ char ch;
+ int n;
+
+ /* convert argument string into number */
+ if (ip->ap == ip->argbuf)
+ return 1;
+ ch = *ip->ap;
+ *ip->ap = 0;
+ n = atoi (ip->argbuf);
+ *ip->ap = ch;
+
+ return n;
+}
+
+static int inline
+ite_zargnum (ip)
+ struct ite_softc *ip;
+{
+ char ch, *cp;
+ int n;
+
+ /* convert argument string into number */
+ if (ip->ap == ip->argbuf)
+ return 0;
+ ch = *ip->ap;
+ *ip->ap = 0;
+ n = atoi (ip->argbuf);
+ *ip->ap = ch;
+
+ return n; /* don't "n ? n : 1" here, <CSI>0m != <CSI>1m ! */
+}
+
+static int inline
+strncmp (a, b, l)
+ const char *a, *b;
+ int l;
+{
+ for (;l--; a++, b++)
+ if (*a != *b)
+ return *a - *b;
+ return 0;
+}
+
+void
+ite_putstr(s, len, dev)
+ const char *s;
+ int len;
+ dev_t dev;
+{
+ struct ite_softc *ip;
+ int i;
+
+ ip = getitesp(dev);
+
+ /* XXX avoid problems */
+ if ((ip->flags & (ITE_ACTIVE|ITE_INGRF)) != ITE_ACTIVE)
+ return;
+
+ SUBR_CURSOR(ip, START_CURSOROPT);
+ for (i = 0; i < len; i++)
+ if (s[i])
+ iteputchar(s[i], ip);
+ SUBR_CURSOR(ip, END_CURSOROPT);
+}
+
+
+void
+iteputchar(c, ip)
+ register int c;
+ struct ite_softc *ip;
+{
+ struct tty *kbd_tty;
+ int n, x, y;
+ char *cp;
+
+ if (kbd_ite == NULL)
+ kbd_tty = NULL;
+ else
+ kbd_tty = kbd_ite->tp;
+
+ if (ip->escape)
+ {
+doesc:
+ switch (ip->escape)
+ {
+ case ESC:
+ switch (c)
+ {
+ /* first 7bit equivalents for the 8bit control characters */
+
+ case 'D':
+ c = IND;
+ ip->escape = 0;
+ break; /* and fall into the next switch below (same for all `break') */
+
+ case 'E':
+ c = NEL;
+ ip->escape = 0;
+ break;
+
+ case 'H':
+ c = HTS;
+ ip->escape = 0;
+ break;
+
+ case 'M':
+ c = RI;
+ ip->escape = 0;
+ break;
+
+ case 'N':
+ c = SS2;
+ ip->escape = 0;
+ break;
+
+ case 'O':
+ c = SS3;
+ ip->escape = 0;
+ break;
+
+ case 'P':
+ c = DCS;
+ ip->escape = 0;
+ break;
+
+ case '[':
+ c = CSI;
+ ip->escape = 0;
+ break;
+
+ case '\\':
+ c = ST;
+ ip->escape = 0;
+ break;
+
+ case ']':
+ c = OSC;
+ ip->escape = 0;
+ break;
+
+ case '^':
+ c = PM;
+ ip->escape = 0;
+ break;
+
+ case '_':
+ c = APC;
+ ip->escape = 0;
+ break;
+
+
+ /* introduces 7/8bit control */
+ case ' ':
+ /* can be followed by either F or G */
+ ip->escape = ' ';
+ break;
+
+
+ /* a lot of character set selections, not yet used...
+ 94-character sets: */
+ case '(': /* G0 */
+ case ')': /* G1 */
+ ip->escape = c;
+ return;
+
+ case '*': /* G2 */
+ case '+': /* G3 */
+ case 'B': /* ASCII */
+ case 'A': /* ISO latin 1 */
+ case '<': /* user preferred suplemental */
+ case '0': /* dec special graphics */
+
+ /* 96-character sets: */
+ case '-': /* G1 */
+ case '.': /* G2 */
+ case '/': /* G3 */
+
+ /* national character sets: */
+ case '4': /* dutch */
+ case '5':
+ case 'C': /* finnish */
+ case 'R': /* french */
+ case 'Q': /* french canadian */
+ case 'K': /* german */
+ case 'Y': /* italian */
+ case '6': /* norwegian/danish */
+ /* note: %5 and %6 are not supported (two chars..) */
+
+ ip->escape = 0;
+ /* just ignore for now */
+ return;
+
+
+ /* locking shift modes (as you might guess, not yet supported..) */
+ case '`':
+ ip->GR = ip->G1;
+ ip->escape = 0;
+ return;
+
+ case 'n':
+ ip->GL = ip->G2;
+ ip->escape = 0;
+ return;
+
+ case '}':
+ ip->GR = ip->G2;
+ ip->escape = 0;
+ return;
+
+ case 'o':
+ ip->GL = ip->G3;
+ ip->escape = 0;
+ return;
+
+ case '|':
+ ip->GR = ip->G3;
+ ip->escape = 0;
+ return;
+
+
+ /* font width/height control */
+ case '#':
+ ip->escape = '#';
+ return;
+
+
+ /* hard terminal reset .. */
+ case 'c':
+ ite_reset (ip);
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ ip->escape = 0;
+ return;
+
+
+ case '7':
+ ip->save_curx = ip->curx;
+ ip->save_cury = ip->cury;
+ ip->save_attribute = ip->attribute;
+ ip->escape = 0;
+ return;
+
+ case '8':
+ ip->curx = ip->save_curx;
+ ip->cury = ip->save_cury;
+ ip->attribute = ip->save_attribute;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ ip->escape = 0;
+ return;
+
+ case '=':
+ ip->keypad_appmode = 1;
+ ip->escape = 0;
+ return;
+
+ case '>':
+ ip->keypad_appmode = 0;
+ ip->escape = 0;
+ return;
+
+ case 'Z': /* request ID */
+ if (ip->emul_level == EMUL_VT100)
+ ite_sendstr ("\033[?61;0c"); /* XXX not clean */
+ else
+ ite_sendstr ("\033[?63;0c"); /* XXX not clean */
+ ip->escape = 0;
+ return;
+
+ /* default catch all for not recognized ESC sequences */
+ default:
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+ case '(':
+ case ')':
+ ip->escape = 0;
+ return;
+
+
+ case ' ':
+ switch (c)
+ {
+ case 'F':
+ ip->eightbit_C1 = 0;
+ ip->escape = 0;
+ return;
+
+ case 'G':
+ ip->eightbit_C1 = 1;
+ ip->escape = 0;
+ return;
+
+ default:
+ /* not supported */
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+ case '#':
+ switch (c)
+ {
+ case '5':
+ /* single height, single width */
+ ip->escape = 0;
+ return;
+
+ case '6':
+ /* double width, single height */
+ ip->escape = 0;
+ return;
+
+ case '3':
+ /* top half */
+ ip->escape = 0;
+ return;
+
+ case '4':
+ /* bottom half */
+ ip->escape = 0;
+ return;
+
+ case '8':
+ /* screen alignment pattern... */
+ alignment_display (ip);
+ ip->escape = 0;
+ return;
+
+ default:
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+
+ case CSI:
+ /* the biggie... */
+ switch (c)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case ';': case '\"': case '$': case '>':
+ if (ip->ap < ip->argbuf + MAX_ARGSIZE)
+ *ip->ap++ = c;
+ return;
+
+ case BS:
+ /* you wouldn't believe such perversion is possible?
+ it is.. BS is allowed in between cursor sequences
+ (at least), according to vttest.. */
+ if (--ip->curx < 0)
+ ip->curx = 0;
+ else
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ break;
+
+ case 'p':
+ *ip->ap = 0;
+ if (! strncmp (ip->argbuf, "61\"", 3))
+ ip->emul_level = EMUL_VT100;
+ else if (! strncmp (ip->argbuf, "63;1\"", 5)
+ || ! strncmp (ip->argbuf, "62;1\"", 5))
+ ip->emul_level = EMUL_VT300_7;
+ else
+ ip->emul_level = EMUL_VT300_8;
+ ip->escape = 0;
+ return;
+
+
+ case '?':
+ *ip->ap = 0;
+ ip->escape = '?';
+ ip->ap = ip->argbuf;
+ return;
+
+
+ case 'c':
+ *ip->ap = 0;
+ if (ip->argbuf[0] == '>')
+ {
+ ite_sendstr ("\033[>24;0;0;0c");
+ }
+ else switch (ite_zargnum(ip))
+ {
+ case 0:
+ /* primary DA request, send primary DA response */
+ if (ip->emul_level == EMUL_VT100)
+ ite_sendstr ("\033[?1;1c");
+ else
+ ite_sendstr ("\033[?63;1c");
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+ case 'n':
+ switch (ite_zargnum(ip))
+ {
+ case 5:
+ ite_sendstr ("\033[0n"); /* no malfunction */
+ break;
+ case 6:
+ /* cursor position report */
+ sprintf (ip->argbuf, "\033[%d;%dR",
+ ip->cury + 1, ip->curx + 1);
+ ite_sendstr (ip->argbuf);
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'x':
+ switch (ite_zargnum(ip))
+ {
+ case 0:
+ /* Fake some terminal parameters. */
+ ite_sendstr ("\033[2;1;1;112;112;1;0x");
+ break;
+ case 1:
+ ite_sendstr ("\033[3;1;1;112;112;1;0x");
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'g':
+ switch (ite_zargnum(ip))
+ {
+ case 0:
+ if (ip->curx < ip->cols)
+ ip->tabs[ip->curx] = 0;
+ break;
+ case 3:
+ for (n = 0; n < ip->cols; n++)
+ ip->tabs[n] = 0;
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'h': case 'l':
+ n = ite_zargnum (ip);
+ switch (n)
+ {
+ case 4:
+ ip->imode = (c == 'h'); /* insert/replace mode */
+ break;
+ case 20:
+ ip->linefeed_newline = (c == 'h');
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'M':
+ ite_dnline (ip, ite_argnum (ip));
+ ip->escape = 0;
+ return;
+
+
+ case 'L':
+ ite_inline (ip, ite_argnum (ip));
+ ip->escape = 0;
+ return;
+
+
+ case 'P':
+ ite_dnchar (ip, ite_argnum (ip));
+ ip->escape = 0;
+ return;
+
+
+ case '@':
+ ite_inchar (ip, ite_argnum (ip));
+ ip->escape = 0;
+ return;
+
+
+ case 'G':
+ /* this one was *not* in my vt320 manual but in
+ a vt320 termcap entry.. who is right?
+ It's supposed to set the horizontal cursor position. */
+ *ip->ap = 0;
+ x = atoi (ip->argbuf);
+ if (x) x--;
+ ip->curx = min(x, ip->cols - 1);
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+
+ case 'd':
+ /* same thing here, this one's for setting the absolute
+ vertical cursor position. Not documented... */
+ *ip->ap = 0;
+ y = atoi (ip->argbuf);
+ if (y) y--;
+ if (ip->inside_margins)
+ y += ip->top_margin;
+ ip->cury = min(y, ip->rows - 1);
+ ip->escape = 0;
+ snap_cury(ip);
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+
+ case 'H':
+ case 'f':
+ *ip->ap = 0;
+ y = atoi (ip->argbuf);
+ x = 0;
+ cp = index (ip->argbuf, ';');
+ if (cp)
+ x = atoi (cp + 1);
+ if (x) x--;
+ if (y) y--;
+ if (ip->inside_margins)
+ y += ip->top_margin;
+ ip->cury = min(y, ip->rows - 1);
+ ip->curx = min(x, ip->cols - 1);
+ ip->escape = 0;
+ snap_cury(ip);
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+ case 'A':
+ n = ite_argnum (ip);
+ n = ip->cury - (n ? n : 1);
+ if (n < 0) n = 0;
+ if (ip->inside_margins)
+ n = max(ip->top_margin, n);
+ else if (n == ip->top_margin - 1)
+ /* allow scrolling outside region, but don't scroll out
+ of active region without explicit CUP */
+ n = ip->top_margin;
+ ip->cury = n;
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+ case 'B':
+ n = ite_argnum (ip);
+ n = ip->cury + (n ? n : 1);
+ n = min(ip->rows - 1, n);
+ if (ip->inside_margins)
+ n = min(ip->bottom_margin, n);
+ else if (n == ip->bottom_margin + 1)
+ /* allow scrolling outside region, but don't scroll out
+ of active region without explicit CUP */
+ n = ip->bottom_margin;
+ ip->cury = n;
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+ case 'C':
+ n = ite_argnum (ip);
+ n = n ? n : 1;
+ ip->curx = min(ip->curx + n, ip->cols - 1);
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+ case 'D':
+ n = ite_argnum (ip);
+ n = n ? n : 1;
+ n = ip->curx - n;
+ ip->curx = n >= 0 ? n : 0;
+ ip->escape = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ clr_attr (ip, ATTR_INV);
+ return;
+
+
+
+
+ case 'J':
+ *ip->ap = 0;
+ n = ite_zargnum (ip);
+ if (n == 0)
+ ite_clrtoeos(ip);
+ else if (n == 1)
+ ite_clrtobos(ip);
+ else if (n == 2)
+ ite_clrscreen(ip);
+ ip->escape = 0;
+ return;
+
+
+ case 'K':
+ n = ite_zargnum (ip);
+ if (n == 0)
+ ite_clrtoeol(ip);
+ else if (n == 1)
+ ite_clrtobol(ip);
+ else if (n == 2)
+ ite_clrline(ip);
+ ip->escape = 0;
+ return;
+
+
+ case 'X':
+ n = ite_argnum(ip) - 1;
+ n = min(n, ip->cols - 1 - ip->curx);
+ for (; n >= 0; n--)
+ {
+ attrclr(ip, ip->cury, ip->curx + n, 1, 1);
+ SUBR_PUTC(ip, ' ', ip->cury, ip->curx + n, ATTR_NOR);
+ }
+ ip->escape = 0;
+ return;
+
+
+ case '}': case '`':
+ /* status line control */
+ ip->escape = 0;
+ return;
+
+
+ case 'r':
+ *ip->ap = 0;
+ x = atoi (ip->argbuf);
+ x = x ? x : 1;
+ y = ip->rows;
+ cp = index (ip->argbuf, ';');
+ if (cp)
+ {
+ y = atoi (cp + 1);
+ y = y ? y : ip->rows;
+ }
+ if (y - x < 2)
+ {
+ /* if illegal scrolling region, reset to defaults */
+ x = 1;
+ y = ip->rows;
+ }
+ x--;
+ y--;
+ ip->top_margin = min(x, ip->rows - 1);
+ ip->bottom_margin = min(y, ip->rows - 1);
+ if (ip->inside_margins)
+ {
+ ip->cury = ip->top_margin;
+ ip->curx = 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'm':
+ /* big attribute setter/resetter */
+ {
+ char *cp;
+ *ip->ap = 0;
+ /* kludge to make CSIm work (== CSI0m) */
+ if (ip->ap == ip->argbuf)
+ ip->ap++;
+ for (cp = ip->argbuf; cp < ip->ap; )
+ {
+ switch (*cp)
+ {
+ case 0:
+ case '0':
+ clr_attr (ip, ATTR_ALL);
+ cp++;
+ break;
+
+ case '1':
+ set_attr (ip, ATTR_BOLD);
+ cp++;
+ break;
+
+ case '2':
+ switch (cp[1])
+ {
+ case '2':
+ clr_attr (ip, ATTR_BOLD);
+ cp += 2;
+ break;
+
+ case '4':
+ clr_attr (ip, ATTR_UL);
+ cp += 2;
+ break;
+
+ case '5':
+ clr_attr (ip, ATTR_BLINK);
+ cp += 2;
+ break;
+
+ case '7':
+ clr_attr (ip, ATTR_INV);
+ cp += 2;
+ break;
+
+ default:
+ cp++;
+ break;
+ }
+ break;
+
+ case '4':
+ set_attr (ip, ATTR_UL);
+ cp++;
+ break;
+
+ case '5':
+ set_attr (ip, ATTR_BLINK);
+ cp++;
+ break;
+
+ case '7':
+ set_attr (ip, ATTR_INV);
+ cp++;
+ break;
+
+ default:
+ cp++;
+ break;
+ }
+ }
+
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'u':
+ /* DECRQTSR */
+ ite_sendstr ("\033P\033\\");
+ ip->escape = 0;
+ return;
+
+
+
+ default:
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+
+ case '?': /* CSI ? */
+ switch (c)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case ';': case '\"': case '$':
+ /* Don't fill the last character; it's needed. */
+ /* XXX yeah, where ?? */
+ if (ip->ap < ip->argbuf + MAX_ARGSIZE - 1)
+ *ip->ap++ = c;
+ return;
+
+
+ case 'n':
+ *ip->ap = 0;
+ if (ip->ap == &ip->argbuf[2])
+ {
+ if (! strncmp (ip->argbuf, "15", 2))
+ /* printer status: no printer */
+ ite_sendstr ("\033[13n");
+
+ else if (! strncmp (ip->argbuf, "25", 2))
+ /* udk status */
+ ite_sendstr ("\033[20n");
+
+ else if (! strncmp (ip->argbuf, "26", 2))
+ /* keyboard dialect: US */
+ ite_sendstr ("\033[27;1n");
+ }
+ ip->escape = 0;
+ return;
+
+
+ case 'h': case 'l':
+ n = ite_zargnum (ip);
+ switch (n)
+ {
+ case 1:
+ ip->cursor_appmode = (c == 'h');
+ break;
+
+ case 3:
+ /* 132/80 columns (132 == 'h') */
+ break;
+
+ case 4: /* smooth scroll */
+ break;
+
+ case 5:
+ /* light background (=='h') /dark background(=='l') */
+ break;
+
+ case 6: /* origin mode */
+ ip->inside_margins = (c == 'h');
+ ip->curx = 0;
+ ip->cury = ip->inside_margins ? ip->top_margin : 0;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ break;
+
+ case 7: /* auto wraparound */
+ ip->auto_wrap = (c == 'h');
+ break;
+
+ case 8: /* keyboard repeat */
+ ip->key_repeat = (c == 'h');
+ break;
+
+ case 20: /* newline mode */
+ ip->linefeed_newline = (c == 'h');
+ break;
+
+ case 25: /* cursor on/off */
+ SUBR_CURSOR(ip, (c == 'h') ? DRAW_CURSOR : ERASE_CURSOR);
+ break;
+ }
+ ip->escape = 0;
+ return;
+
+ default:
+ ip->escape = 0;
+ return;
+ }
+ break;
+
+
+ default:
+ ip->escape = 0;
+ return;
+ }
+ }
+
+ switch (c) {
+
+ case VT: /* VT is treated like LF */
+ case FF: /* so is FF */
+ case LF:
+ /* cr->crlf distinction is done here, on output,
+ not on input! */
+ if (ip->linefeed_newline)
+ ite_crlf (ip);
+ else
+ ite_lf (ip);
+ break;
+
+ case CR:
+ ite_cr (ip);
+ break;
+
+ case BS:
+ if (--ip->curx < 0)
+ ip->curx = 0;
+ else
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ break;
+
+ case HT:
+ for (n = ip->curx + 1; n < ip->cols; n++) {
+ if (ip->tabs[n]) {
+ ip->curx = n;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ break;
+ }
+ }
+ break;
+
+ case BEL:
+ if(kbd_tty && kbd_ite && kbd_ite->tp == kbd_tty)
+ kbdbell();
+ break;
+
+ case SO:
+ ip->GL = ip->G1;
+ break;
+
+ case SI:
+ ip->GL = ip->G0;
+ break;
+
+ case ENQ:
+ /* send answer-back message !! */
+ break;
+
+ case CAN:
+ ip->escape = 0; /* cancel any escape sequence in progress */
+ break;
+
+ case SUB:
+ ip->escape = 0; /* dito, but see below */
+ /* should also display a reverse question mark!! */
+ break;
+
+ case ESC:
+ ip->escape = ESC;
+ break;
+
+
+ /* now it gets weird.. 8bit control sequences.. */
+ case IND: /* index: move cursor down, scroll */
+ ite_lf (ip);
+ break;
+
+ case NEL: /* next line. next line, first pos. */
+ ite_crlf (ip);
+ break;
+
+ case HTS: /* set horizontal tab */
+ if (ip->curx < ip->cols)
+ ip->tabs[ip->curx] = 1;
+ break;
+
+ case RI: /* reverse index */
+ ite_rlf (ip);
+ break;
+
+ case SS2: /* go into G2 for one character */
+ /* not yet supported */
+ break;
+
+ case SS3: /* go into G3 for one character */
+ break;
+
+ case DCS: /* device control string introducer */
+ ip->escape = DCS;
+ ip->ap = ip->argbuf;
+ break;
+
+ case CSI: /* control sequence introducer */
+ ip->escape = CSI;
+ ip->ap = ip->argbuf;
+ break;
+
+ case ST: /* string terminator */
+ /* ignore, if not used as terminator */
+ break;
+
+ case OSC: /* introduces OS command. Ignore everything upto ST */
+ ip->escape = OSC;
+ break;
+
+ case PM: /* privacy message, ignore everything upto ST */
+ ip->escape = PM;
+ break;
+
+ case APC: /* application program command, ignore everything upto ST */
+ ip->escape = APC;
+ break;
+
+ default:
+ if (c < ' ' || c == DEL)
+ break;
+ if (ip->imode)
+ ite_inchar(ip, 1);
+ iteprecheckwrap(ip);
+#ifdef DO_WEIRD_ATTRIBUTES
+ if ((ip->attribute & ATTR_INV) || attrtest(ip, ATTR_INV)) {
+ attrset(ip, ATTR_INV);
+ SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_INV);
+ }
+ else
+ SUBR_PUTC(ip, c, ip->cury, ip->curx, ATTR_NOR);
+#else
+ SUBR_PUTC(ip, c, ip->cury, ip->curx, ip->attribute);
+#endif
+ SUBR_CURSOR(ip, DRAW_CURSOR);
+ itecheckwrap(ip);
+ break;
+ }
+}
+
+iteprecheckwrap(ip)
+ struct ite_softc *ip;
+{
+ if (ip->auto_wrap && ip->curx == ip->cols) {
+ ip->curx = 0;
+ clr_attr(ip, ATTR_INV);
+ if (++ip->cury >= ip->bottom_margin + 1) {
+ ip->cury = ip->bottom_margin;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ SUBR_SCROLL(ip, ip->top_margin + 1, 0, 1, SCROLL_UP);
+ ite_clrtoeol(ip);
+ } else
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ }
+}
+
+itecheckwrap(ip)
+ struct ite_softc *ip;
+{
+ if (ip->curx < ip->cols) {
+ ip->curx++;
+ SUBR_CURSOR(ip, MOVE_CURSOR);
+ }
+}
diff --git a/sys/arch/atari/dev/ite_cc.c b/sys/arch/atari/dev/ite_cc.c
new file mode 100644
index 00000000000..daca2860ec3
--- /dev/null
+++ b/sys/arch/atari/dev/ite_cc.c
@@ -0,0 +1,578 @@
+/* $NetBSD: ite_cc.c,v 1.1.1.1 1995/03/26 07:12:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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 "grf.h"
+#if NGRF > 0
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/termios.h>
+#include <sys/malloc.h>
+#include <dev/cons.h>
+#include <machine/cpu.h>
+#include <atari/dev/itevar.h>
+#include <atari/dev/iteioctl.h>
+#include <atari/dev/grfioctl.h>
+#include <atari/dev/grfabs_reg.h>
+#include <atari/dev/grfvar.h>
+#include <atari/dev/font.h>
+#include <atari/dev/viewioctl.h>
+#include <atari/dev/viewvar.h>
+
+/*
+ * This is what ip->priv points to;
+ * it contains local variables for custom-chip ites.
+ */
+struct ite_priv {
+ u_char **row_ptr; /* array of pointers into the bitmap */
+ u_long row_bytes;
+ u_long cursor_opt;
+ u_short *column_offset; /* array of offsets for columns */
+ u_int row_offset; /* the row offset */
+ u_short width; /* the bitmap width */
+ u_short underline; /* where the underline goes */
+ u_short ft_x; /* the font width */
+ u_short ft_y; /* the font height */
+ u_char *font_cell[256];/* the font pointer */
+};
+typedef struct ite_priv ipriv_t;
+
+/*
+ * We need the following space to get an ite-console setup before
+ * the VM-system is brought up. We setup for a 1280x960 monitor with
+ * an 8x8 font.
+ */
+extern int atari_realconfig;
+
+#define CONS_MAXROW 120 /* Max. number of rows on console */
+#define CONS_MAXCOL 160 /* Max. number of columns on console */
+static u_short con_columns[CONS_MAXCOL];
+static u_char *con_rows[CONS_MAXROW];
+static ipriv_t con_ipriv;
+
+extern font_info font_info_8x8;
+extern font_info font_info_8x16;
+
+static void view_init __P((struct ite_softc *));
+static void view_deinit __P((struct ite_softc *));
+static int ite_newsize __P((struct ite_softc *, struct itewinsize *));
+static void cursor32 __P((struct ite_softc *, int));
+static void putc8 __P((struct ite_softc *, int, int, int, int));
+static void clear8 __P((struct ite_softc *, int, int, int, int));
+static void scroll8 __P((struct ite_softc *, int, int, int, int));
+static void scrollbmap __P((bmap_t *, u_short, u_short, u_short, u_short,
+ short, short));
+
+/*
+ * Patchable
+ */
+int ite_default_x = 0; /* def leftedge offset */
+int ite_default_y = 0; /* def topedge offset */
+int ite_default_width = 640; /* def width */
+int ite_default_depth = 1; /* def depth */
+int ite_default_height = 400; /* def height */
+
+/*
+ * called from grf_cc to return console priority
+ */
+int
+grfcc_cnprobe()
+{
+ return(CN_INTERNAL);
+}
+/*
+ * called from grf_cc to init ite portion of
+ * grf_softc struct
+ */
+void
+grfcc_iteinit(gp)
+struct grf_softc *gp;
+{
+
+ gp->g_itecursor = cursor32;
+ gp->g_iteputc = putc8;
+ gp->g_iteclear = clear8;
+ gp->g_itescroll = scroll8;
+ gp->g_iteinit = view_init;
+ gp->g_itedeinit = view_deinit;
+}
+
+static void
+view_deinit(ip)
+struct ite_softc *ip;
+{
+ ip->flags &= ~ITE_INITED;
+}
+
+static void
+view_init(ip)
+register struct ite_softc *ip;
+{
+ struct itewinsize wsz;
+ ipriv_t *cci;
+
+ if(cci = ip->priv)
+ return;
+
+#if defined(KFONT_8X8)
+ ip->font = font_info_8x8;
+#else
+ ip->font = font_info_8x16;
+#endif
+
+ /* Find the correct set of rendering routines for this font. */
+ if(ip->font.width != 8)
+ panic("kernel font size not supported");
+
+ if(!atari_realconfig)
+ ip->priv = cci = &con_ipriv;
+ else ip->priv = cci = (ipriv_t*)malloc(sizeof(*cci), M_DEVBUF,M_WAITOK);
+ if(cci == NULL)
+ panic("No memory for ite-view");
+ bzero(cci, sizeof(*cci));
+
+ cci->cursor_opt = 0;
+ cci->row_ptr = NULL;
+ cci->column_offset = NULL;
+
+ wsz.x = ite_default_x;
+ wsz.y = ite_default_y;
+ wsz.width = ite_default_width;
+ wsz.height = ite_default_height;
+ wsz.depth = ite_default_depth;
+
+ ite_newsize (ip, &wsz);
+
+ /*
+ * Only console will be turned on by default..
+ */
+ if(ip->flags & ITE_ISCONS)
+ ip->grf->g_mode(ip->grf, GM_GRFON, NULL, 0, 0);
+}
+
+static int
+ite_newsize(ip, winsz)
+struct ite_softc *ip;
+struct itewinsize *winsz;
+{
+ struct view_size vs;
+ ipriv_t *cci = ip->priv;
+ u_long fbp, i, j;
+ int error = 0;
+ view_t *view = ip->grf->g_view;
+
+ vs.x = winsz->x;
+ vs.y = winsz->y;
+ vs.width = winsz->width;
+ vs.height = winsz->height;
+ vs.depth = winsz->depth;
+ error = viewioctl(ip->grf->g_viewdev, VIOCSSIZE, &vs, 0, -1);
+
+ /*
+ * Reinitialize our structs
+ */
+ ip->cols = view->display.width / ip->font.width;
+ ip->rows = view->display.height / ip->font.height;
+
+ /*
+ * save new values so that future opens use them
+ * this may not be correct when we implement Virtual Consoles
+ */
+ ite_default_height = view->display.height;
+ ite_default_width = view->display.width;
+ ite_default_x = view->display.x;
+ ite_default_y = view->display.y;
+ ite_default_depth = view->bitmap->depth;
+
+ if(cci->row_ptr && (cci->row_ptr != con_rows)) {
+ free(cci->row_ptr, M_DEVBUF);
+ cci->row_ptr = NULL;
+ }
+ if(cci->column_offset && (cci->column_offset != con_columns)) {
+ free(cci->column_offset, M_DEVBUF);
+ cci->column_offset = NULL;
+ }
+
+ if(!atari_realconfig) {
+ cci->row_ptr = con_rows;
+ cci->column_offset = con_columns;
+ }
+ else {
+ cci->row_ptr = malloc(sizeof(u_char *) * ip->rows,M_DEVBUF,M_WAITOK);
+ cci->column_offset = malloc(sizeof(u_int)*ip->cols,M_DEVBUF,M_WAITOK);
+ }
+
+ if(!cci->row_ptr || !cci->column_offset)
+ panic("No memory for ite-view");
+
+
+ cci->width = view->bitmap->bytes_per_row << 3;
+ cci->underline = ip->font.baseline + 1;
+ cci->row_offset = view->bitmap->bytes_per_row;
+ cci->ft_x = ip->font.width;
+ cci->ft_y = ip->font.height;
+ cci->row_bytes = cci->row_offset * cci->ft_y;
+ cci->row_ptr[0] = view->bitmap->plane;
+ for(i = 1; i < ip->rows; i++)
+ cci->row_ptr[i] = cci->row_ptr[i-1] + cci->row_bytes;
+
+ /*
+ * Initialize the column offsets to point at the correct location
+ * in the first plane. This definitely assumes a font width of 8!
+ */
+ j = view->bitmap->depth * 2;
+ cci->column_offset[0] = 0;
+ for(i = 1; i < ip->cols; i++)
+ cci->column_offset[i] = ((i >> 1) * j) + (i & 1);
+
+ /* initialize the font cell pointers */
+ cci->font_cell[ip->font.font_lo] = ip->font.font_p;
+ for(i = ip->font.font_lo+1; i <= ip->font.font_hi; i++)
+ cci->font_cell[i] = cci->font_cell[i-1] + ip->font.height;
+
+ return(error);
+}
+
+static void
+cursor32(struct ite_softc *ip, int flag)
+{
+ int cend;
+ u_char *pl;
+ ipriv_t *cci;
+
+ cci = ip->priv;
+
+ if(flag == END_CURSOROPT)
+ cci->cursor_opt--;
+ else if(flag == START_CURSOROPT) {
+ if(!cci->cursor_opt)
+ cursor32(ip, ERASE_CURSOR);
+ cci->cursor_opt++;
+ return; /* if we are already opted. */
+ }
+
+ if(cci->cursor_opt)
+ return; /* if we are still nested. */
+ /* else we draw the cursor. */
+
+ if(flag != DRAW_CURSOR && flag != END_CURSOROPT) {
+ /*
+ * erase the cursor
+ */
+ cend = ip->font.height-1;
+ pl = cci->column_offset[ip->cursorx]
+ + cci->row_ptr[ip->cursory];
+ __asm__ __volatile__
+ ("1: notb %0@ ; addaw %4,%0\n\t"
+ "dbra %1,1b"
+ : "=a" (pl), "=d" (cend)
+ : "0" (pl), "1" (cend),
+ "d" (cci->row_offset)
+ );
+ }
+
+ if(flag != DRAW_CURSOR && flag != MOVE_CURSOR && flag != END_CURSOROPT)
+ return;
+
+ /*
+ * draw the cursor
+ */
+ ip->cursorx = min(ip->curx, ip->cols-1);
+ ip->cursory = ip->cury;
+ cend = ip->font.height-1;
+ pl = cci->column_offset[ip->cursorx]
+ + cci->row_ptr[ip->cursory];
+
+ __asm__ __volatile__
+ ("1: notb %0@ ; addaw %4,%0\n\t"
+ "dbra %1,1b"
+ : "=a" (pl), "=d" (cend)
+ : "0" (pl), "1" (cend),
+ "d" (cci->row_offset)
+ );
+}
+
+static void
+putc8(struct ite_softc *ip, int c, int dy, int dx, int mode)
+{
+ register ipriv_t *cci = (ipriv_t *)ip->priv;
+ register u_char *pl = cci->column_offset[dx] + cci->row_ptr[dy];
+ register u_int fh = cci->ft_y;
+ register u_int ro = cci->row_offset;
+ register u_char eor_mask;
+ register u_char bl, tmp, ul;
+ register u_char *ft;
+
+ if(c < ip->font.font_lo || c > ip->font.font_hi)
+ return;
+
+ ft = cci->font_cell[c];
+
+ if(!mode) {
+ while(fh--) {
+ *pl = *ft++; pl += ro;
+ }
+ return;
+ }
+
+ eor_mask = (mode & ATTR_INV) ? 0xff : 0x00;
+ bl = (mode & ATTR_BOLD) ? 1 : 0;
+ ul = fh - cci->underline;
+ while(fh--) {
+ tmp = *ft++ ^ eor_mask;
+ if(bl)
+ *pl = tmp | (tmp >> 1);
+ else *pl = tmp;
+ if(fh == ul)
+ *pl = 0xff;
+ pl += ro;
+ }
+}
+
+static void
+clear8(struct ite_softc *ip, int sy, int sx, int h, int w)
+{
+ ipriv_t *cci = (ipriv_t *) ip->priv;
+ view_t *v = ip->grf->g_view;
+ bmap_t *bm = v->bitmap;
+
+ if((sx == 0) && (w == ip->cols)) {
+ /* common case: clearing whole lines */
+ while (h--) {
+ int i;
+ u_char *ptr = cci->row_ptr[sy];
+ for(i = 0; i < ip->font.height; i++) {
+ bzero(ptr, bm->bytes_per_row);
+ ptr += bm->bytes_per_row;
+ }
+ sy++;
+ }
+ }
+ else {
+ /*
+ * clearing only part of a line
+ * XXX could be optimized MUCH better, but is it worth the
+ * trouble?
+ */
+
+ int i;
+ u_char *pls, *ple;
+
+ pls = cci->row_ptr[sy];
+ ple = pls + cci->column_offset[sx + w-1];
+ pls = pls + cci->column_offset[sx];
+
+ for(i = ((ip->font.height) * h)-1; i >= 0; i--) {
+ u_char *p = pls;
+ while(p <= ple)
+ *p++ = 0;
+ pls += bm->bytes_per_row;
+ ple += bm->bytes_per_row;
+ }
+ }
+}
+
+/* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT. */
+static void
+scroll8(ip, sy, sx, count, dir)
+register struct ite_softc *ip;
+register int sy;
+int dir, sx, count;
+{
+ bmap_t *bm = ip->grf->g_view->bitmap;
+ u_char *pl = ((ipriv_t *)ip->priv)->row_ptr[sy];
+
+ if(dir == SCROLL_UP) {
+ int dy = sy - count;
+ int height = ip->bottom_margin - sy + 1;
+ int i;
+
+ cursor32(ip, ERASE_CURSOR);
+ scrollbmap(bm, 0, dy*ip->font.height, bm->bytes_per_row >> 3,
+ (ip->bottom_margin-dy+1)*ip->font.height,
+ 0, -(count*ip->font.height));
+ }
+ else if(dir == SCROLL_DOWN) {
+ int dy = sy + count;
+ int height = ip->bottom_margin - dy + 1;
+ int i;
+
+ cursor32(ip, ERASE_CURSOR);
+ scrollbmap(bm, 0, sy*ip->font.height, bm->bytes_per_row >> 3,
+ (ip->bottom_margin-sy+1)*ip->font.height,
+ 0, count*ip->font.height);
+ }
+ else if(dir == SCROLL_RIGHT) {
+ int sofs = (ip->cols - count) * ip->font.width;
+ int dofs = (ip->cols) * ip->font.width;
+ int i, j;
+
+ cursor32(ip, ERASE_CURSOR);
+ for(j = ip->font.height-1; j >= 0; j--) {
+ int sofs2 = sofs, dofs2 = dofs;
+ for (i = (ip->cols - (sx + count))-1; i >= 0; i--) {
+ int t;
+ sofs2 -= ip->font.width;
+ dofs2 -= ip->font.width;
+ asm("bfextu %1@{%2:%3},%0" : "=d" (t)
+ : "a" (pl), "d" (sofs2), "d" (ip->font.width));
+ asm("bfins %3,%0@{%1:%2}" :
+ : "a" (pl), "d" (dofs2), "d" (ip->font.width),
+ "d" (t));
+ }
+ pl += bm->bytes_per_row;
+ }
+ }
+ else { /* SCROLL_LEFT */
+ int sofs = (sx) * ip->font.width;
+ int dofs = (sx - count) * ip->font.width;
+ int i, j;
+
+ cursor32(ip, ERASE_CURSOR);
+ for(j = ip->font.height-1; j >= 0; j--) {
+ int sofs2 = sofs, dofs2 = dofs;
+ for(i = (ip->cols - sx)-1; i >= 0; i--) {
+ int t;
+
+ asm("bfextu %1@{%2:%3},%0" : "=d" (t)
+ : "a" (pl), "d" (sofs2), "d" (ip->font.width));
+ asm("bfins %3,%0@{%1:%2}"
+ : : "a" (pl), "d" (dofs2),"d" (ip->font.width),
+ "d" (t));
+ sofs2 += ip->font.width;
+ dofs2 += ip->font.width;
+ }
+ pl += bm->bytes_per_row;
+ }
+ }
+}
+
+static void
+scrollbmap (bmap_t *bm, u_short x, u_short y, u_short width, u_short height, short dx, short dy)
+{
+ u_short depth = bm->depth;
+ u_short lwpr = bm->bytes_per_row >> 2;
+
+ if(dx) {
+ /* FIX: */ panic ("delta x not supported in scroll bitmap yet.");
+ }
+
+ if(dy == 0) {
+ return;
+ }
+ if(dy > 0) {
+ u_long *pl = (u_long *)bm->plane;
+ u_long *src_y = pl + (lwpr*y);
+ u_long *dest_y = pl + (lwpr*(y+dy));
+ u_long count = lwpr*(height-dy);
+ u_long *clr_y = src_y;
+ u_long clr_count = dest_y - src_y;
+ u_long bc, cbc;
+
+ src_y += count - 1;
+ dest_y += count - 1;
+
+ bc = count >> 4;
+ count &= 0xf;
+
+ while (bc--) {
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ *dest_y-- = *src_y--; *dest_y-- = *src_y--;
+ }
+ while (count--)
+ *dest_y-- = *src_y--;
+
+ cbc = clr_count >> 4;
+ clr_count &= 0xf;
+
+ while (cbc--) {
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ }
+ while(clr_count--)
+ *clr_y++ = 0;
+ }
+ else {
+ u_long *pl = (u_long *)bm->plane;
+ u_long *src_y = pl + (lwpr*(y-dy));
+ u_long *dest_y = pl + (lwpr*y);
+ long count = lwpr*(height + dy);
+ u_long *clr_y = dest_y + count;
+ u_long clr_count = src_y - dest_y;
+ u_long bc, cbc;
+
+ bc = count >> 4;
+ count &= 0xf;
+
+ while(bc--) {
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ *dest_y++ = *src_y++; *dest_y++ = *src_y++;
+ }
+ while(count--)
+ *dest_y++ = *src_y++;
+
+ cbc = clr_count >> 4;
+ clr_count &= 0xf;
+
+ while (cbc--) {
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
+ }
+ while (clr_count--)
+ *clr_y++ = 0;
+ }
+}
+#else
+#error Must be defined
+#endif /* NGRF */
diff --git a/sys/arch/atari/dev/iteioctl.h b/sys/arch/atari/dev/iteioctl.h
new file mode 100644
index 00000000000..1dbd2e9142b
--- /dev/null
+++ b/sys/arch/atari/dev/iteioctl.h
@@ -0,0 +1,82 @@
+/* $NetBSD: iteioctl.h,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * from: Utah $Hdr: iteioctl.h 1.1 90/07/09$
+ *
+ * @(#)iteioctl.h 7.2 (Berkeley) 11/4/90
+ */
+
+struct itewinsize {
+ int x; /* leftedge offset to the right */
+ int y; /* topedge offset down */
+ u_int width; /* width of ite display */
+ u_int height; /* height of ite display */
+ u_int depth; /* depth of ite display */
+};
+
+struct itebell {
+ u_int volume; /* volume of bell (0-64) */
+ u_int pitch; /* pitch of bell (10-2000) */
+ u_int msec; /* duration of bell */
+};
+#define MAXBVOLUME (63)
+#define MAXBPITCH (2000)
+#define MINBPITCH (10)
+#define MAXBTIME (5000) /* 5 seconds */
+
+struct iterepeat {
+ int start; /* number of 100/s before repeat start */
+ int next; /* number of 100/s before next repeat */
+};
+#define ITEMINREPEAT 5 /* mininum number of 100/s for key repeat */
+
+#define ITEIOCSKMAP _IOW('Z',0x70, struct kbdmap)
+#define ITEIOCGKMAP _IOR('Z',0x71, struct kbdmap)
+#define ITEIOCGWINSZ _IOR('Z',0x72, struct itewinsize)
+#define ITEIOCSWINSZ _IOW('Z',0x73, struct itewinsize)
+#define ITEIOCDSPWIN _IO('Z', 0x74)
+#define ITEIOCREMWIN _IO('Z', 0x75)
+#define ITEIOCGBELL _IOR('Z', 0x76, struct itebell)
+#define ITEIOCSBELL _IOW('Z', 0x77, struct itebell)
+#define ITEIOCGREPT _IOR('Z', 0x78, struct iterepeat)
+#define ITEIOCSREPT _IOW('Z', 0x79, struct iterepeat)
+
+
+#define ITESWITCH _IOW('Z',0x69, int) /* XXX */
+
diff --git a/sys/arch/atari/dev/itevar.h b/sys/arch/atari/dev/itevar.h
new file mode 100644
index 00000000000..74de492dc34
--- /dev/null
+++ b/sys/arch/atari/dev/itevar.h
@@ -0,0 +1,199 @@
+/* $NetBSD: itevar.h,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman (Atari modifications)
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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 _ITEVAR_H
+#define _ITEVAR_H
+
+#include <atari/dev/font.h>
+
+enum ite_arraymaxs {
+ MAX_ARGSIZE = 256,
+ MAX_TABS = 256,
+};
+
+enum ite_attr {
+ ATTR_NOR = 0,
+ ATTR_INV = 1,
+ ATTR_UL = 2,
+ ATTR_BOLD = 4,
+ ATTR_BLINK = 8,
+ ATTR_ALL = 16-1,
+
+ ATTR_KEYPAD = 0x80 /* XXX */
+};
+
+struct ite_softc {
+ struct device device; /* _Must_ be first */
+ char argbuf[MAX_ARGSIZE];
+ struct grf_softc *grf; /* XXX */
+ char *ap;
+ struct tty *tp;
+ void *priv;
+ font_info font;
+ u_char *tabs;
+ int flags;
+ short cursorx;
+ short cursory;
+ short rows;
+ short cols;
+ u_char *cursor;
+ char imode;
+ u_char escape;
+ u_char cursor_opt;
+ u_char key_repeat;
+ char GL;
+ char GR;
+ char G0;
+ char G1;
+ char G2;
+ char G3;
+ char linefeed_newline;
+ char auto_wrap;
+ char cursor_appmode;
+ char keypad_appmode;
+ short top_margin;
+ short bottom_margin;
+ short inside_margins;
+ short eightbit_C1;
+ short emul_level;
+ enum ite_attr attribute;
+ enum ite_attr save_attribute;
+ int curx;
+ int save_curx;
+ int cury;
+ int save_cury;
+};
+
+enum ite_flags {
+ ITE_ALIVE = 0x1, /* grf layer is configed */
+ ITE_ISCONS = 0x2, /* ite is acting console. */
+ ITE_INITED = 0x4, /* ite has been inited. */
+ ITE_ISOPEN = 0x8, /* ite has been opened */
+ ITE_INGRF = 0x10, /* ite is in graphics mode */
+ ITE_ACTIVE = 0x20, /* ite is an active terminal */
+};
+
+enum ite_replrules {
+ RR_CLEAR = 0,
+ RR_COPY = 0x3,
+ RR_XOR = 0x6,
+ RR_COYINVERTED = 0xC
+};
+
+enum ite_scrolldir {
+ SCROLL_UP = 1,
+ SCROLL_DOWN,
+ SCROLL_LEFT,
+ SCROLL_RIGHT,
+};
+
+enum ite_cursact {
+ DRAW_CURSOR = 5,
+ ERASE_CURSOR,
+ MOVE_CURSOR,
+ START_CURSOROPT,
+ END_CURSOROPT
+};
+
+enum ite_special_keycodes {
+ KBD_LEFT_SHIFT = 0x2a,
+ KBD_RIGHT_SHIFT = 0x36,
+ KBD_CAPS_LOCK = 0x3a,
+ KBD_CTRL = 0x1d,
+ KBD_ALT = 0x38
+};
+
+enum ite_modifiers {
+ KBD_MOD_LSHIFT = 0x01,
+ KBD_MOD_RSHIFT = 0x02,
+ KBD_MOD_CTRL = 0x04,
+ KBD_MOD_ALT = 0x08,
+ KBD_MOD_CAPS = 0x10,
+ KBD_MOD_SHIFT = (KBD_MOD_LSHIFT | KBD_MOD_RSHIFT)
+};
+
+enum caller {
+ ITEFILT_TTY,
+ ITEFILT_CONSOLE,
+ ITEFILT_REPEATER
+};
+
+enum emul_level {
+ EMUL_VT100 = 1,
+ EMUL_VT300_8,
+ EMUL_VT300_7
+};
+
+enum ite_max_getsize { ITEBURST = 64 };
+
+enum tab_size { TABSIZE = 8 };
+#define TABEND(u) (ite_tty[u]->t_windsize.ws_col - TABSIZE) /* XXX */
+
+#define set_attr(ip, attr) ((ip)->attribute |= (attr))
+#define clr_attr(ip, attr) ((ip)->attribute &= ~(attr))
+#define attrloc(ip, y, x) 0
+#define attrclr(ip, sy, sx, h, w)
+#define attrmov(ip, sy, sx, dy, dx, h, w)
+#define attrtest(ip, attr) 0
+#define attrset(ip, attr)
+
+struct proc;
+struct consdev;
+struct termios;
+
+/* console related function */
+void ite_cnprobe __P((struct consdev *));
+void ite_cninit __P((struct consdev *));
+int ite_cngetc __P((dev_t));
+void ite_cnputc __P((dev_t, int));
+void ite_cnfinish __P((struct ite_softc *));
+
+/* standard ite device entry points. */
+void iteinit __P((dev_t));
+int iteopen __P((dev_t, int, int, struct proc *));
+int iteclose __P((dev_t, int, int, struct proc *));
+int iteread __P((dev_t, struct uio *, int));
+int itewrite __P((dev_t, struct uio *, int));
+int iteioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+void itestart __P((struct tty *));
+
+/* ite functions */
+int ite_on __P((dev_t, int));
+int ite_off __P((dev_t, int));
+void ite_reinit __P((dev_t));
+int ite_param __P((struct tty *, struct termios *));
+void ite_reset __P((struct ite_softc *));
+int ite_cnfilter __P((u_int, enum caller));
+void ite_filter __P((u_int ,enum caller));
+
+#endif /* _ITEVAR_H */
diff --git a/sys/arch/atari/dev/kbd.c b/sys/arch/atari/dev/kbd.c
new file mode 100644
index 00000000000..65f90e33194
--- /dev/null
+++ b/sys/arch/atari/dev/kbd.c
@@ -0,0 +1,353 @@
+/* $NetBSD: kbd.c,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman
+ * Copyright (c) 1982, 1986, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <dev/cons.h>
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+#include <machine/acia.h>
+#include <machine/video.h>
+#include <atari/dev/itevar.h>
+#include <atari/dev/kbdreg.h>
+#include <atari/dev/event_var.h>
+#include <atari/dev/vuid_event.h>
+
+/*
+ * The ringbuffer is the interface between the hard and soft interrupt handler.
+ * The hard interrupt runs straight from the MFP interrupt.
+ */
+#define KBD_RING_SIZE 16 /* Size of the ring buffer, must be power of 2 */
+#define KBD_RING_MASK 15 /* Modulo mask for above */
+
+static u_char kbd_ring[KBD_RING_SIZE];
+static volatile u_int kbd_rbput = 0; /* 'put' index */
+static u_int kbd_rbget = 0; /* 'get' index */
+static u_char kbd_soft = 0; /* 1: Softint has been scheduled*/
+
+struct kbd_softc {
+ int k_event_mode; /* if 1, collect events, */
+ /* else pass to ite */
+ struct evvar k_events; /* event queue state */
+};
+
+static struct kbd_softc kbd_softc;
+
+static void kbdsoft __P((void));
+static void kbdattach __P((struct device *, struct device *, void *));
+static int kbdmatch __P((struct device *, struct cfdata *, void *));
+
+struct cfdriver kbdcd = {
+ NULL, "kbd", (cfmatch_t)kbdmatch, kbdattach,
+ DV_DULL, sizeof(struct device), NULL, 0 };
+
+
+/*ARGSUSED*/
+static int
+kbdmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(!strcmp((char *)auxp, "kbd"))
+ return(1);
+ return(0);
+}
+
+/*ARGSUSED*/
+static void
+kbdattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ printf("\n");
+}
+
+/* definitions for atari keyboard encoding. */
+#define KEY_CODE(c) ((c) & 0x7f)
+#define KEY_UP(c) ((c) & 0x80)
+
+void
+kbdenable()
+{
+ int s, code;
+
+ s = spltty();
+ /*
+ * Initialize ACIA port
+ */
+ code = KBD->ac_da; /* Clear error conditions */
+
+ /* divide by 16, 8 data, 1 stop, no parity, enable interrupts */
+ KBD->ac_cs = KBD_INIT | A_RXINT;
+#if 0 /* XXX Turn off mouse??? */
+ KBD->ac_da = 0x12;
+#endif
+
+ /*
+ * Enable interrupts from MFP
+ */
+ MFP->mf_iprb &= ~IB_AINT;
+ MFP->mf_ierb |= IB_AINT;
+ MFP->mf_imrb |= IB_AINT;
+ code = KBD->ac_da; /* Clear error conditions */
+
+ kbd_softc.k_event_mode = 0;
+ kbd_softc.k_events.ev_io = 0;
+ splx(s);
+}
+
+int kbdopen(dev_t dev, int flags, int mode, struct proc *p)
+{
+ int s, error;
+
+ if(kbd_softc.k_events.ev_io)
+ return EBUSY;
+
+ kbd_softc.k_events.ev_io = p;
+ ev_init(&kbd_softc.k_events);
+ return (0);
+}
+
+int
+kbdclose(dev_t dev, int flags, int mode, struct proc *p)
+{
+ /* Turn off event mode, dump the queue */
+ kbd_softc.k_event_mode = 0;
+ ev_fini(&kbd_softc.k_events);
+ kbd_softc.k_events.ev_io = NULL;
+ return (0);
+}
+
+int
+kbdread(dev_t dev, struct uio *uio, int flags)
+{
+ return ev_read(&kbd_softc.k_events, uio, flags);
+}
+
+/* this routine should not exist, but is convenient to write here for now */
+int kbdwrite(dev_t dev, struct uio *uio, int flags)
+{
+ return EOPNOTSUPP;
+}
+
+int
+kbdioctl(dev_t dev,u_long cmd,register caddr_t data,int flag,struct proc *p)
+{
+ register struct kbd_softc *k = &kbd_softc;
+
+ switch (cmd) {
+ case KIOCTRANS:
+ if(*(int *)data == TR_UNTRANS_EVENT)
+ return 0;
+ break;
+
+ case KIOCGTRANS:
+ /*
+ * Get translation mode
+ */
+ *(int *)data = TR_UNTRANS_EVENT;
+ return 0;
+
+ case KIOCSDIRECT:
+ k->k_event_mode = *(int *)data;
+ return 0;
+
+ case FIONBIO: /* we will remove this someday (soon???) */
+ return 0;
+
+ case FIOASYNC:
+ k->k_events.ev_async = *(int *)data != 0;
+ return 0;
+
+ case TIOCSPGRP:
+ if(*(int *)data != k->k_events.ev_io->p_pgid)
+ return EPERM;
+ return 0;
+
+ default:
+ return ENOTTY;
+ }
+
+ /*
+ * We identified the ioctl, but we do not handle it.
+ */
+ return EOPNOTSUPP; /* misuse, but what the heck */
+}
+
+int
+kbdselect (dev_t dev, int rw, struct proc *p)
+{
+ return ev_select (&kbd_softc.k_events, rw, p);
+}
+
+/*
+ * Keyboard interrupt handler called straight from MFP.
+ */
+int
+kbdintr(sr)
+int sr; /* sr at time of interrupt */
+{
+ int code;
+
+ /*
+ * There may be multiple keys available. Read them all.
+ */
+ while(KBD->ac_cs & (A_IRQ|A_RXRDY)) {
+ if(KBD->ac_cs & (A_OE|A_PE)) {
+ code = KBD->ac_da; /* Silently ignore overruns */
+ continue;
+ }
+ kbd_ring[kbd_rbput++ & KBD_RING_MASK] = KBD->ac_da;
+ }
+ if(!BASEPRI(sr)) {
+ if(!kbd_soft++)
+ add_sicallback(kbdsoft, 0, 0);
+ }
+ else {
+ spl1();
+ kbdsoft();
+ }
+}
+
+/*
+ * Keyboard soft interrupt handler
+ */
+void
+kbdsoft()
+{
+ int s;
+ u_char code;
+ struct kbd_softc *k = &kbd_softc;
+ struct firm_event *fe;
+ int put;
+ int n, get;
+
+ kbd_soft = 0;
+ get = kbd_rbget;
+
+ for(;;) {
+ n = kbd_rbput;
+ if(get == n) /* We're done */
+ break;
+ n -= get;
+ if(n > KBD_RING_SIZE) { /* Ring buffer overflow */
+ get += n - KBD_RING_SIZE;
+ n = KBD_RING_SIZE;
+ }
+ while(--n >= 0) {
+ code = kbd_ring[get++ & KBD_RING_MASK];
+
+ /*
+ * if not in event mode, deliver straight to ite to
+ * process key stroke
+ */
+ if(!k->k_event_mode) {
+ /* Gets to spltty() by itself */
+ ite_filter(code, ITEFILT_TTY);
+ continue;
+ }
+
+ /*
+ * Keyboard is generating events. Turn this keystroke
+ * into an event and put it in the queue. If the queue
+ * is full, the keystroke is lost (sorry!).
+ */
+ s = spltty();
+ put = k->k_events.ev_put;
+ fe = &k->k_events.ev_q[put];
+ put = (put + 1) % EV_QSIZE;
+ if(put == k->k_events.ev_get) {
+ log(LOG_WARNING,
+ "keyboard event queue overflow\n");
+ splx(s);
+ continue;
+ }
+ fe->id = KEY_CODE(code);
+ fe->value = KEY_UP(code) ? VKEY_UP : VKEY_DOWN;
+ fe->time = time;
+ k->k_events.ev_put = put;
+ EV_WAKEUP(&k->k_events);
+ splx(s);
+ }
+ kbd_rbget = get;
+ }
+}
+
+static char sound[] = {
+ 0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00,
+ 0xF8,0x10,0x10,0x10,0x00,0x20,0x03
+};
+
+int
+kbdbell()
+{
+ register int i, sps;
+
+ sps = spltty();
+ for(i = 0; i < sizeof(sound); i++) {
+ SOUND->sd_selr = i;
+ SOUND->sd_wdat = sound[i];
+ }
+ splx(sps);
+}
+
+int
+kbdgetcn()
+{
+ u_char code;
+ int s = spltty();
+
+ MFP->mf_imrb &= ~IB_AINT;
+ while(!(KBD->ac_cs & A_IRQ))
+ ; /* Wait for key */
+
+ MFP->mf_iprb &= ~IB_AINT;
+ MFP->mf_imrb |= IB_AINT;
+
+ code = KBD->ac_da;
+ splx (s);
+ return code;
+}
diff --git a/sys/arch/atari/dev/kbdmap.c b/sys/arch/atari/dev/kbdmap.c
new file mode 100644
index 00000000000..c5ac79d3aeb
--- /dev/null
+++ b/sys/arch/atari/dev/kbdmap.c
@@ -0,0 +1,208 @@
+/* $NetBSD: kbdmap.c,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 <atari/dev/kbdmap.h>
+
+/* define a default keymap. This can be changed by keyboard ioctl's
+ (later at least..) */
+
+/* mode shortcuts: */
+#define S KBD_MODE_STRING
+#define C KBD_MODE_CAPS
+#define K KBD_MODE_KPAD
+
+struct kbdmap kbdmap;
+struct kbdmap ascii_kbdmap = {
+ /* normal map */
+ {
+/* 0x00 */ 0, 0, 0, ESC, 0, '1', 0, '2',
+/* 0x04 */ 0, '3', 0, '4', 0, '5', 0, '6',
+/* 0x08 */ 0, '7', 0, '8', 0, '9', 0, '0',
+/* 0x0c */ 0, '-', 0, '=', 0, '\b', 0, '\t',
+/* 0x10 */ C, 'q', C, 'w', C, 'e', C, 'r',
+/* 0x14 */ C, 't', C, 'y', C, 'u', C, 'i',
+/* 0x18 */ C, 'o', C, 'p', 0, '[', 0, ']',
+/* 0x1c */ 0, '\r', 0, 0, C, 'a', C, 's',
+/* 0x20 */ C, 'd', C, 'f', C, 'g', C, 'h',
+/* 0x24 */ C, 'j', C, 'k', C, 'l', 0, ';',
+#ifdef US_KBD
+/* 0x28 */ 0, '\'', 0, '`', 0, 0, 0, '\\',
+#else
+/* 0x28 */ 0, '\'', 0, '`', 0, 0, 0, '#',
+#endif
+/* 0x2c */ C, 'z', C, 'x', C, 'c', C, 'v',
+/* 0x30 */ C, 'b', C, 'n', C, 'm', 0, ',',
+/* 0x34 */ 0, '.', 0, '/', 0, 0, 0, 0,
+/* 0x38 */ 0, 0, 0, ' ', 0, 0, S, 0x10,
+/* 0x3c */ S, 0x15, S, 0x1A, S, 0x1F, S, 0x24,
+/* 0x40 */ S, 0x29, S, 0x2E, S, 0x33, S, 0x38,
+/* 0x44 */ S, 0x3D, 0, 0, 0, 0, 0, 0,
+/* 0x48 */ S, 0x00, 0, 0, 0, '-', S, 0x0C,
+/* 0x4c */ 0, 0, S, 0x08, 0, '+', 0, 0,
+/* 0x50 */ S, 0x04, 0, 0, 0, 0, 0, DEL,
+/* 0x54 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x5c */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x60 */
+#ifdef US_KBD
+/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, '(',
+#else
+/* 0x60 */ 0, '\\', 0, 0, 0, 0, 0, '(',
+#endif
+/* 0x64 */ 0, ')', 0, '/', 0, '*', K, '7',
+/* 0x68 */ K, '8', K, '9', K, '4', K, '5',
+/* 0x6c */ K, '6', K, '1', K, '2', K, '3',
+/* 0x70 */ K, '0', K, '.', K, '\r', 0, 0,
+/* 0x74 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x7c */ 0, 0, 0, 0, 0, 0, 0, 0
+},
+ /* shifted map */
+ {
+#ifdef US_KBD
+/* 0x00 */ 0, 0, 0, ESC, 0, '!', 0, '@',
+#else
+/* 0x00 */ 0, 0, 0, ESC, 0, '!', 0, '"',
+#endif
+/* 0x04 */ 0, '#', 0, '$', 0, '%', 0, '^',
+/* 0x08 */ 0, '&', 0, '*', 0, '(', 0, ')',
+/* 0x0c */ 0, '_', 0, '+', 0, '\b', 0, '\t',
+/* 0x10 */ C, 'Q', C, 'W', C, 'E', C, 'R',
+/* 0x14 */ C, 'T', C, 'Y', C, 'U', C, 'I',
+/* 0x18 */ C, 'O', C, 'P', 0, '{', 0, '}',
+/* 0x1c */ 0, '\r', 0, 0, C, 'A', C, 'S',
+/* 0x20 */ C, 'D', C, 'F', C, 'G', C, 'H',
+/* 0x24 */ C, 'J', C, 'K', C, 'L', 0, ':',
+#ifdef US_KBD
+/* 0x28 */ 0, '"', 0, '~', 0, 0, 0, '|',
+#else
+/* 0x28 */ 0, '@', 0, '_', 0, 0, 0, '~',
+#endif
+/* 0x2c */ C, 'Z', C, 'X', C, 'C', C, 'V',
+/* 0x30 */ C, 'B', C, 'N', C, 'M', 0, '<',
+/* 0x34 */ 0, '>', 0, '?', 0, 0, 0, 0,
+/* 0x38 */ 0, 0, 0, ' ', 0, 0, S, 0x5d,
+/* 0x3c */ S, 0x63, S, 0x69, S, 0x6F, S, 0x75,
+/* 0x40 */ S, 0x7b, S, 0x81, S, 0x87, S, 0x8d,
+/* 0x44 */ S, 0x93, 0, 0, 0, 0, 0, 0,
+/* 0x48 */ S, 0x47, 0, 0, 0, '-', S, 0x57,
+/* 0x4c */ 0, 0, S, 0x51, 0, '+', 0, 0,
+/* 0x50 */ S, 0x4c, 0, 0, 0, 0, 0, DEL,
+/* 0x54 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x5c */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x60 */
+#ifdef US_KBD
+/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, '(',
+#else
+/* 0x60 */ 0, '|', 0, 0, 0, 0, 0, '(',
+#endif
+/* 0x64 */ 0, ')', 0, '/', 0, '*', K, '7',
+/* 0x68 */ K, '8', K, '9', K, '4', K, '5',
+/* 0x6c */ K, '6', K, '1', K, '2', K, '3',
+/* 0x70 */ K, '0', K, '.', K, '\r', 0, 0,
+/* 0x74 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x7c */ 0, 0, 0, 0, 0, 0, 0, 0
+ },
+
+ /* alt map FIXME: No altmap yet.. */
+ {
+ 0, 0
+ },
+
+ /* shift alt map FIXME: No shift altmap yet... */
+ {
+ 0, 0
+ },
+
+ {
+ /* string table. If there's a better way to get the offsets into the
+ above table, please tell me..
+
+ NOTE: save yourself and others a lot of grief by *not* using
+ CSI == 0x9b, using the two-character sequence gives
+ much less trouble, especially in GNU-Emacs.. */
+
+ 3, ESC, '[', 'A', /* 0x00: CRSR UP */
+ 3, ESC, '[', 'B', /* 0x04: CRSR DOWN */
+ 3, ESC, '[', 'C', /* 0x08: CRSR RIGHT */
+ 3, ESC, '[', 'D', /* 0x0C: CRSR LEFT */
+ 4, ESC, '[', '0', '~', /* 0x10: F1 */
+ 4, ESC, '[', '1', '~', /* 0x15: F2 */
+ 4, ESC, '[', '2', '~', /* 0x1A: F3 */
+ 4, ESC, '[', '3', '~', /* 0x1F: F4 */
+ 4, ESC, '[', '4', '~', /* 0x24: F5 */
+ 4, ESC, '[', '5', '~', /* 0x29: F6 */
+ 4, ESC, '[', '6', '~', /* 0x2E: F7 */
+ 4, ESC, '[', '7', '~', /* 0x33: F8 */
+ 4, ESC, '[', '8', '~', /* 0x38: F9 */
+ 4, ESC, '[', '9', '~', /* 0x3D: F10 */
+ 4, ESC, '[', '?', '~', /* 0x42: HELP */
+
+ 4, ESC, '[', 'T', '~', /* 0x47: shift CRSR UP */
+ 4, ESC, '[', 'S', '~', /* 0x4C: shift CRSR DOWN */
+ 5, ESC, '[', ' ', '@', '~', /* 0x51: shift CRSR RIGHT */
+ 5, ESC, '[', ' ', 'A', '~', /* 0x57: shift CRSR LEFT */
+ 5, ESC, '[', '1', '0', '~', /* 0x5D: shift F1 */
+ 5, ESC, '[', '1', '1', '~', /* 0x63: shift F2 */
+ 5, ESC, '[', '1', '2', '~', /* 0x69: shift F3 */
+ 5, ESC, '[', '1', '3', '~', /* 0x6F: shift F4 */
+ 5, ESC, '[', '1', '4', '~', /* 0x75: shift F5 */
+ 5, ESC, '[', '1', '5', '~', /* 0x7B: shift F6 */
+ 5, ESC, '[', '1', '6', '~', /* 0x81: shift F7 */
+ 5, ESC, '[', '1', '7', '~', /* 0x87: shift F8 */
+ 5, ESC, '[', '1', '8', '~', /* 0x8D: shift F9 */
+ 5, ESC, '[', '1', '9', '~', /* 0x93: shift F10 */
+ 3, ESC, '[', 'Z', /* 0x99: shift TAB */
+ 2, ESC, '[', /* 0x9d: alt ESC == CSI */
+ },
+};
+
+unsigned char acctable[KBD_NUM_ACC][64] = {
+ { "@ÀBCDÈFGHÌJKLMNÒPQRSTÙVWXYZ[\\]^_"
+ "`àbcdèfghìjklmnòpqrstùvwxyz{|}~\177"}, /* KBD_ACC_GRAVE */
+
+ { "@ÁBCDÉFGHÍJKLMNÓPQRSTÚVWXYZ[\\]^_"
+ "`ábcdéfghíjklmnópqrstúvwxyz{|}~\177"}, /* KBD_ACC_ACUTE */
+
+ { "@ÂBCDÊFGHÎJKLMNÔPQRSTÛVWXYZ[\\]^_"
+ "`âbcdêfghîjklmnôpqrstûvwxyz{|}~\177"}, /* KBD_ACC_CIRC */
+
+ { "@ÃBCDEFGHIJKLMÑÕPQRSTUVWXYZ[\\]^_"
+ "`ãbcdefghijklmñÕpqrstuvwxyz{|}~\177"}, /* KBD_ACC_TILDE */
+
+ { "@ÄBCDËFGHÏJKLMNÖPQRSTÜVWXYZ[\\]^_"
+ "`äbcdëfghïjklmnöpqrstüvwxyz{|}~\177"}, /* KBD_ACC_DIER */
+};
+
+
diff --git a/sys/arch/atari/dev/kbdmap.h b/sys/arch/atari/dev/kbdmap.h
new file mode 100644
index 00000000000..d9192fed90c
--- /dev/null
+++ b/sys/arch/atari/dev/kbdmap.h
@@ -0,0 +1,144 @@
+/* $NetBSD: kbdmap.h,v 1.1.1.1 1995/03/26 07:12:11 leo Exp $ */
+
+/*
+ * Copyright (c) 1993 Markus Wild
+ * 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 Markus Wild.
+ * 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 NUL 0
+#define SOH 1
+#define STX 2
+#define ETX 3
+#define EOT 4
+#define ENQ 5
+#define ACK 6
+#define BEL 7
+#define BS 8
+#define HT 9
+#define LF 10
+#define VT 11
+#define FF 12
+#define CR 13
+#define SO 14
+#define SI 15
+#define DLE 16
+#define DC1 17
+#define DC2 18
+#define DC3 19
+#define DC4 20
+#define NAK 21
+#define SYN 22
+#define ETB 23
+#define CAN 24
+#define EM 25
+#define SUB 26
+#define ESC 27
+#define FS 28
+#define GS 29
+#define RS 30
+#define US 31
+#define DEL 127
+#define IND 132
+#define NEL 133
+#define SSA 134
+#define ESA 135
+#define HTS 136
+#define HTJ 137
+#define VTS 138
+#define PLD 139
+#define PLU 140
+#define RI 141
+#define SS2 142
+#define SS3 143
+#define DCS 144
+#define PU1 145
+#define PU2 146
+#define STS 147
+#define CCH 148
+#define MW 149
+#define SPA 150
+#define EPA 151
+#define CSI 155
+#define ST 156
+#define OSC 157
+#define PM 158
+#define APC 159
+
+
+/*
+ * A total of 0x80 scancode are defined for the atari keyboard.
+ */
+#define KBD_NUM_KEYS 0x80
+
+/* size of string table */
+#define KBD_STRTAB_SIZE 255
+
+/* for dead keys, index into acctable */
+/* FIXME: What the hell are dead keys?? */
+#define KBD_ACC_GRAVE 0
+#define KBD_ACC_ACUTE 1
+#define KBD_ACC_CIRC 2
+#define KBD_ACC_TILDE 3
+#define KBD_ACC_DIER 4
+#define KBD_NUM_ACC 5
+
+
+struct key {
+ unsigned char mode; /* see possible values below */
+ unsigned char code;
+};
+
+#define KBD_MODE_STRING (0x01) /* code is index into strings[] */
+#define KBD_MODE_DEAD (0x02) /* acc-index in upper nibble, code = plain acc */
+#define KBD_MODE_CAPS (0x04) /* key is capsable. Only in non-shifted maps */
+#define KBD_MODE_KPAD (0x08) /* key is on keypad */
+#define KBD_MODE_GRAVE (KBD_ACC_GRAVE << 4)
+#define KBD_MODE_ACUTE (KBD_ACC_ACUTE << 4)
+#define KBD_MODE_CIRC (KBD_ACC_CIRC << 4)
+#define KBD_MODE_TILDE (KBD_ACC_TILDE << 4)
+#define KBD_MODE_DIER (KBD_ACC_DIER << 4)
+#define KBD_MODE_ACCENT(m) ((m) >> 4) /* get accent from mode */
+#define KBD_MODE_ACCMASK (0xf0)
+
+#define KBD_SCANCODE(code) (code & 0x7f)
+#define KBD_RELEASED(code) (code & 0x80 ? 1 : 0)
+
+struct kbdmap {
+ struct key keys[KBD_NUM_KEYS],
+ shift_keys[KBD_NUM_KEYS],
+ alt_keys[KBD_NUM_KEYS],
+ alt_shift_keys[KBD_NUM_KEYS];
+ unsigned char strings[KBD_STRTAB_SIZE];
+};
+
+
+#ifdef KERNEL
+/* XXX: ITE interface */
+extern struct kbdmap kbdmap, ascii_kbdmap;
+extern unsigned char acctable[KBD_NUM_ACC][64];
+#endif
diff --git a/sys/arch/atari/dev/kbdreg.h b/sys/arch/atari/dev/kbdreg.h
new file mode 100644
index 00000000000..84301c4fda2
--- /dev/null
+++ b/sys/arch/atari/dev/kbdreg.h
@@ -0,0 +1,54 @@
+/* $NetBSD: kbdreg.h,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)kbio.h 8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: kbio.h,v 1.4 92/11/26 01:16:32 torek Exp (LBL)
+ */
+
+#define KIOCTRANS _IOW('k', 0, int) /* set translation mode */
+ /* (we only accept TR_UNTRANS_EVENT) */
+#define KIOCGTRANS _IOR('k', 5, int) /* get translation mode */
+#define KIOCSDIRECT _IOW('k', 10, int) /* keys to console? */
+
+#define TR_UNTRANS_EVENT 3
diff --git a/sys/arch/atari/dev/ncr5380.c b/sys/arch/atari/dev/ncr5380.c
new file mode 100644
index 00000000000..68468249dea
--- /dev/null
+++ b/sys/arch/atari/dev/ncr5380.c
@@ -0,0 +1,1936 @@
+/* $NetBSD: ncr5380.c,v 1.1.1.1 1995/03/26 07:12:10 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/buf.h>
+#include <scsi/scsi_all.h>
+#include <scsi/scsi_message.h>
+#include <scsi/scsiconf.h>
+#include <machine/iomap.h>
+#include <machine/mfp.h>
+#include <atari/dev/ncr5380reg.h>
+
+/*
+ * This is crap, but because the interrupts now run at MFP spl-level (6),
+ * splbio() is not enough at some places. The code should be checked to
+ * find out where splhigh() is needed and where splbio() should be used.
+ * Now that I use this interrupt sceme, the spl values are fake!
+ */
+#undef splbio()
+#define splbio() splhigh()
+
+/*
+ * SCSI completion status codes, should move to sys/scsi/????
+ */
+#define SCSMASK 0x1e /* status code mask */
+#define SCSGOOD 0x00 /* good status */
+#define SCSCHKC 0x02 /* check condition */
+#define SCSBUSY 0x08 /* busy status */
+#define SCSCMET 0x04 /* condition met / good */
+
+/********************************************************************/
+
+#define NREQ 18 /* Size of issue queue */
+#define AUTO_SENSE 1 /* Automatically issue a request-sense */
+
+#undef DBG_SEL /* Show the selection process */
+#undef DBG_REQ /* Show enqueued/ready requests */
+#undef DBG_NOWRITE /* Do not allow writes to the targets */
+#undef DBG_PIO /* Show the polled-I/O process */
+#undef DBG_INF /* Show information transfer process */
+#undef DBG_NOSTATIC /* No static functions, all in DDB trace*/
+#define DBG_PID /* Keep track of driver */
+#define REAL_DMA /* Use DMA if sensible */
+#define REAL_DMA_POLL 0 /* 1: Poll for end of DMA-transfer */
+#undef NO_TTRAM_DMA /* Do not use DMA to TT-ram. This */
+ /* fails on older atari's */
+
+#ifdef DBG_NOSTATIC
+# define static
+#endif
+#ifdef DBG_SEL
+# define DBG_SELPRINT(a,b) printf(a,b)
+#else
+# define DBG_SELPRINT(a,b)
+#endif
+#ifdef DBG_PIO
+# define DBG_PIOPRINT(a,b,c) printf(a,b,c)
+#else
+# define DBG_PIOPRINT(a,b,c)
+#endif
+#ifdef DBG_INF
+# define DBG_INFPRINT(a,b,c) a(b,c)
+#else
+# define DBG_INFPRINT(a,b,c)
+#endif
+#ifdef DBG_PID
+ static char *last_hit = NULL;
+# define PID(a) last_hit = a
+#else
+# define PID(a)
+#endif
+
+/*
+ * Return values of check_intr()
+ */
+#define INTR_SPURIOUS 0
+#define INTR_RESEL 2
+#define INTR_DMA 3
+
+/*
+ * Set bit for target when parity checking must be disabled.
+ * My (LWP) Maxtor 7245S seems to generate parity errors on about 50%
+ * of all transfers while the data is correct!?
+ */
+u_char ncr5380_no_parchk = 0;
+
+/*
+ * This is the default sense-command we send.
+ */
+static u_char sense_cmd[] = {
+ REQUEST_SENSE, 0, 0, 0, sizeof(struct scsi_sense), 0
+};
+
+/*
+ * True if the main co-routine is running
+ */
+static volatile int main_running = 0;
+
+/*
+ * True if callback to softint scheduled.
+ */
+static volatile int callback_scheduled = 0;
+
+/*
+ * Mask of targets selected
+ */
+u_char busy;
+
+struct ncr_softc {
+ struct device sc_dev;
+ struct scsi_link sc_link;
+};
+
+static void ncr5380_minphys(struct buf *bp);
+static int ncr5380_scsi_cmd(struct scsi_xfer *xs);
+static int ncr5380_show_scsi_cmd(struct scsi_xfer *xs);
+
+struct scsi_adapter ncr5380_switch = {
+ ncr5380_scsi_cmd, /* scsi_cmd() */
+ ncr5380_minphys, /* scsi_minphys() */
+ 0, /* open_target_lu() */
+ 0 /* close_target_lu() */
+};
+
+struct scsi_device ncr5380_dev = {
+ NULL, /* use default error handler */
+ NULL, /* do not have a start functio */
+ NULL, /* have no async handler */
+ NULL /* Use default done routine */
+};
+
+/*
+ * Max. number of dma-chains per request
+ */
+#define MAXDMAIO (MAXPHYS/NBPG + 1)
+
+/*
+ * Some requests are not contiguous in physical memory. We need to break them
+ * up into contiguous parts for DMA.
+ */
+struct dma_chain {
+ u_int dm_count;
+ u_long dm_addr;
+};
+
+/*
+ * Define our issue, free and disconnect queue's.
+ */
+typedef struct req_q {
+ struct req_q *next; /* next in free, issue or discon queue */
+ struct req_q *link; /* next linked command to execute */
+ struct scsi_xfer *xs; /* request from high-level driver */
+ u_char dr_flag; /* driver state */
+ u_char phase; /* current SCSI phase */
+ u_char msgout; /* message to send when requested */
+ u_char targ_id; /* target for command */
+ u_char status; /* returned status byte */
+ u_char message; /* returned message byte */
+ struct dma_chain dm_chain[MAXDMAIO];
+ struct dma_chain *dm_cur; /* current dma-request */
+ struct dma_chain *dm_last; /* last dma-request */
+ long xdata_len; /* length of transfer */
+ u_char *xdata_ptr; /* physical address of transfer */
+ struct scsi_generic xcmd; /* command to execute */
+} SC_REQ;
+
+/*
+ * Values for dr_flag:
+ */
+#define DRIVER_IN_DMA 1 /* Non-polled DMA activated */
+#define DRIVER_AUTOSEN 2 /* Doing automatic sense */
+#define DRIVER_NOINT 4 /* We are booting: no interrupts */
+#define DRIVER_DMAOK 8 /* DMA can be used on this request */
+
+
+static SC_REQ req_queue[NREQ];
+static SC_REQ *free_head = NULL; /* Free request structures */
+static SC_REQ *issue_q = NULL; /* Commands waiting to be issued*/
+static SC_REQ *discon_q = NULL; /* Commands disconnected */
+static SC_REQ *connected = NULL; /* Command currently connected */
+
+/*
+ * Function decls:
+ */
+static int transfer_pio __P((u_char *, u_char *, u_long *));
+static int wait_req_true __P((void));
+static int wait_req_false __P((void));
+static int scsi_select __P((SC_REQ *, int));
+static int handle_message __P((SC_REQ *, u_int));
+static int information_transfer __P((void));
+static void reselect __P((void));
+static int dma_ready __P((int, int));
+static void transfer_dma __P((SC_REQ *, u_int, int));
+static int check_autosense __P((SC_REQ *, int));
+static int reach_msg_out __P((u_long));
+static void timer __P((void));
+static int check_intr __P((void));
+static void scsi_reset __P((void));
+static void scsi_main __P((void));
+static int scsi_dmaok __P((SC_REQ *));
+static void run_main __P((void));
+
+static void show_request __P((SC_REQ *, char *));
+static void show_phase __P((SC_REQ *, int));
+static void show_signals __P((void));
+
+/*
+ * Inline functions:
+ */
+extern __inline__ void scsi_ienable()
+{
+ MFP2->mf_ierb |= IB_SCDM;
+ MFP2->mf_iera |= IA_SCSI;
+ MFP2->mf_imra |= IA_SCSI;
+}
+
+extern __inline__ scsi_idisable()
+{
+ int sps = splbio();
+ MFP2->mf_ierb &= ~IB_SCDM;
+ MFP2->mf_iera &= ~IA_SCSI;
+ splx(sps);
+}
+
+/*
+ * Determine the size of a SCSI command.
+ */
+extern __inline__ int command_size(opcode)
+u_char opcode;
+{
+ switch((opcode >> 4) & 0xf) {
+ case 0:
+ case 1:
+ return(6);
+ case 2:
+ case 3:
+ return(10);
+ }
+ return(12);
+}
+
+
+/*
+ * Wait for request-line to become active. When it doesn't return 0.
+ * Otherwise return != 0.
+ * The timeouts in the 'wait_req_*' functions are arbitrary and rather
+ * large. In 99% of the invocations nearly no timeout is needed but in
+ * some cases (especially when using my tapedrive, a Tandberg 3600) the
+ * device is busy internally and the first SCSI-phase will be delayed.
+ */
+extern __inline__ int wait_req_true(void)
+{
+ int timeout = 25000;
+
+ while(!(SCSI_5380->scsi_idstat & SC_S_REQ) && --timeout)
+ delay(1);
+ return(SCSI_5380->scsi_idstat & SC_S_REQ);
+}
+
+/*
+ * Wait for request-line to become inactive. When it doesn't return 0.
+ * Otherwise return != 0.
+ */
+extern __inline__ int wait_req_false(void)
+{
+ int timeout = 25000;
+
+ while((SCSI_5380->scsi_idstat & SC_S_REQ) && --timeout)
+ delay(1);
+ return(!(SCSI_5380->scsi_idstat & SC_S_REQ));
+}
+
+extern __inline__ void finish_req(SC_REQ *reqp)
+{
+ int sps;
+ struct scsi_xfer *xs = reqp->xs;
+
+ /*
+ * Return request to free-q
+ */
+ sps = splbio();
+ reqp->next = free_head;
+ free_head = reqp;
+ splx(sps);
+
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+}
+
+/*
+ * Auto config stuff....
+ */
+int ncr_print __P((void *auxp, char *));
+void ncr_attach __P((struct device *, struct device *, void *));
+int ncr_match __P((struct device *, struct cfdata *, void *));
+
+struct cfdriver ncrscsicd = {
+ NULL, "ncrscsi", (cfmatch_t)ncr_match, ncr_attach,
+ DV_DULL, sizeof(struct ncr_softc), NULL, 0 };
+
+int
+ncr_match(pdp, cdp, auxp)
+struct device *pdp;
+struct cfdata *cdp;
+void *auxp;
+{
+ if(strcmp(auxp, ncrscsicd.cd_name))
+ return(0);
+ if(cdp->cf_unit != 0) /* Only one unit */
+ return(0);
+ return(1);
+}
+
+void
+ncr_attach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ struct ncr_softc *sc;
+ int i;
+
+ sc = (struct ncr_softc *)dp;
+
+ sc->sc_link.adapter_softc = sc;
+ sc->sc_link.adapter_target = 7;
+ sc->sc_link.adapter = &ncr5380_switch;
+ sc->sc_link.device = &ncr5380_dev;
+ sc->sc_link.openings = NREQ - 1;
+
+ /*
+ * Enable SCSI-related interrupts
+ */
+ MFP2->mf_aer |= 0x80; /* SCSI IRQ goes HIGH!!!!! */
+
+ MFP2->mf_ierb |= IB_SCDM; /* SCSI-dma interrupts */
+ MFP2->mf_iprb &= ~IB_SCDM;
+ MFP2->mf_imrb |= IB_SCDM;
+
+ MFP2->mf_iera |= IA_SCSI; /* SCSI-5380 interrupts */
+ MFP2->mf_ipra &= ~IA_SCSI;
+ MFP2->mf_imra |= IA_SCSI;
+
+ /*
+ * Initialize request queue freelist.
+ */
+ for(i = 0; i < NREQ; i++) {
+ req_queue[i].next = free_head;
+ free_head = &req_queue[i];
+ }
+
+ /*
+ * Initialize the host adapter
+ */
+ scsi_idisable();
+ SCSI_5380->scsi_icom = 0;
+ SCSI_5380->scsi_mode = IMODE_BASE;
+ SCSI_5380->scsi_tcom = 0;
+ SCSI_5380->scsi_idstat = 0;
+
+ printf("\n");
+
+
+ /*
+ * attach all scsi units on us
+ */
+ config_found(dp, &sc->sc_link, ncr_print);
+}
+
+/*
+ * print diag if name is NULL else just extra
+ */
+int
+ncr_print(auxp, name)
+void *auxp;
+char *name;
+{
+ if(name == NULL)
+ return(UNCONF);
+ return(QUIET);
+}
+/*
+ * End of auto config stuff....
+ */
+
+/*
+ * Carry out a request from the high level driver.
+ */
+static int
+ncr5380_scsi_cmd(struct scsi_xfer *xs)
+{
+ int sps;
+ SC_REQ *reqp;
+ int flags = xs->flags;
+
+ /*
+ * Sanity check on flags...
+ */
+ if(flags & ITSDONE) {
+ printf("ncr5380_scsi_cmd: command already done.....\n");
+ xs->flags &= ~ITSDONE;
+ }
+ if(!(flags & INUSE)) {
+ printf("ncr5380_scsi_cmd: command not in use.....\n");
+ xs->flags |= ~INUSE;
+ }
+
+ /*
+ * LWP: No lun support yet XXX
+ */
+ if(xs->sc_link->lun != 0) {
+ xs->error = XS_DRIVER_STUFFUP; /* XXX */
+ return(COMPLETE);
+ }
+
+ /*
+ * We do not queue RESET commands
+ */
+ if(flags & SCSI_RESET) {
+ scsi_reset();
+ return(COMPLETE);
+ }
+
+ /*
+ * Get a request block
+ */
+ sps = splbio();
+ if((reqp = free_head) == 0) {
+ splx(sps);
+ return(TRY_AGAIN_LATER);
+ }
+ free_head = reqp->next;
+ reqp->next = NULL;
+ splx(sps);
+
+ /*
+ * Initialize our private fields
+ */
+ reqp->dr_flag = (xs->flags & SCSI_POLL) ? DRIVER_NOINT : 0;
+ reqp->phase = NR_PHASE;
+ reqp->msgout = MSG_NOOP;
+ reqp->status = SCSGOOD;
+ reqp->link = NULL;
+ reqp->xs = xs;
+ reqp->targ_id = xs->sc_link->target;
+ reqp->xdata_ptr = (u_char*)xs->data;
+ reqp->xdata_len = xs->datalen;
+ memcpy(&reqp->xcmd, xs->cmd, sizeof(struct scsi_generic));
+
+ /*
+ * Check if DMA can be used on this request
+ */
+ if(!(xs->flags & SCSI_POLL) && scsi_dmaok(reqp))
+ reqp->dr_flag |= DRIVER_DMAOK;
+
+ /*
+ * Insert the command into the issue queue. Note that 'REQUEST SENSE'
+ * commands are inserted at the head of the queue since any command
+ * will clear the existing contingent allegience condition and the sense
+ * data is only valid while the condition exists.
+ * When possible, link the command to a previous command to the same
+ * target. This is not very sensible when AUTO_SENSE is not defined!
+ * Interrupts are disabled while we are fiddling with the issue-queue.
+ */
+ sps = splbio();
+ if((issue_q == NULL) || (reqp->xcmd.opcode == REQUEST_SENSE)) {
+ reqp->next = issue_q;
+ issue_q = reqp;
+ }
+ else {
+ SC_REQ *tmp, *link;
+
+ tmp = issue_q;
+ link = NULL;
+ do {
+ if(!link && (tmp->targ_id == reqp->targ_id) && !tmp->link)
+ link = tmp;
+ } while(tmp->next && (tmp = tmp->next));
+ tmp->next = reqp;
+#ifdef AUTO_SENSE
+ if(link) {
+ link->link = reqp;
+ link->xcmd.bytes[link->xs->cmdlen-1] |= 1;
+ }
+#endif
+ }
+ splx(sps);
+
+#ifdef DBG_REQ
+ show_request(reqp,(reqp->xcmd.opcode == REQUEST_SENSE) ? "HEAD":"TAIL");
+#endif
+
+ run_main();
+
+ if(xs->flags & SCSI_POLL)
+ return(COMPLETE); /* We're booting */
+ return(SUCCESSFULLY_QUEUED);
+}
+
+#define MIN_PHYS 65536 /*BARF!!!!*/
+static void
+ncr5380_minphys(struct buf *bp)
+{
+ if(bp->b_bcount > MIN_PHYS) {
+ printf("Uh-oh... ncr5380_minphys setting bp->b_bcount=%x.\n",MIN_PHYS);
+ bp->b_bcount = MIN_PHYS;
+ }
+}
+#undef MIN_PHYS
+
+static int
+ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
+{
+ u_char *b = (u_char *) xs->cmd;
+ int i = 0;
+
+ if(!(xs->flags & SCSI_RESET)) {
+ printf("ncr5380(%d:%d:%d,0x%x)-", xs->sc_link->scsibus,
+ xs->sc_link->target, xs->sc_link->lun, xs->sc_link->flags);
+ while(i < xs->cmdlen) {
+ if(i)
+ printf(",");
+ printf("%x",b[i++]);
+ }
+ printf("-\n");
+ }
+ else {
+ printf("ncr5380(%d:%d:%d)-RESET-\n",
+ xs->sc_link->scsibus,xs->sc_link->target, xs->sc_link->lun);
+ }
+}
+
+/*
+ * The body of the driver.
+ */
+static void
+scsi_main()
+{
+ SC_REQ *req, *prev;
+ int itype;
+ int sps;
+
+ /*
+ * While running in the driver SCSI-interrupts are disabled.
+ */
+ scsi_idisable();
+
+ PID(")");
+ for(;;) {
+ sps = splbio();
+ if(!connected) {
+
+ /*
+ * Search through the issue-queue for a command
+ * destined for a target that isn't busy.
+ */
+ prev = NULL;
+ for(req=issue_q; req != NULL; prev = req, req = req->next) {
+ if(!(busy & (1 << req->targ_id))) {
+ /*
+ * Found one, remove it from the issue queue
+ */
+ if(prev == NULL)
+ issue_q = req->next;
+ else prev->next = req->next;
+ req->next = NULL;
+ break;
+ }
+ }
+
+ /*
+ * When a request has just ended, we get here before an other
+ * device detects that the bus is free and that it can
+ * reconnect. The problem is that when this happens, we always
+ * baffle the device because our (initiator) id is higher. This
+ * can cause a sort of starvation on slow devices. So we check
+ * for a pending reselection here.
+ * Note that 'connected' will be non-null if the reselection
+ * succeeds.
+ */
+ if((SCSI_5380->scsi_idstat&(SC_S_SEL|SC_S_IO))
+ == (SC_S_SEL|SC_S_IO)){
+ if(req != NULL) {
+ req->next = issue_q;
+ issue_q = req;
+ }
+ splx(sps);
+
+ reselect();
+ SC_CLINT;
+ goto connected;
+ }
+
+ /*
+ * The host is not connected and there is no request
+ * pending, exit.
+ */
+ if(req == NULL) {
+ PID("{");
+ goto main_exit;
+ }
+
+ /*
+ * Re-enable interrupts before handling the request.
+ */
+ splx(sps);
+
+#ifdef DBG_REQ
+ show_request(req, "TARGET");
+#endif
+ /*
+ * We found a request. Try to connect to the target. If the
+ * initiator fails arbitration, the command is put back in the
+ * issue queue.
+ */
+ if(scsi_select(req, 0)) {
+ sps = splbio();
+ req->next = issue_q;
+ issue_q = req;
+ splx(sps);
+#ifdef DBG_REQ
+ printf("Select failed on target %d\n", req->targ_id);
+#endif
+ }
+ }
+ else splx(sps);
+connected:
+ if(connected) {
+ /*
+ * If the host is currently connected but a 'real-dma' transfer
+ * is in progress, the 'end-of-dma' interrupt restarts main.
+ * So quit.
+ */
+ sps = splbio();
+ if(connected && (connected->dr_flag & DRIVER_IN_DMA)) {
+ PID("[");
+ goto main_exit;
+ }
+ splx(sps);
+
+ /*
+ * Let the target guide us through the bus-phases
+ */
+ while(information_transfer() == -1)
+ ;
+ }
+ }
+ /* NEVER TO REACH HERE */
+ panic("TTSCSI: not designed to come here");
+
+main_exit:
+ /*
+ * We enter here with interrupts disabled. We are about to exit main
+ * so interrupts should be re-enabled. Because interrupts are edge
+ * triggered, we could already have missed the interrupt. Therefore
+ * we check the IRQ-line here and re-enter when we really missed a
+ * valid interrupt.
+ */
+ PID("S");
+ scsi_ienable();
+ SCSI_5380->scsi_idstat = SC_HOST_ID;
+ if(SCSI_5380->scsi_dmstat & SC_IRQ_SET) {
+ if((itype = check_intr()) != INTR_SPURIOUS) {
+ scsi_idisable();
+ splx(sps);
+
+ if(itype == INTR_RESEL)
+ reselect();
+ else dma_ready(0, 0);
+ SC_CLINT;
+ goto connected;
+ }
+ }
+ main_running = 0;
+ splx(sps);
+ PID("R");
+}
+
+/*
+ * The SCSI-DMA interrupt.
+ * This interrupt can only be triggered when running in non-polled DMA
+ * mode. When DMA is not active, it will be silently ignored, it is usually
+ * to late because the EOP interrupt of the controller happens just a tiny
+ * bit earlier. It might become usefull when scatter/gather is implemented,
+ * because in that case only part of the DATAIN/DATAOUT transfer is taken
+ * out of a single buffer.
+ */
+scsi_dma(sr)
+int sr; /* sr at time of interrupt */
+{
+ SC_REQ *reqp;
+ int dma_done;
+
+ PID("9");
+ if((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)) {
+ scsi_idisable();
+ if(!(dma_done = dma_ready(0, 0))) {
+ scsi_ienable();
+ transfer_dma(reqp, reqp->phase, 0);
+ return;
+ }
+ PID("!");
+ if(!BASEPRI(sr)) {
+ if(!callback_scheduled++)
+ add_sicallback(run_main, 0, 0);
+ }
+ else {
+ spl1();
+ run_main();
+ }
+ }
+ /* PID("#"); */
+}
+
+/*
+ * The SCSI-controller interrupt. This interrupt occurs on reselections and
+ * at the end of non-polled DMA-interrupts.
+ */
+scsi_ctrl(sr)
+int sr; /* sr at time of interrupt */
+{
+ int itype;
+ int dma_done;
+
+ /* PID("$"); */
+ while(SCSI_5380->scsi_dmstat & SC_IRQ_SET) {
+ scsi_idisable();
+ /* PID("&"); */
+ if((itype = check_intr()) != INTR_SPURIOUS) {
+ /* PID("o"); */
+ if(itype == INTR_RESEL)
+ reselect();
+ else {
+ if(!(dma_done = dma_ready(0, 0))) {
+ scsi_ienable();
+ transfer_dma(connected, connected->phase, 0);
+ return;
+ }
+ }
+ SC_CLINT;
+ }
+ /* PID("*"); */
+ if(!BASEPRI(sr)) {
+ if(!callback_scheduled++)
+ add_sicallback(run_main, 0, 0);
+ }
+ else {
+ spl1();
+ run_main();
+ }
+ return;
+ }
+ PID("(");
+}
+
+/*
+ * Initiate a connection path between the host and the target. The function
+ * first goes into arbitration for the SCSI-bus. When this succeeds, the target
+ * is selected and an 'IDENTIFY' message is send.
+ * Returns -1 when the arbitration failed. Otherwise 0 is returned. When
+ * the target does not respond (to either selection or 'MESSAGE OUT') the
+ * 'done' function is executed.
+ * The result code given by the driver can be influenced by setting 'code'
+ * to a non-zero value. This is the case when 'select' is called by abort.
+ */
+static int
+scsi_select(reqp, code)
+SC_REQ *reqp;
+{
+ u_long timeout;
+ u_char tmp[1];
+ u_char phase;
+ u_long cnt;
+ int sps;
+
+ DBG_SELPRINT ("Starting arbitration\n", 0);
+ PID("T");
+
+ sps = splbio();
+
+ /*
+ * Prevent a race condition here. If a reslection interrupt occurred
+ * between the decision to pick a new request and the call to select,
+ * we abort the selection.
+ * Interrupts are lowered when the 5380 is setup to arbitrate for the
+ * bus.
+ */
+ if(connected || (SCSI_5380->scsi_idstat & SC_S_BSY)) {
+ splx(sps);
+ PID("Y");
+ return(-1);
+ }
+
+ /*
+ * Set phase bits to 0, otherwise the 5380 won't drive the bus during
+ * selection.
+ */
+ SCSI_5380->scsi_tcom = 0;
+ SCSI_5380->scsi_icom = 0;
+
+ /*
+ * Arbitrate for the bus.
+ */
+ SCSI_5380->scsi_data = SC_HOST_ID;
+ SCSI_5380->scsi_mode = SC_ARBIT;
+
+ splx(sps);
+
+ cnt = 10000;
+ while(!(SCSI_5380->scsi_icom & SC_AIP) && --cnt)
+ delay(1);
+
+ if(!(SCSI_5380->scsi_icom & SC_AIP)) {
+ SCSI_5380->scsi_mode = IMODE_BASE;
+ delay(1);
+ PID("U");
+
+ if(SCSI_5380->scsi_idstat & SC_S_BSY) {
+ /*
+ * Damn, we have a connected target that we don't know
+ * of. Some targets seem to respond to a selection
+ * AFTER the selection-timeout. Try to get the target
+ * into the Message-out phase so we can send an ABORT
+ * message. We try to avoid resetting the SCSI-bus!
+ */
+ if(!reach_msg_out(sizeof(struct scsi_generic))) {
+ u_long len = 1;
+ u_char phase = PH_MSGOUT;
+ u_char msg = MSG_ABORT;
+
+ transfer_pio(&phase, &msg, &len);
+ }
+ else if(SCSI_5380->scsi_idstat & SC_S_BSY)
+ scsi_reset();
+ }
+ PID("I");
+ return(-1);
+ }
+
+ /* The arbitration delay is 2.2 usecs */
+ delay(3);
+
+ /*
+ * Check the result of the arbitration. If we failed, return -1.
+ */
+ if(SCSI_5380->scsi_icom & SC_LA) {
+ /*
+ * The spec requires that we should read the data register to
+ * check for higher id's and check the SC_LA again.
+ */
+ tmp[0] = SCSI_5380->scsi_data;
+ if(SCSI_5380->scsi_icom & SC_LA) {
+ SCSI_5380->scsi_mode = IMODE_BASE;
+ SCSI_5380->scsi_icom = 0;
+ DBG_SELPRINT ("Arbitration lost,deassert SC_ARBIT\n",0);
+ PID("O");
+ return(-1);
+ }
+ }
+ SCSI_5380->scsi_icom = SC_A_SEL | SC_A_BSY;
+ if(SCSI_5380->scsi_icom & SC_LA) {
+ SCSI_5380->scsi_mode = IMODE_BASE;
+ SCSI_5380->scsi_icom = 0;
+ DBG_SELPRINT ("Arbitration lost, deassert SC_A_SEL\n", 0);
+ PID("P");
+ return(-1);
+ }
+ /* Bus settle delay + Bus clear delay = 1.2 usecs */
+ delay(2);
+ DBG_SELPRINT ("Arbitration complete\n", 0);
+
+ /*
+ * Now that we won the arbitration, start the selection.
+ */
+ SCSI_5380->scsi_data = SC_HOST_ID | (1 << reqp->targ_id);
+
+ /*
+ * Raise ATN while SEL is true before BSY goes false from arbitration,
+ * since this is the only way to guarantee that we'll get a MESSAGE OUT
+ * phase immediately after the selection.
+ */
+ SCSI_5380->scsi_icom = SC_A_BSY | SC_A_SEL | SC_A_ATN | SC_ADTB;
+ SCSI_5380->scsi_mode = IMODE_BASE;
+
+ /*
+ * Turn off reselection interrupts
+ */
+ SCSI_5380->scsi_idstat = 0;
+
+ /*
+ * Reset BSY. The delay following it, surpresses a glitch in the
+ * 5380 which causes us to see our own BSY signal instead of that of
+ * the target.
+ */
+ SCSI_5380->scsi_icom = SC_A_SEL | SC_A_ATN | SC_ADTB;
+ delay(1);
+
+ /*
+ * Wait for the target to react, the specs call for a timeout of
+ * 250 ms.
+ */
+ cnt = 250000 /* 250 */;
+ while(!(SCSI_5380->scsi_idstat & SC_S_BSY) && --cnt)
+ delay(1);
+
+ if(!(SCSI_5380->scsi_idstat & SC_S_BSY)) {
+ /*
+ * There is no reaction from the target, start the selection
+ * timeout procedure. We release the databus but keep SEL
+ * 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.
+ */
+ SCSI_5380->scsi_icom = SC_A_SEL | SC_A_ATN;
+ delay(201);
+ if(!(SCSI_5380->scsi_idstat & SC_S_BSY)) {
+ SCSI_5380->scsi_icom = 0;
+ reqp->xs->error = code ? code : XS_SELTIMEOUT;
+ DBG_SELPRINT ("Target %d not responding to sel\n",
+ reqp->targ_id);
+ finish_req(reqp);
+ PID("A");
+ return(0);
+ }
+ }
+ SCSI_5380->scsi_icom = SC_A_ATN;
+
+ DBG_SELPRINT ("Target %d responding to select.\n", reqp->targ_id);
+
+ /*
+ * The SCSI-interrupts are disabled while a request is being handled.
+ */
+ scsi_idisable();
+
+ /*
+ * Since we followed the SCSI-spec and raised ATN while SEL was true
+ * but before BSY was false during the selection, a 'MESSAGE OUT'
+ * phase should follow. Here we send an 'IDENTIFY' message.
+ * Allow disconnect only when interrups are allowed.
+ */
+ tmp[0] = MSG_IDENTIFY(0, (reqp->dr_flag & DRIVER_NOINT) ? 0 : 1);
+ cnt = 1;
+ phase = PH_MSGOUT;
+ if(transfer_pio(&phase, tmp, &cnt) || cnt) {
+ DBG_SELPRINT ("Target %d: failed to send identify\n",
+ reqp->targ_id);
+ /*
+ * Try to disconnect from the target. We cannot leave it just
+ * hanging here.
+ */
+ if(!reach_msg_out(sizeof(struct scsi_generic))) {
+ u_long len = 1;
+ u_char phase = PH_MSGOUT;
+ u_char msg = MSG_ABORT;
+
+ transfer_pio(&phase, &msg, &len);
+ }
+ else scsi_reset();
+
+ SCSI_5380->scsi_icom = 0;
+ reqp->xs->error = code ? code : XS_DRIVER_STUFFUP;
+ finish_req(reqp);
+ PID("S");
+ return(0);
+ }
+ reqp->phase = PH_MSGOUT;
+
+#ifdef notyet /* LWP: Do we need timeouts in the driver? */
+ /*
+ * Command is connected, start timer ticking.
+ */
+ ccb_p->xtimeout = ccb_p->timeout + Lbolt;
+#endif
+
+ connected = reqp;
+ busy |= 1 << reqp->targ_id;
+ PID("D");
+ return(0);
+}
+
+/*
+ * Return codes:
+ * -1: quit main, trigger on interrupt
+ * 0: keep on running main.
+ */
+static int
+information_transfer()
+{
+ SC_REQ *reqp = connected;
+ u_char tmp, phase;
+ u_long len;
+
+ PID("F");
+ /*
+ * Clear pending interrupts from 5380-chip.
+ */
+ SC_CLINT;
+
+ /*
+ * We only have a valid SCSI-phase when REQ is asserted. Something
+ * is deadly wrong when BSY has dropped.
+ */
+ tmp = SCSI_5380->scsi_idstat;
+
+ if(!(tmp & SC_S_BSY)) {
+ busy &= ~(1 << reqp->targ_id);
+ connected = NULL;
+ reqp->xs->error = XS_BUSY;
+ finish_req(reqp);
+ PID("G");
+ return(0);
+ }
+
+ if(tmp & SC_S_REQ) {
+ phase = (tmp >> 2) & 7;
+ if(phase != reqp->phase) {
+ reqp->phase = phase;
+ DBG_INFPRINT(show_phase, reqp, phase);
+ }
+ }
+ else return(-1);
+
+ switch(phase) {
+ case PH_DATAOUT:
+
+#ifdef DBG_NOWRITE
+ printf("NOWRITE set -- write attempt aborted.");
+ reqp->msgout = MSG_ABORT;
+ SCSI_5380->scsi_icom = SC_A_ATN;
+ return(-1);
+#endif /* DBG_NOWRITE */
+
+ case PH_DATAIN:
+#ifdef REAL_DMA
+ if(reqp->dr_flag & DRIVER_DMAOK) {
+ int poll = REAL_DMA_POLL|(reqp->dr_flag & DRIVER_NOINT);
+ transfer_dma(reqp, phase, poll);
+ if(!poll)
+ return(0);
+ }
+ else
+#endif
+ {
+ PID("H");
+ len = reqp->xdata_len;
+ transfer_pio(&phase, reqp->xdata_ptr, &len);
+ reqp->xdata_ptr += reqp->xdata_len - len;
+ reqp->xdata_len = len;
+ }
+ return(-1);
+ case PH_MSGIN:
+ /*
+ * We only expect single byte messages here.
+ */
+ len = 1;
+ transfer_pio(&phase, &tmp, &len);
+ reqp->message = tmp;
+ return(handle_message(reqp, tmp));
+ case PH_MSGOUT:
+ len = 1;
+ transfer_pio(&phase, &reqp->msgout, &len);
+ if(reqp->msgout == MSG_ABORT) {
+ busy &= ~(1 << reqp->targ_id);
+ connected = NULL;
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ finish_req(reqp);
+ PID("J");
+ return(0);
+ }
+ reqp->msgout = MSG_NOOP;
+ return(-1);
+ case PH_CMD :
+ len = command_size(reqp->xcmd.opcode);
+ transfer_pio(&phase, (u_char *)&reqp->xcmd, &len);
+ PID("K");
+ return(-1);
+ case PH_STATUS:
+ len = 1;
+ transfer_pio(&phase, &tmp, &len);
+ reqp->status = tmp;
+ PID("L");
+ return(-1);
+ default :
+ printf("SCSI: unknown phase on target %d\n", reqp->targ_id);
+ }
+ PID(":");
+ return(-1);
+}
+
+/*
+ * Handle the message 'msg' send to us by the target.
+ * Return values:
+ * 0 : The current command has completed.
+ * -1 : Get on to the next phase.
+ */
+static int
+handle_message(reqp, msg)
+SC_REQ *reqp;
+u_int msg;
+{
+ int sps;
+
+ PID(";");
+ switch(msg) {
+ /*
+ * Linking lets us reduce the time required to get
+ * the next command to the device, skipping the arbitration
+ * and selection time. In the current implementation,
+ * we merely have to start the next command pointed
+ * to by 'next_link'.
+ */
+ case MSG_LINK_CMD_COMPLETE:
+ case MSG_LINK_CMD_COMPLETEF:
+ if(reqp->link == NULL) {
+ printf("SCSI: no link for linked command"
+ "on target %d\n", reqp->targ_id);
+ reqp->msgout = MSG_ABORT;
+ SCSI_5380->scsi_icom = SC_A_ATN;
+ PID("@");
+ return(-1);
+ }
+ reqp->xs->error = 0;
+
+#ifdef AUTO_SENSE
+ if(check_autosense(reqp, 0) == -1)
+ return(-1);
+#endif /* AUTO_SENSE */
+
+#ifdef DBG_REQ
+ show_request(reqp->link, "LINK");
+#endif
+ connected = reqp->link;
+ finish_req(reqp);
+ PID("'");
+ return(-1);
+ case MSG_ABORT:
+ case MSG_CMDCOMPLETE:
+#ifdef DBG_REQ
+ show_request(reqp, "DONE");
+#endif
+ connected = NULL;
+ busy &= ~(1 << reqp->targ_id);
+ if(!(reqp->dr_flag & DRIVER_AUTOSEN))
+ reqp->xs->resid = reqp->xdata_len;
+ reqp->xs->error = 0;
+
+#ifdef AUTO_SENSE
+ if(check_autosense(reqp, 0) == -1) {
+ PID("Z");
+ return(0);
+ }
+#endif /* AUTO_SENSE */
+
+ finish_req(reqp);
+ PID("X");
+ return(0);
+ case MSG_MESSAGE_REJECT:
+ PID("C");
+ return(-1);
+ case MSG_DISCONNECT:
+#ifdef DBG_REQ
+ show_request(reqp, "DISCON");
+#endif
+ sps = splbio();
+ connected = NULL;
+ reqp->next = discon_q;
+ discon_q = reqp;
+ splx(sps);
+ PID("V");
+ return(0);
+ case MSG_SAVEDATAPOINTER:
+ case MSG_RESTOREPOINTERS:
+ /*
+ * We save pointers implicitely at disconnect.
+ * So we can ignore these messages.
+ */
+ PID("B");
+ return(-1);
+ default:
+ printf("SCSI: unkown message %x on target %d\n", msg,
+ reqp->targ_id);
+ return(-1);
+ }
+ PID("N");
+ return(-1);
+}
+
+/*
+ * Handle reselection. If a valid reconnection occurs, connected
+ * points at the reconnected command. The command is removed from the
+ * disconnected queue.
+ */
+static void
+reselect()
+{
+ u_char phase;
+ u_long len;
+ u_char msg;
+ u_char target_mask;
+ int abort = 0;
+ SC_REQ *tmp, *prev;
+
+ PID("M");
+ target_mask = SCSI_5380->scsi_data & ~SC_HOST_ID;
+
+ /*
+ * At this point, we have detected that our SCSI-id is on the bus,
+ * SEL is true and BSY was false for at least one bus settle
+ * delay (400 ns.).
+ * We must assert BSY ourselves, until the target drops the SEL signal.
+ */
+ SCSI_5380->scsi_icom = SC_A_BSY;
+ while(SCSI_5380->scsi_idstat & SC_S_SEL)
+ ;
+
+ SCSI_5380->scsi_icom = 0;
+
+ /*
+ * Get the expected identify message.
+ */
+ phase = PH_MSGIN;
+ len = 1;
+ transfer_pio(&phase, &msg, &len);
+ if(len || !MSG_ISIDENTIFY(msg)) {
+ printf("SCSI: expecting IDENTIFY, got 0x%x\n", msg);
+ abort = 1;
+ }
+ else {
+ /*
+ * Find the command reconnecting
+ */
+ for(tmp = discon_q, prev = NULL; tmp; prev = tmp, tmp = tmp->next){
+ if(target_mask == (1 << tmp->targ_id)) {
+ if(prev)
+ prev->next = tmp->next;
+ else discon_q = tmp->next;
+ tmp->next = NULL;
+ break;
+ }
+ }
+ if(tmp == NULL) {
+ printf("SCSI: no disconnected job for targetmask %x\n",
+ target_mask);
+ abort = 1;
+ }
+ }
+ if(abort) {
+ msg = MSG_ABORT;
+ len = 1;
+ phase = PH_MSGOUT;
+
+ SCSI_5380->scsi_icom = SC_A_ATN;
+ transfer_pio(&phase, &msg, &len);
+ }
+ else {
+ connected = tmp;
+#ifdef DBG_REQ
+ show_request(tmp, "RECON");
+#endif
+ }
+ PID("<");
+}
+
+/*
+ * Transfer data in a given phase using polled I/O.
+ * Returns -1 when a different phase is entered without transferring the
+ * maximum number of bytes, 0 if all bytes or exit is in the same
+ * phase.
+ */
+static int
+transfer_pio(phase, data, len)
+u_char *phase;
+u_char *data;
+u_long *len;
+{
+ u_int cnt = *len;
+ u_char ph = *phase;
+ u_char tmp;
+
+ DBG_PIOPRINT ("SCSI: transfer_pio start: phase: %d, len: %d\n", ph,cnt);
+ PID(",");
+ SCSI_5380->scsi_tcom = ph;
+ do {
+ if(!wait_req_true()) {
+ DBG_PIOPRINT ("SCSI: transfer_pio: missing REQ\n", 0, 0);
+ break;
+ }
+ if(((SCSI_5380->scsi_idstat >> 2) & 7) != ph) {
+ DBG_PIOPRINT ("SCSI: transfer_pio: phase mismatch\n", 0, 0);
+ break;
+ }
+ if(PH_IN(ph)) {
+ *data++ = SCSI_5380->scsi_data;
+ SCSI_5380->scsi_icom = SC_A_ACK;
+ }
+ else {
+ SCSI_5380->scsi_data = *data++;
+
+ /*
+ * The SCSI-standard suggests that in the 'MESSAGE OUT' phase,
+ * the initiator should drop ATN on the last byte of the
+ * message phase after REQ has been asserted for the handshake
+ * but before the initiator raises ACK.
+ */
+ if(!( (ph == PH_MSGOUT) && (cnt > 1) )) {
+ SCSI_5380->scsi_icom = SC_ADTB;
+ SCSI_5380->scsi_icom = SC_ADTB | SC_A_ACK;
+ }
+ else {
+ SCSI_5380->scsi_icom = SC_ADTB | SC_A_ATN;
+ SCSI_5380->scsi_icom = SC_ADTB | SC_A_ATN | SC_A_ACK;
+ }
+ }
+ if(!wait_req_false()) {
+ DBG_PIOPRINT ("SCSI: transfer_pio - REQ not dropping\n", 0, 0);
+ break;
+ }
+
+ if(!( (ph == PH_MSGOUT) && (cnt > 1) ))
+ SCSI_5380->scsi_icom = 0;
+ else SCSI_5380->scsi_icom = SC_A_ATN;
+ } while(--cnt);
+
+ if((tmp = SCSI_5380->scsi_idstat) & SC_S_REQ)
+ *phase = (tmp >> 2) & 7;
+ else *phase = NR_PHASE;
+ *len = cnt;
+ DBG_PIOPRINT ("SCSI: transfer_pio done: phase: %d, len: %d\n",
+ *phase, cnt);
+ PID(">");
+ if(!cnt || (*phase == ph))
+ return(0);
+ return(-1);
+}
+
+/*
+ * Start a DMA-transfer on the device using the current pointers.
+ * If 'poll' is true, the function waits until DMA-has completed.
+ */
+static void
+transfer_dma(reqp, phase, poll)
+SC_REQ *reqp;
+u_int phase;
+int poll;
+{
+ int dmastat;
+ u_char mbase = 0;
+ int sps;
+
+again:
+ PID("?");
+ /*
+ * We should be in phase, otherwise we are not allowed to
+ * drive the bus.
+ */
+ SCSI_5380->scsi_tcom = phase;
+
+ /*
+ * Defer interrupts until DMA is fully running.
+ */
+ sps = splbio();
+
+ /*
+ * Clear pending interrupts and parity errors.
+ */
+ SCSI_DMA->s_dma_ctrl = 0;
+ SC_CLINT;
+
+ if(!poll) {
+ /*
+ * Enable SCSI interrupts and set IN_DMA flag, set 'mbase'
+ * to the interrupts we want enabled.
+ */
+ scsi_ienable();
+ reqp->dr_flag |= DRIVER_IN_DMA;
+ mbase = SC_E_EOPI | SC_MON_BSY;
+ }
+
+ if(PH_IN(phase)) {
+ SCSI_DMA->s_dma_ctrl = SD_IN;
+ set_scsi_dma(&(SCSI_DMA->s_dma_ptr), reqp->dm_cur->dm_addr);
+ set_scsi_dma(&(SCSI_DMA->s_dma_cnt), reqp->dm_cur->dm_count);
+ SCSI_5380->scsi_icom = 0;
+ SCSI_5380->scsi_mode = IMODE_BASE | mbase | SC_M_DMA;
+ SCSI_DMA->s_dma_ctrl = SD_ENABLE;
+ SCSI_5380->scsi_ircv = 0;
+ }
+ else {
+ SCSI_DMA->s_dma_ctrl = SD_OUT;
+ set_scsi_dma(&(SCSI_DMA->s_dma_ptr), reqp->dm_cur->dm_addr);
+ set_scsi_dma(&(SCSI_DMA->s_dma_cnt), reqp->dm_cur->dm_count);
+ SCSI_5380->scsi_mode = IMODE_BASE | mbase | SC_M_DMA;
+ SCSI_5380->scsi_icom = SC_ADTB;
+ SCSI_5380->scsi_dmstat = 0;
+ SCSI_DMA->s_dma_ctrl = SD_ENABLE|SD_OUT;
+ }
+ splx(sps);
+
+ if(poll) {
+ /*
+ * We wait here until the DMA has finished. This can be
+ * achieved by checking the following conditions:
+ * - 5380:
+ * - End of DMA flag is set
+ * - We lost BSY (error!!)
+ * - A phase mismatch has occured (partial transfer)
+ * - DMA-controller:
+ * - A bus error occurred (Kernel error!!)
+ * - All bytes are transferred
+ * We one of the terminating conditions was met, we call
+ * 'dma_ready' to check errors and perform the bookkeeping.
+ */
+ u_char dmstat, dmastat;
+ int dma_done;
+
+ PID("/");
+ for(;;) {
+ dmstat = SCSI_5380->scsi_dmstat;
+ dmastat = SCSI_DMA->s_dma_ctrl;
+ if(dmstat & (SC_END_DMA|SC_BSY_ERR|SC_IRQ_SET))
+ break;
+ if(!(dmstat & SC_PHS_MTCH))
+ break;
+ if(dmastat & (SD_BUSERR|SD_ZERO))
+ break;
+ }
+ PID("q");
+ if(dmastat & (SD_BUSERR|SD_ZERO))
+ dma_done = dma_ready(1, dmastat);
+ else dma_done = dma_ready(0, 0);
+ if(!dma_done)
+ goto again;
+
+ }
+ PID("w");
+}
+
+/*
+ * Check results of a DMA data-transfer.
+ */
+static int
+dma_ready(has_dmastat, dmastat)
+int has_dmastat, dmastat;
+{
+ int dmstat, phase;
+ long tmp, bytes_left, bytes_done;
+ int i;
+ SC_REQ *reqp = connected;
+
+ /*
+ * Get values of the status registers of the 5380 & DMA-controller.
+ */
+ dmstat = SCSI_5380->scsi_dmstat;
+ if(!has_dmastat)
+ dmastat = SCSI_DMA->s_dma_ctrl;
+
+ /*
+ * Check if the call is sensible and not caused by any spurious
+ * interrupt.
+ */
+ if( !(dmastat & (SD_BUSERR|SD_ZERO))
+ && !(dmstat & (SC_END_DMA|SC_BSY_ERR))
+ && (dmstat & SC_PHS_MTCH) ) {
+ printf("dma_ready: spurious call (dma:%x,dm:%x,last_hit: %s)\n",
+ dmastat, dmstat, last_hit);
+ return(0);
+ }
+
+ /*
+ * If end of a DMA transfer, check it's results.
+ */
+ get_scsi_dma(SCSI_DMA->s_dma_cnt, bytes_left);
+
+ if(dmastat & SD_BUSERR) {
+ /*
+ * The DMA-controller seems to access 8 bytes beyond
+ * it's limits on output. Therefore check also the byte
+ * count. If it's zero, ignore the bus error.
+ */
+ if(bytes_left != 0) {
+ get_scsi_dma(SCSI_DMA->s_dma_ptr, tmp);
+ printf("SCSI-DMA buserror - accessing 0x%x\n", tmp);
+ panic("SCSI");
+ }
+ }
+
+ if(bytes_left != 0) {
+ /*
+ * The byte-count is not zero. This is not always an error,on
+ * tape drives this usually means EOF. We check that the
+ * residu is a multiple of 512-bytes, when we know the device
+ * type it should be included in the check.
+ * A severe complication is that if a device wants to
+ * disconnect in the middle of a DMA-transfer, the 5380 has
+ * already prefetched the next byte from the DMA-controller
+ * before the phase mismatch occurs. I don't know how this
+ * fact can be uniquely identified. For the moment, we round
+ * up the residual if it is odd.
+ */
+ if(PH_OUT(reqp->phase) && (bytes_left & 1))
+ bytes_left++;
+
+ }
+ else {
+ if(PH_IN(reqp->phase)) {
+ /*
+ * Check for bytes not transfered. This should never occur
+ * because the buffer-pool is aligned on a 4-byte boundary.
+ */
+ u_char *p, *q;
+
+ if(bytes_left > 3) {
+ scsi_show();
+ printf("SCSI: %d bytes not transferred\n", bytes_left);
+ panic("SCSI");
+ }
+ p = (u_char*)(bytes_left & ~3);
+ q = (u_char*)&(SCSI_DMA->s_dma_res);
+ switch(bytes_left & 3) {
+ case 3: *p++ = *q++;
+ case 2: *p++ = *q++;
+ case 1: *p++ = *q++;
+ printf("SCSI: dma residue count != 0, ");
+ printf("Check buffer alignment\n");
+ }
+ }
+ }
+
+ /*
+ * Update various transfer-pointers/lengths
+ */
+ bytes_done = reqp->dm_cur->dm_count - bytes_left;
+
+ reqp->xdata_ptr = &reqp->xdata_ptr[bytes_done]; /* XXX */
+ reqp->xdata_len -= bytes_done; /* XXX */
+ if((reqp->dm_cur->dm_count -= bytes_done) == 0)
+ reqp->dm_cur++;
+ else reqp->dm_cur->dm_addr += bytes_done;
+
+ if(PH_IN(reqp->phase) && (dmstat & SC_PAR_ERR)) {
+ if(!(ncr5380_no_parchk & (1 << reqp->targ_id)))
+ /* XXX: Should be parity error ???? */
+ reqp->xs->error = XS_DRIVER_STUFFUP;
+ }
+
+ /*
+ * DMA mode should always be reset even when we will continue with the
+ * next chain.
+ */
+ SCSI_5380->scsi_mode &= ~SC_M_DMA;
+
+ if((dmstat & SC_BSY_ERR) || !(dmstat & SC_PHS_MTCH)
+ || (reqp->dm_cur > reqp->dm_last)) {
+ /*
+ * Tell interrupt functions DMA mode has ended.
+ */
+ reqp->dr_flag &= ~DRIVER_IN_DMA;
+
+ /*
+ * Turn off DMA-mode and clear icom
+ */
+ SCSI_5380->scsi_mode &=
+ ~(SC_M_DMA|SC_E_EOPI|SC_MON_BSY|SC_E_PARI);
+ SCSI_5380->scsi_icom = 0;
+
+ /*
+ * Clear all (pending) interrupts.
+ */
+ SCSI_DMA->s_dma_ctrl = 0;
+ SC_CLINT;
+
+ if(dmstat & SC_BSY_ERR) {
+ if(!reqp->xs->error)
+ reqp->xs->error = XS_BUSY;
+ finish_req(reqp);
+ PID("r");
+ return(1);
+ }
+
+ if(reqp->xs->error != 0) {
+printf("dma-ready: code = %d\n", reqp->xs->error); /* LWP */
+ reqp->msgout = MSG_ABORT;
+ SCSI_5380->scsi_icom = SC_A_ATN;
+ }
+ PID("t");
+ return(1);
+ }
+ return(0);
+}
+
+static int
+check_autosense(reqp, linked)
+SC_REQ *reqp;
+int linked;
+{
+ int sps;
+
+ /*
+ * If we not executing an auto-sense and the status code
+ * is request-sense, we automatically issue a request
+ * sense command.
+ */
+ PID("y");
+ if(!(reqp->dr_flag & DRIVER_AUTOSEN)) {
+ if(reqp->status == SCSCHKC) {
+ memcpy(&reqp->xcmd, sense_cmd, sizeof(sense_cmd));
+ reqp->xdata_ptr = (u_char *)&reqp->xs->sense;
+ reqp->xdata_len = sizeof(reqp->xs->sense);
+ reqp->dr_flag |= DRIVER_AUTOSEN;
+ reqp->dr_flag &= ~DRIVER_DMAOK;
+ if(!linked) {
+ sps = splbio();
+ reqp->next = issue_q;
+ issue_q = reqp;
+ splx(sps);
+ }
+ else reqp->xcmd.bytes[4] |= 1;
+
+#ifdef DBG_REQ
+ show_request(reqp, "AUTO-SENSE");
+#endif
+ PID("u");
+ return(-1);
+ }
+ }
+ else {
+ /*
+ * An auto-sense has finished
+ */
+ if((reqp->status & SCSMASK) != SCSGOOD)
+ reqp->xs->error = XS_DRIVER_STUFFUP; /* SC_E_AUTOSEN; */
+ else reqp->xs->error = XS_SENSE;
+ reqp->status = SCSCHKC;
+ }
+ PID("i");
+ return(0);
+}
+
+static int
+reach_msg_out(len)
+u_long len;
+{
+ u_char phase;
+ u_char data;
+
+ printf("SCSI: Trying to reach Message-out phase\n");
+ if((phase = SCSI_5380->scsi_idstat) & SC_S_REQ)
+ phase = (phase >> 2) & 7;
+ else return(-1);
+ printf("SCSI: Trying to reach Message-out phase, now: %d\n", phase);
+ if(phase == PH_MSGOUT)
+ return(0);
+
+ SCSI_5380->scsi_tcom = phase;
+
+ do {
+ if(!wait_req_true()) {
+ break;
+ }
+ if(((SCSI_5380->scsi_idstat >> 2) & 7) != phase) {
+ break;
+ }
+ if(PH_IN(phase)) {
+ data = SCSI_5380->scsi_data;
+ SCSI_5380->scsi_icom = SC_A_ACK | SC_A_ATN;
+ }
+ else {
+ SCSI_5380->scsi_data = 0;
+ SCSI_5380->scsi_icom = SC_ADTB | SC_A_ATN | SC_A_ACK;
+ }
+ if(!wait_req_false()) {
+ break;
+ }
+ SCSI_5380->scsi_icom = SC_A_ATN;
+ } while(--len);
+
+ if((phase = SCSI_5380->scsi_idstat) & SC_S_REQ) {
+ phase = (phase >> 2) & 7;
+ if(phase == PH_MSGOUT) {
+ printf("SCSI: Message-out phase reached.\n");
+ return(0);
+ }
+ }
+ return(-1);
+}
+
+static void
+scsi_reset()
+{
+ SC_REQ *tmp, *next;
+ int sps;
+
+ printf("SCSI: resetting SCSI-bus\n");
+
+ PID("7");
+ sps = splbio();
+ SCSI_5380->scsi_icom = SC_A_RST;
+ delay(1);
+ SCSI_5380->scsi_icom = 0;
+
+ /*
+ * None of the jobs in the discon_q will ever be reconnected,
+ * notify this to the higher level code.
+ */
+ for(tmp = discon_q; tmp ;) {
+ next = tmp->next;
+ tmp->next = NULL;
+ tmp->xs->error = XS_TIMEOUT;
+ busy &= ~(1 << tmp->targ_id);
+ finish_req(tmp);
+ tmp = next;
+ }
+ discon_q = NULL;
+
+ /*
+ * The current job will never finish either.
+ * The problem is that we can't finish the job because an instance
+ * of main is running on it. Our best guess is that the job is currently
+ * doing REAL-DMA. In that case 'dma_ready()' should correctly finish
+ * the job because it detects BSY-loss.
+ */
+ if(tmp = connected) {
+ if(tmp->dr_flag & DRIVER_IN_DMA) {
+ tmp->xs->error = XS_DRIVER_STUFFUP;
+ dma_ready(0, 0);
+ }
+ }
+ splx(sps);
+ PID("8");
+}
+
+/*
+ * Check validity of the IRQ set by the 5380. If the interrupt is valid,
+ * the appropriate action is carried out (reselection or DMA ready) and
+ * INTR_RESEL or INTR_DMA is returned. Otherwise a console notice is written
+ * and INTR_SPURIOUS is returned.
+ */
+static int
+check_intr()
+{
+ SC_REQ *reqp;
+
+ if((SCSI_5380->scsi_idstat & (SC_S_SEL|SC_S_IO))==(SC_S_SEL|SC_S_IO))
+ return(INTR_RESEL);
+ else {
+ if((reqp = connected) && (reqp->dr_flag & DRIVER_IN_DMA)){
+ reqp->dr_flag &= ~DRIVER_IN_DMA;
+ return(INTR_DMA);
+ }
+ }
+ SC_CLINT;
+ printf("-->");
+ scsi_show();
+ printf("SCSI: spurious interrupt.\n");
+ return(INTR_SPURIOUS);
+}
+
+/*
+ * Check if DMA can be used for this request. This function also builds
+ * the dma-chain.
+ */
+static int
+scsi_dmaok(reqp)
+SC_REQ *reqp;
+{
+ u_long phy_buf;
+ u_long phy_len;
+ void *req_addr;
+ u_long req_len;
+ struct dma_chain *dm;
+
+ /*
+ * Initialize locals and requests' DMA-chain.
+ */
+ req_len = reqp->xdata_len;
+ req_addr = (void*)reqp->xdata_ptr;
+ dm = reqp->dm_cur = reqp->dm_last = reqp->dm_chain;
+
+ dm->dm_count = dm->dm_addr = 0;
+
+ /*
+ * Do not accept zero length DMA.
+ */
+ if(req_len == 0)
+ return(0);
+
+ /*
+ * LWP: I think that this restriction is not strictly nessecary.
+ */
+ if((req_len & 0x1) || ((u_int)req_addr & 0x3))
+ return(0);
+
+ /*
+ * Build the DMA-chain.
+ */
+ dm->dm_addr = phy_buf = kvtop(req_addr);
+ while(req_len) {
+ if(req_len < (phy_len = NBPG - ((u_long)req_addr & PGOFSET)))
+ phy_len = req_len;
+
+ req_addr += phy_len;
+ req_len -= phy_len;
+ dm->dm_count += phy_len;
+
+#ifdef NO_TTRAM_DMA
+ /*
+ * LWP: DMA transfers to TT-ram causes data to be garbeled
+ * without notice on some revisons of the TT-mainboard.
+ * When program's generate misterious Segmentations faults,
+ * try turning on NO_TTRAM_DMA.
+ */
+ if(dm->dm_addr > 0x1000000) /* XXX: should be a define??? */
+ return(0);
+#endif
+
+ if(req_len) {
+ u_long tmp = kvtop(req_addr);
+
+ if((phy_buf + phy_len) != tmp) {
+ if(++dm >= &reqp->dm_chain[MAXDMAIO]) {
+ printf("ncr5380_dmaok: DMA chain too long!\n");
+ return(0);
+ }
+ dm->dm_count = 0;
+ dm->dm_addr = tmp;
+ }
+ phy_buf = tmp;
+ }
+ }
+ reqp->dm_last = dm;
+ return(1);
+}
+
+static void
+run_main(void)
+{
+ int sps = splbio();
+
+ callback_scheduled = 0;
+ if(!main_running) {
+ main_running = 1;
+ splx(sps);
+ scsi_main();
+ }
+ else splx(sps);
+}
+
+/****************************************************************************
+ * Start Debugging Functions *
+ ****************************************************************************/
+static void
+show_data_sense(xs)
+struct scsi_xfer *xs;
+{
+ u_char *b;
+ int i;
+ int sz;
+
+ b = (u_char *) xs->cmd;
+ printf("cmd[%d,%d]: ", xs->cmdlen, sz = command_size(*b));
+ for(i = 0; i < sz; i++)
+ printf("%x ", b[i]);
+ printf("\nsense: ");
+ b = (u_char *)&xs->sense;
+ for(i = 0; i < sizeof(xs->sense); i++)
+ printf("%x ", b[i]);
+ printf("\n");
+}
+
+static void
+show_request(reqp, qtxt)
+SC_REQ *reqp;
+char *qtxt;
+{
+ printf("REQ-%s: %d %x[%d] cmd[0]=%x S=%x M=%x R=%x %s\n", qtxt,
+ reqp->targ_id, reqp->xdata_ptr, reqp->xdata_len,
+ reqp->xcmd.opcode, reqp->status, reqp->message,
+ reqp->xs->error, reqp->link ? "L" : "");
+ if(reqp->status == SCSCHKC)
+ show_data_sense(reqp->xs);
+}
+
+scsi_show()
+{
+ SC_REQ *tmp;
+ int sps = splhigh();
+
+#ifndef DBG_PID
+ #define last_hit ""
+#endif
+
+ for(tmp = issue_q; tmp; tmp = tmp->next)
+ show_request(tmp, "ISSUED");
+ for(tmp = discon_q; tmp; tmp = tmp->next)
+ show_request(tmp, "DISCONNECTED");
+ if(connected)
+ show_request(connected, "CONNECTED");
+ /* show_signals(); */
+ if(connected)
+ printf("phase = %d, ", connected->phase);
+ printf("busy:%x, last_hit:%s, spl:%04x\n", busy, last_hit, sps);
+
+ splx(sps);
+}
diff --git a/sys/arch/atari/dev/ncr5380reg.h b/sys/arch/atari/dev/ncr5380reg.h
new file mode 100644
index 00000000000..e9546bf2e39
--- /dev/null
+++ b/sys/arch/atari/dev/ncr5380reg.h
@@ -0,0 +1,182 @@
+/* $NetBSD: ncr5380reg.h,v 1.1.1.1 1995/03/26 07:12:15 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _NCR5380REG_H
+#define _NCR5380REG_H
+/*
+ * Atari TT hardware:
+ * SCSI interface + DMA.
+ * The SCSI chip is an NCR5380
+ */
+
+
+#define SCSI_DMA ((struct scsi_dma *)AD_SCSI_DMA)
+#define SCSI_5380 ((struct scsi_5380 *)AD_NCR5380)
+
+struct scsi_dma {
+ volatile u_char s_dma_ptr[8]; /* use only the odd bytes */
+ volatile u_char s_dma_cnt[8]; /* use only the odd bytes */
+ volatile u_char s_dma_res[4]; /* data residue register */
+ volatile u_char s_dma_gap; /* not used */
+ volatile u_char s_dma_ctrl; /* control register */
+};
+
+#define set_scsi_dma(addr, val) (void)( \
+ { \
+ u_char *address = (u_char*)addr+1; \
+ u_long nval = (u_long)val; \
+ __asm("movepl %0, %1@(0)": :"d" (nval), "a" (address)); \
+ })
+
+#define get_scsi_dma(addr, res) ( \
+ { \
+ u_char *address = (u_char*)addr+1; \
+ u_long nval; \
+ __asm("movepl %1@(0), %0": "=d" (nval) : "a" (address)); \
+ res = (u_long)nval; \
+ })
+
+/*
+ * Defines for DMA control register
+ */
+#define SD_BUSERR 0x80 /* 1 = transfer caused bus error*/
+#define SD_ZERO 0x40 /* 1 = byte counter is zero */
+#define SD_ENABLE 0x02 /* 1 = Enable DMA */
+#define SD_OUT 0x01 /* Direction: memory to SCSI */
+#define SD_IN 0x00 /* Direction: SCSI to memory */
+
+struct scsi_5380 {
+ volatile u_char scsi_5380[16]; /* use only the odd bytes */
+};
+
+#define scsi_data scsi_5380[ 1] /* Data register */
+#define scsi_icom scsi_5380[ 3] /* Initiator command register */
+#define scsi_mode scsi_5380[ 5] /* Mode register */
+#define scsi_tcom scsi_5380[ 7] /* Target command register */
+#define scsi_idstat scsi_5380[ 9] /* Bus status register */
+#define scsi_dmstat scsi_5380[11] /* DMA status register */
+#define scsi_trcv scsi_5380[13] /* Target receive register */
+#define scsi_ircv scsi_5380[15] /* Initiator receive register */
+
+/*
+ * Definitions for Initiator command register.
+ */
+#define SC_A_RST 0x80 /* RW - Assert RST */
+#define SC_TEST 0x40 /* W - Test mode */
+#define SC_AIP 0x40 /* R - Arbitration in progress */
+#define SC_LA 0x20 /* R - Lost arbitration */
+#define SC_A_ACK 0x10 /* RW - Assert ACK */
+#define SC_A_BSY 0x08 /* RW - Assert BSY */
+#define SC_A_SEL 0x04 /* RW - Assert SEL */
+#define SC_A_ATN 0x02 /* RW - Assert ATN */
+#define SC_ADTB 0x01 /* RW - Assert Data To Bus */
+
+/*
+ * Definitions for mode register
+ */
+#define SC_B_DMA 0x80 /* RW - Block mode DMA (not on TT!) */
+#define SC_T_MODE 0x40 /* RW - Target mode */
+#define SC_E_PAR 0x20 /* RW - Enable parity check */
+#define SC_E_PARI 0x10 /* RW - Enable parity interrupt */
+#define SC_E_EOPI 0x08 /* RW - Enable End Of Process Interrupt */
+#define SC_MON_BSY 0x04 /* RW - Monitor BSY */
+#define SC_M_DMA 0x02 /* RW - Set DMA mode */
+#define SC_ARBIT 0x01 /* RW - Arbitrate */
+
+/*
+ * Definitions for tcom register
+ */
+#define SC_LBS 0x80 /* RW - Last Byte Send (not on TT!) */
+#define SC_A_REQ 0x08 /* RW - Assert REQ */
+#define SC_A_MSG 0x04 /* RW - Assert MSG */
+#define SC_A_CD 0x02 /* RW - Assert C/D */
+#define SC_A_IO 0x01 /* RW - Assert I/O */
+
+/*
+ * Definitions for idstat register
+ */
+#define SC_S_RST 0x80 /* R - RST is set */
+#define SC_S_BSY 0x40 /* R - BSY is set */
+#define SC_S_REQ 0x20 /* R - REQ is set */
+#define SC_S_MSG 0x10 /* R - MSG is set */
+#define SC_S_CD 0x08 /* R - C/D is set */
+#define SC_S_IO 0x04 /* R - I/O is set */
+#define SC_S_SEL 0x02 /* R - SEL is set */
+#define SC_S_PAR 0x01 /* R - Parity bit */
+
+/*
+ * Definitions for dmastat register
+ */
+#define SC_END_DMA 0x80 /* R - End of DMA */
+#define SC_DMA_REQ 0x40 /* R - DMA request */
+#define SC_PAR_ERR 0x20 /* R - Parity error */
+#define SC_IRQ_SET 0x10 /* R - IRQ is active */
+#define SC_PHS_MTCH 0x08 /* R - Phase Match */
+#define SC_BSY_ERR 0x04 /* R - Busy error */
+#define SC_ATN_STAT 0x02 /* R - State of ATN line */
+#define SC_ACK_STAT 0x01 /* R - State of ACK line */
+#define SC_S_SEND 0x00 /* W - Start DMA output */
+
+#define SC_CLINT { /* Clear interrupts */ \
+ int i = SCSI_5380->scsi_ircv; \
+ }
+
+
+/*
+ * Definition of SCSI-bus phases. The values are determined by signals
+ * on the SCSI-bus. DO NOT CHANGE!
+ * The values must be used to index the pointers in SCSI-PARMS.
+ */
+#define NR_PHASE 8
+#define PH_DATAOUT 0
+#define PH_DATAIN 1
+#define PH_CMD 2
+#define PH_STATUS 3
+#define PH_RES1 4
+#define PH_RES2 5
+#define PH_MSGOUT 6
+#define PH_MSGIN 7
+
+#define PH_OUT(phase) (!(phase & 1)) /* TRUE if output phase */
+#define PH_IN(phase) (phase & 1) /* TRUE if input phase */
+
+/*
+ * Id of Host-adapter
+ */
+#define SC_HOST_ID 0x80
+
+/*
+ * Base setting for 5380 mode register
+ */
+#define IMODE_BASE SC_E_PAR
+
+#endif /* _NCR5380REG_H */
diff --git a/sys/arch/atari/dev/ramd.c b/sys/arch/atari/dev/ramd.c
new file mode 100644
index 00000000000..eb6ef6e80bb
--- /dev/null
+++ b/sys/arch/atari/dev/ramd.c
@@ -0,0 +1,492 @@
+/* $NetBSD: ramd.c,v 1.1.1.1 1995/03/26 07:12:13 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/conf.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/dkbad.h>
+
+/*
+ * Misc. defines:
+ */
+#define RAMD_CHUNK (9 * 512) /* Chunk-size for auto-load */
+#define RAMD_NDEV 1 /* Number of devices configured */
+
+struct ramd_info {
+ u_long ramd_size; /* Size of disk in bytes */
+ u_long ramd_flag; /* see defs below */
+ dev_t ramd_dev; /* device to load from */
+ u_long ramd_state; /* runtime state see defs below */
+ caddr_t ramd_addr; /* Kernel virtual addr */
+};
+
+/*
+ * ramd_flag:
+ */
+#define RAMD_LOAD 0x01 /* Auto load when first opened */
+#define RAMD_LCOMP 0x02 /* Input is compressed */
+
+/*
+ * ramd_state:
+ */
+#define RAMD_ALLOC 0x01 /* Memory is allocated */
+#define RAMD_OPEN 0x02 /* Ramdisk is open */
+#define RAMD_INOPEN 0x04 /* Ramdisk is being opened */
+#define RAMD_WANTED 0x08 /* Someone is waiting on struct */
+#define RAMD_LOADED 0x10 /* Ramdisk is properly loaded */
+
+struct ramd_info rd_info[RAMD_NDEV] = {
+ {
+ 1105920, /* 1Mb in 2160 sectors */
+ RAMD_LOAD, /* auto-load this device */
+ MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */
+ 0, /* Will be set at runtime */
+ NULL /* Will be set at runtime */
+ },
+ {
+ 1474560, /* 1.44Mb in 2880 sectors */
+ RAMD_LOAD, /* auto-load this device */
+ MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */
+ 0, /* Will be set at runtime */
+ NULL /* Will be set at runtime */
+ }
+};
+
+struct read_info {
+ struct buf *bp; /* buffer for strategy function */
+ long nbytes; /* total number of bytes to read */
+ long offset; /* offset in input medium */
+ caddr_t bufp; /* current output buffer */
+ caddr_t ebufp; /* absolute maximum for bufp */
+ int chunk; /* chunk size on input medium */
+ int media_sz; /* size of input medium */
+ void (*strat)(); /* strategy function for read */
+};
+
+/*
+ * Autoconfig stuff....
+ */
+static int ramdmatch __P((struct device *, struct cfdata *, void *));
+static int ramdprint __P((void *, char *));
+static void ramdattach __P((struct device *, struct device *, void *));
+
+struct cfdriver ramdcd = {
+ NULL, "rd", (cfmatch_t)ramdmatch, ramdattach, DV_DULL,
+ sizeof(struct device), NULL, 0 };
+
+static int
+ramdmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp("rd", auxp) || (cfp->cf_unit >= RAMD_NDEV))
+ return(0);
+ return(1);
+}
+
+static void
+ramdattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ int i;
+
+ for(i = 0; i < RAMD_NDEV; i++)
+ config_found(dp, (void*)i, ramdprint);
+}
+
+static int
+ramdprint(auxp, pnp)
+void *auxp;
+char *pnp;
+{
+ return(UNCONF);
+}
+
+static int loaddisk __P((struct ramd_info *, struct proc *));
+static void rdminphys __P((struct buf *));
+static int ramd_norm_read __P((struct read_info *));
+static int cpy_uncompressed __P((caddr_t, int, struct read_info *));
+static int rd_compressed __P((caddr_t, int, struct read_info *));
+
+int
+rdopen(dev, flags, devtype, p)
+dev_t dev;
+int flags, devtype;
+struct proc *p;
+{
+ struct ramd_info *ri;
+ int s;
+ int error = 0;
+
+ if(DISKUNIT(dev) >= RAMD_NDEV)
+ return(ENXIO);
+
+ ri = &rd_info[DISKUNIT(dev)];
+ if(ri->ramd_state & RAMD_OPEN)
+ return(0);
+
+ /*
+ * If someone is busy opening, wait for it to complete.
+ */
+ s = splbio();
+ while(ri->ramd_state & RAMD_INOPEN) {
+ ri->ramd_state |= RAMD_WANTED;
+ tsleep((caddr_t)ri, PRIBIO, "rdopen", 0);
+ }
+ ri->ramd_state |= RAMD_INOPEN;
+ splx(s);
+
+ if(!(ri->ramd_state & RAMD_ALLOC)) {
+ ri->ramd_addr = malloc(ri->ramd_size, M_DEVBUF, M_WAITOK);
+ if(ri->ramd_addr == NULL) {
+ error = ENXIO;
+ goto done;
+ }
+ ri->ramd_state |= RAMD_ALLOC;
+ }
+ if((ri->ramd_flag & RAMD_LOAD) && !(ri->ramd_state & RAMD_LOADED)) {
+ error = loaddisk(ri, p);
+ if(!error)
+ ri->ramd_state |= RAMD_LOADED;
+ }
+done:
+ ri->ramd_state &= ~RAMD_INOPEN;
+ if(ri->ramd_state & RAMD_WANTED) {
+ ri->ramd_state &= ~RAMD_WANTED;
+ wakeup((caddr_t)ri);
+ }
+ return(error);
+}
+
+int
+rdclose(dev, flags, devtype, p)
+dev_t dev;
+int flags, devtype;
+struct proc *p;
+{
+ return(0);
+}
+
+int
+rdioctl(dev, cmd, addr, flag, p)
+dev_t dev;
+u_long cmd;
+int flag;
+caddr_t addr;
+struct proc *p;
+{
+ return(ENOTTY);
+}
+
+/*
+ * no dumps to ram disks thank you.
+ */
+int
+rdsize(dev)
+dev_t dev;
+{
+ return(-1);
+}
+
+int
+rdread(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
+ dev, B_READ, rdminphys, uio));
+}
+
+int
+rdwrite(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return(physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL,
+ dev, B_WRITE, rdminphys, uio));
+}
+
+/* XXX: Limit to 64k. */
+static void
+rdminphys(bp)
+struct buf *bp;
+{
+ bp->b_bcount = min(bp->b_bcount, (64 * 1024));
+}
+
+void
+rdstrategy(bp)
+struct buf *bp;
+{
+ struct ramd_info *ri;
+ long maxsz, sz;
+ char *datap;
+
+ ri = &rd_info[DISKUNIT(bp->b_dev)];
+
+ maxsz = ri->ramd_size / DEV_BSIZE;
+ sz = (bp->b_bcount + DEV_BSIZE - 1) / DEV_BSIZE;
+ if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+ if((bp->b_blkno == maxsz) && (bp->b_flags & B_READ)) {
+ /* Hitting EOF */
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ sz = maxsz - bp->b_blkno;
+ if((sz <= 0) || (bp->b_blkno < 0)) {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR;
+ goto done;
+ }
+ bp->b_bcount = sz * DEV_BSIZE;
+ }
+ datap = (char*)((u_long)ri->ramd_addr + bp->b_blkno * DEV_BSIZE);
+ if(bp->b_flags & B_READ)
+ bcopy(datap, bp->b_data, bp->b_bcount);
+ else bcopy(bp->b_data, datap, bp->b_bcount);
+ bp->b_resid = 0;
+ biodone(bp);
+ return;
+
+done:
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+}
+
+static int
+loaddisk(ri, proc)
+struct ramd_info *ri;
+struct proc *proc;
+{
+ struct buf buf;
+ int error;
+ struct bdevsw *bdp = &bdevsw[major(ri->ramd_dev)];
+ struct disklabel dl;
+ struct read_info rs;
+
+ /*
+ * Initialize out buffer header:
+ */
+ buf.b_actf = NULL;
+ buf.b_rcred = buf.b_wcred = proc->p_ucred;
+ buf.b_vnbufs.le_next = NOLIST;
+ buf.b_flags = B_BUSY;
+ buf.b_dev = ri->ramd_dev;
+ buf.b_error = 0;
+ buf.b_proc = proc;
+
+ /*
+ * Setup read_info:
+ */
+ rs.bp = &buf;
+ rs.nbytes = ri->ramd_size;
+ rs.offset = 0;
+ rs.bufp = ri->ramd_addr;
+ rs.ebufp = ri->ramd_addr + ri->ramd_size;
+ rs.chunk = RAMD_CHUNK;
+ rs.media_sz = ri->ramd_size;
+ rs.strat = bdp->d_strategy;
+
+ /*
+ * Open device and try to get some statistics.
+ */
+ if(error = bdp->d_open(ri->ramd_dev,FREAD | FNONBLOCK, 0, proc))
+ return(error);
+ if(bdp->d_ioctl(ri->ramd_dev,DIOCGDINFO,(caddr_t)&dl,FREAD,proc) == 0) {
+ /* Read on a cylinder basis */
+ rs.chunk = dl.d_secsize * dl.d_secpercyl;
+ rs.media_sz = dl.d_secperunit * dl.d_secsize;
+ }
+
+#ifdef notyet
+ if(ri->ramd_flag & RAMD_LCOMP)
+ error = decompress(cpy_uncompressed, rd_compressed, &rs);
+ else
+#endif /* notyet */
+ error = ramd_norm_read(&rs);
+
+ bdp->d_close(ri->ramd_dev,FREAD | FNONBLOCK, 0, proc);
+ return(error);
+}
+
+static int
+ramd_norm_read(rsp)
+struct read_info *rsp;
+{
+ long bytes_left;
+ int done, error;
+ struct buf *bp;
+ int s;
+ int dotc = 0;
+
+ bytes_left = rsp->nbytes;
+ bp = rsp->bp;
+ error = 0;
+
+ while(bytes_left > 0) {
+ s = splbio();
+ bp->b_flags = B_BUSY | B_PHYS | B_READ;
+ splx(s);
+ bp->b_blkno = btodb(rsp->offset);
+ bp->b_bcount = rsp->chunk;
+ bp->b_data = rsp->bufp;
+
+ /* Initiate read */
+ (*rsp->strat)(bp);
+
+ /* Wait for results */
+ s = splbio();
+ while ((bp->b_flags & B_DONE) == 0)
+ tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
+ if (bp->b_flags & B_ERROR)
+ error = (bp->b_error ? bp->b_error : EIO);
+ splx(s);
+
+ /* Dot counter */
+ printf(".");
+ if(!(++dotc % 40))
+ printf("\n");
+
+ done = bp->b_bcount - bp->b_resid;
+ bytes_left -= done;
+ rsp->offset += done;
+ rsp->bufp += done;
+
+ if(error || !done)
+ break;
+
+ if((rsp->offset == rsp->media_sz) && (bytes_left != 0)) {
+ printf("\nInsert next media and hit any key...");
+ cngetc();
+ printf("\n");
+ rsp->offset = 0;
+ }
+ }
+ printf("\n");
+ s = splbio();
+ splx(s);
+ return(error);
+}
+
+/*
+ * Functions supporting uncompression:
+ */
+/*
+ * Copy from the uncompression buffer to the ramdisk
+ */
+static int
+cpy_uncompressed(buf, nbyte, rsp)
+caddr_t buf;
+struct read_info *rsp;
+int nbyte;
+{
+ if((rsp->bufp + nbyte) >= rsp->ebufp)
+ return(0);
+ bcopy(buf, rsp->bufp, nbyte);
+ rsp->bufp += nbyte;
+ return(0);
+}
+
+/*
+ * Read a maximum of 'nbyte' bytes into 'buf'.
+ */
+static int
+rd_compressed(buf, nbyte, rsp)
+caddr_t buf;
+struct read_info *rsp;
+int nbyte;
+{
+ static int dotc = 0;
+ struct buf *bp;
+ int nread = 0;
+ int s;
+ int done, error;
+
+
+ error = 0;
+ bp = rsp->bp;
+ nbyte &= ~(DEV_BSIZE - 1);
+
+ while(nbyte > 0) {
+ s = splbio();
+ bp->b_flags = B_BUSY | B_PHYS | B_READ;
+ splx(s);
+ bp->b_blkno = btodb(rsp->offset);
+ bp->b_bcount = min(rsp->chunk, nbyte);
+ bp->b_data = buf;
+
+ /* Initiate read */
+ (*rsp->strat)(bp);
+
+ /* Wait for results */
+ s = splbio();
+ while ((bp->b_flags & B_DONE) == 0)
+ tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
+ if (bp->b_flags & B_ERROR)
+ error = (bp->b_error ? bp->b_error : EIO);
+ splx(s);
+
+ /* Dot counter */
+ printf(".");
+ if(!(++dotc % 40))
+ printf("\n");
+
+ done = bp->b_bcount - bp->b_resid;
+ nbyte -= done;
+ nread += done;
+ rsp->offset += done;
+
+ if(error || !done)
+ break;
+
+ if(rsp->offset == rsp->media_sz) {
+ printf("\nInsert next media and hit any key...");
+ if(cngetc() != '\n')
+ printf("\n");
+ rsp->offset = 0;
+ }
+ }
+ s = splbio();
+ splx(s);
+ return(nread);
+}
diff --git a/sys/arch/atari/dev/view.c b/sys/arch/atari/dev/view.c
new file mode 100644
index 00000000000..3b469d3c5ea
--- /dev/null
+++ b/sys/arch/atari/dev/view.c
@@ -0,0 +1,407 @@
+/* $NetBSD: view.c,v 1.1.1.1 1995/03/26 07:12:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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.
+ */
+
+/* The view major device is a placeholder device. It serves
+ * simply to map the semantics of a graphics dipslay to
+ * the semantics of a character block device. In other
+ * words the graphics system as currently built does not like to be
+ * refered to by open/close/ioctl. This device serves as
+ * a interface to graphics. */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <machine/cpu.h>
+#include <atari/dev/grfabs_reg.h>
+#include <atari/dev/viewioctl.h>
+#include <atari/dev/viewvar.h>
+#include "view.h"
+
+static void view_display __P((struct view_softc *));
+static void view_remove __P((struct view_softc *));
+static int view_setsize __P((struct view_softc *, struct view_size *));
+
+void viewclose __P((dev_t, int));
+int viewioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+int viewopen __P((dev_t, int));
+int viewmap __P((dev_t, int, int));
+
+int view_get_colormap __P((struct view_softc *, colormap_t *));
+int view_set_colormap __P((struct view_softc *, colormap_t *));
+
+int viewprobe ();
+
+struct view_softc views[NVIEW];
+static int view_inited;
+
+int view_default_x;
+int view_default_y;
+int view_default_width = 640;
+int view_default_height = 400;
+int view_default_depth = 1;
+
+/*
+ * functions for probeing.
+ */
+viewattach(cnt)
+ int cnt;
+{
+ viewprobe();
+ printf("%d view%s configured\n", NVIEW, NVIEW > 1 ? "s" : "");
+}
+
+/* this function is called early to set up a display. */
+viewprobe()
+{
+ int i;
+
+ if(view_inited)
+ return(1);
+
+ view_inited = 1;
+
+ for(i=0; i<NVIEW; i++) {
+ views[i].view = NULL;
+ views[i].flags = 0;
+ }
+ return(1);
+}
+
+
+/*
+ * Internal functions.
+ */
+
+static void
+view_display (vu)
+ struct view_softc *vu;
+{
+ int s, i;
+
+ if (vu == NULL)
+ return;
+
+ s = spltty ();
+
+ /*
+ * mark views that share this monitor as not displaying
+ */
+ for (i=0; i<NVIEW; i++) {
+ if(views[i].flags & VUF_DISPLAY)
+ views[i].flags &= ~VUF_DISPLAY;
+ }
+
+ vu->flags |= VUF_ADDED;
+ if (vu->view) {
+ vu->view->display.x = vu->size.x;
+ vu->view->display.y = vu->size.y;
+
+ grf_display_view(vu->view);
+
+ vu->size.x = vu->view->display.x;
+ vu->size.y = vu->view->display.y;
+ vu->flags |= VUF_DISPLAY;
+ }
+ splx(s);
+}
+
+/*
+ * remove a view from our added list if it is marked as displaying
+ * switch to a new display.
+ */
+static void
+view_remove(vu)
+ struct view_softc *vu;
+{
+ int i;
+
+ if ((vu->flags & VUF_ADDED) == 0)
+ return;
+
+ vu->flags &= ~VUF_ADDED;
+ if (vu->flags & VUF_DISPLAY) {
+ for (i = 0; i < NVIEW; i++) {
+ if((views[i].flags & VUF_ADDED) && &views[i] != vu) {
+ view_display(&views[i]);
+ break;
+ }
+ }
+ }
+ vu->flags &= ~VUF_DISPLAY;
+ grf_remove_view(vu->view);
+}
+
+static int
+view_setsize(vu, vs)
+ struct view_softc *vu;
+ struct view_size *vs;
+{
+ view_t *new, *old;
+ dimen_t ns;
+ int co, cs;
+
+ co = 0;
+ cs = 0;
+ if (vs->x != vu->size.x || vs->y != vu->size.y)
+ co = 1;
+
+ if (vs->width != vu->size.width || vs->height != vu->size.height ||
+ vs->depth != vu->size.depth)
+ cs = 1;
+
+ if (cs == 0 && co == 0)
+ return(0);
+
+ ns.width = vs->width;
+ ns.height = vs->height;
+
+ new = grf_alloc_view(NULL, &ns, vs->depth);
+ if (new == NULL)
+ return(ENOMEM);
+
+ old = vu->view;
+ vu->view = new;
+ vu->size.x = new->display.x;
+ vu->size.y = new->display.y;
+ vu->size.width = new->display.width;
+ vu->size.height = new->display.height;
+ vu->size.depth = new->bitmap->depth;
+ vu->size.x = vs->x;
+ vu->size.y = vs->y;
+
+ /*
+ * we need a custom remove here to avoid letting
+ * another view display mark as not added or displayed
+ */
+ if (vu->flags & VUF_DISPLAY) {
+ vu->flags &= ~(VUF_ADDED|VUF_DISPLAY);
+ view_display(vu);
+ }
+ grf_free_view(old);
+ return(0);
+}
+
+/*
+ * functions made available by conf.c
+ */
+
+/*ARGSUSED*/
+int viewopen(dev, flags)
+dev_t dev;
+int flags;
+{
+ dimen_t size;
+ struct view_softc *vu;
+
+ vu = &views[minor(dev)];
+
+ if(minor(dev) >= NVIEW)
+ return(EXDEV);
+ if(vu->flags & VUF_OPEN)
+ return(EBUSY);
+
+ vu->size.x = view_default_x;
+ vu->size.y = view_default_y;
+ size.width = vu->size.width = view_default_width;
+ size.height = vu->size.height = view_default_height;
+ vu->size.depth = view_default_depth;
+
+ vu->view = grf_alloc_view(NULL, &size, vu->size.depth);
+ if (vu->view == NULL)
+ return(ENOMEM);
+
+ vu->size.x = vu->view->display.x;
+ vu->size.y = vu->view->display.y;
+ vu->size.width = vu->view->display.width;
+ vu->size.height = vu->view->display.height;
+ vu->size.depth = vu->view->bitmap->depth;
+ vu->flags |= VUF_OPEN;
+ return(0);
+}
+
+/*ARGSUSED*/
+void
+viewclose (dev, flags)
+ dev_t dev;
+ int flags;
+{
+ struct view_softc *vu;
+
+ vu = &views[minor(dev)];
+
+ if ((vu->flags & VUF_OPEN) == 0)
+ return;
+ view_remove (vu);
+ grf_free_view (vu->view);
+ vu->flags = 0;
+ vu->view = NULL;
+}
+
+
+/*ARGSUSED*/
+int
+viewioctl (dev, cmd, data, flag, p)
+dev_t dev;
+u_long cmd;
+caddr_t data;
+int flag;
+struct proc *p;
+{
+ struct view_softc *vu;
+ bmap_t *bm;
+ int error;
+
+ vu = &views[minor(dev)];
+ error = 0;
+
+ switch (cmd) {
+ case VIOCDISPLAY:
+ view_display(vu);
+ break;
+ case VIOCREMOVE:
+ view_remove(vu);
+ break;
+ case VIOCGSIZE:
+ bcopy(&vu->size, data, sizeof (struct view_size));
+ break;
+ case VIOCSSIZE:
+ error = view_setsize(vu, (struct view_size *)data);
+ break;
+ case VIOCGBMAP:
+ bm = (bmap_t *)data;
+ bcopy(vu->view->bitmap, bm, sizeof(bmap_t));
+ if ((int)p != -1) {
+ bm->plane = NULL;
+ bm->hw_address = NULL;
+ }
+ break;
+ case VIOCGCMAP:
+ error = view_get_colormap(vu, (colormap_t *)data);
+ break;
+ case VIOCSCMAP:
+ error = view_set_colormap(vu, (colormap_t *)data);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return(error);
+}
+
+int view_get_colormap (vu, ucm)
+struct view_softc *vu;
+colormap_t *ucm;
+{
+ int error;
+ u_short *cme;
+ u_short *uep;
+
+ if(ucm->nentries > MAX_CENTRIES)
+ return(EINVAL);
+
+ /* add one incase of zero, ick. */
+ cme = malloc(sizeof(u_short) * (ucm->nentries+1),M_IOCTLOPS,M_WAITOK);
+ if (cme == NULL)
+ return(ENOMEM);
+
+ error = 0;
+ uep = ucm->centry;
+ ucm->centry = cme; /* set entry to out alloc. */
+ if(vu->view == NULL || grf_get_colormap(vu->view, ucm))
+ error = EINVAL;
+ else error = copyout(cme, uep, sizeof(u_short) * ucm->nentries);
+ ucm->centry = uep; /* set entry back to users. */
+ free(cme, M_IOCTLOPS);
+ return(error);
+}
+
+int view_set_colormap(vu, ucm)
+struct view_softc *vu;
+colormap_t *ucm;
+{
+ colormap_t *cm;
+ int error = 0;
+
+ if(ucm->nentries > MAX_CENTRIES)
+ return(EINVAL);
+
+ cm = malloc(sizeof(u_short) * ucm->nentries + sizeof(*cm), M_IOCTLOPS,
+ M_WAITOK);
+ if(cm == NULL)
+ return(ENOMEM);
+
+ bcopy(ucm, cm, sizeof(colormap_t));
+ cm->centry = (u_short *)&cm[1]; /* table directly after. */
+ if (((error =
+ copyin(ucm->centry,cm->centry,sizeof(u_short)*ucm->nentries)) == 0)
+ && (vu->view == NULL || grf_use_colormap(vu->view, cm)))
+ error = EINVAL;
+ free(cm, M_IOCTLOPS);
+ return(error);
+}
+
+/*ARGSUSED*/
+int
+viewmap(dev, off, prot)
+dev_t dev;
+int off, prot;
+{
+ struct view_softc *vu;
+ bmap_t *bm;
+ u_char *bmd_start;
+ u_long bmd_size;
+
+ vu = &views[minor(dev)];
+ bm = vu->view->bitmap;
+ bmd_start = bm->hw_address;
+ bmd_size = bm->bytes_per_row*bm->rows*bm->depth;
+
+ if (off >= 0 && off < bmd_size)
+ return(((u_int)bmd_start + off) >> PGSHIFT);
+
+ return(-1);
+}
+
+/*ARGSUSED*/
+int
+viewselect(dev, rw)
+dev_t dev;
+int rw;
+{
+ if(rw == FREAD)
+ return(0);
+ return(1);
+}
diff --git a/sys/arch/atari/dev/viewioctl.h b/sys/arch/atari/dev/viewioctl.h
new file mode 100644
index 00000000000..86b3970459e
--- /dev/null
+++ b/sys/arch/atari/dev/viewioctl.h
@@ -0,0 +1,57 @@
+/* $NetBSD: viewioctl.h,v 1.1.1.1 1995/03/26 07:12:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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.
+ */
+
+/*
+ * The view major device is a placeholder device. It serves
+ * simply to map the semantics of a graphics display to
+ * the semantics of a character block device. In other
+ * words the graphics system as currently built does not like to be
+ * refered to by open/close/ioctl. This device serves as
+ * a interface to graphics.
+ */
+
+struct view_size {
+ int x;
+ int y;
+ u_int width;
+ u_int height;
+ u_int depth;
+};
+
+#define VIOCREMOVE _IO('V', 0x0) /* if displaying remove. */
+#define VIOCDISPLAY _IO('V', 0x1) /* if not displaying, display */
+#define VIOCSSIZE _IOW('V', 0x2, struct view_size)
+#define VIOCGSIZE _IOR('V', 0x3, struct view_size)
+#define VIOCGBMAP _IOR('V', 0x4, bmap_t)
+#define VIOCSCMAP _IOW('V', 0x5, colormap_t)
+#define VIOCGCMAP _IOWR('V', 0x6, colormap_t)
+
diff --git a/sys/arch/atari/dev/viewvar.h b/sys/arch/atari/dev/viewvar.h
new file mode 100644
index 00000000000..3246a6b76c2
--- /dev/null
+++ b/sys/arch/atari/dev/viewvar.h
@@ -0,0 +1,60 @@
+/* $NetBSD: viewvar.h,v 1.1.1.1 1995/03/26 07:12:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 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.
+ */
+
+/* The view major device is a placeholder device. It serves
+ * simply to map the semantics of a graphics dipslay to
+ * the semantics of a character block device. In other
+ * words the graphics system as currently built does not like to be
+ * refered to by open/close/ioctl. This device serves as
+ * a interface to graphics. */
+
+struct view_softc {
+ struct view_size size;
+ view_t *view;
+ pid_t lock_process;
+ int flags;
+};
+
+enum view_unit_flag_bits {
+ VUB_OPEN,
+ VUB_ADDED,
+ VUB_DISPLAY,
+ VUB_LAST_BIT
+};
+
+enum view_unit_flags {
+ VUF_OPEN = 1<<VUB_OPEN,
+ VUF_ADDED = 1<<VUB_ADDED,
+ VUF_DISPLAY = 1<<VUB_DISPLAY,
+ VUF_MASK = ((1<<VUB_LAST_BIT)-1)
+};
+
diff --git a/sys/arch/atari/dev/vuid_event.h b/sys/arch/atari/dev/vuid_event.h
new file mode 100644
index 00000000000..8342f31f19b
--- /dev/null
+++ b/sys/arch/atari/dev/vuid_event.h
@@ -0,0 +1,87 @@
+/* $NetBSD: vuid_event.h,v 1.1.1.1 1995/03/26 07:12:11 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)vuid_event.h 8.1 (Berkeley) 6/11/93
+ *
+ * from: Header: vuid_event.h,v 1.4 92/11/26 01:20:27 torek Exp (LBL)
+ */
+
+/*
+ * The following is a minimal emulation of Sun's `Firm_event' structures
+ * and related operations necessary to make X11 happy (i.e., make it
+ * compile, and make old X11 binaries run).
+ */
+typedef struct firm_event {
+ u_short id; /* key or MS_* or LOC_[XY]_DELTA */
+ u_short pad; /* unused, at least by X11 */
+ int value; /* VKEY_{UP,DOWN} or locator delta */
+ struct timeval time;
+} Firm_event;
+
+/*
+ * Special `id' fields. These weird numbers simply match the old binaries.
+ * Others are in 0..0x7f and are keyboard key numbers (keyboard dependent!).
+ */
+#define MS_LEFT 0x7f20 /* left mouse button */
+#define MS_MIDDLE 0x7f21 /* middle mouse button */
+#define MS_RIGHT 0x7f22 /* right mouse button */
+#define LOC_X_DELTA 0x7f80 /* mouse delta-X */
+#define LOC_Y_DELTA 0x7f81 /* mouse delta-Y */
+
+/*
+ * Special `value' fields. These apply to keys and mouse buttons. The
+ * value of a mouse delta is the delta. Note that positive deltas are
+ * left and up (not left and down as you might expect).
+ */
+#define VKEY_UP 0 /* key or button went up */
+#define VKEY_DOWN 1 /* key or button went down */
+
+/*
+ * The following ioctls are clearly intended to take things in and out
+ * of `firm event' mode. Since we always run in this mode (as far as
+ * /dev/kbd and /dev/mouse are concerned, anyway), we always claim to
+ * be in this mode and reject anything else.
+ */
+#define VUIDSFORMAT _IOW('v', 1, int)
+#define VUIDGFORMAT _IOR('v', 2, int)
+#define VUID_FIRM_EVENT 1 /* the only format we support */
diff --git a/sys/arch/atari/dev/zs.c b/sys/arch/atari/dev/zs.c
new file mode 100644
index 00000000000..a700fc1137f
--- /dev/null
+++ b/sys/arch/atari/dev/zs.c
@@ -0,0 +1,1016 @@
+/* $NetBSD: zs.c,v 1.1.1.1 1995/03/26 07:12:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 L. Weppelman (Atari modifications)
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)zs.c 8.1 (Berkeley) 7/19/93
+ */
+
+/*
+ * Zilog Z8530 (ZSCC) driver.
+ *
+ * Runs two tty ports (modem2 and serial2) on zs0.
+ *
+ * This driver knows far too much about chip to usage mappings.
+ */
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+#include <machine/scu.h>
+#include <machine/mfp.h>
+
+#include <atari/dev/zsreg.h>
+#include <atari/dev/zsvar.h>
+#include "zs.h"
+#if NZS > 1
+#error "This driver supports only 1 85C30!"
+#endif
+
+#if NZS > 0
+
+#define PCLK (8000000) /* PCLK pin input clock rate */
+
+#define splzs spl5
+
+/*
+ * Software state per found chip.
+ */
+struct zs_softc {
+ struct device zi_dev; /* base device */
+ volatile struct zsdevice *zi_zs; /* chip registers */
+ struct zs_chanstate zi_cs[2]; /* chan A and B software state */
+};
+
+/*
+ * Define the registers for a closed port
+ */
+u_char zs_init_regs[16] = {
+/* 0 */ 0,
+/* 1 */ 0,
+/* 2 */ 0x60,
+/* 3 */ 0,
+/* 4 */ 0,
+/* 5 */ 0,
+/* 6 */ 0,
+/* 7 */ 0,
+/* 8 */ 0,
+/* 9 */ ZSWR9_VECTOR_INCL_STAT,
+/* 10 */ ZSWR10_NRZ,
+/* 11 */ ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
+/* 12 */ 0,
+/* 13 */ 0,
+/* 14 */ ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA,
+/* 15 */ 0
+};
+
+struct tty *zs_tty[NZS * 2]; /* XXX should be dynamic */
+
+/* Definition of the driver for autoconfig. */
+static int zsmatch __P((struct device *, struct cfdata *, void *));
+static void zsattach __P((struct device *, struct device *, void *));
+struct cfdriver zscd = {
+ NULL, "zs", (cfmatch_t)zsmatch, zsattach, DV_TTY,
+ sizeof(struct zs_softc), NULL, 0 };
+
+/* Interrupt handlers. */
+int zshard __P((long));
+static int zssoft __P((long));
+static int zsrint __P((struct zs_chanstate *, volatile struct zschan *));
+static int zsxint __P((struct zs_chanstate *, volatile struct zschan *));
+static int zssint __P((struct zs_chanstate *, volatile struct zschan *));
+
+struct zs_chanstate *zslist;
+
+/* Routines called from other code. */
+static void zsstart __P((struct tty *));
+void zsstop __P((struct tty *, int));
+static int zsparam __P((struct tty *, struct termios *));
+
+/* Routines purely local to this driver. */
+static void zs_reset __P((volatile struct zschan *, int, int));
+static int zs_modem __P((struct zs_chanstate *, int, int));
+static void zs_loadchannelregs __P((volatile struct zschan *, u_char *));
+
+int zsshortcuts; /* number of "shortcut" software interrupts */
+
+static int zsmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp("zs", auxp) || cfp->cf_unit != 0)
+ return(0);
+ return(1);
+}
+
+/*
+ * Attach a found zs.
+ */
+static void
+zsattach(parent, dev, aux)
+struct device *parent;
+struct device *dev;
+void *aux;
+{
+ register struct zs_softc *zi;
+ register struct zs_chanstate *cs;
+ register volatile struct zsdevice *addr;
+ register struct tty *tp;
+ char tmp;
+
+ addr = (struct zsdevice *)AD_SCC;
+ zi = (struct zs_softc *)dev;
+ zi->zi_zs = addr;
+ cs = zi->zi_cs;
+
+ /*
+ * Get the command register into a known state.
+ */
+ tmp = addr->zs_chan[CHAN_A].zc_csr;
+ tmp = addr->zs_chan[CHAN_A].zc_csr;
+ tmp = addr->zs_chan[CHAN_B].zc_csr;
+ tmp = addr->zs_chan[CHAN_B].zc_csr;
+
+ /*
+ * Do a hardware reset.
+ */
+ ZS_WRITE(&addr->zs_chan[CHAN_A], 9, ZSWR9_HARD_RESET);
+ delay(50000); /*enough ? */
+ ZS_WRITE(&addr->zs_chan[CHAN_A], 9, 0);
+
+ /*
+ * Initialize both channels
+ */
+ zs_loadchannelregs(&addr->zs_chan[CHAN_A], zs_init_regs);
+ zs_loadchannelregs(&addr->zs_chan[CHAN_B], zs_init_regs);
+
+ /*
+ * enable scc related interrupts
+ */
+ SCU->sys_mask |= SCU_SCC;
+
+ /* link into interrupt list with order (A,B) (B=A+1) */
+ cs[0].cs_next = &cs[1];
+ cs[1].cs_next = zslist;
+ zslist = cs;
+
+ cs->cs_unit = 0;
+ cs->cs_zc = &addr->zs_chan[CHAN_A];
+ cs++;
+ cs->cs_unit = 1;
+ cs->cs_zc = &addr->zs_chan[CHAN_B];
+
+ printf(": serial2 on channel a and modem2 on channel b\n");
+}
+
+/*
+ * Open a zs serial port.
+ */
+int
+zsopen(dev, flags, mode, p)
+dev_t dev;
+int flags;
+int mode;
+struct proc *p;
+{
+ register struct tty *tp;
+ register struct zs_chanstate *cs;
+ struct zs_softc *zi;
+ int unit = ZS_UNIT(dev);
+ int zs = unit >> 1;
+ int error, s;
+
+ if(zs >= zscd.cd_ndevs || (zi = zscd.cd_devs[zs]) == NULL)
+ return (ENXIO);
+ cs = &zi->zi_cs[unit & 1];
+ tp = cs->cs_ttyp;
+ if(tp == NULL) {
+ cs->cs_ttyp = tp = zs_tty[unit] = ttymalloc();
+ tp->t_dev = dev;
+ tp->t_oproc = zsstart;
+ tp->t_param = zsparam;
+ }
+
+ s = spltty();
+ if((tp->t_state & TS_ISOPEN) == 0) {
+ ttychars(tp);
+ if(tp->t_ispeed == 0) {
+ 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;
+ }
+ (void)zsparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+ }
+ else if(tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
+ splx(s);
+ return (EBUSY);
+ }
+ error = 0;
+ for(;;) {
+ /* loop, turning on the device, until carrier present */
+ zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR, DMSET);
+ if(cs->cs_softcar)
+ tp->t_state |= TS_CARR_ON;
+ if(flags & O_NONBLOCK || tp->t_cflag & CLOCAL ||
+ tp->t_state & TS_CARR_ON)
+ break;
+ tp->t_state |= TS_WOPEN;
+ if(error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
+ ttopen, 0)) {
+ if(!(tp->t_state & TS_ISOPEN)) {
+ zs_modem(cs, 0, DMSET);
+ tp->t_state &= ~TS_WOPEN;
+ ttwakeup(tp);
+ }
+ splx(s);
+ return error;
+ }
+ }
+ splx(s);
+ if(error == 0)
+ error = linesw[tp->t_line].l_open(dev, tp);
+ if(error)
+ zs_modem(cs, 0, DMSET);
+ return(error);
+}
+
+/*
+ * Close a zs serial port.
+ */
+int
+zsclose(dev, flags, mode, p)
+dev_t dev;
+int flags;
+int mode;
+struct proc *p;
+{
+ register struct zs_chanstate *cs;
+ register struct tty *tp;
+ struct zs_softc *zi;
+ int unit = ZS_UNIT(dev);
+ int s;
+
+ zi = zscd.cd_devs[unit >> 1];
+ cs = &zi->zi_cs[unit & 1];
+ tp = cs->cs_ttyp;
+ linesw[tp->t_line].l_close(tp, flags);
+ if(tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
+ (tp->t_state & TS_ISOPEN) == 0) {
+ zs_modem(cs, 0, DMSET);
+ /* hold low for 1 second */
+ (void)tsleep((caddr_t)cs, TTIPRI, ttclos, hz);
+ }
+ if(cs->cs_creg[5] & ZSWR5_BREAK) {
+ s = splzs();
+ cs->cs_preg[5] &= ~ZSWR5_BREAK;
+ cs->cs_creg[5] &= ~ZSWR5_BREAK;
+ ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
+ splx(s);
+ }
+ ttyclose(tp);
+
+ /*
+ * Drop all lines and cancel interrupts
+ */
+ zs_loadchannelregs(&zi->zi_zs->zs_chan[unit & 1], zs_init_regs);
+ return (0);
+}
+
+/*
+ * Read/write zs serial port.
+ */
+int
+zsread(dev, uio, flags)
+dev_t dev;
+struct uio *uio;
+int flags;
+{
+ register struct tty *tp = zs_tty[ZS_UNIT(dev)];
+
+ return(linesw[tp->t_line].l_read(tp, uio, flags));
+}
+
+int zswrite(dev, uio, flags)
+dev_t dev;
+struct uio *uio;
+int flags;
+{
+ register struct tty *tp = zs_tty[ZS_UNIT(dev)];
+
+ return(linesw[tp->t_line].l_write(tp, uio, flags));
+}
+
+/*
+ * ZS hardware interrupt. Scan all ZS channels. NB: we know here that
+ * channels are kept in (A,B) pairs.
+ *
+ * Do just a little, then get out; set a software interrupt if more
+ * work is needed.
+ *
+ * We deliberately ignore the vectoring Zilog gives us, and match up
+ * only the number of `reset interrupt under service' operations, not
+ * the order.
+ */
+int
+zshard(sr)
+long sr;
+{
+ register struct zs_chanstate *a;
+#define b (a + 1)
+ register volatile struct zschan *zc;
+ register int rr3, intflags = 0, v, i;
+
+ for(a = zslist; a != NULL; a = b->cs_next) {
+ rr3 = ZS_READ(a->cs_zc, 3);
+ if(rr3 & (ZSRR3_IP_A_RX|ZSRR3_IP_A_TX|ZSRR3_IP_A_STAT)) {
+ intflags |= 2;
+ zc = a->cs_zc;
+ i = a->cs_rbput;
+ if(rr3 & ZSRR3_IP_A_RX && (v = zsrint(a, zc)) != 0) {
+ a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ if(rr3 & ZSRR3_IP_A_TX && (v = zsxint(a, zc)) != 0) {
+ a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ if(rr3 & ZSRR3_IP_A_STAT && (v = zssint(a, zc)) != 0) {
+ a->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ a->cs_rbput = i;
+ }
+ if(rr3 & (ZSRR3_IP_B_RX|ZSRR3_IP_B_TX|ZSRR3_IP_B_STAT)) {
+ intflags |= 2;
+ zc = b->cs_zc;
+ i = b->cs_rbput;
+ if(rr3 & ZSRR3_IP_B_RX && (v = zsrint(b, zc)) != 0) {
+ b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ if(rr3 & ZSRR3_IP_B_TX && (v = zsxint(b, zc)) != 0) {
+ b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ if(rr3 & ZSRR3_IP_B_STAT && (v = zssint(b, zc)) != 0) {
+ b->cs_rbuf[i++ & ZLRB_RING_MASK] = v;
+ intflags |= 1;
+ }
+ b->cs_rbput = i;
+ }
+ }
+#undef b
+
+ if(intflags & 1) {
+ if(BASEPRI(sr)) {
+ spl1();
+ zsshortcuts++;
+ return(zssoft(sr));
+ }
+ else add_sicallback(zssoft, 0, 0);
+ }
+ return(intflags & 2);
+}
+
+static int
+zsrint(cs, zc)
+register struct zs_chanstate *cs;
+register volatile struct zschan *zc;
+{
+ register int c = zc->zc_data;
+
+ /* compose receive character and status */
+ c <<= 8;
+ c |= ZS_READ(zc, 1);
+
+ /* clear receive error & interrupt condition */
+ zc->zc_csr = ZSWR0_RESET_ERRORS;
+ zc->zc_csr = ZSWR0_CLR_INTR;
+
+ return(ZRING_MAKE(ZRING_RINT, c));
+}
+
+static int
+zsxint(cs, zc)
+register struct zs_chanstate *cs;
+register volatile struct zschan *zc;
+{
+ register int i = cs->cs_tbc;
+
+ if(i == 0) {
+ zc->zc_csr = ZSWR0_RESET_TXINT;
+ zc->zc_csr = ZSWR0_CLR_INTR;
+ return(ZRING_MAKE(ZRING_XINT, 0));
+ }
+ cs->cs_tbc = i - 1;
+ zc->zc_data = *cs->cs_tba++;
+ zc->zc_csr = ZSWR0_CLR_INTR;
+ return (0);
+}
+
+static int
+zssint(cs, zc)
+register struct zs_chanstate *cs;
+register volatile struct zschan *zc;
+{
+ register int rr0;
+
+ rr0 = zc->zc_csr;
+ zc->zc_csr = ZSWR0_RESET_STATUS;
+ zc->zc_csr = ZSWR0_CLR_INTR;
+ /*
+ * The chip's hardware flow control is, as noted in zsreg.h,
+ * busted---if the DCD line goes low the chip shuts off the
+ * receiver (!). If we want hardware CTS flow control but do
+ * not have it, and carrier is now on, turn HFC on; if we have
+ * HFC now but carrier has gone low, turn it off.
+ */
+ if(rr0 & ZSRR0_DCD) {
+ if(cs->cs_ttyp->t_cflag & CCTS_OFLOW &&
+ (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
+ cs->cs_creg[3] |= ZSWR3_HFC;
+ ZS_WRITE(zc, 3, cs->cs_creg[3]);
+ }
+ }
+ else {
+ if (cs->cs_creg[3] & ZSWR3_HFC) {
+ cs->cs_creg[3] &= ~ZSWR3_HFC;
+ ZS_WRITE(zc, 3, cs->cs_creg[3]);
+ }
+ }
+ return(ZRING_MAKE(ZRING_SINT, rr0));
+}
+
+/*
+ * Print out a ring or fifo overrun error message.
+ */
+static void
+zsoverrun(unit, ptime, what)
+int unit;
+long *ptime;
+char *what;
+{
+
+ if(*ptime != time.tv_sec) {
+ *ptime = time.tv_sec;
+ log(LOG_WARNING, "zs%d%c: %s overrun\n", unit >> 1,
+ (unit & 1) + 'a', what);
+ }
+}
+
+/*
+ * ZS software interrupt. Scan all channels for deferred interrupts.
+ */
+int
+zssoft(sr)
+long sr;
+{
+ register struct zs_chanstate *cs;
+ register volatile struct zschan *zc;
+ register struct linesw *line;
+ register struct tty *tp;
+ register int get, n, c, cc, unit, s;
+ int retval = 0;
+
+ s = spltty();
+ for(cs = zslist; cs != NULL; cs = cs->cs_next) {
+ get = cs->cs_rbget;
+again:
+ n = cs->cs_rbput; /* atomic */
+ if(get == n) /* nothing more on this line */
+ continue;
+ retval = 1;
+ unit = cs->cs_unit; /* set up to handle interrupts */
+ zc = cs->cs_zc;
+ tp = cs->cs_ttyp;
+ line = &linesw[tp->t_line];
+ /*
+ * Compute the number of interrupts in the receive ring.
+ * If the count is overlarge, we lost some events, and
+ * must advance to the first valid one. It may get
+ * overwritten if more data are arriving, but this is
+ * too expensive to check and gains nothing (we already
+ * lost out; all we can do at this point is trade one
+ * kind of loss for another).
+ */
+ n -= get;
+ if(n > ZLRB_RING_SIZE) {
+ zsoverrun(unit, &cs->cs_rotime, "ring");
+ get += n - ZLRB_RING_SIZE;
+ n = ZLRB_RING_SIZE;
+ }
+ while(--n >= 0) {
+ /* race to keep ahead of incoming interrupts */
+ c = cs->cs_rbuf[get++ & ZLRB_RING_MASK];
+ switch (ZRING_TYPE(c)) {
+
+ case ZRING_RINT:
+ c = ZRING_VALUE(c);
+ if(c & ZSRR1_DO)
+ zsoverrun(unit, &cs->cs_fotime, "fifo");
+ cc = c >> 8;
+ if(c & ZSRR1_FE)
+ cc |= TTY_FE;
+ if(c & ZSRR1_PE)
+ cc |= TTY_PE;
+ line->l_rint(cc, tp);
+ break;
+
+ case ZRING_XINT:
+ /*
+ * Transmit done: change registers and resume,
+ * or clear BUSY.
+ */
+ if(cs->cs_heldchange) {
+ int sps;
+
+ sps = splzs();
+ c = zc->zc_csr;
+ if((c & ZSRR0_DCD) == 0)
+ cs->cs_preg[3] &= ~ZSWR3_HFC;
+ bcopy((caddr_t)cs->cs_preg,
+ (caddr_t)cs->cs_creg, 16);
+ zs_loadchannelregs(zc, cs->cs_creg);
+ splx(sps);
+ cs->cs_heldchange = 0;
+ if(cs->cs_heldtbc
+ && (tp->t_state & TS_TTSTOP) == 0) {
+ cs->cs_tbc = cs->cs_heldtbc - 1;
+ zc->zc_data = *cs->cs_tba++;
+ goto again;
+ }
+ }
+ tp->t_state &= ~TS_BUSY;
+ if(tp->t_state & TS_FLUSH)
+ tp->t_state &= ~TS_FLUSH;
+ else ndflush(&tp->t_outq,cs->cs_tba
+ - (caddr_t)tp->t_outq.c_cf);
+ line->l_start(tp);
+ break;
+
+ case ZRING_SINT:
+ /*
+ * Status line change. HFC bit is run in
+ * hardware interrupt, to avoid locking
+ * at splzs here.
+ */
+ c = ZRING_VALUE(c);
+ if((c ^ cs->cs_rr0) & ZSRR0_DCD) {
+ cc = (c & ZSRR0_DCD) != 0;
+ if(line->l_modem(tp, cc) == 0)
+ zs_modem(cs, ZSWR5_RTS|ZSWR5_DTR,
+ cc ? DMBIS : DMBIC);
+ }
+ cs->cs_rr0 = c;
+ break;
+
+ default:
+ log(LOG_ERR, "zs%d%c: bad ZRING_TYPE (%x)\n",
+ unit >> 1, (unit & 1) + 'a', c);
+ break;
+ }
+ }
+ cs->cs_rbget = get;
+ goto again;
+ }
+ splx(s);
+ return (retval);
+}
+
+int
+zsioctl(dev, cmd, data, flag, p)
+dev_t dev;
+u_long cmd;
+caddr_t data;
+int flag;
+struct proc *p;
+{
+ int unit = ZS_UNIT(dev);
+ struct zs_softc *zi = zscd.cd_devs[unit >> 1];
+ register struct tty *tp = zi->zi_cs[unit & 1].cs_ttyp;
+ register int error, s;
+ register struct zs_chanstate *cs = &zi->zi_cs[unit & 1];
+
+ 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:
+ s = splzs();
+ cs->cs_preg[5] |= ZSWR5_BREAK;
+ cs->cs_creg[5] |= ZSWR5_BREAK;
+ ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
+ splx(s);
+ break;
+ case TIOCCBRK:
+ s = splzs();
+ cs->cs_preg[5] &= ~ZSWR5_BREAK;
+ cs->cs_creg[5] &= ~ZSWR5_BREAK;
+ ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
+ splx(s);
+ break;
+ case TIOCGFLAGS: {
+ int bits = 0;
+
+ if(cs->cs_softcar)
+ bits |= TIOCFLAG_SOFTCAR;
+ if(cs->cs_creg[15] & ZSWR15_DCD_IE)
+ bits |= TIOCFLAG_CLOCAL;
+ if(cs->cs_creg[3] & ZSWR3_HFC)
+ bits |= TIOCFLAG_CRTSCTS;
+ *(int *)data = bits;
+ break;
+ }
+ case TIOCSFLAGS: {
+ int userbits, driverbits = 0;
+
+ error = suser(p->p_ucred, &p->p_acflag);
+ if(error != 0)
+ return (EPERM);
+
+ userbits = *(int *)data;
+
+ /*
+ * can have `local' or `softcar', and `rtscts' or `mdmbuf'
+ # defaulting to software flow control.
+ */
+ if(userbits & TIOCFLAG_SOFTCAR && userbits & TIOCFLAG_CLOCAL)
+ return(EINVAL);
+ if(userbits & TIOCFLAG_MDMBUF) /* don't support this (yet?) */
+ return(ENXIO);
+
+ s = splzs();
+ if((userbits & TIOCFLAG_SOFTCAR)) {
+ cs->cs_softcar = 1; /* turn on softcar */
+ cs->cs_preg[15] &= ~ZSWR15_DCD_IE; /* turn off dcd */
+ cs->cs_creg[15] &= ~ZSWR15_DCD_IE;
+ ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
+ }
+ else if(userbits & TIOCFLAG_CLOCAL) {
+ cs->cs_softcar = 0; /* turn off softcar */
+ cs->cs_preg[15] |= ZSWR15_DCD_IE; /* turn on dcd */
+ cs->cs_creg[15] |= ZSWR15_DCD_IE;
+ ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
+ tp->t_termios.c_cflag |= CLOCAL;
+ }
+ if(userbits & TIOCFLAG_CRTSCTS) {
+ cs->cs_preg[15] |= ZSWR15_CTS_IE;
+ cs->cs_creg[15] |= ZSWR15_CTS_IE;
+ ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
+ cs->cs_preg[3] |= ZSWR3_HFC;
+ cs->cs_creg[3] |= ZSWR3_HFC;
+ ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]);
+ tp->t_termios.c_cflag |= CRTSCTS;
+ }
+ else {
+ /* no mdmbuf, so we must want software flow control */
+ cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
+ cs->cs_creg[15] &= ~ZSWR15_CTS_IE;
+ ZS_WRITE(cs->cs_zc, 15, cs->cs_creg[15]);
+ cs->cs_preg[3] &= ~ZSWR3_HFC;
+ cs->cs_creg[3] &= ~ZSWR3_HFC;
+ ZS_WRITE(cs->cs_zc, 3, cs->cs_creg[3]);
+ tp->t_termios.c_cflag &= ~CRTSCTS;
+ }
+ splx(s);
+ break;
+ }
+ case TIOCSDTR:
+ zs_modem(cs, ZSWR5_DTR, DMBIS);
+ break;
+ case TIOCCDTR:
+ zs_modem(cs, ZSWR5_DTR, DMBIC);
+ break;
+ case TIOCMGET:
+ zs_modem(cs, 0, DMGET);
+ break;
+ case TIOCMSET:
+ case TIOCMBIS:
+ case TIOCMBIC:
+ default:
+ return (ENOTTY);
+ }
+ return (0);
+}
+
+/*
+ * Start or restart transmission.
+ */
+static void
+zsstart(tp)
+register struct tty *tp;
+{
+ register struct zs_chanstate *cs;
+ register int s, nch;
+ int unit = ZS_UNIT(tp->t_dev);
+ struct zs_softc *zi = zscd.cd_devs[unit >> 1];
+
+ cs = &zi->zi_cs[unit & 1];
+ s = spltty();
+
+ /*
+ * If currently active or delaying, no need to do anything.
+ */
+ if(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
+ goto out;
+
+ /*
+ * If there are sleepers, and output has drained below low
+ * water mark, awaken.
+ */
+ if(tp->t_outq.c_cc <= tp->t_lowat) {
+ if(tp->t_state & TS_ASLEEP) {
+ tp->t_state &= ~TS_ASLEEP;
+ wakeup((caddr_t)&tp->t_outq);
+ }
+ selwakeup(&tp->t_wsel);
+ }
+
+ nch = ndqb(&tp->t_outq, 0); /* XXX */
+ if(nch) {
+ register char *p = tp->t_outq.c_cf;
+
+ /* mark busy, enable tx done interrupts, & send first byte */
+ tp->t_state |= TS_BUSY;
+ (void) splzs();
+ cs->cs_preg[1] |= ZSWR1_TIE;
+ cs->cs_creg[1] |= ZSWR1_TIE;
+ ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]);
+ cs->cs_zc->zc_data = *p;
+ cs->cs_tba = p + 1;
+ cs->cs_tbc = nch - 1;
+ } else {
+ /*
+ * Nothing to send, turn off transmit done interrupts.
+ * This is useful if something is doing polled output.
+ */
+ (void) splzs();
+ cs->cs_preg[1] &= ~ZSWR1_TIE;
+ cs->cs_creg[1] &= ~ZSWR1_TIE;
+ ZS_WRITE(cs->cs_zc, 1, cs->cs_creg[1]);
+ }
+out:
+ splx(s);
+}
+
+/*
+ * Stop output, e.g., for ^S or output flush.
+ */
+void
+zsstop(tp, flag)
+register struct tty *tp;
+ int flag;
+{
+ register struct zs_chanstate *cs;
+ register int s, unit = ZS_UNIT(tp->t_dev);
+ struct zs_softc *zi = zscd.cd_devs[unit >> 1];
+
+ cs = &zi->zi_cs[unit & 1];
+ s = splzs();
+ if(tp->t_state & TS_BUSY) {
+ /*
+ * Device is transmitting; must stop it.
+ */
+ cs->cs_tbc = 0;
+ if ((tp->t_state & TS_TTSTOP) == 0)
+ tp->t_state |= TS_FLUSH;
+ }
+ splx(s);
+}
+
+/*
+ * Set ZS tty parameters from termios.
+ *
+ * This routine makes use of the fact that only registers
+ * 1, 3, 4, 5, 9, 10, 11, 12, 13, 14, and 15 are written.
+ */
+static int
+zsparam(tp, t)
+register struct tty *tp;
+register struct termios *t;
+{
+ int unit = ZS_UNIT(tp->t_dev);
+ struct zs_softc *zi = zscd.cd_devs[unit >> 1];
+ register struct zs_chanstate *cs = &zi->zi_cs[unit & 1];
+ register int tmp, tmp5, cflag, s;
+
+ tmp = t->c_ospeed;
+ if(tmp < 0 || (t->c_ispeed && t->c_ispeed != tmp))
+ return(EINVAL);
+ if(tmp == 0) {
+ /* stty 0 => drop DTR and RTS */
+ zs_modem(cs, 0, DMSET);
+ return(0);
+ }
+ tmp = BPS_TO_TCONST(PCLK / 16, tmp);
+ if(tmp < 2)
+ return(EINVAL);
+
+ cflag = t->c_cflag;
+ tp->t_ispeed = tp->t_ospeed = TCONST_TO_BPS(PCLK / 16, tmp);
+ tp->t_cflag = cflag;
+
+ /*
+ * Block interrupts so that state will not
+ * be altered until we are done setting it up.
+ */
+ s = splzs();
+ cs->cs_preg[12] = tmp;
+ cs->cs_preg[13] = tmp >> 8;
+ cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE;
+ switch(cflag & CSIZE) {
+ case CS5:
+ tmp = ZSWR3_RX_5;
+ tmp5 = ZSWR5_TX_5;
+ break;
+ case CS6:
+ tmp = ZSWR3_RX_6;
+ tmp5 = ZSWR5_TX_6;
+ break;
+ case CS7:
+ tmp = ZSWR3_RX_7;
+ tmp5 = ZSWR5_TX_7;
+ break;
+ case CS8:
+ default:
+ tmp = ZSWR3_RX_8;
+ tmp5 = ZSWR5_TX_8;
+ break;
+ }
+
+ /*
+ * Output hardware flow control on the chip is horrendous: if
+ * carrier detect drops, the receiver is disabled. Hence we
+ * can only do this when the carrier is on.
+ */
+ if(cflag & CCTS_OFLOW && cs->cs_zc->zc_csr & ZSRR0_DCD)
+ tmp |= ZSWR3_HFC | ZSWR3_RX_ENABLE;
+ else tmp |= ZSWR3_RX_ENABLE;
+ cs->cs_preg[3] = tmp;
+ cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
+
+ tmp = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
+ if((cflag & PARODD) == 0)
+ tmp |= ZSWR4_EVENP;
+ if (cflag & PARENB)
+ tmp |= ZSWR4_PARENB;
+ cs->cs_preg[4] = tmp;
+ cs->cs_preg[9] = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT;
+ cs->cs_preg[10] = ZSWR10_NRZ;
+ cs->cs_preg[11] = ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD;
+ cs->cs_preg[14] = ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA;
+ cs->cs_preg[15] = ZSWR15_BREAK_IE | ZSWR15_DCD_IE;
+
+ /*
+ * If nothing is being transmitted, set up new current values,
+ * else mark them as pending.
+ */
+ if(cs->cs_heldchange == 0) {
+ if (cs->cs_ttyp->t_state & TS_BUSY) {
+ cs->cs_heldtbc = cs->cs_tbc;
+ cs->cs_tbc = 0;
+ cs->cs_heldchange = 1;
+ }
+ else {
+ bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16);
+ zs_loadchannelregs(cs->cs_zc, cs->cs_creg);
+ }
+ }
+ splx(s);
+ return (0);
+}
+
+/*
+ * Raise or lower modem control (DTR/RTS) signals. If a character is
+ * in transmission, the change is deferred.
+ */
+static int
+zs_modem(cs, bits, how)
+struct zs_chanstate *cs;
+int bits, how;
+{
+ int s, mbits;
+
+ bits &= ZSWR5_DTR | ZSWR5_RTS;
+
+ s = splzs();
+ mbits = cs->cs_preg[5] & (ZSWR5_DTR | ZSWR5_RTS);
+
+ switch(how) {
+ case DMSET:
+ mbits = bits;
+ break;
+ case DMBIS:
+ mbits |= bits;
+ break;
+ case DMBIC:
+ mbits &= ~bits;
+ break;
+ case DMGET:
+ splx(s);
+ return(mbits);
+ }
+
+ cs->cs_preg[5] = (cs->cs_preg[5] & ~(ZSWR5_DTR | ZSWR5_RTS)) | mbits;
+ if(cs->cs_heldchange == 0) {
+ if(cs->cs_ttyp->t_state & TS_BUSY) {
+ cs->cs_heldtbc = cs->cs_tbc;
+ cs->cs_tbc = 0;
+ cs->cs_heldchange = 1;
+ }
+ else {
+ ZS_WRITE(cs->cs_zc, 5, cs->cs_creg[5]);
+ }
+ }
+ splx(s);
+ return(0);
+}
+
+/*
+ * Write the given register set to the given zs channel in the proper order.
+ * The channel must not be transmitting at the time. The receiver will
+ * be disabled for the time it takes to write all the registers.
+ */
+static void
+zs_loadchannelregs(zc, reg)
+volatile struct zschan *zc;
+u_char *reg;
+{
+ int i;
+
+ zc->zc_csr = ZSM_RESET_ERR; /* reset error condition */
+ i = zc->zc_data; /* drain fifo */
+ i = zc->zc_data;
+ i = zc->zc_data;
+ ZS_WRITE(zc, 4, reg[4]);
+ ZS_WRITE(zc, 10, reg[10]);
+ ZS_WRITE(zc, 3, reg[3] & ~ZSWR3_RX_ENABLE);
+ ZS_WRITE(zc, 5, reg[5] & ~ZSWR5_TX_ENABLE);
+ ZS_WRITE(zc, 1, reg[1]);
+ ZS_WRITE(zc, 9, reg[9]);
+ ZS_WRITE(zc, 11, reg[11]);
+ ZS_WRITE(zc, 12, reg[12]);
+ ZS_WRITE(zc, 13, reg[13]);
+ ZS_WRITE(zc, 14, reg[14]);
+ ZS_WRITE(zc, 15, reg[15]);
+ ZS_WRITE(zc, 3, reg[3]);
+ ZS_WRITE(zc, 5, reg[5]);
+}
+#endif /* NZS > 1 */
diff --git a/sys/arch/atari/dev/zsreg.h b/sys/arch/atari/dev/zsreg.h
new file mode 100644
index 00000000000..ae57dc06e4e
--- /dev/null
+++ b/sys/arch/atari/dev/zsreg.h
@@ -0,0 +1,428 @@
+/* $NetBSD: zsreg.h,v 1.1.1.1 1995/03/26 07:12:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)zsreg.h 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Zilog SCC registers, as implemented on the Sun-4c.
+ *
+ * Each Z8530 implements two channels (called `a' and `b').
+ *
+ * The damnable chip was designed to fit on Z80 I/O ports, and thus
+ * has everything multiplexed out the wazoo. We have to select
+ * a register, then read or write the register, and so on. Worse,
+ * the parameter bits are scattered all over the register space.
+ * This thing is full of `miscellaneous' control registers.
+ *
+ * Worse yet, the registers have incompatible functions on read
+ * and write operations. We describe the registers below according
+ * to whether they are `read registers' (RR) or `write registers' (WR).
+ * As if this were not enough, some of the channel B status bits show
+ * up in channel A, and vice versa. The blasted thing shares write
+ * registers 2 and 9 across both channels, and reads registers 2 and 3
+ * differently for the two channels. We can, however, ignore this much
+ * of the time.
+ */
+#ifndef LOCORE
+struct zschan {
+ u_char zc_xxx0;
+ u_char zc_csr; /* control and status, and indirect access */
+ u_char zc_xxx1;
+ u_char zc_data; /* data */
+};
+
+struct zsdevice {
+ struct zschan zs_chan[2]; /* channel A = 0, B = 1 */
+};
+
+#define CHAN_A 0
+#define CHAN_B 1
+#endif
+
+/*
+ * Some of the names in this files were chosen to make the hsis driver
+ * work unchanged (which means that they will match some in SunOS).
+ *
+ * `S.C.' stands for Special Condition, which is any of these:
+ * receiver overrun (aka silo overflow)
+ * framing error (missing stop bit, etc)
+ * end of frame (in synchronous modes)
+ * parity error (when `parity error is S.C.' is set)
+ */
+
+/*
+ * Registers with only a single `numeric value' get a name.
+ * Other registers hold bits and are only numbered; the bit
+ * definitions imply the register number (see below).
+ *
+ * We never use the receive and transmit data registers as
+ * indirects (choosing instead the zc_data register), so they
+ * are not defined here.
+ */
+#define ZSRR_IVEC 2 /* interrupt vector (channel 0) */
+#define ZSRR_IPEND 3 /* interrupt pending (ch. 0 only) */
+#define ZSRR_BAUDLO 12 /* baud rate generator (low half) */
+#define ZSRR_BAUDHI 13 /* baud rate generator (high half) */
+
+#define ZSWR_IVEC 2 /* interrupt vector (shared) */
+#define ZSWR_TXSYNC 6 /* sync transmit char (monosync mode) */
+#define ZSWR_RXSYNC 7 /* sync receive char (monosync mode) */
+#define ZSWR_SYNCLO 6 /* sync low byte (bisync mode) */
+#define ZSWR_SYNCHI 7 /* sync high byte (bisync mode) */
+#define ZSWR_SDLC_ADDR 6 /* SDLC address (SDLC mode) */
+#define ZSWR_SDLC_FLAG 7 /* SDLC flag 0x7E (SDLC mode) */
+#define ZSWR_BAUDLO 12 /* baud rate generator (low half) */
+#define ZSWR_BAUDHI 13 /* baud rate generator (high half) */
+
+/*
+ * Registers 0 through 7 may be written with any one of the 8 command
+ * modifiers, and/or any one of the 4 reset modifiers, defined below.
+ * To write registers 8 through 15, however, the command modifier must
+ * always be `point high'. Rather than track this bizzareness all over
+ * the driver, we try to avoid using any modifiers, ever (but they are
+ * defined here if you want them).
+ */
+#define ZSM_RESET_TXUEOM 0xc0 /* reset xmit underrun / eom latch */
+#define ZSM_RESET_TXCRC 0x80 /* reset xmit crc generator */
+#define ZSM_RESET_RXCRC 0x40 /* reset recv crc checker */
+#define ZSM_NULL 0x00 /* nothing special */
+
+#define ZSM_RESET_IUS 0x38 /* reset interrupt under service */
+#define ZSM_RESET_ERR 0x30 /* reset error cond */
+#define ZSM_RESET_TXINT 0x28 /* reset xmit interrupt pending */
+#define ZSM_EI_NEXTRXC 0x20 /* enable int. on next rcvd char */
+#define ZSM_SEND_ABORT 0x18 /* send abort (SDLC) */
+#define ZSM_RESET_STINT 0x10 /* reset external/status interrupt */
+#define ZSM_POINTHIGH 0x08 /* `point high' (use r8-r15) */
+#define ZSM_NULL 0x00 /* nothing special */
+
+/*
+ * Commands for Write Register 0 (`Command Register').
+ * These are just the command modifiers or'ed with register number 0
+ * (which of course equals the command modifier).
+ */
+#define ZSWR0_RESET_EOM ZSM_RESET_TXUEOM
+#define ZSWR0_RESET_TXCRC ZSM_RESET_TXCRC
+#define ZSWR0_RESET_RXCRC ZSM_RESET_RXCRC
+#define ZSWR0_CLR_INTR ZSM_RESET_IUS
+#define ZSWR0_RESET_ERRORS ZSM_RESET_ERR
+#define ZSWR0_EI_NEXTRXC ZSM_EI_NEXTRXC
+#define ZSWR0_SEND_ABORT ZSM_SEND_ABORT
+#define ZSWR0_RESET_STATUS ZSM_RESET_STINT
+#define ZSWR0_RESET_TXINT ZSM_RESET_TXINT
+
+/*
+ * Bits in Write Register 1 (`Transmit/Receive Interrupt and Data
+ * Transfer Mode Definition'). Note that bits 3 and 4 are taken together
+ * as a single unit, and bits 5 and 6 are useful only if bit 7 is set.
+ */
+#define ZSWR1_REQ_WAIT 0x80 /* WAIT*-REQ* pin gives WAIT* */
+#define ZSWR1_REQ_REQ 0xc0 /* WAIT*-REQ* pin gives REQ* */
+#define ZSWR1_REQ_TX 0x00 /* WAIT*-REQ* pin follows xmit buf */
+#define ZSWR1_REQ_RX 0x20 /* WAIT*-REQ* pin follows recv buf */
+
+#define ZSWR1_RIE_NONE 0x00 /* disable rxint entirely */
+#define ZSWR1_RIE_FIRST 0x08 /* rxint on first char & on S.C. */
+#define ZSWR1_RIE 0x10 /* rxint per char & on S.C. */
+#define ZSWR1_RIE_SPECIAL_ONLY 0x18 /* rxint on S.C. only */
+
+#define ZSWR1_PE_SC 0x04 /* parity error is special condition */
+#define ZSWR1_TIE 0x02 /* transmit interrupt enable */
+#define ZSWR1_SIE 0x01 /* external/status interrupt enable */
+
+/* HSIS compat */
+#define ZSWR1_REQ_ENABLE (ZSWR1_REQ_WAIT | ZSWR1_REQ_TX)
+
+/*
+ * Bits in Write Register 3 (`Receive Parameters and Control').
+ * Bits 7 and 6 are taken as a unit. Note that the receive bits
+ * per character ordering is insane.
+ *
+ * Here `hardware flow control' means CTS enables the transmitter
+ * and DCD enables the receiver. The latter is neither interesting
+ * nor useful, and gets in our way, making it almost unusable.
+ */
+#define ZSWR3_RX_5 0x00 /* receive 5 bits per char */
+#define ZSWR3_RX_7 0x40 /* receive 7 bits per char */
+#define ZSWR3_RX_6 0x80 /* receive 6 bits per char */
+#define ZSWR3_RX_8 0xc0 /* receive 8 bits per char */
+
+#define ZSWR3_HFC 0x20 /* hardware flow control */
+#define ZSWR3_HUNT 0x10 /* enter hunt mode */
+#define ZSWR3_RXCRC_ENABLE 0x08 /* enable recv crc calculation */
+#define ZSWR3_ADDR_SEARCH_MODE 0x04 /* address search mode (SDLC only) */
+#define ZSWR3_SYNC_LOAD_INH 0x02 /* sync character load inhibit */
+#define ZSWR3_RX_ENABLE 0x01 /* receiver enable */
+
+/*
+ * Bits in Write Register 4 (`Transmit/Receive Miscellaneous Parameters
+ * and Modes'). Bits 7&6, 5&4, and 3&2 are taken as units.
+ */
+#define ZSWR4_CLK_X1 0x00 /* clock divisor = 1 */
+#define ZSWR4_CLK_X16 0x40 /* clock divisor = 16 */
+#define ZSWR4_CLK_X32 0x80 /* clock divisor = 32 */
+#define ZSWR4_CLK_X64 0xc0 /* clock divisor = 64 */
+
+#define ZSWR4_MONOSYNC 0x00 /* 8 bit sync char (sync only) */
+#define ZSWR4_BISYNC 0x10 /* 16 bit sync char (sync only) */
+#define ZSWR4_SDLC 0x20 /* SDLC mode */
+#define ZSWR4_EXTSYNC 0x30 /* external sync mode */
+
+#define ZSWR4_SYNCMODE 0x00 /* one of the above sync modes */
+#define ZSWR4_ONESB 0x04 /* 1 stop bit */
+#define ZSWR4_1P5SB 0x08 /* 1.5 stop bits (clk cannot be 1x) */
+#define ZSWR4_TWOSB 0x0c /* 2 stop bits */
+
+#define ZSWR4_EVENP 0x02 /* check for even parity */
+#define ZSWR4_PARENB 0x01 /* enable parity checking */
+
+/*
+ * Bits in Write Register 5 (`Transmit Parameter and Controls').
+ * Bits 6 and 5 are taken as a unit; the ordering is, as with RX
+ * bits per char, not sensible.
+ */
+#define ZSWR5_DTR 0x80 /* assert (set to -12V) DTR */
+
+#define ZSWR5_TX_5 0x00 /* transmit 5 or fewer bits */
+#define ZSWR5_TX_7 0x20 /* transmit 7 bits */
+#define ZSWR5_TX_6 0x40 /* transmit 6 bits */
+#define ZSWR5_TX_8 0x60 /* transmit 8 bits */
+
+#define ZSWR5_BREAK 0x10 /* send break (continuous 0s) */
+#define ZSWR5_TX_ENABLE 0x08 /* enable transmitter */
+#define ZSWR5_CRC16 0x04 /* use CRC16 (off => use SDLC) */
+#define ZSWR5_RTS 0x02 /* assert RTS */
+#define ZSWR5_TXCRC_ENABLE 0x01 /* enable xmit crc calculation */
+
+#ifdef not_done_here
+/*
+ * Bits in Write Register 7 when the chip is in SDLC mode.
+ */
+#define ZSWR7_SDLCFLAG 0x7e /* this value makes SDLC mode work */
+#endif
+
+/*
+ * Bits in Write Register 9 (`Master Interrupt Control'). Bits 7 & 6
+ * are taken as a unit and indicate the type of reset; 00 means no reset
+ * (and is not defined here).
+ */
+#define ZSWR9_HARD_RESET 0xc0 /* force hardware reset */
+#define ZSWR9_A_RESET 0x80 /* reset channel A (0) */
+#define ZSWR9_B_RESET 0x40 /* reset channel B (1) */
+ /* 0x20 unused */
+
+#define ZSWR9_STATUS_HIGH 0x10 /* status in high bits of intr vec */
+#define ZSWR9_MASTER_IE 0x08 /* master interrupt enable */
+#define ZSWR9_DLC 0x04 /* disable lower chain */
+#define ZSWR9_NO_VECTOR 0x02 /* no vector */
+#define ZSWR9_VECTOR_INCL_STAT 0x01 /* vector includes status */
+
+/*
+ * Bits in Write Register 10 (`Miscellaneous Transmitter/Receiver Control
+ * Bits'). Bits 6 & 5 are taken as a unit, and some of the bits are
+ * meaningful only in certain modes. Bleah.
+ */
+#define ZSWR10_PRESET_ONES 0x80 /* preset CRC to all 1 (else all 0) */
+
+#define ZSWR10_NRZ 0x00 /* NRZ encoding */
+#define ZSWR10_NRZI 0x20 /* NRZI encoding */
+#define ZSWR10_FM1 0x40 /* FM1 encoding */
+#define ZSWR10_FM0 0x60 /* FM0 encoding */
+
+#define ZSWR10_GA_ON_POLL 0x10 /* go active on poll (loop mode) */
+#define ZSWR10_MARK_IDLE 0x08 /* all 1s (vs flag) when idle (SDLC) */
+#define ZSWR10_ABORT_ON_UNDERRUN 0x4 /* abort on xmit underrun (SDLC) */
+#define ZSWR10_LOOP_MODE 0x02 /* loop mode (SDLC) */
+#define ZSWR10_6_BIT_SYNC 0x01 /* 6 bits per sync char (sync modes) */
+
+/*
+ * Bits in Write Register 11 (`Clock Mode Control'). Bits 6&5, 4&3, and
+ * 1&0 are taken as units. Various bits depend on other bits in complex
+ * ways; see the Zilog manual.
+ */
+#define ZSWR11_XTAL 0x80 /* have xtal between RTxC* and SYNC* */
+ /* (else have TTL oscil. on RTxC*) */
+#define ZSWR11_RXCLK_RTXC 0x00 /* recv clock taken from TRxC* pin */
+#define ZSWR11_RXCLK_TRXC 0x20 /* recv clock taken from TRxC* pin */
+#define ZSWR11_RXCLK_BAUD 0x40 /* recv clock taken from BRG */
+#define ZSWR11_RXCLK_DPLL 0x60 /* recv clock taken from DPLL */
+
+#define ZSWR11_TXCLK_RTXC 0x00 /* xmit clock taken from TRxC* pin */
+#define ZSWR11_TXCLK_TRXC 0x08 /* xmit clock taken from RTxC* pin */
+#define ZSWR11_TXCLK_BAUD 0x10 /* xmit clock taken from BRG */
+#define ZSWR11_TXCLK_DPLL 0x18 /* xmit clock taken from DPLL */
+
+#define ZSWR11_TRXC_OUT_ENA 0x04 /* TRxC* pin will be an output */
+ /* (unless it is being used above) */
+#define ZSWR11_TRXC_XTAL 0x00 /* TRxC output from xtal oscillator */
+#define ZSWR11_TRXC_XMIT 0x01 /* TRxC output from xmit clock */
+#define ZSWR11_TRXC_BAUD 0x02 /* TRxC output from BRG */
+#define ZSWR11_TRXC_DPLL 0x03 /* TRxC output from DPLL */
+
+/*
+ * Formula for Write Registers 12 and 13 (`Lower Byte of Baud Rate
+ * Generator Time Constant' and `Upper Byte of ...'). Inputs:
+ *
+ * f BRG input clock frequency (in Hz) AFTER division
+ * by 1, 16, 32, or 64 (per clock divisor in WR4)
+ * bps desired rate in bits per second (9600, etc)
+ *
+ * We want
+ *
+ * f
+ * ----- + 0.5 - 2
+ * 2 bps
+ *
+ * rounded down to an integer. This can be computed entirely
+ * in integer arithemtic as:
+ *
+ * f + bps
+ * ------- - 2
+ * 2 bps
+ */
+#define BPS_TO_TCONST(f, bps) ((((f) + (bps)) / (2 * (bps))) - 2)
+
+/* inverse of above: given a BRG Time Constant, return Bits Per Second */
+#define TCONST_TO_BPS(f, tc) ((f) / 2 / ((tc) + 2))
+
+/*
+ * Bits in Write Register 14 (`Miscellaneous Control Bits').
+ * Bits 7 through 5 are taken as a unit and make up a `DPLL command'.
+ */
+#define ZSWR14_DPLL_NOOP 0x00 /* leave DPLL alone */
+#define ZSWR14_DPLL_SEARCH 0x20 /* enter search mode */
+#define ZSWR14_DPLL_RESET_CM 0x40 /* reset `clock missing' in RR10 */
+#define ZSWR14_DPLL_DISABLE 0x60 /* disable DPLL (continuous search) */
+#define ZSWR14_DPLL_SRC_BAUD 0x80 /* set DPLL src = BRG */
+#define ZSWR14_DPLL_SRC_RTXC 0xa0 /* set DPLL src = RTxC* or xtal osc */
+#define ZSWR14_DPLL_FM 0xc0 /* operate in FM mode */
+#define ZSWR14_DPLL_NRZI 0xe0 /* operate in NRZI mode */
+
+#define ZSWR14_LOCAL_LOOPBACK 0x10 /* set local loopback mode */
+#define ZSWR14_AUTO_ECHO 0x08 /* set auto echo mode */
+#define ZSWR14_DTR_REQ 0x04 /* DTR*/REQ* pin gives REQ* */
+#define ZSWR14_BAUD_FROM_PCLK 0x02 /* BRG clock taken from PCLK */
+ /* (else from RTxC* pin or xtal osc) */
+#define ZSWR14_BAUD_ENA 0x01 /* enable BRG countdown */
+
+/*
+ * Bits in Write Register 15 (`External/Status Interrupt Control').
+ * Most of these cause status interrupts whenever the corresponding
+ * bit or pin changes state (i.e., any rising or falling edge).
+ */
+#define ZSWR15_BREAK_IE 0x80 /* enable break/abort status int */
+#define ZSWR15_TXUEOM_IE 0x40 /* enable TX underrun/EOM status int */
+#define ZSWR15_CTS_IE 0x20 /* enable CTS* pin status int */
+#define ZSWR15_SYNCHUNT_IE 0x10 /* enable SYNC* pin/hunt status int */
+#define ZSWR15_DCD_IE 0x08 /* enable DCD* pin status int */
+ /* 0x04 unused, must be zero */
+#define ZSWR15_ZERO_COUNT_IE 0x02 /* enable BRG-counter = 0 status int */
+ /* 0x01 unused, must be zero */
+
+/*
+ * Bits in Read Register 0 (`Transmit/Receive Buffer Status and External
+ * Status').
+ */
+#define ZSRR0_BREAK 0x80 /* break/abort detected */
+#define ZSRR0_TXUNDER 0x40 /* transmit underrun/EOM (sync) */
+#define ZSRR0_CTS 0x20 /* clear to send */
+#define ZSRR0_SYNC_HUNT 0x10 /* sync/hunt (sync mode) */
+#define ZSRR0_DCD 0x08 /* data carrier detect */
+#define ZSRR0_TX_READY 0x04 /* transmit buffer empty */
+#define ZSRR0_ZERO_COUNT 0x02 /* zero count in baud clock */
+#define ZSRR0_RX_READY 0x01 /* received character ready */
+
+/*
+ * Bits in Read Register 1 (the Zilog book does not name this one).
+ */
+#define ZSRR1_EOF 0x80 /* end of frame (SDLC mode) */
+#define ZSRR1_FE 0x40 /* CRC/framing error */
+#define ZSRR1_DO 0x20 /* data (receiver) overrun */
+#define ZSRR1_PE 0x10 /* parity error */
+#define ZSRR1_RC0 0x08 /* residue code 0 (SDLC mode) */
+#define ZSRR1_RC1 0x04 /* residue code 1 (SDLC mode) */
+#define ZSRR1_RC2 0x02 /* residue code 2 (SDLC mode) */
+#define ZSRR1_ALL_SENT 0x01 /* all chars out of xmitter (async) */
+
+/*
+ * Read Register 2 in B channel contains status bits if VECTOR_INCL_STAT
+ * is set.
+ */
+
+/*
+ * Bits in Read Register 3 (`Interrupt Pending'). Only channel A
+ * has an RR3.
+ */
+ /* 0x80 unused, returned as 0 */
+ /* 0x40 unused, returned as 0 */
+#define ZSRR3_IP_A_RX 0x20 /* channel A recv int pending */
+#define ZSRR3_IP_A_TX 0x10 /* channel A xmit int pending */
+#define ZSRR3_IP_A_STAT 0x08 /* channel A status int pending */
+#define ZSRR3_IP_B_RX 0x04 /* channel B recv int pending */
+#define ZSRR3_IP_B_TX 0x02 /* channel B xmit int pending */
+#define ZSRR3_IP_B_STAT 0x01 /* channel B status int pending */
+
+/*
+ * Bits in Read Register 10 (`contains some miscellaneous status bits').
+ */
+#define ZSRR10_1_CLOCK_MISSING 0x80 /* 1 clock edge missing (FM mode) */
+#define ZSRR10_2_CLOCKS_MISSING 0x40 /* 2 clock edges missing (FM mode) */
+ /* 0x20 unused */
+#define ZSRR10_LOOP_SENDING 0x10 /* xmitter controls loop (SDLC loop) */
+ /* 0x08 unused */
+ /* 0x04 unused */
+#define ZSRR10_ON_LOOP 0x02 /* SCC is on loop (SDLC/X.21 modes) */
+
+/*
+ * Bits in Read Register 15. This register is one of the few that
+ * simply reads back the corresponding Write Register.
+ */
+#define ZSRR15_BREAK_IE 0x80 /* break/abort status int enable */
+#define ZSRR15_TXUEOM_IE 0x40 /* TX underrun/EOM status int enable */
+#define ZSRR15_CTS_IE 0x20 /* CTS* pin status int enable */
+#define ZSRR15_SYNCHUNT_IE 0x10 /* SYNC* pin/hunt status int enable */
+#define ZSRR15_DCD_IE 0x08 /* DCD* pin status int enable */
+ /* 0x04 unused, returned as zero */
+#define ZSRR15_ZERO_COUNT_IE 0x02 /* BRG-counter = 0 status int enable */
+ /* 0x01 unused, returned as zero */
diff --git a/sys/arch/atari/dev/zsvar.h b/sys/arch/atari/dev/zsvar.h
new file mode 100644
index 00000000000..fd222a118d9
--- /dev/null
+++ b/sys/arch/atari/dev/zsvar.h
@@ -0,0 +1,144 @@
+/* $NetBSD: zsvar.h,v 1.1.1.1 1995/03/26 07:12:14 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman (Atari modifications)
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)zsvar.h 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * Software state, per zs channel.
+ *
+ * The zs chip has insufficient buffering, so we provide a software
+ * buffer using a two-level interrupt scheme. The hardware (high priority)
+ * interrupt simply grabs the `cause' of the interrupt and stuffs it into
+ * a ring buffer. It then schedules a software interrupt; the latter
+ * empties the ring as fast as it can, hoping to avoid overflow.
+ *
+ * Interrupts can happen because of:
+ * - received data;
+ * - transmit pseudo-DMA done; and
+ * - status change.
+ * These are all stored together in the (single) ring. The size of the
+ * ring is a power of two, to make % operations fast. Since we need two
+ * bits to distinguish the interrupt type, and up to 16 for the received
+ * data plus RR1 status, we use 32 bits per ring entry.
+ *
+ * When the value is a character + RR1 status, the character is in the
+ * upper 8 bits of the RR1 status.
+ */
+#define ZLRB_RING_SIZE 256 /* ZS line ring buffer size */
+#define ZLRB_RING_MASK 255 /* mask for same */
+
+/* 0 is reserved (means "no interrupt") */
+#define ZRING_RINT 1 /* receive data interrupt */
+#define ZRING_XINT 2 /* transmit done interrupt */
+#define ZRING_SINT 3 /* status change interrupt */
+
+#define ZRING_TYPE(x) ((x) & 3)
+#define ZRING_VALUE(x) ((x) >> 8)
+#define ZRING_MAKE(t, v) ((t) | (v) << 8)
+
+struct zs_chanstate {
+ struct zs_chanstate *cs_next; /* linked list for zshard() */
+ volatile struct zschan *cs_zc; /* points to hardware regs */
+ int cs_unit; /* unit number */
+ struct tty *cs_ttyp; /* ### */
+
+ /*
+ * We must keep a copy of the write registers as they are
+ * mostly write-only and we sometimes need to set and clear
+ * individual bits (e.g., in WR3). Not all of these are
+ * needed but 16 bytes is cheap and this makes the addressing
+ * simpler. Unfortunately, we can only write to some registers
+ * when the chip is not actually transmitting, so whenever
+ * we are expecting a `transmit done' interrupt the preg array
+ * is allowed to `get ahead' of the current values. In a
+ * few places we must change the current value of a register,
+ * rather than (or in addition to) the pending value; for these
+ * cs_creg[] contains the current value.
+ */
+ u_char cs_creg[16]; /* current values */
+ u_char cs_preg[16]; /* pending values */
+ u_char cs_heldchange; /* change pending (creg != preg) */
+ u_char cs_rr0; /* last rr0 processed */
+
+ /* pure software data, per channel */
+ char cs_softcar; /* software carrier */
+ char cs_xxx; /* (spare) */
+
+ /*
+ * The transmit byte count and address are used for pseudo-DMA
+ * output in the hardware interrupt code. PDMA can be suspended
+ * to get pending changes done; heldtbc is used for this. It can
+ * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
+ */
+ int cs_tbc; /* transmit byte count */
+ caddr_t cs_tba; /* transmit buffer address */
+ int cs_heldtbc; /* held tbc while xmission stopped */
+
+ /*
+ * Printing an overrun error message often takes long enough to
+ * cause another overrun, so we only print one per second.
+ */
+ long cs_rotime; /* time of last ring overrun */
+ long cs_fotime; /* time of last fifo overrun */
+
+ /*
+ * The ring buffer.
+ */
+ u_int cs_rbget; /* ring buffer `get' index */
+ volatile u_int cs_rbput; /* ring buffer `put' index */
+ int cs_rbuf[ZLRB_RING_SIZE];/* type, value pairs */
+};
+
+/*
+ * Macros to read and write individual registers (except 0) in a channel.
+ */
+#define ZS_READ(c, r) ((c)->zc_csr = (r), (c)->zc_csr)
+#define ZS_WRITE(c, r, v) ((c)->zc_csr = (r), (c)->zc_csr = (v))
+
+/*
+ * Split minor into unit & flag nibble.
+ */
+#define ZS_UNIT(dev) ((minor(dev) >> 4) & 0xf)
+#define ZS_FLAGS(dev) (minor(dev) & 0xf)
diff --git a/sys/arch/atari/include/acia.h b/sys/arch/atari/include/acia.h
new file mode 100644
index 00000000000..b4accda3b04
--- /dev/null
+++ b/sys/arch/atari/include/acia.h
@@ -0,0 +1,86 @@
+ /* $NetBSD: acia.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MACHINE_ACIA_H
+#define _MACHINE_ACIA_H
+/*
+ * Atari ST hardware:
+ * Motorola 6850 Asynchronous Communications Interface Adapter
+ */
+
+#define KBD (((struct acia *)AD_ACIA))
+#define MDI (((struct acia *)AD_ACIA) + 1)
+
+struct acia {
+ volatile char acb[4]; /* use only the even bytes */
+};
+
+#define ac_cs acb[0] /* control and status register */
+#define ac_da acb[2] /* data register */
+
+/* bits in control register: */
+/* 0x03 *//* clock divider */
+#define A_Q01 0x00 /* don't divide */
+#define A_Q16 0x01 /* divide by 16 */
+#define A_Q64 0x02 /* divide by 64 */
+#define A_RESET 0x03 /* master reset */
+/* 0x1C *//* word select bits */
+#define A_72E 0x00 /* 7 data, 2 stop, parity even */
+#define A_72O 0x04 /* 7 data, 2 stop, parity odd */
+#define A_71E 0x08 /* 7 data, 1 stop, parity even */
+#define A_71O 0x0C /* 7 data, 1 stop, parity odd */
+#define A_82N 0x10 /* 8 data, 2 stop, no parity */
+#define A_81N 0x14 /* 8 data, 1 stop, no parity */
+#define A_81E 0x18 /* 8 data, 1 stop, parity even */
+#define A_81O 0x1C /* 8 data, 1 stop, parity odd */
+/* 0x60 *//* RTS Low/High, TXINT en/dis, BREAK */
+#define A_TXPOL 0x00 /* RTS Low, TXINT disabled */
+#define A_TXINT 0x20 /* RTS Low, TXINT enabled */
+#define A_TXOFF 0x40 /* RTS High, TXINT disabled */
+#define A_BREAK 0x60 /* RTS Low, TXINT disabled, BREAK */
+#define A_RXINT 0x80 /* enable receiver interrupt */
+
+/* bits in status register: */
+#define A_RXRDY 0x01 /* receiver ready */
+#define A_TXRDY 0x02 /* transmitter ready */
+#define A_CLOST 0x04 /* Carrier Lost */
+#define A_CTS 0x08 /* Clear To Send */
+#define A_FE 0x10 /* Frame Error */
+#define A_OE 0x20 /* Overrun Error */
+#define A_PE 0x40 /* Parity Error */
+#define A_IRQ 0x80 /* State of IRQ signal */
+
+/* values for the TT: */
+#define KBD_INIT (A_81N|A_Q64)
+#define MDI_INIT (A_81N|A_Q16)
+
+#endif /* _MACHINE_ACIA_H */
diff --git a/sys/arch/atari/include/ansi.h b/sys/arch/atari/include/ansi.h
new file mode 100644
index 00000000000..31de7856c33
--- /dev/null
+++ b/sys/arch/atari/include/ansi.h
@@ -0,0 +1,8 @@
+/* $NetBSD: ansi.h,v 1.1.1.1 1995/03/26 07:12:09 leo Exp $ */
+
+#ifndef _MACHINE_ANSI_H_
+#define _MACHINE_ANSI_H_
+
+#include <m68k/ansi.h>
+
+#endif
diff --git a/sys/arch/atari/include/aout_machdep.h b/sys/arch/atari/include/aout_machdep.h
new file mode 100644
index 00000000000..6283ab803eb
--- /dev/null
+++ b/sys/arch/atari/include/aout_machdep.h
@@ -0,0 +1,49 @@
+/* $NetBSD: aout_machdep.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+/*
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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 _MACHINE_EXEC_H_
+#define _MACHINE_EXEC_H_
+
+#define __LDPGSZ 8192
+
+/* Relocation format. */
+struct relocation_info_m68k {
+ 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_m68k
+
+#endif /* _MACHINE_EXEC_H_ */
diff --git a/sys/arch/atari/include/asm.h b/sys/arch/atari/include/asm.h
new file mode 100644
index 00000000000..c5f3dd8a213
--- /dev/null
+++ b/sys/arch/atari/include/asm.h
@@ -0,0 +1,8 @@
+/* $NetBSD: asm.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+#ifndef _MACHINE_ASM_H_
+#define _MACHINE_ASM_H_
+
+#include <m68k/asm.h>
+
+#endif
diff --git a/sys/arch/atari/include/cdefs.h b/sys/arch/atari/include/cdefs.h
new file mode 100644
index 00000000000..fbb4f3a5b98
--- /dev/null
+++ b/sys/arch/atari/include/cdefs.h
@@ -0,0 +1,8 @@
+/* $NetBSD: cdefs.h,v 1.1.1.1 1995/03/26 07:12:08 leo Exp $ */
+
+#ifndef _MACHINE_CDEFS_H_
+#define _MACHINE_CDEFS_H_
+
+#include <m68k/cdefs.h>
+
+#endif
diff --git a/sys/arch/atari/include/cpu.h b/sys/arch/atari/include/cpu.h
new file mode 100644
index 00000000000..d748378f37e
--- /dev/null
+++ b/sys/arch/atari/include/cpu.h
@@ -0,0 +1,219 @@
+/* $NetBSD: cpu.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990 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.
+ *
+ * from: Utah $Hdr: cpu.h 1.16 91/03/25$
+ *
+ * @(#)cpu.h 7.7 (Berkeley) 6/27/91
+ */
+
+#ifndef _MACHINE_CPU_H_
+#define _MACHINE_CPU_H_
+
+/*
+ * Exported definitions unique to atari/68k cpu support.
+ */
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+#define COPY_SIGCODE /* copy sigcode above user stack in exec */
+
+#define cpu_exec(p) /* nothing */
+#define cpu_swapin(p) /* nothing */
+#define cpu_wait(p) /* nothing */
+#define cpu_setstack(p, ap) (p)->p_md.md_regs[SP] = ap
+#define cpu_set_init_frame(p, fp) (p)->p_md.md_regs = fp
+
+/*
+ * Arguments to hardclock and gatherstats encapsulate the previous
+ * machine state in an opaque clockframe. On the hp300, we use
+ * what the hardware pushes on an interrupt (frame format 0).
+ */
+struct clockframe {
+ u_short sr; /* sr at time of interrupt */
+ u_long pc; /* pc at time of interrupt */
+ u_short vo; /* vector offset (4-word frame) */
+};
+
+#define CLKF_USERMODE(framep) (((framep)->sr & PSL_S) == 0)
+#define CLKF_BASEPRI(framep) (((framep)->sr & PSL_IPL) == 0)
+#define CLKF_PC(framep) ((framep)->pc)
+#if 0
+/* We would like to do it this way... */
+#define CLKF_INTR(framep) (((framep)->sr & PSL_M) == 0)
+#else
+/* but until we start using PSL_M, we have to do this instead */
+#define CLKF_INTR(framep) (0) /* XXX */
+#endif
+
+
+/*
+ * Preempt the current process if in interrupt from user mode,
+ * or after the current trap/syscall if in system mode.
+ */
+#define need_resched() {want_resched = 1; setsoftast();}
+
+/*
+ * Give a profiling tick to the current process from the softclock
+ * interrupt. On hp300, request an ast to send us through trap(),
+ * marking the proc as needing a profiling tick.
+ */
+#define profile_tick(p, framep) ((p)->p_flag |= P_OWEUPC, setsoftast())
+#define need_proftick(p) ((p)->p_flag |= P_OWEUPC, setsoftast())
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+#define signotify(p) setsoftast()
+
+#define setsoftast() (astpending = 1)
+
+extern int astpending; /* need trap before returning to user mode */
+extern int want_resched; /* resched() was called */
+
+/*
+ * simulated software interrupt register
+ */
+extern unsigned char ssir;
+
+#define SIR_NET 0x1
+#define SIR_CLOCK 0x2
+
+#define siroff(x) ssir &= ~(x)
+#define setsoftnet() ssir |= SIR_NET
+#define setsoftclock() ssir |= SIR_CLOCK
+
+
+/*
+ * The rest of this should probably be moved to ../atari/ataricpu.h,
+ * although some of it could probably be put into generic 68k headers.
+ */
+#define BASEPRI(sr) ((sr & PSL_IPL) == 0)
+
+/*
+ * Values for machineid.
+ */
+#define ATARI_68020 (1L<<2)
+#define ATARI_68030 (1L<<3)
+#define ATARI_68040 (1L<<4)
+#define ATARI_68881 (1L<<8)
+#define ATARI_68882 (1L<<9)
+#define ATARI_FPU40 (1L<<10)
+
+
+/*
+ * Values for mmutype (assigned for quick testing)
+ */
+#define MMU_68030 -1 /* 68030 on-chip subset of 68851 */
+#define MMU_68851 1 /* Motorola 68851 */
+#define MMU_68040 -2 /* 68040 on-chip subsubset */
+
+/* values for cpuspeed (not really related to clock speed due to caches) */
+#define MHZ_8 1
+#define MHZ_16 2
+#define MHZ_25 3
+#define MHZ_33 4
+#define MHZ_50 6
+
+#ifdef KERNEL
+extern int machineid, mmutype, cpu040;
+#endif
+
+/*
+ * 68851 and 68030 MMU
+ */
+#define PMMU_LVLMASK 0x0007
+#define PMMU_INV 0x0400
+#define PMMU_WP 0x0800
+#define PMMU_ALV 0x1000
+#define PMMU_SO 0x2000
+#define PMMU_LV 0x4000
+#define PMMU_BE 0x8000
+#define PMMU_FAULT (PMMU_WP|PMMU_INV)
+
+/* 680X0 function codes */
+#define FC_USERD 1 /* user data space */
+#define FC_USERP 2 /* user program space */
+#define FC_SUPERD 5 /* supervisor data space */
+#define FC_SUPERP 6 /* supervisor program space */
+#define FC_CPU 7 /* CPU space */
+
+/* fields in the 68020 cache control register */
+#define IC_ENABLE 0x0001 /* enable instruction cache */
+#define IC_FREEZE 0x0002 /* freeze instruction cache */
+#define IC_CE 0x0004 /* clear instruction cache entry */
+#define IC_CLR 0x0008 /* clear entire instruction cache */
+
+/* additional fields in the 68030 cache control register */
+#define IC_BE 0x0010 /* instruction burst enable */
+#define DC_ENABLE 0x0100 /* data cache enable */
+#define DC_FREEZE 0x0200 /* data cache freeze */
+#define DC_CE 0x0400 /* clear data cache entry */
+#define DC_CLR 0x0800 /* clear entire data cache */
+#define DC_BE 0x1000 /* data burst enable */
+#define DC_WA 0x2000 /* write allocate */
+
+/* fields in the 68040 cache control register */
+#define IC40_ENABLE 0x00008000 /* enable instruction cache */
+#define DC40_ENABLE 0x80000000 /* enable data cache */
+
+#define CACHE_ON (DC_WA|DC_BE|DC_CLR|DC_ENABLE|IC_BE|IC_CLR|IC_ENABLE)
+#define CACHE_OFF (DC_CLR|IC_CLR)
+#define CACHE_CLR (CACHE_ON)
+#define IC_CLEAR (DC_WA|DC_BE|DC_ENABLE|IC_BE|IC_CLR|IC_ENABLE)
+#define DC_CLEAR (DC_WA|DC_BE|DC_CLR|DC_ENABLE|IC_BE|IC_ENABLE)
+
+/* 68040 cache control */
+#define CACHE40_ON (IC40_ENABLE|DC40_ENABLE)
+#define CACHE40_OFF 0x00000000
+
+/*
+ * CTL_MACHDEP definitions.
+ */
+#define CPU_CONSDEV 1 /* dev_t: console terminal device */
+#define CPU_MAXID 2 /* number of valid machdep ids */
+
+#define CTL_MACHDEP_NAMES { \
+ { 0, 0 }, \
+ { "console_device", CTLTYPE_STRUCT }, \
+}
+
+#endif /* !_MACHINE_CPU_H_ */
diff --git a/sys/arch/atari/include/cpufunc.h b/sys/arch/atari/include/cpufunc.h
new file mode 100644
index 00000000000..3c7842e30b4
--- /dev/null
+++ b/sys/arch/atari/include/cpufunc.h
@@ -0,0 +1,8 @@
+/* $NetBSD: cpufunc.h,v 1.1.1.1 1995/03/26 07:12:05 leo Exp $ */
+
+/*
+ * Functions to provide access to special cpu instructions.
+ */
+#ifndef _MACHINE_CPUFUNC_H_
+#define _MACHINE_CPUFUNC_H_
+#endif /* !_MACHINE_CPUFUNC_H_ */
diff --git a/sys/arch/atari/include/db_machdep.h b/sys/arch/atari/include/db_machdep.h
new file mode 100644
index 00000000000..896d316688c
--- /dev/null
+++ b/sys/arch/atari/include/db_machdep.h
@@ -0,0 +1,8 @@
+/* $NetBSD: db_machdep.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+#ifndef _MACHINE_DB_MACHDEP_H_
+#define _MACHINE_DB_MACHDEP_H_
+
+#include <m68k/db_machdep.h>
+
+#endif
diff --git a/sys/arch/atari/include/disklabel.h b/sys/arch/atari/include/disklabel.h
new file mode 100644
index 00000000000..a634c4780da
--- /dev/null
+++ b/sys/arch/atari/include/disklabel.h
@@ -0,0 +1,45 @@
+ /* $NetBSD: disklabel.h,v 1.1.1.1 1995/03/26 07:12:05 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MACHINE_DISKLABEL_H_
+#define _MACHINE_DISKLABEL_H_
+
+#define LABELSECTOR 0 /* sector containing label */
+#define LABELOFFSET 64 /* offset of label in sector */
+#define MAXPARTITIONS 16
+#define RAW_PART 2 /* xx?c is raw part. */
+
+struct cpu_disklabel {
+ int filler; /* must be something */
+};
+
+#endif /* _MACHINE_DISKLABEL_H_ */
diff --git a/sys/arch/atari/include/dma.h b/sys/arch/atari/include/dma.h
new file mode 100644
index 00000000000..50d810a6558
--- /dev/null
+++ b/sys/arch/atari/include/dma.h
@@ -0,0 +1,88 @@
+ /* $NetBSD: dma.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MACHINE_DMA_H
+#define _MACHINE_DMA_H
+
+/*
+ * Atari TT hardware:
+ * FDC/ACSI DMA circuitry
+ */
+
+#define DMA ((struct dma *)AD_DMA)
+
+struct dma {
+ volatile short dma_gap[2]; /* reserved */
+ volatile short dma_data; /* controller data path */
+ volatile short dma_mode; /* mode register */
+ volatile char dma_addr[6]; /* base address H/M/L */
+ volatile short dma_drvmode; /* floppy density settings */
+};
+
+#define dma_nsec dma_data /* sector count */
+#define dma_stat dma_mode /* status register */
+
+/*
+ * Mode register bits
+ */
+/* 0x0001 *//* not used */
+#define A0 0x0002 /* signal A0 to fdc/hdc */
+#define A1 0x0004 /* signal A1 to fdc/hdc */
+#define HDC 0x0008 /* must be on if accessing hdc */
+#define SCREG 0x0010 /* access sector count register */
+/* 0x0020 *//* reserved */
+#define NODMA 0x0040 /* no DMA (yet) */
+#define FDC 0x0080 /* must be on if accessing fdc */
+#define WRBIT 0x0100 /* write to fdc/hdc via dma_data */
+
+/*
+ * Status register bits
+ */
+#define DMAOK 0x0001 /* something wrong */
+#define SCNOT0 0x0002 /* sector count not 0 */
+#define DATREQ 0x0004 /* FDC data request signal */
+
+/*
+ * Indices into dma_addr.
+ * Access low byte of 16 bits.
+ * Fill low/mid/high in this order.
+ */
+#define AD_HIGH 1
+#define AD_MID 3
+#define AD_LOW 5
+
+/*
+ * Defines for 'dmadrv_mode'.
+ */
+#define FDC_HDSET 1 /* Set FDC for High density */
+#define FDC_HDSIG 2 /* Signal HD present to drive */
+#endif /* _MACHINE_DMA_H */
diff --git a/sys/arch/atari/include/endian.h b/sys/arch/atari/include/endian.h
new file mode 100644
index 00000000000..814afb73d93
--- /dev/null
+++ b/sys/arch/atari/include/endian.h
@@ -0,0 +1,8 @@
+/* $NetBSD: endian.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+#ifndef _MACHINE_ENDIAN_H_
+#define _MACHINE_ENDIAN_H_
+
+#include <m68k/endian.h>
+
+#endif
diff --git a/sys/arch/atari/include/exec.h b/sys/arch/atari/include/exec.h
new file mode 100644
index 00000000000..6227cea790d
--- /dev/null
+++ b/sys/arch/atari/include/exec.h
@@ -0,0 +1,49 @@
+/* $NetBSD: exec.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+/*
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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 _MACHINE_EXEC_H_
+#define _MACHINE_EXEC_H_
+
+#define __LDPGSZ 8192
+
+/* Relocation format. */
+struct relocation_info_m68k {
+ 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_m68k
+
+#endif /* _MACHINE_EXEC_H_ */
diff --git a/sys/arch/atari/include/float.h b/sys/arch/atari/include/float.h
new file mode 100644
index 00000000000..f5cf37fb337
--- /dev/null
+++ b/sys/arch/atari/include/float.h
@@ -0,0 +1,8 @@
+/* $NetBSD: float.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+#ifndef _MACHINE_FLOAT_H_
+#define _MACHINE_FLOAT_H_
+
+#include <m68k/float.h>
+
+#endif
diff --git a/sys/arch/atari/include/frame.h b/sys/arch/atari/include/frame.h
new file mode 100644
index 00000000000..d2079289692
--- /dev/null
+++ b/sys/arch/atari/include/frame.h
@@ -0,0 +1,8 @@
+/* $NetBSD: frame.h,v 1.1.1.1 1995/03/26 07:12:05 leo Exp $ */
+
+#ifndef _MACHINE_FRAME_H_
+#define _MACHINE_FRAME_H_
+
+#include <m68k/frame.h>
+
+#endif
diff --git a/sys/arch/atari/include/iomap.h b/sys/arch/atari/include/iomap.h
new file mode 100644
index 00000000000..2b8cf8c0447
--- /dev/null
+++ b/sys/arch/atari/include/iomap.h
@@ -0,0 +1,63 @@
+ /* $NetBSD: iomap.h,v 1.1.1.1 1995/03/26 07:12:08 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MACHINE_IOMAP_H
+#define _MACHINE_IOMAP_H
+/*
+ * Atari TT hardware:
+ * I/O Address map
+ */
+
+#define AD_RAM (0x000000L) /* main memory */
+#define AD_CART (0xFA0000L) /* expansion cartridge */
+#define AD_ROM (0xFC0000L) /* system ROM */
+#define AD_IO (0xFF8000L) /* I/O devices */
+#define AD_EIO (0xFFFFFFL) /* End of I/O devices */
+
+/*
+ * I/O address parts
+ */
+#define AD_RAMCFG (0xFF8000L) /* ram configuration */
+#define AD_VIDEO (0xFF8200L) /* video controller */
+#define AD_RESERVED (0xFF8400L) /* reserved */
+#define AD_DMA (0xFF8600L) /* DMA device access */
+#define AD_SCSI_DMA (0xFF8700L) /* SCSI DMA registers */
+#define AD_NCR5380 (0xFF8780L) /* SCSI controller */
+#define AD_SOUND (0xFF8800L) /* YM-2149 */
+#define AD_RTC (0xFF8960L) /* TT realtime clock */
+#define AD_SCC (0xFF8C80L) /* SCC 8530 */
+#define AD_SCU (0xFF8E00L) /* System Control Unit */
+
+#define AD_MFP (0xFFFA00L) /* 68901 */
+#define AD_MFP2 (0xFFFA80L) /* 68901-TT */
+#define AD_ACIA (0xFFFC00L) /* 2 * 6850 */
+#endif /* _MACHINE_IOMAP_H */
diff --git a/sys/arch/atari/include/limits.h b/sys/arch/atari/include/limits.h
new file mode 100644
index 00000000000..027cc313e78
--- /dev/null
+++ b/sys/arch/atari/include/limits.h
@@ -0,0 +1,8 @@
+/* $NetBSD: limits.h,v 1.1.1.1 1995/03/26 07:12:05 leo Exp $ */
+
+#ifndef _MACHINE_LIMITS_H_
+#define _MACHINE_LIMITS_H_
+
+#include <m68k/limits.h>
+
+#endif
diff --git a/sys/arch/atari/include/mfp.h b/sys/arch/atari/include/mfp.h
new file mode 100644
index 00000000000..0b12c778382
--- /dev/null
+++ b/sys/arch/atari/include/mfp.h
@@ -0,0 +1,177 @@
+ /* $NetBSD: mfp.h,v 1.1.1.1 1995/03/26 07:12:08 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MACHINE_MFP_H
+#define _MACHINE_MFP_H
+/*
+ * Atari TT hardware: MFP1/MFP2
+ * Motorola 68901 Multi-Function Peripheral
+ */
+
+#define MFP ((struct mfp *)AD_MFP)
+#define MFP2 ((struct mfp *)AD_MFP2)
+
+struct mfp {
+ volatile u_char mfb[48]; /* use only the odd bytes */
+};
+
+#define mf_gpip mfb[ 1] /* general purpose I/O interrupt port */
+#define mf_aer mfb[ 3] /* active edge register */
+#define mf_ddr mfb[ 5] /* data direction register */
+#define mf_iera mfb[ 7] /* interrupt enable register A */
+#define mf_ierb mfb[ 9] /* interrupt enable register B */
+#define mf_ipra mfb[11] /* interrupt pending register A */
+#define mf_iprb mfb[13] /* interrupt pending register B */
+#define mf_isra mfb[15] /* interrupt in-service register A */
+#define mf_isrb mfb[17] /* interrupt in-service register B */
+#define mf_imra mfb[19] /* interrupt mask register A */
+#define mf_imrb mfb[21] /* interrupt mask register B */
+#define mf_vr mfb[23] /* vector register */
+#define mf_tacr mfb[25] /* timer control register A */
+#define mf_tbcr mfb[27] /* timer control register B */
+#define mf_tcdcr mfb[29] /* timer control register C+D */
+#define mf_tadr mfb[31] /* timer data register A */
+#define mf_tbdr mfb[33] /* timer data register B */
+#define mf_tcdr mfb[35] /* timer data register C */
+#define mf_tddr mfb[37] /* timer data register D */
+#define mf_scr mfb[39] /* synchronous character register */
+#define mf_ucr mfb[41] /* USART control register */
+#define mf_rsr mfb[43] /* receiver status register */
+#define mf_tsr mfb[45] /* transmitter status register */
+#define mf_udr mfb[47] /* USART data register */
+
+/* names of IO port bits: */
+#define IO_PBSY 0x01 /* Parallel Busy */
+#define IO_SDCD 0x02 /* Serial Data Carrier Detect */
+#define IO_SCTS 0x04 /* Serial Clear To Send */
+/* 0x08 *//* reserved */
+#define IO_AINT 0x10 /* ACIA interrupt (KB or MIDI) */
+#define IO_DINT 0x20 /* DMA interrupt (FDC or HDC) */
+#define IO_SRI 0x40 /* Serial Ring Indicator */
+#define IO_MONO 0x80 /* Monochrome Monitor Detect */
+
+/* names of interrupts in register A: MFP1 */
+#define IA_MONO 0x80 /* IO_MONO */
+#define IA_SRI 0x40 /* IO_SRI */
+#define IA_TIMA 0x20 /* Timer A */
+#define IA_RRDY 0x10 /* Serial Receiver Ready(=Full) */
+#define IA_RERR 0x08 /* Serial Receiver Error */
+#define IA_TRDY 0x04 /* Serial Transmitter Ready(=Empty) */
+#define IA_TERR 0x02 /* Serial Transmitter Error */
+#define IA_TIMB 0x01 /* Timer B */
+
+/* names of interrupts in register A: MFP2 */
+#define IA_SCSI 0x80 /* SCSI-controller */
+#define IA_RTC 0x40 /* Real Time Clock */
+#define IA_TIMA2 0x20 /* Timer A */
+/* 0x10 *//* reserved */
+/* 0x08 *//* reserved */
+/* 0x04 *//* reserved */
+/* 0x02 *//* reserved */
+#define IA_TIMB2 0x01 /* Timer B */
+
+/* names of interrupts in register B: MFP1*/
+#define IB_DINT 0x80 /* IO_DINT: from DMA devices */
+#define IB_AINT 0x40 /* IO_AINT: from kbd or midi */
+#define IB_TIMC 0x20 /* Timer C */
+#define IB_TIMD 0x10 /* Timer D */
+/* 0x08 *//* reserved */
+#define IB_SCTS 0x04 /* IO_SCTS */
+#define IB_SDCD 0x02 /* IO_SDCD */
+#define IB_PBSY 0x01 /* IO_PBSY */
+
+/* names of interrupts in register B: MFP2*/
+#define IB_SCDM 0x80 /* SCSI-dma */
+#define IB_DCHG 0x40 /* Diskette change */
+/* 0x20 *//* reserved */
+/* 0x10 *//* reserved */
+#define IB_RISB 0x80 /* Serial Ring indicator SCC port B */
+#define IB_DMSC 0x40 /* SCC-dma */
+#define IB_J602_3 0x02 /* Pin 3 J602 */
+#define IB_J602_1 0x01 /* Pin 1 J602 */
+
+/* bits in VR: */
+#define V_S 0x08 /* software end-of-interrupt mode */
+#define V_V 0xF0 /* four high bits of vector */
+
+/* bits in TCR: */
+/* 0x07 *//* divider */
+#define T_STOP 0x00 /* don't count */
+#define T_Q004 0x01 /* divide by 4 */
+#define T_Q010 0x02 /* divide by 10 */
+#define T_Q016 0x03 /* divide by 16 */
+#define T_Q050 0x04 /* divide by 50 */
+#define T_Q064 0x05 /* divide by 64 */
+#define T_Q100 0x06 /* divide by 100 */
+#define T_Q200 0x07 /* divide by 200 */
+#define T_EXTI 0x08 /* use extern impulse */
+#define T_LOWO 0x10 /* force output low */
+
+/* bits in UCR: */
+/* 0x01 *//* not used */
+#define U_EVEN 0x02 /* even parity */
+#define U_PAR 0x04 /* use parity */
+/* 0x18 *//* sync/async and stop bits */
+#define U_SYNC 0x00 /* synchrone */
+#define U_ST1 0x08 /* async, 1 stop bit */
+#define U_ST1_5 0x10 /* async, 1.5 stop bit */
+#define U_ST2 0x18 /* async, 2 stop bits */
+/* 0x60 *//* number of data bits */
+#define U_D8 0x00 /* 8 data bits */
+#define U_D7 0x20 /* 7 data bits */
+#define U_D6 0x40 /* 6 data bits */
+#define U_D5 0x60 /* 5 data bits */
+#define U_Q16 0x80 /* divide clock by 16 */
+
+/* bits in RSR: */
+#define RS_ENA 0x01 /* Receiver Enable */
+#define RS_STRIP 0x02 /* Synchronous Strip Enable */
+#define RS_CIP 0x04 /* Character in Progress */
+#define RS_BREAK 0x08 /* Break Detected */
+#define RS_FE 0x10 /* Frame Error */
+#define RS_PE 0x20 /* Parity Error */
+#define RS_OE 0x40 /* Overrun Error */
+#define RS_FULL 0x80 /* Buffer Full */
+
+/* bits in TSR: */
+#define TS_ENA 0x01 /* Transmitter Enable */
+/* 0x06 *//* state of dead transmitter output */
+#define TS_TRI 0x00 /* Quiet Output Tristate */
+#define TS_LOW 0x02 /* Quiet Output Low */
+#define TS_HIGH 0x04 /* Quiet Output High */
+#define TS_BACK 0x06 /* Loop Back Mode */
+#define TS_BREAK 0x08 /* Break Detected */
+#define TS_EOT 0x10 /* End of Transmission */
+#define TS_TURN 0x20 /* Auto Turnaround */
+#define TS_UE 0x40 /* Underrun Error */
+#define TS_EMPTY 0x80 /* Buffer Empty */
+#endif /* _MACHINE_MFP_H */
diff --git a/sys/arch/atari/include/mtpr.h b/sys/arch/atari/include/mtpr.h
new file mode 100644
index 00000000000..d531675dded
--- /dev/null
+++ b/sys/arch/atari/include/mtpr.h
@@ -0,0 +1,61 @@
+/* $NetBSD: mtpr.h,v 1.1.1.1 1995/03/26 07:12:05 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 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.
+ *
+ * from: Utah $Hdr: mtpr.h 1.1 90/07/09$
+ *
+ * @(#)mtpr.h 7.2 (Berkeley) 11/3/90
+ */
+
+#ifndef _MACHINE_MPTR_H_
+#define _MACHINE_MPTR_H_
+
+/*
+ * simulated software interrupt register
+ */
+
+extern unsigned char ssir;
+
+#define SIR_NET 0x1
+#define SIR_CLOCK 0x2
+
+#define siroff(x) ssir &= ~(x)
+#define setsoftnet() ssir |= SIR_NET
+#define setsoftclock() ssir |= SIR_CLOCK
+
+#endif /* !_MACHINE_MPTR_H_ */
diff --git a/sys/arch/atari/include/param.h b/sys/arch/atari/include/param.h
new file mode 100644
index 00000000000..e32afe724a0
--- /dev/null
+++ b/sys/arch/atari/include/param.h
@@ -0,0 +1,220 @@
+ /* $NetBSD: param.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * from: Utah $Hdr: machparam.h 1.11 89/08/14$
+ *
+ * @(#)param.h 7.8 (Berkeley) 6/28/91
+ */
+
+#ifndef _MACHINE_PARAM_H_
+#define _MACHINE_PARAM_H_
+
+/*
+ * Machine dependent constants for atari
+ */
+#define MACHINE "atari"
+#define MACHINE_ARCH "m68k"
+#define MID_MACHINE MID_M68K
+
+/*
+ * 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) + (sizeof(int) - 1)) &~ (sizeof(int) - 1))
+
+#define NBPG 8192 /* bytes/page */
+#define PGOFSET (NBPG-1) /* byte offset into page */
+#define PGSHIFT 13 /* LOG2(NBPG) */
+#define NPTEPG (NBPG/(sizeof(u_int)))
+
+#define NBSEG (cpu040 ? 32*NBPG : 2048*NBPG) /* bytes/segment */
+#define SEGOFSET (NBSEG-1) /* byte offset into segment */
+#define SEGSHIFT (cpu040 ? 18 : 24) /* LOG2(NBSEG) */
+
+#define KERNBASE 0x0 /* start of kernel virtual */
+#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT)
+
+#define DEV_BSIZE 512
+#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
+#define BLKDEV_IOSIZE 2048
+#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */
+
+#define CLSIZE 1
+#define CLSIZELOG2 0
+
+/* 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)
+
+/*
+ * 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 MCLBYTES 1024
+#define MCLSHIFT 10
+#define MCLOFSET (MCLBYTES - 1)
+#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 (3072*1024/CLBYTES)
+#endif
+
+#define MAXPARTITIONS 16
+
+/* pages ("clicks") to disk blocks */
+#define ctod(x) ((x)<<(PGSHIFT-DEV_BSHIFT))
+#define dtoc(x) ((x)>>(PGSHIFT-DEV_BSHIFT))
+#define dtob(x) ((x)<<DEV_BSHIFT)
+
+/* pages to bytes */
+#define ctob(x) ((x)<<PGSHIFT)
+
+/* bytes to pages */
+#define btoc(x) (((unsigned)(x)+(NBPG-1))>>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))
+
+/*
+ * Mach derived conversion macros
+ */
+#define atari_round_seg(x) ((((unsigned)(x)) + NBSEG - 1) & ~(NBSEG-1))
+#define atari_trunc_seg(x) ((unsigned)(x) & ~(NBSEG-1))
+#define atari_round_page(x) ((((unsigned)(x)) + NBPG - 1) & ~(NBPG-1))
+#define atari_trunc_page(x) ((unsigned)(x) & ~(NBPG-1))
+#define atari_btos(x) ((unsigned)(x) >> SEGSHIFT)
+#define atari_stob(x) ((unsigned)(x) << SEGSHIFT)
+#define atari_btop(x) ((unsigned)(x) >> PGSHIFT)
+#define atari_ptob(x) ((unsigned)(x) << PGSHIFT)
+
+/*
+ * spl functions; all but spl0 are done in-line
+ */
+#include <machine/psl.h>
+
+#define _debug_spl(s) \
+({ \
+ register int _spl_r; \
+\
+ __asm __volatile ("clrl %0; movew sr,%0; movew %1,sr" : \
+ "&=d" (_spl_r) : "di" (s)); \
+ if ((_spl_r&PSL_IPL) > (s&PSL_IPL)) \
+ printf ("%s:%d:spl(%d) ==> spl(%d)!!\n",__FILE__,__LINE__, \
+ ((PSL_IPL&_spl_r)>>8), ((PSL_IPL&s)>>8)); \
+ _spl_r; \
+})
+
+#define _spl_no_check(s) \
+({ \
+ register int _spl_r; \
+\
+ __asm __volatile ("clrl %0; movew sr,%0; movew %1,sr" : \
+ "&=d" (_spl_r) : "di" (s)); \
+ _spl_r; \
+})
+#if defined (DEBUG)
+#define _spl _debug_spl
+#else
+#define _spl _spl_no_check
+#endif
+
+/* spl0 requires checking for software interrupts */
+#define spl1() _spl(PSL_S|PSL_IPL1)
+#define spl2() _spl(PSL_S|PSL_IPL2)
+#define spl3() _spl(PSL_S|PSL_IPL3)
+#define spl4() _spl(PSL_S|PSL_IPL4)
+#define spl5() _spl(PSL_S|PSL_IPL5)
+#define spl6() _spl(PSL_S|PSL_IPL6)
+#define spl7() _spl(PSL_S|PSL_IPL7)
+
+#define splnone() spl0()
+#define splsoftclock() spl1()
+#define splnet() spl1()
+#define splbio() spl3()
+#define splimp() spl3()
+/*
+ * lowered to spl4 to allow for serial input into
+ * private ringbuffer inspite of spltty
+ */
+#define spltty() spl4()
+#define splclock() spl6()
+#define splstatclock() spl6()
+#define splvm() spl6()
+#define splhigh() spl7()
+#define splsched() spl7()
+
+#define splx(s) (s & PSL_IPL ? _spl_no_check(s) : spl0())
+
+#ifdef KERNEL
+extern int cpuspeed;
+void delay __P((int));
+void DELAY __P((int));
+#else
+#define DELAY(n) { register int N = (n); while (--N > 0); }
+#endif
+
+#endif /* !_MACHINE_PARAM_H_ */
diff --git a/sys/arch/atari/include/pcb.h b/sys/arch/atari/include/pcb.h
new file mode 100644
index 00000000000..fbb5f018fbe
--- /dev/null
+++ b/sys/arch/atari/include/pcb.h
@@ -0,0 +1,77 @@
+/* $NetBSD: pcb.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * from: Utah $Hdr: pcb.h 1.13 89/04/23$
+ *
+ * @(#)pcb.h 7.4 (Berkeley) 5/4/91
+ */
+
+#ifndef _MACHINE_PCB_H_
+#define _MACHINE_PCB_H_
+
+#include <machine/frame.h>
+
+/*
+ * ATARI process control block
+ */
+struct pcb
+{
+ short pcb_flags; /* misc. process flags (+0) */
+ short pcb_ps; /* processor status word (+2) */
+ int pcb_ustp; /* user segment table pointer (+4) */
+ int pcb_usp; /* user stack pointer (+8) */
+ int pcb_regs[12]; /* D0-D7, A0-A7 (+C) */
+ int pcb_cmap2; /* temporary copy PTE */
+ caddr_t pcb_onfault; /* for copyin/out faults */
+ struct fpframe pcb_fpregs; /* 68881/2 context save area */
+ int pcb_exec[16]; /* exec structure for core dumps */
+};
+
+/* flags (none currently used) */
+
+/*
+ * The pcb is augmented with machine-dependent additional data for
+ * core dumps. For the hp300, this includes an HP-UX exec header
+ * which is dumped for HP-UX processes.
+ */
+struct md_coredump {
+ int md_exec[16]; /* exec structure for HP-UX core dumps */
+};
+
+#endif /* !_MACHINE_PCB_H_ */
diff --git a/sys/arch/atari/include/pmap.h b/sys/arch/atari/include/pmap.h
new file mode 100644
index 00000000000..57dc7a5a6f7
--- /dev/null
+++ b/sys/arch/atari/include/pmap.h
@@ -0,0 +1,105 @@
+/* $NetBSD: pmap.h,v 1.1.1.1 1995/03/26 07:12:05 leo Exp $ */
+
+/*
+ * Copyright (c) 1987 Carnegie-Mellon University
+ * Copyright (c) 1991 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.
+ *
+ * @(#)pmap.h 7.6 (Berkeley) 5/10/91
+ */
+
+#ifndef _MACHINE_PMAP_H_
+#define _MACHINE_PMAP_H_
+
+/*
+ * Pmap stuff (in anticipation of '40 support)
+ */
+struct pmap {
+ u_int *pm_ptab; /* KVA of page table */
+ u_int *pm_stab; /* KVA of segment table */
+ u_int *pm_rtab; /* KVA of 68040 root table */
+ int pm_stchanged; /* ST changed */
+ short pm_sref; /* segment table ref count */
+ short pm_count; /* pmap reference count */
+ long pm_ptpages; /* more stats: PT pages */
+ simple_lock_data_t pm_lock; /* lock on pmap */
+ struct pmap_statistics pm_stats; /* pmap statistics */
+};
+
+typedef struct pmap *pmap_t;
+extern pmap_t kernel_pmap;
+
+/*
+ * Macros for speed
+ */
+#define PMAP_ACTIVATE(pmapp, pcbp, iscurproc) \
+ if ((pmapp) != NULL && (pmapp)->pm_stchanged) { \
+ (pcbp)->pcb_ustp = \
+ atari_btop(pmap_extract(kernel_pmap, \
+ cpu040 ? (vm_offset_t)(pmapp)->pm_rtab : \
+ (vm_offset_t)(pmapp)->pm_stab)); \
+ if (iscurproc) \
+ loadustp((pcbp)->pcb_ustp); \
+ (pmapp)->pm_stchanged = FALSE; \
+ }
+#define PMAP_DEACTIVATE(pmapp, pcbp)
+
+/*
+ * 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 */
+ struct pmap *pv_pmap; /* pmap where mapping lies */
+ vm_offset_t pv_va; /* virtual address for mapping */
+ u_int *pv_ptste; /* non-zero if VA maps a PT page */
+ struct pmap *pv_ptpmap; /* if pv_ptste, pmap for PT page */
+ int pv_flags; /* flags */
+} *pv_entry_t;
+
+#define PV_CI 0x01 /* all entries must be cache inhibited */
+#define PV_PTPAGE 0x02 /* entry maps a page table page */
+
+#ifdef KERNEL
+extern pv_entry_t pv_table; /* array of entries, one per page */
+extern u_int *Sysmap;
+extern char *vmmap; /* map for mem, dumps, etc. */
+
+#define pa_index(pa) atop(pa - vm_first_phys)
+#define pa_to_pvh(pa) (&pv_table[pa_index(pa)])
+#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
+#endif KERNEL
+
+#endif /* !_MACHINE_PMAP_H_ */
diff --git a/sys/arch/atari/include/proc.h b/sys/arch/atari/include/proc.h
new file mode 100644
index 00000000000..8104668f7cc
--- /dev/null
+++ b/sys/arch/atari/include/proc.h
@@ -0,0 +1,52 @@
+/* $NetBSD: proc.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+/*
+ * Copyright (c) 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.
+ */
+
+#ifndef _MACHINE_PROC_H_
+#define _MACHINE_PROC_H_
+
+/*
+ * Machine-dependent part of the proc structure for atari.
+ */
+struct mdproc {
+ int *md_regs; /* registers on current frame */
+ long md_flags; /* machine-dependent flags */
+};
+
+/* md_flags */
+#define MDP_AST 0x0001 /* async trap pending */
+#define MDP_STACKADJ 0x0002 /* frame SP adjusted, might have to
+ undo when system call returns
+ ERESTART. */
+#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/arch/atari/include/profile.h b/sys/arch/atari/include/profile.h
new file mode 100644
index 00000000000..2c0aad6025c
--- /dev/null
+++ b/sys/arch/atari/include/profile.h
@@ -0,0 +1,8 @@
+/* $NetBSD: profile.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+#ifndef _MACHINE_PROFILE_H_
+#define _MACHINE_PROFILE_H_
+
+#include <m68k/profile.h>
+
+#endif
diff --git a/sys/arch/atari/include/psl.h b/sys/arch/atari/include/psl.h
new file mode 100644
index 00000000000..101d091b428
--- /dev/null
+++ b/sys/arch/atari/include/psl.h
@@ -0,0 +1,8 @@
+/* $NetBSD: psl.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+#ifndef _MACHINE_PSL_H_
+#define _MACHINE_PSL_H_
+
+#include <m68k/psl.h>
+
+#endif
diff --git a/sys/arch/atari/include/pte.h b/sys/arch/atari/include/pte.h
new file mode 100644
index 00000000000..3c65653104a
--- /dev/null
+++ b/sys/arch/atari/include/pte.h
@@ -0,0 +1,143 @@
+/* $NetBSD: pte.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * from: Utah $Hdr: pte.h 1.11 89/09/03$
+ *
+ * @(#)pte.h 7.3 (Berkeley) 5/8/91
+ */
+
+#ifndef _MACHINE_PTE_H_
+#define _MACHINE_PTE_H_
+
+/*
+ * ATARI hardware segment/page table entries
+ */
+
+struct pte {
+ u_int pte;
+};
+
+typedef u_int pt_entry_t;
+
+struct ste {
+ u_int ste;
+};
+
+typedef u_int st_entry_t;
+
+#define PT_ENTRY_NULL ((u_int *) 0)
+#define ST_ENTRY_NULL ((u_int *) 0)
+
+#define SG_V 0x00000002 /* segment is valid */
+#define SG_NV 0x00000000
+#define SG_PROT 0x00000004 /* access protection mask */
+#define SG_RO 0x00000004
+#define SG_RW 0x00000000
+#define SG_U 0x00000008 /* modified bit (68040) */
+#define SG_FRAME 0xffffe000
+#define SG_IMASK 0xff000000
+#define SG_ISHIFT 24
+#define SG_PMASK 0x00ffe000
+#define SG_PSHIFT 13
+
+/* 68040 additions */
+#define SG4_IMASK1 0xfe000000
+#define SG4_ISHIFT1 25
+#define SG4_IMASK2 0x01fc0000
+#define SG4_IMASK 0xfffc0000
+#define SG4_PMASK 0x0003e000
+#define SG4_ISHIFT 18
+
+#define PG_V 0x00000001
+#define PG_NV 0x00000000
+#define PG_PROT 0x00000004
+#define PG_U 0x00000008
+#define PG_M 0x00000010
+#define PG_W 0x00000100
+#define PG_RO 0x00000004
+#define PG_RW 0x00000000
+#define PG_FRAME 0xffffe000
+#define PG_CI 0x00000040
+#define PG_SHIFT 13
+#define PG_PFNUM(x) (((x) & PG_FRAME) >> PG_SHIFT)
+
+/* 68040 additions */
+#define PG_CMASK 0x00000060 /* cache mode mask */
+#define PG_CWT 0x00000000 /* writethrough caching */
+#define PG_CCB 0x00000020 /* copyback caching */
+#define PG_CIS 0x00000040 /* cache inhibited serialized */
+#define PG_CIN 0x00000060 /* cache inhibited nonserialized */
+#define PG_SO 0x00000080 /* supervisor only */
+
+#define ATARI_040RTSIZE 512 /* root (level 1) table size */
+#define ATARI_040STSIZE 512 /* segment (level 2) table size */
+#define ATARI_040PTSIZE 128 /* page (level 3) table size */
+#define ATARI_STSIZE 1024 /* segment table size */
+/*
+ * ATARI_MAX_COREUPT maximum number of incore user page tables
+ * ATARI_USER_PTSIZE the number of bytes for user pagetables
+ * ATARI_PTBASE the VA start of the map from which upt's are allocated
+ * ATARI_PTSIZE the size of the map from which upt's are allocated
+ * ATARI_KPTSIZE size of kernel page table
+ * ATARI_MAX_KPTSIZE the most number of bytes for kpt pages
+ * ATARI_MAX_PTSIZE the number of bytes to map everything
+ */
+#define ATARI_MAX_COREUPT 1024
+#define ATARI_UPTSIZE roundup(VM_MAXUSER_ADDRESS / NPTEPG, NBPG)
+#define ATARI_UPTBASE 0x10000000
+#define ATARI_UPTMAXSIZE \
+ roundup((ATARI_MAX_COREUPT * ATARI_UPTSIZE), NBPG)
+#define ATARI_MAX_KPTSIZE \
+ (ATARI_MAX_COREUPT * ATARI_UPTSIZE / NPTEPG)
+#define ATARI_KPTSIZE \
+ roundup((VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) / NPTEPG, NBPG)
+#define ATARI_MAX_PTSIZE roundup(0xffffffff / NPTEPG, NBPG)
+
+/*
+ * Kernel virtual address to page table entry and to physical address.
+ */
+#define kvtopte(va) \
+ (&Sysmap[((unsigned)(va) - VM_MIN_KERNEL_ADDRESS) >> PGSHIFT])
+#define ptetokv(pt) \
+ ((((u_int *)(pt) - Sysmap) << PGSHIFT) + VM_MIN_KERNEL_ADDRESS)
+#define kvtophys(va) \
+ ((kvtopte(va)->pg_pfnum << PGSHIFT) | ((int)(va) & PGOFSET))
+
+
+#endif /* !_MACHINE_PTE_H_ */
diff --git a/sys/arch/atari/include/ptrace.h b/sys/arch/atari/include/ptrace.h
new file mode 100644
index 00000000000..5f414028faa
--- /dev/null
+++ b/sys/arch/atari/include/ptrace.h
@@ -0,0 +1,8 @@
+/* $NetBSD: ptrace.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+#ifndef _MACHINE_PTRACE_H_
+#define _MACHINE_PTRACE_H_
+
+#include <m68k/ptrace.h>
+
+#endif
diff --git a/sys/arch/atari/include/reg.h b/sys/arch/atari/include/reg.h
new file mode 100644
index 00000000000..15aa532214f
--- /dev/null
+++ b/sys/arch/atari/include/reg.h
@@ -0,0 +1,8 @@
+/* $NetBSD: reg.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+#ifndef _MACHINE_REG_H_
+#define _MACHINE_REG_H_
+
+#include <m68k/reg.h>
+
+#endif
diff --git a/sys/arch/atari/include/scu.h b/sys/arch/atari/include/scu.h
new file mode 100644
index 00000000000..a516266c095
--- /dev/null
+++ b/sys/arch/atari/include/scu.h
@@ -0,0 +1,106 @@
+/* $NetBSD: scu.h,v 1.1.1.1 1995/03/26 07:12:08 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MACHINE_SCU_H
+#define _MACHINE_SCU_H
+/*
+ * Atari TT hardware:
+ * SCU registers
+ */
+
+#define SCU ((struct scu *)AD_SCU)
+
+
+/*
+ * System control unit
+ */
+struct scu {
+ volatile u_char fil1;
+ volatile u_char sys_mask; /* System interrupt mask */
+ volatile u_char fil2;
+ volatile u_char sys_stat; /* System interrupt status */
+ volatile u_char fil3;
+ volatile u_char sys_int; /* System interrupter */
+ volatile u_char fil4;
+ volatile u_char vme_int; /* VME interrupter */
+ volatile u_char fil5;
+ volatile u_char gen_reg1; /* General purpose reg. 1 */
+ volatile u_char fil6;
+ volatile u_char gen_reg2; /* General purpose reg. 2 */
+ volatile u_char fil7;
+ volatile u_char vme_mask; /* VME interrupt mask */
+ volatile u_char fil8;
+ volatile u_char vme_stat; /* VME interrupt status */
+};
+
+/*
+ * Bits for system mask & stat.
+ * Read 'sys_stat' first, reading 'sys_mask' clears pending bits in 'sys_stat'.
+ */
+#define SCU_SYSFAIL 0x80 /* _Sysfail in VME bus (Auto vectored) */
+#define SCU_MFP 0x40 /* MFP interrupt (Programmable) */
+#define SCU_SCC 0x20 /* SCC interrupt (Programmable) */
+#define SCU_VSYNC 0x10 /* Vertical Sync (Auto vectored) */
+ /* 0x08 Not Used */
+#define SCU_HSYNC 0x04 /* Horizontal Sync (Auto vectored) */
+#define SCU_SYS_SOFT 0x02 /* System Software INT (Auto vectored) */
+ /* 0x00 Not Used */
+
+/*
+ * Bits for VME mask & stat.
+ * Read 'vme_stat' first, reading 'vme_mask' clears pending bits in 'vme_stat'.
+ * Not that MFP/SCC interrupts are hard-wired to the mentioned VME IRQ's.
+ * (or'ed).
+ */
+#define SCU_IRQ7 0x80
+#define SCU_IQ6_MFP 0x40 /* Also MFP interrupt */
+#define SCU_IRQ5_SCC 0x20 /* Also SCC interrupt */
+#define SCU_IRQ4 0x10
+#define SCU_IRQ3_SOFT 0x08 /* Also VME Software interrupt */
+#define SCU_IRQ2 0x04
+#define SCU_IRQ1 0x02
+ /* 0x00 Not Used */
+
+/*
+ * Generate/remove Software system interrupt.
+ * Note: Will not be cleared automatically!!
+ */
+#define SET_SOFT_INT (SCU->sys_int = 1)
+#define CLR_SOFT_INT (SCU->sys_int = 0)
+
+/*
+ * Generate/remove Software VME interrupt.
+ * Note: Will not be cleared automatically!!
+ */
+#define SET_VME_INT (SCU->vme_int = 1)
+#define CLR_VME_INT (SCU->vme_int = 0)
+#endif /* _MACHINE_SCU_H */
diff --git a/sys/arch/atari/include/setjmp.h b/sys/arch/atari/include/setjmp.h
new file mode 100644
index 00000000000..47f4334abeb
--- /dev/null
+++ b/sys/arch/atari/include/setjmp.h
@@ -0,0 +1,3 @@
+/* $NetBSD: setjmp.h,v 1.1.1.1 1995/03/26 07:12:09 leo Exp $ */
+
+#include <m68k/setjmp.h>
diff --git a/sys/arch/atari/include/signal.h b/sys/arch/atari/include/signal.h
new file mode 100644
index 00000000000..05f47cbd64a
--- /dev/null
+++ b/sys/arch/atari/include/signal.h
@@ -0,0 +1,8 @@
+/* $NetBSD: signal.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+#ifndef _MACHINE_SIGNAL_H_
+#define _MACHINE_SIGNAL_H_
+
+#include <m68k/signal.h>
+
+#endif
diff --git a/sys/arch/atari/include/stdarg.h b/sys/arch/atari/include/stdarg.h
new file mode 100644
index 00000000000..9b66132359a
--- /dev/null
+++ b/sys/arch/atari/include/stdarg.h
@@ -0,0 +1,4 @@
+/* $NetBSD: stdarg.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/stdarg.h>
diff --git a/sys/arch/atari/include/tospart.h b/sys/arch/atari/include/tospart.h
new file mode 100644
index 00000000000..412ee61ea2a
--- /dev/null
+++ b/sys/arch/atari/include/tospart.h
@@ -0,0 +1,59 @@
+/* $NetBSD: tospart.h,v 1.1.1.1 1995/03/26 07:12:08 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MACHINE_TOSPART_H
+#define _MACHINE_TOSPART_H
+/*
+ * Format of GEM root sector
+ */
+typedef struct gem_part {
+ u_char p_flg; /* bit 0 is in-use flag */
+ u_char p_id[3]; /* id: GEM, BGM, XGM, UNX, MIX */
+ u_long p_st; /* block where partition starts */
+ u_long p_size; /* partition size */
+} GEM_PART;
+
+#define NGEM_PARTS 4 /* Max. partition infos in root sector */
+
+typedef struct gem_root {
+ u_char fill[0x1c2]; /* Filler, can be boot code */
+ u_long hd_siz; /* size of entire volume */
+ GEM_PART parts[NGEM_PARTS];/* see above */
+ u_long bsl_st; /* start of bad-sector list */
+ u_long bsl_cnt; /* # of blocks in bad-sect. list*/
+} GEM_ROOT;
+
+#define TOS_BSIZE 512 /* TOS blocksize */
+#define TOS_BBLOCK 0 /* TOS Bootblock */
+#define TOS_MAXPART 32 /* Maximum number of partitions we read */
+
+#endif /* _MACHINE_TOSPART_H */
diff --git a/sys/arch/atari/include/trap.h b/sys/arch/atari/include/trap.h
new file mode 100644
index 00000000000..192d7a95765
--- /dev/null
+++ b/sys/arch/atari/include/trap.h
@@ -0,0 +1,8 @@
+/* $NetBSD: trap.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+#ifndef _MACHINE_TRAP_H_
+#define _MACHINE_TRAP_H_
+
+#include <m68k/trap.h>
+
+#endif
diff --git a/sys/arch/atari/include/types.h b/sys/arch/atari/include/types.h
new file mode 100644
index 00000000000..625a9d06190
--- /dev/null
+++ b/sys/arch/atari/include/types.h
@@ -0,0 +1,8 @@
+/* $NetBSD: types.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+#ifndef _MACHINE_TYPES_H_
+#define _MACHINE_TYPES_H_
+
+#include <m68k/types.h>
+
+#endif
diff --git a/sys/arch/atari/include/varargs.h b/sys/arch/atari/include/varargs.h
new file mode 100644
index 00000000000..a1ff0b8af18
--- /dev/null
+++ b/sys/arch/atari/include/varargs.h
@@ -0,0 +1,4 @@
+/* $NetBSD: varargs.h,v 1.1.1.1 1995/03/26 07:12:06 leo Exp $ */
+
+/* Just use the common m68k definition */
+#include <m68k/varargs.h>
diff --git a/sys/arch/atari/include/video.h b/sys/arch/atari/include/video.h
new file mode 100644
index 00000000000..6ae02377477
--- /dev/null
+++ b/sys/arch/atari/include/video.h
@@ -0,0 +1,162 @@
+/* $NetBSD: video.h,v 1.1.1.1 1995/03/26 07:12:08 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 Leo Weppelman.
+ * 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 Leo Weppelman.
+ * 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 _MACHINE_VIDEO_H
+#define _MACHINE_VIDEO_H
+/*
+ * Access to circuitry for video
+ */
+
+#define VIDEO ((struct video *)AD_VIDEO)
+
+struct video {
+ volatile char vdb[64]; /* sparsely filled */
+ volatile u_short vd_st_rgb[16]; /* RGB for simultaneous colors (ST)*/
+ volatile u_char vd_st_res; /* ST resolution */
+ volatile char vd_fill1; /* filler */
+ volatile u_short vd_tt_res; /* TT-resultion mode */
+ volatile u_char vd_ste_hscroll; /* MEGA STe hor bitwise scroll */
+ volatile u_char vd_fill2[411];
+ volatile u_short vd_tt_rgb[256]; /* RGB for simultaneous TT colors */
+};
+
+#define vd_ramh vdb[ 1] /* base address Video RAM, high byte */
+#define vd_ramm vdb[ 3] /* base address Video RAM, mid byte */
+#define vd_raml vdb[13] /* base address Video RAM, low byte */
+#define vd_ptrh vdb[ 5] /* scan address Video RAM, high byte */
+#define vd_ptrm vdb[ 7] /* scan address Video RAM, mid byte */
+#define vd_ptrl vdb[ 9] /* scan address Video RAM, low byte */
+#define vd_sync vdb[10] /* synchronization mode */
+
+/* bits in vd_sync: */
+#define SYNC_EXT 0x01 /* extern sync */
+#define SYNC_50 0x02 /* 50 Hertz (used for color) */
+
+/* bits in vd_st_rgb[]: */
+#define RGB_B 0x0007
+#define RGB_G 0x0070
+#define RGB_R 0x0700
+
+/* some values for vd_st_rgb[]: */
+#define RGB_BLACK 0x0000
+#define RGB_RED 0x0700
+#define RGB_GREEN 0x0070
+#define RGB_BLUE 0x0007
+#define RGB_WHITE 0x0777
+#define RGB_MAGENTA 0x0707
+#define RGB_CYAN 0x0077
+#define RGB_YELLOW 0x0770
+#define RGB_LGREY 0x0555
+#define RGB_DGREY 0x0222
+
+/* values for vd_st_res: */
+#define RES_LOW 0x00 /* 320x200, 16 colors */
+#define RES_MID 0x01 /* 640x200, 4 colors */
+#define RES_HIGH 0x02 /* 640x400, monochrome */
+
+/* masks for vd_tt_res: */
+#define RES_STLOW 0x0000 /* 320x200, 16 colors */
+#define RES_STMID 0x0100 /* 640x200, 4 colors */
+#define RES_STHIGH 0x0200 /* 640x400, monochrome */
+#define RES_TTMID 0x0400 /* 640x480, 16 colors */
+#define RES_TTHIGH 0x0600 /* 1280x960, monochrome */
+#define RES_TTLOW 0x0700 /* 320x480, 256 colors */
+#define TT_PALLET 0x000f /* Pallette number */
+#define TT_HYMONO 0x8000 /* Hyper mono mode */
+#define TT_SHOLD 0x1000 /* Sample/hold mode */
+
+/*
+ * Yahama YM-2149 Programmable Sound Generator
+ */
+
+#define SOUND ((struct sound *)AD_SOUND)
+
+struct sound {
+ char sdb[4]; /* use only the even bytes */
+};
+
+#define sd_selr sdb[0] /* select register */
+#define sd_rdat sdb[0] /* read register data */
+#define sd_wdat sdb[2] /* write register data */
+
+/*
+ * Accessing the YM-2149 registers is indirect through ST-specific
+ * circuitry by writing the register number into sd_selr.
+ */
+#define YM_PA0 0 /* Period Channel A, bits 0-7 */
+#define YM_PA1 1 /* Period Channel A, bits 8-11 */
+#define YM_PB0 2 /* Period Channel B, bits 0-7 */
+#define YM_PB1 3 /* Period Channel B, bits 8-11 */
+#define YM_PC0 4 /* Period Channel C, bits 0-7 */
+#define YM_PC1 5 /* Period Channel C, bits 8-11 */
+#define YM_PNG 6 /* Period Noise Generator, bits 0-4 */
+#define YM_MFR 7 /* Multi Function Register */
+#define YM_VA 8 /* Volume Channel A */
+#define YM_VB 9 /* Volume Channel B */
+#define YM_VC 10 /* Volume Channel C */
+#define YM_PE0 11 /* Period Envelope, bits 0-7 */
+#define YM_PE1 12 /* Period Envelope, bits 8-15 */
+#define YM_WFE 13 /* Wave Form Envelope */
+#define YM_IOA 14 /* I/O port A */
+#define YM_IOB 15 /* I/O port B */
+
+/* bits in MFR: */
+#define SA_OFF 0x01 /* Sound Channel A off */
+#define SB_OFF 0x02 /* Sound Channel B off */
+#define SC_OFF 0x04 /* Sound Channel C off */
+#define NA_OFF 0x08 /* Noise Channel A off */
+#define NB_OFF 0x10 /* Noise Channel B off */
+#define NC_OFF 0x20 /* Noise Channel C off */
+#define PA_OUT 0x40 /* Port A for Output */
+#define PB_OUT 0x80 /* Port B for Output */
+
+/* bits in Vx: */
+#define VOLUME 0x0F /* 16 steps */
+#define ENVELOP 0x10 /* volume steered by envelope */
+
+/* bits in WFE: */
+#define WF_HOLD 0x01 /* hold after one period */
+#define WF_ALTERNAT 0x02 /* up and down (no saw teeth) */
+#define WF_ATTACK 0x04 /* start up */
+#define WF_CONTINUE 0x08 /* multiple periods */
+
+/* names for bits in Port A (ST specific): */
+#define PA_SIDEB 0x01 /* select floppy head - if double sided */
+#define PA_FLOP0 0x02 /* Drive Select Floppy 0 */
+#define PA_FLOP1 0x04 /* Drive Select Floppy 1 */
+#define PA_SRTS 0x08 /* Serial RTS */
+#define PA_SDTR 0x10 /* Serial DTR */
+#define PA_PSTROBE 0x20 /* Parallel Strobe */
+#define PA_USER 0x40 /* Free Pin on Monitor Connector */
+/* 0x80 reserved */
+
+#endif /* _MACHINE_VIDEO_H */
diff --git a/sys/arch/atari/include/vmparam.h b/sys/arch/atari/include/vmparam.h
new file mode 100644
index 00000000000..07025dfa6c5
--- /dev/null
+++ b/sys/arch/atari/include/vmparam.h
@@ -0,0 +1,168 @@
+/* $NetBSD: vmparam.h,v 1.1.1.1 1995/03/26 07:12:07 leo Exp $ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990 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.
+ *
+ * from: Utah $Hdr: vmparam.h 1.16 91/01/18$
+ *
+ * @(#)vmparam.h 7.3 (Berkeley) 5/7/91
+ */
+
+#ifndef _MACHINE_VMPARAM_H_
+#define _MACHINE_VMPARAM_H_
+
+#include <machine/pte.h>
+
+/*
+ * Machine dependent constants for HP300
+ */
+/*
+ * USRTEXT is the start of the user text/data space, while USRSTACK
+ * is the top (end) of the user stack. LOWPAGES and HIGHPAGES are
+ * the number of pages from the beginning of the P0 region to the
+ * beginning of the text and from the beginning of the P1 region to the
+ * beginning of the stack respectively.
+ *
+ * These are a mixture of i386, sun3 and hp settings..
+ */
+
+/* Sun settings. Still hope, that I might get sun3 binaries to work... */
+#define USRTEXT 0x2000
+#define USRSTACK 0x0E000000
+#define LOWPAGES btoc(USRTEXT)
+#define KUSER_AREA (-UPAGES*NBPG)
+/*
+ * Virtual memory related constants, all in bytes
+ */
+
+#ifndef MAXTSIZ
+#define MAXTSIZ (6*1024*1024) /* max text size */
+#endif
+#ifndef DFLDSIZ
+#define DFLDSIZ (32*1024*1024) /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define MAXDSIZ (32*1024*1024) /* max data size */
+#endif
+#ifndef DFLSSIZ
+#define DFLSSIZ (2*1024*1024) /* initial stack size limit */
+#endif
+#ifndef MAXSSIZ
+#define MAXSSIZ MAXDSIZ /* 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.
+ * DMMIN should be at least ctod(1) so that vtod() works.
+ * vminit() insures this.
+ */
+#define DMMIN 32 /* smallest swap allocation */
+#define DMMAX NBPG /* largest potential swap allocation */
+
+/*
+ * Sizes of the system and user portions of the system page table.
+ */
+/* SYSPTSIZE IS SILLY; IT SHOULD BE COMPUTED AT BOOT TIME */
+#define SYSPTSIZE (2 * NPTEPG) /* 16mb */
+#define USRPTSIZE (1 * NPTEPG) /* 16mb */
+
+/*
+ * PTEs for mapping user space into the kernel for phyio operations.
+ * One page is enough to handle 16Mb of simultaneous raw IO operations.
+ */
+#ifndef USRIOSIZE
+#define USRIOSIZE (1 * NPTEPG) /* 16mb */
+#endif
+
+/*
+ * PTEs for system V style shared memory.
+ * This is basically slop for kmempt which we actually allocate (malloc) from.
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS (1 * NPTEPG) /* 16mb */
+#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
+
+/*
+ * A swapped in process is given a small amount of core without being bothered
+ * by the page replacement algorithm. Basically this says that if you are
+ * swapped in you deserve some resources. We protect the last SAFERSS
+ * pages against paging and will just swap you out rather than paging you.
+ * Note that each process has at least UPAGES+CLSIZE pages which are not
+ * paged anyways (this is currently 8+2=10 pages or 5k bytes), so this
+ * number just means a swapped in process is given around 25k bytes.
+ * Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81),
+ * so we loan each swapped in process memory worth 100$, or just admit
+ * that we don't consider it worthwhile and swap it out to disk which costs
+ * $30/mb or about $0.75.
+ */
+#define SAFERSS 4 /* nominal ``small'' resident set size
+ protected against replacement */
+
+/*
+ * user/kernel map constants
+ */
+#define VM_MIN_ADDRESS ((vm_offset_t)0)
+#define VM_MAXUSER_ADDRESS ((vm_offset_t)(USRSTACK))
+#define VM_MAX_ADDRESS ((vm_offset_t)(0-(UPAGES*NBPG)))
+#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0)
+#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)(0-NBPG))
+
+/*
+ * 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)
+
+/*
+ * number of kernel PT pages (initial only, can grow dynamically)
+ */
+#define VM_KERNEL_PT_PAGES ((vm_size_t)2) /* XXX: SYSPTSIZE */
+#endif /* !_MACHINE_VMPARAM_H_ */
diff --git a/sys/arch/atari/stand/binpatch/Makefile b/sys/arch/atari/stand/binpatch/Makefile
new file mode 100644
index 00000000000..868b6a0fd7c
--- /dev/null
+++ b/sys/arch/atari/stand/binpatch/Makefile
@@ -0,0 +1,9 @@
+# $NetBSD: Makefile,v 1.1.1.1 1995/03/26 07:12:05 leo Exp $
+
+PROG=binpatch
+MAN8=binpatch.0
+
+BINDIR=/sbin
+LDFLAGS+=-static
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/atari/stand/binpatch/binpatch.8 b/sys/arch/atari/stand/binpatch/binpatch.8
new file mode 100644
index 00000000000..4d0017b3eb4
--- /dev/null
+++ b/sys/arch/atari/stand/binpatch/binpatch.8
@@ -0,0 +1,96 @@
+.\" $NetBSD: binpatch.8,v 1.1.1.1 1995/03/26 07:12:05 leo Exp $
+.\"
+.\" Copyright (c) 1994 Christian E. Hopps
+.\" 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 Christian E. Hopps.
+.\" 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.
+.\"
+.Dd February 2, 1994
+.Dt BINPATCH 8 atari
+.Os
+.Sh NAME
+.Nm binpatch
+.Nd examine and or modify initialized data in a binary file.
+.Sh SYNOPSIS
+.Nm binpatch
+.Op Fl b | Fl w | Fl l
+.Op Fl o Ar offset
+.Fl s Ar symname
+.Op Fl r Ar value
+.Ar binfile
+.Nm binpatch
+.Op Fl b | Fl w | Fl l
+.Op Fl o Ar offset
+.Fl a Ar addr
+.Op Fl r Ar value
+.Ar binfile
+.Sh DESCRIPTION
+.Nm binpatch
+is used to modify or examine the data associated with a symbol in a binary
+file
+.Ar binfile .
+The flags
+.Fl b ,
+.Fl w
+and
+.Fl l
+specify the size of the data to be modified or examined
+(byte, word and long respectively.) The
+.Ar binfile
+is scanned in search of the symbol
+.Ar symname
+(specified with the
+.Fl s
+flag)
+If the symbol is found the current data and address are printed. Next if the
+.Fl r
+flag has been given, the current data is replaced with that of
+.Ar value .
+.Pp
+If the second form is used the address
+.Ar addr
+specified with the
+.Fl a
+flag is used as a direct address into the data section of the binary and
+no symbol search is performed.
+.Pp
+The
+.Fl o
+flag specifies an offset in byte, word or long (
+.Fl b
+,
+.Fl w
+,
+or
+.Fl l
+) units from the given locator (
+.Fl s
+or
+.Fl a
+) for
+.Nm binpatch
+to perform it's described actions.
+
diff --git a/sys/arch/atari/stand/binpatch/binpatch.c b/sys/arch/atari/stand/binpatch/binpatch.c
new file mode 100644
index 00000000000..79f25f72c0a
--- /dev/null
+++ b/sys/arch/atari/stand/binpatch/binpatch.c
@@ -0,0 +1,241 @@
+/* $NetBSD: binpatch.c,v 1.1.1.1 1995/03/26 07:12:04 leo Exp $ */
+
+/*
+ * Copyright (c) 1994 Christian E. Hopps
+ * 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 Christian E. Hopps.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <a.out.h>
+#include <stdio.h>
+
+extern char *optarg;
+extern int optind;
+
+volatile void error ();
+
+int test = 1;
+int testbss;
+char foo = 23;
+
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct exec e;
+ int c;
+ u_long addr = 0, offset = 0;
+ u_long replace = 0, do_replace = 0;
+ char *symbol = 0;
+ char size = 4; /* default to long */
+ char *fname;
+ int fd;
+ int type, off;
+ u_long lval;
+ u_short sval;
+ u_char cval;
+
+
+ while ((c = getopt (argc, argv, "a:bwlr:s:o:")) != EOF)
+ switch (c)
+ {
+ case 'a':
+ if (addr || symbol)
+ error ("only one address/symbol allowed");
+ if (! strncmp (optarg, "0x", 2))
+ sscanf (optarg, "%x", &addr);
+ else
+ addr = atoi (optarg);
+ if (! addr)
+ error ("invalid address");
+ break;
+
+ case 'b':
+ size = 1;
+ break;
+
+ case 'w':
+ size = 2;
+ break;
+
+ case 'l':
+ size = 4;
+ break;
+
+ case 'r':
+ do_replace = 1;
+ if (! strncmp (optarg, "0x", 2))
+ sscanf (optarg, "%x", &replace);
+ else
+ replace = atoi (optarg);
+ break;
+
+ case 's':
+ if (addr || symbol)
+ error ("only one address/symbol allowed");
+ symbol = optarg;
+ break;
+
+ case 'o':
+ if (offset)
+ error ("only one offset allowed");
+ if (! strncmp (optarg, "0x", 2))
+ sscanf (optarg, "%x", &offset);
+ else
+ offset = atoi (optarg);
+ break;
+ }
+
+ argv += optind;
+ argc -= optind;
+
+
+ if (argc < 1)
+ error ("No file to patch.");
+
+ fname = argv[0];
+ if ((fd = open (fname, 0)) < 0)
+ error ("Can't open file");
+
+ if (read (fd, &e, sizeof (e)) != sizeof (e)
+ || N_BADMAG (e))
+ error ("Not a valid executable.");
+
+ /* fake mid, so the N_ macros work on the amiga.. */
+ e.a_midmag |= 127 << 16;
+
+ if (symbol)
+ {
+ struct nlist nl[2];
+ nl[0].n_un.n_name = symbol;
+ nl[1].n_un.n_name = 0;
+ if (nlist (fname, nl) != 0)
+ error ("Symbol not found.");
+ addr = nl[0].n_value;
+ type = nl[0].n_type & N_TYPE;
+ }
+ else
+ {
+ type = N_UNDF;
+ if (addr >= N_TXTADDR(e) && addr < N_DATADDR(e))
+ type = N_TEXT;
+ else if (addr >= N_DATADDR(e) && addr < N_DATADDR(e) + e.a_data)
+ type = N_DATA;
+ }
+ addr += offset;
+
+ /* if replace-mode, have to reopen the file for writing.
+ Can't do that from the beginning, or nlist() will not
+ work (at least not under AmigaDOS) */
+ if (do_replace)
+ {
+ close (fd);
+ if ((fd = open (fname, 2)) == -1)
+ error ("Can't reopen file for writing.");
+ }
+
+ if (type != N_TEXT && type != N_DATA)
+ error ("address/symbol is not in text or data section.");
+
+ if (type == N_TEXT)
+ off = addr - N_TXTADDR(e) + N_TXTOFF(e);
+ else
+ off = addr - N_DATADDR(e) + N_DATOFF(e);
+
+ if (lseek (fd, off, 0) == -1)
+ error ("lseek");
+
+ /* not beautiful, but works on big and little endian machines */
+ switch (size)
+ {
+ case 1:
+ if (read (fd, &cval, 1) != 1)
+ error ("cread");
+ lval = cval;
+ break;
+
+ case 2:
+ if (read (fd, &sval, 2) != 2)
+ error ("sread");
+ lval = sval;
+ break;
+
+ case 4:
+ if (read (fd, &lval, 4) != 4)
+ error ("lread");
+ break;
+ }
+
+
+ if (symbol)
+ printf ("%s(0x%x): %d (0x%x)\n", symbol, addr, lval, lval);
+ else
+ printf ("0x%x: %d (0x%x)\n", addr, lval, lval);
+
+ if (do_replace)
+ {
+ if (lseek (fd, off, 0) == -1)
+ error ("write-lseek");
+ switch (size)
+ {
+ case 1:
+ cval = replace;
+ if (cval != replace)
+ error ("byte-value overflow.");
+ if (write (fd, &cval, 1) != 1)
+ error ("cwrite");
+ break;
+
+ case 2:
+ sval = replace;
+ if (sval != replace)
+ error ("word-value overflow.");
+ if (write (fd, &sval, 2) != 2)
+ error ("swrite");
+ break;
+
+ case 4:
+ if (write (fd, &replace, 4) != 4)
+ error ("lwrite");
+ break;
+ }
+ }
+
+ close (fd);
+}
+
+
+
+volatile void error (str)
+ char *str;
+{
+ fprintf (stderr, "%s\n", str);
+ exit (1);
+}
diff --git a/sys/arch/atari/stand/chg_pid/chg_pid.c b/sys/arch/atari/stand/chg_pid/chg_pid.c
new file mode 100644
index 00000000000..926519b8075
--- /dev/null
+++ b/sys/arch/atari/stand/chg_pid/chg_pid.c
@@ -0,0 +1,240 @@
+/* $NetBSD: chg_pid.c,v 1.1.1.1 1995/03/26 07:12:04 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 L. Weppelman
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *
+ * This program changes the partition id field (p_id) in the GEM
+ * partition info. NetBSD uses these id-fields to determine the kind
+ * of partition. Sensible id's to set are:
+ * NBU : NetBSD User partition
+ * NBR : NetBSD Root partition
+ * NBS : NetBSD Swap partition
+ *
+ * When NetBSD auto boots, the first 'NBR' partition found when scanning the
+ * SCSI-disks becomes the active root partition. The same goes for 'NBS'.
+ * Drives are scanned in 'SCSI-id' order.
+ */
+#include <stdio.h>
+#include <osbind.h>
+
+/*
+ * Format of GEM root sector
+ */
+typedef struct gem_part {
+ u_char p_flg; /* bit 0 is in-use flag */
+ u_char p_id[3]; /* id: GEM, BGM, XGM, UNX, MIX */
+ u_long p_st; /* block where partition starts */
+ u_long p_size; /* partition size */
+} GEM_PART;
+
+#define NGEM_PARTS 4 /* Max. partition infos in root sector */
+
+typedef struct gem_root {
+ u_char fill[0x1c2]; /* Filler, can be boot code */
+ u_long hd_siz; /* size of entire volume */
+ GEM_PART parts[NGEM_PARTS]; /* see above */
+ u_long bsl_st; /* start of bad-sector list */
+ u_long bsl_cnt; /* nr. blocks in bad-sector list*/
+ u_short csum; /* checksum correction */
+} GEM_ROOT;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int driveno = 0;
+ int partno = 0;
+ char *newname;
+ int c;
+
+ if(argc != 4)
+ usage();
+ driveno = atoi(argv[1]);
+ partno = atoi(argv[2]);
+ newname = argv[3];
+
+ printf("Note: drives start numbering at 0!\n");
+ printf("About to change id of partition %d on drive %d to %s\n",
+ partno, driveno, newname);
+ printf("Are you sure (y/n)? ");
+ c = getchar();
+ switch(c) {
+ case 'y':
+ case 'Y':
+ if(chg_tosparts(partno, driveno, newname))
+ printf("Done\n");
+ else printf("Partion number not found\n");
+ break;
+ default :
+ printf("Aborted\n");
+ }
+}
+
+usage()
+{
+ printf("Usage: chg_pid <driveno> <partno> <newid>\n");
+ exit(1);
+}
+
+int chg_tosparts(chg_part, drive, newname)
+int chg_part, drive;
+char *newname;
+{
+ GEM_ROOT *g_root;
+ GEM_PART g_local[NGEM_PARTS];
+ char buf[512];
+ int pno = 1;
+ int i;
+
+ /*
+ * Read root sector
+ */
+ if(read_block(buf, 0, drive) == 0) {
+ fprintf(stderr, "Cannot read block 0\n");
+ exit(1);
+ }
+
+ /*
+ * Make local copy of partition info, we may need to re-use
+ * the buffer in case of 'XGM' partitions.
+ */
+ g_root = (GEM_ROOT*)buf;
+ bcopy(g_root->parts, g_local, NGEM_PARTS*sizeof(GEM_PART));
+
+
+ for(i = 0; i < NGEM_PARTS; i++) {
+ if(!(g_local[i].p_flg & 1))
+ continue;
+ if(!strncmp(g_local[i].p_id, "XGM", 3)) {
+ int j;
+ daddr_t new_root = g_local[i].p_st;
+
+ /*
+ * Loop through extended partition list
+ */
+ for(;;) {
+ if(read_block(buf, new_root, drive) == 0) {
+ fprintf(stderr, "Cannot read block %d\n", new_root);
+ exit(1);
+ }
+ for(j = 0; j < NGEM_PARTS; j++) {
+ if(!(g_root->parts[j].p_flg & 1))
+ continue;
+ if(!strncmp(g_root->parts[j].p_id, "XGM", 3)) {
+ new_root = g_local[i].p_st + g_root->parts[j].p_st;
+ break;
+ }
+ else {
+ if(pno == chg_part) {
+ change_it(pno,g_root->parts[j].p_id, newname);
+ if(write_block(buf, new_root, drive) == 0) {
+ fprintf(stderr, "Cannot write block %d\n",
+ new_root);
+ exit(1);
+ }
+ return(1);
+ }
+ pno++;
+ }
+ }
+ if(j == NGEM_PARTS)
+ break;
+ }
+ }
+ else {
+ if(pno == chg_part) {
+ /*
+ * Re-read block 0
+ */
+ if(read_block(buf, 0, drive) == 0) {
+ fprintf(stderr, "Cannot read block 0\n");
+ exit(1);
+ }
+ change_it(pno, g_root->parts[i].p_id, newname);
+ set_csum(buf);
+ if(write_block(buf, 0, drive) == 0) {
+ fprintf(stderr, "Cannot write block 0\n");
+ exit(1);
+ }
+ return(1);
+ }
+ pno++;
+ }
+ }
+ return(0);
+}
+
+change_it(pno, p_id, newname)
+int pno;
+char *p_id, *newname;
+{
+ char s1[4], s2[4];
+
+ strncpy(s1, p_id, 3);
+ strncpy(s2, newname, 3);
+ s1[3] = s2[3] = '\0';
+ printf("Changing partition %d: %s -> %s ...", pno, s1, s2);
+ p_id[0] = s2[0]; p_id[1] = s2[1]; p_id[2] = s2[2];
+}
+
+read_block(buf, blkno, drive)
+void *buf;
+int blkno;
+int drive;
+{
+ if(Dmaread(blkno, 1, buf, drive + 8) != 0)
+ return(0);
+ return(1);
+}
+
+write_block(buf, blkno, drive)
+void *buf;
+int blkno;
+int drive;
+{
+ if(Dmawrite(blkno, 1, buf, drive + 8) != 0)
+ return(0);
+ return(1);
+}
+
+set_csum(buf)
+char *buf;
+{
+ unsigned short *p = (unsigned short *)buf;
+ unsigned short csum = 0;
+ int i;
+
+ p[255] = 0;
+ for(i = 0; i < 256; i++)
+ csum += *p++;
+ *--p = (0x1234 - csum) & 0xffff;
+}
diff --git a/sys/arch/atari/stand/loadbsd/loadbsd.c b/sys/arch/atari/stand/loadbsd/loadbsd.c
new file mode 100644
index 00000000000..b4143e3740e
--- /dev/null
+++ b/sys/arch/atari/stand/loadbsd/loadbsd.c
@@ -0,0 +1,383 @@
+/* $NetBSD: loadbsd.c,v 1.1.1.1 1995/03/26 07:12:04 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 L. Weppelman
+ * 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 Leo Weppelman.
+ * 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.
+ */
+
+/*
+ * NetBSD loader for the Atari-TT.
+ */
+
+#include <stdio.h>
+#include <a_out.h>
+#include <fcntl.h>
+#include <osbind.h>
+#include <stdarg.h>
+#include "loader.h"
+
+char *Progname; /* How are we called */
+int t_flag = 0; /* Just test, do not execute */
+
+char version[] = "$VER: LoadBSD 1.0 (11/01/95)";
+
+/*
+ * Default name of kernel to boot, large enough to patch
+ */
+char kname[80] = "n:/netbsd";
+
+static struct {
+ u_char *kp; /* 00: Kernel load address */
+ long ksize; /* 04: Size of loaded kernel */
+ u_long entry; /* 08: Kernel entry point */
+ long stmem_size; /* 12: Size of st-ram */
+ long ttmem_size; /* 16: Size of tt-ram */
+ long cputype; /* 20: Type of cpu */
+ long boothowto; /* 24: How to boot */
+ long ttmem_start; /* 28: Start of tt-ram */
+ long esym_loc; /* 32: End of symbol table */
+} kparam;
+
+void get_sys_info(void);
+void error(char *fmt, ...);
+void help(void);
+void usage(void);
+void start_kernel(void);
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ /*
+ * Option parsing
+ */
+ extern int optind;
+ extern char *optarg;
+ int ch;
+ int fd;
+ long textsz, stringsz;
+ struct exec ehdr;
+
+ Progname = argv[0];
+
+ kparam.boothowto = RB_SINGLE;
+
+ while ((ch = getopt(argc, argv, "abdhtv")) != EOF) {
+ switch(ch) {
+ case 'a':
+ kparam.boothowto &= ~(RB_SINGLE);
+ kparam.boothowto |= RB_AUTOBOOT;
+ break;
+ case 'b':
+ kparam.boothowto |= RB_ASKNAME;
+ break;
+ case 'd':
+ kparam.boothowto |= RB_KDB;
+ break;
+ case 't':
+ t_flag = 1;
+ break;
+ case 'v':
+ fprintf(stderr,"%s\n", version);
+ break;
+ case 'h':
+ help();
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if(argc == 1)
+ strcpy(kname, argv[0]);
+
+ /*
+ * Get system info to pass to NetBsd
+ */
+ get_sys_info();
+
+ /*
+ * Find the kernel to boot and read it's exec-header
+ */
+ if((fd = open(kname, O_RDONLY)) < 0)
+ error("Cannot open kernel '%s'", kname);
+ if(read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
+ error("Cannot read exec-header of '%s'", kname);
+ if((ehdr.a_magic & 0xffff) != NMAGIC) /* XXX */
+ error("Not an NMAGIC file '%s'", kname);
+
+ /*
+ * Extract various sizes from the kernel executable
+ */
+ textsz = (ehdr.a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1);
+ kparam.esym_loc = 0;
+ kparam.ksize = textsz + ehdr.a_data + ehdr.a_bss;
+ kparam.entry = ehdr.a_entry;
+
+ if(ehdr.a_syms) {
+ if(lseek(fd,ehdr.a_text+ehdr.a_data+ehdr.a_syms+sizeof(ehdr), 0) <= 0)
+ error("Cannot seek to string table in '%s'", kname);
+ if(read(fd, &stringsz, sizeof(long)) != sizeof(long))
+ error("Cannot read string-table size");
+ if(lseek(fd, sizeof(ehdr), 0) <= 0)
+ error("Cannot seek back to text start");
+ kparam.ksize += ehdr.a_syms + sizeof(long) + stringsz;
+ }
+
+ if((kparam.kp = (u_char *)malloc(kparam.ksize)) == NULL)
+ error("Cannot malloc kernel image space");
+
+ /*
+ * Read text & data, clear bss
+ */
+ if((read(fd, kparam.kp, ehdr.a_text) != ehdr.a_text)
+ || (read(fd, kparam.kp + textsz, ehdr.a_data) != ehdr.a_data))
+ error("Unable to read kernel image\n");
+ memset(kparam.kp + textsz + ehdr.a_data, 0, ehdr.a_bss);
+
+ /*
+ * Read symbol and string table
+ */
+ if(ehdr.a_syms) {
+ long *p;
+
+ p = (long *)(kparam.kp + textsz + ehdr.a_data + ehdr.a_bss);
+ *p++ = ehdr.a_syms;
+ if(read(fd, (char *)p, ehdr.a_syms) != ehdr.a_syms)
+ error("Cannot read symbol table\n");
+ p = (long *)((char *)p + ehdr.a_syms);
+ if(read(fd, (char *)p, stringsz) != stringsz)
+ error("Cannot read string table\n");
+ kparam.esym_loc = (long)((char *)p-(char *)kparam.kp +stringsz);
+ }
+
+ if(!t_flag)
+ start_kernel();
+ /* NOT REACHED */
+
+ fprintf(stderr, "Kernel '%s' was loaded OK\n", kname);
+ exit(0);
+}
+
+/*
+ * Extract memory and cpu/fpu info from system.
+ */
+void get_sys_info()
+{
+ long stck;
+ long *jar;
+
+ kparam.cputype = 0;
+
+ stck = Super(0);
+
+ kparam.ttmem_start = TTRAM_BASE;
+ kparam.ttmem_size = *ADDR_RAMTOP - TTRAM_BASE;
+ kparam.stmem_size = *ADDR_PHYSTOP;
+
+ /*
+ * Scan cookiejar for cpu/fpu types
+ */
+ jar = *ADDR_P_COOKIE;
+ if(jar != NULL) {
+ do {
+ if(jar[0] == 0x5f435055) { /* _CPU */
+ switch(jar[1]) {
+ case 0:
+ kparam.cputype |= ATARI_68000;
+ break;
+ case 10:
+ kparam.cputype |= ATARI_68010;
+ break;
+ case 20:
+ kparam.cputype |= ATARI_68020;
+ break;
+ case 30:
+ kparam.cputype |= ATARI_68030;
+ break;
+ case 40:
+ kparam.cputype |= ATARI_68040;
+ break;
+ default:
+ error("Unknown CPU-type");
+ }
+ }
+ if(jar[0] == 0x5f465055) { /* _FPU */
+ switch(jar[1]) {
+ case 0x10000:
+ case 0x20000:
+ kparam.cputype |= ATARI_68881;
+ break;
+ case 0x30000:
+ kparam.cputype |= ATARI_68882;
+ break;
+ case 0x40000:
+ kparam.cputype |= ATARI_FPU40;
+ break;
+ default:
+ error("Unknown FPU-type");
+ }
+ }
+ jar = &jar[2];
+ } while(jar[-2]);
+ }
+ if(!(kparam.cputype & ATARI_ANYCPU))
+ error("Cannot determine CPU-type");
+ if(!(kparam.cputype & ATARI_ANYFPU))
+ error("Cannot determine FPU-type");
+
+ Super(stck);
+}
+
+void error(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ fprintf(stderr, "%s: ", Progname);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ exit(1);
+ /*NOTREACHED*/
+}
+
+void help()
+{
+ fprintf(stderr, "
+NetBSD loader for the Atari-TT
+
+Usage: %s [-abdhtv] [kernel]
+
+Description of options:
+
+\t-a Boot up to multi-user mode.
+\t-b Ask for root device to use.
+\t-d Enter kernel debugger.
+\t-h What your getting right now.
+\t-t Test the loader. It will do everything except executing the
+\t loaded kernel.
+\t-v Print loader version.
+", Progname);
+ exit(1);
+}
+
+void usage()
+{
+ fprintf(stderr, "Usage: %s [-abdhtv] [kernel]", Progname);
+ exit(1);
+}
+
+void start_kernel()
+{
+ long stck;
+
+ stck = Super(0);
+ startit();
+ /* NOT REACHED */
+
+ Super(stck);
+}
+
+asm("
+ .text
+ .globl _startit
+
+_startit:
+ move.w #0x2700,sr
+
+ | the BSD kernel wants values into the following registers:
+ | d0: ttmem-size
+ | d1: stmem-size
+ | d2: cputype
+ | d3: boothowto
+ | d4: length of loaded kernel
+ | a0: start of loaded kernel
+ | a1: end of symbols (esym)
+ | All other registers zeroed for possible future requirements.
+
+ lea _kparam, a3 | a3 points to parameter block
+ lea _startit,sp | make sure we have a good stack ***
+ move.l (a3),a0 | loaded kernel
+ move.l 8(a3),-(sp) | push entry point ***
+ move.l a0,d0 | offset of loaded kernel
+ add.l d0,(sp) | add offset
+ move.l 12(a3),d1 | stmem-size
+ move.l 16(a3),d0 | ttmem-size
+ move.l 20(a3),d2 | cputype
+ move.l 24(a3),d3 | boothowto
+ move.l 4(a3),d4 | length of loaded kernel
+ move.l 28(a3),d5 | start of fastram
+ move.l 32(a3),a1 | end of symbols
+ sub.l a5,a5 | target, load to 0
+ btst #4, d2 | Is this an 68040?
+ beq not040
+
+ | Turn off 68040 MMU
+ .word 0x4e7b,0xd003 | movec a5,tc
+ .word 0x4e7b,0xd806 | movec a5,urp
+ .word 0x4e7b,0xd807 | movec a5,srp
+ .word 0x4e7b,0xd004 | movec a5,itt0
+ .word 0x4e7b,0xd005 | movec a5,itt1
+ .word 0x4e7b,0xd006 | movec a5,dtt0
+ .word 0x4e7b,0xd007 | movec a5,dtt1
+ bra nott
+
+not040:
+ lea zero,a3
+ pmove (a3),tcr | Turn off MMU
+ lea nullrp,a3
+ pmove (a3),crp | Turn off MMU some more
+ pmove (a3),srp | Really, really, turn off MMU
+
+ | Turn off 68030 TT registers
+ btst #3, d2 | Is this an 68030?
+ beq.b nott
+ lea zero,a3
+ pmove (a3),tt0
+ pmove (a3),tt1
+
+nott:
+ moveq.l #0,d6 | would have known contents)
+ moveq.l #0,d7
+ movea.l d6,a2
+ movea.l d6,a3
+ movea.l d6,a4
+ movea.l d6,a5
+ movea.l d6,a6
+ rts | enter kernel at address on stack ***
+
+
+| A do-nothing MMU root pointer (includes the following long as well)
+
+nullrp: .long 0x80000202
+zero: .long 0
+svsp: .long 0
+
+
+");
diff --git a/sys/arch/atari/stand/loadbsd/loader.h b/sys/arch/atari/stand/loadbsd/loader.h
new file mode 100644
index 00000000000..3b06189eda0
--- /dev/null
+++ b/sys/arch/atari/stand/loadbsd/loader.h
@@ -0,0 +1,75 @@
+/* $NetBSD: loader.h,v 1.1.1.1 1995/03/26 07:12:04 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 L. Weppelman
+ * 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 Leo Weppelman.
+ * 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.
+ */
+
+/*
+ * NetBSD loader for the Atari-TT.
+ *
+ * Assume compiling under TOS or MINT. The page-size will always
+ * be incorrect then (if it is defined anyway).
+ */
+#ifdef __LDPGSZ
+#undef __LDPGSZ
+#endif
+
+#define __LDPGSZ (8*1024) /* Page size for Netbsd */
+
+#define TTRAM_BASE 0x1000000 /* Fastram always starts here */
+
+/*
+ * System var's used in low-memory
+ */
+#define ADDR_RAMTOP ((long*)0x5a4) /* End of TT-ram (unofficial) */
+#define ADDR_PHYSTOP ((long*)0x42e) /* End of ST-ram */
+#define ADDR_P_COOKIE ((long**)0x5a0) /* Pointer to cookie jar */
+
+/*
+ * These should match with the values NetBsd uses!
+ */
+#define ATARI_68000 1 /* 68000 CPU */
+#define ATARI_68010 (1<<1) /* 68010 CPU */
+#define ATARI_68020 (1<<2) /* 68020 CPU */
+#define ATARI_68030 (1<<3) /* 68030 CPU */
+#define ATARI_68040 (1<<4) /* 68040 CPU */
+#define ATARI_68881 (1<<8) /* 68881 or 68882 FPU */
+#define ATARI_68882 (1<<9) /* 68882 FPU */
+#define ATARI_FPU40 (1<<10) /* 68040 FPU */
+
+#define ATARI_ANYCPU (0x1f)
+#define ATARI_ANYFPU (0x300)
+
+/*
+ * Definitions for boothowto
+ */
+#define RB_AUTOBOOT 0x00
+#define RB_ASKNAME 0x01
+#define RB_SINGLE 0x02
+#define RB_KDB 0x40
diff --git a/sys/arch/atari/stand/tostools/chg_pid/chg_pid.c b/sys/arch/atari/stand/tostools/chg_pid/chg_pid.c
new file mode 100644
index 00000000000..926519b8075
--- /dev/null
+++ b/sys/arch/atari/stand/tostools/chg_pid/chg_pid.c
@@ -0,0 +1,240 @@
+/* $NetBSD: chg_pid.c,v 1.1.1.1 1995/03/26 07:12:04 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 L. Weppelman
+ * 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 Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *
+ * This program changes the partition id field (p_id) in the GEM
+ * partition info. NetBSD uses these id-fields to determine the kind
+ * of partition. Sensible id's to set are:
+ * NBU : NetBSD User partition
+ * NBR : NetBSD Root partition
+ * NBS : NetBSD Swap partition
+ *
+ * When NetBSD auto boots, the first 'NBR' partition found when scanning the
+ * SCSI-disks becomes the active root partition. The same goes for 'NBS'.
+ * Drives are scanned in 'SCSI-id' order.
+ */
+#include <stdio.h>
+#include <osbind.h>
+
+/*
+ * Format of GEM root sector
+ */
+typedef struct gem_part {
+ u_char p_flg; /* bit 0 is in-use flag */
+ u_char p_id[3]; /* id: GEM, BGM, XGM, UNX, MIX */
+ u_long p_st; /* block where partition starts */
+ u_long p_size; /* partition size */
+} GEM_PART;
+
+#define NGEM_PARTS 4 /* Max. partition infos in root sector */
+
+typedef struct gem_root {
+ u_char fill[0x1c2]; /* Filler, can be boot code */
+ u_long hd_siz; /* size of entire volume */
+ GEM_PART parts[NGEM_PARTS]; /* see above */
+ u_long bsl_st; /* start of bad-sector list */
+ u_long bsl_cnt; /* nr. blocks in bad-sector list*/
+ u_short csum; /* checksum correction */
+} GEM_ROOT;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int driveno = 0;
+ int partno = 0;
+ char *newname;
+ int c;
+
+ if(argc != 4)
+ usage();
+ driveno = atoi(argv[1]);
+ partno = atoi(argv[2]);
+ newname = argv[3];
+
+ printf("Note: drives start numbering at 0!\n");
+ printf("About to change id of partition %d on drive %d to %s\n",
+ partno, driveno, newname);
+ printf("Are you sure (y/n)? ");
+ c = getchar();
+ switch(c) {
+ case 'y':
+ case 'Y':
+ if(chg_tosparts(partno, driveno, newname))
+ printf("Done\n");
+ else printf("Partion number not found\n");
+ break;
+ default :
+ printf("Aborted\n");
+ }
+}
+
+usage()
+{
+ printf("Usage: chg_pid <driveno> <partno> <newid>\n");
+ exit(1);
+}
+
+int chg_tosparts(chg_part, drive, newname)
+int chg_part, drive;
+char *newname;
+{
+ GEM_ROOT *g_root;
+ GEM_PART g_local[NGEM_PARTS];
+ char buf[512];
+ int pno = 1;
+ int i;
+
+ /*
+ * Read root sector
+ */
+ if(read_block(buf, 0, drive) == 0) {
+ fprintf(stderr, "Cannot read block 0\n");
+ exit(1);
+ }
+
+ /*
+ * Make local copy of partition info, we may need to re-use
+ * the buffer in case of 'XGM' partitions.
+ */
+ g_root = (GEM_ROOT*)buf;
+ bcopy(g_root->parts, g_local, NGEM_PARTS*sizeof(GEM_PART));
+
+
+ for(i = 0; i < NGEM_PARTS; i++) {
+ if(!(g_local[i].p_flg & 1))
+ continue;
+ if(!strncmp(g_local[i].p_id, "XGM", 3)) {
+ int j;
+ daddr_t new_root = g_local[i].p_st;
+
+ /*
+ * Loop through extended partition list
+ */
+ for(;;) {
+ if(read_block(buf, new_root, drive) == 0) {
+ fprintf(stderr, "Cannot read block %d\n", new_root);
+ exit(1);
+ }
+ for(j = 0; j < NGEM_PARTS; j++) {
+ if(!(g_root->parts[j].p_flg & 1))
+ continue;
+ if(!strncmp(g_root->parts[j].p_id, "XGM", 3)) {
+ new_root = g_local[i].p_st + g_root->parts[j].p_st;
+ break;
+ }
+ else {
+ if(pno == chg_part) {
+ change_it(pno,g_root->parts[j].p_id, newname);
+ if(write_block(buf, new_root, drive) == 0) {
+ fprintf(stderr, "Cannot write block %d\n",
+ new_root);
+ exit(1);
+ }
+ return(1);
+ }
+ pno++;
+ }
+ }
+ if(j == NGEM_PARTS)
+ break;
+ }
+ }
+ else {
+ if(pno == chg_part) {
+ /*
+ * Re-read block 0
+ */
+ if(read_block(buf, 0, drive) == 0) {
+ fprintf(stderr, "Cannot read block 0\n");
+ exit(1);
+ }
+ change_it(pno, g_root->parts[i].p_id, newname);
+ set_csum(buf);
+ if(write_block(buf, 0, drive) == 0) {
+ fprintf(stderr, "Cannot write block 0\n");
+ exit(1);
+ }
+ return(1);
+ }
+ pno++;
+ }
+ }
+ return(0);
+}
+
+change_it(pno, p_id, newname)
+int pno;
+char *p_id, *newname;
+{
+ char s1[4], s2[4];
+
+ strncpy(s1, p_id, 3);
+ strncpy(s2, newname, 3);
+ s1[3] = s2[3] = '\0';
+ printf("Changing partition %d: %s -> %s ...", pno, s1, s2);
+ p_id[0] = s2[0]; p_id[1] = s2[1]; p_id[2] = s2[2];
+}
+
+read_block(buf, blkno, drive)
+void *buf;
+int blkno;
+int drive;
+{
+ if(Dmaread(blkno, 1, buf, drive + 8) != 0)
+ return(0);
+ return(1);
+}
+
+write_block(buf, blkno, drive)
+void *buf;
+int blkno;
+int drive;
+{
+ if(Dmawrite(blkno, 1, buf, drive + 8) != 0)
+ return(0);
+ return(1);
+}
+
+set_csum(buf)
+char *buf;
+{
+ unsigned short *p = (unsigned short *)buf;
+ unsigned short csum = 0;
+ int i;
+
+ p[255] = 0;
+ for(i = 0; i < 256; i++)
+ csum += *p++;
+ *--p = (0x1234 - csum) & 0xffff;
+}
diff --git a/sys/arch/atari/stand/tostools/loadbsd/loadbsd.c b/sys/arch/atari/stand/tostools/loadbsd/loadbsd.c
new file mode 100644
index 00000000000..b4143e3740e
--- /dev/null
+++ b/sys/arch/atari/stand/tostools/loadbsd/loadbsd.c
@@ -0,0 +1,383 @@
+/* $NetBSD: loadbsd.c,v 1.1.1.1 1995/03/26 07:12:04 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 L. Weppelman
+ * 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 Leo Weppelman.
+ * 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.
+ */
+
+/*
+ * NetBSD loader for the Atari-TT.
+ */
+
+#include <stdio.h>
+#include <a_out.h>
+#include <fcntl.h>
+#include <osbind.h>
+#include <stdarg.h>
+#include "loader.h"
+
+char *Progname; /* How are we called */
+int t_flag = 0; /* Just test, do not execute */
+
+char version[] = "$VER: LoadBSD 1.0 (11/01/95)";
+
+/*
+ * Default name of kernel to boot, large enough to patch
+ */
+char kname[80] = "n:/netbsd";
+
+static struct {
+ u_char *kp; /* 00: Kernel load address */
+ long ksize; /* 04: Size of loaded kernel */
+ u_long entry; /* 08: Kernel entry point */
+ long stmem_size; /* 12: Size of st-ram */
+ long ttmem_size; /* 16: Size of tt-ram */
+ long cputype; /* 20: Type of cpu */
+ long boothowto; /* 24: How to boot */
+ long ttmem_start; /* 28: Start of tt-ram */
+ long esym_loc; /* 32: End of symbol table */
+} kparam;
+
+void get_sys_info(void);
+void error(char *fmt, ...);
+void help(void);
+void usage(void);
+void start_kernel(void);
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ /*
+ * Option parsing
+ */
+ extern int optind;
+ extern char *optarg;
+ int ch;
+ int fd;
+ long textsz, stringsz;
+ struct exec ehdr;
+
+ Progname = argv[0];
+
+ kparam.boothowto = RB_SINGLE;
+
+ while ((ch = getopt(argc, argv, "abdhtv")) != EOF) {
+ switch(ch) {
+ case 'a':
+ kparam.boothowto &= ~(RB_SINGLE);
+ kparam.boothowto |= RB_AUTOBOOT;
+ break;
+ case 'b':
+ kparam.boothowto |= RB_ASKNAME;
+ break;
+ case 'd':
+ kparam.boothowto |= RB_KDB;
+ break;
+ case 't':
+ t_flag = 1;
+ break;
+ case 'v':
+ fprintf(stderr,"%s\n", version);
+ break;
+ case 'h':
+ help();
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if(argc == 1)
+ strcpy(kname, argv[0]);
+
+ /*
+ * Get system info to pass to NetBsd
+ */
+ get_sys_info();
+
+ /*
+ * Find the kernel to boot and read it's exec-header
+ */
+ if((fd = open(kname, O_RDONLY)) < 0)
+ error("Cannot open kernel '%s'", kname);
+ if(read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
+ error("Cannot read exec-header of '%s'", kname);
+ if((ehdr.a_magic & 0xffff) != NMAGIC) /* XXX */
+ error("Not an NMAGIC file '%s'", kname);
+
+ /*
+ * Extract various sizes from the kernel executable
+ */
+ textsz = (ehdr.a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1);
+ kparam.esym_loc = 0;
+ kparam.ksize = textsz + ehdr.a_data + ehdr.a_bss;
+ kparam.entry = ehdr.a_entry;
+
+ if(ehdr.a_syms) {
+ if(lseek(fd,ehdr.a_text+ehdr.a_data+ehdr.a_syms+sizeof(ehdr), 0) <= 0)
+ error("Cannot seek to string table in '%s'", kname);
+ if(read(fd, &stringsz, sizeof(long)) != sizeof(long))
+ error("Cannot read string-table size");
+ if(lseek(fd, sizeof(ehdr), 0) <= 0)
+ error("Cannot seek back to text start");
+ kparam.ksize += ehdr.a_syms + sizeof(long) + stringsz;
+ }
+
+ if((kparam.kp = (u_char *)malloc(kparam.ksize)) == NULL)
+ error("Cannot malloc kernel image space");
+
+ /*
+ * Read text & data, clear bss
+ */
+ if((read(fd, kparam.kp, ehdr.a_text) != ehdr.a_text)
+ || (read(fd, kparam.kp + textsz, ehdr.a_data) != ehdr.a_data))
+ error("Unable to read kernel image\n");
+ memset(kparam.kp + textsz + ehdr.a_data, 0, ehdr.a_bss);
+
+ /*
+ * Read symbol and string table
+ */
+ if(ehdr.a_syms) {
+ long *p;
+
+ p = (long *)(kparam.kp + textsz + ehdr.a_data + ehdr.a_bss);
+ *p++ = ehdr.a_syms;
+ if(read(fd, (char *)p, ehdr.a_syms) != ehdr.a_syms)
+ error("Cannot read symbol table\n");
+ p = (long *)((char *)p + ehdr.a_syms);
+ if(read(fd, (char *)p, stringsz) != stringsz)
+ error("Cannot read string table\n");
+ kparam.esym_loc = (long)((char *)p-(char *)kparam.kp +stringsz);
+ }
+
+ if(!t_flag)
+ start_kernel();
+ /* NOT REACHED */
+
+ fprintf(stderr, "Kernel '%s' was loaded OK\n", kname);
+ exit(0);
+}
+
+/*
+ * Extract memory and cpu/fpu info from system.
+ */
+void get_sys_info()
+{
+ long stck;
+ long *jar;
+
+ kparam.cputype = 0;
+
+ stck = Super(0);
+
+ kparam.ttmem_start = TTRAM_BASE;
+ kparam.ttmem_size = *ADDR_RAMTOP - TTRAM_BASE;
+ kparam.stmem_size = *ADDR_PHYSTOP;
+
+ /*
+ * Scan cookiejar for cpu/fpu types
+ */
+ jar = *ADDR_P_COOKIE;
+ if(jar != NULL) {
+ do {
+ if(jar[0] == 0x5f435055) { /* _CPU */
+ switch(jar[1]) {
+ case 0:
+ kparam.cputype |= ATARI_68000;
+ break;
+ case 10:
+ kparam.cputype |= ATARI_68010;
+ break;
+ case 20:
+ kparam.cputype |= ATARI_68020;
+ break;
+ case 30:
+ kparam.cputype |= ATARI_68030;
+ break;
+ case 40:
+ kparam.cputype |= ATARI_68040;
+ break;
+ default:
+ error("Unknown CPU-type");
+ }
+ }
+ if(jar[0] == 0x5f465055) { /* _FPU */
+ switch(jar[1]) {
+ case 0x10000:
+ case 0x20000:
+ kparam.cputype |= ATARI_68881;
+ break;
+ case 0x30000:
+ kparam.cputype |= ATARI_68882;
+ break;
+ case 0x40000:
+ kparam.cputype |= ATARI_FPU40;
+ break;
+ default:
+ error("Unknown FPU-type");
+ }
+ }
+ jar = &jar[2];
+ } while(jar[-2]);
+ }
+ if(!(kparam.cputype & ATARI_ANYCPU))
+ error("Cannot determine CPU-type");
+ if(!(kparam.cputype & ATARI_ANYFPU))
+ error("Cannot determine FPU-type");
+
+ Super(stck);
+}
+
+void error(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ fprintf(stderr, "%s: ", Progname);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ exit(1);
+ /*NOTREACHED*/
+}
+
+void help()
+{
+ fprintf(stderr, "
+NetBSD loader for the Atari-TT
+
+Usage: %s [-abdhtv] [kernel]
+
+Description of options:
+
+\t-a Boot up to multi-user mode.
+\t-b Ask for root device to use.
+\t-d Enter kernel debugger.
+\t-h What your getting right now.
+\t-t Test the loader. It will do everything except executing the
+\t loaded kernel.
+\t-v Print loader version.
+", Progname);
+ exit(1);
+}
+
+void usage()
+{
+ fprintf(stderr, "Usage: %s [-abdhtv] [kernel]", Progname);
+ exit(1);
+}
+
+void start_kernel()
+{
+ long stck;
+
+ stck = Super(0);
+ startit();
+ /* NOT REACHED */
+
+ Super(stck);
+}
+
+asm("
+ .text
+ .globl _startit
+
+_startit:
+ move.w #0x2700,sr
+
+ | the BSD kernel wants values into the following registers:
+ | d0: ttmem-size
+ | d1: stmem-size
+ | d2: cputype
+ | d3: boothowto
+ | d4: length of loaded kernel
+ | a0: start of loaded kernel
+ | a1: end of symbols (esym)
+ | All other registers zeroed for possible future requirements.
+
+ lea _kparam, a3 | a3 points to parameter block
+ lea _startit,sp | make sure we have a good stack ***
+ move.l (a3),a0 | loaded kernel
+ move.l 8(a3),-(sp) | push entry point ***
+ move.l a0,d0 | offset of loaded kernel
+ add.l d0,(sp) | add offset
+ move.l 12(a3),d1 | stmem-size
+ move.l 16(a3),d0 | ttmem-size
+ move.l 20(a3),d2 | cputype
+ move.l 24(a3),d3 | boothowto
+ move.l 4(a3),d4 | length of loaded kernel
+ move.l 28(a3),d5 | start of fastram
+ move.l 32(a3),a1 | end of symbols
+ sub.l a5,a5 | target, load to 0
+ btst #4, d2 | Is this an 68040?
+ beq not040
+
+ | Turn off 68040 MMU
+ .word 0x4e7b,0xd003 | movec a5,tc
+ .word 0x4e7b,0xd806 | movec a5,urp
+ .word 0x4e7b,0xd807 | movec a5,srp
+ .word 0x4e7b,0xd004 | movec a5,itt0
+ .word 0x4e7b,0xd005 | movec a5,itt1
+ .word 0x4e7b,0xd006 | movec a5,dtt0
+ .word 0x4e7b,0xd007 | movec a5,dtt1
+ bra nott
+
+not040:
+ lea zero,a3
+ pmove (a3),tcr | Turn off MMU
+ lea nullrp,a3
+ pmove (a3),crp | Turn off MMU some more
+ pmove (a3),srp | Really, really, turn off MMU
+
+ | Turn off 68030 TT registers
+ btst #3, d2 | Is this an 68030?
+ beq.b nott
+ lea zero,a3
+ pmove (a3),tt0
+ pmove (a3),tt1
+
+nott:
+ moveq.l #0,d6 | would have known contents)
+ moveq.l #0,d7
+ movea.l d6,a2
+ movea.l d6,a3
+ movea.l d6,a4
+ movea.l d6,a5
+ movea.l d6,a6
+ rts | enter kernel at address on stack ***
+
+
+| A do-nothing MMU root pointer (includes the following long as well)
+
+nullrp: .long 0x80000202
+zero: .long 0
+svsp: .long 0
+
+
+");
diff --git a/sys/arch/atari/stand/tostools/loadbsd/loader.h b/sys/arch/atari/stand/tostools/loadbsd/loader.h
new file mode 100644
index 00000000000..3b06189eda0
--- /dev/null
+++ b/sys/arch/atari/stand/tostools/loadbsd/loader.h
@@ -0,0 +1,75 @@
+/* $NetBSD: loader.h,v 1.1.1.1 1995/03/26 07:12:04 leo Exp $ */
+
+/*
+ * Copyright (c) 1995 L. Weppelman
+ * 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 Leo Weppelman.
+ * 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.
+ */
+
+/*
+ * NetBSD loader for the Atari-TT.
+ *
+ * Assume compiling under TOS or MINT. The page-size will always
+ * be incorrect then (if it is defined anyway).
+ */
+#ifdef __LDPGSZ
+#undef __LDPGSZ
+#endif
+
+#define __LDPGSZ (8*1024) /* Page size for Netbsd */
+
+#define TTRAM_BASE 0x1000000 /* Fastram always starts here */
+
+/*
+ * System var's used in low-memory
+ */
+#define ADDR_RAMTOP ((long*)0x5a4) /* End of TT-ram (unofficial) */
+#define ADDR_PHYSTOP ((long*)0x42e) /* End of ST-ram */
+#define ADDR_P_COOKIE ((long**)0x5a0) /* Pointer to cookie jar */
+
+/*
+ * These should match with the values NetBsd uses!
+ */
+#define ATARI_68000 1 /* 68000 CPU */
+#define ATARI_68010 (1<<1) /* 68010 CPU */
+#define ATARI_68020 (1<<2) /* 68020 CPU */
+#define ATARI_68030 (1<<3) /* 68030 CPU */
+#define ATARI_68040 (1<<4) /* 68040 CPU */
+#define ATARI_68881 (1<<8) /* 68881 or 68882 FPU */
+#define ATARI_68882 (1<<9) /* 68882 FPU */
+#define ATARI_FPU40 (1<<10) /* 68040 FPU */
+
+#define ATARI_ANYCPU (0x1f)
+#define ATARI_ANYFPU (0x300)
+
+/*
+ * Definitions for boothowto
+ */
+#define RB_AUTOBOOT 0x00
+#define RB_ASKNAME 0x01
+#define RB_SINGLE 0x02
+#define RB_KDB 0x40