diff options
Diffstat (limited to 'sys/arch')
104 files changed, 22364 insertions, 0 deletions
diff --git a/sys/arch/hppa64/Makefile b/sys/arch/hppa64/Makefile new file mode 100644 index 00000000000..bb151360666 --- /dev/null +++ b/sys/arch/hppa64/Makefile @@ -0,0 +1,34 @@ +# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:46 mickey Exp $ + +# Makefile for hppa64 tags file and boot blocks + +S=${.CURDIR}/../.. +.include "$S/kern/Make.tags.inc" + +NOPROG= noprog +NOMAN= noman + +SUBDIR= stand + +THPPA= $S/arch/hppa64/tags +SHPPA= $S/arch/hppa64/hppa64/*.[ch] $S/arch/hppa64/include/*.h \ + $S/arch/hppa64/dev/*.[ch] +AHPPA= $S/arch/hppa64/hppa64/*.S $S/lib/libkern/arch/hppa64/*.[sS] + +# Directories in which to place hppa64 tags links +DHPPA= conf dev hppa64 include + +tags: + -ctags -wdtf ${THPPA} ${COMM} ${SHPPA} + egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AHPPA} | \ + sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \ + >> ${THPPA} + sort -o ${THPPA} ${THPPA} + +links: + -for i in ${DHPPA}; do \ + cd $$i && rm -f tags; ln -s ${THPPA} tags; done + +obj: _SUBDIRUSE + +.include <bsd.prog.mk> diff --git a/sys/arch/hppa64/compile/.cvsignore b/sys/arch/hppa64/compile/.cvsignore new file mode 100644 index 00000000000..b72af3039e6 --- /dev/null +++ b/sys/arch/hppa64/compile/.cvsignore @@ -0,0 +1,2 @@ +GENERIC +RAMDISK diff --git a/sys/arch/hppa64/conf/GENERIC b/sys/arch/hppa64/conf/GENERIC new file mode 100644 index 00000000000..db3760bcc32 --- /dev/null +++ b/sys/arch/hppa64/conf/GENERIC @@ -0,0 +1,176 @@ +# $OpenBSD: GENERIC,v 1.1 2005/04/01 10:40:47 mickey Exp $ + +# Machine architecture; required by config(8) +machine hppa64 + +include "../../../conf/GENERIC" +option DEBUG + +option USER_PCICONF # user-space PCI configuration + +# Need to set locally +maxusers 32 + +option TIMEZONE=0 # time zone to adjust RTC time by +option DST=0 # daylight saving time used by RTC + +#option COMPAT_HPUX +#option COMPAT_LINUX + +config bsd swap generic + +mainbus0 at root # root bus + +mem* at mainbus0 flags 0x00 # /dev/*mem and memory controller +pdc0 at mainbus0 # PDC/IODC wrapper for boot console +#power0 at mainbus0 # power/fail manager (iv 30) +cpu* at mainbus0 # HP PA-RISC cpu +plut0 at mainbus0 # Astro Runway-Ropes, MIOC and IOA + +elroy* at plut0 +pci* at elroy? +option PCIVERBOSE + +ppb* at pci? +pci* at ppb? + +#goofy* at pci? # NS87560UBD +#com* at goofy? +#lpt* at goofy? +#fdc* at goofy? + +# CardBus bus support +#cbb* at pci? +#cardslot* at cbb? +#option CARDBUS_DEBUG,CARDSLOT_DEBUG,CARDBUS_MAP_DEBUG +#cardbus* at cardslot? +#option PCMCIADEBUG,PCMCIAVERBOSE +#pcmcia* at cardslot? + +# PCI USB Controllers +#ehci* at pci? # Enhanced Host Controller +#uhci* at pci? # Universal Host Controller (Intel) +#ohci* at pci? # Open Host Controller + +# USB bus support +#usb* at ehci? +#usb* at uhci? +#usb* at ohci? + +# USB devices +#uhub* at usb? # USB Hubs +#uhub* at uhub? # USB Hubs +#umodem* at uhub? # USB Modems/Serial +#ucom* at umodem? +#uvisor* at uhub? # Handspring Visor +#ucom* at uvisor? +#uvscom* at uhub? # SUNTAC Slipper U VS-10U serial +#ucom* at uvscom? +#ubsa* at uhub? # Belkin serial adapter +#ucom* at ubsa? +#uftdi* at uhub? # FTDI FT8U100AX serial adapter +#ucom* at uftdi? +#uplcom* at uhub? # I/O DATA USB-RSAQ2 serial adapter +#ucom* at uplcom? +#umct* at uhub? # MCT USB-RS232 serial adapter +#ucom* at umct? +#uaudio* at uhub? # USB Audio +#audio* at uaudio? +#umidi* at uhub? # USB MIDI +#midi* at umidi? +#ulpt* at uhub? # USB Printers +#umass* at uhub? # USB Mass Storage devices +#scsibus* at umass? +#uhidev* at uhub? # Human Interface Devices +#ums* at uhidev? # USB mouse +#wsmouse* at ums? mux 0 +#ukbd* at uhidev? # USB keyboard +#wskbd* at ukbd? mux 1 +#uhid* at uhidev? # USB generic HID support +#aue* at uhub? # ADMtek AN986 Pegasus Ethernet +#axe* at uhub? # ASIX Electronics AX88172 USB Ethernet +#cue* at uhub? # CATC USB-EL1201A based Ethernet +#kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet +#cdce* at uhub? # CDC Ethernet +#udav* at uhub? # Davicom DM9601 based Ethernet +#upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network' +#url* at uhub? # Realtek RTL8150L based adapters +#wi* at uhub? # WaveLAN IEEE 802.11DS +#urio* at uhub? # Diamond Multimedia Rio 500 +#uscanner* at uhub? # USB Scanners +#usscanner* at uhub? # USB SCSI scanners, e.g., HP5300 +#scsibus* at usscanner? +#uyap* at uhub? # Y@P firmware loader +#udsbr* at uhub? # D-Link DSB-R100 radio +#radio* at udsbr? # USB radio +#ugen* at uhub? # USB Generic driver + +#sti* at pci? # EG-PCI, FX* +#wsdisplay* at sti? + +#com* at pcmcia? # PCMCIA modems + +#ie* at pci? + +#siop* at pci? # NCR 538XX SCSI controllers(new) +#scsibus* at siop? +#ahd* at pci? # Adaptec 79?? SCSI controllers +#scsibus* at ahd? + +#em* at pci? # Intel Pro/1000 ethernet +#ti* at pci? # Alteon Tigon 1Gb ethernet +#txp* at pci? # 3com 3CR990 +#fpa* at pci? # DEC DEFPA FDDI +dc* at pci? # 21143, "tulip" clone ethernet +#dc* at cardbus? +#rl* at pci? # RealTek 81[23]9 ethernet +#rl* at cardbus? +#ep* at pci? # 3c59x +#ep* at cardbus? +#xl* at pci? # 3C9xx ethernet +#xl* at cardbus? +#fxp* at pci? # EtherExpress 10/100B ethernet +#fxp* at cardbus? +#ne* at pci? # NE2000-compatible Ethernet +#ne* at pcmcia? +#an* at pci? # Cisco/Aironet 802.11DS +#an* at pcmcia? +#wi* at pci? # WaveLAN IEEE 802.11DS +#wi* at pcmcia? + +dcphy* at mii? # Digital Clone PHYs +#amphy* at mii? # AMD 79C873 PHYs +#exphy* at mii? # 3Com internal PHYs +#inphy* at mii? # Intel 82555 PHYs +#iophy* at mii? # Intel 82553 PHYs +#icsphy* at mii? # ICS1890 PHYs +lxtphy* at mii? # Level One LXT-970 PHYs +nsphy* at mii? # NS83840 PHYs +#nsphyter* at mii? # NS83843 PHYs +#mtdphy* at mii? # Myson MTD972 PHYs +#qsphy* at mii? # Quality Semi QS6612 PHYs +#sqphy* at mii? # Seeq 8022[013] PHYs +#tlphy* at mii? # ThunderLAN PHYs +#tqphy* at mii? # TDK Semiconductor PHYs +#brgphy* at mii? # Broadcom 10/100/1000 PHYs +#bmtphy* at mii? # Broadcom 10/100 PHYs +#eephy* at mii? # Marvell 88E1000 Gigabit PHYs +ukphy* at mii? # generic unknown PHYs + +#pciide* at pci? flags 0x0000 +#wdc* at pcmcia? +#wd* at wdc? flags 0x0000 +#wd* at pciide? flags 0x0000 +#atapiscsi* at pciide? +#scsibus* at atapiscsi? + +# These entries find devices on all SCSI busses and assign +# unit numers dynamically. +#sd* at scsibus? +#st* at scsibus? +#cd* at scsibus? +#ch* at scsibus? +#ss* at scsibus? +#uk* at scsibus? + +#pseudo-device wsmux 2 # mouse and keyboard multiplexor diff --git a/sys/arch/hppa64/conf/Makefile.hppa64 b/sys/arch/hppa64/conf/Makefile.hppa64 new file mode 100644 index 00000000000..8091bba9c26 --- /dev/null +++ b/sys/arch/hppa64/conf/Makefile.hppa64 @@ -0,0 +1,191 @@ +# $OpenBSD: Makefile.hppa64,v 1.1 2005/04/01 10:40:47 mickey Exp $ + +# Makefile for OpenBSD +# +# This makefile is constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/arch/hppa64/conf/``machineid'' +# after which you should do +# config machineid +# Machine generic makefile changes should be made in +# /sys/arch/hppa64/conf/Makefile.hppa64 +# 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. + +.include <bsd.own.mk> + +MKDEP?= mkdep +SIZE?= size +STRIP?= strip + +# source tree is located via $S relative to the compilation directory +.ifndef S +S!= cd ../../../..; pwd +.endif +HPPA= $S/arch/hppa64 + +INCLUDES= -I. -I$S/arch -I$S -nostdinc +CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \ + -Dhppa64 +CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wno-uninitialized \ + -Wno-format -Wno-main +CMACHFLAGS= -fno-stack-protector -fno-builtin-log -fno-builtin-printf \ + -fno-builtin-snprintf -fno-builtin-vsnprintf +COPTS?= -Os -mpa-risc-2-0 -mno-space-regs -mdisable-fpregs +CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE} +AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE +LINKFLAGS= -X -T ${HPPA}/conf/ld.script -Ttext 80000 --warn-common +STRIPFLAGS= -g -x + +.if ${IDENT:M-DDDB} != "" +CFLAGS+= -fno-omit-frame-pointer +.endif + +HOSTCC?= ${CC} +HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//} +HOSTED_CFLAGS= ${CFLAGS} + +# this line must be there because libkern needs assym.h generated early +depend:: .NOTMAIN .depend + +### find out what to use for libkern +.include "$S/lib/libkern/Makefile.inc" +.ifndef PROF +LIBKERN= ${KERNLIB} +.else +LIBKERN= ${KERNLIB_PROF} +.endif + +### find out what to use for libcompat +.include "$S/compat/common/Makefile.inc" +.ifndef PROF +LIBCOMPAT= ${COMPATLIB} +.else +LIBCOMPAT= ${COMPATLIB_PROF} +.endif + +# compile rules: rules are named ${TYPE}_${SUFFIX} where TYPE is NORMAL or +# HOSTED}, and SUFFIX is the file suffix, capitalized (e.g. C for a .c file). + +NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< +NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< + +HOSTED_C= ${HOSTCC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $< + +%OBJS + +%CFILES + +%SFILES + +SYSTEM_OBJ= locore.o param.o ioconf.o ${OBJS} \ + ${LIBKERN} ${LIBCOMPAT} ${LIBSPMATH} +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" +SYSTEM_LD_TAIL+=; \ + echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \ + echo ${STRIP} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@ +.else +LINKFLAGS+= -S +.endif + +%LOAD + +assym.h: $S/kern/genassym.sh ${HPPA}/hppa64/genassym.cf Makefile + sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} \ + < ${HPPA}/hppa64/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 + + +clean:: + rm -f eddep *bsd bsd.map bsd.gdb tags *.[io] [a-z]*.s \ + [Ee]rrs linterrs makelinks assym.h + +lint: + @lint -hbxncez -DGENERIC -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= ${HPPA}/hppa64/locore.S \ + param.c ioconf.c ${CFILES} ${SFILES} +.depend: ${SRCS} assym.h param.c + ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${HPPA}/hppa64/locore.S + ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} + -if test -n "${SFILES}"; then \ + ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES}; \ + fi + sh $S/kern/genassym.sh ${MKDEP} -f assym.dep ${CFLAGS} \ + ${CPPFLAGS} < ${HPPA}/hppa64/genassym.cf + @sed -e 's/.*\.o:.* /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 +assym.h machdep.o: Makefile + +# depend on CPU configuration +locore.o machdep.o trap.o: Makefile + + +locore.o: ${HPPA}/hppa64/locore.S assym.h + ${NORMAL_S} +fpemu.o: assym.h + +# The install target can be redefined by putting a +# install-kernel-${MACHINE_NAME} target into /etc/mk.conf +MACHINE_NAME!= uname -n +install: install-kernel-${MACHINE_NAME} +.if !target(install-kernel-${MACHINE_NAME}}) +install-kernel-${MACHINE_NAME}: + rm -f /obsd + ln /bsd /obsd + cp bsd /nbsd + mv /nbsd /bsd +.endif + +%RULES diff --git a/sys/arch/hppa64/conf/RAMDISK b/sys/arch/hppa64/conf/RAMDISK new file mode 100644 index 00000000000..5db92686d5f --- /dev/null +++ b/sys/arch/hppa64/conf/RAMDISK @@ -0,0 +1,199 @@ +# $OpenBSD: RAMDISK,v 1.1 2005/04/01 10:40:47 mickey Exp $ +# +# Diskless kernel config +# + +# Machine architecture; required by config(8) +machine hppa + +option DDB # in-kernel debugger +option DIAGNOSTIC # internal consistency checks + +option FFS # UFS +option NFSCLIENT # Network File System client +option CD9660 # ISO 9660 + Rock Ridge file system +option FDESC # /dev/fd +option FIFO # FIFOs; RECOMMENDED +option INET # IP + ICMP + TCP + UDP +option INET6 # IPv6 (needs INET) + +#option USER_PCICONF # user-space PCI configuration +option BOOT_CONFIG # add support for boot -c + +# Need to set locally +maxusers 32 + +option TIMEZONE=0 # time zone to adjust RTC time by +option DST=0 # daylight saving time used by RTC + +option RAMDISK_HOOKS +option MINIROOTSIZE=5120 +config bsd root on rd0a swap on rd0b # and sd0b + +mainbus0 at root # root bus + +mem* at mainbus0 flags 0x00 # /dev/*mem and memory controller +pdc0 at mainbus0 # PDC/IODC wrapper for boot console +power0 at mainbus0 # power/fail manager (iv 30) +cpu* at mainbus0 # HP PA-RISC cpu +plut0 at mainbus0 # Astro Runway-Ropes, MIOC and IOA + +option PCIVERBOSE +elroy* at plut0 +pci* at elroy? + +ppb* at pci? +pci* at ppb? + +#goofy* at pci? # NS87560UBD +#com* at goofy? +#lpt* at goofy? +#fdc* at goofy? + +# CardBus bus support +cbb* at pci? +cardslot* at cbb? +option CARDBUS_DEBUG,CARDSLOT_DEBUG,CARDBUS_MAP_DEBUG +cardbus* at cardslot? +option PCMCIADEBUG,PCMCIAVERBOSE +pcmcia* at cardslot? + +# PCI USB Controllers +#ehci* at pci? # Enhanced Host Controller +#uhci* at pci? # Universal Host Controller (Intel) +#ohci* at pci? # Open Host Controller + +# USB bus support +#usb* at ehci? +#usb* at uhci? +#usb* at ohci? + +# USB devices +#uhub* at usb? # USB Hubs +#uhub* at uhub? # USB Hubs +#umodem* at uhub? # USB Modems/Serial +#ucom* at umodem? +#uvisor* at uhub? # Handspring Visor +#ucom* at uvisor? +#uvscom* at uhub? # SUNTAC Slipper U VS-10U serial +#ucom* at uvscom? +#ubsa* at uhub? # Belkin serial adapter +#ucom* at ubsa? +#uftdi* at uhub? # FTDI FT8U100AX serial adapter +#ucom* at uftdi? +#uplcom* at uhub? # I/O DATA USB-RSAQ2 serial adapter +#ucom* at uplcom? +#umct* at uhub? # MCT USB-RS232 serial adapter +#ucom* at umct? +#uaudio* at uhub? # USB Audio +#audio* at uaudio? +#umidi* at uhub? # USB MIDI +#midi* at umidi? +#ulpt* at uhub? # USB Printers +#umass* at uhub? # USB Mass Storage devices +#scsibus* at umass? +#uhidev* at uhub? # Human Interface Devices +#ums* at uhidev? # USB mouse +#wsmouse* at ums? mux 0 +#ukbd* at uhidev? # USB keyboard +#wskbd* at ukbd? mux 1 +#uhid* at uhidev? # USB generic HID support +#aue* at uhub? # ADMtek AN986 Pegasus Ethernet +#axe* at uhub? # ASIX Electronics AX88172 USB Ethernet +#cue* at uhub? # CATC USB-EL1201A based Ethernet +#kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet +#cdce* at uhub? # CDC Ethernet +#udav* at uhub? # Davicom DM9601 based Ethernet +#upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network' +#url* at uhub? # Realtek RTL8150L based adapters +#wi* at uhub? # WaveLAN IEEE 802.11DS +#urio* at uhub? # Diamond Multimedia Rio 500 +#uscanner* at uhub? # USB Scanners +#usscanner* at uhub? # USB SCSI scanners, e.g., HP5300 +#scsibus* at usscanner? +#uyap* at uhub? # Y@P firmware loader +#udsbr* at uhub? # D-Link DSB-R100 radio +#radio* at udsbr? # USB radio +#ugen* at uhub? # USB Generic driver + +#sti* at pci? # EG-PCI, FX* +wsdisplay* at sti? + +#com* at pcmcia? # PCMCIA modems + +#ie* at pci? + +#ep* at pci? # 3c59x ethernets +ahc* at pci? # Adaptec 2940 SCSI controllers +scsibus* at ahc? +#option BHADEBUG +#bha* at pci? +#scsibus* at bha? + +siop* at pci? # NCR 538XX SCSI controllers(new) +scsibus* at siop? +#ahd* at pci? # Adaptec 79?? SCSI controllers +#scsibus* at ahd? + +#em* at pci? # Intel Pro/1000 ethernet +#ti* at pci? # Alteon Tigon 1Gb ethernet +#txp* at pci? # 3com 3CR990 +#fpa* at pci? # DEC DEFPA FDDI +dc* at pci? # 21143, "tulip" clone ethernet +#dc* at cardbus? +#rl* at pci? # RealTek 81[23]9 ethernet +#rl* at cardbus? +#ep* at pci? # 3c59x +#ep* at cardbus? +#xl* at pci? # 3C9xx ethernet +#xl* at cardbus? +fxp* at pci? # EtherExpress 10/100B ethernet +#fxp* at cardbus? +ne* at pci? # NE2000-compatible Ethernet +ne* at pcmcia? +#an* at pci? # Cisco/Aironet 802.11DS +an* at pcmcia? +#wi* at pci? # WaveLAN IEEE 802.11DS +wi* at pcmcia? + +dcphy* at mii? # Digital Clone PHYs +amphy* at mii? # AMD 79C873 PHYs +#exphy* at mii? # 3Com internal PHYs +inphy* at mii? # Intel 82555 PHYs +#iophy* at mii? # Intel 82553 PHYs +icsphy* at mii? # ICS1890 PHYs +lxtphy* at mii? # Level One LXT-970 PHYs +nsphy* at mii? # NS83840 PHYs +nsphyter* at mii? # NS83843 PHYs +#mtdphy* at mii? # Myson MTD972 PHYs +#qsphy* at mii? # Quality Semi QS6612 PHYs +#sqphy* at mii? # Seeq 8022[013] PHYs +#tlphy* at mii? # ThunderLAN PHYs +#tqphy* at mii? # TDK Semiconductor PHYs +#brgphy* at mii? # Broadcom 10/100/1000 PHYs +bmtphy* at mii? # Broadcom 10/100 PHYs +#eephy* at mii? # Marvell 88E1000 Gigabit PHYs +ukphy* at mii? # generic unknown PHYs + +#pciide* at pci? flags 0x0000 +#wdc* at pcmcia? +#wd* at wdc? flags 0x0000 +#wd* at pciide? flags 0x0000 +#atapiscsi* at pciide? +#scsibus* at atapiscsi? + +# These entries find devices on all SCSI busses and assign +# unit numers dynamically. +sd* at scsibus? +st* at scsibus? +cd* at scsibus? +ch* at scsibus? +ss* at scsibus? +uk* at scsibus? + +pseudo-device rd 1 # ramdisk +pseudo-device loop 1 # network loopback +pseudo-device bpfilter 1 # packet filter +pseudo-device pty 16 # pseudo-terminals +pseudo-device ksyms 1 # kernel symbols device +pseudo-device ccd 4 # concatenated disk devices diff --git a/sys/arch/hppa64/conf/files.hppa64 b/sys/arch/hppa64/conf/files.hppa64 new file mode 100644 index 00000000000..ec650e77a5c --- /dev/null +++ b/sys/arch/hppa64/conf/files.hppa64 @@ -0,0 +1,133 @@ +# $OpenBSD: files.hppa64,v 1.1 2005/04/01 10:40:47 mickey Exp $ +# +# hppa64-specific configuration info + +# maxpartitions must be the first item in files.${ARCH} +maxpartitions 16 + +maxusers 2 8 64 + +# +# "workstation console" routines +# +include "dev/wscons/files.wscons" +file arch/hppa64/hppa64/wscons_machdep.c wsdisplay + +# +# Media Independent Interface (mii) +# +include "dev/mii/files.mii" + +# +# Machine-independent SCSI drivers +# +include "scsi/files.scsi" +major { sd = 4 } +major { st = 5 } +major { cd = 6 } + +# I2O +include "dev/i2o/files.i2o" + +# +# MI ATAPI drivers +# +include "dev/atapiscsi/files.atapiscsi" +include "dev/ata/files.ata" + +# +# PCI Bus support +# +include "dev/pci/files.pci" + +# +# CardBus support +# +include "dev/cardbus/files.cardbus" + +# +# Machine-independent PCMCIA drivers +# +include "dev/pcmcia/files.pcmcia" + +# +# Machine-independent USB drivers +# +include "dev/usb/files.usb" + +# +# Mainbus +# + +define gedoens {} +device mainbus: gedoens +attach mainbus at root +file arch/hppa64/hppa64/mainbus.c mainbus + +device pdc +attach pdc at gedoens +file arch/hppa64/dev/pdc.c pdc + +device power +attach power at gedoens +file arch/hppa64/dev/power.c power needs-flag + +device mem +attach mem at gedoens +file arch/hppa64/dev/mem.c mem + +device cpu +attach cpu at gedoens +file arch/hppa64/dev/cpu.c cpu + +# Astro/Pluto, integrated Runway-Ropes bridge, MIOC and IOA +device plut: gedoens +attach plut at gedoens +file arch/hppa64/dev/pluto.c plut + +# Elroy, Ropes to PCI Bridge. Supports 4X PCI and dual address cycle. +# Mercury; QuickSilver is an AGP also +device elroy: pcibus +attach elroy at gedoens +file arch/hppa64/dev/elroy.c elroy +file arch/hppa64/dev/apic.c elroy + +### + +major {ccd = 1} +major {vnd = 2} +major {rd = 3} + +# PS/2 mouse +include "dev/pckbc/files.pckbc" + +# +# Compatibility +# +#include "compat/hpux/hppa64/files.hpux" +#file arch/hppa64/hppa64/hpux_machdep.c compat_hpux +#include "compat/osf1/files.osf1" +#file arch/hppa64/hppa64/osf1_machdep.c compat_osf1 +#include "compat/linux/files.linux" +#include "compat/ossaudio/files.ossaudio" +#file arch/hppa64/hppa64/linux_machdep.c compat_linux + +# +# Non-device files +# + +file arch/hppa64/hppa64/autoconf.c +file arch/hppa64/hppa64/conf.c +file arch/hppa64/hppa64/db_interface.c ddb +file arch/hppa64/hppa64/db_disasm.c ddb +file arch/hppa64/hppa64/disksubr.c disk +file arch/hppa64/hppa64/machdep.c +file arch/hppa64/hppa64/pmap.c +file arch/hppa64/hppa64/process_machdep.c +file arch/hppa64/hppa64/sys_machdep.c +file arch/hppa64/hppa64/trap.c +file arch/hppa64/hppa64/vm_machdep.c +file arch/hppa64/hppa64/in_cksum.c inet +file arch/hppa64/dev/clock.c + +file dev/cninit.c diff --git a/sys/arch/hppa64/conf/ld.script b/sys/arch/hppa64/conf/ld.script new file mode 100644 index 00000000000..7df2c2c79d2 --- /dev/null +++ b/sys/arch/hppa64/conf/ld.script @@ -0,0 +1,88 @@ +/* $OpenBSD: ld.script,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +OUTPUT_FORMAT("elf64-hppa") +OUTPUT_ARCH(hppa2.0w) +ENTRY($start) +SECTIONS +{ + . = + SIZEOF_HEADERS; + .text : + { + kernel_text = . ; + *(.text) *(.text.*) + *(.reginfo) + *(.init) + *(.stub) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + . = ALIGN(4096); + etext = ABSOLUTE(.); + } = 0x08000240 /* nop filled */ + . = 0x400000; + + .rodata : + { + __rodata_start = .; + *(.rodata) *(.rodata1) + __unwind_start = .; + *(.PARISC.unwind) + __unwind_end = .; + __rodata_end = .; + } = 0 + __data_start = ABSOLUTE(.); + + .data : + { + *(.data) + CONSTRUCTORS + . = ALIGN(4096); + edata = ABSOLUTE(.); + } = 0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + .opd : { *(.opd) } + PROVIDE(__gp = .); + .plt : { *(.plt) } + .dlt : { *(.dlt) } + + . = ALIGN(4096); + + __bss_start = .; + /* .sbss : { *(.sbss) *(.scommon) } */ + .bss : + { + *(.dynbss) *(.bss) + *(COMMON) *($COMMON$) + . = ALIGN(4096); + __kernel_pagedir = ABSOLUTE(.); + . += 5*4096; /* PIT + 4*PIE */ + } + end = ABSOLUTE(.); + + /DISCARD/ : { + *(.exitcall.exit) + *(.interp) + *(.dynsym) + *(.dynstr) + *(.dynamic) + *(.hash) + } +} diff --git a/sys/arch/hppa64/dev/apic.c b/sys/arch/hppa64/dev/apic.c new file mode 100644 index 00000000000..d4a94787853 --- /dev/null +++ b/sys/arch/hppa64/dev/apic.c @@ -0,0 +1,132 @@ +/* $OpenBSD: apic.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define APIC_DEBUG + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <hppa64/dev/elroyreg.h> +#include <hppa64/dev/elroyvar.h> + + +void +apic_write(volatile struct elroy_regs *r, u_int32_t reg, u_int32_t val) +{ + elroy_write32(&r->apic_addr, htole32(reg)); + elroy_write32(&r->apic_data, htole32(val)); +} + +u_int32_t +apic_read(volatile struct elroy_regs *r, u_int32_t reg) +{ + elroy_write32(&r->apic_addr, htole32(reg)); + return letoh32(elroy_read32(&r->apic_data)); +} + +void +apic_attach(struct elroy_softc *sc) +{ + volatile struct elroy_regs *r = sc->sc_regs; + u_int32_t data; + + data = apic_read(r, APIC_VERSION); + sc->sc_nints = (data & APIC_VERSION_NENT) >> APIC_VERSION_NENT_SHIFT; + printf("APIC ver 0x%x %d ents\n", + data & APIC_VERSION_MASK, sc->sc_nints); +} + +int +apic_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) +{ + pci_chipset_tag_t pc = pa->pa_pc; + struct elroy_softc *sc = pc->_cookie; + pcitag_t tag = pa->pa_tag; + hppa_hpa_t hpa = cpu_gethpa(0); + pcireg_t reg; + + reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); +printf(" pin=%d line=%d ", PCI_INTERRUPT_PIN(reg), PCI_INTERRUPT_LINE(reg)); + apic_write(sc->sc_regs, APIC_ENT0(PCI_INTERRUPT_PIN(reg)), + PCI_INTERRUPT_LINE(reg)); + apic_write(sc->sc_regs, APIC_ENT1(PCI_INTERRUPT_PIN(reg)), + ((hpa & 0x0ff00000) >> 4) | ((hpa & 0x000ff000) << 12)); + *ihp = PCI_INTERRUPT_LINE(reg) + 1; + return (*ihp == 0); +} + +const char * +apic_intr_string(void *v, pci_intr_handle_t ih) +{ + static char buf[32]; + + snprintf(buf, 32, "irq %ld", ih); + + return (buf); +} + +void * +apic_intr_establish(void *v, pci_intr_handle_t ih, + int pri, int (*handler)(void *), void *arg, char *name) +{ + /* struct elroy_softc *sc = v; */ + /* volatile struct elroy_regs *r = sc->sc_regs; */ + /* void *iv = NULL; */ + + /* no mapping or bogus */ + if (ih <= 0 || ih > 63) + return (NULL); + +#if 0 +TODO + if ((iv = cpu_intr_map(sc->sc_ih, pri, ih - 1, handler, arg, name))) { + if (cold) + sc->sc_imr |= (1 << (ih - 1)); + else + /* r->imr = sc->sc_imr |= (1 << (ih - 1)) */; + } +#endif + + return (arg); +} + +void +apic_intr_disestablish(void *v, void *cookie) +{ +#if 0 + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + + r->imr &= ~(1 << (ih - 1)); + + TODO cpu_intr_unmap(sc->sc_ih, cookie); +#endif +} + +int +apic_intr(void *v) +{ + + return (0); +} diff --git a/sys/arch/hppa64/dev/clock.c b/sys/arch/hppa64/dev/clock.c new file mode 100644 index 00000000000..2c68f463ca2 --- /dev/null +++ b/sys/arch/hppa64/dev/clock.c @@ -0,0 +1,43 @@ +/* $OpenBSD: clock.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/time.h> + +#include <dev/clock_subr.h> + +void +cpu_initclocks() +{ + +} + +void +setstatclockrate(int newhz) +{ + +} + +void +microtime(struct timeval *tv) +{ + +} diff --git a/sys/arch/hppa64/dev/cpu.c b/sys/arch/hppa64/dev/cpu.c new file mode 100644 index 00000000000..a4ce15560e2 --- /dev/null +++ b/sys/arch/hppa64/dev/cpu.c @@ -0,0 +1,139 @@ +/* $OpenBSD: cpu.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/reboot.h> + +#include <machine/pdc.h> +#include <machine/reg.h> +#include <machine/iomod.h> +#include <machine/autoconf.h> + +#include <arch/hppa/dev/cpudevs.h> + +struct cpu_softc { + struct device sc_dev; + + hppa_hpa_t sc_hpa; + void *sc_ih; +}; + +int cpumatch(struct device *, void *, void *); +void cpuattach(struct device *, struct device *, void *); + +struct cfattach cpu_ca = { + sizeof(struct cpu_softc), cpumatch, cpuattach +}; + +struct cfdriver cpu_cd = { + NULL, "cpu", DV_DULL +}; + +int +cpumatch(parent, cfdata, aux) + struct device *parent; + void *cfdata; + void *aux; +{ + struct confargs *ca = aux; + /* struct cfdata *cf = cfdata; */ + + if (strcmp(ca->ca_name, "cpu")) + return 0; + + return 1; +} + +int +cpu_hardclock(void *v) +{ + hardclock(v); + return (1); +} + +void +cpuattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + /* machdep.c */ + extern struct pdc_model pdc_model; + extern struct pdc_cache pdc_cache; + extern u_int cpu_ticksnum, cpu_ticksdenom; + extern u_int fpu_enable; + + /* struct cpu_softc *sc = (struct cpu_softc *)self; */ + /* struct confargs *ca = aux; */ + u_int mhz = 100 * cpu_ticksnum / cpu_ticksdenom; + const char *p; + + printf (": %s ", cpu_typename); + if (pdc_model.hvers) { + static const char lvls[4][4] = { "0", "1", "1.5", "2" }; + + printf("L%s-%c ", lvls[pdc_model.pa_lvl], "AB"[pdc_model.mc]); + } + + printf ("%d", mhz / 100); + if (mhz % 100 > 9) + printf(".%02d", mhz % 100); + printf("MHz"); + + if (fpu_enable) { + extern u_int fpu_version; + u_int32_t ver[2]; + + mtctl(fpu_enable, CR_CCR); + __asm volatile( + "fstds %%fr0,0(%0)\n\t" + "copr,0,0\n\t" + "fstds %%fr0,0(%0)" + :: "r" (&ver) : "memory"); + mtctl(0, CR_CCR); + fpu_version = HPPA_FPUVER(ver[0]); + printf(", FPU %s rev %d", + hppa_mod_info(HPPA_TYPE_FPU, fpu_version >> 5), + fpu_version & 0x1f); + } + + printf("\n%s: ", self->dv_xname); + p = ""; + if (!pdc_cache.dc_conf.cc_sh) { + printf("%uK(%db/l) Icache, ", + pdc_cache.ic_size / 1024, pdc_cache.ic_conf.cc_line * 16); + p = "D"; + } + printf("%uK(%db/l) wr-%s %scoherent %scache, ", + pdc_cache.dc_size / 1024, pdc_cache.dc_conf.cc_line * 16, + pdc_cache.dc_conf.cc_wt? "thru" : "back", + pdc_cache.dc_conf.cc_cst? "" : "in", p); + + p = ""; + if (!pdc_cache.dt_conf.tc_sh) { + printf("%u ITLB, ", pdc_cache.it_size); + p = "D"; + } + printf("%u %scoherent %sTLB\n", + pdc_cache.dt_size, pdc_cache.dt_conf.tc_cst? "" : "in", p); + +/* TODO spin up others */ +} diff --git a/sys/arch/hppa64/dev/elroy.c b/sys/arch/hppa64/dev/elroy.c new file mode 100644 index 00000000000..9f7d3f6b6b4 --- /dev/null +++ b/sys/arch/hppa64/dev/elroy.c @@ -0,0 +1,1181 @@ +/* $OpenBSD: elroy.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "cardbus.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/reboot.h> +#include <sys/malloc.h> +#include <sys/extent.h> + +#include <machine/iomod.h> +#include <machine/autoconf.h> + +#if NCARDBUS > 0 +#include <dev/cardbus/rbus.h> +#endif + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <hppa64/dev/elroyreg.h> +#include <hppa64/dev/elroyvar.h> + +#define ELROY_MEM_CHUNK 0x800000 +#define ELROY_MEM_WINDOW (2 * ELROY_MEM_CHUNK) + +/* global interrupt masks */ +u_int64_t cpu_maskfree; +volatile u_int64_t imask[NIPL]; + +int elroymatch(struct device *, void *, void *); +void elroyattach(struct device *, struct device *, void *); +int elroy_intr(void *); + +struct cfattach elroy_ca = { + sizeof(struct elroy_softc), elroymatch, elroyattach +}; + +struct cfdriver elroy_cd = { + NULL, "elroy", DV_DULL +}; + +int +elroymatch(parent, cfdata, aux) + struct device *parent; + void *cfdata; + void *aux; +{ + struct confargs *ca = aux; + /* struct cfdata *cf = cfdata; */ + + if (strcmp(ca->ca_name, "lba")) + return (0); + + return (1); +} + +void +elroy_write32(volatile u_int32_t *p, u_int32_t v) +{ + *p = v; +} + +u_int32_t +elroy_read32(volatile u_int32_t *p) +{ + return *p; +} + +void +elroy_attach_hook(struct device *parent, struct device *self, + struct pcibus_attach_args *pba) +{ + +} + +int +elroy_maxdevs(void *v, int bus) +{ + return (32); +} + +pcitag_t +elroy_make_tag(void *v, int bus, int dev, int func) +{ + if (bus > 255 || dev > 31 || func > 7) + panic("elroy_make_tag: bad request"); + + return ((bus << 16) | (dev << 11) | (func << 8)); +} + +void +elroy_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func) +{ + *bus = (tag >> 16) & 0xff; + *dev = (tag >> 11) & 0x1f; + *func= (tag >> 8) & 0x07; +} + +pcireg_t +elroy_conf_read(void *v, pcitag_t tag, int reg) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + u_int32_t arb_mask, err_cfg, control; + pcireg_t data, data1; + +/* printf("elroy_conf_read(%p, 0x%08x, 0x%x)", v, tag, reg); */ + arb_mask = elroy_read32(&r->arb_mask); + err_cfg = elroy_read32(&r->err_cfg); + control = elroy_read32(&r->control); + if (!arb_mask) + elroy_write32(&r->arb_mask, htole64(ELROY_ARB_ENABLE)); + elroy_write32(&r->err_cfg, err_cfg | + htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM)); + elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) & + ~htole32(ELROY_CONTROL_HF)); + + elroy_write32(&r->pci_conf_addr, htole32(tag | reg)); + data1 = elroy_read32(&r->pci_conf_addr); + data = elroy_read32(&r->pci_conf_data); + + elroy_write32(&r->control, control | + htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL)); + elroy_write32(&r->control, control); + elroy_write32(&r->err_cfg, err_cfg); + if (!arb_mask) + elroy_write32(&r->arb_mask, arb_mask); + + data = letoh32(data); +/* printf("=0x%08x (@ 0x%08x)\n", data, letoh32(data1)); */ + return (data); +} + +void +elroy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + u_int32_t arb_mask, err_cfg, control; + pcireg_t data1; + +/* printf("elroy_conf_write(%p, 0x%08x, 0x%x, 0x%x)\n", v, tag, reg, data); */ + arb_mask = elroy_read32(&r->arb_mask); + err_cfg = elroy_read32(&r->err_cfg); + control = elroy_read32(&r->control); + if (!arb_mask) + elroy_write32(&r->arb_mask, htole64(ELROY_ARB_ENABLE)); + elroy_write32(&r->err_cfg, err_cfg | + htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM)); + elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) & + ~htole32(ELROY_CONTROL_HF)); + + /* fix coalescing config writes errata by interleaving w/ a read */ + elroy_write32(&r->pci_conf_addr, htole32(tag | PCI_ID_REG)); + data1 = elroy_read32(&r->pci_conf_addr); + data1 = elroy_read32(&r->pci_conf_data); + + elroy_write32(&r->pci_conf_addr, htole32(tag | reg)); + data1 = elroy_read32(&r->pci_conf_addr); + elroy_write32(&r->pci_conf_data, htole32(data)); + data1 = elroy_read32(&r->pci_conf_addr); + + elroy_write32(&r->control, control | + htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL)); + elroy_write32(&r->control, control); + elroy_write32(&r->err_cfg, err_cfg); + if (!arb_mask) + elroy_write32(&r->arb_mask, arb_mask); +} + +int +elroy_iomap(void *v, bus_addr_t bpa, bus_size_t size, + int flags, bus_space_handle_t *bshp) +{ + struct elroy_softc *sc = v; + /* volatile struct elroy_regs *r = sc->sc_regs; */ + int error; + + if ((error = bus_space_map(sc->sc_bt, bpa + sc->sc_iobase, size, + flags, bshp))) + return (error); + + return (0); +} + +int +elroy_memmap(void *v, bus_addr_t bpa, bus_size_t size, + int flags, bus_space_handle_t *bshp) +{ + struct elroy_softc *sc = v; + /* volatile struct elroy_regs *r = sc->sc_regs; */ + int error; + + bpa |= 0xffffffff00000000ULL; + if ((error = bus_space_map(sc->sc_bt, bpa, size, flags, bshp))) + return (error); + + return (0); +} + +int +elroy_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t size, bus_space_handle_t *nbshp) +{ + *nbshp = bsh + offset; + return (0); +} + +int +elroy_ioalloc(void *v, 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) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + bus_addr_t iostart, ioend; + + iostart = r->io_base & ~htole32(ELROY_BASE_RE); + ioend = iostart + ~htole32(r->io_mask) + 1; + if (rstart < iostart || rend > ioend) + panic("elroy_ioalloc: bad region start/end"); + + rstart += sc->sc_iobase; + rend += sc->sc_iobase; + if (bus_space_alloc(sc->sc_bt, rstart, rend, size, + align, boundary, flags, addrp, bshp)) + return (ENOMEM); + + return (0); +} + +int +elroy_memalloc(void *v, 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) +{ + struct elroy_softc *sc = v; + /* volatile struct elroy_regs *r = sc->sc_regs; */ + + if (bus_space_alloc(sc->sc_bt, rstart, rend, size, + align, boundary, flags, addrp, bshp)) + return (ENOMEM); + + return (0); +} + +void +elroy_unmap(void *v, bus_space_handle_t bsh, bus_size_t size) +{ + struct elroy_softc *sc = v; + + bus_space_free(sc->sc_bt, bsh, size); +} + +void +elroy_free(void *v, bus_space_handle_t bh, bus_size_t size) +{ + /* should be enough */ + elroy_unmap(v, bh, size); +} + +void +elroy_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + u_int32_t data; + + sync_caches(); + if (op & BUS_SPACE_BARRIER_WRITE) { + data = r->pci_id; /* flush write fifo */ + sync_caches(); + } +} + +#if NCARDBUS > 0 +void * +elroy_alloc_parent(struct device *self, struct pci_attach_args *pa, int io) +{ +#if 0 /* TODO */ + + struct elroy_softc *sc = pa->pa_pc->_cookie; + struct extent *ex; + bus_space_tag_t tag; + bus_addr_t start; + bus_size_t size; + + if (io) { + ex = sc->sc_ioex; + tag = pa->pa_iot; + start = 0xa000; + size = 0x1000; + } else { + if (!sc->sc_memex) { + bus_space_handle_t memh; + bus_addr_t mem_start; + + if (elroy_memalloc(sc, 0xf0800000, 0xff7fffff, + ELROY_MEM_WINDOW, ELROY_MEM_WINDOW, EX_NOBOUNDARY, + 0, &mem_start, &memh)) + return (NULL); + + snprintf(sc->sc_memexname, sizeof(sc->sc_memexname), + "%s_mem", sc->sc_dv.dv_xname); + if ((sc->sc_memex = extent_create(sc->sc_memexname, + mem_start, mem_start + ELROY_MEM_WINDOW, M_DEVBUF, + NULL, 0, EX_NOWAIT | EX_MALLOCOK)) == NULL) { + extent_destroy(sc->sc_ioex); + bus_space_free(sc->sc_bt, memh, + ELROY_MEM_WINDOW); + return (NULL); + } + } + ex = sc->sc_memex; + tag = pa->pa_memt; + start = ex->ex_start; + size = ELROY_MEM_CHUNK; + } + + if (extent_alloc_subregion(ex, start, ex->ex_end, size, size, 0, + EX_NOBOUNDARY, EX_NOWAIT, &start)) + return (NULL); + + extent_free(ex, start, size, EX_NOWAIT); + return rbus_new_root_share(tag, ex, start, size, 0); +#else + return (NULL); +#endif +} +#endif + +u_int8_t +elroy_r1(void *v, bus_space_handle_t h, bus_size_t o) +{ + h += o; + return *(volatile u_int8_t *)h; +} + +u_int16_t +elroy_r2(void *v, bus_space_handle_t h, bus_size_t o) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + return (letoh16(*p)); +} + +u_int32_t +elroy_r4(void *v, bus_space_handle_t h, bus_size_t o) +{ + u_int32_t data; + + h += o; + data = *(volatile u_int32_t *)h; + return (letoh32(data)); +} + +u_int64_t +elroy_r8(void *v, bus_space_handle_t h, bus_size_t o) +{ + u_int64_t data; + + h += o; + data = *(volatile u_int64_t *)h; + return (letoh64(data)); +} + +void +elroy_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv) +{ + h += o; + *(volatile u_int8_t *)h = vv; +} + +void +elroy_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + *p = htole16(vv); +} + +void +elroy_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv) +{ + h += o; + vv = htole32(vv); + *(volatile u_int32_t *)h = vv; +} + +void +elroy_w8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv) +{ + h += o; + *(volatile u_int64_t *)h = htole64(vv); +} + + +void +elroy_rm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *a++ = *p; +} + +void +elroy_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + while (c--) + *a++ = letoh16(*p); +} + +void +elroy_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) +{ + volatile u_int32_t *p; + + h += o; + p = (volatile u_int32_t *)h; + while (c--) + *a++ = letoh32(*p); +} + +void +elroy_rm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c) +{ + volatile u_int64_t *p; + + h += o; + p = (volatile u_int64_t *)h; + while (c--) + *a++ = letoh64(*p); +} + +void +elroy_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *p = *a++; +} + +void +elroy_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + while (c--) + *p = htole16(*a++); +} + +void +elroy_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) +{ + volatile u_int32_t *p; + + h += o; + p = (volatile u_int32_t *)h; + while (c--) + *p = htole32(*a++); +} + +void +elroy_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c) +{ + volatile u_int64_t *p; + + h += o; + p = (volatile u_int64_t *)h; + while (c--) + *p = htole64(*a++); +} + +void +elroy_sm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *p = vv; +} + +void +elroy_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + vv = htole16(vv); + while (c--) + *p = vv; +} + +void +elroy_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) +{ + volatile u_int32_t *p; + + h += o; + p = (volatile u_int32_t *)h; + vv = htole32(vv); + while (c--) + *p = vv; +} + +void +elroy_sm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c) +{ + volatile u_int64_t *p; + + h += o; + p = (volatile u_int64_t *)h; + vv = htole64(vv); + while (c--) + *p = vv; +} + +void +elroy_rrm_2(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int16_t *p, *q = (u_int16_t *)a; + + h += o; + p = (volatile u_int16_t *)h; + c /= 2; + while (c--) + *q++ = *p; +} + +void +elroy_rrm_4(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int32_t *p, *q = (u_int32_t *)a; + + h += o; + p = (volatile u_int32_t *)h; + c /= 4; + while (c--) + *q++ = *p; +} + +void +elroy_rrm_8(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int64_t *p, *q = (u_int64_t *)a; + + h += o; + p = (volatile u_int64_t *)h; + c /= 8; + while (c--) + *q++ = *p; +} + +void +elroy_wrm_2(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int16_t *p; + const u_int16_t *q = (const u_int16_t *)a; + + h += o; + p = (volatile u_int16_t *)h; + c /= 2; + while (c--) + *p = *q++; +} + +void +elroy_wrm_4(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int32_t *p; + const u_int32_t *q = (const u_int32_t *)a; + + h += o; + p = (volatile u_int32_t *)h; + c /= 4; + while (c--) + *p = *q++; +} + +void +elroy_wrm_8(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int64_t *p; + const u_int64_t *q = (const u_int64_t *)a; + + h += o; + p = (volatile u_int64_t *)h; + c /= 8; + while (c--) + *p = *q++; +} + +void +elroy_rr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *a++ = *p++; +} + +void +elroy_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) +{ + volatile u_int16_t *p, data; + + h += o; + p = (volatile u_int16_t *)h; + while (c--) { + data = *p++; + *a++ = letoh16(data); + } +} + +void +elroy_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) +{ + volatile u_int32_t *p, data; + + h += o; + p = (volatile u_int32_t *)h; + while (c--) { + data = *p++; + *a++ = letoh32(data); + } +} + +void +elroy_rr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c) +{ + volatile u_int64_t *p, data; + + h += o; + p = (volatile u_int64_t *)h; + while (c--) { + data = *p++; + *a++ = letoh64(data); + } +} + +void +elroy_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *p++ = *a++; +} + +void +elroy_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) +{ + volatile u_int16_t *p, data; + + h += o; + p = (volatile u_int16_t *)h; + while (c--) { + data = *a++; + *p++ = htole16(data); + } +} + +void +elroy_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) +{ + volatile u_int32_t *p, data; + + h += o; + p = (volatile u_int32_t *)h; + while (c--) { + data = *a++; + *p++ = htole32(data); + } +} + +void +elroy_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c) +{ + volatile u_int64_t *p, data; + + h += o; + p = (volatile u_int64_t *)h; + while (c--) { + data = *a++; + *p++ = htole64(data); + } +} + +void +elroy_rrr_2(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int16_t *p, *q = (u_int16_t *)a; + + c /= 2; + h += o; + p = (volatile u_int16_t *)h; + while (c--) + *q++ = *p++; +} + +void +elroy_rrr_4(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int32_t *p, *q = (u_int32_t *)a; + + c /= 4; + h += o; + p = (volatile u_int32_t *)h; + while (c--) + *q++ = *p++; +} + +void +elroy_rrr_8(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int64_t *p, *q = (u_int64_t *)a; + + c /= 8; + h += o; + p = (volatile u_int64_t *)h; + while (c--) + *q++ = *p++; +} + +void +elroy_wrr_2(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int16_t *p; + const u_int16_t *q = (u_int16_t *)a; + + c /= 2; + h += o; + p = (volatile u_int16_t *)h; + while (c--) + *p++ = *q++; +} + +void +elroy_wrr_4(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int32_t *p; + const u_int32_t *q = (u_int32_t *)a; + + c /= 4; + h += o; + p = (volatile u_int32_t *)h; + while (c--) + *p++ = *q++; +} + +void +elroy_wrr_8(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int64_t *p; + const u_int64_t *q = (u_int64_t *)a; + + c /= 8; + h += o; + p = (volatile u_int64_t *)h; + while (c--) + *p++ = *q++; +} + +void +elroy_sr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *p++ = vv; +} + +void +elroy_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) +{ + volatile u_int16_t *p; + + h += o; + vv = htole16(vv); + p = (volatile u_int16_t *)h; + while (c--) + *p++ = vv; +} + +void +elroy_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) +{ + volatile u_int32_t *p; + + h += o; + vv = htole32(vv); + p = (volatile u_int32_t *)h; + while (c--) + *p++ = vv; +} + +void +elroy_sr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c) +{ + volatile u_int64_t *p; + + h += o; + vv = htole64(vv); + p = (volatile u_int64_t *)h; + while (c--) + *p++ = vv; +} + +void +elroy_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + while (c--) + elroy_w1(v, h1, o1++, elroy_r1(v, h2, o2++)); +} + +void +elroy_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + while (c--) { + elroy_w2(v, h1, o1, elroy_r2(v, h2, o2)); + o1 += 2; + o2 += 2; + } +} + +void +elroy_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + while (c--) { + elroy_w4(v, h1, o1, elroy_r4(v, h2, o2)); + o1 += 4; + o2 += 4; + } +} + +void +elroy_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + while (c--) { + elroy_w8(v, h1, o1, elroy_r8(v, h2, o2)); + o1 += 8; + o2 += 8; + } +} + +const struct hppa64_bus_space_tag elroy_iomemt = { + NULL, + + NULL, elroy_unmap, elroy_subregion, NULL, elroy_free, + elroy_barrier, + elroy_r1, elroy_r2, elroy_r4, elroy_r8, + elroy_w1, elroy_w2, elroy_w4, elroy_w8, + elroy_rm_1, elroy_rm_2, elroy_rm_4, elroy_rm_8, + elroy_wm_1, elroy_wm_2, elroy_wm_4, elroy_wm_8, + elroy_sm_1, elroy_sm_2, elroy_sm_4, elroy_sm_8, + elroy_rrm_2, elroy_rrm_4, elroy_rrm_8, + elroy_wrm_2, elroy_wrm_4, elroy_wrm_8, + elroy_rr_1, elroy_rr_2, elroy_rr_4, elroy_rr_8, + elroy_wr_1, elroy_wr_2, elroy_wr_4, elroy_wr_8, + elroy_rrr_2, elroy_rrr_4, elroy_rrr_8, + elroy_wrr_2, elroy_wrr_4, elroy_wrr_8, + elroy_sr_1, elroy_sr_2, elroy_sr_4, elroy_sr_8, + elroy_cp_1, elroy_cp_2, elroy_cp_4, elroy_cp_8 +}; + +int +elroy_dmamap_create(void *v, bus_size_t size, int nsegments, + bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) +{ + struct elroy_softc *sc = v; + + /* TODO check the addresses, boundary, enable dma */ + + return (bus_dmamap_create(sc->sc_dmat, size, nsegments, + maxsegsz, boundary, flags, dmamp)); +} + +void +elroy_dmamap_destroy(void *v, bus_dmamap_t map) +{ + struct elroy_softc *sc = v; + + bus_dmamap_destroy(sc->sc_dmat, map); +} + +int +elroy_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size, + struct proc *p, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags)); +} + +int +elroy_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags)); +} + +int +elroy_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags)); +} + +int +elroy_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs, + int nsegs, bus_size_t size, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags)); +} + +void +elroy_dmamap_unload(void *v, bus_dmamap_t map) +{ + struct elroy_softc *sc = v; + + bus_dmamap_unload(sc->sc_dmat, map); +} + +void +elroy_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off, + bus_size_t len, int ops) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_sync(sc->sc_dmat, map, off, len, ops)); +} + +int +elroy_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment, + bus_size_t boundary, bus_dma_segment_t *segs, + int nsegs, int *rsegs, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary, + segs, nsegs, rsegs, flags)); +} + +void +elroy_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs) +{ + struct elroy_softc *sc = v; + + bus_dmamem_free(sc->sc_dmat, segs, nsegs); +} + +int +elroy_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size, + caddr_t *kvap, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags)); +} + +void +elroy_dmamem_unmap(void *v, caddr_t kva, size_t size) +{ + struct elroy_softc *sc = v; + + bus_dmamem_unmap(sc->sc_dmat, kva, size); +} + +paddr_t +elroy_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off, + int prot, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags)); +} + +const struct hppa64_bus_dma_tag elroy_dmat = { + NULL, + elroy_dmamap_create, elroy_dmamap_destroy, + elroy_dmamap_load, elroy_dmamap_load_mbuf, + elroy_dmamap_load_uio, elroy_dmamap_load_raw, + elroy_dmamap_unload, elroy_dmamap_sync, + + elroy_dmamem_alloc, elroy_dmamem_free, elroy_dmamem_map, + elroy_dmamem_unmap, elroy_dmamem_mmap +}; + +const struct hppa64_pci_chipset_tag elroy_pc = { + NULL, + elroy_attach_hook, elroy_maxdevs, elroy_make_tag, elroy_decompose_tag, + elroy_conf_read, elroy_conf_write, + apic_intr_map, apic_intr_string, + apic_intr_establish, apic_intr_disestablish, +#if NCARDBUS > 0 + elroy_alloc_parent +#else + NULL +#endif +}; + +int +elroyprint(void *aux, const char *pnp) +{ + struct pcibus_attach_args *pba = aux; + + if (pnp) + printf("%s at %s\n", pba->pba_busname, pnp); + return (UNCONF); +} + +void +elroyattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct elroy_softc *sc = (struct elroy_softc *)self; + struct confargs *ca = (struct confargs *)aux; + struct pcibus_attach_args pba; + volatile struct elroy_regs *r; + const char *p = NULL, *q; + int i; + + sc->sc_bt = ca->ca_iot; + sc->sc_dmat = ca->ca_dmatag; + if (bus_space_map(sc->sc_bt, ca->ca_hpa, ca->ca_hpasz, 0, &sc->sc_bh)) { + printf(": can't map space\n"); + return; + } + + sc->sc_regs = r = (void *)bus_space_vaddr(sc->sc_bt, sc->sc_bh); + elroy_write32(&r->pci_cmdstat, htole32(PCI_COMMAND_IO_ENABLE | + PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)); + + elroy_write32(&r->control, elroy_read32(&r->control) & + ~htole32(ELROY_CONTROL_RF)); + for (i = 5000; i-- && + elroy_read32(&r->status) & htole32(ELROY_STATUS_RC); DELAY(10)); + if (i < 0) { + printf(": reset failed; status %b\n", + ELROY_STATUS_BITS, htole32(r->status)); + return; + } + + q = ""; + sc->sc_ver = PCI_REVISION(letoh32(elroy_read32(&r->pci_class))); + switch ((ca->ca_type.iodc_model << 4) | + (ca->ca_type.iodc_revision >> 4)) { + case 0x782: + p = "Elroy"; + switch (sc->sc_ver) { + default: + q = "+"; + case 5: sc->sc_ver = 0x40; break; + case 4: sc->sc_ver = 0x30; break; + case 3: sc->sc_ver = 0x22; break; + case 2: sc->sc_ver = 0x21; break; + case 1: sc->sc_ver = 0x20; break; + case 0: sc->sc_ver = 0x10; break; + } + break; + + case 0x783: + p = "Mercury"; + break; + + case 0x784: + p = "Quicksilver"; + break; + + default: + p = "Mojo"; + break; + } + + printf(": %s TR%d.%d%s", p, sc->sc_ver >> 4, sc->sc_ver & 0xf, q); + apic_attach(sc); + + /* TODO reserve elroy's pci space ? */ + +printf("lmm %llx/%llx gmm %llx/%llx wlm %llx/%llx wgm %llx/%llx io %llx/%llx eio %llx/%llx\n", +letoh64(r->lmmio_base), letoh64(r->lmmio_mask), +letoh64(r->gmmio_base), letoh64(r->gmmio_mask), +letoh64(r->wlmmio_base), letoh64(r->wlmmio_mask), +letoh64(r->wgmmio_base), letoh64(r->wgmmio_mask), +letoh64(r->io_base), letoh64(r->io_mask), +letoh64(r->eio_base), letoh64(r->eio_mask)); + + /* XXX evil hack! */ + sc->sc_iobase = 0xfee00000; + + sc->sc_iot = elroy_iomemt; + sc->sc_iot.hbt_cookie = sc; + sc->sc_iot.hbt_map = elroy_iomap; + sc->sc_iot.hbt_alloc = elroy_ioalloc; + sc->sc_memt = elroy_iomemt; + sc->sc_memt.hbt_cookie = sc; + sc->sc_memt.hbt_map = elroy_memmap; + sc->sc_memt.hbt_alloc = elroy_memalloc; + sc->sc_pc = elroy_pc; + sc->sc_pc._cookie = sc; + sc->sc_dmatag = elroy_dmat; + sc->sc_dmatag._cookie = sc; + + pba.pba_busname = "pci"; + pba.pba_iot = &sc->sc_iot; + pba.pba_memt = &sc->sc_memt; + pba.pba_dmat = &sc->sc_dmatag; + pba.pba_pc = &sc->sc_pc; + pba.pba_bus = 0; /* (letoh32(elroy_read32(&r->busnum)) & 0xff) >> 4; */ + config_found(self, &pba, elroyprint); + + /* enable interrupts now that all the devices are there */ + /* r->imr = sc->sc_imr; */ +} diff --git a/sys/arch/hppa64/dev/elroyreg.h b/sys/arch/hppa64/dev/elroyreg.h new file mode 100644 index 00000000000..0ffaa3875d1 --- /dev/null +++ b/sys/arch/hppa64/dev/elroyreg.h @@ -0,0 +1,146 @@ +/* $OpenBSD: elroyreg.h,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct elroy_regs { + /* std PCI bridge header */ + u_int32_t pci_id; /* 0x000 rw PCI_ID */ + u_int32_t pci_cmdstat; /* 0x004 rw PCI_COMMAND_STATUS_REG */ + u_int32_t pci_class; /* 0x008 ro PCI_CLASS_REG */ + u_int32_t pci_bhlc; /* 0x00c rw PCI_BHLC_REG */ + u_int32_t res0[0x30/4]; /* 0x010 */ + + /* HW Bridge registers */ + u_int32_t pci_conf_addr; /* 0x040 rw config space address */ + u_int32_t pad040; + u_int32_t pci_conf_data; /* 0x048 rw config space data */ + u_int32_t pad048; + u_int64_t elroy_mtlt; /* 0x050 */ + u_int32_t busnum; /* 0x058 bus number/scratch */ + u_int32_t par058; + u_int64_t res1; /* 0x060 */ + u_int64_t rope; /* 0x068 rope parity, loopback */ + u_int64_t err_addr; /* 0x070 error log: address */ + u_int64_t suspend; /* 0x078 rw suspend control */ + u_int32_t arb_mask; /* 0x080 rw arbitration mask */ + u_int32_t pad080; +#define ELROY_ARB_ENABLE 0x01 /* enable arbitration */ +#define ELROY_ARB_PCIDEVA 0x02 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVB 0x04 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVC 0x08 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVD 0x10 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVE 0x20 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVF 0x40 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVG 0x80 /* PCI device A allow */ + u_int64_t arb_pri; /* 0x088 arbitration priority */ + u_int64_t arb_mode; /* 0x090 arbitration mode */ + u_int64_t mtlt; /* 0x098 */ + u_int64_t res2[12]; /* 0x0a0 */ + u_int64_t mod_info; /* 0x100 */ + u_int32_t control; /* 0x108 */ +#define ELROY_CONTROL_RF 0x01 /* reset pci */ +#define ELROY_CONTROL_VE 0x08 /* VGA enable */ +#define ELROY_CONTROL_CL 0x10 /* clear error log */ +#define ELROY_CONTROL_CE 0x20 /* clear error log enable */ +#define ELROY_CONTROL_HF 0x40 /* hard fail enable */ + u_int32_t status; /* 0x10c */ +#define ELROY_STATUS_RC 0x01 /* reset complete */ +#define ELROY_STATUS_BITS "\020\01RC" + u_int64_t res3[30]; /* 0x110 */ + u_int64_t lmmio_base; /* 0x200 */ + u_int64_t lmmio_mask; /* 0x208 */ + u_int64_t gmmio_base; /* 0x210 */ + u_int64_t gmmio_mask; /* 0x218 */ + u_int64_t wlmmio_base; /* 0x220 */ + u_int64_t wlmmio_mask; /* 0x228 */ + u_int64_t wgmmio_base; /* 0x230 */ + u_int64_t wgmmio_mask; /* 0x238 */ + u_int32_t io_base; /* 0x240 */ + u_int32_t pad240; + u_int32_t io_mask; /* 0x248 */ + u_int32_t pad248; + u_int32_t res4[4]; /* 0x250 */ + u_int32_t eio_base; /* 0x260 */ + u_int32_t pad260; + u_int32_t eio_mask; /* 0x268 */ + u_int32_t pad268; +#define ELROY_BASE_RE 0x01 /* range enable */ + u_int64_t res5; /* 0x270 */ + u_int64_t dmac_ctrl; /* 0x278 DMA connection control */ + u_int64_t res6[16]; /* 0x280 */ + u_int64_t ibase; /* 0x300 */ + u_int64_t imask; /* 0x308 */ + u_int64_t hint_cfg; /* 0x310 */ + u_int64_t res7[13]; /* 0x318 */ + u_int64_t hints[14]; /* 0x380 */ + u_int64_t res8[2]; /* 0x3f0 */ + u_int64_t res9[64]; /* 0x400 */ + u_int64_t pad0; /* 0x600 */ + u_int64_t pci_drive; /* 0x608 */ + u_int64_t rope_cfg; /* 0x610 */ + u_int64_t clk_ctl; /* 0x618 */ + u_int32_t pad1; /* 0x620 */ + u_int32_t res10[23]; /* 0x624 */ + u_int32_t err_cfg; /* 0x680 error config */ + u_int32_t pad680; +#define ELROY_ERRCFG_PW 0x01 /* PIO writes parity errors */ +#define ELROY_ERRCFG_PR 0x02 /* PIO reads parity errors */ +#define ELROY_ERRCFG_DW 0x04 /* DMA writes parity errors */ +#define ELROY_ERRCFG_DR 0x08 /* DMA reads parity errors */ +#define ELROY_ERRCFG_CM 0x10 /* no fatal on config space */ +#define ELROY_ERRCFG_SMART 0x20 /* smart bus mode */ + u_int64_t err_stat; /* 0x688 error status */ + u_int64_t err_mid; /* 0x690 error log: master id */ + u_int64_t rope_estat; /* 0x698 rope error status */ + u_int64_t rope_eclr; /* 0x6a0 rope error clear */ + u_int64_t res11[42]; /* 0x6a8 */ + u_int64_t regbus; /* 0x7f8 reads 0x3ff */ + u_int32_t apic_addr; /* 0x800 APIC address register */ + u_int32_t pad800; + u_int64_t res12; + u_int32_t apic_data; /* 0x810 APIC data register */ + u_int32_t pad808; + u_int64_t res13[5]; + u_int32_t apic_eoi; /* 0x840 APIC interrupt ack */ + u_int32_t pad840; + u_int32_t apic_softint; /* 0x850 write generates softint */ + u_int32_t pad850; + u_int64_t res14[123]; /* 0x858 */ + /*0x1000 */ +} __packed; + +/* APIC registers */ +#define APIC_VERSION 0x01 +#define APIC_VERSION_MASK 0xff +#define APIC_VERSION_NENT 0xff0000 +#define APIC_VERSION_NENT_SHIFT 16 +#define APIC_ENT0(i) (0x10 + (i)*2) +#define APIC_ENT0_VEC 0x000ff +#define APIC_ENT0_MOD 0x00700 /* delivery mode */ +#define APIC_ENT0_FXD 0x00000 +#define APIC_ENT0_RDR 0x00100 +#define APIC_ENT0_PMI 0x00200 +#define APIC_ENT0_NMI 0x00400 +#define APIC_ENT0_INI 0x00500 +#define APIC_ENT0_EXT 0x00700 +#define APIC_ENT0_PEND 0x01000 /* int is pending */ +#define APIC_ENT0_LOW 0x02000 /* polarity */ +#define APIC_ENT0_LEV 0x08000 /* edge/level */ +#define APIC_ENT0_MASK 0x10000 /* mask int */ +#define APIC_ENT1(i) (0x11 + (i)*2) + diff --git a/sys/arch/hppa64/dev/elroyvar.h b/sys/arch/hppa64/dev/elroyvar.h new file mode 100644 index 00000000000..921d1f0b4d5 --- /dev/null +++ b/sys/arch/hppa64/dev/elroyvar.h @@ -0,0 +1,50 @@ +/* $OpenBSD: elroyvar.h,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct elroy_softc { + struct device sc_dv; + + int sc_ver; + bus_space_tag_t sc_bt; + bus_space_handle_t sc_bh; + bus_dma_tag_t sc_dmat; + volatile struct elroy_regs *sc_regs; + bus_addr_t sc_iobase; + + u_int32_t sc_imr; + int sc_nints; + + struct hppa64_pci_chipset_tag sc_pc; + struct hppa64_bus_space_tag sc_iot; + struct hppa64_bus_space_tag sc_memt; + char sc_memexname[20]; + struct extent *sc_memex; + struct hppa64_bus_dma_tag sc_dmatag; +}; + +void apic_attach(struct elroy_softc *sc); +int apic_intr(void *v); +int apic_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp); +const char *apic_intr_string(void *v, pci_intr_handle_t ih); +void *apic_intr_establish(void *v, pci_intr_handle_t ih, int pri, + int (*handler)(void *), void *arg, char *name); +void apic_intr_disestablish(void *v, void *cookie); + +void elroy_write32(volatile u_int32_t *p, u_int32_t v); +u_int32_t elroy_read32(volatile u_int32_t *p); diff --git a/sys/arch/hppa64/dev/mem.c b/sys/arch/hppa64/dev/mem.c new file mode 100644 index 00000000000..4b6fcc17fe0 --- /dev/null +++ b/sys/arch/hppa64/dev/mem.c @@ -0,0 +1,268 @@ +/* $OpenBSD: mem.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 1991,1992,1994, The University of Utah and + * the Computer Systems Laboratory (CSL). All rights reserved. + * + * Subject to your agreements with CMU, + * permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: mem.c 1.9 94/12/16$ + */ +/* + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/uio.h> +#include <sys/types.h> +#include <sys/device.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/file.h> + +#include <uvm/uvm.h> + +#include <machine/conf.h> +#include <machine/bus.h> +#include <machine/iomod.h> +#include <machine/autoconf.h> +#include <machine/pmap.h> + +struct mem_softc { + struct device sc_dev; +}; + +int memmatch(struct device *, void *, void *); +void memattach(struct device *, struct device *, void *); + +struct cfattach mem_ca = { + sizeof(struct mem_softc), memmatch, memattach +}; + +struct cfdriver mem_cd = { + NULL, "mem", DV_DULL +}; + +caddr_t zeropage; + +int +memmatch(parent, cfdata, aux) + struct device *parent; + void *cfdata; + void *aux; +{ + struct confargs *ca = aux; + + if (strcmp(ca->ca_name, "memory")) + return 0; + + return 1; +} + +void +memattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct pdc_iodc_minit pdc_minit PDC_ALIGNMENT; + /* struct mem_softc *sc = (struct mem_softc *)self; */ + struct confargs *ca = aux; + int err; + +/* TODO scan the memory regions list */ + + if ((err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_NINIT, + &pdc_minit, ca->ca_hpa, PAGE0->imm_spa_size)) < 0) + pdc_minit.max_spa = PAGE0->imm_max_mem; + + printf(": size %d", pdc_minit.max_spa / (1024*1024)); + if (pdc_minit.max_spa % (1024*1024)) + printf(".%d", pdc_minit.max_spa % (1024*1024)); + printf("MB\n"); +} + +int +mmopen(dev, flag, ioflag, p) + dev_t dev; + int flag; + int ioflag; + struct proc *p; +{ + return (0); +} + +/*ARGSUSED*/ +int +mmclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + return (0); +} + +int +mmrw(dev, uio, flags) + dev_t dev; + struct uio *uio; + int flags; +{ + struct iovec *iov; + vaddr_t v, o; + int error = 0; + u_int c; + + 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)) { + + case 0: /* /dev/mem */ + + /* If the address isn't in RAM, bail. */ + v = uio->uio_offset; + if (btoc(v) > physmem) { + error = EFAULT; + /* this will break us out of the loop */ + continue; + } + c = ctob(physmem) - v; + c = min(c, uio->uio_resid); + error = uiomove((caddr_t)v, c, uio); + break; + + case 1: /* /dev/kmem */ + v = uio->uio_offset; + o = v & PAGE_MASK; + c = min(uio->uio_resid, (int)(PAGE_SIZE - o)); + if (btoc(v) > physmem && !uvm_kernacc((caddr_t)v, + c, (uio->uio_rw == UIO_READ) ? B_READ : B_WRITE)) { + error = EFAULT; + /* this will break us out of the loop */ + continue; + } + error = uiomove((caddr_t)v, c, uio); + break; + + case 2: /* /dev/null */ + if (uio->uio_rw == UIO_WRITE) + uio->uio_resid = 0; + return (0); + + case 12: /* /dev/zero */ + /* Write to /dev/zero is ignored. */ + if (uio->uio_rw == UIO_WRITE) { + uio->uio_resid = 0; + return (0); + } + /* + * On the first call, allocate and zero a page + * of memory for use with /dev/zero. + */ + if (zeropage == NULL) { + zeropage = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); + bzero(zeropage, PAGE_SIZE); + } + c = min(iov->iov_len, PAGE_SIZE); + error = uiomove(zeropage, c, uio); + break; + + default: + return (ENXIO); + } + } + + return (error); +} + +paddr_t +mmmmap(dev, off, prot) + dev_t dev; + off_t off; + int prot; +{ + if (minor(dev) != 0) + return (-1); + + /* + * Allow access only in RAM. + */ +#if 0 + if (off < ctob(firstusablepage) || + off >= ctob(lastusablepage + 1)) + return (-1); +#endif + return (btop(off)); +} + +int +mmioctl(dev, cmd, data, flags, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flags; + struct proc *p; +{ + return (EOPNOTSUPP); +} diff --git a/sys/arch/hppa64/dev/pdc.c b/sys/arch/hppa64/dev/pdc.c new file mode 100644 index 00000000000..2f9764f6d5c --- /dev/null +++ b/sys/arch/hppa64/dev/pdc.c @@ -0,0 +1,469 @@ +/* $OpenBSD: pdc.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "com.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/tty.h> +#include <sys/user.h> +#include <sys/timeout.h> + +#include <dev/cons.h> + +#include <machine/conf.h> +#include <machine/pdc.h> +#include <machine/iomod.h> +#include <machine/autoconf.h> + +typedef +struct pdc_softc { + struct device sc_dv; + struct tty *sc_tty; + struct timeout sc_to; +} pdcsoftc_t; + +pdcio_t pdc; +int pdcret[32] PDC_ALIGNMENT; +char pdc_consbuf[IODC_MINIOSIZ] PDC_ALIGNMENT; +iodcio_t pdc_cniodc, pdc_kbdiodc; +pz_device_t *pz_kbd, *pz_cons; +hppa_hpa_t conaddr; +int conunit; + +int pdcmatch(struct device *, void *, void *); +void pdcattach(struct device *, struct device *, void *); + +struct cfattach pdc_ca = { + sizeof(pdcsoftc_t), pdcmatch, pdcattach +}; + +struct cfdriver pdc_cd = { + NULL, "pdc", DV_DULL +}; + +void pdcstart(struct tty *tp); +void pdctimeout(void *v); +int pdcparam(struct tty *tp, struct termios *); +int pdccnlookc(dev_t dev, int *cp); + +#if NCOM_GSC > 0 +/* serial console speed table */ +static int pdc_speeds[] = { + B50, + B75, + B110, + B150, + B300, + B600, + B1200, + B2400, + B4800, + B7200, + B9600, + B19200, + B38400, + B57600, + B115200, + B230400, +}; +#endif + +void +pdc_init() +{ + static int kbd_iodc[IODC_MAXSIZE/sizeof(int)]; + static int cn_iodc[IODC_MAXSIZE/sizeof(int)]; + int err; + + /* XXX make pdc current console */ + cn_tab = &constab[0]; + + /* pdc = (pdcio_t)(long)PAGE0->mem_pdc; */ + pz_kbd = &PAGE0->mem_kbd; + pz_cons = &PAGE0->mem_cons; + + /* XXX should we reset the console/kbd here? + well, /boot did that for us anyway */ + if ((err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ, pdcret, + pz_cons->pz_hpa, IODC_IO, cn_iodc, (long)IODC_MAXSIZE)) < 0 || + (err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, PDC_IODC_READ, pdcret, + pz_kbd->pz_hpa, IODC_IO, kbd_iodc, (long)IODC_MAXSIZE)) < 0) { +#ifdef DEBUG + printf("pdc_init: failed reading IODC (%d)\n", err); +#endif + } + + pdc_cniodc = (iodcio_t)cn_iodc; + pdc_kbdiodc = (iodcio_t)kbd_iodc; + + /* setup the console */ +#if NCOM_GSC > 0 + if (PAGE0->mem_cons.pz_class == PCL_DUPLEX) { + struct pz_device *pzd = &PAGE0->mem_cons; + extern int comdefaultrate; +#ifdef DEBUG + printf("console: class %d flags %b ", + pzd->pz_class, pzd->pz_flags, PZF_BITS); + printf("bc %d/%d/%d/%d/%d/%d ", + pzd->pz_bc[0], pzd->pz_bc[1], pzd->pz_bc[2], + pzd->pz_bc[3], pzd->pz_bc[4], pzd->pz_bc[5]); + printf("mod %x layers %x/%x/%x/%x/%x/%x hpa %x\n", pzd->pz_mod, + pzd->pz_layers[0], pzd->pz_layers[1], pzd->pz_layers[2], + pzd->pz_layers[3], pzd->pz_layers[4], pzd->pz_layers[5], + pzd->pz_hpa); +#endif + conaddr = (u_long)pzd->pz_hpa + IOMOD_DEVOFFSET; + conunit = 0; + + /* compute correct baud rate */ + if (PZL_SPEED(pzd->pz_layers[0]) < + sizeof(pdc_speeds) / sizeof(int)) + comdefaultrate = + pdc_speeds[PZL_SPEED(pzd->pz_layers[0])]; + else + comdefaultrate = B9600; /* XXX */ + } +#endif +} + +int +pdcmatch(parent, cfdata, aux) + struct device *parent; + void *cfdata; + void *aux; +{ + struct cfdata *cf = cfdata; + struct confargs *ca = aux; + + /* there could be only one */ + if (cf->cf_unit > 0 && !strcmp(ca->ca_name, "pdc")) + return 0; + + return 1; +} + +void +pdcattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct pdc_softc *sc = (struct pdc_softc *)self; + + if (!pdc) + pdc_init(); + + printf("\n"); + + timeout_set(&sc->sc_to, pdctimeout, sc); +} + +int +pdcopen(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = minor(dev); + struct pdc_softc *sc; + struct tty *tp; + int s; + int error = 0, setuptimeout = 0; + + if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL) + return ENXIO; + + s = spltty(); + + if (sc->sc_tty) + tp = sc->sc_tty; + else { + tp = sc->sc_tty = ttymalloc(); + } + + tp->t_oproc = pdcstart; + tp->t_param = pdcparam; + tp->t_dev = dev; + if ((tp->t_state & TS_ISOPEN) == 0) { + ttychars(tp); + tp->t_iflag = TTYDEF_IFLAG; + tp->t_oflag = TTYDEF_OFLAG; + tp->t_cflag = TTYDEF_CFLAG|CLOCAL; + tp->t_lflag = TTYDEF_LFLAG; + tp->t_ispeed = tp->t_ospeed = B9600; + ttsetwater(tp); + + setuptimeout = 1; + } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) { + splx(s); + return (EBUSY); + } + tp->t_state |= TS_CARR_ON; + splx(s); + + error = (*linesw[tp->t_line].l_open)(dev, tp); + if (error == 0 && setuptimeout) + pdctimeout(sc); + + return error; +} + +int +pdcclose(dev, flag, mode, p) + dev_t dev; + int flag, mode; + struct proc *p; +{ + int unit = minor(dev); + struct tty *tp; + struct pdc_softc *sc; + + if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL) + return ENXIO; + + tp = sc->sc_tty; + timeout_del(&sc->sc_to); + (*linesw[tp->t_line].l_close)(tp, flag); + ttyclose(tp); + return 0; +} + +int +pdcread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct tty *tp; + struct pdc_softc *sc; + + if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL) + return ENXIO; + + tp = sc->sc_tty; + return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); +} + +int +pdcwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int unit = minor(dev); + struct tty *tp; + struct pdc_softc *sc; + + if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL) + return ENXIO; + + tp = sc->sc_tty; + return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); +} + +int +pdcioctl(dev, cmd, data, flag, p) + dev_t dev; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + int unit = minor(dev); + int error; + struct tty *tp; + struct pdc_softc *sc; + + if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL) + return ENXIO; + + tp = sc->sc_tty; + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (error >= 0) + return error; + error = ttioctl(tp, cmd, data, flag, p); + if (error >= 0) + return error; + + return ENOTTY; +} + +int +pdcparam(tp, t) + struct tty *tp; + struct termios *t; +{ + + return 0; +} + +void +pdcstart(tp) + struct tty *tp; +{ + int s; + + s = spltty(); + if (tp->t_state & (TS_TTSTOP | TS_BUSY)) { + splx(s); + return; + } + 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); + } + tp->t_state |= TS_BUSY; + while (tp->t_outq.c_cc != 0) + pdccnputc(tp->t_dev, getc(&tp->t_outq)); + tp->t_state &= ~TS_BUSY; + splx(s); +} + +int +pdcstop(tp, flag) + struct tty *tp; + int flag; +{ + int s; + + s = spltty(); + if (tp->t_state & TS_BUSY) + if ((tp->t_state & TS_TTSTOP) == 0) + tp->t_state |= TS_FLUSH; + splx(s); + return 0; +} + +void +pdctimeout(v) + void *v; +{ + struct pdc_softc *sc = v; + struct tty *tp = sc->sc_tty; + int c; + + while (pdccnlookc(tp->t_dev, &c)) { + if (tp->t_state & TS_ISOPEN) + (*linesw[tp->t_line].l_rint)(c, tp); + } + timeout_add(&sc->sc_to, 1); +} + +struct tty * +pdctty(dev) + dev_t dev; +{ + int unit = minor(dev); + struct pdc_softc *sc; + + if (unit >= pdc_cd.cd_ndevs || (sc = pdc_cd.cd_devs[unit]) == NULL) + return NULL; + + return sc->sc_tty; +} + +void +pdccnprobe(cn) + struct consdev *cn; +{ + cn->cn_dev = makedev(22,0); + cn->cn_pri = CN_NORMAL; +} + +void +pdccninit(cn) + struct consdev *cn; +{ +#ifdef DEBUG + printf("pdc0: console init\n"); +#endif +} + +int +pdccnlookc(dev, cp) + dev_t dev; + int *cp; +{ + int err, l; + int s = splhigh(); + + err = pdc_call(pdc_kbdiodc, 0, pz_kbd->pz_hpa, IODC_IO_CONSIN, + pz_kbd->pz_spa, pz_kbd->pz_layers, pdcret, 0, pdc_consbuf, + (long)1, (long)0); + + l = pdcret[0]; + *cp = pdc_consbuf[0]; + splx(s); +#ifdef DEBUG + if (err < 0) + printf("pdccnlookc: input error: %d\n", err); +#endif + + return l; +} + +int +pdccngetc(dev) + dev_t dev; +{ + int c; + + if (!pdc) + return 0; + + while(!pdccnlookc(dev, &c)) + ; + + return (c); +} + +void +pdccnputc(dev, c) + dev_t dev; + int c; +{ + register int err; + int s = splhigh(); + + *pdc_consbuf = c; + err = pdc_call(pdc_cniodc, 0, pz_cons->pz_hpa, IODC_IO_CONSOUT, + pz_cons->pz_spa, pz_cons->pz_layers, pdcret, 0, pdc_consbuf, + (long)1, (long)0); + splx(s); + + if (err < 0) { +#ifdef DEBUG + printf("pdccnputc: output error: %d\n", err); +#endif + } +} + +void +pdccnpollc(dev, on) + dev_t dev; + int on; +{ + +} diff --git a/sys/arch/hppa64/dev/pluto.c b/sys/arch/hppa64/dev/pluto.c new file mode 100644 index 00000000000..f69dcc0d7a7 --- /dev/null +++ b/sys/arch/hppa64/dev/pluto.c @@ -0,0 +1,145 @@ +/* $OpenBSD: pluto.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* TODO IOA programming */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/reboot.h> + +#include <machine/iomod.h> +#include <machine/autoconf.h> +#include <machine/bus.h> + +struct pluto_regs { + u_int32_t version; /* 0x000: version */ + u_int32_t pad00; + u_int32_t ctrl; /* 0x008: control register */ +#define PLUTO_CTRL_TOC 0x0001 /* enable toc */ +#define PLUTO_CTRL_COE 0x0002 /* enable coalescing */ +#define PLUTO_CTRL_DIE 0x0004 /* enable dillon */ +#define PLUTO_CTRL_RM 0x0010 /* real mode */ +#define PLUTO_CTRL_NCO 0x0020 /* non-coherent mode */ + u_int32_t pad08; + u_int32_t resv0[(0x200-0x10)/4]; + u_int64_t rope0; /* 0x200: */ + u_int64_t rope1; + u_int64_t rope2; + u_int64_t rope3; + u_int64_t rope4; + u_int64_t rope5; + u_int64_t rope6; + u_int64_t rope7; + u_int32_t resv1[(0x100-0x40)/4]; + u_int64_t ibase; + u_int64_t imask; + u_int64_t pcom; + u_int64_t tconf; + u_int64_t pdir; +} __packed; + +struct pluto_softc { + struct device sc_dv; + + struct pluto_regs volatile *sc_regs; +}; + +int plutomatch(struct device *, void *, void *); +void plutoattach(struct device *, struct device *, void *); + +struct cfattach plut_ca = { + sizeof(struct pluto_softc), plutomatch, plutoattach +}; + +struct cfdriver plut_cd = { + NULL, "plut", DV_DULL +}; + +int +plutomatch(parent, cfdata, aux) + struct device *parent; + void *cfdata; + void *aux; +{ + struct confargs *ca = aux; + /* struct cfdata *cf = cfdata; */ + + if (strcmp(ca->ca_name, "sba")) + return 0; + + return 1; +} + +void +plutoattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct confargs *ca = aux, nca; + struct pluto_softc *sc = (struct pluto_softc *)self; + struct pluto_regs volatile *r; + bus_space_handle_t ioh; + u_int32_t ver; + char buf[16]; + + if (bus_space_map(ca->ca_iot, ca->ca_hpa, ca->ca_hpasz, 0, &ioh)) { + printf(": can't map IO space\n"); + return; + } + sc->sc_regs = r = (void *)bus_space_vaddr(ca->ca_iot, ioh); + + /* r->ctrl = PLUTO_CTRL_RM|PLUTO_CTRL_TOC; */ + + ver = letoh32(r->version); + switch ((ca->ca_type.iodc_model << 4) | + (ca->ca_type.iodc_revision >> 4)) { + case 0x582: + case 0x780: + snprintf(buf, sizeof(buf), "Astro rev %d.%d", + (ver & 7) + 1, (ver >> 3) & 3); + break; + + case 0x803: + case 0x781: + snprintf(buf, sizeof(buf), "Ike rev %d", ver & 0xff); + break; + + case 0x804: + case 0x782: + snprintf(buf, sizeof(buf), "Reo rev %d", ver & 0xff); + break; + + case 0x880: + case 0x784: + snprintf(buf, sizeof(buf), "Pluto rev %d.%d", + (ver >> 4) & 0xf, ver & 0xf); + break; + + default: + snprintf(buf, sizeof(buf), "Fluffy rev 0x%x", ver); + break; + } + + printf(": %s\n", buf); + + nca = *ca; /* clone from us */ + pdc_patscan(self, &nca, 0); +} diff --git a/sys/arch/hppa64/dev/power.c b/sys/arch/hppa64/dev/power.c new file mode 100644 index 00000000000..ce3befc9523 --- /dev/null +++ b/sys/arch/hppa64/dev/power.c @@ -0,0 +1,142 @@ +/* $OpenBSD: power.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/reboot.h> +#include <sys/device.h> +#include <sys/kthread.h> + +#include <machine/reg.h> +#include <machine/pdc.h> +#include <machine/autoconf.h> + +struct power_softc { + struct device sc_dev; + void *sc_ih; + + struct proc *sc_thread; + void (*sc_kicker)(void *); + + int sc_dr_cnt; + paddr_t sc_pwr_reg; + volatile int sc_interrupted; +}; + +int powermatch(struct device *, void *, void *); +void powerattach(struct device *, struct device *, void *); + +struct cfattach power_ca = { + sizeof(struct power_softc), powermatch, powerattach +}; + +struct cfdriver power_cd = { + NULL, "power", DV_DULL +}; + +void power_thread_create(void *v); +void power_thread_reg(void *v); +void power_cold_hook_reg(int); +int power_intr(void *); + +int +powermatch(struct device *parent, void *cfdata, void *aux) +{ + struct cfdata *cf = cfdata; + struct confargs *ca = aux; + + if (cf->cf_unit > 0 && !strcmp(ca->ca_name, "power")) + return (0); + + return (1); +} + +void +powerattach(struct device *parent, struct device *self, void *aux) +{ + struct power_softc *sc = (struct power_softc *)self; + struct confargs *ca = aux; + + if (ca->ca_hpa) { + extern void (*cold_hook)(int); + + sc->sc_pwr_reg = ca->ca_hpa; + cold_hook = power_cold_hook_reg; + sc->sc_kicker = power_thread_reg; + printf("\n"); + } else + printf(": not available\n"); + + if (ca->ca_irq >= 0) + sc->sc_ih = cpu_intr_establish(IPL_CLOCK, ca->ca_irq, + power_intr, sc, sc->sc_dev.dv_xname); + + if (sc->sc_kicker) + kthread_create_deferred(power_thread_create, sc); +} + +int +power_intr(void *v) +{ + struct power_softc *sc = v; + + sc->sc_interrupted = 1; + + return (1); +} + +void +power_thread_create(void *v) +{ + struct power_softc *sc = v; + + if (kthread_create(sc->sc_kicker, sc, &sc->sc_thread, + sc->sc_dev.dv_xname)) + printf("WARNING: failed to create kernel power thread\n"); +} + +void +power_thread_reg(void *v) +{ + struct power_softc *sc = v; + u_int32_t r; + + for (;;) { + __asm __volatile("ldwas 0(%1), %0" + : "=&r" (r) : "r" (sc->sc_pwr_reg)); + + if (!(r & 1)) + boot(RB_POWERDOWN | RB_HALT); + + tsleep(v, PWAIT, "regpower", 10); + } +} + +void +power_cold_hook_reg(int on) +{ + extern struct pdc_power_info pdc_power_info; /* machdep.c */ + int error; + + if ((error = pdc_call((iodcio_t)pdc, 0, PDC_SOFT_POWER, + PDC_SOFT_POWER_ENABLE, &pdc_power_info, + on == HPPA_COLD_HOT))) + printf("power_cold_hook_reg: failed (%d)\n", error); +} diff --git a/sys/arch/hppa64/hppa64/autoconf.c b/sys/arch/hppa64/hppa64/autoconf.c new file mode 100644 index 00000000000..3605b9ec49b --- /dev/null +++ b/sys/arch/hppa64/hppa64/autoconf.c @@ -0,0 +1,843 @@ +/* $OpenBSD: autoconf.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 1998-2005 Michael Shalayeff + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)autoconf.c 8.4 (Berkeley) 10/1/93 + */ + +#include "pci.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/disklabel.h> +#include <sys/conf.h> +#include <sys/reboot.h> +#include <sys/device.h> +#include <sys/timeout.h> + +#include <machine/iomod.h> +#include <machine/autoconf.h> +#include <machine/reg.h> + +#include <dev/cons.h> + +#include <hppa/dev/cpudevs.h> + +#if NPCI > 0 +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#endif + +void setroot(void); +void swapconf(void); +void dumpconf(void); + +int findblkmajor(struct device *dv); +const char *findblkname(int maj); +struct device *parsedisk(char *str, int len, int defpart, dev_t *devp); +struct device *getdisk(char *str, int len, int defpart, dev_t *devp); +int getstr(char *cp, int size); + +void (*cold_hook)(int); /* see below */ + +/* device we booted from */ +struct device *bootdv; + +/* + * LED blinking thing + */ +#ifdef USELEDS +#include <sys/dkstat.h> +#include <sys/kernel.h> + +struct timeout heartbeat_tmo; +void heartbeat(void *); +#endif + +#include "cd.h" +#include "sd.h" +#include "st.h" +#if NCD > 0 || NSD > 0 || NST > 0 +#include <scsi/scsi_all.h> +#include <scsi/scsiconf.h> +#endif + +/* + * cpu_configure: + * called at boot time, configure all devices on system + */ +void +cpu_configure(void) +{ + struct confargs ca; + + splhigh(); + bzero(&ca, sizeof(ca)); + if (config_rootfound("mainbus", &ca) == NULL) + panic("no mainbus found"); + + mtctl(0xffffffffffffffffULL, CR_EIEM); + spl0(); + + setroot(); + swapconf(); + dumpconf(); + if (cold_hook) + (*cold_hook)(HPPA_COLD_HOT); + +#ifdef USELEDS + timeout_set(&heartbeat_tmo, heartbeat, NULL); + heartbeat(NULL); +#endif + cold = 0; +} + +#ifdef USELEDS +/* + * turn the heartbeat alive. + * right thing would be to pass counter to each subsequent timeout + * as an argument to heartbeat() incrementing every turn, + * i.e. avoiding the static hbcnt, but doing timeout_set() on each + * timeout_add() sounds ugly, guts of struct timeout looks ugly + * to ponder in even more. + */ +void +heartbeat(v) + void *v; +{ + static u_int hbcnt = 0, ocp_total, ocp_idle; + int toggle, cp_mask, cp_total, cp_idle; + + timeout_add(&heartbeat_tmo, hz / 16); + + cp_idle = cp_time[CP_IDLE]; + cp_total = cp_time[CP_USER] + cp_time[CP_NICE] + cp_time[CP_SYS] + + cp_time[CP_INTR] + cp_time[CP_IDLE]; + if (cp_total == ocp_total) + cp_total = ocp_total + 1; + if (cp_idle == ocp_idle) + cp_idle = ocp_idle + 1; + cp_mask = 0xf0 >> (cp_idle - ocp_idle) * 4 / (cp_total - ocp_total); + cp_mask &= 0xf0; + ocp_total = cp_total; + ocp_idle = cp_idle; + /* + * do this: + * + * |~| |~| + * _| |_| |_,_,_,_ + * 0 1 2 3 4 6 7 + */ + toggle = 0; + if (hbcnt++ < 8 && hbcnt & 1) + toggle = PALED_HEARTBEAT; + hbcnt &= 15; + ledctl(cp_mask, + (~cp_mask & 0xf0) | PALED_NETRCV | PALED_NETSND | PALED_DISK, + toggle); +} +#endif + +/* + * Configure swap space and related parameters. + */ +void +swapconf(void) +{ + struct swdevt *swp; + int nblks, maj; + + for (swp = swdevt; swp->sw_dev != NODEV; swp++) { + maj = major(swp->sw_dev); + if (maj > nblkdev) + break; + if (bdevsw[maj].d_psize) { + nblks = (*bdevsw[maj].d_psize)(swp->sw_dev); + if (nblks != -1 && + (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) + swp->sw_nblks = nblks; + swp->sw_nblks = ctod(dtoc(swp->sw_nblks)); + } + } +} + +/* + * This is called by configure to set dumplo and dumpsize. + * Dumps always skip the first CLBYTES of disk space + * in case there might be a disk label stored there. + * If there is extra space, put dump at the end to + * reduce the chance that swapping trashes it. + */ +void +dumpconf(void) +{ + extern int dumpsize; + int nblks, dumpblks; /* size of dump area */ + int maj; + + if (dumpdev == NODEV) + goto bad; + maj = major(dumpdev); + if (maj < 0 || maj >= nblkdev) + panic("dumpconf: bad dumpdev=0x%x", dumpdev); + if (bdevsw[maj].d_psize == NULL) + goto bad; + nblks = (*bdevsw[maj].d_psize)(dumpdev); + if (nblks <= ctod(1)) + goto bad; + dumpblks = cpu_dumpsize(); + if (dumpblks < 0) + goto bad; + dumpblks += ctod(physmem); + + /* If dump won't fit (incl. room for possible label), punt. */ + if (dumpblks > (nblks - ctod(1))) + goto bad; + + /* Put dump at end of partition */ + dumplo = nblks - dumpblks; + + /* dumpsize is in page units, and doesn't include headers. */ + dumpsize = physmem; + return; + +bad: + dumpsize = 0; + return; +} + +const struct nam2blk { + char name[4]; + int maj; +} nam2blk[] = { + { "rd", 3 }, + { "sd", 4 }, + { "st", 5 }, + { "cd", 6 }, +#if 0 + { "wd", ? }, + { "fd", 7 }, +#endif +}; + +#ifdef RAMDISK_HOOKS +struct device fakerdrootdev = { DV_DISK, {}, NULL, 0, "rd0", NULL }; +#endif + +int +findblkmajor(dv) + struct device *dv; +{ + char *name = dv->dv_xname; + int i; + + for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); ++i) + if (!strncmp(name, nam2blk[i].name, strlen(nam2blk[0].name))) + return (nam2blk[i].maj); + return (-1); +} + +const char * +findblkname(maj) + int maj; +{ + int i; + + for (i = 0; i < sizeof(nam2blk) / sizeof(nam2blk[0]); ++i) + if (maj == nam2blk[i].maj) + return (nam2blk[i].name); + return (NULL); +} + +struct device * +getdisk(str, len, defpart, devp) + char *str; + int len, defpart; + dev_t *devp; +{ + struct device *dv; + + if ((dv = parsedisk(str, len, defpart, devp)) == NULL) { + printf("use one of:"); +#ifdef RAMDISK_HOOKS + printf(" %s[a-p]", fakerdrootdev.dv_xname); +#endif + for (dv = alldevs.tqh_first; dv != NULL; + dv = dv->dv_list.tqe_next) { + if (dv->dv_class == DV_DISK) + printf(" %s[a-p]", dv->dv_xname); +#ifdef NFSCLIENT + if (dv->dv_class == DV_IFNET) + printf(" %s", dv->dv_xname); +#endif + } + printf(" halt\n"); + } + return (dv); +} + +struct device * +parsedisk(str, len, defpart, devp) + char *str; + int len, defpart; + dev_t *devp; +{ + struct device *dv; + char *cp, c; + int majdev, part; + + if (len == 0) + return (NULL); + + if (len == 4 && !strcmp(str, "halt")) + boot(RB_HALT); + + cp = str + len - 1; + c = *cp; + if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) { + part = c - 'a'; + *cp = '\0'; + } else + part = defpart; + +#ifdef RAMDISK_HOOKS + if (strcmp(str, fakerdrootdev.dv_xname) == 0) { + dv = &fakerdrootdev; + goto gotdisk; + } +#endif + for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) { + if (dv->dv_class == DV_DISK && + strcmp(str, dv->dv_xname) == 0) { +#ifdef RAMDISK_HOOKS +gotdisk: +#endif + majdev = findblkmajor(dv); + if (majdev < 0) + panic("parsedisk"); + *devp = MAKEDISKDEV(majdev, dv->dv_unit, part); + break; + } +#ifdef NFSCLIENT + if (dv->dv_class == DV_IFNET && + strcmp(str, dv->dv_xname) == 0) { + *devp = NODEV; + break; + } +#endif + } + + *cp = c; + return (dv); +} + +void +print_devpath(const char *label, struct pz_device *pz) +{ + int i; + + printf("%s: ", label); + + for (i = 0; i < 6; i++) + if (pz->pz_bc[i] >= 0) + printf("%d/", pz->pz_bc[i]); + + printf("%d.%x", pz->pz_mod, pz->pz_layers[0]); + for (i = 1; i < 6 && pz->pz_layers[i]; i++) + printf(".%x", pz->pz_layers[i]); + + printf(" class=%d flags=%b hpa=%p spa=%p io=%p\n", pz->pz_class, + pz->pz_flags, PZF_BITS, pz->pz_hpa, pz->pz_spa, pz->pz_iodc_io); +} + +/* + * Attempt to find the device from which we were booted. + * If we can do so, and not instructed not to do so, + * change rootdev to correspond to the load device. + * + * XXX Actually, swap and root must be on the same type of device, + * (ie. DV_DISK or DV_IFNET) because of how (*mountroot) is written. + * That should be fixed. + */ +void +setroot(void) +{ + struct swdevt *swp; + struct device *dv; + int len, majdev, part; + dev_t nrootdev, nswapdev = NODEV; + char buf[128]; + dev_t temp; + const char *rootdevname; + struct device *rootdv, *swapdv; +#ifdef NFSCLIENT + extern char *nfsbootdevname; +#endif + +#ifdef RAMDISK_HOOKS + bootdv = &fakerdrootdev; +#endif + part = 0; + + print_devpath("boot path", &PAGE0->mem_boot); + + /* + * If 'swap generic' and we couldn't determine boot device, + * ask the user. + */ + if (mountroot == NULL && bootdv == NULL) + boothowto |= RB_ASKNAME; + + if (boothowto & RB_ASKNAME) { + for (;;) { + printf("root device? "); + if (bootdv != NULL) { + printf(" (default %s", bootdv->dv_xname); + if (bootdv->dv_class == DV_DISK) + printf("%c", part + 'a'); + printf(")"); + } + printf(": "); + len = getstr(buf, sizeof(buf)); + if (len == 0 && bootdv != NULL) { + strlcpy(buf, bootdv->dv_xname, sizeof buf); + len = strlen(buf); + } + if (len > 0 && buf[len - 1] == '*') { + buf[--len] = '\0'; + dv = getdisk(buf, len, 1, &nrootdev); + if (dv != NULL) { + rootdv = swapdv = dv; + nswapdev = nrootdev; + goto gotswap; + } + } + dv = getdisk(buf, len, part, &nrootdev); + if (dv != NULL) { + rootdv = dv; + break; + } + } + + /* + * because swap must be on same device type as root, for + * network devices this is easy. + */ + if (rootdv->dv_class == DV_IFNET) { + swapdv = NULL; + goto gotswap; + } + for (;;) { + printf("swap device (default %s", rootdv->dv_xname); + if (rootdv->dv_class == DV_DISK) + printf("b"); + printf("): "); + len = getstr(buf, sizeof(buf)); + if (len == 0) { + switch (rootdv->dv_class) { + case DV_IFNET: + nswapdev = NODEV; + break; + case DV_DISK: + nswapdev = MAKEDISKDEV(major(nrootdev), + DISKUNIT(nrootdev), 1); + break; + case DV_TAPE: + case DV_TTY: + case DV_DULL: + case DV_CPU: + break; + } + swapdv = rootdv; + break; + } + dv = getdisk(buf, len, 1, &nswapdev); + if (dv) { + if (dv->dv_class == DV_IFNET) + nswapdev = NODEV; + swapdv = dv; + break; + } + } +gotswap: + majdev = major(nrootdev); + rootdev = nrootdev; + dumpdev = nswapdev; + swdevt[0].sw_dev = nswapdev; + swdevt[1].sw_dev = NODEV; + } else if (mountroot == NULL) { + + /* + * `swap generic': Use the device the ROM told us to use. + */ + majdev = findblkmajor(bootdv); + if (majdev >= 0) { + /* + * Root and swap are on a disk. + * Assume swap is on partition b. + */ + rootdv = swapdv = bootdv; + rootdev = MAKEDISKDEV(majdev, bootdv->dv_unit, part); + nswapdev = dumpdev = + MAKEDISKDEV(majdev, bootdv->dv_unit, 1); + } else { + /* + * Root and swap are on a net. + */ + rootdv = swapdv = bootdv; + nswapdev = dumpdev = NODEV; + } + swdevt[0].sw_dev = nswapdev; + swdevt[1].sw_dev = NODEV; + } else { + /* + * `root DEV swap DEV': honour rootdev/swdevt. + * rootdev/swdevt/mountroot already properly set. + */ + + rootdevname = findblkname(major(rootdev)); + return; + } + + switch (rootdv->dv_class) { +#ifdef NFSCLIENT + case DV_IFNET: + mountroot = nfs_mountroot; + nfsbootdevname = rootdv->dv_xname; + return; +#endif +#ifndef DISKLESS + case DV_DISK: + mountroot = dk_mountroot; + printf("root on %s%c", rootdv->dv_xname, + DISKPART(rootdev) + 'a'); + if (nswapdev != NODEV) + printf(" swap on %s%c", swapdv->dv_xname, + DISKPART(nswapdev) + 'a'); + printf("\n"); + break; +#endif + default: + printf("can't figure root, hope your kernel is right\n"); + return; + } + + /* + * Make the swap partition on the root drive the primary swap. + */ + temp = NODEV; + for (swp = swdevt; swp->sw_dev != NODEV; swp++) { + if (majdev == major(swp->sw_dev) && + DISKUNIT(rootdev) == DISKUNIT(swp->sw_dev)) { + temp = swdevt[0].sw_dev; + swdevt[0].sw_dev = swp->sw_dev; + swp->sw_dev = temp; + break; + } + } + if (swp->sw_dev == NODEV) + return; + + /* + * If dumpdev was the same as the old primary swap device, + * move it to the new primary swap device. + */ + if (temp == dumpdev) + dumpdev = swdevt[0].sw_dev; +} + +int +getstr(cp, size) + char *cp; + int size; +{ + char *lp; + int c; + int len; + + lp = cp; + len = 0; + for (;;) { + c = cngetc(); + switch (c) { + case '\n': + case '\r': + printf("\n"); + *lp++ = '\0'; + return (len); + case '\b': + case '\177': + case '#': + if (len) { + --len; + --lp; + printf("\b \b"); + } + continue; + case '@': + case 'u'&037: + len = 0; + lp = cp; + printf("\n"); + continue; + default: + if (len + 1 >= size || c < ' ') { + printf("\007"); + continue; + } + printf("%c", c); + ++len; + *lp++ = c; + } + } +} + +struct pdc_iodc_read pdc_iodc_read PDC_ALIGNMENT; +struct pdc_pat_cell_id pdc_pat_cell_id PDC_ALIGNMENT; +struct pdc_pat_cell_module pdc_pat_cell_module PDC_ALIGNMENT; +const char *pat_names[] = { + "central", + "cpu", + "memory", + "sba", + "lba", + "pbc", + "cfc", + "fabric" +}; + +void +pdc_patscan(struct device *self, struct confargs *ca, int mod) +{ + u_long rv[16]; + int i, err; + + if (pdc_call((iodcio_t)pdc, 0, PDC_PAT_CELL, PDC_PAT_CELL_GETID, + &pdc_pat_cell_id, 0)) { + printf("pat_fetch: cannot fetch cell number\n"); + return; + } + + i = 0; + for (i = 0; !pdc_call((iodcio_t)pdc, 0, PDC_PAT_CELL, + PDC_PAT_CELL_MODULE, rv, pdc_pat_cell_id.loc, i, + PDC_PAT_PAVIEW, &pdc_pat_cell_module, 0); i++) { + if (autoconf_verbose) + printf(">> chpa %lx info %lx loc %lx " + "dp %d/%d/%d/%d/%d/%d.%d\n", + pdc_pat_cell_module.chpa, pdc_pat_cell_module.info, + pdc_pat_cell_module.loc, + pdc_pat_cell_module.dp.dp_bc[0], + pdc_pat_cell_module.dp.dp_bc[1], + pdc_pat_cell_module.dp.dp_bc[2], + pdc_pat_cell_module.dp.dp_bc[3], + pdc_pat_cell_module.dp.dp_bc[4], + pdc_pat_cell_module.dp.dp_bc[5], + pdc_pat_cell_module.dp.dp_mod); + + if (pdc_pat_cell_module.dp.dp_bc[5] == mod) { + struct confargs nca; + int t; + + t = PDC_PAT_CELL_MODTYPE(pdc_pat_cell_module.info); + if (t >= sizeof(pat_names)/sizeof(pat_names[0])) + continue; + + nca = *ca; + nca.ca_name = pat_names[t]; + nca.ca_hpa = pdc_pat_cell_module.chpa & + ~(u_long)PAGE_MASK; + nca.ca_hpasz = + PDC_PAT_CELL_MODSIZE(pdc_pat_cell_module.info); + + err = pdc_call((iodcio_t)pdc, 0, PDC_IODC, + PDC_IODC_READ, &pdc_iodc_read, nca.ca_hpa, + IODC_DATA, &nca.ca_type, sizeof(nca.ca_type)); + if (err < 0 || pdc_iodc_read.size < 8) { + if (autoconf_verbose) + printf(">> iodc_data error %d\n", err); + bzero(&nca.ca_type, sizeof(nca.ca_type)); + } + if (autoconf_verbose) { + u_int *p = (u_int *)&nca.ca_type; + printf(">> iodc_data 0x%08x 0x%08x\n", + p[0], p[1]); + } + + config_found(self, &nca, mbprint); + } + } +} + +const struct hppa_mod_info hppa_knownmods[] = { +#include <arch/hppa/dev/cpudevs_data.h> +}; + +const char * +hppa_mod_info(type, sv) + int type, sv; +{ + const struct hppa_mod_info *mi; + static char fakeid[32]; + + for (mi = hppa_knownmods; mi->mi_type >= 0 && + (mi->mi_type != type || mi->mi_sv != sv); mi++); + + if (mi->mi_type < 0) { + snprintf(fakeid, sizeof fakeid, "type %x, sv %x", type, sv); + return fakeid; + } else + return mi->mi_name; +} + +void +device_register(struct device *dev, void *aux) +{ +#if NPCI > 0 + extern struct cfdriver pci_cd; +#endif + struct confargs *ca = aux; + char *basename; + static struct device *elder = NULL; + + if (bootdv != NULL) + return; /* We already have a winner */ + +#if NPCI > 0 + if (dev->dv_parent && + dev->dv_parent->dv_cfdata->cf_driver == &pci_cd) { + struct pci_attach_args *pa = aux; + pcireg_t addr; + int reg; + + for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) { + addr = pci_conf_read(pa->pa_pc, pa->pa_tag, reg); + if (PCI_MAPREG_TYPE(addr) == PCI_MAPREG_TYPE_IO) + addr = PCI_MAPREG_IO_ADDR(addr); + else + addr = PCI_MAPREG_MEM_ADDR(addr); + + if (addr == (pcireg_t)(u_long)PAGE0->mem_boot.pz_hpa) { + elder = dev; + break; + } + } + } else +#endif + if (ca->ca_hpa == (hppa_hpa_t)PAGE0->mem_boot.pz_hpa) { + /* + * If hpa matches, the only thing we know is that the + * booted device is either this one or one of its children. + * And the children will not necessarily have the correct + * hpa value. + * Save this elder for now. + */ + elder = dev; + } else if (elder == NULL) { + return; /* not the device we booted from */ + } + + /* + * Unfortunately, we can not match on pz_class vs dv_class on + * older snakes netbooting using the rbootd protocol. + * In this case, we'll end up with pz_class == PCL_RANDOM... + * Instead, trust the device class from what the kernel attached + * now... + */ + switch (dev->dv_class) { + case DV_IFNET: + /* + * Netboot is the top elder + */ + if (elder == dev) { + bootdv = dev; + } + return; + case DV_DISK: + if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_RANDOM) + return; + break; + case DV_TAPE: + if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_SEQU) + return; + break; + default: + /* No idea what we were booted from, but better ask the user */ + return; + } + + /* + * If control goes here, we are booted from a block device and we + * matched a block device. + */ + basename = dev->dv_cfdata->cf_driver->cd_name; + + /* TODO wd detect */ + + /* + * We only grok SCSI boot currently. Match on proper device hierarchy, + * name and unit/lun values. + */ +#if NCD > 0 || NSD > 0 || NST > 0 + if (strcmp(basename, "sd") == 0 || strcmp(basename, "cd") == 0 || + strcmp(basename, "st") == 0) { + struct scsibus_attach_args *sa = aux; + struct scsi_link *sl = sa->sa_sc_link; + + /* + * sd/st/cd is attached to scsibus which is attached to + * the controller. Hence the grandparent here should be + * the elder. + */ + if (dev->dv_parent == NULL || + dev->dv_parent->dv_parent != elder) { + return; + } + + /* + * And now check for proper target and lun values + */ + if (sl->target == PAGE0->mem_boot.pz_layers[0] && + sl->lun == PAGE0->mem_boot.pz_layers[1]) { + bootdv = dev; + } + } +#endif +} diff --git a/sys/arch/hppa64/hppa64/conf.c b/sys/arch/hppa64/hppa64/conf.c new file mode 100644 index 00000000000..f58c4df177f --- /dev/null +++ b/sys/arch/hppa64/hppa64/conf.c @@ -0,0 +1,284 @@ +/* $OpenBSD: conf.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)conf.c 7.9 (Berkeley) 5/28/91 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/vnode.h> + +#include <machine/conf.h> + +#include "ccd.h" +#include "vnd.h" +#include "rd.h" +#include "sd.h" +#include "st.h" +#include "cd.h" +#include "ch.h" +#include "ss.h" +#include "ses.h" +#include "uk.h" +#include "wd.h" +bdev_decl(wd); +cdev_decl(wd); +#if 0 +#include "fd.h" +#else +#define NFD 0 +#endif +bdev_decl(fd); +cdev_decl(fd); + +struct bdevsw bdevsw[] = +{ + bdev_swap_init(1,sw), /* 0: swap pseudo-device */ + bdev_disk_init(NCCD,ccd), /* 1: concatenated disk driver */ + bdev_disk_init(NVND,vnd), /* 2: vnode disk driver */ + bdev_disk_init(NRD,rd), /* 3: RAM disk */ + bdev_disk_init(NSD,sd), /* 4: SCSI disk */ + bdev_tape_init(NST,st), /* 5: SCSI tape */ + bdev_disk_init(NCD,cd), /* 6: SCSI CD-ROM */ + bdev_disk_init(NFD,fd), /* 7: floppy drive */ + bdev_disk_init(NWD,wd), /* 8: ST506 drive */ + /* 9: */ + bdev_lkm_dummy(), + bdev_lkm_dummy(), + bdev_lkm_dummy(), + bdev_lkm_dummy(), + bdev_lkm_dummy(), + bdev_lkm_dummy(), +}; +int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]); + +/* open, close, read, write, ioctl, tty, mmap */ +#define cdev_wscons_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ + dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ + dev_init(c,n,tty), ttpoll, dev_init(c,n,mmap) } + +#include "audio.h" +#include "pty.h" +#include "wsdisplay.h" +#include "wskbd.h" +#include "wsmouse.h" +#include "wsmux.h" +#ifdef XFS +#include <xfs/nxfs.h> +cdev_decl(xfs_dev); +#endif + +#include "inet.h" +#include "bpfilter.h" +#include "tun.h" + +#include "ksyms.h" + +#include "lpt.h" +cdev_decl(lpt); + +#include "com.h" +cdev_decl(com); + +#include "pf.h" + +#include "systrace.h" + +#ifdef USER_PCICONF +#include "pci.h" +cdev_decl(pci); +#endif + +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_disk_init(NCCD,ccd), /* 7: concatenated disk */ + cdev_disk_init(NVND,vnd), /* 8: vnode disk driver */ + cdev_disk_init(NRD,rd), /* 9: RAM disk */ + cdev_disk_init(NSD,sd), /* 10: SCSI disk */ + cdev_tape_init(NST,st), /* 11: SCSI tape */ + cdev_disk_init(NCD,cd), /* 12: SCSI cd-rom */ + cdev_ch_init(NCH,ch), /* 13: SCSI changer */ + cdev_ss_init(NSS,ss), /* 14: SCSI scanner */ + cdev_uk_init(NUK,uk), /* 15: SCSI unknown */ + cdev_fd_init(1,filedesc), /* 16: file descriptor pseudo-device */ + cdev_bpftun_init(NBPFILTER,bpf),/* 17: Berkeley packet filter */ + cdev_bpftun_init(NTUN,tun), /* 18: network tunnel */ + cdev_lkm_init(NLKM,lkm), /* 19: loadable module driver */ + cdev_random_init(1,random), /* 20: random generator */ + cdev_pf_init(NPF,pf), /* 21: packet filter */ + cdev_tty_init(1,pdc), /* 22: PDC device */ + cdev_tty_init(NCOM,com), /* 23: RS232 */ + cdev_disk_init(NFD,fd), /* 24: floppy drive */ + cdev_ksyms_init(NKSYMS,ksyms), /* 25: Kernel symbols device */ + cdev_lpt_init(NLPT,lpt), /* 26: parallel printer */ + cdev_wsdisplay_init(NWSDISPLAY, /* 27: workstation console */ + wsdisplay), + cdev_mouse_init(NWSKBD,wskbd), /* 28: keyboards */ + cdev_mouse_init(NWSMOUSE,wsmouse), /* 29: mice */ + cdev_mouse_init(NWSMUX,wsmux), /* 30: mux */ +#ifdef USER_PCICONF + cdev_pci_init(NPCI,pci), /* 31: PCI user */ +#else + cdev_notdef(), +#endif +#ifdef XFS + cdev_xfs_init(NXFS,xfs_dev), /* 32: xfs communication device */ +#else + cdev_notdef(), +#endif + cdev_notdef(), /* 33: ALTQ (deprecated) */ + cdev_systrace_init(NSYSTRACE,systrace), /* 34: system call tracing */ + cdev_audio_init(NAUDIO,audio), /* 35: /dev/audio */ + cdev_crypto_init(NCRYPTO,crypto), /* 36: /dev/crypto */ + cdev_ses_init(NSES,ses), /* 37: SCSI SES/SAF-TE */ + cdev_ptm_init(NPTY,ptm), /* 38: pseudo-tty ptm device */ + cdev_disk_init(NWD,wd), /* 39: ST506 disk */ + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), + cdev_lkm_dummy(), +}; +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(0, 0); + +int chrtoblktbl[] = { + /* XXXX This needs to be dynamic for LKMs. */ + /*VCHR*/ /*VBLK*/ + /* 0 */ NODEV, + /* 1 */ NODEV, + /* 2 */ NODEV, + /* 3 */ NODEV, + /* 4 */ NODEV, + /* 5 */ NODEV, + /* 6 */ NODEV, + /* 7 */ 1, + /* 8 */ 2, + /* 9 */ 3, + /* 10 */ 4, + /* 11 */ 5, + /* 12 */ 6, + /* 13 */ NODEV, + /* 14 */ NODEV, + /* 15 */ NODEV, + /* 16 */ NODEV, + /* 17 */ NODEV, + /* 18 */ NODEV, + /* 19 */ NODEV, + /* 20 */ NODEV, + /* 21 */ NODEV, + /* 22 */ NODEV, + /* 23 */ NODEV, + /* 24 */ 7, + /* 25 */ NODEV, + /* 26 */ NODEV, + /* 27 */ NODEV, + /* 28 */ NODEV, + /* 29 */ NODEV, + /* 30 */ NODEV, + /* 31 */ NODEV, + /* 32 */ NODEV, + /* 33 */ NODEV, + /* 34 */ NODEV, + /* 35 */ NODEV, + /* 36 */ NODEV, + /* 37 */ NODEV, + /* 38 */ NODEV, + /* 39 */ NODEV, +}; +int nchrtoblktbl = sizeof(chrtoblktbl) / sizeof(chrtoblktbl[0]); + +/* + * Returns true if dev is /dev/zero. + */ +int +iszerodev(dev) + dev_t dev; +{ + return (major(dev) == mem_no && minor(dev) == 12); +} + +dev_t +getnulldev() +{ + return makedev(mem_no, 2); +} + +/* + * Returns true if dev is /dev/mem or /dev/kmem. + */ +int +iskmemdev(dev) + dev_t dev; +{ + return (major(dev) == mem_no && minor(dev) < 2); +} + +#include <dev/cons.h> + +cons_decl(pdc); +cons_decl(ws); +cons_decl(com); + +struct consdev constab[] = { + cons_init(pdc), /* XXX you'd better leave it here for pdc.c */ +#if NWSDISPLAY1 > 0 + cons_init(ws), +#endif +#if NCOM1 > 0 + cons_init(com), +#endif + { 0 } +}; + diff --git a/sys/arch/hppa64/hppa64/db_disasm.c b/sys/arch/hppa64/hppa64/db_disasm.c new file mode 100644 index 00000000000..c1e1fe3434b --- /dev/null +++ b/sys/arch/hppa64/hppa64/db_disasm.c @@ -0,0 +1,2353 @@ +/* $OpenBSD: db_disasm.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* TODO parse 64bit insns or rewrite */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * (c) Copyright 1992 HEWLETT-PACKARD COMPANY + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Hewlett-Packard Company not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Hewlett-Packard Company makes no representations about the + * suitability of this software for any purpose. + */ + +/* + * unasm.c -- HP_PA Instruction Printer + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <machine/db_machdep.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_output.h> +#include <ddb/db_interface.h> + + +/* IMPORTANT NOTE: + * All modules using this header may assume that the datatype "int" is a + * 32-bit (or > 32-bit) signed quantity. + */ + + +/* Spectrum Architecturally Defined Datatypes */ +struct doubleword { + int wd0; + int wd1; +}; + +struct quadword { + struct doubleword d0; + struct doubleword d1; +}; + + /* datatypes for halfword and byte fields of a word are defined + * in ssBits.h */ + +/* Memory addressing datatypes */ +typedef unsigned int SID, /* range [0..MAXSID] */ + PGID, /* range [0..MAXPGID] */ + OFS, /* range [0..MAXINT] */ + REALADR; /* range [0..MAXINT] */ + + +/* data sizes */ +enum datasize { Byte, Halfword, Word, Doubleword, Quadword, Variable }; + +/* Miscellaneous datatypes */ +typedef unsigned int FLAGS; + +/* struct for entry in unwind table */ +struct ute { + int word1; + int word2; + int word3; + int word4; +}; +/* + * Header: /n/schirf/u/baford/CVS/mach4-parisc/kernel_unused/parisc/kdb/unasm.c,v 1.5 1994/07/21 22:32:05 mike Exp + * + * Spectrum Instruction Set Condition Completer Bit Assignments + * Dan Magenheimer - 6/14/82 + * Terrence Miller - 6/21/82 + * Computer Research Center, Hewlett-Packard Labs + * + * (c) copyright 1982 + * (p) protected 1982 + * The Hewlett-Packard Company + * Hewlett-Packard Laboratories + * Computer Research Center + * Palo Alto, California + * + * *** HP Company Confidential *** + * + * Log: unasm.c,v + * Revision 1.5 1994/07/21 22:32:05 mike + * official HP copyright notice + * + * Revision 1.4 1992/07/08 12:19:52 dalton + * Checkin before split to 1.0.4 release (by LBS). + * + * Revision 1.3 92/06/06 16:16:45 dalton + * *** empty log message *** + * + * Revision 1.2 92/06/06 15:42:28 dalton + * Changed include to be a path relative to hp800. + * + * Revision 1.1 92/06/06 14:05:33 dalton + * Initial revision + * + * Revision 1.2 91/04/14 20:29:49 osfrcs + * Initial version. + * [91/03/30 09:20:34 brezak] + * + * Revision 1.1.2.2 91/04/02 10:42:50 brezak + * Initial version. + * [91/03/30 09:20:34 brezak] + * + * Revision 1.1.1.2 91/03/30 09:20:34 brezak + * Initial version. + * + * Revision 1.1 88/07/11 14:05:15 14:05:15 ren (Bob Naas) + * Initial revision + * + * Revision 5.2 87/07/02 14:45:57 14:45:57 kent (Kent McMullen) + * added constants to support addDasm and addDCond added to ssDID.c + * + * Revision 5.1 87/02/27 11:12:08 11:12:08 kent (Kent McMullen) + * update all src to 5.1 + * + * Revision 5.0 87/02/18 16:31:15 16:31:15 kent (Kent McMullen) + * update all revision numbers to 5.0 for release + * + * Revision 1.1 86/07/15 08:34:55 08:34:55 kent (Kent McMullen) + * Initial revision + * + * Revision 4.1 83/10/25 17:01:22 17:01:22 djm (Daniel J Magenheimer) + * First release for ACD v4 + * + * Revision 3.0 83/06/13 10:22:59 djm (Daniel Magenheimer) + * First release for distribution + * + * + */ + + +/* Arithmetic/Logical Conditions */ +#define NEV 0x0 +#define EQZ 0x2 +#define LT 0x4 +#define LE 0x6 +#define LLT 0x8 +#define NUV 0x8 +#define LLE 0xA +#define ZNV 0xA +#define SV 0xC +#define OD 0xE +#define TR 0x1 +#define NEQZ 0x3 +#define GE 0x5 +#define GT 0x7 +#define LGE 0x9 +#define UV 0x9 +#define LGT 0xB +#define VNZ 0xB +#define NSV 0xD +#define EV 0xF + +/* unit conditions */ +#define SBZ 0x4 +#define SHZ 0x6 +#define SDC 0x8 +#define SBC 0xC +#define SHC 0xE +#define NBZ 0x5 +#define NHZ 0x7 +#define NDC 0x9 +#define NBC 0xD +#define NHC 0xF + +/*field conditions */ +#define XEQ 0x1 +#define XLT 0x2 +#define XOD 0x3 +#define XTR 0x4 +#define XNE 0x5 +#define XGE 0x6 +#define XEV 0x7 + + + +/* + * These macros are designed to be portable to all machines that have + * a wordsize greater than or equal to 32 bits that support the portable + * C compiler and the standard C preprocessor. Wordsize (default 32) + * and bitfield assignment (default left-to-right, unlike VAX, PDP-11) + * should be predefined using the constants HOSTWDSZ and BITFRL and + * the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20). + * Note that the macro arguments assume that the integer being referenced + * is a 32-bit integer (right-justified on the 20) and that bit 0 is the + * most significant bit. + */ + +#ifndef HOSTWDSZ +#define HOSTWDSZ 32 +#endif + +#ifdef vax +#ifndef BITFLR +#define BITFRL +#endif +#else +#define BITFLR +#endif + +/*########################### Macros ######################################*/ + +/*--------------------------------------------------------------------------- + * DeclareBitfield$Reference - Declare a structure to be used to reference + * a specified bitfield within an integer (using BitfR, see below). + * The argument "n" must be an identifier name not used elsewhere in the + * program , "s" and "l" must (alas!) be constants. (Suggestion: if + * "s" == 2 and "l" == 8, use _b28 for "n".) The name "BITFLR" should + * be pre-defined if the compiler assigns bitfields from left-to-right. + * The resultant macro expansion defines a stucture in which the bit field + * starting at position "s" with length "l" may be referenced by accessing + * member "n". [Note: The leftmost bits in a 36-bit word may be accessed + * by specifying -4 <= s < 0 on the DEC-20.] + *---------------------------------------------------------------------------*/ + +#ifdef BITFRL +#define DeclBitfR(s,l,n) struct n { int:(HOSTWDSZ-(s)-(l)); unsigned n:l;}; +#else +#define DeclBitfR(s,l,n) struct n { int:((s)+(HOSTWDSZ-32)); unsigned n:l;}; +#endif + +/*--------------------------------------------------------------------------- + * Bitfield$Reference - Reference a specified bitfield within an integer. + * The argument "i" must be an addressable variable (i.e., not a register + * variable or an expression... but see BitfX below), "n" must be an + * identifier name declared in a DeclBitfR invocation. The resultant + * macro expansion references the bit field in "i" described by the + * DeclBitfR invocation with the same name ("n"). BitfR may be used as + * an lvalue or an rvalue. (i.e., either side of an assignment statement) + * The "s" and "l" arguments are historical and are now unused. (They + * correspond to the "s" and "l" arguments in DeclBitfR) + * Translates to a single instruction on both the VAX and the DEC-20. + *---------------------------------------------------------------------------*/ +#define BitfR(i,s,l,n) (((struct n *)&i)->n) + +/*--------------------------------------------------------------------------- + * Bitfield$eXtract - Extract the specified field from an integer. Arguments + * are the same as for BitfR (except no "n"), however both "s" and "l" need + * no longer be constants. May only be used as an rvalue. Translates to + * two instructions on the VAX, three on the DEC-20. + *---------------------------------------------------------------------------*/ + +#define BitfX(i,s,l) (((i) >> (32-(s)-(l))) & ((1 << (l)) - 1)) + + +/*--------------------------------------------------------------------------- + * Mask$32bits - Mask the low order 32 bits of passed word. No-op on 32 + * bit machines. + *---------------------------------------------------------------------------*/ + +#if HOSTWDSZ > 32 +#define Mask32(x) ((x) & 0xffffffff) +#else +#define Mask32(x) (x) +#endif + + +/*--------------------------------------------------------------------------- + * SignExtend$32bits - Force the high-order bits in machines with wordsize + * longer than 32 to match bit 0. + *---------------------------------------------------------------------------*/ + +#if HOSTWDSZ > 32 +#define SignEx32(x) (((x) & 0x80000000) ? ((x) | ((unsigned)-1 << 32)) \ + : Mask32(x)) +#else +#define SignEx32(x) (x) +#endif + +/**************************/ +/* bit field declarations */ +/**************************/ + +/* since the compiler complains if a structure name is declared twice, even + * if the declarations are identical, all DeclBitfR invocations are + * given here in one file. */ + +DeclBitfR(0,1,_b01) +DeclBitfR(0,15,_b015) +DeclBitfR(0,16,_b016) +DeclBitfR(0,4,_b04) +DeclBitfR(0,6,_b06) +DeclBitfR(0,8,_b08) +DeclBitfR(4,1,_b41) +DeclBitfR(4,4,_b44) +DeclBitfR(6,1,_b61) +DeclBitfR(6,13,_b613) +DeclBitfR(6,15,_b615) +DeclBitfR(6,17,_b617) +DeclBitfR(6,26,_b626) +DeclBitfR(6,5,_b65) +DeclBitfR(7,1,_b71) +DeclBitfR(8,1,_b81) +DeclBitfR(8,4,_b84) +DeclBitfR(8,8,_b88) +DeclBitfR(9,1,_b91) +DeclBitfR(10,1,_b101) +DeclBitfR(11,1,_b111) +DeclBitfR(11,10,_b1110) +DeclBitfR(11,4,_b114) +DeclBitfR(11,5,_b115) +DeclBitfR(12,1,_b121) +DeclBitfR(12,4,_b124) +DeclBitfR(13,1,_b131) +DeclBitfR(14,1,_b141) +DeclBitfR(15,1,_b151) +DeclBitfR(16,1,_b161) +DeclBitfR(16,15,_b1615) +DeclBitfR(16,16,_b1616) +DeclBitfR(16,2,_b162) +DeclBitfR(16,3,_b163) +DeclBitfR(16,4,_b164) +DeclBitfR(16,5,_b165) +DeclBitfR(16,8,_b168) +DeclBitfR(17,1,_b171) +DeclBitfR(18,1,_b181) +DeclBitfR(18,13,_b1813) +DeclBitfR(18,2,_b182) +DeclBitfR(18,7,_b187) +DeclBitfR(19,1,_b191) +DeclBitfR(19,8,_b198) +DeclBitfR(19,10,_b1910) +DeclBitfR(20,11,_b2011) +DeclBitfR(20,2,_b202) +DeclBitfR(20,4,_b204) +DeclBitfR(21,10,_b2110) +DeclBitfR(21,2,_b212) +DeclBitfR(21,5,_b215) +DeclBitfR(22,5,_b225) +DeclBitfR(23,3,_b233) +DeclBitfR(24,1,_b241) +DeclBitfR(24,4,_b244) +DeclBitfR(24,8,_b248) +DeclBitfR(25,1,_b251) +DeclBitfR(26,1,_b261) +DeclBitfR(27,1,_b271) +DeclBitfR(27,4,_b274) +DeclBitfR(27,5,_b275) +DeclBitfR(28,1,_b281) +DeclBitfR(28,4,_b284) +DeclBitfR(29,1,_b291) +DeclBitfR(30,1,_b301) +DeclBitfR(30,2,_b302) +DeclBitfR(31,1,_b311) + +/******************/ +/* Word subfields */ +/******************/ + +#define Sign(i) BitfR(i,0,1,_b01) +/* halfwords */ +#define Hwd0(i) BitfR(i,0,16,_b016) +#define Hwd1sign(i) BitfR(i,16,1,_b161) +#define Hwd1(i) BitfR(i,16,16,_b1616) +/* bytes */ +#define Byte0(i) BitfR(i,0,8,_b08) +#define Byte1sign(i) BitfR(i,8,1,_b81) +#define Byte1(i) BitfR(i,8,8,_b88) +#define Byte2(i) BitfR(i,16,8,_b168) +#define Byte3sign(i) BitfR(i,24,1,_b241) +#define Byte3(i) BitfR(i,24,8,_b248) +/* digits */ +#define Digit0(i) BitfR(i,0,4,_b04) +#define Digit1(i) BitfR(i,4,4,_b44) +#define Digit2(i) BitfR(i,8,4,_b84) +#define Digit3(i) BitfR(i,12,4,_b124) +#define Digit4(i) BitfR(i,16,4,_b164) +#define Digit5(i) BitfR(i,20,4,_b204) +#define Digit6(i) BitfR(i,24,4,_b244) +#define Digit7(i) BitfR(i,28,4,_b284) + +/* Wordsize definitions */ + +#define BIT_P_DW 64 /* bits/doubleword */ +#define BIT_P_WD 32 /* bits/word */ +#define BIT_P_HW 16 /* bits/halfword */ +#define BIT_P_BYT 8 /* bits/byte */ +#define BYT_P_DW 8 /* bytes/doubleword */ +#define BYT_P_WD 4 /* bytes/word */ +#define BYT_P_HW 2 /* bytes/halfword */ + +/* Masks */ + +#define WDMASK 0xffffffff /* 32-bit mask */ +#define OFSMASK 0xffffffff /* 32-bit mask */ +#define SIDMASK 0xffffffff /* 32-bit mask */ +#define SIGNMASK 0x80000000 /* 32 bit word sign bit */ + +/* Alignments */ + +#define wdalign(ofs) (ofs &= ~3) +/* + * Header: /n/schirf/u/baford/CVS/mach4-parisc/kernel_unused/parisc/kdb/unasm.c,v 1.5 1994/07/21 22:32:05 mike Exp + * + * Spectrum Simulator Instruction Opcode Definitions + * Dan Magenheimer + * Computer Research Center, Hewlett-Packard Labs + * + * (c) copyright 1982 + * (p) protected 1982 + * The Hewlett-Packard Company + * Hewlett-Packard Laboratories + * Computer Research Center + * Palo Alto, California + * + * *** HP Company Confidential *** + * + * Log: unasm.c,v + * Revision 1.5 1994/07/21 22:32:05 mike + * official HP copyright notice + * + * Revision 1.4 1992/07/08 12:19:52 dalton + * Checkin before split to 1.0.4 release (by LBS). + * + * Revision 1.3 92/06/06 16:16:45 dalton + * *** empty log message *** + * + * Revision 1.2 92/06/06 15:42:28 dalton + * Changed include to be a path relative to hp800. + * + * Revision 1.1 92/06/06 14:05:33 dalton + * Initial revision + * + * Revision 1.2 91/04/14 20:29:49 osfrcs + * Initial version. + * [91/03/30 09:20:34 brezak] + * + * Revision 1.1.2.2 91/04/02 10:42:50 brezak + * Initial version. + * [91/03/30 09:20:34 brezak] + * + * Revision 1.1.1.2 91/03/30 09:20:34 brezak + * Initial version. + * + * Revision 6.1 89/09/06 10:39:58 burroughs + * Added shadow registers for gr0-gr7. + * gr0-7 are copied into sh0-7 whenever a trap occurs + * the instruction RFIR restores gr0-7 from sh0-7 and returns from + * interrupt. + * the "sh" command displays the shadow registers + * = sh7 0x789 works, too. + * + * Revision 6.0 89/09/01 15:46:37 15:46:37 burroughs (Greg Burroughs) + * baseline for pcx simple offsite + * + * Revision 5.2 87/09/02 14:30:23 14:30:23 kent + * separated stat gathering for indexed vs short. + * this will NOT work if cache hints ever get used + * since this field was assumed always zero + * + * Revision 5.1 87/02/27 11:12:16 11:12:16 kent (Kent McMullen) + * update all src to 5.1 + * + * Revision 5.0 87/02/18 16:31:35 16:31:35 kent (Kent McMullen) + * update all revision numbers to 5.0 for release + * + * Revision 1.1 86/07/15 08:34:57 08:34:57 kent (Kent McMullen) + * Initial revision + * + * Revision 4.1 83/10/25 17:02:34 17:02:34 djm (Daniel J Magenheimer) + * First release for ACD v4 + * + * Revision 3.0 83/06/13 10:24:45 djm (Daniel Magenheimer) + * First release for distribution + * + * + */ + +/* + * Changes: + * 01/30/90 ejf Simplify SPOPn support, now only gives assist emulation trap. + * 01/19/90 ejf Replace linpak instructions with just FSTQ[SX]. + * 12/19/89 ejf Add PA89 new floating point opcode 0E. + * 12/18/89 ejf Change 5 ops to PA89 format. + * 12/01/89 ejf Move additional instructions fmas, fmaa, fld2, fst2 to ssILst + * 09/22/89 ejf Fix unbalanced comments. + */ + + +/* ..and modified by hand to remove the load/store short references */ +/* ..and modified by hand to make memory management ops conform to the + * requirement that all subops of a major opcode begin in the same + * place and have the same length */ + +#define LDW 0x12, 0x00, 0, 0 /* LOAD WORD */ +#define LDWM 0x13, 0x00, 0, 0 /* LOAD WORD and MODIFY */ +#define LDH 0x11, 0x00, 0, 0 /* LOAD HALFWORD */ +#define LDB 0x10, 0x00, 0, 0 /* LOAD BYTE */ +#define LDO 0x0d, 0x00, 0, 0 /* LOAD OFFSET */ +#define STW 0x1a, 0x00, 0, 0 /* STORE WORD */ +#define STWM 0x1b, 0x00, 0, 0 /* STORE WORD and MODIFY */ +#define STH 0x19, 0x00, 0, 0 /* STORE HALFWORD */ +#define STB 0x18, 0x00, 0, 0 /* STORE BYTE */ +#define LDWX 0x03, 0x02, 19, 7 /* LOAD WORD INDEXED */ +#define LDHX 0x03, 0x01, 19, 7 /* LOAD HALFWORD INDEXED */ +#define LDBX 0x03, 0x00, 19, 7 /* LOAD BYTE INDEXED */ +#define LDWAX 0x03, 0x06, 19, 7 /* LOAD WORD ABSOLUTE INDEXED */ +#define LDCWX 0x03, 0x07, 19, 7 /* LOAD and CLEAR WORD INDEXED */ +#define LDWS 0x03, 0x42, 19, 7 /* LOAD WORD SHORT DISP */ +#define LDHS 0x03, 0x41, 19, 7 /* LOAD HALFWORD SHORT DISP */ +#define LDBS 0x03, 0x40, 19, 7 /* LOAD BYTE SHORT DISP */ +#define LDWAS 0x03, 0x46, 19, 7 /* LOAD WORD ABSOLUTE SHORT DISP */ +#define LDCWS 0x03, 0x47, 19, 7 /* LOAD and CLEAR WORD SHORT DISP */ +#define STWS 0x03, 0x4a, 19, 7 /* STORE WORD SHORT DISP */ +#define STHS 0x03, 0x49, 19, 7 /* STORE HALFWORD SHORT DISP */ +#define STBS 0x03, 0x48, 19, 7 /* STORE BYTE SHORT DISP */ +#define STWAS 0x03, 0x4e, 19, 7 /* STORE WORD ABSOLUTE SHORT DISP */ +#define STBYS 0x03, 0x4c, 19, 7 /* STORE BYTES SHORT DISP */ +#define LDIL 0x08, 0x00, 0, 0 /* LOAD IMMED LEFT */ +#define ADDIL 0x0a, 0x00, 0, 0 /* ADD IMMED LEFT */ +#define BL 0x3a, 0x00, 16, 3 /* BRANCH [and LINK] */ +#define GATE 0x3a, 0x01, 16, 3 /* GATEWAY */ +#define BLR 0x3a, 0x02, 16, 3 /* BRANCH and LINK REGISTER */ +#define BV 0x3a, 0x06, 16, 3 /* BRANCH VECTORED */ +#define BE 0x38, 0x00, 0, 0 /* BRANCH EXTERNAL */ +#define BLE 0x39, 0x00, 0, 0 /* BRANCH and LINK EXTERNAL */ +#define MOVB 0x32, 0x00, 0, 0 /* MOVE and BRANCH */ +#define MOVIB 0x33, 0x00, 0, 0 /* MOVE IMMED and BRANCH */ +#define COMBT 0x20, 0x00, 0, 0 /* COMPARE and BRANCH if TRUE */ +#define COMBF 0x22, 0x00, 0, 0 /* COMPARE and BRANCH if FALSE */ +#define COMIBT 0x21, 0x00, 0, 0 /* COMPARE IMMED and BRANCH if TRUE */ +#define COMIBF 0x23, 0x00, 0, 0 /* COMPARE IMMED and BRANCH if FALSE */ +#define ADDBT 0x28, 0x00, 0, 0 /* ADD and BRANCH if TRUE */ +#define ADDBF 0x2a, 0x00, 0, 0 /* ADD and BRANCH if FALSE */ +#define ADDIBT 0x29, 0x00, 0, 0 /* ADD IMMED and BRANCH if TRUE */ +#define ADDIBF 0x2b, 0x00, 0, 0 /* ADD IMMED and BRANCH if FALSE */ +#define BVB 0x30, 0x00, 0, 0 /* BRANCH on VARIABLE BIT */ +#define BB 0x31, 0x00, 0, 0 /* BRANCH on BIT */ +#define ADD 0x02, 0x30, 20, 7 /* ADD */ +#define ADDL 0x02, 0x50, 20, 7 /* ADD LOGICAL */ +#define ADDO 0x02, 0x70, 20, 7 /* ADD and TRAP on OVFLO */ +#define SH1ADD 0x02, 0x32, 20, 7 /* SHIFT 1, ADD */ +#define SH1ADDL 0x02, 0x52, 20, 7 /* SHIFT 1, ADD LOGICAL */ +#define SH1ADDO 0x02, 0x72, 20, 7 /* SHIFT 1, ADD and TRAP on OVFLO */ +#define SH2ADD 0x02, 0x34, 20, 7 /* SHIFT 2, ADD */ +#define SH2ADDL 0x02, 0x54, 20, 7 /* SHIFT 2, ADD LOGICAL */ +#define SH2ADDO 0x02, 0x74, 20, 7 /* SHIFT 2, ADD and TRAP on OVFLO */ +#define SH3ADD 0x02, 0x36, 20, 7 /* SHIFT 3, ADD */ +#define SH3ADDL 0x02, 0x56, 20, 7 /* SHIFT 3, ADD LOGICAL */ +#define SH3ADDO 0x02, 0x76, 20, 7 /* SHIFT 3, ADD and TRAP on OVFLO */ +#define ADDC 0x02, 0x38, 20, 7 /* ADD with CARRY */ +#define ADDCO 0x02, 0x78, 20, 7 /* ADD with CARRY and TRAP on OVFLO */ +#define SUB 0x02, 0x20, 20, 7 /* SUBTRACT */ +#define SUBO 0x02, 0x60, 20, 7 /* SUBTRACT and TRAP on OVFLO */ +#define SUBB 0x02, 0x28, 20, 7 /* SUBTRACT with BORROW */ +#define SUBBO 0x02, 0x68, 20, 7 /* SUBTRACT with BORROW and TRAP on OVFLO */ +#define SUBT 0x02, 0x26, 20, 7 /* SUBTRACT and TRAP on COND */ +#define SUBTO 0x02, 0x66, 20, 7 /* SUBTRACT and TRAP on COND or OVFLO */ +#define DS 0x02, 0x22, 20, 7 /* DIVIDE STEP */ +#define COMCLR 0x02, 0x44, 20, 7 /* COMPARE and CLEAR */ +#define OR 0x02, 0x12, 20, 7 /* INCLUSIVE OR */ +#define XOR 0x02, 0x14, 20, 7 /* EXCLUSIVE OR */ +#define AND 0x02, 0x10, 20, 7 /* AND */ +#define ANDCM 0x02, 0x00, 20, 7 /* AND COMPLEMENT */ +#define UXOR 0x02, 0x1c, 20, 7 /* UNIT XOR */ +#define UADDCM 0x02, 0x4c, 20, 7 /* UNIT ADD COMPLEMENT */ +#define UADDCMT 0x02, 0x4e, 20, 7 /* UNIT ADD COMPLEMENT and TRAP on COND */ +#define DCOR 0x02, 0x5c, 20, 7 /* DECIMAL CORRECT */ +#define IDCOR 0x02, 0x5e, 20, 7 /* INTERMEDIATE DECIMAL CORRECT */ +#define ADDI 0x2d, 0x00, 20, 1 /* ADD to IMMED */ +#define ADDIO 0x2d, 0x01, 20, 1 /* ADD to IMMED and TRAP on OVFLO */ +#define ADDIT 0x2c, 0x00, 20, 1 /* ADD to IMMED and TRAP on COND */ +#define ADDITO 0x2c, 0x01, 20, 1 /* ADD to IMMED and TRAP on COND or OVFLO */ +#define SUBI 0x25, 0x00, 20, 1 /* SUBTRACT from IMMED */ +#define SUBIO 0x25, 0x01, 20, 1 /* SUBTRACT from IMMED and TRAP on OVFLO */ +#define COMICLR 0x24, 0x00, 0, 0 /* COMPARE IMMED and CLEAR */ +#define VSHD 0x34, 0x00, 19, 3 /* VARIABLE SHIFT DOUBLE */ +#define SHD 0x34, 0x02, 19, 3 /* SHIFT DOUBLE */ +#define VEXTRU 0x34, 0x04, 19, 3 /* VARIABLE EXTRACT RIGHT UNSIGNED */ +#define VEXTRS 0x34, 0x05, 19, 3 /* VARIABLE EXTRACT RIGHT SIGNED */ +#define EXTRU 0x34, 0x06, 19, 3 /* EXTRACT RIGHT UNSIGNED */ +#define EXTRS 0x34, 0x07, 19, 3 /* EXTRACT RIGHT SIGNED */ +#define VDEP 0x35, 0x01, 19, 3 /* VARIABLE DEPOSIT */ +#define DEP 0x35, 0x03, 19, 3 /* DEPOSIT */ +#define VDEPI 0x35, 0x05, 19, 3 /* VARIABLE DEPOSIT IMMED */ +#define DEPI 0x35, 0x07, 19, 3 /* DEPOSIT IMMED */ +#define ZVDEP 0x35, 0x00, 19, 3 /* ZERO and VARIABLE DEPOSIT */ +#define ZDEP 0x35, 0x02, 19, 3 /* ZERO and DEPOSIT */ +#define ZVDEPI 0x35, 0x04, 19, 3 /* ZERO and VARIABLE DEPOSIT IMMED */ +#define ZDEPI 0x35, 0x06, 19, 3 /* ZERO and DEPOSIT IMMED */ +#define BREAK 0x00, 0x00, 19, 8 /* BREAK */ +#define RFI 0x00, 0x60, 19, 8 /* RETURN FROM INTERRUPTION */ +#define RFIR 0x00, 0x65, 19, 8 /* RFI & RESTORE SHADOW REGISTERS */ +#define SSM 0x00, 0x6b, 19, 8 /* SET SYSTEM MASK */ +#define RSM 0x00, 0x73, 19, 8 /* RESET SYSTEM MASK */ +#define MTSM 0x00, 0xc3, 19, 8 /* MOVE TO SYSTEM MASK */ +#define LDSID 0x00, 0x85, 19, 8 /* LOAD SPACE IDENTIFIER */ +#define MTSP 0x00, 0xc1, 19, 8 /* MOVE TO SPACE REGISTER */ +#define MTCTL 0x00, 0xc2, 19, 8 /* MOVE TO SYSTEM CONTROL REGISTER */ +#define MFSP 0x00, 0x25, 19, 8 /* MOVE FROM SPACE REGISTER */ +#define MFCTL 0x00, 0x45, 19, 8 /* MOVE FROM SYSTEM CONTROL REGISTER */ +#define SYNC 0x00, 0x20, 19, 8 /* SYNCHRONIZE DATA CACHE */ +#define DIAG 0x05, 0x00, 0, 0 /* DIAGNOSE */ +#define SPOP 0x04, 0x00, 0, 0 /* SPECIAL FUNCTION UNIT */ +#define COPR 0x0c, 0x00, 0, 0 /* COPROCESSOR */ +#define CLDWX 0x09, 0x00, 19, 4 /* COPROCESSOR LOAD WORD INDEXED */ +#define CLDDX 0x0b, 0x00, 19, 4 /* COPROCESSOR LOAD WORD INDEXED */ +#define CSTWX 0x09, 0x01, 19, 4 /* COPROCESSOR STORE WORD INDEXED */ +#define CSTDX 0x0b, 0x01, 19, 4 /* COPROCESSOR STORE WORD INDEXED */ +#define CLDWS 0x09, 0x08, 19, 4 /* COPROCESSOR LOAD WORD SHORT */ +#define CLDDS 0x0b, 0x08, 19, 4 /* COPROCESSOR LOAD WORD SHORT */ +#define CSTWS 0x09, 0x09, 19, 4 /* COPROCESSOR STORE WORD SHORT */ +#define CSTDS 0x0b, 0x09, 19, 4 /* COPROCESSOR STORE WORD SHORT */ +#define FLOAT0 0x0e, 0x00, 21, 2 /* FLOATING POINT CLASS 0 */ +#define FLOAT1 0x0e, 0x01, 21, 2 /* FLOATING POINT CLASS 1 */ +#define FLOAT2 0x0e, 0x02, 21, 2 /* FLOATING POINT CLASS 2 */ +#define FLOAT3 0x0e, 0x03, 21, 2 /* FLOATING POINT CLASS 3 */ +#define FMPYSUB 0x26, 0x00, 0, 0 /* FP MULTIPLY AND SUBTRACT */ +#define FMPYADD 0x06, 0x00, 0, 0 /* FP MULTIPLY AND ADD/TRUNCATE */ +#define FSTQX 0x0f, 0x01, 19, 4 /* FLOATING POINT STORE QUAD INDEXED */ +#define FSTQS 0x0f, 0x09, 19, 4 /* FLOATING POINT STORE QUAD SHORT */ +/* all of the following have been pushed around to conform */ +#define PROBER 0x01, 0x46, 19, 7 /* PROBE READ ACCESS */ +#ifdef notdef +#define PROBERI 0x01, 0xc6, 19, 7 /* PROBE READ ACCESS IMMEDIATE */ +#endif +#define PROBEW 0x01, 0x47, 19, 7 /* PROBE WRITE ACCESS */ +#ifdef notdef +#define PROBEWI 0x01, 0xc7, 19, 7 /* PROBE WRITE ACCESS IMMEDIATE */ +#endif +#define LPA 0x01, 0x4d, 19, 7 /* LOAD PHYSICAL ADDRESS */ +#define LHA 0x01, 0x4c, 19, 7 /* LOAD HASH ADDRESS */ +#define PDTLB 0x01, 0x48, 19, 7 /* PURGE DATA TRANS LOOKASIDE BUFFER */ +#define PITLB 0x01, 0x08, 19, 7 /* PURGE INST TRANS LOOKASIDE BUFFER */ +#define PDTLBE 0x01, 0x49, 19, 7 /* PURGE DATA TLB ENTRY */ +#define PITLBE 0x01, 0x09, 19, 7 /* PURGE INST TLB ENTRY */ +#define IDTLBA 0x01, 0x41, 19, 7 /* INSERT DATA TLB ADDRESS */ +#define IITLBA 0x01, 0x01, 19, 7 /* INSERT INSTRUCTION TLB ADDRESS */ +#define IDTLBP 0x01, 0x40, 19, 7 /* INSERT DATA TLB PROTECTION */ +#define IITLBP 0x01, 0x00, 19, 7 /* INSERT INSTRUCTION TLB PROTECTION */ +#define PDC 0x01, 0x4e, 19, 7 /* PURGE DATA CACHE */ +#define FDC 0x01, 0x4a, 19, 7 /* FLUSH DATA CACHE */ +#define FIC 0x01, 0x0a, 19, 7 /* FLUSH INSTRUCTION CACHE */ +#define FDCE 0x01, 0x4b, 19, 7 /* FLUSH DATA CACHE ENTRY */ +#define FICE 0x01, 0x0b, 19, 7 /* FLUSH DATA CACHE ENTRY */ + +/* + * Header: /n/schirf/u/baford/CVS/mach4-parisc/kernel_unused/parisc/kdb/unasm.c,v 1.5 1994/07/21 22:32:05 mike Exp + * + * Spectrum Simulator Instruction Set Constants and Datatypes + * Dan Magenheimer - 4/28/82 + * Computer Research Center, Hewlett-Packard Labs + * + * (c) copyright 1982 + * (p) protected 1982 + * The Hewlett-Packard Company + * Hewlett-Packard Laboratories + * Computer Research Center + * Palo Alto, California + * + * *** HP Company Confidential *** + * + * Log: unasm.c,v + * Revision 1.5 1994/07/21 22:32:05 mike + * official HP copyright notice + * + * Revision 1.4 1992/07/08 12:19:52 dalton + * Checkin before split to 1.0.4 release (by LBS). + * + * Revision 1.3 92/06/06 16:16:45 dalton + * *** empty log message *** + * + * Revision 1.2 92/06/06 15:42:28 dalton + * Changed include to be a path relative to hp800. + * + * Revision 1.1 92/06/06 14:05:33 dalton + * Initial revision + * + * Revision 1.2 91/04/14 20:29:49 osfrcs + * Initial version. + * [91/03/30 09:20:34 brezak] + * + * Revision 1.1.2.2 91/04/02 10:42:50 brezak + * Initial version. + * [91/03/30 09:20:34 brezak] + * + * Revision 1.1.1.2 91/03/30 09:20:34 brezak + * Initial version. + * +;Revision 1.1 88/07/11 14:05:21 14:05:21 ren (Bob Naas) +;Initial revision +; + * Revision 5.1 87/02/27 11:12:23 11:12:23 kent (Kent McMullen) + * update all src to 5.1 + * + * Revision 5.0 87/02/18 16:31:52 16:31:52 kent (Kent McMullen) + * update all revision numbers to 5.0 for release + * + * Revision 1.1 86/07/15 08:35:00 08:35:00 kent (Kent McMullen) + * Initial revision + * + * Revision 4.3 85/11/12 09:28:44 09:28:44 viggy (Viggy Mokkarala) + * first mpsim version, partially stable + * + * Revision 4.2 84/07/16 17:20:57 17:20:57 djm () + * Define field macros for COPR and SFU insts + * + * Revision 4.1 83/10/25 17:10:14 djm (Daniel Magenheimer) + * First release for ACD v4 + * + * Revision 3.1 83/08/03 14:09:59 djm (Daniel Magenheimer) + * Sys calls, args, -S, bug fixes, etc. + * + * Revision 3.0 83/06/13 10:25:13 djm (Daniel Magenheimer) + * First release for distribution + * + * + */ +/* + * Changes: + * 12/01/89 ejf Add Rsd(), Rse(), Rtd(), Rte() for 5 ops. + * 11/30/89 ejf Make instruction use counters shared, not per cpu. + * 11/28/89 ejf Change majoropcode for quicker extension extract. + */ + + + +/* + * Dependencies: std.h, ssDefs.h, bits.h + */ + + +/* Lookup/Execute structure for instructions */ +struct inst { + u_char majopc; /* major opcode of instruction, 0..MAXOPC */ + u_char opcext; /* opcode extension, 0 if not applic. */ + u_char extbs; /* starting bit pos of extension field */ + u_char extbl; /* bit length of extension field */ + u_int count; /* frequency counter for analysis */ + char mnem[8]; /* ascii mnemonic */ + /* disassembly function */ + int (*dasmfcn)(const struct inst *, OFS, int); +}; + + +#define NMAJOPCS 64 + +struct majoropcode { + const struct inst **subops; /* pointer to table of subops indexed by + * opcode extension */ + u_int maxsubop; /* largest opcode extension value or 0 */ + u_int extshft; /* right shift amount for extension field */ + u_int extmask; /* post shift mask for extension field */ +}; + +#define OpExt(i,m) ((i >> m->extshft) & m->extmask) /* extract opcode extension */ + + +/*****************************/ +/* Miscellaneous definitions */ +/*****************************/ + +/* Load/Store Indexed Opcode Extension Cache Control */ +#define NOACTION 0 +#define STACKREF 1 +#define SEQPASS 2 +#define PREFETCH 3 + +/******************************/ +/* Fields within instructions */ +/******************************/ + +/* opcode */ +#define Opcode(i) BitfR(i,0,6,_b06) +/* opcode true/false bit */ +#define OpcTF(i) BitfR(i,4,1,_b41) +/* register sources */ +#define Rsa(i) BitfR(i,11,5,_b115) +#define Rsb(i) BitfR(i,6,5,_b65) +#define Rsc(i) BitfR(i,27,5,_b275) +#define Rsd(i) BitfR(i,21,5,_b215) +#define Rse(i) BitfR(i,16,5,_b165) +/* register targets */ +#define Rta(i) BitfR(i,11,5,_b115) +#define Rtb(i) BitfR(i,6,5,_b65) +#define Rtc(i) BitfR(i,27,5,_b275) +#define Rtd(i) BitfR(i,21,5,_b215) +#define Rte(i) BitfR(i,16,5,_b165) +/* 5-bit immediates (Magnitude, Sign) */ +#define Imb5(i) BitfR(i,6,5,_b65) +#define Ima5M(i) BitfR(i,11,4,_b114) +#define Ima5S(i) BitfR(i,15,1,_b151) +#define Ima5A(i) BitfR(i,11,5,_b115) +#define Imd5(i) BitfR(i,22,5,_b225) +#define Imc5M(i) BitfR(i,27,4,_b274) +#define Imc5S(i) BitfR(i,31,1,_b311) +#define Imc5A(i) BitfR(i,27,5,_b275) +/* Other immediates */ +#define Im21L(i) BitfR(i,18,2,_b182) +#define Im21H(i) BitfR(i,20,11,_b2011) +#define Im21M1(i) BitfR(i,16,2,_b162) +#define Im21M2(i) BitfR(i,11,5,_b115) +#define Im21S(i) BitfR(i,31,1,_b311) +#define Im11M(i) BitfR(i,21,10,_b2110) +#define Im11S(i) BitfR(i,31,1,_b311) +/* displacements/offsets */ +#define DispM(i) BitfR(i,18,13,_b1813) +#define DispS(i) BitfR(i,31,1,_b311) +#define Off5(i) BitfR(i,11,5,_b115) +#define Off11H(i) BitfR(i,19,10,_b1910) +#define Off11L(i) BitfR(i,29,1,_b291) +#define OffS(i) BitfR(i,31,1,_b311) +/* miscellaneous */ +#define Dss(i) BitfR(i,16,2,_b162) +#define Cond(i) BitfR(i,16,3,_b163) +#define Cneg(i) BitfR(i,19,1,_b191) +#define Cond4(i) BitfR(i,16,4,_b164) /* Cond AND Cneg */ +#define Nu(i) BitfR(i,30,1,_b301) +#define SrL(i) BitfR(i,16,2,_b162) +#define SrH(i) BitfR(i,18,1,_b181) +#define ShortDisp(i) BitfR(i,19,1,_b191) +#define IndxShft(i) BitfR(i,18,1,_b181) +#define ModBefore(i) BitfR(i,18,1,_b181) +#define CacheCtrl(i) BitfR(i,20,2,_b202) +#define Modify(i) BitfR(i,26,1,_b261) +#define ProbeI(i) BitfR(i,18,1,_b181) +#define Uid(i) BitfR(i,23,3,_b233) +#define Sfu(i) BitfR(i,23,3,_b233) +#define CopExt17(i) BitfR(i,6,17,_b617) +#define CopExt5(i) BitfR(i,27,5,_b275) +#define SpopType(i) BitfR(i,21,2,_b212) +#define SpopExt15(i) BitfR(i,6,15,_b615) +#define SpopExt10(i) BitfR(i,11,10,_b1110) +#define SpopExt5L(i) BitfR(i,16,5,_b165) +#define SpopExt5(i) BitfR(i,27,5,_b275) +#define NoMajOpc(i) BitfR(i,6,26,_b626) +#define Bi1(i) BitfR(i,27,5,_b275) /* fields in BREAK */ +#define Bi2(i) BitfR(i,6,13,_b613) + +/* fragmented field collating macros */ +#define Ima5(i) (Ima5S(i) ? Ima5M(i) | (-1<<4) : Ima5M(i)) + +#define Imc5(i) (Imc5S(i) ? Imc5M(i) | (-1<<4) : Imc5M(i)) + +#define Disp(i) (DispS(i) ? DispM(i) | (-1<<13) : DispM(i)) + +#define Im21(i) (Im21S(i) << 31 | Im21H(i) << 20 | Im21M1(i) << 18 | \ + Im21M2(i) << 13 | Im21L(i) << 11) + +#define Im11(i) (Im11S(i) ? Im11M(i) | (-1<<10) : Im11M(i)) + +#define Bdisp(i) ((OffS(i) ? (Off5(i)<<11 | Off11L(i)<<10|Off11H(i)) \ +/* branch displacement (bytes) */ | (-1 << 16) \ + : (Off5(i)<<11|Off11L(i)<<10|Off11H(i))) << 2) + +#define Cbdisp(i) ((OffS(i) ? (Off11L(i) << 10 | Off11H(i)) \ + /* compare/branch disp (bytes) */ | (-1 << 11) \ + : Off11L(i) << 10 | Off11H(i)) << 2) + +#define Sr(i) (SrH(i)<<2 | SrL(i)) + +/* sfu/copr */ +#define CoprExt1(i) (CopExt17(i)) +#define CoprExt2(i) (CopExt5(i)) +#define CoprExt(i) ((CopExt17(i)<<5) | CopExt5(i)) +#define Spop0Ext(i) ((SpopExt15(i)<<5) | SpopExt5(i)) +#define Spop1Ext(i) (SpopExt15(i)) +#define Spop2Ext(i) ((SpopExt10(i)<<5) | SpopExt5(i)) +#define Spop3Ext(i) ((SpopExt5L(i)<<5) | SpopExt5(i)) + + +/*##################### Globals - Imports ##################################*/ + +/* Disassembly functions */ +int fcoprDasm(int w, u_int op1, u_int); +char *edDCond(u_int cond); +char *unitDCond(u_int cond); +char *addDCond(u_int cond); +char *subDCond(u_int cond); +int blDasm(const struct inst *i, OFS ofs, int w); +int ldDasm(const struct inst *, OFS, int); +int stDasm(const struct inst *i, OFS, int); +int addDasm(const struct inst *i, OFS, int); +int unitDasm(const struct inst *i, OFS, int); +int iaDasm(const struct inst *i, OFS, int); +int shdDasm(const struct inst *i, OFS, int); +int extrDasm(const struct inst *i, OFS, int); +int vextrDasm(const struct inst *i, OFS, int); +int depDasm(const struct inst *i, OFS, int); +int vdepDasm(const struct inst *i, OFS, int); +int depiDasm(const struct inst *i, OFS, int); +int vdepiDasm(const struct inst *i, OFS, int); +int limmDasm(const struct inst *i, OFS, int); +int brkDasm(const struct inst *i, OFS, int); +int lpkDasm(const struct inst *i, OFS, int); +int fmpyaddDasm(const struct inst *i, OFS, int); +int fmpysubDasm(const struct inst *i, OFS, int); +int floatDasm(const struct inst *i, OFS, int); +int coprDasm(const struct inst *i, OFS, int); +int diagDasm(const struct inst *i, OFS, int); +int scDasm(const struct inst *i, OFS, int); +int mmgtDasm(const struct inst *i, OFS, int); +int ldxDasm(const struct inst *i, OFS, int); +int stsDasm(const struct inst *i, OFS, int); +int stbysDasm(const struct inst *i, OFS, int); +int brDasm(const struct inst *i, OFS, int); +int bvDasm(const struct inst *i, OFS, int); +int beDasm(const struct inst *i, OFS, int); +int cbDasm(const struct inst *i,OFS ofs, int); +int cbiDasm(const struct inst *i,OFS ofs, int); +int bbDasm(const struct inst *i,OFS ofs, int); +int ariDasm(const struct inst *i, OFS, int); + +/*##################### Globals - Exports ##################################*/ +/*##################### Local Variables ####################################*/ + +static const char fmtStrTbl[][5] = { "sgl", "dbl", "sgl", "quad" }; +static const char condStrTbl[][7] = { + "false?", "false", "?", "!<=>", "=", "=t", "?=", "!<>", + "!?>=", "<", "?<", "!>=", "!?>", "<=", "?<=", "!>", + "!?<=", ">", "?>", "!<=", "!?<", ">=", "?>=", "!<", + "!?=", "<>", "!=", "!=t", "!?", "<=>", "true?", "true" +}; +static const char fsreg[][5] = { + "r0L", "r0R", "r1L", "r1R", "r2L", "r2R", "r3L", "r3R", + "r4L", "r4R", "r5L", "r5R", "r6L", "r6R", "r7L", "r7R", + "r8L", "r8R", "r9L", "r9R", "r10L", "r10R", "r11L", "r11R", + "r12L", "r12R", "r13L", "r13R", "r14L", "r14R", "r15L", "r15R", + "r16L", "r16R", "r17L", "r17R", "r18L", "r18R", "r19L", "r19R", + "r20L", "r20R", "r21L", "r21R", "r22L", "r22R", "r23L", "r23R", + "r24L", "r24R", "r25L", "r25R", "r26L", "r26R", "r27L", "r27R", + "r28L", "r28R", "r29L", "r29R", "r30L", "r30R", "r31L", "r31R" +}; +static const char fdreg[][4] = { + "r0", "r0", "r1", "r1", "r2", "r2", "r3", "r3", + "r4", "r4", "r5", "r5", "r6", "r6", "r7", "r7", + "r8", "r8", "r9", "r9", "r10", "r10", "r11", "r11", + "r12", "r12", "r13", "r13", "r14", "r14", "r15", "r15", + "r16", "r16", "r17", "r17", "r18", "r18", "r19", "r19", + "r20", "r20", "r21", "r21", "r22", "r22", "r23", "r23", + "r24", "r24", "r25", "r25", "r26", "r26", "r27", "r27", + "r28", "r28", "r29", "r29", "r30", "r30", "r31", "r31" +}; + +/*##################### Macros #############################################*/ + +#define Match(s) (strncmp(s,i->mnem,sizeof(s)-1) == 0) + +/* bits for assist ops */ +#define AstNu(w) Modify(w) +#define Fpi(w) (Uid(w)>3) + +/* bits for 5 ops */ +#define SinglePrec(i) Modify(i) +#define Ms1(i) ((Rsb(i)<<1)+(SinglePrec(i)?((Rsb(i)>15)?1:32):0)) +#define Ms2(i) ((Rsa(i)<<1)+(SinglePrec(i)?((Rsa(i)>15)?1:32):0)) +#define Mt(i) ((Rtc(i)<<1)+(SinglePrec(i)?((Rtc(i)>15)?1:32):0)) +#define As(i) ((Rsd(i)<<1)+(SinglePrec(i)?((Rsd(i)>15)?1:32):0)) +#define Ad(i) ((Rte(i)<<1)+(SinglePrec(i)?((Rte(i)>15)?1:32):0)) + +/*##################### Globals - Exports ##################################*/ + +/* To replace instr function, do the following: */ +/* a) locate the desired entry in instrs[] below */ +/* b) change the 3rd field if an alternate mneumonic is */ +/* desired for window disassembly */ +/* c) change the 4th field to the name of the function being */ +/* used for replacement (i.e. ldwRepl instead of ldw) */ +/* d) change the 5th field if an alternate disassembly routine */ +/* is desired (i.e. ldDasmRepl) */ + +static const struct inst instrs[] = { + { LDW, 0, "ldw", ldDasm }, + { LDH, 0, "ldh", ldDasm }, + { LDB, 0, "ldb", ldDasm }, + { LDWM, 0, "ldwm", ldDasm }, + { LDO, 0, "ldo", ldDasm }, + { STW, 0, "stw", stDasm }, + { STH, 0, "sth", stDasm }, + { STB, 0, "stb", stDasm }, + { STWM, 0, "stwm", stDasm }, + { LDWX, 0, "ldw", ldxDasm }, + { LDHX, 0, "ldh", ldxDasm }, + { LDBX, 0, "ldb", ldxDasm }, + { LDCWX, 0, "ldcw", ldxDasm }, + { LDWAX, 0, "ldwa", ldxDasm }, + { LDWS, 0, "ldw", ldxDasm }, + { LDHS, 0, "ldh", ldxDasm }, + { LDBS, 0, "ldb", ldxDasm }, + { LDCWS, 0, "ldcw", ldxDasm }, + { LDWAS, 0, "ldwa", ldxDasm }, + { STWS, 0, "stws", stsDasm }, + { STHS, 0, "sths", stsDasm }, + { STBS, 0, "stbs", stsDasm }, + { STWAS, 0, "stwas", stsDasm }, + { STBYS, 0, "stbys", stbysDasm }, + { LDIL, 0, "ldil", limmDasm }, + { ADDIL, 0, "addil", limmDasm }, + { GATE, 0, "gate", blDasm }, + { BL, 0, "b", blDasm }, + { BLR, 0, "blr", brDasm }, + { BV, 0, "bv", bvDasm }, + { BE, 0, "be", beDasm }, + { BLE, 0, "ble", beDasm }, + { COMBT, 0, "combt", cbDasm }, + { COMBF, 0, "combf", cbDasm }, + { COMIBT, 0, "comibt", cbiDasm }, + { COMIBF, 0, "comibf", cbiDasm }, + { ADDBT, 0, "addbt", cbDasm }, + { ADDBF, 0, "addbf", cbDasm }, + { ADDIBT, 0, "addibt", cbiDasm }, + { ADDIBF, 0, "addibf", cbiDasm }, + { MOVB, 0, "movb", cbDasm }, + { MOVIB, 0, "movib", cbiDasm }, + { BB, 0, "bb", bbDasm }, + { BVB, 0, "bvb", bbDasm }, + { SUBO, 0, "subo", ariDasm }, + { ADD, 0, "add", addDasm }, + { ADDL, 0, "addl", addDasm }, + { ADDO, 0, "addo", ariDasm }, + { SH1ADD, 0, "sh1add", ariDasm }, + { SH1ADDL,0, "sh1addl", ariDasm }, + { SH1ADDO,0, "sh1addo", ariDasm }, + { SH2ADD, 0, "sh2add", ariDasm }, + { SH2ADDL,0, "sh2addl", ariDasm }, + { SH2ADDO,0, "sh2addo", ariDasm }, + { SH3ADD, 0, "sh3add", ariDasm }, + { SH3ADDL,0, "sh3addl", ariDasm }, + { SH3ADDO,0, "sh3addo", ariDasm }, + { SUB, 0, "sub", ariDasm }, + { ADDCO, 0, "addco", ariDasm }, + { SUBBO, 0, "subbo", ariDasm }, + { ADDC, 0, "addc", ariDasm }, + { SUBB, 0, "subb", ariDasm }, + { COMCLR, 0, "comclr", ariDasm }, + { OR, 0, "or", ariDasm }, + { AND, 0, "and", ariDasm }, + { XOR, 0, "xor", ariDasm }, + { ANDCM, 0, "andcm", ariDasm }, + { DS, 0, "ds", ariDasm }, + { UXOR, 0, "uxor", unitDasm }, + { UADDCM, 0, "uaddcm", unitDasm }, + { UADDCMT,0, "uaddcmt", unitDasm }, + { SUBTO, 0, "subto", ariDasm }, + { SUBT, 0, "subt", ariDasm }, + { DCOR, 0, "dcor", unitDasm }, + { IDCOR, 0, "idcor", unitDasm }, + { ADDIO, 0, "addio", iaDasm }, + { SUBIO, 0, "subio", iaDasm }, + { ADDI, 0, "addi", iaDasm }, + { SUBI, 0, "subi", iaDasm }, + { COMICLR,0, "comiclr", iaDasm }, + { ADDITO, 0, "addito", iaDasm }, + { ADDIT, 0, "addit", iaDasm }, + { SHD, 0, "shd", shdDasm }, + { VSHD, 0, "vshd", shdDasm }, + { EXTRU, 0, "extru", extrDasm }, + { EXTRS, 0, "extrs", extrDasm }, + { VEXTRU, 0, "vextru", vextrDasm }, + { VEXTRS, 0, "vextrs", vextrDasm }, + { DEP, 0, "dep", depDasm }, + { VDEP, 0, "vdep", vdepDasm }, + { DEPI, 0, "depi", depiDasm }, + { VDEPI, 0, "vdepi", vdepiDasm }, + { ZDEP, 0, "zdep", depDasm }, + { ZVDEP, 0, "zvdep", vdepDasm }, + { ZDEPI, 0, "zdepi", depiDasm }, + { ZVDEPI, 0, "zvdepi", vdepiDasm }, + { BREAK, 0, "break", brkDasm }, + { RFI, 0, "rfi", 0 }, + { RFIR, 0, "rfir", 0 }, + { SSM, 0, "ssm", scDasm }, + { RSM, 0, "rsm", scDasm }, + { MTSM, 0, "mtsm", scDasm }, + { PROBER, 0, "prober", mmgtDasm }, + { PROBEW, 0, "probew", mmgtDasm }, + { LPA, 0, "lpa", mmgtDasm }, + { LHA, 0, "lha", mmgtDasm }, + { LDSID, 0, "ldsid", scDasm }, + { PDTLB, 0, "pdtlb", mmgtDasm }, + { PDTLBE, 0, "pdtlbe", mmgtDasm }, + { PITLB, 0, "pitlb", mmgtDasm }, + { PITLBE, 0, "pitlbe", mmgtDasm }, + { IDTLBA, 0, "idtlba", mmgtDasm }, + { IITLBA, 0, "iitlba", mmgtDasm }, + { IDTLBP, 0, "idtlbp", mmgtDasm }, + { IITLBP, 0, "iitlbp", mmgtDasm }, + { FIC, 0, "fic", mmgtDasm }, + { FICE, 0, "fice", mmgtDasm }, + { PDC, 0, "pdc", mmgtDasm }, + { FDC, 0, "fdc", mmgtDasm }, + { FDCE, 0, "fdce", mmgtDasm }, + { SYNC, 0, "sync", 0 }, + { MTSP, 0, "mtsp", scDasm }, + { MTCTL, 0, "mtctl", scDasm }, + { MFSP, 0, "mfsp", scDasm }, + { MFCTL, 0, "mfctl", scDasm }, + { DIAG, 0, "diag", diagDasm }, + { SPOP, 0, "???", 0 }, + { COPR, 0, "copr", coprDasm }, + { CLDWX, 0, "cldw", coprDasm }, + { CLDDX, 0, "cldd", coprDasm }, + { CSTWX, 0, "cstw", coprDasm }, + { CSTDX, 0, "cstd", coprDasm }, + { CLDWS, 0, "cldw", coprDasm }, + { CLDDS, 0, "cldd", coprDasm }, + { CSTWS, 0, "cstw", coprDasm }, + { CSTDS, 0, "cstd", coprDasm }, + { FLOAT0, 0, "f", floatDasm }, + { FLOAT1, 0, "fcnv", floatDasm }, + { FLOAT2, 0, "f", floatDasm }, + { FLOAT3, 0, "f", floatDasm }, + { FMPYSUB,0, "fmpy", fmpysubDasm }, + { FMPYADD,0, "fmpy", fmpyaddDasm }, + { FSTQX, 0, "fstqx", lpkDasm }, + { FSTQS, 0, "fstqs", lpkDasm }, + {0} +}; + + +static const struct inst illeg = { 0, 0, 0, 0, 0, "???", 0 }; +static const struct inst *so_sysop[0xd0]; +static const struct inst *so_mmuop[0x50]; +static const struct inst *so_arith[0x80]; +static const struct inst *so_loads[0x50]; +static const struct inst *so_cldw [0x0A]; +static const struct inst *so_cldd [0x0A]; +static const struct inst *so_float[0x04]; +static const struct inst *so_fstq [0x0A]; +static const struct inst *so_ebran[0x08]; +static const struct inst *so_addit[0x02]; +static const struct inst *so_addi [0x02]; +static const struct inst *so_subi [0x02]; +static const struct inst *so_shext[0x08]; +static const struct inst *so_deps [0x08]; + +#define ILLEG (const struct inst **)&illeg +#define NENTS(a) (sizeof(a)/sizeof(a[0])-1) +static struct majoropcode majopcs[NMAJOPCS] = { + { so_sysop, NENTS(so_sysop) }, /* 00 */ + { so_mmuop, NENTS(so_mmuop) }, /* 01 */ + { so_arith, NENTS(so_arith) }, /* 02 */ + { so_loads, NENTS(so_loads) }, /* 03 */ + { ILLEG, 1 }, /* 04 */ + { ILLEG, 1 }, /* 05 */ + { ILLEG, 1 }, /* 06 */ + { ILLEG, 1 }, /* 07 */ + { ILLEG, 1 }, /* 08 */ + { so_cldw , NENTS(so_cldw ) }, /* 09 */ + { ILLEG, 1 }, /* 0A */ + { so_cldd , NENTS(so_cldd ) }, /* 0B */ + { ILLEG, 1 }, /* 0C */ + { ILLEG, 1 }, /* 0D */ + { so_float, NENTS(so_float) }, /* 0E */ + { so_fstq , NENTS(so_fstq ) }, /* 0F */ + { ILLEG, 1 }, /* 10 */ + { ILLEG, 1 }, /* 11 */ + { ILLEG, 1 }, /* 12 */ + { ILLEG, 1 }, /* 13 */ + { ILLEG, 1 }, /* 14 */ + { ILLEG, 1 }, /* 15 */ + { ILLEG, 1 }, /* 16 */ + { ILLEG, 1 }, /* 17 */ + { ILLEG, 1 }, /* 18 */ + { ILLEG, 1 }, /* 19 */ + { ILLEG, 1 }, /* 1A */ + { ILLEG, 1 }, /* 1B */ + { ILLEG, 1 }, /* 1C */ + { ILLEG, 1 }, /* 1D */ + { ILLEG, 1 }, /* 1E */ + { ILLEG, 1 }, /* 1F */ + { ILLEG, 1 }, /* 20 */ + { ILLEG, 1 }, /* 21 */ + { ILLEG, 1 }, /* 22 */ + { ILLEG, 1 }, /* 23 */ + { ILLEG, 1 }, /* 24 */ + { so_subi , NENTS(so_subi ) }, /* 25 */ + { ILLEG, 1 }, /* 26 */ + { ILLEG, 1 }, /* 27 */ + { ILLEG, 1 }, /* 28 */ + { ILLEG, 1 }, /* 29 */ + { ILLEG, 1 }, /* 2A */ + { ILLEG, 1 }, /* 2B */ + { so_addit, NENTS(so_addit) }, /* 2C */ + { so_addi , NENTS(so_addi ) }, /* 2D */ + { ILLEG, 1 }, /* 2E */ + { ILLEG, 1 }, /* 2F */ + { ILLEG, 1 }, /* 30 */ + { ILLEG, 1 }, /* 31 */ + { ILLEG, 1 }, /* 32 */ + { ILLEG, 1 }, /* 33 */ + { so_shext, NENTS(so_shext) }, /* 34 */ + { so_deps , NENTS(so_deps ) }, /* 35 */ + { ILLEG, 1 }, /* 36 */ + { ILLEG, 1 }, /* 37 */ + { ILLEG, 1 }, /* 38 */ + { ILLEG, 1 }, /* 39 */ + { so_ebran, NENTS(so_ebran) }, /* 3A */ + { ILLEG, 1 }, /* 3B */ + { ILLEG, 1 }, /* 3C */ + { ILLEG, 1 }, /* 3D */ + { ILLEG, 1 }, /* 3E */ + { ILLEG, 1 }, /* 3F */ +}; +#undef NENTS +#undef ILLEG + +/*-------------------------------------------------------------------------- + * instruction$ExecutionInitialize - Initialize the instruction execution + * data structures. + *---------------------------------------------------------------------------*/ +int +iExInit(void) +{ + static int unasm_initted = 0; + register const struct inst *i; + register struct majoropcode *m; + u_int shft, mask; + + if (unasm_initted) + return 0; + + /* + * Determine maxsubop for each major opcode. + * Also, check all instructions of a given major opcode + * for consistent opcode extension field definition, and + * save a converted form of this definition in the majopcs + * entry for this major opcode. + */ + for (i = &instrs[0]; *i->mnem; i++) { + m = &majopcs[i->majopc]; + if (m->maxsubop < i->opcext) + panic("iExInit not enough space for opcode %d", + i->majopc); + shft = 32 - i->extbs - i->extbl; + mask = (1 << i->extbl) - 1; + if (m->extshft || m->extmask) { + if (m->extshft != shft || m->extmask != mask) { + db_printf("%s - Bad instruction initialization!\n", i->mnem); + return (0); + } + } else { + m->extshft = shft; + m->extmask = mask; + } + } + + /* + * Lastly, fill in all legal subops with the appropriate info. + */ + for (i = &instrs[0]; *i->mnem; i++) { + m = &majopcs[i->majopc]; + if (m->maxsubop == 1) + m->subops = (const struct inst **)i; + else + m->subops[i->opcext] = i; + } + + unasm_initted++; + return (1); +} + + + +/*##################### Functions and Subroutines ##########################*/ + +/**************************************/ +/* Miscellaneous Disassembly Routines */ +/**************************************/ + +/* Add instructions */ +int +addDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%%r%d,%%r%d,%%r%d",addDCond(Cond4(w)), + Rsa(w),Rsb(w),Rtc(w)); + return (1); +} + +/* Unit instructions */ +int +unitDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf(unitDCond(Cond4(w))); + if (Match("dcor") || Match("idcor")) + db_printf("\t%%r%d,%%r%d",Rsb(w),Rtc(w)); + else + db_printf("\t%%r%d,%%r%d,%%r%d",Rsa(w),Rsb(w),Rtc(w)); + return (1); +} + +/* Immediate Arithmetic instructions */ +int +iaDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + if (Match("addi")) + db_printf("%s\t%d,%%r%d,%%r%d", + addDCond(Cond4(w)),Im11(w),Rsb(w),Rta(w)); + else + db_printf("%s\t%d,%%r%d,%%r%d", + subDCond(Cond4(w)),Im11(w),Rsb(w),Rta(w)); + return (1); +} + +/* Shift double instructions */ +int +shdDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + if (Match("vshd")) + db_printf("%s\t%%r%d,%%r%d,%%r%d", + edDCond(Cond(w)), Rsa(w),Rsb(w),Rtc(w)); + else + db_printf("%s\t%%r%d,%%r%d,%d,%%r%d", + edDCond(Cond(w)),Rsa(w),Rsb(w),31-Imd5(w),Rtc(w)); + return (1); +} + +/* Extract instructions */ +int +extrDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%%r%d,%d,%d,%%r%d", + edDCond(Cond(w)),Rsb(w),Imd5(w),32 - Rsc(w),Rta(w)); + return (1); +} + + +/* Variable extract instructions */ +int +vextrDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%%r%d,%d,%%r%d", + edDCond(Cond(w)),Rsb(w),32 - Rsc(w),Rta(w)); + return (1); +} + + +/* Deposit instructions */ +int +depDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%%r%d,%d,%d,%%r%d", + edDCond(Cond(w)),Rsa(w),31 - Imd5(w),32 - Rsc(w),Rtb(w)); + return (1); +} + + +/* Variable deposit instructions */ +int +vdepDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%%r%d,%d,%%r%d", + edDCond(Cond(w)),Rsa(w),32 - Rsc(w),Rtb(w)); + return (1); +} + + +/* Deposit Immediate instructions */ +int +depiDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%d,%d,%d,%%r%d", + edDCond(Cond(w)),Ima5(w),31 - Imd5(w),32 - Imc5A(w),Rtb(w)); + return (1); +} + +/* Variable Deposit Immediate instructions */ +int +vdepiDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%d,%d,%%r%d",edDCond(Cond(w)),Ima5(w),32-Imc5A(w),Rtb(w)); + return (1); +} + +/*--------------------------------------------------------------------------- + * conditionType$DisassembleCondition - Return a string which contains the + * ascii description of the passed numeric condition. + *---------------------------------------------------------------------------*/ + +char * +subDCond(cond) + u_int cond; +{ + switch(cond) { + case EQZ: return(",="); + case LT: return(",<"); + case LE: return(",<="); + case LLT: return(",<<"); + case LLE: return(",<<="); + case SV: return(",sv"); + case OD: return(",od"); + case NEQZ: return(",<>"); + case GE: return(",>="); + case GT: return(",>"); + case LGE: return(",>>="); + case LGT: return(",>>"); + case NSV: return(",nsv"); + case EV: return(",ev"); + case TR: return(",tr"); + case NEV: return(""); + default: + panic("subDCond: unknown condition"); + } +} + + +/*--------------------------------------------------------------------------- + * conditionType$DisassembleCondition - Return a string which contains the + * ascii description of the passed numeric condition. + *---------------------------------------------------------------------------*/ + +char * +addDCond(cond) + u_int cond; +{ + switch(cond) { + case EQZ: return(",="); + case LT: return(",<"); + case LE: return(",<="); + case NUV: return(",nuv"); + case ZNV: return(",znv"); + case SV: return(",sv"); + case OD: return(",od"); + case NEQZ: return(",<>"); + case GE: return(",>="); + case GT: return(",>"); + case UV: return(",uv"); + case VNZ: return(",vnz"); + case NSV: return(",nsv"); + case EV: return(",ev"); + case TR: return(",tr"); + case NEV: return(""); + default: + panic("addDCond: unknown condition"); + } +} + +char * +unitDCond(cond) + u_int cond; +{ + switch(cond) { + case SHC: return(",shc"); + case SHZ: return(",shz"); + case SBC: return(",sbc"); + case SBZ: return(",sbz"); + case SDC: return(",sdc"); + case NHC: return(",nhc"); + case NHZ: return(",nhz"); + case NBC: return(",nbc"); + case NBZ: return(",nbz"); + case NDC: return(",ndc"); + case TR: return(",tr"); + case NEV: return(""); + default: + panic("unitDCond: unknown condition"); + } +} + +char * +edDCond(cond) + u_int cond; +{ + switch(cond) { + case XOD: return(",od"); + case XTR: return(",tr"); + case XNE: return(",<>"); + case XLT: return(",<"); + case XEQ: return(",="); + case XGE: return(",>="); + case XEV: return(",ev"); + case NEV: return(""); + default: + panic("edDCond: unknown condition"); + } +} + + + +/****************************************/ +/* Format Specific Disassembly Routines */ +/****************************************/ + + +/* Load [modify] instructions */ +int +ldDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register int d = Disp(w); + char s[2]; + + s[1] = '\0'; + if (d < 0) { + d = -d; + s[0] = '-'; + } else + s[0] = '\0'; + + if (Rsb(w) == 0 && Match("ldo")) { + db_printf("ldi\t%s%X,%%r%d",s,d,Rta(w)); + return (1); + } + db_printf("%s\t%s%s%X",i->mnem,(d < 2048? "R'":""), s, d); + if (Dss(w)) + db_printf("(%%sr%d,%%r%d),%%r%d",Dss(w),Rsb(w),Rta(w)); + else + db_printf("(%%r%d),%%r%d",Rsb(w),Rta(w)); + return (1); +} + +/* Store [modify] instructions */ +int +stDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register int d = Disp(w); + char s[2]; + + db_printf("\t%%r%d,",Rta(w)); + + s[1] = '\0'; + if (d < 0) { + d = -d; + s[0] = '-'; + } else + s[0] = '\0'; + + db_printf("%s%s%X", (d < 2048? "R'":""), s, d); + + if (Dss(w)) + db_printf("(%%sr%d,%%r%d)",Dss(w),Rsb(w)); + else + db_printf("(%%r%d)",Rsb(w)); + return (1); +} + +/* Load indexed instructions */ +int +ldxDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register const char *p; + + if (ShortDisp(w)) { + db_printf("s"); + if (Modify(w)) + db_printf(",m%s", ModBefore(w)? "b": "a"); + } else { + db_printf("x"); + if (Modify(w)) + db_printf(",%sm", IndxShft(w)? "s":""); + } + switch (CacheCtrl(w)) { + case NOACTION: p = ""; break; + case STACKREF: p = ",c"; break; + case SEQPASS: p = ",q"; break; + case PREFETCH: p = ",p"; break; + } + if (ShortDisp(w)) + db_printf("%s\t%d", p, Ima5(w)); + else + db_printf("%s\t%%r%d", p, Rsa(w)); + + if (Dss(w)) + db_printf("(%%sr%d,%%r%d),%%r%d",Dss(w),Rsb(w),Rtc(w)); + else + db_printf("(%%r%d),%%r%d",Rsb(w),Rtc(w)); + return (1); +} + +/* Store short displacement instructions */ +int +stsDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register const char *p; + if (Modify(w)) + db_printf(",m%s", ModBefore(w)? "b":"a"); + + switch (CacheCtrl(w)) { + case NOACTION: p = ""; break; + case STACKREF: p = ",c"; break; + case SEQPASS: p = ",q"; break; + case PREFETCH: p = ",p"; break; + } + db_printf("%s\t%%r%d,", p, Rta(w)); + if (Dss(w)) + db_printf("%d(%%sr%d,%%r%d)",Imc5(w),Dss(w),Rsb(w)); + else + db_printf("%d(%%r%d)",Imc5(w),Rsb(w)); + return (1); +} + +/* Store Bytes Instruction */ +int +stbysDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register const char *p; + db_printf(ModBefore(w)? ",e":",b"); + if (Modify(w)) + db_printf(",m"); + switch (CacheCtrl(w)) { + case NOACTION: p = ""; break; + case STACKREF: p = ",f"; break; + case SEQPASS: p = ",r"; break; + case PREFETCH: p = ",z"; break; + } + db_printf("%s\t%%r%d,", p, Rta(w)); + if (Dss(w)) + db_printf("%d(%%sr%d,%%r%d)",Imc5(w),Dss(w),Rsb(w)); + else + db_printf("%d(%%r%d)",Imc5(w),Rsb(w)); + return (1); +} + +/* Long Immediate instructions */ +int +limmDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("\tL'%X,%%r%d", Im21(w), Rtb(w)); + return (1); +} + + +/* Branch and Link instruction(s) (Branch, too!!) */ +int +blDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register OFS tgtofs = ofs + 8 + Bdisp(w); + register u_int link = Rtb(w); + + if (link && !Match("gate")) + db_printf("l"); + if (Nu(w)) + db_printf(",n"); + db_printf("\t"); + + db_printsym((db_addr_t)tgtofs, DB_STGY_ANY, db_printf); + + if (link || Match("gate")) + db_printf(",%%r%d",link); + + return (1); +} + +/* Branch Register instruction */ +int +brDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%%r%d,%%r%d", Nu(w)?",n":"", Rsa(w), Rtb(w)); + return (1); +} + +/* Dispatch instructions */ +int +bvDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("%s\t%%r%d(%%r%d)", Nu(w)?",n":"", Rsa(w), Rsb(w)); + return (1); +} + +/* Branch External instructions */ +int +beDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register int d = Bdisp(w); + register const char *p; + char s[2]; + + s[1] = '\0'; + if (d < 0) { + d = -d; + s[0] = '-'; + } else + s[0] = '\0'; + + p = Nu(w)? ",n":""; + db_printf("%s\tR'%s%X(%%sr%d,%%r%d)", p, s, d, Sr(w), Rsb(w)); + return (1); +} + + +/* Compare/Add and Branch instructions */ +int +cbDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register OFS tgtofs = ofs + 8 + Cbdisp(w); + + if (Match("movb")) + db_printf(edDCond(Cond(w))); + else if (Match("addb")) + db_printf(addDCond(Cond(w) << 1)); + else + db_printf(subDCond(Cond(w) << 1)); + db_printf("%s\t%%r%d,%%r%d,", Nu(w)?",n":"", Rsa(w), Rsb(w)); + db_printsym((db_addr_t)tgtofs, DB_STGY_ANY, db_printf); + return (1); +} + +/* Compare/Add and Branch Immediate instructions */ +int +cbiDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register OFS tgtofs = ofs + 8 + Cbdisp(w); + + if (Match("movib")) + db_printf(edDCond(Cond(w))); + else if (Match("addib")) + db_printf(addDCond(Cond(w) << 1)); + else + db_printf(subDCond(Cond(w) << 1)); + db_printf("%s\t%d,%%r%d,", Nu(w)? ",n":"", Ima5(w), Rsb(w)); + db_printsym((db_addr_t)tgtofs, DB_STGY_ANY, db_printf); + return (1); +} + +/* Branch on Bit instructions */ +int +bbDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register OFS tgtofs = ofs + 8 + Cbdisp(w); + register const char *p; + + db_printf(edDCond(Cond(w))); + p = Nu(w)? ",n":""; + if (Match("bvb")) + db_printf("%s\t%%r%d,", p, Rta(w)); + else + db_printf("%s\t%%r%d,%d,", p, Rsa(w), Imb5(w)); + db_printsym((db_addr_t)tgtofs, DB_STGY_ANY, db_printf); + return (1); +} + +/* Arithmetic instructions */ +int +ariDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + if (Match("or") && Rsb(w) == 0 && Cond4(w) == NEV) { + if (Rsa(w) == 0 && Rtc(w) == 0) + db_printf("nop"); + else + db_printf("copy\t%%r%d,%%r%d",Rsa(w),Rtc(w)); + } else + db_printf("%s%s\t%%r%d,%%r%d,%%r%d", i->mnem, + subDCond(Cond4(w)), Rsa(w),Rsb(w),Rtc(w)); + return(1); +} + +/* System control operations */ +int +scDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + if (Match("mtctl")) { + if (Rtb(w) == 11) + db_printf("mtsar\t%%r%d",Rsa(w)); + else + db_printf("mtctl\t%%r%d,%%cr%d",Rsa(w),Rtb(w)); + return (1); + } + db_printf(i->mnem); + if (Match("ssm") || Match("rsm")) + db_printf("\t%d,%%r%d",Ima5A(w),Rtc(w)); + else if (Match("mtsm")) db_printf("\t%%r%d",Rsa(w)); + else if (Match("ldprid")) db_printf("\t%%r%d",Rtc(w)); + else if (Match("mtsp")) db_printf("\t%%r%d,%%sr%d",Rsa(w),Sr(w)); + else if (Match("mfsp")) db_printf("\t%%sr%d,%%r%d",Sr(w),Rtc(w)); + else if (Match("mfctl")) db_printf("\t%%cr%d,%%r%d",Rsb(w),Rtc(w)); + else if (Match("ldsid")) { + if (Dss(w)) + db_printf("\t(%%sr%d,%%r%d),%%r%d",Dss(w),Rsb(w),Rtc(w)); + else + db_printf("\t(%%r%d),%%r%d",Rsb(w),Rtc(w)); + } else + return (0); + + return (1); +} + +/* Instruction cache/tlb control instructions */ +int +mmgtDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + if (Match("probe")) { + if (ProbeI(w)) { + if (Dss(w)) + db_printf("i\t(%%sr%d,%%r%d),%d,%%r%d", + Dss(w),Rsb(w),Rsa(w),Rtc(w)); + else + db_printf("i\t(%%r%d),%d,%%r%d", + Rsb(w),Rsa(w),Rtc(w)); + } else { + if (Dss(w)) + db_printf("\t(%%sr%d,%%r%d),%%r%d,%%r%d", + Dss(w),Rsb(w),Rsa(w),Rtc(w)); + else + db_printf("\t(%%r%d),%%r%d,%%r%d", + Rsb(w),Rsa(w),Rtc(w)); + } + } + else if (Match("lha") || Match("lpa")) { + if (Modify(w)) + db_printf(",m"); + if (Dss(w)) + db_printf("\t%%r%d(%%sr%d,%%r%d),%%r%d", + Rsa(w),Dss(w),Rsb(w),Rtc(w)); + else + db_printf("\t%%r%d(%%r%d),%%r%d",Rsa(w),Rsb(w),Rtc(w)); + } + else if (Match("pdtlb") || Match("pdc") || Match("fdc")) { + if (Modify(w)) db_printf(",m"); + if (Dss(w)) + db_printf("\t%%r%d(%%sr%d,%%r%d)",Rsa(w),Dss(w),Rsb(w)); + else + db_printf("\t%%r%d(%%r%d)",Rsa(w),Rsb(w)); + } + else if (Match("pitlb") || Match("fic")) { + if (Modify(w)) + db_printf(",m"); + db_printf("\t%%r%d(%%sr%d,%%r%d)",Rsa(w),Sr(w),Rsb(w)); + } + else if (Match("idtlb")) { + if (Dss(w)) + db_printf("\t%%r%d,(%%sr%d,%%r%d)",Rsa(w),Dss(w),Rsb(w)); + else + db_printf("\t%%r%d,(%%r%d)",Rsa(w),Rsb(w)); + } + else if (Match("iitlb")) + db_printf("\t%%r%d,(%%sr%d,%%r%d)",Rsa(w),Sr(w),Rsb(w)); + else + return (0); + + return(1); +} + +/* break instruction */ +int +brkDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + db_printf("\t%d,%d",Bi1(w),Bi2(w)); + return (1); +} + +int +floatDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register u_int op1, r1, fmt, t; + u_int op2, r2, dfmt; + char *p; + + op1 = CoprExt1(w); + op2 = CoprExt2(w); + fmt = (op1 >> 2) & 3; /* get precision of source */ + +#define ST(r) ((fmt & 1)? fdreg[(r)]:fsreg[(r)]) + /* + * get first (or only) source register + * (independent of class) + */ + r1 = (op1 >> 11) & 0x3e; + if ((fmt & 1) == 0 && (Uid(w) & 2)) + r1++; + + if (op1 & 2) { /* class 2 or 3 */ + /* + * get second source register + */ + r2 = (op1 >> 6) & 0x3e; + if (fmt == 2) + r2++; + + if ((op1 & 1) == 0) { /* class 2 */ + /* Opclass 2: 2 sources, no destination */ + switch((op1 >> 4) & 7) { + case 0: + p = "cmp"; + break; + default: + return(0); + } + db_printf("%s,%s",p,fmtStrTbl[fmt]); + db_printf(",%s\t%%f%s,%%f%s", + condStrTbl[op2], ST(r1), ST(r2)); + return (1); + } + /* + * get target register (class 3) + */ + t = (op2 << 1); + if ((fmt & 1) == 0 && (Uid(w) & 1)) + t++; + /* Opclass 3: 2 sources, 1 destination */ + switch((op1 >> 4) & 7) { + case 0: p = "add"; break; + case 1: p = "sub"; break; + case 2: p = (Fpi(w)) ? "mpyi" : "mpy"; break; + case 3: p = "div"; break; + case 4: p = "rem"; break; + default: return (0); + } + db_printf("%s,%s", p, fmtStrTbl[fmt]); + db_printf("\t%%f%s,%%f%s,%%f%s",ST(r1),ST(r2),ST(t)); + } else if (op1 & 1) { /* class 1 */ + dfmt = (op1 >> 4) & 3; +#define DT(r) ((dfmt & 1)? fdreg[(r)]:fsreg[(r)]) + + /* + * get target register + */ + t = (op2 << 1); + if ((dfmt & 1) == 0 && (Uid(w) & 1)) + t++; + /* Opclass 1: 1 source, 1 destination conversions */ + switch((op1 >> 6) & 3) { + case 0: p = "ff"; break; + case 1: p = "xf"; break; + case 2: p = "fx"; break; + case 3: p = "fxt"; break; + } + db_printf("%s,%s", p, fmtStrTbl[fmt]); + db_printf(",%s\t%%f%s,%%f%s",fmtStrTbl[dfmt],ST(r1),DT(t)); + } else { /* class 0 */ + /* + * get target register + */ + t = (op2 << 1); + if ((fmt & 1) == 0 && (Uid(w) & 1)) + t++; + /* Opclass 0: 1 source, 1 destination */ + switch((op1 >> 4) & 7) { + case 1: p = "rsqrt"; break; + case 2: p = "cpy"; break; + case 3: p = "abs"; break; + case 4: p = "sqrt"; break; + case 5: p = "rnd"; break; + default: return (0); + } + db_printf("%s,%s",p,fmtStrTbl[fmt]); + db_printf("\t%%f%s,%%f%s",ST(r1),ST(t)); + } + return (1); +} + +int +fcoprDasm(w, op1, op2) + int w; + u_int op1, op2; +{ + register u_int r1, r2, t, fmt, dfmt; + register char *p; + + if (AstNu(w) && op1 == ((1<<4) | 2)) { + if (op2 == 0 || op2 == 1 || op2 == 2) { + db_printf("ftest"); + if (op2 == 1) + db_printf(",acc"); + else if (op2 == 2) + db_printf(",rej"); + return (1); + } + return (0); + } else if (0 == op1 && 0 == op2) { + db_printf("fcopr identify"); + return (1); + } + switch(op1 & 3) { + case 0: + /* Opclass 0: 1 source, 1 destination */ + r1 = (op1 >> 12) & 0x1f; t = op2; fmt = (op1 >> 2) & 3; + switch((op1 >> 4) & 7) { + case 1: p = "rsqrt"; break; + case 2: p = "cpy"; break; + case 3: p = "abs"; break; + case 4: p = "sqrt"; break; + case 5: p = "rnd"; break; + default: return(0); + } + db_printf("f%s,%s\t%%fr%d,%%fr%d", p, fmtStrTbl[fmt], r1, t); + break; + case 1: + /* Opclass 1: 1 source, 1 destination conversions */ + r1 = (op1 >> 12) & 0x1f; t = op2; + fmt = (op1 >> 2) & 3; dfmt = (op1 >> 4) & 3; + switch((op1 >> 6) & 3) { + case 0: p = "ff"; break; + case 1: p = "xf"; break; + case 2: p = "fx"; break; + case 3: p = "fxt"; break; + } + db_printf("fcnv%s,%s,%s\t%%fr%d,%%fr%d", + p, fmtStrTbl[fmt], fmtStrTbl[dfmt], r1, t); + break; + case 2: + /* Opclass 2: 2 sources, no destination */ + r1 = (op1 >> 12) & 0x1f; r2 = (op1 >> 7) & 0x1f; + fmt = (op1 >> 2) & 3; + switch((op1 >> 4) & 7) { + case 0: p = "fcmp"; break; + default: return (0); + } + db_printf("%s,%s,%s\t%%fr%d,%%fr%d", + p,fmtStrTbl[fmt],condStrTbl[op2],r1,r2); + break; + case 3: + /* Opclass 3: 2 sources, 1 destination */ + r1 = (op1 >> 12) & 0x1f; r2 = (op1 >> 7) & 0x1f; t = op2; + fmt = (op1 >> 2) & 3; + switch((op1 >> 4) & 7) { + case 0: p = "add"; break; + case 1: p = "sub"; break; + case 2: p = "mpy"; break; + case 3: p = "div"; break; + case 4: p = "rem"; break; + default: return (0); + } + db_printf("f%s,%s\t%%fr%d,%%fr%d,%%fr%d", + p, fmtStrTbl[fmt], r1, r2, t); + break; + default: + return(0); + } + return (1); +} + +int +coprDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register u_int uid = Uid(w); + register int load = 0; + register char *pfx = uid > 1 ? "c" : "f"; + register int dreg = 0; + + if (Match("copr")) { + if (uid) { + db_printf("copr,%d,0x%x",uid,CoprExt(w)); + if (AstNu(w)) + db_printf(",n"); + return (1); + } + return fcoprDasm(w, CoprExt1(w),CoprExt2(w)); + } + if (Match("cldd")) { + dreg = 1; + load = 1; + db_printf("%sldd",pfx); + } else if (Match("cldw")) { + load = 1; + db_printf("%sldw",pfx); + } else if (Match("cstd")) { + dreg = 1; + db_printf("%sstd",pfx); + } else if (Match("cstw")) + db_printf("%sstw",pfx); + else + return (0); + + if (ShortDisp(w)) { + db_printf("s"); + if (AstNu(w)) + db_printf(",m%s", ModBefore(w)?"b":"a"); + } + else { + db_printf("x"); + if (AstNu(w)) + db_printf(",%sm", IndxShft(w)?"s":""); + else if (IndxShft(w)) + db_printf(",s"); + } + switch (CacheCtrl(w)) { + case NOACTION: break; + case STACKREF: db_printf(",c"); break; + case SEQPASS: db_printf(",q"); break; + case PREFETCH: db_printf(",p"); break; + } + if (load) { + register const char *p; + + if (dreg) + p = fdreg[(Rtc(w)<<1)+(uid&1)]; + else + p = fsreg[(Rtc(w)<<1)+(uid&1)]; + + if (ShortDisp(w)) + db_printf("\t%d",Ima5(w)); + else + db_printf("\t%%r%d",Rsa(w)); + if (Dss(w)) + db_printf("(%%sr%d,%%r%d),%%f%s", Dss(w),Rsb(w), p); + else + db_printf("(%%r%d),%%f%s",Rsb(w), p); + } else { + register const char *p; + + if (dreg) + p = fdreg[(Rsc(w)<<1)+(uid&1)]; + else + p = fsreg[(Rsc(w)<<1)+(uid&1)]; + + if (ShortDisp(w)) + db_printf("\t%%f%s,%d", p, Ima5(w)); + else + db_printf("\t%%f%s,%%r%d", p, Rta(w)); + if (Dss(w)) + db_printf("(%%sr%d,%%r%d)",Dss(w),Rsb(w)); + else + db_printf("(%%r%d)",Rsb(w)); + } + return (1); +} + +int +lpkDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + /* + * Floating point STore Quad + * Short or Indexed + */ + if (ShortDisp(w)) { + if (Modify(w)) + db_printf(",m%s", ModBefore(w)?"b":"a"); + } else { + if (Modify(w)) + db_printf(",%sm", IndxShft(w)? "s":""); + else if (IndxShft(w)) + db_printf(",s"); + } + switch (CacheCtrl(w)) { + case NOACTION: break; + case STACKREF: db_printf(",c"); break; + case SEQPASS: db_printf(",q"); break; + case PREFETCH: db_printf(",p"); break; + } + if (ShortDisp(w)) + db_printf("\t%%fr%d,%d",Rsc(w),Ima5(w)); + else + db_printf("\t%%fr%d,%%r%d",Rsc(w),Rta(w)); + if (Dss(w)) + db_printf("(%%sr%d,%%r%d)",Dss(w),Rsb(w)); + else + db_printf("(%%r%d)",Rsb(w)); + return (1); +} + +int +diagDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + if (0x0b0 == BitfR(w,19,8,_b198)) /* mtcpu */ + db_printf("mtcpu\t%%r%d,%%dr%d", Rsa(w), Rtb(w)); + else if (0x0d0 == BitfR(w,19,8,_b198)) /* mfcpu */ + db_printf("mfcpu\t%%dr%d,%%r%d", Rsb(w), Rta(w)); + else { + db_printf(i->mnem); + if (Match("diag")) + db_printf("\t0x%X",w & 0x03ffffff); + else + return (0); + } + return (1); +} + +int +fmpysubDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + if (SinglePrec(w)) + db_printf("SUB,SGL\t%%f%s,%%f%s,%%f%s,%%f%s,%%f%s", + fsreg[Ms1(w)], fsreg[Ms2(w)], fsreg[Mt(w)], + fsreg[As(w)], fsreg[Ad(w)]); + else + db_printf("SUB,DBL\t%%f%s,%%f%s,%%f%s,%%f%s,%%f%s", + fdreg[Ms1(w)], fdreg[Ms2(w)], fdreg[Mt(w)], + fdreg[As(w)], fdreg[Ad(w)]); + return (1); +} + +int +fmpyaddDasm(i, ofs, w) + const struct inst *i; + OFS ofs; + int w; +{ + register const char + *ms1 = SinglePrec(w) ? fsreg[Ms1(w)] : fdreg[Ms1(w)], + *ms2 = SinglePrec(w) ? fsreg[Ms2(w)] : fdreg[Ms2(w)], + *mt = SinglePrec(w) ? fsreg[Mt(w)] : fdreg[Mt(w)], + *as = SinglePrec(w) ? fsreg[As(w)] : fdreg[As(w)], + *ad = SinglePrec(w) ? fsreg[Ad(w)] : fdreg[Ad(w)]; + + if (Rsd(w) == 0) + db_printf("\t%%fcfxt,%s,%%f%s,%%f%s,%%f%s", + ((SinglePrec(w)) ? "sgl" : "dbl"), ms1, ms2, mt); + else + db_printf("add%s\t%%f%s,%%f%s,%%f%s,%%f%s,%%f%s", + ((SinglePrec(w)) ? "sgl" : "dbl"), ms1, ms2, mt, as, ad); + + return (1); +} + +vaddr_t +db_disasm(loc, flag) + vaddr_t loc; + boolean_t flag; +{ + register const struct inst *i; + register const struct majoropcode *m; + register u_int ext; + int ok, instruct; + OFS ofs = 0; + + iExInit(); +/* TODO if (loc == PC_REGS(&ddb_regs) && ddb_regs.tf_iir) + instruct = ddb_regs.tf_iir; + else */ if (USERMODE(loc)) { + if (copyin((caddr_t)(loc &~ HPPA_PC_PRIV_MASK), + &instruct, sizeof(instruct))) + instruct = 0; + } else + instruct = *(int *)loc; + + ok = 0; + m = &majopcs[Opcode(instruct)]; + ext = OpExt(instruct, m); + if (ext <= m->maxsubop) { + /* special hack for majopcs table layout */ + if (m->maxsubop == 1) + i = (const struct inst *)m->subops; + else + i = m->subops[ext]; + + if (i && i->mnem[0] != '?') { + if (i->dasmfcn != coprDasm && i->dasmfcn != diagDasm && + i->dasmfcn != ariDasm && i->dasmfcn != scDasm && + i->dasmfcn != ldDasm) + db_printf(i->mnem); + if (i->dasmfcn) + ok = (*i->dasmfcn)(i, ofs, instruct); + } + } + + if (!ok) + db_printf("<%08x>", instruct); + + db_printf("\n"); + return (loc + sizeof(instruct)); +} diff --git a/sys/arch/hppa64/hppa64/db_interface.c b/sys/arch/hppa64/hppa64/db_interface.c new file mode 100644 index 00000000000..8467caa93db --- /dev/null +++ b/sys/arch/hppa64/hppa64/db_interface.c @@ -0,0 +1,320 @@ +/* $OpenBSD: db_interface.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define DDB_DEBUG + +#include <sys/param.h> +#include <sys/systm.h> + +#include <machine/db_machdep.h> +#include <machine/frame.h> + +#include <ddb/db_access.h> +#include <ddb/db_command.h> +#include <ddb/db_output.h> +#include <ddb/db_run.h> +#include <ddb/db_sym.h> +#include <ddb/db_var.h> +#include <ddb/db_variables.h> +#include <ddb/db_extern.h> +#include <ddb/db_interface.h> + +#include <dev/cons.h> + +void kdbprinttrap(int, int); + +extern char *trap_type[]; +extern int trap_types; + +db_regs_t ddb_regs; +struct db_variable db_regs[] = { + { "flags", (long *)&ddb_regs.tf_flags, FCN_NULL }, + { "r1", (long *)&ddb_regs.tf_r1, FCN_NULL }, + { "rp", (long *)&ddb_regs.tf_rp, FCN_NULL }, + { "r3", (long *)&ddb_regs.tf_r3, FCN_NULL }, + { "r4", (long *)&ddb_regs.tf_r4, FCN_NULL }, + { "r5", (long *)&ddb_regs.tf_r5, FCN_NULL }, + { "r6", (long *)&ddb_regs.tf_r6, FCN_NULL }, + { "r7", (long *)&ddb_regs.tf_r7, FCN_NULL }, + { "r8", (long *)&ddb_regs.tf_r8, FCN_NULL }, + { "r9", (long *)&ddb_regs.tf_r9, FCN_NULL }, + { "r10", (long *)&ddb_regs.tf_r10, FCN_NULL }, + { "r11", (long *)&ddb_regs.tf_r11, FCN_NULL }, + { "r12", (long *)&ddb_regs.tf_r12, FCN_NULL }, + { "r13", (long *)&ddb_regs.tf_r13, FCN_NULL }, + { "r14", (long *)&ddb_regs.tf_r14, FCN_NULL }, + { "r15", (long *)&ddb_regs.tf_r15, FCN_NULL }, + { "r16", (long *)&ddb_regs.tf_r16, FCN_NULL }, + { "r17", (long *)&ddb_regs.tf_r17, FCN_NULL }, + { "r18", (long *)&ddb_regs.tf_r18, FCN_NULL }, + { "r19", (long *)&ddb_regs.tf_args[7], FCN_NULL }, + { "r20", (long *)&ddb_regs.tf_args[6], FCN_NULL }, + { "r21", (long *)&ddb_regs.tf_args[5], FCN_NULL }, + { "r22", (long *)&ddb_regs.tf_args[4], FCN_NULL }, + { "r23", (long *)&ddb_regs.tf_args[3], FCN_NULL }, + { "r24", (long *)&ddb_regs.tf_args[2], FCN_NULL }, + { "r25", (long *)&ddb_regs.tf_args[1], FCN_NULL }, + { "r26", (long *)&ddb_regs.tf_args[0], FCN_NULL }, + { "r27", (long *)&ddb_regs.tf_dp, FCN_NULL }, + { "r28", (long *)&ddb_regs.tf_ret0, FCN_NULL }, + { "r29", (long *)&ddb_regs.tf_ret1, FCN_NULL }, + { "r30", (long *)&ddb_regs.tf_sp, FCN_NULL }, + { "r31", (long *)&ddb_regs.tf_r31, FCN_NULL }, + { "sar", (long *)&ddb_regs.tf_sar, FCN_NULL }, + + { "rctr", (long *)&ddb_regs.tf_rctr, FCN_NULL }, + { "ccr", (long *)&ddb_regs.tf_ccr, FCN_NULL }, + { "eirr", (long *)&ddb_regs.tf_eirr, FCN_NULL }, + { "eiem", (long *)&ddb_regs.tf_eiem, FCN_NULL }, + { "iir", (long *)&ddb_regs.tf_iir, FCN_NULL }, + { "isr", (long *)&ddb_regs.tf_isr, FCN_NULL }, + { "ior", (long *)&ddb_regs.tf_ior, FCN_NULL }, + { "ipsw", (long *)&ddb_regs.tf_ipsw, FCN_NULL }, + { "iisqh", (long *)&ddb_regs.tf_iisq[0], FCN_NULL }, + { "iioqh", (long *)&ddb_regs.tf_iioq[0], FCN_NULL }, + { "iisqt", (long *)&ddb_regs.tf_iisq[1], FCN_NULL }, + { "iioqt", (long *)&ddb_regs.tf_iioq[1], FCN_NULL }, + { "ci", (long *)&ddb_regs.tf_ci, FCN_NULL }, + { "vtop", (long *)&ddb_regs.tf_vtop, FCN_NULL }, + { "cr27", (long *)&ddb_regs.tf_cr27, FCN_NULL }, + { "cr30", (long *)&ddb_regs.tf_cr30, FCN_NULL }, + + { "sr0", (long *)&ddb_regs.tf_sr0, FCN_NULL }, + { "sr1", (long *)&ddb_regs.tf_sr1, FCN_NULL }, + { "sr2", (long *)&ddb_regs.tf_sr2, FCN_NULL }, + { "sr3", (long *)&ddb_regs.tf_sr3, FCN_NULL }, + { "sr4", (long *)&ddb_regs.tf_sr4, FCN_NULL }, + { "sr5", (long *)&ddb_regs.tf_sr5, FCN_NULL }, + { "sr6", (long *)&ddb_regs.tf_sr6, FCN_NULL }, + { "sr7", (long *)&ddb_regs.tf_sr7, FCN_NULL }, + + { "pidr1", (long *)&ddb_regs.tf_pidr1, FCN_NULL }, + { "pidr2", (long *)&ddb_regs.tf_pidr2, FCN_NULL }, +}; +struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); +int db_active = 0; + +void +Debugger() +{ + __asm __volatile ("break %0, %1" + :: "i" (HPPA_BREAK_KERNEL), "i" (HPPA_BREAK_KGDB)); +} + +void +db_read_bytes(addr, size, data) + vaddr_t addr; + size_t size; + char *data; +{ + register char *src = (char *)addr; + + while (size--) + *data++ = *src++; +} + +void +db_write_bytes(addr, size, data) + vaddr_t addr; + size_t size; + char *data; +{ + register char *dst = (char *)addr; + + while (size--) + *dst++ = *data++; + + /* unfortunately ddb does not provide any hooks for these */ + ficache(HPPA_SID_KERNEL, (vaddr_t)data, size); + fdcache(HPPA_SID_KERNEL, (vaddr_t)data, size); +} + + +/* + * Print trap reason. + */ +void +kdbprinttrap(type, code) + int type, code; +{ + type &= ~T_USER; /* just in case */ + db_printf("kernel: "); + if (type >= trap_types || type < 0) + db_printf("type 0x%x", type); + else + db_printf("%s", trap_type[type]); + db_printf(" trap, code=0x%x\n", code); +} + +/* + * kdb_trap - field a BPT trap + */ +int +kdb_trap(type, code, regs) + int type, code; + db_regs_t *regs; +{ + extern label_t *db_recover; + int s; + + switch (type) { + case T_IBREAK: + case T_DBREAK: + case -1: + break; + default: + if (!db_panic) + return (0); + + kdbprinttrap(type, code); + if (db_recover != 0) { + db_error("Caught exception in DDB; continuing...\n"); + /* NOT REACHED */ + } + } + + /* XXX Should switch to kdb`s own stack here. */ + + s = splhigh(); + bcopy(regs, &ddb_regs, sizeof(ddb_regs)); + db_active++; + cnpollc(TRUE); + db_trap(type, code); + cnpollc(FALSE); + db_active--; + bcopy(&ddb_regs, regs, sizeof(*regs)); + splx(s); + + return (1); +} + +/* + * Validate an address for use as a breakpoint. + * Any address is allowed for now. + */ +int +db_valid_breakpoint(addr) + db_addr_t addr; +{ + return (1); +} + +void +db_stack_trace_print(addr, have_addr, count, modif, pr) + db_expr_t addr; + int have_addr; + db_expr_t count; + char *modif; + int (*pr)(const char *, ...); +{ + register_t *fp, pc, rp, *argp; + db_sym_t sym; + db_expr_t off; + char *name; + char **argnp, *argnames[8]; + int nargs; + + if (count < 0) + count = 65536; + + if (!have_addr) { + fp = (register_t *)ddb_regs.tf_r3; + pc = ddb_regs.tf_iioq[0]; + rp = ddb_regs.tf_rp; + } else { + fp = (register_t *)addr; + pc = 0; + rp = ((register_t *)fp)[-5]; + } + +#ifdef DDB_DEBUG + (*pr) (">> %p, 0x%lx, 0x%lx\t", fp, pc, rp); +#endif + while (fp && count--) { + + if (USERMODE(pc)) + return; + + sym = db_search_symbol(pc, DB_STGY_ANY, &off); + db_symbol_values (sym, &name, NULL); + + (*pr)("%s(", name); + + /* args */ + nargs = 8; + argnp = NULL; + if (db_sym_numargs(sym, &nargs, argnames)) + argnp = argnames; + else + nargs = 4; + /* + * XXX first eight args are passed on registers, and may not + * be stored on stack, dunno how to recover their values yet + */ + for (argp = &fp[-9]; nargs--; argp--) { + if (argnp) + (*pr)("%s=", *argnp++); + (*pr)("%x%s", db_get_value((long)argp, 8, FALSE), + nargs? ",":""); + } + (*pr)(") at "); + db_printsym(pc, DB_STGY_PROC, pr); + (*pr)("\n"); + + /* TODO: print locals */ + + /* next frame */ + pc = rp; + rp = fp[-2]; + + /* if a terminal frame and not a start of a page + * then skip the trapframe and the terminal frame */ + if (!fp[0]) { + struct trapframe *tf; + + tf = (struct trapframe *)((char *)fp - sizeof(*tf)); + + if (tf->tf_flags & TFF_SYS) + (*pr)("-- syscall #%d(%lx, %lx, %lx, %lx, ...)\n", + tf->tf_r1, tf->tf_args[0], tf->tf_args[1], + tf->tf_args[2], tf->tf_args[3], + tf->tf_args[4], tf->tf_args[5], + tf->tf_args[6], tf->tf_args[7]); + else + (*pr)("-- trap #%d%s\n", tf->tf_flags & 0x3f, + (tf->tf_flags & T_USER)? " from user" : ""); + + if (!(tf->tf_flags & TFF_LAST)) { + fp = (register_t *)tf->tf_r3; + pc = tf->tf_iioq[0]; + rp = tf->tf_rp; + } else + fp = 0; + } else + fp = (register_t *)fp[0]; +#ifdef DDB_DEBUG + (*pr) (">> %p, 0x%lx, 0x%lx\t", fp, pc, rp); +#endif + } + + if (count && pc) { + db_printsym(pc, DB_STGY_XTRN, pr); + (*pr)(":\n"); + } +} diff --git a/sys/arch/hppa64/hppa64/disksubr.c b/sys/arch/hppa64/hppa64/disksubr.c new file mode 100644 index 00000000000..bddccac5a5c --- /dev/null +++ b/sys/arch/hppa64/hppa64/disksubr.c @@ -0,0 +1,986 @@ +/* $OpenBSD: disksubr.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 1999 Michael Shalayeff + * Copyright (c) 1997 Niklas Hallqvist + * Copyright (c) 1996 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. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 + */ + +/* + * This disksubr.c module started to take it's present form on OpenBSD/alpha + * but it was always thought it should be made completely MI and not need to + * be in that alpha-specific tree at all. + * + * XXX The DOS partitioning code is not endian-independent, only native + * endian DOS partition tables can be parsed yet. + * + * XXX Amiga RDB partitioning is not understood yet. + * + * XXX HPUX disklabel is not understood yet. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/disklabel.h> +#include <sys/syslog.h> +#include <sys/disk.h> + +/* The native defaults... */ +#if defined(alpha) && !defined(DISKLABEL_ALPHA) +#define DISKLABEL_ALPHA +#elif (defined(i386) || defined(arc)) && !defined(DISKLABEL_I386) +#define DISKLABEL_I386 +#elif defined(amiga) && !defined(DISKLABEL_AMIGA) +#define DISKLABEL_AMIGA +#elif (defined(hppa) || defined(hppa64)) && !defined(DISKLABEL_HPPA) +#define DISKLABEL_HPPA +#endif + +#define b_cylin b_resid + +#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALPHA) || defined(DISKLABEL_AMIGA) || defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL) +void swapdisklabel(struct disklabel *d); +char *readbsdlabel(struct buf *, void (*)(struct buf *), int, int, + int, int, struct disklabel *, int); +#endif +#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALL) +char *readdoslabel(struct buf *, void (*)(struct buf *), + struct disklabel *, struct cpu_disklabel *, int *, int *, int); +#endif +#if defined(DISKLABEL_AMIGA) || defined(DISKLABEL_ALL) +char *readamigalabel(struct buf *, void (*)(struct buf *), + struct disklabel *, struct cpu_disklabel *, int); +#endif +#if defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL) +char *readliflabel(struct buf *, void (*)(struct buf *), + struct disklabel *, struct cpu_disklabel *, int *, int *, int); +#endif + +static enum disklabel_tag probe_order[] = { LABELPROBES, -1 }; + +void +dk_establish(dk, dev) + struct disk *dk; + struct device *dev; +{ +} + +#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALPHA) || defined(DISKLABEL_AMIGA) || defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL) + +/* + * Byteswap all the fields that might be swapped. + */ +void +swapdisklabel(dlp) + struct disklabel *dlp; +{ + int i; + struct partition *pp; + + swap32(dlp->d_magic); + swap16(dlp->d_type); + swap16(dlp->d_subtype); + swap32(dlp->d_secsize); + swap32(dlp->d_nsectors); + swap32(dlp->d_ntracks); + swap32(dlp->d_ncylinders); + swap32(dlp->d_secpercyl); + swap32(dlp->d_secperunit); + swap16(dlp->d_sparespertrack); + swap16(dlp->d_sparespercyl); + swap32(dlp->d_acylinders); + swap16(dlp->d_rpm); + swap16(dlp->d_interleave); + swap16(dlp->d_trackskew); + swap16(dlp->d_cylskew); + swap32(dlp->d_headswitch); + swap32(dlp->d_trkseek); + swap32(dlp->d_flags); + for (i = 0; i < NDDATA; i++) + swap32(dlp->d_drivedata[i]); + for (i = 0; i < NSPARE; i++) + swap32(dlp->d_spare[i]); + swap32(dlp->d_magic2); + swap16(dlp->d_checksum); + swap16(dlp->d_npartitions); + swap32(dlp->d_bbsize); + swap32(dlp->d_sbsize); + for (i = 0; i < MAXPARTITIONS; i++) { + pp = &dlp->d_partitions[i]; + swap32(pp->p_size); + swap32(pp->p_offset); + swap32(pp->p_fsize); + swap16(pp->p_cpg); + } +} + +/* + * Try to read a standard BSD disklabel at a certain sector. + */ +char * +readbsdlabel(bp, strat, cyl, sec, off, endian, lp, spoofonly) + struct buf *bp; + void (*strat)(struct buf *); + int cyl, sec, off, endian; + struct disklabel *lp; + int spoofonly; +{ + struct disklabel *dlp; + char *msg = NULL; + u_int16_t cksum; + u_int32_t magic; + + if (endian != LITTLE_ENDIAN && endian != BIG_ENDIAN) + panic("readbsdlabel: unsupported byteorder %d", endian); + + /* don't read the on-disk label if we are in spoofed-only mode */ + if (spoofonly) + return (NULL); + + bp->b_blkno = sec; + bp->b_cylin = cyl; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + + /* if successful, locate disk label within block and validate */ + if (biowait(bp)) { + /* XXX we return the faked label built so far */ + msg = "disk label I/O error"; + return (msg); + } + + magic = endian == BIG_ENDIAN ? htobe32(DISKMAGIC) : htole32(DISKMAGIC); + + /* + * If off is negative, search until the end of the sector for + * the label, otherwise, just look at the specific location + * we're given. + */ + dlp = (struct disklabel *)(bp->b_data + (off >= 0 ? off : 0)); + do { + if (dlp->d_magic != magic || dlp->d_magic2 != magic) { + if (msg == NULL) + msg = "no disk label"; + } else { + cksum = dkcksum(dlp); + if (endian != BYTE_ORDER) + swapdisklabel(dlp); + if (dlp->d_npartitions > MAXPARTITIONS || cksum != 0) { + msg = "disk label corrupted"; + /* swap back if necessary. */ + if (off < 0 && endian != BYTE_ORDER) + swapdisklabel(dlp); + } else { + *lp = *dlp; + /* Recalc magic on foreign labels */ + if (endian != BYTE_ORDER) { + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + } + msg = NULL; + break; + } + } + if (off >= 0) + break; + dlp = (struct disklabel *)((char *)dlp + sizeof(int32_t)); + } while (dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - + sizeof(*dlp))); + return (msg); +} +#endif + +/* + * Attempt to read a disk label from a device + * using the indicated strategy 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. + * + * Returns null on success and an error string on failure. + */ +char * +readdisklabel(dev, strat, lp, osdep, spoofonly) + dev_t dev; + void (*strat)(struct buf *); + struct disklabel *lp; + struct cpu_disklabel *osdep; + int spoofonly; +{ + struct buf *bp = NULL; + char *msg = "no disk label"; + enum disklabel_tag *tp; + int i; + struct disklabel minilabel, fallbacklabel; + + /* minimal requirements for archtypal disk label */ + if (lp->d_secsize < DEV_BSIZE) + lp->d_secsize = DEV_BSIZE; + if (lp->d_secperunit == 0) + lp->d_secperunit = 0x1fffffff; + if (lp->d_secpercyl == 0) { + msg = "invalid geometry"; + goto done; + } + lp->d_npartitions = RAW_PART + 1; + for (i = 0; i < RAW_PART; i++) { + lp->d_partitions[i].p_size = 0; + lp->d_partitions[i].p_offset = 0; + } + if (lp->d_partitions[i].p_size == 0) + lp->d_partitions[i].p_size = 0x1fffffff; + lp->d_partitions[i].p_offset = 0; + minilabel = fallbacklabel = *lp; + + /* get a buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + for (tp = probe_order; msg && *tp != -1; tp++) { + switch (*tp) { + case DLT_ALPHA: +#if defined(DISKLABEL_ALPHA) || defined(DISKLABEL_ALL) + msg = readbsdlabel(bp, strat, 0, ALPHA_LABELSECTOR, + ALPHA_LABELOFFSET, LITTLE_ENDIAN, lp, spoofonly); +#endif + break; + + case DLT_I386: +#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALL) + msg = readdoslabel(bp, strat, lp, osdep, 0, 0, spoofonly); + if (msg) + /* Fallback alternative */ + fallbacklabel = *lp; +#endif + break; + + case DLT_AMIGA: +#if defined(DISKLABEL_AMIGA) || defined(DISKLABEL_ALL) + msg = readamigalabel(bp, strat, lp, osdep, spoofonly); +#endif + break; + + case DLT_HPPA: +#if defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL) + msg = readliflabel(bp, strat, lp, osdep, 0, 0, spoofonly); +#endif + break; + + default: + panic("unrecognized disklabel tag %d", *tp); + } + if (msg) + *lp = minilabel; + } + + /* Record metainformation about the disklabel. */ + if (msg == NULL) { + osdep->labelsector = bp->b_blkno; + osdep->labeltag = *tp; + } + +#if defined(CD9660) + if (msg && iso_disklabelspoof(dev, strat, lp) == 0) + msg = NULL; +#endif + + /* If there was an error, still provide a decent fake one. */ + if (msg) + *lp = fallbacklabel; + +done: + if (bp) { + bp->b_flags |= B_INVAL; + brelse(bp); + } + return (msg); +} + +#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALL) +/* + * If dos partition table requested, attempt to load it and + * find disklabel inside a DOS partition. Also, if bad block + * table needed, attempt to extract it as well. Return buffer + * for use in signalling errors if requested. + * + * We would like to check if each MBR has a valid BOOT_MAGIC, but + * we cannot because it doesn't always exist. So.. we assume the + * MBR is valid. + */ +char * +readdoslabel(bp, strat, lp, osdep, partoffp, cylp, spoofonly) + struct buf *bp; + void (*strat)(struct buf *); + struct disklabel *lp; + struct cpu_disklabel *osdep; + int *partoffp; + int *cylp; + int spoofonly; +{ + struct dos_partition *dp = osdep->u._i386.dosparts, *dp2; + struct dkbad *db, *bdp = &DKBAD(osdep); + char *msg = NULL, *cp; + int dospartoff, cyl, i, ourpart = -1; + dev_t dev; + + if (lp->d_secpercyl == 0) { + msg = "invalid label, d_secpercyl == 0"; + return (msg); + } + if (lp->d_secsize == 0) { + msg = "invalid label, d_secsize == 0"; + return (msg); + } + + /* do dos partitions in the process of getting disklabel? */ + dospartoff = 0; + cyl = I386_LABELSECTOR / lp->d_secpercyl; + if (dp) { + daddr_t part_blkno = DOSBBSECTOR; + unsigned long extoff = 0; + int wander = 1, n = 0, loop = 0; + + /* + * Read dos partition table, follow extended partitions. + * Map the partitions to disklabel entries i-p + */ + while (wander && n < 8 && loop < 8) { + loop++; + wander = 0; + if (part_blkno < extoff) + part_blkno = extoff; + + /* read boot record */ + bp->b_blkno = part_blkno; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + bp->b_cylin = part_blkno / lp->d_secpercyl; + (*strat)(bp); + + /* if successful, wander through dos partition table */ + if (biowait(bp)) { + msg = "dos partition I/O error"; + if (partoffp) + *partoffp = -1; + return (msg); + } + bcopy(bp->b_data + DOSPARTOFF, dp, + NDOSPART * sizeof(*dp)); + + if (ourpart == -1) { + /* Search for our MBR partition */ + for (dp2=dp, i=0; + i < NDOSPART && ourpart == -1; i++, dp2++) + if (dp2->dp_size && + dp2->dp_typ == DOSPTYP_OPENBSD) + ourpart = i; + for (dp2=dp, i=0; + i < NDOSPART && ourpart == -1; i++, dp2++) + if (dp2->dp_size && + dp2->dp_typ == DOSPTYP_FREEBSD) + ourpart = i; + for (dp2=dp, i=0; + i < NDOSPART && ourpart == -1; i++, dp2++) + if (dp2->dp_size && + dp2->dp_typ == DOSPTYP_NETBSD) + ourpart = i; + if (ourpart == -1) + goto donot; + /* + * This is our MBR partition. need sector + * address for SCSI/IDE, cylinder for + * ESDI/ST506/RLL + */ + dp2 = &dp[ourpart]; + dospartoff = dp2->dp_start + part_blkno; + cyl = DPCYL(dp2->dp_scyl, dp2->dp_ssect); + + /* XXX build a temporary disklabel */ + lp->d_partitions[0].p_size = dp2->dp_size; + lp->d_partitions[0].p_offset = dp2->dp_start + + part_blkno; + if (lp->d_ntracks == 0) + lp->d_ntracks = dp2->dp_ehd + 1; + if (lp->d_nsectors == 0) + lp->d_nsectors = DPSECT(dp2->dp_esect); + if (lp->d_secpercyl == 0) + lp->d_secpercyl = lp->d_ntracks * + lp->d_nsectors; + } +donot: + /* + * In case the disklabel read below fails, we want to + * provide a fake label in i-p. + */ + for (dp2=dp, i=0; i < NDOSPART && n < 8; i++, dp2++) { + struct partition *pp = &lp->d_partitions[8+n]; + + if (dp2->dp_typ == DOSPTYP_OPENBSD) + continue; + if (dp2->dp_size) + pp->p_size = dp2->dp_size; + if (dp2->dp_start) + pp->p_offset = + dp2->dp_start + part_blkno; + + switch (dp2->dp_typ) { + case DOSPTYP_UNUSED: + for (cp = (char *)dp2; + cp < (char *)(dp2 + 1); cp++) + if (*cp) + break; + /* + * Was it all zeroes? If so, it is + * an unused entry that we don't + * want to show. + */ + if (cp == (char *)(dp2 + 1)) + continue; + lp->d_partitions[8 + n++].p_fstype = + FS_UNUSED; + break; + + case DOSPTYP_LINUX: + pp->p_fstype = FS_EXT2FS; + n++; + break; + + case DOSPTYP_FAT12: + case DOSPTYP_FAT16S: + case DOSPTYP_FAT16B: + case DOSPTYP_FAT32: + case DOSPTYP_FAT32L: + case DOSPTYP_FAT16L: + pp->p_fstype = FS_MSDOS; + n++; + break; + case DOSPTYP_EXTEND: + part_blkno = dp2->dp_start + extoff; + if (!extoff) { + extoff = dp2->dp_start; + part_blkno = 0; + } + wander = 1; + break; + default: + pp->p_fstype = FS_OTHER; + n++; + break; + } + } + } + lp->d_bbsize = 8192; + lp->d_sbsize = 64*1024; /* XXX ? */ + lp->d_npartitions = n > 0 ? n + 8 : 3; + } + + /* record the OpenBSD partition's placement for the caller */ + if (partoffp) + *partoffp = dospartoff; + if (cylp) + *cylp = cyl; + + /* next, dig out disk label */ + msg = readbsdlabel(bp, strat, cyl, dospartoff + I386_LABELSECTOR, -1, + LITTLE_ENDIAN, lp, spoofonly); + if (msg) + return (msg); + + /* obtain bad sector table if requested and present */ + if (bdp && (lp->d_flags & D_BADSECT)) { + /* + * get a new buffer and initialize it as callers trust the + * buffer given to us, to point at the disklabel sector. + */ + dev = bp->b_dev; + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + i = 0; + do { + /* read a bad sector table */ + bp->b_flags = B_BUSY | B_READ; + bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i; + if (lp->d_secsize > DEV_BSIZE) + bp->b_blkno *= lp->d_secsize / DEV_BSIZE; + else + bp->b_blkno /= DEV_BSIZE / lp->d_secsize; + bp->b_bcount = lp->d_secsize; + bp->b_cylin = lp->d_ncylinders - 1; + (*strat)(bp); + + /* if successful, validate, otherwise try another */ + if (biowait(bp)) + msg = "bad sector table I/O error"; + else { + db = (struct dkbad *)(bp->b_data); +#define DKBAD_MAGIC 0x4321 + if (db->bt_mbz == 0 && + db->bt_flag == DKBAD_MAGIC) { + msg = NULL; + *bdp = *db; + break; + } else + msg = "bad sector table corrupted"; + } + } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 && + i < lp->d_nsectors); + + /* Give back the bad block buffer. */ + bp->b_flags |= B_INVAL; + brelse(bp); + } + return (msg); +} +#endif + +#if defined(DISKLABEL_AMIGA) || defined(DISKLABEL_ALL) +/* + * XXX RDB parsing is missing still. + */ +char * +readamigalabel(bp, strat, lp, osdep, spoofonly) + struct buf *bp; + void (*strat)(struct buf *); + struct disklabel *lp; + struct cpu_disklabel *osdep; + int spoofonly; +{ + char *msg; + + msg = readbsdlabel(bp, strat, 0, AMIGA_LABELSECTOR, AMIGA_LABELOFFSET, + BIG_ENDIAN, lp, spoofonly); + return (msg); +} +#endif + +#if defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL) +char * +readliflabel (bp, strat, lp, osdep, partoffp, cylp, spoofonly) + struct buf *bp; + void (*strat)(struct buf *); + struct disklabel *lp; + struct cpu_disklabel *osdep; + int *partoffp; + int *cylp; + int spoofonly; +{ + int fsoff; + + /* read LIF volume header */ + bp->b_blkno = btodb(LIF_VOLSTART); + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + bp->b_cylin = btodb(LIF_VOLSTART) / lp->d_secpercyl; + (*strat)(bp); + + if (biowait(bp)) { + if (partoffp) + *partoffp = -1; + return "LIF volume header I/O error"; + } + + bcopy (bp->b_data, &osdep->u._hppa.lifvol, sizeof(struct lifvol)); + if (osdep->u._hppa.lifvol.vol_id != LIF_VOL_ID) { + fsoff = 0; + } else { + struct lifdir *p; + struct buf *dbp; + dev_t dev; + + dev = bp->b_dev; + dbp = geteblk(LIF_DIRSIZE); + dbp->b_dev = dev; + + /* read LIF directory */ + dbp->b_blkno = lifstodb(osdep->u._hppa.lifvol.vol_addr); + dbp->b_bcount = lp->d_secsize; + dbp->b_flags = B_BUSY | B_READ; + dbp->b_cylin = dbp->b_blkno / lp->d_secpercyl; + (*strat)(dbp); + + if (biowait(dbp)) { + if (partoffp) + *partoffp = -1; + + dbp->b_flags |= B_INVAL; + brelse(dbp); + return ("LIF directory I/O error"); + } + + bcopy(dbp->b_data, osdep->u._hppa.lifdir, LIF_DIRSIZE); + dbp->b_flags |= B_INVAL; + brelse(dbp); + + /* scan for LIF_DIR_FS dir entry */ + for (fsoff = -1, p = &osdep->u._hppa.lifdir[0]; + fsoff < 0 && p < &osdep->u._hppa.lifdir[LIF_NUMDIR]; p++) { + if (p->dir_type == LIF_DIR_FS || + p->dir_type == LIF_DIR_HPLBL) + break; + } + + if (p->dir_type == LIF_DIR_FS) + fsoff = lifstodb(p->dir_addr); + else if (p->dir_type == LIF_DIR_HPLBL) { + struct hpux_label *hl; + struct partition *pp; + u_int8_t fstype; + int i; + + dev = bp->b_dev; + dbp = geteblk(LIF_DIRSIZE); + dbp->b_dev = dev; + + /* read LIF directory */ + dbp->b_blkno = lifstodb(p->dir_addr); + dbp->b_bcount = lp->d_secsize; + dbp->b_flags = B_BUSY | B_READ; + dbp->b_cylin = dbp->b_blkno / lp->d_secpercyl; + (*strat)(dbp); + + if (biowait(dbp)) { + if (partoffp) + *partoffp = -1; + + dbp->b_flags |= B_INVAL; + brelse(dbp); + return ("HOUX label I/O error"); + } + + bcopy(dbp->b_data, &osdep->u._hppa.hplabel, + sizeof(osdep->u._hppa.hplabel)); + dbp->b_flags |= B_INVAL; + brelse(dbp); + + hl = &osdep->u._hppa.hplabel; + if (hl->hl_magic1 != hl->hl_magic2 || + hl->hl_magic != HPUX_MAGIC || + hl->hl_version != 1) { + if (partoffp) + *partoffp = -1; + + return "HPUX label magic mismatch"; + } + + lp->d_bbsize = 8192; + lp->d_sbsize = 8192; + for (i = 0; i < MAXPARTITIONS; i++) { + lp->d_partitions[i].p_size = 0; + lp->d_partitions[i].p_offset = 0; + lp->d_partitions[i].p_fstype = 0; + } + + for (i = 0; i < HPUX_MAXPART; i++) { + if (!hl->hl_flags[i]) + continue; + + if (hl->hl_flags[i] == HPUX_PART_ROOT) { + pp = &lp->d_partitions[0]; + fstype = FS_BSDFFS; + } else if (hl->hl_flags[i] == HPUX_PART_SWAP) { + pp = &lp->d_partitions[1]; + fstype = FS_SWAP; + } else if (hl->hl_flags[i] == HPUX_PART_BOOT) { + pp = &lp->d_partitions[RAW_PART + 1]; + fstype = FS_BSDFFS; + } else + continue; + + pp->p_size = hl->hl_parts[i].hlp_length * 2; + pp->p_offset = hl->hl_parts[i].hlp_start * 2; + pp->p_fstype = fstype; + } + + lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; + lp->d_partitions[RAW_PART].p_offset = 0; + lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; + lp->d_npartitions = MAXPARTITIONS; + lp->d_magic = DISKMAGIC; + lp->d_magic2 = DISKMAGIC; + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + + return (NULL); + } + + /* if no suitable lifdir entry found assume zero */ + if (fsoff < 0) { + fsoff = 0; + } + } + + if (partoffp) + *partoffp = fsoff; + + return readbsdlabel(bp, strat, 0, fsoff + HPPA_LABELSECTOR, + HPPA_LABELOFFSET, BIG_ENDIAN, lp, spoofonly); +} +#endif + +/* + * Check new disk label for sensibility + * before setting it. + */ +int +setdisklabel(olp, nlp, openmask, osdep) + struct disklabel *olp, *nlp; + u_long openmask; + struct cpu_disklabel *osdep; +{ + int i; + struct partition *opp, *npp; + + /* sanity clause */ + if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 || + (nlp->d_secsize % DEV_BSIZE) != 0) + return(EINVAL); + + /* + * XXX Nice thought, but it doesn't work, if the intention was to + * force a reread at the next *readdisklabel call. That does not + * happen. There's still some use for it though as you can pseudo- + * partitition the disk. + * + * Special case to allow disklabel to be invalidated. + */ + if (nlp->d_magic == 0xffffffff) { + *olp = *nlp; + return (0); + } + + if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC || + dkcksum(nlp) != 0) + return (EINVAL); + + /* XXX missing check if other dos partitions will be overwritten */ + + while (openmask != 0) { + i = ffs((long)openmask) - 1; + openmask &= ~(1 << i); + if (nlp->d_npartitions <= i) + return (EBUSY); + opp = &olp->d_partitions[i]; + npp = &nlp->d_partitions[i]; + if (npp->p_offset != opp->p_offset || + npp->p_size < opp->p_size) + return (EBUSY); + /* + * Copy internally-set partition information + * if new label doesn't include it. XXX + */ + if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) { + npp->p_fstype = opp->p_fstype; + npp->p_fsize = opp->p_fsize; + npp->p_frag = opp->p_frag; + npp->p_cpg = opp->p_cpg; + } + } + nlp->d_checksum = 0; + nlp->d_checksum = dkcksum(nlp); + *olp = *nlp; + return (0); +} + + +/* + * Write disk label back to device after modification. + */ +int +writedisklabel(dev, strat, lp, osdep) + dev_t dev; + void (*strat)(struct buf *); + struct disklabel *lp; + struct cpu_disklabel *osdep; +{ + enum disklabel_tag *tp; + char *msg = "no disk label"; + struct buf *bp; + struct disklabel dl; +#if defined(DISKLABEL_I386) || defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL) + struct cpu_disklabel cdl; +#endif + int labeloffset, error, i, endian, partoff = 0, cyl = 0; + u_int64_t csum, *p; + + /* get a buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + /* + * I once played with the thought of using osdep->label{tag,sector} + * as a cache for knowing where (and what) to write. However, now I + * think it might be useful to reprobe if someone has written + * a newer disklabel of another type with disklabel(8) and -r. + */ + for (tp = probe_order; msg && *tp != -1; tp++) { + dl = *lp; + switch (*tp) { + case DLT_ALPHA: +#if defined(DISKLABEL_ALPHA) || defined(DISKLABEL_ALL) + msg = readbsdlabel(bp, strat, 0, ALPHA_LABELSECTOR, + ALPHA_LABELOFFSET, LITTLE_ENDIAN, &dl, 0); + labeloffset = ALPHA_LABELOFFSET; + endian = LITTLE_ENDIAN; +#endif + break; + + case DLT_I386: +#if defined(DISKLABEL_I386) || defined(DISKLABEL_ALL) + msg = readdoslabel(bp, strat, &dl, &cdl, &partoff, + &cyl, 0); + labeloffset = I386_LABELOFFSET; + endian = LITTLE_ENDIAN; +#endif + break; + + case DLT_AMIGA: +#if defined(DISKLABEL_AMIGA) || defined(DISKLABEL_ALL) + msg = readamigalabel(bp, strat, &dl, &cdl, 0); + labeloffset = AMIGA_LABELOFFSET; + endian = BIG_ENDIAN; +#endif + break; + + case DLT_HPPA: +#if defined(DISKLABEL_HPPA) || defined(DISKLABEL_ALL) + msg = readliflabel(bp, strat, &dl, &cdl, &partoff, + &cyl, 0); + labeloffset = HPPA_LABELOFFSET; + endian = BIG_ENDIAN; +#endif + break; + + default: + panic("unrecognized disklabel tag %d", *tp); + } + } + + if (msg) { + if (partoff == -1) + return EIO; + + /* Write it in the regular place with native byte order. */ + labeloffset = LABELOFFSET; + endian = BYTE_ORDER; + bp->b_blkno = partoff + LABELSECTOR; + bp->b_cylin = cyl; + bp->b_bcount = lp->d_secsize; + } + + if (endian != BYTE_ORDER) { + swapdisklabel(lp); + /* recalc checksum */ + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + } + + *(struct disklabel *)(bp->b_data + labeloffset) = *lp; + + /* Alpha bootblocks are checksummed. */ + if (*tp == DLT_ALPHA) { + for (csum = i = 0, p = (u_int64_t *)bp->b_data; i < 63; i++) + csum += *p++; + *p = csum; + } + + bp->b_flags = B_BUSY | B_WRITE; + (*strat)(bp); + error = biowait(bp); + + bp->b_flags |= B_INVAL; + brelse(bp); + return (error); +} + +/* + * Determine the size of the transfer, and make sure it is + * within the boundaries of the partition. Adjust transfer + * if needed, and signal errors or early completion. + */ +int +bounds_check_with_label(bp, lp, osdep, wlabel) + struct buf *bp; + struct disklabel *lp; + struct cpu_disklabel *osdep; + int wlabel; +{ +#define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE)) + struct partition *p = lp->d_partitions + DISKPART(bp->b_dev); + int labelsector = blockpersec(lp->d_partitions[RAW_PART].p_offset, + lp) + osdep->labelsector; + int sz = howmany(bp->b_bcount, DEV_BSIZE); + + /* avoid division by zero */ + if (lp->d_secpercyl == 0) { + bp->b_error = EINVAL; + goto bad; + } + + /* beyond partition? */ + if (bp->b_blkno + sz > blockpersec(p->p_size, lp)) { + sz = blockpersec(p->p_size, lp) - bp->b_blkno; + if (sz == 0) { + /* If exactly at end of disk, return EOF. */ + bp->b_resid = bp->b_bcount; + goto done; + } + if (sz < 0) { + /* If past end of disk, return EINVAL. */ + bp->b_error = EINVAL; + goto bad; + } + /* Otherwise, truncate request. */ + bp->b_bcount = sz << DEV_BSHIFT; + } + + /* Overwriting disk label? */ + if (bp->b_blkno + blockpersec(p->p_offset, lp) <= labelsector && + bp->b_blkno + blockpersec(p->p_offset, lp) + sz > labelsector && + (bp->b_flags & B_READ) == 0 && !wlabel) { + bp->b_error = EROFS; + goto bad; + } + + /* calculate cylinder for disksort to order transfers with */ + bp->b_cylin = (bp->b_blkno + blockpersec(p->p_offset, lp)) / + lp->d_secpercyl; + return (1); + +bad: + bp->b_flags |= B_ERROR; +done: + return (0); +} diff --git a/sys/arch/hppa64/hppa64/genassym.cf b/sys/arch/hppa64/hppa64/genassym.cf new file mode 100644 index 00000000000..45e598e1d19 --- /dev/null +++ b/sys/arch/hppa64/hppa64/genassym.cf @@ -0,0 +1,142 @@ +# $OpenBSD: genassym.cf,v 1.1 2005/04/01 10:40:47 mickey 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. 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 <sys/param.h> +include <sys/systm.h> +include <sys/proc.h> +include <sys/syscall.h> +include <sys/user.h> + +include <machine/cpu.h> +include <machine/psl.h> +include <machine/reg.h> +include <machine/vmparam.h> +include <machine/frame.h> +include <machine/pcb.h> + +include <uvm/uvm.h> + +# `break' entry points +export HPPA_BREAK_KERNEL +export HPPA_BREAK_GET_PSW +export HPPA_BREAK_SET_PSW + +# saved state fields +struct trapframe +member tf_flags +member tf_r1 +member tf_rp +member tf_r3 +member tf_r4 +member tf_r5 +member tf_r6 +member tf_r7 +member tf_r8 +member tf_r9 +member tf_r10 +member tf_r11 +member tf_r12 +member tf_r13 +member tf_r14 +member tf_r15 +member tf_r16 +member tf_r17 +member tf_r18 +member tf_args +member tf_dp +member tf_ret0 +member tf_ret1 +member tf_sp +member tf_r31 +member tf_sr0 +member tf_sr1 +member tf_sr2 +member tf_sr3 +member tf_sr4 +member tf_sr5 +member tf_sr6 +member tf_sr7 +member tf_rctr +member tf_ccr +member tf_iioq +member tf_iisq +member tf_pidr1 +member tf_pidr2 +member tf_eiem +member tf_eirr +member tf_isr +member tf_ior +member tf_iir +member tf_ipsw +member tf_ci +member tf_vtop +member tf_cr27 +member tf_cr30 +member tf_sar + +# proc fields and values +struct proc +member p_forw +member p_back +member p_addr +member p_priority +member p_stat +member p_wchan +member p_md +member P_MD_FLAGS p_md.md_flags +member P_MD_REGS p_md.md_regs + +export SRUN +export SONPROC + +struct user +member u_pcb + +struct pcb +member pcb_fpregs +member pcb_onfault +member pcb_uva +member pcb_ksp +member pcb_space + +struct cpu_info +member ci_curproc + +struct uvm +member page_idle_zero + +# system calls +export SYSCALLGATE +export SYS_exit +export SYS_execve +export SYS_sigreturn diff --git a/sys/arch/hppa64/hppa64/in_cksum.c b/sys/arch/hppa64/hppa64/in_cksum.c new file mode 100644 index 00000000000..4aec07520df --- /dev/null +++ b/sys/arch/hppa64/hppa64/in_cksum.c @@ -0,0 +1,125 @@ +/* $OpenBSD: in_cksum.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2000 Michael Shalayeff + * All rights reserved. + * + * based on a sparc version of Zubin Dittia. + * Copyright (c) 1995 Zubin Dittia. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <netinet/in.h> + +/* + * Checksum routine for Internet Protocol family headers. + * + * This routine is very heavily used in the network + * code and should be modified for each CPU to be as fast as possible. + * + * HPPA version. + */ + +/* TODO optimize */ + +#define ADD32 asm volatile( "ldw 0x00(%1), %%r19! ldw 0x04(%1), %%r20\n\t" \ + "add %0, %%r19, %0 ! addc %0, %%r20, %0\n\t" \ + "ldw 0x08(%1), %%r19! ldw 0x0c(%1), %%r20\n\t" \ + "addc %0, %%r19, %0 ! addc %0, %%r20, %0\n\t" \ + "ldw 0x10(%1), %%r19! ldw 0x14(%1), %%r20\n\t" \ + "addc %0, %%r19, %0 ! addc %0, %%r20, %0\n\t" \ + "ldw 0x18(%1), %%r19! ldw 0x1c(%1), %%r20\n\t" \ + "addc %0, %%r19, %0 ! addc %0, %%r20, %0\n\t" \ + "ldo 0x20(%1), %1 ! addc %0, %%r0 , %0" \ + : "+r" (sum), "+r" (w) :: "r20", "r19") +#define ADD16 asm volatile( "ldw 0x00(%1), %%r19! ldw 0x04(%1), %%r20\n\t" \ + "add %0, %%r19, %0! addc %0, %%r20, %0\n\t" \ + "ldw 0x08(%1), %%r19! ldw 0x0c(%1), %%r20\n\t" \ + "addc %0, %%r19, %0! addc %0, %%r20, %0\n\t" \ + "ldo 0x10(%1), %1 ! addc %0, %%r0 , %0" \ + : "+r" (sum), "+r" (w) :: "r20", "r19") + +#define ADDCARRY {if (sum > 0xffff) sum -= 0xffff;} +#define REDUCE {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY} +#define ROL asm volatile ("shd %0, %0, 8, %0" : "+r" (sum)) +#define ADDBYTE {ROL; sum += *w++; bins++; mlen--;} +#define ADDSHORT {sum += *((u_short *)w)++; mlen -= 2;} +#define ADDWORD asm volatile( "ldwm 4(%1), %%r19! add %0, %%r19, %0\n\t" \ + "ldo -4(%2), %2 ! addc %0, 0, %0" \ + : "+r" (sum), "+r" (w), "+r" (mlen) :: "r19") + +int +in_cksum(m, len) + register struct mbuf *m; + register int len; +{ + register u_int sum = 0; + register u_int bins = 0; + + for (; m && len; m = m->m_next) { + register int mlen = m->m_len; + register u_char *w; + + if (!mlen) + continue; + if (len < mlen) + mlen = len; + len -= mlen; + w = mtod(m, u_char *); + + if (mlen > 16) { + /* + * If we are aligned on a doubleword boundary + * do 32 bit bundled operations + */ + if ((7 & (u_long)w) != 0) { + if ((1 & (u_long)w) != 0) + ADDBYTE; + if ((2 & (u_long)w) != 0) + ADDSHORT; + if ((4 & (u_long)w) != 0) + ADDWORD; + } + + while ((mlen -= 32) >= 0) + ADD32; + + mlen += 32; + if (mlen >= 16) { + ADD16; + mlen -= 16; + } + } + + while (mlen > 0) + ADDBYTE; + } + if (bins & 1) + ROL; + REDUCE; + + return (0xffff ^ sum); +} diff --git a/sys/arch/hppa64/hppa64/locore.S b/sys/arch/hppa64/hppa64/locore.S new file mode 100644 index 00000000000..8882c934d28 --- /dev/null +++ b/sys/arch/hppa64/hppa64/locore.S @@ -0,0 +1,1879 @@ +/* $OpenBSD: locore.S,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + .level 2.0w + +#include <sys/errno.h> +#include <sys/reboot.h> +#include <machine/param.h> +#include <machine/asm.h> +#include <machine/psl.h> +#include <machine/trap.h> +#include <machine/iomod.h> +#include <machine/pdc.h> +#include <machine/frame.h> +#include <machine/reg.h> +#include <machine/pte.h> +#include "assym.h" + + .import __gp, data + .import pdc, data + .import boothowto, data + .import bootdev, data + .import esym, data + .import want_resched, data + .import proc0, data + .import proc0paddr, data + +#define EMRG_STACKSIZE (1*PAGE_SIZE) +#define FPEMU_STACKSIZE (1*PAGE_SIZE) + + .data + + .export netisr, data + .align 16 +netisr + .word 0 + .align 16 +$kpsl + .word PSL_W | PSL_Q | PSL_P | PSL_C | PSL_D | PSL_S | PSL_O + .export cpl, data +cpl + .word IPL_HIGH + + BSS(pdc_stack, 8) /* temp stack for PDC call */ + BSS(emrg_stack, 8) /* stack for HPMC/TOC/PWRF */ + BSS(fpemu_stack, 8) /* stack for FPU emulation */ + + .export fpu_csw, data + BSS(fpu_csw, 4) /* count fpu context switches */ + .export fpu_enable, data + BSS(fpu_enable, 4) /* bits to set in the %cr10 to enable fpu */ + .export fpu_curpcb, data + BSS(fpu_curpcb, 8) /* pcb of the fpu owner */ + BSS(fpu_scratch, 16) /* FPU scratch space, enough for a quad */ + + .text + +/* + * $start(pdc, boothowto, bootdev, esym) + */ + .export $start, entry +$start + rsm (PSL_R|PSL_Q|PSL_I|PSL_P|PSL_D), %r0 + nop ! nop ! nop ! nop + + ldil L%__gp, %dp + ldo R%__gp(%dp), %dp + + ldi HPPA_PID_KERNEL, %r1 + mtctl %r1, %pidr1 + mtctl %r1, %pidr2 + mtctl %r0, %pidr3 + mtctl %r0, %pidr4 + + mtsp %r0, %sr0 + mtsp %r0, %sr1 + mtsp %r0, %sr2 + mtsp %r0, %sr3 + mtsp %r0, %sr4 + mtsp %r0, %sr5 + mtsp %r0, %sr6 + mtsp %r0, %sr7 + + ldi -1, %r1 + mtctl %r0, %eiem + mtctl %r1, %eirr + mtctl %r0, %cr10 /* ccr */ + + ldil L%pdc, %r1 + std %arg0, R%pdc(%r1) + ldil L%boothowto, %r1 + stw %arg1, R%boothowto(%r1) + ldil L%bootdev, %r1 + stw %arg2, R%bootdev(%r1) + ldil L%esym, %r1 + std %arg3, R%esym(%r1) + + /* align esym */ + ldo PAGE_MASK(%arg3), %arg3 + depw %r0, 31, PAGE_SHIFT, %arg3 + + .import __kernel_pagedir, data + ldil L%__kernel_pagedir, %r1 + ldo R%__kernel_pagedir(%r1), %r1 + mtctl %r1, %cr25 /* vtop */ + + /* setup kernel initial PIEs */ + ldo PAGE_SIZE(%r1), %r31 + extrd,u %r31, 51, 32, %arg0 + ldo 1(%arg0), %arg1 + ldo 2(%arg0), %arg2 + stw %arg0, 0(%r1) + stw %arg1, 4(%r1) + /* (VM_MIN_KERNEL_ADDRESS & PIE_MASK) >> PIE_SHIFT */ + ldo 1(%arg2), %arg0 + stw %arg2, 0x20*4(%r1) + stw %arg0, 0xffc(%r1) + + .import kernel_ptes, data + ldil L%kernel_ptes, %r1 + ldo R%kernel_ptes(%r1), %r1 + + ldd,ma 8(%r1), %r8 + ldd,ma 8(%r1), %r9 + ldd,ma 8(%r1), %r10 + ldd,ma 8(%r1), %r11 + + /* fill eight pages at the same time */ + copy %arg3, %arg0 + ldo PAGE_SIZE(%arg0), %arg1 + extrd,u %arg0, 51, 32, %r1 + stw,ma %r1, 4(%r31) + ldo PAGE_SIZE(%arg1), %arg2 + extrd,u %arg1, 51, 32, %r1 + stw,ma %r1, 4(%r31) + ldo PAGE_SIZE(%arg2), %arg3 + extrd,u %arg2, 51, 32, %r1 + stw,ma %r1, 4(%r31) + ldo PAGE_SIZE(%arg3), arg4 + extrd,u %arg3, 51, 32, %r1 + stw,ma %r1, 4(%r31) + ldo PAGE_SIZE(arg4), arg5 + extrd,u arg4, 51, 32, %r1 + stw,ma %r1, 4(%r31) + ldo PAGE_SIZE(arg5), arg6 + extrd,u arg5, 51, 32, %r1 + stw,ma %r1, 4(%r31) + ldo PAGE_SIZE(arg6), arg7 + extrd,u arg6, 51, 32, %r1 + stw,ma %r1, 4(%r31) + extrd,u arg7, 51, 32, %r1 + stw,ma %r1, 4(%r31) + ldi PAGE_SIZE, %r1 +$start_set_ptes + std,ma,bc %r8, 8(%arg0) + std,ma,bc %r8, 8(%arg1) + std,ma,bc %r9, 8(%arg2) + std,ma,bc %r9, 8(%arg3) + std,ma,bc %r10, 8(arg4) + std,ma,bc %r10, 8(arg5) + std,ma,bc %r11, 8(arg6) + addib,>= -8, %r1, $start_set_ptes + std,ma,bc %r11, 8(arg7) + + ldo -8(arg7), %arg3 + + /* assuming size being page-aligned */ +#define STACK_ALLOC(n,s) \ + ldil L%n, %r1 ! \ + ldil L%s, %r31 ! \ + std %arg3, R%n(%r1) ! \ + add %arg3, %r31, %arg3 + + STACK_ALLOC(pdc_stack, PDC_STACKSIZE) + STACK_ALLOC(emrg_stack, EMRG_STACKSIZE) + STACK_ALLOC(fpemu_stack, FPEMU_STACKSIZE) + + copy %arg3, %arg0 + ldi PAGE_SIZE+TRAPFRAME_SIZEOF, %r1 +$start_zero_tf + std,ma,bc %r0, 8(%arg0) + addib,>= -16, %r1, $start_zero_tf + std,ma,bc %r0, 8(%arg0) + + /* setup proc0/user0 */ + ldil L%(USPACE+PAGE_SIZE), %arg0 + add %arg0, %arg3, %arg0 + ldil L%proc0paddr, %r1 + std %arg3, R%proc0paddr(%r1) + + ldo PAGE_SIZE(%arg3), %sp + mtctl %arg3, %cr30 + std %r0, U_PCB+PCB_ONFAULT(%arg3) + std %r0, U_PCB+PCB_SPACE(%arg3) + std %arg3, U_PCB+PCB_UVA(%arg3) + + ldil L%proc0, %r1 + ldo R%proc0(%r1), %r1 + ldo -TRAPFRAME_SIZEOF(%sp), %arg2 + std %arg3, P_ADDR(%r1) + std %arg2, P_MD_REGS(%r1) + + ldil TFF_LAST, %r1 + std %r1, TF_FLAGS(%arg2) + std %arg3, TF_CR30(%arg2) + + ldil L%$kpsl, %r1 + ldw R%$kpsl(%r1), arg7 + ldil L%$start_virt, %r31 + ldo R%$start_virt(%r31), %r31 + ldil L%$ivaaddr, %r1 + ldo R%$ivaaddr(%r1), %r1 + mtctl %r1, %iva + mtctl %r0, %pcsq + mtctl %r0, %pcsq + mtctl %r31, %pcoq + ldo 4(%r31), %r31 + mtctl %r31, %pcoq + mtctl arg7, %ipsw + rfi + nop + +$start_virt + copy %arg0, %r5 + copy %sp, %r3 + std,ma %r0, HPPA_FRAME_SIZE(%sp) + .call + b,l hppa_init, %rp + ldo -16(%sp), ap + +$start_callmain + .import main, code + .call + b,l main, %rp + ldo -TRAPFRAME_SIZEOF(%arg0), %r5 + .size $start, .-$start + +/* int + * pdc_call(func, pdc_flag, ...) + * iodcio_t func; + * int pdc_flag; + */ +ENTRY(pdc_call,160) + std %rp, HPPA_FRAME_RP(%sp) + std %sp, HPPA_FRAME_PSP(%sp) + copy %r3, %r31 + copy %sp, %ret0 + + ldil L%pdc_stack, %r1 + ldd R%pdc_stack(%r1), %r3 + copy %r3, %sp + std,ma %r31, 32+12*4+12*8(%sp) /* old frame+args+save(64) */ + + mfctl %eiem, %r1 + mtctl %r0, %eiem + std %r1, 1*8(%r3) + + copy %arg0, %r31 + /* copy arguments */ + copy %arg2, %arg0 + copy %arg3, %arg1 + copy arg4, %arg2 + copy arg5, %arg3 + + ldd 0*8(ap), arg4 + ldd 1*8(ap), arg5 + stw arg6, -32-(4+1)*4(%sp) + stw arg7, -32-(5+1)*4(%sp) + stw arg4, -32-(6+1)*4(%sp) + stw arg5, -32-(7+1)*4(%sp) + ldd 2*8(ap), arg4 + ldd 3*8(ap), arg5 + ldd 4*8(ap), arg6 + ldd 5*8(ap), arg7 + stw arg4, -32-(8+1)*4(%sp) + stw arg5, -32-(9+1)*4(%sp) + stw arg6, -32-(10+1)*4(%sp) + stw arg7, -32-(11+1)*4(%sp) + + mfctl %cr24, arg4 + mfctl %cr25, arg5 + mfctl %cr26, arg6 + mfctl %cr27, arg7 + std arg4, 2*8(%r3) + std arg5, 3*8(%r3) + std arg6, 4*8(%r3) + std arg7, 5*8(%r3) + mfctl %cr28, arg4 + mfctl %cr29, arg5 + mfctl %cr30, arg6 + mfctl %cr31, arg7 + std arg4, 6*8(%r3) + std arg5, 7*8(%r3) + std arg6, 8*8(%r3) + std arg7, 9*8(%r3) + + copy %arg0, %ret1 + std %ret0, 11*8(%r3) /* old %sp */ + ldi PSL_Q, %arg0 + break HPPA_BREAK_KERNEL, HPPA_BREAK_SET_PSW + copy %ret1, %arg0 + + .call + blr %r0, %rp + bv,n (%r31) + nop + + /* load temp control regs */ + ldd 2*8(%r3), arg4 + ldd 3*8(%r3), arg5 + ldd 4*8(%r3), arg6 + ldd 5*8(%r3), arg7 + mtctl arg4, %cr24 + mtctl arg5, %cr25 + mtctl arg6, %cr26 + mtctl arg7, %cr27 + ldd 6*8(%r3), arg4 + ldd 7*8(%r3), arg5 + ldd 8*8(%r3), arg6 + ldd 9*8(%r3), arg7 + mtctl arg4, %cr28 + mtctl arg5, %cr29 + mtctl arg6, %cr30 + mtctl arg7, %cr31 + + ldil L%$kpsl, %r1 + ldw R%$kpsl(%r1), %arg0 + copy %ret0, %arg1 + break HPPA_BREAK_KERNEL, HPPA_BREAK_SET_PSW + copy %arg1, %ret0 + + ldd 1*8(%r3), arg5 /* %eiem */ + ldd 11*8(%r3), %sp + ldd HPPA_FRAME_RP(%sp), %rp + ldd 0(%r3), %r3 + + bv %r0(%rp) + mtctl arg5, %eiem +EXIT(pdc_call) + +/* + * the whole syscall() glue is fit on one page + * both enter and return paths + */ +/* TODO has to be mapped w/a special perms */ + .align PAGE_SIZE + .export gateway_page, entry +gateway_page + nop + gate,n $bsd_syscall,%r0 + nop + + .align 256 +#ifdef COMPAT_LINUX + gate,n $linux_syscall, %r0 /* TODO linux syscall fix */ + nop + +$linux_syscall + nop +#endif + +$bsd_syscall + mfctl %eiem, %r1 + mtctl %r0, %eiem + mtsp %r0, %sr1 + mfctl %pidr1, %ret0 + ldi HPPA_PID_KERNEL, %ret0 + mtctl %ret0, %pidr1 + +/* TODO prepare for syscall() */ + + .import syscall,code + b,l syscall, %rp + nop + + mfctl %cr24, %arg1 + ldd CI_CURPROC(%arg1), %r1 + ldw P_MD_REGS(%r1), %arg0 + +$syscall_return + /* %arg0 -- trapframe */ + + mtctl %r0, %eiem + + ldo 8(%arg0), %r31 /* flags */ + + rfi + nop + .size $bsd_syscall, .-$bsd_syscall + .size $syscall_return, .-$syscall_return + +gateway_end + . = gateway_page + PAGE_SIZE + .size $gateway_page, .-$gateway_page + +/* + * interrupt vector table + */ +#define TLABEL(name) $trap$name +#define TRAP(name,num,pre) \ + .export TLABEL(name)$num, entry ! \ + .label TLABEL(name)$num ! \ + pre ! \ + .call ! \ + .import TLABEL(name), code ! \ + b TLABEL(name) ! \ + ldi num, %r1 ! \ + .align 32 + +#define ITLBPRE \ + mfctl %pcsq, %r8 ! \ + mfctl %pcoq, %r9 ! \ + extrd,u %r8, 63, SID_SHIFT, %r1 ! \ + depd %r1, 31, SID_SHIFT, %r9 ! \ + depd %r0, 63, SID_SHIFT, %r8 + +#define DTLBPRE \ + mfctl %isr, %r8 ! \ + mfctl %ior, %r9 ! \ + extrd,u %r8, 63, SID_SHIFT, %r1 ! \ + depd %r1, 31, SID_SHIFT, %r9 ! \ + depd %r0, 63, SID_SHIFT, %r8 + +#define HPMCPRE nop + +#define BRKPRE \ + mfctl %pcoq, %r8 + + .align PAGE_SIZE /* already */ + .export $ivaaddr, entry + .export hpmc_v, entry +$ivaaddr + TRAP(all,T_NONEXIST,) /* 0. invalid interrupt vector */ +hpmc_v + TRAP(hpmc,T_HPMC,HPMCPRE) /* 1. high priority machine check */ + TRAP(pfr,T_POWERFAIL,) /* 2. power failure */ + TRAP(all,T_RECOVERY,) /* 3. recovery counter trap */ + TRAP(all,T_INTERRUPT,) /* 4. external interrupt */ + TRAP(all,T_LPMC,) /* 5. low-priority machine check */ + TRAP(itlb,T_ITLBMISS,ITLBPRE) /* 6. instruction TLB miss fault */ + TRAP(all,T_IPROT,) /* 7. instruction protection trap */ + TRAP(all,T_ILLEGAL,) /* 8. Illegal instruction trap */ + TRAP(ibrk,T_IBREAK,BRKPRE) /* 9. break instruction trap */ + TRAP(all,T_PRIV_OP,) /* 10. privileged operation trap */ + TRAP(all,T_PRIV_REG,) /* 11. privileged register trap */ + TRAP(all,T_OVERFLOW,) /* 12. overflow trap */ + TRAP(all,T_CONDITION,) /* 13. conditional trap */ + TRAP(excpt,T_EXCEPTION,) /* 14. assist exception trap */ + TRAP(dtlb,T_DTLBMISS,DTLBPRE) /* 15. data TLB miss fault */ + TRAP(itlbna,T_ITLBMISSNA,DTLBPRE)/* 16. ITLB non-access miss fault */ + TRAP(dtlbna,T_DTLBMISSNA,DTLBPRE)/* 17. DTLB non-access miss fault */ + TRAP(all,T_DPROT,) /* 18. data protection trap + unalligned data reference trap */ + TRAP(all,T_DBREAK,) /* 19. data break trap */ + TRAP(tlbd,T_TLB_DIRTY,DTLBPRE) /* 20. TLB dirty bit trap */ + TRAP(all,T_PAGEREF,) /* 21. page reference trap */ + TRAP(emu,T_EMULATION,) /* 22. assist emulation trap */ + TRAP(all,T_HIGHERPL,) /* 23. higher-privelege transfer trap*/ + TRAP(all,T_LOWERPL,) /* 24. lower-privilege transfer trap */ + TRAP(all,T_TAKENBR,) /* 25. taken branch trap */ + TRAP(all,T_DATACC,) /* 26. data access rights trap */ + TRAP(all,T_DATAPID,) /* 27. data protection ID trap */ + TRAP(all,T_DATALIGN,) /* 28. unaligned data ref trap */ + TRAP(all,29,) + TRAP(all,30,) + TRAP(all,31,) + TRAP(all,32,) + TRAP(all,33,) + TRAP(all,34,) + TRAP(all,35,) + TRAP(all,36,) + TRAP(all,37,) + TRAP(all,38,) + TRAP(all,39,) + TRAP(all,40,) + TRAP(all,41,) + TRAP(all,42,) + TRAP(all,43,) + TRAP(all,44,) + TRAP(all,45,) + TRAP(all,46,) + TRAP(all,47,) + TRAP(all,48,) + TRAP(all,49,) + TRAP(all,50,) + TRAP(all,51,) + TRAP(all,52,) + TRAP(all,53,) + TRAP(all,54,) + TRAP(all,55,) + TRAP(all,56,) + TRAP(all,57,) + TRAP(all,58,) + TRAP(all,59,) + TRAP(all,60,) + TRAP(all,61,) + TRAP(all,62,) + TRAP(all,63,) + /* 64 */ + +/* + * High Priority Machine Check Interrupt + */ + .export TLABEL(hpmc), entry +ENTRY(TLABEL(hpmc),0) + rfi + nop + +hpmc_never_dies + b hpmc_never_dies + nop +EXIT(TLABEL(hpmc)) + +/* + * transfer of control handler + */ +ENTRY(hppa_toc,0) + rfi + nop + +ALTENTRY(hppa_toc_end) + .word 0 +EXIT(hppa_toc) + +/* + * power fail recovery handler + */ +ENTRY(TLABEL(pfr),0) + rfi + nop + +ALTENTRY(hppa_pfr_end) + .word 0 +EXIT(hppa_pfr) + +/* + * system breaks + */ + .export TLABEL(ibrk), entry +ENTRY(TLABEL(ibrk),0) + /* If called by a user process then always pass it to trap() */ + extrd,u,*= %r8, 63, 2, %r0 + b,n TLABEL(all) + + /* don't accept breaks from data segments */ + .import etext, code + ldil L%etext, %r9 + ldo R%etext(%r9), %r9 + cmpb,*>>=,n %r8, %r9, TLABEL(all) + + mfctl %iir, %r8 + extrd,u,*= %r8, 63, 5, %r0 + b,n TLABEL(all) + + /* now process all those `break' calls we make */ + extrd,u %r8, 50, 13, %r9 + comib,=,n HPPA_BREAK_GET_PSW, %r9, $ibrk_getpsw + comib,=,n HPPA_BREAK_SET_PSW, %r9, $ibrk_setpsw + + b TLABEL(all) + nop + +$ibrk_getpsw + b $ibrk_exit + mfctl %ipsw, %ret0 + +$ibrk_setpsw + mfctl %ipsw, %ret0 + b $ibrk_exit + mtctl %arg0, %ipsw + + /* insert other fast breaks here */ + nop ! nop + +$ibrk_exit + /* skip the break */ + mtctl %r0, %pcoq + mfctl %pcoq, %r9 + mtctl %r9, %pcoq + ldo 4(%r9), %r9 + mtctl %r9, %pcoq + + rfi,r + nop +EXIT(TLABEL(ibrk)) + + .export TLABEL(all), entry +ENTRY(TLABEL(all),0) + /* %r1 still has trap type */ + mfctl %ipsw, %r9 + mtctl %r9, %cr31 + + mtsp %r0, %sr3 + ldi HPPA_PID_KERNEL, %r9 + mtctl %r9, %pidr3 + + mfctl %isr, %r8 + mfctl %ior, %r9 + extrd,u %r8, 63, SID_SHIFT, %r16 + depd %r16, 31, SID_SHIFT, %r9 + depd %r0, 63, SID_SHIFT, %r8 + mtsp %r8, %sr6 + mtctl %r9, %cr27 + + mfctl %pcsq, %r24 + mtctl %r0, %pcsq + mfctl %pcsq, %r25 + mtctl %r0, %pcsq + mtsp %r24, %sr4 + mtsp %r25, %sr5 + + /* TODO fix pcsq:pcoq split */ + ldil L%TLABEL(all_virt), %r9 + ldo R%TLABEL(all_virt)(%r9), %r9 + mfctl %pcoq, %r24 + mtctl %r9, %pcoq + mfctl %pcoq, %r25 + ldo 4(%r9), %r9 + mtctl %r24, %cr28 + mtctl %r9, %pcoq + mtctl %r25, %cr29 + + ldil L%$kpsl, %r9 + ldw R%$kpsl(%r9), %r9 + mtctl %r9, %ipsw + + mfctl %cr30, %r9 + + mfsp %sr0, %r8 + extrd,u,*<> %r24, 63, 2, %r0 /* still pcoq head */ + cmpb,*= %r0, %r8, TLABEL(all_kern) + copy %sp, %r17 + + depdi 1, T_USER_POS, 1, %r1 + depdi 1, TFF_LAST_POS, 1, %r1 + ldd U_PCB+PCB_UVA(%r9), %sp + ldo PAGE_SIZE-TRAPFRAME_SIZEOF(%sp), %sp + +TLABEL(all_kern) + ldo 127(%sp), %sp + depdi 0, 63, 7, %sp + + ldo TF_SP(%sp), %r8 + std %r17, 0(%r8) + fdc %r0(%r8) + + mfctl %iir, %r16 + ldo TF_IIR(%sp), %r8 + std %r16, 0(%r8) + fdc %r0(%r8) + + mtctl %r1, %cr26 + rfi,r + nop ! nop ! nop ! nop ! nop ! nop ! nop ! nop +TLABEL(all_virt) + + ldo 8(%sp), %sp /* space for flags */ + std,ma %r1, 8(%sr3,%sp) + mfctl %cr26, %r1 /* sar */ + std %r1, -16(%sr3,%sp) + std,ma %rp, 8(%sr3,%sp) + std,ma %r3, 8(%sr3,%sp) + std,ma %r4, 8(%sr3,%sp) + std,ma %r5, 8(%sr3,%sp) + std,ma %r6, 8(%sr3,%sp) + std,ma %r7, 8(%sr3,%sp) + std,ma %r8, 8(%sr3,%sp) + std,ma %r9, 8(%sr3,%sp) + std,ma %r10, 8(%sr3,%sp) + std,ma %r11, 8(%sr3,%sp) + std,ma %r12, 8(%sr3,%sp) + std,ma %r13, 8(%sr3,%sp) + std,ma %r14, 8(%sr3,%sp) + std,ma %r15, 8(%sr3,%sp) + std,ma %r16, 8(%sr3,%sp) + std,ma %r17, 8(%sr3,%sp) + std,ma %r18, 8(%sr3,%sp) + std,ma %r19, 8(%sr3,%sp) + std,ma %r20, 8(%sr3,%sp) + std,ma %r21, 8(%sr3,%sp) + std,ma %r22, 8(%sr3,%sp) + std,ma %r23, 8(%sr3,%sp) + std,ma %r24, 8(%sr3,%sp) + std,ma %r25, 8(%sr3,%sp) + std,ma %r26, 8(%sr3,%sp) + std,ma %r27, 8(%sr3,%sp) + std,ma %r28, 8(%sr3,%sp) + std,ma %r29, 8(%sr3,%sp) + ldo -30*8(%sp), %arg1 + ldo 8(%sp), %sp /* %sp */ + std,ma %r31, 8(%sr3,%sp) + copy %r1, %arg0 + + mfsp %sr0, %arg2 + mfsp %sr1, %arg3 + std,ma %arg2, 8(%sr3,%sp) /* %sr0 */ + std,ma %arg3, 8(%sr3,%sp) /* %sr1 */ + std,ma %arg2, 8(%sr3,%sp) /* %sr2 */ + std,ma %arg2, 8(%sr3,%sp) /* %sr3 */ + std,ma %arg2, 8(%sr3,%sp) /* %sr4 */ + std,ma %arg2, 8(%sr3,%sp) /* %sr5 */ + std,ma %arg2, 8(%sr3,%sp) /* %sr6 */ + std,ma %arg2, 8(%sr3,%sp) /* %sr7 */ + + mfctl %cr0, %arg3 + mfctl %cr10, %arg2 + std,ma %arg3, 8(%sr3,%sp) /* rctr */ + std,ma %arg2, 8(%sr3,%sp) /* ccr */ + + mfctl %cr28, %arg2 /* pcoq */ + mfctl %cr29, %arg3 + std,ma %arg2, 8(%sr3,%sp) + std,ma %arg3, 8(%sr3,%sp) + + mfsp %sr4, %arg2 /* pcsq */ + mfsp %sr5, %arg3 + std,ma %arg2, 8(%sr3,%sp) + std,ma %arg3, 8(%sr3,%sp) + + mfctl %pidr1, %arg2 + mfctl %pidr2, %arg3 + std,ma %arg2, 8(%sr3,%sp) /* pidr1 */ + std,ma %arg3, 8(%sr3,%sp) /* pidr2 */ + + mfctl %pidr3, %r1 + mtctl %r1, %pidr1 + mtctl %r0, %pidr3 + + mfctl %eiem, %arg2 + mfctl %eirr, %arg3 + std,ma %arg2, 8(%sr3,%sp) /* eiem */ + std,ma %arg3, 8(%sr3,%sp) /* eirr */ + + mfctl %cr27, %arg2 + mfsp %sr6, %arg3 + std,ma %arg2, 8(%sr3,%sp) /* ior */ + std,ma %arg3, 8(%sr3,%sp) /* isr */ + + ldo 8(%sp), %sp /* iir */ + mfctl %cr31, %arg3 + std,ma %arg3, 8(%sr3,%sp) /* ipsw */ + + mfctl %cr24, %arg2 + mfctl %cr25, %arg3 + std,ma %arg2, 8(%sr3,%sp) /* curcpuinfo */ + std,ma %arg3, 8(%sr3,%sp) /* vtop */ + + mfctl %cr30, %arg2 + mfctl %cr27, %arg3 /* XXX */ + std,ma %arg2, 8(%sr3,%sp) /* pa(u) */ + std,ma %arg3, 8(%sr3,%sp) /* user curthread */ + + mfctl %sar, %arg2 + std,ma %arg2, 8(%sr3,%sp) /* sar */ + + mtsp %r0, %sr0 + mtsp %r0, %sr1 + mtsp %r0, %sr2 + mtsp %r0, %sr3 + mtsp %r0, %sr4 + mtsp %r0, %sr5 + mtsp %r0, %sr6 + mtsp %r0, %sr7 + + ldo TRAPFRAME_SIZEOF(%arg1), %sp + copy %sp, %r3 + std,ma %r0, HPPA_FRAME_SIZE(%sp) + + ldil L%__gp, %dp + ldo R%__gp(%dp), %dp + copy %arg1, %r5 + + depd %r0, T_USER_POS+1, T_USER_POS, %arg0 + .import trap, code + b,l trap, %rp + copy %arg0, %r4 + + /* non-terminal frames return to the same proc */ + bb,*>=,n %r4, TFF_LAST_POS, $syscall_return + copy %r5, %arg0 + + /* see if curproc have really changed */ + mfctl %cr24, %arg1 + ldd CI_CURPROC(%arg1), %r1 + sub,*= %r0, %r1, %r0 + ldd P_MD_REGS(%r1), %r5 + + b $syscall_return + copy %r5, %arg0 +EXIT(TLABEL(all)) + +#define PTPULL(bits,lbl) \ + /* space:offset -- %r8:%r9 */ ! \ + ldil L%__kernel_pagedir, %r24 ! \ + or,*= %r8, %r8, %r0 ! \ + mfctl %cr25, %r24 /* vtop */ ! \ + ldo PAGE_SIZE(%r24), %r25 ! \ + extrd,u %r25, 51, 32, %r25 ! \ + extrd,u,*= %r9, 32, 10, %r17 ! \ + ldw,s %r17(%r24), %r25 ! \ + extrd,u %r9, 42, 10, %r17 ! \ + depd,z,*<> %r25, 51, 32, %r25 ! \ + b,n lbl ! \ + ldw,s %r17(%r25), %r25 ! \ + extrd,u %r9, 51, 9, %r24 ! \ + depd,z,*<> %r25, 51, 32, %r25 ! \ + b,n lbl ! \ + ldd,s %r24(%r25), %r16 ! \ + or,*<> %r16, %r0, %r17 ! \ + b,n lbl ! \ + depdi bits, 2+bits, 1+bits, %r17 ! \ + shladd,l %r24, 3, %r25, %r25 ! \ + sub,*= %r16, %r17, %r0 ! \ + std %r17, 0(%r25) ! \ + extrd,s %r16, 63, 37, %r16 ! \ + depd %r8, 63, 48, %r17 ! \ + depdi 1, 62, 1, %r17 + +TLABEL(itlb) + PTPULL(0, TLABEL(all)) + iitlbt %r16, %r17 + rfi,r + nop + +TLABEL(tlbd) + PTPULL(1, TLABEL(all)) + idtlbt %r16, %r17 + rfi,r + nop + +TLABEL(itlbna) +TLABEL(dtlbna) + PTPULL(0, TLABEL(dtlbna_fake)) + idtlbt %r16, %r17 + rfi,r + nop +TLABEL(dtlbna_fake) + /* parse probei?,[rw] insns, decent to trap() to set regs proper */ + mfctl %iir, %r16 + extrd,u %r16, 38, 6, %r24 + comib,=,n 1, %r24, TLABEL(all) + extrd,u %r16, 56, 6, %r24 + subi,<> 0x23, %r24, %r0 + b TLABEL(all) + subi,<> 0x63, %r24, %r0 + b TLABEL(all) + /* otherwise generate a flush-only tlb entry */ + depd,z %r8, 62, 47, %r17 + depdi -13, 11, 7, %r17 + ldo 2(%r17), %r17 /* 3? */ + idtlbt %r0, %r17 + rfi,r + nop + +TLABEL(dtlb) + PTPULL(0, TLABEL(all)) + idtlbt %r16, %r17 + rfi,r + nop + + .export TLABEL(excpt), entry +ENTRY(TLABEL(excpt),0) + /* assume we never get this one w/o fpu [enabled] */ + copy %rp, %r1 + copy %arg0, %r8 + mfctl %cr30, %r9 +#if (PCB_FPREGS+U_PCB) != 0 + ldo PCB_FPREGS+U_PCB(%r9), %r9 +#endif + .import fpu_save, code + .call + b,l fpu_save, %rp + copy %r9, %arg0 + copy %r1, %rp + copy %r8, %arg0 + mtctl %r0, %cr10 /* reset ccr: cause a reload after exception */ + ldil L%fpu_curpcb, %r1 + std %r0, R%fpu_curpcb(%r1) + + /* now, check for trap */ + ldw 0(%r9), %r1 + bb,>=,n %r1, HPPA_FPU_T_POS, excpt_notrap + ldw 1*4(%r9), %r1 + comb,<>,n %r0, %r1, excpt_emulate + ldw 2*4(%r9), %r1 + comb,<>,n %r0, %r1, excpt_emulate + ldw 3*4(%r9), %r1 + comb,<>,n %r0, %r1, excpt_emulate + ldw 4*4(%r9), %r1 + comb,<>,n %r0, %r1, excpt_emulate + ldw 5*4(%r9), %r1 + comb,<>,n %r0, %r1, excpt_emulate + ldw 6*4(%r9), %r1 + comb,<>,n %r0, %r1, excpt_emulate + ldw 7*4(%r9), %r1 + +excpt_emulate + bb,*>=,n %r1, 37, excpt_notrap /* HPPA_FPU_UNMPL not set */ + +#if TODO_emulate + ldw 0(%r9), %r16 + depi 0, HPPA_FPU_T_POS, 1, %r16 + .import $fpu_emulate, code + b $fpu_emulate + stw %r16, 0(%r9) +#endif + +excpt_notrap + sync + b TLABEL(all) + ldi T_EXCEPTION, %r1 +EXIT(TLABEL(excpt)) + + .export TLABEL(emu), entry +ENTRY(TLABEL(emu),0) + /* + * Switch FPU/SFU context + * + * %isr:%ior - data address + * %iir - instruction to emulate + * iisq:iioq - address of instruction to emulate + * + * note: ISR and IOR contain valid data only if the + * instruction is a coprocessor load or store. + * + */ + + mfctl %iir, %r8 + extrd,u %r8, 37, 6, %r9 /* no sfu implementation right now */ + comib,= 4, %r9, TLABEL(all) + ldi T_ILLEGAL, %r1 + + /* + * pass through for all coprocessors now and + * do not check the uid here. + * in case that piece does not exist emulate + * or the trap will be generted later. + */ + + /* if we are already enabled and hit again, emulate */ + mfctl %cr10, %r1 /* ccr */ + extru,<> %r1, 25, 2, %r0 + b,n $fpusw_set + nop + +$fpusw_emu + mtctl %r0, %cr10 /* reset ccr: cause a reload after exception */ + std %r0, R%fpu_curpcb(%r1) +#if TODO_emulate + /* here we emulate the fld/fst */ + mfctl %iir, %r1 + extrd,u %r1, 37, 6, %r1 + comib,= 0xb, %r9, TLABEL(all) + ldi T_ILLEGAL, %r1 + + mfctl %iir, %r1 + extrd,u %r1, 37, 6, %r1 + comib,= 0x9, %r9, TLABEL(all) + ldi T_ILLEGAL, %r1 + + mfctl %iir, %r1 + .import $fpu_emulate, code + b $fpu_emulate + nop +#else + b TLABEL(all) + ldi T_ILLEGAL, %r1 +#endif +$fpusw_set + /* enable coprocessor */ + depdi 3, 37, 2, %r1 + mtctl %r1, %cr10 /* ccr */ + + ldil L%fpu_curpcb, %r16 + mfctl %cr30, %r9 + ldd R%fpu_curpcb(%r16), %r16 + + comb,=,n %r16, %r0, $fpusw_nosave + comb,=,n %r16, %r9, $fpusw_done + + copy %arg0, %r17 + copy %rp, %r1 +#if (PCB_FPREGS+U_PCB) != 0 + ldo PCB_FPREGS+U_PCB(%r16), %r16 +#endif + .import fpu_save, code + .call + b,l fpu_save, %rp + copy %r16, %arg0 + copy %r1, %rp + copy %r17, %arg0 + +$fpusw_nosave + /* count switches */ + ldil L%fpu_csw, %r1 + ldw R%fpu_csw(%r1), %r16 + ldo 31*8+PCB_FPREGS+U_PCB(%r9), %r17 + ldo 1(%r16), %r16 + stw %r16, R%fpu_csw(%r1) + + fldds,ma -8(%r17), %fr31 + fldds,ma -8(%r17), %fr30 + fldds,ma -8(%r17), %fr29 + fldds,ma -8(%r17), %fr28 + fldds,ma -8(%r17), %fr27 + fldds,ma -8(%r17), %fr26 + fldds,ma -8(%r17), %fr25 + fldds,ma -8(%r17), %fr24 + fldds,ma -8(%r17), %fr23 + fldds,ma -8(%r17), %fr22 + fldds,ma -8(%r17), %fr21 + fldds,ma -8(%r17), %fr20 + fldds,ma -8(%r17), %fr19 + fldds,ma -8(%r17), %fr18 + fldds,ma -8(%r17), %fr17 + fldds,ma -8(%r17), %fr16 + fldds,ma -8(%r17), %fr15 + fldds,ma -8(%r17), %fr14 + fldds,ma -8(%r17), %fr13 + fldds,ma -8(%r17), %fr12 + fldds,ma -8(%r17), %fr11 + fldds,ma -8(%r17), %fr10 + fldds,ma -8(%r17), %fr9 + fldds,ma -8(%r17), %fr8 + fldds,ma -8(%r17), %fr7 + fldds,ma -8(%r17), %fr6 + fldds,ma -8(%r17), %fr5 + fldds,ma -8(%r17), %fr4 + fldds,ma -8(%r17), %fr3 + fldds,ma -8(%r17), %fr2 + fldds,ma -8(%r17), %fr1 + fldds 0(%r17), %fr0 /* fr0 must be restored last */ + + ldil L%fpu_curpcb, %r1 + std %r17, R%fpu_curpcb(%r1) + +$fpusw_done + rfir + nop +EXIT(TLABEL(emu)) + +LEAF_ENTRY(fpu_exit) + /* enable coprocessor XXX */ + depi 3, 25, 2, %r1 + mtctl %r1, %cr10 + + ldil L%fpu_scratch, %r25 + ldo R%fpu_scratch(%r25), %r25 + fstds %fr0, 0(%r25) + sync + bv %r0(%rp) + mtctl %r0, %cr10 +EXIT(fpu_exit) + +LEAF_ENTRY(fpu_save) + fstds,ma %fr0 , 8(%arg0) + fstds,ma %fr1 , 8(%arg0) + fstds,ma %fr2 , 8(%arg0) + fstds,ma %fr3 , 8(%arg0) + fstds,ma %fr4 , 8(%arg0) + fstds,ma %fr5 , 8(%arg0) + fstds,ma %fr6 , 8(%arg0) + fstds,ma %fr7 , 8(%arg0) + fstds,ma %fr8 , 8(%arg0) + fstds,ma %fr9 , 8(%arg0) + fstds,ma %fr10, 8(%arg0) + fstds,ma %fr11, 8(%arg0) + fstds,ma %fr12, 8(%arg0) + fstds,ma %fr13, 8(%arg0) + fstds,ma %fr14, 8(%arg0) + fstds,ma %fr15, 8(%arg0) + fstds,ma %fr16, 8(%arg0) + fstds,ma %fr17, 8(%arg0) + fstds,ma %fr18, 8(%arg0) + fstds,ma %fr19, 8(%arg0) + fstds,ma %fr20, 8(%arg0) + fstds,ma %fr21, 8(%arg0) + fstds,ma %fr22, 8(%arg0) + fstds,ma %fr23, 8(%arg0) + fstds,ma %fr24, 8(%arg0) + fstds,ma %fr25, 8(%arg0) + fstds,ma %fr26, 8(%arg0) + fstds,ma %fr27, 8(%arg0) + fstds,ma %fr28, 8(%arg0) + fstds,ma %fr29, 8(%arg0) + fstds,ma %fr30, 8(%arg0) + fstds %fr31, 0(%arg0) + ldo -24(%arg0), %arg0 + ldi -32, %r25 /* gotta be free for all callers */ + fdc,m %r25(%arg0) + fdc,m %r25(%arg0) + fdc,m %r25(%arg0) + fdc,m %r25(%arg0) + fdc,m %r25(%arg0) + fdc,m %r25(%arg0) + fdc,m %r25(%arg0) + fdc,m %r25(%arg0) + bv %r0(%rp) + sync +EXIT(fpu_save) + +/* + * void + * mtctl(register_t val, int reg) + */ +LEAF_ENTRY(mtctl) + b,l mtctl_end, %r1 + extrd,u %arg1, 63, 32, %arg1 + bv %r0(%rp) + mtctl %arg0, %cr0 + bv %r0(%rp) + nop /* mtctl %arg0, %cr1 */ + bv %r0(%rp) + nop /* mtctl %arg0, %cr2 */ + bv %r0(%rp) + nop /* mtctl %arg0, %cr3 */ + bv %r0(%rp) + nop /* mtctl %arg0, %cr4 */ + bv %r0(%rp) + nop /* mtctl %arg0, %cr5 */ + bv %r0(%rp) + nop /* mtctl %arg0, %cr6 */ + bv %r0(%rp) + nop /* mtctl %arg0, %cr7 */ + bv %r0(%rp) + mtctl %arg0, %cr8 + bv %r0(%rp) + mtctl %arg0, %cr9 + bv %r0(%rp) + mtctl %arg0, %cr10 + bv %r0(%rp) + mtctl %arg0, %cr11 + bv %r0(%rp) + mtctl %arg0, %cr12 + bv %r0(%rp) + mtctl %arg0, %cr13 + bv %r0(%rp) + mtctl %arg0, %cr14 + bv %r0(%rp) + mtctl %arg0, %cr15 + bv %r0(%rp) + mtctl %arg0, %cr16 + bv %r0(%rp) + mtctl %arg0, %cr17 + bv %r0(%rp) + mtctl %arg0, %cr18 + bv %r0(%rp) + mtctl %arg0, %cr19 + bv %r0(%rp) + mtctl %arg0, %cr20 + bv %r0(%rp) + mtctl %arg0, %cr21 + bv %r0(%rp) + mtctl %arg0, %cr22 + bv %r0(%rp) + mtctl %arg0, %cr23 + bv %r0(%rp) + mtctl %arg0, %cr24 + bv %r0(%rp) + mtctl %arg0, %cr25 + bv %r0(%rp) + mtctl %arg0, %cr26 + bv %r0(%rp) + mtctl %arg0, %cr27 + bv %r0(%rp) + mtctl %arg0, %cr28 + bv %r0(%rp) + mtctl %arg0, %cr29 + bv %r0(%rp) + mtctl %arg0, %cr30 + bv %r0(%rp) + mtctl %arg0, %cr31 +mtctl_end + subi,<< 31, %arg1, %r0 + bv,n %arg1(%r1) + bv %r0(%rp) + nop +EXIT(mtctl) + +/* + * void + * pdtlb(pa_space_t sp, vaddr_t va) + */ +LEAF_ENTRY(pdtlb) + mfsp %sr1, %arg2 + mtsp %arg0, %sr1 + pdtlb %r0(%sr1, %arg1) + bv %r0(%rp) + mtsp %arg2, %sr1 +EXIT(pdtlb) + +/* + * void + * pitlb(pa_space_t sp, vaddr_t va) + */ +LEAF_ENTRY(pitlb) + mfsp %sr1, %arg2 + mtsp %arg0, %sr1 + pitlb %r0(%sr1, %arg1) + bv %r0(%rp) + mtsp %arg2, %sr1 +EXIT(pitlb) + +/* + * register_t + * mfctl(int reg) + */ +LEAF_ENTRY(mfctl) + b,l mfctl_end, %r1 + extrd,u %arg0, 63, 32, %arg0 + bv %r0(%rp) + mfctl %cr0, %ret0 + bv %r0(%rp) + nop /* mfctl %cr1, %ret0 */ + bv %r0(%rp) + nop /* mfctl %cr2, %ret0 */ + bv %r0(%rp) + nop /* mfctl %cr3, %ret0 */ + bv %r0(%rp) + nop /* mfctl %cr4, %ret0 */ + bv %r0(%rp) + nop /* mfctl %cr5, %ret0 */ + bv %r0(%rp) + nop /* mfctl %cr6, %ret0 */ + bv %r0(%rp) + nop /* mfctl %cr7, %ret0 */ + bv %r0(%rp) + mfctl %cr8, %ret0 + bv %r0(%rp) + mfctl %cr9, %ret0 + bv %r0(%rp) + mfctl %cr10, %ret0 + bv %r0(%rp) + mfctl %cr11, %ret0 + bv %r0(%rp) + mfctl %cr12, %ret0 + bv %r0(%rp) + mfctl %cr13, %ret0 + bv %r0(%rp) + mfctl %cr14, %ret0 + bv %r0(%rp) + mfctl %cr15, %ret0 + bv %r0(%rp) + mfctl %cr16, %ret0 + bv %r0(%rp) + mfctl %cr17, %ret0 + bv %r0(%rp) + mfctl %cr18, %ret0 + bv %r0(%rp) + mfctl %cr19, %ret0 + bv %r0(%rp) + mfctl %cr20, %ret0 + bv %r0(%rp) + mfctl %cr21, %ret0 + bv %r0(%rp) + mfctl %cr22, %ret0 + bv %r0(%rp) + mfctl %cr23, %ret0 + bv %r0(%rp) + mfctl %cr24, %ret0 + bv %r0(%rp) + mfctl %cr25, %ret0 + bv %r0(%rp) + mfctl %cr26, %ret0 + bv %r0(%rp) + mfctl %cr27, %ret0 + bv %r0(%rp) + mfctl %cr28, %ret0 + bv %r0(%rp) + mfctl %cr29, %ret0 + bv %r30(%rp) + mfctl %cr30, %ret0 + bv %r30(%rp) + mfctl %cr31, %ret0 + +mfctl_end + subi,<< 31, %arg0, %r0 + bv,n %arg0(%r1) + bv %r0(%rp) + nop +EXIT(mfctl) + +#define CACHELOOP(sp,addr,len,step,insn) \ + mtsp sp, %sr1 ! \ + ldi -1, arg7 ! \ + sh3add step, arg7, %r1 ! \ + andcm len, %r1, %r1 ! \ + add addr, %r1, %r1 ! \ + b __CONCAT(insn,_loop) ! \ + add addr, len, len ! \ + .label __CONCAT(insn,_loop8) ! \ + insn,m step(%sr1, addr) ! \ + insn,m step(%sr1, addr) ! \ + insn,m step(%sr1, addr) ! \ + insn,m step(%sr1, addr) ! \ + insn,m step(%sr1, addr) ! \ + insn,m step(%sr1, addr) ! \ + insn,m step(%sr1, addr) ! \ + .label __CONCAT(insn,_loop) ! \ + comb,<< addr, %r1, __CONCAT(insn,_loop8) ! \ + insn,m step(%sr1, addr) ! \ + .label __CONCAT(insn,_loop1) ! \ + comb,<<,n addr, len, __CONCAT(insn,_loop1) ! \ + insn,m step(%sr1, addr) + + +LEAF_ENTRY(fdcache) + ldil L%dcache_stride, %r1 + ldw R%dcache_stride(%r1), %arg3 + CACHELOOP(%arg0,%arg1,%arg2,%arg3,fdc) + bv %r0(%rp) + sync +EXIT(fdcache) + +LEAF_ENTRY(pdcache) + ldil L%dcache_stride, %r1 + ldw R%dcache_stride(%r1), %arg3 + CACHELOOP(%arg0,%arg1,%arg2,%arg3,pdc) + bv %r0(%rp) + sync +EXIT(pdcache) + +LEAF_ENTRY(ficache) + ldil L%icache_stride, %r1 + ldw R%icache_stride(%r1), %arg3 + CACHELOOP(%arg0,%arg1,%arg2,%arg3,fic) + bv %r0(%rp) + sync +EXIT(ficache) + +LEAF_ENTRY(copy_on_fault) + mtsp %r0, %sr1 + mtsp %r0, %sr2 + std %r1, PCB_ONFAULT+U_PCB(%rp) + ldd HPPA_FRAME_RP(%sp), %rp + ldo -HPPA_FRAME_SIZE(%sp), %sp + bv %r0(%rp) + ldi EFAULT, %ret0 +EXIT(copy_on_fault) + +LEAF_ENTRY(sync_caches) + sync + syncdma + sync + nop + nop + nop + nop + nop + nop + bv %r0(%rp) + nop +EXIT(sync_caches) + +/* + * int spstrcpy (pa_space_t ssp, const void *src, pa_space_t dsp, void *dst, + * size_t size, size_t *rsize) + * do a space to space strncpy, return actual copy size in the rsize; + */ +LEAF_ENTRY(spstrcpy) + stw %rp, HPPA_FRAME_RP(%sp) + ldo HPPA_FRAME_SIZE(%sp), %sp + add arg4, %arg1, arg4 + /* setup fault handler */ + mfctl %cr24, %arg1 + ldd CI_CURPROC(%arg1), %r1 + ldil L%copy_on_fault, arg7 + ldd P_ADDR(arg6), %rp + ldo R%copy_on_fault(arg7), arg7 + ldd PCB_ONFAULT+U_PCB(%rp), %r1 + std arg7, PCB_ONFAULT+U_PCB(%rp) + + mtsp %arg0, %sr1 + mtsp %arg2, %sr2 + copy %arg1, %arg0 + +$spstrcpy_loop + ldbs,ma 1(%sr1, %arg1), arg7 + comb,= arg4, %arg1, $spstrcpy_exit + stbs,ma arg7, 1(%sr2, %arg3) + comb,<>,n %r0, arg7, $spstrcpy_loop + nop + +$spstrcpy_exit + ldo -HPPA_FRAME_SIZE(%sp), %sp + mtsp %r0, %sr1 + mtsp %r0, %sr2 + std %r1, PCB_ONFAULT+U_PCB(%rp) + sub %arg1, %arg0, %arg1 + ldd HPPA_FRAME_RP(%sp), %rp + sub,= %r0, arg5, %r0 + stw %arg1, 0(arg5) + bv 0(%rp) + copy %r0, %ret0 +EXIT(spstrcpy) + +LEAF_ENTRY(setjmp) + std,ma %rp, 8(%arg0) + std,ma %sp, 8(%arg0) + std,ma %r3, 8(%arg0) + std,ma %r4, 8(%arg0) + std,ma %r5, 8(%arg0) + std,ma %r6, 8(%arg0) + std,ma %r7, 8(%arg0) + std,ma %r8, 8(%arg0) + std,ma %r9, 8(%arg0) + std,ma %r10, 8(%arg0) + std,ma %r11, 8(%arg0) + std,ma %r12, 8(%arg0) + std,ma %r13, 8(%arg0) + std,ma %r14, 8(%arg0) + std,ma %r15, 8(%arg0) + std,ma %r16, 8(%arg0) + std,ma %r17, 8(%arg0) + std,ma %r18, 8(%arg0) + std,ma %r19, 8(%arg0) + std,ma %r27, 8(%arg0) + + bv %r0(%rp) + copy %r0, %ret0 +EXIT(setjmp) + +LEAF_ENTRY(longjmp) + ldd,ma 8(%arg0), %rp + ldd,ma 8(%arg0), %sp + ldd,ma 8(%arg0), %r3 + ldd,ma 8(%arg0), %r4 + ldd,ma 8(%arg0), %r5 + ldd,ma 8(%arg0), %r6 + ldd,ma 8(%arg0), %r7 + ldd,ma 8(%arg0), %r8 + ldd,ma 8(%arg0), %r9 + ldd,ma 8(%arg0), %r10 + ldd,ma 8(%arg0), %r11 + ldd,ma 8(%arg0), %r12 + ldd,ma 8(%arg0), %r13 + ldd,ma 8(%arg0), %r14 + ldd,ma 8(%arg0), %r15 + ldd,ma 8(%arg0), %r16 + ldd,ma 8(%arg0), %r17 + ldd,ma 8(%arg0), %r18 + ldd,ma 8(%arg0), %r19 + ldd,ma 8(%arg0), %r27 + + bv %r0(%rp) + copy %arg1, %ret0 +EXIT(longjmp) + + .import whichqs, data + .import qs, data +/* + * setrunqueue(struct proc *p); + * Insert a process on the appropriate queue. Should be called at splclock(). + */ + .align 32 +ENTRY(setrunqueue,0) +#ifdef DIAGNOSTIC + ldd P_BACK(%arg0), %r1 + comb,<>,n %r0, %r1, Lsetrunqueue_panic + ldd P_WCHAN(%arg0), %r1 + comb,<>,n %r0, %r1, Lsetrunqueue_panic + ldb P_STAT(%arg0), %r1 + comib,=,n SRUN, %r1, Lsetrunqueue_ok +Lsetrunqueue_panic + copy %arg0, %arg1 + ldil L%Lsrqpstr, %arg0 + .call + b,l panic, %rp + ldo R%Lsrqpstr(%arg0), %arg0 +Lsrqpstr + .asciz "setrunqueue(%p)" + .align 8 +Lsetrunqueue_ok +#endif + + ldb P_PRIORITY(%arg0), %r1 + ldil L%qs, arg7 + shd %r0, %r1, 2, %r1 + ldo R%qs(arg7), arg7 + sh3add %r1, arg7, arg7 + ldil L%whichqs, %arg3 + ldd P_BACK(arg7), arg6 + std arg7, P_FORW(%arg0) + std %arg0, P_BACK(arg7) + ldw R%whichqs(%arg3), arg5 + std %arg0, P_FORW(arg6) + mtctl %r1, %sar + std arg6, P_BACK(%arg0) + vdepi 1, 1, arg5 + bv 0(%rp) + stw arg5, R%whichqs(%arg3) +EXIT(setrunqueue) + +/* + * remrunqueue(struct proc *p); + * Remove a process from its queue. Should be called at splclock(). + */ + .align 32 +ENTRY(remrunqueue,0) + ldb P_PRIORITY(%arg0), %r1 + shd %r0, %r1, 2, %r1 + ldil L%whichqs, arg5 + mtsar %r1 + ldw R%whichqs(arg5), arg6 + +#ifdef DIAGNOSTIC + bvb,<,n arg6, remrunqueue_ok + +Lremrunqueue_panic + copy %arg0, %arg1 + ldil L%Lrrqpstr, %arg0 + .call + b,l panic, %rp + ldo R%Lrrqpstr(%arg0), %arg0 + +Lrrqpstr + .asciz "remrunqueue(%p), bit=%x" + .align 8 +remrunqueue_ok +#endif + ldd P_BACK(%arg0), arg7 + std %r0, P_BACK(%arg0) + ldd P_FORW(%arg0), %arg0 + std %arg0, P_FORW(arg7) + vdepi 0, 1, arg6 + sub,*<> arg7, %arg0, %r0 + stw arg6, R%whichqs(arg5) + bv 0(%rp) + std arg7, P_BACK(%arg0) +EXIT(remrunqueue) + +/* + * cpu_switch() + * find the highest priority process and resume it. + */ + .align 32 +ENTRY(cpu_switch,128) + ldil L%cpl, %r1 + ldw R%cpl(%r1), %ret0 + copy %r3, %r1 + std %rp, HPPA_FRAME_RP(%sp) + copy %sp, %r3 + stwm %r1, HPPA_FRAME_SIZE+20*8(%sp) + ldo -(HPPA_FRAME_SIZE)(%sp), ap + stw %ret0, 2*8(ap) /* cpl */ + + /* + * Clear curproc so that we don't accumulate system time while idle. + */ + mfctl %cr24, %r1 + ldd CI_CURPROC(%r1), %arg2 + b switch_search + std %r0, CI_CURPROC(%r1) + /* remain on the old (curproc)'s stack until we have a better choice */ + +cpu_idle + .call + b,l spllower, %rp + copy %r0, %arg0 + .import uvm, data + ldil L%uvm, %r1 + ldo R%uvm(%r1), %r1 + ldw PAGE_IDLE_ZERO(%r1), %r1 + sub,<> %r0, %r1, %r0 + b,n cpu_loop + + .call + b,l uvm_pageidlezero, %rp + std %arg2, 8(%r3) + + ldw 2*8(ap), %ret0 /* cpl */ + ldd 8(%r3), %arg2 + +cpu_loop + ldil L%cpl, %arg0 + stw %ret0, R%cpl(%arg0) + +switch_search + /* + * t1: &whichqs + * arg2: old curproc + * + */ + ldil L%whichqs, %r1 + ldw R%whichqs(%r1), %arg2 + comb,=,n %r0, %arg2, cpu_idle + copy %r0, %arg0 + + ldi 0, %arg3 +getbit + mtsar %arg3 + bvb,>=,n %arg2, getbit + ldo 1(%arg3), %arg3 + + ldil L%qs, %arg2 + ldo R%qs(%arg2), %arg2 + depd %arg3, 62, 63, %arg3 + shladd,l %arg3, 3, %arg2, %arg2 + + ldd P_FORW(%arg2), %arg1 +#ifdef DIAGNOSTIC + comb,<> %arg2, %arg1, link_ok + nop +switch_error + copy %arg3, %arg1 + copy %arg2, %arg2 + ldil L%Lcspstr, %arg0 + .call + b,l panic, %rp + ldo R%Lcspstr(%arg0), %arg0 +Lcspstr + .asciz "cpu_switch: bit=%x, q/p=%p" + .align 8 +link_ok +#endif + ldil L%want_resched, %r1 + stw %r0, R%want_resched(%r1) + + ldd P_FORW(%arg1), %arg0 + std %arg0, P_FORW(%arg2) + std %arg2, P_BACK(%arg0) + std %r0, P_BACK(%arg1) + + ldil L%whichqs, %r1 + vdepi 0, 1, %arg3 + sub,<> %arg2, %arg0, %r0 + stw %arg3, R%whichqs(%r1) + + /* don't need &whichqs (t1) starting here */ +#ifdef DIAGNOSTIC + ldd P_WCHAN(%arg1), %arg3 + comb,<>,n %r0, %arg3, switch_error + copy %arg1, %t2 + ldb P_STAT(%arg1), %arg3 + comib,<>,n SRUN, %arg3, switch_error + copy %arg1, %arg2 + /* + * Either we must be switching to the same process, or + * the new process' kernel stack must be reasonable. + */ + comb,=,n %arg1, %arg2, kstack_ok + ldd P_ADDR(%arg1), %arg0 + ldd U_PCB+PCB_KSP(%arg0), %arg3 + ldo NBPG(%arg0), %arg0 + comb,>>,n %arg0, %arg3, switch_error + copy %arg1, %arg2 + sub %arg3, %arg0, %arg3 + ldil L%USPACE, %arg0 + ldo R%USPACE(%arg0), %arg0 + comb,<<=,n %arg0, %arg3, switch_error + copy %arg1, %arg2 +kstack_ok +#endif + ldi SONPROC, %r1 + stb %r1, P_STAT(%arg1) + /* Skip context switch if same process. */ + comb,=,n %arg1, %arg2, switch_return + + /* If old process exited, don't bother. */ + comb,=,n %r0, %arg2, switch_exited + + /* + * 2. save old proc context + * + * arg2: old proc + */ + ldd P_ADDR(%arg2), %r1 + /* save callee-save registers */ + std %r4, 1*8(%r3) + std %sp, U_PCB+PCB_KSP(%r1) + std %r5, 2*8(%r3) + std %r6, 3*8(%r3) + std %r7, 4*8(%r3) + std %r8, 5*8(%r3) + std %r9, 6*8(%r3) + std %r10, 7*8(%r3) + std %r11, 8*8(%r3) + std %r12, 9*8(%r3) + std %r13, 10*8(%r3) + std %r14, 11*8(%r3) + std %r15, 12*8(%r3) + std %r16, 13*8(%r3) + std %r17, 14*8(%r3) + std %r18, 15*8(%r3) + fdc %r0(%r1) + std %r0, 1*8(ap) /* say no trampoline */ + sync + + /* don't need old curproc (arg2) starting from here */ +switch_exited + /* + * 3. restore new proc context + * + * arg1: new proc + */ + ldd P_ADDR(%arg1), %arg3 + ldd P_MD_REGS(%arg1), %r1 + ldd U_PCB+PCB_KSP(%arg3), %sp + mtctl %r0, %cr10 /* ccr */ + ldd TF_CR30(%r1), %arg2 + ldd TF_PIDR2(%r1), %arg3 + mtctl %arg2, %cr30 + mtctl %arg3, %pidr2 + ldo -(HPPA_FRAME_SIZE+20*8)(%sp), %r3 + ldo -(HPPA_FRAME_SIZE)(%sp), ap + ldd 0*8(ap), %arg0 + ldd 1*8(ap), %arg3 /* in case we're on trampoline */ + sub,*= %r0, %arg3, %r0 + b,n switch_gonnajump + ldd 1*8(%r3), %r4 + ldd 2*8(%r3), %r5 + ldd 3*8(%r3), %r6 + ldd 4*8(%r3), %r7 + ldd 5*8(%r3), %r8 + ldd 6*8(%r3), %r9 + ldd 7*8(%r3), %r10 + ldd 8*8(%r3), %r11 + ldd 9*8(%r3), %r12 + ldd 10*8(%r3), %r13 + ldd 11*8(%r3), %r14 + ldd 12*8(%r3), %r15 + ldd 13*8(%r3), %r16 + ldd 14*8(%r3), %r17 + ldd 15*8(%r3), %r18 +switch_gonnajump + ldw 2*8(ap), %ret0 /* cpl */ + ldil L%cpl, %r1 + stw %ret0, R%cpl(%r1) + sync + +switch_return + mfctl %cr24, %r1 + std %arg1, CI_CURPROC(%r1) + ldd HPPA_FRAME_RP(%r3), %rp + bv 0(%rp) + ldd,mb -(HPPA_FRAME_SIZE+20*8)(%sp), %r3 +EXIT(cpu_switch) + +ENTRY(switch_trampoline,0) + .call + blr %r0, %rp + bv,n %r0(%arg3) + nop + mfctl %cr24, %arg1 + ldd CI_CURPROC(%arg1), %r1 + b $syscall_return + ldd P_MD_REGS(%r1), %arg0 +EXIT(switch_trampoline) + +/* + * Signal "trampoline" code. Invoked from RTE setup by sendsig(). + */ +ENTRY(sigcode,0) + bb,>=,n %arg3, 30, sigcode_call + dep %r0, 31, 2, %arg3 + ldd 4(%arg3), %r19 + ldd 0(%arg3), %arg3 +sigcode_call + .call + ble 0(%sr0, %arg3) + copy %r31, %rp + + ldil L%SYSCALLGATE, %r1 + copy %r4, %arg0 + .call + ble 4(%sr7, %r1) + ldi SYS_sigreturn, %r1 + + ldil L%SYSCALLGATE, %r1 + copy %ret0, %arg0 + .call + ble 4(%sr7, %r1) + ldi SYS_exit, %r1 + + .align 256 +/* TODO syscall entry */ + +ALTENTRY(esigcode) +EXIT(sigcode) + +/* + * struct cpu_info *curcpu(void); + */ +LEAF_ENTRY(curcpu) + bv %r0(%rp) + mfctl %cr24, %ret0 +EXIT(curcpu) + +/* + * int splraise(int newcpl); + */ +LEAF_ENTRY(splraise) + bv %r0(%rp) + nop + + extrd,u %arg0, 63, 32, %arg0 +#ifdef DEBUG + cmpib,<=,n NIPL, %arg0, splraise_ok + copy %arg0, %arg1 + ldil L%splraise_fmt, %arg0 + b,l panic, %rp + ldo R%splraise_fmt(%arg0), %arg0 + bv %r0(%rp) + ldi IPL_HIGH, %ret0 +splraise_fmt + .asciz "splraise(%d)" + .align 8 +splraise_ok +#endif + sync + mfctl %eiem, %arg2 + mtctl %r0, %eiem + ldil L%cpl, %r1 + ldw R%cpl(%r1), %ret0 + ldil L%imask, %arg3 + ldo R%imask(%arg3), %arg3 + sub,<= %arg0, %ret0, %r0 + ldd,s %arg0(%arg3), %arg2 + sub,<= %arg0, %ret0, %r0 + stw %arg0, R%cpl(%r1) + sync + bv %r0(%rp) + mtctl %arg2, %eiem +EXIT(splraise) + +/* + * int spllower(int newcpl); + */ +LEAF_ENTRY(spllower) + bv %r0(%rp) + nop + + extrd,u %arg0, 63, 32, %arg0 +#ifdef DEBUG + cmpib,<=,n NIPL, %arg0, spllower_ok + copy %arg0, %arg1 + ldil L%spllower_fmt, %arg0 + b,l panic, %rp + ldo R%spllower_fmt(%arg0), %arg0 + bv %r0(%rp) + ldi IPL_HIGH, %ret0 +spllower_fmt + .asciz "spllower(%d)" + .align 8 +spllower_ok +#endif + sync + mfctl %eiem, %arg2 + mtctl %r0, %eiem + ldil L%cpl, %r1 + ldw R%cpl(%r1), %ret0 + ldil L%imask, %arg3 + ldo R%imask(%arg3), %arg3 + sub,>= %arg0, %ret0, %r0 + ldd,s %arg0(%arg3), %arg2 + sub,>= %arg0, %ret0, %r0 + stw %arg0, R%cpl(%r1) + sync + bv %r0(%rp) + mtctl %arg2, %eiem +EXIT(spllower) + + .end diff --git a/sys/arch/hppa64/hppa64/machdep.c b/sys/arch/hppa64/hppa64/machdep.c new file mode 100644 index 00000000000..4f47ca92e49 --- /dev/null +++ b/sys/arch/hppa64/hppa64/machdep.c @@ -0,0 +1,1200 @@ +/* $OpenBSD: machdep.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/signalvar.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/buf.h> +#include <sys/reboot.h> +#include <sys/device.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/timeout.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/msgbuf.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/user.h> +#include <sys/exec.h> +#include <sys/sysctl.h> +#include <sys/core.h> +#include <sys/kcore.h> +#include <sys/extent.h> +#ifdef SYSVMSG +#include <sys/msg.h> +#endif + +#include <sys/mount.h> +#include <sys/syscallargs.h> + +#include <uvm/uvm.h> +#include <uvm/uvm_page.h> + +#include <dev/cons.h> +#include <dev/clock_subr.h> + +#include <machine/pdc.h> +#include <machine/iomod.h> +#include <machine/psl.h> +#include <machine/reg.h> +#include <machine/autoconf.h> +#include <machine/kcore.h> + +#ifdef COMPAT_HPUX +#include <compat/hpux/hpux.h> +#endif + +#ifdef DDB +#include <machine/db_machdep.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_extern.h> +#endif + +#include <hppa/dev/cpudevs.h> + +/* + * Patchable buffer cache parameters + */ +#ifdef NBUF +int nbuf = NBUF; +#else +int nbuf = 0; +#endif + +#ifndef BUFCACHEPERCENT +#define BUFCACHEPERCENT 10 +#endif /* BUFCACHEPERCENT */ + +#ifdef BUFPAGES +int bufpages = BUFPAGES; +#else +int bufpages = 0; +#endif +int bufcachepercent = BUFCACHEPERCENT; + +/* + * Different kinds of flags used throughout the kernel. + */ +int cold = 1; /* unset when engine is up to go */ +extern int msgbufmapped; /* set when safe to use msgbuf */ + +/* + * cache configuration, for most machines is the same + * numbers, so it makes sense to do defines w/ numbers depending + * on configured cpu types in the kernel + */ +int icache_stride, icache_line_mask; +int dcache_stride, dcache_line_mask; + +/* + * things to not kill + */ +volatile u_int8_t *machine_ledaddr; +int machine_ledword, machine_leds; +struct cpu_info cpu0_info; + +/* + * CPU params (should be the same for all cpus in the system) + */ +struct pdc_cache pdc_cache PDC_ALIGNMENT; +struct pdc_model pdc_model PDC_ALIGNMENT; + + /* w/ a little deviation should be the same for all installed cpus */ +u_int cpu_ticksnum, cpu_ticksdenom; + + /* exported info */ +char machine[] = MACHINE_ARCH; +char cpu_model[128]; +int cpu_hvers; +enum hppa_cpu_type cpu_type; +const char *cpu_typename; +u_int fpu_version; +#ifdef COMPAT_HPUX +int cpu_model_hpux; /* contains HPUX_SYSCONF_CPU* kind of value */ +#endif + +dev_t bootdev; +int physmem, resvmem, resvphysmem, esym; +paddr_t avail_end; + +/* + * Things for MI glue to stick on. + */ +struct user *proc0paddr; +long mem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(32) / sizeof(long)]; +struct extent *hppa_ex; + +struct vm_map *exec_map = NULL; +struct vm_map *phys_map = NULL; +/* Virtual page frame for /dev/mem (see mem.c) */ +vaddr_t vmmap; + +void delay_init(void); +static __inline void fall(int, int, int, int, int); +void dumpsys(void); +void hpmc_dump(void); +void cpuid(void); + +/* + * wide used hardware params + */ +struct pdc_hwtlb pdc_hwtlb PDC_ALIGNMENT; +struct pdc_coproc pdc_coproc PDC_ALIGNMENT; +struct pdc_coherence pdc_coherence PDC_ALIGNMENT; +struct pdc_spidb pdc_spidbits PDC_ALIGNMENT; +struct pdc_model pdc_model PDC_ALIGNMENT; + +#ifdef DEBUG +int sigdebug = 0; +pid_t sigpid = 0; +#define SDB_FOLLOW 0x01 +#endif + +int +hppa_cpuspeed(int *mhz) +{ + *mhz = PAGE0->mem_10msec / 10000; + + return (0); +} + +void +hppa_init(start) + paddr_t start; +{ + extern int kernel_text; + int error; + + mtctl((long)&cpu0_info, 24); + + pdc_init(); /* init PDC iface, so we can call em easy */ + + delay_init(); /* calculate cpu clock ratio */ + + cpuid(); + + /* cache parameters */ + if ((error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_DFLT, + &pdc_cache)) < 0) { +#ifdef DEBUG + printf("WARNING: PDC_CACHE error %d\n", error); +#endif + } + + dcache_line_mask = pdc_cache.dc_conf.cc_line * 16 - 1; + dcache_stride = pdc_cache.dc_stride; + icache_line_mask = pdc_cache.ic_conf.cc_line * 16 - 1; + icache_stride = pdc_cache.ic_stride; + + /* cache coherence params (pbably available for 8k only) */ + error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_SETCS, + &pdc_coherence, 1, 1, 1, 1); +#ifdef DEBUG + printf ("PDC_CACHE_SETCS: %d, %d, %d, %d (%d)\n", + pdc_coherence.ia_cst, pdc_coherence.da_cst, + pdc_coherence.ita_cst, pdc_coherence.dta_cst, error); +#endif + error = pdc_call((iodcio_t)pdc, 0, PDC_CACHE, PDC_CACHE_GETSPIDB, + &pdc_spidbits, 0, 0, 0, 0); + printf("SPID bits: 0x%x, error = %d\n", pdc_spidbits.spidbits, error); + +#if 0 +TODO hpmc/toc/pfr + /* setup hpmc handler */ + { + extern u_int hpmc_v[]; /* from locore.s */ + register u_int *p = hpmc_v; + + if (pdc_call((iodcio_t)pdc, 0, PDC_INSTR, PDC_INSTR_DFLT, p)) + *p = 0x08000240; + + p[6] = (u_int)&hpmc_dump; + p[7] = 32; + p[5] = -(p[0] + p[1] + p[2] + p[3] + p[4] + p[6] + p[7]); + } + + { + extern u_int hppa_toc[], hppa_toc_end[]; + register u_int cksum, *p; + + for (cksum = 0, p = hppa_toc; p < hppa_toc_end; p++) + cksum += *p; + + *p = cksum; + PAGE0->ivec_toc = (u_int)&hppa_toc[0]; + PAGE0->ivec_toclen = (hppa_toc_end - hppa_toc + 1) * 4; + } + + { + extern u_int hppa_pfr[], hppa_pfr_end[]; + register u_int cksum, *p; + + for (cksum = 0, p = hppa_pfr; p < hppa_pfr_end; p++) + cksum += *p; + + *p = cksum; + PAGE0->ivec_mempf = (u_int)&hppa_pfr[0]; + PAGE0->ivec_mempflen = (hppa_pfr_end - hppa_pfr + 1) * 4; + } +#endif + avail_end = trunc_page(PAGE0->imm_max_mem); + if (avail_end > 0x4000000) + avail_end = 0x4000000; + physmem = btoc(avail_end); + resvmem = btoc(((vaddr_t)&kernel_text)); + + /* we hope this won't fail */ + hppa_ex = extent_create("mem", 0, HPPA_PHYSMAP, M_DEVBUF, + (caddr_t)mem_ex_storage, sizeof(mem_ex_storage), + EX_NOCOALESCE|EX_NOWAIT); + if (extent_alloc_region(hppa_ex, 0, (vaddr_t)PAGE0->imm_max_mem, + EX_NOWAIT)) + panic("cannot reserve main memory"); + +#ifdef SYSVMSG +{ + vaddr_t v; + + v = hppa_round_page(start); +#define valloc(name, type, num) (name) = (type *)v; v = (vaddr_t)((name)+(num)) + valloc(msgpool, char, msginfo.msgmax); + valloc(msgmaps, struct msgmap, msginfo.msgseg); + valloc(msghdrs, struct msg, msginfo.msgtql); + valloc(msqids, struct msqid_ds, msginfo.msgmni); +#undef valloc + v = hppa_round_page(v); + bzero ((void *)start, (v - start)); + start = v; +} +#endif + /* sets resvphysmem */ + pmap_bootstrap(start); + + /* buffer cache parameters */ + if (bufpages == 0) + bufpages = physmem / 100 * + (physmem <= 0x1000? 5 : bufcachepercent); + + if (nbuf == 0) + nbuf = bufpages < 16? 16 : bufpages; + + /* Restrict to at most 50% filled kvm */ + if (nbuf * MAXBSIZE > + (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / 2) + nbuf = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / + MAXBSIZE / 2; + + /* More buffer pages than fits into the buffers is senseless. */ + if (bufpages > nbuf * MAXBSIZE / PAGE_SIZE) + bufpages = nbuf * MAXBSIZE / PAGE_SIZE; + + if (!(buf = (struct buf *)pmap_steal_memory(round_page(nbuf * + sizeof(struct buf)), NULL, NULL))) + panic("cpu_startup: no space for bufs"); + bzero(buf, nbuf * sizeof(struct buf)); + + /* space has been reserved in pmap_bootstrap() */ + msgbufp = (struct msgbuf *)(ptoa(physmem) - round_page(MSGBUFSIZE)); + initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE)); + msgbufmapped = 1; + + /* they say PDC_COPROC might turn fault light on */ + pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_DISP, + PDC_OSTAT(PDC_OSTAT_RUN) | 0xCEC0); + + cpu_cpuspeed = &hppa_cpuspeed; + +#ifdef DDB + ddb_init(); + if (boothowto & RB_KDB) + Debugger(); +#endif + ptlball(); + ficacheall(); + fdcacheall(); +printf("out\n"); +} + +void +cpuid() +{ + extern u_int fpu_enable; + struct pdc_cpuid pdc_cpuid PDC_ALIGNMENT; + int error; + + /* identify system type */ + if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_INFO, + &pdc_model)) < 0) { +#ifdef DEBUG + printf("WARNING: PDC_MODEL error %d\n", error); +#endif + pdc_model.hvers = 0; + } + + bzero(&pdc_cpuid, sizeof(pdc_cpuid)); + if (pdc_call((iodcio_t)pdc, 0, PDC_MODEL, PDC_MODEL_CPUID, + &pdc_cpuid, 0, 0, 0, 0) >= 0) { + + /* patch for old 8200 */ + if (pdc_cpuid.version == HPPA_CPU_PCXU && + pdc_cpuid.revision > 0x0d) + pdc_cpuid.version = HPPA_CPU_PCXUP; + + cpu_type = pdc_cpuid.version; + } + + /* locate coprocessors and SFUs */ + bzero(&pdc_coproc, sizeof(pdc_coproc)); + if ((error = pdc_call((iodcio_t)pdc, 0, PDC_COPROC, PDC_COPROC_DFLT, + &pdc_coproc, 0, 0, 0, 0)) < 0) + printf("WARNING: PDC_COPROC error %d\n", error); + else { + printf("pdc_coproc: 0x%x, 0x%x; model %x rev %x\n", + pdc_coproc.ccr_enable, pdc_coproc.ccr_present, + pdc_coproc.fpu_model, pdc_coproc.fpu_revision); + fpu_enable = pdc_coproc.ccr_enable & 0xc0; + + /* a kludge to detect PCXW */ + if (pdc_coproc.fpu_model == HPPA_FPU_PCXW) + cpu_type = HPPA_CPU_PCXW; + } + + if (!cpu_type) + printf("WARNING: UNKNOWN CPU TYPE; GOOD LUCK\n"); + cpu_typename = hppa_mod_info(HPPA_TYPE_CPU, cpu_type); + + if (pdc_model.arch_rev != 8) + panic("CANNOT RUN 64BIT KERNEL on 32BIT CPU"); + + { + const char *p; + char buf[32]; + + cpu_hvers = pdc_model.hvers >> 4; + if (!cpu_hvers) { + p = "(UNKNOWN)"; + } else { + p = hppa_mod_info(HPPA_TYPE_BOARD, cpu_hvers); + if (!p) { + snprintf(buf, sizeof buf, "(UNKNOWN 0x%x)", + cpu_hvers); + p = buf; + } + } + + snprintf(cpu_model, sizeof cpu_model, + "HP 9000/%s PA-RISC 2.0", p); + } +#ifdef DEBUG + printf("%s\n", cpu_model); +#endif +} + +void +cpu_startup(void) +{ + vaddr_t minaddr, maxaddr; + vsize_t size; + int i, base, residual; + + /* + * psychodelic kingdom come + * ... run, run, run + * psychodelic kings and queens + * join me in this one love dream + */ + printf("%s%s\n", version, cpu_model); + printf("real mem = %u (%u reserved for PROM, %u used by OpenBSD)\n", + ctob(physmem), ctob(resvmem), ctob(resvphysmem - resvmem)); + +printf("here2\n"); + size = MAXBSIZE * nbuf; + if (uvm_map(kernel_map, &minaddr, round_page(size), + NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_NONE, + UVM_PROT_NONE, UVM_INH_NONE, UVM_ADV_NORMAL, 0))) + panic("cpu_startup: cannot allocate VM for buffers"); + buffers = (caddr_t)minaddr; + base = bufpages / nbuf; + residual = bufpages % nbuf; + for (i = 0; i < nbuf; i++) { + vaddr_t curbuf; + int cbpgs, pd; + +{ extern int pmapdebug; pd = pmapdebug; pmapdebug = 0; } + /* + * First <residual> buffers get (base+1) physical pages + * allocated for them. The rest get (base) physical pages. + * + * The rest of each buffer occupies virtual space, + * but has no physical memory allocated for it. + */ + curbuf = (vaddr_t) buffers + (i * MAXBSIZE); + + for (cbpgs = base + (i < residual? 1 : 0); cbpgs--; ) { + struct vm_page *pg; + + if ((pg = uvm_pagealloc(NULL, 0, NULL, 0)) == NULL) + panic("cpu_startup: not enough memory for " + "buffer cache"); + pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), + UVM_PROT_RW); + curbuf += PAGE_SIZE; + } +{ extern int pmapdebug; pmapdebug = pd; } + } + +printf("here3\n"); + /* + * 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); + +printf("here4\n"); + /* + * Allocate a submap for physio + */ + phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + VM_PHYS_SIZE, 0, FALSE, NULL); + +printf("here5\n"); + printf("avail mem = %lu\n", ptoa(uvmexp.free)); + printf("using %u buffers containing %u bytes of memory\n", + nbuf, (unsigned)bufpages * PAGE_SIZE); + + /* + * Set up buffers, so they can be used to read disk labels. + */ + bufinit(); + vmmap = uvm_km_valloc_wait(kernel_map, NBPG); + +printf("here6\n"); + /* + * Configure the system. + */ + if (boothowto & RB_CONFIG) { +#ifdef BOOT_CONFIG + user_config(); +#else + printf("kernel does not support -c; continuing..\n"); +#endif + } +printf("here7\n"); +} + +/* + * initialize the system time from the time of day clock + */ +void +inittodr(t) + time_t t; +{ + struct pdc_tod tod PDC_ALIGNMENT; + int error, tbad = 0; + + if (t < 12*SECYR) { + printf ("WARNING: preposterous time in file system"); + t = 6*SECYR + 186*SECDAY + SECDAY/2; + tbad = 1; + } + + if ((error = pdc_call((iodcio_t)pdc, + 1, PDC_TOD, PDC_TOD_READ, &tod, 0, 0, 0, 0, 0))) + printf("clock: failed to fetch (%d)\n", error); + + time.tv_sec = tod.sec; + time.tv_usec = tod.usec; + + if (!tbad) { + u_long dt; + + dt = (time.tv_sec < t)? t - time.tv_sec : time.tv_sec - t; + + if (dt < 2 * SECDAY) + return; + printf("WARNING: clock %s %ld days", + time.tv_sec < t? "lost" : "gained", dt / SECDAY); + } + + printf (" -- CHECK AND RESET THE DATE!\n"); +} + +/* + * reset the time of day clock to the value in time + */ +void +resettodr() +{ + int error; + + if ((error = pdc_call((iodcio_t)pdc, 1, PDC_TOD, PDC_TOD_WRITE, + time.tv_sec, time.tv_usec))) + printf("clock: failed to save (%d)\n", error); +} + +/* + * compute cpu clock ratio such as: + * cpu_ticksnum / cpu_ticksdenom = t + delta + * delta -> 0 + */ +void +delay_init(void) +{ + u_long num, denom, delta, mdelta; + + mdelta = ULONG_MAX; + for (denom = 1; denom < 1000; denom++) { + num = (PAGE0->mem_10msec * denom) / 10000; + delta = num * 10000 / denom - PAGE0->mem_10msec; + if (!delta) { + cpu_ticksdenom = denom; + cpu_ticksnum = num; + break; + } else if (delta < mdelta) { + cpu_ticksdenom = denom; + cpu_ticksnum = num; + mdelta = delta; + } + } +printf("nom=%lu denom=%lu\n", cpu_ticksnum, cpu_ticksdenom); +} + +void +delay(us) + u_int us; +{ + u_long start, end, n; + + start = mfctl(CR_ITMR); + while (us) { + n = min(1000, us); + end = start + n * cpu_ticksnum / cpu_ticksdenom; + + /* N.B. Interval Timer may wrap around */ + if (end < start) + do + start = mfctl(CR_ITMR); + while (start > end); + + do + start = mfctl(CR_ITMR); + while (start < end); + + us -= n; + } +} + +static __inline void +fall(c_base, c_count, c_loop, c_stride, data) + int c_base, c_count, c_loop, c_stride, data; +{ + int loop; + + for (; c_count--; c_base += c_stride) + for (loop = c_loop; loop--; ) + if (data) + __asm __volatile("fdce 0(%%sr0,%0)" + :: "r" (c_base)); + else + __asm __volatile("fice 0(%%sr0,%0)" + :: "r" (c_base)); +} + +void +ficacheall(void) +{ + /* + * Flush the instruction, then data cache. + */ + fall(pdc_cache.ic_base, pdc_cache.ic_count, pdc_cache.ic_loop, + pdc_cache.ic_stride, 0); + sync_caches(); +} + +void +fdcacheall(void) +{ + fall(pdc_cache.dc_base, pdc_cache.dc_count, pdc_cache.dc_loop, + pdc_cache.dc_stride, 1); + sync_caches(); +} + +void +ptlball(void) +{ + register pa_space_t sp; + register int i, j, k; + + /* instruction TLB */ + sp = pdc_cache.it_sp_base; + for (i = 0; i < pdc_cache.it_sp_count; i++) { + register vaddr_t off = pdc_cache.it_off_base; + for (j = 0; j < pdc_cache.it_off_count; j++) { + for (k = 0; k < pdc_cache.it_loop; k++) + pitlb(sp, off); + off += pdc_cache.it_off_stride; + } + sp += pdc_cache.it_sp_stride; + } + + /* data TLB */ + sp = pdc_cache.dt_sp_base; + for (i = 0; i < pdc_cache.dt_sp_count; i++) { + register vaddr_t off = pdc_cache.dt_off_base; + for (j = 0; j < pdc_cache.dt_off_count; j++) { + for (k = 0; k < pdc_cache.dt_loop; k++) + pdtlb(sp, off); + off += pdc_cache.dt_off_stride; + } + sp += pdc_cache.dt_sp_stride; + } +} + +void +boot(howto) + int howto; +{ + /* If system is cold, just halt. */ + if (cold) { + /* (Unless the user explicitly asked for reboot.) */ + if ((howto & RB_USERREQ) == 0) + howto |= RB_HALT; + } else { + + boothowto = howto | (boothowto & RB_HALT); + + if (!(howto & RB_NOSYNC)) { + vfs_shutdown(); + /* + * If we've been adjusting the clock, the todr + * will be out of synch; adjust it now unless + * the system was sitting in ddb. + */ + if ((howto & RB_TIMEBAD) == 0) + resettodr(); + else + printf("WARNING: not updating battery clock\n"); + } + + /* XXX probably save howto into stable storage */ + + splhigh(); + + if (howto & RB_DUMP) + dumpsys(); + + doshutdownhooks(); + } + + /* in case we came on powerfail interrupt */ + if (cold_hook) + (*cold_hook)(HPPA_COLD_COLD); + + if (howto & RB_HALT) { + if (howto & RB_POWERDOWN && cold_hook) { + printf("Powering off..."); + DELAY(2000000); + (*cold_hook)(HPPA_COLD_OFF); + DELAY(1000000); + } + + printf("System halted!\n"); + DELAY(2000000); + __asm __volatile("stwas %0, 0(%1)" + :: "r" (CMD_STOP), "r" (HPPA_LBCAST + iomod_command)); + } else { + printf("rebooting..."); + DELAY(2000000); + __asm __volatile(".export hppa_reset, entry\n\t" + ".label hppa_reset"); + __asm __volatile("stwas %0, 0(%1)" + :: "r" (CMD_RESET), "r" (HPPA_LBCAST + iomod_command)); + } + + for(;;); /* loop while bus reset is comming up */ + /* NOTREACHED */ +} + +u_long dumpmag = 0x8fca0101; /* magic number */ +int dumpsize = 0; /* pages */ +long dumplo = 0; /* blocks */ + +/* + * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers. + */ +int +cpu_dumpsize(void) +{ + int size; + + size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)); + if (roundup(size, dbtob(1)) != dbtob(1)) + return -1; + + return 1; +} + +/* + * Called from HPMC handler in locore + */ +void +hpmc_dump(void) +{ + printf("HPMC\n"); + + cold = 0; + boot(RB_NOSYNC); +} + +int +cpu_dump(void) +{ + long buf[dbtob(1) / sizeof (long)]; + kcore_seg_t *segp; + cpu_kcore_hdr_t *cpuhdrp; + + segp = (kcore_seg_t *)buf; + cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp)) / sizeof (long)]; + + /* + * Generate a segment header. + */ + CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU); + segp->c_size = dbtob(1) - ALIGN(sizeof(*segp)); + + /* + * Add the machine-dependent header info + */ + /* nothing for now */ + + return (bdevsw[major(dumpdev)].d_dump) + (dumpdev, dumplo, (caddr_t)buf, dbtob(1)); +} + +/* + * Dump the kernel's image to the swap partition. + */ +#define BYTES_PER_DUMP NBPG + +void +dumpsys(void) +{ + int psize, bytes, i, n; + register caddr_t maddr; + register daddr_t blkno; + register int (*dump)(dev_t, daddr_t, caddr_t, size_t); + register int error; + + /* Save registers + savectx(&dumppcb); */ + + if (dumpsize == 0) + dumpconf(); + if (dumplo <= 0) { + printf("\ndump to dev %x not possible\n", dumpdev); + return; + } + printf("\ndumping to dev %x, offset %ld\n", dumpdev, dumplo); + + psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev); + printf("dump "); + if (psize == -1) { + printf("area unavailable\n"); + return; + } + + if (!(error = cpu_dump())) { + + bytes = ctob(physmem); + maddr = NULL; + blkno = dumplo + cpu_dumpsize(); + dump = bdevsw[major(dumpdev)].d_dump; + for (i = 0; i < bytes; i += n) { + + /* Print out how many MBs we are to go. */ + n = bytes - i; + if (n && (n % (1024*1024)) == 0) + printf("%d ", n / (1024 * 1024)); + + /* Limit size for next transfer. */ + if (n > BYTES_PER_DUMP) + n = BYTES_PER_DUMP; + + if ((error = (*dump)(dumpdev, blkno, maddr, n))) + break; + maddr += n; + blkno += btodb(n); + } + } + + switch (error) { + case ENXIO: printf("device bad\n"); break; + case EFAULT: printf("device not ready\n"); break; + case EINVAL: printf("area improper\n"); break; + case EIO: printf("i/o error\n"); break; + case EINTR: printf("aborted from console\n"); break; + case 0: printf("succeeded\n"); break; + default: printf("error %d\n", error); break; + } +} + +/* bcopy(), error on fault */ +int +kcopy(from, to, size) + const void *from; + void *to; + size_t size; +{ + return spcopy(HPPA_SID_KERNEL, from, HPPA_SID_KERNEL, to, size); +} + +int +copystr(src, dst, size, lenp) + const void *src; + void *dst; + size_t size; + size_t *lenp; +{ + return spstrcpy(HPPA_SID_KERNEL, src, HPPA_SID_KERNEL, dst, size, lenp); +} + +int +copyinstr(src, dst, size, lenp) + const void *src; + void *dst; + size_t size; + size_t *lenp; +{ + return spstrcpy(curproc->p_addr->u_pcb.pcb_space, src, + HPPA_SID_KERNEL, dst, size, lenp); +} + + +int +copyoutstr(src, dst, size, lenp) + const void *src; + void *dst; + size_t size; + size_t *lenp; +{ + return spstrcpy(HPPA_SID_KERNEL, src, + curproc->p_addr->u_pcb.pcb_space, dst, size, lenp); +} + + +int +copyin(src, dst, size) + const void *src; + void *dst; + size_t size; +{ + return spcopy(curproc->p_addr->u_pcb.pcb_space, src, + HPPA_SID_KERNEL, dst, size); +} + +int +copyout(src, dst, size) + const void *src; + void *dst; + size_t size; +{ + return spcopy(HPPA_SID_KERNEL, src, + curproc->p_addr->u_pcb.pcb_space, dst, size); +} + +/* + * Set registers on exec. + */ +void +setregs(p, pack, stack, retval) + struct proc *p; + struct exec_package *pack; + u_long stack; + register_t *retval; +{ + extern paddr_t fpu_curpcb; /* from locore.S */ + struct trapframe *tf = p->p_md.md_regs; + struct pcb *pcb = &p->p_addr->u_pcb; + register_t zero; + + tf->tf_flags = TFF_SYS|TFF_LAST; + tf->tf_iioq[1] = 4 + + (tf->tf_iioq[0] = pack->ep_entry | HPPA_PC_PRIV_USER); + tf->tf_rp = 0; + tf->tf_args[0] = (u_long)PS_STRINGS; + tf->tf_args[1] = tf->tf_args[2] = 0; /* XXX dynload stuff */ + + /* setup terminal stack frame */ + stack = (stack + 0x1f) & ~0x1f; + tf->tf_r3 = stack; + tf->tf_sp = stack += HPPA_FRAME_SIZE; + tf->tf_ret1 = stack - 16; /* ap */ + zero = 0; + copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t)); + copyout(&zero, (caddr_t)(stack + HPPA_FRAME_RP), sizeof(register_t)); + + /* reset any of the pending FPU exceptions */ + if (tf->tf_cr30 == fpu_curpcb) { + fpu_exit(); + fpu_curpcb = 0; + } + pcb->pcb_fpregs[0] = ((u_int64_t)HPPA_FPU_INIT) << 32; + pcb->pcb_fpregs[1] = 0; + pcb->pcb_fpregs[2] = 0; + pcb->pcb_fpregs[3] = 0; + fdcache(HPPA_SID_KERNEL, (vaddr_t)pcb->pcb_fpregs, 8 * 4); + + retval[1] = 0; +} + +/* + * Send an interrupt to process. + */ +void +sendsig(catcher, sig, mask, code, type, val) + sig_t catcher; + int sig, mask; + u_long code; + int type; + union sigval val; +{ + extern paddr_t fpu_curpcb; /* from locore.S */ + extern u_int fpu_enable; + struct proc *p = curproc; + struct trapframe *tf = p->p_md.md_regs; + struct sigacts *psp = p->p_sigacts; + struct sigcontext ksc; + siginfo_t ksi; + register_t scp, sip, zero; + int sss; + + /* TODO sendsig */ + +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) + printf("sendsig: %s[%d] sig %d catcher %p\n", + p->p_comm, p->p_pid, sig, catcher); +#endif + + /* flush the FPU ctx first */ + if (tf->tf_cr30 == fpu_curpcb) { + mtctl(fpu_enable, CR_CCR); + fpu_save(fpu_curpcb); + /* fpu_curpcb = 0; only needed if fpregs are preset */ + mtctl(0, CR_CCR); + } + + ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; + + /* + * Allocate space for the signal handler context. + */ + if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack && + (psp->ps_sigonstack & sigmask(sig))) { + scp = (register_t)psp->ps_sigstk.ss_sp; + psp->ps_sigstk.ss_flags |= SS_ONSTACK; + } else + scp = (tf->tf_sp + 63) & ~63; + + sss = (sizeof(ksc) + 63) & ~63; + sip = 0; + if (psp->ps_siginfo & sigmask(sig)) { + sip = scp + sizeof(ksc); + sss += (sizeof(ksi) + 63) & ~63; + } + +#ifdef DEBUG + if ((tf->tf_iioq[0] & ~PAGE_MASK) == SYSCALLGATE) + printf("sendsig: interrupted syscall at 0x%x:0x%x, flags %b\n", + tf->tf_iioq[0], tf->tf_iioq[1], tf->tf_ipsw, PSL_BITS); +#endif + + ksc.sc_mask = mask; + ksc.sc_fp = scp + sss; + ksc.sc_ps = tf->tf_ipsw; + ksc.sc_pcoqh = tf->tf_iioq[0]; + ksc.sc_pcoqt = tf->tf_iioq[1]; + bcopy(tf, &ksc.sc_regs[0], 32*8); + ksc.sc_regs[0] = tf->tf_sar; + bcopy(p->p_addr->u_pcb.pcb_fpregs, ksc.sc_fpregs, + sizeof(ksc.sc_fpregs)); + + sss += HPPA_FRAME_SIZE; + tf->tf_args[0] = sig; + tf->tf_args[1] = sip; + tf->tf_args[2] = tf->tf_r4 = scp; + tf->tf_args[3] = (register_t)catcher; + tf->tf_sp = scp + sss; + tf->tf_ipsw &= ~(PSL_N|PSL_B); + tf->tf_iioq[0] = HPPA_PC_PRIV_USER | p->p_sigcode; + tf->tf_iioq[1] = tf->tf_iioq[0] + 4; + /* disable tracing in the trapframe */ + +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) + printf("sendsig(%d): sig %d scp %p fp %p sp 0x%x\n", + p->p_pid, sig, scp, ksc.sc_fp, (register_t)scp + sss); +#endif + + if (copyout(&ksc, (void *)scp, sizeof(ksc))) + sigexit(p, SIGILL); + + if (sip) { + initsiginfo(&ksi, sig, code, type, val); + if (copyout(&ksi, (void *)sip, sizeof(ksi))) + sigexit(p, SIGILL); + } + + zero = 0; + if (copyout(&zero, (caddr_t)scp + sss - HPPA_FRAME_SIZE, + sizeof(register_t))) + sigexit(p, SIGILL); + +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) + printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid, + tf->tf_iioq[0], tf->tf_args[3]); +#endif +} + +int +sys_sigreturn(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + extern paddr_t fpu_curpcb; /* from locore.S */ + struct sys_sigreturn_args /* { + syscallarg(struct sigcontext *) sigcntxp; + } */ *uap = v; + struct sigcontext *scp, ksc; + struct trapframe *tf = p->p_md.md_regs; + int error; + + /* TODO sigreturn */ + + scp = SCARG(uap, sigcntxp); +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) + printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); +#endif + + /* flush the FPU ctx first */ + if (tf->tf_cr30 == fpu_curpcb) { + fpu_exit(); + fpu_curpcb = 0; + } + + if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc))) + return (error); + +#define PSL_MBS (PSL_C|PSL_Q|PSL_P|PSL_D|PSL_I) +#define PSL_MBZ (PSL_Y|PSL_Z|PSL_S|PSL_X|PSL_M|PSL_R) + if ((ksc.sc_ps & (PSL_MBS|PSL_MBZ)) != PSL_MBS) + return (EINVAL); + + if (ksc.sc_onstack) + p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; + p->p_sigmask = ksc.sc_mask &~ sigcantmask; + + tf->tf_sar = ksc.sc_regs[0]; + ksc.sc_regs[0] = tf->tf_flags; + bcopy(&ksc.sc_regs[0], tf, 32*8); + bcopy(ksc.sc_fpregs, p->p_addr->u_pcb.pcb_fpregs, + sizeof(ksc.sc_fpregs)); + fdcache(HPPA_SID_KERNEL, (vaddr_t)p->p_addr->u_pcb.pcb_fpregs, + sizeof(ksc.sc_fpregs)); + + tf->tf_iioq[0] = ksc.sc_pcoqh; + tf->tf_iioq[1] = ksc.sc_pcoqt; + tf->tf_ipsw = ksc.sc_ps; + +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) + printf("sigreturn(%d): returns\n", p->p_pid); +#endif + return (EJUSTRETURN); +} + +/* + * machine dependent system variables. + */ +int +cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; + struct proc *p; +{ + 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 */ +} + + +/* + * consinit: + * initialize the system console. + */ +void +consinit(void) +{ + static int initted; + + if (!initted) { + initted++; + cninit(); + } +} + +#ifdef DIAGNOSTIC +void +splassert_check(int wantipl, const char *func) +{ + extern int cpl; /* from locoore.s */ + + if (cpl < wantipl) { + splassert_fail(wantipl, cpl, func); + } +} +#endif diff --git a/sys/arch/hppa64/hppa64/mainbus.c b/sys/arch/hppa64/hppa64/mainbus.c new file mode 100644 index 00000000000..871d032d846 --- /dev/null +++ b/sys/arch/hppa64/hppa64/mainbus.c @@ -0,0 +1,661 @@ +/* $OpenBSD: mainbus.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "power.h" + +#undef BTLBDEBUG + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/reboot.h> +#include <sys/extent.h> +#include <sys/mbuf.h> + +#include <uvm/uvm.h> +#include <uvm/uvm_page.h> + +#include <machine/pdc.h> +#include <machine/iomod.h> +#include <machine/autoconf.h> + +struct mainbus_softc { + struct device sc_dv; + + hppa_hpa_t sc_hpa; +}; + +int mbmatch(struct device *, void *, void *); +void mbattach(struct device *, struct device *, void *); + +struct cfattach mainbus_ca = { + sizeof(struct mainbus_softc), mbmatch, mbattach +}; + +struct cfdriver mainbus_cd = { + NULL, "mainbus", DV_DULL +}; + +struct pdc_hpa pdc_hpa PDC_ALIGNMENT; +struct pdc_power_info pdc_power_info PDC_ALIGNMENT; + +/* from machdep.c */ +extern struct extent *hppa_ex; + +int +mbus_add_mapping(bus_addr_t bpa, bus_size_t size, int flags, + bus_space_handle_t *bshp) +{ + paddr_t spa, epa; + int bank, off; + + if ((bank = vm_physseg_find(atop(bpa), &off)) >= 0) + panic("mbus_add_mapping: mapping real memory @0x%lx", bpa); + + for (spa = trunc_page(bpa), epa = bpa + size; + spa < epa; spa += PAGE_SIZE) + pmap_kenter_pa(spa, spa, UVM_PROT_RW); + + *bshp = bpa; + return (0); +} + +int +mbus_map(void *v, bus_addr_t bpa, bus_size_t size, + int flags, bus_space_handle_t *bshp) +{ + int error; + + bpa &= HPPA_PHYSMAP; + if ((error = extent_alloc_region(hppa_ex, bpa, size, EX_NOWAIT))) + return (error); + + if ((error = mbus_add_mapping(bpa, size, flags, bshp))) { + if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) { + printf("bus_space_map: pa 0x%lx, size 0x%lx\n", + bpa, size); + printf("bus_space_map: can't free region\n"); + } + } + + return error; +} + +void +mbus_unmap(void *v, bus_space_handle_t bsh, bus_size_t size) +{ + u_long sva, eva; + + sva = hppa_trunc_page(bsh); + eva = hppa_round_page(bsh + size); + +#ifdef DIAGNOSTIC + if (eva <= sva) + panic("bus_space_unmap: overflow"); +#endif + + pmap_kremove(sva, eva - sva); + + if (extent_free(hppa_ex, bsh, size, EX_NOWAIT)) { + printf("bus_space_unmap: ps 0x%lx, size 0x%lx\n", + bsh, size); + printf("bus_space_unmap: can't free region\n"); + } +} + +int +mbus_alloc(void *v, 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) +{ + bus_addr_t bpa; + int error; + + rstart &= HPPA_PHYSMAP; + rend &= HPPA_PHYSMAP; + if (rstart < hppa_ex->ex_start || rend > hppa_ex->ex_end) + panic("bus_space_alloc: bad region start/end"); + + if ((error = extent_alloc_subregion(hppa_ex, rstart, rend, size, + align, 0, boundary, EX_NOWAIT, &bpa))) + return (error); + + if ((error = mbus_add_mapping(bpa, size, flags, bshp))) { + if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) { + printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n", + bpa, size); + printf("bus_space_alloc: can't free region\n"); + } + } + + *addrp = bpa | ~HPPA_PHYSMAP; + return (error); +} + +void +mbus_free(void *v, bus_space_handle_t h, bus_size_t size) +{ + /* bus_space_unmap() does all that we need to do. */ + mbus_unmap(v, h, size); +} + +int +mbus_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t size, bus_space_handle_t *nbshp) +{ + *nbshp = bsh + offset; + return (0); +} + +void +mbus_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op) +{ + sync_caches(); +} + +struct hppa64_bus_space_tag hppa_bustag = { + NULL, + + mbus_map, mbus_unmap, mbus_subregion, mbus_alloc, mbus_free, + mbus_barrier, +}; + +int +mbus_dmamap_create(void *v, bus_size_t size, int nsegments, + bus_size_t maxsegsz, bus_size_t boundary, int flags, + bus_dmamap_t *dmamp) +{ + struct hppa64_bus_dmamap *map; + size_t mapsize; + + mapsize = sizeof(*map) + (sizeof(bus_dma_segment_t) * (nsegments - 1)); + map = malloc(mapsize, M_DEVBUF, + (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK); + if (!map) + return (ENOMEM); + + bzero(map, mapsize); + map->_dm_size = size; + map->_dm_segcnt = nsegments; + map->_dm_maxsegsz = maxsegsz; + map->_dm_boundary = boundary; + map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT); + map->dm_mapsize = 0; + map->dm_nsegs = 0; + + *dmamp = map; + return (0); +} + +void +mbus_dmamap_unload(void *v, bus_dmamap_t map) +{ + map->dm_mapsize = 0; + map->dm_nsegs = 0; +} + +void +mbus_dmamap_destroy(void *v, bus_dmamap_t map) +{ + if (map->dm_mapsize != 0) + mbus_dmamap_unload(v, map); + + free(map, M_DEVBUF); +} + +/* + * Utility function to load a linear buffer. lastaddrp holds state + * between invocations (for multiple-buffer loads). segp contains + * the starting segment on entrace, and the ending segment on exit. + * first indicates if this is the first invocation of this function. + */ +int +_bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, + bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp, + int *segp, int first) +{ + bus_size_t sgsize; + bus_addr_t curaddr, lastaddr, baddr, bmask; + vaddr_t vaddr = (vaddr_t)buf; + int seg; + pmap_t pmap; + + pmap = p? p->p_vmspace->vm_map.pmap : pmap_kernel(); + lastaddr = *lastaddrp; + bmask = ~(map->_dm_boundary - 1); + + for (seg = *segp; buflen > 0 ; ) { + /* + * Get the physical address for this segment. + */ + pmap_extract(pmap, vaddr, (paddr_t *)&curaddr); + + /* + * Compute the segment size, and adjust counts. + */ + sgsize = PAGE_SIZE - ((u_long)vaddr & PAGE_MASK); + if (buflen < sgsize) + sgsize = buflen; + + /* + * Make sure we don't cross any boundaries. + */ + if (map->_dm_boundary > 0) { + baddr = (curaddr + map->_dm_boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + + /* + * Insert chunk into a segment, coalescing with + * previous segment if possible. + */ + if (first) { + map->dm_segs[seg].ds_addr = curaddr; + map->dm_segs[seg].ds_len = sgsize; + map->dm_segs[seg]._ds_va = vaddr; + first = 0; + } else { + if (curaddr == lastaddr && + (map->dm_segs[seg].ds_len + sgsize) <= + map->_dm_maxsegsz && + (map->_dm_boundary == 0 || + (map->dm_segs[seg].ds_addr & bmask) == + (curaddr & bmask))) + map->dm_segs[seg].ds_len += sgsize; + else { + if (++seg >= map->_dm_segcnt) + break; + map->dm_segs[seg].ds_addr = curaddr; + map->dm_segs[seg].ds_len = sgsize; + map->dm_segs[seg]._ds_va = vaddr; + } + } + + lastaddr = curaddr + sgsize; + vaddr += sgsize; + buflen -= sgsize; + } + + *segp = seg; + *lastaddrp = lastaddr; + + /* + * Did we fit? + */ + if (buflen != 0) + return (EFBIG); /* XXX better return value here? */ + return (0); +} + +int +mbus_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size, + struct proc *p, int flags) +{ + paddr_t lastaddr; + int seg, error; + + /* + * Make sure that on error condition we return "no valid mappings". + */ + map->dm_nsegs = 0; + map->dm_mapsize = 0; + + if (size > map->_dm_size) + return (EINVAL); + + seg = 0; + lastaddr = 0; + error = _bus_dmamap_load_buffer(NULL, map, addr, size, p, flags, + &lastaddr, &seg, 1); + if (error == 0) { + map->dm_mapsize = size; + map->dm_nsegs = seg + 1; + } + + return (0); +} + +int +mbus_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m0, int flags) +{ + paddr_t lastaddr; + int seg, error, first; + struct mbuf *m; + + map->dm_mapsize = 0; + map->dm_nsegs = 0; + +#ifdef DIAGNOSTIC + if ((m0->m_flags & M_PKTHDR) == 0) + panic("_bus_dmamap_load_mbuf: no packet header"); +#endif + + if (m0->m_pkthdr.len > map->_dm_size) + return (EINVAL); + + first = 1; + seg = 0; + error = 0; + lastaddr = 0; + for (m = m0; m != NULL && error == 0; m = m->m_next) { + error = _bus_dmamap_load_buffer(NULL, map, m->m_data, m->m_len, + NULL, flags, &lastaddr, &seg, first); + first = 0; + } + if (error == 0) { + map->dm_mapsize = m0->m_pkthdr.len; + map->dm_nsegs = seg + 1; + } + + return (error); +} + +int +mbus_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags) +{ + paddr_t lastaddr; + int seg, i, error, first; + bus_size_t minlen, resid; + struct proc *p = NULL; + struct iovec *iov; + caddr_t addr; + + /* + * Make sure that on error condition we return "no valid mappings". + */ + map->dm_mapsize = 0; + map->dm_nsegs = 0; + + resid = uio->uio_resid; + iov = uio->uio_iov; + + if (resid > map->_dm_size) + return (EINVAL); + + if (uio->uio_segflg == UIO_USERSPACE) { + p = uio->uio_procp; +#ifdef DIAGNOSTIC + if (p == NULL) + panic("_bus_dmamap_load_uio: USERSPACE but no proc"); +#endif + } + + first = 1; + seg = 0; + error = 0; + lastaddr = 0; + for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) { + /* + * Now at the first iovec to load. Load each iovec + * until we have exhausted the residual count. + */ + minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len; + addr = (caddr_t)iov[i].iov_base; + + error = _bus_dmamap_load_buffer(NULL, map, addr, minlen, + p, flags, &lastaddr, &seg, first); + first = 0; + + resid -= minlen; + } + if (error == 0) { + map->dm_mapsize = uio->uio_resid; + map->dm_nsegs = seg + 1; + } + return (error); +} + +int +mbus_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs, + int nsegs, bus_size_t size, int flags) +{ + if (nsegs > map->_dm_segcnt || size > map->_dm_size) + return (EINVAL); + + /* + * Make sure we don't cross any boundaries. + */ + if (map->_dm_boundary) { + bus_addr_t bmask = ~(map->_dm_boundary - 1); + int i; + + for (i = 0; i < nsegs; i++) { + if (segs[i].ds_len > map->_dm_maxsegsz) + return (EINVAL); + if ((segs[i].ds_addr & bmask) != + ((segs[i].ds_addr + segs[i].ds_len - 1) & bmask)) + return (EINVAL); + } + } + + bcopy(segs, map->dm_segs, nsegs * sizeof(*segs)); + map->dm_nsegs = nsegs; + map->dm_mapsize = size; + return (0); +} + +void +mbus_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off, bus_size_t len, + int ops) +{ + bus_dma_segment_t *ps = map->dm_segs, + *es = &map->dm_segs[map->dm_nsegs]; + + if (off >= map->_dm_size) + return; + + if ((off + len) > map->_dm_size) + len = map->_dm_size - off; + + for (; len && ps < es; ps++) + if (off > ps->ds_len) + off -= ps->ds_len; + else { + bus_size_t l = ps->ds_len - off; + if (l > len) + l = len; + fdcache(HPPA_SID_KERNEL, ps->_ds_va + off, l); + len -= l; + off = 0; + } + + /* for either operation sync the shit away */ + sync_caches(); +} + +int +mbus_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment, + bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, + int *rsegs, int flags) +{ + extern paddr_t avail_end; + struct pglist pglist; + struct vm_page *pg; + + size = round_page(size); + + TAILQ_INIT(&pglist); + if (uvm_pglistalloc(size, 0, avail_end, alignment, boundary, + &pglist, 1, flags & BUS_DMA_NOWAIT)) + return (ENOMEM); + + pg = TAILQ_FIRST(&pglist); + segs[0]._ds_va = segs[0].ds_addr = VM_PAGE_TO_PHYS(pg); + segs[0].ds_len = size; + *rsegs = 1; + + for(; pg; pg = TAILQ_NEXT(pg, pageq)) + /* XXX for now */ + pmap_changebit(pg, PTE_UNCACHABLE, 0); + pmap_update(pmap_kernel()); + + return (0); +} + +void +mbus_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs) +{ + struct pglist pglist; + paddr_t pa, epa; + + TAILQ_INIT(&pglist); + for(; nsegs--; segs++) + for (pa = segs->ds_addr, epa = pa + segs->ds_len; + pa < epa; pa += PAGE_SIZE) { + struct vm_page *pg = PHYS_TO_VM_PAGE(pa); + if (!pg) + panic("mbus_dmamem_free: no page for pa"); + TAILQ_INSERT_TAIL(&pglist, pg, pageq); + } + uvm_pglistfree(&pglist); +} + +int +mbus_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size, + caddr_t *kvap, int flags) +{ + *kvap = (caddr_t)segs[0].ds_addr; + return 0; +} + +void +mbus_dmamem_unmap(void *v, caddr_t kva, size_t size) +{ +} + +paddr_t +mbus_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off, + int prot, int flags) +{ + panic("_dmamem_mmap: not implemented"); +} + +const struct hppa64_bus_dma_tag hppa_dmatag = { + NULL, + mbus_dmamap_create, mbus_dmamap_destroy, + mbus_dmamap_load, mbus_dmamap_load_mbuf, + mbus_dmamap_load_uio, mbus_dmamap_load_raw, + mbus_dmamap_unload, mbus_dmamap_sync, + + mbus_dmamem_alloc, mbus_dmamem_free, mbus_dmamem_map, + mbus_dmamem_unmap, mbus_dmamem_mmap +}; + +int +mbmatch(parent, cfdata, aux) + struct device *parent; + void *cfdata; + void *aux; +{ + struct cfdata *cf = cfdata; + + /* there will be only one */ + if (cf->cf_unit) + return 0; + + return 1; +} + +void +mbattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct mainbus_softc *sc = (struct mainbus_softc *)self; + struct confargs nca; + bus_space_handle_t ioh; + bus_addr_t hpa; + + /* fetch the "default" cpu hpa */ + if (pdc_call((iodcio_t)pdc, 0, PDC_HPA, PDC_HPA_DFLT, &pdc_hpa) < 0) + panic("mbattach: PDC_HPA failed"); + hpa = pdc_hpa.hpa | 0xffffffff00000000UL; + + printf(" [flex %lx]\n", hpa & HPPA_FLEX_MASK); + + /* map all the way till the end of the memory */ + if (bus_space_map(&hppa_bustag, hpa, HPPA_PHYSEND - hpa + 1, 0, &ioh)) + panic("mbattach: cannot map mainbus IO space"); + + /* + * Local-Broadcast the HPA to all modules on this bus + */ + ((struct iomod *)(HPPA_LBCAST & HPPA_PHYSMAP))->io_flex = + (hpa & HPPA_FLEX_MASK) | DMA_ENABLE; + + sc->sc_hpa = hpa; + + /* PDC first */ + bzero (&nca, sizeof(nca)); + nca.ca_name = "pdc"; + nca.ca_iot = &hppa_bustag; + nca.ca_dmatag = &hppa_dmatag; + config_found(self, &nca, mbprint); + +#if NPOWER > 0 + /* get some power */ + bzero (&nca, sizeof(nca)); + nca.ca_name = "power"; + nca.ca_irq = -1; + if (!pdc_call((iodcio_t)pdc, 0, PDC_SOFT_POWER, + PDC_SOFT_POWER_INFO, &pdc_power_info, 0)) { + nca.ca_iot = &hppa_bustag; + nca.ca_hpa = pdc_power_info.addr; + nca.ca_hpamask = HPPA_IOBEGIN; + } + config_found(self, &nca, mbprint); +#endif + + bzero (&nca, sizeof(nca)); + nca.ca_iot = &hppa_bustag; + nca.ca_dmatag = &hppa_dmatag; + pdc_patscan(self, &nca, -1); +} + +/* + * retrive CPU #N HPA value + */ +hppa_hpa_t +cpu_gethpa(n) + int n; +{ + struct mainbus_softc *sc; + + sc = mainbus_cd.cd_devs[0]; + + return sc->sc_hpa; +} + +int +mbprint(aux, pnp) + void *aux; + const char *pnp; +{ + struct confargs *ca = aux; + + if (pnp) + printf("\"%s\" at %s", ca->ca_name, pnp); + + if (ca->ca_hpa) + printf(" hpa %lx", ca->ca_hpa); + + return (UNCONF); +} diff --git a/sys/arch/hppa64/hppa64/pmap.c b/sys/arch/hppa64/hppa64/pmap.c new file mode 100644 index 00000000000..4edab6922d7 --- /dev/null +++ b/sys/arch/hppa64/hppa64/pmap.c @@ -0,0 +1,1216 @@ +/* $OpenBSD: pmap.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define PMAPDEBUG + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/lock.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <sys/pool.h> +#include <sys/extent.h> + +#include <uvm/uvm.h> + +#include <machine/iomod.h> + +#include <dev/rndvar.h> + +#ifdef PMAPDEBUG +#define DPRINTF(l,s) do { \ + if ((pmapdebug & (l)) == (l)) \ + printf s; \ +} while(0) +#define PDB_FOLLOW 0x00000001 +#define PDB_INIT 0x00000002 +#define PDB_ENTER 0x00000004 +#define PDB_REMOVE 0x00000008 +#define PDB_CREATE 0x00000010 +#define PDB_PTPAGE 0x00000020 +#define PDB_CACHE 0x00000040 +#define PDB_BITS 0x00000080 +#define PDB_COLLECT 0x00000100 +#define PDB_PROTECT 0x00000200 +#define PDB_EXTRACT 0x00000400 +#define PDB_VP 0x00000800 +#define PDB_PV 0x00001000 +#define PDB_PARANOIA 0x00002000 +#define PDB_WIRING 0x00004000 +#define PDB_PMAP 0x00008000 +#define PDB_STEAL 0x00010000 +#define PDB_PHYS 0x00020000 +#define PDB_POOL 0x00040000 +int pmapdebug = 0 + | PDB_INIT +/* | PDB_FOLLOW */ +/* | PDB_VP */ +/* | PDB_PV */ +/* | PDB_ENTER */ +/* | PDB_REMOVE */ +/* | PDB_STEAL */ +/* | PDB_PROTECT */ +/* | PDB_PHYS */ + ; +#else +#define DPRINTF(l,s) /* */ +#endif + +paddr_t physical_steal, physical_end; + +struct pmap kernel_pmap_store; +struct pool pmap_pmap_pool; +struct pool pmap_pv_pool; +int pmap_pvlowat = 252; +int pmap_initialized; +int pmap_nkpdes = 32; + +pt_entry_t hppa_prot[8]; +#define pmap_prot(m,vp) (hppa_prot[(vp)] | ((m) == pmap_kernel()? 0 : PTE_USER)) + +pt_entry_t kernel_ptes[] = { + PTE_EXEC | PTE_ORDER | PTE_PREDICT | PTE_WIRED | + TLB_PAGE(0x000000) | PTE_PG4M, + PTE_WRITE | PTE_ORDER | PTE_DIRTY | PTE_WIRED | + TLB_PAGE(0x400000) | PTE_PG4M, + PTE_WRITE | PTE_ORDER | PTE_DIRTY | PTE_WIRED | + TLB_PAGE(0x800000) | PTE_PG4M, + PTE_WRITE | PTE_ORDER | PTE_DIRTY | PTE_WIRED | + TLB_PAGE(0xc00000) | PTE_PG4M +}; + +#define pmap_pvh_attrs(a) \ + (((a) & PTE_DIRTY) | ((a) ^ PTE_REFTRAP)) + +struct vm_page * +pmap_pagealloc(int wait) +{ + struct vm_page *pg; + + if ((pg = uvm_pagealloc(NULL, 0, NULL, + UVM_PGA_USERESERVE | UVM_PGA_ZERO)) == NULL) + printf("pmap_pagealloc fail\n"); + + return (pg); +} + +volatile pt_entry_t * +pmap_pde_get(volatile u_int32_t *pd, vaddr_t va) +{ + int i; + + DPRINTF(PDB_FOLLOW|PDB_VP, + ("pmap_pde_get(%p, 0x%lx)\n", pd, va)); + + i = (va & PIE_MASK) >> PIE_SHIFT; + if (i) { + pd = (volatile u_int32_t *)((u_int64_t)pd[i] << PAGE_SHIFT); + + if (!pd) + return (NULL); + } else + pd += PAGE_SIZE / sizeof(*pd); + + i = (va & PDE_MASK) >> PDE_SHIFT; + return (pt_entry_t *)((u_int64_t)pd[i] << PAGE_SHIFT); +} + +void +pmap_pde_set(struct pmap *pm, vaddr_t va, paddr_t ptp) +{ + volatile u_int32_t *pd = pm->pm_pdir; + int i; + + DPRINTF(PDB_FOLLOW|PDB_VP, + ("pmap_pde_set(%p, 0x%lx, 0x%lx)\n", pm, va, ptp)); + + i = (va & PIE_MASK) >> PIE_SHIFT; + if (i) + pd = (volatile u_int32_t *)((u_int64_t)pd[i] << PAGE_SHIFT); + else + pd += PAGE_SIZE / sizeof(*pd); + + i = (va & PDE_MASK) >> PDE_SHIFT; + pd[i] = ptp >> PAGE_SHIFT; +} + +pt_entry_t * +pmap_pde_alloc(struct pmap *pm, vaddr_t va, struct vm_page **pdep) +{ + struct vm_page *pg; + paddr_t pa; + + DPRINTF(PDB_FOLLOW|PDB_VP, + ("pmap_pde_alloc(%p, 0x%lx, %p)\n", pm, va, pdep)); + + if ((pg = pmap_pagealloc(0)) == NULL) + return (NULL); + + pa = VM_PAGE_TO_PHYS(pg); + + DPRINTF(PDB_FOLLOW|PDB_VP, ("pmap_pde_alloc: pde %lx\n", pa)); + + pg->flags &= ~PG_BUSY; /* never busy */ + pg->wire_count = 1; /* no mappings yet */ + pmap_pde_set(pm, va, pa); + pm->pm_stats.resident_count++; /* count PTP as resident */ + pm->pm_ptphint = pg; + if (pdep) + *pdep = pg; + return ((pt_entry_t *)pa); +} + +static __inline struct vm_page * +pmap_pde_ptp(struct pmap *pm, volatile pt_entry_t *pde) +{ + paddr_t pa = (paddr_t)pde; + + DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pde_ptp(%p, %p)\n", pm, pde)); + + if (pm->pm_ptphint && VM_PAGE_TO_PHYS(pm->pm_ptphint) == pa) + return (pm->pm_ptphint); + + DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pde_ptp: lookup 0x%lx\n", pa)); + + return (PHYS_TO_VM_PAGE(pa)); +} + +static __inline void +pmap_pde_release(struct pmap *pmap, vaddr_t va, struct vm_page *ptp) +{ + DPRINTF(PDB_FOLLOW|PDB_PV, + ("pmap_pde_release(%p, 0x%lx, %p)\n", pmap, va, ptp)); + + if (pmap != pmap_kernel() && --ptp->wire_count <= 1) { + DPRINTF(PDB_FOLLOW|PDB_PV, + ("pmap_pde_release: disposing ptp %p\n", ptp)); + pmap_pde_set(pmap, va, 0); + pmap->pm_stats.resident_count--; + if (pmap->pm_ptphint == ptp) + pmap->pm_ptphint = NULL; + ptp->wire_count = 0; +#ifdef DIAGNOSTIC + if (ptp->flags & PG_BUSY) + panic("pmap_pde_release: busy page table page"); +#endif + pdcache(HPPA_SID_KERNEL, (vaddr_t)ptp, PAGE_SIZE); + uvm_pagefree(ptp); + } +} + +static __inline pt_entry_t +pmap_pte_get(volatile pt_entry_t *pde, vaddr_t va) +{ + DPRINTF(PDB_FOLLOW|PDB_VP, + ("pmap_pte_get(%p, 0x%lx)\n", pde, va)); + + return (pde[(va & PTE_MASK) >> PTE_SHIFT]); +} + +static __inline void +pmap_pte_set(volatile pt_entry_t *pde, vaddr_t va, pt_entry_t pte) +{ + DPRINTF(PDB_FOLLOW|PDB_VP, + ("pmap_pte_set(%p, 0x%lx, 0x%lx)\n", pde, va, pte)); + + pde[(va & PTE_MASK) >> PTE_SHIFT] = pte; +} + +void +pmap_pte_flush(struct pmap *pmap, vaddr_t va, pt_entry_t pte) +{ + if (pte & PTE_EXEC) { + ficache(pmap->pm_space, va, PAGE_SIZE); + pitlb(pmap->pm_space, va); + } + fdcache(pmap->pm_space, va, PAGE_SIZE); + pdtlb(pmap->pm_space, va); +} + +static __inline pt_entry_t +pmap_vp_find(struct pmap *pm, vaddr_t va) +{ + volatile pt_entry_t *pde; + + if (!(pde = pmap_pde_get(pm->pm_pdir, va))) + return (0); + + return (pmap_pte_get(pde, va)); +} + +#ifdef DDB +void +pmap_dump_table(pa_space_t space, vaddr_t sva) +{ + pa_space_t sp; + volatile pt_entry_t *pde; + volatile u_int32_t *pd; + pt_entry_t pte; + vaddr_t va, pdemask; + + if (space) + pd = (u_int32_t *)mfctl(CR_VTOP); + else + pd = pmap_kernel()->pm_pdir; + + for (pdemask = 1, va = sva ? sva : 0; + va < VM_MAX_ADDRESS; va += PAGE_SIZE) { + if (pdemask != (va & (PDE_MASK|PIE_MASK))) { + pdemask = va & (PDE_MASK|PIE_MASK); + if (!(pde = pmap_pde_get(pd, va))) { + va += ~PDE_MASK + 1 - PAGE_SIZE; + continue; + } + printf("%x:%8p:\n", sp, pde); + } + + if (!(pte = pmap_pte_get(pde, va))) + continue; + + printf("0x%08lx-0x%08lx:%b\n", + va, PTE_PAGE(pte), PTE_GETBITS(pte), PTE_BITS); + } +} + +void +pmap_dump_pv(paddr_t pa) +{ + struct vm_page *pg; + struct pv_entry *pve; + + pg = PHYS_TO_VM_PAGE(pa); + simple_lock(&pg->mdpage.pvh_lock); + for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next) + printf("%x:%lx\n", pve->pv_pmap->pm_space, pve->pv_va); + simple_unlock(&pg->mdpage.pvh_lock); +} +#endif + +#ifdef PMAPDEBUG +int +pmap_check_alias(struct pv_entry *pve, vaddr_t va, pt_entry_t pte) +{ + int ret; + + /* check for non-equ aliased mappings */ + for (ret = 0; pve; pve = pve->pv_next) { + pte |= pmap_vp_find(pve->pv_pmap, pve->pv_va); + if ((va & HPPA_PGAOFF) != (pve->pv_va & HPPA_PGAOFF) && + (pte & PTE_WRITE)) { + printf("pmap_check_alias: " + "aliased writable mapping 0x%x:0x%lx\n", + pve->pv_pmap->pm_space, pve->pv_va); + ret++; + } + } + + return (ret); +} +#endif + +static __inline struct pv_entry * +pmap_pv_alloc(void) +{ + struct pv_entry *pv; + + DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_alloc()\n")); + + pv = pool_get(&pmap_pv_pool, PR_NOWAIT); + + DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_alloc: %p\n", pv)); + + return (pv); +} + +void +pmap_pv_free(struct pv_entry *pv) +{ + if (pv->pv_ptp) + pmap_pde_release(pv->pv_pmap, pv->pv_va, pv->pv_ptp); + + pool_put(&pmap_pv_pool, pv); +} + +void +pmap_pv_enter(struct vm_page *pg, struct pv_entry *pve, struct pmap *pm, + vaddr_t va, struct vm_page *pdep) +{ + DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_enter(%p, %p, %p, 0x%lx, %p)\n", + pg, pve, pm, va, pdep)); + pve->pv_pmap = pm; + pve->pv_va = va; + pve->pv_ptp = pdep; + pve->pv_next = pg->mdpage.pvh_list; + pg->mdpage.pvh_list = pve; +#ifdef PMAPDEBUG + if (pmap_check_alias(pve, va, 0)) + Debugger(); +#endif +} + +struct pv_entry * +pmap_pv_remove(struct vm_page *pg, struct pmap *pmap, vaddr_t va) +{ + struct pv_entry **pve, *pv; + + DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_pv_remove(%p, %p, 0x%lx)\n", + pg, pmap, va)); + + simple_lock(&pg->mdpage.pvh_lock); /* lock pv_head */ + for(pv = *(pve = &pg->mdpage.pvh_list); + pv; pv = *(pve = &(*pve)->pv_next)) + if (pv->pv_pmap == pmap && pv->pv_va == va) { + *pve = pv->pv_next; + break; + } + simple_unlock(&pg->mdpage.pvh_lock); /* unlock, done! */ + return (pv); +} + +const pt_entry_t hppa_pgs[] = { + PTE_PG4K, + PTE_PG16K, + PTE_PG64K, + PTE_PG256K, + PTE_PG1M, + PTE_PG4M, + PTE_PG16M, + PTE_PG64M +}; +#define nhppa_pgs sizeof(hppa_pgs)/sizeof(hppa_pgs[0]) + +void +pmap_maphys(paddr_t spa, paddr_t epa) +{ + volatile pt_entry_t *pde, *epde, pte; + paddr_t pa, tpa; + int s, e, i; + + DPRINTF(PDB_INIT, ("pmap_maphys: mapping 0x%lx - 0x%lx\n", spa, epa)); + + s = ffs(spa) - 12; + e = ffs(epa) - 12; + + if (s < e || (s == e && s / 2 < nhppa_pgs)) { + i = s / 2; + if (i > nhppa_pgs) + i = nhppa_pgs; + pa = spa; + spa = tpa = 0x1000 << ((i + 1) * 2); + } else if (s > e) { + i = e / 2; + if (i > nhppa_pgs) + i = nhppa_pgs; + epa = pa = epa & (0xfffff000 << ((i + 1) * 2)); + tpa = epa; + } else { + i = s / 2; + if (i > nhppa_pgs) + i = nhppa_pgs; + pa = spa; + spa = tpa = epa; + } + +printf("pa 0x%lx tpa 0x%lx\n", pa, tpa); + while (pa < tpa) { + pte = TLB_PAGE(pa) | hppa_pgs[i - 1] | + PTE_WRITE | PTE_ORDER | PTE_DIRTY | PTE_WIRED; + pde = pmap_pde_get(pmap_kernel()->pm_pdir, pa); + epde = pde + (PTE_MASK >> PTE_SHIFT) + 1; + if (pa + (PTE_MASK + (1 << PTE_SHIFT)) > tpa) + epde = pde + ((tpa & PTE_MASK) >> PTE_SHIFT); +printf("pde %p epde %p pte 0x%lx\n", pde, epde, pte); + for (pde += (pa & PTE_MASK) >> PTE_SHIFT; pde < epde;) + *pde++ = pte; + pa += PTE_MASK + (1 << PTE_SHIFT); + pa &= ~(PTE_MASK | PAGE_MASK); + } + + if (spa < epa) + pmap_maphys(spa, epa); +} + +void +pmap_bootstrap(vstart) + vaddr_t vstart; +{ + extern int resvphysmem, __rodata_end, __data_start; + vaddr_t va, eaddr, addr = hppa_round_page(vstart); + struct pmap *kpm; + + DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_bootstrap(0x%lx)\n", vstart)); + + uvm_setpagesize(); + + hppa_prot[UVM_PROT_NONE] = PTE_ORDER|PTE_ACC_NONE; + hppa_prot[UVM_PROT_READ] = PTE_ORDER|PTE_READ; + hppa_prot[UVM_PROT_WRITE] = PTE_ORDER|PTE_WRITE; + hppa_prot[UVM_PROT_RW] = PTE_ORDER|PTE_READ|PTE_WRITE; + hppa_prot[UVM_PROT_EXEC] = PTE_ORDER|PTE_EXEC; + hppa_prot[UVM_PROT_RX] = PTE_ORDER|PTE_READ|PTE_EXEC; + hppa_prot[UVM_PROT_WX] = PTE_ORDER|PTE_WRITE|PTE_EXEC; + hppa_prot[UVM_PROT_RWX] = PTE_ORDER|PTE_READ|PTE_WRITE|PTE_EXEC; + + /* + * Initialize kernel pmap + */ + kpm = &kernel_pmap_store; + bzero(kpm, sizeof(*kpm)); + simple_lock_init(&kpm->pm_lock); + kpm->pm_refcount = 1; + kpm->pm_space = HPPA_SID_KERNEL; + TAILQ_INIT(&kpm->pm_pglist); + kpm->pm_pdir = (u_int32_t *)mfctl(CR_VTOP); + + /* + * Allocate various tables and structures. + */ + + if (&__rodata_end < &__data_start) { + physical_steal = (vaddr_t)&__rodata_end; + physical_end = (vaddr_t)&__data_start; + DPRINTF(PDB_INIT, ("physpool: 0x%lx @ 0x%lx\n", + physical_end - physical_steal, physical_steal)); + } + + /* map enough PDEs to map initial physmem */ + for (va = 0x1000000, eaddr = ptoa(physmem); + va < eaddr; addr += PAGE_SIZE, va += 1 << PDE_SHIFT) { + bzero((void *)addr, PAGE_SIZE); + pmap_pde_set(kpm, va, addr); + kpm->pm_stats.resident_count++; /* count PTP as resident */ + } + + /* map a little of initial kmem */ + for (va = VM_MIN_KERNEL_ADDRESS + ((pmap_nkpdes - 1) << PDE_SHIFT); + va >= VM_MIN_KERNEL_ADDRESS; + addr += PAGE_SIZE, va -= 1 << PDE_SHIFT) { + bzero((void *)addr, PAGE_SIZE); + pmap_pde_set(kpm, va, addr); + kpm->pm_stats.resident_count++; /* count PTP as resident */ + } + + pmap_maphys(0x1000000, ctob(physmem)); + + eaddr = physmem - atop(round_page(MSGBUFSIZE)); + resvphysmem = atop(addr); + DPRINTF(PDB_INIT, ("physmem: 0x%lx - 0x%lx\n", resvphysmem, eaddr)); + uvm_page_physload(0, physmem, + resvphysmem, eaddr, VM_FREELIST_DEFAULT); +} + +void +pmap_init() +{ + DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_init()\n")); + + pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl", + &pool_allocator_nointr); + pool_init(&pmap_pv_pool, sizeof(struct pv_entry),0,0,0, "pmappv", NULL); + pool_setlowat(&pmap_pv_pool, pmap_pvlowat); + pool_sethiwat(&pmap_pv_pool, pmap_pvlowat * 32); + + pmap_initialized = 1; + + DPRINTF(PDB_FOLLOW|PDB_INIT, ("pmap_init(): done\n")); +} + +#ifdef PMAP_STEAL_MEMORY +vaddr_t +pmap_steal_memory(vsize_t size, vaddr_t *vstartp, vaddr_t *vendp) +{ + vaddr_t va; + int npg; + + DPRINTF(PDB_FOLLOW|PDB_PHYS, + ("pmap_steal_memory(0x%lx, %p, %p)\n", size, vstartp, vendp)); + + size = round_page(size); + npg = atop(size); + + if (vm_physmem[0].avail_end - vm_physmem[0].avail_start < npg) + panic("pmap_steal_memory: no more"); + + if (vstartp) + *vstartp = VM_MIN_KERNEL_ADDRESS; + if (vendp) + *vendp = VM_MAX_KERNEL_ADDRESS; + + vm_physmem[0].end -= npg; + vm_physmem[0].avail_end -= npg; + va = ptoa(vm_physmem[0].avail_end) - size; + bzero((void *)va, size); + + DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_steal_memory: 0x%lx\n", va)); + + return (va); +} +#else +void +pmap_virtual_space(vaddr_t *startp, vaddr_t *endp) +{ + *startp = VM_MIN_KERNEL_ADDRESS; + *endp = VM_MAX_KERNEL_ADDRESS; +} +#endif /* PMAP_STEAL_MEMORY */ + +#ifdef PMAP_GROWKERNEL +vaddr_t +pmap_growkernel(vaddr_t kva) +{ + vaddr_t va; + + DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_growkernel(0x%lx)\n", kva)); + + va = VM_MIN_KERNEL_ADDRESS + (pmap_nkpdes << PDE_SHIFT); + DPRINTF(PDB_PHYS, ("pmap_growkernel: was va 0x%lx\n", va)); + if (va < kva) { + simple_lock(&pmap_kernel()->pm_obj.vmobjlock); + + for ( ; va < kva ; pmap_nkpdes++, va += 1 << PDE_SHIFT) + if (uvm.page_init_done) { + if (!pmap_pde_alloc(pmap_kernel(), va, NULL)) + break; + } else { + paddr_t pa; + + pa = pmap_steal_memory(PAGE_SIZE, NULL, NULL); + if (pa) + panic("pmap_growkernel: out of memory"); + pmap_pde_set(pmap_kernel(), va, pa); + pmap_kernel()->pm_stats.resident_count++; + } + + simple_unlock(&pmap_kernel()->pm_obj.vmobjlock); + } + DPRINTF(PDB_PHYS|PDB_VP, ("pmap_growkernel: now va 0x%lx\n", va)); + return (va); +} +#endif /* PMAP_GROWKERNEL */ + +struct pmap * +pmap_create() +{ + struct pmap *pmap; + struct vm_page *pg; + pa_space_t space; + paddr_t pa; + + DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_create()\n")); + + pmap = pool_get(&pmap_pmap_pool, PR_WAITOK); + + simple_lock_init(&pmap->pm_lock); + pmap->pm_refcount = 1; + pmap->pm_ptphint = NULL; + + TAILQ_INIT(&pmap->pm_pglist); + if (uvm_pglistalloc(2 * PAGE_SIZE, 0, VM_MIN_KERNEL_ADDRESS, + PAGE_SIZE, 2 * PAGE_SIZE, &pmap->pm_pglist, 1, 1)) + panic("pmap_create: no pages"); + + pg = TAILQ_FIRST(&pmap->pm_pglist); + pg->flags &= ~(PG_BUSY|PG_CLEAN); + pmap->pm_pdir = (u_int32_t *)(pa = VM_PAGE_TO_PHYS(pg)); + bzero((void *)pa, PAGE_SIZE); + + /* set the first PIE that's covering low 2g of the address space */ + pg = TAILQ_LAST(&pmap->pm_pglist, pglist); + pg->flags &= ~(PG_BUSY|PG_CLEAN); + *pmap->pm_pdir = (pa = VM_PAGE_TO_PHYS(pg)) >> PAGE_SHIFT; + bzero((void *)pa, PAGE_SIZE); + +/* TODO for (space = 1 + (arc4random() & HPPA_SID_MAX); + pmap_sdir_get(space); space = (space + 1) % HPPA_SID_MAX); */ + pmap->pm_space = space; + + pmap->pm_stats.resident_count = 2; + pmap->pm_stats.wired_count = 0; + + return (pmap); +} + +void +pmap_destroy(pmap) + struct pmap *pmap; +{ + int refs; + + DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_destroy(%p)\n", pmap)); + + simple_lock(&pmap->pm_lock); + refs = --pmap->pm_refcount; + simple_unlock(&pmap->pm_lock); + + if (refs > 0) + return; + + uvm_pglistfree(&pmap->pm_pglist); + TAILQ_INIT(&pmap->pm_pglist); + pool_put(&pmap_pmap_pool, pmap); +} + +/* + * Add a reference to the specified pmap. + */ +void +pmap_reference(struct pmap *pmap) +{ + DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_reference(%p)\n", pmap)); + + simple_lock(&pmap->pm_lock); + pmap->pm_refcount++; + simple_unlock(&pmap->pm_lock); +} + +void +pmap_collect(struct pmap *pmap) +{ + DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_collect(%p)\n", pmap)); + /* nothing yet */ +} + +int +pmap_enter(pmap, va, pa, prot, flags) + struct pmap *pmap; + vaddr_t va; + paddr_t pa; + vm_prot_t prot; + int flags; +{ + volatile pt_entry_t *pde; + pt_entry_t pte; + struct vm_page *pg, *ptp = NULL; + struct pv_entry *pve; + boolean_t wired = (flags & PMAP_WIRED) != 0; + + DPRINTF(PDB_FOLLOW|PDB_ENTER, + ("pmap_enter(%p, 0x%lx, 0x%lx, 0x%x, 0x%x)\n", + pmap, va, pa, prot, flags)); + + simple_lock(&pmap->pm_lock); + + if (!(pde = pmap_pde_get(pmap->pm_pdir, va)) && + !(pde = pmap_pde_alloc(pmap, va, &ptp))) { + if (flags & PMAP_CANFAIL) { + simple_unlock(&pmap->pm_lock); + return (KERN_RESOURCE_SHORTAGE); + } + + panic("pmap_enter: cannot allocate pde"); + } + + if (!ptp) + ptp = pmap_pde_ptp(pmap, pde); + + if ((pte = pmap_pte_get(pde, va))) { + + DPRINTF(PDB_ENTER, + ("pmap_enter: remapping 0x%lx -> 0x%lx\n", pte, pa)); + + pmap_pte_flush(pmap, va, pte); + if (wired && !(pte & PTE_WIRED)) + pmap->pm_stats.wired_count++; + else if (!wired && (pte & PTE_WIRED)) + pmap->pm_stats.wired_count--; + pte &= PTE_UNCACHABLE|PTE_DIRTY|PTE_REFTRAP; + + if (PTE_PAGE(pte) == pa) { + DPRINTF(PDB_FOLLOW|PDB_ENTER, + ("pmap_enter: same page\n")); + goto enter; + } + + pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)); + simple_lock(&pg->mdpage.pvh_lock); + pve = pmap_pv_remove(pg, pmap, va); + pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte); + } else { + DPRINTF(PDB_ENTER, + ("pmap_enter: new mapping 0x%lx -> 0x%lx\n", va, pa)); + pte = PTE_REFTRAP; + pve = NULL; + pmap->pm_stats.resident_count++; + if (wired) + pmap->pm_stats.wired_count++; + if (ptp) + ptp->wire_count++; + simple_lock(&pg->mdpage.pvh_lock); + } + + if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(pa))) { + if (!pve && !(pve = pmap_pv_alloc())) { + if (flags & PMAP_CANFAIL) { + simple_unlock(&pg->mdpage.pvh_lock); + simple_unlock(&pmap->pm_lock); + return (KERN_RESOURCE_SHORTAGE); + } + panic("pmap_enter: no pv entries available"); + } + pmap_pv_enter(pg, pve, pmap, va, ptp); + } else if (pve) + pmap_pv_free(pve); + simple_unlock(&pg->mdpage.pvh_lock); + +enter: + /* preserve old ref & mod */ + pte = TLB_PAGE(pa) | pmap_prot(pmap, prot); + if (wired) + pte |= PTE_WIRED; + pmap_pte_set(pde, va, pte); + + simple_unlock(&pmap->pm_lock); + + DPRINTF(PDB_FOLLOW|PDB_ENTER, ("pmap_enter: leaving\n")); + + return (0); +} + +void +pmap_remove(pmap, sva, eva) + struct pmap *pmap; + vaddr_t sva; + vaddr_t eva; +{ + struct pv_entry *pve; + volatile pt_entry_t *pde; + pt_entry_t pte; + struct vm_page *pg; + vaddr_t pdemask; + int batch; + + DPRINTF(PDB_FOLLOW|PDB_REMOVE, + ("pmap_remove(%p, 0x%lx, 0x%lx)\n", pmap, sva, eva)); + + simple_lock(&pmap->pm_lock); + + for (batch = 0, pdemask = 1; sva < eva; sva += PAGE_SIZE) { + if (pdemask != (sva & PDE_MASK)) { + pdemask = sva & PDE_MASK; + if (!(pde = pmap_pde_get(pmap->pm_pdir, sva))) { + sva += ~PDE_MASK + 1 - PAGE_SIZE; + continue; + } + batch = pdemask == sva && sva + ~PDE_MASK + 1 <= eva; + } + + if ((pte = pmap_pte_get(pde, sva))) { + + /* TODO measure here the speed tradeoff + * for flushing whole PT vs per-page + * in case of non-complete pde fill + */ + pmap_pte_flush(pmap, sva, pte); + if (pte & PTE_WIRED) + pmap->pm_stats.wired_count--; + pmap->pm_stats.resident_count--; + + /* iff properly accounted pde will be dropped anyway */ + if (!batch) + pmap_pte_set(pde, sva, 0); + + if (pmap_initialized && + (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) { + + simple_lock(&pg->mdpage.pvh_lock); + pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte); + if ((pve = pmap_pv_remove(pg, pmap, sva))) + pmap_pv_free(pve); + simple_unlock(&pg->mdpage.pvh_lock); + } + } + } + + simple_unlock(&pmap->pm_lock); + + DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_remove: leaving\n")); +} + +void +pmap_write_protect(pmap, sva, eva, prot) + struct pmap *pmap; + vaddr_t sva; + vaddr_t eva; + vm_prot_t prot; +{ + struct vm_page *pg; + volatile pt_entry_t *pde; + pt_entry_t pte; + u_int tlbprot, pdemask; + + DPRINTF(PDB_FOLLOW|PDB_PMAP, + ("pmap_write_protect(%p, %lx, %lx, %x)\n", pmap, sva, eva, prot)); + + sva = hppa_trunc_page(sva); + tlbprot = pmap_prot(pmap, prot); + + simple_lock(&pmap->pm_lock); + + for (pdemask = 1; sva < eva; sva += PAGE_SIZE) { + if (pdemask != (sva & PDE_MASK)) { + pdemask = sva & PDE_MASK; + if (!(pde = pmap_pde_get(pmap->pm_pdir, sva))) { + sva += ~PDE_MASK + 1 - PAGE_SIZE; + continue; + } + } + if ((pte = pmap_pte_get(pde, sva))) { + + DPRINTF(PDB_PMAP, + ("pmap_write_protect: va=0x%lx pte=0x%lx\n", + sva, pte)); + /* + * Determine if mapping is changing. + * If not, nothing to do. + */ + if ((pte & PTE_ACC_MASK) == tlbprot) + continue; + + pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)); + simple_lock(&pg->mdpage.pvh_lock); + pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte); + simple_unlock(&pg->mdpage.pvh_lock); + + pmap_pte_flush(pmap, sva, pte); + pte &= ~PTE_ACC_MASK; + pte |= tlbprot; + pmap_pte_set(pde, sva, pte); + } + } + + simple_unlock(&pmap->pm_lock); +} + +void +pmap_page_remove(pg) + struct vm_page *pg; +{ + struct pv_entry *pve, *ppve; + + DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_page_remove(%p)\n", pg)); + + if (pg->mdpage.pvh_list == NULL) + return; + + simple_lock(&pg->mdpage.pvh_lock); + for (pve = pg->mdpage.pvh_list; pve; + pve = (ppve = pve)->pv_next, pmap_pv_free(ppve)) { + struct pmap *pmap = pve->pv_pmap; + vaddr_t va = pve->pv_va; + volatile pt_entry_t *pde; + pt_entry_t pte; + + simple_lock(&pmap->pm_lock); + + pde = pmap_pde_get(pmap->pm_pdir, va); + pte = pmap_pte_get(pde, va); + pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte); + + pmap_pte_flush(pmap, va, pte); + if (pte & PTE_WIRED) + pmap->pm_stats.wired_count--; + pmap->pm_stats.resident_count--; + + pmap_pte_set(pde, va, 0); + simple_unlock(&pmap->pm_lock); + } + pg->mdpage.pvh_list = NULL; + simple_unlock(&pg->mdpage.pvh_lock); + + DPRINTF(PDB_FOLLOW|PDB_PV, ("pmap_page_remove: leaving\n")); + +} + +void +pmap_unwire(pmap, va) + struct pmap *pmap; + vaddr_t va; +{ + volatile pt_entry_t *pde; + pt_entry_t pte = 0; + + DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_unwire(%p, 0x%lx)\n", pmap, va)); + + simple_lock(&pmap->pm_lock); + if ((pde = pmap_pde_get(pmap->pm_pdir, va))) { + pte = pmap_pte_get(pde, va); + + if (pte & PTE_WIRED) { + pte &= ~PTE_WIRED; + pmap->pm_stats.wired_count--; + pmap_pte_set(pde, va, pte); + } + } + simple_unlock(&pmap->pm_lock); + + DPRINTF(PDB_FOLLOW|PDB_PMAP, ("pmap_unwire: leaving\n")); + +#ifdef DIAGNOSTIC + if (!pte) + panic("pmap_unwire: invalid va 0x%lx", va); +#endif +} + +boolean_t +pmap_changebit(struct vm_page *pg, pt_entry_t set, pt_entry_t clear) +{ + struct pv_entry *pve; + pt_entry_t res; + + DPRINTF(PDB_FOLLOW|PDB_BITS, + ("pmap_changebit(%p, %lx, %lx)\n", pg, set, clear)); + + simple_lock(&pg->mdpage.pvh_lock); + res = pg->mdpage.pvh_attrs = 0; + for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next) { + struct pmap *pmap = pve->pv_pmap; + vaddr_t va = pve->pv_va; + volatile pt_entry_t *pde; + pt_entry_t opte, pte; + + simple_lock(&pmap->pm_lock); + if ((pde = pmap_pde_get(pmap->pm_pdir, va))) { + opte = pte = pmap_pte_get(pde, va); +#ifdef PMAPDEBUG + if (!pte) { + printf("pmap_changebit: zero pte for 0x%lx\n", + va); + continue; + } +#endif + pte &= ~clear; + pte |= set; + pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte); + res |= pmap_pvh_attrs(opte); + + if (opte != pte) { + pmap_pte_flush(pmap, va, opte); + pmap_pte_set(pde, va, pte); + } + } + simple_unlock(&pmap->pm_lock); + } + simple_unlock(&pg->mdpage.pvh_lock); + + return ((res & (clear | set)) != 0); +} + +boolean_t +pmap_testbit(struct vm_page *pg, pt_entry_t bit) +{ + struct pv_entry *pve; + pt_entry_t pte; + + DPRINTF(PDB_FOLLOW|PDB_BITS, ("pmap_testbit(%p, %lx)\n", pg, bit)); + + simple_lock(&pg->mdpage.pvh_lock); + for(pve = pg->mdpage.pvh_list; !(pg->mdpage.pvh_attrs & bit) && pve; + pve = pve->pv_next) { + simple_lock(&pve->pv_pmap->pm_lock); + pte = pmap_vp_find(pve->pv_pmap, pve->pv_va); + simple_unlock(&pve->pv_pmap->pm_lock); + pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte); + } + simple_unlock(&pg->mdpage.pvh_lock); + + return ((pg->mdpage.pvh_attrs & bit) != 0); +} + +boolean_t +pmap_extract(pmap, va, pap) + struct pmap *pmap; + vaddr_t va; + paddr_t *pap; +{ + pt_entry_t pte; + + DPRINTF(PDB_FOLLOW|PDB_EXTRACT, ("pmap_extract(%p, %lx)\n", pmap, va)); + + simple_lock(&pmap->pm_lock); + pte = pmap_vp_find(pmap, va); + simple_unlock(&pmap->pm_lock); + + if (pte) { + if (pap) + *pap = PTE_PAGE(pte) | (va & PAGE_MASK); + return (TRUE); + } + + return (FALSE); +} + +void +pmap_activate(struct proc *p) +{ + struct pmap *pmap = p->p_vmspace->vm_map.pmap; + struct pcb *pcb = &p->p_addr->u_pcb; + + pcb->pcb_space = pmap->pm_space; + pcb->pcb_uva = (vaddr_t)p->p_addr; +} + +void +pmap_deactivate(struct proc *p) +{ + +} + +static __inline void +pmap_flush_page(struct vm_page *pg, int purge) +{ + struct pv_entry *pve; + + /* purge cache for all possible mappings for the pa */ + simple_lock(&pg->mdpage.pvh_lock); + for(pve = pg->mdpage.pvh_list; pve; pve = pve->pv_next) + if (purge) + pdcache(pve->pv_pmap->pm_space, pve->pv_va, PAGE_SIZE); + else + fdcache(pve->pv_pmap->pm_space, pve->pv_va, PAGE_SIZE); + simple_unlock(&pg->mdpage.pvh_lock); +} + +void +pmap_zero_page(struct vm_page *pg) +{ + paddr_t pa = VM_PAGE_TO_PHYS(pg); + + DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_zero_page(%lx)\n", pa)); + + pmap_flush_page(pg, 1); + bzero((void *)pa, PAGE_SIZE); + fdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE); +} + +void +pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg) +{ + paddr_t spa = VM_PAGE_TO_PHYS(srcpg); + paddr_t dpa = VM_PAGE_TO_PHYS(dstpg); + DPRINTF(PDB_FOLLOW|PDB_PHYS, ("pmap_copy_page(%lx, %lx)\n", spa, dpa)); + + pmap_flush_page(srcpg, 0); + pmap_flush_page(dstpg, 1); + bcopy((void *)spa, (void *)dpa, PAGE_SIZE); + pdcache(HPPA_SID_KERNEL, spa, PAGE_SIZE); + fdcache(HPPA_SID_KERNEL, dpa, PAGE_SIZE); +} + +void +pmap_kenter_pa(va, pa, prot) + vaddr_t va; + paddr_t pa; + vm_prot_t prot; +{ + volatile pt_entry_t *pde; + pt_entry_t pte, opte; + + DPRINTF(PDB_FOLLOW|PDB_ENTER, + ("pmap_kenter_pa(%lx, %lx, %x)\n", va, pa, prot)); + + simple_lock(&pmap->pm_lock); + + if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, va)) && + !(pde = pmap_pde_alloc(pmap_kernel(), va, NULL))) + panic("pmap_kenter_pa: cannot allocate pde for va=0x%lx", va); + opte = pmap_pte_get(pde, va); + pte = TLB_PAGE(pa) | PTE_WIRED | PTE_REFTRAP | + pmap_prot(pmap_kernel(), prot); + if (pa >= 0xf0000000ULL /* TODO (HPPA_IOBEGIN & HPPA_PHYSMAP) */) + pte |= PTE_UNCACHABLE | PTE_ORDER; + DPRINTF(PDB_ENTER, ("pmap_kenter_pa: pde %p va %lx pte %lx\n", + pde, va, pte)); + pmap_pte_set(pde, va, pte); + pmap_kernel()->pm_stats.wired_count++; + pmap_kernel()->pm_stats.resident_count++; + if (opte) + pmap_pte_flush(pmap_kernel(), va, opte); + +#ifdef PMAPDEBUG + { + struct vm_page *pg; + + if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) { + + simple_lock(&pg->mdpage.pvh_lock); + if (pmap_check_alias(pg->mdpage.pvh_list, va, pte)) + Debugger(); + simple_unlock(&pg->mdpage.pvh_lock); + } + } +#endif + simple_unlock(&pmap->pm_lock); + + DPRINTF(PDB_FOLLOW|PDB_ENTER, ("pmap_kenter_pa: leaving\n")); +} + +void +pmap_kremove(va, size) + vaddr_t va; + vsize_t size; +{ + struct pv_entry *pve; + vaddr_t eva, pdemask; + volatile pt_entry_t *pde; + pt_entry_t pte; + struct vm_page *pg; + + DPRINTF(PDB_FOLLOW|PDB_REMOVE, + ("pmap_kremove(%lx, %lx)\n", va, size)); +#ifdef PMAPDEBUG + if (va < ptoa(physmem)) { + printf("pmap_kremove(%lx, %lx): unmapping physmem\n", va, size); + return; + } +#endif + + simple_lock(&pmap->pm_lock); + + for (pdemask = 1, eva = va + size; va < eva; va += PAGE_SIZE) { + if (pdemask != (va & PDE_MASK)) { + pdemask = va & PDE_MASK; + if (!(pde = pmap_pde_get(pmap_kernel()->pm_pdir, va))) { + va += ~PDE_MASK + 1 - PAGE_SIZE; + continue; + } + } + if (!(pte = pmap_pte_get(pde, va))) { +#ifdef DEBUG + printf("pmap_kremove: unmapping unmapped 0x%lx\n", va); +#endif + continue; + } + + pmap_pte_flush(pmap_kernel(), va, pte); + pmap_pte_set(pde, va, 0); + if (pmap_initialized && (pg = PHYS_TO_VM_PAGE(PTE_PAGE(pte)))) { + + simple_lock(&pg->mdpage.pvh_lock); + pg->mdpage.pvh_attrs |= pmap_pvh_attrs(pte); + /* just in case we have enter/kenter mismatch */ + if ((pve = pmap_pv_remove(pg, pmap_kernel(), va))) + pmap_pv_free(pve); + simple_unlock(&pg->mdpage.pvh_lock); + } + } + + simple_unlock(&pmap->pm_lock); + + DPRINTF(PDB_FOLLOW|PDB_REMOVE, ("pmap_kremove: leaving\n")); +} diff --git a/sys/arch/hppa64/hppa64/process_machdep.c b/sys/arch/hppa64/hppa64/process_machdep.c new file mode 100644 index 00000000000..564af417d85 --- /dev/null +++ b/sys/arch/hppa64/hppa64/process_machdep.c @@ -0,0 +1,116 @@ +/* $OpenBSD: process_machdep.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/user.h> + +int +process_read_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + struct trapframe *tf = p->p_md.md_regs; + + regs->r_regs[0] = tf->tf_sar; + bcopy(&tf->tf_r1, ®s->r_regs[1], 31*8); + regs->r_pc = tf->tf_iioq[0]; + regs->r_npc = tf->tf_iioq[1]; + + return (0); +} + +int +process_read_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + extern paddr_t fpu_curpcb; + extern u_int fpu_enable; + + if (p->p_md.md_regs->tf_cr30 == fpu_curpcb) { + mtctl(fpu_enable, CR_CCR); + fpu_save((vaddr_t)p->p_addr->u_pcb.pcb_fpregs); + mtctl(0, CR_CCR); + } + bcopy(p->p_addr->u_pcb.pcb_fpregs, fpregs, 32*8); + + return (0); +} + +#ifdef PTRACE + +int +process_write_regs(p, regs) + struct proc *p; + struct reg *regs; +{ + struct trapframe *tf = p->p_md.md_regs; + + tf->tf_sar = regs->r_regs[0]; + bcopy(®s->r_regs[1], &tf->tf_r1, 31*8); + tf->tf_iioq[0] = regs->r_pc | 3; + tf->tf_iioq[1] = regs->r_npc | 3; + + return (0); +} + +int +process_write_fpregs(p, fpregs) + struct proc *p; + struct fpreg *fpregs; +{ + extern paddr_t fpu_curpcb; + + if (p->p_md.md_regs->tf_cr30 == fpu_curpcb) { + fpu_exit(); + fpu_curpcb = 0; + } + + bcopy(fpregs, p->p_addr->u_pcb.pcb_fpregs, 32 * 8); + + return (0); +} + +int +process_sstep(p, sstep) + struct proc *p; + int sstep; +{ + if (sstep) + return (EINVAL); + + return (0); +} + +int +process_set_pc(p, addr) + struct proc *p; + caddr_t addr; +{ + p->p_md.md_regs->tf_iioq[1] = 4 + + (p->p_md.md_regs->tf_iioq[0] = (register_t)addr | 3); + + return (0); +} + +#endif /* PTRACE */ diff --git a/sys/arch/hppa64/hppa64/sys_machdep.c b/sys/arch/hppa64/hppa64/sys_machdep.c new file mode 100644 index 00000000000..d905414aa7c --- /dev/null +++ b/sys/arch/hppa64/hppa64/sys_machdep.c @@ -0,0 +1,58 @@ +/* $OpenBSD: sys_machdep.c,v 1.1 2005/04/01 10:40:47 mickey 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. 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/param.h> +#include <sys/systm.h> + +#include <sys/mount.h> +#include <sys/syscallargs.h> + +int +sys_sysarch(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct sys_sysarch_args /* { + syscallarg(int) op; + syscallarg(char *) parms; + } */ *uap = v; + int error = 0; + + switch (SCARG(uap, op)) { + default: + error = EINVAL; + break; + } + return (error); +} diff --git a/sys/arch/hppa64/hppa64/trap.c b/sys/arch/hppa64/hppa64/trap.c new file mode 100644 index 00000000000..e0046725ad1 --- /dev/null +++ b/sys/arch/hppa64/hppa64/trap.c @@ -0,0 +1,723 @@ +/* $OpenBSD: trap.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define TRAPDEBUG + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/syscall.h> +#include <sys/ktrace.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/user.h> + +#include <net/netisr.h> + +#include "systrace.h" +#include <dev/systrace.h> + +#include <uvm/uvm.h> + +#include <machine/autoconf.h> +#include <machine/psl.h> + +#include <machine/db_machdep.h> /* XXX always needed for inst_store() */ +#ifdef DDB +#ifdef TRAPDEBUG +#include <ddb/db_output.h> +#endif +#endif + +const char *trap_type[] = { + "invalid", + "HPMC", + "power failure", + "recovery counter", + "external interrupt", + "LPMC", + "ITLB miss fault", + "instruction protection", + "Illegal instruction", + "break instruction", + "privileged operation", + "privileged register", + "overflow", + "conditional", + "assist exception", + "DTLB miss", + "ITLB non-access miss", + "DTLB non-access miss", + "data protection/rights/alignment", + "data break", + "TLB dirty", + "page reference", + "assist emulation", + "higher-priv transfer", + "lower-priv transfer", + "taken branch", + "data access rights", + "data protection", + "unaligned data ref", +}; +int trap_types = sizeof(trap_type)/sizeof(trap_type[0]); + +int want_resched, astpending; + +#define frame_regmap(tf,r) (((register_t *)(tf))[hppa64_regmap[(r)]]) +u_char hppa64_regmap[32] = { + offsetof(struct trapframe, tf_pad[0]) / 8, /* r0 XXX */ + offsetof(struct trapframe, tf_r1) / 8, + offsetof(struct trapframe, tf_rp) / 8, + offsetof(struct trapframe, tf_r3) / 8, + offsetof(struct trapframe, tf_r4) / 8, + offsetof(struct trapframe, tf_r5) / 8, + offsetof(struct trapframe, tf_r6) / 8, + offsetof(struct trapframe, tf_r7) / 8, + offsetof(struct trapframe, tf_r8) / 8, + offsetof(struct trapframe, tf_r9) / 8, + offsetof(struct trapframe, tf_r10) / 8, + offsetof(struct trapframe, tf_r11) / 8, + offsetof(struct trapframe, tf_r12) / 8, + offsetof(struct trapframe, tf_r13) / 8, + offsetof(struct trapframe, tf_r14) / 8, + offsetof(struct trapframe, tf_r15) / 8, + offsetof(struct trapframe, tf_r16) / 8, + offsetof(struct trapframe, tf_r17) / 8, + offsetof(struct trapframe, tf_r18) / 8, + offsetof(struct trapframe, tf_args[7]) / 8, + offsetof(struct trapframe, tf_args[6]) / 8, + offsetof(struct trapframe, tf_args[5]) / 8, + offsetof(struct trapframe, tf_args[4]) / 8, + offsetof(struct trapframe, tf_args[3]) / 8, + offsetof(struct trapframe, tf_args[2]) / 8, + offsetof(struct trapframe, tf_args[1]) / 8, + offsetof(struct trapframe, tf_args[0]) / 8, + offsetof(struct trapframe, tf_dp) / 8, + offsetof(struct trapframe, tf_ret0) / 8, + offsetof(struct trapframe, tf_ret1) / 8, + offsetof(struct trapframe, tf_sp) / 8, + offsetof(struct trapframe, tf_r31) / 8, +}; + +void +userret(struct proc *p, register_t pc, u_quad_t oticks) +{ + int sig; + + /* take pending signals */ + while ((sig = CURSIG(p)) != 0) + postsig(sig); + + p->p_priority = p->p_usrpri; + if (astpending) { + astpending = 0; + if (p->p_flag & P_OWEUPC) { + p->p_flag &= ~P_OWEUPC; + ADDUPROF(p); + } + } + if (want_resched) { + /* + * We're being preempted. + */ + preempt(NULL); + while ((sig = CURSIG(p)) != 0) + postsig(sig); + } + + /* + * If profiling, charge recent system time to the trapped pc. + */ + if (p->p_flag & P_PROFIL) { + extern int psratio; + + addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio); + } + + p->p_cpu->ci_schedstate.spc_curpriority = p->p_priority; +} + +void +trap(type, frame) + int type; + struct trapframe *frame; +{ + extern int cpl; /* from locore.o */ + struct proc *p = curproc; + vaddr_t va; + struct vm_map *map; + struct vmspace *vm; + register vm_prot_t vftype; + register pa_space_t space; + union sigval sv; + u_int opcode; + int ret, trapnum; + const char *tts; + vm_fault_t fault = VM_FAULT_INVALID; +#ifdef DIAGNOSTIC + long oldcpl; +#endif + + trapnum = type & ~T_USER; + opcode = frame->tf_iir; + if (trapnum <= T_EXCEPTION || trapnum == T_HIGHERPL || + trapnum == T_LOWERPL || trapnum == T_TAKENBR || + trapnum == T_IDEBUG || trapnum == T_PERFMON) { + va = frame->tf_iioq[0]; + space = frame->tf_iisq[0]; + vftype = UVM_PROT_EXEC; + } else { + va = frame->tf_ior; + space = frame->tf_isr; + if (va == frame->tf_iioq[0]) + vftype = UVM_PROT_EXEC; + else if (inst_store(opcode)) + vftype = UVM_PROT_WRITE; + else + vftype = UVM_PROT_READ; + } + + if (frame->tf_flags & TFF_LAST) + p->p_md.md_regs = frame; + + if (trapnum > trap_types) + tts = "reserved"; + else + tts = trap_type[trapnum]; + +#ifdef TRAPDEBUG + if (trapnum != T_INTERRUPT && trapnum != T_IBREAK) + db_printf("trap: %x, %s for %x:%lx at %x:%lx, fl=%x, fp=%p\n", + type, tts, space, va, frame->tf_iisq[0], + frame->tf_iioq[0], frame->tf_flags, frame); + else if (trapnum == T_IBREAK) + db_printf("trap: break instruction %x:%x at %x:%lx, fp=%p\n", + opcode & 0x1f, (opcode >> 13) & 0x1fff, + frame->tf_iisq[0], frame->tf_iioq[0], frame); + + { + extern int etext; + if (frame < (struct trapframe *)&etext) { + printf("trap: bogus frame ptr %p\n", frame); + goto dead_end; + } + } +#endif + if (trapnum != T_INTERRUPT) { + uvmexp.traps++; + /* TODO mtctl(frame->tf_eiem, CR_EIEM); */ + } + + switch (type) { + case T_NONEXIST: + case T_NONEXIST | T_USER: + /* we've got screwed up by the central scrutinizer */ + printf("trap: elvis has just left the building!\n"); + goto dead_end; + + case T_RECOVERY: + case T_RECOVERY | T_USER: + /* XXX will implement later */ + printf("trap: handicapped"); + goto dead_end; + +#ifdef DIAGNOSTIC + case T_EXCEPTION: + panic("FPU/SFU emulation botch"); + + /* these just can't happen ever */ + case T_PRIV_OP: + case T_PRIV_REG: + /* these just can't make it to the trap() ever */ + case T_HPMC: + case T_HPMC | T_USER: +#endif + case T_IBREAK: + case T_DATALIGN: + case T_DBREAK: + dead_end: +#ifdef DDB + if (kdb_trap (type, va, frame)) { + if (type == T_IBREAK) { + /* skip break instruction */ + frame->tf_iioq[0] = frame->tf_iioq[1]; + frame->tf_iioq[1] += 4; + } + return; + } +#else + if (type == T_DATALIGN) + panic ("trap: %s at 0x%x", tts, va); + else + panic ("trap: no debugger for \"%s\" (%d)", tts, type); +#endif + break; + + case T_IBREAK | T_USER: + case T_DBREAK | T_USER: + /* pass to user debugger */ + trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_BRKPT, sv); + break; + + case T_EXCEPTION | T_USER: { + u_int64_t *fpp = (u_int64_t *)frame->tf_cr30; + u_int32_t *pex; + int i, flt; + + pex = (u_int32_t *)&fpp[0]; + for (i = 0, pex++; i < 7 && !*pex; i++, pex++); + flt = 0; + if (i < 7) { + u_int32_t stat = HPPA_FPU_OP(*pex); + if (stat & HPPA_FPU_UNMPL) + flt = FPE_FLTINV; + else if (stat & (HPPA_FPU_V << 1)) + flt = FPE_FLTINV; + else if (stat & (HPPA_FPU_Z << 1)) + flt = FPE_FLTDIV; + else if (stat & (HPPA_FPU_I << 1)) + flt = FPE_FLTRES; + else if (stat & (HPPA_FPU_O << 1)) + flt = FPE_FLTOVF; + else if (stat & (HPPA_FPU_U << 1)) + flt = FPE_FLTUND; + /* still left: under/over-flow w/ inexact */ + + /* cleanup exceptions (XXX deliver all ?) */ + while (i++ < 7) + *pex++ = 0; + } + /* reset the trap flag, as if there was none */ + fpp[0] &= ~(((u_int64_t)HPPA_FPU_T) << 32); + /* flush out, since load is done from phys, only 4 regs */ + fdcache(HPPA_SID_KERNEL, (vaddr_t)fpp, 8 * 4); + + sv.sival_int = va; + trapsignal(p, SIGFPE, type &~ T_USER, flt, sv); + } + break; + + case T_EMULATION: + panic("trap: emulation trap in the kernel"); + break; + + case T_EMULATION | T_USER: + sv.sival_int = va; + trapsignal(p, SIGILL, type &~ T_USER, ILL_COPROC, sv); + break; + + case T_OVERFLOW | T_USER: + sv.sival_int = va; + trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTOVF, sv); + break; + + case T_CONDITION | T_USER: + sv.sival_int = va; + trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTDIV, sv); + break; + + case T_PRIV_OP | T_USER: + sv.sival_int = va; + trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVOPC, sv); + break; + + case T_PRIV_REG | T_USER: + sv.sival_int = va; + trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVREG, sv); + break; + + /* these should never got here */ + case T_HIGHERPL | T_USER: + case T_LOWERPL | T_USER: + sv.sival_int = va; + trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv); + break; + + case T_IPROT | T_USER: + case T_DPROT | T_USER: + sv.sival_int = va; + trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv); + break; + + case T_ITLBMISSNA: + case T_ITLBMISSNA | T_USER: + case T_DTLBMISSNA: + case T_DTLBMISSNA | T_USER: + if (space == HPPA_SID_KERNEL) + map = kernel_map; + else { + vm = p->p_vmspace; + map = &vm->vm_map; + } + + /* dig probei?,[rw] insns */ + if ((opcode & 0xfc001f80) == 0x04001180) { + int pl; + + if (opcode & 0x2000) + pl = (opcode >> 16) & 3; + else + pl = frame_regmap(frame, + (opcode >> 16) & 0x1f) & 3; + + if ((type & T_USER && space == HPPA_SID_KERNEL) || + (type & T_USER && !pl) || + (type & T_USER && va >= VM_MAXUSER_ADDRESS) || + uvm_fault(map, hppa_trunc_page(va), fault, + opcode & 0x40? UVM_PROT_WRITE : UVM_PROT_READ)) { + frame_regmap(frame, opcode & 0x1f) = 0; + frame->tf_ipsw |= PSL_N; + } + } else if (type & T_USER) { + sv.sival_int = va; + trapsignal(p, SIGILL, type & ~T_USER, ILL_ILLTRP, sv); + } else + panic("trap: %s @ 0x%x:0x%x for 0x%x:0x%x irr 0x%08x\n", + tts, frame->tf_iisq[0], frame->tf_iioq[0], + space, va, opcode); + break; + + case T_TLB_DIRTY: + case T_TLB_DIRTY | T_USER: + case T_DATACC: + case T_DATACC | T_USER: + fault = VM_FAULT_PROTECT; + case T_ITLBMISS: + case T_ITLBMISS | T_USER: + case T_DTLBMISS: + case T_DTLBMISS | T_USER: + /* + * it could be a kernel map for exec_map faults + */ + if (space == HPPA_SID_KERNEL) + map = kernel_map; + else { + vm = p->p_vmspace; + map = &vm->vm_map; + } + + /* + * user faults out of user addr space are always a fail, + * this happens on va >= VM_MAXUSER_ADDRESS, where + * space id will be zero and therefore cause + * a misbehave lower in the code. + * + * also check that faulted space id matches the curproc. + */ + if ((type & T_USER && va >= VM_MAXUSER_ADDRESS) || + (type & T_USER && map->pmap->pm_space != space)) { + sv.sival_int = va; + trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv); + break; + } + +printf("here\n"); + ret = uvm_fault(map, hppa_trunc_page(va), fault, vftype); + + /* + * If this was a stack access we keep track of the maximum + * accessed stack size. Also, if uvm_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 (space != HPPA_SID_KERNEL && + va < (vaddr_t)vm->vm_minsaddr) { + if (ret == 0) + uvm_grow(p, va); + else if (ret == EACCES) + ret = EFAULT; + } + + if (ret != 0) { + if (type & T_USER) { + sv.sival_int = va; + trapsignal(p, SIGSEGV, vftype, + ret == EACCES? SEGV_ACCERR : SEGV_MAPERR, + sv); + } else { + if (p && p->p_addr->u_pcb.pcb_onfault) { + frame->tf_iioq[1] = 4 + + (frame->tf_iioq[0] = + p->p_addr->u_pcb.pcb_onfault); +#ifdef DDB + frame->tf_iir = 0; +#endif + } else { + panic("trap: " + "uvm_fault(%p, %lx, %d, %d): %d", + map, va, fault, vftype, ret); + } + } + } + break; + + case T_DATALIGN | T_USER: + sv.sival_int = va; + trapsignal(p, SIGBUS, vftype, BUS_ADRALN, sv); + break; + + case T_INTERRUPT: + case T_INTERRUPT | T_USER: +/* cpu_intr(frame); */ +printf("eirr 0x%08x\n", mfctl(CR_EIRR)); + break; + + case T_CONDITION: + panic("trap: divide by zero in the kernel"); + break; + + case T_ILLEGAL: + case T_ILLEGAL | T_USER: + /* see if it's a SPOP1,,0 */ + if ((opcode & 0xfffffe00) == 0x10000200) { + frame_regmap(frame, opcode & 0x1f) = 0; + frame->tf_ipsw |= PSL_N; + break; + } + if (type & T_USER) { + sv.sival_int = va; + trapsignal(p, SIGILL, type &~ T_USER, ILL_ILLOPC, sv); + break; + } + /* FALLTHROUGH */ + + case T_LOWERPL: + case T_DPROT: + case T_IPROT: + case T_OVERFLOW: + case T_HIGHERPL: + case T_TAKENBR: + case T_POWERFAIL: + case T_LPMC: + case T_PAGEREF: + case T_DATAPID: + case T_DATAPID | T_USER: + if (0 /* T-chip */) { + break; + } + /* FALLTHROUGH to unimplemented */ + default: +#if 1 +if (kdb_trap (type, va, frame)) + return; +#endif + panic("trap: unimplemented \'%s\' (%d)", tts, trapnum); + } + +#ifdef DIAGNOSTIC + if (cpl != oldcpl) + printf("WARNING: SPL (%d) NOT LOWERED ON " + "TRAP (%d) EXIT\n", cpl, trapnum); +#endif + + if (trapnum != T_INTERRUPT) + splx(cpl); /* process softints */ + + /* + * in case we were interrupted from the syscall gate page + * treat this as we were not realy running user code no more + * for weird things start to happen on return to the userland + * and also see a note in locore.S:TLABEL(all) + */ + if ((type & T_USER) && + (frame->tf_iioq[0] & ~PAGE_MASK) != SYSCALLGATE) + userret(p, frame->tf_iioq[0], 0); +} + +void +child_return(arg) + void *arg; +{ + struct proc *p = (struct proc *)arg; + struct trapframe *tf = p->p_md.md_regs; + + /* + * Set up return value registers as libc:fork() expects + */ + tf->tf_ret0 = 0; + tf->tf_ret1 = 1; /* ischild */ + tf->tf_r1 = 0; /* errno */ + + userret(p, tf->tf_iioq[0], 0); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p, SYS_fork, 0, 0); +#endif +} + + +/* + * call actual syscall routine + */ +void +syscall(struct trapframe *frame) +{ + extern int cpl; /* from locore.o */ + register struct proc *p = curproc; + register const struct sysent *callp; + int retq, nsys, code, argsize, argoff, oerror, error; + register_t args[8], rval[2]; +#ifdef DIAGNOSTIC + long oldcpl; +#endif + + /* TODO syscall */ + + uvmexp.syscalls++; + + if (!USERMODE(frame->tf_iioq[0])) + panic("syscall"); + + p->p_md.md_regs = frame; + nsys = p->p_emul->e_nsysent; + callp = p->p_emul->e_sysent; + + argoff = 4; retq = 0; + switch (code = frame->tf_r1) { + case SYS_syscall: + code = frame->tf_args[0]; + args[0] = frame->tf_args[1]; + args[1] = frame->tf_args[2]; + args[2] = frame->tf_args[3]; + argoff = 3; + break; + case SYS___syscall: + if (callp != sysent) + break; + /* + * this works, because quads get magically swapped + * due to the args being laid backwards on the stack + * and then copied in words + */ + code = frame->tf_args[0]; + args[0] = frame->tf_args[2]; + args[1] = frame->tf_args[3]; + argoff = 2; + retq = 1; + break; + default: + args[0] = frame->tf_args[0]; + args[1] = frame->tf_args[1]; + args[2] = frame->tf_args[2]; + args[3] = frame->tf_args[3]; + break; + } + + if (code < 0 || code >= nsys) + callp += p->p_emul->e_nosys; /* bad syscall # */ + else + callp += code; + + oerror = error = 0; + if ((argsize = callp->sy_argsize)) { + int i; + +/* TODO syscallargs */ + + /* + * coming from syscall() or __syscall we must be + * having one of those w/ a 64 bit arguments, + * which needs a word swap due to the order + * of the arguments on the stack. + * this assumes that none of 'em are called + * by their normal syscall number, maybe a regress + * test should be used, to watch the behaviour. + */ + if (!error && argoff < 4) { + int t; + + i = 0; + switch (code) { + case SYS_lseek: retq = 0; + case SYS_truncate: + case SYS_ftruncate: i = 2; break; + case SYS_preadv: + case SYS_pwritev: + case SYS_pread: + case SYS_pwrite: i = 4; break; + case SYS_mmap: i = 6; break; + } + + if (i) { + t = args[i]; + args[i] = args[i + 1]; + args[i + 1] = t; + } + } + } + +#ifdef SYSCALL_DEBUG + scdebug_call(p, code, args); +#endif +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSCALL)) + ktrsyscall(p, code, callp->sy_argsize, args); +#endif + if (error) + goto bad; + + rval[0] = 0; + rval[1] = frame->tf_ret1; +#if NSYSTRACE > 0 + if (ISSET(p->p_flag, P_SYSTRACE)) + oerror = error = systrace_redirect(code, p, args, rval); + else +#endif + oerror = error = (*callp->sy_call)(p, args, rval); + p = curproc; + frame = p->p_md.md_regs; + switch (error) { + case 0: + frame->tf_ret0 = rval[0]; + frame->tf_ret1 = rval[!retq]; + frame->tf_r1 = 0; + break; + case ERESTART: + frame->tf_iioq[0] -= 12; + frame->tf_iioq[1] -= 12; + case EJUSTRETURN: + break; + default: + bad: + if (p->p_emul->e_errno) + error = p->p_emul->e_errno[error]; + frame->tf_r1 = error; + frame->tf_ret0 = error; + frame->tf_ret1 = 0; + break; + } +#ifdef SYSCALL_DEBUG + scdebug_ret(p, code, oerror, rval); +#endif + userret(p, frame->tf_iioq[1], 0); +#ifdef KTRACE + if (KTRPOINT(p, KTR_SYSRET)) + ktrsysret(p, code, oerror, rval[0]); +#endif +#ifdef DIAGNOSTIC + if (cpl != oldcpl) { + printf("WARNING: SPL (0x%x) NOT LOWERED ON " + "syscall(0x%x, 0x%x, 0x%x, 0x%x...) EXIT, PID %d\n", + cpl, code, args[0], args[1], args[2], p->p_pid); + cpl = oldcpl; + } +#endif + splx(cpl); /* process softints */ +} diff --git a/sys/arch/hppa64/hppa64/vm_machdep.c b/sys/arch/hppa64/hppa64/vm_machdep.c new file mode 100644 index 00000000000..53700d03818 --- /dev/null +++ b/sys/arch/hppa64/hppa64/vm_machdep.c @@ -0,0 +1,307 @@ +/* $OpenBSD: vm_machdep.c,v 1.1 2005/04/01 10:40:47 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/malloc.h> +#include <sys/buf.h> +#include <sys/vnode.h> +#include <sys/user.h> +#include <sys/ptrace.h> +#include <sys/exec.h> +#include <sys/core.h> + +#include <machine/psl.h> +#include <machine/pmap.h> +#include <machine/pcb.h> + +#include <uvm/uvm.h> + + +/* + * Dump the machine specific header information at the start of a core dump. + */ +int +cpu_coredump(p, vp, cred, core) + struct proc *p; + struct vnode *vp; + struct ucred *cred; + struct core *core; +{ + struct md_coredump md_core; + struct coreseg cseg; + off_t off; + int error; + + CORE_SETMAGIC(*core, COREMAGIC, MID_HPPA20, 0); + core->c_hdrsize = ALIGN(sizeof(*core)); + core->c_seghdrsize = ALIGN(sizeof(cseg)); + core->c_cpusize = sizeof(md_core); + + process_read_regs(p, &md_core.md_reg); + process_read_fpregs(p, &md_core.md_fpreg); + + CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_HPPA20, CORE_CPU); + cseg.c_addr = 0; + cseg.c_size = core->c_cpusize; + +#define write(vp, addr, n) \ + vn_rdwr(UIO_WRITE, (vp), (caddr_t)(addr), (n), off, \ + UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p) + + off = core->c_hdrsize; + if ((error = write(vp, &cseg, core->c_seghdrsize))) + return error; + off += core->c_seghdrsize; + if ((error = write(vp, &md_core, sizeof md_core))) + return error; + +#undef write + core->c_nseg++; + + return error; +} + +/* + * Move pages from one kernel virtual address to another. + * Both addresses are assumed to reside in the Sysmap. + */ +void +pagemove(from, to, size) + register caddr_t from, to; + size_t size; +{ + paddr_t pa; + + while (size > 0) { + if (pmap_extract(pmap_kernel(), (vaddr_t)from, &pa) == FALSE) + panic("pagemove"); + pmap_kremove((vaddr_t)from, PAGE_SIZE); + pmap_kenter_pa((vaddr_t)to, pa, UVM_PROT_RW); + from += PAGE_SIZE; + to += PAGE_SIZE; + size -= PAGE_SIZE; + } + pmap_update(pmap_kernel()); +} + +void +cpu_swapin(p) + struct proc *p; +{ + struct trapframe *tf = p->p_md.md_regs; + paddr_t pa; + + /* + * Stash the physical for the pcb of U for later perusal + */ + if (!pmap_extract(pmap_kernel(), (vaddr_t)p->p_addr, &pa)) + panic("pmap_extract(%p) failed", p->p_addr); + + tf->tf_cr30 = pa; +} + +void +cpu_swapout(p) + struct proc *p; +{ + extern paddr_t fpu_curpcb; /* from locore.S */ + extern u_int fpu_enable; + struct trapframe *tf = p->p_md.md_regs; + + if (tf->tf_cr30 == fpu_curpcb) { + mtctl(fpu_enable, CR_CCR); + fpu_save(fpu_curpcb); + fpu_curpcb = 0; + mtctl(0, CR_CCR); + } +} + +void +cpu_fork(p1, p2, stack, stacksize, func, arg) + struct proc *p1, *p2; + void *stack; + size_t stacksize; + void (*func)(void *); + void *arg; +{ + extern paddr_t fpu_curpcb; /* from locore.S */ + extern u_int fpu_enable; + struct pcb *pcbp; + struct trapframe *tf; + register_t sp, osp; + +#ifdef DIAGNOSTIC + if (round_page(sizeof(struct user) + sizeof(*tf)) > PAGE_SIZE) + panic("USPACE too small for user"); +#endif + if (p1->p_md.md_regs->tf_cr30 == fpu_curpcb) { + mtctl(fpu_enable, CR_CCR); + fpu_save(fpu_curpcb); + mtctl(0, CR_CCR); + } + + pcbp = &p2->p_addr->u_pcb; + bcopy(&p1->p_addr->u_pcb, pcbp, sizeof(*pcbp)); + /* space is cached for the copy{in,out}'s pleasure */ + pcbp->pcb_space = p2->p_vmspace->vm_map.pmap->pm_space; + pcbp->pcb_uva = (vaddr_t)p2->p_addr; + /* reset any of the pending FPU exceptions from parent */ + pcbp->pcb_fpregs[0] = HPPA_FPU_FORK(pcbp->pcb_fpregs[0]); + pcbp->pcb_fpregs[1] = 0; + pcbp->pcb_fpregs[2] = 0; + pcbp->pcb_fpregs[3] = 0; + fdcache(HPPA_SID_KERNEL, (vaddr_t)&pcbp->pcb_fpregs[0], 8 * 4); + + sp = (register_t)p2->p_addr + PAGE_SIZE; + p2->p_md.md_regs = tf = (struct trapframe *)sp; + sp += sizeof(struct trapframe); + bcopy(p1->p_md.md_regs, tf, sizeof(*tf)); + + /* + * cpu_swapin() is supposed to fill out all the PAs + * we gonna need in locore + */ + cpu_swapin(p2); + + tf->tf_sr0 = tf->tf_sr1 = tf->tf_sr2 = tf->tf_sr3 = + tf->tf_sr4 = tf->tf_sr5 = tf->tf_sr6 = + tf->tf_iisq[0] = tf->tf_iisq[1] = + p2->p_vmspace->vm_map.pmap->pm_space; + tf->tf_pidr1 = tf->tf_pidr2 = pmap_sid2pid(tf->tf_sr0); + + /* + * theoretically these could be inherited from the father, + * but just in case. + */ + tf->tf_sr7 = HPPA_SID_KERNEL; + tf->tf_eiem = mfctl(CR_EIEM); + tf->tf_ipsw = PSL_C | PSL_Q | PSL_P | PSL_D | PSL_I /* | PSL_L */; + + /* + * If specified, give the child a different stack. + */ + if (stack != NULL) + tf->tf_sp = (register_t)stack; + + /* + * Build stack frames for the cpu_switch & co. + */ + osp = sp + HPPA_FRAME_SIZE; + *(register_t*)(osp - HPPA_FRAME_SIZE) = 0; + *(register_t*)(osp + HPPA_FRAME_RP) = (register_t)&switch_trampoline; + *(register_t*)(osp) = (osp - HPPA_FRAME_SIZE); + + sp = osp + HPPA_FRAME_SIZE + 20*8; /* frame + calee-save registers */ + *(register_t*)(sp - HPPA_FRAME_SIZE + 0) = (register_t)arg; + *(register_t*)(sp - HPPA_FRAME_SIZE + 8) = KERNMODE(func); + *(register_t*)(sp - HPPA_FRAME_SIZE + 16) = 0; /* cpl */ + pcbp->pcb_ksp = sp; + fdcache(HPPA_SID_KERNEL, (vaddr_t)p2->p_addr, sp - (vaddr_t)p2->p_addr); +} + +void +cpu_exit(p) + struct proc *p; +{ + extern paddr_t fpu_curpcb; /* from locore.S */ + struct trapframe *tf = p->p_md.md_regs; + + if (fpu_curpcb == tf->tf_cr30) { + fpu_exit(); + fpu_curpcb = 0; + } + + exit2(p); + cpu_switch(p); +} + +void +cpu_wait(p) + struct proc *p; +{ +} + +/* + * Map an IO request into kernel virtual address space. + */ +void +vmapbuf(bp, len) + struct buf *bp; + vsize_t len; +{ + struct pmap *pm = vm_map_pmap(&bp->b_proc->p_vmspace->vm_map); + vaddr_t kva, uva; + vsize_t size, off; + +#ifdef DIAGNOSTIC + if ((bp->b_flags & B_PHYS) == 0) + panic("vmapbuf"); +#endif + bp->b_saveaddr = bp->b_data; + uva = trunc_page((vaddr_t)bp->b_data); + off = (vaddr_t)bp->b_data - uva; + size = round_page(off + len); + + /* + * We do it on our own here to be able to specify an offset to uvm_map + * so that we can get all benefits of PMAP_PREFER. + * - art@ + */ + kva = uvm_km_valloc_prefer_wait(kernel_map, size, uva); + fdcache(pm->pm_space, uva, size); + bp->b_data = (caddr_t)(kva + off); + while (size > 0) { + paddr_t pa; + + if (pmap_extract(pm, uva, &pa) == FALSE) + panic("vmapbuf: null page frame"); + else + pmap_kenter_pa(kva, pa, UVM_PROT_RW); + uva += PAGE_SIZE; + kva += PAGE_SIZE; + size -= PAGE_SIZE; + } + pmap_update(pmap_kernel()); +} + +/* + * Unmap IO request from the kernel virtual address space. + */ +void +vunmapbuf(bp, len) + struct buf *bp; + vsize_t len; +{ + vaddr_t addr, off; + +#ifdef DIAGNOSTIC + if ((bp->b_flags & B_PHYS) == 0) + panic("vunmapbuf"); +#endif + addr = trunc_page((vaddr_t)bp->b_data); + off = (vaddr_t)bp->b_data - addr; + len = round_page(off + len); + uvm_km_free_wakeup(kernel_map, addr, len); + bp->b_data = bp->b_saveaddr; + bp->b_saveaddr = NULL; +} diff --git a/sys/arch/hppa64/hppa64/wscons_machdep.c b/sys/arch/hppa64/hppa64/wscons_machdep.c new file mode 100644 index 00000000000..a491c5fbd04 --- /dev/null +++ b/sys/arch/hppa64/hppa64/wscons_machdep.c @@ -0,0 +1,81 @@ +/* $OpenBSD: wscons_machdep.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/conf.h> + +#include <dev/cons.h> + +#include "wsdisplay.h" +#if NWSDISPLAY > 0 +#include <dev/wscons/wsdisplayvar.h> +#endif + +#include "wskbd.h" +#if NWSKBD > 0 +#include <dev/wscons/wskbdvar.h> +#endif + +cons_decl(ws); + +void +wscnprobe(struct consdev *cp) +{ + /* + * Due to various device probe restrictions, the wscons console + * can never be enabled early during boot. + * It will be enabled as soon as enough wscons components get + * attached. + * So do nothing there, the switch will occur in + * wsdisplay_emul_attach() later. + */ +} + +void +wscninit(struct consdev *cp) +{ +} + +void +wscnputc(dev_t dev, int i) +{ +#if NWSDISPLAY > 0 + wsdisplay_cnputc(dev, i); +#endif +} + +int +wscngetc(dev_t dev) +{ +#if NWSKBD > 0 + return (wskbd_cngetc(dev)); +#else + return (0); +#endif +} + +void +wscnpollc(dev_t dev, int on) +{ +#if NWSKBD > 0 + wskbd_cnpollc(dev, on); +#endif +} diff --git a/sys/arch/hppa64/include/ansi.h b/sys/arch/hppa64/include/ansi.h new file mode 100644 index 00000000000..7e0df957749 --- /dev/null +++ b/sys/arch/hppa64/include/ansi.h @@ -0,0 +1,79 @@ +/* $OpenBSD: ansi.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE_ANSI_H_ +#define _MACHINE_ANSI_H_ + +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _BSD_SIZE_T_ + * typedef _BSD_SIZE_T_ size_t; + * #undef _BSD_SIZE_T_ + * #endif + */ +#define _BSD_CLOCK_T_ int /* clock() */ +#define _BSD_PTRDIFF_T_ long int /* ptr1 - ptr2 */ +#define _BSD_SIZE_T_ long unsigned int /* sizeof() */ +#define _BSD_SSIZE_T_ long int /* byte count or error */ +#define _BSD_TIME_T_ int /* time() */ +#define _BSD_VA_LIST_ __builtin_va_list +#define _BSD_CLOCKID_T_ int +#define _BSD_TIMER_T_ int + +/* + * Runes (wchar_t) is declared to be an ``int'' instead of the more natural + * ``unsigned long'' or ``long''. Two things are happening here. It is not + * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, + * it looks like 10646 will be a 31 bit standard. This means that if your + * ints cannot hold 32 bits, you will be in trouble. The reason an int was + * chosen over a long is that the is*() and to*() routines take ints (says + * ANSI C), but they use _RUNE_T_ instead of int. By changing it here, you + * lose a bit of ANSI conformance, but your programs will still work. + * + * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type. When wchar_t + * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains + * defined for ctype.h. + */ +#define _BSD_WCHAR_T_ int /* wchar_t */ +#define _BSD_WINT_T_ int /* wint_t */ +#define _BSD_RUNE_T_ int /* rune_t */ + +/* + * We describe off_t here so its declaration can be visible to + * stdio without pulling in all of <sys/type.h>, thus appeasing ANSI. + */ +#define _BSD_OFF_T_ long long /* file offset */ + +#endif /* _MACHINE_ANSI_H_ */ diff --git a/sys/arch/hppa64/include/asm.h b/sys/arch/hppa64/include/asm.h new file mode 100644 index 00000000000..ed1ca9acafe --- /dev/null +++ b/sys/arch/hppa64/include/asm.h @@ -0,0 +1,70 @@ +/* $OpenBSD: asm.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1990,1991,1994 The University of Utah and + * the Computer Systems Laboratory (CSL). All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: asm.h 1.8 94/12/14$ + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +/* + * hppa assembler definitions + */ + +arg7 .reg %r19 +arg6 .reg %r20 +arg5 .reg %r21 +arg4 .reg %r22 +ap .reg %r29 + +#ifdef __STDC__ +#define __CONCAT(a,b) a ## b +#else +#define __CONCAT(a,b) a/**/b +#endif + +#ifdef PROF +#define _PROF_PROLOGUE \ + stw %rp, HPPA_FRAME_CRP(%sr0,%sp) !\ + ldil L%_mcount,%r1 !\ + ble R%_mcount(%sr0,%r1) !\ + ldo HPPA_FRAME_SIZE(%sp),%sp !\ + ldw PPA_FRAME_CRP(%sr0,%sp),%rp +#else +#define _PROF_PROLOGUE +#endif + +#define LEAF_ENTRY(x) ! .text ! .align 4 !\ + .export x, entry ! .label x ! .proc !\ + .callinfo frame=0,no_calls,save_rp !\ + .entry ! _PROF_PROLOGUE + +#define ENTRY(x,n) ! .text ! .align 4 !\ + .export x, entry ! .label x ! .proc !\ + .callinfo frame=n,calls, save_rp, save_sp !\ + .entry ! _PROF_PROLOGUE + +#define ALTENTRY(x) ! .export x, entry ! .label x +#define EXIT(x) ! .exit ! .procend ! .size x, .-x + +#define BSS(n,s) ! .data ! .label n ! .comm s + +#endif /* _MACHINE_ASM_H_ */ diff --git a/sys/arch/hppa64/include/autoconf.h b/sys/arch/hppa64/include/autoconf.h new file mode 100644 index 00000000000..2d40eb5e236 --- /dev/null +++ b/sys/arch/hppa64/include/autoconf.h @@ -0,0 +1,53 @@ +/* $OpenBSD: autoconf.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <machine/bus.h> +#include <machine/pdc.h> + +struct confargs { + const char *ca_name; /* device name/description */ + struct iodc_data ca_type; /* iodc-specific type descrition */ + bus_space_tag_t ca_iot; /* io tag */ + bus_dma_tag_t ca_dmatag; /* DMA tag */ + hppa_hpa_t ca_hpa; /* module HPA */ + u_int ca_hpasz; /* module HPA size (if avail) */ +}; + +/* this is used for hppa_knownmodules table + * describing known to this port modules, + * system boards, cpus, fpus and busses + */ +struct hppa_mod_info { + int mi_type; + int mi_sv; + const char *mi_name; +}; + +extern void (*cold_hook)(int); +#define HPPA_COLD_COLD 0 +#define HPPA_COLD_HOT 1 +#define HPPA_COLD_OFF 2 + +struct device; + +const char *hppa_mod_info(int, int); +void pdc_patscan(struct device *, struct confargs *, int); +int mbprint(void *, const char *); + +void dumpconf(void); diff --git a/sys/arch/hppa64/include/bus.h b/sys/arch/hppa64/include/bus.h new file mode 100644 index 00000000000..bfd7606dbaf --- /dev/null +++ b/sys/arch/hppa64/include/bus.h @@ -0,0 +1,410 @@ +/* $OpenBSD: bus.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +/* addresses in bus space */ +typedef u_long bus_addr_t; +typedef u_long bus_size_t; + +/* access methods for bus space */ +typedef u_long bus_space_handle_t; + +struct hppa64_bus_space_tag { + void *hbt_cookie; + + int (*hbt_map)(void *v, bus_addr_t addr, bus_size_t size, + int flags, bus_space_handle_t *bshp); + void (*hbt_unmap)(void *v, bus_space_handle_t bsh, bus_size_t size); + int (*hbt_subregion)(void *v, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, + bus_space_handle_t *nbshp); + int (*hbt_alloc)(void *v, 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); + void (*hbt_free)(void *, bus_space_handle_t, bus_size_t); + void (*hbt_barrier)(void *v, bus_space_handle_t h, + bus_size_t o, bus_size_t l, int op); + u_int8_t (*hbt_r1)(void *, bus_space_handle_t, bus_size_t); + u_int16_t (*hbt_r2)(void *, bus_space_handle_t, bus_size_t); + u_int32_t (*hbt_r4)(void *, bus_space_handle_t, bus_size_t); + u_int64_t (*hbt_r8)(void *, bus_space_handle_t, bus_size_t); + + void (*hbt_w1)(void *, bus_space_handle_t, bus_size_t, u_int8_t); + void (*hbt_w2)(void *, bus_space_handle_t, bus_size_t, u_int16_t); + void (*hbt_w4)(void *, bus_space_handle_t, bus_size_t, u_int32_t); + void (*hbt_w8)(void *, bus_space_handle_t, bus_size_t, u_int64_t); + + void (*hbt_rm_1)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, bus_size_t c); + void (*hbt_rm_2)(void *v, bus_space_handle_t h, + bus_size_t o, u_int16_t *a, bus_size_t c); + void (*hbt_rm_4)(void *v, bus_space_handle_t h, + bus_size_t o, u_int32_t *a, bus_size_t c); + void (*hbt_rm_8)(void *v, bus_space_handle_t h, + bus_size_t o, u_int64_t *a, bus_size_t c); + + void (*hbt_wm_1)(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c); + void (*hbt_wm_2)(void *v, bus_space_handle_t h, bus_size_t o, + const u_int16_t *a, bus_size_t c); + void (*hbt_wm_4)(void *v, bus_space_handle_t h, bus_size_t o, + const u_int32_t *a, bus_size_t c); + void (*hbt_wm_8)(void *v, bus_space_handle_t h, bus_size_t o, + const u_int64_t *a, bus_size_t c); + + void (*hbt_sm_1)(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t vv, bus_size_t c); + void (*hbt_sm_2)(void *v, bus_space_handle_t h, bus_size_t o, + u_int16_t vv, bus_size_t c); + void (*hbt_sm_4)(void *v, bus_space_handle_t h, bus_size_t o, + u_int32_t vv, bus_size_t c); + void (*hbt_sm_8)(void *v, bus_space_handle_t h, bus_size_t o, + u_int64_t vv, bus_size_t c); + + void (*hbt_rrm_2)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, bus_size_t c); + void (*hbt_rrm_4)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, bus_size_t c); + void (*hbt_rrm_8)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, bus_size_t c); + + void (*hbt_wrm_2)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int8_t *a, bus_size_t c); + void (*hbt_wrm_4)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int8_t *a, bus_size_t c); + void (*hbt_wrm_8)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int8_t *a, bus_size_t c); + + void (*hbt_rr_1)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, bus_size_t c); + void (*hbt_rr_2)(void *v, bus_space_handle_t h, + bus_size_t o, u_int16_t *a, bus_size_t c); + void (*hbt_rr_4)(void *v, bus_space_handle_t h, + bus_size_t o, u_int32_t *a, bus_size_t c); + void (*hbt_rr_8)(void *v, bus_space_handle_t h, + bus_size_t o, u_int64_t *a, bus_size_t c); + + void (*hbt_wr_1)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int8_t *a, bus_size_t c); + void (*hbt_wr_2)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int16_t *a, bus_size_t c); + void (*hbt_wr_4)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int32_t *a, bus_size_t c); + void (*hbt_wr_8)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int64_t *a, bus_size_t c); + + void (*hbt_rrr_2)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, bus_size_t c); + void (*hbt_rrr_4)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, bus_size_t c); + void (*hbt_rrr_8)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, bus_size_t c); + + void (*hbt_wrr_2)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int8_t *a, bus_size_t c); + void (*hbt_wrr_4)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int8_t *a, bus_size_t c); + void (*hbt_wrr_8)(void *v, bus_space_handle_t h, + bus_size_t o, const u_int8_t *a, bus_size_t c); + + void (*hbt_sr_1)(void *v, bus_space_handle_t h, + bus_size_t o, u_int8_t vv, bus_size_t c); + void (*hbt_sr_2)(void *v, bus_space_handle_t h, + bus_size_t o, u_int16_t vv, bus_size_t c); + void (*hbt_sr_4)(void *v, bus_space_handle_t h, + bus_size_t o, u_int32_t vv, bus_size_t c); + void (*hbt_sr_8)(void *v, bus_space_handle_t h, + bus_size_t o, u_int64_t vv, bus_size_t c); + + void (*hbt_cp_1)(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c); + void (*hbt_cp_2)(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c); + void (*hbt_cp_4)(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c); + void (*hbt_cp_8)(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c); +}; +typedef struct hppa64_bus_space_tag *bus_space_tag_t; + +/* flags for bus space map functions */ +#define BUS_SPACE_MAP_CACHEABLE 0x0001 +#define BUS_SPACE_MAP_LINEAR 0x0002 +#define BUS_SPACE_MAP_READONLY 0x0004 +#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 + +/* bus access routines */ + +#define bus_space_map(t,a,c,ca,hp) \ + (((t)->hbt_map)((t)->hbt_cookie,(a),(c),(ca),(hp))) +#define bus_space_unmap(t,h,c) \ + (((t)->hbt_unmap)((t)->hbt_cookie,(h),(c))) +#define bus_space_subregion(t,h,o,c,hp) \ + (((t)->hbt_subregion)((t)->hbt_cookie,(h),(o),(c),(hp))) +#define bus_space_alloc(t,b,e,c,al,bn,ca,ap,hp) \ + (((t)->hbt_alloc)((t)->hbt_cookie,(b),(e),(c),(al),(bn),(ca),(ap),(hp))) +#define bus_space_free(t,h,c) \ + (((t)->hbt_free)((t)->hbt_cookie,(h),(c))) + +#define BUS_SPACE_BARRIER_READ 0 +#define BUS_SPACE_BARRIER_WRITE 1 + +#define bus_space_barrier(t,h,o,l,op) \ + ((t)->hbt_barrier((t)->hbt_cookie, (h), (o), (l), (op))) +#define bus_space_vaddr(t,h) ((vaddr_t)(h)) + +#define bus_space_read_1(t,h,o) (((t)->hbt_r1)((t)->hbt_cookie,(h),(o))) +#define bus_space_read_2(t,h,o) (((t)->hbt_r2)((t)->hbt_cookie,(h),(o))) +#define bus_space_read_4(t,h,o) (((t)->hbt_r4)((t)->hbt_cookie,(h),(o))) +#define bus_space_read_8(t,h,o) (((t)->hbt_r8)((t)->hbt_cookie,(h),(o))) + +#define bus_space_write_1(t,h,o,v) (((t)->hbt_w1)((t)->hbt_cookie,(h),(o),(v))) +#define bus_space_write_2(t,h,o,v) (((t)->hbt_w2)((t)->hbt_cookie,(h),(o),(v))) +#define bus_space_write_4(t,h,o,v) (((t)->hbt_w4)((t)->hbt_cookie,(h),(o),(v))) +#define bus_space_write_8(t,h,o,v) (((t)->hbt_w8)((t)->hbt_cookie,(h),(o),(v))) + +#define bus_space_read_multi_1(t,h,o,a,c) \ + (((t)->hbt_rm_1)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_multi_2(t,h,o,a,c) \ + (((t)->hbt_rm_2)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_multi_4(t,h,o,a,c) \ + (((t)->hbt_rm_4)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_multi_8(t,h,o,a,c) \ + (((t)->hbt_rm_8)((t)->hbt_cookie, (h), (o), (a), (c))) + +#define bus_space_write_multi_1(t,h,o,a,c) \ + (((t)->hbt_wm_1)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_multi_2(t,h,o,a,c) \ + (((t)->hbt_wm_2)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_multi_4(t,h,o,a,c) \ + (((t)->hbt_wm_4)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_multi_8(t,h,o,a,c) \ + (((t)->hbt_wm_8)((t)->hbt_cookie, (h), (o), (a), (c))) + +#define bus_space_set_multi_1(t,h,o,v,c) \ + (((t)->hbt_sm_1)((t)->hbt_cookie, (h), (o), (v), (c))) +#define bus_space_set_multi_2(t,h,o,v,c) \ + (((t)->hbt_sm_2)((t)->hbt_cookie, (h), (o), (v), (c))) +#define bus_space_set_multi_4(t,h,o,v,c) \ + (((t)->hbt_sm_4)((t)->hbt_cookie, (h), (o), (v), (c))) +#define bus_space_set_multi_8(t,h,o,v,c) \ + (((t)->hbt_sm_8)((t)->hbt_cookie, (h), (o), (v), (c))) + +#define bus_space_read_raw_multi_2(t, h, o, a, c) \ + (((t)->hbt_rrm_2)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_raw_multi_4(t, h, o, a, c) \ + (((t)->hbt_rrm_4)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_raw_multi_8(t, h, o, a, c) \ + (((t)->hbt_rrm_8)((t)->hbt_cookie, (h), (o), (a), (c))) + +#define bus_space_write_raw_multi_2(t, h, o, a, c) \ + (((t)->hbt_wrm_2)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_raw_multi_4(t, h, o, a, c) \ + (((t)->hbt_wrm_4)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_raw_multi_8(t, h, o, a, c) \ + (((t)->hbt_wrm_8)((t)->hbt_cookie, (h), (o), (a), (c))) + +#define bus_space_read_region_1(t, h, o, a, c) \ + (((t)->hbt_rr_1)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_region_2(t, h, o, a, c) \ + (((t)->hbt_rr_2)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_region_4(t, h, o, a, c) \ + (((t)->hbt_rr_4)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_region_8(t, h, o, a, c) \ + (((t)->hbt_rr_8)((t)->hbt_cookie, (h), (o), (a), (c))) + +#define bus_space_write_region_1(t, h, o, a, c) \ + (((t)->hbt_wr_1)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_region_2(t, h, o, a, c) \ + (((t)->hbt_wr_2)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_region_4(t, h, o, a, c) \ + (((t)->hbt_wr_4)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_region_8(t, h, o, a, c) \ + (((t)->hbt_wr_8)((t)->hbt_cookie, (h), (o), (a), (c))) + +#define bus_space_read_raw_region_2(t, h, o, a, c) \ + (((t)->hbt_rrr_2)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_raw_region_4(t, h, o, a, c) \ + (((t)->hbt_rrr_4)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_read_raw_region_8(t, h, o, a, c) \ + (((t)->hbt_rrr_8)((t)->hbt_cookie, (h), (o), (a), (c))) + +#define bus_space_write_raw_region_2(t, h, o, a, c) \ + (((t)->hbt_wrr_2)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_raw_region_4(t, h, o, a, c) \ + (((t)->hbt_wrr_4)((t)->hbt_cookie, (h), (o), (a), (c))) +#define bus_space_write_raw_region_8(t, h, o, a, c) \ + (((t)->hbt_wrr_8)((t)->hbt_cookie, (h), (o), (a), (c))) + +#define bus_space_set_region_1(t, h, o, v, c) \ + (((t)->hbt_sr_1)((t)->hbt_cookie, (h), (o), (v), (c))) +#define bus_space_set_region_2(t, h, o, v, c) \ + (((t)->hbt_sr_2)((t)->hbt_cookie, (h), (o), (v), (c))) +#define bus_space_set_region_4(t, h, o, v, c) \ + (((t)->hbt_sr_4)((t)->hbt_cookie, (h), (o), (v), (c))) +#define bus_space_set_region_8(t, h, o, v, c) \ + (((t)->hbt_sr_8)((t)->hbt_cookie, (h), (o), (v), (c))) + +#define bus_space_copy_1(t, h1, o1, h2, o2, c) \ + (((t)->hbt_cp_1)((t)->hbt_cookie, (h1), (o1), (h2), (o2), (c))) +#define bus_space_copy_2(t, h1, o1, h2, o2, c) \ + (((t)->hbt_cp_2)((t)->hbt_cookie, (h1), (o1), (h2), (o2), (c))) +#define bus_space_copy_4(t, h1, o1, h2, o2, c) \ + (((t)->hbt_cp_4)((t)->hbt_cookie, (h1), (o1), (h2), (o2), (c))) +#define bus_space_copy_8(t, h1, o1, h2, o2, c) \ + (((t)->hbt_cp_8)((t)->hbt_cookie, (h1), (o1), (h2), (o2), (c))) +#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ +#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ +#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ +#define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ +#define BUS_DMAMEM_NOSYNC 0x010 +#define BUS_DMA_BUS1 0x020 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x040 +#define BUS_DMA_BUS3 0x080 +#define BUS_DMA_BUS4 0x100 +#define BUS_DMA_STREAMING 0x200 /* hint: sequential, unidirectional */ +#define BUS_DMA_READ 0x400 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x800 /* mapping is memory -> device only */ + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +/* Operations performed by bus_dmamap_sync(). */ +#define BUS_DMASYNC_POSTREAD 0x01 +#define BUS_DMASYNC_POSTWRITE 0x02 +#define BUS_DMASYNC_PREREAD 0x04 +#define BUS_DMASYNC_PREWRITE 0x08 + +typedef const struct hppa64_bus_dma_tag *bus_dma_tag_t; +typedef struct hppa64_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct hppa64_bus_dma_segment { + vaddr_t _ds_va; /* needed for syncing */ + + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ +}; +typedef struct hppa64_bus_dma_segment bus_dma_segment_t; + +/* + * bus_dma_tag_t + * + * A machine-dependent opaque type describing the implementation of + * DMA for a given bus. + */ + +struct hppa64_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(void *, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(void *, bus_dmamap_t); + int (*_dmamap_load)(void *, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(void *, bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(void *, bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(void *, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(void *, bus_dmamap_t); + void (*_dmamap_sync)(void *, bus_dmamap_t, bus_addr_t, + bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(void *, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(void *, bus_dma_segment_t *, int); + int (*_dmamem_map)(void *, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(void *, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(void *, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t)->_cookie, (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t)->_cookie, (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t)->_cookie, (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t)->_cookie, (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t)->_cookie, (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t)->_cookie, (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t)->_cookie, (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t)->_cookie, (p), (a), (l), (o)) : (void)0) + +#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ + (*(t)->_dmamem_alloc)((t)->_cookie, (s), (a), (b), (sg), (n), (r), (f)) +#define bus_dmamem_free(t, sg, n) \ + (*(t)->_dmamem_free)((t)->_cookie, (sg), (n)) +#define bus_dmamem_map(t, sg, n, s, k, f) \ + (*(t)->_dmamem_map)((t)->_cookie, (sg), (n), (s), (k), (f)) +#define bus_dmamem_unmap(t, k, s) \ + (*(t)->_dmamem_unmap)((t)->_cookie, (k), (s)) +#define bus_dmamem_mmap(t, sg, n, o, p, f) \ + (*(t)->_dmamem_mmap)((t)->_cookie, (sg), (n), (o), (p), (f)) + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct hppa64_bus_dmamap { + /* + * PRIVATE MEMBERS: not for use by machine-independent code. + */ + bus_size_t _dm_size; /* largest DMA transfer mappable */ + int _dm_segcnt; /* number of segs this map can map */ + bus_size_t _dm_maxsegsz; /* largest possible segment */ + bus_size_t _dm_boundary; /* don't cross this */ + int _dm_flags; /* misc. flags */ + + void *_dm_cookie; /* cookie for bus-specific functions */ + + /* + * PUBLIC MEMBERS: these are used by machine-independent code. + */ + bus_size_t dm_mapsize; /* size of the mapping */ + int dm_nsegs; /* # valid segments in mapping */ + bus_dma_segment_t dm_segs[1]; /* segments; variable length */ +}; + +#endif /* _MACHINE_BUS_H_ */ diff --git a/sys/arch/hppa64/include/cdefs.h b/sys/arch/hppa64/include/cdefs.h new file mode 100644 index 00000000000..8e7e74a501b --- /dev/null +++ b/sys/arch/hppa64/include/cdefs.h @@ -0,0 +1,39 @@ +/* $OpenBSD: cdefs.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ +/* $NetBSD: cdefs.h,v 1.5 1996/10/12 18:08:12 cgd Exp $ */ + +/* + * Copyright (c) 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +#define __weak_alias(alias,sym) \ + __asm__(".export " __STRING(alias) ", entry\n\t.weak " __STRING(alias) "\n\t" __STRING(alias) " = " __STRING(sym)) +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." __STRING(sym) "\n\t.ascii \"" msg "\"\n\t.text") + +#endif /* !_MACHINE_CDEFS_H_ */ diff --git a/sys/arch/hppa64/include/conf.h b/sys/arch/hppa64/include/conf.h new file mode 100644 index 00000000000..cbe367c02f5 --- /dev/null +++ b/sys/arch/hppa64/include/conf.h @@ -0,0 +1,38 @@ +/* $OpenBSD: conf.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_CONF_H_ +#define _MACHINE_CONF_H_ + +#include <sys/conf.h> +struct tty; +struct termios; + +cdev_decl(pdc); +int pdcparam(struct tty *, struct termios *); +void pdcstart(struct tty *); + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); + +cdev_decl(fd); +bdev_decl(fd); + +#endif /* _MACHINE_CONF_H_ */ diff --git a/sys/arch/hppa64/include/cpu.h b/sys/arch/hppa64/include/cpu.h new file mode 100644 index 00000000000..41aec18205d --- /dev/null +++ b/sys/arch/hppa64/include/cpu.h @@ -0,0 +1,303 @@ +/* $OpenBSD: cpu.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 1988-1994, The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: cpu.h 1.19 94/12/16$ + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +#include <machine/trap.h> +#include <machine/frame.h> + +/* + * COPR/SFUs + */ +#define HPPA_FPUS 0xc0 +#define HPPA_FPUVER(w) (((w) & 0x003ff800) >> 11) +#define HPPA_FPU_OP(w) ((w) >> 26) +#define HPPA_FPU_UNMPL 0x01 /* exception reg, the rest is << 1 */ +#define HPPA_FPU_ILL 0x80 /* software-only */ +#define HPPA_FPU_I 0x01 +#define HPPA_FPU_U 0x02 +#define HPPA_FPU_O 0x04 +#define HPPA_FPU_Z 0x08 +#define HPPA_FPU_V 0x10 +#define HPPA_FPU_D 0x20 +#define HPPA_FPU_T 0x40 +#define HPPA_FPU_XMASK 0x7f +#define HPPA_FPU_T_POS 25 /* 32bit reg! */ +#define HPPA_FPU_RM 0x00000600 +#define HPPA_FPU_CQ 0x00fff800 +#define HPPA_FPU_C 0x04000000 +#define HPPA_FPU_FLSH 27 +#define HPPA_FPU_INIT (0) +#define HPPA_FPU_FORK(s) ((s) & ~((u_int64_t)(HPPA_FPU_XMASK)<<32)) +#define HPPA_PMSFUS 0x20 /* ??? */ + +/* + * Interrupts stuff + */ +#define IPL_NONE 0 +#define IPL_SOFTCLOCK 1 +#define IPL_SOFTNET 2 +#define IPL_BIO 3 +#define IPL_NET 4 +#define IPL_SOFTTTY 5 +#define IPL_TTY 6 +#define IPL_VM 7 +#define IPL_AUDIO 8 +#define IPL_CLOCK 9 +#define IPL_SCHED 9 +#define IPL_STATCLOCK 10 +#define IPL_HIGH 11 + +#define NIPL 12 + +#define IST_NONE 0 +#define IST_PULSE 1 +#define IST_EDGE 2 +#define IST_LEVEL 3 + +#define spllowersoftclock() spllower(IPL_SOFTCLOCK) +#define splsoftclock() splraise(IPL_SOFTCLOCK) +#define splsoftnet() splraise(IPL_SOFTNET) +#define splbio() splraise(IPL_BIO) +#define splnet() splraise(IPL_NET) +#define splsofttty() splraise(IPL_SOFTTTY) +#define spltty() splraise(IPL_TTY) +#define splvm() splraise(IPL_VM) +#define splimp() splvm() +#define splaudio() splraise(IPL_AUDIO) +#define splclock() splraise(IPL_CLOCK) +#define splsched() splraise(IPL_SCHED) +#define splstatclock() splraise(IPL_STATCLOCK) +#define splhigh() splraise(IPL_HIGH) +#define spl0() spllower(IPL_NONE) +#define splx(c) spllower(c) + +#define setsoftast() (astpending = 1) +#define setsoftclock() /* TODO */ +#define setsoftnet() /* TODO */ +#define setsofttty() /* TODO */ + +#ifndef _LOCORE +#include <sys/time.h> +#include <sys/sched.h> + +struct cpu_info { + struct proc *ci_curproc; + struct pcb *ci_cpcb; + struct cpu_info *ci_next; + + struct proc *ci_fpproc; + int ci_number; + struct schedstate_percpu ci_schedstate; /* scheduler state */ + + /* DEBUG/DIAGNOSTIC stuff */ + u_long ci_spin_locks; /* # of spin locks held */ + u_long ci_simple_locks;/* # of simple locks held */ + + /* Spinning up the CPU */ + void (*ci_spinup)(void); /* spinup routine */ + void *ci_initstack; +}; + +struct cpu_info *curcpu(void); +#define cpu_number() (curcpu()->ci_number) +#define CPU_IS_PRIMARY(ci) ((ci)->ci_number == 0) +#define CPU_INFO_ITERATOR int +#define CPU_INFO_FOREACH(cii,ci) \ + cii = 0, ci = curcpu(); ci != NULL; ci = ci->ci_next +#define CPU_INFO_UNIT(ci) ((ci)->ci_number) + +#ifdef DIAGNOSTIC +void splassert_fail(int, int, const char *); +extern int splassert_ctl; +void splassert_check(int, const char *); +#define splassert(__wantipl) do { \ + if (__predict_false(splassert_ctl > 0)) { \ + splassert_check(__wantipl, __func__); \ + } \ +} while (0) +#else +#define splassert(__wantipl) do { /* nada */ } while (0) +#endif /* DIAGNOSTIC */ + +/* types */ +enum hppa_cpu_type { + hpcxu, hpcxu2, hpcxw +}; +extern enum hppa_cpu_type cpu_type; +extern const char *cpu_typename; +extern int cpu_hvers; +#endif + +/* + * Exported definitions unique to hp700/PA-RISC cpu support. + */ + +#define HPPA_PGALIAS 0x0000000000100000UL +#define HPPA_PGAMASK 0xfffffffffff00000UL +#define HPPA_PGAOFF 0x00000000000fffffUL + +#define HPPA_PHYSMAP 0x000001ffffffffffUL +#define HPPA_IOBEGIN 0xfffffff000000000UL +#define HPPA_IOLEN 0x0000001000000000UL +#define HPPA_PHYSEND 0xffffffffffffffffUL +#define HPPA_IOADDR 0xfffffff100000000UL +#define HPPA_IOBCAST 0xfffffffffffc0000UL +#define HPPA_LBCAST 0xfffffffffffc0000UL +#define HPPA_GBCAST 0xfffffffffffe0000UL +#define HPPA_FPADDR 0xfffffffffff80000UL +#define HPPA_FLEX_MASK 0xfffffffffffc0000UL +#define HPPA_DMA_ENABLE 0x00000001 +#define HPPA_SPA_ENABLE 0x00000020 +#define HPPA_NMODSPBUS 64 + +#define clockframe trapframe +#define CLKF_PC(framep) ((framep)->tf_iioq[0]) +#define CLKF_INTR(framep) ((framep)->tf_flags & TFF_INTR) +#define CLKF_USERMODE(framep) ((framep)->tf_flags & T_USER) +#define CLKF_SYSCALL(framep) ((framep)->tf_flags & TFF_SYS) + +#define signotify(p) (setsoftast()) +#define need_resched(ci) (want_resched = 1, setsoftast()) +#define need_proftick(p) ((p)->p_flag |= P_OWEUPC, setsoftast()) + +#ifndef _LOCORE +#ifdef _KERNEL + +extern int want_resched, astpending; + +#define DELAY(x) delay(x) + +int splraise(int cpl); +int spllower(int cpl); + +void delay(u_int us); +void hppa_init(paddr_t start); +void trap(int type, struct trapframe *frame); +int spcopy(pa_space_t ssp, const void *src, + pa_space_t dsp, void *dst, size_t size); +int spstrcpy(pa_space_t ssp, const void *src, + pa_space_t dsp, void *dst, size_t size, size_t *rsize); +int copy_on_fault(void); +void switch_trampoline(void); +int cpu_dumpsize(void); +int cpu_dump(void); + +#ifdef USELEDS +#define PALED_NETSND 0x01 +#define PALED_NETRCV 0x02 +#define PALED_DISK 0x04 +#define PALED_HEARTBEAT 0x08 +#define PALED_LOADMASK 0xf0 + +#define PALED_DATA 0x01 +#define PALED_STROBE 0x02 + +extern volatile u_int8_t *machine_ledaddr; +extern int machine_ledword, machine_leds; + +static __inline void +ledctl(int on, int off, int toggle) +{ + if (machine_ledaddr) { + int r; + + if (on) + machine_leds |= on; + if (off) + machine_leds &= ~off; + if (toggle) + machine_leds ^= toggle; + + r = ~machine_leds; /* it seems they should be reversed */ + + if (machine_ledword) + *machine_ledaddr = r; + else { + register int b; + for (b = 0x80; b; b >>= 1) { + *machine_ledaddr = (r & b)? PALED_DATA : 0; + DELAY(1); + *machine_ledaddr = ((r & b)? PALED_DATA : 0) | + PALED_STROBE; + } + } + } +} +#endif + +void fpu_save(vaddr_t va); +void fpu_exit(void); +void ficache(pa_space_t sp, vaddr_t va, vsize_t size); +void fdcache(pa_space_t sp, vaddr_t va, vsize_t size); +void pdcache(pa_space_t sp, vaddr_t va, vsize_t size); +void ficacheall(void); +void fdcacheall(void); +void pitlb(pa_space_t sp, vaddr_t va); +void pdtlb(pa_space_t sp, vaddr_t va); +void ptlball(void); +void mtctl(register_t val, int reg); +register_t mfctl(int reg); +hppa_hpa_t cpu_gethpa(int n); +void sync_caches(void); +#endif + +/* + * Boot arguments stuff + */ + +#define BOOTARG_LEN (NBPG) +#define BOOTARG_OFF (0x10000) + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_CONSDEV 1 /* dev_t: console terminal device */ +#define CPU_MAXID 1 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "console_device", CTLTYPE_STRUCT }, \ +} +#endif + +#endif /* _MACHINE_CPU_H_ */ diff --git a/sys/arch/hppa64/include/db_machdep.h b/sys/arch/hppa64/include/db_machdep.h new file mode 100644 index 00000000000..9c90cab7611 --- /dev/null +++ b/sys/arch/hppa64/include/db_machdep.h @@ -0,0 +1,107 @@ +/* $OpenBSD: db_machdep.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_DB_MACHDEP_H_ +#define _MACHINE_DB_MACHDEP_H_ + +#include <uvm/uvm_extern.h> + +#define DB_ELF_SYMBOLS +#define DB_ELFSIZE 64 + +/* types the generic ddb module needs */ +typedef vaddr_t db_addr_t; +typedef long db_expr_t; + +typedef struct trapframe db_regs_t; +extern db_regs_t ddb_regs; +#define DDB_REGS (&ddb_regs) + +#define PC_REGS(regs) ((db_addr_t)(regs)->tf_iioq[0]) +#define SET_PC_REGS(r,pc) ((r)->tf_iioq[0] = (pc), (r)->tf_iioq[1] = (pc) + 4) + +/* Breakpoint related definitions */ +#define BKPT_INST 0x00010000 /* break 0,8 */ +#define BKPT_SIZE sizeof(int) +#define BKPT_SET(inst) BKPT_INST + +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_IBREAK) +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_DBREAK) + +#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_iioq[0] -= sizeof(int)) + +#define DB_VALID_BREAKPOINT(addr) db_valid_breakpoint(addr) + +/* TODO 64bit insns */ + +static __inline int inst_call(u_int ins) { + return (ins & 0xfc00e000) == 0xe8000000 || + (ins & 0xfc00e000) == 0xe8004000 || + (ins & 0xfc000000) == 0xe4000000; +} +static __inline int inst_branch(u_int ins) { + return (ins & 0xf0000000) == 0xe0000000 || + (ins & 0xf0000000) == 0xc0000000 || + (ins & 0xf0000000) == 0xa0000000 || + (ins & 0xf0000000) == 0x80000000; +} +static __inline int inst_load(u_int ins) { + return (ins & 0xf0000000) == 0x40000000 || + (ins & 0xf4000200) == 0x24000000 || + (ins & 0xfc000200) == 0x0c000000 || + (ins & 0xfc001fc0) != 0x0c0011c0; +} +static __inline int inst_store(u_int ins) { + return (ins & 0xf0000000) == 0x60000000 || /* st */ + (ins & 0xf4000200) == 0x24000200 || /* fst/cst */ + (ins & 0xfc000200) == 0x0c000200 || /* stby */ + (ins & 0xfc0003c0) == 0x0c0001c0; /* ldcw */ +} +static __inline int inst_return(u_int ins) { + return (ins & 0xfc00e000) == 0xe800c000 || + (ins & 0xfc000000) == 0xe0000000; +} +static __inline int inst_trap_return(u_int ins) { + return (ins & 0xfc001fc0) == 0x00000ca0; +} + +#if 0 +#define db_clear_single_step(r) ((r)->tf_flags &= ~(PSL_Z)) +#define db_set_single_step(r) ((r)->tf_flags |= (PSL_Z)) +#else +#define SOFTWARE_SSTEP 1 +#define SOFTWARE_SSTEP_EMUL 1 + +static __inline db_addr_t +next_instr_address(db_addr_t addr, int b) { + return (addr + 4); +} + +#define branch_taken(ins,pc,f,regs) branch_taken1(ins, pc, regs) +static __inline db_addr_t +branch_taken1(int ins, db_addr_t pc, db_regs_t *regs) { + return (pc); +} + +#endif + +int db_valid_breakpoint(db_addr_t); +int kdb_trap(int, int, db_regs_t *); + +#endif /* _MACHINE_DB_MACHDEP_H_ */ diff --git a/sys/arch/hppa64/include/disklabel.h b/sys/arch/hppa64/include/disklabel.h new file mode 100644 index 00000000000..423637e6644 --- /dev/null +++ b/sys/arch/hppa64/include/disklabel.h @@ -0,0 +1,375 @@ +/* $OpenBSD: disklabel.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ +/* $NetBSD: disklabel.h,v 1.1 1995/02/13 23:07:34 cgd 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_ + +enum disklabel_tag { DLT_ALPHA, DLT_I386, DLT_AMIGA, DLT_HPPA }; + +/* + * What disklabels are we probing for, and in which order? + */ +#ifndef LABELPROBES +#define LABELPROBES DLT_ALPHA, DLT_I386, DLT_AMIGA, DLT_HPPA +#endif + +#define ALPHA_LABELSECTOR 0 /* sector containing label */ +#define ALPHA_LABELOFFSET 64 /* offset of label in sector */ +#define I386_LABELSECTOR 1 /* sector containing label */ +#define I386_LABELOFFSET 0 /* offset of label in sector */ +#define AMIGA_LABELSECTOR 0 /* sector containing label */ +#define AMIGA_LABELOFFSET 64 /* offset of label in sector */ +#define HPPA_LABELSECTOR 1 /* sector containing label */ +#define HPPA_LABELOFFSET 0 /* offset of label in sector */ + +#define LABELSECTOR HPPA_LABELSECTOR +#define LABELOFFSET HPPA_LABELOFFSET + +#define MAXPARTITIONS 16 /* number of partitions */ +#define RAW_PART 2 /* raw partition: xx?c */ + +/* DOS partition table -- located in boot block */ +#define DOSBBSECTOR 0 /* DOS boot block relative sector # */ +#define DOSPARTOFF 446 +#define DOSACTIVE 0x80 +#define NDOSPART 4 +#define DOSMBR_SIGNATURE 0xaa55 +#define DOSMBR_SIGNATURE_OFF 0x1fe + +struct dos_partition { + u_int8_t dp_flag; /* bootstrap flags */ + u_int8_t dp_shd; /* starting head */ + u_int8_t dp_ssect; /* starting sector */ + u_int8_t dp_scyl; /* starting cylinder */ + u_int8_t dp_typ; /* partition type (see below) */ + u_int8_t dp_ehd; /* end head */ + u_int8_t dp_esect; /* end sector */ + u_int8_t dp_ecyl; /* end cylinder */ + u_int32_t dp_start; /* absolute starting sector number */ + u_int32_t dp_size; /* partition size in sectors */ +}; + +/* Known DOS partition types. */ +#define DOSPTYP_UNUSED 0x00 /* Unused partition */ +#define DOSPTYP_FAT12 0x01 /* 12-bit FAT */ +#define DOSPTYP_FAT16S 0x04 /* 16-bit FAT, less than 32M */ +#define DOSPTYP_EXTEND 0x05 /* Extended; contains sub-partitions */ +#define DOSPTYP_FAT16B 0x06 /* 16-bit FAT, more than 32M */ +#define DOSPTYP_FAT32 0x0b /* 32-bit FAT */ +#define DOSPTYP_FAT32L 0x0c /* 32-bit FAT, LBA-mapped */ +#define DOSPTYP_FAT16L 0x0e /* 16-bit FAT, LBA-mapped */ +#define DOSPTYP_ONTRACK 0x54 +#define DOSPTYP_LINUX 0x83 /* That other thing */ +#define DOSPTYP_FREEBSD 0xa5 /* FreeBSD partition type */ +#define DOSPTYP_OPENBSD 0xa6 /* OpenBSD partition type */ +#define DOSPTYP_NETBSD 0xa9 /* NetBSD partition type */ + +/* Isolate the relevant bits to get sector and cylinder. */ +#define DPSECT(s) ((s) & 0x3f) +#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2)) + +/* + * describes ados Rigid Disk Blocks + * which are used to partition a drive + */ +#define RDBNULL ((u_int32_t)0xffffffff) + +/* + * you will find rdblock somewhere in [0, RDBMAXBLOCKS) + */ +#define RDB_MAXBLOCKS 16 + +struct rdblock { + u_int32_t id; /* 'RDSK' */ + u_int32_t nsumlong; /* number of longs in check sum */ + u_int32_t chksum; /* simple additive with wrap checksum */ + u_int32_t hostid; /* scsi target of host */ + u_int32_t nbytes; /* size of disk blocks */ + u_int32_t flags; + u_int32_t badbhead; /* linked list of badblocks */ + u_int32_t partbhead; /* linked list of partblocks */ + u_int32_t fsbhead; /* " " of fsblocks */ + u_int32_t driveinit; + u_int32_t resv1[6]; /* RDBNULL */ + u_int32_t ncylinders; /* number of cylinders on drive */ + u_int32_t nsectors; /* number of sectors per track */ + u_int32_t nheads; /* number of tracks per cylinder */ + u_int32_t interleave; + u_int32_t park; /* only used with st506 i.e. not */ + u_int32_t resv2[3]; + u_int32_t wprecomp; /* start cyl for write precomp */ + u_int32_t reducedwrite; /* start cyl for reduced write current */ + u_int32_t steprate; /* driver step rate in ?s */ + u_int32_t resv3[5]; + u_int32_t rdblowb; /* lowblock of range for rdb's */ + u_int32_t rdbhighb; /* high block of range for rdb's */ + u_int32_t lowcyl; /* low cylinder of partition area */ + u_int32_t highcyl; /* upper cylinder of partition area */ + u_int32_t secpercyl; /* number of sectors per cylinder */ + u_int32_t parkseconds; /* zero if no park needed */ + u_int32_t resv4[2]; + char diskvendor[8]; /* inquiry stuff */ + char diskproduct[16]; /* inquiry stuff */ + char diskrevision[4]; /* inquiry stuff */ + char contvendor[8]; /* inquiry stuff */ + char contproduct[16]; /* inquiry stuff */ + char contrevision[4]; /* inquiry stuff */ +#if never_use_secsize + u_int32_t resv5[0]; +#endif +}; + + +#define RDBF_LAST 0x1 /* last drive available */ +#define RDBF_LASTLUN 0x2 /* last LUN available */ +#define RDBF_LASTUNIT 0x4 /* last target available */ +#define RDBF_NORESELECT 0x8 /* do not use reselect */ +#define RDBF_DISKID 0x10 /* disk id is valid ?? */ +#define RDBF_CTRLID 0x20 /* ctrl id is valid ?? */ +#define RDBF_SYNC 0x40 /* drive supports SCSI synchronous mode */ + +struct ados_environ { + u_int32_t tabsize; /* 0: environ table size */ + u_int32_t sizeblock; /* 1: n long words in a block */ + u_int32_t secorg; /* 2: not used must be zero */ + u_int32_t numheads; /* 3: number of surfaces */ + u_int32_t secperblk; /* 4: must be 1 */ + u_int32_t secpertrk; /* 5: blocks per track */ + u_int32_t resvblocks; /* 6: reserved blocks at start */ + u_int32_t prefac; /* 7: must be 0 */ + u_int32_t interleave; /* 8: normally 1 */ + u_int32_t lowcyl; /* 9: low cylinder of partition */ + u_int32_t highcyl; /* 10: upper cylinder of partition */ + u_int32_t numbufs; /* 11: ados: number of buffers */ + u_int32_t membuftype; /* 12: ados: type of bufmem */ + u_int32_t maxtrans; /* 13: maxtrans the ctrlr supports */ + u_int32_t mask; /* 14: mask for valid address */ + u_int32_t bootpri; /* 15: boot priority for autoboot */ + u_int32_t dostype; /* 16: filesystem type */ + u_int32_t baud; /* 17: serial handler baud rate */ + u_int32_t control; /* 18: control word for fs */ + u_int32_t bootblocks; /* 19: blocks containing boot code */ + u_int32_t fsize; /* 20: file system block size */ + u_int32_t frag; /* 21: allowable frags per block */ + u_int32_t cpg; /* 22: cylinders per group */ +}; + +struct partblock { + u_int32_t id; /* 'PART' */ + u_int32_t nsumlong; /* number of longs in check sum */ + u_int32_t chksum; /* simple additive with wrap checksum */ + u_int32_t hostid; /* scsi target of host */ + u_int32_t next; /* next in chain */ + u_int32_t flags; /* see below */ + u_int32_t resv1[3]; + u_char partname[32]; /* (BCPL) part name (may not be unique) */ + u_int32_t resv2[15]; + struct ados_environ e; +#if never_use_secsize + u_int32_t extra[9]; /* 8 for extra added to environ */ +#endif +}; + +#define PBF_BOOTABLE 0x1 /* partition is bootable */ +#define PBF_NOMOUNT 0x2 /* partition should be mounted */ + +struct badblock { + u_int32_t id; /* 'BADB' */ + u_int32_t nsumlong; /* number of longs in check sum */ + u_int32_t chksum; /* simple additive with wrap checksum */ + u_int32_t hostid; /* scsi target of host */ + u_int32_t next; /* next in chain */ + u_int32_t resv; + struct badblockent { + u_int32_t badblock; + u_int32_t goodblock; + } badtab[0]; /* 61 for secsize == 512 */ +}; + +struct fsblock { + u_int32_t id; /* 'FSHD' */ + u_int32_t nsumlong; /* number of longs in check sum */ + u_int32_t chksum; /* simple additive with wrap checksum */ + u_int32_t hostid; /* scsi target of host */ + u_int32_t next; /* next in chain */ + u_int32_t flags; + u_int32_t resv1[2]; + u_int32_t dostype; /* this is a file system for this type */ + u_int32_t version; /* version of this fs */ + u_int32_t patchflags; /* describes which functions to replace */ + u_int32_t type; /* zero */ + u_int32_t task; /* zero */ + u_int32_t lock; /* zero */ + u_int32_t handler; /* zero */ + u_int32_t stacksize; /* to use when loading handler */ + u_int32_t priority; /* to run the fs at. */ + u_int32_t startup; /* zero */ + u_int32_t lsegblocks; /* linked list of lsegblocks of fs code */ + u_int32_t globalvec; /* bcpl vector not used mostly */ +#if never_use_secsize + u_int32_t resv2[44]; +#endif +}; + +struct lsegblock { + u_int32_t id; /* 'LSEG' */ + u_int32_t nsumlong; /* number of longs in check sum */ + u_int32_t chksum; /* simple additive with wrap checksum */ + u_int32_t hostid; /* scsi target of host */ + u_int32_t next; /* next in chain */ + u_int32_t loaddata[0]; /* load segment data, 123 for secsize == 512 */ +}; + +#define RDBLOCK_ID 0x5244534b /* 'RDSK' */ +#define PARTBLOCK_ID 0x50415254 /* 'PART' */ +#define BADBLOCK_ID 0x42414442 /* 'BADB' */ +#define FSBLOCK_ID 0x46534844 /* 'FSHD' */ +#define LSEGBLOCK_ID 0x4c534547 /* 'LSEG' */ + +/* + * volume header for "LIF" format volumes + */ +struct lifvol { + short vol_id; + char vol_label[6]; + u_int vol_addr; + short vol_oct; + short vol_dummy; + u_int vol_dirsize; + short vol_version; + short vol_zero; + u_int vol_number; + u_int vol_lastvol; + u_int vol_length; + char vol_toc[6]; + char vol_dummy1[198]; + + u_int ipl_addr; + u_int ipl_size; + u_int ipl_entry; + + u_int vol_dummy2; +}; + +struct lifdir { + char dir_name[10]; + u_short dir_type; + u_int dir_addr; + u_int dir_length; + char dir_toc[6]; + short dir_flag; + u_int dir_implement; +}; + +struct lif_load { + int address; + int count; +}; + +#define HPUX_MAGIC 0x8b7f6a3c +#define HPUX_MAXPART 16 +struct hpux_label { + int32_t hl_magic1; + u_int32_t hl_magic; + int32_t hl_version; + struct { + int32_t hlp_blah[2]; + int32_t hlp_start; + int32_t hlp_length; + } hl_parts[HPUX_MAXPART]; + u_int8_t hl_flags[HPUX_MAXPART]; +#define HPUX_PART_ROOT 0x10 +#define HPUX_PART_SWAP 0x14 +#define HPUX_PART_BOOT 0x32 + int32_t hl_blah[3*16]; + u_int16_t hl_boot; + u_int16_t hl_reserved; + int32_t hl_magic2; +}; + +#define LIF_VOL_ID -32768 +#define LIF_VOL_OCT 4096 +#define LIF_DIR_SWAP 0x5243 +#define LIF_DIR_HPLBL 0xa271 +#define LIF_DIR_FS 0xcd38 +#define LIF_DIR_IOMAP 0xcd60 +#define LIF_DIR_HPUX 0xcd80 +#define LIF_DIR_ISL 0xce00 +#define LIF_DIR_PAD 0xcffe +#define LIF_DIR_AUTO 0xcfff +#define LIF_DIR_EST 0xd001 +#define LIF_DIR_TYPE 0xe942 + +#define LIF_DIR_FLAG 0x8001 /* dont ask me! */ +#define LIF_SECTSIZE 256 + +#define LIF_NUMDIR 16 + +#define LIF_VOLSTART 0 +#define LIF_VOLSIZE sizeof(struct lifvol) +#define LIF_DIRSTART 2048 +#define LIF_DIRSIZE (LIF_NUMDIR * sizeof(struct lifdir)) +#define LIF_FILESTART 8192 + +#define btolifs(b) (((b) + (LIF_SECTSIZE - 1)) / LIF_SECTSIZE) +#define lifstob(s) ((s) * LIF_SECTSIZE) +#define lifstodb(s) ((s) * LIF_SECTSIZE / DEV_BSIZE) + +#include <sys/dkbad.h> +struct cpu_disklabel { + enum disklabel_tag labeltag; + int labelsector; + union { + struct { + } _alpha; + struct { + struct dos_partition dosparts[NDOSPART]; + struct dkbad bad; + } _i386; + struct { + u_int32_t rdblock; /* RDBNULL -> inval. */ + u_int32_t pblist[MAXPARTITIONS];/* pblock number */ + int pbindex[MAXPARTITIONS]; /* index of pblock */ + int valid; /* valid? */ + } _amiga; + struct { + struct lifvol lifvol; + struct lifdir lifdir[LIF_NUMDIR]; + struct hpux_label hplabel; + } _hppa; + } u; +}; + +#define DKBAD(x) ((x)->u._i386.bad) + +#endif /* _MACHINE_DISKLABEL_H_ */ diff --git a/sys/arch/hppa64/include/endian.h b/sys/arch/hppa64/include/endian.h new file mode 100644 index 00000000000..3138bcc84d8 --- /dev/null +++ b/sys/arch/hppa64/include/endian.h @@ -0,0 +1,28 @@ +/* $OpenBSD: endian.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _HPPA64_ENDIAN_H_ +#define _HPPA64_ENDIAN_H_ + +#define BYTE_ORDER BIG_ENDIAN +#include <sys/endian.h> + +#define __STRICT_ALIGNMENT + +#endif /* !_HPPA64_ENDIAN_H_ */ diff --git a/sys/arch/hppa64/include/exec.h b/sys/arch/hppa64/include/exec.h new file mode 100644 index 00000000000..3b2ccc70267 --- /dev/null +++ b/sys/arch/hppa64/include/exec.h @@ -0,0 +1,113 @@ +/* $OpenBSD: exec.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1994, The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: exec.h 1.3 94/12/16$ + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define cpu_exec_aout_makecmds(p, epp) ENOEXEC + +/* Size of a page in an object file. */ +#define __LDPGSZ 4096 + +#define ARCH_ELFSIZE 64 + +#define ELF_TARG_CLASS ELFCLASS64 +#define ELF_TARG_DATA ELFDATA2MSB +#define ELF_TARG_MACH EM_PARISC + +#define NATIVE_EXEC_ELF +#define _NLIST_DO_ELF +#define _KERN_DO_ELF + +/* + * the following MD ELF values defenitions are from the: + * "Processor-Specific ELF Supplement for PA-RISC. + * Including HP and HP-UX Extensions. Version 1.43. October 6, 1997" + * http://devrsrc1.external.hp.com/STK/partner/elf-pa.pdf + * + */ + +/* parisc-specific elf flags */ +#define EF_PARISC_TRAPNIL 0x00010000 /* trap on NULL derefs */ +#define EF_PARISC_EXT 0x00020000 /* program uses arch exts */ +#define EF_PARISC_LSB 0x00040000 /* program expects LSB mode */ +#define EF_PARISC_WIDE 0x00080000 /* program expects wide mode */ +#define EF_PARISC_NO_KABP 0x00100000 /* don't allow kernel assisted + branch prediction */ +#define EF_PARISC_LAZYSWAP 0x00200000 /* allow lazy swap allocation + for dynamically allocated + program segments */ +#define EF_PARISC_ARCH 0x0000ffff /* architecture version */ +#define EFA_PARISC_1_0 0x020B +#define EFA_PARISC_1_1 0x0210 +#define EFA_PARISC_2_0 0x0214 + +/* legend: 0 - pa7000, 1 - pa7100, 2 - pa7200, 3 - pa7100LC, 4 - pa8000 */ +#define PARISC_AE_QWSI 0x00000001 /* 0 : enable quadword stores */ +#define PARISC_AE_FPLSU 0x00000002 /* 1: fp load/store to I/O space */ +#define PARISC_AE_RSQRT 0x00000004 /* 0 : reciprocal sqrt */ +#define PARISC_AE_FDCG 0x00000008 /* 0,1: fdc includes graph flushes */ +#define PARISC_AE_HPAR 0x00000010 /* 3,4: half-word add/sub/av */ +#define PARISC_AE_BSW 0x00000020 /* 3,4: half-word shift-add */ +#define PARISC_AE_HPSA 0x00000040 /* 3 : byte-swapping stores */ +#define PARISC_AE_DPR0 0x00000080 /* 2,4: data prefetch via ld to r0 */ + +#define SHN_PARISC_ANSI_COMMON 0xff00 +#define SHN_PARISC_HUGE_COMMON 0xff01 + +/* sh_type */ +#define SHT_PARISC_EXT 0x70000000 /* contains product-specific + extension bits */ +#define SHT_PARISC_UNWIND 0x70000001 /* contains unwind table enries + sh_info contains index of + the code section to which + unwind entries apply */ +#define SHT_PARISC_DOC 0x70000002 /* contains debug info for -O */ +#define SHT_PARISC_ANNOT 0x70000003 /* contains code annotations */ + +/* sh_flags */ +#define SHF_PARISC_SBP 0x80000000 /* contains code compiled for + static branch prediction */ +#define SHF_PARISC_HUGE 0x40000000 /* should be allocated far from gp */ +#define SHF_PARISC_SHORT 0x20000000 /* should be allocated near from gp */ + +#define ELF_PARISC_ARCHEXT ".PARISC.archext" +#define ELF_PARISC_MILLI ".PARISC.milli" +#define ELF_PARISC_UNWIND ".PARISC.unwind" +#define ELF_PARISC_UNWIND_INFO ".PARISC.unwind_info" +#define ELF_PARISC_SDATA ".sdata" +#define ELF_PARISC_NOBITS ".sbss" + +#define STT_PARISC_MILLI 13 /* entry point of a millicode routine */ + +#define PT_PARISC_ARCHEXT 0x70000000 /* segment contains + .PARISC.archext section */ +#define PT_PARISC_UNWIND 0x70000001 /* segment contains + .unwind section */ + +#define PF_PARISC_SBP 0x08000000 /* segment contains code + compiled for static branch prediction */ + +#endif /* _MACHINE_EXEC_H_ */ diff --git a/sys/arch/hppa64/include/float.h b/sys/arch/hppa64/include/float.h new file mode 100644 index 00000000000..4260471309c --- /dev/null +++ b/sys/arch/hppa64/include/float.h @@ -0,0 +1,76 @@ +/* $OpenBSD: float.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)float.h 7.1 (Berkeley) 5/8/90 + */ + +#ifndef _HPPA_FLOAT_H_ +#define _HPPA_FLOAT_H_ + +#include <sys/cdefs.h> + +__BEGIN_DECLS +int __flt_rounds(void); +__END_DECLS + +#define FLT_RADIX 2 +#define FLT_ROUNDS __flt_rounds() + +#define FLT_MANT_DIG 24 +#define FLT_EPSILON 1.19209290E-07F +#define FLT_DIG 6 +#define FLT_MIN_EXP (-125) +#define FLT_MIN 1.17549435E-38F +#define FLT_MIN_10_EXP (-37) +#define FLT_MAX_EXP 128 +#define FLT_MAX 3.40282347E+38F +#define FLT_MAX_10_EXP 38 + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MAX_10_EXP 308 + +#define LDBL_MANT_DIG 113 +#define LDBL_EPSILON 1.9259299443872358530559779425849273E-34L +#define LDBL_DIG 33 +#define LDBL_MIN_EXP (-16381) +#define LDBL_MIN 3.3621031431120935062626778173217526026E-4932L +#define LDBL_MIN_10_EXP (-4931) +#define LDBL_MAX_EXP 16384 +#define LDBL_MAX 1.1897314953572317650857593266280070162E4932L +#define LDBL_MAX_10_EXP 4932 + +#endif /* _MACHINE_FLOAT_H_ */ diff --git a/sys/arch/hppa64/include/frame.h b/sys/arch/hppa64/include/frame.h new file mode 100644 index 00000000000..3be63ffa0a5 --- /dev/null +++ b/sys/arch/hppa64/include/frame.h @@ -0,0 +1,113 @@ +/* $OpenBSD: frame.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +/* + * Call frame definitions + */ +#define HPPA_FRAME_SIZE (128) +#define HPPA_FRAME_PSP (-8) +#define HPPA_FRAME_RP (-16) + +/* + * Macros to decode processor status word. + */ +#define HPPA_PC_PRIV_MASK 3 +#define HPPA_PC_PRIV_KERN 0 +#define HPPA_PC_PRIV_USER 3 +#define USERMODE(pc) ((((register_t)pc) & HPPA_PC_PRIV_MASK) != HPPA_PC_PRIV_KERN) +#define KERNMODE(pc) (((register_t)pc) & ~HPPA_PC_PRIV_MASK) + +/* + * + */ +#define HPPA_SID_MAX 0x7ffffe00 +#define HPPA_SID_KERNEL 0 +#define HPPA_PID_KERNEL 2 + +#ifndef _LOCORE +/* + * the trapframe is divided into two parts: + * one is saved while we are in the physical mode (beginning of the trap), + * and should be kept as small as possible, since all the interrupts will + * be lost during this phase, also it must be 64-bytes aligned, per + * pa-risc stack conventions, and its dependencies in the code (; + * the other part is filled out when we are already in the virtual mode, + * are able to catch interrupts (they are kept pending) and perform + * other trap activities (like tlb misses). + */ +struct trapframe { + unsigned long tf_flags; + unsigned long tf_r1; + unsigned long tf_rp; + unsigned long tf_r3; + unsigned long tf_r4; + unsigned long tf_r5; + unsigned long tf_r6; + unsigned long tf_r7; + unsigned long tf_r8; + unsigned long tf_r9; + unsigned long tf_r10; + unsigned long tf_r11; + unsigned long tf_r12; + unsigned long tf_r13; + unsigned long tf_r14; + unsigned long tf_r15; + unsigned long tf_r16; + unsigned long tf_r17; + unsigned long tf_r18; + unsigned long tf_args[8]; + unsigned long tf_dp; /* r27 */ + unsigned long tf_ret0; + unsigned long tf_ret1; + unsigned long tf_sp; + unsigned long tf_r31; + unsigned long tf_sr0; + unsigned long tf_sr1; + unsigned long tf_sr2; + unsigned long tf_sr3; + unsigned long tf_sr4; + unsigned long tf_sr5; + unsigned long tf_sr6; + unsigned long tf_sr7; + unsigned long tf_rctr; + unsigned long tf_ccr; /* cr10 */ + unsigned long tf_iioq[2]; + unsigned long tf_iisq[2]; + unsigned long tf_pidr1; + unsigned long tf_pidr2; + unsigned long tf_eiem; + unsigned long tf_eirr; + unsigned long tf_ior; + unsigned long tf_isr; + unsigned long tf_iir; + unsigned long tf_ipsw; + unsigned long tf_ci; /* cr24 */ + unsigned long tf_vtop; /* cr25 */ + unsigned long tf_cr30; /* pa(u) */ + unsigned long tf_cr27; /* user curthread */ + unsigned long tf_sar; + + unsigned long tf_pad[5]; +}; +#endif /* !_LOCORE */ + +#endif /* !_MACHINE_FRAME_H_ */ diff --git a/sys/arch/hppa64/include/ieee.h b/sys/arch/hppa64/include/ieee.h new file mode 100644 index 00000000000..dfd8044fd80 --- /dev/null +++ b/sys/arch/hppa64/include/ieee.h @@ -0,0 +1,137 @@ +/* $OpenBSD: ieee.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACBITS 52 + +#ifdef notyet +#define E80_EXPBITS 15 +#define E80_FRACBITS 64 +#endif + +#define EXT_EXPBITS 15 +#define EXT_FRACBITS 112 + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +struct ieee_ext { + u_int ext_sign:1; + u_int ext_exp:15; + u_int ext_frach:16; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 diff --git a/sys/arch/hppa64/include/ieeefp.h b/sys/arch/hppa64/include/ieeefp.h new file mode 100644 index 00000000000..d33f6ac542e --- /dev/null +++ b/sys/arch/hppa64/include/ieeefp.h @@ -0,0 +1,24 @@ +/* $OpenBSD: ieeefp.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Written by Miodrag Vallat. Public domain. + */ + +#ifndef _HPPA64_IEEEFP_H_ +#define _HPPA64_IEEEFP_H_ + +typedef int fp_except; +#define FP_X_INV 0x10 /* invalid operation exception */ +#define FP_X_DZ 0x08 /* divide-by-zero exception */ +#define FP_X_OFL 0x04 /* overflow exception */ +#define FP_X_UFL 0x02 /* underflow exception */ +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd; + +#endif /* _HPPA64_IEEEFP_H_ */ diff --git a/sys/arch/hppa64/include/internal_types.h b/sys/arch/hppa64/include/internal_types.h new file mode 100644 index 00000000000..2ceb6165937 --- /dev/null +++ b/sys/arch/hppa64/include/internal_types.h @@ -0,0 +1,7 @@ +/* $OpenBSD: internal_types.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ +/* Public domain */ + +#ifndef _MACHINE_INTERNAL_TYPES_H_ +#define _MACHINE_INTERNAL_TYPES_H_ + +#endif diff --git a/sys/arch/hppa64/include/iomod.h b/sys/arch/hppa64/include/iomod.h new file mode 100644 index 00000000000..04b20060d5f --- /dev/null +++ b/sys/arch/hppa64/include/iomod.h @@ -0,0 +1,3 @@ +/* $OpenBSD: iomod.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +#include <arch/hppa/include/iomod.h> diff --git a/sys/arch/hppa64/include/kcore.h b/sys/arch/hppa64/include/kcore.h new file mode 100644 index 00000000000..3f652493bee --- /dev/null +++ b/sys/arch/hppa64/include/kcore.h @@ -0,0 +1,28 @@ +/* $OpenBSD: kcore.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_KCORE_H_ +#define _MACHINE_KCORE_H_ + +typedef +struct cpu_kcore_hdr { + int dummy; +} cpu_kcore_hdr_t; + +#endif /* _MACHINE_KCORE_H_ */ diff --git a/sys/arch/hppa64/include/limits.h b/sys/arch/hppa64/include/limits.h new file mode 100644 index 00000000000..bc4736a98e1 --- /dev/null +++ b/sys/arch/hppa64/include/limits.h @@ -0,0 +1,55 @@ +/* $OpenBSD: limits.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1988, 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. 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. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#define MB_LEN_MAX 32 /* Allow 31 bit UTF2 */ + +#if !defined(_ANSI_SOURCE) +#define SIZE_MAX ULONG_MAX /* max value for a size_t */ +#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ + +#if !defined(_POSIX_SOURCE) +#define SIZE_T_MAX ULONG_MAX /* max value for a size_t */ + +/* GCC requires that quad constants be written as expressions. */ +#define UQUAD_MAX ((u_quad_t)0-1) /* max value for a uquad_t */ + /* max value for a quad_t */ +#define QUAD_MAX ((quad_t)(UQUAD_MAX >> 1)) +#define QUAD_MIN (-QUAD_MAX-1) /* min value for a quad_t */ + +#endif /* !_POSIX_SOURCE */ +#endif /* !_ANSI_SOURCE */ + +#endif /* _MACHINE_LIMITS_H_ */ diff --git a/sys/arch/hppa64/include/loadfile_machdep.h b/sys/arch/hppa64/include/loadfile_machdep.h new file mode 100644 index 00000000000..3ce4f899109 --- /dev/null +++ b/sys/arch/hppa64/include/loadfile_machdep.h @@ -0,0 +1,83 @@ +/* $OpenBSD: loadfile_machdep.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/*- + * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas 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. + */ + +#ifndef _HPPA64_LOADFILE_MACHDEP_H_ +#define _HPPA64_LOADFILE_MACHDEP_H_ + +#define BOOT_ELF +#define ELFSIZE 64 + +#define LOAD_KERNEL LOAD_ALL +#define COUNT_KERNEL COUNT_ALL + +#ifdef _STANDALONE + +#define LOADADDR(a) ((a) + offset) +#define ALIGNENTRY(a) 0 +#define READ(f, b, c) pread((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) vpbcopy((s), (void *)LOADADDR(d), (c)) +#define BZERO(d, c) pbzero((void *)LOADADDR(d), (c)) +#define WARN(a) (void)(printf a, \ + printf((errno ? ": %s\n" : "\n"), \ + strerror(errno))) +#define PROGRESS(a) (void) printf a +#define ALLOC(a) alloc(a) +#define FREE(a, b) free(a, b) + +#define vpbcopy bcopy +#define pbzero bzero +#define pread read + +#else + +#define LOADADDR(a) (((u_long)(a)) + offset) +#define ALIGNENTRY(a) ((u_long)(a)) +#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c)) +#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c)) +#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c)) +#define WARN(a) warn a +#define PROGRESS(a) /* nothing */ +#define ALLOC(a) malloc(a) +#define FREE(a, b) free(a) + +ssize_t vread(int, u_long, u_long *, size_t); +void vcopy(u_long, u_long, u_long *, size_t); +void vzero(u_long, u_long *, size_t); + +#endif +#endif /* ! _HPPA64_LOADFILE_MACHDEP_H_ */ diff --git a/sys/arch/hppa64/include/nvm.h b/sys/arch/hppa64/include/nvm.h new file mode 100644 index 00000000000..d050076e88b --- /dev/null +++ b/sys/arch/hppa64/include/nvm.h @@ -0,0 +1,74 @@ +/* $OpenBSD: nvm.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1990, 1994 The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: nvm.h 1.4 94/12/14$ + * Author: Jeff Forys, University of Utah CSL + */ + +#ifndef _MACHINE_NVM_H_ +#define _MACHINE_NVM_H_ + +/* + * The PDC provides access to Non-Volatile Memory (NVM). If this + * is implemented (it's HVERSION dependent), the first 256 bytes + * are formatted as follows: + * + * 0x000 +----------------------------+ + * | Implementation information | + * 0x024 +----------------------------+ + * | | + * | IPL information | + * | | + * 0x080 +----------------------------+ + * | | + * | | + * | OS Panic information | + * | | + * | | + * 0x100 +----------------------------+ + * + * It appears that there are at least 256 bytes of NVM, and only + * the "OS Panic information" is not architected. This means that + * we can use locations 0x80 - 0xFF for saving information across + * boots (e.g. boot flags and boot device). I think we should use + * the higher portions of this space first, to avoid conflicting + * with possible future HP-PA plans for the NVM. + * + * The PDC requires that NVM be read/written to in word multiples. + */ + +/* + * Boot flags and boot device (0xF4 - 0xFF). + */ + +#define NVM_BOOTDATA 0xF4 /* location of bootdata in NVM */ +#define NVM_BOOTMAGIC 0xACCEDE /* magic used for bootdata cksum */ +#define NVM_BOOTCKSUM(bd) \ + ((unsigned int) NVM_BOOTMAGIC + (bd).flags + (bd).device) + +struct bootdata { + unsigned int cksum; /* NVM_BOOTMAGIC + flags + device */ + unsigned int flags; /* boot flags */ + unsigned int device; /* boot device */ +}; + +#endif /* _MACHINE_NVM_H_ */ diff --git a/sys/arch/hppa64/include/param.h b/sys/arch/hppa64/include/param.h new file mode 100644 index 00000000000..a5a9b428918 --- /dev/null +++ b/sys/arch/hppa64/include/param.h @@ -0,0 +1,131 @@ +/* $OpenBSD: param.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1988-1994, The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: param.h 1.18 94/12/16$ + */ + +#include <machine/cpu.h> + +/* + * Machine dependent constants for PA-RISC. + */ + +#define _MACHINE hppa64 +#define MACHINE "hppa64" +#define _MACHINE_ARCH hppa64 +#define MACHINE_ARCH "hppa64" +#define MID_MACHINE MID_HPPA20 + +/* + * Round p (pointer or byte index) up to a correctly-aligned value for all + * data types (int, long, ...). The result is u_int and must be cast to + * any desired pointer type. + */ +#define ALIGNBYTES 7 +#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES) +#define ALIGNED_POINTER(p,t) ((((u_long)(p)) & (sizeof(t) - 1)) == 0) + +#define PAGE_SIZE 4096 +#define PAGE_MASK (PAGE_SIZE-1) +#define PAGE_SHIFT 12 + +#define NBPG 4096 /* bytes/page */ +#define PGOFSET (NBPG-1) /* byte offset into page */ +#define PGSHIFT 12 /* LOG2(NBPG) */ + +#define KERNBASE 0x00000000 /* start of kernel virtual */ +#define BTOPKERNBASE ((u_long)KERNBASE >> PAGE_SHIFT) + +#define DEV_BSIZE 512 +#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */ +#define BLKDEV_IOSIZE 2048 +#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */ + +#define MACHINE_STACK_GROWS_UP 1 /* stack grows to higher addresses */ + +#define SSIZE (4) /* initial stack size/NBPG */ +#define SINCR (1) /* increment of stack/NBPG */ + +#define USPACE (4 * NBPG) /* pages for user struct and kstack */ +#define USPACE_ALIGN (0) /* u-area alignment 0-none */ + +#ifndef MSGBUFSIZE +#define MSGBUFSIZE 2*NBPG /* default message buffer size */ +#endif + +/* + * Constants related to network buffer management. + * MCLBYTES must be no larger than the software page size, and, + * on machines that exchange pages of input or output buffers with mbuf + * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple + * of the hardware page size. + */ +#define MSIZE 256 /* size of an mbuf */ +#define MCLSHIFT 11 +#define MCLBYTES (1 << MCLSHIFT) /* large enough for ether MTU */ +#define MCLOFSET (MCLBYTES - 1) +#define NMBCLUSTERS 4096 /* map size, max cluster allocation */ + +/* + * Minimum and maximum sizes of the kernel malloc arena in PAGE_SIZE-sized + * logical pages. + */ +#define NKMEMPAGES_MIN_DEFAULT ((4 * 1024 * 1024) >> PAGE_SHIFT) +#define NKMEMPAGES_MAX_DEFAULT ((64 * 1024 * 1024) >> PAGE_SHIFT) + +/* pages ("clicks") (4096 bytes) to disk blocks */ +#define ctod(x) ((x) << (PAGE_SHIFT - DEV_BSHIFT)) +#define dtoc(x) ((x) >> (PAGE_SHIFT - DEV_BSHIFT)) + +/* pages to bytes */ +#define ctob(x) ((x) << PAGE_SHIFT) +#define btoc(x) (((x) + PAGE_MASK) >> PAGE_SHIFT) + +#define btodb(x) ((x) >> DEV_BSHIFT) +#define dbtob(x) ((x) << DEV_BSHIFT) + +/* + * Map a ``block device block'' to a file system block. + * This should be device dependent, and should use the bsize + * field from the disk label. + * For now though just use DEV_BSIZE. + */ +#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE/DEV_BSIZE)) + +/* + * Mach derived conversion macros + */ +#define hppa_round_page(x) ((((unsigned long)(x)) + NBPG - 1) & ~(NBPG-1)) +#define hppa_trunc_page(x) ((unsigned long)(x) & ~(NBPG-1)) + +#define btop(x) ((unsigned long)(x) >> PAGE_SHIFT) +#define ptob(x) ((unsigned long)(x) << PAGE_SHIFT) + +#ifndef _LOCORE +#define CONADDR conaddr +#define CONUNIT conunit +#define COM_FREQ 7372800 +extern hppa_hpa_t conaddr; +extern int conunit; +#endif + +#define __SWAP_BROKEN diff --git a/sys/arch/hppa64/include/pcb.h b/sys/arch/hppa64/include/pcb.h new file mode 100644 index 00000000000..ab366a4d14e --- /dev/null +++ b/sys/arch/hppa64/include/pcb.h @@ -0,0 +1,44 @@ +/* $OpenBSD: pcb.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +#include <machine/reg.h> + +struct pcb { + u_int64_t pcb_fpregs[HPPA_NFPREGS+1]; /* not in the trapframe */ + u_int64_t pcb_onfault; /* SW copy fault handler */ + vaddr_t pcb_uva; /* KVA for U-area */ + u_int64_t pcb_ksp; /* kernel sp for ctxsw */ + pa_space_t pcb_space; /* copy pmap_space, for asm's sake */ + +#if 0 /* imaginary part that is after user but in the same page */ + u_int32_t pcb_pad[53+768]; + u_int64_t pcb_frame[64]; /* the very end */ +#endif +}; + +struct md_coredump { + struct reg md_reg; + struct fpreg md_fpreg; +}; + + +#endif /* _MACHINE_PCB_H_ */ diff --git a/sys/arch/hppa64/include/pci_machdep.h b/sys/arch/hppa64/include/pci_machdep.h new file mode 100644 index 00000000000..9e122ad90ab --- /dev/null +++ b/sys/arch/hppa64/include/pci_machdep.h @@ -0,0 +1,82 @@ +/* $OpenBSD: pci_machdep.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PCI_MACHDEP_H_ +#define _MACHINE_PCI_MACHDEP_H_ + +/* + * Types provided to machine-independent PCI code + */ +typedef struct hppa64_pci_chipset_tag *pci_chipset_tag_t; +typedef u_int pcitag_t; +typedef u_long pci_intr_handle_t; + +struct pci_attach_args; + +struct hppa64_pci_chipset_tag { + void *_cookie; + void (*pc_attach_hook)(struct device *, + struct device *, struct pcibus_attach_args *); + int (*pc_bus_maxdevs)(void *, int); + pcitag_t (*pc_make_tag)(void *, int, int, int); + void (*pc_decompose_tag)(void *, pcitag_t, int *, + int *, int *); + pcireg_t (*pc_conf_read)(void *, pcitag_t, int); + void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t); + + int (*pc_intr_map)(struct pci_attach_args *, + pci_intr_handle_t *); + const char *(*pc_intr_string)(void *, pci_intr_handle_t); + void *(*pc_intr_establish)(void *, pci_intr_handle_t, + int, int (*)(void *), void *, char *); + void (*pc_intr_disestablish)(void *, void *); + + void *(*pc_alloc_parent)(struct device *, + struct pci_attach_args *, int); +}; + +/* + * Functions provided to machine-independent PCI code. + */ +#define pci_attach_hook(p, s, pba) \ + (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba)) +#define pci_bus_maxdevs(c, b) \ + (*(c)->pc_bus_maxdevs)((c)->_cookie, (b)) +#define pci_make_tag(c, b, d, f) \ + (*(c)->pc_make_tag)((c)->_cookie, (b), (d), (f)) +#define pci_decompose_tag(c, t, bp, dp, fp) \ + (*(c)->pc_decompose_tag)((c)->_cookie, (t), (bp), (dp), (fp)) +#define pci_conf_read(c, t, r) \ + (*(c)->pc_conf_read)((c)->_cookie, (t), (r)) +#define pci_conf_write(c, t, r, v) \ + (*(c)->pc_conf_write)((c)->_cookie, (t), (r), (v)) +#define pci_intr_map(p, ihp) \ + (*(p)->pa_pc->pc_intr_map)((p), (ihp)) +#define pci_intr_line(ih) (ih) +#define pci_intr_string(c, ih) \ + (*(c)->pc_intr_string)((c)->_cookie, (ih)) +#define pci_intr_establish(c, ih, l, h, a, nm) \ + (*(c)->pc_intr_establish)((c)->_cookie, (ih), (l), (h), (a), (nm)) +#define pci_intr_disestablish(c, iv) \ + (*(c)->pc_intr_disestablish)((c)->_cookie, (iv)) + +#define pciide_machdep_compat_intr_establish(a, b, c, d, e) (NULL) +#define pciide_machdep_compat_intr_disestablish(a, b) ((void)(a), (void)(b)) + +#endif /* _MACHINE_PCI_MACHDEP_H_ */ diff --git a/sys/arch/hppa64/include/pdc.h b/sys/arch/hppa64/include/pdc.h new file mode 100644 index 00000000000..89034c60e79 --- /dev/null +++ b/sys/arch/hppa64/include/pdc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pdc.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +#include <arch/hppa/include/pdc.h> diff --git a/sys/arch/hppa64/include/pmap.h b/sys/arch/hppa64/include/pmap.h new file mode 100644 index 00000000000..1014076b7e2 --- /dev/null +++ b/sys/arch/hppa64/include/pmap.h @@ -0,0 +1,117 @@ +/* $OpenBSD: pmap.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#include <machine/pte.h> +#include <uvm/uvm_pglist.h> +#include <uvm/uvm_object.h> + +struct pmap { + simple_lock_data_t pm_lock; + int pm_refcount; + struct vm_page *pm_ptphint; + struct pglist pm_pglist; + volatile u_int32_t *pm_pdir; /* page dir (read-only after create) */ + pa_space_t pm_space; /* space id (read-only after create) */ + + struct pmap_statistics pm_stats; +}; +typedef struct pmap *pmap_t; + +struct pv_entry { /* locked by its list's pvh_lock */ + struct pv_entry *pv_next; + struct pmap *pv_pmap; /* the pmap */ + vaddr_t pv_va; /* the virtual address */ + struct vm_page *pv_ptp; /* the vm_page of the PTP */ +}; + +#ifdef _KERNEL + +extern struct pmap kernel_pmap_store; + +/* + * pool quickmaps + */ +#define pmap_map_direct(pg) ((vaddr_t)VM_PAGE_TO_PHYS(pg)) +#define pmap_unmap_direct(va) PHYS_TO_VM_PAGE((paddr_t)(va)) +#define __HAVE_PMAP_DIRECT + +/* + * according to the parisc manual aliased va's should be + * different by high 12 bits only. + */ +#define PMAP_PREFER(o,h) do { \ + vaddr_t pmap_prefer_hint; \ + pmap_prefer_hint = (*(h) & HPPA_PGAMASK) | ((o) & HPPA_PGAOFF); \ + if (pmap_prefer_hint < *(h)) \ + pmap_prefer_hint += HPPA_PGALIAS; \ + *(h) = pmap_prefer_hint; \ +} while(0) + +#define PMAP_GROWKERNEL +#define PMAP_STEAL_MEMORY + +#define pmap_sid2pid(s) (((s) + 1) << 1) +#define pmap_kernel() (&kernel_pmap_store) +#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count) +#define pmap_update(pm) (void)(pm) +#define pmap_copy(dpmap,spmap,da,len,sa) + +#define pmap_clear_modify(pg) pmap_changebit(pg, 0, PTE_DIRTY) +#define pmap_clear_reference(pg) pmap_changebit(pg, PTE_REFTRAP, 0) +#define pmap_is_modified(pg) pmap_testbit(pg, PTE_DIRTY) +#define pmap_is_referenced(pg) pmap_testbit(pg, PTE_REFTRAP) +#define pmap_phys_address(ppn) ((ppn) << PAGE_SHIFT) + +#define pmap_proc_iflush(p,va,len) /* nothing */ +#define pmap_unuse_final(p) /* nothing */ + +void pmap_bootstrap(vaddr_t); +boolean_t pmap_changebit(struct vm_page *, pt_entry_t, pt_entry_t); +boolean_t pmap_testbit(struct vm_page *, pt_entry_t); +void pmap_write_protect(struct pmap *, vaddr_t, vaddr_t, vm_prot_t); +void pmap_remove(struct pmap *pmap, vaddr_t sva, vaddr_t eva); +void pmap_page_remove(struct vm_page *pg); + +static __inline void +pmap_page_protect(struct vm_page *pg, vm_prot_t prot) +{ + if ((prot & UVM_PROT_WRITE) == 0) { + if (prot & (UVM_PROT_RX)) + pmap_changebit(pg, 0, PTE_WRITE); + else + pmap_page_remove(pg); + } +} + +static __inline void +pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) +{ + if ((prot & UVM_PROT_WRITE) == 0) { + if (prot & (UVM_PROT_RX)) + pmap_write_protect(pmap, sva, eva, prot); + else + pmap_remove(pmap, sva, eva); + } +} + +#endif /* _KERNEL */ +#endif /* _MACHINE_PMAP_H_ */ diff --git a/sys/arch/hppa64/include/proc.h b/sys/arch/hppa64/include/proc.h new file mode 100644 index 00000000000..1197ef43208 --- /dev/null +++ b/sys/arch/hppa64/include/proc.h @@ -0,0 +1,43 @@ +/* $OpenBSD: proc.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1992, 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. 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 7.1 (Berkeley) 5/15/91 + */ + +/* + * Machine-dependent part of the proc structure for hppa. + */ +struct mdproc { + struct trapframe *md_regs; /* registers on current frame */ + long md_flags; /* machine-dependent flags */ +}; + +/* md_flags */ + diff --git a/sys/arch/hppa64/include/profile.h b/sys/arch/hppa64/include/profile.h new file mode 100644 index 00000000000..36e8b335fe7 --- /dev/null +++ b/sys/arch/hppa64/include/profile.h @@ -0,0 +1,45 @@ +/* $OpenBSD: profile.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1992, 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. 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. + * + * @(#)profile.h 8.1 (Berkeley) 6/11/93 + */ + +#define _MCOUNT_DECL void _mcount + +#define MCOUNT + +#ifdef _KERNEL +/* + * Note that we assume splhigh() and splx() cannot call mcount() + * recursively. + */ +#define MCOUNT_ENTER s = splhigh() +#define MCOUNT_EXIT splx(s) +#endif /* _KERNEL */ diff --git a/sys/arch/hppa64/include/psl.h b/sys/arch/hppa64/include/psl.h new file mode 100644 index 00000000000..94be150eba0 --- /dev/null +++ b/sys/arch/hppa64/include/psl.h @@ -0,0 +1,94 @@ +/* $OpenBSD: psl.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * Rference: + * 1. PA-RISC 1.1 Architecture and Instruction Set Manual + * Hewlett Packard, 3rd Edition, February 1994; Part Number 09740-90039 + */ + +/* + * Processor Status Word Bit Positions (in PA-RISC bit order) + */ +#define PSL_Y_POS (0) +#define PSL_Z_POS (1) +#define PSL_W_POS (4) +#define PSL_E_POS (5) +#define PSL_S_POS (6) +#define PSL_T_POS (7) +#define PSL_H_POS (8) +#define PSL_L_POS (9) +#define PSL_N_POS (10) +#define PSL_X_POS (11) +#define PSL_B_POS (12) +#define PSL_C_POS (13) +#define PSL_V_POS (14) +#define PSL_M_POS (15) +#define PSL_CB_POS (16) +#define PSL_O_POS (24) +#define PSL_G_POS (25) +#define PSL_F_POS (26) +#define PSL_R_POS (27) +#define PSL_Q_POS (28) +#define PSL_P_POS (29) +#define PSL_D_POS (30) +#define PSL_I_POS (31) + +#define PSL_BITS "\020\001I\002D\003P\004Q\005R\006F\007G\010O" \ + "\021M\022V\023C\024B\025X\026N\027L\030H" \ + "\031T\032S\033E\034W\037Z\040Y" + +/* + * Processor Status Word Bit Values + */ +#define PSL_Y (1 << (31-PSL_Y_POS)) /* Data Debug Trap Disable */ +#define PSL_Z (1 << (31-PSL_Z_POS)) /* Instruction Debug Trap Disable */ +#define PSL_W (1 << (31-PSL_W_POS)) /* 64bit address decode enable */ +#define PSL_E (1 << (31-PSL_E_POS)) /* Little Endian Memory Access Enable */ +#define PSL_S (1 << (31-PSL_S_POS)) /* Secure Interval Timer */ +#define PSL_T (1 << (31-PSL_T_POS)) /* Taken Branch Trap Enable */ +#define PSL_H (1 << (31-PSL_H_POS)) /* Higher-privilege xfer Trap Enable */ +#define PSL_L (1 << (31-PSL_L_POS)) /* Lower-privilege xfer Trap Enable */ +#define PSL_N (1 << (31-PSL_N_POS)) /* Nullify */ +#define PSL_X (1 << (31-PSL_X_POS)) /* Data Memory Break Disable */ +#define PSL_B (1 << (31-PSL_B_POS)) /* Taken Branch */ +#define PSL_C (1 << (31-PSL_C_POS)) /* Instruction Address Translation */ +#define PSL_V (1 << (31-PSL_V_POS)) /* Divide Step Correction */ +#define PSL_M (1 << (31-PSL_M_POS)) /* High-priority Machine Check Mask */ +#define PSL_CB (1 << (31-PSL_CB_POS)) /* Carry/Borrow Bits */ +#define PSL_O (1 << (31-PSL_O_POS)) /* Force strong ordering (2.0) */ +#define PSL_G (1 << (31-PSL_G_POS)) /* Debug Trap Enable */ +#define PSL_F (1 << (31-PSL_F_POS)) /* Perfomance Monitor Interrupt */ +#define PSL_R (1 << (31-PSL_R_POS)) /* Recover Counter Enable */ +#define PSL_Q (1 << (31-PSL_Q_POS)) /* Interrupt State Collection Enable */ +#define PSL_P (1 << (31-PSL_P_POS)) /* Protection Identifier Validation */ +#define PSL_D (1 << (31-PSL_D_POS)) /* Data Address Translation Enable */ +#define PSL_I (1 << (31-PSL_I_POS)) /* External Interrupt, Power Failure + Interrupt, and Low-Priority Machine + Check Interrupt unmask */ + +/* + * Frequently Used PSW Values + */ +#define RESET_PSL (PSL_R | PSL_Q | PSL_P | PSL_D | PSL_I) + +#endif /* _MACHINE_PSL_H_ */ diff --git a/sys/arch/hppa64/include/pte.h b/sys/arch/hppa64/include/pte.h new file mode 100644 index 00000000000..4440b2da827 --- /dev/null +++ b/sys/arch/hppa64/include/pte.h @@ -0,0 +1,68 @@ +/* $OpenBSD: pte.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +#define SID_MASK (0x1ff) +#define SID_SHIFT (9) +#define PIE_MASK (0x1ff80000000UL) +#define PIE_SHIFT (PDE_SHIFT+10) +#define PDE_MASK (0x0007fe00000UL) +#define PDE_SHIFT (PTE_SHIFT+9) +#define PTE_MASK (0x000001ff000UL) +#define PTE_SHIFT PAGE_SHIFT +#define PTE_PAGE(pte) (((pte) & ~PTE_PGMASK) << 7) +#define TLB_PAGE(pg) (((pg) >> 7) & PTE_PGMASK) + +#define PTE_IFLUSH 0x8000000000000000UL /* software */ +#define PTE_DFLUSH 0x4000000000000000UL /* software */ +#define PTE_REFTRAP 0x2000000000000000UL /* used as a ref bit */ +#define PTE_DIRTY 0x1000000000000000UL +#define PTE_BREAK 0x0800000000000000UL +#define PTE_GATEWAY 0x04c0000000000000UL +#define PTE_EXEC 0x0200000000000000UL +#define PTE_WRITE 0x0100000000000000UL +#define PTE_READ 0x0000000000000000UL +#define PTE_USER 0x00f0000000000000UL +#define PTE_ACC_NONE 0x0730000000000000UL +#define PTE_ACC_MASK 0x07f0000000000000UL +#define PTE_UNCACHABLE 0x0008000000000000UL +#define PTE_ORDER 0x0004000000000000UL +#define PTE_PREDICT 0x0002000000000000UL +#define PTE_WIRED 0x0001000000000000UL /* software */ +#define PTE_PGMASK 0x0000001fffffffe0UL +#define PTE_PG4K 0x0000000000000000UL +#define PTE_PG16K 0x0000000000000001UL +#define PTE_PG64K 0x0000000000000002UL +#define PTE_PG256K 0x0000000000000003UL +#define PTE_PG1M 0x0000000000000004UL +#define PTE_PG4M 0x0000000000000005UL +#define PTE_PG16M 0x0000000000000006UL +#define PTE_PG64M 0x0000000000000007UL + +#define PTE_GETBITS(pte) ((pte) >> 48) +#define PTE_BITS \ + "\020\01H\02P\03O\04UC\05U\010W\11X\12G\014B\015D\016REF\017FD\020FI" + +#ifndef _LOCORE +typedef u_int64_t pt_entry_t; +#endif + +#endif /* _MACHINE_PTE_H_ */ diff --git a/sys/arch/hppa64/include/ptrace.h b/sys/arch/hppa64/include/ptrace.h new file mode 100644 index 00000000000..a48a429b5a1 --- /dev/null +++ b/sys/arch/hppa64/include/ptrace.h @@ -0,0 +1,27 @@ +/* $OpenBSD: ptrace.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * MD ptrace definitions + */ +#define PT_STEP (PT_FIRSTMACH + 0) +#define PT_GETREGS (PT_FIRSTMACH + 1) +#define PT_SETREGS (PT_FIRSTMACH + 2) +#define PT_GETFPREGS (PT_FIRSTMACH + 3) +#define PT_SETFPREGS (PT_FIRSTMACH + 4) diff --git a/sys/arch/hppa64/include/rbus_machdep.h b/sys/arch/hppa64/include/rbus_machdep.h new file mode 100644 index 00000000000..963e54b89ff --- /dev/null +++ b/sys/arch/hppa64/include/rbus_machdep.h @@ -0,0 +1,34 @@ +/* $OpenBSD: rbus_machdep.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +static __inline int +md_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, bus_space_handle_t *bshp) +{ + if (bshp) + *(bshp) = bpa; + + return (0); +} + +#define md_space_unmap(t,bsh,s,addrp) do { *(addrp) = (bsh); } while (0) + +struct pci_attach_args; + +#define rbus_pccbb_parent_mem(d, p) (*(p)->pa_pc->pc_alloc_parent)((d), (p), 0) +#define rbus_pccbb_parent_io(d, p) (*(p)->pa_pc->pc_alloc_parent)((d), (p), 1) diff --git a/sys/arch/hppa64/include/reg.h b/sys/arch/hppa64/include/reg.h new file mode 100644 index 00000000000..ce4cc5add6f --- /dev/null +++ b/sys/arch/hppa64/include/reg.h @@ -0,0 +1,93 @@ +/* $OpenBSD: reg.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 1990,1994 The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: regs.h 1.6 94/12/14$ + * Author: Bob Wheeler, University of Utah CSL + */ + +#ifndef _MACHINE_REG_H_ +#define _MACHINE_REG_H_ + +/* + * constants for registers for use with the following routines: + * + * void mtctl(reg, value) - move to control register + * int mfctl(reg) - move from control register + * int mtsp(sreg, value) - move to space register + * int mfsr(sreg) - move from space register + */ + +#define CR_RCTR 0 +#define CR_PIDR1 8 +#define CR_PIDR2 9 +#define CR_CCR 10 +#define CR_SAR 11 +#define CR_PIDR3 12 +#define CR_PIDR4 13 +#define CR_IVA 14 +#define CR_EIEM 15 +#define CR_ITMR 16 +#define CR_PCSQ 17 +#define CR_PCOQ 18 +#define CR_IIR 19 +#define CR_ISR 20 +#define CR_IOR 21 +#define CR_IPSW 22 +#define CR_EIRR 23 +#define CR_CPUINFO 24 +#define CR_VTOP 25 +#define CR_UPADDR 30 /* paddr of U-area of curproc */ +#define CR_TR7 31 + +#define HPPA_NREGS (32) +#define HPPA_NFPREGS (33) /* 33rd is used for r0 in fpemul */ + +#ifndef _LOCORE + +struct reg { + u_int64_t r_regs[HPPA_NREGS]; /* r0 is sar */ + u_int64_t r_pc; + u_int64_t r_npc; +}; + +struct fpreg { + u_int64_t fpr_regs[HPPA_NFPREGS]; +}; +#endif /* !_LOCORE */ + +#endif /* _MACHINE_REG_H_ */ diff --git a/sys/arch/hppa64/include/reloc.h b/sys/arch/hppa64/include/reloc.h new file mode 100644 index 00000000000..6c32cad2433 --- /dev/null +++ b/sys/arch/hppa64/include/reloc.h @@ -0,0 +1,123 @@ +/* $OpenBSD: reloc.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_RELOC_H_ +#define _MACHINE_RELOC_H_ + +/* pa1 compatibility */ +#define RELOC_DLTREL21L RELOC_GPREL21L +#define RELOC_DLTREL14R RELOC_GPREL14R +#define RELOC_DLTIND21L RELOC_LTOFF21L +#define RELOC_DLTIND14R RELOC_LTOFF14R +#define RELOC_DLTIND14F RELOC_LTOFF14F +#define RELOC_DLTREL14WR RELOC_GPREL14WR +#define RELOC_DLTREL14DR RELOC_GPREL14DR +#define RELOC_DLTIND14WR RELOC_LTOFF14WR +#define RELOC_DLTIND14DR RELOC_LTOFF14DR + + +enum reloc_type { + RELOC_NONE = 0, + RELOC_DIR32, /* symbol + addend*/ + RELOC_DIR21L, /* LR(symbol, addend) */ + RELOC_DIR17R, /* RR(symbol, addend) */ + RELOC_DIR17F, /* symbol + addend */ + RELOC_DIR14R = 6, /* RR(symbol, addend) */ + RELOC_PCREL32 = 9, /* pa2: symbol - PC - 8 + addend */ + RELOC_PCREL21L, /* L(symbol - PC - 8 + addend */ + RELOC_PCREL17R, /* R(symbol - PC - 8 + addend */ + RELOC_PCREL17F, /* symbol - PC - 8 + addend */ + RELOC_PCREL17C, /* pa1: symbol - PC - 8 + addend */ + RELOC_PCREL14R, /* R(symbol - PC - 8 + addend */ + RELOC_DPREL21L = 18, /* pa1: LR(symbol - GP, addend */ + RELOC_DPREL14WR, /* pa1: RR(symbol - GP, addend */ + RELOC_DPREL14DR, /* pa1: RR(symbol - GP, addend */ + RELOC_DPREL14R, /* pa1: RR(symbol - GP, addend */ + RELOC_GPREL21L = 26, /* LR(symbol - GP, addend */ + RELOC_GPREL14R = 30, /* RR(symbol - GP, addend */ + RELOC_LTOFF21L = 34, /* L(ltoff(symbol + addend)) */ + RELOC_LTOFF14R = 38, /* R(ltoff(symbol + addend)) */ + RELOC_LTOFF14F, /* pa1: ltoff(symbol + addend) */ + RELOC_SETBASE, /* no relocation; base = symbol */ + RELOC_SECREL32, /* symbol - SECT + addend */ + RELOC_BASEREL21L, /* pa1: LR(symbol - base, addend) */ + RELOC_BASEREL17R, /* pa1: RR(symbol - base, addend) */ + RELOC_BASEREL14R = 46, /* pa1: RR(symbol - base, addend) */ + RELOC_SEGBASE = 48, /* no relocation; SB = symbol */ + RELOC_SEGREL32, /* symbol - SB + addend */ + RELOC_PLTOFF21L, /* LR(pltoff(symbol), addend */ + RELOC_PLTOFF14R = 54, /* RR(pltoff(symbol), addend */ + RELOC_PLTOFF14F, /* pa1: pltoff(symbol) + addend */ + RELOC_LTOFF_FPTR32 = 57,/* pa2: ltoff(fptr(symbol + addend)) */ + RELOC_LTOFF_FPTR21L, /* pa2: L(ltoff(fptr(symbol + addend))) */ + RELOC_LTOFF_FPTR14R= 62,/* pa2: R(ltoff(fptr(symbol + addend))) */ + RELOC_FPTR64 = 64, /* pa2: fptr(symbol + addend) */ + RELOC_PLABEL32, /* pa1: fptr(symbol) */ + RELOC_PCREL64 = 72, /* pa2: symbol - PC - 8 + addend */ + RELOC_PCREL22C, /* pa1: symbol - PC - 8 + addend */ + RELOC_PCREL22F, /* symbol - PC - 8 + addend */ + RELOC_PCREL14WR, /* R(symbol - PC - 8 + addend) */ + RELOC_PCREL14DR, /* R(symbol - PC - 8 + addend) */ + RELOC_PCREL16F, /* pa2: symbol - PC - 8 + addend */ + RELOC_PCREL16WF, /* pa2: symbol - PC - 8 + addend */ + RELOC_PCREL16DF, /* pa2: symbol - PC - 8 + addend */ + RELOC_DIR64, /* pa2: symbol + addend */ + RELOC_DIR14WR = 83, /* RR(symbol, addend) */ + RELOC_DIR14DR, /* RR(symbol, addend) */ + RELOC_DIR16F, /* pa2: symbol + addend */ + RELOC_DIR16WF, /* pa2: symbol + addend */ + RELOC_DIR16DF, /* pa2: symbol + addend */ + RELOC_GPREL64, /* pa2: symbol - GP + addend */ + RELOC_GPREL14WR = 91, /* RR(symbol - GP, addend) */ + RELOC_GPREL14DR, /* RR(symbol - GP, addend) */ + RELOC_GPREL16F, /* pa2: symbol - GP + addend */ + RELOC_GPREL16WF, /* pa2: symbol - GP + addend */ + RELOC_GPREL16DF, /* pa2: symbol - GP + addend */ + RELOC_LTOFF64 = 96, /* pa2: ltoff(symbol + addend) */ + RELOC_LTOFF14WR = 99, /* R(ltoff(symbol + addend)) */ + RELOC_LTOFF14DR, /* R(ltoff(symbol + addend)) */ + RELOC_LTOFF16F, /* pa2: ltoff(symbol + addend) */ + RELOC_LTOFF16WF, /* pa2: ltoff(symbol + addend) */ + RELOC_LTOFF16DF, /* pa2: ltoff(symbol + addend) */ + RELOC_SECREL64, /* pa2: symbol - SECT + addend */ + RELOC_BASEREL14WR=107, /* pa1: RR(symbol - base, addend */ + RELOC_BASEREL14DR, /* pa1: RR(symbol - base, addend */ + RELOC_SEGREL64 = 112, /* pa2: symbol - SB + addend */ + RELOC_PLTOFF14WR =115, /* RR(pltoff(symbol) + addend) */ + RELOC_PLTOFF14DR, /* RR(pltoff(symbol) + addend) */ + RELOC_PLTOFF16F, /* pa2: pltoff(symbol) + addend */ + RELOC_PLTOFF16WF, /* pa2: pltoff(symbol) + addend */ + RELOC_PLTOFF16DF, /* pa2: pltoff(symbol) + addend */ + RELOC_LTOFF_FPTR64, /* pa2: ltoff(fptr(symbol + addend)) */ + RELOC_LTOFF_FPTR14WR=123,/* pa2: R(ltoff(fptr(symbol + addend) */ + RELOC_LTOFF_FPTR14DR, /* pa2: R(ltoff(fptr(symbol + addend) */ + RELOC_LTOFF_FPTR16F, /* pa2: ltoff(fptr(symbol + addend)) */ + RELOC_LTOFF_FPTR16WF, /* pa2: ltoff(fptr(symbol + addend)) */ + RELOC_LTOFF_FPTR16DF, /* pa2: ltoff(fptr(symbol + addend)) */ + RELOC_LORESERVE, /* reserved for environment-specific use */ + RELOC_COPY = 128, + RELOC_IPLT, + RELOC_EPLT, + RELOC_GDATA, + RELOC_JMPSLOT, + RELOC_RELATIVE, + RELOC_HIRESERVE = 255 +}; + +#endif /* _MACHINE_RELOC_H_ */ diff --git a/sys/arch/hppa64/include/setjmp.h b/sys/arch/hppa64/include/setjmp.h new file mode 100644 index 00000000000..aee122ff95e --- /dev/null +++ b/sys/arch/hppa64/include/setjmp.h @@ -0,0 +1,7 @@ +/* $OpenBSD: setjmp.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * machine/setjmp.h: machine dependent setjmp-related information. + */ + +#define _JBLEN 48 /* size, in longs, of a jmp_buf */ diff --git a/sys/arch/hppa64/include/signal.h b/sys/arch/hppa64/include/signal.h new file mode 100644 index 00000000000..c09fcd73ea1 --- /dev/null +++ b/sys/arch/hppa64/include/signal.h @@ -0,0 +1,57 @@ +/* $OpenBSD: signal.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1994, The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: signal.h 1.3 94/12/16$ + */ + +#ifndef _HPPA64_SIGNAL_H_ +#define _HPPA64_SIGNAL_H_ + +/* + * Machine-dependent signal definitions + */ + +typedef int sig_atomic_t; + +#ifndef _ANSI_SOURCE +#include <machine/trap.h> + +/* + * Information pushed on stack when a signal is delivered. + * This is used by the kernel to restore state following + * execution of the signal handler. It is also made available + * to the handler to allow it to restore state properly if + * a non-standard exit is performed. + */ +struct sigcontext { + unsigned long sc_onstack; /* sigstack state to restore */ + unsigned long sc_mask; /* signal mask to restore */ + unsigned long sc_ps; /* psl to restore */ + unsigned long sc_fp; /* fp to restore */ + unsigned long sc_pcoqh; /* pc offset queue (head) to restore */ + unsigned long sc_pcoqt; /* pc offset queue (tail) to restore */ + unsigned long sc_resv[2]; + unsigned long sc_regs[32]; + unsigned long sc_fpregs[64]; +}; +#endif /* !_ANSI_SOURCE */ +#endif /* !_HPPA64_SIGNAL_H_ */ diff --git a/sys/arch/hppa64/include/spinlock.h b/sys/arch/hppa64/include/spinlock.h new file mode 100644 index 00000000000..d9e362736c5 --- /dev/null +++ b/sys/arch/hppa64/include/spinlock.h @@ -0,0 +1,10 @@ +/* $OpenBSD: spinlock.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +#ifndef _MACHINE_SPINLOCK_H_ +#define _MACHINE_SPINLOCK_H_ + +#define _SPINLOCK_UNLOCKED (1) +#define _SPINLOCK_LOCKED (0) +typedef long _spinlock_lock_t; + +#endif diff --git a/sys/arch/hppa64/include/stdarg.h b/sys/arch/hppa64/include/stdarg.h new file mode 100644 index 00000000000..5d0e1a203d9 --- /dev/null +++ b/sys/arch/hppa64/include/stdarg.h @@ -0,0 +1,62 @@ +/* $OpenBSD: stdarg.h,v 1.1 2005/04/01 10:40:48 mickey 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. 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. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _MACHINE_STDARG_H_ +#define _MACHINE_STDARG_H_ + +typedef double *va_list; + +#ifdef __GNUC__ +#define va_start(ap,lastarg) ((ap) = (va_list)__builtin_saveregs()) +#else +#define va_start(ap,lastarg) __builtin_va_start(ap, &lastarg) +#endif + +#define va_arg(ap,type) \ + (sizeof(type) > 8 ? \ + ((ap = (va_list) ((char *)ap - sizeof (int))), \ + (*((type *) (void *) (*((int *) (ap)))))): \ + ((ap = (va_list) ((long)((char *)ap - sizeof (type)) & \ + (sizeof(type) > 4 ? ~0x7 : ~0x3))),\ + (*((type *) (void *) ((char *)ap + ((8 - sizeof(type)) % 4)))))) + +#if !defined(_ANSI_SOURCE) && \ + (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) || \ + defined(_ISOC99_SOURCE) || (__STDC_VERSION__ - 0) >= 199901L) +#define va_copy(dest, src) \ + ((dest) = (src)) +#endif + +#define va_end(ap) + +#endif /* !_MACHINE_STDARG_H */ diff --git a/sys/arch/hppa64/include/trap.h b/sys/arch/hppa64/include/trap.h new file mode 100644 index 00000000000..16014a425b2 --- /dev/null +++ b/sys/arch/hppa64/include/trap.h @@ -0,0 +1,91 @@ +/* $OpenBSD: trap.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MACHINE_TRAP_H_ +#define _MACHINE_TRAP_H_ + +/* + * This is PA-RISC trap types per 1.1 specs, see .c files for references. + */ +#define T_NONEXIST 0 /* invalid interrupt vector */ +#define T_HPMC 1 /* high priority machine check */ +#define T_POWERFAIL 2 /* power failure */ +#define T_RECOVERY 3 /* recovery counter */ +#define T_INTERRUPT 4 /* external interrupt */ +#define T_LPMC 5 /* low-priority machine check */ +#define T_ITLBMISS 6 /* instruction TLB miss fault */ +#define T_IPROT 7 /* instruction protection */ +#define T_ILLEGAL 8 /* Illegal instruction */ +#define T_IBREAK 9 /* break instruction */ +#define T_PRIV_OP 10 /* privileged operation */ +#define T_PRIV_REG 11 /* privileged register */ +#define T_OVERFLOW 12 /* overflow */ +#define T_CONDITION 13 /* conditional */ +#define T_EXCEPTION 14 /* assist exception */ +#define T_DTLBMISS 15 /* data TLB miss */ +#define T_ITLBMISSNA 16 /* ITLB non-access miss */ +#define T_DTLBMISSNA 17 /* DTLB non-access miss */ +#define T_DPROT 18 /* data protection/rights/alignment <7100 */ +#define T_DBREAK 19 /* data break */ +#define T_TLB_DIRTY 20 /* TLB dirty bit */ +#define T_PAGEREF 21 /* page reference */ +#define T_EMULATION 22 /* assist emulation */ +#define T_HIGHERPL 23 /* higher-privelege transfer */ +#define T_LOWERPL 24 /* lower-privilege transfer */ +#define T_TAKENBR 25 /* taken branch */ +#define T_DATACC 26 /* data access rights >=7100 */ +#define T_DATAPID 27 /* data protection ID >=7100 */ +#define T_DATALIGN 28 /* unaligned data ref */ +#define T_PERFMON 29 /* performance monitor interrupt */ +#define T_IDEBUG 30 /* debug SFU interrupt */ +#define T_DDEBUG 31 /* debug SFU interrupt */ + +/* + * Reserved range for traps is 0-63, place user flag at 6th bit + */ +#define T_USER_POS 57 +#define T_USER (1 << (63 - T_USER_POS)) + +/* + * Various trap frame flags. + */ +#define TFF_LAST_POS 40 +#define TFF_SYS_POS 41 +#define TFF_INTR_POS 42 + +#define TFF_LAST (1 << (63 - TFF_LAST_POS)) +#define TFF_SYS (1 << (63 - TFF_SYS_POS)) +#define TFF_INTR (1 << (63 - TFF_INTR_POS)) + +/* + * Define this for pretty printings of trapflags. + */ +#define T_BITS "\020\07user\036intr\037itlb\040last" + +/* + * These are break instruction entry points. + */ +/* im5 */ +#define HPPA_BREAK_KERNEL 0 +/* im13 */ +#define HPPA_BREAK_KGDB 5 +#define HPPA_BREAK_GET_PSW 9 +#define HPPA_BREAK_SET_PSW 10 + +#endif /* _MACHINE_TRAP_H_ */ diff --git a/sys/arch/hppa64/include/types.h b/sys/arch/hppa64/include/types.h new file mode 100644 index 00000000000..b098db4f83c --- /dev/null +++ b/sys/arch/hppa64/include/types.h @@ -0,0 +1,81 @@ +/* $OpenBSD: types.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + */ + +#ifndef _MACHINE_TYPES_H_ +#define _MACHINE_TYPES_H_ + +#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +typedef struct label_t { + int lbl_rp; + int lbl_sp; + int lbl_s[17]; + int lbl_ss[1]; + double lbl_sf[10]; /* hp800:fr12-fr15, hp700:fr12-fr21 */ +} label_t; + +typedef unsigned long hppa_hpa_t; +typedef unsigned long hppa_spa_t; +typedef unsigned int pa_space_t; +typedef unsigned long vaddr_t; +typedef unsigned long vsize_t; +typedef unsigned long paddr_t; +typedef unsigned long psize_t; +#endif + +/* + * Basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ +#define __BIT_TYPES_DEFINED__ +typedef __signed char int8_t; +typedef unsigned char u_int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short u_int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int u_int32_t; +typedef unsigned int uint32_t; +typedef long int64_t; +typedef unsigned long u_int64_t; +typedef unsigned long uint64_t; + +typedef int64_t register_t; + +typedef long int __intptr_t; +typedef unsigned long int __uintptr_t; + +#define __HAVE_DEVICE_REGISTER +#define __HAVE_CPUINFO + +#endif /* _MACHINE_TYPES_H_ */ diff --git a/sys/arch/hppa64/include/varargs.h b/sys/arch/hppa64/include/varargs.h new file mode 100644 index 00000000000..f0ddb6d4709 --- /dev/null +++ b/sys/arch/hppa64/include/varargs.h @@ -0,0 +1,17 @@ +/* $OpenBSD: varargs.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +#ifndef _MACHINE_VARARGS_H_ +#define _MACHINE_VARARGS_H_ + +#include <machine/stdarg.h> + +#define __va_ellipsis ... + +#define va_alist __builtin_va_alist +#define va_dcl long __builtin_va_alist; __va_ellipsis + +#undef va_start +#define va_start(ap) \ + ((ap) = (va_list)&__builtin_va_alist) + +#endif /* !_MACHINE_VARARGS_H */ diff --git a/sys/arch/hppa64/include/vmparam.h b/sys/arch/hppa64/include/vmparam.h new file mode 100644 index 00000000000..88e16e672b4 --- /dev/null +++ b/sys/arch/hppa64/include/vmparam.h @@ -0,0 +1,105 @@ +/* $OpenBSD: vmparam.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 1988-1994, The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Utah $Hdr: vmparam.h 1.16 94/12/16$ + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +/* + * Machine dependent constants for HP PA + */ +/* + * USRTEXT is the start of the user text/data space, while USRSTACK + * is the bottm (start) of the user stack. + */ +#define USRTEXT PAGE_SIZE /* Start of user .text */ +#define USRSTACK 0x68FF3000 /* Start of user stack */ +#define SYSCALLGATE 0xC0000000 /* syscall gateway page */ + +/* + * Virtual memory related constants, all in bytes + */ +#ifndef MAXTSIZ +#define MAXTSIZ (64*1024*1024) /* max text size */ +#endif +#ifndef DFLDSIZ +#define DFLDSIZ (16*1024*1024) /* initial data size limit */ +#endif +#ifndef MAXDSIZ +#define MAXDSIZ (1*1024*1024*1024) /* max data size */ +#endif +#ifndef DFLSSIZ +#define DFLSSIZ (512*1024) /* initial stack size limit */ +#endif +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#ifndef USRIOSIZE +#define USRIOSIZE ((2*HPPA_PGALIAS)/PAGE_SIZE) /* 2mb */ +#endif + +/* + * PTEs for system V style shared memory. + * This is basically slop for kmempt which we actually allocate (malloc) from. + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 /* 32mb */ +#endif + +#define VM_MIN_ADDRESS (0UL) +#define VM_MAXUSER_ADDRESS (0x20000000000UL) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#define VM_MIN_KERNEL_ADDRESS (0x1000000000UL) +#define VM_MAX_KERNEL_ADDRESS (0x10f0000000UL) + +/* virtual sizes (bytes) for various kernel submaps */ +#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE) + +#define VM_PHYSSEG_MAX 8 /* this many physmem segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST + +#define VM_PHYSSEG_NOADD /* XXX until uvm code is fixed */ + +#define VM_NFREELIST 2 +#define VM_FREELIST_DEFAULT 0 +#define VM_FREELIST_ARCH 1 + +#if defined(_KERNEL) && !defined(_LOCORE) +#define __HAVE_VM_PAGE_MD +struct pv_entry; +struct vm_page_md { + struct simplelock pvh_lock; /* locks every pv on this list */ + struct pv_entry *pvh_list; /* head of list (locked by pvh_lock) */ + u_int pvh_attrs; /* to preserve ref/mod */ +}; + +#define VM_MDPAGE_INIT(pg) do { \ + simple_lock_init(&(pg)->mdpage.pvh_lock); \ + (pg)->mdpage.pvh_list = NULL; \ + (pg)->mdpage.pvh_attrs = 0; \ +} while (0) +#endif + +#endif /* _MACHINE_VMPARAM_H_ */ diff --git a/sys/arch/hppa64/stand/Makefile b/sys/arch/hppa64/stand/Makefile new file mode 100644 index 00000000000..296da014aa6 --- /dev/null +++ b/sys/arch/hppa64/stand/Makefile @@ -0,0 +1,11 @@ +# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $ + +.if ${MACHINE} == "hppa64" +SUBDIR= libsa libkern libz +.endif +SUBDIR+= mkboot boot +.if ${MACHINE} == "hppa64" +#SUBDIR+= cdboot +.endif + +.include <bsd.subdir.mk> diff --git a/sys/arch/hppa64/stand/Makefile.inc b/sys/arch/hppa64/stand/Makefile.inc new file mode 100644 index 00000000000..2f7a45dcf73 --- /dev/null +++ b/sys/arch/hppa64/stand/Makefile.inc @@ -0,0 +1,44 @@ +# $OpenBSD: Makefile.inc,v 1.1 2005/04/01 10:40:48 mickey Exp $ + +CFLAGS=${DEBUG} -Os -Wall -Werror +CPPFLAGS+=-I${S} -I. -I${.CURDIR} -Derrno=errno +SACFLAGS=-nostdinc -fno-builtin -D_STANDALONE -I${STANDIR}/libsa +SACFLAGS+=-mdisable-fpregs -fno-stack-protector +#DEBUGFLAGS=-DDEBUG +#DEBUGFLAGS+=-DPDCDEBUG +#DEBUGFLAGS+=-DLIFDEBUG +#DEBUGFLAGS+=-DEXEC_DEBUG +#DEBUGFLAGS+=-DALLOC_TRACE +LINKADDR=0x780000 +LOADADDR=0x780000 +HEAP_LIMIT=0x7f8000 +CLEANFILES+= machine +DEBUGLIBS= no + +.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(kernlibdir) && !make(obj) && !(defined(PROG) && ${PROG} == "mkboot") +.BEGIN: + @([ -h machine ] || ln -s $(S)/arch/hppa64/include machine) +.endif + +.if exists(${STANDIR}/libsa/libsa.a) +LIBSA=${STANDIR}/libsa/libsa.a +.else +LIBSA=${STANDIR}/libsa/${__objdir}/libsa.a +.endif +.if exists(${STANDIR}/libkern/libkern.a) +LIBKERN=${STANDIR}/libkern/libkern.a +.else +LIBKERN=${STANDIR}/libkern/${__objdir}/libkern.a +.endif +.if exists(${STANDIR}/libz/libz.a) +LIBZ=${STANDIR}/libz/libz.a +.else +LIBZ=${STANDIR}/libz/${__objdir}/libz.a +.endif +.if exists(${STANDIR}/mkboot/mkboot) +MKBOOT=${STANDIR}/mkboot/mkboot +.else +MKBOOT=${STANDIR}/mkboot/${__objdir}/mkboot +.endif + +BINDIR= /usr/mdec diff --git a/sys/arch/hppa64/stand/boot/Makefile b/sys/arch/hppa64/stand/boot/Makefile new file mode 100644 index 00000000000..dd9bc44c62f --- /dev/null +++ b/sys/arch/hppa64/stand/boot/Makefile @@ -0,0 +1,60 @@ +# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $ + +MAN= boot.8 +MANSUBDIR=hppa64 +MLINKS= boot.8 boot.conf.8 +S =${.CURDIR}/../../../.. +CLEANFILES+= boot.gdb boot.map boot.lif + +.if ${MACHINE} == "hppa64" +PROG= boot +SRCS= srt0.S exec.c boot.c cmd.c vars.c bootarg.c conf.c +LD?= ld +LDFLAGS+=-Bstatic -nostartfiles -nostdlib -N -Ttext $(LINKADDR) +LDFLAGS+=-T ${.CURDIR}/ld.script -Map boot.map +LDFLAGS+=--warn-constructors --warn-common +SIZE?= size +STRIP?= strip +STANDIR=${.CURDIR}/.. +CRTBEGIN= +CRTEND= +LINKS= ${BINDIR}/boot.lif ${BINDIR}/sdboot \ + ${BINDIR}/boot.lif ${BINDIR}/stboot \ + ${BINDIR}/boot.lif ${BINDIR}/xxboot + +LDADD= ${LIBSA} ${LIBZ} ${LIBKERN} +DPADD= ${LIBSA} ${LIBZ} ${LIBKERN} + +.PATH: ${S}/stand/boot + +all: boot.lif + +realinstall: + ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + boot ${DESTDIR}${BINDIR} + ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + boot.lif ${DESTDIR}${BINDIR} + +.if exists(${.CURDIR}/../../compile/GENERIC/bsd) +bsd: ${.CURDIR}/../../compile/GENERIC/bsd + gzip -9 -c ${.CURDIR}/../../compile/GENERIC/bsd > bsd +ADDBOOT+=bsd +.endif + +# probably we should check for 256k limit for ISL +boot.lif: ${PROG} ${ADDBOOT} + -@cp ${PROG} ${PROG}.gdb + ${STRIP} ${PROG} + ${MKBOOT} -v ${PROG} ${ADDBOOT} boot.lif + +${PROG}: $(OBJS) $(DPADD) + $(LD) $(LDFLAGS) -o $(PROG) $(OBJS) $(LDADD) + @${SIZE} $(PROG) +.else +NOPROG= +.endif + +.include <bsd.prog.mk> + +CPPFLAGS+=${DEBUGFLAGS} -DRELOC=${LOADADDR} -DHEAP_LIMIT=${HEAP_LIMIT} +CFLAGS+=$(SACFLAGS) diff --git a/sys/arch/hppa64/stand/boot/boot.8 b/sys/arch/hppa64/stand/boot/boot.8 new file mode 100644 index 00000000000..4b52dabbe02 --- /dev/null +++ b/sys/arch/hppa64/stand/boot/boot.8 @@ -0,0 +1,342 @@ +.\" $OpenBSD: boot.8,v 1.1 2005/04/01 10:40:48 mickey Exp $ +.\" +.\" Copyright (c) 2002 Miodrag Vallat +.\" Copyright (c) 1997-2005 Michael Shalayeff +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, +.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +.\" SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +.\" THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" +.Dd March 16, 2005 +.Dt BOOT 8 hppa +.Os +.Sh NAME +.Nm boot , +.Nm boot.conf +.Nd +hppa-specific bootstrap +.Sh DESCRIPTION +The main purpose of this program is to load the system kernel while dealing +with the various features of the PA-RISC hardware. +.Pp +As described in +.Xr boot_hppa 8 , +this program is loaded by the PDC firmware +and provides a convenient way to load the kernel. +.Pp +Basic operations include: +.Pp +.Bl -bullet -compact +.It +Loading kernels from any device supported by your system. +.It +Loading kernels compressed by +.Xr gzip 1 . +.It +Providing an interactive command line. +.It +Detecting and switching between multiple consoles. +.El +.Pp +The sequence of its operation is as follows: initialization, +parsing the configuration file, then an interactive command line. +While at the command line you have 5 seconds to type any commands, if needed. +If time expires, the kernel will be loaded according to +the current variable settings (see the +.Nm set +command). +Each time a kernel load fails, the timeout is increased by one second. +The sequence of +.Nm +operations is as follows: +.Bl -enum +.It +If the file +.Pa /etc/boot.conf +exists on the filesystem or LIF image +.Nm +was loaded from, open and parse it. +This file may contain any commands +.Nm +accepts at the interactive prompt. +Though default settings usually suffice, they can be changed here. +.It +The header line +.Pp +.Dl >> OpenBSD/hppa BOOT [x.xx] +.Pp +is displayed to the active console, where +.Ar x.xx +is the version number of the +.Nm +program, followed by the +.Pp +.Dl boot> +.Pp +prompt, which means you are in interactive mode and may enter commands. +If you do not, +.Nm +will proceed to load the kernel with the current parameters after the +timeout period has expired. +.El +.Pp +By default, +.Nm +attempts to load the kernel executable +.Pa /bsd . +If that fails, it will attempt to load +.Pa /obsd +and then +.Pa /bsd.old . +If it fails to find any of these files, +and no alternative kernel image has been specified, +the system will be unable to boot. +.Sh COMMANDS +The following commands are accepted at the +.Nm +prompt: +.Bl -tag -width shorten +.It boot Op Ar image Op Fl acds +Boots the kernel image specified by +.Ar image +with any options given. +Image specification consists of a pair +.Ar device : Ns Ar filename ; +either or both can be omitted (`:' is not needed if both are omitted), +in which case values from +.Nm +variables will be used. +.Bl -tag -width _a_ +.It Fl a +Causes the kernel to ask for the +.Nm root +device to use. +.It Fl c +Causes the kernel to go into +.Xr boot_config 8 +before performing +.Xr autoconf 4 +procedures. +.It Fl d +Causes the kernel to drop into +.Xr ddb 4 +at the earliest convenient point. +.It Fl s +Causes the kernel to boot single-user. +.El +.It echo Op Ar args +Displays +.Ar args +on the console device. +.It help +Prints a list of available commands and machine dependent +commands, if any. +.It machine Op Ar command +Issues machine-dependent commands. +These are defined for hppa architecture: +.Bl -tag -width keyboard +.It Nm console +Displays or sets the console path. +.Pp +When invoked with no argument, this command will display the configured +console path found in the stable storage area. +.Pp +Otherwise, the argument will be interpreted as a console path +definition string, and +.Nm +will attempt to switch the console configuration to the desired device. +The console definition attempts to follow the PDC syntax, +and would have a form of: +.Pp +.Bd -filled -compact +graphics +.Op _head +.Op .mode +.Ed +for graphics console, and +.Pp +.Bd -filled -compact +rs232 +.Op _2 +.Op .speed Op .bits Op .parity +.Ed +for serial console. +.Pp +The default head and mode for graphics console are 0, that is the default +videomode of the first graphics device. +The default serial settings are 9600 bps, 8 data bits, and no parity. +.It Nm keyboard +Displays or sets the keyboard path. +.Pp +When invoked with no argument, this command will display the configured +keyboard path found in the stable storage area. +.Pp +Otherwise, the argument will be interpreted as a keyboard path definition +string, and +.Nm +will attempt to switch the keyboard configuration to the desired port. +The keyboard definition attempts to follow the PDC syntax, +and would have a form of: +.Pp +.Bd -filled -compact +hil +.Ed +for hil keyboard, and +.Pp +.Bd -filled -compact +ps2 +.Ed +for PS/2 keyboard. +.El +.Pp +After changing any path settings, the machine usually has to be restarted for +the changes to have effect. +.It ls Op Ar directory +Prints contents of the specified +.Ar directory +in long format including: attributes and file type, owner, group, +size, filename. +.It reboot +Reboots the machine by initiating a warm boot procedure. +.It set Op Ar varname Op Ar value +If invoked without arguments, prints a list of variables and their values. +If only +.Ar varname +is specified, displays contents of that variable. +If +.Ar varname +and +.Ar value +are both specified, sets that variable to the given value. +Variables include: +.Pp +.Bl -tag -compact -width boothow +.It Nm addr +Address at which to load the kernel. +.It Nm debug +Debug flag if +.Nm +was compiled with DEBUG defined. +.It Nm device +Boot device name (i.e., +.Li lf0a , +.Li sd0a ) . +.It Nm howto +Options to pass to the loaded kernel. +.It Nm image +File name containing the kernel image. +.It Nm timeout +Number of seconds boot will wait for human intervention before +booting the default kernel image. +.\" .It Nm tty +.\" Active console device name (i.e., +.\" .Li ttya , +.\" .Li ttyb , +.\" .Li ite0) . +.El +.\" .It stty Op Ar device Op Ar speed +.\" Displays or sets the +.\" .Ar speed +.\" for a console +.\" .Ar device . +.\" If changing the baudrate for the currently active console, +.\" .Nm +.\" offers you five seconds of grace time before committing the change +.\" to allow you to change your terminal's speed to match. +.\" If changing speed +.\" .Em not +.\" for the active console, the baudrate is set for the +.\" .Em next +.\" time you switch to a serial console. +.\" The baudrate value is not used for the +.\" .Li ite0 +.\" console. +.\" .Pp +.\" The default baudrate is 9600bps. +.It time +Displays system time and date. +.El +.Sh FILES +.Bl -tag -width /etc/boot.conf -compact +.It Pa /boot +system bootstrap +.It Pa /etc/boot.conf +system bootstrap's startup file +.It Pa /bsd +kernel image +.El +.Sh EXAMPLES +Boot the default kernel: +.Pp +.Dl boot> boot +.Pp +Remove the 5 second pause at boot-time permanently, causing +.Nm +to load the kernel immediately without prompting: +.Pp +.Dl # echo \&"boot\&" > /etc/boot.conf +.Pp +Use serial console on the first serial port, with the usual 9600 8N1 settings. +A null modem cable should connect the specified serial port to a terminal. +Useful for debugging. +.Pp +.Dl boot> machine console rs232.9600.8.none +.Pp +Boot the kernel named +.Pa /bsd +from the second SCSI disk in +.Dq User Kernel Configuration +mode (see +.Xr boot_config 8 ) . +This mechanism allows for the explicit enabling and disabling of devices +during the current boot sequence, as well as the modification +of device parameters. +Once booted, such changes can be made permanent by using +.Xr config 8 Ns 's +.Fl e +option. +.Pp +.Dl boot> boot sd1a:/bsd -c +.Sh SEE ALSO +.Xr gzip 1 , +.Xr autoconf 4 , +.Xr ddb 4 , +.Xr boot_config 8 , +.Xr boot_hppa 8 , +.\" .Xr installboot 8 , +.Xr reboot 8 +.Pp +RFC 1950 describes the zlib library interface. +.Pp +The official home page for the version of zlib used in this +operating system see http://quest.jpl.nasa.gov/zlib/. +.Sh HISTORY +This program was written by Michael Shalayeff for +.Ox 2.1 . +The hppa specific parts were written by Michael Shalayeff and Miodrag Vallat +for +.Ox 3.1 . +.Sh CAVEATS +Making mistakes in console paths may cost you a toupee. +.Sh BUGS +Changing the display resolution (mode) on a graphics console does not work +correctly. diff --git a/sys/arch/hppa64/stand/boot/conf.c b/sys/arch/hppa64/stand/boot/conf.c new file mode 100644 index 00000000000..91ecd77b2b1 --- /dev/null +++ b/sys/arch/hppa64/stand/boot/conf.c @@ -0,0 +1,51 @@ +/* $OpenBSD: conf.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <libsa.h> +#include <lib/libsa/ufs.h> +#include <lib/libsa/cd9660.h> +#include <dev/cons.h> + +const char version[] = "0.8"; +int debug = 0; + +struct fs_ops file_system[] = { + { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, + ufs_stat, ufs_readdir }, + { cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek, + cd9660_stat, cd9660_readdir }, + { lif_open, lif_close, lif_read, lif_write, lif_seek, + lif_stat, lif_readdir }, +}; +int nfsys = NENTS(file_system); + +struct devsw devsw[] = { + { "dk", iodcstrategy, dkopen, dkclose, noioctl }, + { "ct", iodcstrategy, ctopen, ctclose, noioctl }, + { "lf", iodcstrategy, lfopen, lfclose, noioctl } +}; +int ndevs = NENTS(devsw); + +struct consdev constab[] = { + { ite_probe, ite_init, ite_getc, ite_putc }, + { NULL } +}; +struct consdev *cn_tab; + diff --git a/sys/arch/hppa64/stand/boot/exec.c b/sys/arch/hppa64/stand/boot/exec.c new file mode 100644 index 00000000000..adc206b3a19 --- /dev/null +++ b/sys/arch/hppa64/stand/boot/exec.c @@ -0,0 +1,42 @@ +/* $OpenBSD: exec.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <machine/pdc.h> +#include "libsa.h" +#include <lib/libsa/loadfile.h> +#include <stand/boot/bootarg.h> +#include "dev_hppa64.h" + +typedef void (*startfuncp)(int, int, int, int, int, int, caddr_t) + __attribute__ ((noreturn)); + +void +run_loadfile(u_long *marks, int howto) +{ + fcacheall(); + + __asm("mtctl %r0, %cr17"); + __asm("mtctl %r0, %cr17"); + /* stack and the gung is ok at this point, so, no need for asm setup */ + (*(startfuncp)(marks[MARK_ENTRY]))((int)(long)(long)pdc, howto, bootdev, + marks[MARK_END], BOOTARG_APIVER, BOOTARG_LEN, (caddr_t)BOOTARG_OFF); + + /* not reached */ +} diff --git a/sys/arch/hppa64/stand/boot/ld.script b/sys/arch/hppa64/stand/boot/ld.script new file mode 100644 index 00000000000..51aed14df19 --- /dev/null +++ b/sys/arch/hppa64/stand/boot/ld.script @@ -0,0 +1,61 @@ +/* $OpenBSD: ld.script,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +OUTPUT_FORMAT("elf64-hppa") +OUTPUT_ARCH(hppa2.0w) +ENTRY(begin) + +SECTIONS { + + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .text : { + *(.text) + *(.text.*) + *(.rodata) + *(.rodata1) + *($CODE$) + etext = .; + } = 0x08000240 + + /* Read-write sections, merged into data segment: */ + .data : { + $global$ = .; + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + edata = ABSOLUTE(.); + } = 0 + + .opd : { *(.opd) } + PROVIDE(__gp = .); + .plt : { *(.plt) } + .dlt : { *(.dlt) } + + .bss : { + __bss_start = .; + *(.dynbss) + *(.bss) + *(.sbss) + *(.scommon) + *(COMMON) + end = ABSOLUTE(.); + __bss_end = .; + } + + /* don't need an unwind in the boot, unless we'll have a boot-ddb (; */ + /DISCARD/ : + { + *(.PARISC.unwind) + *(.exitcall.exit) + *(.interp) + *(.dynsym) + *(.dynstr) + *(.dynamic) + *(.hash) + *(.stub) + } +} + diff --git a/sys/arch/hppa64/stand/boot/srt0.S b/sys/arch/hppa64/stand/boot/srt0.S new file mode 100644 index 00000000000..99498dbf970 --- /dev/null +++ b/sys/arch/hppa64/stand/boot/srt0.S @@ -0,0 +1,181 @@ +/* $OpenBSD: srt0.S,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +; +; Copyright (c) 1990 mt Xinu, Inc. All rights reserved. +; Copyright (c) 1990 University of Utah. All rights reserved. +; +; This file may be freely distributed in any form as long as +; this copyright notice is included. +; THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +; IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +; WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +; +; Utah $Hdr: srt0.c 1.3 94/12/13$ +; + +#define _LOCORE +#include <machine/iomod.h> +#include <machine/asm.h> +#include <machine/frame.h> + +/* + * This is the ending of the begin + */ +ENTRY(begin,0) + + blr %r0,%r5 ; Get address of 'boff' into 'r5', + ldo begin-boff(%r5),%r5 ; and subtract to get 'begin'. +boff + ldil L%RELOC,%r4 + ldo R%RELOC(%r4),%r4 + ldo start-begin(%r4),%rp + ldil L%edata,%r3 + ldo R%edata(%r3),%r3 ; Get address of edata. + ldil L%begin,%r1 + ldo R%begin(%r1),%r1 ; Get address of begin + sub %r3,%r1,%r3 ; Subtract to get # of bytes to copy +copyloop ; do + ldwm 4(%r5),%r1 ; *r4++ = *r5++; + addib,>= -4,%r3,copyloop ; while (--r3 >= 0); + stwm %r1,4(%r4) + + ; here we zero the .bss + ldil L%__bss_start, %r4 + ldo R%__bss_start(%r4), %r4 + ldil L%__bss_end, %r3 + ldo R%__bss_end(%r3), %r3 +zeroloop + combf,<,n %r3,%r4, zeroloop ; while (r4 < r3); + stwm %r0,4(%r4) ; *r4++ = 0; + + ldil L%$global$,%dp + ldo R%$global$(%dp),%dp + ldil L%start,%r1 + ldo R%start(%r1),%r1 + sub %dp,%r1,%dp ; Subtract to get difference + add %rp,%dp,%dp ; and relocate it. + +; +; We have relocated ourself to RELOC. If we are running on a machine +; with separate instruction and data caches, we must flush our data +; cache before trying to execute the code starting at rp. +; + ldil L%RELOC,%r22 ; Set %t1 to start of relocated code. + ldo R%RELOC(%r22),%r22 + ldil L%edata,%r21 ; Set r21 to address of edata + ldo R%edata(%r21),%r21 + ldil L%begin,%r1 ; set %r1 to address of begin + ldo R%begin(%r1),%r1 + sub %r21,%r1,%r21 ; Subtract to get length + mtsp %r0,%sr0 ; Set sr0 to kernel space. + ldo -1(%r21),%r21 + fdc %r21(0,%r22) +loop addib,>,n -16,%r21,loop ; Decrement by cache line size (16). + fdc %r21(%sr0,%r22) + fdc 0(%sr0,%r22) ; Flush first word at addr to handle + sync ; arbitrary cache line boundary. + nop ; Prevent prefetching. + nop + nop + nop + nop + nop + nop + bv 0(%rp) + nop +EXIT(begin) /* jump to relocated code */ + +start + ldil L%HEAP_LIMIT, %sp + ldo R%HEAP_LIMIT(%sp), %sp + + .import bootprompt, data + ldil L%bootprompt, %r1 + stw %arg0, R%bootprompt(%r1) + b boot ; Call boot(), + copy %r0, %arg0 ; use default boot device + nop + +/* + * rtt - restart the box + */ +LEAF_ENTRY(_rtt) + ldil L%LBCAST_ADDR, %arg1 + ldi CMD_RESET, %arg0 + stw %arg0, R%iomod_command(%arg1) +forever ; Loop until bus reset takes effect. + b,n forever + + bv 0(%rp) + ldo -48(%sp),%sp +EXIT(_rtt) + +ENTRY(pdc_call,96) + copy %r3, %r1 + std %rp, HPPA_FRAME_RP(%sp) + copy %sp, %r3 + std,ma %r1, HPPA_FRAME_SIZE+8*4(%sp) + + copy %arg0, %r1 + copy %arg1, %arg0 + copy %arg2, %arg1 + copy %arg3, %arg2 + copy arg4, %arg3 + stw arg5, -(32 + 4*(4 + 1))(%sp) + stw arg6, -(32 + 4*(5 + 1))(%sp) + stw arg7, -(32 + 4*(6 + 1))(%sp) + ldw 0(ap), arg5 + ldw 8(ap), arg6 + ldw 16(ap), arg7 + stw arg5, -(32 + 4*(7 + 1))(%sp) + stw arg6, -(32 + 4*(8 + 1))(%sp) + stw arg7, -(32 + 4*(9 + 1))(%sp) + + .call + blr %r0, %rp + bv,n %r0(%r1) + nop + + ldd HPPA_FRAME_RP(%r3), %rp + bv %r0(%rp) + ldd,mb -(HPPA_FRAME_SIZE+8*4)(%sp), %r3 +EXIT(pdc_call) + + .end diff --git a/sys/arch/hppa64/stand/cdboot/Makefile b/sys/arch/hppa64/stand/cdboot/Makefile new file mode 100644 index 00000000000..6ff9c00821a --- /dev/null +++ b/sys/arch/hppa64/stand/cdboot/Makefile @@ -0,0 +1,55 @@ +# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $ + +NOMAN= no man +S =${.CURDIR}/../../../.. +CLEANFILES+= cdboot.gdb cdboot.map + +.if ${MACHINE} == "hppa64" + +PROG= cdboot +SRCS= srt0.S cdboot.c pdc.c itecons.c dev_hppa64.c dk.c +LD?= ld +LDFLAGS+=-Bstatic -nostartfiles -nostdlib -N -Ttext $(LINKADDR) +LDFLAGS+=-T ${.CURDIR}/ld.script -Map cdboot.map +SIZE?= size +STRIP?= strip +STANDIR=${.CURDIR}/.. +CRTBEGIN= +CRTEND= + +SAREL= +USE_LOADFILE=yes +.include "${S}/lib/libsa/Makefile.inc" +DPADD+= $(SALIB) $(LIBKERN) +LDADD+= $(SALIB) $(LIBKERN) + +.PATH: ${S}/stand/boot +.PATH: ${.CURDIR}/../boot +.PATH: ${.CURDIR}/../libsa + +all: ${PROG} + +clean:: + rm -f a.out [Ee]rrs mklog core *.core \ + ${PROG} ${OBJS} ${LOBJS} ${CLEANFILES} + +realinstall: + ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${PROG} ${DESTDIR}${BINDIR} + +# TODO check for <=32k +${PROG}: $(OBJS) $(DPADD) + $(LD) $(LDFLAGS) -o $(PROG) $(OBJS) $(LDADD) + @cp ${PROG} ${PROG}.gdb + ${STRIP} ${PROG} + @${SIZE} $(PROG) + @${MKBOOT} -v ${PROG} ${PROG}.lif + @mv ${PROG}.lif ${PROG} +.else +NOPROG= +.endif + +.include <bsd.prog.mk> + +CPPFLAGS+=-DRELOC=${LOADADDR} -DHEAP_LIMIT=${HEAP_LIMIT} +CFLAGS+=$(SACFLAGS) -I../.. -I${.CURDIR}/../libsa -I${S}/stand/boot diff --git a/sys/arch/hppa64/stand/cdboot/cdboot.c b/sys/arch/hppa64/stand/cdboot/cdboot.c new file mode 100644 index 00000000000..2ceb33315df --- /dev/null +++ b/sys/arch/hppa64/stand/cdboot/cdboot.c @@ -0,0 +1,82 @@ +/* $OpenBSD: cdboot.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/reboot.h> +#include <sys/stat.h> +#include <libsa.h> +#include <lib/libsa/cd9660.h> +#include <lib/libsa/loadfile.h> +#include <dev/cons.h> +#include <machine/pdc.h> +#include <stand/boot/bootarg.h> +#include "dev_hppa64.h" +#include "cmd.h" + +dev_t bootdev; +int debug = 1; +int bootprompt = 1; + +struct fs_ops file_system[] = { + { cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek, + cd9660_stat, cd9660_readdir }, +}; +int nfsys = NENTS(file_system); + +struct devsw devsw[] = { + { "dk", iodcstrategy, dkopen, dkclose, noioctl }, +}; +int ndevs = NENTS(devsw); + +struct consdev constab[] = { + { ite_probe, ite_init, ite_getc, ite_putc }, + { NULL } +}; +struct consdev *cn_tab; + +typedef void (*startfuncp)(int, int, int, int, int, int, caddr_t) + __attribute__ ((noreturn)); + +void +boot(dev_t dev) +{ + u_long marks[MARK_MAX]; + char path[128]; + + pdc_init(); + cninit(); + devboot(dev, path); + strncpy(path + strlen(path), ":/bsd.rd", 9); + printf(">> OpenBSD/" MACHINE " CDBOOT 0.1\n" + "booting %s: ", path); + + marks[MARK_START] = (u_long)DEFAULT_KERNEL_ADDRESS; + if (!loadfile(path, marks, LOAD_KERNEL)) { + marks[MARK_END] = ALIGN(marks[MARK_END] - + (u_long)DEFAULT_KERNEL_ADDRESS); + fcacheall(); + + __asm("mtctl %r0, %cr17"); + __asm("mtctl %r0, %cr17"); + (*(startfuncp)(marks[MARK_ENTRY]))((int)(long)pdc, 0, bootdev, + marks[MARK_END], BOOTARG_APIVER, BOOTARG_LEN, + (caddr_t)BOOTARG_OFF); + /* not reached */ + } +} diff --git a/sys/arch/hppa64/stand/cdboot/ld.script b/sys/arch/hppa64/stand/cdboot/ld.script new file mode 100644 index 00000000000..b36df9be9e4 --- /dev/null +++ b/sys/arch/hppa64/stand/cdboot/ld.script @@ -0,0 +1,49 @@ +/* $OpenBSD: ld.script,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +OUTPUT_FORMAT("elf64-hppa") +OUTPUT_ARCH(hppa2.0w) +ENTRY(begin) + +SECTIONS { + + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .text : { + *(.text) + *(.text.*) + *(.rodata) + *(.rodata1) + *($CODE$) + etext = .; + } = 0x08000240 + + /* Read-write sections, merged into data segment: */ + .data : { + $global$ = .; + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + edata = ABSOLUTE(.); + } = 0 + + .bss : { + __bss_start = .; + *(.dynbss) + *(.bss) + *(.sbss) + *(.scommon) + *(COMMON) + end = ABSOLUTE(.); + __bss_end = .; + } + + /* don't need an unwind in the boot, unless we'll have a boot-ddb (; */ + /DISCARD/ : + { + *(.PARISC.unwind) + } +} + diff --git a/sys/arch/hppa64/stand/libkern/Makefile b/sys/arch/hppa64/stand/libkern/Makefile new file mode 100644 index 00000000000..6815b67c49b --- /dev/null +++ b/sys/arch/hppa64/stand/libkern/Makefile @@ -0,0 +1,29 @@ +# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $ + +LIB= kern + +S= ${.CURDIR}/../../../.. +M= ${KERNDIR}/arch/${MACHINE_ARCH} +SADIR= ${.CURDIR}/.. +KERNDIR=$S/lib/libkern + +NOPIC= nopic +NOPROFILE= noprofile + +.PATH: ${KERNDIR} + +.include "arch/hppa64/Makefile.inc" + +# Quad support +SRCS+= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \ + lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \ + subdi3.c ucmpdi2.c udivdi3.c umoddi3.c xordi3.c + +# Other stuff +SRCS+= srandom.c bcd.c + +install: + +.include <bsd.lib.mk> +CPPFLAGS+= ${DEBUGFLAGS} +CFLAGS+= ${SACFLAGS} diff --git a/sys/arch/hppa64/stand/libsa/Makefile b/sys/arch/hppa64/stand/libsa/Makefile new file mode 100644 index 00000000000..eda10f3436e --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/Makefile @@ -0,0 +1,43 @@ +# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:48 mickey Exp $ + +.include "${.CURDIR}/../Makefile.inc" + +LIB= sa + +S=${.CURDIR}/../../../.. +SADIR=${.CURDIR}/.. +DIR_SA= $S/lib/libsa + +NOPROFILE=noprofile +NOPIC=nopic + +#AS=cat ; +#AS+= -R +#AS+= -a + +# hppa64 stuff +SRCS= machdep.c pdc.c itecons.c dev_hppa64.c time.c \ + ct.c dk.c lf.c lif.c cmd_hppa64.c + +# stand routines +SRCS+= alloc.c exit.c getfile.c gets.c globals.c \ + printf.c strerror.c strtol.c strchr.c ctime.c loadfile.c snprintf.c + +# io routines +SRCS+= close.c closeall.c dev.c disklabel.c dkcksum.c fstat.c ioctl.c lseek.c \ + open.c read.c stat.c write.c cread.c readdir.c cons.c + +# boot filesystems +SRCS+= ufs.c cd9660.c + +.PATH: ${DIR_SA} + +all: ${SALIB} + +install: + +.include <bsd.lib.mk> + +CPPFLAGS+=-DHEAP_LIMIT=${HEAP_LIMIT} ${DEBUGFLAGS} -DNO_NET +CPPFLAGS+=-I${S}/stand/boot +CFLAGS+=${SACFLAGS} -D__INTERNAL_LIBSA_CREAD -DCOMPAT_UFS diff --git a/sys/arch/hppa64/stand/libsa/cmd_hppa64.c b/sys/arch/hppa64/stand/libsa/cmd_hppa64.c new file mode 100644 index 00000000000..1aa6117cb07 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/cmd_hppa64.c @@ -0,0 +1,819 @@ +/* $OpenBSD: cmd_hppa64.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2002 Miodrag Vallat + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*#define DEBUG*/ + +#include <sys/param.h> +/* would come from <sys/param.h> if -D_KERNEL */ +#define offsetof(s, e) ((size_t)&((s *)0)->e) + +#include <machine/iomod.h> +#include <machine/pdc.h> + +#include <arch/hppa/dev/cpudevs.h> + +#include <libsa.h> +#include "cmd.h" +#include "dev_hppa64.h" /* pdc */ + +extern struct stable_storage sstor; +extern int sstorsiz; + +/* storage sizes we're interested in */ +#define CONSOLEOFFSET \ + offsetof(struct stable_storage, ss_console) +#define CONSOLESIZE \ + (offsetof(struct stable_storage, ss_console) + \ + sizeof(struct device_path)) + +#define KEYBOARDOFFSET \ + offsetof(struct stable_storage, ss_keyboard) +#define KEYBOARDSIZE \ + (offsetof(struct stable_storage, ss_keyboard) + \ + sizeof(struct device_path)) + +/* + * Table for the possible console devices found during the device walk. + */ +struct consoledev { + struct device_path dp; + int type; + int iodc_type; + int iodc_model; +}; + +#define PS2 1 +#define HIL 2 +#define SERIAL 3 +#define GRAPHICS 4 + +/* max. serial ports */ +#define MAX_SERIALS 4 +/* max. HIL and PS2 */ +#define MAX_KEYBOARDS 2 +/* max. heads */ +#define MAX_GRAPHICS 4 + +struct consoledev serials[MAX_SERIALS]; +struct consoledev keyboards[MAX_KEYBOARDS]; +struct consoledev graphics[MAX_GRAPHICS]; + +/* Relaxed device comparison */ +#define MATCH(dev1, dev2) \ + (dev1).dp_mod == (dev2).dp_mod && \ + (dev1).dp_bc[0] == (dev2).dp_bc[0] && \ + (dev1).dp_bc[1] == (dev2).dp_bc[1] && \ + (dev1).dp_bc[2] == (dev2).dp_bc[2] && \ + (dev1).dp_bc[3] == (dev2).dp_bc[3] && \ + (dev1).dp_bc[4] == (dev2).dp_bc[4] && \ + (dev1).dp_bc[5] == (dev2).dp_bc[5] + +int walked; + +void bus_walk(struct device_path *); +void register_device(struct consoledev *, int, + struct device_path *, struct iodc_data *, int, int); + +int Xconsole(void); +void print_console(void); +int set_graphics(struct device_path *, int, char *); +int set_serial(struct device_path *, int, char *); +int set_console(struct device_path *); + +int Xkeyboard(void); +void print_keyboard(void); +int set_keyboard(struct device_path *); + +struct cmd_table cmd_machine[] = { + { "console", CMDT_CMD, Xconsole }, + { "keyboard", CMDT_CMD, Xkeyboard }, + { NULL, }, +}; + +/* value to console speed table */ +int i_speeds[] = { + 50, + 75, + 110, + 150, + 300, + 600, + 1200, + 2400, + 4800, + 7200, + 9600, + 19200, + 38400, + 57600, + 115200, + 230400, +}; + +char *c_speeds[] = { + "50", + "75", + "110", + "150", + "300", + "600", + "1200", + "2400", + "4800", + "7200", + "9600", + "19200", + "38400", + "57600", + "115200", + "230400", +}; + +/* values to console parity table */ +char *parities[] = { + "none", + "odd", + "<unknown parity>", + "even", +}; + +/* + * C O N S O L E S E T T I N G S + */ + +void +print_console() +{ + int port, mode, speed, parity, bits; + int i; + +#ifdef DEBUG + printf("console flags %x mod %x bc %d/%d/%d/%d/%d/%d\n", + sstor.ss_console.dp_flags, + sstor.ss_console.dp_mod, + sstor.ss_console.dp_bc[0], + sstor.ss_console.dp_bc[1], + sstor.ss_console.dp_bc[2], + sstor.ss_console.dp_bc[3], + sstor.ss_console.dp_bc[4], + sstor.ss_console.dp_bc[5]); + + printf("console path %x/%x/%x/%x/%x/%x\n", + sstor.ss_console.dp_layers[0], + sstor.ss_console.dp_layers[1], + sstor.ss_console.dp_layers[2], + sstor.ss_console.dp_layers[3], + sstor.ss_console.dp_layers[4], + sstor.ss_console.dp_layers[5]); +#endif + + printf("Console path: "); + + /* look for a serial console */ + for (port = i = 0; i < MAX_SERIALS; i++) + if (MATCH(serials[i].dp, sstor.ss_console)) { + port = i + 1; + break; + } + + if (port == 0) { + /* + * Graphics console + */ + + for (port = i = 0; i < MAX_GRAPHICS; i++) + if (MATCH(graphics[i].dp, sstor.ss_console)) { + port = i; + break; + } + + /* + * If the console could still not be identified, consider + * it is a simplified encoding for the default graphics + * console. Hence port == 0, no need to check. + */ + if (port == 0) + printf("graphics"); + else + printf("graphics_%d", port); + + mode = sstor.ss_console.dp_layers[0]; + if (mode != 0) + printf(".%d", mode); + } else { + /* + * Serial console + */ + + if (port == 1) + printf("rs232"); + else + printf("rs232_%d", port); + + speed = PZL_SPEED(sstor.ss_console.dp_layers[0]); + printf(".%d", i_speeds[speed]); + + bits = PZL_BITS(sstor.ss_console.dp_layers[0]); + printf(".%d", bits); + + parity = PZL_PARITY(sstor.ss_console.dp_layers[0]); + printf(".%s", parities[parity]); + } + + printf("\n"); +} + +int +set_graphics(console, port, arg) + struct device_path *console; + int port; + char *arg; +{ + int maxmode, mode = 0; + char *digit; + + /* head */ + if (graphics[port].type == 0) { + printf("no such device found\n"); + return 0; + } + + /* mode */ + if (arg != NULL) { + for (digit = arg; *digit != '\0'; digit++) { + if (*digit >= '0' && *digit <= '9') + mode = 10 * mode + (*digit - '0'); + else { + printf("invalid mode specification, %s\n", + arg); + return 0; + } + } + + if (mode <= 0) { + printf("invalid mode specification, %s\n", + arg); + return 0; + } + } + + /* + * If we are just changing the mode of the same graphics + * console, check that our mode is in the valid range. + */ + if (MATCH(graphics[port].dp, sstor.ss_console)) { + maxmode = sstor.ss_console.dp_layers[1]; + + /* pick back same mode if unspecified */ + if (mode == 0) + mode = sstor.ss_console.dp_layers[0]; + + if (mode > maxmode) { + printf("invalid mode value, available range is 1-%d\n", + maxmode); + return 0; + } + } else { + if (mode == 0) + mode = 1; + maxmode = mode; + } + + *console = graphics[port].dp; + console->dp_layers[0] = mode; + console->dp_layers[1] = maxmode; + console->dp_layers[2] = console->dp_layers[3] = + console->dp_layers[4] = console->dp_layers[5] = 0; + + return 1; +} + +int +set_serial(console, port, arg) + struct device_path *console; + int port; + char *arg; +{ + char *dot; + int i; + int speed, parity, bits; + + /* port */ + port--; + if (serials[port].type == 0) { + printf("no such device found\n"); + return 0; + } + + /* speed */ + dot = strchr(arg, '.'); + if (dot != NULL) + *dot++ = '\0'; + + speed = 0; + if (arg == NULL || *arg == '\0') { + for (i = 0; i < NENTS(i_speeds); i++) + if (i_speeds[i] == 9600) { + speed = i; + break; + } + } else { + for (i = 0; i < NENTS(c_speeds); i++) + if (strcmp(arg, c_speeds[i]) == 0) { + speed = i; + break; + } + if (speed == 0) { + printf("invalid speed specification, %s\n", arg); + return 0; + } + } + + /* data bits */ + arg = dot; + dot = strchr(arg, '.'); + + if (arg == NULL || *arg == '\0') + bits = 8; + else { + if (dot == arg + 1) + bits = *arg - '0'; + else + bits = 0; + + if (bits < 5 || bits > 8) { + printf("invalid bits specification, %s\n", arg); + return 0; + } + } + if (dot != NULL) + *dot++ = '\0'; + + /* parity */ + arg = dot; + if (arg == NULL || *arg == '\0') + parity = 0; /* none */ + else { + parity = -1; + for (i = 0; i <= 3; i++) + if (strcmp(arg, parities[i]) == 0) { + parity = i; + break; + } + if (parity == 2) + parity = -1; /* unknown parity */ + } + if (parity < 0) { + printf("invalid parity specification, %s\n", arg); + return 0; + } + + *console = serials[port].dp; + console->dp_layers[0] = PZL_ENCODE(bits, parity, speed); + + return 1; +} + +int +set_console(console) + struct device_path *console; +{ + char *arg = cmd.argv[1], *dot; + int port; + + /* extract first word */ + dot = strchr(arg, '.'); + if (dot != NULL) + *dot++ = '\0'; + + /* + * Graphics console + */ + if (strcmp(arg, "graphics") == 0) + return set_graphics(console, 0, dot); + if (strncmp(arg, "graphics_", 9) == 0) { + port = arg[9] - '0'; + if (port > 0 && port < MAX_GRAPHICS) + return set_graphics(console, port, dot); + } + + /* + * Serial console + */ + if (strcmp(arg, "rs232") == 0) + return set_serial(console, 1, dot); + if (strncmp(arg, "rs232_", 6) == 0) { + port = arg[6] - '0'; + if (port > 0 && port <= MAX_SERIALS) + return set_serial(console, port, dot); + } + + printf("invalid device specification, %s\n", arg); + return 0; +} + +int +Xconsole() +{ + struct device_path console; + int rc; + + /* walk the device list if not already done */ + if (walked == 0) { + bus_walk(NULL); + walked++; + } + + if (sstorsiz < CONSOLESIZE) { + printf("no console information in stable storage\n"); + return 0; + } + + if (cmd.argc == 1) { + print_console(); + } else { + console = sstor.ss_console; + if (set_console(&console)) { + if (memcmp(&sstor.ss_console, &console, + sizeof console) != 0) { + sstor.ss_console = console; + + /* alea jacta est */ + rc = (*pdc)(PDC_STABLE, PDC_STABLE_WRITE, + CONSOLEOFFSET, &sstor.ss_console, + sizeof(sstor.ss_console)); + if (rc != 0) { + printf("failed to save console settings, error %d\n", + rc); + /* read sstor again for safety */ + (*pdc)(PDC_STABLE, PDC_STABLE_READ, + CONSOLEOFFSET, &sstor.ss_console, + sizeof(sstor.ss_console)); + } else + printf("you will need to power-cycle " + "your machine for the changes " + "to take effect.\n"); + } + print_console(); + } + } + + return 0; +} + +/* + * K E Y B O A R D S E T T I N G S + */ + +void +print_keyboard() +{ + int type; + int i; + +#ifdef DEBUG + printf("keyboard flags %x mod %x bc %d/%d/%d/%d/%d/%d\n", + sstor.ss_keyboard.dp_flags, + sstor.ss_keyboard.dp_mod, + sstor.ss_keyboard.dp_bc[0], + sstor.ss_keyboard.dp_bc[1], + sstor.ss_keyboard.dp_bc[2], + sstor.ss_keyboard.dp_bc[3], + sstor.ss_keyboard.dp_bc[4], + sstor.ss_keyboard.dp_bc[5]); + + printf("keyboard path %x/%x/%x/%x/%x/%x\n", + sstor.ss_keyboard.dp_layers[0], + sstor.ss_keyboard.dp_layers[1], + sstor.ss_keyboard.dp_layers[2], + sstor.ss_keyboard.dp_layers[3], + sstor.ss_keyboard.dp_layers[4], + sstor.ss_keyboard.dp_layers[5]); +#endif + + printf("Keyboard path: "); + + for (type = i = 0; i < MAX_KEYBOARDS; i++) + if (MATCH(keyboards[i].dp, sstor.ss_keyboard)) { + type = keyboards[i].type; + break; + } + + switch (type) { + case HIL: + printf("hil"); + break; + case PS2: + printf("ps2"); + break; + default: + printf("unknown"); + break; + } + + printf("\n"); +} + +int +set_keyboard(keyboard) + struct device_path *keyboard; +{ + int i; + char *arg = cmd.argv[1]; + int type; + + if (strcmp(arg, "hil") == 0) + type = HIL; + else if (strcmp(arg, "ps2") == 0) + type = PS2; + else { + printf("invalid device specification, %s\n", arg); + return 0; + } + + for (i = 0; i < MAX_KEYBOARDS; i++) + if (keyboards[i].type == type) { + *keyboard = keyboards[i].dp; + return 1; + } + + printf("no such device found\n"); + return 0; +} + +int +Xkeyboard() +{ + struct device_path keyboard; + int rc; + + /* walk the device list if not already done */ + if (walked == 0) { + bus_walk(NULL); + walked++; + } + + if (sstorsiz < KEYBOARDSIZE) { + printf("no keyboard information in stable storage\n"); + return 0; + } + + if (cmd.argc == 1) { + print_keyboard(); + } else { + keyboard = sstor.ss_keyboard; + if (set_keyboard(&keyboard)) { + if (memcmp(&sstor.ss_keyboard, &keyboard, + sizeof keyboard) != 0) { + sstor.ss_keyboard = keyboard; + + /* alea jacta est */ + rc = (*pdc)(PDC_STABLE, PDC_STABLE_WRITE, + KEYBOARDOFFSET, &sstor.ss_keyboard, + sizeof(sstor.ss_keyboard)); + if (rc != 0) { + printf("failed to save keyboard settings, error %d\n", + rc); + /* read sstor again for safety */ + (*pdc)(PDC_STABLE, PDC_STABLE_READ, + KEYBOARDOFFSET, &sstor.ss_keyboard, + sizeof(sstor.ss_keyboard)); + } else + printf("you will need to power-cycle " + "your machine for the changes " + "to take effect.\n"); + } + print_keyboard(); + } + } + + return 0; +} + +/* + * U T I L I T I E S + */ + +/* + * Bus walker. + * This routine will walk all the modules on a given bus, registering + * serial ports, keyboard and graphics devices as they are found. + */ +void +bus_walk(struct device_path *idp) +{ + struct device_path dp; + struct pdc_memmap memmap; + struct iodc_data mptr; + int err, i, kluge_ps2 = 0; /* kluge, see below */ + + for (i = 0; i < MAXMODBUS; i++) { + + if (idp) { + dp.dp_bc[0] = idp->dp_bc[1]; + dp.dp_bc[1] = idp->dp_bc[2]; + dp.dp_bc[2] = idp->dp_bc[3]; + dp.dp_bc[3] = idp->dp_bc[4]; + dp.dp_bc[4] = idp->dp_bc[5]; + dp.dp_bc[5] = idp->dp_mod; + } else { + dp.dp_bc[0] = dp.dp_bc[1] = dp.dp_bc[2] = + dp.dp_bc[3] = dp.dp_bc[4] = dp.dp_bc[5] = -1; + } + + dp.dp_mod = i; + if ((pdc)(PDC_MEMMAP, PDC_MEMMAP_HPA, &memmap, &dp) < 0 && + (pdc)(PDC_SYSMAP, PDC_SYSMAP_HPA, &memmap, &dp) < 0) + continue; + + if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, &pdcbuf, memmap.hpa, + IODC_DATA, &mptr, sizeof(mptr))) < 0) + continue; + +#ifdef DEBUG + printf("device %d/%d/%d/%d/%d/%d " + "flags %d mod %x type %x model %x\n", + dp.dp_bc[0], dp.dp_bc[1], dp.dp_bc[2], dp.dp_bc[3], + dp.dp_bc[4], dp.dp_bc[5], dp.dp_flags, dp.dp_mod, + mptr.iodc_type, mptr.iodc_sv_model); +#endif + /* + * If the device can be considered as a valid rs232, + * graphics console or keyboard, register it. + * + * Unfortunately, devices which should be considered as + * ``main'' aren't necessarily seen first. + * The rules we try to enforce here are as follows: + * - GIO PS/2 ports wins over any other PS/2 port. + * - the first GIO serial found wins over any other + * serial port. + * The second rule is a bit tricky to achieve, since on + * some machines (for example, 715/100XC), the two serial + * ports are not seen as attached to the same busses... + */ + switch (mptr.iodc_type) { + case HPPA_TYPE_BCPORT: + bus_walk(&dp); + break; + case HPPA_TYPE_BHA: + case HPPA_TYPE_BRIDGE: + /* if there was no phantomas here */ + if (dp.dp_bc[5] == -1) { + dp.dp_bc[0] = dp.dp_bc[1]; + dp.dp_bc[1] = dp.dp_bc[2]; + dp.dp_bc[2] = dp.dp_bc[3]; + dp.dp_bc[3] = dp.dp_bc[4]; + dp.dp_bc[4] = dp.dp_bc[5]; + dp.dp_bc[5] = dp.dp_mod; + dp.dp_mod = 0; + } + bus_walk(&dp); + break; + case HPPA_TYPE_ADIRECT: + switch (mptr.iodc_sv_model) { + case HPPA_ADIRECT_RS232: + register_device(serials, MAX_SERIALS, + &dp, &mptr, SERIAL, 0); + break; + case HPPA_ADIRECT_HIL: + register_device(keyboards, MAX_KEYBOARDS, + &dp, &mptr, HIL, 0); + break; + case HPPA_ADIRECT_PEACOCK: + case HPPA_ADIRECT_LEONARDO: + register_device(graphics, MAX_GRAPHICS, + &dp, &mptr, GRAPHICS, 0); + break; + } + break; + case HPPA_TYPE_FIO: + switch (mptr.iodc_sv_model) { + case HPPA_FIO_HIL: + register_device(keyboards, MAX_KEYBOARDS, + &dp, &mptr, HIL, 0); + break; + case HPPA_FIO_RS232: + register_device(serials, MAX_SERIALS, + &dp, &mptr, SERIAL, 0); + break; + case HPPA_FIO_DINOPCK: + register_device(keyboards, MAX_KEYBOARDS, + &dp, &mptr, PS2, 0); + break; + case HPPA_FIO_GPCIO: + /* + * KLUGE! At this point, there is no way to + * know if this port is the keyboard port or + * the mouse port. + * Let's assume the first port found is the + * keyboard, and ignore the others. + */ + if (kluge_ps2 != 0) + break; + register_device(keyboards, MAX_KEYBOARDS, + &dp, &mptr, PS2, 1); + kluge_ps2++; + break; + case HPPA_FIO_GRS232: + { + int j, first; + + /* + * If a GIO serial port is already registered, + * register as extra port... + */ + first = 1; + for (j = 0; j < MAX_SERIALS; j++) + if (serials[j].type == SERIAL && + serials[j].iodc_type == + HPPA_TYPE_FIO && + serials[j].iodc_model == + HPPA_FIO_GRS232) { + first = 0; + break; + } + + register_device(serials, MAX_SERIALS, + &dp, &mptr, SERIAL, first); + } + break; + case HPPA_FIO_SGC: + register_device(graphics, MAX_GRAPHICS, + &dp, &mptr, GRAPHICS, 0); + break; + case HPPA_FIO_GSGC: + register_device(graphics, MAX_GRAPHICS, + &dp, &mptr, GRAPHICS, 1); + break; + } + break; + } + } +} + +void +register_device(devlist, cnt, dp, mptr, type, first) + struct consoledev *devlist; + int cnt; + struct device_path *dp; + struct iodc_data *mptr; + int type; + int first; +{ + int i; + struct consoledev *dev; + + for (i = 0, dev = devlist; i < cnt; i++, dev++) + if (dev->type == 0) + break; + + if (i == cnt) { +#ifdef DEBUG + printf("can't register device, need more room!\n"); +#endif + return; + } + + /* + * If this is supposedly the main device, insert on top + */ + if (first != 0) { + memcpy(devlist + 1, devlist, + (cnt - 1) * sizeof(struct consoledev)); + dev = devlist; + } + + dev->dp = *dp; + dev->type = type; + dev->iodc_type = mptr->iodc_type; + dev->iodc_model = mptr->iodc_sv_model; + +#ifdef DEBUG + printf("(registered as type %d)\n", type); +#endif +} diff --git a/sys/arch/hppa64/stand/libsa/ct.c b/sys/arch/hppa64/stand/libsa/ct.c new file mode 100644 index 00000000000..44316e10b12 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/ct.c @@ -0,0 +1,71 @@ +/* $OpenBSD: ct.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "libsa.h" + +#include <sys/param.h> +#include <sys/disklabel.h> +#include <sys/reboot.h> + +#include <machine/pdc.h> +#include <machine/iomod.h> + +#include "dev_hppa64.h" + +int +ctopen(struct open_file *f, ...) +{ + struct hppa_dev *dp = f->f_devdata; + + if (!(dp->pz_dev = pdc_findev(-1, PCL_SEQU))) + return (ENXIO); + + return (0); +} + +/*ARGSUSED*/ +int +ctclose(f) + struct open_file *f; +{ + free (f->f_devdata, sizeof(struct hppa_dev)); + f->f_devdata = NULL; + return 0; +} diff --git a/sys/arch/hppa64/stand/libsa/dev_hppa64.c b/sys/arch/hppa64/stand/libsa/dev_hppa64.c new file mode 100644 index 00000000000..75eb87528e4 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/dev_hppa64.c @@ -0,0 +1,228 @@ +/* $OpenBSD: dev_hppa64.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "libsa.h" +#include <sys/param.h> +#include <sys/disklabel.h> +#include <sys/reboot.h> +#include <dev/cons.h> + +#include <machine/iomod.h> + +#include "dev_hppa64.h" + +extern int debug; + +const char cdevs[][4] = { + "ite", "", "", "", "", "", "", "", + "", "", "", "", "" +}; +const int ncdevs = NENTS(cdevs); + +const struct pdc_devs { + char name[3]; + int dev_type; +} pdc_devs[] = { + { "dk", 0 }, + { "ct", 1 }, + { "lf", 2 }, + { "", -1 }, + { "rd", -1 }, + { "sw", -1 }, + { "fl", -1 }, +}; + +/* pass dev_t to the open routines */ +int +devopen(f, fname, file) + struct open_file *f; + const char *fname; + char **file; +{ + struct hppa_dev *hpd; + const struct pdc_devs *dp = pdc_devs; + int rc = 1; + + if (!(*file = strchr(fname, ':'))) + return ENODEV; + else + (*file)++; + +#ifdef DEBUGBUG + if (debug) + printf("devopen: "); +#endif + + for (dp = pdc_devs; dp < &pdc_devs[NENTS(pdc_devs)]; dp++) + if (!strncmp(fname, dp->name, sizeof(dp->name)-1)) + break; + + if (dp >= &pdc_devs[NENTS(pdc_devs)] || dp->dev_type < 0) + return ENODEV; +#ifdef DEBUGBUG + if (debug) + printf("%s\n", dp->name); +#endif + + if (!(hpd = alloc(sizeof *hpd))) { +#ifdef DEBUG + printf ("devopen: no mem\n"); +#endif + } else { + bzero(hpd, sizeof *hpd); + hpd->bootdev = bootdev; + hpd->buf = (char *)(((u_long)hpd->ua_buf + IODC_MINIOSIZ-1) & + ~(IODC_MINIOSIZ-1)); + f->f_devdata = hpd; + if ((rc = (*devsw[dp->dev_type].dv_open)(f, file)) == 0) { + f->f_dev = &devsw[dp->dev_type]; + return 0; + } + free (hpd, 0); + f->f_devdata = NULL; + } + + if (!(f->f_flags & F_NODEV)) + f->f_dev = &devsw[dp->dev_type]; + + if (!f->f_devdata) + *file = NULL; + + return rc; +} + +void +devboot(dev, p) + dev_t dev; + char *p; +{ + const char *q; + if (!dev) { + int type, unit; + + switch (PAGE0->mem_boot.pz_class) { + case PCL_RANDOM: + type = 0; + unit = PAGE0->mem_boot.pz_layers[0]; + break; + case PCL_SEQU: + type = 1; + unit = PAGE0->mem_boot.pz_layers[0]; + break; + case PCL_NET_MASK|PCL_SEQU: + type = 2; + unit = 0; + break; + default: + type = 0; + unit = 0; + break; + } + dev = bootdev = MAKEBOOTDEV(type, 0, 0, unit, B_PARTITION(dev)); + } +#ifdef _TEST + *p++ = '/'; + *p++ = 'd'; + *p++ = 'e'; + *p++ = 'v'; + *p++ = '/'; + *p++ = 'r'; +#endif + /* quick copy device name */ + for (q = pdc_devs[B_TYPE(dev)].name; (*p++ = *q++);); + p[-1] = '0' + B_UNIT(dev); + *p++ = 'a' + B_PARTITION(dev); + *p = '\0'; +} + +int pch_pos; + +void +putchar(c) + int c; +{ + switch(c) { + case '\177': /* DEL erases */ + cnputc('\b'); + cnputc(' '); + case '\b': + cnputc('\b'); + if (pch_pos) + pch_pos--; + break; + case '\t': + do + cnputc(' '); + while(++pch_pos % 8); + break; + case '\n': + case '\r': + cnputc(c); + pch_pos=0; + break; + default: + cnputc(c); + pch_pos++; + break; + } +} + +int +getchar() +{ + int c = cngetc(); + + if (c == '\r') + c = '\n'; + + if ((c < ' ' && c != '\n') || c == '\177') + return(c); + + putchar(c); + + return(c); +} + +char ttyname_buf[8]; +char * +ttyname(fd) + int fd; +{ + snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d", + cdevs[major(cn_tab->cn_dev)], + minor(cn_tab->cn_dev)); + return (ttyname_buf); +} + +dev_t +ttydev(name) + char *name; +{ + int i, unit = -1; + char *no = name + strlen(name) - 1; + + while (no >= name && *no >= '0' && *no <= '9') + unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0'; + if (no < name || unit < 0) + return (NODEV); + for (i = 0; i < ncdevs; i++) + if (strncmp(name, cdevs[i], no - name + 1) == 0) + return (makedev(i, unit)); + return (NODEV); +} diff --git a/sys/arch/hppa64/stand/libsa/dev_hppa64.h b/sys/arch/hppa64/stand/libsa/dev_hppa64.h new file mode 100644 index 00000000000..a47daa2173a --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/dev_hppa64.h @@ -0,0 +1,43 @@ +/* $OpenBSD: dev_hppa64.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + + +#define IOPGSHIFT 11 +#define IONBPG (1 << IOPGSHIFT) +#define IOPGOFSET (IONBPG - 1) + +struct disklabel; +struct hppa_dev { + dev_t bootdev; + struct pz_device *pz_dev; /* device descriptor */ + daddr_t fsoff; /* offset to the file system */ + daddr_t last_blk; /* byte offset for last read blk */ + size_t last_read; /* amount read last time */ + struct disklabel *label; + /* buffer to cache data (aligned properly) */ + char *buf; + char ua_buf[IODC_IOSIZ + IODC_MINIOSIZ]; +}; + +#ifdef PDCDEBUG +#define DEVPATH_PRINT(dp) \ + printf("%x, %d.%d.%d.%d.%d.%d, 0x%x, %x.%x.%x.%x.%x.%x\n", \ + (dp)->dp_flags, (dp)->dp_bc[0], (dp)->dp_bc[1], (dp)->dp_bc[2], \ + (dp)->dp_bc[3], (dp)->dp_bc[4], (dp)->dp_bc[5], (dp)->dp_mod, \ + (dp)->dp_layers[0], (dp)->dp_layers[1], (dp)->dp_layers[2], \ + (dp)->dp_layers[3], (dp)->dp_layers[4], (dp)->dp_layers[5]); +#define PZDEV_PRINT(dp) \ + printf("devpath={%x, %d.%d.%d.%d.%d.%d, 0x%x, %x.%x.%x.%x.%x.%x}," \ + "\n\thpa=%p, spa=%p, io=%p, class=%u\n", \ + (dp)->pz_flags, (dp)->pz_bc[0], (dp)->pz_bc[1], (dp)->pz_bc[2], \ + (dp)->pz_bc[3], (dp)->pz_bc[4], (dp)->pz_bc[5], (dp)->pz_mod, \ + (dp)->pz_layers[0], (dp)->pz_layers[1], (dp)->pz_layers[2], \ + (dp)->pz_layers[3], (dp)->pz_layers[4], (dp)->pz_layers[5], \ + (dp)->pz_hpa, (dp)->pz_spa, (dp)->pz_iodc_io, (dp)->pz_class); +#endif + +extern pdcio_t pdc; +extern int pdcbuf[]; /* PDC returns, pdc.c */ + +int iodc_rw(char *, u_int, u_int, int func, struct pz_device *); +const char *dk_disklabel(struct hppa_dev *dp, struct disklabel *label); +int pdc_call(void *, ...); diff --git a/sys/arch/hppa64/stand/libsa/dk.c b/sys/arch/hppa64/stand/libsa/dk.c new file mode 100644 index 00000000000..d20d19d5b3f --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/dk.c @@ -0,0 +1,101 @@ +/* $OpenBSD: dk.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "libsa.h" + +#include <sys/param.h> +#include <sys/disklabel.h> +#include <sys/reboot.h> +#include <machine/pdc.h> +#include <machine/iomod.h> + +#include "dev_hppa64.h" + +const char * +dk_disklabel(struct hppa_dev *dp, struct disklabel *label) +{ + char buf[DEV_BSIZE]; + size_t ret; + + if (iodcstrategy(dp, F_READ, LABELSECTOR, DEV_BSIZE, buf, &ret)) + if (ret != DEV_BSIZE) + return "cannot read disklabel"; + + return (getdisklabel(buf, label)); +} + +int +dkopen(struct open_file *f, ...) +{ + struct disklabel *lp; + struct hppa_dev *dp = f->f_devdata; + const char *st; + +#ifdef DEBUG + if (debug) + printf("dkopen(%p)\n", f); +#endif + + if (!(dp->pz_dev = pdc_findev(-1, PCL_RANDOM))) + return ENXIO; + + lp = dp->label; + st = NULL; + +#ifdef DEBUG + if (debug) + printf ("disklabel\n"); +#endif + + if ((st = dk_disklabel(dp, lp)) != NULL) { +#ifdef DEBUG + if (debug) + printf ("dkopen: %s\n", st); +#endif + /* we do not know if it's a disk or net, but do not fail */ + } else { + u_int i; + + i = B_PARTITION(dp->bootdev); + if (i >= lp->d_npartitions || !lp->d_partitions[i].p_size) + return (EPART); + + dp->fsoff = lp->d_partitions[i].p_offset; + } + +#ifdef DEBUGBUG + if (debug) + printf ("dkopen() ret\n"); +#endif + return (0); +} + +int +dkclose(f) + struct open_file *f; +{ + free (f->f_devdata, sizeof(struct hppa_dev)); + f->f_devdata = NULL; + return 0; +} diff --git a/sys/arch/hppa64/stand/libsa/itecons.c b/sys/arch/hppa64/stand/libsa/itecons.c new file mode 100644 index 00000000000..49e4413e2d2 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/itecons.c @@ -0,0 +1,212 @@ +/* $OpenBSD: itecons.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "libsa.h" + +#include <sys/param.h> +#include <sys/disklabel.h> +#include <machine/pdc.h> +#include <machine/iomod.h> +#include <dev/cons.h> + +#include "dev_hppa64.h" + +iodcio_t cniodc; /* console IODC entry point */ +iodcio_t kyiodc; /* keyboard IODC entry point */ +pz_device_t *cons_pzdev, *kbd_pzdev; + +/* + * Console. + */ + +char cnbuf[IODC_MINIOSIZ] __attribute__ ((aligned (IODC_MINIOSIZ))); +int kycode[IODC_MAXSIZE/sizeof(int)]; + +int +cnspeed(dev, sp) + dev_t dev; + int sp; +{ + return 9600; +} + +void +ite_probe(cn) + struct consdev *cn; +{ + cniodc = (iodcio_t)(u_long)PAGE0->mem_free; + cons_pzdev = &PAGE0->mem_cons; + kbd_pzdev = &PAGE0->mem_kbd; + + if (pdc_call(pdc, PDC_IODC, PDC_IODC_READ, pdcbuf, cons_pzdev->pz_hpa, + IODC_INIT, cniodc, IODC_MAXSIZE) < 0 || + pdc_call(cniodc, cons_pzdev->pz_hpa, + (cons_pzdev->pz_hpa==PAGE0->mem_boot.pz_hpa)? + IODC_INIT_DEV: IODC_INIT_ALL, cons_pzdev->pz_spa, + cons_pzdev->pz_layers, pdcbuf, 0,0,0,0) < 0 || + pdc_call(pdc, PDC_IODC, PDC_IODC_READ, pdcbuf, cons_pzdev->pz_hpa, + IODC_IO, cniodc, IODC_MAXSIZE) < 0) { + /* morse code with the LED's?!! */ + cons_pzdev->pz_iodc_io = kbd_pzdev->pz_iodc_io = NULL; + } else { + cn->cn_pri = CN_INTERNAL; + cn->cn_dev = makedev(0, 0); + } +} + +void +ite_init(cn) + struct consdev *cn; +{ + /* + * If the keyboard is separate from the console output device, + * we load the keyboard code at `kycode'. + * + * N.B. In this case, since the keyboard code is part of the + * boot code, it will be overwritten when we load a kernel. + */ + if (cons_pzdev->pz_class != PCL_DUPLEX || + kbd_pzdev->pz_class == PCL_KEYBD) { + + kyiodc = (iodcio_t)kycode; + + if (pdc_call(pdc, PDC_IODC, PDC_IODC_READ, pdcbuf, kbd_pzdev->pz_hpa, + IODC_INIT, kyiodc, IODC_MAXSIZE) < 0 || + pdc_call(kyiodc, kbd_pzdev->pz_hpa, + (kbd_pzdev->pz_hpa == PAGE0->mem_boot.pz_hpa || + kbd_pzdev->pz_hpa == cons_pzdev->pz_hpa)? + IODC_INIT_DEV: IODC_INIT_ALL, kbd_pzdev->pz_spa, + kbd_pzdev->pz_layers, pdcbuf, 0, 0, 0, 0) < 0 || + pdc_call(pdc, PDC_IODC, PDC_IODC_READ, pdcbuf, kbd_pzdev->pz_hpa, + IODC_IO, kyiodc, IODC_MAXSIZE)) + kyiodc = NULL; + } else { + kyiodc = cniodc; + + bcopy((char *)&PAGE0->mem_cons, (char *)&PAGE0->mem_kbd, + sizeof(struct pz_device)); + } + + cons_pzdev->pz_iodc_io = (u_long)cniodc; + kbd_pzdev->pz_iodc_io = (u_long)kyiodc; +#ifdef DEBUG + if (!kyiodc) + printf("ite_init: no kbd\n"); +#endif +} + +void +ite_putc(dev, c) + dev_t dev; + int c; +{ + if (cniodc == NULL) + return; + + *cnbuf = c; + + pdc_call(cniodc, cons_pzdev->pz_hpa, IODC_IO_CONSOUT, + cons_pzdev->pz_spa, cons_pzdev->pz_layers, pdcbuf, 0, cnbuf, 1, 0); +} + +/* + * since i don't know how to 'just check the char available' + * i store the key into the stash removing on read op later; + */ +int +ite_getc(dev) + dev_t dev; +{ + static int stash = 0; + int err, c, l, i; + + if (kyiodc == NULL) + return(0x100); + + if (stash) { + c = stash; + if (!(dev & 0x80)) + stash = 0; + return c; + } + + i = 16; + do { + err = pdc_call(kyiodc, kbd_pzdev->pz_hpa, IODC_IO_CONSIN, + kbd_pzdev->pz_spa, kbd_pzdev->pz_layers, pdcbuf, + 0, cnbuf, 1, 0); + l = pdcbuf[0]; + c = cnbuf[0]; +#ifdef DEBUG + if (debug && err < 0) + printf("KBD input error: %d", err); +#endif + + /* if we are doing ischar() report immidiatelly */ + if (!i-- && (dev & 0x80) && l == 0) { +#ifdef DEBUG + if (debug > 2) + printf("ite_getc(0x%x): no char %d(%x)\n", + dev, l, c); +#endif + return (0); + } + } while(!l); + +#if DEBUG + if (debug && l > 1) + printf("KBD input got too much (%d)\n", l); + + if (debug > 3) + printf("kbd: \'%c\' (0x%x)\n", c, c); +#endif + if (dev & 0x80) + stash = c; + + return (c); +} + +void +ite_pollc(dev, on) + dev_t dev; + int on; +{ + +} diff --git a/sys/arch/hppa64/stand/libsa/lf.c b/sys/arch/hppa64/stand/libsa/lf.c new file mode 100644 index 00000000000..15b7a6c0957 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/lf.c @@ -0,0 +1,44 @@ +/* $OpenBSD: lf.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "libsa.h" +#include <machine/pdc.h> +#include <machine/iomod.h> +#include <machine/param.h> + +#include "dev_hppa64.h" + +int +lfopen(struct open_file *f, ...) +{ + struct hppa_dev *dp = f->f_devdata; + + if (!(dp->pz_dev = pdc_findev(-1, PCL_NET_MASK|PCL_SEQU))) + return ENXIO; + + return 0; +} + +int +lfclose(struct open_file *f) +{ + free(f->f_devdata, sizeof(struct hppa_dev)); + f->f_devdata = NULL; + return 0; +} diff --git a/sys/arch/hppa64/stand/libsa/libsa.h b/sys/arch/hppa64/stand/libsa/libsa.h new file mode 100644 index 00000000000..9952a35a383 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/libsa.h @@ -0,0 +1,72 @@ +/* $OpenBSD: libsa.h,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <lib/libsa/stand.h> + +#define EXEC_ELF +#define EXEC_SOM + +#define DEFAULT_KERNEL_ADDRESS 0 + +extern dev_t bootdev; + +void pdc_init(void); +struct pz_device; +struct pz_device *pdc_findev(int, int); + +int iodcstrategy(void *, int, daddr_t, size_t, void *, size_t *); + +int ctopen(struct open_file *, ...); +int ctclose(struct open_file *); + +int dkopen(struct open_file *, ...); +int dkclose(struct open_file *); + +int lfopen(struct open_file *, ...); +int lfstrategy(void *, int, daddr_t, size_t, void *, size_t *); +int lfclose(struct open_file *); + +void ite_probe(struct consdev *); +void ite_init(struct consdev *); +int ite_getc(dev_t); +void ite_putc(dev_t, int); +void ite_pollc(dev_t, int); + +void machdep(void); +void devboot(dev_t, char *); +void fcacheall(void); +void run_loadfile(u_long *marks, int howto); + +int lif_open(char *path, struct open_file *f); +int lif_close(struct open_file *f); +int lif_read(struct open_file *f, void *buf, size_t size, size_t *resid); +int lif_write(struct open_file *f, void *buf, size_t size, size_t *resid); +off_t lif_seek(struct open_file *f, off_t offset, int where); +int lif_stat(struct open_file *f, struct stat *sb); +int lif_readdir(struct open_file *f, char *name); + +union x_header; +struct x_param; +int som_probe(int, union x_header *); +int som_load(int, struct x_param *); +int som_ldsym(int, struct x_param *); + +extern int debug; + +#define MACHINE_CMD cmd_machine /* we have hppa specific commands */ diff --git a/sys/arch/hppa64/stand/libsa/lif.c b/sys/arch/hppa64/stand/libsa/lif.c new file mode 100644 index 00000000000..25c25471f14 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/lif.c @@ -0,0 +1,261 @@ +/* $OpenBSD: lif.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/disklabel.h> +#include "libsa.h" + +extern int debug; + +struct file { + char f_buf[LIF_FILESTART];/* buffer for lif volume header and dir */ + struct lifvol *f_lp; /* lif volume header pointer */ + struct lifdir *f_ld; /* lif dir pointer */ + int f_nfiles; /* gross number for lif dir entries */ + + off_t f_seek; /* seek pointer for file read */ + struct lifdir *f_rd; /* lif dir pointer for readdir */ + + int f_isdir; /* special hacky flag for '.' dir */ + int f_count; /* this file length */ + int f_off; /* this file offset */ +}; + +int +lif_open (path, f) + char *path; + struct open_file *f; +{ + struct file *fp; + struct lifdir *dp; + char *p, *q; + struct lif_load load; + size_t buf_size; + int err, l; + +#ifdef LIFDEBUG + if (debug) + printf("lif_open(%s, %p)\n", path, f); +#endif + + fp = alloc(sizeof(*fp)); + /* XXX we're assuming here that sizeof(fp->f_buf) >= LIF_FILESTART */ + if ((err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, 0, + sizeof(fp->f_buf), &fp->f_buf, &buf_size)) || + buf_size != sizeof(fp->f_buf)) { +#ifdef LIFDEBUG + if (debug) + printf("lif_open: unable to read LIF header (%d)\n", err); +#endif + } else if ((fp->f_lp = (struct lifvol *)fp->f_buf)->vol_id == LIF_VOL_ID) { + f->f_fsdata = fp; + fp->f_ld = (struct lifdir *)(fp->f_buf + LIF_DIRSTART); + fp->f_seek = 0; + fp->f_rd = fp->f_ld; + fp->f_nfiles = lifstob(fp->f_lp->vol_dirsize) / + sizeof(struct lifdir); + + /* no dirs on the lif */ + for (p = path + (l = strlen(path)); p >= path; p--) + if (*p == '/') { + p++; + break; + } + if (p > path) + path = p; + } else + err = EINVAL; + + if (!err && *path != '.') { + fp->f_isdir = 0; + err = ENOENT; + for (dp = fp->f_ld; dp < &fp->f_ld[fp->f_nfiles]; dp++) { +#ifdef LIFDEBUG + if (debug) + printf("lif_open: " + "%s <--> '%c%c%c%c%c%c%c%c%c%c'\n", + path, dp->dir_name[0], dp->dir_name[1], + dp->dir_name[2], dp->dir_name[3], + dp->dir_name[4], dp->dir_name[5], + dp->dir_name[6], dp->dir_name[7], + dp->dir_name[8], dp->dir_name[9]); +#endif + for (p = path, q = dp->dir_name; + *q && *q != ' '; q++, p++) + if (tolower(*q) != tolower(*p)) + break; + if ((!*q || *q == ' ') && !*p) { + err = 0; + break; + } + } + if (!err) { + fp->f_off = lifstodb(dp->dir_addr); + if (!(err =(f->f_dev->dv_strategy)(f->f_devdata, F_READ, + fp->f_off, sizeof(load), &load, &buf_size)) && + buf_size == sizeof(load)) { + /* no checksum */ + fp->f_count = load.count - sizeof(int); + fp->f_off = dbtob(fp->f_off) + sizeof(load); +#ifdef LIFDEBUG + if (debug) + printf("lif_open: %u @ %u [%x]\n", + fp->f_count, fp->f_off, + load.address); +#endif + } else if (!err) + err = EIO; + } + } else + fp->f_isdir = 1; + + if (err) { + free (fp, sizeof(*fp)); + f->f_fsdata = NULL; + } +#ifdef LIFDEBUG + if (debug) + printf("ret(%d)\n", err); +#endif + return err; +} + +int +lif_close(f) + struct open_file *f; +{ + free (f->f_fsdata, sizeof(struct file)); + f->f_fsdata = NULL; + return 0; +} + +int +lif_read(f, buf, size, resid) + struct open_file *f; + void *buf; + size_t size; + size_t *resid; +{ + struct file *fp = (struct file *)f->f_fsdata; + char *p; + char bbuf[DEV_BSIZE]; + size_t bsize, count = sizeof(bbuf); + int err = 0; + int foff; + +#ifdef LIFDEBUG + if (debug) + printf("lif_read(%p, %p, %u, %p)\n", f, buf, size, resid); +#endif + + for (p = bbuf; size; fp->f_seek += bsize, p += bsize) { + twiddle(); + foff = fp->f_off + fp->f_seek; + if (fp->f_seek >= fp->f_count || + (err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, + btodb(foff), count, p, &bsize))) + break; + if (p == bbuf) { + bsize = sizeof(bbuf) - (foff & (sizeof(bbuf) - 1)); + bsize = min(bsize, size); + bcopy(bbuf + (foff & (sizeof(bbuf) - 1)), buf, bsize); + p = buf; + } + count = size -= bsize; + } + if (resid) + *resid = size; + + return err; +} + +int +lif_write(f, buf, size, resid) + struct open_file *f; + void *buf; + size_t size; + size_t *resid; +{ + return EOPNOTSUPP; +} + +off_t +lif_seek(f, offset, where) + struct open_file *f; + off_t offset; + int where; +{ + struct file *fp = (struct file *)f->f_fsdata; + + switch (where) { + case SEEK_SET: + fp->f_seek = offset; + break; + case SEEK_CUR: + fp->f_seek += offset; + break; + case SEEK_END: + fp->f_seek = fp->f_count - offset; + break; + default: + return (-1); + } + return (fp->f_seek); +} + +int +lif_stat(f, sb) + struct open_file *f; + struct stat *sb; +{ + struct file *fp = (struct file *)f->f_fsdata; + + sb->st_mode = 0755 | (fp->f_isdir? S_IFDIR: 0); /* XXX */ + sb->st_uid = 0; + sb->st_gid = 0; + sb->st_size = fp->f_count; + return 0; +} + +int +lif_readdir(f, name) + struct open_file *f; + char *name; +{ + struct file *fp = (struct file *)f->f_fsdata; + char *p; + + if (name) { + while ((fp->f_rd->dir_name[0] == ' ' || + !fp->f_rd->dir_name[0]) && + (fp->f_rd - fp->f_ld) < fp->f_nfiles) + fp->f_rd++; + if ((fp->f_rd - fp->f_ld) >= fp->f_nfiles) { + *name = '\0'; + return -1; + } + strncpy(name, fp->f_rd->dir_name, sizeof(fp->f_rd->dir_name)); + if ((p = strchr(name, ' '))) + *p = '\0'; + fp->f_rd++; + } else + fp->f_rd = fp->f_ld; + + return 0; +} diff --git a/sys/arch/hppa64/stand/libsa/machdep.c b/sys/arch/hppa64/stand/libsa/machdep.c new file mode 100644 index 00000000000..521488e2257 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/machdep.c @@ -0,0 +1,75 @@ +/* $OpenBSD: machdep.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/disklabel.h> +#include <sys/reboot.h> +#include "libsa.h" +#include <machine/iomod.h> +#include <machine/pdc.h> + +#include "dev_hppa64.h" + +extern struct stable_storage sstor; /* contents of Stable Storage */ +int howto; +dev_t bootdev; + +void +machdep() +{ + pdc_init(); +#ifdef notyet + debug_init(); +#endif + cninit(); + +#ifdef PDCDEBUG + if (debug) { + int i; + + printf("SSTOR:\n"); + printf("pri_boot="); DEVPATH_PRINT(&sstor.ss_pri_boot); + printf("alt_boot="); DEVPATH_PRINT(&sstor.ss_alt_boot); + printf("console ="); DEVPATH_PRINT(&sstor.ss_console); + printf("keyboard="); DEVPATH_PRINT(&sstor.ss_keyboard); + printf("mem=%d, fn=%s, osver=%d\nos={", + sstor.ss_fast_size, sstor.ss_filenames, + sstor.ss_os_version); + for (i = 0; i < sizeof(sstor.ss_os); i++) + printf ("%x%c", sstor.ss_os[i], (i%8)? ',' : '\n'); + + printf("}\nPAGE0:\n"); + printf("ivec=%x, pf=%p[%u], toc=%p[%u], rndz=%p, clk/10ms=%u\n", + PAGE0->ivec_special, PAGE0->ivec_mempf, + PAGE0->ivec_mempflen, PAGE0->ivec_toc, + PAGE0->ivec_toclen, PAGE0->ivec_rendz, + PAGE0->mem_10msec); + printf ("mem: cont=%u, phys=%u, pdc_spa=%u, resv=%u, free=%x\n" + "cpu_hpa=%x, pdc=%p, imm_hpa=%p[%u,%u], soft=%u\n", + PAGE0->memc_cont, PAGE0->memc_phsize, PAGE0->memc_adsize, + PAGE0->memc_resv, PAGE0->mem_free, PAGE0->mem_hpa, + PAGE0->mem_pdc, PAGE0->imm_hpa, PAGE0->imm_spa_size, + PAGE0->imm_max_mem, PAGE0->imm_soft_boot); + + printf("console: "); PZDEV_PRINT(&PAGE0->mem_cons); + printf("boot: "); PZDEV_PRINT(&PAGE0->mem_boot); + printf("keyboard: "); PZDEV_PRINT(&PAGE0->mem_kbd); + } +#endif +} diff --git a/sys/arch/hppa64/stand/libsa/pdc.c b/sys/arch/hppa64/stand/libsa/pdc.c new file mode 100644 index 00000000000..1569c52a1dd --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/pdc.c @@ -0,0 +1,448 @@ +/* $OpenBSD: pdc.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright 1996 1995 by Open Software Foundation, Inc. + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appears in all copies and + * that both the copyright notice and this permission notice appear in + * supporting documentation. + * + * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, + * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * Copyright (c) 1990 mt Xinu, Inc. All rights reserved. + * Copyright (c) 1990 University of Utah. All rights reserved. + * + * This file may be freely distributed in any form as long as + * this copyright notice is included. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Utah $Hdr: pdc.c 1.8 92/03/14$ + */ + +#include <sys/time.h> +#include "libsa.h" +#include <sys/reboot.h> +#include <sys/disklabel.h> + +#include <machine/trap.h> +#include <machine/pdc.h> +#include <machine/iomod.h> +#include <machine/nvm.h> +#include <machine/param.h> +#include <machine/cpufunc.h> + +#include "dev_hppa64.h" + +/* + * Interface routines to initialize and access the PDC. + */ + +pdcio_t pdc; +int pdcbuf[64] PDC_ALIGNMENT;/* PDC return buffer */ +struct stable_storage sstor; /* contents of Stable Storage */ +int sstorsiz; /* size of Stable Storage */ +struct bootdata bd; +int bdsize = sizeof(struct bootdata); + +/* + * Initialize PDC and related variables. + */ +void +pdc_init() +{ + int err; + + /* + * Initialize important global variables (defined above). + */ + pdc = (pdcio_t)(u_long)PAGE0->mem_pdc; + + err = pdc_call(pdc, PDC_STABLE, PDC_STABLE_SIZE, pdcbuf, 0, 0); + if (err >= 0) { + sstorsiz = min(pdcbuf[0],sizeof(sstor)); + err = (*pdc)(PDC_STABLE, PDC_STABLE_READ, 0, &sstor, sstorsiz); + } + + /* + * Now that we (may) have an output device, if we encountered + * an error reading Stable Storage (above), let them know. + */ +#ifdef DEBUG + if (debug && err) + printf("Stable storage PDC_STABLE Read Ret'd %d\n", err); +#endif + + /* + * Clear the FAULT light (so we know when we get a real one) + */ + pdc_call(pdc, PDC_CHASSIS, PDC_CHASSIS_DISP, + PDC_OSTAT(PDC_OSTAT_BOOT) | 0xCEC0); +} + +/* + * Generic READ/WRITE through IODC. Takes pointer to PDC device + * information, returns (positive) number of bytes actually read or + * the (negative) error condition, or zero if at "EOF". + */ +int +iodcstrategy(devdata, rw, blk, size, buf, rsize) + void *devdata; + int rw; + daddr_t blk; + size_t size; + void *buf; + size_t *rsize; +{ + struct hppa_dev *dp = devdata; + struct pz_device *pzdev = dp->pz_dev; + iodcio_t iodc = (iodcio_t)(u_long)pzdev->pz_iodc_io; + int offset, xfer, ret; + +#ifdef PDCDEBUG + if (debug) + printf("iodcstrategy(%p, %s, %u, %u, %p, %p)\n", devdata, + rw==F_READ? "READ" : "WRITE", blk, size, buf, rsize); + + if (debug > 1) + PZDEV_PRINT(pzdev); +#endif + + blk += dp->fsoff; + blk <<= DEV_BSHIFT; + if ((pzdev->pz_class & PCL_CLASS_MASK) == PCL_SEQU) { + /* rewind and re-read to seek */ + if (blk < dp->last_blk) { +#ifdef PDCDEBUG + if (debug) + printf("iodc: rewind "); +#endif + if ((ret = ((iodcio_t)(long)pzdev->pz_iodc_io)( + pzdev->pz_hpa, IODC_IO_READ, pzdev->pz_spa, + pzdev->pz_layers, pdcbuf, 0, dp->buf, 0, 0)) < 0) { +#ifdef DEBUG + if (debug) + printf("IODC_IO: %d\n", ret); +#endif + return (EIO); + } else { + dp->last_blk = 0; + dp->last_read = 0; + } + } + +#ifdef PDCDEBUG + if (debug) + printf("seek %d ", dp->last_blk); +#endif + for (; (dp->last_blk + dp->last_read) <= blk; + dp->last_read = ret) { + twiddle(); + dp->last_blk += dp->last_read; + if ((ret = (iodc)(pzdev->pz_hpa, + IODC_IO_READ, pzdev->pz_spa, pzdev->pz_layers, + pdcbuf, dp->last_blk, dp->buf, IODC_IOSIZ, + IODC_IOSIZ)) < 0) { +#ifdef DEBUG + if (debug) + printf("IODC_IO: %d\n", ret); +#endif + return (EIO); + } + if ((ret = pdcbuf[0]) == 0) + break; +#ifdef PDCDEBUG + if (debug) + printf("-"); +#endif + } +#ifdef PDCDEBUG + if (debug) + printf("> %d[%d]\n", dp->last_blk, dp->last_read); +#endif + } + + xfer = 0; + /* see if we can scratch anything from buffer */ + if (dp->last_blk <= blk && (dp->last_blk + dp->last_read) > blk) { + twiddle(); + offset = blk - dp->last_blk; + xfer = min(dp->last_read - offset, size); + size -= xfer; + blk += xfer; +#ifdef PDCDEBUG + if (debug) + printf("off=%d,xfer=%d,size=%d,blk=%d\n", + offset, xfer, size, blk); +#endif + bcopy(dp->buf + offset, buf, xfer); + buf += xfer; + } + + /* + * double buffer it all the time, to cache + */ + for (; size; size -= ret, buf += ret, blk += ret, xfer += ret) { + offset = blk & IOPGOFSET; + if ((ret = (iodc)(pzdev->pz_hpa, + (rw == F_READ? IODC_IO_READ: IODC_IO_WRITE), + pzdev->pz_spa, pzdev->pz_layers, pdcbuf, + blk - offset, dp->buf, IODC_IOSIZ, IODC_IOSIZ)) < 0) { +#ifdef DEBUG + if (debug) + printf("iodc_read(%d,%d): %d\n", + blk - offset, IODC_IOSIZ, ret); +#endif + if (xfer) + break; + else + return (EIO); + } + if ((ret = pdcbuf[0]) <= 0) + break; + dp->last_blk = blk - offset; + dp->last_read = ret; + if ((ret -= offset) > size) + ret = size; + bcopy(dp->buf + offset, buf, ret); +#ifdef PDCDEBUG + if (debug) + printf("read %d(%d,%d)@%x ", ret, + dp->last_blk, dp->last_read, (u_int)buf); +#endif + } + +#ifdef PDCDEBUG + if (debug) + printf("\n"); +#endif + + if (rsize) + *rsize = xfer; + return (0); +} + +/* + * Find a device with specified unit number + * (any if unit == -1), and of specified class (PCL_*). + */ +struct pz_device * +pdc_findev(unit, class) + int unit, class; +{ + static struct pz_device pz; + int layers[sizeof(pz.pz_layers)/sizeof(pz.pz_layers[0])]; + iodcio_t iodc; + int err = 0; + u_int hpa, spa; + +#ifdef PDCDEBUG + if (debug) + printf("pdc_finddev(%d, %x)\n", unit, class); +#endif + iodc = (iodcio_t)((u_long)PAGE0->mem_free + IODC_MAXSIZE); + hpa = PAGE0->mem_boot.pz_hpa; + spa = ((struct iomod *)(u_long)hpa)->io_spa; + + /* quick hack for boot device */ + if (PAGE0->mem_boot.pz_class == class && + (unit == -1 || PAGE0->mem_boot.pz_layers[0] == unit)) { + + bcopy (&PAGE0->mem_boot.pz_dp, &pz.pz_dp, sizeof(pz.pz_dp)); + bcopy (pz.pz_layers, layers, sizeof(layers)); + if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa, + IODC_INIT, iodc, IODC_MAXSIZE)) < 0) { +#ifdef DEBUG + if (debug) + printf("IODC_READ: %d\n", err); +#endif + return NULL; + } + } else { + struct pdc_memmap memmap; + struct iodc_data mptr; + int i, stp; + + for (i = 0; i < 0xf; i++) { + pz.pz_bc[0] = pz.pz_bc[1] = + pz.pz_bc[2] = pz.pz_bc[3] = -1; + pz.pz_bc[4] = 2; + pz.pz_bc[5] = 0; /* core bus */ + pz.pz_mod = i; + if ((pdc)(PDC_MEMMAP, PDC_MEMMAP_HPA, &memmap, + &pz.pz_dp) < 0) + continue; +#ifdef PDCDEBUG + if (debug) + printf("memap: %d.%d.%d, hpa=%x, mpgs=%x\n", + pz.pz_bc[4], pz.pz_bc[5], pz.pz_mod, + memmap.hpa, memmap.morepages); +#endif + hpa = memmap.hpa; + + if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, &pdcbuf, hpa, + IODC_DATA, &mptr, sizeof(mptr))) < 0) { +#ifdef DEBUG + if (debug) + printf("IODC_DATA: %d\n", err); +#endif + continue; + } + + if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa, + IODC_INIT, iodc, IODC_MAXSIZE)) < 0) { +#ifdef DEBUG + if (debug) + printf("IODC_READ: %d\n", err); +#endif + continue; + } + + stp = IODC_INIT_FIRST; + do { + if ((err = (iodc)(hpa, stp, spa, layers, + pdcbuf, 0, 0, 0, 0)) < 0) { +#ifdef DEBUG + if (debug && err != PDC_ERR_EOD) + printf("IODC_INIT_%s: %d\n", + stp==IODC_INIT_FIRST? + "FIRST":"NEXT", err); +#endif + break; + } +#ifdef PDCDEBUG + if (debug) + printf("[%x,%x,%x,%x,%x,%x], " + "[%x,%x,%x,%x,%x,%x]\n", + pdcbuf[0], pdcbuf[1], pdcbuf[2], + pdcbuf[3], pdcbuf[4], pdcbuf[5], + layers[0], layers[1], layers[2], + layers[3], layers[4], layers[5]); +#endif + stp = IODC_INIT_NEXT; + + } while (pdcbuf[1] != class && + unit != -1 && unit != layers[0]); + + if (err >= 0) + break; + } + } + + if (err >= 0) { + /* init device */ + if (0 && (err = (iodc)(hpa, IODC_INIT_DEV, spa, + layers, pdcbuf, 0, 0, 0, 0)) < 0) { +#ifdef DEBUG + if (debug) + printf("INIT_DEV: %d\n", err); +#endif + return NULL; + } + + /* read i/o entry code */ + if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa, + IODC_IO, iodc, IODC_MAXSIZE)) < 0) { +#ifdef DEBUG + if (debug) + printf("IODC_READ: %d\n", err); +#endif + return NULL; + } + + pz.pz_flags = 0; + bcopy(layers, pz.pz_layers, sizeof(pz.pz_layers)); + pz.pz_hpa = hpa; +/* XXX pz.pz_spa = spa; */ + pz.pz_iodc_io = (u_long)iodc; + pz.pz_class = class; + + return &pz; + } + + return NULL; +} + +static __inline void +fall(int c_base, int c_count, int c_loop, int c_stride, int data) +{ + int loop; /* Internal vars */ + + for (; c_count--; c_base += c_stride) + for (loop = c_loop; loop--; ) + if (data) + fdce(0, c_base); + else + fice(0, c_base); +} + +/* + * fcacheall - Flush all caches. + * + * This routine is just a wrapper around the real cache flush routine. + */ +struct pdc_cache pdc_cacheinfo PDC_ALIGNMENT; + +void +fcacheall() +{ + int err; + + if ((err = (*pdc)(PDC_CACHE, PDC_CACHE_DFLT, &pdc_cacheinfo)) < 0) { +#ifdef DEBUG + if (debug) + printf("fcacheall: PDC_CACHE failed (%d).\n", err); +#endif + return; + } +#if PDCDEBUG + if (debug) + printf("pdc_cache:\nic={%u,%x,%x,%u,%u,%u}\n" + "dc={%u,%x,%x,%u,%u,%u}\n", + pdc_cacheinfo.ic_size, *(u_int *)&pdc_cacheinfo.ic_conf, + pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_stride, + pdc_cacheinfo.ic_count, pdc_cacheinfo.ic_loop, + pdc_cacheinfo.dc_size, *(u_int *)&pdc_cacheinfo.ic_conf, + pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_stride, + pdc_cacheinfo.dc_count, pdc_cacheinfo.dc_loop); +#endif + /* + * Flush the instruction, then data cache. + */ + fall(pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_count, + pdc_cacheinfo.ic_loop, pdc_cacheinfo.ic_stride, 0); + sync_caches(); + fall(pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_count, + pdc_cacheinfo.dc_loop, pdc_cacheinfo.dc_stride, 1); + sync_caches(); +} diff --git a/sys/arch/hppa64/stand/libsa/time.c b/sys/arch/hppa64/stand/libsa/time.c new file mode 100644 index 00000000000..fd1fa22f1e7 --- /dev/null +++ b/sys/arch/hppa64/stand/libsa/time.c @@ -0,0 +1,47 @@ +/* $OpenBSD: time.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <machine/pdc.h> +#include <sys/disklabel.h> +#include "libsa.h" +#include "dev_hppa64.h" + +time_t +getsecs() +{ + time_t tt; + int err; + + if ((err = (*pdc)(PDC_TOD, PDC_TOD_READ, &pdcbuf)) < 0) { + tt = 0; +#ifdef DEBUG + if (debug) + printf("getsecs: TOD read failed (%d)\n", err); +#endif + } else { + tt = ((struct pdc_tod *)pdcbuf)->sec; +#ifdef DEBUG + if (debug && tt < 800000000) + printf("getsecs: got %u seconds\n", tt); +#endif + } + + return tt; +} diff --git a/sys/arch/hppa64/stand/libz/Makefile b/sys/arch/hppa64/stand/libz/Makefile new file mode 100644 index 00000000000..d6ed6c93837 --- /dev/null +++ b/sys/arch/hppa64/stand/libz/Makefile @@ -0,0 +1,10 @@ +# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:49 mickey Exp $ + +S=${.CURDIR}/../../../.. +ZDST=${.OBJDIR} +SADIR=${.CURDIR}/.. + +.PATH: ${S}/lib/libz + +.include "${S}/lib/libz/Makefile" +CFLAGS+=${SACFLAGS} -I${S}/lib/libsa diff --git a/sys/arch/hppa64/stand/mkboot/Makefile b/sys/arch/hppa64/stand/mkboot/Makefile new file mode 100644 index 00000000000..e83c1dd1f66 --- /dev/null +++ b/sys/arch/hppa64/stand/mkboot/Makefile @@ -0,0 +1,14 @@ +# $OpenBSD: Makefile,v 1.1 2005/04/01 10:40:49 mickey Exp $ + +MAN= mkboot.8 +MANSUBDIR=hppa64 + +.if ${MACHINE} == "hppa64" +PROG= mkboot +CC= ${HOSTCC} +LDSTATIC= -static +.else +NOPROG= +.endif + +.include <bsd.prog.mk> diff --git a/sys/arch/hppa64/stand/mkboot/mkboot.8 b/sys/arch/hppa64/stand/mkboot/mkboot.8 new file mode 100644 index 00000000000..536bc587019 --- /dev/null +++ b/sys/arch/hppa64/stand/mkboot/mkboot.8 @@ -0,0 +1,58 @@ +.\" $OpenBSD: mkboot.8,v 1.1 2005/04/01 10:40:49 mickey Exp $ +.\" +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. 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. +.\" +.Dd November 11, 2002 +.Dt MKBOOT 8 +.Os +.Sh NAME +.Nm mkboot +.Nd create LIF files +.Sh SYNOPSIS +.Nm mkboot +.Op Fl v +.Op Fl l Ar loadpoint +.Ar program ... outfile +.Sh DESCRIPTION +Creates the LIF file containing the bootstrap +.Ar program +and possibly other programs to be used by the +.Tn HP 9000/700 +and +.Tn HP 9000/800 +systems. +.Pp +An argument to the +.Fl l +option specifies the load point for the boot program, +with the default value of zero. +.Sh HISTORY +An +.Nm +utility first appeared in +.Ox 2.4 . diff --git a/sys/arch/hppa64/stand/mkboot/mkboot.c b/sys/arch/hppa64/stand/mkboot/mkboot.c new file mode 100644 index 00000000000..ced89972b56 --- /dev/null +++ b/sys/arch/hppa64/stand/mkboot/mkboot.c @@ -0,0 +1,430 @@ +/* $OpenBSD: mkboot.c,v 1.1 2005/04/01 10:40:49 mickey Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)mkboot.c 8.1 (Berkeley) 7/15/93 + */ + +#if 0 +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: mkboot.c,v 1.1 2005/04/01 10:40:49 mickey Exp $"; +#endif /* not lint */ +#endif + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#ifdef __OpenBSD__ +#include <err.h> +#endif + +#include <sys/exec_aout.h> +#include <sys/exec_elf.h> + +#ifndef hppa +/* hack for cross compile XXX */ +#include "../../include/disklabel.h" +#else +#include <sys/disklabel.h> +#endif + +#include <stdio.h> +#include <ctype.h> + +int putfile(char *, int); +void __dead usage(void); +void bcddate(char *, char *); +char *lifname(char *); +int cksum(int, int *, int); + +char *to_file; +int loadpoint, verbose; +u_long entry; +#ifndef __OpenBSD__ +char *__progname = "mkboot"; +#endif + +/* + * Old Format: + * sector 0: LIF volume header (40 bytes) + * sector 1: <unused> + * sector 2: LIF directory (8 x 32 == 256 bytes) + * sector 3-: LIF file 0, LIF file 1, etc. + * where sectors are 256 bytes. + * + * New Format: + * sector 0: LIF volume header (40 bytes) + * sector 1: <unused> + * sector 2: LIF directory (8 x 32 == 256 bytes) + * sector 3: <unused> + * sector 4-31: disklabel (~300 bytes right now) + * sector 32-: LIF file 0, LIF file 1, etc. + */ +int +main(int argc, char **argv) +{ + int to; + register int n, pos, c; + char buf[LIF_FILESTART]; + struct lifvol *lifv = (struct lifvol *)buf; + struct lifdir *lifd = (struct lifdir *)(buf + LIF_DIRSTART); + + while ((c = getopt(argc, argv, "vl:")) != -1) { + switch (c) { + case 'v': + verbose++; + break; + case 'l': + sscanf(optarg, "0x%x", &loadpoint); + break; + default: + usage(); + } + } + if (argc - optind < 2) + usage(); + else if (argc - optind > 8) + errx(1, "too many boot programs (max 8 supported)"); + + to_file = argv[--argc]; + if ((to = open(to_file, O_RDWR | O_TRUNC | O_CREAT, 0644)) < 0) + err(1, "%s: open", to_file); + + bzero(buf, sizeof(buf)); + /* clear possibly unused directory entries */ + memset(lifd[1].dir_name, ' ', sizeof lifd[1].dir_name); + lifd[1].dir_type = -1; + lifd[1].dir_addr = 0; + lifd[1].dir_length = 0; + lifd[1].dir_flag = 0xFF; + lifd[1].dir_implement = 0; + lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1]; + + /* record volume info */ + lifv->vol_id = htobe16(LIF_VOL_ID); + strncpy(lifv->vol_label, "BOOT44", 6); + lifv->vol_addr = htobe32(btolifs(LIF_DIRSTART)); + lifv->vol_oct = htobe16(LIF_VOL_OCT); + lifv->vol_dirsize = htobe32(btolifs(LIF_DIRSIZE)); + lifv->vol_version = htobe16(1); + lifv->vol_lastvol = lifv->vol_number = htobe16(1); + lifv->vol_length = LIF_FILESTART; + bcddate(to_file, lifv->vol_toc); + lifv->ipl_addr = htobe32(LIF_FILESTART); + lifv->ipl_size = 0; + lifv->ipl_entry = 0; + + argv += optind; + argc -= optind; + optind = 0; + for (pos = LIF_FILESTART; optind < argc; optind++) { + + /* output bootfile */ + lseek(to, pos, 0); + lifd[optind].dir_addr = htobe32(btolifs(pos)); + n = btolifs(putfile(argv[optind], to)); + if (lifv->ipl_entry == 0) { + lifv->ipl_entry = htobe32(loadpoint + entry); + lifv->ipl_size = htobe32(lifstob(n)); + lifd[optind].dir_type = htobe16(LIF_DIR_ISL); + lifd[optind].dir_implement = 0; + } else { + lifd[optind].dir_type = htobe16(LIF_DIR_TYPE); + lifd[1].dir_implement = htobe32(loadpoint + entry); + } + + strlcpy(lifd[optind].dir_name, lifname(argv[optind]), + sizeof lifd[optind].dir_name); + lifd[optind].dir_length = htobe32(n); + bcddate(argv[optind], lifd[optind].dir_toc); + lifd[optind].dir_flag = htobe16(LIF_DIR_FLAG); + + lifv->vol_length += n; + pos += lifstob(n); + } + + lifv->vol_length = htobe32(lifv->vol_length); + + /* output volume/directory header info */ + lseek(to, LIF_VOLSTART, 0); + if (write(to, buf, sizeof(buf)) != sizeof(buf)) + err(1, "%s: write LIF volume", to_file); + lseek(to, 0, SEEK_END); + + if (close(to) < 0) + err(1, "%s", to_file); + + return(0); +} + +int +putfile(from_file, to) + char *from_file; + int to; +{ + struct exec ex; + register int n, total; + char buf[2048]; + int from, check_sum = 0; + struct lif_load load; + + if ((from = open(from_file, O_RDONLY)) < 0) + err(1, "%s", from_file); + + n = read(from, &ex, sizeof(ex)); + if (n != sizeof(ex)) + err(1, "%s: reading file header", from_file); + + entry = ex.a_entry; + if (N_GETMAGIC(ex) == OMAGIC || N_GETMAGIC(ex) == NMAGIC) + entry += sizeof(ex); + else if (IS_ELF(*(Elf64_Ehdr *)&ex)) { + Elf64_Ehdr elf_header; + Elf64_Phdr *elf_segments; + int i,header_count, memory_needed, elf_load_image_segment; + + (void) lseek(from, 0, SEEK_SET); + n = read(from, &elf_header, sizeof (elf_header)); + if (n != sizeof (elf_header)) + err(1, "%s: reading ELF header", from_file); + header_count = betoh32(elf_header.e_phnum); + memory_needed = header_count * sizeof (*elf_segments); + elf_segments = malloc(memory_needed); + if (elf_segments == NULL) + err(1, "malloc"); + (void) lseek(from, betoh32(elf_header.e_phoff), SEEK_SET); + n = read(from, elf_segments, memory_needed); + if (n != memory_needed) + err(1, "%s: reading ELF segments", from_file); + elf_load_image_segment = -1; + for (i = 0; i < header_count; i++) { + if (elf_segments[i].p_filesz && + elf_segments[i].p_type == htobe32(PT_LOAD) && + elf_segments[i].p_flags & htobe32(PF_X)) { + if (elf_load_image_segment != -1) + warnx("%s: more than one ELF program segment", from_file); + else + elf_load_image_segment = i; + } + } + if (elf_load_image_segment == -1) + errx(1, "%s: no suitable ELF program segment", from_file); + entry = betoh32(elf_header.e_entry) + + betoh32(elf_segments[elf_load_image_segment].p_offset) - + betoh32(elf_segments[elf_load_image_segment].p_vaddr); + } else if (*(u_char *)&ex == 0x1f && ((u_char *)&ex)[1] == 0x8b) { + entry = 0; + } else + errx(1, "%s: bad magic number", from_file); + + entry += sizeof(load); + lseek(to, sizeof(load), SEEK_CUR); + total = 0; + n = sizeof(buf) - sizeof(load); + /* copy the whole file */ + for (lseek(from, 0, 0); ; n = sizeof(buf)) { + bzero(buf, sizeof(buf)); + if ((n = read(from, buf, n)) < 0) + err(1, "%s", from_file); + else if (n == 0) + break; + + if (write(to, buf, n) != n) + err(1, "%s", to_file); + + total += n; + check_sum = cksum(check_sum, (int *)buf, n); + } + + /* load header */ + load.address = htobe32(loadpoint + sizeof(load)); + load.count = htobe32(4 + total); + check_sum = cksum(check_sum, (int *)&load, sizeof(load)); + + if (verbose) + warnx("wrote %d bytes of file \'%s\'", total, from_file); + + total += sizeof(load); + /* insert the header */ + lseek(to, -total, SEEK_CUR); + if (write(to, &load, sizeof(load)) != sizeof(load)) + err(1, "%s", to_file); + lseek(to, total - sizeof(load), SEEK_CUR); + + bzero(buf, sizeof(buf)); + /* pad to int */ + n = sizeof(int) - total % sizeof(int); + if (total % sizeof(int)) { + if (write(to, buf, n) != n) + err(1, "%s", to_file); + else + total += n; + } + + /* pad to the blocksize */ + n = sizeof(buf) - total % sizeof(buf); + + if (n < sizeof(int)) { + n += sizeof(buf); + total += sizeof(buf); + } else + total += n; + + /* TODO should pad here to the 65k boundary for tape boot */ + + if (verbose) + warnx("checksum is 0x%08x", -check_sum); + + check_sum = htobe32(-check_sum); + if (write(to, &check_sum, sizeof(int)) != sizeof(int)) + err(1, "%s", to_file); + + n -= sizeof(int); + + if (write(to, buf, n) != n) + err(1, "%s", to_file); + + if (close(from) < 0 ) + err(1, "%s", from_file); + + return total; +} + +int +cksum(ck, p, size) + int ck; + int *p; + int size; +{ + /* we assume size is int-aligned */ + for (size = (size + sizeof(int) - 1) / sizeof(int); size--; p++ ) + ck += betoh32(*p); + + return ck; +} + +void __dead +usage() +{ + extern char *__progname; + fprintf(stderr, + "usage: %s [-v] [-l loadpoint] prog1 {progN} outfile\n", + __progname); + exit(1); +} + +char * +lifname(str) + char *str; +{ + static char lname[10] = "XXXXXXXXXX"; + register int i; + + for (i = 0; i < 9; i++) { + if (islower(*str)) + lname[i] = toupper(*str); + else if (isalnum(*str) || *str == '_') + lname[i] = *str; + else + break; + str++; + } + for ( ; i < 10; i++) + lname[i] = ' '; + return(lname); +} + + +void +bcddate(file, toc) + char *file; + char *toc; +{ + struct stat statb; +#ifndef __OpenBSD__ + struct tm { + int tm_sec; /* second (0-61, allows for leap seconds) */ + int tm_min; /* minute (0-59) */ + int tm_hour; /* hour (0-23) */ + int tm_mday; /* day of the month (1-31) */ + int tm_mon; /* month (0-11) */ + int tm_year; /* years since 1900 */ + int tm_wday; /* day of the week (0-6) */ + int tm_yday; /* day of the year (0-365) */ + int tm_isdst; /* non-0 if daylight saving time is in effect */ + } *tm; +#else + struct tm *tm; +#endif + + stat(file, &statb); + tm = localtime(&statb.st_ctime); + *toc = (tm->tm_year / 10) << 4; + *toc++ |= tm->tm_year % 10; + *toc = ((tm->tm_mon+1) / 10) << 4; + *toc++ |= (tm->tm_mon+1) % 10; + *toc = (tm->tm_mday / 10) << 4; + *toc++ |= tm->tm_mday % 10; + *toc = (tm->tm_hour / 10) << 4; + *toc++ |= tm->tm_hour % 10; + *toc = (tm->tm_min / 10) << 4; + *toc++ |= tm->tm_min % 10; + *toc = (tm->tm_sec / 10) << 4; + *toc |= tm->tm_sec % 10; +} + +#ifndef __OpenBSD__ +int +err(ex, str) + int ex; + char *str; +{ + perror(str); + exit(ex); +} + +int +errx(ex, str) + int ex; + char *str; +{ + perror(str); + exit(ex); +} +#endif |