diff options
| author | nisimura <nisimura@NetBSD.org> | 2000-01-05 08:48:53 +0000 |
|---|---|---|
| committer | nisimura <nisimura@NetBSD.org> | 2000-01-05 08:48:53 +0000 |
| commit | 95d00ea75d53c2f18b36eaa2bb7f5bf4ce38b733 (patch) | |
| tree | 5ffef25ee0d0d225561ab8b8b61c40a1507d65de /sys | |
| parent | e7552e93d728e62c90c4b413dd4e86eb0293b4fa (diff) | |
Introduce NetBSD/luna68k port into CVS repository.
Diffstat (limited to 'sys')
73 files changed, 15139 insertions, 0 deletions
diff --git a/sys/arch/luna68k/Makefile b/sys/arch/luna68k/Makefile new file mode 100644 index 00000000000..ee8175b68e2 --- /dev/null +++ b/sys/arch/luna68k/Makefile @@ -0,0 +1,31 @@ +# $NetBSD: Makefile,v 1.1 2000/01/05 08:48:53 nisimura Exp $ + +# Makefile for luna68k tags file + +# Find where mips source files are for inclusion in tags +.include <../m68k/Makefile.inc> + +TLUNA68K= ../luna68k/tags +SLUNA68K= ../luna68k/luna68k/*.[ch] ../luna68k/include/*.h \ + ../luna68k/dev/*.[ch] +ALUNA68K= ../luna68k/luna68k/*.s + +# Directories in which to place tags links +DLUNA68K= dev include + +.include "../../kern/Make.tags.inc" + +tags: + -ctags -wdtf ${TLUNA68K} ${SLUNA68K} ${COMM} + egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${ALUNA68K} | \ + sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \ + >> ${TLUNA68K} + sort -o ${TLUNA68K} ${TLUNA68K} + +links: + -for i in ${DLUNA68K}; do \ + cd $$i && rm -f tags; ln -s ../tags tags; done + +SUBDIR= include + +.include <bsd.subdir.mk> diff --git a/sys/arch/luna68k/conf/GENERIC b/sys/arch/luna68k/conf/GENERIC new file mode 100644 index 00000000000..e82c84ebc39 --- /dev/null +++ b/sys/arch/luna68k/conf/GENERIC @@ -0,0 +1,150 @@ +# $NetBSD: GENERIC,v 1.1 2000/01/05 08:48:54 nisimura Exp $ +# +# GENERIC LUNA68K +# +include "arch/luna68k/conf/std.luna68k" + +maxusers 8 + +options M68030 +#options M68040 +#options FPSP # on m68040 to emulate some missing FP instructions + +# Needs to be set per system. i.e change these as you see fit + +# Standard system options +options NTP # NTP phase/frequency locked loop +options KTRACE +#options SYSVMSG # System V message queues +#options SYSVSEM # System V semaphores +#options SYSVSHM # System V shared memory +#optoins SHMMAXPGS=1024 # 1024 pages is the default +#options LKM # loadable kernel modules +#options NKMEMCLUSTERS=1024 # 4K pages in kernel malloc pool +#options UCONSOLE # users can redirect console (unsafe) + +# Debugging options +options DDB +#options DDB_HISTORY_SIZE=100 # enable history editing in DDB +#options SYMTAB_SPACE=72000 # place DDB symbols in data segment +options DEBUG # extra kernel debugging support +options DIAGNOSTIC # extra kernel sanity checking +options SCSIVERBOSE # Verbose SCSI errors +options SCSIDEBUG +#makeoptions DEBUG="-g" # compile full symbol table + +# Compatability options +options COMPAT_43 # and 4.3BSD and ... +options COMPAT_12 # NetBSD 1.2 binary compatibility +options COMPAT_13 # NetBSD 1.3 binary compatibility +options COMPAT_14 # NetBSD 1.4 binary compatibility + +# Filesystem options +file-system FFS # ufs file system +#file-system LFS # log-structured file system +file-system NFS # nfs client support +file-system MFS +#file-system CD9660 # ISO 9660 + Rock Ridge file system +#file-system MSDOSFS # MS-DOS FAT file system +file-system KERNFS # /kern +file-system PROCFS # /proc +#file-system FDESC # /dev/fd/* +file-system NULLFS # loopback file system +#file-system PORTAL # portal filesystem (still experimental) +#file-system UMAPFS # NULLFS + uid and gid remapping +#file-system UNION # union file system +#file-system CODA # Coda File System; also needs vcode (below) + +#options NFSSERVER # nfs server support +#options QUOTA # ffs quotas +#options FFS_EI # ffs endian independant support +#options SOFTDEP # ffs soft updates support + +# Pull in config fragments for kernel crypto. This is required for +# options IPSEC etc. to work. If you want to run with IPSEC, uncomment +# one of these, based on whether you use crypto-us or crypto-intl, and +# adjust the prefixes as necessary. + +#prefix ../crypto-us/sys +#cinclude "conf/files.crypto-us" +#prefix + +#prefix ../crypto-intl/sys +#cinclude "conf/files.crypto-intl" +#prefix + +# Networking options +options INET # IP prototol stack support +#options INET6 # IPV6 +#options IPSEC # IP security +#options IPSEC_ESP # IP securyty (encryption part; define w/IPSEC) +#options IPSEC_DEBUG # debug for IP security +#options GATEWAY # IP packet forwarding +#options MROUTING # IP multicast routing +#options TCP_COMPAT_42 # TCP bug compatibility with 4.2BSD +#options NS # XNS +#options NSIP # XNS tunneling over IP +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options CCITT,LLC,HDLC # X.25 +#options NETATALK # AppleTalk networking protocols +#options PPP_BSDCOMP # BSD-Compress compression support for PPP +#options PPP_DEFLATE # Deflate compression support for PPP +#options PPP_FILTER # Active filter support for PPP (requires bpf) +#options PFIL_HOOKS # pfil(9) packet filter hooks +#options IPFILTER_LOG # ipmon(8) log support +options NFS_BOOT_DHCP # superset of BOOTP + +# WS console uses SUN or VT100 terminal emulation +options WSEMUL_VT100 + +config netbsd root on ? type nfs + +mainbus0 at root + +clock0 at mainbus0 + +# uPD7201 SIO +sio0 at mainbus0 +siotty0 at sio0 # ttya +ws0 at sio0 # port for keyboard and mouse +# AM7990 LANCE +le0 at mainbus0 +# MB89532 SPC +spc0 at mainbus0 +#spc1 at mainbus0 # 2nd SCSI on LUNA-II +# framebuffer +fb0 at mainbus0 # 16 or 256 pseudo color + +# Workstation Console attachments +wsdisplay* at fb? +wskbd* at ws? console ? +#wsmouse* at ws? # not supported, yet... + +# SCSI bus support +scsibus* at spc? + +# SCSI devices +sd* at scsibus? target ? lun ? # SCSI disks +st* at scsibus? target ? lun ? # SCSI tapes +#cd* at scsibus? target ? lun ? # SCSI CD-ROMs +#ch* at scsibus? target ? lun ? # SCSI changer devices +#ss* at scsibus? target ? lun ? # SCSI scanners +#uk* at scsibus? target ? lun ? # unknown SCSI devices + +pseudo-device bpfilter 2 # Berkeley Packet Filter +#pseudo-device ccd 2 # concatenated and striped disks +#pseudo-device gre 2 # generic L3 over IP tunnel +#pseudo-device ipfilter 1 # ip filter +pseudo-device loop 1 # loopback interface; required +pseudo-device md 1 # memory disk device +#pseudo-device ppp 1 # PPP interfaces +pseudo-device pty 32 # pseudo-terminals +#pseudo-device raid 2 # RAIDframe disk driver +#pseudo-device sl 1 # SLIP interfaces +#pseudo-device tun 2 # Network "tunnel" device +#pseudo-device vnd 2 # disk-like interface to files + +# rnd is EXPERIMENTAL +#pseudo-device rnd # /dev/random and in-kernel generator +#options RND_COM # use "com" randomness too diff --git a/sys/arch/luna68k/conf/Makefile.luna68k b/sys/arch/luna68k/conf/Makefile.luna68k new file mode 100644 index 00000000000..aa46085a2ce --- /dev/null +++ b/sys/arch/luna68k/conf/Makefile.luna68k @@ -0,0 +1,199 @@ +# $NetBSD: Makefile.luna68k,v 1.1 2000/01/05 08:48:54 nisimura Exp $ + +# Makefile for NetBSD +# +# This makefile is constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/arch/luna68k/conf/``machineid'' +# after which you should do +# config machineid +# Machine generic makefile changes should be made in +# /sys/arch/luna68k/conf/Makefile.luna68k +# after which config should be rerun for all machines of that type. +# +# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE +# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING +# +# -DTRACE compile in kernel tracing hooks +# -DQUOTA compile in file system quotas + +# DEBUG is set to -g if debugging. +# PROF is set to -pg if profiling. + +AR?= ar +AS?= as +CC?= cc +CPP?= cpp +LD?= ld +LORDER?=lorder +MKDEP?= mkdep +NM?= nm +RANLIB?=ranlib +SIZE?= size +STRIP?= strip +TSORT?= tsort -q +OBJCOPY?= objcopy + +COPTS?= -O2 + +# source tree is located via $S relative to the compilation directory +.ifndef S +S!= cd ../../../..; pwd +.endif +LUNA68K=$S/arch/luna68k + +# Override CPP defaults entirely, so cross-compilation works. +# Keep -nostdinc before all -I flags, similar for -undef ... +HAVE_GCC28!= ${CC} --version | egrep "^(2\.8|egcs)" ; echo +INCLUDES= -nostdinc -I. -I$S/arch -I$S +CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dluna68k +CWARNFLAGS?= -Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes +.if (${HAVE_GCC28} != "") +CWARNFLAGS+= -Wno-main +.endif +CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} -msoft-float +AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE +LINKFLAGS= -N -Ttext 0xc000 -e start +STRIPFLAGS= -d + +%INCLUDES + +HOSTED_CC= ${CC} +HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//} +HOSTED_CFLAGS= ${CFLAGS} + +### find out what to use for libkern +.include "$S/lib/libkern/Makefile.inc" +.ifndef PROF +LIBKERN= ${KERNLIB} +.else +LIBKERN= ${KERNLIB_PROF} +.endif + +### find out what to use for libcompat +.include "$S/compat/common/Makefile.inc" +.ifndef PROF +LIBCOMPAT= ${COMPATLIB} +.else +LIBCOMPAT= ${COMPATLIB_PROF} +.endif + +### for the Motorola 68040 Floating Point Software Product +# .include "$S/arch/m68k/fpsp/Makefile.inc" + +# compile rules: rules are named ${TYPE}_${SUFFIX} where TYPE is NORMAL or +# HOSTED}, and SUFFIX is the file suffix, capitalized (e.g. C for a .c file). + +NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< +NOPROF_C= ${CC} ${CFLAGS} ${CPPFLAGS} -c $< +NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< + +HOSTED_C= ${HOSTED_CC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $< + +%OBJS + +%CFILES + +%SFILES + +# load lines for config "xxx" will be emitted as: +# xxx: ${SYSTEM_DEP} swapxxx.o +# ${SYSTEM_LD_HEAD} +# ${SYSTEM_LD} swapxxx.o +# ${SYSTEM_LD_TAIL} +SYSTEM_OBJ= locore.o ${FPSP} \ + param.o ioconf.o ${OBJS} ${LIBCOMPAT} ${LIBKERN} +SYSTEM_DEP= Makefile ${SYSTEM_OBJ} +SYSTEM_LD_HEAD= @rm -f $@ +SYSTEM_LD= @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_OBJ}' vers.o; \ + ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_OBJ} vers.o +SYSTEM_LD_TAIL= @${SIZE} $@; chmod 755 $@ + +DEBUG?= +.if ${DEBUG} == "-g" +LINKFLAGS+= -X +SYSTEM_LD_TAIL+=; \ + echo mv -f $@ $@.gdb; mv -f $@ $@.gdb; \ + echo ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb; \ + ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb +.else +LINKFLAGS+= -S +.endif + +%LOAD + +assym.h: $S/kern/genassym.sh ${LUNA68K}/luna68k/genassym.cf + sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} \ + < ${LUNA68K}/luna68k/genassym.cf > assym.h.tmp && \ + mv -f assym.h.tmp assym.h + +param.c: $S/conf/param.c + rm -f param.c + cp $S/conf/param.c . + +param.o: param.c Makefile + ${NORMAL_C} + +ioconf.o: ioconf.c + ${NORMAL_C} + +newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} + sh $S/conf/newvers.sh + ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c + +__CLEANKERNEL: .USE + @echo "${.TARGET}ing the kernel objects" + rm -f eddep *netbsd netbsd.gdb tags *.[io] [a-z]*.s \ + [Ee]rrs linterrs makelinks assym.h.tmp assym.h + +__CLEANDEPEND: .USE + rm -f .depend + +clean: __CLEANKERNEL + +cleandir distclean: __CLEANKERNEL __CLEANDEPEND + +lint: + @lint -hbxncez -Dvolatile= ${CPPFLAGS} -UKGDB \ + ${CFILES} ioconf.c param.c | \ + grep -v 'static function .* unused' + +tags: + @echo "see $S/kern/Makefile for tags" + +links: + egrep '#if' ${CFILES} | sed -f $S/conf/defines | \ + sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink + echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ + sort -u | comm -23 - dontlink | \ + sed 's,../.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks + sh makelinks && rm -f dontlink + +SRCS= ${LUNA68K}/luna68k/locore.s \ + param.c ioconf.c ${CFILES} ${SFILES} +depend: .depend +.depend: ${SRCS} assym.h param.c + ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${LUNA68K}/luna68k/locore.s + ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} + sh $S/kern/genassym.sh ${MKDEP} -f assym.dep ${CFLAGS} \ + ${CPPFLAGS} < ${LUNA68K}/luna68k/genassym.cf + @sed -e 's/.*\.o:.*\.c/assym.h:/' < assym.dep >> .depend + @rm -f assym.dep + +# depend on root or device configuration +autoconf.o conf.o: Makefile + +# depend on network or filesystem configuration +uipc_proto.o vfs_conf.o: Makefile + +# depend on maxusers +machdep.o: Makefile + +# depend on CPU configuration +machdep.c trap.o: Makefile + +locore.o: ${LUNA68K}/luna68k/locore.s assym.h + ${NORMAL_S} + +%RULES diff --git a/sys/arch/luna68k/conf/files.luna68k b/sys/arch/luna68k/conf/files.luna68k new file mode 100644 index 00000000000..4356510b659 --- /dev/null +++ b/sys/arch/luna68k/conf/files.luna68k @@ -0,0 +1,67 @@ +# +# $NetBSD: files.luna68k,v 1.1 2000/01/05 08:48:54 nisimura Exp $ +# +maxpartitions 8 +maxusers 2 8 64 + +file arch/luna68k/luna68k/autoconf.c +file arch/luna68k/luna68k/clock.c +file arch/luna68k/luna68k/conf.c +file arch/luna68k/luna68k/db_memrw.c ddb | kgdb +file arch/luna68k/luna68k/disksubr.c +file arch/luna68k/luna68k/isr.c +file arch/luna68k/luna68k/machdep.c +file arch/luna68k/luna68k/mem.c +file arch/luna68k/luna68k/pmap.c +file arch/luna68k/luna68k/pmap_bootstrap.c +file arch/luna68k/luna68k/sys_machdep.c +file arch/luna68k/luna68k/trap.c +file arch/luna68k/luna68k/vm_machdep.c +file arch/m68k/m68k/cacheops.c +file dev/clock_subr.c +file dev/cons.c +file arch/luna68k/dev/lcd.c + +device mainbus {} +attach mainbus at root +file arch/luna68k/luna68k/mainbus.c + +device clock +attach clock at mainbus +file arch/luna68k/dev/timekeeper.c clock + +attach le at mainbus: le24 +file arch/luna68k/dev/if_le.c le + +device sio { [channel = -1] } +attach sio at mainbus +file arch/luna68k/dev/sio.c sio + +device siotty: tty +attach siotty at sio +file arch/luna68k/dev/siotty.c siotty needs-flag +device ws: wskbddev,wsmousedev +attach ws at sio +file arch/luna68k/dev/lunaws.c ws + +device fb: wsemuldisplaydev +attach fb at mainbus +file arch/luna68k/dev/lunafb.c fb +file arch/luna68k/dev/omrasops.c fb + +device spc: scsi +attach spc at mainbus +file arch/luna68k/dev/spc.c spc +file dev/ic/mb89352.c spc + +# Machine-idependent SCSI driver. +include "dev/scsipi/files.scsipi" +major {sd = 2} # SCSI disk +major {cd = 4} # SCSI CD-ROM + +# Memory Disk for boot tape +file arch/luna68k/dev/md_root.c memory_disk_hooks +major {md = 7} # Memory disk (for mini-kernel) + +# "Workstation Console" glue. +include "dev/wscons/files.wscons" diff --git a/sys/arch/luna68k/conf/std.luna68k b/sys/arch/luna68k/conf/std.luna68k new file mode 100644 index 00000000000..1763e2ae954 --- /dev/null +++ b/sys/arch/luna68k/conf/std.luna68k @@ -0,0 +1,10 @@ +# $NetBSD: std.luna68k,v 1.1 2000/01/05 08:48:54 nisimura Exp $ + +machine luna68k m68k + +prefix ../gnu/sys +cinclude "conf/files.softdep" +prefix + +options EXEC_AOUT # exec a.out binaries +options EXEC_SCRIPT # exec #! scripts diff --git a/sys/arch/luna68k/dev/if_le.c b/sys/arch/luna68k/dev/if_le.c new file mode 100644 index 00000000000..67b615805ed --- /dev/null +++ b/sys/arch/luna68k/dev/if_le.c @@ -0,0 +1,236 @@ +/* $NetBSD: if_le.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ + +/*- + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: if_le.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $"); + +#include "opt_inet.h" +#include "bpfilter.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/device.h> + +#include <net/if.h> +#include <net/if_ether.h> +#include <net/if_media.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/if_inarp.h> +#endif + +#include <machine/cpu.h> +#include <machine/autoconf.h> + +#include <luna68k/luna68k/isr.h> + +#include <dev/ic/lancereg.h> +#include <dev/ic/lancevar.h> +#include <dev/ic/am7990reg.h> +#include <dev/ic/am7990var.h> + +/* + * LANCE registers. + */ +struct lereg1 { + volatile u_int16_t ler1_rdp; /* data port */ + volatile u_int16_t ler1_rap; /* register select port */ +}; + +/* + * Ethernet software status per interface. + * + * Each interface is referenced by a network interface structure, + * arpcom.ac_if, which the routing code uses to locate the interface. + * This structure contains the output queue for the interface, its address, ... + */ +struct le_softc { + struct am7990_softc sc_am7990; /* glue to MI code */ + + struct lereg1 *sc_r1; /* LANCE registers */ +}; + +static int le_match __P((struct device *, struct cfdata *, void *)); +static void le_attach __P((struct device *, struct device *, void *)); + +const struct cfattach le_ca = { + sizeof(struct le_softc), le_match, le_attach +}; +extern struct cfdriver le_cd; + +static void lesrcsr __P((struct lance_softc *, u_int16_t, u_int16_t)); +static u_int16_t lerdcsr __P((struct lance_softc *, u_int16_t)); +static void myetheraddr __P((u_int8_t *)); + +static void +lesrcsr(sc, port, val) + struct lance_softc *sc; + u_int16_t port, val; +{ + struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; + + ler1->ler1_rap = port; + ler1->ler1_rdp = val; +} + +static u_int16_t +lerdcsr(sc, port) + struct lance_softc *sc; + u_int16_t port; +{ + struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1; + u_int16_t val; + + ler1->ler1_rap = port; + val = ler1->ler1_rdp; + return (val); +} + +static int +le_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct mainbus_attach_args *ma = aux; + + if (strcmp(ma->ma_name, le_cd.cd_name)) + return (0); + + return (1); +} + +void +le_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct le_softc *lesc = (void *)self; + struct lance_softc *sc = &lesc->sc_am7990.lsc; + struct mainbus_attach_args *ma = aux; + + /* Map control registers. */ + lesc->sc_r1 = (struct lereg1 *)ma->ma_addr; /* LANCE */ + + sc->sc_mem = (void *)0x71010000; /* SRAM */ + sc->sc_conf3 = LE_C3_BSWP; + sc->sc_addr = (u_long)sc->sc_mem & 0xffffff; + sc->sc_memsize = 64 * 1024; /* 64KB */ + + myetheraddr(sc->sc_enaddr); + + sc->sc_copytodesc = lance_copytobuf_contig; + sc->sc_copyfromdesc = lance_copyfrombuf_contig; + sc->sc_copytobuf = lance_copytobuf_contig; + sc->sc_copyfrombuf = lance_copyfrombuf_contig; + sc->sc_zerobuf = lance_zerobuf_contig; + + sc->sc_rdcsr = lerdcsr; + sc->sc_wrcsr = lesrcsr; + sc->sc_hwinit = NULL; + + am7990_config(&lesc->sc_am7990); + + isrlink_autovec(am7990_intr, (void *)sc, ma->ma_ilvl, ISRPRI_NET); +} + +/* + * LUNA-I has 1Mbit CPU ROM, which contains MAC address directly + * readable at 0x4100FFE0 as a sequence of 12 ASCII characters. + * + * LUNA-II has 16Kbit NVSRAM on its ethercard, whose contents are + * accessible 4bit-wise by ctl register operation. The register is + * mapped at 0xF1000004. + */ +void +myetheraddr(ether) + u_int8_t *ether; +{ + unsigned i, loc; + u_int8_t *ea; + volatile struct { u_int32_t ctl; } *ds1220; + + switch (machtype) { + case LUNA_I: + ea = (u_int8_t *)0x4101FFE0; + for (i = 0; i < 6; i++) { + int u, l; + + u = ea[0]; + u = (u < 'A') ? u & 0xf : u - 'A' + 10; + l = ea[1]; + l = (l < 'A') ? l & 0xf : l - 'A' + 10; + + ether[i] = l | (u << 4); + ea += 2; + } + break; + case LUNA_II: + ds1220 = (void *)0xF1000004; + loc = 12; + for (i = 0; i < 6; i++) { + unsigned u, l, hex; + + ds1220->ctl = (loc) << 16; + u = 0xf0 & (ds1220->ctl >> 12); + ds1220->ctl = (loc + 1) << 16; + l = 0x0f & (ds1220->ctl >> 16); + hex = (u < '9') ? l : l + 9; + + ds1220->ctl = (loc + 2) << 16; + u = 0xf0 & (ds1220->ctl >> 12); + ds1220->ctl = (loc + 3) << 16; + l = 0x0f & (ds1220->ctl >> 16); + + ether[i] = ((u < '9') ? l : l + 9) | (hex << 4); + loc += 4; + } + break; + default: + ether[0] = 0x00; ether[1] = 0x00; ether[2] = 0x0a; + ether[3] = 0xDE; ether[4] = 0xAD; ether[5] = 0x00; + break; + } +} diff --git a/sys/arch/luna68k/dev/lcd.c b/sys/arch/luna68k/dev/lcd.c new file mode 100644 index 00000000000..d69a1b610d2 --- /dev/null +++ b/sys/arch/luna68k/dev/lcd.c @@ -0,0 +1,170 @@ +/* $NetBSD: lcd.c,v 1.1 2000/01/05 08:48:55 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: lcd.c,v 1.1 2000/01/05 08:48:55 nisimura Exp $"); + +/* + * XXX + * Following code segments are subject to change. + * XXX + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#define PIO1_MODE_OUTPUT 0x84 +#define PIO1_MODE_INPUT 0x94 + +#define POWER 0x10 + +#define ENABLE 0x80 +#define DISABLE 0x00 + +#define WRITE_CMD (0x00 | 0x00) +#define WRITE_DATA (0x00 | 0x40) +#define READ_BUSY (0x20 | 0x00) +#define READ_DATA (0x20 | 0x40) + +#define LCD_INIT 0x38 +#define LCD_ENTRY 0x06 +#define LCD_ON 0x0c +#define LCD_CLS 0x01 +#define LCD_HOME 0x02 +#define LCD_LOCATE(X, Y) (((Y) & 1 ? 0xc0 : 0x80) | ((X) & 0x0f)) + +struct pio { + u_int8_t portA; + u_int8_t portB; + u_int8_t portC; + u_int8_t cntrl; +}; + +void lcdbusywait __P((void)); +void lcdput __P((int)); +void lcdctrl __P((int)); +void lcdshow __P((char *)); +void greeting __P((void)); + /* "1234567890123456" */ +static char lcd_boot_message1[] = " NetBSD/luna68k "; +static char lcd_boot_message2[] = " SX-9100/DT "; + +void +lcdbusywait() +{ + struct pio *p1 = (struct pio *)0x4D000000; + int msb, s; + + s = splhigh(); + p1->cntrl = PIO1_MODE_INPUT; + p1->portC = POWER | READ_BUSY | ENABLE; + splx(s); + + do { + msb = p1->portA & ENABLE; + delay(5); + } while (msb != 0); + + s = splhigh(); + p1->portC = POWER | READ_BUSY | DISABLE; + splx(s); +} + +void +lcdput(cc) + int cc; +{ + struct pio *p1 = (struct pio *)0x4D000000; + int s; + + lcdbusywait(); + + s = splhigh(); + p1->cntrl = PIO1_MODE_OUTPUT; + + p1->portC = POWER | WRITE_DATA | ENABLE; + p1->portA = cc; + p1->portC = POWER | WRITE_DATA | DISABLE; + splx(s); +} + +void +lcdctrl(cc) + int cc; +{ + struct pio *p1 = (struct pio *)0x4D000000; + int s; + + lcdbusywait(); + + s = splhigh(); + p1->cntrl = PIO1_MODE_OUTPUT; + + p1->portC = POWER | WRITE_CMD | ENABLE; + p1->portA = cc; + p1->portC = POWER | WRITE_CMD | DISABLE; + splx(s); +} + +void +lcdshow(s) + char *s; +{ + int cc; + + while ((cc = *s++) != '\0') + lcdput(cc); +} + +void +greeting() +{ + lcdctrl(LCD_INIT); + lcdctrl(LCD_ENTRY); + lcdctrl(LCD_ON); + + lcdctrl(LCD_CLS); + lcdctrl(LCD_HOME); + + lcdctrl(LCD_LOCATE(0, 0)); + lcdshow(lcd_boot_message1); + lcdctrl(LCD_LOCATE(0, 1)); + lcdshow(lcd_boot_message2); +} diff --git a/sys/arch/luna68k/dev/lunafb.c b/sys/arch/luna68k/dev/lunafb.c new file mode 100644 index 00000000000..8e361e9b344 --- /dev/null +++ b/sys/arch/luna68k/dev/lunafb.c @@ -0,0 +1,495 @@ +/* $NetBSD: lunafb.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: lunafb.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/ioctl.h> +#include <sys/malloc.h> +#include <sys/mman.h> +#include <sys/proc.h> +#include <sys/tty.h> +#include <sys/errno.h> +#include <sys/buf.h> +#include <vm/vm.h> +#include <uvm/uvm_extern.h> + +#include <dev/rcons/raster.h> +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wscons_raster.h> +#include <dev/wscons/wsdisplayvar.h> + +#include <machine/cpu.h> +#include <machine/autoconf.h> + +struct bt454 { + u_int8_t bt_addr; /* map address register */ + u_int8_t bt_cmap; /* colormap data register */ +}; + +struct bt458 { + u_int8_t bt_addr; /* map address register */ + unsigned :24; + u_int8_t bt_cmap; /* colormap data register */ + unsigned :24; + u_int8_t bt_ctrl; /* control register */ + unsigned :24; + u_int8_t bt_omap; /* overlay (cursor) map register */ + unsigned :24; +}; + +#define OMFB_RFCNT 0xB1000000 /* video h-origin/v-origin */ +#define OMFB_PLANEMASK 0xB1040000 /* planemask register */ +#define OMFB_FB_WADDR 0xB1080008 /* common plane */ +#define OMFB_FB_RADDR 0xB10C0008 /* plane #0 */ +#define OMFB_ROPFUNC 0xB12C0000 /* ROP function code */ +#define OMFB_RAMDAC 0xC1100000 /* Bt454/Bt458 RAMDAC */ +#define OMFB_SIZE (0xB1300000 - 0xB1080000 + NBPG) + +struct om_hwdevconfig { + int dc_wid; /* width of frame buffer */ + int dc_ht; /* height of frame buffer */ + int dc_depth; /* depth, bits per pixel */ + int dc_rowbytes; /* bytes in a FB scan line */ + int dc_cmsize; /* colormap size */ + vaddr_t dc_videobase; /* base of flat frame buffer */ + struct raster dc_raster; /* raster description */ + struct rcons dc_rcons; /* raster blitter control info */ +}; + +struct hwcmap { +#define CMAP_SIZE 256 + u_int8_t r[CMAP_SIZE]; + u_int8_t g[CMAP_SIZE]; + u_int8_t b[CMAP_SIZE]; +}; + +struct omfb_softc { + struct device sc_dev; /* base device */ + struct om_hwdevconfig *sc_dc; /* device configuration */ + struct hwcmap sc_cmap; /* software copy of colormap */ + int nscreens; +}; + +static int omgetcmap __P((struct omfb_softc *, struct wsdisplay_cmap *)); +static int omsetcmap __P((struct omfb_softc *, struct wsdisplay_cmap *)); + +static struct om_hwdevconfig omfb_console_dc; +static void omfb_getdevconfig __P((paddr_t, struct om_hwdevconfig *)); + +extern struct wsdisplay_emulops omfb_emulops; + +static struct wsscreen_descr omfb_stdscreen = { + "std", 0, 0, + &omfb_emulops, + 0, 0, + 0 +}; + +static const struct wsscreen_descr *_omfb_scrlist[] = { + &omfb_stdscreen, +}; + +static const struct wsscreen_list omfb_screenlist = { + sizeof(_omfb_scrlist) / sizeof(struct wsscreen_descr *), _omfb_scrlist +}; + +static int omfbioctl __P((void *, u_long, caddr_t, int, struct proc *)); +static int omfbmmap __P((void *, off_t, int)); +static int omfb_alloc_screen __P((void *, const struct wsscreen_descr *, + void **, int *, int *, long *)); +static void omfb_free_screen __P((void *, void *)); +static int omfb_show_screen __P((void *, void *, int, + void (*) (void *, int, int), void *)); + +static const struct wsdisplay_accessops omfb_accessops = { + omfbioctl, + omfbmmap, + omfb_alloc_screen, + omfb_free_screen, + omfb_show_screen, + 0 /* load_font */ +}; + +static int omfbmatch __P((struct device *, struct cfdata *, void *)); +static void omfbattach __P((struct device *, struct device *, void *)); + +const struct cfattach fb_ca = { + sizeof(struct omfb_softc), omfbmatch, omfbattach +}; +extern struct cfdriver fb_cd; + +extern int hwplanemask; /* hardware planemask; retrieved at boot */ + +static int omfb_console; +int omfb_cnattach __P((void)); + +static int +omfbmatch(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct mainbus_attach_args *ma = aux; + + if (strcmp(ma->ma_name, fb_cd.cd_name)) + return (0); + if (badaddr((caddr_t)ma->ma_addr, 4)) + return (0); + return (1); +} + +static void +omfbattach(parent, self, args) + struct device *parent, *self; + void *args; +{ + struct omfb_softc *sc = (struct omfb_softc *)self; + struct wsemuldisplaydev_attach_args waa; + + if (omfb_console) { + sc->sc_dc = &omfb_console_dc; + sc->nscreens = 1; + } + else { + sc->sc_dc = (struct om_hwdevconfig *) + malloc(sizeof(struct om_hwdevconfig), M_DEVBUF, M_WAITOK); + omfb_getdevconfig(OMFB_FB_WADDR, sc->sc_dc); + } + printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht, + sc->sc_dc->dc_depth); + +#if 0 /* WHITE on BLACK */ + cm = &sc->sc_cmap; + memset(cm, 255, sizeof(struct hwcmap)); + cm->r[0] = cm->g[0] = cm->b[0] = 0; +#endif + waa.console = omfb_console; + waa.scrdata = &omfb_screenlist; + waa.accessops = &omfb_accessops; + waa.accesscookie = sc; + + config_found(self, &waa, wsemuldisplaydevprint); +} + +/* EXPORT */ int +omfb_cnattach() +{ + struct om_hwdevconfig *dc = &omfb_console_dc; + long defattr; + + omfb_getdevconfig(OMFB_FB_WADDR, dc); + (*omfb_emulops.alloc_attr)(&dc->dc_rcons, 0, 0, 0, &defattr); + wsdisplay_cnattach(&omfb_stdscreen, &dc->dc_rcons, 0, 0, defattr); + omfb_console = 1; + return (0); +} + +static int +omfbioctl(v, cmd, data, flag, p) + void *v; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct omfb_softc *sc = v; + struct om_hwdevconfig *dc = sc->sc_dc; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = 0x19990927; + return (0); + + case WSDISPLAYIO_GINFO: +#define wsd_fbip ((struct wsdisplay_fbinfo *)data) + wsd_fbip->height = dc->dc_ht; + wsd_fbip->width = dc->dc_wid; + wsd_fbip->depth = dc->dc_depth; + wsd_fbip->cmsize = dc->dc_cmsize; +#undef fbt + return (0); + + case WSDISPLAYIO_GETCMAP: + return omgetcmap(sc, (struct wsdisplay_cmap *)data); + + case WSDISPLAYIO_PUTCMAP: + return omsetcmap(sc, (struct wsdisplay_cmap *)data); + + case WSDISPLAYIO_SVIDEO: + case WSDISPLAYIO_GVIDEO: + case WSDISPLAYIO_GCURPOS: + case WSDISPLAYIO_SCURPOS: + case WSDISPLAYIO_GCURMAX: + case WSDISPLAYIO_GCURSOR: + case WSDISPLAYIO_SCURSOR: + break; + } + return (ENOTTY); +} + +/* + * Return the address that would map the given device at the given + * offset, allowing for the given protection, or return -1 for error. + */ +static int +omfbmmap(v, offset, prot) + void *v; + off_t offset; + int prot; +{ + struct omfb_softc *sc = v; + + if (offset >= OMFB_SIZE || offset < 0) + return (-1); + return m68k_btop(m68k_trunc_page(sc->sc_dc->dc_videobase) + offset); +} + +static int +omgetcmap(sc, p) + struct omfb_softc *sc; + struct wsdisplay_cmap *p; +{ + u_int index = p->index, count = p->count; + int cmsize; + + cmsize = sc->sc_dc->dc_cmsize; + if (index >= cmsize || (index + count) > cmsize) + return (EINVAL); + + if (!uvm_useracc(p->red, count, B_WRITE) || + !uvm_useracc(p->green, count, B_WRITE) || + !uvm_useracc(p->blue, count, B_WRITE)) + return (EFAULT); + + copyout(&sc->sc_cmap.r[index], p->red, count); + copyout(&sc->sc_cmap.g[index], p->green, count); + copyout(&sc->sc_cmap.b[index], p->blue, count); + + return (0); +} + +static int +omsetcmap(sc, p) + struct omfb_softc *sc; + struct wsdisplay_cmap *p; +{ + u_int index = p->index, count = p->count; + int cmsize, i; + + cmsize = sc->sc_dc->dc_cmsize; + if (index >= cmsize || (index + count) > cmsize) + return (EINVAL); + + if (!uvm_useracc(p->red, count, B_READ) || + !uvm_useracc(p->green, count, B_READ) || + !uvm_useracc(p->blue, count, B_READ)) + return (EFAULT); + + copyin(p->red, &sc->sc_cmap.r[index], count); + copyin(p->green, &sc->sc_cmap.g[index], count); + copyin(p->blue, &sc->sc_cmap.b[index], count); + + if (hwplanemask == 0x0f) { + struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC; + odac->bt_addr = index; + for (i = index; i < count; i++) { + odac->bt_cmap = sc->sc_cmap.r[i]; + odac->bt_cmap = sc->sc_cmap.g[i]; + odac->bt_cmap = sc->sc_cmap.b[i]; + } + } + else if (hwplanemask == 0xff) { + struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC; + ndac->bt_addr = index; + for (i = index; i < count; i++) { + ndac->bt_cmap = sc->sc_cmap.r[i]; + ndac->bt_cmap = sc->sc_cmap.g[i]; + ndac->bt_cmap = sc->sc_cmap.b[i]; + } + } + return (0); +} + +static void +omfb_getdevconfig(paddr, dc) + paddr_t paddr; + struct om_hwdevconfig *dc; +{ + int bpp, i; + struct raster *rap; + struct rcons *rcp; + struct { short h, v; } *rfcnt; + + switch (hwplanemask) { + case 0xff: + bpp = 8; /* XXX check monochrome bit in DIPSW */ + break; + default: + case 0x0f: + bpp = 4; /* XXX check monochrome bit in DIPSW */ + break; + case 1: + bpp = 1; + break; + } + dc->dc_wid = 1240; + dc->dc_ht = 1024; + dc->dc_depth = bpp; + dc->dc_rowbytes = 2048 / 8; + dc->dc_cmsize = (bpp == 1) ? 0 : 1 << bpp; + dc->dc_videobase = paddr; + +#if 0 /* WHITE on BLACK */ + if (hwplanemask == 0x0f) { + /* XXX Need Bt454 initialization */ + struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC; + odac->bt_addr = 0; + odac->bt_cmap = 0; + odac->bt_cmap = 0; + odac->bt_cmap = 0; + for (i = 1; i < 16; i++) { + odac->bt_cmap = 255; + odac->bt_cmap = 255; + odac->bt_cmap = 255; + } + } + else if (hwplanemask == 0xff) { + struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC; + + ndac->bt_addr = 0x04; + ndac->bt_ctrl = 0xff; /* all planes will be read */ + ndac->bt_ctrl = 0x00; /* all planes have non-blink */ + ndac->bt_ctrl = 0x43; /* pallete enabled, ovly plane */ + ndac->bt_ctrl = 0x00; /* no test mode */ + ndac->bt_addr = 0; + ndac->bt_cmap = 0; + ndac->bt_cmap = 0; + ndac->bt_cmap = 0; + for (i = 1; i < 256; i++) { + ndac->bt_cmap = 255; + ndac->bt_cmap = 255; + ndac->bt_cmap = 255; + } + } +#endif + + /* adjust h/v orgin on screen */ + /* XXX not sure it's necessary XXX */ + rfcnt = (void *)OMFB_RFCNT; + rfcnt->h = 0; + rfcnt->v = 0; + + /* clear the screen */ + *(u_int32_t *)OMFB_PLANEMASK = 0xff; + ((u_int32_t *)OMFB_ROPFUNC)[5] = ~0; /* ROP copy */ + for (i = 0; i < dc->dc_ht * dc->dc_rowbytes/sizeof(u_int32_t); i++) + *(u_int32_t *)(dc->dc_videobase + i) = 0; + *(u_int32_t *)OMFB_PLANEMASK = 0x01; + + /* initialize the raster */ + rap = &dc->dc_raster; + rap->width = dc->dc_wid; + rap->height = dc->dc_ht; + rap->depth = dc->dc_depth; + rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t); + rap->pixels = (u_int32_t *)dc->dc_videobase; + + /* initialize the raster console blitter */ + rcp = &dc->dc_rcons; + rcp->rc_sp = rap; + rcp->rc_crow = rcp->rc_ccol = -1; + rcp->rc_crowp = &rcp->rc_crow; + rcp->rc_ccolp = &rcp->rc_ccol; + rcons_init(rcp, 34, 80); + + omfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow; + omfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol; +} + +static int +omfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp) + void *v; + const struct wsscreen_descr *type; + void **cookiep; + int *curxp, *curyp; + long *attrp; +{ + struct omfb_softc *sc = v; + long defattr; + + if (sc->nscreens > 0) + return (ENOMEM); + + *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */ + *curxp = 0; + *curyp = 0; + (*omfb_emulops.alloc_attr)(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr); + *attrp = defattr; + sc->nscreens++; + return (0); +} + +static void +omfb_free_screen(v, cookie) + void *v; + void *cookie; +{ + struct omfb_softc *sc = v; + + if (sc->sc_dc == &omfb_console_dc) + panic("omfb_free_screen: console"); + + sc->nscreens--; +} + +static int +omfb_show_screen(v, cookie, waitok, cb, cbarg) + void *v; + void *cookie; + int waitok; + void (*cb) __P((void *, int, int)); + void *cbarg; +{ + return 0; +} diff --git a/sys/arch/luna68k/dev/lunaws.c b/sys/arch/luna68k/dev/lunaws.c new file mode 100644 index 00000000000..82d0ea70574 --- /dev/null +++ b/sys/arch/luna68k/dev/lunaws.c @@ -0,0 +1,465 @@ +/* $NetBSD: lunaws.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: lunaws.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $"); + +#include "wsmouse.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/device.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> +#include <dev/wscons/wsmousevar.h> + +#include <luna68k/dev/sioreg.h> +#include <luna68k/dev/siovar.h> + +static const u_int8_t ch1_regs[6] = { + WR0_RSTINT, /* Reset E/S Interrupt */ + WR1_RXALLS, /* Rx per char, No Tx */ + 0, /* */ + WR3_RX8BIT | WR3_RXENBL, /* Rx */ + WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY, /* Tx/Rx */ + WR5_TX8BIT | WR5_TXENBL, /* Tx */ +}; + +struct ws_softc { + struct device sc_dv; + struct device *sc_wskbddev; + struct device *sc_wsmousedev; + struct sioreg *sc_ctl; + u_int8_t sc_wr[6]; +}; + +static void omkbd_input __P((void *, int)); +static int omkbd_decode __P((void *, int, u_int *, int *)); +static int omkbd_enable __P((void *, int)); +static void omkbd_set_leds __P((void *, int)); +static int omkbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); + +struct wscons_keydesc omkbd_keydesctab[]; + +static const struct wskbd_mapdata omkbd_keymapdata = { + omkbd_keydesctab, + KB_JP, +}; +static const struct wskbd_accessops omkbd_accessops = { + omkbd_enable, + omkbd_set_leds, + omkbd_ioctl, +}; + +void ws_cnattach __P((void)); +static void ws_cngetc __P((void *, u_int *, int *)); +static void ws_cnpollc __P((void *, int)); +static const struct wskbd_consops ws_consops = { + ws_cngetc, + ws_cnpollc, +}; + +#if NWSMOUSE > 0 +static int omms_enable __P((void *)); +static int omms_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); +static void omms_disable __P((void *)); + +static const struct wsmouse_accessops omms_accessops = { + omms_enable, + omms_ioctl, + omms_disable, +}; +#endif + +static void wsintr __P((int)); + +static int wsmatch __P((struct device *, struct cfdata *, void *)); +static void wsattach __P((struct device *, struct device *, void *)); + +const struct cfattach ws_ca = { + sizeof(struct ws_softc), wsmatch, wsattach +}; +extern struct cfdriver ws_cd; + +extern int syscngetc __P((dev_t)); +extern void syscnputc __P((dev_t, int)); + +static int +wsmatch(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + struct sio_attach_args *args = aux; + + if (args->channel != 1) + return 0; + return 1; +} + +static void +wsattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct ws_softc *sc = (struct ws_softc *)self; + struct sio_softc *scp = (struct sio_softc *)parent; + struct sio_attach_args *args = aux; + struct wskbddev_attach_args a; + + sc->sc_ctl = (struct sioreg *)scp->scp_ctl + 1; + bcopy(ch1_regs, sc->sc_wr, sizeof(ch1_regs)); + scp->scp_intr[1] = wsintr; + + setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); + setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]); + setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]); + setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]); + setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); + setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]); + + syscnputc((dev_t)1, 0x20); /* keep quiet mouse */ + + printf("\n"); + + a.console = (args->hwflags == 1); + a.keymap = &omkbd_keymapdata; + a.accessops = &omkbd_accessops; + a.accesscookie = (void *)sc; + sc->sc_wskbddev = config_found(self, &a, wskbddevprint); + +#if NWSMOUSE > 0 + { + struct wsmousedev_attach_args b; + b.accessops = &omms_accessops; + b.accesscookie = (void *)sc; + sc->sc_wsmousedev = config_found(self, &b, wsmousedevprint); + } +#endif +} + +/*ARGSUSED*/ +static void +wsintr(chan) + int chan; +{ + struct ws_softc *sc = ws_cd.cd_devs[0]; + struct sioreg *sio = sc->sc_ctl; + u_int code; + int rr; + extern int getsiocsr __P((struct sioreg *)); + + rr = getsiocsr(sio); + if (rr & RR_RXRDY) { + do { + code = sio->sio_data; + if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) { + sio->sio_cmd = WR0_ERRRST; +#if 0 + if (sio->sio_stat & RR_FRAMING) + code |= TTY_FE; + else if (sio->sio_stat & RR_PARITY) + code |= TTY_PE; +#endif + continue; + } +#if 0 + /* + * if (code >= 0x80 || code <= 0x87), then + * it's the first byte of 3 byte long mouse report + * code[0] & 07 -> LMR button condition + * code[1], [2] -> x,y delta + */ +#endif + omkbd_input(sc, code & 0xff); + } while ((rr = getsiocsr(sio)) & RR_RXRDY); + } + if (rr && RR_TXRDY) + sio->sio_cmd = WR0_RSTPEND; + /* not capable of transmit, yet */ +} + +static void +omkbd_input(v, data) + void *v; + int data; +{ + struct ws_softc *sc = v; + u_int type; + int key; + + if (omkbd_decode(v, data, &type, &key)) + wskbd_input(sc->sc_wskbddev, type, key); +} + +static int +omkbd_decode(v, datain, type, dataout) + void *v; + int datain; + u_int *type; + int *dataout; +{ + *type = (datain & 0x80) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; + *dataout = datain & 0x7f; + return 1; +} + +#define KC(n) KS_KEYCODE(n) + +static const keysym_t omkbd_keydesc_1[] = { +/* pos command normal shifted */ + KC(0x9), KS_Tab, + KC(0xa), KS_Control_L, + KC(0xb), KS_Mode_switch, /* Kana */ + KC(0xc), KS_Shift_R, + KC(0xd), KS_Shift_L, + KC(0xe), KS_Caps_Lock, + KC(0xf), KS_Meta_L, /* Zenmen */ + KC(0x10), KS_Escape, + KC(0x11), KS_BackSpace, + KC(0x12), KS_Return, + KC(0x14), KS_space, + KC(0x15), KS_Delete, + KC(0x16), KS_Alt_L, /* Henkan */ + KC(0x17), KS_Alt_R, /* Kakutei */ + KC(0x18), KS_f11, /* Shokyo */ + KC(0x19), KS_f12, /* Yobidashi */ + KC(0x1a), KS_f13, /* Bunsetsu L */ + KC(0x1b), KS_f14, /* Bunsetsu R */ + KC(0x1c), KS_KP_Up, + KC(0x1d), KS_KP_Left, + KC(0x1e), KS_KP_Right, + KC(0x1f), KS_KP_Down, + /* KC(0x20), KS_f11, */ + /* KC(0x21), KS_f12, */ + KC(0x22), KS_1, KS_exclam, + KC(0x23), KS_2, KS_quotedbl, + KC(0x24), KS_3, KS_numbersign, + KC(0x25), KS_4, KS_dollar, + KC(0x26), KS_5, KS_percent, + KC(0x27), KS_6, KS_ampersand, + KC(0x28), KS_7, KS_apostrophe, + KC(0x29), KS_8, KS_parenleft, + KC(0x2a), KS_9, KS_parenright, + KC(0x2b), KS_0, + KC(0x2c), KS_minus, KS_equal, + KC(0x2d), KS_asciicircum, KS_asciitilde, + KC(0x2e), KS_backslash, KS_bar, + /* KC(0x30), KS_f13, */ + /* KC(0x31), KS_f14, */ + KC(0x32), KS_q, + KC(0x33), KS_w, + KC(0x34), KS_e, + KC(0x35), KS_r, + KC(0x36), KS_t, + KC(0x37), KS_y, + KC(0x38), KS_u, + KC(0x39), KS_i, + KC(0x3a), KS_o, + KC(0x3b), KS_p, + KC(0x3c), KS_at, KS_grave, + KC(0x3d), KS_bracketleft, KS_braceleft, + KC(0x42), KS_a, + KC(0x43), KS_s, + KC(0x44), KS_d, + KC(0x45), KS_f, + KC(0x46), KS_g, + KC(0x47), KS_h, + KC(0x48), KS_j, + KC(0x49), KS_k, + KC(0x4a), KS_l, + KC(0x4b), KS_semicolon, KS_plus, + KC(0x4c), KS_colon, KS_asterisk, + KC(0x4d), KS_bracketright, KS_braceright, + KC(0x52), KS_z, + KC(0x53), KS_x, + KC(0x54), KS_c, + KC(0x55), KS_v, + KC(0x56), KS_b, + KC(0x57), KS_n, + KC(0x58), KS_m, + KC(0x59), KS_comma, KS_less, + KC(0x5a), KS_period, KS_greater, + KC(0x5b), KS_slash, KS_question, + KC(0x5c), KS_underscore, + KC(0x60), KS_KP_Delete, + KC(0x61), KS_KP_Add, + KC(0x62), KS_KP_Subtract, + KC(0x63), KS_KP_7, + KC(0x64), KS_KP_8, + KC(0x65), KS_KP_9, + KC(0x66), KS_KP_4, + KC(0x67), KS_KP_5, + KC(0x68), KS_KP_6, + KC(0x69), KS_KP_1, + KC(0x6a), KS_KP_2, + KC(0x6b), KS_KP_3, + KC(0x6c), KS_KP_0, + KC(0x6d), KS_KP_Decimal, + KC(0x6e), KS_KP_Enter, + KC(0x72), KS_f1, + KC(0x73), KS_f2, + KC(0x74), KS_f3, + KC(0x75), KS_f4, + KC(0x76), KS_f5, + KC(0x77), KS_f6, + KC(0x78), KS_f7, + KC(0x79), KS_f8, + KC(0x7a), KS_f9, + KC(0x7b), KS_f10, + KC(0x7c), KS_KP_Multiply, + KC(0x7d), KS_KP_Divide, + KC(0x7e), KS_KP_Equal, + KC(0x7f), KS_KP_Separator, +}; + +#define SIZE(map) (sizeof(map)/sizeof(keysym_t)) + +struct wscons_keydesc omkbd_keydesctab[] = { + { KB_JP, 0, SIZE(omkbd_keydesc_1), omkbd_keydesc_1, }, + { 0, 0, 0, 0 }, +}; + +static void +ws_cngetc(v, type, data) + void *v; + u_int *type; + int *data; +{ + int code; + + do { + code = syscngetc((dev_t)1); + } while (!omkbd_decode(v, code, type, data)); +} + +static void +ws_cnpollc(v, on) + void *v; + int on; +{ +} + +/* EXPORT */ void +ws_cnattach() +{ + static int voidfill; + + wskbd_cnattach(&ws_consops, &voidfill, &omkbd_keymapdata); +} + +static int +omkbd_enable(v, on) + void *v; + int on; +{ + return 0; +} + +static void +omkbd_set_leds(v, leds) + void *v; + int leds; +{ +#if 0 + syscnputc((dev_t)1, 0x10); /* kana LED on */ + syscnputc((dev_t)1, 0x00); /* kana LED off */ + syscnputc((dev_t)1, 0x11); /* caps LED off */ + syscnputc((dev_t)1, 0x01); /* caps LED off */ +#endif +} + +static int +omkbd_ioctl(v, cmd, data, flag, p) + void *v; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + switch (cmd) { + case WSKBDIO_GTYPE: + *(int *)data = 0x19991005 /* XXX */; + return 0; + case WSKBDIO_SETLEDS: + case WSKBDIO_GETLEDS: + case WSKBDIO_COMPLEXBELL: + return 0; + } + return -1; +} + +#if NWSMOUSE > 0 + +static int +omms_enable(v) + void *v; +{ + syscnputc((dev_t)1, 0x60); /* enable 3 byte long mouse reporting */ + return 0; +} + +/*ARGUSED*/ +static int +omms_ioctl(v, cmd, data, flag, p) + void *v; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + if (cmd == WSMOUSEIO_GTYPE) { + *(u_int *)data = 0x19991005; /* XXX */ + return 0; + } + return ENOTTY; +} + +static void +omms_disable(v) + void *v; +{ + syscnputc((dev_t)1, 0x20); /* quiet mouse */ +} +#endif diff --git a/sys/arch/luna68k/dev/md_root.c b/sys/arch/luna68k/dev/md_root.c new file mode 100644 index 00000000000..0db9aae1b51 --- /dev/null +++ b/sys/arch/luna68k/dev/md_root.c @@ -0,0 +1,91 @@ +/* $NetBSD: md_root.c,v 1.1 2000/01/05 08:48:55 nisimura Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Gordon W. Ross. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/reboot.h> +#include <sys/systm.h> + +#include <dev/md.h> + +#include "opt_mdsize.h" + +extern int boothowto; + +#ifndef MINIROOTSIZE +#define MINIROOTSIZE 512 +#endif + +#define ROOTBYTES (MINIROOTSIZE << DEV_BSHIFT) + +/* + * This array will be patched to contain a file-system image. + * See the program: src/distrib/sun3/common/rdsetroot.c + */ +int md_root_size = ROOTBYTES; +char md_root_image[ROOTBYTES] = "|This is the root ramdisk!\n"; + +/* + * This is called during autoconfig. + */ +void +md_attach_hook(unit, md) + int unit; + struct md_conf *md; +{ + if (unit == 0) { + /* Setup root ramdisk */ + md->md_addr = (caddr_t) md_root_image; + md->md_size = (size_t) md_root_size; + md->md_type = MD_KMEM_FIXED; + printf(" fixed, %d blocks", MINIROOTSIZE); + } +} + +/* + * This is called during open (i.e. mountroot) + */ +void +md_open_hook(unit, md) + int unit; + struct md_conf *md; +{ + if (unit == 0) { + /* The root ramdisk only works single-user. */ + boothowto |= RB_SINGLE; + } +} diff --git a/sys/arch/luna68k/dev/omrasops.c b/sys/arch/luna68k/dev/omrasops.c new file mode 100644 index 00000000000..8b4e364e2de --- /dev/null +++ b/sys/arch/luna68k/dev/omrasops.c @@ -0,0 +1,518 @@ +/* $NetBSD: omrasops.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: omrasops.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $"); + +/* + * Designed speficically for 'm68k bitorder'; + * - most significant byte is stored at lower address, + * - most significant bit is displayed at left most on screen. + * Implementation relys on; + * - every memory references is done in aligned 32bit chunk, + * - font glyphs are stored in 32bit padded. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <dev/rcons/raster.h> +#include <dev/wscons/wscons_raster.h> +#include <dev/wscons/wscons_rfont.h> +#include <dev/wscons/wsdisplayvar.h> + +void rcons_init __P((struct rcons *, int, int)); + +/* wscons emulator operations */ +static void om_cursor __P((void *, int, int, int)); +static int om_mapchar __P((void *, int, unsigned int *)); +static void om_putchar __P((void *, int, int, u_int, long)); +static void om_copycols __P((void *, int, int, int, int)); +static void om_copyrows __P((void *, int, int, int num)); +static void om_erasecols __P((void *, int, int, int, long)); +static void om_eraserows __P((void *, int, int, long)); +static int om_alloc_attr __P((void *, int, int, int, long *)); + +struct wsdisplay_emulops omfb_emulops = { + om_cursor, + om_mapchar, + om_putchar, + om_copycols, + om_erasecols, + om_copyrows, + om_eraserows, + om_alloc_attr +}; + +#define ALL1BITS (~0U) +#define ALL0BITS (0U) +#define BLITWIDTH (32) +#define ALIGNMASK (0x1f) +#define BYTESDONE (4) + +#define W(p) (*(u_int32_t *)(p)) +#define R(p) (*(u_int32_t *)((caddr_t)(p) + 0x40000)) + +/* + * Blit a character at the specified co-ordinates. + */ +static void +om_putchar(cookie, row, startcol, uc, attr) + void *cookie; + int row, startcol; + u_int uc; + long attr; +{ + struct rcons *rc = cookie; + struct raster *rap = rc->rc_sp; + caddr_t p; + int scanspan, startx, height, width, align, y; + u_int32_t lmask, rmask, glyph, inverse; + u_int32_t *g; + + scanspan = rap->linelongs * 4; + y = rc->rc_yorigin + rc->rc_font->height * row; + startx = rc->rc_xorigin + rc->rc_font->width * startcol; + height = rc->rc_font->height; + g = rc->rc_font->chars[uc].r->pixels; + inverse = (attr != 0) ? ALL1BITS : ALL0BITS; + + p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4); + align = startx & ALIGNMASK; + width = rc->rc_font->width + align; + lmask = ALL1BITS >> align; + rmask = ALL1BITS << (-width & ALIGNMASK); + if (width <= BLITWIDTH) { + lmask &= rmask; + while (height > 0) { + glyph = *g; + glyph = (glyph >> align) ^ inverse; + W(p) = (R(p) & ~lmask) | (glyph & lmask); + p += scanspan; + g += 1; + height--; + } + } + else { + caddr_t q = p; + u_int32_t lhalf, rhalf; + + while (height > 0) { + glyph = *g; + lhalf = (glyph >> align) ^ inverse; + W(p) = (R(p) & ~lmask) | (lhalf & lmask); + p += BYTESDONE; + rhalf = (glyph << (BLITWIDTH - align)) ^ inverse; + W(p) = (rhalf & rmask) | (R(p) & ~rmask); + + p = (q += scanspan); + g += 1; + height--; + } + } +} + +static void +om_erasecols(cookie, row, startcol, ncols, attr) + void *cookie; + int row, startcol, ncols; + long attr; +{ + struct rcons *rc = cookie; + struct raster *rap = rc->rc_sp; + caddr_t p; + int scanspan, startx, height, width, align, w, y; + u_int32_t lmask, rmask, fill; + + scanspan = rap->linelongs * 4; + y = rc->rc_yorigin + rc->rc_font->height * row; + startx = rc->rc_xorigin + rc->rc_font->width * startcol; + height = rc->rc_font->height; + w = rc->rc_font->width * ncols; + fill = (attr != 0) ? ALL1BITS : ALL0BITS; + + p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4); + align = startx & ALIGNMASK; + width = w + align; + lmask = ALL1BITS >> align; + rmask = ALL1BITS << (-width & ALIGNMASK); + if (width <= BLITWIDTH) { + lmask &= rmask; + fill &= lmask; + while (height > 0) { + W(p) = (R(p) & ~lmask) | fill; + p += scanspan; + height--; + } + } + else { + caddr_t q = p; + while (height > 0) { + W(p) = (R(p) & ~lmask) | (fill & lmask); + width -= 2 * BLITWIDTH; + while (width > 0) { + p += BYTESDONE; + W(p) = fill; + width -= BLITWIDTH; + } + p += BYTESDONE; + W(p) = (fill & rmask) | (R(p) & ~rmask); + + p = (q += scanspan); + width = w + align; + height--; + } + } +} + +static void +om_eraserows(cookie, startrow, nrows, attr) + void *cookie; + int startrow, nrows; + long attr; +{ + struct rcons *rc = cookie; + struct raster *rap = rc->rc_sp; + caddr_t p, q; + int scanspan, starty, height, width, w; + u_int32_t rmask, fill; + + scanspan = rap->linelongs * 4; + starty = rc->rc_yorigin + rc->rc_font->height * startrow; + height = rc->rc_font->height * nrows; + w = rc->rc_font->width * rc->rc_maxcol; + fill = (attr == 1) ? ALL1BITS : ALL0BITS; + + p = (caddr_t)rap->pixels + starty * scanspan; + p += (rc->rc_xorigin / 32) * 4; + width = w; + rmask = ALL1BITS << (-width & ALIGNMASK); + q = p; + while (height > 0) { + W(p) = fill; /* always aligned */ + width -= 2 * BLITWIDTH; + while (width > 0) { + p += BYTESDONE; + W(p) = fill; + width -= BLITWIDTH; + } + p += BYTESDONE; + W(p) = (fill & rmask) | (R(p) & ~rmask); + p = (q += scanspan); + width = w; + height--; + } +} + +static void +om_copyrows(cookie, srcrow, dstrow, nrows) + void *cookie; + int srcrow, dstrow, nrows; +{ + struct rcons *rc = cookie; + struct raster *rap = rc->rc_sp; + caddr_t p, q; + int scanspan, offset, srcy, height, width, w; + u_int32_t rmask; + + scanspan = rap->linelongs * 4; + height = rc->rc_font->height * nrows; + offset = (dstrow - srcrow) * scanspan * rc->rc_font->height; + srcy = rc->rc_yorigin + rc->rc_font->height * srcrow; + if (srcrow < dstrow && srcrow + nrows > dstrow) { + scanspan = -scanspan; + srcy += height; + } + + p = (caddr_t)rap->pixels + srcy * (rap->linelongs * 4); + p += (rc->rc_xorigin / 32) * 4; + w = rc->rc_font->width * rc->rc_maxcol; + width = w; + rmask = ALL1BITS << (-width & ALIGNMASK); + q = p; + while (height > 0) { + W(p + offset) = R(p); /* always aligned */ + width -= 2 * BLITWIDTH; + while (width > 0) { + p += BYTESDONE; + W(p + offset) = R(p); + width -= BLITWIDTH; + } + p += BYTESDONE; + W(p + offset) = (R(p) & rmask) | (R(p + offset) & ~rmask); + + p = (q += scanspan); + width = w; + height--; + } +} + +static void +om_copycols(cookie, startrow, srccol, dstcol, ncols) + void *cookie; + int startrow, srccol, dstcol, ncols; +{ + struct rcons *rc = cookie; + struct raster *rap = rc->rc_sp; + caddr_t sp, dp, basep; + int scanspan, height, width, align, shift, w, y, srcx, dstx; + u_int32_t lmask, rmask; + + scanspan = rap->linelongs * 4; + y = rc->rc_yorigin + rc->rc_font->height * startrow; + srcx = rc->rc_xorigin + rc->rc_font->width * srccol; + dstx = rc->rc_xorigin + rc->rc_font->width * dstcol; + height = rc->rc_font->height; + w = rc->rc_font->width * ncols; + basep = (caddr_t)rap->pixels + y * scanspan; + + align = shift = srcx & ALIGNMASK; + width = w + align; + align = dstx & ALIGNMASK; + lmask = ALL1BITS >> align; + rmask = ALL1BITS << (-(w + align) & ALIGNMASK); + shift = align - shift; + sp = basep + (srcx / 32) * 4; + dp = basep + (dstx / 32) * 4; + + if (shift != 0) + goto hardluckalignment; + + /* alignments comfortably match */ + if (width <= BLITWIDTH) { + lmask &= rmask; + while (height > 0) { + W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); + dp += scanspan; + sp += scanspan; + height--; + } + } + /* copy forward (left-to-right) */ + else if (dstcol < srccol || srccol + ncols < dstcol) { + caddr_t sq = sp, dq = dp; + + w = width; + while (height > 0) { + W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); + width -= 2 * BLITWIDTH; + while (width > 0) { + sp += BYTESDONE; + dp += BYTESDONE; + W(dp) = R(sp); + width -= BLITWIDTH; + } + sp += BYTESDONE; + dp += BYTESDONE; + W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask); + sp = (sq += scanspan); + dp = (dq += scanspan); + width = w; + height--; + } + } + /* copy backward (right-to-left) */ + else { + caddr_t sq, dq; + + sq = (sp += width / 32 * 4); + dq = (dp += width / 32 * 4); + w = width; + while (height > 0) { + W(dp) = (R(sp) & rmask) | (R(dp) & ~rmask); + width -= 2 * BLITWIDTH; + while (width > 0) { + sp -= BYTESDONE; + dp -= BYTESDONE; + W(dp) = R(sp); + width -= BLITWIDTH; + } + sp -= BYTESDONE; + dp -= BYTESDONE; + W(dp) = (R(dp) & ~lmask) | (R(sp) & lmask); + + sp = (sq += scanspan); + dp = (dq += scanspan); + width = w; + height--; + } + } + return; + + hardluckalignment: + /* alignments painfully disagree */ +} + +/* + * Map a character. + */ +static int +om_mapchar(cookie, c, cp) + void *cookie; + int c; + u_int *cp; +{ + if (c < 128) { + *cp = c; + return (5); + } + *cp = ' '; + return (0); +} + +/* + * Position|{enable|disable} the cursor at the specified location. + */ +static void +om_cursor(cookie, on, row, col) + void *cookie; + int on, row, col; +{ + struct rcons *rc = cookie; + struct raster *rap = rc->rc_sp; + caddr_t p; + int scanspan, startx, height, width, align, y; + u_int32_t lmask, rmask, image; + + if (!on) { + /* make sure it's on */ + if ((rc->rc_bits & RC_CURSOR) == 0) + return; + + row = *rc->rc_crowp; + col = *rc->rc_ccolp; + } else { + /* unpaint the old copy. */ + *rc->rc_crowp = row; + *rc->rc_ccolp = col; + } + + scanspan = rap->linelongs * 4; + y = rc->rc_yorigin + rc->rc_font->height * row; + startx = rc->rc_xorigin + rc->rc_font->width * col; + height = rc->rc_font->height; + + p = (caddr_t)rap->pixels + y * scanspan + ((startx / 32) * 4); + align = startx & ALIGNMASK; + width = rc->rc_font->width + align; + lmask = ALL1BITS >> align; + rmask = ALL1BITS << (-width & ALIGNMASK); + if (width <= BLITWIDTH) { + lmask &= rmask; + while (height > 0) { + image = R(p); + W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); + p += scanspan; + height--; + } + } + else { + caddr_t q = p; + + while (height > 0) { + image = R(p); + W(p) = (image & ~lmask) | ((image ^ ALL1BITS) & lmask); + p += BYTESDONE; + image = R(p); + W(p) = ((image ^ ALL1BITS) & rmask) | (image & ~rmask); + + p = (q += scanspan); + height--; + } + } + rc->rc_bits ^= RC_CURSOR; +} + +/* + * Allocate attribute. We just pack these into an integer. + */ +static int +om_alloc_attr(id, fg, bg, flags, attrp) + void *id; + int fg, bg, flags; + long *attrp; +{ + if (flags & (WSATTR_HILIT | WSATTR_BLINK | + WSATTR_UNDERLINE | WSATTR_WSCOLORS)) + return (EINVAL); + if (flags & WSATTR_REVERSE) + *attrp = 1; + else + *attrp = 0; + return (0); +} + +void +rcons_init(rc, mrow, mcol) + struct rcons *rc; + int mrow, mcol; +{ + struct raster *rp = rc->rc_sp; + int i; + + rc->rc_font = &gallant19; /* 12x22 monospacing font */ + + /* Get distance to top and bottom of font from font origin */ + rc->rc_font_ascent = -(rc->rc_font->chars)['a'].homey; + + i = rp->height / rc->rc_font->height; + rc->rc_maxrow = min(i, mrow); + + i = rp->width / rc->rc_font->width; + rc->rc_maxcol = min(i, mcol); + + /* Center emulator screen (but align x origin to 32 bits) */ + rc->rc_xorigin = + ((rp->width - rc->rc_maxcol * rc->rc_font->width) / 2) & ~ALIGNMASK; + rc->rc_yorigin = + (rp->height - rc->rc_maxrow * rc->rc_font->height) / 2; +#if 0 + /* Raster width used for row copies */ + rc->rc_raswidth = rc->rc_maxcol * rc->rc_font->width; + if (rc->rc_raswidth & ALIGNMASK) { + /* Pad to 32 bits */ + i = (rc->rc_raswidth + ALIGNMASK) & ~ALIGNMASK; + /* Make sure width isn't too wide */ + if (rc->rc_xorigin + i <= rp->width) + rc->rc_raswidth = i; + } +#endif + rc->rc_bits = 0; +} diff --git a/sys/arch/luna68k/dev/sio.c b/sys/arch/luna68k/dev/sio.c new file mode 100644 index 00000000000..47cccc1e7c8 --- /dev/null +++ b/sys/arch/luna68k/dev/sio.c @@ -0,0 +1,131 @@ +/* $NetBSD: sio.c,v 1.1 2000/01/05 08:48:55 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: sio.c,v 1.1 2000/01/05 08:48:55 nisimura Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/cpu.h> +#include <machine/autoconf.h> + +#include <luna68k/luna68k/isr.h> +#include <luna68k/dev/siovar.h> + +static int sio_match __P((struct device *, struct cfdata *, void *)); +static void sio_attach __P((struct device *, struct device *, void *)); +static int sio_print __P((void *, const char *)); + +const struct cfattach sio_ca = { + sizeof(struct sio_softc), sio_match, sio_attach +}; +extern struct cfdriver sio_cd; + +static void nullintr __P((int)); +static int xsiointr __P((void *)); + +static int +sio_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct mainbus_attach_args *ma = aux; + + if (strcmp(ma->ma_name, sio_cd.cd_name)) + return 0; + if (badaddr((caddr_t)ma->ma_addr, 4)) + return 0; + return 1; +} + +static void +sio_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct sio_softc *sc = (void *)self; + struct mainbus_attach_args *ma = aux; + struct sio_attach_args sio_args; + int channel; + extern int sysconsole; /* console: 0 for ttya, 1 for desktop */ + + printf(": 7201a\n"); + + sc->scp_ctl = (caddr_t)ma->ma_addr; + sc->scp_intr[0] = sc->scp_intr[1] = nullintr; + for (channel = 0; channel < 2; channel++) { + sio_args.channel = channel; + sio_args.hwflags = (channel == sysconsole); + config_found(self, (void *)&sio_args, sio_print); + } + + isrlink_autovec(xsiointr, sc, ma->ma_ilvl, ISRPRI_TTYNOBUF); +} + +static int +sio_print(aux, name) + void *aux; + const char *name; +{ + struct sio_attach_args *args = aux; + + if (name != NULL) + printf("%s: ", name); + + if (args->channel != -1) + printf(" channel %d", args->channel); + + return UNCONF; +} + +static int +xsiointr(arg) + void *arg; +{ + struct sio_softc *sc = arg; + + (*sc->scp_intr[0])(0); /* 0: ttya system serial port */ + (*sc->scp_intr[1])(1); /* 1: keyboard and mouse */ + return 1; +} + +static void nullintr(v) int v; { } diff --git a/sys/arch/luna68k/dev/sioreg.h b/sys/arch/luna68k/dev/sioreg.h new file mode 100644 index 00000000000..c6116f61a94 --- /dev/null +++ b/sys/arch/luna68k/dev/sioreg.h @@ -0,0 +1,136 @@ +/* $NetBSD: sioreg.h,v 1.1 2000/01/05 08:48:55 nisimura Exp $ */ +/* + * Copyright (c) 1992 OMRON Corporation. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * OMRON Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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. + * + * @(#)sioreg.h 8.1 (Berkeley) 6/10/93 + */ + +#define WR0 0x00 +#define WR1 0x01 +#define WR2 0x02 +#define WR3 0x03 +#define WR4 0x04 +#define WR5 0x05 +#define WR6 0x06 +#define WR7 0x07 + +#define WR2A WR2 +#define WR2B (WR2|0x10) + +#define RR0 0x08 +#define RR1 0x09 +#define RR2 0x0A +#define RR3 0x0B +#define RR4 0x0C + +#define RR2A RR2 +#define RR2B (RR2|0x10) + +#define WR0_NOP 0x00 /* No Operation */ +#define WR0_SNDABRT 0x08 /* Send Abort (HDLC) */ +#define WR0_RSTINT 0x10 /* Reset External/Status Interrupt */ +#define WR0_CHANRST 0x18 /* Channel Reset */ +#define WR0_INTNXT 0x20 /* Enable Interrupt on Next Receive Character */ +#define WR0_RSTPEND 0x28 /* Reset Transmitter Interrput/DMA Pending */ +#define WR0_ERRRST 0x30 /* Error Reset */ +#define WR0_ENDINTR 0x38 /* End of Interrupt */ + +#define WR1_ESENBL 0x01 /* External/Status Interrupt Enable */ +#define WR1_TXENBL 0x02 /* Tx Interrupt/DMA Enable */ +#define WR1_STATVEC 0x04 /* Status Affects Vector (Only Chan-B) */ +#define WR1_RXDSEBL 0x00 /* Rx Interrupt/DMA Disable */ +#define WR1_RXFIRST 0x08 /* Interrupt only First Character Received */ +#define WR1_RXALLS 0x10 /* Interrupt Every Characters Received (with Special Char.) */ +#define WR1_RXALL 0x18 /* Interrupt Every Characters Received (without Special Char.) */ + +#define WR2_INTR_0 0x00 /* Interrupt Priority: RxA TxA RxB TxB E/SA E/SA */ +#define WR2_INTR_1 0x04 /* Interrupt Priority: RxA RxB TxA TxB E/SA E/SA */ +#define WR2_VEC85_1 0x00 /* 8085 Vectored Mode - 1 */ +#define WR2_VEC85_2 0x08 /* 8085 Vectored Mode - 2 */ +#define WR2_VEC86 0x10 /* 8086 Vectored */ +#define WR2_VEC85_3 0x18 /* 8085 Vectored Mode - 3 */ + +#define WR3_RXENBL 0x01 /* Rx Enable */ +#define WR3_RXCRC 0x08 /* Rx CRC Check */ +#define WR3_AUTOEBL 0x20 /* Auto Enable (flow control for MODEM) */ +#define WR3_RX5BIT 0x00 /* Rx Bits/Character: 5 Bits */ +#define WR3_RX7BIT 0x40 /* Rx Bits/Character: 7 Bits */ +#define WR3_RX6BIT 0x80 /* Rx Bits/Character: 6 Bits */ +#define WR3_RX8BIT 0xc0 /* Rx Bits/Character: 8 Bits */ + +#define WR4_NPARITY 0x00 /* No Parity */ +#define WR4_PARENAB 0x01 /* Parity Enable */ +#define WR4_OPARITY 0x01 /* Parity Odd */ +#define WR4_EPARITY 0x02 /* Parity Even */ +#define WR4_STOP1 0x04 /* Stop Bits (1bit) */ +#define WR4_STOP15 0x08 /* Stop Bits (1.5bit) */ +#define WR4_STOP2 0x0c /* Stop Bits (2bit) */ +#define WR4_BAUD96 0x40 /* Clock Rate (9600 BAUD) */ +#define WR4_BAUD48 0x80 /* Clock Rate (4800 BAUD) */ +#define WR4_BAUD24 0xc0 /* Clock Rate (2400 BAUD) */ + +#define WR5_TXCRC 0x01 /* Tx CRC Check */ +#define WR5_RTS 0x02 /* Request To Send [RTS] */ +#define WR5_TXENBL 0x08 /* Transmit Enable */ +#define WR5_BREAK 0x10 /* Send Break [BRK] */ +#define WR5_TX5BIT 0x00 /* Tx Bits/Character: 5 Bits */ +#define WR5_TX7BIT 0x20 /* Tx Bits/Character: 7 Bits */ +#define WR5_TX6BIT 0x40 /* Tx Bits/Character: 6 Bits */ +#define WR5_TX8BIT 0x60 /* Tx Bits/Character: 8 Bits */ +#define WR5_DTR 0x80 /* Data Terminal Ready [DTR] */ + +#define RR0_RXAVAIL 0x01 /* Rx Character Available */ +#define RR0_INTRPEND 0x02 /* Interrupt Pending (Channel-A Only) */ +#define RR0_TXEMPTY 0x04 /* Tx Buffer Empty */ +#define RR0_DCD 0x08 /* Data Carrier Detect [DCD] */ +#define RR0_SYNC 0x10 /* Synchronization */ +#define RR0_CTS 0x20 /* Clear To Send [CTS] */ +#define RR0_BREAK 0x80 /* Break Detected [BRK] */ + +#define RR1_PARITY 0x10 /* Parity Error */ +#define RR1_OVERRUN 0x20 /* Data Over Run */ +#define RR1_FRAMING 0x40 /* Framing Error */ + +#define RR_RXRDY 0x0100 /* Rx Character Available */ +#define RR_INTRPEND 0x0200 /* Interrupt Pending (Channel-A Only) */ +#define RR_TXRDY 0x0400 /* Tx Buffer Empty */ +#define RR_DCD 0x0800 /* Data Carrier Detect [DCD] */ +#define RR_SYNC 0x1000 /* Synchronization */ +#define RR_CTS 0x2000 /* Clear To Send [CTS] */ +#define RR_BREAK 0x8000 /* Break Detected */ +#define RR_PARITY 0x0010 /* Parity Error */ +#define RR_OVERRUN 0x0020 /* Data Over Run */ +#define RR_FRAMING 0x0040 /* Framing Error */ diff --git a/sys/arch/luna68k/dev/siotty.c b/sys/arch/luna68k/dev/siotty.c new file mode 100644 index 00000000000..ff7bfc3eda3 --- /dev/null +++ b/sys/arch/luna68k/dev/siotty.c @@ -0,0 +1,623 @@ +/* $NetBSD: siotty.c,v 1.1 2000/01/05 08:48:55 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: siotty.c,v 1.1 2000/01/05 08:48:55 nisimura Exp $"); + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/conf.h> +#include <sys/ioctl.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/tty.h> +#include <sys/uio.h> +#include <sys/callout.h> +#include <sys/fcntl.h> +#include <dev/cons.h> + +#include <machine/cpu.h> + +#include <luna68k/dev/sioreg.h> +#include <luna68k/dev/siovar.h> + +#define TIOCM_BREAK 01000 /* non standard use */ + +static const u_int8_t ch0_regs[6] = { + WR0_RSTINT, /* reset E/S interrupt */ + WR1_RXALLS | WR1_TXENBL, /* Rx per char, Tx */ + 0, /* */ + WR3_RX8BIT | WR3_RXENBL, /* Rx */ + WR4_BAUD96 | WR4_STOP1, /* Tx/Rx */ + WR5_TX8BIT | WR5_TXENBL | WR5_DTR | WR5_RTS, /* Tx */ +}; + +static struct speedtab siospeedtab[] = { + { 2400, WR4_BAUD24, }, + { 4800, WR4_BAUD48, }, + { 9600, WR4_BAUD96, }, + { -1, 0, }, +}; + +struct siotty_softc { + struct device sc_dev; + struct tty *sc_tty; + struct sioreg *sc_ctl; + u_int sc_flags; + u_int8_t sc_wr[6]; +}; + +#include "siotty.h" +cdev_decl(sio); +static void siostart __P((struct tty *)); +static int sioparam __P((struct tty *, struct termios *)); +static void siottyintr __P((int)); +static int siomctl __P((struct siotty_softc *, int, int)); + +static int siotty_match __P((struct device *, struct cfdata *, void *)); +static void siotty_attach __P((struct device *, struct device *, void *)); + +const struct cfattach siotty_ca = { + sizeof(struct siotty_softc), siotty_match, siotty_attach +}; +extern struct cfdriver siotty_cd; + +static int +siotty_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct sio_attach_args *args = aux; + + if (args->channel != 0) /* XXX allow tty on Ch.B XXX */ + return 0; + return 1; +} + +static void +siotty_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct sio_softc *scp = (void *)parent; + struct siotty_softc *sc = (void *)self; + struct sio_attach_args *args = aux; + + sc->sc_ctl = (struct sioreg *)scp->scp_ctl + args->channel; + bcopy(ch0_regs, sc->sc_wr, sizeof(ch0_regs)); + scp->scp_intr[args->channel] = siottyintr; + + if (args->hwflags == 1) { + printf(" (console)"); + sc->sc_flags = TIOCFLAG_SOFTCAR; + } + else { + setsioreg(sc->sc_ctl, WR0, WR0_CHANRST); + setsioreg(sc->sc_ctl, WR2A, WR2_VEC86 | WR2_INTR_1); + setsioreg(sc->sc_ctl, WR2B, 0); + setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); + setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]); + setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]); + setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]); + setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]); + } + setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]); /* now interrupt driven */ + + printf("\n"); +} + +/*-------------------- low level routine --------------------*/ + +static void +siottyintr(chan) + int chan; +{ + struct siotty_softc *sc; + struct sioreg *sio; + struct tty *tp; + unsigned int code; + int rr; + + if (chan >= siotty_cd.cd_ndevs) + return; + sc = siotty_cd.cd_devs[chan]; + tp = sc->sc_tty; + sio = sc->sc_ctl; + rr = getsiocsr(sio); +#if defined(DDB) + if ((rr && RR_BREAK) && tp != NULL && tp->t_dev == cn_tab->cn_dev) + cpu_Debugger(); + else +#endif + if (rr & RR_RXRDY) { + do { + code = sio->sio_data; + if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) { + sio->sio_cmd = WR0_ERRRST; + if (sio->sio_stat & RR_FRAMING) + code |= TTY_FE; + else if (sio->sio_stat & RR_PARITY) + code |= TTY_PE; + } + if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0) + continue; + (*linesw[tp->t_line].l_rint)(code, tp); + } while ((rr = getsiocsr(sio)) & RR_RXRDY); + } + if (rr & RR_TXRDY) { + sio->sio_cmd = WR0_RSTPEND; + if (tp != NULL) { + tp->t_state &= ~(TS_BUSY|TS_FLUSH); + if (tp->t_line) + (*linesw[tp->t_line].l_start)(tp); + else + siostart(tp); + } + } +} + +static void +siostart(tp) + struct tty *tp; +{ + struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)]; + int s, c; + + s = spltty(); + if (tp->t_state & (TS_BUSY|TS_TIMEOUT|TS_TTSTOP)) + goto out; + 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); + } + if (tp->t_outq.c_cc == 0) + goto out; + + tp->t_state |= TS_BUSY; + while (getsiocsr(sc->sc_ctl) & RR_TXRDY) { + if ((c = getc(&tp->t_outq)) == -1) + break; + sc->sc_ctl->sio_data = c; + } +out: + splx(s); +} + +void +siostop(tp, flag) + struct tty *tp; + int flag; +{ + int s; + + s = spltty(); + if (TS_BUSY == (tp->t_state & (TS_BUSY|TS_TTSTOP))) { + /* + * Device is transmitting; must stop it. + */ + tp->t_state |= TS_FLUSH; + } + splx(s); +} + +static int +sioparam(tp, t) + struct tty *tp; + struct termios *t; +{ + struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)]; + int wr4, s; + + if (t->c_ispeed && t->c_ispeed != t->c_ospeed) + return EINVAL; + wr4 = ttspeedtab(t->c_ospeed, siospeedtab); + if (wr4 < 0) + return EINVAL; + + if (sc->sc_flags & TIOCFLAG_SOFTCAR) { + t->c_cflag |= CLOCAL; + t->c_cflag &= ~HUPCL; + } + if (sc->sc_flags & TIOCFLAG_CLOCAL) + t->c_cflag |= CLOCAL; + + /* + * If there were no changes, don't do anything. This avoids dropping + * input and improves performance when all we did was frob things like + * VMIN and VTIME. + */ + if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag) + return 0; + + tp->t_ispeed = t->c_ispeed; + tp->t_ospeed = t->c_ospeed; + tp->t_cflag = t->c_cflag; + + sc->sc_wr[WR3] &= 0x3f; + sc->sc_wr[WR5] &= 0x9f; + switch (tp->t_cflag & CSIZE) { + case CS7: + sc->sc_wr[WR3] |= WR3_RX7BIT; sc->sc_wr[WR5] |= WR5_TX7BIT; + break; + case CS8: + sc->sc_wr[WR3] |= WR3_RX8BIT; sc->sc_wr[WR5] |= WR5_TX8BIT; + break; + } + if (tp->t_cflag & PARENB) { + wr4 |= WR4_PARENAB; + if ((tp->t_cflag & PARODD) == 0) + wr4 |= WR4_EPARITY; + } + wr4 |= (tp->t_cflag & CSTOPB) ? WR4_STOP2 : WR4_STOP1; + sc->sc_wr[WR4] = wr4; + + s = spltty(); + setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]); + setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]); + setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]); + splx(s); + + return 0; +} + +static int +siomctl(sc, control, op) + struct siotty_softc *sc; + int control, op; +{ + int val, s, wr5, rr; + + val = 0; + if (control & TIOCM_BREAK) + val |= WR5_BREAK; + if (control & TIOCM_DTR) + val |= WR5_DTR; + if (control & TIOCM_RTS) + val |= WR5_RTS; + s = spltty(); + wr5 = sc->sc_wr[WR5]; + switch (op) { + case DMSET: + wr5 &= ~(WR5_BREAK|WR5_DTR|WR5_RTS); + /* FALLTHRU */ + case DMBIS: + wr5 |= val; + break; + case DMBIC: + wr5 &= ~val; + break; + case DMGET: + val = 0; + rr = getsiocsr(sc->sc_ctl); + if (wr5 & WR5_DTR) + val |= TIOCM_DTR; + if (wr5 & WR5_RTS) + val |= TIOCM_RTS; + if (rr & RR_CTS) + val |= TIOCM_CTS; + if (rr & RR_DCD) + val |= TIOCM_CD; + goto done; + } + sc->sc_wr[WR5] = wr5; + setsioreg(sc->sc_ctl, WR5, wr5); + val = 0; + done: + splx(s); + return val; +} + +/*-------------------- cdevsw[] interface --------------------*/ + +int +sioopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + struct siotty_softc *sc; + struct tty *tp; + int error; + + if ((sc = siotty_cd.cd_devs[minor(dev)]) == NULL) + return ENXIO; + if ((tp = sc->sc_tty) == NULL) { + tp = sc->sc_tty = ttymalloc(); + tty_attach(tp); + } + else if ((tp->t_state & TS_ISOPEN) && (tp->t_state & TS_XCLUDE) + && p->p_ucred->cr_uid != 0) + return EBUSY; + + tp->t_oproc = siostart; + tp->t_param = sioparam; + tp->t_hwiflow = NULL /* XXX siohwiflow XXX */; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) { + struct termios t; + + t.c_ispeed = t.c_ospeed = TTYDEF_SPEED; + t.c_cflag = TTYDEF_CFLAG; + tp->t_ospeed = 0; /* force register update */ + (void)sioparam(tp, &t); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_lflag = TTYDEF_LFLAG; + ttychars(tp); + ttsetwater(tp); + /* raise RTS and DTR here; but, DTR lead is not wired */ + /* then check DCD condition; but, DCD lead is not wired */ + tp->t_state |= TS_CARR_ON; /* assume detected all the time */ +#if 0 + if ((sc->sc_flags & TIOCFLAG_SOFTCAR) + || (tp->t_cflag & MDMBUF) + || (getsiocsr(sc->sc_ctl) & RR_DCD)) + tp->t_state |= TS_CARR_ON; + else + tp->t_state &= ~TS_CARR_ON; +#endif + } + + error = ttyopen(tp, 0, (flag & O_NONBLOCK)); + if (error > 0) + return error; + return (*linesw[tp->t_line].l_open)(dev, tp); +} + +int +sioclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)]; + struct tty *tp = sc->sc_tty; + int s; + + (*linesw[tp->t_line].l_close)(tp, flag); + + s = spltty(); + siomctl(sc, TIOCM_BREAK, DMBIC); +#if 0 /* because unable to feed DTR signal */ + if ((tp->t_cflag & HUPCL) + || tp->t_wopen || (tp->t_state & TS_ISOPEN) == 0) { + siomctl(sc, TIOCM_DTR, DMBIC); + /* Yield CPU time to others for 1 second, then ... */ + siomctl(sc, TIOCM_DTR, DMBIS); + } +#endif + splx(s); + return ttyclose(tp); +} + +int +sioread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)]; + struct tty *tp = sc->sc_tty; + + return (*linesw[tp->t_line].l_read)(tp, uio, flag); +} + +int +siowrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)]; + struct tty *tp = sc->sc_tty; + + return (*linesw[tp->t_line].l_write)(tp, uio, flag); +} + +int +sioioctl(dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)]; + struct tty *tp = sc->sc_tty; + int error; + + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return error; + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return error; + + /* the last resort for TIOC ioctl tranversing */ + switch (cmd) { + case TIOCSBRK: /* Set the hardware into BREAK condition */ + siomctl(sc, TIOCM_BREAK, DMBIS); + break; + case TIOCCBRK: /* Clear the hardware BREAK condition */ + siomctl(sc, TIOCM_BREAK, DMBIC); + break; + case TIOCSDTR: /* Assert DTR signal */ + siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIS); + break; + case TIOCCDTR: /* Clear DTR signal */ + siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIC); + break; + case TIOCMSET: /* Set modem state replacing current one */ + siomctl(sc, *(int *)data, DMSET); + break; + case TIOCMGET: /* Return current modem state */ + *(int *)data = siomctl(sc, 0, DMGET); + break; + case TIOCMBIS: /* Set individual bits of modem state */ + siomctl(sc, *(int *)data, DMBIS); + break; + case TIOCMBIC: /* Clear individual bits of modem state */ + siomctl(sc, *(int *)data, DMBIC); + break; + case TIOCSFLAGS: /* Instruct how serial port behaves */ + sc->sc_flags = *(int *)data; + break; + case TIOCGFLAGS: /* Return current serial port state */ + *(int *)data = sc->sc_flags; + break; + default: + return ENOTTY; + } + return 0; +} + +/* ARSGUSED */ +struct tty * +siotty(dev) + dev_t dev; +{ + struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)]; + + return sc->sc_tty; +} + +/*-------------------- miscelleneous routine --------------------*/ + +/* EXPORT */ void +setsioreg(sio, regno, val) + struct sioreg *sio; + int regno, val; +{ + if (regno != 0) + sio->sio_cmd = regno; /* DELAY(); */ + sio->sio_cmd = val; /* DELAY(); */ +} + +/* EXPORT */ int +getsiocsr(sio) + struct sioreg *sio; +{ + int val; + + val = sio->sio_stat << 8; /* DELAY(); */ + sio->sio_cmd = 1; /* DELAY(); */ + val |= sio->sio_stat; /* DELAY(); */ + return val; +} + +/*--------------------- console interface ----------------------*/ + +void syscnattach __P((int)); +int syscngetc __P((dev_t)); +void syscnputc __P((dev_t, int)); + +struct consdev syscons = { + NULL, + NULL, + syscngetc, + syscnputc, + nullcnpollc, + NODEV, + CN_REMOTE, +}; + +/* EXPORT */ void +syscnattach(channel) + int channel; +{ +/* + * Channel A is immediately initialized with 9600N1 right after cold + * boot/reset/poweron. ROM monitor emits one line message on CH.A. + */ + struct sioreg *sio; + sio = (struct sioreg *)0x51000000 + channel; + + syscons.cn_dev = makedev(7, channel); + cn_tab = &syscons; + + setsioreg(sio, WR0, WR0_CHANRST); + setsioreg(sio, WR2A, WR2_VEC86 | WR2_INTR_1); + setsioreg(sio, WR2B, 0); + setsioreg(sio, WR0, ch0_regs[WR0]); + setsioreg(sio, WR4, ch0_regs[WR4]); + setsioreg(sio, WR3, ch0_regs[WR3]); + setsioreg(sio, WR5, ch0_regs[WR5]); + setsioreg(sio, WR0, ch0_regs[WR0]); +} + +/* EXPORT */ int +syscngetc(dev) + dev_t dev; +{ + struct sioreg *sio; + int s, c; + + sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1); + s = splhigh(); + while ((getsiocsr(sio) & RR_RXRDY) == 0) + ; + c = sio->sio_data; + splx(s); + + return c; +} + +/* EXPORT */ void +syscnputc(dev, c) + dev_t dev; + int c; +{ + struct sioreg *sio; + int s; + + sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1); + s = splhigh(); + while ((getsiocsr(sio) & RR_TXRDY) == 0) + ; + sio->sio_cmd = WR0_RSTPEND; + sio->sio_data = c; + splx(s); +} diff --git a/sys/arch/luna68k/dev/siovar.h b/sys/arch/luna68k/dev/siovar.h new file mode 100644 index 00000000000..b7e94598423 --- /dev/null +++ b/sys/arch/luna68k/dev/siovar.h @@ -0,0 +1,59 @@ +/* $NetBSD: siovar.h,v 1.1 2000/01/05 08:48:55 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +struct sio_softc { + struct device scp_dev; + caddr_t scp_ctl; + void (*scp_intr[2]) __P((int)); +}; + +struct sio_attach_args { + int channel; + int hwflags; +}; + +struct sioreg { + volatile u_int8_t sio_data; + unsigned : 8; + volatile u_int8_t sio_cmd; + unsigned : 8; +#define sio_stat sio_cmd +}; + +int getsiocsr __P((struct sioreg *)); +void setsioreg __P((struct sioreg *, int, int)); diff --git a/sys/arch/luna68k/dev/spc.c b/sys/arch/luna68k/dev/spc.c new file mode 100644 index 00000000000..92fff867ee0 --- /dev/null +++ b/sys/arch/luna68k/dev/spc.c @@ -0,0 +1,104 @@ +/* $NetBSD: spc.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: spc.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/bus.h> +#include <machine/cpu.h> +#include <machine/autoconf.h> + +#include <dev/scsipi/scsi_all.h> +#include <dev/scsipi/scsipi_all.h> +#include <dev/scsipi/scsi_message.h> +#include <dev/scsipi/scsiconf.h> + +#include <dev/ic/mb89352reg.h> +#include <dev/ic/mb89352var.h> + +#include <luna68k/luna68k/isr.h> + +static int spc_match __P((struct device *, struct cfdata *, void *)); +static void spc_attach __P((struct device *, struct device *, void *)); + +const struct cfattach spc_ca = { + sizeof(struct spc_softc), spc_match, spc_attach +}; +extern struct cfdriver spc_cd; + +static int +spc_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct mainbus_attach_args *ma = aux; + + if (strcmp(ma->ma_name, spc_cd.cd_name)) + return 0; +#if 0 + if (badaddr((caddr_t)ma->ma_addr, 4)) + return 0; + /* Experiments proved 2nd SPC address does NOT make a buserror. */ +#endif + return 1; +} + +static void +spc_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct spc_softc *sc = (void *)self; + struct mainbus_attach_args *ma = aux; + + printf ("\n"); + + sc->sc_iot = /* XXX */ 0; + sc->sc_ioh = ma->ma_addr; + sc->sc_initiator = 7; + + isrlink_autovec(spcintr, (void *)sc, ma->ma_ilvl, ISRPRI_BIO); + + spcattach(sc); +} diff --git a/sys/arch/luna68k/dev/timekeeper.c b/sys/arch/luna68k/dev/timekeeper.c new file mode 100644 index 00000000000..735ee347152 --- /dev/null +++ b/sys/arch/luna68k/dev/timekeeper.c @@ -0,0 +1,248 @@ +/* $NetBSD: timekeeper.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: timekeeper.c,v 1.1 2000/01/05 08:48:56 nisimura Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> + +#include <machine/cpu.h> + +#include <dev/clock_subr.h> +#include <luna68k/luna68k/clockvar.h> +#include <luna68k/dev/timekeeper.h> +#include <machine/autoconf.h> + +#define YEAR0 1970 /* year offset */ + +struct timekeeper_softc { + struct device sc_dev; + void *sc_clock, *sc_nvram; + int sc_nvramsize; + u_int8_t sc_image[2040]; +}; + +/* + * BCD to decimal and decimal to BCD. + */ +#define FROMBCD(x) (((x) >> 4) * 10 + ((x) & 0xf)) +#define TOBCD(x) (((x) / 10 * 16) + ((x) % 10)) + +static int clock_match __P((struct device *, struct cfdata *, void *)); +static void clock_attach __P((struct device *, struct device *, void *)); + +const struct cfattach clock_ca = { + sizeof (struct timekeeper_softc), clock_match, clock_attach +}; +extern struct cfdriver clock_cd; + +static void mkclock_get __P((struct device *, time_t, struct clock_ymdhms *)); +static void mkclock_set __P((struct device *, struct clock_ymdhms *)); +static void dsclock_get __P((struct device *, time_t, struct clock_ymdhms *)); +static void dsclock_set __P((struct device *, struct clock_ymdhms *)); + +static struct clockfns mkclock_clockfns = { + NULL /* never used */, mkclock_get, mkclock_set, +}; + +static struct clockfns dsclock_clockfns = { + NULL /* never used */, dsclock_get, dsclock_set, +}; + +static int +clock_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + struct mainbus_attach_args *ma = aux; + + if (strcmp(ma->ma_name, clock_cd.cd_name)) + return 0; + return 1; +} + +static void +clock_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct timekeeper_softc *sc = (void *)self; + struct mainbus_attach_args *ma = aux; + struct clockfns *clockwork; + + switch (machtype) { + default: + case LUNA_I: /* Mostek MK48T02 */ + sc->sc_clock = (void *)(ma->ma_addr + 2040); + sc->sc_nvram = (void *)ma->ma_addr; + sc->sc_nvramsize = 2040; + clockwork = &mkclock_clockfns; + printf(": mk48t02\n"); + break; + case LUNA_II: /* Dallas DS1287A */ + sc->sc_clock = (void *)ma->ma_addr; + sc->sc_nvram = (void *)(ma->ma_addr + 50); + sc->sc_nvramsize = 50; + clockwork = &dsclock_clockfns; + printf(": ds1287a\n"); + break; + } + clockattach(&sc->sc_dev, clockwork); + memcpy(sc->sc_image, sc->sc_nvram, sc->sc_nvramsize); +} + +/* + * Get the time of day, based on the clock's value and/or the base value. + */ +static void +mkclock_get(dev, base, dt) + struct device *dev; + time_t base; + struct clock_ymdhms *dt; +{ + struct timekeeper_softc *sc = (void *)dev; + volatile u_int8_t *chiptime = (void *)sc->sc_clock; + int s; + + s = splclock(); + chiptime[MK_CSR] |= MK_CSR_READ; /* enable read (stop time) */ + dt->dt_sec = FROMBCD(chiptime[MK_SEC]); + dt->dt_min = FROMBCD(chiptime[MK_MIN]); + dt->dt_hour = FROMBCD(chiptime[MK_HOUR]); + dt->dt_wday = FROMBCD(chiptime[MK_DOW]); + dt->dt_day = FROMBCD(chiptime[MK_DOM]); + dt->dt_mon = FROMBCD(chiptime[MK_MONTH]); + dt->dt_year = FROMBCD(chiptime[MK_YEAR]) + YEAR0; + chiptime[MK_CSR] &= ~MK_CSR_READ; /* time wears on */ + splx(s); +#ifdef TIMEKEEPER_DEBUG + printf("get %d/%d/%d %d:%d:%d\n", + dt->dt_year, dt->dt_mon, dt->dt_day, + dt->dt_hour, dt->dt_min, dt->dt_sec); +#endif +} + +/* + * Reset the TODR based on the time value. + */ +static void +mkclock_set(dev, dt) + struct device *dev; + struct clock_ymdhms *dt; +{ + struct timekeeper_softc *sc = (void *)dev; + volatile u_int8_t *chiptime = (void *)sc->sc_clock; + volatile u_int8_t *stamp = (u_int8_t *)sc->sc_nvram + 0x10; + int s; + + s = splclock(); + chiptime[MK_CSR] |= MK_CSR_WRITE; /* enable write */ + chiptime[MK_SEC] = TOBCD(dt->dt_sec); + chiptime[MK_MIN] = TOBCD(dt->dt_min); + chiptime[MK_HOUR] = TOBCD(dt->dt_hour); + chiptime[MK_DOW] = TOBCD(dt->dt_wday); + chiptime[MK_DOM] = TOBCD(dt->dt_day); + chiptime[MK_MONTH] = TOBCD(dt->dt_mon); + chiptime[MK_YEAR] = TOBCD(dt->dt_year - YEAR0); + chiptime[MK_CSR] &= ~MK_CSR_WRITE; /* load them up */ + splx(s); +#ifdef TIMEKEEPER_DEBUG + printf("set %d/%d/%d %d:%d:%d\n", + dt->dt_year, dt->dt_mon, dt->dt_day, + dt->dt_hour, dt->dt_min, dt->dt_sec); +#endif + + stamp[0] = 'R'; stamp[1] = 'T'; stamp[2] = 'C'; stamp[3] = '\0'; +} + +/* + * Get the time of day, based on the clock's value and/or the base value. + */ +static void +dsclock_get(dev, base, dt) + struct device *dev; + time_t base; + struct clock_ymdhms *dt; +{ + struct timekeeper_softc *sc = (void *)dev; + volatile u_int8_t *chiptime = (void *)sc->sc_clock; + int s; + + s = splclock(); + /* update in progress; spin loop */ + while (chiptime[MC_REGA] & MC_REGA_UIP) + ; + dt->dt_sec = chiptime[MC_SEC]; + dt->dt_min = chiptime[MC_MIN]; + dt->dt_hour = chiptime[MC_HOUR]; + dt->dt_wday = chiptime[MC_DOW]; + dt->dt_day = chiptime[MC_DOM]; + dt->dt_mon = chiptime[MC_MONTH]; + dt->dt_year = chiptime[MC_YEAR] + YEAR0; + splx(s); +} + +/* + * Reset the TODR based on the time value. + */ +static void +dsclock_set(dev, dt) + struct device *dev; + struct clock_ymdhms *dt; +{ + struct timekeeper_softc *sc = (void *)dev; + volatile u_int8_t *chiptime = (void *)sc->sc_clock; + int s; + + s = splclock(); + chiptime[MC_REGB] |= MC_REGB_SET; /* enable write */ + chiptime[MC_SEC] = dt->dt_sec; + chiptime[MC_MIN] = dt->dt_min; + chiptime[MC_HOUR] = dt->dt_hour; + chiptime[MC_DOW] = dt->dt_wday; + chiptime[MC_DOM] = dt->dt_day; + chiptime[MC_MONTH] = dt->dt_mon; + chiptime[MC_YEAR] = dt->dt_year - YEAR0; + chiptime[MC_REGB] &= ~MC_REGB_SET; /* load them up */ + splx(s); +} diff --git a/sys/arch/luna68k/dev/timekeeper.h b/sys/arch/luna68k/dev/timekeeper.h new file mode 100644 index 00000000000..7c4f92ea55d --- /dev/null +++ b/sys/arch/luna68k/dev/timekeeper.h @@ -0,0 +1,95 @@ +/* $NetBSD: timekeeper.h,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Mostek MK48T02 for LUNA-1 + */ +#define MK_CSR 0 /* control register */ +#define MK_SEC 1 /* seconds (0..59; BCD) */ +#define MK_MIN 2 /* minutes (0..59; BCD) */ +#define MK_HOUR 3 /* hour (0..23; BCD) */ +#define MK_DOW 4 /* weekday (1..7) */ +#define MK_DOM 5 /* day in month (1..31; BCD) */ +#define MK_MONTH 6 /* month (1..12; BCD) */ +#define MK_YEAR 7 /* year (0..99; BCD) */ +/* bits in cl_csr */ +#define MK_CSR_WRITE 0x80 /* want to write */ +#define MK_CSR_READ 0x40 /* want to read (freeze clock) */ + +/* + * Dallas Semiconductor DS1287 -- mc146818 compatible, for LUNA-2 + */ +#define MC_SEC 0x0 /* Time of year: seconds (0-59) */ +#define MC_ASEC 0x1 /* Alarm: seconds */ +#define MC_MIN 0x2 /* Time of year: minutes (0-59) */ +#define MC_AMIN 0x3 /* Alarm: minutes */ +#define MC_HOUR 0x4 /* Time of year: hour (see above) */ +#define MC_AHOUR 0x5 /* Alarm: hour */ +#define MC_DOW 0x6 /* Time of year: day of week (1-7) */ +#define MC_DOM 0x7 /* Time of year: day of month (1-31) */ +#define MC_MONTH 0x8 /* Time of year: month (1-12) */ +#define MC_YEAR 0x9 /* Time of year: year in century (0-99) */ + +#define MC_REGA 0xa /* Control register A */ +#define MC_REGA_RSMASK 0x0f /* Interrupt rate select mask (see below) */ +#define MC_REGA_DVMASK 0x70 /* Divisor select mask (see below) */ +#define MC_REGA_UIP 0x80 /* Update in progress; read only. */ + +#define MC_REGB 0xb /* Control register B */ +#define MC_REGB_DSE 0x01 /* Daylight Savings Enable */ +#define MC_REGB_24HR 0x02 /* 24-hour mode (AM/PM mode when clear) */ +#define MC_REGB_BINARY 0x04 /* Binary mode (BCD mode when clear) */ +#define MC_REGB_SQWE 0x08 /* Square Wave Enable */ +#define MC_REGB_UIE 0x10 /* Update End interrupt enable */ +#define MC_REGB_AIE 0x20 /* Alarm interrupt enable */ +#define MC_REGB_PIE 0x40 /* Periodic interrupt enable */ +#define MC_REGB_SET 0x80 /* Allow time to be set; stops updates */ + +#define MC_REGC 0xc /* Control register C */ +/* MC_REGC_UNUSED 0x0f UNUSED */ +#define MC_REGC_UF 0x10 /* Update End interrupt flag */ +#define MC_REGC_AF 0x20 /* Alarm interrupt flag */ +#define MC_REGC_PF 0x40 /* Periodic interrupt flag */ +#define MC_REGC_IRQF 0x80 /* Interrupt request pending flag */ + +#define MC_REGD 0xd /* Control register D */ +/* MC_REGD_UNUSED 0x7f UNUSED */ +#define MC_REGD_VRT 0x80 /* Valid RAM and Time bit */ + +#define MC_NREGS 0xe /* 14 registers; CMOS follows */ +#define MC_NTODREGS 0xa /* 10 of those regs are for TOD and alarm */ diff --git a/sys/arch/luna68k/include/Makefile b/sys/arch/luna68k/include/Makefile new file mode 100644 index 00000000000..0e4791a5f68 --- /dev/null +++ b/sys/arch/luna68k/include/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 2000/01/05 08:49:01 nisimura Exp $ + +KDIR= /sys/arch/luna68k/include +INCSDIR= /usr/include/luna68k + +INCS= ansi.h aout_machdep.h asm.h autoconf.h bswap.h bus.h cdefs.h \ + cpu.h db_machdep.h disklabel.h endian.h float.h frame.h ieee.h \ + ieeefp.h intr.h kcore.h limits.h math.h param.h pcb.h pmap.h \ + proc.h profile.h psl.h pte.h ptrace.h reg.h setjmp.h signal.h \ + stdarg.h trap.h types.h varargs.h vmparam.h + +.include <bsd.kinc.mk> diff --git a/sys/arch/luna68k/include/ansi.h b/sys/arch/luna68k/include/ansi.h new file mode 100644 index 00000000000..c162fe306b9 --- /dev/null +++ b/sys/arch/luna68k/include/ansi.h @@ -0,0 +1,4 @@ +/* $NetBSD: ansi.h,v 1.1 2000/01/05 08:48:56 nisimura Exp $ */ + +/* Just use the common m68k definition */ +#include <m68k/ansi.h> diff --git a/sys/arch/luna68k/include/aout_machdep.h b/sys/arch/luna68k/include/aout_machdep.h new file mode 100644 index 00000000000..bb3732de756 --- /dev/null +++ b/sys/arch/luna68k/include/aout_machdep.h @@ -0,0 +1,8 @@ +/* $NetBSD: aout_machdep.h,v 1.1 2000/01/05 08:49:00 nisimura Exp $ */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#include <m68k/aout_machdep.h> + +#endif /* _MACHINE_EXEC_H_ */ diff --git a/sys/arch/luna68k/include/asm.h b/sys/arch/luna68k/include/asm.h new file mode 100644 index 00000000000..054bd72b381 --- /dev/null +++ b/sys/arch/luna68k/include/asm.h @@ -0,0 +1,3 @@ +/* $NetBSD: asm.h,v 1.1 2000/01/05 08:48:57 nisimura Exp $ */ + +#include <m68k/asm.h> diff --git a/sys/arch/luna68k/include/autoconf.h b/sys/arch/luna68k/include/autoconf.h new file mode 100644 index 00000000000..98847fe8ab6 --- /dev/null +++ b/sys/arch/luna68k/include/autoconf.h @@ -0,0 +1,43 @@ +/* $Id: autoconf.h,v 1.1 2000/01/05 08:49:01 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +struct mainbus_attach_args { + const char *ma_name; + paddr_t ma_addr; + int ma_ilvl; +}; diff --git a/sys/arch/luna68k/include/bswap.h b/sys/arch/luna68k/include/bswap.h new file mode 100644 index 00000000000..badc9b5d265 --- /dev/null +++ b/sys/arch/luna68k/include/bswap.h @@ -0,0 +1,3 @@ +/* $NetBSD: bswap.h,v 1.1 2000/01/05 08:49:00 nisimura Exp $ */ + +#include <m68k/bswap.h> diff --git a/sys/arch/luna68k/include/bus.h b/sys/arch/luna68k/include/bus.h new file mode 100644 index 00000000000..522353fa249 --- /dev/null +++ b/sys/arch/luna68k/include/bus.h @@ -0,0 +1,604 @@ +/* $NetBSD: bus.h,v 1.1 2000/01/05 08:49:01 nisimura Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (C) 1997 Scott Reynolds. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce 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_BUS_H_ +#define _MACHINE_BUS_H_ + +/* + * Value for the luna68k bus space tag, not to be used directly by MI code. + */ +#define MACHINE_BUS_SPACE_MEM 0 /* space is mem space */ + +/* + * Bus address and size types + */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* + * Access methods for bus resources and address space. + */ +typedef int bus_space_tag_t; +typedef u_long bus_space_handle_t; + +/* + * int bus_space_map __P((bus_space_tag_t t, bus_addr_t addr, + * bus_size_t size, int flags, bus_space_handle_t *bshp)); + * + * Map a region of bus space. + */ + +#define BUS_SPACE_MAP_CACHEABLE 0x01 +#define BUS_SPACE_MAP_LINEAR 0x02 + +int bus_space_map __P((bus_space_tag_t, bus_addr_t, bus_size_t, + int, bus_space_handle_t *)); + +/* + * void bus_space_unmap __P((bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t size)); + * + * Unmap a region of bus space. + */ + +void bus_space_unmap __P((bus_space_tag_t, bus_space_handle_t, bus_size_t)); + +/* + * int bus_space_subregion __P((bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, + * bus_space_handle_t *nbshp)); + * + * Get a new handle for a subregion of an already-mapped area of bus space. + */ + +int bus_space_subregion __P((bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)); + +/* + * int bus_space_alloc __P((bus_space_tag_t t, bus_addr_t, rstart, + * bus_addr_t rend, bus_size_t size, bus_size_t align, + * bus_size_t boundary, int flags, bus_addr_t *addrp, + * bus_space_handle_t *bshp)); + * + * Allocate a region of bus space. + */ + +int bus_space_alloc __P((bus_space_tag_t t, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t align, + bus_size_t boundary, int cacheable, bus_addr_t *addrp, + bus_space_handle_t *bshp)); + +/* + * int bus_space_free __P((bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t size)); + * + * Free a region of bus space. + */ + +void bus_space_free __P((bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size)); + +/* + * int mac68k_bus_space_probe __P((bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t offset, int sz)); + * + * Probe the bus at t/bsh/offset, using sz as the size of the load. + * + * This is a machine-dependent extension, and is not to be used by + * machine-independent code. + */ + +int mac68k_bus_space_probe __P((bus_space_tag_t t, + bus_space_handle_t bsh, bus_size_t offset, int sz)); + +/* + * u_intN_t bus_space_read_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset)); + * + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ + +#define bus_space_read_1(t, h, o) \ + ((void) t, (*(volatile u_int8_t *)((h) + (o)))) + +#define bus_space_read_2(t, h, o) \ + ((void) t, (*(volatile u_int16_t *)((h) + (o)))) + +#define bus_space_read_4(t, h, o) \ + ((void) t, (*(volatile u_int32_t *)((h) + (o)))) + +#if 0 /* Cause a link error for bus_space_read_8 */ +#define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!! +#endif + +/* + * void bus_space_read_multi_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count)); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + +#define bus_space_read_multi_1(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movb a0@,a1@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#define bus_space_read_multi_2(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movw a0@,a1@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#define bus_space_read_multi_4(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movl a0@,a1@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#if 0 /* Cause a link error for bus_space_read_multi_8 */ +#define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_read_region_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count)); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ + +#define bus_space_read_region_1(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movb a0@+,a1@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#define bus_space_read_region_2(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movw a0@+,a1@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#define bus_space_read_region_4(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movl a0@+,a1@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#if 0 /* Cause a link error for bus_space_read_region_8 */ +#define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!! +#endif + +/* + * void bus_space_write_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t value)); + * + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ + +#define bus_space_write_1(t, h, o, v) \ + ((void) t, ((void)(*(volatile u_int8_t *)((h) + (o)) = (v)))) + +#define bus_space_write_2(t, h, o, v) \ + ((void) t, ((void)(*(volatile u_int16_t *)((h) + (o)) = (v)))) + +#define bus_space_write_4(t, h, o, v) \ + ((void) t, ((void)(*(volatile u_int32_t *)((h) + (o)) = (v)))) + +#if 0 /* Cause a link error for bus_space_write_8 */ +#define bus_space_write_8 !!! bus_space_write_8 not implemented !!! +#endif + +/* + * void bus_space_write_multi_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count)); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + +#define bus_space_write_multi_1(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movb a1@+,a0@ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#define bus_space_write_multi_2(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movw a1@+,a0@ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#define bus_space_write_multi_4(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movl a1@+,a0@ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#if 0 /* Cause a link error for bus_space_write_8 */ +#define bus_space_write_multi_8(t, h, o, a, c) \ + !!! bus_space_write_multi_8 unimplimented !!! +#endif + +/* + * void bus_space_write_region_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count)); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + +#define bus_space_write_region_1(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movb a1@+,a0@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#define bus_space_write_region_2(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movw a1@+,a0@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#define bus_space_write_region_4(t, h, o, a, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,a1 ; \ + movl %2,d0 ; \ + 1: movl a1@+,a0@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h) + (o)), "g" (a), "g" ((size_t)(c)) : \ + "a0","a1","d0"); \ +} while (0) + +#if 0 /* Cause a link error for bus_space_write_region_8 */ +#define bus_space_write_region_8 \ + !!! bus_space_write_region_8 unimplemented !!! +#endif + +/* + * void bus_space_set_multi_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count)); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ + +#define bus_space_set_multi_1(t, h, o, val, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,d1 ; \ + movl %2,d0 ; \ + 1: movb d1,a0@ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h)+(o)), "g" ((u_long)val), \ + "g" ((size_t)(c)) : \ + "a0","d0","d1"); \ +} while (0) + +#define bus_space_set_multi_2(t, h, o, val, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,d1 ; \ + movl %2,d0 ; \ + 1: movw d1,a0@ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h)+(o)), "g" ((u_long)val), \ + "g" ((size_t)(c)) : \ + "a0","d0","d1"); \ +} while (0) + +#define bus_space_set_multi_4(t, h, o, val, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,d1 ; \ + movl %2,d0 ; \ + 1: movl d1,a0@ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h)+(o)), "g" ((u_long)val), \ + "g" ((size_t)(c)) : \ + "a0","d0","d1"); \ +} while (0) + +#if 0 /* Cause a link error for bus_space_set_multi_8 */ +#define bus_space_set_multi_8 \ + !!! bus_space_set_multi_8 unimplemented !!! +#endif + +/* + * void bus_space_set_region_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count)); + * + * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle starting at `offset'. + */ + +#define bus_space_set_region_1(t, h, o, val, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,d1 ; \ + movl %2,d0 ; \ + 1: movb d1,a0@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h)+(o)), "g" ((u_long)val), \ + "g" ((size_t)(c)) : \ + "a0","d0","d1"); \ +} while (0) + +#define bus_space_set_region_2(t, h, o, val, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,d1 ; \ + movl %2,d0 ; \ + 1: movw d1,a0@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h)+(o)), "g" ((u_long)val), \ + "g" ((size_t)(c)) : \ + "a0","d0","d1"); \ +} while (0) + +#define bus_space_set_region_4(t, h, o, val, c) do { \ + (void) t; \ + __asm __volatile (" \ + movl %0,a0 ; \ + movl %1,d1 ; \ + movl %2,d0 ; \ + 1: movl d1,a0@+ ; \ + subql #1,d0 ; \ + jne 1b" : \ + : \ + "r" ((h)+(o)), "g" ((u_long)val), \ + "g" ((size_t)(c)) : \ + "a0","d0","d1"); \ +} while (0) + +#if 0 /* Cause a link error for bus_space_set_region_8 */ +#define bus_space_set_region_8 \ + !!! bus_space_set_region_8 unimplemented !!! +#endif + +/* + * void bus_space_copy_N __P((bus_space_tag_t tag, + * bus_space_handle_t bsh1, bus_size_t off1, + * bus_space_handle_t bsh2, bus_size_t off2, + * size_t count)); + * + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ + +#define __MACHINE_copy_region_N(BYTES) \ +static __inline void __CONCAT(bus_space_copy_region_,BYTES) \ + __P((bus_space_tag_t, \ + bus_space_handle_t bsh1, bus_size_t off1, \ + bus_space_handle_t bsh2, bus_size_t off2, \ + bus_size_t count)); \ + \ +static __inline void \ +__CONCAT(bus_space_copy_region_,BYTES)(t, h1, o1, h2, o2, c) \ + bus_space_tag_t t; \ + bus_space_handle_t h1, h2; \ + bus_size_t o1, o2, c; \ +{ \ + bus_size_t o; \ + \ + if ((h1 + o1) >= (h2 + o2)) { \ + /* src after dest: copy forward */ \ + for (o = 0; c != 0; c--, o += BYTES) \ + __CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o, \ + __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \ + } else { \ + /* dest after src: copy backwards */ \ + for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES) \ + __CONCAT(bus_space_write_,BYTES)(t, h2, o2 + o, \ + __CONCAT(bus_space_read_,BYTES)(t, h1, o1 + o)); \ + } \ +} +__MACHINE_copy_region_N(1) +__MACHINE_copy_region_N(2) +__MACHINE_copy_region_N(4) +#if 0 /* Cause a link error for bus_space_copy_8 */ +#define bus_space_copy_8 \ + !!! bus_space_copy_8 unimplemented !!! +#endif + +#undef __MACHINE_copy_region_N + +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier __P((bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags)); + * + * Note: the 680x0 does not currently require barriers, but we must + * provide the flags to MI code. + */ +#define bus_space_barrier(t, h, o, l, f) \ + ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) + +#endif /* _MACHINE_BUS_H_ */ diff --git a/sys/arch/luna68k/include/cdefs.h b/sys/arch/luna68k/include/cdefs.h new file mode 100644 index 00000000000..abca7f9dc14 --- /dev/null +++ b/sys/arch/luna68k/include/cdefs.h @@ -0,0 +1,8 @@ +/* $NetBSD: cdefs.h,v 1.1 2000/01/05 08:48:59 nisimura Exp $ */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#include <m68k/cdefs.h> + +#endif diff --git a/sys/arch/luna68k/include/cpu.h b/sys/arch/luna68k/include/cpu.h new file mode 100644 index 00000000000..f961418fd4e --- /dev/null +++ b/sys/arch/luna68k/include/cpu.h @@ -0,0 +1,179 @@ +/* $Id: cpu.h,v 1.1 2000/01/05 08:48:57 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: cpu.h 1.16 91/03/25$ + * + * @(#)cpu.h 8.4 (Berkeley) 1/5/94 + */ + +#ifndef _MACHINE_CPU_H +#define _MACHINE_CPU_H + +/* + * Get common m68k CPU definitions. + */ +#include <m68k/cpu.h> +#define M68K_MMU_MOTOROLA + +/* + * definitions of cpu-dependent requirements + * referenced in generic code + */ +#define cpu_swapin(p) /* nothing */ +#define cpu_wait(p) /* nothing */ +#define cpu_swapout(p) /* nothing */ +#define cpu_number() 0 + +/* + * Arguments to hardclock and gatherstats encapsulate the previous + * machine state in an opaque clockframe. One the luna68k, 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; aston(); } + +/* + * Give a profiling tick to the current process when the user profiling + * buffer pages are invalid. On the hp300, request an ast to send us + * through trap, marking the proc as needing a profiling tick. + */ +#define need_proftick(p) { (p)->p_flag |= P_OWEUPC; aston(); } + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ +#define signotify(p) aston() + +#define aston() (astpending = 1) + +extern int astpending; /* need to 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 siron(x) \ + __asm __volatile ("orb %0,%1" : : "di" ((u_char)(x)), "g" (ssir)) +#define siroff(x) \ + __asm __volatile ("andb %0,%1" : : "di" ((u_char)~(x)), "g" (ssir)) + +#define setsoftnet() siron(SIR_NET) +#define setsoftclock() siron(SIR_CLOCK) + +/* + * 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 }, \ +} + +/* + * Values for machtype + */ +#define LUNA_I 1 +#define LUNA_II 2 + +#ifdef _KERNEL +extern int machtype; +extern char *intiobase, *intiolimit; /* XXX */ +extern u_int intiobase_phys, intiotop_phys; /* XXX */ + +/* machdep.c functions */ +void dumpconf __P((void)); +void dumpsys __P((void)); + +/* locore.s functions */ +struct pcb; +struct fpframe; +int suline __P((caddr_t, caddr_t)); +void savectx __P((struct pcb *)); +void switch_exit __P((struct proc *)); +void proc_trampoline __P((void)); +void loadustp __P((int)); +void m68881_save __P((struct fpframe *)); +void m68881_restore __P((struct fpframe *)); + +/* machdep.c functions */ +int badaddr __P((caddr_t, int)); + +/* sys_machdep.c functions */ +int cachectl1 __P((unsigned long, vaddr_t, size_t, struct proc *)); +int dma_cachectl __P((caddr_t, int)); + +/* vm_machdep.c functions */ +void physaccess __P((caddr_t, caddr_t, int, int)); +void physunaccess __P((caddr_t, int)); +int kvtop __P((caddr_t)); + +/* trap.c functions */ +void child_return __P((void *)); +#endif + +#endif /* _MACHINE_CPU_H */ diff --git a/sys/arch/luna68k/include/db_machdep.h b/sys/arch/luna68k/include/db_machdep.h new file mode 100644 index 00000000000..111d79f8e05 --- /dev/null +++ b/sys/arch/luna68k/include/db_machdep.h @@ -0,0 +1,4 @@ +/* $NetBSD: db_machdep.h,v 1.1 2000/01/05 08:48:57 nisimura Exp $ */ + +/* Just use the common m68k definition */ +#include <m68k/db_machdep.h> diff --git a/sys/arch/luna68k/include/disklabel.h b/sys/arch/luna68k/include/disklabel.h new file mode 100644 index 00000000000..3698badea8c --- /dev/null +++ b/sys/arch/luna68k/include/disklabel.h @@ -0,0 +1,57 @@ +/* $NetBSD: disklabel.h,v 1.1 2000/01/05 08:48:57 nisimura Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 0 /* sector containing label */ +#define LABELOFFSET 64 /* offset of label in sector */ +#define MAXPARTITIONS 8 /* number of partitions */ +#define RAW_PART 2 /* raw partition: xx?c */ + +/* + * This holds a copy of the whole label block, saved in here by + * readdisklabel() so that writedisklabel() can preserve the + * parts of the label block outside of the actual label. + * (i.e. Sun label info, bad block table, etc.) + */ +struct cpu_disklabel { + char cd_block[512]; +}; + +#ifdef _KERNEL + +struct dkbad; +int isbad __P((struct dkbad *bt, int, int, int)); + +#endif /* _KERNEL */ +#endif /* _MACHINE_DISKLABEL_H_ */ diff --git a/sys/arch/luna68k/include/endian.h b/sys/arch/luna68k/include/endian.h new file mode 100644 index 00000000000..cfa03d3ece8 --- /dev/null +++ b/sys/arch/luna68k/include/endian.h @@ -0,0 +1,4 @@ +/* $NetBSD: endian.h,v 1.1 2000/01/05 08:48:57 nisimura Exp $ */ + +/* Just use the common m68k definition */ +#include <m68k/endian.h> diff --git a/sys/arch/luna68k/include/float.h b/sys/arch/luna68k/include/float.h new file mode 100644 index 00000000000..c6df94eb97c --- /dev/null +++ b/sys/arch/luna68k/include/float.h @@ -0,0 +1,8 @@ +/* $NetBSD: float.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +#ifndef _MACHINE_FLOAT_H_ +#define _MACHINE_FLOAT_H_ + +#include <m68k/float.h> + +#endif diff --git a/sys/arch/luna68k/include/frame.h b/sys/arch/luna68k/include/frame.h new file mode 100644 index 00000000000..35d9fc3d028 --- /dev/null +++ b/sys/arch/luna68k/include/frame.h @@ -0,0 +1,3 @@ +/* $NetBSD: frame.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +#include <m68k/frame.h> diff --git a/sys/arch/luna68k/include/ieee.h b/sys/arch/luna68k/include/ieee.h new file mode 100644 index 00000000000..36ded585747 --- /dev/null +++ b/sys/arch/luna68k/include/ieee.h @@ -0,0 +1,3 @@ +/* $NetBSD: ieee.h,v 1.1 2000/01/05 08:49:01 nisimura Exp $ */ + +#include <m68k/ieee.h> diff --git a/sys/arch/luna68k/include/ieeefp.h b/sys/arch/luna68k/include/ieeefp.h new file mode 100644 index 00000000000..e29843eebbb --- /dev/null +++ b/sys/arch/luna68k/include/ieeefp.h @@ -0,0 +1,4 @@ +/* $NetBSD: ieeefp.h,v 1.1 2000/01/05 08:49:00 nisimura Exp $ */ + +/* Just use the common m68k definition */ +#include <m68k/ieeefp.h> diff --git a/sys/arch/luna68k/include/intr.h b/sys/arch/luna68k/include/intr.h new file mode 100644 index 00000000000..ed145ad8894 --- /dev/null +++ b/sys/arch/luna68k/include/intr.h @@ -0,0 +1,68 @@ +/* $NetBSD: intr.h,v 1.1 2000/01/05 08:49:01 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_INTR_H +#define _MACHINE_INTR_H + +/* + * spl functions; all but spl0 are done in-line + */ +#include <machine/psl.h> + +#define splnone() spl0() +#define spllowersoftclock() spl1() +#define splsoftclock() splraise1() +#define splsoftnet() splraise1() +#define splbio() spl2() +#define splnet() spl3() +#define spltty() spl6() +#define splimp() spl7() +#define splclock() spl5() +#define splstatclock() spl5() +#define splvm() spl7() +#define splhigh() spl7() +#define splsched() spl7() + +/* watch out for side effects */ +#define splx(s) ((s) & PSL_IPL ? _spl(s) : spl0()) + +#ifdef _KERNEL +int spl0 __P((void)); +#endif /* _KERNEL */ + +#endif /* _MACHINE_INTR_H */ diff --git a/sys/arch/luna68k/include/kcore.h b/sys/arch/luna68k/include/kcore.h new file mode 100644 index 00000000000..614620c075b --- /dev/null +++ b/sys/arch/luna68k/include/kcore.h @@ -0,0 +1,8 @@ +/* $NetBSD: kcore.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +#ifndef _MACHINE_KCORE_H_ +#define _MACHINE_KCORE_H_ + +#include <m68k/kcore.h> + +#endif diff --git a/sys/arch/luna68k/include/limits.h b/sys/arch/luna68k/include/limits.h new file mode 100644 index 00000000000..745d12c82f0 --- /dev/null +++ b/sys/arch/luna68k/include/limits.h @@ -0,0 +1,9 @@ +/* $NetBSD: limits.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +/* Just use the common m68k definition */ +#include <m68k/limits.h> + +#endif /* _MACHINE_LIMITS_H_ */ diff --git a/sys/arch/luna68k/include/math.h b/sys/arch/luna68k/include/math.h new file mode 100644 index 00000000000..9266b1f4c12 --- /dev/null +++ b/sys/arch/luna68k/include/math.h @@ -0,0 +1,3 @@ +/* $NetBSD: math.h,v 1.1 2000/01/05 08:49:02 nisimura Exp $ */ + +#include <m68k/math.h> diff --git a/sys/arch/luna68k/include/param.h b/sys/arch/luna68k/include/param.h new file mode 100644 index 00000000000..2d99d49932e --- /dev/null +++ b/sys/arch/luna68k/include/param.h @@ -0,0 +1,81 @@ +/* $Id: param.h,v 1.1 2000/01/05 08:49:01 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: machparam.h 1.16 92/12/20$ + * + * @(#)param.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#define _MACHINE luna68k +#define MACHINE "luna68k" + +#define PGSHIFT 12 /* LOG2(NBPG) */ +#define KERNBASE 0x00000000 /* start of kernel virtual */ + +#define SEGSHIFT 22 /* LOG2(NBSEG) */ +#define NBSEG (1 << SEGSHIFT) /* bytes/segment */ +#define SEGOFSET (NBSEG-1) /* byte offset into segment */ + +#define UPAGES 3 /* pages of u-area */ + +#include <m68k/param.h> + +#define NPTEPG (NBPG/(sizeof (pt_entry_t))) + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE NBPG /* default message buffer size */ +#endif + +#ifndef NKMEMCLUSTERS +# define NKMEMCLUSTERS (2048 * 1024 / NBPG) +#endif + +#include <machine/intr.h> + +#if defined(_KERNEL) && !defined(_LOCORE) +#define delay(us) _delay((us)<<8) +#define DELAY(n) delay(n) + +void _delay __P((unsigned)); +#endif /* _KERNEL && !_LOCORE */ + +#endif /* !_MACHINE_PARAM_H_ */ diff --git a/sys/arch/luna68k/include/pcb.h b/sys/arch/luna68k/include/pcb.h new file mode 100644 index 00000000000..2044ddcba80 --- /dev/null +++ b/sys/arch/luna68k/include/pcb.h @@ -0,0 +1,3 @@ +/* $NetBSD: pcb.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +#include <m68k/pcb.h> diff --git a/sys/arch/luna68k/include/pmap.h b/sys/arch/luna68k/include/pmap.h new file mode 100644 index 00000000000..fba6454e3f4 --- /dev/null +++ b/sys/arch/luna68k/include/pmap.h @@ -0,0 +1,150 @@ +/* $NetBSD: pmap.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +/* + * Copyright (c) 1987 Carnegie-Mellon University + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pmap.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#include <machine/pte.h> + +/* + * Pmap stuff + */ +struct pmap { + pt_entry_t *pm_ptab; /* KVA of page table */ + st_entry_t *pm_stab; /* KVA of segment table */ + int pm_stfree; /* 040: free lev2 blocks */ + st_entry_t *pm_stpa; /* 040: ST phys addr */ + short pm_sref; /* segment table ref count */ + short pm_count; /* pmap reference count */ + simple_lock_data_t pm_lock; /* lock on pmap */ + struct pmap_statistics pm_stats; /* pmap statistics */ + long pm_ptpages; /* more stats: PT pages */ +}; + +typedef struct pmap *pmap_t; + +/* + * On the 040 we keep track of which level 2 blocks are already in use + * with the pm_stfree mask. Bits are arranged from LSB (block 0) to MSB + * (block 31). For convenience, the level 1 table is considered to be + * block 0. + * + * MAX[KU]L2SIZE control how many pages of level 2 descriptors are allowed. + * for the kernel and users. 8 implies only the initial "segment table" + * page is used. WARNING: don't change MAXUL2SIZE unless you can allocate + * physically contiguous pages for the ST in pmap.c! + */ +#define MAXKL2SIZE 32 +#define MAXUL2SIZE 8 +#define l2tobm(n) (1 << (n)) +#define bmtol2(n) (ffs(n) - 1) + +/* + * Macros for speed + */ +#define PMAP_ACTIVATE(pmap, loadhw) \ +{ \ + if ((loadhw)) \ + loadustp(m68k_btop((paddr_t)(pmap)->pm_stpa)); \ +} + +/* + * For each vm_page_t, there is a list of all currently valid virtual + * mappings of that page. An entry is a pv_entry, the list is pv_table. + */ +struct pv_entry { + struct pv_entry *pv_next; /* next pv_entry */ + struct pmap *pv_pmap; /* pmap where mapping lies */ + vaddr_t pv_va; /* virtual address for mapping */ + st_entry_t *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 */ +}; + +#define PV_CI 0x01 /* header: all entries are cache inhibited */ +#define PV_PTPAGE 0x02 /* header: entry maps a page table page */ + +struct pv_page; + +struct pv_page_info { + TAILQ_ENTRY(pv_page) pgi_list; + struct pv_entry *pgi_freelist; + int pgi_nfree; +}; + +/* + * This is basically: + * ((NBPG - sizeof(struct pv_page_info)) / sizeof(struct pv_entry)) + */ +#define NPVPPG 170 + +struct pv_page { + struct pv_page_info pvp_pgi; + struct pv_entry pvp_pv[NPVPPG]; +}; + +#ifdef _KERNEL + +extern struct pmap kernel_pmap_store; + +#define pmap_kernel() (&kernel_pmap_store) +#define active_pmap(pm) \ + ((pm) == pmap_kernel() || (pm) == curproc->p_vmspace->vm_map.pmap) +#define active_user_pmap(pm) \ + (curproc && \ + (pm) != pmap_kernel() && (pm) == curproc->p_vmspace->vm_map.pmap) + +extern struct pv_entry *pv_table; /* array of entries, one per page */ + +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count) + +extern pt_entry_t *Sysmap; +extern char *vmmap; /* map for mem, dumps, etc. */ + +vaddr_t pmap_map __P((vaddr_t, paddr_t, paddr_t, int)); +void pmap_procwr __P((struct proc *, vaddr_t, size_t)); +#define PMAP_NEED_PROCWR + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_PMAP_H_ */ diff --git a/sys/arch/luna68k/include/proc.h b/sys/arch/luna68k/include/proc.h new file mode 100644 index 00000000000..c237dbb9de9 --- /dev/null +++ b/sys/arch/luna68k/include/proc.h @@ -0,0 +1,53 @@ +/* $NetBSD: proc.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)proc.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Machine-dependent part of the proc structure for luna68k. + */ +struct mdproc { + int *md_regs; /* registers on current frame */ + int md_flags; /* machine-dependent flags */ +}; + +/* md_flags */ +#define MDP_STACKADJ 0x0002 /* frame SP adjusted, might have to + undo when system call returns + ERESTART. */ +#define MDP_HPUXTRACE 0x0004 /* being traced by HP-UX process */ +#define MDP_HPUXMMAP 0x0008 /* VA space is multiply mapped */ +#define MDP_CCBDATA 0x0010 /* copyback caching of data (68040) */ +#define MDP_CCBSTACK 0x0020 /* copyback caching of stack (68040) */ diff --git a/sys/arch/luna68k/include/profile.h b/sys/arch/luna68k/include/profile.h new file mode 100644 index 00000000000..f3c16720929 --- /dev/null +++ b/sys/arch/luna68k/include/profile.h @@ -0,0 +1,3 @@ +/* $NetBSD: profile.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +#include <m68k/profile.h> diff --git a/sys/arch/luna68k/include/psl.h b/sys/arch/luna68k/include/psl.h new file mode 100644 index 00000000000..a8136b7ee2a --- /dev/null +++ b/sys/arch/luna68k/include/psl.h @@ -0,0 +1,3 @@ +/* $NetBSD: psl.h,v 1.1 2000/01/05 08:48:58 nisimura Exp $ */ + +#include <m68k/psl.h> diff --git a/sys/arch/luna68k/include/pte.h b/sys/arch/luna68k/include/pte.h new file mode 100644 index 00000000000..2cf3139281c --- /dev/null +++ b/sys/arch/luna68k/include/pte.h @@ -0,0 +1,152 @@ +/* $NetBSD: pte.h,v 1.1 2000/01/05 08:48:59 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: pte.h 1.13 92/01/20$ + * + * @(#)pte.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * m68k hardware segment/page table entries + */ + +#if 0 +struct ste { + unsigned int sg_pfnum:20; /* page table frame number */ + unsigned int :8; /* reserved at 0 */ + unsigned int :1; /* reserved at 1 */ + unsigned int sg_prot:1; /* write protect bit */ + unsigned int sg_v:2; /* valid bits */ +}; + +struct ste40 { + unsigned int sg_ptaddr:24; /* page table page addr */ + unsigned int :4; /* reserved at 0 */ + unsigned int sg_u; /* hardware modified (dirty) bit */ + unsigned int sg_prot:1; /* write protect bit */ + unsigned int sg_v:2; /* valid bits */ +}; + +struct pte { + unsigned int pg_pfnum:20; /* page frame number or 0 */ + unsigned int :3; + unsigned int pg_w:1; /* is wired */ + unsigned int :1; /* reserved at zero */ + unsigned int pg_ci:1; /* cache inhibit bit */ + unsigned int :1; /* reserved at zero */ + unsigned int pg_m:1; /* hardware modified (dirty) bit */ + unsigned int pg_u:1; /* hardware used (reference) bit */ + unsigned int pg_prot:1; /* write protect bit */ + unsigned int pg_v:2; /* valid bit */ +}; +#endif + +typedef int st_entry_t; /* segment table entry */ +typedef int pt_entry_t; /* Mach page table entry */ + +#define PT_ENTRY_NULL ((pt_entry_t *) 0) +#define ST_ENTRY_NULL ((st_entry_t *) 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 0xfffff000 +#define SG_IMASK 0xffc00000 +#define SG_ISHIFT 22 +#define SG_PMASK 0x003ff000 +#define SG_PSHIFT 12 + +/* 68040 additions */ +#define SG4_MASK1 0xfe000000 +#define SG4_SHIFT1 25 +#define SG4_MASK2 0x01fc0000 +#define SG4_SHIFT2 18 +#define SG4_MASK3 0x0003f000 +#define SG4_SHIFT3 12 +#define SG4_ADDR1 0xfffffe00 +#define SG4_ADDR2 0xffffff00 +#define SG4_LEV1SIZE 128 +#define SG4_LEV2SIZE 128 +#define SG4_LEV3SIZE 64 + +#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 0xfffff000 +#define PG_CI 0x00000040 +#define PG_SHIFT 12 +#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 STSIZE (MAXUL2SIZE*SG4_LEV2SIZE*sizeof(st_entry_t)) + /* user process segment table size */ +#define MAX_PTSIZE 0x400000 /* max size of UPT */ +#define MAX_KPTSIZE 0x100000 /* max memory to allocate to KPT */ +#define PTBASE 0x10000000 /* UPT map base address */ +#define PTMAXSIZE 0x70000000 /* UPT map maximum size */ + +/* + * 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) \ + ((((pt_entry_t *)(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/luna68k/include/ptrace.h b/sys/arch/luna68k/include/ptrace.h new file mode 100644 index 00000000000..9b1c615ebe2 --- /dev/null +++ b/sys/arch/luna68k/include/ptrace.h @@ -0,0 +1,4 @@ +/* $NetBSD: ptrace.h,v 1.1 2000/01/05 08:48:59 nisimura Exp $ */ + +/* Just use the common m68k definition */ +#include <m68k/ptrace.h> diff --git a/sys/arch/luna68k/include/reg.h b/sys/arch/luna68k/include/reg.h new file mode 100644 index 00000000000..d3ddf233958 --- /dev/null +++ b/sys/arch/luna68k/include/reg.h @@ -0,0 +1,8 @@ +/* $NetBSD: reg.h,v 1.1 2000/01/05 08:49:01 nisimura Exp $ */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +#include <m68k/reg.h> + +#endif /* _MACHINE_REG_H_ */ diff --git a/sys/arch/luna68k/include/setjmp.h b/sys/arch/luna68k/include/setjmp.h new file mode 100644 index 00000000000..deb4c0d04e0 --- /dev/null +++ b/sys/arch/luna68k/include/setjmp.h @@ -0,0 +1,3 @@ +/* $NetBSD: setjmp.h,v 1.1 2000/01/05 08:48:59 nisimura Exp $ */ + +#include <m68k/setjmp.h> diff --git a/sys/arch/luna68k/include/signal.h b/sys/arch/luna68k/include/signal.h new file mode 100644 index 00000000000..ecf4f256b1d --- /dev/null +++ b/sys/arch/luna68k/include/signal.h @@ -0,0 +1,4 @@ +/* $NetBSD: signal.h,v 1.1 2000/01/05 08:48:59 nisimura Exp $ */ + +/* Just use the common m68k definition */ +#include <m68k/signal.h> diff --git a/sys/arch/luna68k/include/stdarg.h b/sys/arch/luna68k/include/stdarg.h new file mode 100644 index 00000000000..f5407abca7d --- /dev/null +++ b/sys/arch/luna68k/include/stdarg.h @@ -0,0 +1,4 @@ +/* $NetBSD: stdarg.h,v 1.1 2000/01/05 08:48:59 nisimura Exp $ */ + +/* Just use the common m68k definition */ +#include <m68k/stdarg.h> diff --git a/sys/arch/luna68k/include/trap.h b/sys/arch/luna68k/include/trap.h new file mode 100644 index 00000000000..4a60aeae33f --- /dev/null +++ b/sys/arch/luna68k/include/trap.h @@ -0,0 +1,3 @@ +/* $NetBSD: trap.h,v 1.1 2000/01/05 08:48:59 nisimura Exp $ */ + +#include <m68k/trap.h> diff --git a/sys/arch/luna68k/include/types.h b/sys/arch/luna68k/include/types.h new file mode 100644 index 00000000000..d610dde29b2 --- /dev/null +++ b/sys/arch/luna68k/include/types.h @@ -0,0 +1,8 @@ +/* $NetBSD: types.h,v 1.1 2000/01/05 08:48:59 nisimura Exp $ */ + +#ifndef _MACHINE_TYPES_H_ +#define _MACHINE_TYPES_H_ + +#include <m68k/types.h> + +#endif diff --git a/sys/arch/luna68k/include/varargs.h b/sys/arch/luna68k/include/varargs.h new file mode 100644 index 00000000000..9a199e76250 --- /dev/null +++ b/sys/arch/luna68k/include/varargs.h @@ -0,0 +1,4 @@ +/* $NetBSD: varargs.h,v 1.1 2000/01/05 08:49:00 nisimura Exp $ */ + +/* Just use the common m68k definition */ +#include <m68k/varargs.h> diff --git a/sys/arch/luna68k/include/vmparam.h b/sys/arch/luna68k/include/vmparam.h new file mode 100644 index 00000000000..86f229a5582 --- /dev/null +++ b/sys/arch/luna68k/include/vmparam.h @@ -0,0 +1,142 @@ +/* $NetBSD: vmparam.h,v 1.1 2000/01/05 08:49:01 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: vmparam.h 1.16 91/01/18$ + * + * @(#)vmparam.h 8.2 (Berkeley) 4/19/94 + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * USRTEXT is the start of the user text/data space, while USRSTACK + * is the top (end) of the user stack. + */ +#define USRTEXT 8192 +#define USRSTACK VM_MAXUSER_ADDRESS + +/* + * Virtual memory related constants, all in bytes + */ +#ifndef MAXTSIZ +#define MAXTSIZ (8*1024*1024) /* max text size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ (16*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (64*1024*1024) /* max data size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (512*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ MAXDSIZ /* max stack size */ +#endif + +/* + * 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) /* 8mb */ +#define USRPTSIZE (1 * NPTEPG) /* 4mb */ + +/* + * PTEs for mapping user space into the kernel for phyio operations. + * One page is enough to handle 4Mb of simultaneous raw IO operations. + */ +#ifndef USRIOSIZE +#define USRIOSIZE (1 * NPTEPG) /* 4mb */ +#endif + +/* + * PTEs for system V style shared memory. + * This is basically slop for kmempt which we actually allocate (malloc) from. + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 /* 8mb */ +#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 + +/* user/kernel map constants */ +#define VM_MIN_ADDRESS ((vaddr_t)0) +#define VM_MAXUSER_ADDRESS ((vaddr_t)0xFFFC0000) +#define VM_MAX_ADDRESS ((vaddr_t)0xFFFC0000) +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)0) +#define VM_MAX_KERNEL_ADDRESS ((vaddr_t)(0-NBPG)) + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES) +#define VM_KMEM_SIZE (NKMEMCLUSTERS*NBPG) +#define VM_PHYS_SIZE (USRIOSIZE*NBPG) + +/* # of kernel PT pages (initial only, can grow dynamically) */ +#define VM_KERNEL_PT_PAGES ((vsize_t)2) /* XXX: SYSPTSIZE */ + +/* + * Constants which control the way the VM system deals with memory segments. + * Only one physical contigous memory segment. + */ +#define VM_PHYSSEG_MAX 1 +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD + +#define VM_NFREELIST 1 +#define VM_FREELIST_DEFAULT 0 + +/* + * pmap-specific data stored in the vm_physmem[] array. + */ +struct pmap_physseg { + struct pv_entry *pvent; /* pv table for this seg */ + char *attrs; /* page attributes for this seg */ +}; + +#endif /* _MACHINE_VMPARAM_H_ */ diff --git a/sys/arch/luna68k/luna68k/autoconf.c b/sys/arch/luna68k/luna68k/autoconf.c new file mode 100644 index 00000000000..618aa401b9f --- /dev/null +++ b/sys/arch/luna68k/luna68k/autoconf.c @@ -0,0 +1,116 @@ +/* $NetBSD: autoconf.c,v 1.1 2000/01/05 08:49:02 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.1 2000/01/05 08:49:02 nisimura Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/map.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/reboot.h> +#include <sys/device.h> + +#include <machine/disklabel.h> +#include <machine/cpu.h> + +#include <luna68k/luna68k/isr.h> + +/* + * The following several variables are related to + * the configuration process, and are used in initializing + * the machine. + */ +struct device *booted_device; /* set by device drivers (if found) */ + +/* + * Determine mass storage and memory configuration for a machine. + */ +void +cpu_configure() +{ + booted_device = NULL; /* set by device drivers (if found) */ + + (void)splhigh(); + isrinit(); + if (config_rootfound("mainbus", NULL) == NULL) + panic("autoconfig failed, no root"); + + spl0(); +} + +void +cpu_rootconf() +{ + printf("boot device: %s\n", + (booted_device) ? booted_device->dv_xname : "<unknown>"); + + setroot(booted_device, 0); +} + +#if 0 /* What is this for !? */ +/* + * find a device matching "name" and unit number + */ +struct device * +getdevunit(name, unit) + char *name; + int unit; +{ + struct device *dev = alldevs.tqh_first; + char num[10], fullname[16]; + int lunit; + + /* compute length of name and decimal expansion of unit number */ + sprintf(num, "%d", unit); + lunit = strlen(num); + if (strlen(name) + lunit >= sizeof(fullname) - 1) + panic("config_attach: device name too long"); + + strcpy(fullname, name); + strcat(fullname, num); + + while (strcmp(dev->dv_xname, fullname) != 0) { + if ((dev = dev->dv_list.tqe_next) == NULL) + return NULL; + } + return dev; +} +#endif diff --git a/sys/arch/luna68k/luna68k/clock.c b/sys/arch/luna68k/luna68k/clock.c new file mode 100644 index 00000000000..efe20469277 --- /dev/null +++ b/sys/arch/luna68k/luna68k/clock.c @@ -0,0 +1,222 @@ +/* $NetBSD: clock.c,v 1.1 2000/01/05 08:49:02 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department and Ralph Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with 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 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.1 2000/01/05 08:49:02 nisimura Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> + +#include <machine/cpu.h> + +#include <dev/clock_subr.h> +#include <luna68k/luna68k/clockvar.h> + +#define CLOCK_LEVEL 5 +#include <luna68k/luna68k/isr.h> + +extern int machtype; + +static struct device *clockdev; +static struct clockfns *clockfns; +static int clockinitted; + +void +clockattach(dev, fns) + struct device *dev; + struct clockfns *fns; +{ + /* + * Just bookkeeping. + */ + if (clockfns != NULL) + panic("clockattach: multiple clocks"); + clockdev = dev; + clockfns = fns; +} + +/* + * 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. Its primary function is to use some file + * system information in case the hardare clock lost state. + * + * Resettodr restores the time of day hardware after a time change. + */ + +int clock_enable; /* XXX to be removed XXX */ + +/* + * Start the real-time and statistics clocks. Leave stathz 0 since there + * are no other timers available. + */ +void +cpu_initclocks() +{ + int s; + + if (clockfns == NULL) + panic("cpu_initclocks: no clock attached"); + + if (machtype == LUNA_I) + hz = 60; /* LUNA-I is clocked at 60Hz, not 100Hz */ + + tick = 1000000 / hz; /* number of microseconds between interrupts */ + tickfix = 1000000 - (hz * tick); + if (tickfix) { + int ftp; + + ftp = min(ffs(tickfix), ffs(hz)); + tickfix >>= (ftp - 1); + tickfixinterval = hz >> (ftp - 1); + } + /* + * Get the clock started. + */ + s = splhigh(); + /* + * XXX + * I guess it's necessary to program clock source with + * approprivate mode/value. + * XXX + */ + clock_enable = 1; + splx(s); +} + +/* + * We assume newhz is either stathz or profhz, and that neither will + * change after being set up above. Could recalculate intervals here + * but that would be a drag. + */ +void +setstatclockrate(newhz) + int newhz; +{ + /* nothing we can do */ +} + +/* + * Initialze the time of day register, based on the time base which is, e.g. + * from a filesystem. Base provides the time to within six months, + * and the time of year clock (if any) provides the rest. + */ +void +inittodr(base) + time_t base; +{ + struct clock_ymdhms dt; + time_t deltat; + int badbase; + + if (base < 5*SECYR) { + printf("WARNING: preposterous time in file system"); + /* read the system clock anyway */ + base = 6*SECYR + 186*SECDAY + SECDAY/2; + badbase = 1; + } else + badbase = 0; + + (*clockfns->cf_get)(clockdev, base, &dt); + clockinitted = 1; + /* simple sanity checks */ + if (dt.dt_year < 1970 || dt.dt_mon < 1 || dt.dt_mon > 12 + || dt.dt_day < 1 || dt.dt_day > 31 + || dt.dt_hour > 23 || dt.dt_min > 59 || dt.dt_sec > 59) { + /* + * Believe the time in the file system for lack of + * anything better, resetting the TODR. + */ + time.tv_sec = base; + if (!badbase) { + printf("WARNING: preposterous clock chip time"); + resettodr(); + } + goto bad; + } + /* now have days since Jan 1, 1970; the rest is easy... */ + time.tv_sec = clock_ymdhms_to_secs(&dt); + + if (!badbase) { + /* + * See if we gained/lost two or more days; + * if so, assume something is amiss. + */ + deltat = time.tv_sec - base; + if (deltat < 0) + deltat = -deltat; + if (deltat < 2 * SECDAY) + return; + printf("WARNING: clock %s %d days", + time.tv_sec < base ? "lost" : "gained", + (int) (deltat / SECDAY)); + } +bad: + printf(" -- CHECK AND RESET THE DATE!\n"); +} + +/* + * Reset the TODR based on the time value; used when the TODR + * has a preposterous value and also when the time is reset + * by the stime system call. Also called when the TODR goes past + * TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight) + * to wrap the TODR around. + */ +void +resettodr() +{ + struct clock_ymdhms dt; + + if (!clockinitted) + return; + clock_secs_to_ymdhms(time.tv_sec, &dt); + (*clockfns->cf_set)(clockdev, &dt); +} diff --git a/sys/arch/luna68k/luna68k/clockvar.h b/sys/arch/luna68k/luna68k/clockvar.h new file mode 100644 index 00000000000..69795a02570 --- /dev/null +++ b/sys/arch/luna68k/luna68k/clockvar.h @@ -0,0 +1,53 @@ +/* $NetBSD: clockvar.h,v 1.1 2000/01/05 08:49:02 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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. + */ + +struct clock_ymdhms; + +/* + * clockfns structure: + * + * function switch used by chip-independent clock code, to access + * chip-dependent routines. + */ +struct clockfns { + void (*cf_init) __P((struct device *)); + void (*cf_get) __P((struct device *, time_t, struct clock_ymdhms *)); + void (*cf_set) __P((struct device *, struct clock_ymdhms *)); +}; + +void clockattach __P((struct device *, struct clockfns *)); diff --git a/sys/arch/luna68k/luna68k/conf.c b/sys/arch/luna68k/luna68k/conf.c new file mode 100644 index 00000000000..258d1256abe --- /dev/null +++ b/sys/arch/luna68k/luna68k/conf.c @@ -0,0 +1,257 @@ +/* $NetBSD: conf.c,v 1.1 2000/01/05 08:49:02 nisimura Exp $ */ +/* $NetBSD: conf.c,v 1.1 2000/01/05 08:49:02 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: conf.c,v 1.1 2000/01/05 08:49:02 nisimura Exp $"); + +#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> + +bdev_decl(sw); +#include "st.h" +bdev_decl(st); +#include "cd.h" +bdev_decl(cd); +#include "sd.h" +bdev_decl(sd); +#include "vnd.h" +bdev_decl(vnd); +#include "ccd.h" +bdev_decl(ccd); +#include "md.h" +bdev_decl(md); + +struct bdevsw bdevsw[] = +{ + bdev_notdef(), /* 0 */ + bdev_swap_init(1,sw), /* 1: swap pseudo-device */ + bdev_disk_init(NSD,sd), /* 2: SCSI disk */ + bdev_tape_init(NST,st), /* 3: SCSI tape */ + bdev_disk_init(NCD,cd), /* 4: SCSI CD-ROM */ + bdev_disk_init(NCCD,ccd), /* 5: concatenated disk driver */ + bdev_disk_init(NVND,vnd), /* 6: vnode disk driver */ + bdev_disk_init(NMD,md), /* 7: memory disk - for install tape */ + bdev_lkm_dummy(), /* 8 */ + bdev_lkm_dummy(), /* 9 */ + bdev_lkm_dummy(), /* 10 */ + bdev_lkm_dummy(), /* 11 */ + bdev_lkm_dummy(), /* 12 */ + bdev_lkm_dummy(), /* 13 */ +}; +int nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]); + +cdev_decl(cn); +cdev_decl(ctty); +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); +cdev_decl(sw); +#include "pty.h" +#define ptstty ptytty +#define ptsioctl ptyioctl +cdev_decl(pts); +#define ptctty ptytty +#define ptcioctl ptyioctl +cdev_decl(ptc); +cdev_decl(log); +#include "tun.h" +cdev_decl(tun); +cdev_decl(sd); +cdev_decl(vnd); +cdev_decl(ccd); +dev_type_open(filedescopen); +#include "bpfilter.h" +cdev_decl(bpf); +cdev_decl(st); +cdev_decl(cd); +#include "ch.h" +cdev_decl(ch); +cdev_decl(md); +#include "ss.h" +cdev_decl(ss); +#include "uk.h" +cdev_decl(uk); +cdev_decl(fd); +#include "ipfilter.h" +cdev_decl(ipl); +#include "siotty.h" +cdev_decl(sio); + +#include "wsdisplay.h" +cdev_decl(wsdisplay); +#include "wskbd.h" +cdev_decl(wskbd); +#include "wsmouse.h" +cdev_decl(wsmouse); + +#include "scsibus.h" +cdev_decl(scsibus); + +struct cdevsw cdevsw[] = +{ + cdev_cn_init(1,cn), /* 0: virtual console */ + cdev_ctty_init(1,ctty), /* 1: controlling terminal */ + cdev_mm_init(1,mm), /* 2: /dev/{null,mem,kmem,...} */ + cdev_swap_init(1,sw), /* 3: /dev/drum (swap pseudo-device) */ + cdev_tty_init(NPTY,pts), /* 4: pseudo-tty slave */ + cdev_ptc_init(NPTY,ptc), /* 5: pseudo-tty master */ + cdev_log_init(1,log), /* 6: /dev/klog */ + cdev_tty_init(NSIOTTY,sio), /* 7: ttya */ + cdev_disk_init(NSD,sd), /* 8: SCSI disk */ + cdev_tape_init(NST,st), /* 9: SCSI tape */ + cdev_disk_init(NCD,cd), /* 10: SCSI CD-ROM */ + cdev_ch_init(NCH,ch), /* 11: SCSI autochanger */ + cdev_scanner_init(NSS,ss), /* 12: SCSI scanner */ + cdev_uk_init(NUK,uk), /* 13: SCSI unknown */ + cdev_disk_init(NCCD,ccd), /* 14: concatenated disk driver */ + cdev_disk_init(NVND,vnd), /* 15: vnode disk */ + cdev_disk_init(NMD,md), /* 16: memory disk driver */ + cdev_mouse_init(NWSKBD, wskbd), /* 17: keyboards */ + cdev_mouse_init(NWSMOUSE, + wsmouse), /* 18: mice */ + cdev_wsdisplay_init(NWSDISPLAY, + wsdisplay), /* 19: frame buffers, etc. */ + cdev_fd_init(1,filedesc), /* 20: file descriptor pseudo-dev */ + cdev_bpftun_init(NBPFILTER,bpf),/* 21: berkeley packet filter */ + cdev_bpftun_init(NTUN,tun), /* 22: network tunnel */ + cdev_ipf_init(NIPFILTER,ipl), /* 23: ip-filter device */ + cdev_lkm_init(NLKM,lkm), /* 24: loadable module driver */ + cdev_lkm_dummy(), /* 25 */ + cdev_lkm_dummy(), /* 26 */ + cdev_lkm_dummy(), /* 27 */ + cdev_lkm_dummy(), /* 28 */ + cdev_lkm_dummy(), /* 30 */ + cdev_lkm_dummy(), /* 31 */ + cdev_scsibus_init(NSCSIBUS,scsibus), /* 32: SCSI bus */ +}; +int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]); + +int mem_no = 2; /* major device number of memory special file */ + +/* + * Swapdev is a fake device implemented + * in sw.c used only internally to get to swstrategy. + * It cannot be provided to the users, because the + * swstrategy routine munches the b_dev and b_blkno entries + * before calling the appropriate driver. This would horribly + * confuse, e.g. the hashing routines. Instead, /dev/drum is + * provided as a character (raw) device. + */ +dev_t swapdev = makedev(1, 0); + +/* + * Returns true if dev is /dev/mem or /dev/kmem. + */ +int +iskmemdev(dev) + dev_t dev; +{ + return (major(dev) == mem_no && minor(dev) < 2); +} + +/* + * Returns true if dev is /dev/zero. + */ +int +iszerodev(dev) + dev_t dev; +{ + return (major(dev) == mem_no && minor(dev) == 12); +} + +static int chrtoblktbl[] = { + /*VCHR*/ /*VBLK*/ + /* 0 */ NODEV, + /* 1 */ NODEV, + /* 2 */ NODEV, + /* 3 */ NODEV, + /* 4 */ NODEV, + /* 5 */ NODEV, + /* 6 */ NODEV, + /* 7 */ NODEV, + /* 8 */ 2, /* sd */ + /* 9 */ 3, /* st */ + /* 10 */ 4, /* cd */ + /* 11 */ NODEV, + /* 12 */ NODEV, + /* 13 */ NODEV, + /* 14 */ 5, /* ccd */ + /* 15 */ 6, /* vnd */ + /* 16 */ 7, /* md */ + /* 17 */ NODEV, + /* 18 */ NODEV, + /* 19 */ NODEV, + /* 20 */ NODEV, + /* 21 */ NODEV, + /* 22 */ NODEV, + /* 23 */ NODEV, + /* 24 */ NODEV, + /* 25 */ NODEV, + /* 26 */ NODEV, + /* 27 */ NODEV, + /* 28 */ NODEV, + /* 29 */ NODEV, + /* 30 */ NODEV, + /* 31 */ NODEV, + /* 32 */ NODEV, +}; + +/* + * Convert a character device number to a block device number. + */ +dev_t +chrtoblk(dev) + dev_t dev; +{ + int blkmaj; + + if (major(dev) >= nchrdev + || major(dev) >= (sizeof(chrtoblktbl) / sizeof(chrtoblktbl[0]))) + return (NODEV); + blkmaj = chrtoblktbl[major(dev)]; + if (blkmaj == NODEV) + return (NODEV); + return (makedev(blkmaj, minor(dev))); +} diff --git a/sys/arch/luna68k/luna68k/db_memrw.c b/sys/arch/luna68k/luna68k/db_memrw.c new file mode 100644 index 00000000000..06e536f1b12 --- /dev/null +++ b/sys/arch/luna68k/luna68k/db_memrw.c @@ -0,0 +1,230 @@ +/* $NetBSD: db_memrw.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ +/* $NetBSD: db_memrw.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ + +/*- + * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Gordon W. Ross and Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: db_memrw.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $"); + +/* + * Interface to the debugger for virtual memory read/write. + * This file is shared by DDB and KGDB, and must work even + * when only KGDB is included (thus no db_printf calls). + * + * To write in the text segment, we have to first make + * the page writable, do the write, then restore the PTE. + * For writes outside the text segment, and all reads, + * just do the access -- if it causes a fault, the debugger + * will recover with a longjmp to an appropriate place. + * + * ALERT! If you want to access device registers with a + * specific size, then the read/write functions have to + * make sure to do the correct sized pointer access. + * + * Modified from sun3 version for hp300 (and probably other m68ks, too) + * by Jason R. Thorpe <thorpej@NetBSD.ORG>. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> + +#include <vm/vm.h> + +#include <machine/pte.h> +#include <machine/db_machdep.h> +#include <machine/cpu.h> +#include <m68k/cacheops.h> + +#include <ddb/db_access.h> + +static void db_write_text __P((db_addr_t, size_t, char *)); + +/* + * Read bytes from kernel address space for debugger. + * This used to check for valid PTEs, but now that + * traps in DDB work correctly, "Just Do It!" + */ +void +db_read_bytes(addr, size, data) + db_addr_t addr; + size_t size; + char *data; +{ + char *src = (char*)addr; + + if (size == 4) { + *((int*)data) = *((int*)src); + return; + } + + if (size == 2) { + *((short*)data) = *((short*)src); + return; + } + + while (size > 0) { + --size; + *data++ = *src++; + } +} + +/* + * Write bytes somewhere in kernel text. + * Makes text page writable temporarily. + * We're probably a little to cache-paranoid. + */ +static void +db_write_text(addr, size, data) + db_addr_t addr; + size_t size; + char *data; +{ + char *dst, *odst; + pt_entry_t *pte, oldpte, tmppte; + vaddr_t pgva; + int limit; + + if (size == 0) + return; + + dst = (char *)addr; + + do { + /* + * Get the VA for the page. + */ + pgva = m68k_trunc_page((u_long)dst); + + /* + * Save this destination address, for TLB + * flush. + */ + odst = dst; + + /* + * Compute number of bytes that can be written + * with this mapping and subtract it from the + * total size. + */ + limit = NBPG - ((u_long)dst & PGOFSET); + if (limit > size) + limit = size; + size -= limit; + +#ifdef M68K_MMU_HP + /* + * Flush the supervisor side of the VAC to + * prevent a cache hit on the old, read-only PTE. + * XXX Is this really necessary, or am I just + * paranoid? + */ + if (ectype == EC_VIRT) + DCIS(); +#endif + + /* + * Make the page writable. Note the mapping is + * cache-inhibited to save hair. + */ + pte = kvtopte(pgva); + oldpte = *pte; + + if ((oldpte & PG_V) == 0) { + printf(" address %p not a valid page\n", dst); + return; + } + + tmppte = (oldpte & ~PG_RO) | PG_RW | PG_CI; + *pte = tmppte; + TBIS((vaddr_t)odst); + + /* + * Page is now writable. Do as much access as we + * can in this page. + */ + for (; limit > 0; limit--) + *dst++ = *data++; + + /* + * Restore the old PTE. + */ + *pte = oldpte; + TBIS((vaddr_t)odst); + } while (size != 0); + + /* + * Invalidate the instruction cache so our changes + * take effect. + */ + ICIA(); +} + +/* + * Write bytes to kernel address space for debugger. + */ +extern char kernel_text[], etext[]; +void +db_write_bytes(addr, size, data) + db_addr_t addr; + size_t size; + char *data; +{ + char *dst = (char *)addr; + + /* If any part is in kernel text, use db_write_text() */ + if ((dst < etext) && ((dst + size) > kernel_text)) { + db_write_text(addr, size, data); + return; + } + + if (size == 4) { + *((int*)dst) = *((int*)data); + return; + } + + if (size == 2) { + *((short*)dst) = *((short*)data); + return; + } + + while (size > 0) { + --size; + *dst++ = *data++; + } +} diff --git a/sys/arch/luna68k/luna68k/disksubr.c b/sys/arch/luna68k/luna68k/disksubr.c new file mode 100644 index 00000000000..f2033e6bbee --- /dev/null +++ b/sys/arch/luna68k/luna68k/disksubr.c @@ -0,0 +1,487 @@ +/* $NetBSD: disksubr.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ +/* $NetBSD: disksubr.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ + +/* + * Copyright (c) 1994, 1995 Gordon W. Ross + * Copyright (c) 1994 Theo de Raadt + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Credits: + * This file was based mostly on the i386/disksubr.c file: + * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + * The functions: disklabel_sun_to_bsd, disklabel_bsd_to_sun + * were originally taken from arch/sparc/scsi/sun_disklabel.c + * (which was written by Theo de Raadt) and then substantially + * rewritten by Gordon W. Ross. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/disklabel.h> +#include <sys/disk.h> +#include <sys/dkbad.h> + +#include <dev/sun/disklabel.h> + +/* XXX encoding of disk minor numbers, should be elsewhere... */ +#define dkpart(dev) (minor(dev) & 7) + +#define b_cylin b_resid + +#if LABELSECTOR != 0 +#error "Default value of LABELSECTOR no longer zero?" +#endif + +static char * disklabel_om_to_bsd(char *, struct disklabel *); +static int disklabel_bsd_to_om(struct disklabel *, char *); +#define OM_DKMAGIC 0xdabe + +/* + * Attempt to read a disk label from a device + * using the indicated stategy routine. + * The label must be partly set up before this: + * secpercyl, secsize and anything required for a block i/o read + * operation in the driver's strategy/start routines + * must be filled in before calling us. + * + * Return buffer for use in signalling errors if requested. + * + * Returns null on success and an error string on failure. + */ +char * +readdisklabel(dev, strat, lp, clp) + dev_t dev; + void (*strat) __P((struct buf *)); + struct disklabel *lp; + struct cpu_disklabel *clp; +{ + struct buf *bp; + struct disklabel *dlp; + struct sun_disklabel *slp; + int error; + + /* minimal requirements for archtypal disk label */ + if (lp->d_secperunit == 0) + lp->d_secperunit = 0x1fffffff; + lp->d_npartitions = 1; + if (lp->d_partitions[0].p_size == 0) + lp->d_partitions[0].p_size = 0x1fffffff; + lp->d_partitions[0].p_offset = 0; + + /* obtain buffer to probe drive with */ + bp = geteblk((int)lp->d_secsize); + + /* next, dig out disk label */ + bp->b_dev = dev; + bp->b_blkno = LABELSECTOR; + bp->b_cylin = 0; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + + /* if successful, locate disk label within block and validate */ + error = biowait(bp); + if (!error) { + /* Save the whole block in case it has info we need. */ + bcopy(bp->b_un.b_addr, clp->cd_block, sizeof(clp->cd_block)); + } + bp->b_flags = B_INVAL | B_AGE | B_READ; + brelse(bp); + if (error) + return ("disk label read error"); + + /* Check for a UniOS-B disk label (for PROM compatibility). */ + slp = (struct sun_disklabel *)clp->cd_block; + if (slp->sl_magic == OM_DKMAGIC) { + return (disklabel_om_to_bsd(clp->cd_block, lp)); + } + + /* Check for a NetBSD disk label (PROM can not boot it). */ + dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET); + if (dlp->d_magic == DISKMAGIC) { + if (dkcksum(dlp)) + return ("NetBSD disk label corrupted"); + *lp = *dlp; /* struct assignment */ + return (NULL); + } + + memset(clp->cd_block, 0, sizeof(clp->cd_block)); + return ("no disk label"); +} + +/* + * Check new disk label for sensibility + * before setting it. + */ +int +setdisklabel(olp, nlp, openmask, clp) + struct disklabel *olp, *nlp; + u_long openmask; + struct cpu_disklabel *clp; +{ + struct partition *opp, *npp; + int i; + + /* sanity clause */ + if ((nlp->d_secpercyl == 0) || (nlp->d_secsize == 0) || + (nlp->d_secsize % DEV_BSIZE) != 0) + return(EINVAL); + + /* special case to allow disklabel to be invalidated */ + if (nlp->d_magic == 0xffffffff) { + *olp = *nlp; + return (0); + } + + if (nlp->d_magic != DISKMAGIC || + nlp->d_magic2 != DISKMAGIC || + dkcksum(nlp) != 0) + return (EINVAL); + + while (openmask != 0) { + i = ffs(openmask) - 1; + openmask &= ~(1 << i); + if (nlp->d_npartitions <= i) + return (EBUSY); + opp = &olp->d_partitions[i]; + npp = &nlp->d_partitions[i]; + if (npp->p_offset != opp->p_offset || + npp->p_size < opp->p_size) + return (EBUSY); + } + + /* We did not modify the new label, so the checksum is OK. */ + *olp = *nlp; + return (0); +} + + +/* + * Write disk label back to device after modification. + * Current label is already in clp->cd_block[] + */ +int +writedisklabel(dev, strat, lp, clp) + dev_t dev; + void (*strat) __P((struct buf *)); + struct disklabel *lp; + struct cpu_disklabel *clp; +{ + struct buf *bp; + int error; + + error = disklabel_bsd_to_om(lp, clp->cd_block); + if (error) + return(error); + +#if 0 /* XXX - Allow writing NetBSD disk labels? */ + { + struct disklabel *dlp; + dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET); + *dlp = *lp; /* struct assignment */ + } +#endif + + /* Get a buffer and copy the new label into it. */ + bp = geteblk((int)lp->d_secsize); + bcopy(clp->cd_block, bp->b_un.b_addr, sizeof(clp->cd_block)); + + /* Write out the updated label. */ + bp->b_dev = dev; + bp->b_blkno = LABELSECTOR; + bp->b_cylin = 0; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_WRITE; + (*strat)(bp); + error = biowait(bp); + brelse(bp); + + return (error); +} + +/* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. Adjust transfer + * if needed, and signal errors or early completion. + */ +int +bounds_check_with_label(bp, lp, wlabel) + struct buf *bp; + struct disklabel *lp; + int wlabel; +{ + struct partition *p; + int sz, maxsz; + + p = lp->d_partitions + dkpart(bp->b_dev); + maxsz = p->p_size; + sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; + + /* overwriting disk label ? */ + /* XXX should also protect bootstrap in first 8K */ + /* XXX PR#2598: labelsect is always sector zero. */ + if (((bp->b_blkno + p->p_offset) <= LABELSECTOR) && + ((bp->b_flags & B_READ) == 0) && (wlabel == 0)) + { + bp->b_error = EROFS; + goto bad; + } + + /* beyond partition? */ + if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { + /* if exactly at end of disk, return an EOF */ + if (bp->b_blkno == maxsz) { + bp->b_resid = bp->b_bcount; + return(0); + } + /* or truncate if part of it fits */ + sz = maxsz - bp->b_blkno; + if (sz <= 0) { + bp->b_error = EINVAL; + goto bad; + } + bp->b_bcount = sz << DEV_BSHIFT; + } + + /* calculate cylinder for disksort to order transfers with */ + bp->b_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl; + return(1); + +bad: + bp->b_flags |= B_ERROR; + return(-1); +} + +/* + * This function appears to be called by each disk driver. + * Aparently this is to give this MD code a chance to do + * additional "device registration" types of work. (?) + * For example, the sparc port uses this to record the + * device node for the PROM-specified boot device. + */ +void +dk_establish(dk, dev) + struct disk *dk; + struct device *dev; +{ +} + +/************************************************************************ + * + * The rest of this was taken from arch/sparc/scsi/sun_disklabel.c + * and then substantially rewritten by Gordon W. Ross + * + ************************************************************************/ + +/* What partition types to assume for Sun disklabels: */ +static u_char +sun_fstypes[8] = { + FS_BSDFFS, /* a */ + FS_SWAP, /* b */ + FS_OTHER, /* c - whole disk */ + FS_BSDFFS, /* d */ + FS_BSDFFS, /* e */ + FS_BSDFFS, /* f */ + FS_BSDFFS, /* g */ + FS_BSDFFS, /* h */ +}; + +/* + * Given a UniOS-B disk label, set lp to a BSD disk label. + * Returns NULL on success, else an error string. + * + * The BSD label is cleared out before this is called. + */ +static char * +disklabel_om_to_bsd(cp, lp) + char *cp; + struct disklabel *lp; +{ + struct sun_disklabel *sl; + struct partition *npp; + struct sun_dkpart *spp; + int i, secpercyl; + u_short cksum, *sp1, *sp2; + + sl = (struct sun_disklabel *)cp; + + /* Verify the XOR check. */ + sp1 = (u_short *)sl; + sp2 = (u_short *)(sl + 1); + cksum = 0; + while (sp1 < sp2) + cksum ^= *sp1++; + if (cksum != 0) + return ("UNIOS-B disk label, bad checksum"); + + memset((caddr_t)lp, 0, sizeof(struct disklabel)); + + /* Format conversion. */ + lp->d_magic = DISKMAGIC; + lp->d_magic2 = DISKMAGIC; + memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); + + lp->d_type = DTYPE_SCSI; + lp->d_secsize = 512; + lp->d_nsectors = sl->sl_nsectors; + lp->d_ntracks = sl->sl_ntracks; + lp->d_ncylinders = sl->sl_ncylinders; + + secpercyl = sl->sl_nsectors * sl->sl_ntracks; + lp->d_secpercyl = secpercyl; + lp->d_secperunit = secpercyl * sl->sl_ncylinders; + + lp->d_rpm = 3600; /* XXX */ + lp->d_interleave = 1; /* XXX */ + + lp->d_npartitions = 8; + /* These are as defined in <ufs/ffs/fs.h> */ + lp->d_bbsize = 8192; /* XXX */ + lp->d_sbsize = 8192; /* XXX */ + + for (i = 0; i < 8; i++) { + spp = &sl->sl_part[i]; + npp = &lp->d_partitions[i]; + npp->p_offset = spp->sdkp_cyloffset * secpercyl; + npp->p_size = spp->sdkp_nsectors; + if (npp->p_size == 0) + npp->p_fstype = FS_UNUSED; + else { + /* Partition has non-zero size. Set type, etc. */ + npp->p_fstype = sun_fstypes[i]; + /* + * The sun label does not store the FFS fields, + * so just set them with default values here. + * XXX: This keeps newfs from trying to rewrite + * XXX: the disk label in the most common case. + * XXX: (Should remove that code from newfs...) + */ + if (npp->p_fstype == FS_BSDFFS) { + npp->p_fsize = 1024; + npp->p_frag = 8; + npp->p_cpg = 16; + } + } + } + + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + + return (NULL); +} + +/* + * Given a BSD disk label, update the Sun disklabel + * pointed to by cp with the new info. Note that the + * Sun disklabel may have other info we need to keep. + * Returns zero or error code. + */ +static int +disklabel_bsd_to_om(lp, cp) + struct disklabel *lp; + char *cp; +{ + struct sun_disklabel *sl; + struct partition *npp; + struct sun_dkpart *spp; + int i, secpercyl; + u_short cksum, *sp1, *sp2; + + if (lp->d_secsize != 512) + return (EINVAL); + + sl = (struct sun_disklabel *)cp; + + /* Format conversion. */ + memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname)); +#if 0 + sl->sl_rpm = lp->d_rpm; + sl->sl_pcyl = lp->d_ncylinders + lp->d_acylinders; /* XXX */ + sl->sl_sparespercyl = lp->d_sparespercyl; + sl->sl_interleave = lp->d_interleave; +#endif + sl->sl_ncylinders = lp->d_ncylinders; +#if 0 + sl->sl_acylinders = lp->d_acylinders; +#endif + sl->sl_ntracks = lp->d_ntracks; + sl->sl_nsectors = lp->d_nsectors; + + secpercyl = sl->sl_nsectors * sl->sl_ntracks; + for (i = 0; i < 8; i++) { + spp = &sl->sl_part[i]; + npp = &lp->d_partitions[i]; + + if (npp->p_offset % secpercyl) + return (EINVAL); + spp->sdkp_cyloffset = npp->p_offset / secpercyl; + spp->sdkp_nsectors = npp->p_size; + } + sl->sl_magic = OM_DKMAGIC; + + /* Correct the XOR check. */ + sp1 = (u_short *)sl; + sp2 = (u_short *)(sl + 1); + sl->sl_cksum = cksum = 0; + while (sp1 < sp2) + cksum ^= *sp1++; + sl->sl_cksum = cksum; + + return (0); +} + +/* + * Search the bad sector table looking for the specified sector. + * Return index if found. + * Return -1 if not found. + */ +int +isbad(bt, cyl, trk, sec) + register struct dkbad *bt; + int cyl, trk, sec; +{ + 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); +} diff --git a/sys/arch/luna68k/luna68k/genassym.cf b/sys/arch/luna68k/luna68k/genassym.cf new file mode 100644 index 00000000000..c2e76bff560 --- /dev/null +++ b/sys/arch/luna68k/luna68k/genassym.cf @@ -0,0 +1,205 @@ +# $NetBSD: genassym.cf,v 1.1 2000/01/05 08:49:03 nisimura Exp $ + +# +# Copyright (c) 1982, 1990, 1993 +# The Regents of the University of California. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by the University of +# California, Berkeley and its contributors. +# 4. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)genassym.c 8.3 (Berkeley) 1/4/94 +# + +include "opt_compat_svr4.h" + +include <sys/param.h> +include <sys/buf.h> +include <sys/map.h> +include <sys/proc.h> +include <sys/mbuf.h> +include <sys/msgbuf.h> +include <sys/syscall.h> +include <sys/user.h> + +include <vm/vm.h> + +include <uvm/uvm_extern.h> + +ifdef COMPAT_SVR4 +include <compat/svr4/svr4_syscall.h> +include <compat/svr4/svr4_ucontext.h> +endif + +include <machine/cpu.h> +include <machine/psl.h> +include <machine/reg.h> +include <machine/pte.h> + +# values for mmutype +define MMU_68030 MMU_68030 +define MMU_68851 MMU_68851 +define MMU_68040 MMU_68040 + +# values for cputype +define CPU_68020 CPU_68020 +define CPU_68030 CPU_68030 +define CPU_68040 CPU_68040 + +# CPU configuration options +ifdef M68020 +define M68020 1 +endif +ifdef M68030 +define M68030 1 +endif +ifdef M68040 +define M68040 1 +endif + +# values for fputype +define FPU_NONE FPU_NONE +define FPU_68881 FPU_68881 +define FPU_68882 FPU_68882 +define FPU_68040 FPU_68040 + +# values for ectype +define EC_PHYS EC_PHYS +define EC_NONE EC_NONE +define EC_VIRT EC_VIRT + +# general constants +define UPAGES UPAGES +define USPACE USPACE +define NBPG NBPG +define PGSHIFT PGSHIFT +define USRSTACK USRSTACK + +# proc fields and values +define P_FORW offsetof(struct proc, p_forw) +define P_BACK offsetof(struct proc, p_back) +define P_VMSPACE offsetof(struct proc, p_vmspace) +define P_ADDR offsetof(struct proc, p_addr) +define P_PRIORITY offsetof(struct proc, p_priority) +define P_STAT offsetof(struct proc, p_stat) +define P_WCHAN offsetof(struct proc, p_wchan) +define P_MD_FLAGS offsetof(struct proc, p_md.md_flags) +define P_MD_REGS offsetof(struct proc, p_md.md_regs) +define SSLEEP SSLEEP +define SRUN SRUN + +# interrupt/fault metering +define UVMEXP_INTRS offsetof(struct uvmexp, intrs) + +define T_BUSERR T_BUSERR +define T_ADDRERR T_ADDRERR +define T_ILLINST T_ILLINST +define T_ZERODIV T_ZERODIV +define T_CHKINST T_CHKINST +define T_TRAPVINST T_TRAPVINST +define T_PRIVINST T_PRIVINST +define T_TRACE T_TRACE +define T_MMUFLT T_MMUFLT +define T_SSIR T_SSIR +define T_FMTERR T_FMTERR +define T_COPERR T_COPERR +define T_FPERR T_FPERR +define T_ASTFLT T_ASTFLT +define T_TRAP15 T_TRAP15 +define T_FPEMULI T_FPEMULI +define T_FPEMULD T_FPEMULD + +# PSL values (should just include psl.h?) +define PSL_S PSL_S +define PSL_IPL7 PSL_IPL7 +define PSL_LOWIPL PSL_LOWIPL +define PSL_HIGHIPL PSL_HIGHIPL +define PSL_USER PSL_USER +define PSL_TS PSL_T | PSL_S +define SPL1 PSL_S | PSL_IPL1 +define SPL2 PSL_S | PSL_IPL2 +define SPL3 PSL_S | PSL_IPL3 +define SPL4 PSL_S | PSL_IPL4 +define SPL5 PSL_S | PSL_IPL5 +define SPL6 PSL_S | PSL_IPL6 + +# magic +define FC_USERD FC_USERD +define FC_SUPERD FC_SUPERD +define CACHE_ON CACHE_ON +define CACHE_OFF CACHE_OFF +define CACHE_CLR CACHE_CLR +define IC_CLEAR IC_CLEAR +define DC_CLEAR DC_CLEAR + +# pte/ste bits +define PG_V PG_V +define PG_NV PG_NV +define PG_RO PG_RO +define PG_RW PG_RW +define PG_CI PG_CI +define PG_PROT PG_PROT +define PG_FRAME PG_FRAME +define SG_V SG_V +define SG_NV SG_NV +define SG_RW SG_RW +define SG_FRAME SG_FRAME +define SG_ISHIFT SG_ISHIFT + +# pcb fields +define PCB_PS offsetof(struct pcb, pcb_ps) +define PCB_USP offsetof(struct pcb, pcb_usp) +define PCB_REGS offsetof(struct pcb, pcb_regs) +define PCB_ONFAULT offsetof(struct pcb, pcb_onfault) +define PCB_FPCTX offsetof(struct pcb, pcb_fpregs) +define SIZEOF_PCB sizeof(struct pcb) + +# exception frame offset/sizes +define FR_SP offsetof(struct frame, f_regs[15]) +define FR_HW offsetof(struct frame, f_sr) +define FR_ADJ offsetof(struct frame, f_stackadj) +define FR_SIZE sizeof(struct trapframe) + +# system calls +define SYS_exit SYS_exit +define SYS_execve SYS_execve +define SYS___sigreturn14 SYS___sigreturn14 +define SYS_compat_13_sigreturn13 SYS_compat_13_sigreturn13 + +# errno +define EFAULT EFAULT +define ENAMETOOLONG ENAMETOOLONG + +# SVR4 binary compatibility +ifdef COMPAT_SVR4 +define SVR4_SIGF_HANDLER offsetof(struct svr4_sigframe, sf_handler) +define SVR4_SIGF_UC offsetof(struct svr4_sigframe, sf_uc) +define SVR4_SYS_context SVR4_SYS_context +define SVR4_SYS_exit SVR4_SYS_exit +define SVR4_SETCONTEXT SVR4_SETCONTEXT +endif + diff --git a/sys/arch/luna68k/luna68k/isr.c b/sys/arch/luna68k/luna68k/isr.c new file mode 100644 index 00000000000..917c82955f3 --- /dev/null +++ b/sys/arch/luna68k/luna68k/isr.c @@ -0,0 +1,356 @@ +/* $NetBSD: isr.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ +/* $NetBSD: isr.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Adam Glass, Gordon W. Ross, and Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: isr.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $"); + +/* + * Link and dispatch interrupts. + */ + +#include "opt_inet.h" +#include "opt_atalk.h" +#include "opt_ccitt.h" +#include "opt_iso.h" +#include "opt_ns.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/vmmeter.h> + +#include <vm/vm.h> + +#include <uvm/uvm_extern.h> + +#include <net/netisr.h> + +#include <machine/cpu.h> + +#include <luna68k/luna68k/isr.h> + +isr_autovec_list_t isr_autovec[NISRAUTOVEC]; +struct isr_vectored isr_vectored[NISRVECTORED]; + +extern int intrcnt[]; /* from locore.s */ +extern void (*vectab[]) __P((void)); +extern void badtrap __P((void)); +extern void intrhand_vectored __P((void)); + +extern int getsr __P((void)); /* in locore.s */ + +void +isrinit() +{ + int i; + + /* Initialize the autovector lists. */ + for (i = 0; i < NISRAUTOVEC; ++i) { + LIST_INIT(&isr_autovec[i]); + } +} + +/* + * Establish an autovectored interrupt handler. + * Called by driver attach functions. + */ +void +isrlink_autovec(func, arg, ipl, priority) + int (*func) __P((void *)); + void *arg; + int ipl; + int priority; +{ + struct isr_autovec *newisr, *curisr; + isr_autovec_list_t *list; + + if ((ipl < 0) || (ipl >= NISRAUTOVEC)) + panic("isrlink_autovec: bad ipl %d", ipl); + + newisr = (struct isr_autovec *)malloc(sizeof(struct isr_autovec), + M_DEVBUF, M_NOWAIT); + if (newisr == NULL) + panic("isrlink_autovec: can't allocate space for isr"); + + /* Fill in the new entry. */ + newisr->isr_func = func; + newisr->isr_arg = arg; + newisr->isr_ipl = ipl; + newisr->isr_priority = priority; + + /* + * Some devices are particularly sensitive to interrupt + * handling latency. The SCC, for example, can lose many + * characters if its interrupt isn't handled with reasonable + * speed. + * + * To work around this problem, each device can give itself a + * "priority". An unbuffered SCC would give itself a higher + * priority than a SCSI device, for example. + * + * This solution was originally developed for the hp300, which + * has a flat spl scheme (by necessity). Thankfully, the + * MVME systems don't have this problem, though this may serve + * a useful purpose in any case. + */ + + /* + * Get the appropriate ISR list. If the list is empty, no + * additional work is necessary; we simply insert ourselves + * at the head of the list. + */ + list = &isr_autovec[ipl]; + if (list->lh_first == NULL) { + LIST_INSERT_HEAD(list, newisr, isr_link); + return; + } + + /* + * A little extra work is required. We traverse the list + * and place ourselves after any ISRs with our current (or + * higher) priority. + */ + for (curisr = list->lh_first; curisr->isr_link.le_next != NULL; + curisr = curisr->isr_link.le_next) { + if (newisr->isr_priority > curisr->isr_priority) { + LIST_INSERT_BEFORE(curisr, newisr, isr_link); + return; + } + } + + /* + * We're the least important entry, it seems. We just go + * on the end. + */ + LIST_INSERT_AFTER(curisr, newisr, isr_link); +} + +/* + * Establish a vectored interrupt handler. + * Called by bus interrupt establish functions. + */ +void +isrlink_vectored(func, arg, ipl, vec) + int (*func) __P((void *)); + void *arg; + int ipl, vec; +{ + struct isr_vectored *isr; + + if ((ipl < 0) || (ipl >= NISRAUTOVEC)) + panic("isrlink_vectored: bad ipl %d", ipl); + if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) + panic("isrlink_vectored: bad vec 0x%x", vec); + + isr = &isr_vectored[vec - ISRVECTORED]; + + if ((vectab[vec] != badtrap) || (isr->isr_func != NULL)) + panic("isrlink_vectored: vec 0x%x not available", vec); + + /* Fill in the new entry. */ + isr->isr_func = func; + isr->isr_arg = arg; + isr->isr_ipl = ipl; + + /* Hook into the vector table. */ + vectab[vec] = intrhand_vectored; +} + +/* + * Unhook a vectored interrupt. + */ +void +isrunlink_vectored(vec) + int vec; +{ + + if ((vec < ISRVECTORED) || (vec >= ISRVECTORED + NISRVECTORED)) + panic("isrunlink_vectored: bad vec 0x%x", vec); + + if (vectab[vec] != intrhand_vectored) + panic("isrunlink_vectored: not vectored interrupt"); + + vectab[vec] = badtrap; + bzero(&isr_vectored[vec - ISRVECTORED], sizeof(struct isr_vectored)); +} + +/* + * This is the dispatcher called by the low-level + * assembly language autovectored interrupt routine. + */ +void +isrdispatch_autovec(evec) + int evec; /* format | vector offset */ +{ + struct isr_autovec *isr; + isr_autovec_list_t *list; + int handled = 0, ipl, vec; + static int straycount, unexpected; + + vec = (evec & 0xfff) >> 2; + if ((vec < ISRAUTOVEC) || (vec >= (ISRAUTOVEC + NISRAUTOVEC))) + panic("isrdispatch_autovec: bad vec 0x%x\n", vec); + ipl = vec - ISRAUTOVEC; + + intrcnt[ipl]++; + uvmexp.intrs++; + + list = &isr_autovec[ipl]; + if (list->lh_first == NULL) { + printf("isrdispatch_autovec: ipl %d unexpected\n", ipl); + if (++unexpected > 10) + panic("too many unexpected interrupts"); + return; + } + + /* Give all the handlers a chance. */ + for (isr = list->lh_first ; isr != NULL; isr = isr->isr_link.le_next) + handled |= (*isr->isr_func)(isr->isr_arg); + + if (handled) + straycount = 0; + else if (++straycount > 50) + panic("isr_dispatch_autovec: too many stray interrupts"); + else + printf("isrdispatch_autovec: stray level %d interrupt\n", ipl); +} + +/* + * This is the dispatcher called by the low-level + * assembly language vectored interrupt routine. + */ +void +isrdispatch_vectored(pc, evec, frame) + int pc, evec; + void *frame; +{ + struct isr_vectored *isr; + int ipl, vec; + + vec = (evec & 0xfff) >> 2; + ipl = (getsr() >> 8) & 7; + + intrcnt[ipl]++; + uvmexp.intrs++; + + if ((vec < ISRVECTORED) || (vec >= (ISRVECTORED + NISRVECTORED))) + panic("isrdispatch_vectored: bad vec 0x%x\n", vec); + isr = &isr_vectored[vec - ISRVECTORED]; + + if (isr->isr_func == NULL) { + printf("isrdispatch_vectored: no handler for vec 0x%x\n", vec); + vectab[vec] = badtrap; + return; + } + + /* + * Handler gets exception frame if argument is NULL. + */ + if ((*isr->isr_func)(isr->isr_arg ? isr->isr_arg : frame) == 0) + printf("isrdispatch_vectored: vec 0x%x not claimed\n", vec); +} + +/* + * XXX Why on earth isn't this in a common file?! + */ +void netintr __P((void)); +void arpintr __P((void)); +void atintr __P((void)); +void ipintr __P((void)); +void ip6intr __P((void)); +void nsintr __P((void)); +void clnlintr __P((void)); +void ccittintr __P((void)); +void pppintr __P((void)); + +void +netintr() +{ +#ifdef INET +#include "arp.h" +#if NARP > 0 + if (netisr & (1 << NETISR_ARP)) { + netisr &= ~(1 << NETISR_ARP); + arpintr(); + } +#endif + if (netisr & (1 << NETISR_IP)) { + netisr &= ~(1 << NETISR_IP); + ipintr(); + } +#endif +#ifdef INET6 + if (netisr & (1 << NETISR_IPV6)) { + netisr &= ~(1 << NETISR_IPV6); + ip6intr(); + } +#endif +#ifdef NETATALK + if (netisr & (1 << NETISR_ATALK)) { + netisr &= ~(1 << NETISR_ATALK); + atintr(); + } +#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 +#ifdef CCITT + if (netisr & (1 << NETISR_CCITT)) { + netisr &= ~(1 << NETISR_CCITT); + ccittintr(); + } +#endif +#include "ppp.h" +#if NPPP > 0 + if (netisr & (1 << NETISR_PPP)) { + netisr &= ~(1 << NETISR_PPP); + pppintr(); + } +#endif +} diff --git a/sys/arch/luna68k/luna68k/isr.h b/sys/arch/luna68k/luna68k/isr.h new file mode 100644 index 00000000000..a1faca6cb47 --- /dev/null +++ b/sys/arch/luna68k/luna68k/isr.h @@ -0,0 +1,92 @@ +/* $NetBSD: isr.h,v 1.1 2000/01/05 08:49:04 nisimura Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/queue.h> + +/* + * The location and size of the autovectored interrupt portion + * of the vector table. + */ +#define ISRAUTOVEC 0x18 +#define NISRAUTOVEC 8 + +/* + * The location and size of the vectored interrupt portion + * of the vector table. + */ +#define ISRVECTORED 0x40 +#define NISRVECTORED 192 + +/* + * Autovectored interupt handler cookie. + */ +struct isr_autovec { + LIST_ENTRY(isr_autovec) isr_link; + int (*isr_func) __P((void *)); + void *isr_arg; + int isr_ipl; + int isr_priority; +}; + +typedef LIST_HEAD(, isr_autovec) isr_autovec_list_t; + +/* + * Vectored interrupt handler cookie. The handler may request to + * receive the exception frame as an argument by specifying NULL + * when establishing the interrupt. + */ +struct isr_vectored { + int (*isr_func) __P((void *)); + void *isr_arg; + int isr_ipl; +}; + +/* + * Autovectored ISR priorities. These are not the same as interrupt levels. + */ +#define ISRPRI_BIO 0 +#define ISRPRI_NET 1 +#define ISRPRI_TTY 2 +#define ISRPRI_TTYNOBUF 3 + +void isrinit __P((void)); +void isrlink_autovec __P((int (*)(void *), void *, int, int)); +void isrlink_vectored __P((int (*)(void *), void *, int, int)); +void isrunlink_vectored __P((int)); +void isrdispatch_autovec __P((int)); +void isrdispatch_vectored __P((int, int, void *)); diff --git a/sys/arch/luna68k/luna68k/locore.s b/sys/arch/luna68k/luna68k/locore.s new file mode 100644 index 00000000000..ddc4629fc2f --- /dev/null +++ b/sys/arch/luna68k/luna68k/locore.s @@ -0,0 +1,1427 @@ +/* $NetBSD: locore.s,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1980, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: locore.s 1.66 92/12/22$ + * + * @(#)locore.s 8.6 (Berkeley) 5/27/94 + */ + +#include "opt_compat_netbsd.h" +#include "opt_ddb.h" + +#include "assym.h" +#include <machine/asm.h> +#include <machine/trap.h> + +#define PRINT(msg) \ + pea 9f ; \ + jbsr _C_LABEL(printf); \ + addl #4,sp ; \ + .data ; \ + 9: .asciz msg ; \ + .text +#undef PRINT + +/* + * Temporary stack for a variety of purposes. + * Try and make this the first thing is the data segment so it + * is page aligned. Note that if we overflow here, we run into + * our text segment. + */ + .data + .space NBPG +ASLOCAL(tmpstk) + +#include <luna68k/luna68k/vectors.s> + +/* + * Macro to relocate a symbol, used before MMU is enabled. + */ +#define _RELOC(var,ar) \ + lea var,ar; \ + addl a5,ar +#define RELOC(var,ar) _RELOC(_C_LABEL(var), ar) +#define ASRELOC(var,ar) _RELOC(_ASM_LABEL(var), ar) + +BSS(lowram,4) +BSS(esym,4) + +/* + * This is for kvm_mkdb, and should be the address of the beginning + * of the kernel text segment (not necessarily the same as kernbase). + */ + .text +GLOBAL(kernel_text) + +/* + * start of kernel and .text! + */ +ASENTRY_NOPROFILE(start) + movw #PSL_HIGHIPL,sr | no interrupts + movl #0,a5 | RAM starts at 0 + ASRELOC(tmpstk,a0) + movl a0,sp | give ourselves a temporary stack + +#if 0 /* not sure useful values, need a bootloader tailored for us */ + RELOC(boothowto,a0) + movl d7,a0@ | save boothowto + RELOC(bootdev,a0) + movl d6,a0@ | save bootdev + RELOC(esym,a0) + movl d5,a0@ | save esym +#endif + RELOC(edata,a0) | clear out BSS + movl #_C_LABEL(end)-4,d0 | (must be <= 256 kB) + subl #_C_LABEL(edata),d0 + lsrl #2,d0 +1: clrl a0@+ + dbra d0,1b + +#if 1 + RELOC(esym,a0) + clrl a0@ | store end of symbol table XXX +#endif + RELOC(lowram,a0) + movl a5,a0@ | store start of physical memory + + movl #0x41000000,a0 | available memory in bytes + movl a0@(12),a0 | (int *)base[3]) + movl a0@,d5 + RELOC(memavail,a0) + movl d5, a0@ | save memavail + + movl #0x41000000,a0 | planemask; 0x0f or 0xff + movl a0@(184),a0 | (int *)base[46] + movl a0@,d5 + RELOC(hwplanemask,a0) + movl d5,a0@ | save hwplanemask + + movl #0x41000000,a0 | argument of 'x' command on boot + movl a0@(212),a0 | (char *)base[53] + RELOC(bootarg, a1) + movl #63,d0 +1: movb a0@+,a1@+ | copy to bootarg + dbra d0,1b | upto 63 characters + + movl #CACHE_OFF,d0 + movc d0,cacr | clear and disable on-chip cache(s) + +/* determine our CPU/MMU combo - check for all regardless of kernel config */ + movl #0x200,d0 | data freeze bit + movc d0,cacr | only exists on 68030 + movc cacr,d0 | read it back + tstl d0 | zero? + jeq Lnot68030 | yes, we have 68040 + movl #CPU_68030,d0 + movl #MMU_68030,d1 + movl #FPU_68881,d2 + jra Lstart0 +Lnot68030: + movl #CPU_68040,d0 + movl #MMU_68040,d1 + movl #FPU_68040,d2 +Lstart0: + RELOC(cputype,a0) + movl d0,a0@ + RELOC(mmutype,a0) + movl d1,a0@ + RELOC(fputype,a0) + movl d2,a0@ + + /* + * Now that we know what CPU we have, initialize the address error + * and bus error handlers in the vector table: + * + * vectab+8 bus error + * vectab+12 address error + */ + lea _C_LABEL(cputype),a0 + lea _C_LABEL(vectab),a2 +#if defined(M68040) + cmpl #CPU_68040,a0@ | 68040? + jne 1f | no, skip + movl #_C_LABEL(buserr40),a2@(8) + movl #_C_LABEL(addrerr4060),a2@(12) + jra Lstart2 +1: +#endif + cmpl #CPU_68030,a0@ | 68030? + jne 1f | no, skip + movl #_C_LABEL(busaddrerr2030),a2@(8) + movl #_C_LABEL(busaddrerr2030),a2@(12) + jra Lstart2 +1: + /* Config botch; no hope. */ + PANIC("Config botch in locore") + +Lstart2: +/* 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 +/* initialize memory sizes (for pmap_bootstrap) */ + RELOC(memavail,a0) + movl a0@,d1 + moveq #PGSHIFT,d2 + lsrl d2,d1 | convert to page (click) number + RELOC(maxmem,a0) + movl d1,a0@ | save as maxmem + RELOC(physmem,a0) + movl d1,a0@ | and physmem +/* configure kernel and proc0 VA space so we can get going */ +#ifdef DDB + RELOC(esym,a0) | end of static kernel test/data/syms + movl a0@,d2 + jne Lstart3 +#endif + RELOC(end,a0) + movl a0,d2 | end of static kernel text/data +Lstart3: + addl #NBPG-1,d2 + andl #PG_FRAME,d2 | round to a page + movl d2,a4 + addl a5,a4 | convert to PA + pea a5@ | firstpa + pea a4@ | nextpa + RELOC(pmap_bootstrap,a0) + jbsr a0@ | pmap_bootstrap(firstpa, nextpa) + addql #8,sp +/* + * Enable the MMU. + * Since the kernel is mapped logical == physical, we just turn it on. + */ + RELOC(Sysseg,a0) | system segment table addr + movl a0@,d1 | read value (a KVA) + addl a5,d1 | convert to PA (a5 == 0, indeed) +#if defined(M68040) + RELOC(mmutype,a0) + cmpl #MMU_68040,a0@ | 68040? + jne Lmotommu1 | no, skip +Lmotommu0: + .long 0x4e7b1807 | movc d1,srp + RELOC(proto040tt0,a0) + movl a0@,d0 | tt0 range 4000.0000-7fff.ffff + .long 0x4e7b0004 | movc d0,itt0 + .long 0x4e7b0006 | movc d0,dtt0 + RELOC(proto040tt1,a0) + movl a0@,d0 | tt1 range 8000.0000-feff.ffff + .long 0x4e7b0005 | movc d0,itt1 + .long 0x4e7b0007 | movc d0,dtt1 + .word 0xf4d8 | cinva bc + pflusha | flush entire TLB + RELOC(proto040tc,a0) + movl a0@,d0 + .long 0x4e7b0003 | movc d0,tc + movl #0x80008000,d0 + movc d0,cacr | turn on both caches + jmp Lenab1 +Lmotommu1: +#endif + RELOC(protosrp,a0) | nolimit + share global + 4 byte PTEs + movl d1,a0@(4) | + segtable address + RELOC(protocrp,a1) + movl d1,a1@(4) | set lower half of CRP + pmove a0@,srp | load the supervisor root pointer + RELOC(protott0,a0) | tt0 range 4000.0000-7fff.ffff + .long 0xf0100800 | pmove a0@,mmutt0 + RELOC(protott1,a0) | tt1 range 8000.0000-ffff.ffff + .long 0xf0100c00 | pmove a0@,mmutt1 + RELOC(prototc,a0) | tc: SRP,CRP,4KB page,A=10bit,B=10bit + pmove a0@,tc +/* + * Should be running mapped from this point on + */ +Lenab1: +/* select the software page size now */ + lea _ASM_LABEL(tmpstk),sp | temporary stack + jbsr _C_LABEL(uvm_setpagesize) | select software page size + +/* set kernel stack, user SP, proc0, and initial pcb */ + movl _C_LABEL(proc0paddr),a1 | get proc0 pcb addr + lea a1@(USPACE-4),sp | set kernel stack to end of area + lea _C_LABEL(proc0),a2 | initialize proc0.p_addr so that + movl a1,a2@(P_ADDR) | we don't deref NULL in trap() + movl #USRSTACK-4,a2 + movl a2,usp | init user SP + movl a1,_C_LABEL(curpcb) | proc0 is running + + tstl _C_LABEL(fputype) | Have an FPU? + jeq Lenab2 | No, skip. + clrl a1@(PCB_FPCTX) | ensure null FP context + movl a1,sp@- + jbsr _C_LABEL(m68881_restore) | restore it (does not kill a1) + addql #4,sp +Lenab2: + pflusha | flush entire TLB + cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? + jeq Lenab3 | yes, cache already on + tstl _C_LABEL(mmutype) + jpl Lenab3 | 68851 implies no d-cache + movl #CACHE_ON,d0 + movc d0,cacr | clear cache(s) +Lenab3: + +/* final setup for C code */ + movl #_C_LABEL(vectab),d0 | get our VBR address + movc d0,vbr + jbsr _C_LABEL(luna68k_init) | additional pre-main initialization + +/* + * Create a fake exception frame that returns to user mode, + * and save its address in p->p_md.md_regs for cpu_fork(). + * The new frames for process 1 and 2 will be adjusted by + * cpu_set_kpc() to arrange for a call to a kernel function + * before the new process does its rte out to user mode. + */ + 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 and padding + lea sp@(-64),sp | construct space for D0-D7/A0-A7 + lea _C_LABEL(proc0),a0 | save pointer to frame + movl sp,a0@(P_MD_REGS) | in proc0.p_md.md_regs + jra _C_LABEL(main) | main() + PANIC("main() returned") + /* NOTREACHED */ + +/* + * proc_trampoline: call function in register a2 with a3 as an arg + * and then rei. + */ +GLOBAL(proc_trampoline) + movl a3,sp@- | process' frame pointer in sp + jbsr a2@ + addql #4,sp + movl sp@(FR_SP),a0 | grab and load + movl a0,usp | user SP + moveml sp@+,#0x7FFF | restore most user regs + addql #8,sp | toss SP and stack adjust + jra _ASM_LABEL(rei) | and return + +/* + * Trap/interrupt vector routines + */ +#include <m68k/m68k/trap_subr.s> + + .data +GLOBAL(m68k_fault_addr) + .long 0 + +#if defined(M68040) || defined(M68060) +ENTRY_NOPROFILE(addrerr4060) + 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 sp@(FR_HW+8),sp@- + clrl sp@- | dummy code + movl #T_ADDRERR,sp@- | mark address error + jra _ASM_LABEL(faultstkadj) | and deal with it +#endif + +#if defined(M68060) +ENTRY_NOPROFILE(buserr60) + 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 + movel sp@(FR_HW+12),d0 | FSLW + btst #2,d0 | branch prediction error? + jeq Lnobpe + movc cacr,d2 + orl #IC60_CABC,d2 | clear all branch cache entries + movc d2,cacr + movl d0,d1 + addql #1,L60bpe + andl #0x7ffd,d1 + jeq _ASM_LABEL(faultstkadjnotrap2) +Lnobpe: +| we need to adjust for misaligned addresses + movl sp@(FR_HW+8),d1 | grab VA + btst #27,d0 | check for mis-aligned access + jeq Lberr3 | no, skip + addl #28,d1 | yes, get into next page + | operand case: 3, + | instruction case: 4+12+12 + andl #PG_FRAME,d1 | and truncate +Lberr3: + movl d1,sp@- + movl d0,sp@- | code is FSLW now. + andw #0x1f80,d0 + jeq Lberr60 | it is a bus error + movl #T_MMUFLT,sp@- | show that we are an MMU fault + jra _ASM_LABEL(faultstkadj) | and deal with it +Lberr60: + tstl _C_LABEL(nofault) | catch bus error? + jeq Lisberr | no, handle as usual + movl sp@(FR_HW+8+8),_C_LABEL(m68k_fault_addr) | save fault addr + movl _C_LABEL(nofault),sp@- | yes, + jbsr _C_LABEL(longjmp) | longjmp(nofault) + /* NOTREACHED */ +#endif +#if defined(M68040) +ENTRY_NOPROFILE(buserr40) + 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 sp@(FR_HW+20),d1 | get fault address + moveq #0,d0 + movw sp@(FR_HW+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@- | pass fault address. + movl d0,sp@- | pass SSW as code + btst #10,d0 | test ATC + jeq Lberr40 | it is a bus error + movl #T_MMUFLT,sp@- | show that we are an MMU fault + jra _ASM_LABEL(faultstkadj) | and deal with it +Lberr40: + tstl _C_LABEL(nofault) | catch bus error? + jeq Lisberr | no, handle as usual + movl sp@(FR_HW+8+20),_C_LABEL(m68k_fault_addr) | save fault addr + movl _C_LABEL(nofault),sp@- | yes, + jbsr _C_LABEL(longjmp) | longjmp(nofault) + /* NOTREACHED */ +#endif + +ENTRY_NOPROFILE(busaddrerr2030) + 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 + moveq #0,d0 + movw sp@(FR_HW+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,sp@(FR_HW+10) | for hardware too +LbeX0: + btst #13,d0 | RC set? + jeq LbeX1 | no, skip + bset #15,d0 | yes, must set FC + movw d0,sp@(FR_HW+10) | for hardware too +LbeX1: + btst #8,d0 | data fault? + jeq Lbe0 | no, check for hard cases + movl sp@(FR_HW+16),d1 | fault address is as given in frame + jra Lbe10 | thats it +Lbe0: + btst #4,sp@(FR_HW+6) | long (type B) stack frame? + jne Lbe4 | yes, go handle + movl sp@(FR_HW+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 sp@(FR_HW+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 sp@(FR_HW+8+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 + movl sp@,d0 | function code from ssw + btst #8,d0 | data fault? + jne Lbe10a + movql #1,d0 | user program access FC + | (we dont seperate data/program) + btst #5,sp@(FR_HW+8) | supervisor mode? + jeq Lbe10a | if no, done + movql #5,d0 | else supervisor program access +Lbe10a: + ptestr d0,a0@,#7 | do a table search + pmove psr,sp@ | save result + movb sp@,d1 + btst #2,d1 | invalid (incl. limit viol. and berr)? + jeq Lmightnotbemerr | no -> wp check + btst #7,d1 | is it MMU table berr? + jne Lisberr1 | yes, needs not be fast. +Lismerr: + movl #T_MMUFLT,sp@- | show that we are an MMU fault + jra _ASM_LABEL(faultstkadj) | and deal with it +Lmightnotbemerr: + btst #3,d1 | write protect bit set? + jeq Lisberr1 | no: must be bus error + movl sp@,d0 | ssw into low word of d0 + andw #0xc0,d0 | Write protect is set on page: + cmpw #0x40,d0 | was it read cycle? + jne Lismerr | no, was not WPE, must be MMU fault + jra Lisberr1 | real bus err needs not be fast. +Lisaerr: + movl #T_ADDRERR,sp@- | mark address error + jra _ASM_LABEL(faultstkadj) | and deal with it +Lisberr1: + clrw sp@ | re-clear pad word + tstl _C_LABEL(nofault) | catch bus error? + jeq Lisberr | no, handle as usual + movl sp@(FR_HW+8+16),_C_LABEL(m68k_fault_addr) | save fault addr + movl _C_LABEL(nofault),sp@- | yes, + jbsr _C_LABEL(longjmp) | longjmp(nofault) + /* NOTREACHED */ + .even +Lisberr: | also used by M68040/60 + movl #T_BUSERR,sp@- | mark bus error + jra _ASM_LABEL(faultstkadj) | and deal with it + +/* + * FP exceptions. + */ +ENTRY_NOPROFILE(fpfline) +#if defined(M68040) + cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? + jne Lfp_unimp | no, skip FPSP + cmpw #0x202c,sp@(6) | format type 2? + jne _C_LABEL(illinst) | no, not an FP emulation +Ldofp_unimp: +#ifdef FPSP + jmp _ASM_LABEL(fpsp_unimp) | yes, go handle it +#endif +Lfp_unimp: +#endif /* M68040 */ +#ifdef FPU_EMULATE + clrl sp@- | stack adjust count + moveml #0xFFFF,sp@- | save registers + moveq #T_FPEMULI,d0 | denote as FP emulation trap + jra _ASM_LABEL(fault) | do it +#else + jra _C_LABEL(illinst) +#endif + +ENTRY_NOPROFILE(fpunsupp) +#if defined(M68040) + cmpl #FPU_68040,_C_LABEL(fputype) | 68040 FPU? + jne _C_LABEL(illinst) | no, treat as illinst +#ifdef FPSP + jmp _ASM_LABEL(fpsp_unsupp) | yes, go handle it +#endif +Lfp_unsupp: +#endif /* M68040 */ +#ifdef FPU_EMULATE + clrl sp@- | stack adjust count + moveml #0xFFFF,sp@- | save registers + moveq #T_FPEMULD,d0 | denote as FP emulation trap + jra _ASM_LABEL(fault) | do it +#else + jra _C_LABEL(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. + */ +ENTRY_NOPROFILE(fpfault) + 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 _C_LABEL(curpcb),a0 | current pcb + lea a0@(PCB_FPCTX),a0 | address of FP savearea + fsave a0@ | save state +#if defined(M68040) || defined(M68060) + /* always null state frame on 68040, 68060 */ + cmpl #FPU_68040,_C_LABEL(fputype) + jle Lfptnull +#endif + 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 _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup + +/* + * Other exceptions only cause four and six word stack frame and require + * no post-trap stack adjustment. + */ + +ENTRY_NOPROFILE(badtrap) + moveml #0xC0C0,sp@- | save scratch regs + movw sp@(22),sp@- | push exception vector info + clrw sp@- + movl sp@(22),sp@- | and PC + jbsr _C_LABEL(straytrap) | report + addql #8,sp | pop args + moveml sp@+,#0x0303 | restore regs + jra _ASM_LABEL(rei) | all done + +ENTRY_NOPROFILE(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 _C_LABEL(syscall) | handle it + addql #4,sp | pop syscall arg + tstl _C_LABEL(astpending) + jne Lrei2 + tstb _C_LABEL(ssir) + jeq Ltrap1 + movw #SPL1,sr + tstb _C_LABEL(ssir) + jne Lsir1 +Ltrap1: + 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 + rte + +/* + * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD) + * cachectl(command, addr, length) + * command in d0, addr in a1, length in d1 + */ +ENTRY_NOPROFILE(trap12) + movl _C_LABEL(curproc),sp@- | push curproc pointer + movl d1,sp@- | push length + movl a1,sp@- | push addr + movl d0,sp@- | push command + jbsr _C_LABEL(cachectl1) | do it + lea sp@(16),sp | pop args + jra _ASM_LABEL(rei) | all done + +/* + * Trace (single-step) trap. Kernel-mode is special. + * User mode traps are simply passed on to trap(). + */ +ENTRY_NOPROFILE(trace) + clrl sp@- | stack adjust count + moveml #0xFFFF,sp@- + moveq #T_TRACE,d0 + + | Check PSW and see what happen. + | T=0 S=0 (should not happen) + | T=1 S=0 trace trap from user mode + | T=0 S=1 trace trap on a trap instruction + | T=1 S=1 trace trap from system mode (kernel breakpoint) + + movw sp@(FR_HW),d1 | get PSW + notw d1 | XXX no support for T0 on 680[234]0 + andw #PSL_TS,d1 | from system mode (T=1, S=1)? + jeq Lkbrkpt | yes, kernel breakpoint + jra _ASM_LABEL(fault) | no, user-mode fault + +/* + * Trap 15 is used for: + * - GDB breakpoints (in user programs) + * - KGDB breakpoints (in the kernel) + * - trace traps for SUN binaries (not fully supported yet) + * User mode traps are simply passed to trap(). + */ +ENTRY_NOPROFILE(trap15) + clrl sp@- | stack adjust count + moveml #0xFFFF,sp@- + moveq #T_TRAP15,d0 + movw sp@(FR_HW),d1 | get PSW + andw #PSL_S,d1 | from system mode? + jne Lkbrkpt | yes, kernel breakpoint + jra _ASM_LABEL(fault) | no, user-mode fault + +Lkbrkpt: | Kernel-mode breakpoint or trace trap. (d0=trap_type) + | Save the system sp rather than the user sp. + movw #PSL_HIGHIPL,sr | lock out interrupts + lea sp@(FR_SIZE),a6 | Save stack pointer + movl a6,sp@(FR_SP) | from before trap + + | If were are not on tmpstk switch to it. + | (so debugger can change the stack pointer) + movl a6,d1 + cmpl #_ASM_LABEL(tmpstk),d1 + jls Lbrkpt2 | already on tmpstk + | Copy frame to the temporary stack + movl sp,a0 | a0=src + lea _ASM_LABEL(tmpstk)-96,a1 | a1=dst + movl a1,sp | sp=new frame + moveq #FR_SIZE,d1 +Lbrkpt1: + movl a0@+,a1@+ + subql #4,d1 + jgt Lbrkpt1 + +Lbrkpt2: + | Call the trap handler for the kernel debugger. + | Do not call trap() to do it, so that we can + | set breakpoints in trap() if we want. We know + | the trap type is either T_TRACE or T_BREAKPOINT. + | If we have both DDB and KGDB, let KGDB see it first, + | because KGDB will just return 0 if not connected. + | Save args in d2, a2 + movl d0,d2 | trap type + movl sp,a2 | frame ptr +#ifdef KGDB + | Let KGDB handle it (if connected) + movl a2,sp@- | push frame ptr + movl d2,sp@- | push trap type + jbsr _C_LABEL(kgdb_trap) | handle the trap + addql #8,sp | pop args + cmpl #0,d0 | did kgdb handle it? + jne Lbrkpt3 | yes, done +#endif +#ifdef DDB + | Let DDB handle it + movl a2,sp@- | push frame ptr + movl d2,sp@- | push trap type + jbsr _C_LABEL(kdb_trap) | handle the trap + addql #8,sp | pop args +#if 0 /* not needed on hp300 */ + cmpl #0,d0 | did ddb handle it? + jne Lbrkpt3 | yes, done +#endif +#endif + /* Sun 3 drops into PROM here. */ +Lbrkpt3: + | The stack pointer may have been modified, or + | data below it modified (by kgdb push call), + | so push the hardware frame at the current sp + | before restoring registers and returning. + + movl sp@(FR_SP),a0 | modified sp + lea sp@(FR_SIZE),a1 | end of our frame + movl a1@-,a0@- | copy 2 longs with + movl a1@-,a0@- | ... predecrement + movl a0,sp@(FR_SP) | sp = h/w frame + moveml sp@+,#0x7FFF | restore all but sp + movl sp@,sp | ... and sp + rte | all done + +/* Use common m68k sigreturn */ +#include <m68k/m68k/sigreturn.s> + +/* + * Interrupt handlers. + * + * For auto-vectored interrupts, the CPU provides the + * vector 0x18+level. Note we count spurious interrupts, + * but don't do anything else with them. + * + * _intrhand_autovec is the entry point for auto-vectored + * interrupts. + * + * For vectored interrupts, we pull the pc, evec, and exception frame + * and pass them to the vectored interrupt dispatcher. The vectored + * interrupt dispatcher will deal with strays. + * + * _intrhand_vectored is the entry point for vectored interrupts. + */ + +#define INTERRUPT_SAVEREG moveml #0xC0C0,sp@- +#define INTERRUPT_RESTOREREG moveml sp@+,#0x0303 + +ENTRY_NOPROFILE(spurintr) /* Level 0 */ + addql #1,_C_LABEL(intrcnt)+0 + addql #1,_C_LABEL(uvmexp)+UVMEXP_INTRS + jra _ASM_LABEL(rei) + +ENTRY_NOPROFILE(intrhand_autovec) /* Levels 1 through 6 */ + INTERRUPT_SAVEREG + movw sp@(22),sp@- | push exception vector + clrw sp@- + jbsr _C_LABEL(isrdispatch_autovec) | call dispatcher + addql #4,sp + INTERRUPT_RESTOREREG + jra _ASM_LABEL(rei) | all done + +ENTRY_NOPROFILE(lev7intr) /* Level 7: NMI */ + addql #1,_C_LABEL(intrcnt)+32 + clrl sp@- + moveml #0xFFFF,sp@- | save registers + movl usp,a0 | and save + movl a0,sp@(FR_SP) | the user stack pointer + jbsr _C_LABEL(nmihand) | call handler + movl sp@(FR_SP),a0 | restore + movl a0,usp | user SP + moveml sp@+,#0x7FFF | and remaining registers + addql #8,sp | pop SP and stack adjust + jra _ASM_LABEL(rei) | all done + +ENTRY_NOPROFILE(intrhand_vectored) + INTERRUPT_SAVEREG + lea sp@(16),a1 | get pointer to frame + movl a1,sp@- + movw sp@(26),d0 + movl d0,sp@- | push exception vector info + movl sp@(26),sp@- | and PC + jbsr _C_LABEL(isrdispatch_vectored) | call dispatcher + lea sp@(12),sp | pop value args + INTERRUPT_RESTOREREG + jra _ASM_LABEL(rei) | all done + +#if 1 /* XXX wild timer -- how can I disable/enable the interrupt? */ +ENTRY_NOPROFILE(lev5intr) + btst #7,0x63000000 | check whether system clock + beq 1f + movb #1,0x63000000 | clear the interrupt + tstl _C_LABEL(clock_enable) | is hardclock() available? + jeq 1f + INTERRUPT_SAVEREG + lea sp@(16),a1 | a1 = &clockframe + movl a1,sp@- + jbsr _C_LABEL(hardclock) | hardclock(&frame) + addql #4,sp + addql #1,_C_LABEL(intrcnt)+20 + INTERRUPT_RESTOREREG +1: + jra _ASM_LABEL(rei) | all done +#endif + +#undef INTERRUPT_SAVEREG +#undef INTERRUPT_RESTOREREG + +/* + * 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. + */ +BSS(ssir,1) + +ASENTRY_NOPROFILE(rei) + tstl _C_LABEL(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 +Lrei2: + clrl sp@- | VA == none + clrl sp@- | code == none + movl #T_ASTFLT,sp@- | type == async system trap + jbsr _C_LABEL(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 _C_LABEL(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 _C_LABEL(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 +Lsir1: + clrl sp@- | VA == none + clrl sp@- | code == none + movl #T_SSIR,sp@- | type == software interrupt + jbsr _C_LABEL(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 + +/* + * Use common m68k sigcode. + */ +#include <m68k/m68k/sigcode.s> + +/* + * Primitives + */ + +/* + * Use common m68k support routines. + */ +#include <m68k/m68k/support.s> + +/* + * Use common m68k process manipulation routines. + */ +#include <m68k/m68k/proc_subr.s> + + .data +GLOBAL(curpcb) +GLOBAL(masterpaddr) + .long 0 + +ASLOCAL(mdpflag) + .byte 0 | copy of proc md_flags low byte + .align 2 + +ASBSS(nullpcb, SIZEOF_PCB) + +/* + * At exit of a process, do a switch for the last time. + * Switch to a safe stack and PCB, and select a new process to run. The + * old stack and u-area will be freed by the reaper. + */ +ENTRY(switch_exit) + movl sp@(4),a0 + /* save state into garbage pcb */ + movl #_ASM_LABEL(nullpcb),_C_LABEL(curpcb) + lea _ASM_LABEL(tmpstk),sp | goto a tmp stack + + /* Schedule the vmspace and stack to be freed. */ + movl a0,sp@- | exit2(p) + jbsr _C_LABEL(exit2) + lea sp@(4),sp | pop args + + jra _C_LABEL(cpu_switch) + +/* + * When no processes are on the runq, Swtch branches to Idle + * to wait for something to come ready. + */ +ASENTRY_NOPROFILE(Idle) + stop #PSL_LOWIPL + movw #PSL_HIGHIPL,sr + movl _C_LABEL(whichqs),d0 + jeq _ASM_LABEL(Idle) + jra Lsw1 + +Lbadsw: + PANIC("switch") + /*NOTREACHED*/ + +/* + * cpu_switch() + * + * NOTE: On the mc68851 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 _C_LABEL(curpcb),a0 | current pcb + movw sr,a0@(PCB_PS) | save sr before changing ipl +#ifdef notyet + movl _C_LABEL(curproc),sp@- | remember last proc running +#endif + clrl _C_LABEL(curproc) + + /* + * Find the highest-priority queue that isn't empty, + * then take the first proc from that queue. + */ + movw #PSL_HIGHIPL,sr | lock out interrupts + movl _C_LABEL(whichqs),d0 + jeq _ASM_LABEL(Idle) +Lsw1: + movl d0,d1 + negl d0 + andl d1,d0 + bfffo d0{#0:#32},d1 + eorib #31,d1 + + movl d1,d0 + lslb #3,d1 | convert queue number to index + addl #_C_LABEL(qs),d1 | locate queue (q) + movl d1,a1 + movl a1@(P_FORW),a0 | p = q->p_forw + cmpal d1,a0 | anyone on queue? + jeq Lbadsw | no, panic + movl a0@(P_FORW),a1@(P_FORW) | q->p_forw = p->p_forw + movl a0@(P_FORW),a1 | n = p->p_forw + movl d1,a1@(P_BACK) | n->p_back = q + cmpal d1,a1 | anyone left on queue? + jne Lsw2 | yes, skip + movl _C_LABEL(whichqs),d1 + bclr d0,d1 | no, clear bit + movl d1,_C_LABEL(whichqs) +Lsw2: + movl a0,_C_LABEL(curproc) + clrl _C_LABEL(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 _C_LABEL(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 + + tstl _C_LABEL(fputype) | Do we have an FPU? + jeq Lswnofpsave | No Then don't attempt save. + lea a1@(PCB_FPCTX),a2 | pointer to FP save area + fsave a2@ | save FP state +#if defined(M68030) || defined(M68040) + 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 +#endif +Lswnofpsave: + +#ifdef DIAGNOSTIC + tstl a0@(P_WCHAN) + jne Lbadsw + cmpb #SRUN,a0@(P_STAT) + jne Lbadsw +#endif + + clrl a0@(P_BACK) | clear back link + movb a0@(P_MD_FLAGS+3),mdpflag | low byte of p_md.md_flags + movl a0@(P_ADDR),a1 | get p_addr + movl a1,_C_LABEL(curpcb) + + /* + * Activate process's address space. + * XXX Should remember the last USTP value loaded, and call this + * XXX only of it has changed. + */ + pea a0@ | push proc + jbsr _C_LABEL(pmap_activate) | pmap_activate(p) + addql #4,sp + movl _C_LABEL(curpcb),a1 | restore p_addr + + lea _ASM_LABEL(tmpstk),sp | now goto a tmp stack for NMI + + moveml a1@(PCB_REGS),#0xFCFC | and registers + movl a1@(PCB_USP),a0 + movl a0,usp | and USP + + tstl _C_LABEL(fputype) | If we don't have an FPU, + jeq Lnofprest | don't try to restore it. + lea a1@(PCB_FPCTX),a0 | pointer to FP save area + tstb a0@ | null state frame? + jeq Lresfprest | yes, easy +#if defined(M68030) || defined(M68040) +#if defined(M68040) + cmpl #FPU_68040,_C_LABEL(fputype) | 68040? + jne Lresnot040 | no, skip + clrl sp@- | yes... + frestore sp@+ | ...magic! +Lresnot040: +#endif + fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers + fmovem a0@(216),fp0-fp7 | restore FP general registers +#endif +Lresfprest: + frestore a0@ | restore state +Lnofprest: + movw a1@(PCB_PS),sr | no, restore PS + moveq #1,d0 | return 1 (for alternate returns) + rts + +/* + * savectx(pcb) + * Update pcb, saving current processor state. + */ +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 + + tstl _C_LABEL(fputype) | Do we have FPU? + jeq Lsvnofpsave | No? Then don't save state. + 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: + moveq #0,d0 | return 0 + rts + +#if defined(M68040) +ENTRY(suline) + movl sp@(4),a0 | address to write + movl _C_LABEL(curpcb),a1 | current pcb + movl #Lslerr,a1@(PCB_ONFAULT) | where to return to o0,dfc + .word 0xf508 | pflush a0@ + moveq #5,d0 | super space + movc d0,dfc + .word 0xf508 | pflush a0@ + movc d1,dfc + rts +Lmotommu4: +#endif + tstl _C_LABEL(mmutype) | is 68851? + jpl Lmc68851b | + movl sp@(4),a0 | get addr to flush + 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 + +ENTRY(getsr) + moveq #0,d0 + movw sr,d0 + rts + +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). + */ +ENTRY(getsp) + movl sp,d0 | get current SP + addql #4,d0 | compensate for return address + rts + +ENTRY_NOPROFILE(getsfc) + movc sfc,d0 + rts + +ENTRY_NOPROFILE(getdfc) + movc dfc,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 +#if defined(M68040) + cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? + jne LmotommuC | no, skip + .long 0x4e7b0806 | movc d0,urp + rts +LmotommuC: +#endif + lea _C_LABEL(protocrp),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 + +ENTRY(ploadw) +#if defined(M68040) + cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? + jeq Lploadwskp | yes, skip +#endif + movl sp@(4),a0 | address to load + ploadw #1,a0@ | pre-load translation +#if defined(M68040) +Lploadwskp: +#endif + 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 _C_LABEL(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 + +/* + * _delay(unsigned N) + * + * Delay for at least (N/256) microseconds. + * This routine depends on the variable: delay_divisor + * which should be set based on the CPU clock rate. + */ +GLOBAL(_delay) + | d0 = arg = (usecs << 8) + movl sp@(4),d0 + | d1 = delay_divisor + movl _C_LABEL(delay_divisor),d1 +L_delay: + subl d1,d0 + jgt L_delay + rts + +/* + * Save and restore 68881 state. + */ +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 + +/* + * Do a dump. + * Called by auto-restart. + */ +GLOBAL(doadump) + jbsr _C_LABEL(dumpsys) + jbsr _C_LABEL(doboot) + /*NOTREACHED*/ + +/* + * Handle the nitty-gritty of rebooting the machine. + * Basically we just turn off the MMU, restore the initial VBR + * and return to monitor. + */ +ENTRY_NOPROFILE(doboot) + movw #PSL_HIGHIPL,sr | no interrupts +#if defined(M68040) + cmpl #MMU_68040,_C_LABEL(mmutype) | 68040? + jeq Lnocache5 | yes, skip +#endif + movl #CACHE_OFF,d0 + movc d0,cacr | disable on-chip cache(s) + movl #0,a7@ | value for pmove to TC + pmove a7@,tc | disable MMU + lea _ASM_LABEL(nullrp),a0 + pmove a0@,crp | Invalidate CPU root pointer + pmove a0@,srp | and the Supervisor root pointer + jra Lbootcommon +#if defined(M68040) +Lnocache5: + .word 0xf4f8 | cpusha bc + movql #0,d0 + movc d0,cacr + .long 0x4e7b0003 | movc d0,tc (disable MMU) + .long 0x4e7b0806 | movc d0,URP + .long 0x4e7b0807 | movc d0,SRP +#endif /* M68040 */ +Lbootcommon: + movl _C_LABEL(boothowto),d0 | load howto + movl sp@(4),d2 | arg + lea _ASM_LABEL(tmpstk),sp | physical SP in case of NMI + movl #0,d3 + movc d3,vbr | monitor VBR +#if 0 + andl #0,d0 | mask off + tstl d0 | + bne Lsboot | sboot? + tstl d2 + beq Ldoreset +#endif + + movl #0x41000000,a0 | base = (int **)0x4100.0000 + movl a0@,d0 | *((int *)base[0]) + movc d0,isp | set initial stack pointer + movc d0,msp | set initial stack pointer + movl a0@(4),a0 | *((int (*)(void))base[1]) + jmp a0@ | go cold boot! + +/* + * Utility call for LUNA rom monitor routines + */ +ENTRY_NOPROFILE(romcall) + link a6,#-8 + movel a6@(8),d0 | 1st arg is routine no. + moveq #0,d1 + movw sr,d1 | get old SR for return + movel d1,a6@(-4) + movw #PSL_HIGHIPL,sr | splhigh() + movc vbr,d1 + movel d1,a6@(-8) + movl #0,d1 + movc d1,vbr | switch to monitor VBR + movel #0x41000000,a0 | base = (int **)0x41000000 + movel a6@(12),sp@- + movel a0@(d0:l:4),a0 | (*(int (*)(int))base[n])(arg) + jbsr a0@ + movl a6@(-8),d1 | restore previous VBR + movc d1,vbr + movel a6@(-4),d1 + movew d1,sr | splx() + unlk a6 + rts + + .data +GLOBAL(cputype) + .long CPU_68030 | default to 68030 +GLOBAL(mmutype) + .long MMU_68030 | default to 68030 +GLOBAL(fputype) + .long FPU_68881 | default to 68881 + +GLOBAL(protosrp) + .long 0x80000202,0 | prototype supervisor root pointer +GLOBAL(protocrp) + .long 0x80000002,0 | prototype cpu root pointer + +GLOBAL(prototc) + .long 0x82c0aa00 | tc (SRP,CRP,4KB page, TIA/TIB=10/10bits) +GLOBAL(protott0) | tt0 0x4000.0000-0x7fff.ffff + .long 0x403f8543 | +GLOBAL(protott1) | tt1 0x8000.0000-0xffff.ffff + .long 0x807f8543 | +GLOBAL(proto040tc) + .long 0x8000 | tc (4KB page) +GLOBAL(proto040tt0) | tt0 0x4000.0000-0x7fff.ffff + .long 0x403fa040 | kernel only, cache inhebit, serialized +GLOBAL(proto040tt1) | tt1 0x8000.0000-0xfeff.ffff + .long 0x807ea040 | kernel only, cache inhebit, serialized +nullrp: + .long 0x7fff0001 | do-nothing MMU root pointer + +GLOBAL(memavail) + .long 0 +GLOBAL(want_resched) + .long 0 +GLOBAL(proc0paddr) + .long 0 +GLOBAL(boothowto) + .long 0 +GLOBAL(bootdev) + .long 0 +GLOBAL(hwplanemask) + .long 0 +GLOBAL(bootarg) + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + +#ifdef DEBUG +ASGLOBAL(fulltflush) + .long 0 + +ASGLOBAL(fullcflush) + .long 0 +#endif + +GLOBAL(intiobase) + .long 0 | KVA of base of internal IO space +GLOBAL(intiolimit) + .long 0 | KVA of end of internal IO space +GLOBAL(intiobase_phys) + .long 0 | PA of board's I/O registers +GLOBAL(intiotop_phys) + .long 0 | PA of top of board's I/O registers + +GLOBAL(intrnames) + .asciz "spur" + .asciz "lev1" + .asciz "scsi" + .asciz "network" + .asciz "lev4" + .asciz "clock" + .asciz "serial" + .asciz "nmi" + .asciz "statclock" +GLOBAL(eintrnames) + .even +GLOBAL(intrcnt) + .long 0,0,0,0,0,0,0,0,0,0 +GLOBAL(eintrcnt) diff --git a/sys/arch/luna68k/luna68k/machdep.c b/sys/arch/luna68k/luna68k/machdep.c new file mode 100644 index 00000000000..5ff59d0e196 --- /dev/null +++ b/sys/arch/luna68k/luna68k/machdep.c @@ -0,0 +1,991 @@ +/* $NetBSD: machdep.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $"); + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/systm.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/device.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/msgbuf.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/mount.h> +#include <sys/user.h> +#include <sys/exec.h> +#include <sys/core.h> +#include <sys/kcore.h> +#include <sys/vnode.h> +#include <sys/syscallargs.h> +#ifdef KGDB +#include <sys/kgdb.h> +#endif + +#include <vm/vm.h> +#include <vm/vm_map.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> + +#include <uvm/uvm_extern.h> + +#include <sys/sysctl.h> + +#include <machine/cpu.h> +#include <machine/reg.h> +#include <machine/psl.h> +#include <machine/pte.h> +#include <machine/kcore.h> /* XXX should be pulled in by sys/kcore.h */ + +#include <dev/cons.h> + +#if defined(DDB) +#include <machine/db_machdep.h> +#include <ddb/db_sym.h> +#include <ddb/db_extern.h> +#endif + +/* + * Info for CTL_HW + */ +char machine[] = MACHINE; +char cpu_model[60]; +extern char version[]; + +extern char kernel_text[]; +extern char etext[]; + +vm_map_t exec_map = NULL; +vm_map_t mb_map = NULL; +vm_map_t phys_map = NULL; + +caddr_t msgbufaddr; +int maxmem; /* max memory per process */ +int physmem; /* set by locore */ +/* + * safepri is a safe priority for sleep to set for a spin-wait + * during autoconfiguration or after a panic. + */ +int safepri = PSL_LOWIPL; + +void luna68k_init __P((void)); +void identifycpu __P((void)); +void dumpsys __P((void)); + +void straytrap __P((int, u_short)); +void nmihand __P((struct frame)); + +int cpu_dumpsize __P((void)); +int cpu_dump __P((int (*)(dev_t, daddr_t, caddr_t, size_t), daddr_t *)); +void cpu_init_kcore_hdr __P((void)); + +/* + * Machine-independent crash dump header info. + */ +cpu_kcore_hdr_t cpu_kcore_hdr; + +int machtype; /* model: 1 for LUNA-1, 2 for LUNA-2 */ +int sysconsole; /* console: 0 for ttya, 1 for video */ + +extern struct consdev syscons; +extern void omfb_cnattach __P((void)); +extern void ws_cnattach __P((void)); +extern void syscnattach __P((int)); + +/* + * On the 68020/68030, the value of delay_divisor is roughly + * 2048 / cpuspeed (where cpuspeed is in MHz). + * + * On the 68040/68060(?), the value of delay_divisor is roughly + * 759 / cpuspeed (where cpuspeed is in MHz). + * XXX -- is the above formula correct? + */ +int cpuspeed = 25; /* only used for printing later */ +int delay_divisor = 300; /* for delay() loop count */ + +/* + * Early initialization, before main() is called. + */ +void +luna68k_init() +{ + int i; + + extern paddr_t avail_start, avail_end; + + /* + * Tell the VM system about available physical memory. The + * luna68k only has one segment. + */ + uvm_page_physload(atop(avail_start), atop(avail_end), + atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); + + /* + * Initialize error message buffer (at end of core). + * avail_end was pre-decremented in pmap_bootstrap to compensate. + */ + for (i = 0; i < btoc(MSGBUFSIZE); i++) + pmap_enter(pmap_kernel(), (vaddr_t)msgbufaddr + i * NBPG, + avail_end + i * NBPG, VM_PROT_READ|VM_PROT_WRITE, + VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); + initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); +} + +/* + * Console initialization: called early on from main, + */ +void +consinit() +{ + volatile unsigned char *pio0 = (void *)0x49000000; + int sw1, i; + char *cp; + extern char bootarg[64]; + + pio0[3] = 0xb6; + pio0[2] = 1 << 6; /* enable parity check */ + + pio0[3] = 0xb6; + sw1 = pio0[0]; /* dipssw1 value */ + sw1 ^= 0xff; + sysconsole = !(sw1 & 0x2); /* console selection */ + + boothowto = 0; + i = 0; + /* + * 'bootarg' has; + * "<args of x command> ENADDR=<addr> HOST=<host> SERVER=<name>" + * where <addr> is MAC address of which network loader used (not + * necessarily same as one at 0x4101.FFE0), <host> and <name> + * are the values of HOST and SERVER environment variables, + * + * NetBSD/luna68k cares only the first argment; any of "sda". + */ + for (cp = bootarg; *cp != ' '; cp++) { + switch (*cp) { + case 's': + boothowto |= RB_SINGLE; + break; + case 'd': + boothowto |= RB_KDB; + break; + case 'a': + boothowto |= RB_ASKNAME; + break; + } + if (i++ >= sizeof(bootarg)) + break; + } + if (boothowto == 0) + boothowto = (sw1 & 0x1) ? RB_SINGLE : 0; + + if (sysconsole == 0) + syscnattach(0); + else { + omfb_cnattach(); + ws_cnattach(); + } + +#ifdef DDB + { + extern int end; + extern int *esym; + + ddb_init(*(int *)&end, ((int *)&end) + 1, esym); + } + if (boothowto & RB_KDB) + cpu_Debugger(); +#endif +} + +/* + * cpu_startup: allocate memory for variable-sized tables. + */ +void +cpu_startup() +{ + int i; + caddr_t v; + int base, residual; + vaddr_t minaddr, maxaddr; + vsize_t size; + char pbuf[9]; + extern void greeting __P((void)); + + /* + * Initialize the kernel crash dump header. + */ + cpu_init_kcore_hdr(); + + /* + * Good {morning,afternoon,evening,night}. + */ + printf(version); + identifycpu(); + + format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); + printf("total memory = %s\n", pbuf); + + /* + * Find out how much space we need, allocate it, + * and then give everything true virtual addresses. + */ + size = (int)allocsys(NULL, NULL); + if ((v = (caddr_t)uvm_km_alloc(kernel_map, round_page(size))) == 0) + panic("startup: no room for tables"); + if (allocsys(v, NULL) - v != 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; + if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size), + NULL, UVM_UNKNOWN_OFFSET, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_NORMAL, 0)) != KERN_SUCCESS) + panic("startup: cannot allocate VM for buffers"); + minaddr = (vaddr_t)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++) { + vsize_t curbufsize; + vaddr_t curbuf; + struct vm_page *pg; + + /* + * Each buffer has MAXBSIZE bytes of VM space allocated. Of + * that MAXBSIZE space, we allocate and map (base+1) pages + * for the first "residual" buffers, and then we allocate + * "base" pages for the rest. + */ + curbuf = (vsize_t) buffers + (i * MAXBSIZE); + curbufsize = NBPG * ((i < residual) ? (base+1) : base); + + while (curbufsize) { + pg = uvm_pagealloc(NULL, 0, NULL, 0); + if (pg == NULL) + panic("cpu_startup: not enough memory for " + "buffer cache"); + pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), + VM_PROT_READ|VM_PROT_WRITE); + curbuf += PAGE_SIZE; + curbufsize -= PAGE_SIZE; + } + } + + /* + * Allocate a submap for exec arguments. This map effectively + * limits the number of processes exec'ing at any time. + */ + exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); + + /* + * Allocate a submap for physio + */ + phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + VM_PHYS_SIZE, 0, FALSE, NULL); + + /* + * Finally, allocate mbuf cluster submap. + */ + mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + nmbclusters * mclbytes, VM_MAP_INTRSAFE, + FALSE, NULL); + + /* + * Initialize callouts + */ + callfree = callout; + for (i = 1; i < ncallout; i++) + callout[i-1].c_next = &callout[i]; + callout[i-1].c_next = NULL; + + format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); + printf("avail memory = %s\n", pbuf); + format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); + printf("using %d buffers containing %s of memory\n", nbuf, pbuf); + + /* + * Tell the VM system that the area before the text segment + * is invalid. + * + * XXX Should just change KERNBASE and VM_MIN_KERNEL_ADDRESS, + * XXX but not right now. + */ + if (uvm_map_protect(kernel_map, 0, round_page(&kernel_text), + UVM_PROT_NONE, TRUE) != KERN_SUCCESS) + panic("can't mark pre-text pages off-limits"); + + /* + * Tell the VM system that writing to kernel text isn't allowed. + * If we don't, we might end up COW'ing the text segment! + */ + if (uvm_map_protect(kernel_map, trunc_page(&kernel_text), + trunc_page(&etext), UVM_PROT_READ|UVM_PROT_EXEC, TRUE) + != KERN_SUCCESS) + panic("can't protect kernel text"); + + /* + * Set up buffers, so they can be used to read disk labels. + */ + bufinit(); + + /* + * Say "Hi" to the world + */ + greeting(); +} + +/* + * Set registers on exec. + */ +void +setregs(p, pack, stack) + register struct proc *p; + struct exec_package *pack; + u_long stack; +{ + struct frame *frame = (struct frame *)p->p_md.md_regs; + extern int fputype; + + frame->f_sr = PSL_USERSET; + frame->f_pc = pack->ep_entry & ~1; + frame->f_regs[D0] = 0; + frame->f_regs[D1] = 0; + frame->f_regs[D2] = 0; + frame->f_regs[D3] = 0; + frame->f_regs[D4] = 0; + frame->f_regs[D5] = 0; + frame->f_regs[D6] = 0; + frame->f_regs[D7] = 0; + frame->f_regs[A0] = 0; + frame->f_regs[A1] = 0; + frame->f_regs[A2] = (int)PS_STRINGS; + frame->f_regs[A3] = 0; + frame->f_regs[A4] = 0; + frame->f_regs[A5] = 0; + frame->f_regs[A6] = 0; + frame->f_regs[SP] = stack; + + /* restore a null state frame */ + p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0; + if (fputype) + m68881_restore(&p->p_addr->u_pcb.pcb_fpregs); +} + +void +identifycpu() +{ + extern int cputype; + char *cpu; + + bzero(cpu_model, sizeof(cpu_model)); + switch (cputype) { + case CPU_68030: + cpu = "MC68030 CPU+MMU, MC68882 FPU"; + machtype = LUNA_I; + cpuspeed = 20; delay_divisor = 102; /* 20MHz 68030 */ + hz = 60; + break; +#ifdef M68040 + case CPU_68040: + cpu = "MC68040 CPU+MMU+FPU, 4k on-chip physical I/D caches"; + machtype = LUNA_II; + cpuspeed = 25; delay_divisor = 300; /* 25MHz 68040 */ + break; +#endif + default: + panic("unknown CPU type"); + } + strcpy(cpu_model, cpu); + printf("%s\n", cpu_model); +} + +/* + * machine dependent system variables. + */ +int +cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; + struct proc *p; +{ + 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 */ +} + +int waittime = -1; + +void +cpu_reboot(howto, bootstr) + volatile int howto; /* XXX to shutup GCC XXX */ + char *bootstr; +{ + extern void doboot __P((void)); + + /* take a snap shot before clobbering any registers */ + if (curproc && curproc->p_addr) + savectx(&curproc->p_addr->u_pcb); + + /* If system is hold, just halt. */ + if (cold) { + howto |= RB_HALT; + goto haltsys; + } + + boothowto = howto; + if ((howto & RB_NOSYNC) == 0 && waittime < 0) { + waittime = 0; + vfs_shutdown(); + /* + * If we've been adjusting the clock, the todr + * will be out of synch; adjust it now. + */ + resettodr(); + } + + /* Disable interrupts. */ + splhigh(); + + /* If rebooting and a dump is requested, do it. */ + if (howto & RB_DUMP) + dumpsys(); + +haltsys: + /* Run any shutdown hooks. */ + doshutdownhooks(); + + /* Finally, halt/reboot the system. */ + if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { + u_int8_t *pio = (void *)0x4d000000; + + printf("power is going down.\n"); + DELAY(100000); + pio[3] = 0x94; + pio[2] = 0 << 4; + for (;;) /* NOP */; + } + if (howto & RB_HALT) { + printf("System halted. Hit any key to reboot.\n\n"); + (void)cngetc(); + } + + printf("rebooting...\n"); + DELAY(100000); + doboot(); + /*NOTREACHED*/ + while (1) ; +} + +/* + * Initialize the kernel crash dump header. + */ +void +cpu_init_kcore_hdr() +{ + cpu_kcore_hdr_t *h = &cpu_kcore_hdr; + struct m68k_kcore_hdr *m = &h->un._m68k; + extern char end[]; + + bzero(&cpu_kcore_hdr, sizeof(cpu_kcore_hdr)); + + /* + * Initialize the `dispatcher' portion of the header. + */ + strcpy(h->name, machine); + h->page_size = NBPG; + h->kernbase = KERNBASE; + + /* + * Fill in information about our MMU configuration. + */ + m->mmutype = mmutype; + m->sg_v = SG_V; + m->sg_frame = SG_FRAME; + m->sg_ishift = SG_ISHIFT; + m->sg_pmask = SG_PMASK; + m->sg40_shift1 = SG4_SHIFT1; + m->sg40_mask2 = SG4_MASK2; + m->sg40_shift2 = SG4_SHIFT2; + m->sg40_mask3 = SG4_MASK3; + m->sg40_shift3 = SG4_SHIFT3; + m->sg40_addr1 = SG4_ADDR1; + m->sg40_addr2 = SG4_ADDR2; + m->pg_v = PG_V; + m->pg_frame = PG_FRAME; + + /* + * Initialize pointer to kernel segment table. + */ + m->sysseg_pa = (u_int32_t)(pmap_kernel()->pm_stpa); + + /* + * Initialize relocation value such that: + * + * pa = (va - KERNBASE) + reloc + * + * Since we're linked and loaded at the same place, + * and the kernel is mapped va == pa, this is 0. + */ + m->reloc = 0; + + /* + * Define the end of the relocatable range. + */ + m->relocend = (u_int32_t)end; + + /* + * The luna68k has one contiguous memory segment. + */ + m->ram_segs[0].start = 0 /* lowram */; + m->ram_segs[0].size = ctob(physmem); +} + +/* + * Compute the size of the machine-dependent crash dump header. + * Returns size in disk blocks. + */ +int +cpu_dumpsize() +{ + int size; + + size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); + return (btodb(roundup(size, dbtob(1)))); +} + +/* + * Called by dumpsys() to dump the machine-dependent header. + */ +int +cpu_dump(dump, blknop) + int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); + daddr_t *blknop; +{ + int buf[dbtob(1) / sizeof(int)]; + cpu_kcore_hdr_t *chdr; + kcore_seg_t *kseg; + int error; + + kseg = (kcore_seg_t *)buf; + chdr = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(kcore_seg_t)) / + sizeof(int)]; + + /* Create the segment header. */ + CORE_SETMAGIC(*kseg, KCORE_MAGIC, MID_MACHINE, CORE_CPU); + kseg->c_size = dbtob(1) - ALIGN(sizeof(kcore_seg_t)); + + bcopy(&cpu_kcore_hdr, chdr, sizeof(cpu_kcore_hdr_t)); + error = (*dump)(dumpdev, *blknop, (caddr_t)buf, sizeof(buf)); + *blknop += btodb(sizeof(buf)); + return (error); +} + +/* + * These variables are needed by /sbin/savecore + */ +u_long dumpmag = 0x8fca0101; /* magic number */ +int dumpsize = 0; /* pages */ +long dumplo = 0; /* blocks */ + +/* + * This is called by main to set dumplo and dumpsize. + * Dumps always skip the first NBPG of disk space + * in case there might be a disk label stored there. + * If there is extra space, put dump at the end to + * reduce the chance that swapping trashes it. + */ +void +cpu_dumpconf() +{ + int chdrsize; /* size of dump header */ + int nblks; /* size of dump area */ + int maj; + + if (dumpdev == NODEV) + return; + maj = major(dumpdev); + if (maj < 0 || maj >= nblkdev) + panic("dumpconf: bad dumpdev=0x%x", dumpdev); + if (bdevsw[maj].d_psize == NULL) + return; + nblks = (*bdevsw[maj].d_psize)(dumpdev); + chdrsize = cpu_dumpsize(); + + dumpsize = btoc(cpu_kcore_hdr.un._m68k.ram_segs[0].size); + + /* + * Check do see if we will fit. Note we always skip the + * first NBPG in case there is a disk label there. + */ + if (nblks < (ctod(dumpsize) + chdrsize + ctod(1))) { + dumpsize = 0; + dumplo = -1; + return; + } + + /* + * Put dump at the end of the partition. + */ + dumplo = (nblks - 1) - ctod(dumpsize) - chdrsize; +} + +/* + * Dump physical memory onto the dump device. Called by cpu_reboot(). + */ +void +dumpsys() +{ + daddr_t blkno; /* current block to write */ + /* dump routine */ + int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); + int pg; /* page being dumped */ + paddr_t maddr; /* PA being dumped */ + int error; /* error code from (*dump)() */ + + /* XXX initialized here because of gcc lossage */ + maddr = 0 /* lowram */; + pg = 0; + + /* Don't put dump messages in msgbuf. */ + msgbufenabled = 0; + + /* Make sure dump device is valid. */ + if (dumpdev == NODEV) + return; + if (dumpsize == 0) { + cpu_dumpconf(); + if (dumpsize == 0) + return; + } + if (dumplo <= 0) { + printf("\ndump to dev %u,%u not possible\n", major(dumpdev), + minor(dumpdev)); + return; + } + dump = bdevsw[major(dumpdev)].d_dump; + blkno = dumplo; + + printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev), + minor(dumpdev), dumplo); + + printf("dump "); + + /* Write the dump header. */ + error = cpu_dump(dump, &blkno); + if (error) + goto bad; + + for (pg = 0; pg < dumpsize; pg++) { +#define NPGMB (1024*1024/NBPG) + /* print out how many MBs we have dumped */ + if (pg && (pg % NPGMB) == 0) + printf("%d ", pg / NPGMB); +#undef NPGMB + pmap_enter(pmap_kernel(), (vaddr_t)vmmap, maddr, + VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); + + error = (*dump)(dumpdev, blkno, vmmap, NBPG); + bad: + switch (error) { + case 0: + maddr += NBPG; + blkno += btodb(NBPG); + break; + + case ENXIO: + printf("device bad\n"); + return; + + case EFAULT: + printf("device not ready\n"); + return; + + case EINVAL: + printf("area improper\n"); + return; + + case EIO: + printf("i/o error\n"); + return; + + case EINTR: + printf("aborted from console\n"); + return; + + default: + printf("error %d\n", error); + return; + } + } + printf("succeeded\n"); +} + +void +straytrap(pc, evec) + int pc; + u_short evec; +{ + printf("unexpected trap (vector offset %x) from %x\n", + evec & 0xFFF, pc); +} + +int *nofault; + +int +badaddr(addr, nbytes) + register caddr_t addr; + int nbytes; +{ + 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); + } + + switch (nbytes) { + case 1: + i = *(volatile char *)addr; + break; + + case 2: + i = *(volatile short *)addr; + break; + + case 4: + i = *(volatile int *)addr; + break; + + default: + panic("badaddr: bad request"); + } + nofault = (int *) 0; + return (0); +} + +void luna68k_abort __P((char *)); + +static int innmihand; /* simple mutex */ + +/* + * Level 7 interrupts are caused by e.g. the ABORT switch. + * + * If we have DDB, then break into DDB on ABORT. In a production + * environment, bumping the ABORT switch would be bad, so we enable + * panic'ing on ABORT with the kernel option "PANICBUTTON". + */ +void +nmihand(frame) + struct frame frame; +{ + /* Prevent unwanted recursion */ + if (innmihand) + return; + innmihand = 1; + + luna68k_abort("ABORT SWITCH"); +} + +/* + * Common code for handling ABORT signals from buttons, switches, + * serial lines, etc. + */ +void +luna68k_abort(cp) + char *cp; +{ +#ifdef DDB + printf("%s\n", cp); + cpu_Debugger(); +#else +#ifdef PANICBUTTON + panic(cp); +#else + printf("%s ignored\n", cp); +#endif /* PANICBUTTON */ +#endif /* DDB */ +} + +/* + * cpu_exec_aout_makecmds(): + * cpu-dependent a.out format hook for execve(). + * + * Determine of the given exec package refers to something which we + * understand and, if so, set up the vmcmds for it. + */ +int +cpu_exec_aout_makecmds(p, epp) + struct proc *p; + struct exec_package *epp; +{ + int error = ENOEXEC; +#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; +} + +/* + * Return the best possible estimate of the time in the timeval + * to which tvp points. Unfortunately, we can't read the hardware registers. + * 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 = splclock(); + static struct timeval lasttime; + + *tvp = time; +#ifdef notdef + tvp->tv_usec += clkread(); + while (tvp->tv_usec > 1000000) { + tvp->tv_sec++; + tvp->tv_usec -= 1000000; + } +#endif + 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); +} + +#ifndef ROMCONS + +struct consdev *cn_tab = &syscons; + +#else + +/* + * romcons is useful until m68k TC register is initialized. + */ +int romcngetc __P((dev_t)); +void romcnputc __P((dev_t, int)); + +struct consdev romcons = { + NULL, + NULL, + romcngetc, + romcnputc, + nullcnpollc, + makedev(7, 0), /* XXX */ + CN_DEAD, +}; +struct consdev *cn_tab = &romcons; + +extern int romcall __P((int, int)); + +#define ROMGETC() romcall(6, 0) +#define ROMPUTC(x) romcall(7, x) + +void +romcnputc(dev, c) + dev_t dev; + int c; +{ + ROMPUTC(c); +} + +int +romcngetc(dev) + dev_t dev; +{ + int c; + + do { + c = ROMGETC(); + } while (c == -1); + return c; +} +#endif diff --git a/sys/arch/luna68k/luna68k/mainbus.c b/sys/arch/luna68k/luna68k/mainbus.c new file mode 100644 index 00000000000..940d476ae3a --- /dev/null +++ b/sys/arch/luna68k/luna68k/mainbus.c @@ -0,0 +1,109 @@ +/* $NetBSD: mainbus.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Tohru Nishimura. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> + +__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/autoconf.h> + +extern int machtype; + +static struct mainbus_attach_args devs[] = { + { "clock", 0x45000000, -1 }, /* Mostek/Dallas TimeKeeper */ + { "le", 0xf1000000, 3 }, /* Am7990 */ + { "sio", 0x51000000, 6 }, /* uPD7201A */ + { "fb", 0xc1100000, -1 }, /* BrookTree RAMDAC */ +#if 0 + { "spc", 0xe1000000, 2 }, /* MB89352 */ + { "spc", 0xe1000040, 2 }, /* ditto */ +#endif +}; + +static void mainbus_attach __P((struct device *, struct device *, void *)); +static int mainbus_match __P((struct device *, struct cfdata *, void *)); +static int mainbus_print __P((void *, const char *)); + +const struct cfattach mainbus_ca = { + sizeof(struct device), mainbus_match, mainbus_attach +}; + +static int +mainbus_match(parent, cf, args) + struct device *parent; + struct cfdata *cf; + void *args; +{ + static int mainbus_matched; + + if (mainbus_matched) + return (0); + + return ((mainbus_matched = 1)); +} + +static void +mainbus_attach(parent, self, args) + struct device *parent, *self; + void *args; +{ + int i; + + if (machtype == LUNA_II) + devs[1].ma_addr = 0xf0000000; + printf("\n"); + for (i = 0; i < sizeof(devs)/sizeof(devs[0]); i++) + config_found(self, (void *)&devs[i], mainbus_print); +} + +static int +mainbus_print(aux, pnp) + void *aux; + const char *pnp; +{ + struct mainbus_attach_args *ma = aux; + + if (pnp) + printf("%s at %s", ma->ma_name, pnp); + + return (UNCONF); +} diff --git a/sys/arch/luna68k/luna68k/mem.c b/sys/arch/luna68k/luna68k/mem.c new file mode 100644 index 00000000000..9c96be25e37 --- /dev/null +++ b/sys/arch/luna68k/luna68k/mem.c @@ -0,0 +1,232 @@ +/* $NetBSD: mem.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ +/* $NetBSD: mem.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mem.c 8.3 (Berkeley) 1/12/94 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: mem.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $"); + +/* + * Memory special file + */ + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/buf.h> +#include <sys/systm.h> +#include <sys/uio.h> +#include <sys/malloc.h> +#include <sys/proc.h> + +#include <machine/cpu.h> + +#include <vm/vm.h> + +#include <uvm/uvm_extern.h> + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +extern u_int lowram; +static caddr_t devzeropage; + +/*ARGSUSED*/ +int +mmopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + + return (0); +} + +/*ARGSUSED*/ +int +mmclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + + return (0); +} + +/*ARGSUSED*/ +int +mmrw(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + vaddr_t o, v; + int c; + struct iovec *iov; + int error = 0; + static int physlock; + vm_prot_t prot; + + if (minor(dev) == 0) { + /* lock against other uses of shared vmmap */ + while (physlock > 0) { + physlock++; + error = tsleep((caddr_t)&physlock, PZERO | PCATCH, + "mmrw", 0); + if (error) + return (error); + } + physlock = 1; + } + while (uio->uio_resid > 0 && error == 0) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("mmrw"); + continue; + } + switch (minor(dev)) { + +/* minor device 0 is physical memory */ + case 0: + v = uio->uio_offset; +#ifndef DEBUG + /* allow reads only in RAM (except for DEBUG) */ + if (v >= 0xFFFFFFFC || v < lowram) { + error = EFAULT; + goto unlock; + } +#endif + prot = uio->uio_rw == UIO_READ ? VM_PROT_READ : + VM_PROT_WRITE; + pmap_enter(pmap_kernel(), (vaddr_t)vmmap, + trunc_page(v), prot, prot|PMAP_WIRED); + o = uio->uio_offset & PGOFSET; + c = min(uio->uio_resid, (int)(NBPG - o)); + error = uiomove((caddr_t)vmmap + o, c, uio); + pmap_remove(pmap_kernel(), (vaddr_t)vmmap, + (vaddr_t)vmmap + NBPG); + continue; + +/* minor device 1 is kernel memory */ + case 1: + v = uio->uio_offset; + c = min(iov->iov_len, MAXPHYS); + if (!uvm_kernacc((caddr_t)v, c, + uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) + return (EFAULT); + error = uiomove((caddr_t)v, c, uio); + continue; + +/* minor device 2 is EOF/RATHOLE */ + case 2: + if (uio->uio_rw == UIO_WRITE) + uio->uio_resid = 0; + return (0); + +/* minor device 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; + } + /* + * On the first call, allocate and zero a page + * of memory for use with /dev/zero. + */ + if (devzeropage == NULL) { + devzeropage = (caddr_t) + malloc(NBPG, M_TEMP, M_WAITOK); + bzero(devzeropage, NBPG); + } + c = min(iov->iov_len, NBPG); + error = uiomove(devzeropage, c, uio); + continue; + + default: + return (ENXIO); + } + if (error) + break; + iov->iov_base = (caddr_t)iov->iov_base + c; + iov->iov_len -= c; + uio->uio_offset += c; + uio->uio_resid -= c; + } + if (minor(dev) == 0) { +#ifndef DEBUG +unlock: +#endif + if (physlock > 1) + wakeup((caddr_t)&physlock); + physlock = 0; + } + return (error); +} + +int +mmmmap(dev, off, prot) + dev_t dev; + int off, prot; +{ + /* + * /dev/mem is the only one that makes sense through this + * interface. For /dev/kmem any physaddr we return here + * could be transient and hence incorrect or invalid at + * a later time. /dev/null just doesn't make any sense + * and /dev/zero is a hack that is handled via the default + * pager in mmap(). + */ + if (minor(dev) != 0) + return (-1); + /* + * Allow access only in RAM. + * + * XXX could be extended to allow access to IO space but must + * be very careful. + */ + if ((u_int)off < lowram || (u_int)off >= 0xFFFFFFFC) + return (-1); + return (m68k_btop((u_int)off)); +} diff --git a/sys/arch/luna68k/luna68k/pmap.c b/sys/arch/luna68k/luna68k/pmap.c new file mode 100644 index 00000000000..38050c4f18a --- /dev/null +++ b/sys/arch/luna68k/luna68k/pmap.c @@ -0,0 +1,2520 @@ +/* $NetBSD: pmap.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ + +/*- + * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pmap.c 8.6 (Berkeley) 5/27/94 + */ + +/* + * Physical map management code. + * + * Supports: + * 68030 with on-chip MMU + * 68040 with on-chip MMU + * + * Notes: + * Don't even pay lip service to multiprocessor support. + * + * We assume TLB entries don't have process tags (except for the + * supervisor/user distinction) so we only invalidate TLB entries + * when changing mappings for the current (or kernel) pmap. This is + * technically not true for the 68551 but we flush the TLB on every + * context switch, so it effectively winds up that way. + * + * Bitwise and/or operations are significantly faster than bitfield + * references so we use them when accessing STE/PTEs in the pmap_pte_* + * macros. Note also that the two are not always equivalent; e.g.: + * (*pte & PG_PROT) [4] != pte->pg_prot [1] + * and a couple of routines that deal with protection and wiring take + * some shortcuts that assume the and/or definitions. + * + * This implementation will only work for PAGE_SIZE == NBPG + * (i.e. 4096 bytes). + */ + +/* + * 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/systm.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/user.h> +#include <sys/pool.h> + +#include <machine/vmparam.h> +#include <machine/pte.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> + +#include <uvm/uvm.h> + +#include <machine/cpu.h> +#include <m68k/cacheops.h> + + +#ifdef DEBUG +#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_MULTIMAP 0x0800 +#define PDB_PARANOIA 0x2000 +#define PDB_WIRING 0x4000 +#define PDB_PVDUMP 0x8000 + +int debugmap = 0; +int pmapdebug = PDB_PARANOIA; + +#define PMAP_DPRINTF(l, x) if (pmapdebug & (l)) printf x + +#if defined(M68040) +int dowriteback = 1; /* 68040: enable writeback caching */ +int dokwriteback = 1; /* 68040: enable writeback caching of kernel AS */ +#endif +#else /* ! DEBUG */ +#define PMAP_DPRINTF(l, x) /* nothing */ +#endif /* DEBUG */ + +/* + * Get STEs and PTEs for user/kernel address space + */ +#if defined(M68040) +#define pmap_ste1(m, v) \ + (&((m)->pm_stab[(vaddr_t)(v) >> SG4_SHIFT1])) +/* XXX assumes physically contiguous ST pages (if more than one) */ +#define pmap_ste2(m, v) \ + (&((m)->pm_stab[(st_entry_t *)(*(u_int *)pmap_ste1(m, v) & SG4_ADDR1) \ + - (m)->pm_stpa + (((v) & SG4_MASK2) >> SG4_SHIFT2)])) +#define pmap_ste(m, v) \ + (&((m)->pm_stab[(vaddr_t)(v) \ + >> (mmutype == MMU_68040 ? SG4_SHIFT1 : SG_ISHIFT)])) +#define pmap_ste_v(m, v) \ + (mmutype == MMU_68040 \ + ? ((*pmap_ste1(m, v) & SG_V) && \ + (*pmap_ste2(m, v) & SG_V)) \ + : (*pmap_ste(m, v) & SG_V)) +#else +#define pmap_ste(m, v) (&((m)->pm_stab[(vaddr_t)(v) >> SG_ISHIFT])) +#define pmap_ste_v(m, v) (*pmap_ste(m, v) & SG_V) +#endif + +#define pmap_pte(m, v) (&((m)->pm_ptab[(vaddr_t)(v) >> PG_SHIFT])) +#define pmap_pte_pa(pte) (*(pte) & PG_FRAME) +#define pmap_pte_w(pte) (*(pte) & PG_W) +#define pmap_pte_ci(pte) (*(pte) & PG_CI) +#define pmap_pte_m(pte) (*(pte) & PG_M) +#define pmap_pte_u(pte) (*(pte) & PG_U) +#define pmap_pte_prot(pte) (*(pte) & PG_PROT) +#define pmap_pte_v(pte) (*(pte) & PG_V) + +#define pmap_pte_set_w(pte, v) \ + if (v) *(pte) |= PG_W; else *(pte) &= ~PG_W +#define pmap_pte_set_prot(pte, v) \ + if (v) *(pte) |= PG_PROT; else *(pte) &= ~PG_PROT +#define pmap_pte_w_chg(pte, nw) ((nw) ^ pmap_pte_w(pte)) +#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte)) + +/* + * Given a map and a machine independent protection code, + * convert to an m68k 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 */ + vaddr_t kpt_va; /* always valid kernel VA */ + paddr_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. + */ +st_entry_t *Sysseg; +pt_entry_t *Sysmap, *Sysptmap; +st_entry_t *Segtabzero, *Segtabzeropa; +vsize_t Sysptsize = VM_KERNEL_PT_PAGES; + +struct pmap kernel_pmap_store; +vm_map_t st_map, pt_map; +struct vm_map st_map_store, pt_map_store; + +paddr_t avail_start; /* PA of first available physical page */ +paddr_t avail_end; /* PA of last available physical page */ +vsize_t mem_size; /* memory size in bytes */ +vaddr_t virtual_avail; /* VA of first avail page (after kernel bss)*/ +vaddr_t virtual_end; /* VA of last avail page (end of kernel AS) */ +int page_cnt; /* number of pages managed by VM system */ + +boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ +struct pv_entry *pv_table; +char *pmap_attributes; /* reference and modify bits */ +TAILQ_HEAD(pv_page_list, pv_page) pv_page_freelist; +int pv_nfree; + +#if defined(M68040) +int protostfree; /* prototype (default) free ST map */ +#endif + +extern caddr_t CADDR1, CADDR2; + +pt_entry_t *caddr1_pte; /* PTE for CADDR1 */ +pt_entry_t *caddr2_pte; /* PTE for CADDR2 */ + +struct pool pmap_pmap_pool; /* memory pool for pmap structures */ + +struct pv_entry *pmap_alloc_pv __P((void)); +void pmap_free_pv __P((struct pv_entry *)); +void pmap_collect_pv __P((void)); + +#define PAGE_IS_MANAGED(pa) (pmap_initialized && \ + vm_physseg_find(atop((pa)), NULL) != -1) + +#define pa_to_pvh(pa) \ +({ \ + int bank_, pg_; \ + \ + bank_ = vm_physseg_find(atop((pa)), &pg_); \ + &vm_physmem[bank_].pmseg.pvent[pg_]; \ +}) + +#define pa_to_attribute(pa) \ +({ \ + int bank_, pg_; \ + \ + bank_ = vm_physseg_find(atop((pa)), &pg_); \ + &vm_physmem[bank_].pmseg.attrs[pg_]; \ +}) + +/* + * Internal routines + */ +void pmap_remove_mapping __P((pmap_t, vaddr_t, pt_entry_t *, int)); +boolean_t pmap_testbit __P((paddr_t, int)); +void pmap_changebit __P((paddr_t, int, int)); +void pmap_enter_ptpage __P((pmap_t, vaddr_t)); +void pmap_ptpage_addref __P((vaddr_t)); +int pmap_ptpage_delref __P((vaddr_t)); +void pmap_collect1 __P((pmap_t, paddr_t, paddr_t)); +void pmap_pinit __P((pmap_t)); +void pmap_release __P((pmap_t)); + +#ifdef DEBUG +void pmap_pvdump __P((paddr_t)); +void pmap_check_wiring __P((char *, vaddr_t)); +#endif + +/* pmap_remove_mapping flags */ +#define PRM_TFLUSH 0x01 +#define PRM_CFLUSH 0x02 +#define PRM_KEEPPTPAGE 0x04 + +/* + * pmap_virtual_space: [ INTERFACE ] + * + * Report the range of available kernel virtual address + * space to the VM system during bootstrap. + * + * This is only an interface function if we do not use + * pmap_steal_memory()! + * + * Note: no locking is necessary in this function. + */ +void +pmap_virtual_space(vstartp, vendp) + vaddr_t *vstartp, *vendp; +{ + + *vstartp = virtual_avail; + *vendp = virtual_end; +} + +/* + * pmap_init: [ INTERFACE ] + * + * Initialize the pmap module. Called by vm_init(), to initialize any + * structures that the pmap system needs to map virtual memory. + * + * Note: no locking is necessary in this function. + */ +void +pmap_init() +{ + vaddr_t addr, addr2; + vsize_t s; + struct pv_entry *pv; + char *attr; + int rv; + int npages; + int bank; + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_init()\n")); + + /* + * Before we do anything else, initialize the PTE pointers + * used by pmap_zero_page() and pmap_copy_page(). + */ + caddr1_pte = pmap_pte(pmap_kernel(), CADDR1); + caddr2_pte = pmap_pte(pmap_kernel(), CADDR2); + + /* + * Now that kernel map has been allocated, we can mark as + * unavailable regions which we have mapped in pmap_bootstrap(). + */ + addr = (vaddr_t) intiobase; + if (uvm_map(kernel_map, &addr, + intiotop_phys - intiobase_phys, + NULL, UVM_UNKNOWN_OFFSET, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, + UVM_INH_NONE, UVM_ADV_RANDOM, + UVM_FLAG_FIXED)) != KERN_SUCCESS) + goto bogons; + addr = (vaddr_t) Sysmap; + if (uvm_map(kernel_map, &addr, MAX_PTSIZE, + NULL, UVM_UNKNOWN_OFFSET, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, + UVM_INH_NONE, UVM_ADV_RANDOM, + UVM_FLAG_FIXED)) != KERN_SUCCESS) { + /* + * 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. + */ + bogons: + panic("pmap_init: bogons in the VM system!\n"); + } + + PMAP_DPRINTF(PDB_INIT, + ("pmap_init: Sysseg %p, Sysmap %p, Sysptmap %p\n", + Sysseg, Sysmap, Sysptmap)); + PMAP_DPRINTF(PDB_INIT, + (" pstart %lx, pend %lx, vstart %lx, vend %lx\n", + avail_start, avail_end, virtual_avail, virtual_end)); + + /* + * Allocate memory for random pmap data structures. Includes the + * initial segment table, pv_head_table and pmap_attributes. + */ + for (page_cnt = 0, bank = 0; bank < vm_nphysseg; bank++) + page_cnt += vm_physmem[bank].end - vm_physmem[bank].start; + s = STSIZE; /* Segtabzero */ + s += page_cnt * sizeof(struct pv_entry); /* pv table */ + s += page_cnt * sizeof(char); /* attribute table */ + s = round_page(s); + addr = uvm_km_zalloc(kernel_map, s); + if (addr == 0) + panic("pmap_init: can't allocate data structures"); + + Segtabzero = (st_entry_t *) addr; + (void) pmap_extract(pmap_kernel(), addr, (paddr_t *)&Segtabzeropa); + addr += STSIZE; + + pv_table = (struct pv_entry *) addr; + addr += page_cnt * sizeof(struct pv_entry); + + pmap_attributes = (char *) addr; + + PMAP_DPRINTF(PDB_INIT, ("pmap_init: %lx bytes: page_cnt %x s0 %p(%p) " + "tbl %p atr %p\n", + s, page_cnt, Segtabzero, Segtabzeropa, + pv_table, pmap_attributes)); + + /* + * Now that the pv and attribute tables have been allocated, + * assign them to the memory segments. + */ + pv = pv_table; + attr = pmap_attributes; + for (bank = 0; bank < vm_nphysseg; bank++) { + npages = vm_physmem[bank].end - vm_physmem[bank].start; + vm_physmem[bank].pmseg.pvent = pv; + vm_physmem[bank].pmseg.attrs = attr; + pv += npages; + attr += npages; + } + + /* + * Allocate physical memory for kernel PT pages and their management. + * We need 1 PT page per possible task plus some slop. + */ + npages = min(atop(MAX_KPTSIZE), maxproc+16); + s = ptoa(npages) + round_page(npages * sizeof(struct kpt_page)); + + /* + * Verify that space will be allocated in region for which + * we already have kernel PT pages. + */ + addr = 0; + rv = uvm_map(kernel_map, &addr, s, NULL, UVM_UNKNOWN_OFFSET, + UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, + UVM_ADV_RANDOM, UVM_FLAG_NOMERGE)); + if (rv != KERN_SUCCESS || (addr + s) >= (vaddr_t)Sysmap) + panic("pmap_init: kernel PT too small"); + rv = uvm_unmap(kernel_map, addr, addr + s); + if (rv != KERN_SUCCESS) + panic("pmap_init: uvm_unmap failed"); + + /* + * Now allocate the space and link the pages together to + * form the KPT free list. + */ + addr = uvm_km_zalloc(kernel_map, s); + if (addr == 0) + panic("pmap_init: cannot allocate KPT free list"); + s = ptoa(npages); + addr2 = addr + s; + kpt_pages = &((struct kpt_page *)addr2)[npages]; + 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; + (void) pmap_extract(pmap_kernel(), addr2, + (paddr_t *)&kpt_pages->kpt_pa); + } while (addr != addr2); + + PMAP_DPRINTF(PDB_INIT, ("pmap_init: KPT: %ld pages from %lx to %lx\n", + atop(s), addr, addr + s)); + + /* + * Allocate the segment table map and the page table map. + */ + s = maxproc * STSIZE; + st_map = uvm_km_suballoc(kernel_map, &addr, &addr2, s, 0, + FALSE, &st_map_store); + + addr = PTBASE; + if ((PTMAXSIZE / MAX_PTSIZE) < maxproc) { + s = PTMAXSIZE; + /* + * XXX We don't want to hang when we run out of + * page tables, so we lower maxproc so that fork() + * will fail instead. Note that root could still raise + * this value via sysctl(2). + */ + maxproc = (PTMAXSIZE / MAX_PTSIZE); + } else + s = (maxproc * MAX_PTSIZE); + pt_map = uvm_km_suballoc(kernel_map, &addr, &addr2, s, VM_MAP_PAGEABLE, + TRUE, &pt_map_store); + +#if defined(M68040) + if (mmutype == MMU_68040) { + protostfree = ~l2tobm(0); + for (rv = MAXUL2SIZE; rv < sizeof(protostfree)*NBBY; rv++) + protostfree &= ~l2tobm(rv); + } +#endif + + /* + * Initialize the pmap pools. + */ + pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl", + 0, pool_page_alloc_nointr, pool_page_free_nointr, M_VMPMAP); + + /* + * Now it is safe to enable pv_table recording. + */ + pmap_initialized = TRUE; +} + +/* + * pmap_alloc_pv: + * + * Allocate a pv_entry. + */ +struct pv_entry * +pmap_alloc_pv() +{ + struct pv_page *pvp; + struct pv_entry *pv; + int i; + + if (pv_nfree == 0) { + pvp = (struct pv_page *)uvm_km_zalloc(kernel_map, NBPG); + if (pvp == 0) + panic("pmap_alloc_pv: uvm_km_zalloc() failed"); + pvp->pvp_pgi.pgi_freelist = pv = &pvp->pvp_pv[1]; + for (i = NPVPPG - 2; i; i--, pv++) + pv->pv_next = pv + 1; + pv->pv_next = 0; + pv_nfree += pvp->pvp_pgi.pgi_nfree = NPVPPG - 1; + TAILQ_INSERT_HEAD(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + pv = &pvp->pvp_pv[0]; + } else { + --pv_nfree; + pvp = pv_page_freelist.tqh_first; + if (--pvp->pvp_pgi.pgi_nfree == 0) { + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + } + pv = pvp->pvp_pgi.pgi_freelist; +#ifdef DIAGNOSTIC + if (pv == 0) + panic("pmap_alloc_pv: pgi_nfree inconsistent"); +#endif + pvp->pvp_pgi.pgi_freelist = pv->pv_next; + } + return pv; +} + +/* + * pmap_free_pv: + * + * Free a pv_entry. + */ +void +pmap_free_pv(pv) + struct pv_entry *pv; +{ + struct pv_page *pvp; + + pvp = (struct pv_page *) trunc_page(pv); + switch (++pvp->pvp_pgi.pgi_nfree) { + case 1: + TAILQ_INSERT_TAIL(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + default: + pv->pv_next = pvp->pvp_pgi.pgi_freelist; + pvp->pvp_pgi.pgi_freelist = pv; + ++pv_nfree; + break; + case NPVPPG: + pv_nfree -= NPVPPG - 1; + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + uvm_km_free(kernel_map, (vaddr_t)pvp, NBPG); + break; + } +} + +/* + * pmap_collect_pv: + * + * Perform compaction on the PV list, called via pmap_collect(). + */ +void +pmap_collect_pv() +{ + struct pv_page_list pv_page_collectlist; + struct pv_page *pvp, *npvp; + struct pv_entry *ph, *ppv, *pv, *npv; + int s; + + TAILQ_INIT(&pv_page_collectlist); + + for (pvp = pv_page_freelist.tqh_first; pvp; pvp = npvp) { + if (pv_nfree < NPVPPG) + break; + npvp = pvp->pvp_pgi.pgi_list.tqe_next; + if (pvp->pvp_pgi.pgi_nfree > NPVPPG / 3) { + TAILQ_REMOVE(&pv_page_freelist, pvp, pvp_pgi.pgi_list); + TAILQ_INSERT_TAIL(&pv_page_collectlist, pvp, + pvp_pgi.pgi_list); + pv_nfree -= NPVPPG; + pvp->pvp_pgi.pgi_nfree = -1; + } + } + + if (pv_page_collectlist.tqh_first == 0) + return; + + for (ph = &pv_table[page_cnt - 1]; ph >= &pv_table[0]; ph--) { + if (ph->pv_pmap == 0) + continue; + s = splimp(); + for (ppv = ph; (pv = ppv->pv_next) != 0; ) { + pvp = (struct pv_page *) trunc_page(pv); + if (pvp->pvp_pgi.pgi_nfree == -1) { + pvp = pv_page_freelist.tqh_first; + if (--pvp->pvp_pgi.pgi_nfree == 0) { + TAILQ_REMOVE(&pv_page_freelist, pvp, + pvp_pgi.pgi_list); + } + npv = pvp->pvp_pgi.pgi_freelist; +#ifdef DIAGNOSTIC + if (npv == 0) + panic("pmap_collect_pv: pgi_nfree inconsistent"); +#endif + pvp->pvp_pgi.pgi_freelist = npv->pv_next; + *npv = *pv; + ppv->pv_next = npv; + ppv = npv; + } else + ppv = pv; + } + splx(s); + } + + for (pvp = pv_page_collectlist.tqh_first; pvp; pvp = npvp) { + npvp = pvp->pvp_pgi.pgi_list.tqe_next; + uvm_km_free(kernel_map, (vaddr_t)pvp, NBPG); + } +} + +/* + * pmap_map: + * + * 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. + * + * Note: THIS FUNCTION IS DEPRECATED, AND SHOULD BE REMOVED! + */ +vaddr_t +pmap_map(va, spa, epa, prot) + vaddr_t va; + paddr_t spa, epa; + int prot; +{ + + PMAP_DPRINTF(PDB_FOLLOW, + ("pmap_map(%lx, %lx, %lx, %x)\n", va, spa, epa, prot)); + + while (spa < epa) { + pmap_enter(pmap_kernel(), va, spa, prot, 0); + va += NBPG; + spa += NBPG; + } + return (va); +} + +/* + * pmap_create: [ INTERFACE ] + * + * Create and return a physical map. + * + * Note: no locking is necessary in this function. + */ +pmap_t +pmap_create() +{ + pmap_t pmap; + + PMAP_DPRINTF(PDB_FOLLOW|PDB_CREATE, + ("pmap_create\n")); + + pmap = pool_get(&pmap_pmap_pool, PR_WAITOK); + bzero(pmap, sizeof(*pmap)); + pmap_pinit(pmap); + return (pmap); +} + +/* + * pmap_pinit: + * + * Initialize a preallocated and zeroed pmap structure. + * + * Note: THIS FUNCTION SHOULD BE MOVED INTO pmap_create()! + */ +void +pmap_pinit(pmap) + struct pmap *pmap; +{ + + PMAP_DPRINTF(PDB_FOLLOW|PDB_CREATE, + ("pmap_pinit(%p)\n", pmap)); + + /* + * 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. + */ + pmap->pm_stab = Segtabzero; + pmap->pm_stpa = Segtabzeropa; +#if defined(M68040) + if (mmutype == MMU_68040) + pmap->pm_stfree = protostfree; +#endif + pmap->pm_count = 1; + simple_lock_init(&pmap->pm_lock); +} + +/* + * pmap_destroy: [ INTERFACE ] + * + * Drop the reference count on the specified pmap, releasing + * all resources if the reference count drops to zero. + */ +void +pmap_destroy(pmap) + pmap_t pmap; +{ + int count; + + if (pmap == NULL) + return; + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_destroy(%p)\n", pmap)); + + simple_lock(&pmap->pm_lock); + count = --pmap->pm_count; + simple_unlock(&pmap->pm_lock); + if (count == 0) { + pmap_release(pmap); + pool_put(&pmap_pmap_pool, pmap); + } +} + +/* + * pmap_release: + * + * Relese the resources held by a pmap. + * + * Note: THIS FUNCTION SHOULD BE MOVED INTO pmap_destroy(). + */ +void +pmap_release(pmap) + struct pmap *pmap; +{ + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_release(%p)\n", pmap)); + +#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) + uvm_km_free_wakeup(pt_map, (vaddr_t)pmap->pm_ptab, + MAX_PTSIZE); + if (pmap->pm_stab != Segtabzero) + uvm_km_free_wakeup(st_map, (vaddr_t)pmap->pm_stab, + STSIZE); +} + +/* + * pmap_reference: [ INTERFACE ] + * + * Add a reference to the specified pmap. + */ +void +pmap_reference(pmap) + pmap_t pmap; +{ + + if (pmap == NULL) + return; + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_reference(%p)\n", pmap)); + + simple_lock(&pmap->pm_lock); + pmap->pm_count++; + simple_unlock(&pmap->pm_lock); +} + +/* + * pmap_activate: [ INTERFACE ] + * + * Activate the pmap used by the specified process. This includes + * reloading the MMU context if the current process, and marking + * the pmap in use by the processor. + * + * Note: we may only use spin locks here, since we are called + * by a critical section in cpu_switch()! + */ +void +pmap_activate(p) + struct proc *p; +{ + pmap_t pmap = p->p_vmspace->vm_map.pmap; + + PMAP_DPRINTF(PDB_FOLLOW|PDB_SEGTAB, + ("pmap_activate(%p)\n", p)); + + PMAP_ACTIVATE(pmap, p == curproc); +} + +/* + * pmap_deactivate: [ INTERFACE ] + * + * Mark that the pmap used by the specified process is no longer + * in use by the processor. + * + * The comment above pmap_activate() wrt. locking applies here, + * as well. + */ +void +pmap_deactivate(p) + struct proc *p; +{ + + /* No action necessary in this pmap implementation. */ +} + +/* + * pmap_remove: [ INTERFACE ] + * + * 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) + pmap_t pmap; + vaddr_t sva, eva; +{ + vaddr_t nssva; + pt_entry_t *pte; + int flags; + + PMAP_DPRINTF(PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT, + ("pmap_remove(%p, %lx, %lx)\n", pmap, sva, eva)); + + if (pmap == NULL) + return; + + flags = active_pmap(pmap) ? PRM_TFLUSH : 0; + while (sva < eva) { + nssva = m68k_trunc_seg(sva) + NBSEG; + if (nssva == 0 || nssva > eva) + nssva = eva; + /* + * If VA belongs to an unallocated segment, + * skip to the next segment boundary. + */ + if (!pmap_ste_v(pmap, sva)) { + sva = nssva; + continue; + } + /* + * Invalidate every valid mapping within this segment. + */ + pte = pmap_pte(pmap, sva); + while (sva < nssva) { + if (pmap_pte_v(pte)) { + pmap_remove_mapping(pmap, sva, pte, flags); + } + pte++; + sva += NBPG; + } + } +} + +/* + * pmap_page_protect: [ INTERFACE ] + * + * Lower the permission for all mappings to a given page to + * the permissions specified. + */ +void +pmap_page_protect(pg, prot) + struct vm_page *pg; + vm_prot_t prot; +{ + paddr_t pa = VM_PAGE_TO_PHYS(pg); + struct pv_entry *pv; + int s; + +#ifdef DEBUG + if ((pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) || + (prot == VM_PROT_NONE && (pmapdebug & PDB_REMOVE))) + printf("pmap_page_protect(%lx, %x)\n", pa, prot); +#endif + if (PAGE_IS_MANAGED(pa) == 0) + return; + + switch (prot) { + case VM_PROT_READ|VM_PROT_WRITE: + case VM_PROT_ALL: + return; + /* copy_on_write */ + case VM_PROT_READ: + case VM_PROT_READ|VM_PROT_EXECUTE: + pmap_changebit(pa, PG_RO, ~0); + return; + /* remove_all */ + default: + break; + } + pv = pa_to_pvh(pa); + s = splimp(); + while (pv->pv_pmap != NULL) { + pt_entry_t *pte; + + pte = pmap_pte(pv->pv_pmap, pv->pv_va); +#ifdef DEBUG + if (!pmap_ste_v(pv->pv_pmap, pv->pv_va) || + pmap_pte_pa(pte) != pa) + panic("pmap_page_protect: bad mapping"); +#endif + if (!pmap_pte_w(pte)) + pmap_remove_mapping(pv->pv_pmap, pv->pv_va, + pte, PRM_TFLUSH|PRM_CFLUSH); + else { + pv = pv->pv_next; +#ifdef DEBUG + if (pmapdebug & PDB_PARANOIA) + printf("%s wired mapping for %lx not removed\n", + "pmap_page_protect:", pa); +#endif + if (pv == NULL) + break; + } + } + splx(s); +} + +/* + * pmap_protect: [ INTERFACE ] + * + * Set the physical protectoin on the specified range of this map + * as requested. + */ +void +pmap_protect(pmap, sva, eva, prot) + pmap_t pmap; + vaddr_t sva, eva; + vm_prot_t prot; +{ + vaddr_t nssva; + pt_entry_t *pte; + boolean_t firstpage, needtflush; + int isro; + + PMAP_DPRINTF(PDB_FOLLOW|PDB_PROTECT, + ("pmap_protect(%p, %lx, %lx, %x)\n", + pmap, sva, eva, prot)); + + if (pmap == NULL) + return; + +#ifdef PMAPSTATS + protect_stats.calls++; +#endif + if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + pmap_remove(pmap, sva, eva); + return; + } + if (prot & VM_PROT_WRITE) + return; + + isro = pte_prot(pmap, prot); + needtflush = active_pmap(pmap); + firstpage = TRUE; + while (sva < eva) { + nssva = m68k_trunc_seg(sva) + NBSEG; + if (nssva == 0 || nssva > eva) + nssva = eva; + /* + * If VA belongs to an unallocated segment, + * skip to the next segment boundary. + */ + if (!pmap_ste_v(pmap, sva)) { + sva = nssva; + continue; + } + /* + * Change protection on mapping if it is valid and doesn't + * already have the correct protection. + */ + pte = pmap_pte(pmap, sva); + while (sva < nssva) { + if (pmap_pte_v(pte) && pmap_pte_prot_chg(pte, isro)) { +#if defined(M68040) + /* + * Clear caches if making RO (see section + * "7.3 Cache Coherency" in the manual). + */ + if (isro && mmutype == MMU_68040) { + paddr_t pa = pmap_pte_pa(pte); + + DCFP(pa); + ICPP(pa); + } +#endif + pmap_pte_set_prot(pte, isro); + if (needtflush) + TBIS(sva); + firstpage = FALSE; + } + pte++; + sva += NBPG; + } + } +} + +/* + * pmap_enter: [ INTERFACE ] + * + * Insert the given physical page (pa) at + * the specified virtual address (va) in the + * target physical map with the protection requested. + * + * If specified, the page will be wired down, meaning + * that the related pte cannot be reclaimed. + * + * Note: This is the only routine which MAY NOT lazy-evaluate + * or lose information. Thatis, this routine must actually + * insert this page into the given map NOW. + */ +int +pmap_enter(pmap, va, pa, prot, flags) + pmap_t pmap; + vaddr_t va; + paddr_t pa; + vm_prot_t prot; + int flags; +{ + pt_entry_t *pte; + int npte; + paddr_t opa; + boolean_t cacheable = TRUE; + boolean_t checkpv = TRUE; + boolean_t wired = (flags & PMAP_WIRED) != 0; + + PMAP_DPRINTF(PDB_FOLLOW|PDB_ENTER, + ("pmap_enter(%p, %lx, %lx, %x, %x)\n", + pmap, va, pa, prot, wired)); + + if (pmap == NULL) + return (KERN_SUCCESS); + +#ifdef DIAGNOSTIC + /* + * pmap_enter() should never be used for CADDR1 and CADDR2. + */ + if (pmap == pmap_kernel() && + (va == (vaddr_t)CADDR1 || va == (vaddr_t)CADDR2)) + panic("pmap_enter: used for CADDR1 or CADDR2"); +#endif + + /* + * For user mapping, allocate kernel VM resources if necessary. + */ + if (pmap->pm_ptab == NULL) + pmap->pm_ptab = (pt_entry_t *) + uvm_km_valloc_wait(pt_map, MAX_PTSIZE); + + /* + * Segment table entry not valid, we need a new PT page + */ + if (!pmap_ste_v(pmap, va)) + pmap_enter_ptpage(pmap, va); + + pa = m68k_trunc_page(pa); + pte = pmap_pte(pmap, va); + opa = pmap_pte_pa(pte); + + PMAP_DPRINTF(PDB_ENTER, ("enter: pte %p, *pte %x\n", pte, *pte)); + + /* + * Mapping has not changed, must be protection or wiring change. + */ + if (opa == pa) { + /* + * 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 (pmap_pte_w_chg(pte, wired ? PG_W : 0)) { + PMAP_DPRINTF(PDB_ENTER, + ("enter: wiring change -> %x\n", wired)); + if (wired) + pmap->pm_stats.wired_count++; + else + pmap->pm_stats.wired_count--; + } + /* + * 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) { + PMAP_DPRINTF(PDB_ENTER, + ("enter: removing old mapping %lx\n", va)); + pmap_remove_mapping(pmap, va, pte, + PRM_TFLUSH|PRM_CFLUSH|PRM_KEEPPTPAGE); + } + + /* + * 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 != pmap_kernel()) + pmap_ptpage_addref(trunc_page(pte)); + + /* + * 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 (PAGE_IS_MANAGED(pa)) { + struct pv_entry *pv, *npv; + int s; + + pv = pa_to_pvh(pa); + s = splimp(); + + PMAP_DPRINTF(PDB_ENTER, + ("enter: pv at %p: %lx/%p/%p\n", + pv, pv->pv_va, pv->pv_pmap, pv->pv_next)); + /* + * No entries yet, use header as the first entry + */ + if (pv->pv_pmap == NULL) { + 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 = pmap_alloc_pv(); + npv->pv_va = va; + npv->pv_pmap = pmap; + npv->pv_next = pv->pv_next; + npv->pv_ptste = NULL; + npv->pv_ptpmap = NULL; + npv->pv_flags = 0; + pv->pv_next = npv; + } + + /* + * Speed pmap_is_referenced() or pmap_is_modified() based + * on the hint provided in access_type. + */ +#ifdef DIAGNOSTIC + if ((flags & VM_PROT_ALL) & ~prot) + panic("pmap_enter: access_type exceeds prot"); +#endif + if (flags & VM_PROT_WRITE) + *pa_to_attribute(pa) |= (PG_U|PG_M); + else if (flags & VM_PROT_ALL) + *pa_to_attribute(pa) |= PG_U; + + 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; + } + + /* + * Increment counters + */ + pmap->pm_stats.resident_count++; + if (wired) + pmap->pm_stats.wired_count++; + +validate: + /* + * Build the new PTE. + */ + npte = pa | pte_prot(pmap, prot) | (*pte & (PG_M|PG_U)) | PG_V; + if (wired) + npte |= PG_W; + if (!checkpv && !cacheable) + npte |= PG_CI; +#if defined(M68040) + if (mmutype == MMU_68040 && (npte & (PG_PROT|PG_CI)) == PG_RW) +#ifdef DEBUG + if (dowriteback && (dokwriteback || pmap != pmap_kernel())) +#endif + npte |= PG_CCB; +#endif + + PMAP_DPRINTF(PDB_ENTER, ("enter: new pte value %x\n", npte)); + + /* + * Remember if this was a wiring-only change. + * If so, we need not flush the TLB and caches. + */ + wired = ((*pte ^ npte) == PG_W); +#if defined(M68040) + if (mmutype == MMU_68040 && !wired) { + DCFP(pa); + ICPP(pa); + } +#endif + *pte = npte; + if (!wired && active_pmap(pmap)) + TBIS(va); +#ifdef DEBUG + if ((pmapdebug & PDB_WIRING) && pmap != pmap_kernel()) + pmap_check_wiring("enter", trunc_page(pte)); +#endif + + return (KERN_SUCCESS); +} + +void +pmap_kenter_pa(va, pa, prot) + vaddr_t va; + paddr_t pa; + vm_prot_t prot; +{ + pmap_enter(pmap_kernel(), va, pa, prot, PMAP_WIRED); +} + +void +pmap_kenter_pgs(va, pgs, npgs) + vaddr_t va; + struct vm_page **pgs; + int npgs; +{ + int i; + + for (i = 0; i < npgs; i++, va += PAGE_SIZE) { + pmap_enter(pmap_kernel(), va, VM_PAGE_TO_PHYS(pgs[i]), + VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED); + } +} + +void +pmap_kremove(va, len) + vaddr_t va; + vsize_t len; +{ + for (len >>= PAGE_SHIFT; len > 0; len--, va += PAGE_SIZE) { + pmap_remove(pmap_kernel(), va, va + PAGE_SIZE); + } +} + +/* + * pmap_unwire: [ INTERFACE ] + * + * Clear the wired attribute for a map/virtual-address pair. + * + * The mapping must already exist in the pmap. + */ +void +pmap_unwire(pmap, va) + pmap_t pmap; + vaddr_t va; +{ + pt_entry_t *pte; + + PMAP_DPRINTF(PDB_FOLLOW, + ("pmap_unwire(%p, %lx)\n", pmap, va)); + + 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, va)) { + if (pmapdebug & PDB_PARANOIA) + printf("pmap_unwire: invalid STE for %lx\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_unwire: invalid PTE for %lx\n", va); + } +#endif + /* + * If wiring actually changed (always?) clear the wire bit and + * update the wire count. Note that wiring is not a hardware + * characteristic so there is no need to invalidate the TLB. + */ + if (pmap_pte_w_chg(pte, 0)) { + pmap_pte_set_w(pte, FALSE); + pmap->pm_stats.wired_count--; + } +#ifdef DIAGNOSTIC + else { + printf("pmap_unwire: wiring for pmap %p va 0x%lx " + "didn't change!\n", pmap, va); + } +#endif +} + +/* + * pmap_extract: [ INTERFACE ] + * + * Extract the physical address associated with the given + * pmap/virtual address pair. + */ +boolean_t +pmap_extract(pmap, va, pap) + pmap_t pmap; + vaddr_t va; + paddr_t *pap; +{ + boolean_t rv = FALSE; + paddr_t pa; + u_int pte; + + PMAP_DPRINTF(PDB_FOLLOW, + ("pmap_extract(%p, %lx) -> ", pmap, va)); + + if (pmap && pmap_ste_v(pmap, va)) { + pte = *(u_int *)pmap_pte(pmap, va); + if (pte) { + pa = (pte & PG_FRAME) | (va & ~PG_FRAME); + if (pap != NULL) + *pap = pa; + rv = TRUE; + } + } +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) { + if (rv) + printf("%lx\n", pa); + else + printf("failed\n"); + } +#endif + return (rv); +} + +/* + * pmap_copy: [ INTERFACE ] + * + * Copy the mapping 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; + vaddr_t dst_addr; + vsize_t len; + vaddr_t src_addr; +{ + + PMAP_DPRINTF(PDB_FOLLOW, + ("pmap_copy(%p, %p, %lx, %lx, %lx)\n", + dst_pmap, src_pmap, dst_addr, len, src_addr)); +} + +/* + * pmap_update: + * + * Require that all active physical maps contain no + * incorrect entires NOW, by processing any deferred + * pmap operations. + */ +void +pmap_update() +{ + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_update()\n")); + +#if (defined(M68020)||defined(M68040)||defined(M68060)) + TBIA(); +#endif +} + +/* + * pmap_collect: [ INTERFACE ] + * + * 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. + * + * Called by the pageout daemon when pages are scarce. + */ +void +pmap_collect(pmap) + pmap_t pmap; +{ + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_collect(%p)\n", pmap)); + + if (pmap == pmap_kernel()) { + int bank, s; + + /* + * XXX This is very bogus. We should handle kernel PT + * XXX pages much differently. + */ + + s = splimp(); + for (bank = 0; bank < vm_nphysseg; bank++) + pmap_collect1(pmap, ptoa(vm_physmem[bank].start), + ptoa(vm_physmem[bank].end)); + splx(s); + } else { + /* + * This process is about to be swapped out; free all of + * the PT pages by removing the physical mappings for its + * entire address space. Note: pmap_remove() performs + * all necessary locking. + */ + pmap_remove(pmap, VM_MIN_ADDRESS, VM_MAX_ADDRESS); + } + +#ifdef notyet + /* Go compact and garbage-collect the pv_table. */ + pmap_collect_pv(); +#endif +} + +/* + * pmap_collect1(): + * + * Garbage-collect KPT pages. Helper for the above (bogus) + * pmap_collect(). + * + * Note: THIS SHOULD GO AWAY, AND BE REPLACED WITH A BETTER + * WAY OF HANDLING PT PAGES! + */ +void +pmap_collect1(pmap, startpa, endpa) + pmap_t pmap; + paddr_t startpa, endpa; +{ + paddr_t pa; + struct pv_entry *pv; + pt_entry_t *pte; + paddr_t kpa; +#ifdef DEBUG + st_entry_t *ste; + int opmapdebug = 0 /* XXX initialize to quiet gcc -Wall */; +#endif + + for (pa = startpa; pa < endpa; pa += NBPG) { + 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 != pmap_kernel() || !(pv->pv_flags & PV_PTPAGE)) + continue; + do { + if (pv->pv_ptste && pv->pv_ptpmap == pmap_kernel()) + break; + } while ((pv = pv->pv_next)); + if (pv == NULL) + continue; +#ifdef DEBUG + if (pv->pv_va < (vaddr_t)Sysmap || + pv->pv_va >= (vaddr_t)Sysmap + MAX_PTSIZE) + printf("collect: kernel PT VA out of range\n"); + else + goto ok; + pmap_pvdump(pa); + continue; +ok: +#endif + pte = (pt_entry_t *)(pv->pv_va + NBPG); + while (--pte >= (pt_entry_t *)pv->pv_va && *pte == PG_NV) + ; + if (pte >= (pt_entry_t *)pv->pv_va) + continue; + +#ifdef DEBUG + if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) { + printf("collect: freeing KPT page at %lx (ste %x@%p)\n", + pv->pv_va, *pv->pv_ptste, pv->pv_ptste); + opmapdebug = pmapdebug; + pmapdebug |= PDB_PTPAGE; + } + + ste = pv->pv_ptste; +#endif + /* + * If all entries were invalid we can remove the page. + * We call pmap_remove_entry to take care of invalidating + * ST and Sysptmap entries. + */ + (void) pmap_extract(pmap, pv->pv_va, (paddr_t *)&kpa); + pmap_remove_mapping(pmap, pv->pv_va, PT_ENTRY_NULL, + PRM_TFLUSH|PRM_CFLUSH); + /* + * 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: %lx (%lx) 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 + if (pmapdebug & (PDB_PTPAGE|PDB_COLLECT)) + pmapdebug = opmapdebug; + + if (*ste != SG_NV) + printf("collect: kernel STE at %p still valid (%x)\n", + ste, *ste); + ste = &Sysptmap[ste - pmap_ste(pmap_kernel(), 0)]; + if (*ste != SG_NV) + printf("collect: kernel PTmap at %p still valid (%x)\n", + ste, *ste); +#endif + } +} + +/* + * pmap_zero_page: [ INTERFACE ] + * + * Zero 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. + * + * Note: WE DO NOT CURRENTLY LOCK THE TEMPORARY ADDRESSES! + * (Actually, we go to splimp(), and since we don't + * support multiple processors, this is sufficient.) + */ +void +pmap_zero_page(phys) + paddr_t phys; +{ + int s, npte; + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_zero_page(%lx)\n", phys)); + + npte = phys | PG_V; + +#if defined(M68040) || defined(M68060) + if (mmutype == MMU_68040) { + /* + * Set copyback caching on the page; this is required + * for cache consistency (since regular mappings are + * copyback as well). + */ + npte |= PG_CCB; + } +#endif + + s = splimp(); + + *caddr1_pte = npte; + TBIS((vaddr_t)CADDR1); + + zeropage(CADDR1); + +#ifdef DEBUG + *caddr1_pte = PG_NV; + TBIS((vaddr_t)CADDR1); +#endif + + splx(s); +} + +/* + * pmap_copy_page: [ INTERFACE ] + * + * Copy 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. + * + * Note: WE DO NOT CURRENTLY LOCK THE TEMPORARY ADDRESSES! + * (Actually, we go to splimp(), and since we don't + * support multiple processors, this is sufficient.) + */ +void +pmap_copy_page(src, dst) + paddr_t src, dst; +{ + int s, npte1, npte2; + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_copy_page(%lx, %lx)\n", src, dst)); + + npte1 = src | PG_RO | PG_V; + npte2 = dst | PG_V; + +#if defined(M68040) || defined(M68060) + if (mmutype == MMU_68040) { + /* + * Set copyback caching on the pages; this is required + * for cache consistency (since regular mappings are + * copyback as well). + */ + npte1 |= PG_CCB; + npte2 |= PG_CCB; + } +#endif + + s = splimp(); + + *caddr1_pte = npte1; + TBIS((vaddr_t)CADDR1); + + *caddr2_pte = npte2; + TBIS((vaddr_t)CADDR2); + + copypage(CADDR1, CADDR2); + +#ifdef DEBUG + *caddr1_pte = PG_NV; + TBIS((vaddr_t)CADDR1); + + *caddr2_pte = PG_NV; + TBIS((vaddr_t)CADDR2); +#endif + + splx(s); +} + +/* + * pmap_clear_modify: [ INTERFACE ] + * + * Clear the modify bits on the specified physical page. + */ +boolean_t +pmap_clear_modify(pg) + struct vm_page *pg; +{ + paddr_t pa = VM_PAGE_TO_PHYS(pg); + boolean_t rv; + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_clear_modify(%lx)\n", pa)); + + rv = pmap_testbit(pa, PG_M); + pmap_changebit(pa, 0, ~PG_M); + return rv; +} + +/* + * pmap_clear_reference: [ INTERFACE ] + * + * Clear the reference bit on the specified physical page. + */ +boolean_t +pmap_clear_reference(pg) + struct vm_page *pg; +{ + paddr_t pa = VM_PAGE_TO_PHYS(pg); + boolean_t rv; + + PMAP_DPRINTF(PDB_FOLLOW, ("pmap_clear_reference(%lx)\n", pa)); + + rv = pmap_testbit(pa, PG_U); + pmap_changebit(pa, 0, ~PG_U); + return rv; +} + +/* + * pmap_is_referenced: [ INTERFACE ] + * + * Return whether or not the specified physical page is referenced + * by any physical maps. + */ +boolean_t +pmap_is_referenced(pg) + struct vm_page *pg; +{ + paddr_t pa = VM_PAGE_TO_PHYS(pg); + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) { + boolean_t rv = pmap_testbit(pa, PG_U); + printf("pmap_is_referenced(%lx) -> %c\n", pa, "FT"[rv]); + return(rv); + } +#endif + return(pmap_testbit(pa, PG_U)); +} + +/* + * pmap_is_modified: [ INTERFACE ] + * + * Return whether or not the specified physical page is modified + * by any physical maps. + */ +boolean_t +pmap_is_modified(pg) + struct vm_page *pg; +{ + paddr_t pa = VM_PAGE_TO_PHYS(pg); + +#ifdef DEBUG + if (pmapdebug & PDB_FOLLOW) { + boolean_t rv = pmap_testbit(pa, PG_M); + printf("pmap_is_modified(%lx) -> %c\n", pa, "FT"[rv]); + return(rv); + } +#endif + return(pmap_testbit(pa, PG_M)); +} + +/* + * pmap_phys_address: [ INTERFACE ] + * + * Return the physical address corresponding to the specified + * cookie. Used by the device pager to decode a device driver's + * mmap entry point return value. + * + * Note: no locking is necessary in this function. + */ +paddr_t +pmap_phys_address(ppn) + int ppn; +{ + return(m68k_ptob(ppn)); +} + +/* + * Miscellaneous support routines follow + */ + +/* + * pmap_remove_mapping: + * + * Invalidate a single page denoted by pmap/va. + * + * If (pte != NULL), it is the already computed PTE for the page. + * + * If (flags & PRM_TFLUSH), we must invalidate any TLB information. + * + * If (flags & PRM_CFLUSH), we must flush/invalidate any cache + * information. + * + * If (flags & PRM_KEEPPTPAGE), we don't free the page table page + * if the reference drops to zero. + */ +/* static */ +void +pmap_remove_mapping(pmap, va, pte, flags) + pmap_t pmap; + vaddr_t va; + pt_entry_t *pte; + int flags; +{ + paddr_t pa; + struct pv_entry *pv, *npv; + pmap_t ptpmap; + st_entry_t *ste; + int s, bits; +#ifdef DEBUG + pt_entry_t opte; +#endif + + PMAP_DPRINTF(PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT, + ("pmap_remove_mapping(%p, %lx, %p, %x)\n", + pmap, va, pte, flags)); + + /* + * PTE not provided, compute it from pmap and va. + */ + if (pte == PT_ENTRY_NULL) { + pte = pmap_pte(pmap, va); + if (*pte == PG_NV) + return; + } + + pa = pmap_pte_pa(pte); +#ifdef DEBUG + opte = *pte; +#endif + /* + * Update statistics + */ + if (pmap_pte_w(pte)) + pmap->pm_stats.wired_count--; + pmap->pm_stats.resident_count--; + + /* + * Invalidate the PTE after saving the reference modify info. + */ + PMAP_DPRINTF(PDB_REMOVE, ("remove: invalidating pte at %p\n", pte)); + bits = *pte & (PG_U|PG_M); + *pte = PG_NV; + if ((flags & PRM_TFLUSH) && active_pmap(pmap)) + TBIS(va); + /* + * For user mappings decrement the wiring count on + * the PT page. + */ + if (pmap != pmap_kernel()) { + vaddr_t ptpva = trunc_page(pte); + int refs = pmap_ptpage_delref(ptpva); +#ifdef DEBUG + if (pmapdebug & PDB_WIRING) + pmap_check_wiring("remove", ptpva); +#endif + /* + * If reference count drops to 1, and we're not instructed + * to keep it around, free the PT page. + * + * Note: refcnt == 1 comes from the fact that we allocate + * the page with uvm_fault_wire(), which initially wires + * the page. The first reference we actually add causes + * the refcnt to be 2. + */ + if (refs == 1 && (flags & PRM_KEEPPTPAGE) == 0) { + struct pv_entry *pv; + paddr_t pa; + + pa = pmap_pte_pa(pmap_pte(pmap_kernel(), ptpva)); +#ifdef DIAGNOSTIC + if (PAGE_IS_MANAGED(pa) == 0) + panic("pmap_remove_mapping: unmanaged PT page"); +#endif + pv = pa_to_pvh(pa); +#ifdef DIAGNOSTIC + if (pv->pv_ptste == NULL) + panic("pmap_remove_mapping: ptste == NULL"); + if (pv->pv_pmap != pmap_kernel() || + pv->pv_va != ptpva || + pv->pv_next != NULL) + panic("pmap_remove_mapping: " + "bad PT page pmap %p, va 0x%lx, next %p", + pv->pv_pmap, pv->pv_va, pv->pv_next); +#endif + pmap_remove_mapping(pv->pv_pmap, pv->pv_va, + NULL, PRM_TFLUSH|PRM_CFLUSH); + uvm_pagefree(PHYS_TO_VM_PAGE(pa)); + PMAP_DPRINTF(PDB_REMOVE|PDB_PTPAGE, + ("remove: PT page 0x%lx (0x%lx) freed\n", + ptpva, pa)); + } + } + /* + * If this isn't a managed page, we are all done. + */ + if (PAGE_IS_MANAGED(pa) == 0) + return; + /* + * Otherwise remove it from the PV table + * (raise IPL since we may be called at interrupt time). + */ + pv = pa_to_pvh(pa); + ste = ST_ENTRY_NULL; + 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 = pv->pv_ptste; + ptpmap = pv->pv_ptpmap; + npv = pv->pv_next; + if (npv) { + npv->pv_flags = pv->pv_flags; + *pv = *npv; + pmap_free_pv(npv); + } else + pv->pv_pmap = NULL; + } else { + for (npv = pv->pv_next; npv; npv = npv->pv_next) { + 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 = npv->pv_ptste; + ptpmap = npv->pv_ptpmap; + pv->pv_next = npv->pv_next; + pmap_free_pv(npv); + pv = pa_to_pvh(pa); + } + /* + * If this was a PT page we must also remove the + * mapping from the associated segment table. + */ + if (ste) { + PMAP_DPRINTF(PDB_REMOVE|PDB_PTPAGE, + ("remove: ste was %x@%p pte was %x@%p\n", + *ste, ste, opte, pmap_pte(pmap, va))); +#if defined(M68040) + if (mmutype == MMU_68040) { + st_entry_t *este = &ste[NPTEPG/SG4_LEV3SIZE]; + + while (ste < este) + *ste++ = SG_NV; +#ifdef DEBUG + ste -= NPTEPG/SG4_LEV3SIZE; +#endif + } else +#endif + *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 != pmap_kernel()) { + PMAP_DPRINTF(PDB_REMOVE|PDB_SEGTAB, + ("remove: stab %p, refcnt %d\n", + ptpmap->pm_stab, ptpmap->pm_sref - 1)); +#ifdef DEBUG + if ((pmapdebug & PDB_PARANOIA) && + ptpmap->pm_stab != (st_entry_t *)trunc_page(ste)) + panic("remove: bogus ste"); +#endif + if (--(ptpmap->pm_sref) == 0) { + PMAP_DPRINTF(PDB_REMOVE|PDB_SEGTAB, + ("remove: free stab %p\n", + ptpmap->pm_stab)); + uvm_km_free_wakeup(st_map, + (vaddr_t)ptpmap->pm_stab, + STSIZE); + ptpmap->pm_stab = Segtabzero; + ptpmap->pm_stpa = Segtabzeropa; +#if defined(M68040) + if (mmutype == MMU_68040) + ptpmap->pm_stfree = protostfree; +#endif + /* + * XXX may have changed segment table + * pointer for current process so + * update now to reload hardware. + */ + if (active_user_pmap(ptpmap)) + PMAP_ACTIVATE(ptpmap, 1); + } +#ifdef DEBUG + else if (ptpmap->pm_sref < 0) + panic("remove: sref < 0"); +#endif + } +#if 0 + /* + * XXX this should be unnecessary as we have been + * flushing individual mappings as we go. + */ + if (ptpmap == pmap_kernel()) + TBIAS(); + else + TBIAU(); +#endif + pv->pv_flags &= ~PV_PTPAGE; + ptpmap->pm_ptpages--; + } + /* + * Update saved attributes for managed page + */ + *pa_to_attribute(pa) |= bits; + splx(s); +} + +/* + * pmap_testbit: + * + * Test the modified/referenced bits of a physical page. + */ +/* static */ +boolean_t +pmap_testbit(pa, bit) + paddr_t pa; + int bit; +{ + struct pv_entry *pv; + pt_entry_t *pte; + int s; + + if (PAGE_IS_MANAGED(pa) == 0) + return(FALSE); + + pv = pa_to_pvh(pa); + s = splimp(); + /* + * Check saved info first + */ + if (*pa_to_attribute(pa) & bit) { + splx(s); + return(TRUE); + } + + /* + * Not found. Check current mappings, returning immediately if + * found. Cache a hit to speed future lookups. + */ + if (pv->pv_pmap != NULL) { + for (; pv; pv = pv->pv_next) { + pte = pmap_pte(pv->pv_pmap, pv->pv_va); + if (*pte & bit) { + *pa_to_attribute(pa) |= bit; + splx(s); + return(TRUE); + } + } + } + splx(s); + return(FALSE); +} + +/* + * pmap_changebit: + * + * Change the modified/referenced bits, or other PTE bits, + * for a physical page. + */ +/* static */ +void +pmap_changebit(pa, set, mask) + paddr_t pa; + int set, mask; +{ + struct pv_entry *pv; + pt_entry_t *pte, npte; + vaddr_t va; + int s; +#if defined(M68040) + boolean_t firstpage = TRUE; +#endif + + PMAP_DPRINTF(PDB_BITS, + ("pmap_changebit(%lx, %x, %x)\n", pa, set, mask)); + + if (PAGE_IS_MANAGED(pa) == 0) + return; + + pv = pa_to_pvh(pa); + s = splimp(); + + /* + * Clear saved attributes (modify, reference) + */ + *pa_to_attribute(pa) &= mask; + + /* + * Loop over all current mappings setting/clearing as appropos + * If setting RO do we need to clear the VAC? + */ + if (pv->pv_pmap != NULL) { +#ifdef DEBUG + int toflush = 0; +#endif + for (; pv; pv = pv->pv_next) { +#ifdef DEBUG + toflush |= (pv->pv_pmap == pmap_kernel()) ? 2 : 1; +#endif + va = pv->pv_va; + + /* + * XXX don't write protect pager mappings + */ + if (set == PG_RO) { + if (va >= uvm.pager_sva && va < uvm.pager_eva) + continue; + } + + pte = pmap_pte(pv->pv_pmap, va); + npte = (*pte | set) & mask; + if (*pte != npte) { +#if defined(M68040) + /* + * If we are changing caching status or + * protection make sure the caches are + * flushed (but only once). + */ + if (firstpage && (mmutype == MMU_68040) && + ((set == PG_RO) || + (set & PG_CMASK) || + (mask & PG_CMASK) == 0)) { + firstpage = FALSE; + DCFP(pa); + ICPP(pa); + } +#endif + *pte = npte; + if (active_pmap(pv->pv_pmap)) + TBIS(va); + } + } + } + splx(s); +} + +/* + * pmap_enter_ptpage: + * + * Allocate and map a PT page for the specified pmap/va pair. + */ +/* static */ +void +pmap_enter_ptpage(pmap, va) + pmap_t pmap; + vaddr_t va; +{ + paddr_t ptpa; + struct pv_entry *pv; + st_entry_t *ste; + int s; + + PMAP_DPRINTF(PDB_FOLLOW|PDB_ENTER|PDB_PTPAGE, + ("pmap_enter_ptpage: pmap %p, va %lx\n", pmap, va)); + + /* + * Allocate a segment table if necessary. Note that it is allocated + * from a private 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) { + pmap->pm_stab = (st_entry_t *) + uvm_km_zalloc(st_map, STSIZE); + (void) pmap_extract(pmap_kernel(), (vaddr_t)pmap->pm_stab, + (paddr_t *)&pmap->pm_stpa); +#if defined(M68040) + if (mmutype == MMU_68040) { +#ifdef DEBUG + if (dowriteback && dokwriteback) +#endif + pmap_changebit((paddr_t)pmap->pm_stpa, 0, ~PG_CCB); + pmap->pm_stfree = protostfree; + } +#endif + /* + * XXX may have changed segment table pointer for current + * process so update now to reload hardware. + */ + if (active_user_pmap(pmap)) + PMAP_ACTIVATE(pmap, 1); + + PMAP_DPRINTF(PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB, + ("enter: pmap %p stab %p(%p)\n", + pmap, pmap->pm_stab, pmap->pm_stpa)); + } + + ste = pmap_ste(pmap, va); +#if defined(M68040) + /* + * Allocate level 2 descriptor block if necessary + */ + if (mmutype == MMU_68040) { + if (*ste == SG_NV) { + int ix; + caddr_t addr; + + ix = bmtol2(pmap->pm_stfree); + if (ix == -1) + panic("enter: out of address space"); /* XXX */ + pmap->pm_stfree &= ~l2tobm(ix); + addr = (caddr_t)&pmap->pm_stab[ix*SG4_LEV2SIZE]; + bzero(addr, SG4_LEV2SIZE*sizeof(st_entry_t)); + addr = (caddr_t)&pmap->pm_stpa[ix*SG4_LEV2SIZE]; + *ste = (u_int)addr | SG_RW | SG_U | SG_V; + + PMAP_DPRINTF(PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB, + ("enter: alloc ste2 %d(%p)\n", ix, addr)); + } + ste = pmap_ste2(pmap, va); + /* + * Since a level 2 descriptor maps a block of SG4_LEV3SIZE + * level 3 descriptors, we need a chunk of NPTEPG/SG4_LEV3SIZE + * (16) such descriptors (NBPG/SG4_LEV3SIZE bytes) to map a + * PT page--the unit of allocation. We set `ste' to point + * to the first entry of that chunk which is validated in its + * entirety below. + */ + ste = (st_entry_t *)((int)ste & ~(NBPG/SG4_LEV3SIZE-1)); + + PMAP_DPRINTF(PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB, + ("enter: ste2 %p (%p)\n", pmap_ste2(pmap, va), ste)); + } +#endif + va = trunc_page((vaddr_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 == pmap_kernel()) { + 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. + */ + PMAP_DPRINTF(PDB_COLLECT, + ("enter: no KPT pages, collecting...\n")); + pmap_collect(pmap_kernel()); + if ((kpt = kpt_free_list) == (struct kpt_page *)0) + panic("pmap_enter_ptpage: can't get KPT page"); + } + kpt_free_list = kpt->kpt_next; + kpt->kpt_next = kpt_used_list; + kpt_used_list = kpt; + ptpa = kpt->kpt_pa; + bzero((caddr_t)kpt->kpt_va, NBPG); + pmap_enter(pmap, va, ptpa, VM_PROT_DEFAULT, + VM_PROT_DEFAULT|PMAP_WIRED); +#ifdef DEBUG + if (pmapdebug & (PDB_ENTER|PDB_PTPAGE)) { + int ix = pmap_ste(pmap, va) - pmap_ste(pmap, 0); + + printf("enter: add &Sysptmap[%d]: %x (KPT page %lx)\n", + ix, Sysptmap[ix], 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. + * + * Note we use a wire-fault to keep the page off the paging + * queues. This sets our PT page's reference (wire) count to + * 1, which is what we use to check if the page can be freed. + * See pmap_remove_mapping(). + */ + else { + /* + * Count the segment table reference now so that we won't + * lose the segment table when low on memory. + */ + pmap->pm_sref++; + PMAP_DPRINTF(PDB_ENTER|PDB_PTPAGE, + ("enter: about to fault UPT pg at %lx\n", va)); + s = uvm_fault_wire(pt_map, va, va + PAGE_SIZE, + VM_PROT_READ|VM_PROT_WRITE); + if (s != KERN_SUCCESS) { + printf("uvm_fault_wire(pt_map, 0x%lx, 0x%lx, RW) " + "-> %d\n", va, va + PAGE_SIZE, s); + panic("pmap_enter: uvm_fault_wire failed"); + } + ptpa = pmap_pte_pa(pmap_pte(pmap_kernel(), va)); + } +#if defined(M68040) + /* + * Turn off copyback caching of page table pages, + * could get ugly otherwise. + */ +#ifdef DEBUG + if (dowriteback && dokwriteback) +#endif + if (mmutype == MMU_68040) { +#ifdef DEBUG + pt_entry_t *pte = pmap_pte(pmap_kernel(), va); + if ((pmapdebug & PDB_PARANOIA) && (*pte & PG_CCB) == 0) + printf("%s PT no CCB: kva=%lx ptpa=%lx pte@%p=%x\n", + pmap == pmap_kernel() ? "Kernel" : "User", + va, ptpa, pte, *pte); +#endif + pmap_changebit(ptpa, 0, ~PG_CCB); + } +#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 == pmap_kernel() && 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; + + PMAP_DPRINTF(PDB_ENTER|PDB_PTPAGE, + ("enter: new PT page at PA %lx, ste at %p\n", ptpa, ste)); + + /* + * 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. + */ +#if defined(M68040) + if (mmutype == MMU_68040) { + st_entry_t *este; + + for (este = &ste[NPTEPG/SG4_LEV3SIZE]; ste < este; ste++) { + *ste = ptpa | SG_U | SG_RW | SG_V; + ptpa += SG4_LEV3SIZE * sizeof(st_entry_t); + } + } else +#endif + *ste = (ptpa & SG_FRAME) | SG_RW | SG_V; + if (pmap != pmap_kernel()) { + PMAP_DPRINTF(PDB_ENTER|PDB_PTPAGE|PDB_SEGTAB, + ("enter: stab %p refcnt %d\n", + pmap->pm_stab, pmap->pm_sref)); + } +#if 0 + /* + * Flush stale TLB info. + */ + if (pmap == pmap_kernel()) + TBIAS(); + else + TBIAU(); +#endif + pmap->pm_ptpages++; + splx(s); +} + +/* + * pmap_ptpage_addref: + * + * Add a reference to the specified PT page. + */ +void +pmap_ptpage_addref(ptpva) + vaddr_t ptpva; +{ + vm_page_t m; + + simple_lock(&uvm.kernel_object->vmobjlock); + m = uvm_pagelookup(uvm.kernel_object, ptpva - vm_map_min(kernel_map)); + m->wire_count++; + simple_unlock(&uvm.kernel_object->vmobjlock); +} + +/* + * pmap_ptpage_delref: + * + * Delete a reference to the specified PT page. + */ +int +pmap_ptpage_delref(ptpva) + vaddr_t ptpva; +{ + vm_page_t m; + int rv; + + simple_lock(&uvm.kernel_object->vmobjlock); + m = uvm_pagelookup(uvm.kernel_object, ptpva - vm_map_min(kernel_map)); + rv = --m->wire_count; + simple_unlock(&uvm.kernel_object->vmobjlock); + return (rv); +} + +/* + * Routine: pmap_procwr + * + * Function: + * Synchronize caches corresponding to [addr, addr+len) in p. + */ +void +pmap_procwr(p, va, len) + struct proc *p; + vaddr_t va; + size_t len; +{ + (void)cachectl1(0x80000004, va, len, p); +} + + +#ifdef DEBUG +/* + * pmap_pvdump: + * + * Dump the contents of the PV list for the specified physical page. + */ +/* static */ +void +pmap_pvdump(pa) + paddr_t pa; +{ + struct pv_entry *pv; + + printf("pa %lx", pa); + for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next) + printf(" -> pmap %p, va %lx, ptste %p, ptpmap %p, flags %x", + pv->pv_pmap, pv->pv_va, pv->pv_ptste, pv->pv_ptpmap, + pv->pv_flags); + printf("\n"); +} + +/* + * pmap_check_wiring: + * + * Count the number of valid mappings in the specified PT page, + * and ensure that it is consistent with the number of wirings + * to that page that the VM system has. + */ +/* static */ +void +pmap_check_wiring(str, va) + char *str; + vaddr_t va; +{ + pt_entry_t *pte; + paddr_t pa; + vm_page_t m; + int count; + + if (!pmap_ste_v(pmap_kernel(), va) || + !pmap_pte_v(pmap_pte(pmap_kernel(), va))) + return; + + pa = pmap_pte_pa(pmap_pte(pmap_kernel(), va)); + m = PHYS_TO_VM_PAGE(pa); + if (m->wire_count < 1) { + printf("*%s*: 0x%lx: wire count %d\n", str, va, m->wire_count); + return; + } + + count = 0; + for (pte = (pt_entry_t *)va; pte < (pt_entry_t *)(va + NBPG); pte++) + if (*pte) + count++; + if ((m->wire_count - 1) != count) + printf("*%s*: 0x%lx: w%d/a%d\n", + str, va, (m->wire_count - 1), count); +} +#endif /* DEBUG */ diff --git a/sys/arch/luna68k/luna68k/pmap_bootstrap.c b/sys/arch/luna68k/luna68k/pmap_bootstrap.c new file mode 100644 index 00000000000..2cc66df11a0 --- /dev/null +++ b/sys/arch/luna68k/luna68k/pmap_bootstrap.c @@ -0,0 +1,474 @@ +/* $NetBSD: pmap_bootstrap.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ +/* $NetBSD: pmap_bootstrap.c,v 1.1 2000/01/05 08:49:03 nisimura Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pmap_bootstrap.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/param.h> +#include <sys/proc.h> + +#include <machine/frame.h> +#include <machine/cpu.h> +#include <machine/vmparam.h> +#include <machine/pte.h> + +#include <vm/vm.h> + +#define RELOC(v, t) *((t*)((u_int)&(v) + firstpa)) + +extern char *etext; +extern int Sysptsize; +extern char *proc0paddr; +extern st_entry_t *Sysseg; +extern pt_entry_t *Sysptmap, *Sysmap; + +extern int maxmem, physmem; +extern paddr_t avail_start, avail_end; +extern vaddr_t virtual_avail, virtual_end; +extern vsize_t mem_size; +extern int protection_codes[]; + +void pmap_bootstrap __P((paddr_t, paddr_t)); + +/* + * Special purpose kernel virtual addresses, used for mapping + * physical pages for a variety of temporary or permanent purposes: + * + * CADDR1, CADDR2: pmap zero/copy operations + * vmmap: /dev/mem, crash dumps, parity error checking + * msgbufaddr: kernel message buffer + */ +caddr_t CADDR1, CADDR2, vmmap; +extern caddr_t msgbufaddr; + +/* + * Bootstrap the VM system. + * + * Called with MMU off so we must relocate all global references by `firstpa' + * (don't call any functions here!) `nextpa' is the first available physical + * memory address. Returns an updated first PA reflecting the memory we + * have allocated. MMU is still off when we return. + * + * XXX assumes sizeof(u_int) == sizeof(pt_entry_t) + * XXX a PIC compiler would make this much easier. + */ +void +pmap_bootstrap(nextpa, firstpa) + paddr_t nextpa; + paddr_t firstpa; +{ + paddr_t kstpa, kptpa, eiiopa, iiopa, kptmpa, lkptpa, p0upa; + u_int nptpages, kstsize; + st_entry_t protoste, *ste; + pt_entry_t protopte, *pte, *epte; + u_int iiomapsize; + + /* + * Calculate important physical addresses: + * + * kstpa kernel segment table 1 page (!040) + * N pages (040) + * + * kptpa statically allocated + * kernel PT pages Sysptsize+ pages + * + * iiopa internal IO space + * PT pages iiomapsize pages + * + * eiiopa page following + * internal IO space + * + * [ Sysptsize is the number of pages of PT, and iiomapsize + * is the number of PTEs, hence we need to round + * the total to a page boundary with IO maps at the end. ] + * + * kptmpa kernel PT map 1 page + * + * lkptpa last kernel PT page 1 page + * + * p0upa proc 0 u-area UPAGES pages + * + * The KVA corresponding to any of these PAs is: + * (PA - firstpa + KERNBASE). + */ + iiomapsize = m68k_btop(RELOC(intiotop_phys, u_int) - + RELOC(intiobase_phys, u_int)); + + if (RELOC(mmutype, int) == MMU_68040) + kstsize = MAXKL2SIZE / (NPTEPG/SG4_LEV2SIZE); + else + kstsize = 1; + kstpa = nextpa; + nextpa += kstsize * NBPG; + kptpa = nextpa; + nptpages = RELOC(Sysptsize, int) + + (iiomapsize + NPTEPG - 1) / NPTEPG; + nextpa += nptpages * NBPG; + eiiopa = nextpa; /* just a reference for later */ + iiopa = nextpa - iiomapsize * sizeof(pt_entry_t); + kptmpa = nextpa; + nextpa += NBPG; + lkptpa = nextpa; + nextpa += NBPG; + p0upa = nextpa; + nextpa += USPACE; + + /* + * Clear all PTEs to zero + */ + for (pte = (pt_entry_t *)kstpa; pte < (pt_entry_t *)nextpa; pte++) + *pte = 0; + + /* + * Initialize segment table and kernel page table map. + * + * On 68030s and earlier MMUs the two are identical except for + * the valid bits so both are initialized with essentially the + * same values. On the 68040, which has a mandatory 3-level + * structure, the segment table holds the level 1 table and part + * (or all) of the level 2 table and hence is considerably + * different. Here the first level consists of 128 descriptors + * (512 bytes) each mapping 32mb of address space. Each of these + * points to blocks of 128 second level descriptors (512 bytes) + * each mapping 256kb. Note that there may be additional "segment + * table" pages depending on how large MAXKL2SIZE is. + * + * Portions of the last segment of KVA space (0xFFF00000 - + * 0xFFFFFFFF) are mapped for a couple of purposes. 0xFFF00000 + * for UPAGES is used for mapping the current process u-area + * (u + kernel stack). The very last page (0xFFFFF000) is mapped + * to the last physical page of RAM to give us a region in which + * PA == VA. We use the first part of this page for enabling + * and disabling mapping. The last part of this page also contains + * info left by the boot ROM. + * + * XXX cramming two levels of mapping into the single "segment" + * table on the 68040 is intended as a temporary hack to get things + * working. The 224mb of address space that this allows will most + * likely be insufficient in the future (at least for the kernel). + */ + if (RELOC(mmutype, int) == MMU_68040) { + int num; + + /* + * First invalidate the entire "segment table" pages + * (levels 1 and 2 have the same "invalid" value). + */ + pte = (u_int *)kstpa; + epte = &pte[kstsize * NPTEPG]; + while (pte < epte) + *pte++ = SG_NV; + /* + * Initialize level 2 descriptors (which immediately + * follow the level 1 table). We need: + * NPTEPG / SG4_LEV3SIZE + * level 2 descriptors to map each of the nptpages+1 + * pages of PTEs. Note that we set the "used" bit + * now to save the HW the expense of doing it. + */ + num = (nptpages + 1) * (NPTEPG / SG4_LEV3SIZE); + pte = &((u_int *)kstpa)[SG4_LEV1SIZE]; + epte = &pte[num]; + protoste = kptpa | SG_U | SG_RW | SG_V; + while (pte < epte) { + *pte++ = protoste; + protoste += (SG4_LEV3SIZE * sizeof(st_entry_t)); + } + /* + * Initialize level 1 descriptors. We need: + * roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE + * level 1 descriptors to map the `num' level 2's. + */ + pte = (u_int *)kstpa; + epte = &pte[roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE]; + protoste = (u_int)&pte[SG4_LEV1SIZE] | SG_U | SG_RW | SG_V; + while (pte < epte) { + *pte++ = protoste; + protoste += (SG4_LEV2SIZE * sizeof(st_entry_t)); + } + /* + * Initialize the final level 1 descriptor to map the last + * block of level 2 descriptors. + */ + ste = &((u_int *)kstpa)[SG4_LEV1SIZE-1]; + pte = &((u_int *)kstpa)[kstsize*NPTEPG - SG4_LEV2SIZE]; + *ste = (u_int)pte | SG_U | SG_RW | SG_V; + /* + * Now initialize the final portion of that block of + * descriptors to map the "last PT page". + */ + pte = &((u_int *)kstpa)[kstsize*NPTEPG - NPTEPG/SG4_LEV3SIZE]; + epte = &pte[NPTEPG/SG4_LEV3SIZE]; + protoste = lkptpa | SG_U | SG_RW | SG_V; + while (pte < epte) { + *pte++ = protoste; + protoste += (SG4_LEV3SIZE * sizeof(st_entry_t)); + } + /* + * Initialize Sysptmap + */ + pte = (u_int *)kptmpa; + epte = &pte[nptpages+1]; + protopte = kptpa | PG_RW | PG_CI | PG_V; + while (pte < epte) { + *pte++ = protopte; + protopte += NBPG; + } + /* + * Invalidate all but the last remaining entry. + */ + epte = &((u_int *)kptmpa)[NPTEPG-1]; + while (pte < epte) { + *pte++ = PG_NV; + } + *pte = lkptpa | PG_RW | PG_CI | PG_V; + } else { + /* + * Map the page table pages in both the HW segment table + * and the software Sysptmap. Note that Sysptmap is also + * considered a PT page hence the +1. + */ + ste = (u_int *)kstpa; + pte = (u_int *)kptmpa; + epte = &pte[nptpages+1]; + protoste = kptpa | SG_RW | SG_V; + protopte = kptpa | PG_RW | PG_CI | PG_V; + while (pte < epte) { + *ste++ = protoste; + *pte++ = protopte; + protoste += NBPG; + protopte += NBPG; + } + /* + * Invalidate all but the last remaining entries in both. + */ + epte = &((u_int *)kptmpa)[NPTEPG-1]; + while (pte < epte) { + *ste++ = SG_NV; + *pte++ = PG_NV; + } + /* + * Initialize the last to point to point to the page + * table page allocated earlier. + */ + *ste = lkptpa | SG_RW | SG_V; + *pte = lkptpa | PG_RW | PG_CI | PG_V; + } + /* + * Invalidate all but the final entry in the last kernel PT page + * (u-area PTEs will be validated later). The final entry maps + * the last page of physical memory. + */ + pte = (u_int *)lkptpa; + epte = &pte[NPTEPG-1]; + while (pte < epte) + *pte++ = PG_NV; + + /* + * Initialize kernel page table. + * Start by invalidating the `nptpages' that we have allocated. + */ + pte = (u_int *)kptpa; + epte = &pte[nptpages * NPTEPG]; + while (pte < epte) + *pte++ = PG_NV; + /* + * Validate PTEs for kernel text (RO) + */ + pte = &((u_int *)kptpa)[m68k_btop(KERNBASE)]; + epte = &pte[m68k_btop(m68k_trunc_page(&etext))]; + protopte = firstpa | PG_RO | PG_V; + while (pte < epte) { + *pte++ = protopte; + protopte += NBPG; + } + /* + * Validate PTEs for kernel data/bss, dynamic data allocated + * by us so far (nextpa - firstpa bytes), and pages for proc0 + * u-area and page table allocated below (RW). + */ + epte = &((u_int *)kptpa)[m68k_btop(nextpa - firstpa)]; + protopte = (protopte & ~PG_PROT) | PG_RW; + /* + * Enable copy-back caching of data pages + */ + if (RELOC(mmutype, int) == MMU_68040) + protopte |= PG_CCB; + while (pte < epte) { + *pte++ = protopte; + protopte += NBPG; + } + + /* + * Finally, validate the internal IO space PTEs (RW+CI). + */ + pte = (u_int *)iiopa; + epte = (u_int *)eiiopa; + protopte = RELOC(intiobase_phys, u_int) | PG_RW | PG_CI | PG_V; + while (pte < epte) { + *pte++ = protopte; + protopte += NBPG; + } + + /* + * Calculate important exported kernel virtual addresses + */ + /* + * Sysseg: base of kernel segment table + */ + RELOC(Sysseg, st_entry_t *) = + (st_entry_t *)(kstpa - firstpa); + /* + * Sysptmap: base of kernel page table map + */ + RELOC(Sysptmap, pt_entry_t *) = + (pt_entry_t *)(kptmpa - firstpa); + /* + * Sysmap: kernel page table (as mapped through Sysptmap) + * Immediately follows `nptpages' of static kernel page table. + */ + RELOC(Sysmap, pt_entry_t *) = + (pt_entry_t *)m68k_ptob(nptpages * NPTEPG); + /* + * intiobase, intiolimit: base and end of internal IO space. + * iiomapsize pages prior to external IO space at end of static + * kernel page table. + */ + RELOC(intiobase, char *) = + (char *)m68k_ptob(nptpages*NPTEPG - iiomapsize); + RELOC(intiolimit, char *) = + (char *)m68k_ptob(nptpages*NPTEPG); + + /* + * Setup u-area for process 0. + */ + /* + * Zero the u-area. + * NOTE: `pte' and `epte' aren't PTEs here. + */ + pte = (u_int *)p0upa; + epte = (u_int *)(p0upa + USPACE); + while (pte < epte) + *pte++ = 0; + /* + * Remember the u-area address so it can be loaded in the + * proc struct p_addr field later. + */ + RELOC(proc0paddr, char *) = (char *)(p0upa - firstpa); + + RELOC(avail_start, paddr_t) = nextpa; + RELOC(avail_end, paddr_t) = m68k_ptob(RELOC(maxmem, int)) - + (m68k_round_page(MSGBUFSIZE)); + RELOC(mem_size, vsize_t) = m68k_ptob(RELOC(physmem, int)); + + RELOC(virtual_avail, vaddr_t) = + VM_MIN_KERNEL_ADDRESS + (vaddr_t)(nextpa - firstpa); + RELOC(virtual_end, vaddr_t) = VM_MAX_KERNEL_ADDRESS; + + /* + * Initialize protection array. + * XXX don't use a switch statement, it might produce an + * absolute "jmp" table. + */ + { + int *kp; + + kp = &RELOC(protection_codes, int); + kp[VM_PROT_NONE|VM_PROT_NONE|VM_PROT_NONE] = 0; + kp[VM_PROT_READ|VM_PROT_NONE|VM_PROT_NONE] = PG_RO; + kp[VM_PROT_READ|VM_PROT_NONE|VM_PROT_EXECUTE] = PG_RO; + kp[VM_PROT_NONE|VM_PROT_NONE|VM_PROT_EXECUTE] = PG_RO; + kp[VM_PROT_NONE|VM_PROT_WRITE|VM_PROT_NONE] = PG_RW; + kp[VM_PROT_NONE|VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW; + kp[VM_PROT_READ|VM_PROT_WRITE|VM_PROT_NONE] = PG_RW; + kp[VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW; + } + + /* + * Kernel page/segment table allocated above, + * just initialize pointers. + */ + { + struct pmap *kpm = &RELOC(kernel_pmap_store, struct pmap); + + kpm->pm_stab = RELOC(Sysseg, st_entry_t *); + kpm->pm_ptab = RELOC(Sysmap, pt_entry_t *); + simple_lock_init(&kpm->pm_lock); + kpm->pm_count = 1; + kpm->pm_stpa = (st_entry_t *)kstpa; + /* + * For the 040 we also initialize the free level 2 + * descriptor mask noting that we have used: + * 0: level 1 table + * 1 to `num': map page tables + * MAXKL2SIZE-1: maps last-page page table + */ + if (RELOC(mmutype, int) == MMU_68040) { + int num; + + kpm->pm_stfree = ~l2tobm(0); + num = roundup((nptpages + 1) * (NPTEPG / SG4_LEV3SIZE), + SG4_LEV2SIZE) / SG4_LEV2SIZE; + while (num) + kpm->pm_stfree &= ~l2tobm(num--); + kpm->pm_stfree &= ~l2tobm(MAXKL2SIZE-1); + for (num = MAXKL2SIZE; + num < sizeof(kpm->pm_stfree)*NBBY; + num++) + kpm->pm_stfree &= ~l2tobm(num); + } + } + + /* + * Allocate some fixed, special purpose kernel virtual addresses + */ + { + vaddr_t va = RELOC(virtual_avail, vaddr_t); + + RELOC(CADDR1, caddr_t) = (caddr_t)va; + va += NBPG; + RELOC(CADDR2, caddr_t) = (caddr_t)va; + va += NBPG; + RELOC(vmmap, caddr_t) = (caddr_t)va; + va += NBPG; + RELOC(msgbufaddr, caddr_t) = (caddr_t)va; + va += m68k_round_page(MSGBUFSIZE); + RELOC(virtual_avail, vaddr_t) = va; + } +} diff --git a/sys/arch/luna68k/luna68k/sys_machdep.c b/sys/arch/luna68k/luna68k/sys_machdep.c new file mode 100644 index 00000000000..c456d7b88d2 --- /dev/null +++ b/sys/arch/luna68k/luna68k/sys_machdep.c @@ -0,0 +1,310 @@ +/* $NetBSD: sys_machdep.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $ */ +/* $NetBSD: sys_machdep.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sys_machdep.c 8.2 (Berkeley) 1/13/94 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $"); + +#include "opt_compat_hpux.h" + +#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/buf.h> +#include <sys/trace.h> +#include <sys/mount.h> + +#include <vm/vm.h> + +#include <sys/syscallargs.h> + +#include <machine/cpu.h> +#include <m68k/cacheops.h> + +#ifdef TRACE +int nvualarm; + +sys_vtrace(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_vtrace_args /* { + syscallarg(int) request; + syscallarg(int) value; + } */ *uap = v; + 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, (void *)p->p_pid, SCARG(uap, value)); + break; + + case VTR_STAMP: + trace(TR_STAMP, SCARG(uap, value), p->p_pid); + break; + } + return (0); +} + +vdoualarm(arg) + void *arg; +{ + int pid = (int)arg; + struct proc *p; + + p = pfind(pid); + 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 */ + +/* + * Note that what we do here for a 68040 is different than HP-UX. + * + * In 'pux they either act on a line (len == 16), a page (len == NBPG) + * or the whole cache (len == anything else). + * + * In BSD we attempt to be more optimal when acting on "odd" sizes. + * For lengths up to 1024 we do all affected lines, up to 2*NBPG we + * do pages, above that we do the entire cache. + */ +/*ARGSUSED1*/ +int +cachectl1(req, addr, len, p) + unsigned long req; + vaddr_t addr; + size_t len; + struct proc *p; +{ + int error = 0; + +#if defined(M68040) + if (mmutype == MMU_68040) { + int inc = 0, doall = 0; + paddr_t pa = 0 + vaddr_t end; + + if (addr == 0 || + (req & ~CC_EXTPURGE) != CC_PURGE && len > 2*NBPG) + doall = 1; + + if (!doall) { + end = addr + len; + if (len <= 1024) { + addr = addr & ~0xF; + inc = 16; + } else { + addr = 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)) { + if (pmap_extract(p->p_vmspace->vm_map.pmap, + addr, &pa) == FALSE) + 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 + 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(); + /* fall into... */ + case CC_IPURGE: + ICIA(); + break; + default: + error = EINVAL; + break; + } + return(error); +} + +/* + * DMA cache control + */ + +/*ARGSUSED1*/ +int +dma_cachectl(addr, len) + caddr_t addr; + int len; +{ +#if defined(M68040) + if (mmutype == MMU_68040) { + 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(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 +sys_sysarch(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ +#if 0 /* unused */ + struct sys_sysarch_args /* { + syscallarg(int) op; + syscallarg(void *) parms; + } */ *uap = v; +#endif + + return (ENOSYS); +} diff --git a/sys/arch/luna68k/luna68k/trap.c b/sys/arch/luna68k/luna68k/trap.c new file mode 100644 index 00000000000..801026466c6 --- /dev/null +++ b/sys/arch/luna68k/luna68k/trap.c @@ -0,0 +1,1062 @@ +/* $NetBSD: trap.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $ */ +/* $NetBSD: trap.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: trap.c 1.37 92/12/20$ + * + * @(#)trap.c 8.5 (Berkeley) 1/4/94 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $"); + +#include "opt_ddb.h" +#include "opt_execfmt.h" +#include "opt_ktrace.h" +#include "opt_compat_netbsd.h" + +#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/syscall.h> +#include <sys/syslog.h> +#include <sys/user.h> +#ifdef KTRACE +#include <sys/ktrace.h> +#endif + +#include <machine/psl.h> +#include <machine/trap.h> +#include <machine/cpu.h> +#include <machine/reg.h> +#include <machine/db_machdep.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <uvm/uvm_extern.h> + +#include <dev/cons.h> + +int writeback __P((struct frame *fp, int docachepush)); +void trap __P((int type, u_int code, u_int v, struct frame frame)); +void syscall __P((register_t code, struct frame frame)); + +#if defined(M68040) +#ifdef DEBUG +static void dumpssw __P((u_short)); +static void dumpwb __P((int, u_short, u_int, u_int)); +#endif +#endif + +static inline void userret __P((struct proc *p, struct frame *fp, + u_quad_t oticks, u_int faultaddr, int fromtrap)); + +int astpending; + +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 M68040 +#define KDFAULT(c) (mmutype == MMU_68040 ? \ + ((c) & SSW4_TMMASK) == SSW4_TMKD : \ + ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)) +#define WRFAULT(c) (mmutype == MMU_68040 ? \ + ((c) & SSW4_RW) == 0 : \ + ((c) & (SSW_DF|SSW_RW)) == SSW_DF) +#else +#define KDFAULT(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD)) +#define WRFAULT(c) (((c) & (SSW_DF|SSW_RW)) == SSW_DF) +#endif + +#ifdef DEBUG +int mmudebug = 0; +int mmupid = -1; +#define MDB_FOLLOW 1 +#define MDB_WBFOLLOW 2 +#define MDB_WBFAILED 4 +#define MDB_ISPID(p) ((p) == mmupid) +#endif + +/* + * trap and syscall both need the following work done before returning + * to user mode. + */ +static inline void +userret(p, fp, oticks, faultaddr, fromtrap) + struct proc *p; + struct frame *fp; + u_quad_t oticks; + u_int faultaddr; + int fromtrap; +{ + int sig, s; +#ifdef M68040 + int beenhere = 0; + +again: +#endif + /* take pending signals */ + 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 put ourselves on the run queue + * but before we mi_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 system time to the trapped pc. + */ + if (p->p_flag & P_PROFIL) { + extern int psratio; + + addupc_task(p, fp->f_pc, + (int)(p->p_sticks - oticks) * psratio); + } +#ifdef M68040 + /* + * Deal with user mode writebacks (from trap, or from sigreturn). + * If any writeback fails, go back and attempt signal delivery. + * unless we have already been here and attempted the writeback + * (e.g. bad address with user ignoring SIGSEGV). In that case + * we just return to the user without sucessfully completing + * the writebacks. Maybe we should just drop the sucker? + */ + if (cputype == CPU_68040 && fp->f_format == FMT7) { + if (beenhere) { +#ifdef DEBUG + if (mmudebug & MDB_WBFAILED) + printf(fromtrap ? + "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" : + "pid %d(%s): writeback aborted in sigreturn, pc=%x\n", + p->p_pid, p->p_comm, fp->f_pc, faultaddr); +#endif + } else if ((sig = writeback(fp, fromtrap))) { + beenhere = 1; + oticks = p->p_sticks; + trapsignal(p, sig, faultaddr); + goto again; + } + } +#endif + curpriority = p->p_priority; +} + +/* + * 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*/ +void +trap(type, code, v, frame) + int type; + unsigned code; + unsigned v; + struct frame frame; +{ + extern char fubail[], subail[]; +#ifdef DDB + extern char trap0[], trap1[], trap2[], trap12[], trap15[], illinst[]; +#endif + struct proc *p; + int i; + u_int ucode; + u_quad_t sticks = 0 /* XXX initializer works around compiler bug */; + + uvmexp.traps++; + p = curproc; + ucode = 0; + + /* I have verified that this DOES happen! -gwr */ + if (p == NULL) + p = &proc0; +#ifdef DIAGNOSTIC + if (p->p_addr == NULL) + panic("trap: no pcb"); +#endif + + if (USERMODE(frame.f_sr)) { + type |= T_USER; + sticks = p->p_sticks; + p->p_md.md_regs = frame.f_regs; + } + switch (type) { + + default: + dopanic: + printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v); +#ifdef DDB + if (kdb_trap(type, (db_regs_t *)&frame)) + return; +#endif + printf("%s program counter = 0x%x\n", + (type & T_USER) ? "user" : "kernel", frame.f_pc); + regdump((struct trapframe *)&frame, 128); + type &= ~T_USER; + if ((u_int)type < trap_types) + panic(trap_type[type]); + panic("trap"); + + case T_BUSERR: /* kernel bus error */ + if (p->p_addr->u_pcb.pcb_onfault == 0) + goto dopanic; + /* FALLTHROUGH */ + + copyfault: + /* + * If we have arranged to catch this fault in any 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. + */ + frame.f_stackadj = exframesize[frame.f_format]; + frame.f_format = frame.f_vector = 0; + frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault; + return; + + case T_BUSERR|T_USER: /* bus error */ + case T_ADDRERR|T_USER: /* address error */ + ucode = v; + i = SIGBUS; + break; + + case T_COPERR: /* kernel coprocessor violation */ + case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */ + case T_FMTERR: /* ...just in case... */ + /* + * The user has most likely trashed the RTE or FP state info + * in the stack frame of a signal handler. + */ + printf("pid %d: kernel %s exception\n", p->p_pid, + type==T_COPERR ? "coprocessor" : "format"); + type |= T_USER; + p->p_sigacts->ps_sigact[SIGILL].sa_handler = SIG_DFL; + sigdelset(&p->p_sigignore, SIGILL); + sigdelset(&p->p_sigcatch, SIGILL); + sigdelset(&p->p_sigmask, SIGILL); + i = SIGILL; + ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */ + break; + + case T_COPERR|T_USER: /* user coprocessor violation */ + /* What is a proper response here? */ + ucode = 0; + i = SIGFPE; + break; + + case T_FPERR|T_USER: /* 68881 exceptions */ + /* + * 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; + +#ifdef M68040 + case T_FPEMULI|T_USER: /* unimplemented FP instuction */ + case T_FPEMULD|T_USER: /* unimplemented FP data type */ + /* XXX need to FSAVE */ + printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n", + p->p_pid, p->p_comm, + frame.f_format == 2 ? "instruction" : "data type", + frame.f_pc, frame.f_fmt2.f_iaddr); + /* XXX need to FRESTORE */ + i = SIGFPE; + break; +#endif + + case T_ILLINST|T_USER: /* illegal instruction fault */ +#ifdef COMPAT_HPUX + if (p->p_emul == &emul_hpux) { + ucode = HPUX_ILL_ILLINST_TRAP; + i = SIGILL; + break; + } + /* fall through */ +#endif + case T_PRIVINST|T_USER: /* privileged instruction fault */ +#ifdef COMPAT_HPUX + if (p->p_emul == &emul_hpux) + ucode = HPUX_ILL_PRIV_TRAP; + else +#endif + ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */ + i = SIGILL; + break; + + case T_ZERODIV|T_USER: /* Divide by zero */ + ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */ + i = SIGFPE; + break; + + case T_CHKINST|T_USER: /* CHK instruction trap */ + ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */ + i = SIGFPE; + break; + + case T_TRAPVINST|T_USER: /* TRAPV instruction trap */ + ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */ + i = SIGFPE; + break; + + /* + * XXX: Trace traps are a nightmare. + * + * HP-UX uses trap #1 for breakpoints, + * HPBSD uses trap #2, + * SUN 3.x uses trap #15, + * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere). + * + * HPBSD and HP-UX traps both 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: /* kernel trace trap */ + case T_TRAP15: /* SUN trace trap */ +#ifdef DDB + if (type == T_TRAP15 || + ((caddr_t)frame.f_pc != trap0 && + (caddr_t)frame.f_pc != trap1 && + (caddr_t)frame.f_pc != trap2 && + (caddr_t)frame.f_pc != trap12 && + (caddr_t)frame.f_pc != trap15 && + (caddr_t)frame.f_pc != illinst)) { + if (kdb_trap(type, (db_regs_t *)&frame)) + return; + } +#endif + frame.f_sr &= ~PSL_T; + i = SIGTRAP; + break; + + case T_TRACE|T_USER: /* user trace trap */ + case T_TRAP15|T_USER: /* SUN user trace trap */ + frame.f_sr &= ~PSL_T; + i = SIGTRAP; + break; + + case T_ASTFLT: /* system async trap, cannot happen */ + goto dopanic; + + case T_ASTFLT|T_USER: /* user async trap */ + 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(); + /* fall into... */ + + case T_SSIR: /* software interrupt */ + case T_SSIR|T_USER: + if (ssir & SIR_NET) { + void netintr __P((void)); + siroff(SIR_NET); + uvmexp.softs++; + netintr(); + } + if (ssir & SIR_CLOCK) { + siroff(SIR_CLOCK); + uvmexp.softs++; + softclock(); + } + /* + * If this was not an AST trap, we are all done. + */ + if (type != (T_ASTFLT|T_USER)) { + uvmexp.traps--; + return; + } + spl0(); + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + ADDUPROF(p); + } + goto out; + + case T_MMUFLT: /* kernel mode page fault */ + /* + * If we were doing profiling ticks or other user mode + * stuff from interrupt code, Just Say No. + */ + if (p->p_addr->u_pcb.pcb_onfault == fubail || + p->p_addr->u_pcb.pcb_onfault == subail) + goto copyfault; + /* fall into ... */ + + case T_MMUFLT|T_USER: /* page fault */ + { + vaddr_t va; + struct vmspace *vm = p->p_vmspace; + vm_map_t map; + int rv; + vm_prot_t ftype; + extern vm_map_t kernel_map; + +#ifdef DEBUG + if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) + printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n", + p->p_pid, code, v, frame.f_pc, frame.f_sr); +#endif + /* + * 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. + */ + if ((type & T_USER) == 0 && + ((p->p_addr->u_pcb.pcb_onfault == 0) || KDFAULT(code))) + map = kernel_map; + else + map = vm ? &vm->vm_map : kernel_map; + + if (WRFAULT(code)) + ftype = VM_PROT_READ | VM_PROT_WRITE; + else + ftype = VM_PROT_READ; + + va = trunc_page((vaddr_t)v); + + if (map == kernel_map && va == 0) { + printf("trap: bad kernel %s access at 0x%x\n", + (ftype & VM_PROT_WRITE) ? "read/write" : + "read", v); + goto dopanic; + } + + rv = uvm_fault(map, va, 0, ftype); +#ifdef DEBUG + if (rv && MDB_ISPID(p->p_pid)) + printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", + map, va, ftype, rv); +#endif + /* + * 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 ((vm != NULL && (caddr_t)va >= vm->vm_maxsaddr) + && map != kernel_map) { + if (rv == KERN_SUCCESS) { + unsigned nss; + + nss = 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) { +#ifdef M68040 + if (cputype == CPU_68040) + (void) writeback(&frame, 1); +#endif + return; + } + goto out; + } + if (type == T_MMUFLT) { + if (p->p_addr->u_pcb.pcb_onfault) + goto copyfault; + printf("uvm_fault(%p, 0x%lx, 0, 0x%x) -> 0x%x\n", + map, va, ftype, rv); + printf(" type %x, code [mmu,,ssw]: %x\n", + type, code); + goto dopanic; + } + ucode = v; + if (rv == KERN_RESOURCE_SHORTAGE) { + printf("UVM: pid %d (%s), uid %d killed: out of swap\n", + p->p_pid, p->p_comm, + p->p_cred && p->p_ucred ? + p->p_ucred->cr_uid : -1); + i = SIGKILL; + } else { + i = SIGSEGV; + } + break; + } + } + if (i) + trapsignal(p, i, ucode); + if ((type & T_USER) == 0) + return; +out: + userret(p, &frame, sticks, v, 1); +} + +#ifdef M68040 +#ifdef DEBUG +struct writebackstats { + int calls; + int cpushes; + int move16s; + int wb1s, wb2s, wb3s; + int wbsize[4]; +} wbstats; + +char *f7sz[] = { "longword", "byte", "word", "line" }; +char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" }; +char *f7tm[] = { "d-push", "u-data", "u-code", "M-data", + "M-code", "k-data", "k-code", "RES" }; +char wberrstr[] = + "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n"; +#endif + +int +writeback(fp, docachepush) + struct frame *fp; + int docachepush; +{ + struct fmt7 *f = &fp->f_fmt7; + struct proc *p = curproc; + int err = 0; + u_int fa; + caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault; + +#ifdef DEBUG + if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { + printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa); + dumpssw(f->f_ssw); + } + wbstats.calls++; +#endif + /* + * Deal with special cases first. + */ + if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) { + /* + * Dcache push fault. + * Line-align the address and write out the push data to + * the indicated physical address. + */ +#ifdef DEBUG + if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) { + printf(" pushing %s to PA %x, data %x", + f7sz[(f->f_ssw & SSW4_SZMASK) >> 5], + f->f_fa, f->f_pd0); + if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN) + printf("/%x/%x/%x", + f->f_pd1, f->f_pd2, f->f_pd3); + printf("\n"); + } + if (f->f_wb1s & SSW4_WBSV) + panic("writeback: cache push with WB1S valid"); + wbstats.cpushes++; +#endif + /* + * XXX there are security problems if we attempt to do a + * cache push after a signal handler has been called. + */ + if (docachepush) { + pmap_enter(pmap_kernel(), (vaddr_t)vmmap, + trunc_page(f->f_fa), VM_PROT_WRITE, TRUE, + VM_PROT_WRITE); + fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF]; + bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16); + DCFL(pmap_extract(pmap_kernel(), (paddr_t)fa)); + pmap_remove(pmap_kernel(), (vaddr_t)vmmap, + (vaddr_t)&vmmap[NBPG]); + } else + printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n", + p->p_pid, p->p_comm, p->p_ucred->cr_uid); + } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) { + /* + * MOVE16 fault. + * Line-align the address and write out the push data to + * the indicated virtual address. + */ +#ifdef DEBUG + if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) + printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n", + f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1, + f->f_pd2, f->f_pd3); + if (f->f_wb1s & SSW4_WBSV) + panic("writeback: MOVE16 with WB1S valid"); + wbstats.move16s++; +#endif + if (KDFAULT(f->f_wb1s)) + bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16); + else + err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0); + if (err) { + fa = f->f_fa & ~0xF; +#ifdef DEBUG + if (mmudebug & MDB_WBFAILED) + printf(wberrstr, p->p_pid, p->p_comm, + "MOVE16", fp->f_pc, f->f_fa, + f->f_fa & ~0xF, f->f_pd0); +#endif + } + } else if (f->f_wb1s & SSW4_WBSV) { + /* + * Writeback #1. + * Position the "memory-aligned" data and write it out. + */ + u_int wb1d = f->f_wb1d; + int off; + +#ifdef DEBUG + if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) + dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d); + wbstats.wb1s++; + wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; +#endif + off = (f->f_wb1a & 3) * 8; + switch (f->f_wb1s & SSW4_SZMASK) { + case SSW4_SZLW: + if (off) + wb1d = (wb1d >> (32 - off)) | (wb1d << off); + if (KDFAULT(f->f_wb1s)) + *(long *)f->f_wb1a = wb1d; + else + err = suword((caddr_t)f->f_wb1a, wb1d); + break; + case SSW4_SZB: + off = 24 - off; + if (off) + wb1d >>= off; + if (KDFAULT(f->f_wb1s)) + *(char *)f->f_wb1a = wb1d; + else + err = subyte((caddr_t)f->f_wb1a, wb1d); + break; + case SSW4_SZW: + off = (off + 16) % 32; + if (off) + wb1d = (wb1d >> (32 - off)) | (wb1d << off); + if (KDFAULT(f->f_wb1s)) + *(short *)f->f_wb1a = wb1d; + else + err = susword((caddr_t)f->f_wb1a, wb1d); + break; + } + if (err) { + fa = f->f_wb1a; +#ifdef DEBUG + if (mmudebug & MDB_WBFAILED) + printf(wberrstr, p->p_pid, p->p_comm, + "#1", fp->f_pc, f->f_fa, + f->f_wb1a, f->f_wb1d); +#endif + } + } + /* + * Deal with the "normal" writebacks. + * + * XXX writeback2 is known to reflect a LINE size writeback after + * a MOVE16 was already dealt with above. Ignore it. + */ + if (err == 0 && (f->f_wb2s & SSW4_WBSV) && + (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) { +#ifdef DEBUG + if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) + dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); + wbstats.wb2s++; + wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++; +#endif + switch (f->f_wb2s & SSW4_SZMASK) { + case SSW4_SZLW: + if (KDFAULT(f->f_wb2s)) + *(long *)f->f_wb2a = f->f_wb2d; + else + err = suword((caddr_t)f->f_wb2a, f->f_wb2d); + break; + case SSW4_SZB: + if (KDFAULT(f->f_wb2s)) + *(char *)f->f_wb2a = f->f_wb2d; + else + err = subyte((caddr_t)f->f_wb2a, f->f_wb2d); + break; + case SSW4_SZW: + if (KDFAULT(f->f_wb2s)) + *(short *)f->f_wb2a = f->f_wb2d; + else + err = susword((caddr_t)f->f_wb2a, f->f_wb2d); + break; + } + if (err) { + fa = f->f_wb2a; +#ifdef DEBUG + if (mmudebug & MDB_WBFAILED) { + printf(wberrstr, p->p_pid, p->p_comm, + "#2", fp->f_pc, f->f_fa, + f->f_wb2a, f->f_wb2d); + dumpssw(f->f_ssw); + dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d); + } +#endif + } + } + if (err == 0 && (f->f_wb3s & SSW4_WBSV)) { +#ifdef DEBUG + if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) + dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d); + wbstats.wb3s++; + wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++; +#endif + switch (f->f_wb3s & SSW4_SZMASK) { + case SSW4_SZLW: + if (KDFAULT(f->f_wb3s)) + *(long *)f->f_wb3a = f->f_wb3d; + else + err = suword((caddr_t)f->f_wb3a, f->f_wb3d); + break; + case SSW4_SZB: + if (KDFAULT(f->f_wb3s)) + *(char *)f->f_wb3a = f->f_wb3d; + else + err = subyte((caddr_t)f->f_wb3a, f->f_wb3d); + break; + case SSW4_SZW: + if (KDFAULT(f->f_wb3s)) + *(short *)f->f_wb3a = f->f_wb3d; + else + err = susword((caddr_t)f->f_wb3a, f->f_wb3d); + break; +#ifdef DEBUG + case SSW4_SZLN: + panic("writeback: wb3s indicates LINE write"); +#endif + } + if (err) { + fa = f->f_wb3a; +#ifdef DEBUG + if (mmudebug & MDB_WBFAILED) + printf(wberrstr, p->p_pid, p->p_comm, + "#3", fp->f_pc, f->f_fa, + f->f_wb3a, f->f_wb3d); +#endif + } + } + p->p_addr->u_pcb.pcb_onfault = oonfault; + if (err) + err = SIGSEGV; + return (err); +} + +#ifdef DEBUG +static void +dumpssw(ssw) + u_short ssw; +{ + printf(" SSW: %x: ", ssw); + if (ssw & SSW4_CP) + printf("CP,"); + if (ssw & SSW4_CU) + printf("CU,"); + if (ssw & SSW4_CT) + printf("CT,"); + if (ssw & SSW4_CM) + printf("CM,"); + if (ssw & SSW4_MA) + printf("MA,"); + if (ssw & SSW4_ATC) + printf("ATC,"); + if (ssw & SSW4_LK) + printf("LK,"); + if (ssw & SSW4_RW) + printf("RW,"); + printf(" SZ=%s, TT=%s, TM=%s\n", + f7sz[(ssw & SSW4_SZMASK) >> 5], + f7tt[(ssw & SSW4_TTMASK) >> 3], + f7tm[ssw & SSW4_TMMASK]); +} + +static void +dumpwb(num, s, a, d) + int num; + u_short s; + u_int a, d; +{ + struct proc *p = curproc; + paddr_t pa; + + printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n", + num, a, d, f7sz[(s & SSW4_SZMASK) >> 5], + f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]); + printf(" PA "); + pa = pmap_extract(p->p_vmspace->vm_map.pmap, (paddr_t)a); + if (pa == 0) + printf("<invalid address>"); + else + printf("%lx, current value %lx", pa, fuword((caddr_t)a)); + printf("\n"); +} +#endif +#endif + +/* + * Process a system call. + */ +void +syscall(code, frame) + register_t code; + struct frame frame; +{ + caddr_t params; + struct sysent *callp; + struct proc *p; + int error, opc, nsys; + size_t argsize; + register_t args[8], rval[2]; + u_quad_t sticks; + + uvmexp.syscalls++; + if (!USERMODE(frame.f_sr)) + panic("syscall"); + p = curproc; + sticks = p->p_sticks; + p->p_md.md_regs = frame.f_regs; + opc = frame.f_pc; + + nsys = p->p_emul->e_nsysent; + callp = p->p_emul->e_sysent; + +#ifdef COMPAT_SUNOS + if (p->p_emul == &emul_sunos) { + /* + * 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 stored pc + * on the stack to skip, the argument follows 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; + } else + p->p_md.md_flags &= ~MDP_STACKADJ; + } +#endif + + 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. + */ + switch (code) { +#ifdef COMPAT_13 + case SYS_compat_13_sigreturn13: +#endif + case SYS___sigreturn14: + code = nsys; + break; + } + break; + case SYS___syscall: + /* + * Like syscall, but code is a quad, so as to maintain + * quad alignment for the rest of the arguments. + */ + if (callp != sysent) + break; + code = fuword(params + _QUAD_LOWWORD * sizeof(int)); + params += sizeof(quad_t); + break; + default: + break; + } + if (code < 0 || code >= nsys) + callp += p->p_emul->e_nosys; /* illegal */ + else + callp += code; + argsize = callp->sy_argsize; + if (argsize) + error = copyin(params, (caddr_t)args, argsize); + else + error = 0; +#ifdef SYSCALL_DEBUG + scdebug_call(p, code, args); +#endif +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p->p_tracep, code, argsize, args); +#endif + if (error) + goto bad; + 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; /* carry bit */ + break; + case ERESTART: + /* + * We always enter through a `trap' instruction, which is 2 + * bytes, so adjust the pc by that amount. + */ + frame.f_pc = opc - 2; + break; + case EJUSTRETURN: + /* nothing to do */ + break; + default: + bad: + if (p->p_emul->e_errno) + error = p->p_emul->e_errno[error]; + frame.f_regs[D0] = error; + frame.f_sr |= PSL_C; /* carry bit */ + break; + } + +#ifdef SYSCALL_DEBUG + scdebug_ret(p, code, error, rval); +#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); +#endif + userret(p, &frame, sticks, (u_int)0, 0); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, code, error, rval[0]); +#endif +} + +void +child_return(arg) + void *arg; +{ + struct proc *p = arg; + /* See cpu_fork() */ + struct frame *f = (struct frame *)p->p_md.md_regs; + + f->f_regs[D0] = 0; + f->f_sr &= ~PSL_C; + f->f_format = FMT0; + + userret(p, f, 0, (u_int)0, 0); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p->p_tracep, SYS_fork, 0, 0); +#endif +} diff --git a/sys/arch/luna68k/luna68k/vectors.s b/sys/arch/luna68k/luna68k/vectors.s new file mode 100644 index 00000000000..7f4ccabb894 --- /dev/null +++ b/sys/arch/luna68k/luna68k/vectors.s @@ -0,0 +1,134 @@ +| $NetBSD: vectors.s,v 1.1 2000/01/05 08:49:04 nisimura Exp $ + +| Copyright (c) 1997 Jason R. Thorpe. All rights reserved. +| Copyright (c) 1988 University of Utah +| Copyright (c) 1990, 1993 +| The Regents of the University of California. All rights reserved. +| +| Redistribution and use in source and binary forms, with or without +| modification, are permitted provided that the following conditions +| are met: +| 1. Redistributions of source code must retain the above copyright +| notice, this list of conditions and the following disclaimer. +| 2. Redistributions in binary form must reproduce the above copyright +| notice, this list of conditions and the following disclaimer in the +| documentation and/or other materials provided with the distribution. +| 3. All advertising materials mentioning features or use of this software +| must display the following acknowledgement: +| This product includes software developed by the University of +| California, Berkeley and its contributors. +| 4. Neither the name of the University nor the names of its contributors +| may be used to endorse or promote products derived from this software +| without specific prior written permission. +| +| THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +| OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +| SUCH DAMAGE. +| +| @(#)vectors.s 8.2 (Berkeley) 1/21/94 +| + +#define BADTRAP16 \ + VECTOR(badtrap) ; VECTOR(badtrap) ; \ + VECTOR(badtrap) ; VECTOR(badtrap) ; \ + VECTOR(badtrap) ; VECTOR(badtrap) ; \ + VECTOR(badtrap) ; VECTOR(badtrap) ; \ + VECTOR(badtrap) ; VECTOR(badtrap) ; \ + VECTOR(badtrap) ; VECTOR(badtrap) ; \ + VECTOR(badtrap) ; VECTOR(badtrap) ; \ + VECTOR(badtrap) ; VECTOR(badtrap) + + /* + * bus error and address error vectors are initialized + * in locore.s once we know our CPU type. + */ + + .data +GLOBAL(vectab) + VECTOR_UNUSED /* 0: (unused reset SSP) */ + VECTOR_UNUSED /* 1: NOT USED (reset PC) */ + VECTOR_UNUSED /* 2: bus error */ + VECTOR_UNUSED /* 3: address error */ + VECTOR(illinst) /* 4: illegal instruction */ + VECTOR(zerodiv) /* 5: zero divide */ + VECTOR(chkinst) /* 6: CHK instruction */ + VECTOR(trapvinst) /* 7: TRAPV instruction */ + VECTOR(privinst) /* 8: privilege violation */ + VECTOR(trace) /* 9: trace */ + VECTOR(illinst) /* 10: line 1010 emulator */ + VECTOR(fpfline) /* 11: line 1111 emulator */ + VECTOR(badtrap) /* 12: unassigned, reserved */ + VECTOR(coperr) /* 13: coprocessor protocol violation */ + VECTOR(fmterr) /* 14: format error */ + VECTOR(badtrap) /* 15: uninitialized interrupt vector */ + VECTOR(badtrap) /* 16: unassigned, reserved */ + VECTOR(badtrap) /* 17: unassigned, reserved */ + VECTOR(badtrap) /* 18: unassigned, reserved */ + VECTOR(badtrap) /* 19: unassigned, reserved */ + VECTOR(badtrap) /* 20: unassigned, reserved */ + VECTOR(badtrap) /* 21: unassigned, reserved */ + VECTOR(badtrap) /* 22: unassigned, reserved */ + VECTOR(badtrap) /* 23: unassigned, reserved */ + VECTOR(spurintr) /* 24: spurious interrupt */ + VECTOR(intrhand_autovec)/* 25: level 1 interrupt autovector */ + VECTOR(intrhand_autovec)/* 26: level 2 interrupt autovector */ + VECTOR(intrhand_autovec)/* 27: level 3 interrupt autovector */ + VECTOR(intrhand_autovec)/* 28: level 4 interrupt autovector */ + VECTOR(lev5intr) /* 29: level 5 interrupt hardwired */ + VECTOR(intrhand_autovec)/* 30: level 6 interrupt autovector */ + VECTOR(lev7intr) /* 31: level 7 interrupt hardwired */ + VECTOR(trap0) /* 32: syscalls */ +#ifdef COMPAT_13 + VECTOR(trap1) /* 33: compat_13_sigreturn */ +#else + VECTOR(illinst) +#endif + VECTOR(trap2) /* 34: trace */ + VECTOR(trap3) /* 35: sigreturn special syscall */ + VECTOR(illinst) /* 36: TRAP instruction vector */ + VECTOR(illinst) /* 37: TRAP instruction vector */ + VECTOR(illinst) /* 38: TRAP instruction vector */ + VECTOR(illinst) /* 39: TRAP instruction vector */ + VECTOR(illinst) /* 40: TRAP instruction vector */ + VECTOR(illinst) /* 41: TRAP instruction vector */ + VECTOR(illinst) /* 42: TRAP instruction vector */ + VECTOR(illinst) /* 43: TRAP instruction vector */ + VECTOR(trap12) /* 44: TRAP instruction vector */ + VECTOR(illinst) /* 45: TRAP instruction vector */ + VECTOR(illinst) /* 46: TRAP instruction vector */ + VECTOR(trap15) /* 47: TRAP instruction vector */ +#ifdef FPSP + ASVECTOR(bsun) /* 48: FPCP branch/set on unordered cond */ + ASVECTOR(inex) /* 49: FPCP inexact result */ + ASVECTOR(dz) /* 50: FPCP divide by zero */ + ASVECTOR(unfl) /* 51: FPCP underflow */ + ASVECTOR(operr) /* 52: FPCP operand error */ + ASVECTOR(ovfl) /* 53: FPCP overflow */ + ASVECTOR(snan) /* 54: FPCP signalling NAN */ +#else + VECTOR(fpfault) /* 48: FPCP branch/set on unordered cond */ + VECTOR(fpfault) /* 49: FPCP inexact result */ + VECTOR(fpfault) /* 50: FPCP divide by zero */ + VECTOR(fpfault) /* 51: FPCP underflow */ + VECTOR(fpfault) /* 52: FPCP operand error */ + VECTOR(fpfault) /* 53: FPCP overflow */ + VECTOR(fpfault) /* 54: FPCP signalling NAN */ +#endif + + VECTOR(fpunsupp) /* 55: FPCP unimplemented data type */ + VECTOR(badtrap) /* 56: unassigned, reserved */ + VECTOR(badtrap) /* 57: unassigned, reserved */ + VECTOR(badtrap) /* 58: unassigned, reserved */ + VECTOR(badtrap) /* 59: unassigned, reserved */ + VECTOR(badtrap) /* 60: unassigned, reserved */ + VECTOR(badtrap) /* 61: unassigned, reserved */ + VECTOR(badtrap) /* 62: unassigned, reserved */ + VECTOR(badtrap) /* 63: unassigned, reserved */ diff --git a/sys/arch/luna68k/luna68k/vm_machdep.c b/sys/arch/luna68k/luna68k/vm_machdep.c new file mode 100644 index 00000000000..f041e01d3ba --- /dev/null +++ b/sys/arch/luna68k/luna68k/vm_machdep.c @@ -0,0 +1,374 @@ +/* $NetBSD: vm_machdep.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $ */ +/* $NetBSD: vm_machdep.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: vm_machdep.c 1.21 91/04/06$ + * + * @(#)vm_machdep.c 8.6 (Berkeley) 1/12/94 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ +__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.1 2000/01/05 08:49:04 nisimura Exp $"); + +#include "opt_compat_hpux.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/vnode.h> +#include <sys/user.h> +#include <sys/core.h> +#include <sys/exec.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> + +#include <uvm/uvm_extern.h> + +#include <machine/cpu.h> +#include <machine/pte.h> +#include <machine/reg.h> +#include <m68k/cacheops.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. + * When scheduled, child p2 will start from proc_trampoline(). cpu_fork() + * returns once for forking parent p1. + */ +void +cpu_fork(p1, p2, stack, stacksize) + struct proc *p1, *p2; + void *stack; + size_t stacksize; +{ + struct pcb *pcb = &p2->p_addr->u_pcb; + struct trapframe *tf; + struct switchframe *sf; + extern struct pcb *curpcb; + + p2->p_md.md_flags = p1->p_md.md_flags & ~MDP_HPUXTRACE; + + /* Copy pcb from proc p1 to p2. */ + if (p1 == curproc) { + /* Sync the PCB before we copy it. */ + savectx(curpcb); + } +#ifdef DIAGNOSTIC + else if (p1 != &proc0) + panic("cpu_fork: curproc"); +#endif + *pcb = p1->p_addr->u_pcb; + + /* + * Copy the trap frame, and arrange for the child to return directly + * through child_return(). Note the in-line cpu_set_kpc(). + */ + tf = (struct trapframe *)((u_int)p2->p_addr + USPACE) - 1; + p2->p_md.md_regs = (int *)tf; + *tf = *(struct trapframe *)p1->p_md.md_regs; + + /* + * If specified, give the child a different stack. + */ + if (stack != NULL) + tf->tf_regs[15] = (u_int)stack + stacksize; + + sf = (struct switchframe *)tf - 1; + sf->sf_pc = (u_int)proc_trampoline; + pcb->pcb_regs[6] = (int)child_return; /* A2 */ + pcb->pcb_regs[7] = (int)p2; /* A3 */ + pcb->pcb_regs[11] = (int)sf; /* SSP */ +} + +/* + * Arrange for in-kernel execution of a process to continue at the + * named pc, as if the code at that address were called as a function + * with the supplied argument. + * + * Note that it's assumed that when the named process returns, rei() + * should be invoked, to return to user mode. + */ +void +cpu_set_kpc(p, pc, arg) + struct proc *p; + void (*pc) __P((void *)); + void *arg; +{ + + p->p_addr->u_pcb.pcb_regs[6] = (u_long) pc; /* A2 */ + p->p_addr->u_pcb.pcb_regs[7] = (u_long) arg; /* A3 */ +} + +/* + * cpu_exit is called as the last action during exit. + * + * Block context switches and then call switch_exit() which will + * switch to another process thus we never return. + */ +void +cpu_exit(p) + struct proc *p; +{ + + (void) splhigh(); + uvmexp.swtch++; + switch_exit(p); + /* NOTREACHED */ +} + +/* + * Dump the machine specific header information at the start of a core dump. + */ +struct md_core { + struct reg intreg; + struct fpreg freg; +}; +int +cpu_coredump(p, vp, cred, chdr) + struct proc *p; + struct vnode *vp; + struct ucred *cred; + struct core *chdr; +{ + struct md_core md_core; + struct coreseg cseg; + int error; + +#ifdef COMPAT_HPUX + extern struct emul emul_hpux; + + /* + * If we loaded from an HP-UX format binary file we dump enough + * of an HP-UX style user struct so that the HP-UX debuggers can + * grok it. + */ + if (p->p_emul == &emul_hpux) + return (hpux_dumpu(vp, cred)); +#endif + + CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); + chdr->c_hdrsize = ALIGN(sizeof(*chdr)); + chdr->c_seghdrsize = ALIGN(sizeof(cseg)); + chdr->c_cpusize = sizeof(md_core); + + /* Save integer registers. */ + error = process_read_regs(p, &md_core.intreg); + if (error) + return error; + + /* Save floating point registers. */ + error = process_read_fpregs(p, &md_core.freg); + if (error) + return error; + + CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); + cseg.c_addr = 0; + cseg.c_size = chdr->c_cpusize; + + error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, + (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, + NULL, p); + if (error) + return error; + + error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core), + (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, + IO_NODELOCKED|IO_UNIT, cred, NULL, p); + if (error) + return error; + + chdr->c_nseg++; + return 0; +} + +/* + * 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 NBPG. + */ +void +pagemove(from, to, size) + caddr_t from, to; + size_t size; +{ + paddr_t pa; + boolean_t rv; + +#ifdef DEBUG + if (size & PGOFSET) + panic("pagemove"); +#endif + while (size > 0) { + rv = pmap_extract(pmap_kernel(), (vaddr_t)from, &pa); +#ifdef DEBUG + if (rv == FALSE) + panic("pagemove 2"); + if (pmap_extract(pmap_kernel(), (vaddr_t)to, NULL) == TRUE) + panic("pagemove 3"); +#endif + pmap_remove(pmap_kernel(), + (vaddr_t)from, (vaddr_t)from + PAGE_SIZE); + pmap_enter(pmap_kernel(), + (vaddr_t)to, pa, VM_PROT_READ|VM_PROT_WRITE, + VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); + 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'. + */ +void +physaccess(vaddr, paddr, size, prot) + caddr_t vaddr, paddr; + int size, prot; +{ + pt_entry_t *pte; + u_int page; + + pte = kvtopte(vaddr); + page = (u_int)paddr & PG_FRAME; + for (size = btoc(size); size; size--) { + *pte++ = PG_V | prot | page; + page += NBPG; + } + TBIAS(); +} + +void +physunaccess(vaddr, size) + caddr_t vaddr; + int size; +{ + pt_entry_t *pte; + + pte = kvtopte(vaddr); + for (size = btoc(size); size; size--) + *pte++ = PG_NV; + TBIAS(); +} + +/* + * Convert kernel VA to physical address + */ +int +kvtop(addr) + caddr_t addr; +{ + paddr_t pa; + + if (pmap_extract(pmap_kernel(), (vaddr_t)addr, &pa) == FALSE) + panic("kvtop: zero page frame"); + return((int)pa); +} + +extern vm_map_t phys_map; + +/* + * Map a user I/O request into kernel virtual address space. + * Note: the pages are already locked by uvm_vslock(), so we + * do not need to pass an access_type to pmap_enter(). + */ +void +vmapbuf(bp, len) + struct buf *bp; + vsize_t len; +{ + struct pmap *upmap, *kpmap; + vaddr_t uva; /* User VA (map from) */ + vaddr_t kva; /* Kernel VA (new to) */ + paddr_t pa; /* physical address */ + vsize_t off; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vmapbuf"); + + uva = m68k_trunc_page(bp->b_saveaddr = bp->b_data); + off = (vaddr_t)bp->b_data - uva; + len = m68k_round_page(off + len); + kva = uvm_km_valloc_wait(phys_map, len); + bp->b_data = (caddr_t)(kva + off); + + upmap = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map); + kpmap = vm_map_pmap(phys_map); + do { + if (pmap_extract(upmap, uva, &pa) == FALSE) + panic("vmapbuf: null page frame"); + pmap_enter(kpmap, kva, pa, VM_PROT_READ|VM_PROT_WRITE, + PMAP_WIRED); + uva += PAGE_SIZE; + kva += PAGE_SIZE; + len -= PAGE_SIZE; + } while (len); +} + +/* + * Unmap a previously-mapped user I/O request. + */ +void +vunmapbuf(bp, len) + struct buf *bp; + vsize_t len; +{ + vaddr_t kva; + vsize_t off; + + if ((bp->b_flags & B_PHYS) == 0) + panic("vunmapbuf"); + + kva = m68k_trunc_page(bp->b_data); + off = (vaddr_t)bp->b_data - kva; + len = m68k_round_page(off + len); + + /* + * pmap_remove() is unnecessary here, as kmem_free_wakeup() + * will do it for us. + */ + uvm_km_free_wakeup(phys_map, kva, len); + bp->b_data = bp->b_saveaddr; + bp->b_saveaddr = 0; +} |
