diff options
| author | leo <leo@NetBSD.org> | 1995-03-26 07:12:03 +0000 |
|---|---|---|
| committer | leo <leo@NetBSD.org> | 1995-03-26 07:12:03 +0000 |
| commit | 8b0113cfceadf3ee3bc427c4680b6b46bb57ceea (patch) | |
| tree | 2a5b7db0400149a733175c4b1a56774b2d4c1eb7 | |
| parent | 282052c7a8346370f47965457329f3b0b3fa01b7 (diff) | |
NetBSD/Atari, port by Leo Weppelman.
111 files changed, 29300 insertions, 0 deletions
diff --git a/share/man/man8/man8.atari/binpatch.8 b/share/man/man8/man8.atari/binpatch.8 new file mode 100644 index 00000000000..4d0017b3eb4 --- /dev/null +++ b/share/man/man8/man8.atari/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/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 |
