diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-05-10 12:02:22 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-05-10 12:02:22 +0000 |
commit | 7d98c945375fabf74b3dfed117622c9532b65472 (patch) | |
tree | 5f8404dd419128ceb16ec086918ee170fa127d65 /sys/arch | |
parent | a78fda83c38d040af173e172985fe83d04dc0982 (diff) |
OpenBSD/socppc, a port to the Thecus N1200, and potentially other Freescale
PowerPC SoC platforms that use u-boot as a bootloader.
Diffstat (limited to 'sys/arch')
54 files changed, 5805 insertions, 0 deletions
diff --git a/sys/arch/socppc/conf/GENERIC b/sys/arch/socppc/conf/GENERIC new file mode 100644 index 00000000000..5021ce57449 --- /dev/null +++ b/sys/arch/socppc/conf/GENERIC @@ -0,0 +1,63 @@ +# $OpenBSD: GENERIC,v 1.1 2008/05/10 12:02:20 kettenis Exp $g +# +# For further information on compiling OpenBSD kernels, see the config(8) +# man page. +# +# For further information on hardware support for this architecture, see +# the intro(4) man page. For further information about kernel options +# for this architecture, see the options(4) man page. For an explanation +# of each device driver in this file see the section 4 man page for the +# device. + +machine socppc powerpc +include "../../../conf/GENERIC" +maxusers 32 # estimated number of users + +option USB_DEBUG +option PCIVERBOSE +option USBVERBOSE + +option USER_PCICONF # user-space PCI configuration +option APERTURE + +config bsd swap generic + +mainbus0 at root +cpu0 at mainbus0 +obio0 at mainbus0 + +# On-board IPIC +ipic0 at obio? addr 0x00700 + +# On-board I2C +sociic0 at obio? addr 0x03000 ivec 14 +sociic1 at obio? addr 0x03100 ivec 15 +iic* at sociic? +ricohrtc0 at iic? addr 0x32 # Ricoh RTC +fintek0 at iic? flags 0x0001 # temp/fan controller + +# On-board DUART +com0 at obio? addr 0x04500 ivec 9 +com1 at obio? addr 0x04600 ivec 10 + +# On-board PCI +socpcic0 at obio? addr 0x08300 +socpcic1 at obio? addr 0x08380 +pci* at socpcic? + +pciide* at pci? +wd* at pciide? flags 0x0000 + +# Ob-board USB +ehci0 at obio? addr 0x22100 ivec 39 +usb* at ehci? + +# USB devices +uhub* at usb? # USB Hubs +uhub* at uhub? # USB Hubs +umass* at uhub? # USB Mass Storage devices +scsibus* at umass? +ural* at uhub? # Ralink RT2500USB +rum* at uhub? # Ralink RT2501USB/RT2601USB + +sd* at scsibus? diff --git a/sys/arch/socppc/conf/Makefile.socppc b/sys/arch/socppc/conf/Makefile.socppc new file mode 100644 index 00000000000..baa5d9ca8c7 --- /dev/null +++ b/sys/arch/socppc/conf/Makefile.socppc @@ -0,0 +1,189 @@ +# $OpenBSD: Makefile.socppc,v 1.1 2008/05/10 12:02:20 kettenis Exp $ +# +# Makefile for OpenBSD PowerPC +# +# This makefile is constructed from a machine description: +# config machineid +# Most changes should be made in the machine description +# /sys/arch/socppc/conf/``machineid'' +# after which you should do +# config machineid +# Machine generic makefile changes should be made in +# /sys/arch/socppc/conf/Makefile.socppc +# 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 +# +.SUFFIXES: .S .c .o + +# DEBUG is set to -g if debugging. +# PROF is set to -pg if profiling. + +.include <bsd.own.mk> + +MKDEP?= mkdep +STRIP?= strip +SIZE?= size + +# source tree is located via $S relative to the compilation directory +.ifndef S +S!= cd ../../../..; pwd +.endif +SOCPPC= $S/arch/socppc + +INCLUDES= -I. -I$S -I$S/arch -nostdinc +CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL \ + -D__socppc__ +CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \ + -Wno-uninitialized -Wno-format -Wno-main \ + -Wstack-larger-than-2047 -Wvariable-decl +CMACHFLAGS= -msoft-float -Wa,-many -fno-builtin-printf -fno-builtin-log +.if ${IDENT:M-DNO_PROPOLICE} +CMACHFLAGS+= -fno-stack-protector +.endif +COPTS?= -O2 +CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE} +AFLAGS= -D_LOCORE -Wa,-many +LINKFLAGS= -N -Ttext 200000 -e start --warn-common +STRIPFLAGS= -g -X -x + +HOSTCC?= ${CC} +HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//} +HOSTED_CFLAGS= ${CFLAGS} + +# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP} +# where TYPE is NORMAL, DRIVER, or PROFILE}; SUFFIX is the file suffix, +# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file +# is marked as config-dependent. + +NORMAL_C_NOP= ${CC} ${CFLAGS} ${CPPFLAGS} -c $< +NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< +NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< + +DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $< +DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $< + +NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $< +NORMAL_S_C= ${AS} ${COPTS} ${PARAM} $< -o $@ + + +%OBJS + +%CFILES + +%SFILES + +# load lines for config "xxx" will be emitted as: +# xxx: ${SYSTEM_DEP} swapxxx.o +# ${SYSTEM_LD_HEAD} +# ${SYSTEM_LD} swapxxx.o +# ${SYSTEM_LD_TAIL} +SYSTEM_OBJ= locore.o param.o ioconf.o ${OBJS} +SYSTEM_DEP= Makefile ${SYSTEM_OBJ} +SYSTEM_LD_HEAD= rm -f $@ +SYSTEM_LD= @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_OBJ}' vers.o; \ + ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_OBJ} vers.o +SYSTEM_LD_TAIL= @${SIZE} $@; chmod 755 $@ + +DEBUG?= +.if ${DEBUG} == "-g" +LINKFLAGS+= -X +SYSTEM_LD_TAIL+=; \ + echo mv $@ $@.gdb; rm -f $@.gdb; mv $@ $@.gdb; \ + echo ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb; \ + ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb +.else +LINKFLAGS+= -S -x +.endif + +%LOAD + +assym.h: $S/kern/genassym.sh ${SOCPPC}/socppc/genassym.cf Makefile + sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} \ + < ${SOCPPC}/socppc/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_C} + +mcount.o: $S/lib/libkern/mcount.c Makefile + ${NORMAL_C_NOP} + +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.gdb tags *.[io] [a-z]*.s \ + [Ee]rrs linterrs makelinks genassym genassym.o 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= ${SOCPPC}/socppc/locore.S \ + param.c ioconf.c ${CFILES} ${SFILES} +depend:: .depend +.depend: ${SRCS} assym.h param.c + ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${SOCPPC}/socppc/locore.S + ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES} +.if ${SFILES} != "" + ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES} +.endif + sh $S/kern/genassym.sh ${MKDEP} -f assym.dep ${CFLAGS} \ + ${CPPFLAGS} < ${SOCPPC}/socppc/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 +genassym.o machdep.o: Makefile + +# depend on CPU configuration +locore.o machdep.o: Makefile + + +locore.o: ${SOCPPC}/socppc/locore.S assym.h + ${NORMAL_S} + +# 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/socppc/conf/files.socppc b/sys/arch/socppc/conf/files.socppc new file mode 100644 index 00000000000..d22ecf309f2 --- /dev/null +++ b/sys/arch/socppc/conf/files.socppc @@ -0,0 +1,93 @@ +# $OpenBSD: files.socppc,v 1.1 2008/05/10 12:02:20 kettenis Exp $ + +# +# macppc-specific configuration info +# +maxpartitions 16 + +maxusers 2 8 64 + +file arch/socppc/socppc/autoconf.c +file arch/socppc/socppc/clock.c +file arch/socppc/socppc/conf.c +file arch/socppc/socppc/disksubr.c disk +file arch/socppc/socppc/machdep.c +file arch/socppc/socppc/mem.c +file arch/socppc/socppc/dma.c +file dev/cninit.c +file arch/socppc/socppc/db_interface.c ddb + + +define mainbus {} +device mainbus +attach mainbus at root +file arch/socppc/socppc/mainbus.c mainbus + +device cpu +attach cpu at mainbus +file arch/socppc/socppc/cpu.c + +# MPC8349E on-board devices +device obio {addr, [ivec = -1]} +attach obio at mainbus +file arch/socppc/dev/obio.c + +# On-board IPIC +device ipic +attach ipic at obio +file arch/socppc/dev/ipic.c + +# On-board I2C +device sociic: i2cbus +attach sociic at obio +file arch/socppc/dev/sociic.c + +# On-board DUART +attach com at obio with com_obio +file arch/socppc/dev/com_obio.c + +# +# Media Independent Interface (mii) +# +include "../../../dev/mii/files.mii" + +major {rd = 17} +major {wd = 0} +major {sd = 2} +major {cd = 3} + +include "../../../scsi/files.scsi" + +# +# I2O +# +include "../../../dev/i2o/files.i2o" + +include "dev/pci/files.pci" +file arch/socppc/dev/pciide_machdep.c pciide + +# On-board PCI +device socpcic: pcibus +attach socpcic at obio +file arch/socppc/dev/socpcic.c + +# +# Machine-independent ATAPI drivers +# + +include "../../../dev/atapiscsi/files.atapiscsi" +include "../../../dev/ata/files.ata" + +# +# Machine-independent USB drivers +# +include "dev/usb/files.usb" + +# On-board USB +attach ehci at obio with ehci_obio +file arch/socppc/dev/ehci_obio.c + +# +# Machine-independent I2C drivers +# +include "dev/i2c/files.i2c" diff --git a/sys/arch/socppc/dev/com_obio.c b/sys/arch/socppc/dev/com_obio.c new file mode 100644 index 00000000000..c509c800e05 --- /dev/null +++ b/sys/arch/socppc/dev/com_obio.c @@ -0,0 +1,69 @@ +/* $OpenBSD: com_obio.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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/tty.h> + +#include <machine/autoconf.h> + +#include <dev/ic/comreg.h> +#include <dev/ic/comvar.h> + +int com_obio_match(struct device *, void *, void *); +void com_obio_attach(struct device *, struct device *, void *); + +struct cfattach com_obio_ca = { + sizeof(struct com_softc), com_obio_match, com_obio_attach +}; + +struct cfdriver com_obio_cd = { + NULL, "com", DV_DULL +}; + +int +com_obio_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + +void +com_obio_attach(struct device *parent, struct device *self, void *aux) +{ + struct com_softc *sc = (void *)self; + struct obio_attach_args *oa = aux; + + sc->sc_iot = oa->oa_iot; + sc->sc_iobase = oa->oa_offset; + sc->sc_frequency = 266666666; /* XXX */ + + if (sc->sc_iobase != comconsaddr) { + if (bus_space_map(sc->sc_iot, sc->sc_iobase, + COM_NPORTS, 0, &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } + } else + sc->sc_ioh = comconsioh; + + com_attach_subr(sc); + + intr_establish(oa->oa_ivec, IST_LEVEL, IPL_TTY, comintr, + sc, sc->sc_dev.dv_xname); +} diff --git a/sys/arch/socppc/dev/ehci_obio.c b/sys/arch/socppc/dev/ehci_obio.c new file mode 100644 index 00000000000..93039e45533 --- /dev/null +++ b/sys/arch/socppc/dev/ehci_obio.c @@ -0,0 +1,118 @@ +/* $OpenBSD: ehci_obio.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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/rwlock.h> +#include <sys/timeout.h> + +#include <machine/autoconf.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdivar.h> +#include <dev/usb/usb_mem.h> + +#include <dev/usb/ehcireg.h> +#include <dev/usb/ehcivar.h> + +#include <dev/pci/pcidevs.h> + +int ehci_obio_match(struct device *, void *, void *); +void ehci_obio_attach(struct device *, struct device *, void *); + +struct cfattach ehci_obio_ca = { + sizeof(struct ehci_softc), ehci_obio_match, ehci_obio_attach +}; + +struct cfdriver ehci_obio_cd = { + NULL, "ehci", DV_DULL +}; + +struct powerpc_bus_dma_tag ehci_bus_dma_tag = { + NULL, + _dmamap_create, + _dmamap_destroy, + _dmamap_load, + _dmamap_load_mbuf, + _dmamap_load_uio, + _dmamap_load_raw, + _dmamap_unload, + _dmamap_sync, + _dmamem_alloc, + _dmamem_free, + _dmamem_map, + _dmamem_unmap, + _dmamem_mmap +}; + +int +ehci_obio_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + +void +ehci_obio_attach(struct device *parent, struct device *self, void *aux) +{ + struct ehci_softc *sc = (void *)self; + struct obio_attach_args *oa = aux; + usbd_status r; + int s; + + sc->iot = oa->oa_iot; + sc->sc_size = 1024; + if (bus_space_map(sc->iot, oa->oa_offset, sc->sc_size, 0, &sc->ioh)) { + printf(": can't map registers\n"); + return; + } + + sc->sc_id_vendor = PCI_VENDOR_FREESCALE; + strlcpy(sc->sc_vendor, "Freescale", sizeof sc->sc_vendor); + + sc->sc_bus.dmatag = &ehci_bus_dma_tag; + + bus_space_write_4(sc->iot, sc->ioh, 0x400, 0x04000000); + bus_space_write_4(sc->iot, sc->ioh, 0x300, 0x1e000000); + + s = splhardusb(); + sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); + EOWRITE2(sc, EHCI_USBINTR, 0); + + intr_establish(oa->oa_ivec, IST_LEVEL, IPL_USB, ehci_intr, sc, + sc->sc_bus.bdev.dv_xname); + + r = ehci_init(sc); + if (r != USBD_NORMAL_COMPLETION) { + printf(": init failed, error=%d\n", r); + goto unmap_ret; + } + splx(s); + + printf("\n"); + + /* Attach usb device. */ + sc->sc_child = config_found((void *)sc, &sc->sc_bus, usbctlprint); + + return; + +unmap_ret: + bus_space_unmap(sc->iot, sc->ioh, sc->sc_size); + splx(s); +} diff --git a/sys/arch/socppc/dev/ipic.c b/sys/arch/socppc/dev/ipic.c new file mode 100644 index 00000000000..befc10c43e3 --- /dev/null +++ b/sys/arch/socppc/dev/ipic.c @@ -0,0 +1,333 @@ +/* $OpenBSD: ipic.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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/malloc.h> + +#include <machine/autoconf.h> +#include <machine/intr.h> + +#define IPIC_SICFR 0x00 +#define IPIC_SIVCR 0x04 +#define IPIC_SIPNR_H 0x08 +#define IPIC_SIPNR_L 0x0c +#define IPIC_SIPRR_A 0x10 +#define IPIC_SIPRR_D 0x1c +#define IPIC_SIMSR_H 0x20 +#define IPIC_SIMSR_L 0x24 +#define IPIC_SICNR 0x28 +#define IPIC_SEPNR 0x2c +#define IPIC_SMPRR_A 0x30 +#define IPIC_SMPRR_B 0x34 +#define IPIC_SEMSR 0x38 +#define IPIC_SECNR 0x3c +#define IPIC_SERSR 0x40 +#define IPIC_SERMR 0x44 +#define IPIC_SERCR 0x48 +#define IPIC_SIFCR_H 0x50 +#define IPIC_SIFCR_L 0x54 +#define IPIC_SEFCR 0x58 +#define IPIC_SERFR 0x5c +#define IPIC_SCVCR 0x60 +#define IPIC_SMVCR 0x64 + +#define IPIC_NVEC 128 + +#define IPIC_EXTERNAL(ivec) ((ivec) >= 17 && (ivec) <= 23) + +struct ipic_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + uint32_t sc_simsr_h[IPL_NUM]; + uint32_t sc_simsr_l[IPL_NUM]; + uint32_t sc_semsr[IPL_NUM]; +}; + +uint32_t ipic_imask; +struct intrhand *ipic_intrhand[IPIC_NVEC]; +struct ipic_softc *ipic_sc; + +int ipic_match(struct device *, void *, void *); +void ipic_attach(struct device *, struct device *, void *); + +struct cfattach ipic_ca = { + sizeof(struct ipic_softc), ipic_match, ipic_attach +}; + +struct cfdriver ipic_cd = { + NULL, "ipic", DV_DULL +}; + +uint32_t ipic_read(struct ipic_softc *, bus_addr_t); +void ipic_write(struct ipic_softc *, bus_addr_t, uint32_t); +uint32_t ipic_simsr_h(int); +uint32_t ipic_simsr_l(int); +uint32_t ipic_semsr(int); + +void ext_intr(void); +void ipic_do_pending_int(void); + +int +ipic_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + +void +ipic_attach(struct device *parent, struct device *self, void *aux) +{ + struct ipic_softc *sc = (void *)self; + struct obio_attach_args *oa = aux; + + sc->sc_iot = oa->oa_iot; + if (bus_space_map(sc->sc_iot, oa->oa_offset, 128, 0, &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } + + ipic_sc = sc; + printf("\n"); +} + +uint32_t +ipic_read(struct ipic_softc *sc, bus_addr_t addr) +{ + return (letoh32(bus_space_read_4(sc->sc_iot, sc->sc_ioh, addr))); +} + +void +ipic_write(struct ipic_softc *sc, bus_addr_t addr, uint32_t data) +{ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, addr, htole32(data)); +} + +uint32_t +ipic_simsr_h(int ivec) +{ + switch (ivec) { + case 9: + return 0x00000080; + case 10: + return 0x00000040; + case 39: + return 0x01000000; + } + + return 0; +} + +uint32_t +ipic_simsr_l(int ivec) +{ + return 0; +} + +uint32_t +ipic_semsr(int ivec) +{ + switch (ivec) { + case 17: + return 0x40000000; + case 18: + return 0x20000000; + case 19: + return 0x10000000; + case 20: + return 0x08000000; + case 21: + return 0x04000000; + case 22: + return 0x02000000; + case 23: + return 0x01000000; + } + + return 0; +} + +static void +intr_calculatemasks(void) +{ + struct ipic_softc *sc = ipic_sc; + int level; + + for (level = IPL_NONE; level < IPL_NUM; level++) + imask[level] = SINT_MASK | (1 << level); + + /* + * There are tty, network and disk drivers that use free() at interrupt + * time, so vm > (tty | net | bio). + * + * Enforce a hierarchy that gives slow devices a better chance at not + * dropping data. + */ + imask[IPL_NET] |= imask[IPL_BIO]; + imask[IPL_TTY] |= imask[IPL_NET]; + imask[IPL_VM] |= imask[IPL_TTY]; + imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK; + + /* + * These are pseudo-levels. + */ + imask[IPL_NONE] = 0x00000000; + imask[IPL_HIGH] = 0xffffffff; + + sc->sc_simsr_h[IPL_NET] |= sc->sc_simsr_h[IPL_BIO]; + sc->sc_simsr_h[IPL_TTY] |= sc->sc_simsr_h[IPL_NET]; + sc->sc_simsr_h[IPL_VM] |= sc->sc_simsr_h[IPL_TTY]; + sc->sc_simsr_h[IPL_NET] |= sc->sc_simsr_h[IPL_VM]; + sc->sc_simsr_h[IPL_HIGH] |= sc->sc_simsr_h[IPL_NET]; + + sc->sc_simsr_l[IPL_NET] |= sc->sc_simsr_l[IPL_BIO]; + sc->sc_simsr_l[IPL_TTY] |= sc->sc_simsr_l[IPL_NET]; + sc->sc_simsr_l[IPL_VM] |= sc->sc_simsr_l[IPL_TTY]; + sc->sc_simsr_l[IPL_NET] |= sc->sc_simsr_l[IPL_VM]; + sc->sc_simsr_l[IPL_HIGH] |= sc->sc_simsr_l[IPL_NET]; + + sc->sc_semsr[IPL_NET] |= sc->sc_semsr[IPL_BIO]; + sc->sc_semsr[IPL_TTY] |= sc->sc_semsr[IPL_NET]; + sc->sc_semsr[IPL_VM] |= sc->sc_semsr[IPL_TTY]; + sc->sc_semsr[IPL_NET] |= sc->sc_semsr[IPL_VM]; + sc->sc_semsr[IPL_HIGH] |= sc->sc_semsr[IPL_NET]; +} + +void * +intr_establish(int ivec, int type, int level, + int (*ih_fun)(void *), void *ih_arg, const char *name) +{ + struct ipic_softc *sc = ipic_sc; + struct intrhand **p, *q, *ih; + uint32_t mask; + + ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK); + if (ih == NULL) + panic("xxx"); + + if (ivec < 0 || ivec >= IPIC_NVEC) + panic("xxx"); + + for (p = &ipic_intrhand[ivec]; (q = *p) != NULL; p = &q->ih_next) + ; + + sc->sc_simsr_h[level] |= ipic_simsr_h(ivec); + sc->sc_simsr_l[level] |= ipic_simsr_l(ivec); + sc->sc_semsr[level] |= ipic_semsr(ivec); + intr_calculatemasks(); + + ih->ih_fun = ih_fun; + ih->ih_arg = ih_arg; + ih->ih_next = NULL; + ih->ih_level = level; + ih->ih_irq = ivec; + evcount_attach(&ih->ih_count, name, NULL, &evcount_intr); + *p = ih; + + /* Unmask the interrupt. */ + mask = ipic_read(sc, IPIC_SIMSR_H); + mask |= ipic_simsr_h(ivec); + ipic_write(sc, IPIC_SIMSR_H, mask); + mask = ipic_read(sc, IPIC_SIMSR_L); + mask |= ipic_simsr_l(ivec); + ipic_write(sc, IPIC_SIMSR_L, mask); + mask = ipic_read(sc, IPIC_SEMSR); + mask |= ipic_semsr(ivec); + ipic_write(sc, IPIC_SEMSR, mask); + + return (ih); +} + +void +ext_intr(void) +{ + struct cpu_info *ci = curcpu(); + struct ipic_softc *sc = ipic_sc; + struct intrhand *ih; + uint32_t simsr_h, simsr_l, semsr; + int pcpl, ocpl; + int ivec; + + pcpl = ci->ci_cpl; + ivec = ipic_read(sc, IPIC_SIVCR) & 0x7f; + + simsr_h = ipic_read(sc, IPIC_SIMSR_H); + simsr_l = ipic_read(sc, IPIC_SIMSR_L); + semsr = ipic_read(sc, IPIC_SEMSR); + ipic_write(sc, IPIC_SIMSR_H, simsr_h & ~ipic_simsr_h(ivec)); + ipic_write(sc, IPIC_SIMSR_L, simsr_l & ~ipic_simsr_l(ivec)); + ipic_write(sc, IPIC_SEMSR, semsr & ~ipic_semsr(ivec)); + + ih = ipic_intrhand[ivec]; + while (ih) { + if (ci->ci_cpl & (1 << ih->ih_level)) { + ci->ci_ipending |= (1 << ih->ih_level); + return; + } + + ipic_write(sc, IPIC_SIMSR_H, sc->sc_simsr_h[ih->ih_level]); + ipic_write(sc, IPIC_SIMSR_L, sc->sc_simsr_l[ih->ih_level]); + ipic_write(sc, IPIC_SEMSR, sc->sc_semsr[ih->ih_level]); + ocpl = splraise(imask[ih->ih_level]); + ppc_intr_enable(1); + + KERNEL_LOCK(); + if ((*ih->ih_fun)(ih->ih_arg)) + ih->ih_count.ec_count++; + KERNEL_UNLOCK(); + + ppc_intr_disable(); + ci->ci_cpl = ocpl; + ih = ih->ih_next; + } + + ipic_write(sc, IPIC_SIMSR_H, simsr_h); + ipic_write(sc, IPIC_SIMSR_L, simsr_l); + ipic_write(sc, IPIC_SEMSR, semsr); + splx(pcpl); +} + +static __inline int +cntlzw(int x) +{ + int a; + + __asm __volatile("cntlzw %0,%1" : "=r"(a) : "r"(x)); + + return a; +} + +void +ipic_do_pending_int(void) +{ + struct cpu_info *ci = curcpu(); + struct ipic_softc *sc = ipic_sc; + uint32_t mask; + int level; + + ci->ci_ipending &= SINT_MASK; + level = cntlzw(31 - (ci->ci_cpl & ~(SPL_CLOCK|SINT_MASK))); + mask = sc->sc_simsr_h[IPL_HIGH] & ~sc->sc_simsr_h[level]; + ipic_write(sc, IPIC_SIMSR_H, mask); + mask = sc->sc_simsr_l[IPL_HIGH] & ~sc->sc_simsr_l[level]; + ipic_write(sc, IPIC_SIMSR_L, mask); + mask = sc->sc_semsr[IPL_HIGH] & ~sc->sc_semsr[level]; + ipic_write(sc, IPIC_SEMSR, mask); +} diff --git a/sys/arch/socppc/dev/obio.c b/sys/arch/socppc/dev/obio.c new file mode 100644 index 00000000000..036564fc8a4 --- /dev/null +++ b/sys/arch/socppc/dev/obio.c @@ -0,0 +1,83 @@ +/* $OpenBSD: obio.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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 <machine/autoconf.h> + +int obio_match(struct device *, void *, void *); +void obio_attach(struct device *, struct device *, void *); + +struct cfattach obio_ca = { + sizeof(struct device), obio_match, obio_attach +}; + +struct cfdriver obio_cd = { + NULL, "obio", DV_DULL +}; + +int obio_search(struct device *, void *, void *); +int obio_print(void *, const char *); + +int +obio_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + +void +obio_attach(struct device *parent, struct device *self, void *aux) +{ + printf("\n"); + + config_search(obio_search, self, aux); +} + +int +obio_search(struct device *parent, void *cfdata, void *aux) +{ + struct mainbus_attach_args *ma = aux; + struct obio_attach_args oa; + struct cfdata *cf = cfdata; + + bzero(&oa, sizeof oa); + oa.oa_iot = ma->ma_iot; + oa.oa_name = cf->cf_driver->cd_name; + oa.oa_offset = cf->cf_offset; + oa.oa_ivec = cf->cf_ivec; + config_found(parent, &oa, obio_print); + + return (1); +} + +int +obio_print(void *aux, const char *name) +{ + struct obio_attach_args *oa = aux; + + if (name) + printf("%s at %s", oa->oa_name, name); + if (oa->oa_offset) + printf(" offset 0x%05x", oa->oa_offset); + if (oa->oa_ivec != -1) + printf(" ivec %d", oa->oa_ivec); + + return (UNCONF); +} diff --git a/sys/arch/socppc/dev/pciide_machdep.c b/sys/arch/socppc/dev/pciide_machdep.c new file mode 100644 index 00000000000..b9b3ab8a9c9 --- /dev/null +++ b/sys/arch/socppc/dev/pciide_machdep.c @@ -0,0 +1,40 @@ +/* $OpenBSD: pciide_machdep.c,v 1.1 2008/05/10 12:02:20 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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 <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pciidereg.h> +#include <dev/pci/pciidevar.h> + +#include <machine/autoconf.h> + +void * +pciide_machdep_compat_intr_establish(struct device *dev, + struct pci_attach_args *pa, int chan, int (*func)(void *), void *arg) +{ + return (NULL); +} + +void +pciide_machdep_compat_intr_disestablish(pci_chipset_tag_t pc, void *cookie) +{ +} diff --git a/sys/arch/socppc/dev/sociic.c b/sys/arch/socppc/dev/sociic.c new file mode 100644 index 00000000000..b35c0397963 --- /dev/null +++ b/sys/arch/socppc/dev/sociic.c @@ -0,0 +1,290 @@ +/* $OpenBSD: sociic.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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. + */ + +/* + * Driver for the I2C interface on the MPC8349E processors. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/rwlock.h> + +#include <machine/autoconf.h> +#include <machine/bus.h> + +#include <dev/i2c/i2cvar.h> + +#define I2C_ADR 0x00 /* Address Register */ +#define I2C_FDR 0x04 /* Fequency Divider Register */ +#define I2C_CR 0x08 /* Control Register */ +#define I2C_CR_MEN 0x80 +#define I2C_CR_MIEN 0x40 +#define I2C_CR_MSTA 0x20 +#define I2C_CR_MTX 0x10 +#define I2C_CR_TXAK 0x08 +#define I2C_CR_RSTA 0x04 +#define I2C_CR_BCST 0x01 +#define I2C_SR 0x0c /* Status Register */ +#define I2C_SR_MCF 0x80 +#define I2C_SR_MAAS 0x40 +#define I2C_SR_MBB 0x20 +#define I2C_SR_MAL 0x10 +#define I2C_SR_BCSTM 0x08 +#define I2C_SR_SRW 0x04 +#define I2C_SR_MIF 0x02 +#define I2C_SR_RXAK 0x01 +#define I2C_DR 0x10 /* Data Register */ +#define I2C_DFSRR 0x14 /* Digital Filter Sampling Rate Register */ + +struct sociic_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + struct i2c_controller sc_i2c; + struct rwlock sc_lock; +}; + +int sociic_match(struct device *, void *, void *); +void sociic_attach(struct device *, struct device *, void *); + +struct cfattach sociic_ca = { + sizeof(struct sociic_softc), sociic_match, sociic_attach +}; + +struct cfdriver sociic_cd = { + NULL, "sociic", DV_DULL +}; + +void sociic_write(struct sociic_softc *, bus_addr_t, uint8_t); +uint8_t sociic_read(struct sociic_softc *, bus_addr_t); +int sociic_wait(struct sociic_softc *, int); +int sociic_wait_bus(struct sociic_softc *); +int sociic_i2c_acquire_bus(void *, int); +void sociic_i2c_release_bus(void *, int); +int sociic_i2c_exec(void *, i2c_op_t, i2c_addr_t, + const void *, size_t, void *, size_t, int); + +int +sociic_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + +void +sociic_attach(struct device *parent, struct device *self, void *aux) +{ + struct sociic_softc *sc = (void *)self; + struct obio_attach_args *oa = aux; + struct i2cbus_attach_args iba; + + sc->sc_iot = oa->oa_iot; + if (bus_space_map(sc->sc_iot, oa->oa_offset, 24, 0, &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } + + printf("\n"); + + rw_init(&sc->sc_lock, "iiclk"); + sc->sc_i2c.ic_cookie = sc; + sc->sc_i2c.ic_acquire_bus = sociic_i2c_acquire_bus; + sc->sc_i2c.ic_release_bus = sociic_i2c_release_bus; + sc->sc_i2c.ic_exec = sociic_i2c_exec; + + bzero(&iba, sizeof iba); + iba.iba_name = "iic"; + iba.iba_tag = &sc->sc_i2c; + config_found(&sc->sc_dev, &iba, iicbus_print); +} + +void +sociic_write(struct sociic_softc *sc, bus_addr_t addr, uint8_t data) +{ + bus_space_write_1(sc->sc_iot, sc->sc_ioh, addr, data); +} + +uint8_t +sociic_read(struct sociic_softc *sc, bus_addr_t addr) +{ + return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, addr)); +} + +int +sociic_wait(struct sociic_softc *sc, int flags) +{ + uint8_t sr; + int i; + + for (i = 0; i < 1000; i++) { + sr = sociic_read(sc, I2C_SR); + if (sr & I2C_SR_MIF) { + sociic_write(sc, I2C_SR, 0); + + if (sr & I2C_SR_MAL) + return (EIO); + + if ((sr & I2C_SR_MCF) == 0) + return (EIO); + + if ((flags & I2C_F_READ) == 0 && (sr & I2C_SR_RXAK)) + return (EIO); + + return (0); + } + delay(100); + } + + return (ETIMEDOUT); +} + +int +sociic_wait_bus(struct sociic_softc *sc) +{ + uint8_t sr; + int i; + + for (i = 0; i < 1000; i++) { + sr = sociic_read(sc, I2C_SR); + if ((sr & I2C_SR_MBB) == 0) + return (0); + delay(1000); + } + + return (ETIMEDOUT); +} + +int +sociic_i2c_acquire_bus(void *arg, int flags) +{ + struct sociic_softc *sc = arg; + + if (cold || (flags & I2C_F_POLL)) + return (0); + + return (rw_enter(&sc->sc_lock, RW_WRITE | RW_INTR)); +} + +void +sociic_i2c_release_bus(void *arg, int flags) +{ + struct sociic_softc *sc = arg; + + if (cold || (flags & I2C_F_POLL)) + return; + + rw_exit(&sc->sc_lock); +} + +int +sociic_i2c_exec(void *arg, i2c_op_t op, i2c_addr_t addr, + const void *vcmdbuf, size_t cmdlen, void *vbuf, size_t buflen, int flags) +{ + struct sociic_softc *sc = arg; + const uint8_t *cmdbuf = vcmdbuf; + uint8_t *buf = vbuf; + int err = 0; + size_t len; + uint8_t val; + + /* Clear the bus. */ + sociic_write(sc, I2C_SR, 0); + sociic_write(sc, I2C_CR, I2C_CR_MEN); + err = sociic_wait_bus(sc); + if (err) + return (err); + + if (cmdlen > 0) { + sociic_write(sc, I2C_CR, I2C_CR_MEN|I2C_CR_MSTA|I2C_CR_MTX); + sociic_write(sc, I2C_DR, addr << 1); + err = sociic_wait(sc, I2C_F_WRITE); + if (err) + goto out; + + len = cmdlen; + while (len--) { + sociic_write(sc, I2C_DR, *cmdbuf++); + err = sociic_wait(sc, I2C_F_WRITE); + if (err) + goto out; + } + } + + if (I2C_OP_READ_P(op) && buflen > 0) { + /* RESTART if we did write a command above. */ + val = I2C_CR_MEN|I2C_CR_MSTA|I2C_CR_MTX; + if (cmdlen > 0) + val |= I2C_CR_RSTA; + sociic_write(sc, I2C_CR, val); + sociic_write(sc, I2C_DR, (addr << 1) | 1); + err = sociic_wait(sc, I2C_F_WRITE); + if (err) + goto out; + + /* NACK if we're only sending one byte. */ + val = I2C_CR_MEN|I2C_CR_MSTA; + if (buflen == 1) + val |= I2C_CR_TXAK; + sociic_write(sc, I2C_CR, val); + + /* Dummy read. */ + sociic_read(sc, I2C_DR); + + len = buflen; + while (len--) { + err = sociic_wait(sc, I2C_F_READ); + if (err) + goto out; + + /* NACK on last byte. */ + if (len == 1) + sociic_write(sc, I2C_CR, + I2C_CR_MEN|I2C_CR_MSTA|I2C_CR_TXAK); + /* STOP after last byte. */ + if (len == 0) + sociic_write(sc, I2C_CR, + I2C_CR_MEN|I2C_CR_TXAK); + *buf++ = sociic_read(sc, I2C_DR); + } + } + + if (I2C_OP_WRITE_P(op) && cmdlen == 0 && buflen > 0) { + /* START if we didn't write a command. */ + sociic_write(sc, I2C_CR, I2C_CR_MEN|I2C_CR_MSTA|I2C_CR_MTX); + sociic_write(sc, I2C_DR, addr << 1); + err = sociic_wait(sc, I2C_F_WRITE); + if (err) + goto out; + } + + if (I2C_OP_WRITE_P(op) && buflen > 0) { + len = buflen; + while (len--) { + sociic_write(sc, I2C_DR, *buf++); + err = sociic_wait(sc, I2C_F_WRITE); + if (err) + goto out; + } + } + +out: + /* STOP if we're still holding the bus. */ + sociic_write(sc, I2C_CR, I2C_CR_MEN); + return (err); +} diff --git a/sys/arch/socppc/dev/socpcic.c b/sys/arch/socppc/dev/socpcic.c new file mode 100644 index 00000000000..94fef8a70f6 --- /dev/null +++ b/sys/arch/socppc/dev/socpcic.c @@ -0,0 +1,266 @@ +/* $OpenBSD: socpcic.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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 <machine/autoconf.h> +#include <machine/bus.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +struct socpcic_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_cfg_ioh; + struct ppc_bus_space sc_mem_bus_space; + struct ppc_bus_space sc_io_bus_space; + struct ppc_pci_chipset sc_pc; +}; + +int socpcic_match(struct device *, void *, void *); +void socpcic_attach(struct device *, struct device *, void *); + +struct cfattach socpcic_ca = { + sizeof(struct socpcic_softc), socpcic_match, socpcic_attach +}; + +struct cfdriver socpcic_cd = { + NULL, "socpcic", DV_DULL +}; + +void socpcic_attach_hook(struct device *, struct device *, + struct pcibus_attach_args *); +int socpcic_bus_maxdevs(void *, int); +pcitag_t socpcic_make_tag(void *, int, int, int); +void socpcic_decompose_tag(void *, pcitag_t, int *, int *, int *); +pcireg_t socpcic_conf_read(void *, pcitag_t, int); +void socpcic_conf_write(void *, pcitag_t, int, pcireg_t); +int socpcic_intr_map(void *, pcitag_t, int, int, pci_intr_handle_t *); +const char *socpcic_intr_string(void *, pci_intr_handle_t); +int socpcic_intr_line(void *, pci_intr_handle_t); +void *socpcic_intr_establish(void *, pci_intr_handle_t, int, + int (*)(void *), void *, char *); +void socpcic_intr_disestablish(void *, void *); +int socpcic_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *); + +int socpcic_print(void *, const char *); + +struct powerpc_bus_dma_tag pci_bus_dma_tag = { + NULL, + _dmamap_create, + _dmamap_destroy, + _dmamap_load, + _dmamap_load_mbuf, + _dmamap_load_uio, + _dmamap_load_raw, + _dmamap_unload, + _dmamap_sync, + _dmamem_alloc, + _dmamem_free, + _dmamem_map, + _dmamem_unmap, + _dmamem_mmap +}; + +int +socpcic_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + +void +socpcic_attach(struct device *parent, struct device *self, void *aux) +{ + struct socpcic_softc *sc = (void *)self; + struct obio_attach_args *oa = aux; + struct pcibus_attach_args pba; + + sc->sc_iot = oa->oa_iot; + if (bus_space_map(sc->sc_iot, oa->oa_offset, 16, 0, &sc->sc_cfg_ioh)) { + printf(": can't map configuration registers\n"); + return; + } + + sc->sc_io_bus_space.bus_base = 0xe2000000; + sc->sc_io_bus_space.bus_size = 0x01000000; + + sc->sc_pc.pc_conf_v = sc; + sc->sc_pc.pc_attach_hook = socpcic_attach_hook; + sc->sc_pc.pc_bus_maxdevs = socpcic_bus_maxdevs; + sc->sc_pc.pc_make_tag = socpcic_make_tag; + sc->sc_pc.pc_decompose_tag = socpcic_decompose_tag; + sc->sc_pc.pc_conf_read = socpcic_conf_read; + sc->sc_pc.pc_conf_write = socpcic_conf_write; + + sc->sc_pc.pc_intr_v = sc; + sc->sc_pc.pc_intr_map = socpcic_intr_map; + sc->sc_pc.pc_intr_string = socpcic_intr_string; + sc->sc_pc.pc_intr_line = socpcic_intr_line; + sc->sc_pc.pc_intr_establish = socpcic_intr_establish; + sc->sc_pc.pc_intr_disestablish = socpcic_intr_disestablish; + sc->sc_pc.pc_ether_hw_addr = socpcic_ether_hw_addr; + + pba.pba_busname = "pci"; + pba.pba_iot = &sc->sc_io_bus_space; + pba.pba_memt = &sc->sc_mem_bus_space; + pba.pba_dmat = &pci_bus_dma_tag; + pba.pba_pc = &sc->sc_pc; + pba.pba_domain = pci_ndomains++; + pba.pba_bus = 0; + pba.pba_bridgetag = NULL; + + printf("\n"); + + config_found(self, &pba, socpcic_print); +} + +void +socpcic_attach_hook(struct device *parent, struct device *self, + struct pcibus_attach_args *pba) +{ +} + +int +socpcic_bus_maxdevs(void *cpv, int bus) +{ + return (32); +} + +pcitag_t +socpcic_make_tag(void *cpv, int bus, int dev, int fun) +{ + return ((bus << 16) | (dev << 11) | (fun << 8)); +} + +void +socpcic_decompose_tag(void *cpv, pcitag_t tag, int *busp, int *devp, int *funp) +{ + if (busp) + *busp = (tag >> 16) & 0xff; + if (devp) + *devp = (tag >> 11) & 0x1f; + if (funp) + *funp = (tag >> 8) & 0x7; +} + +pcireg_t +socpcic_conf_read(void *cpv, pcitag_t tag, int offset) +{ + struct socpcic_softc *sc = cpv; + int bus, dev, fun; + pcireg_t addr, data; + + socpcic_decompose_tag(sc, tag, &bus, &dev, &fun); + if (bus == 0) { + if (dev > 0 && dev < 11) + return (0xffffffff); + if (dev == 31) + tag = (10 << 11) | (fun << 8); + } + + addr = 0x80000000 | tag | offset; + bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 0, addr); + bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 0); + data = bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 4); + bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 0, 0); + bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 0); + + return (data); +} + +void +socpcic_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) +{ + struct socpcic_softc *sc = cpv; + int bus, dev, fun; + pcireg_t addr; + + socpcic_decompose_tag(sc, tag, &bus, &dev, &fun); + if (bus == 0) { + if (dev > 0 && dev < 11) + return; + if (dev == 31) + tag = (10 << 11) | (fun << 8); + } + + addr = 0x80000000 | tag | offset; + bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 0, addr); + bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 0); + bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 4, data); + bus_space_write_4(sc->sc_iot, sc->sc_cfg_ioh, 0, 0); + bus_space_read_4(sc->sc_iot, sc->sc_cfg_ioh, 0); +} + +int +socpcic_intr_map(void *cpv, pcitag_t tag, int pin, int line, + pci_intr_handle_t *ihp) +{ + *ihp = 20; /* XXX */ + return (0); +} + +const char * +socpcic_intr_string(void *cpv, pci_intr_handle_t ih) +{ + static char str[16]; + + snprintf(str, sizeof str, "ivec %ld", ih); + return (str); +} + +int +socpcic_intr_line(void *cpv, pci_intr_handle_t ih) +{ + return (ih); +} + +void * +socpcic_intr_establish(void *cpv, pci_intr_handle_t ih, int level, + int (*func)(void *), void *arg, char *name) +{ + return (intr_establish(ih, IST_LEVEL, level, func, arg, name)); +} + +void +socpcic_intr_disestablish(void *lcv, void *cookie) +{ +} + +int +socpcic_ether_hw_addr(struct ppc_pci_chipset *lcpc, u_int8_t *oaddr) +{ + oaddr[0] = oaddr[1] = oaddr[2] = 0xff; + oaddr[3] = oaddr[4] = oaddr[5] = 0xff; + + return (0); +} + +int +socpcic_print(void *aux, const char *pnp) +{ + struct pcibus_attach_args *pba = aux; + + if (pnp) + printf("%s at %s", pba->pba_busname, pnp); + printf(" bus %d", pba->pba_bus); + return (UNCONF); +} diff --git a/sys/arch/socppc/include/_types.h b/sys/arch/socppc/include/_types.h new file mode 100644 index 00000000000..f6f4ea673a5 --- /dev/null +++ b/sys/arch/socppc/include/_types.h @@ -0,0 +1,3 @@ +/* $OpenBSD: _types.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/_types.h> diff --git a/sys/arch/socppc/include/asm.h b/sys/arch/socppc/include/asm.h new file mode 100644 index 00000000000..35852110f54 --- /dev/null +++ b/sys/arch/socppc/include/asm.h @@ -0,0 +1,3 @@ +/* $OpenBSD: asm.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/asm.h> diff --git a/sys/arch/socppc/include/atomic.h b/sys/arch/socppc/include/atomic.h new file mode 100644 index 00000000000..1dbd296cee4 --- /dev/null +++ b/sys/arch/socppc/include/atomic.h @@ -0,0 +1,3 @@ +/* $OpenBSD: atomic.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/atomic.h> diff --git a/sys/arch/socppc/include/autoconf.h b/sys/arch/socppc/include/autoconf.h new file mode 100644 index 00000000000..0f9ba3fc9e7 --- /dev/null +++ b/sys/arch/socppc/include/autoconf.h @@ -0,0 +1,45 @@ +/* $OpenBSD: autoconf.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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_AUTOCONF_H_ +#define _MACHINE_AUTOCONF_H_ + +#include <machine/bus.h> + +struct mainbus_attach_args { + bus_space_tag_t ma_iot; + char *ma_name; +}; + +struct obio_attach_args { + bus_space_tag_t oa_iot; + bus_addr_t oa_offset; + int oa_ivec; + char *oa_name; +}; + +#define cf_offset cf_loc[0] +#define cf_ivec cf_loc[1] + +typedef int (time_read_t)(time_t *sec); +typedef int (time_write_t)(time_t sec); + +extern time_read_t *time_read; +extern time_write_t *time_write; + +#endif /* _MACHINE_AUTOCONF_H_ */ diff --git a/sys/arch/socppc/include/bat.h b/sys/arch/socppc/include/bat.h new file mode 100644 index 00000000000..16a586e725d --- /dev/null +++ b/sys/arch/socppc/include/bat.h @@ -0,0 +1,3 @@ +/* $OpenBSD: bat.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/bat.h> diff --git a/sys/arch/socppc/include/bus.h b/sys/arch/socppc/include/bus.h new file mode 100644 index 00000000000..81696e1d3ec --- /dev/null +++ b/sys/arch/socppc/include/bus.h @@ -0,0 +1,609 @@ +/* $OpenBSD: bus.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom. All rights reserved. + * Copyright (c) 1996 Niklas Hallqvist. 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 + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_BUS_H_ +#define _MACHINE_BUS_H_ + +#include <machine/pio.h> + +#ifdef __STDC__ +#define CAT(a,b) a##b +#define CAT3(a,b,c) a##b##c +#else +#define CAT(a,b) a/**/b +#define CAT3(a,b,c) a/**/b/**/c +#endif + +/* + * Bus access types. + */ +typedef u_long bus_addr_t; +typedef u_int32_t bus_size_t; +typedef u_int32_t bus_space_handle_t; +typedef struct ppc_bus_space *bus_space_tag_t; + +struct ppc_bus_space { + u_int32_t bus_base; + u_int32_t bus_size; + u_int8_t bus_io; /* IO or memory */ +}; +#define POWERPC_BUS_TAG_BASE(x) ((x)->bus_base) + +extern struct ppc_bus_space ppc_isa_io, ppc_isa_mem; + +/* + * Access methods for bus resources + */ +int bus_space_map(bus_space_tag_t t, bus_addr_t addr, + bus_size_t size, int cacheable, bus_space_handle_t *bshp); +void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t size); +int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp); +int bus_space_alloc(bus_space_tag_t tag, bus_addr_t rstart, + bus_addr_t rend, bus_size_t size, bus_size_t alignment, + bus_size_t boundary, int cacheable, bus_addr_t *addrp, + bus_space_handle_t *handlep); +void bus_space_free(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t size); + +#define bus_space_read(n,m) \ +static __inline CAT3(u_int,m,_t) \ +CAT(bus_space_read_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba) \ +{ \ + return CAT3(in,m,rb)((volatile CAT3(u_int,m,_t) *)(bsh + (ba))); \ +} + +bus_space_read(1,8) +bus_space_read(2,16) +bus_space_read(4,32) + +#define bus_space_read_8 !!! bus_space_read_8 unimplemented !!! + +#define bus_space_write(n,m) \ +static __inline void \ +CAT(bus_space_write_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_addr_t ba, CAT3(u_int,m,_t) x) \ +{ \ + CAT3(out,m,rb)((volatile CAT3(u_int,m,_t) *)(bsh + (ba)), x); \ +} + +bus_space_write(1,8) +bus_space_write(2,16) +bus_space_write(4,32) + +#define bus_space_write_8 !!! bus_space_write_8 unimplemented !!! + +#define bus_space_read_multi(n, m) \ +static __inline void \ +CAT(bus_space_read_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t ba, CAT3(u_int,m,_t) *buf, bus_size_t cnt) \ +{ \ + while (cnt--) \ + *buf++ = CAT(bus_space_read_,n)(bst, bsh, ba); \ +} + +bus_space_read_multi(1,8) +bus_space_read_multi(2,16) +bus_space_read_multi(4,32) + +#define bus_space_read_multi_8 !!! bus_space_read_multi_8 not implemented !!! + + +#define bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!! + +#define bus_space_write_multi(n, m) \ +static __inline void \ +CAT(bus_space_write_multi_,n)(bus_space_tag_t bst, bus_space_handle_t bsh, \ + bus_size_t ba, const CAT3(u_int,m,_t) *buf, bus_size_t cnt) \ +{ \ + while (cnt--) \ + CAT(bus_space_write_,n)(bst, bsh, ba, *buf++); \ +} + +bus_space_write_multi(1,8) +bus_space_write_multi(2,16) +bus_space_write_multi(4,32) + +#define bus_space_write_multi_8 !!! bus_space_write_multi_8 not implemented !!! + +/* + * void bus_space_read_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ +#define __BA(t, h, o) ((void *)((h) + (o))) + +static __inline void +bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int8_t *s = __BA(tag, bsh, offset); + + while (count--) + *addr++ = *s++; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + volatile u_int16_t *s = __BA(tag, bsh, offset); + + while (count--) + __asm __volatile("lhbrx %0, 0, %1" : + "=r"(*addr++) : "r"(s++)); + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + volatile u_int32_t *s = __BA(tag, bsh, offset); + + while (count--) + __asm __volatile("lwbrx %0, 0, %1" : + "=r"(*addr++) : "r"(s++)); + __asm __volatile("eieio; sync"); +} + +#if 0 /* Cause a link error for bus_space_read_region_8 */ +#define bus_space_read_region_8 !!! unimplemented !!! +#endif + + +/* + * void bus_space_write_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + +static __inline void +bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int8_t *d = __BA(tag, bsh, offset); + + while (count--) + *d++ = *addr++; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int16_t *addr, size_t count) +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm __volatile("sthbrx %0, 0, %1" :: + "r"(*addr++), "r"(d++)); + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm __volatile("stwbrx %0, 0, %1" :: + "r"(*addr++), "r"(d++)); + __asm __volatile("eieio; sync"); +} + +#if 0 +#define bus_space_write_region_8 !!! bus_space_write_region_8 unimplemented !!! +#endif + +/* + * void bus_space_read_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count); + * + * Read `count' bytes from bus space described by tag/handle and starting + * at `offset' and copy into buffer provided w/o bus-host byte swapping. + */ + +static __inline void +bus_space_read_raw_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int16_t *s = __BA(tag, bsh, offset); + u_int16_t *laddr = (void *)addr; + + count = count >> 1; + + while (count--) + *laddr++ = *s++; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_read_raw_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int32_t *s = __BA(tag, bsh, offset); + u_int32_t *laddr = (void *)addr; + + count = count >> 2; + + while (count--) + *laddr++ = *s++; + __asm __volatile("eieio; sync"); +} + +#if 0 /* Cause a link error for bus_space_read_raw_region_8 */ +#define bus_space_read_raw_region_8 \ + !!! bus_space_read_raw_region_8 unimplemented !!! +#endif + + +/* + * void bus_space_write_raw_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count); + * + * Write `count' bytes from the buffer provided to bus space described + * by tag/handle starting at `offset' w/o host-bus byte swapping. + */ + +static __inline void +bus_space_write_raw_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + const u_int16_t *laddr = (void *)addr; + + count = count >> 1; + + while (count--) + *d++ = *laddr++; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_write_raw_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + const u_int32_t *laddr = (void *)addr; + + count = count >> 2; + + while (count--) + *d++ = *laddr++; + __asm __volatile("eieio; sync"); +} + +#if 0 +#define bus_space_write_raw_region_8 \ + !!! bus_space_write_raw_region_8 unimplemented !!! +#endif + +/* + * void bus_space_set_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ +static __inline void bus_space_set_multi_1(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int8_t, size_t); +static __inline void bus_space_set_multi_2(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int16_t, size_t); +static __inline void bus_space_set_multi_4(bus_space_tag_t, + bus_space_handle_t, bus_size_t, u_int32_t, size_t); + +static __inline void +bus_space_set_multi_1(tag, bsh, offset, val, count) + bus_space_tag_t tag; + bus_space_handle_t bsh; + bus_size_t offset; + u_int8_t val; + size_t count; +{ + volatile u_int8_t *d = __BA(tag, bsh, offset); + + while (count--) + *d = val; + __asm__ volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_2(tag, bsh, offset, val, count) + bus_space_tag_t tag; + bus_space_handle_t bsh; + bus_size_t offset; + u_int16_t val; + size_t count; +{ + volatile u_int16_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm__ volatile("sthbrx %0, 0, %1" :: + "r"(val), "r"(d)); + __asm__ volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_4(tag, bsh, offset, val, count) + bus_space_tag_t tag; + bus_space_handle_t bsh; + bus_size_t offset; + u_int32_t val; + size_t count; +{ + volatile u_int32_t *d = __BA(tag, bsh, offset); + + while (count--) + __asm__ volatile("stwbrx %0, 0, %1" :: + "r"(val), "r"(d)); + __asm__ volatile("eieio; sync"); +} + +#define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! + +/* These are OpenBSD extensions to the general NetBSD bus interface. */ +void +bus_space_read_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, u_int8_t *dst, bus_size_t size); +void +bus_space_read_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, u_int8_t *dst, bus_size_t size); +#define bus_space_read_raw_multi_8 \ + !!! bus_space_read_raw_multi_8 not implemented !!! + +void +bus_space_write_raw_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, const u_int8_t *src, bus_size_t size); +void +bus_space_write_raw_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, + bus_addr_t ba, const u_int8_t *src, bus_size_t size); +#define bus_space_write_raw_multi_8 \ + !!! bus_space_write_raw_multi_8 not implemented !!! + +void +bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int8_t val, bus_size_t c); +void +bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int16_t val, bus_size_t c); +void +bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t h, bus_size_t o, + u_int32_t val, bus_size_t c); +#define bus_space_set_region_8 \ + !!! bus_space_set_region_8 not implemented !!! + +void +bus_space_copy_1(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +void +bus_space_copy_2(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +void +bus_space_copy_4(void *v, bus_space_handle_t h1, bus_space_handle_t h2, + bus_size_t o1, bus_size_t o2, bus_size_t c); +#define bus_space_copy_8 \ + !!! bus_space_write_raw_multi_8 not implemented !!! + +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags); + * + * Note: powerpc does not currently implement barriers, but we must + * provide the flags to MI code. + * the processor does have eieio which is effectively the barrier + * operator, however due to how memory is mapped this should? not + * be required. + */ +#define bus_space_barrier(t, h, o, l, f) \ + ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ +/* Compatibility defines */ +#define BUS_BARRIER_READ BUS_SPACE_BARRIER_READ +#define BUS_BARRIER_WRITE BUS_SPACE_BARRIER_WRITE + + +#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_DMAMEM_NOSYNC 0x004 +#define BUS_DMA_COHERENT 0x008 /* hint: map memory DMA coherent */ +#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ +#define BUS_DMA_BUS2 0x020 +#define BUS_DMA_BUS3 0x040 +#define BUS_DMA_BUS4 0x080 +#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ +#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ +#define BUS_DMA_STREAMING 0x400 /* hint: sequential, unidirectional */ + + +/* Forwards needed by prototypes below. */ +struct mbuf; +struct proc; +struct uio; + +#define BUS_DMASYNC_POSTREAD 0x01 +#define BUS_DMASYNC_POSTWRITE 0x02 +#define BUS_DMASYNC_PREREAD 0x04 +#define BUS_DMASYNC_PREWRITE 0x08 + +typedef struct powerpc_bus_dma_tag *bus_dma_tag_t; +typedef struct powerpc_bus_dmamap *bus_dmamap_t; + +/* + * bus_dma_segment_t + * + * Describes a single contiguous DMA transaction. Values + * are suitable for programming into DMA registers. + */ +struct powerpc_bus_dma_segment { + bus_addr_t ds_addr; /* DMA address */ + bus_size_t ds_len; /* length of transfer */ +}; +typedef struct powerpc_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 powerpc_bus_dma_tag { + void *_cookie; /* cookie used in the guts */ + + /* + * DMA mapping methods. + */ + int (*_dmamap_create)(bus_dma_tag_t , bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); + void (*_dmamap_destroy)(bus_dma_tag_t , bus_dmamap_t); + int (*_dmamap_load)(bus_dma_tag_t , bus_dmamap_t, void *, + bus_size_t, struct proc *, int); + int (*_dmamap_load_mbuf)(bus_dma_tag_t , bus_dmamap_t, + struct mbuf *, int); + int (*_dmamap_load_uio)(bus_dma_tag_t , bus_dmamap_t, + struct uio *, int); + int (*_dmamap_load_raw)(bus_dma_tag_t , bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); + void (*_dmamap_unload)(bus_dma_tag_t , bus_dmamap_t); + void (*_dmamap_sync)(bus_dma_tag_t , bus_dmamap_t, + bus_addr_t, bus_size_t, int); + + /* + * DMA memory utility functions. + */ + int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); + void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); + int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); + void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t); + paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, + int, off_t, int, int); +}; + +#define bus_dmamap_create(t, s, n, m, b, f, p) \ + (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) +#define bus_dmamap_destroy(t, p) \ + (*(t)->_dmamap_destroy)((t), (p)) +#define bus_dmamap_load(t, m, b, s, p, f) \ + (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) +#define bus_dmamap_load_mbuf(t, m, b, f) \ + (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) +#define bus_dmamap_load_uio(t, m, u, f) \ + (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) +#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ + (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) +#define bus_dmamap_unload(t, p) \ + (*(t)->_dmamap_unload)((t), (p)) +#define bus_dmamap_sync(t, p, a, l, o) \ + (void)((t)->_dmamap_sync ? \ + (*(t)->_dmamap_sync)((t), (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)) + +int _dmamap_create(bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *); +void _dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); +int _dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int); +int _dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); +int _dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); +int _dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int); +void _dmamap_unload(bus_dma_tag_t, bus_dmamap_t); +void _dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t, + int); + +int _dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, + bus_size_t, bus_dma_segment_t *, int, int *, int); +void _dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int); +int _dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, + int, size_t, caddr_t *, int); +void _dmamem_unmap(bus_dma_tag_t, caddr_t, size_t); +paddr_t _dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int, int); + +/* + * bus_dmamap_t + * + * Describes a DMA mapping. + */ +struct powerpc_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/socppc/include/cdefs.h b/sys/arch/socppc/include/cdefs.h new file mode 100644 index 00000000000..8362c75969c --- /dev/null +++ b/sys/arch/socppc/include/cdefs.h @@ -0,0 +1,3 @@ +/* $OpenBSD: cdefs.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/cdefs.h> diff --git a/sys/arch/socppc/include/conf.h b/sys/arch/socppc/include/conf.h new file mode 100644 index 00000000000..2797e30ad4c --- /dev/null +++ b/sys/arch/socppc/include/conf.h @@ -0,0 +1,37 @@ +/* $OpenBSD: conf.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */ + +/* + * Copyright (c) 1996 Christos Zoulas. 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 Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/conf.h> + +#define mmread mmrw +#define mmwrite mmrw +cdev_decl(mm); diff --git a/sys/arch/socppc/include/cpu.h b/sys/arch/socppc/include/cpu.h new file mode 100644 index 00000000000..9e21d0c6084 --- /dev/null +++ b/sys/arch/socppc/include/cpu.h @@ -0,0 +1,53 @@ +/* $OpenBSD: cpu.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +#include <powerpc/cpu.h> + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_ALLOWAPERTURE 1 /* allow mmap of /dev/xf86 */ +#define CPU_ALTIVEC 2 /* altivec is present */ +#define CPU_MAXID 3 /* number of valid machdep ids */ + +#define CTL_MACHDEP_NAMES { \ + { 0, 0 }, \ + { "allowaperture", CTLTYPE_INT }, \ + { "altivec", CTLTYPE_INT }, \ +} + +#endif /* _MACHINE_CPU_H_ */ diff --git a/sys/arch/socppc/include/db_machdep.h b/sys/arch/socppc/include/db_machdep.h new file mode 100644 index 00000000000..df6783f5cc6 --- /dev/null +++ b/sys/arch/socppc/include/db_machdep.h @@ -0,0 +1,3 @@ +/* $OpenBSD: db_machdep.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/db_machdep.h> diff --git a/sys/arch/socppc/include/disklabel.h b/sys/arch/socppc/include/disklabel.h new file mode 100644 index 00000000000..1bf6635ae0f --- /dev/null +++ b/sys/arch/socppc/include/disklabel.h @@ -0,0 +1,90 @@ +/* $OpenBSD: disklabel.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_DISKLABEL_H_ +#define _MACHINE_DISKLABEL_H_ + +#define LABELSECTOR 1 /* sector containing label */ +#define LABELOFFSET 0 /* offset of label in sector */ +#define MAXPARTITIONS 16 /* number of partitions */ + +/* HFS/DPME */ + +/* partition map structure from Inside Macintosh: Devices, SCSI Manager + * pp. 13-14. The partition map always begins on physical block 1. + * + * With the exception of block 0, all blocks on the disk must belong to + * exactly one partition. The partition map itself belongs to a partition + * of type `APPLE_PARTITION_MAP', and is not limited in size by anything + * other than available disk space. The partition map is not necessarily + * the first partition listed. + */ +struct part_map_entry { +#define PART_ENTRY_MAGIC 0x504d + u_int16_t pmSig; /* partition signature */ + u_int16_t pmSigPad; /* (reserved) */ + u_int32_t pmMapBlkCnt; /* number of blocks in partition map */ + u_int32_t pmPyPartStart; /* first physical block of partition */ + u_int32_t pmPartBlkCnt; /* number of blocks in partition */ + char pmPartName[32]; /* partition name */ + char pmPartType[32]; /* partition type */ + u_int32_t pmLgDataStart; /* first logical block of data area */ + u_int32_t pmDataCnt; /* number of blocks in data area */ + u_int32_t pmPartStatus; /* partition status information */ + u_int32_t pmLgBootStart; /* first logical block of boot code */ + u_int32_t pmBootSize; /* size of boot code, in bytes */ + u_int32_t pmBootLoad; /* boot code load address */ + u_int32_t pmBootLoad2; /* (reserved) */ + u_int32_t pmBootEntry; /* boot code entry point */ + u_int32_t pmBootEntry2; /* (reserved) */ + u_int32_t pmBootCksum; /* boot code checksum */ + char pmProcessor[16]; /* processor type (e.g. "68020") */ + u_int8_t pmBootArgs[128]; /* A/UX boot arguments */ + /* we do not index the disk image as an array, + * leave out the on disk padding + */ +#if 0 + u_int8_t pad[248]; /* pad to end of block */ +#endif +}; + +#define PART_TYPE_DRIVER "APPLE_DRIVER" +#define PART_TYPE_DRIVER43 "APPLE_DRIVER43" +#define PART_TYPE_DRIVERATA "APPLE_DRIVER_ATA" +#define PART_TYPE_DRIVERIOKIT "APPLE_DRIVER_IOKIT" +#define PART_TYPE_FWDRIVER "APPLE_FWDRIVER" +#define PART_TYPE_FWB_COMPONENT "FWB DRIVER COMPONENTS" +#define PART_TYPE_FREE "APPLE_FREE" +#define PART_TYPE_MAC "APPLE_HFS" +#define PART_TYPE_OPENBSD "OPENBSD" + +#endif /* _MACHINE_DISKLABEL_H_ */ diff --git a/sys/arch/socppc/include/endian.h b/sys/arch/socppc/include/endian.h new file mode 100644 index 00000000000..1a72bba14a8 --- /dev/null +++ b/sys/arch/socppc/include/endian.h @@ -0,0 +1,3 @@ +/* $OpenBSD: endian.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/endian.h> diff --git a/sys/arch/socppc/include/exec.h b/sys/arch/socppc/include/exec.h new file mode 100644 index 00000000000..01c0c5722a1 --- /dev/null +++ b/sys/arch/socppc/include/exec.h @@ -0,0 +1,3 @@ +/* $OpenBSD: exec.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/exec.h> diff --git a/sys/arch/socppc/include/fpu.h b/sys/arch/socppc/include/fpu.h new file mode 100644 index 00000000000..83e3b628f83 --- /dev/null +++ b/sys/arch/socppc/include/fpu.h @@ -0,0 +1,3 @@ +/* $OpenBSD: fpu.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/fpu.h> diff --git a/sys/arch/socppc/include/frame.h b/sys/arch/socppc/include/frame.h new file mode 100644 index 00000000000..ba860b82dd9 --- /dev/null +++ b/sys/arch/socppc/include/frame.h @@ -0,0 +1,3 @@ +/* $OpenBSD: frame.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/frame.h> diff --git a/sys/arch/socppc/include/internal_types.h b/sys/arch/socppc/include/internal_types.h new file mode 100644 index 00000000000..4eb1ac1cfe1 --- /dev/null +++ b/sys/arch/socppc/include/internal_types.h @@ -0,0 +1,3 @@ +/* $OpenBSD: internal_types.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/internal_types.h> diff --git a/sys/arch/socppc/include/intr.h b/sys/arch/socppc/include/intr.h new file mode 100644 index 00000000000..f79a4c6d006 --- /dev/null +++ b/sys/arch/socppc/include/intr.h @@ -0,0 +1,11 @@ +/* $OpenBSD: intr.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/intr.h> + +#ifndef _LOCORE + +void softtty(void); + +void *intr_establish(int, int, int, int (*)(void *), void *, const char *); + +#endif diff --git a/sys/arch/socppc/include/limits.h b/sys/arch/socppc/include/limits.h new file mode 100644 index 00000000000..d6468bd2aa1 --- /dev/null +++ b/sys/arch/socppc/include/limits.h @@ -0,0 +1,3 @@ +/* $OpenBSD: limits.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/limits.h> diff --git a/sys/arch/socppc/include/lock.h b/sys/arch/socppc/include/lock.h new file mode 100644 index 00000000000..0ec5a702b00 --- /dev/null +++ b/sys/arch/socppc/include/lock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: lock.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/lock.h> diff --git a/sys/arch/socppc/include/mutex.h b/sys/arch/socppc/include/mutex.h new file mode 100644 index 00000000000..6564781e0c5 --- /dev/null +++ b/sys/arch/socppc/include/mutex.h @@ -0,0 +1,3 @@ +/* $OpenBSD: mutex.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/mutex.h> diff --git a/sys/arch/socppc/include/param.h b/sys/arch/socppc/include/param.h new file mode 100644 index 00000000000..161ce9f6e9c --- /dev/null +++ b/sys/arch/socppc/include/param.h @@ -0,0 +1,51 @@ +/* $OpenBSD: param.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: param.h,v 1.1 1996/09/30 16:34:28 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef _KERNEL +#ifndef _LOCORE +#include <machine/cpu.h> +#endif /* _LOCORE */ +#endif + +#include <powerpc/param.h> + +/* + * Machine dependent constants for socppc + */ +#define MACHINE "socppc" +#define _MACHINE socppc + +#define KERNBASE 0x200000 + +#define MSGBUFSIZE (NBPG*2) diff --git a/sys/arch/socppc/include/pcb.h b/sys/arch/socppc/include/pcb.h new file mode 100644 index 00000000000..0fde40255c1 --- /dev/null +++ b/sys/arch/socppc/include/pcb.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pcb.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/pcb.h> diff --git a/sys/arch/socppc/include/pio.h b/sys/arch/socppc/include/pio.h new file mode 100644 index 00000000000..6be1eecbd9c --- /dev/null +++ b/sys/arch/socppc/include/pio.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pio.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/pio.h> diff --git a/sys/arch/socppc/include/pmap.h b/sys/arch/socppc/include/pmap.h new file mode 100644 index 00000000000..b310d018415 --- /dev/null +++ b/sys/arch/socppc/include/pmap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pmap.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/pmap.h> diff --git a/sys/arch/socppc/include/powerpc.h b/sys/arch/socppc/include/powerpc.h new file mode 100644 index 00000000000..378d9259b93 --- /dev/null +++ b/sys/arch/socppc/include/powerpc.h @@ -0,0 +1,94 @@ +/* $OpenBSD: powerpc.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: powerpc.h,v 1.1 1996/09/30 16:34:30 ws Exp $ */ + +/* + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHINE_POWERPC_H_ +#define _MACHINE_POWERPC_H_ + +struct mem_region { + vaddr_t start; + vsize_t size; +}; + +void mem_regions(struct mem_region **, struct mem_region **); + +/* + * These two functions get used solely in boot() in machdep.c. + * + * Not sure whether boot itself should be implementation dependent instead. XXX + */ +typedef void (exit_f)(void) /*__attribute__((__noreturn__))*/ ; +typedef void (boot_f)(char *bootspec) /* __attribute__((__noreturn__))*/ ; +typedef void (vmon_f)(void); + +/* firmware interface. + * regardless of type of firmware used several items + * are need from firmware to boot up. + * these include: + * memory information + * vmsetup for firmware calls. + * default character print mechanism ??? + * firmware exit (return) + * firmware boot (reset) + * vmon - tell firmware the bsd vm is active. + */ + +typedef void (mem_regions_f)(struct mem_region **memp, + struct mem_region **availp); + +struct firmware { + mem_regions_f *mem_regions; + exit_f *exit; + boot_f *boot; + vmon_f *vmon; + +#ifdef FW_HAS_PUTC + boot_f *putc; +#endif +}; +extern struct firmware *fw; +int ppc_open_pci_bridge(void); +void ppc_close_pci_bridge(int); +void install_extint(void (*handler) (void)); +void ppc_intr_enable(int enable); +int ppc_intr_disable(void); + +struct dumpmem { + vaddr_t start; + vsize_t end; +}; +extern struct dumpmem dumpmem[VM_PHYSSEG_MAX]; +extern u_int ndumpmem; +extern vaddr_t dumpspace; + +#endif /* _MACHINE_POWERPC_H_ */ diff --git a/sys/arch/socppc/include/proc.h b/sys/arch/socppc/include/proc.h new file mode 100644 index 00000000000..1b78bbf4d75 --- /dev/null +++ b/sys/arch/socppc/include/proc.h @@ -0,0 +1,3 @@ +/* $OpenBSD: proc.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/proc.h> diff --git a/sys/arch/socppc/include/psl.h b/sys/arch/socppc/include/psl.h new file mode 100644 index 00000000000..2efac1c8750 --- /dev/null +++ b/sys/arch/socppc/include/psl.h @@ -0,0 +1,3 @@ +/* $OpenBSD: psl.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/psl.h> diff --git a/sys/arch/socppc/include/pte.h b/sys/arch/socppc/include/pte.h new file mode 100644 index 00000000000..cca262bf6e7 --- /dev/null +++ b/sys/arch/socppc/include/pte.h @@ -0,0 +1,3 @@ +/* $OpenBSD: pte.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/pte.h> diff --git a/sys/arch/socppc/include/ptrace.h b/sys/arch/socppc/include/ptrace.h new file mode 100644 index 00000000000..1c82569d472 --- /dev/null +++ b/sys/arch/socppc/include/ptrace.h @@ -0,0 +1,3 @@ +/* $OpenBSD: ptrace.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/ptrace.h> diff --git a/sys/arch/socppc/include/reg.h b/sys/arch/socppc/include/reg.h new file mode 100644 index 00000000000..26ed5eaa4e2 --- /dev/null +++ b/sys/arch/socppc/include/reg.h @@ -0,0 +1,3 @@ +/* $OpenBSD: reg.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/reg.h> diff --git a/sys/arch/socppc/include/signal.h b/sys/arch/socppc/include/signal.h new file mode 100644 index 00000000000..7ab86d1b3fe --- /dev/null +++ b/sys/arch/socppc/include/signal.h @@ -0,0 +1,3 @@ +/* $OpenBSD: signal.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/signal.h> diff --git a/sys/arch/socppc/include/spinlock.h b/sys/arch/socppc/include/spinlock.h new file mode 100644 index 00000000000..22bbf5008eb --- /dev/null +++ b/sys/arch/socppc/include/spinlock.h @@ -0,0 +1,3 @@ +/* $OpenBSD: spinlock.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/spinlock.h> diff --git a/sys/arch/socppc/include/trap.h b/sys/arch/socppc/include/trap.h new file mode 100644 index 00000000000..80a0f96d872 --- /dev/null +++ b/sys/arch/socppc/include/trap.h @@ -0,0 +1,3 @@ +/* $OpenBSD: trap.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +#include <powerpc/trap.h> diff --git a/sys/arch/socppc/include/vmparam.h b/sys/arch/socppc/include/vmparam.h new file mode 100644 index 00000000000..0cdd4986416 --- /dev/null +++ b/sys/arch/socppc/include/vmparam.h @@ -0,0 +1,114 @@ +/* $OpenBSD: vmparam.h,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: vmparam.h,v 1.1 1996/09/30 16:34:38 ws Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MACHINE_VMPARAM_H +#define MACHINE_VMPARAM_H + +#define USRTEXT PAGE_SIZE +#define USRSTACK VM_MAXUSER_ADDRESS + +#ifndef MAXTSIZ +#define MAXTSIZ (64*1024*1024) /* max text size */ +#endif + +#ifndef DFLDSIZ +#define DFLDSIZ (64*1024*1024) /* default data size */ +#endif + +#ifndef MAXDSIZ +#define MAXDSIZ (512*1024*1024) /* max data size */ +#endif + +#ifndef DFLSSIZ +#define DFLSSIZ (1*1024*1024) /* default stack size */ +#endif + +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +#define STACKGAP_RANDOM 256*1024 + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 8192 /* 32mb */ +#endif + +/* + * Size of User Raw I/O map + */ +#define USRIOSIZE 1024 + +/* + * Would like to have MAX addresses = 0, but this doesn't (currently) work + */ +#define VM_MIN_ADDRESS ((vaddr_t)0) +#define VM_MAXUSER_ADDRESS ((vaddr_t)0xfffff000) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#define VM_MIN_KERNEL_ADDRESS ((vaddr_t)(PPC_KERNEL_SR << ADDR_SR_SHIFT)) + +/* ppc_kvm_stolen is so that vm space can be stolen before vm is fully + * initialized. + */ +extern vaddr_t ppc_kvm_stolen; +#define VM_KERN_ADDRESS_SIZE (PPC_SEGMENT_LENGTH - (32 * 1024 * 1024)) +#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + VM_KERN_ADDRESS_SIZE) + +#define VM_PHYS_SIZE (USRIOSIZE * PAGE_SIZE) + +#define VM_PHYSSEG_MAX 32 /* actually we could have this many segments */ +#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH +#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */ + +#define VM_NFREELIST 1 +#define VM_FREELIST_DEFAULT 0 + +#ifdef _KERNEL + +#define __HAVE_VM_PAGE_MD +struct pv_entry; +struct vm_page_md { + LIST_HEAD(,pte_desc) pv_list; +}; + +#define VM_MDPAGE_INIT(pg) do { \ + LIST_INIT(&((pg)->mdpage.pv_list)); \ +} while (0) + +#endif + + +#endif diff --git a/sys/arch/socppc/socppc/autoconf.c b/sys/arch/socppc/socppc/autoconf.c new file mode 100644 index 00000000000..90da6d18b0c --- /dev/null +++ b/sys/arch/socppc/socppc/autoconf.c @@ -0,0 +1,69 @@ +/* $OpenBSD: autoconf.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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/reboot.h> + +#include <uvm/uvm_extern.h> + +#include <machine/powerpc.h> + +void dumpconf(void); + +int cold = 1; + +struct dumpmem dumpmem[VM_PHYSSEG_MAX]; +u_int ndumpmem; + +void +cpu_configure(void) +{ + splhigh(); + + if (config_rootfound("mainbus", "mainbus") == 0) + panic("no mainbus found"); + + /* Configuration is finished, turn on interrupts. */ + spl0(); + cold = 0; +} + +void +device_register(struct device *dev, void *aux) +{ +} + +void +diskconf(void) +{ + struct device *dv; + dev_t tmpdev; + + dv = parsedisk("wd0a", strlen("wd0a"), 0, &tmpdev); + setroot(dv, 0, RB_USERREQ); + dumpconf(); +} + +struct nam2blk nam2blk[] = { + { "wd", 0 }, + { "sd", 2 }, + { "rd", 17 }, + { "raid", 19 }, + { NULL, -1 } +}; diff --git a/sys/arch/socppc/socppc/clock.c b/sys/arch/socppc/socppc/clock.c new file mode 100644 index 00000000000..bb2bcb814a8 --- /dev/null +++ b/sys/arch/socppc/socppc/clock.c @@ -0,0 +1,342 @@ +/* $OpenBSD: clock.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: clock.c,v 1.1 1996/09/30 16:34:40 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/timetc.h> + +#include <machine/autoconf.h> + +#include <dev/clock_subr.h> + +void decr_intr(struct clockframe *frame); +u_int tb_get_timecount(struct timecounter *); + +/* + * Initially we assume a processor with a bus frequency of 266 MHz. + */ +static u_int32_t ticks_per_sec = 66666666; +static u_int32_t ns_per_tick = 15; +static int32_t ticks_per_intr; + +static struct timecounter tb_timecounter = { + tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL +}; + +/* Global TOD clock handle. */ +todr_chip_handle_t todr_handle; + +/* vars for stats */ +int statint; +u_int32_t statvar; +u_int32_t statmin; + +static struct evcount clk_count; +static struct evcount stat_count; +static int clk_irq = PPC_CLK_IRQ; +static int stat_irq = PPC_STAT_IRQ; + +/* + * Set up the system's time, given a `reasonable' time value. + */ +void +inittodr(time_t base) +{ + int badbase = 0, waszero = base == 0; + char *bad = NULL; + struct timeval tv; + struct timespec ts; + + if (base < 5 * SECYR) { + /* + * If base is 0, assume filesystem time is just unknown + * instead of preposterous. Don't bark. + */ + if (base != 0) + printf("WARNING: preposterous time in file system\n"); + /* not going to use it anyway, if the chip is readable */ + base = 21*SECYR + 186*SECDAY + SECDAY/2; + badbase = 1; + } + + if (todr_handle != NULL && todr_gettime(todr_handle, &tv) != 0) + tv.tv_sec = tv.tv_usec = 0; + + if (tv.tv_sec == 0) { + /* + * Believe the time in the file system for lack of + * anything better, resetting the clock. + */ + bad = "WARNING: unable to get date/time"; + tv.tv_sec = base; + tv.tv_usec = 0; + if (!badbase) + resettodr(); + } else { + int deltat; + + tv.tv_sec += tz.tz_minuteswest * 60; + if (tz.tz_dsttime) + tv.tv_sec -= 3600; + + deltat = tv.tv_sec - base; + + if (deltat < 0) + deltat = -deltat; + if (!(waszero || deltat < 2 * SECDAY)) { + printf("WARNING: clock %s %d days", + tv.tv_sec < base ? "lost" : "gained", deltat / SECDAY); + bad = ""; + + if (tv.tv_sec < base && deltat > 1000 * SECDAY) { + printf(", using FS time"); + tv.tv_sec = base; + } + } + } + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + tc_setclock(&ts); + + if (bad) { + printf("%s", bad); + printf(" -- CHECK AND RESET THE DATE!\n"); + } +} + +/* + * Similar to the above + */ +void +resettodr(void) +{ + struct timeval tv; + + if (time_second == 0) + return; + + microtime(&tv); + + if (todr_handle == NULL || todr_settime(todr_handle, &tv) != 0) + printf("Cannot set time in time-of-day clock\n"); +} + +void +decr_intr(struct clockframe *frame) +{ + u_int64_t tb; + u_int64_t nextevent; + struct cpu_info *ci = curcpu(); + int nstats; + int s; + + /* + * Check whether we are initialized. + */ + if (!ticks_per_intr) + return; + + /* + * Based on the actual time delay since the last decrementer reload, + * we arrange for earlier interrupt next time. + */ + + tb = ppc_mftb(); + while (ci->ci_nexttimerevent <= tb) + ci->ci_nexttimerevent += ticks_per_intr; + + ci->ci_prevtb = ci->ci_nexttimerevent - ticks_per_intr; + + for (nstats = 0; ci->ci_nextstatevent <= tb; nstats++) { + int r; + do { + r = random() & (statvar -1); + } while (r == 0); /* random == 0 not allowed */ + ci->ci_nextstatevent += statmin + r; + } + + /* only count timer ticks for CLK_IRQ */ + stat_count.ec_count += nstats; + + if (ci->ci_nexttimerevent < ci->ci_nextstatevent) + nextevent = ci->ci_nexttimerevent; + else + nextevent = ci->ci_nextstatevent; + + /* + * Need to work about the near constant skew this introduces??? + * reloading tb here could cause a missed tick. + */ + ppc_mtdec(nextevent - tb); + + if (curcpu()->ci_cpl & SPL_CLOCK) { + ci->ci_statspending += nstats; + } else { + KERNEL_LOCK(); + + nstats += ci->ci_statspending; + ci->ci_statspending = 0; + + s = splclock(); + + /* + * Reenable interrupts + */ + ppc_intr_enable(1); + + /* + * Do standard timer interrupt stuff. + */ + while (ci->ci_lasttb < ci->ci_prevtb) { + /* sync lasttb with hardclock */ + ci->ci_lasttb += ticks_per_intr; + clk_count.ec_count++; + hardclock(frame); + } + + while (nstats-- > 0) + statclock(frame); + + splx(s); + (void) ppc_intr_disable(); + + /* if a tick has occurred while dealing with these, + * dont service it now, delay until the next tick. + */ + KERNEL_UNLOCK(); + } +} + +void cpu_startclock(void); + +void +cpu_initclocks(void) +{ + int intrstate; + int minint; + + intrstate = ppc_intr_disable(); + + stathz = 100; + profhz = 1000; /* must be a multiple of stathz */ + + /* init secondary clock to stathz */ + statint = ticks_per_sec / stathz; + statvar = 0x40000000; /* really big power of two */ + /* find largest 2^n which is nearly smaller than statint/2 */ + minint = statint / 2 + 100; + while (statvar > minint) + statvar >>= 1; + statmin = statint - (statvar >> 1); + + evcount_attach(&clk_count, "clock", (void *)&clk_irq, &evcount_intr); + evcount_attach(&stat_count, "stat", (void *)&stat_irq, &evcount_intr); + + ticks_per_intr = ticks_per_sec / hz; + cpu_startclock(); + + tb_timecounter.tc_frequency = ticks_per_sec; + tc_init(&tb_timecounter); + ppc_intr_enable(intrstate); +} + +void +cpu_startclock() +{ + struct cpu_info *ci = curcpu(); + u_int64_t nextevent; + + ci->ci_lasttb = ppc_mftb(); + + /* + * no point in having random on the first tick, + * it just complicates the code. + */ + ci->ci_nexttimerevent = ci->ci_lasttb + ticks_per_intr; + nextevent = ci->ci_nextstatevent = ci->ci_nexttimerevent; + + ci->ci_statspending = 0; + + ppc_mtdec(nextevent - ci->ci_lasttb); +} + +void +delay(unsigned n) +{ + u_int64_t tb; + u_int32_t tbh, tbl, scratch; + + tb = ppc_mftb(); + tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick; + tbh = tb >> 32; + tbl = (u_int32_t)tb; + asm ("1: mftbu %0; cmplw %0,%1; blt 1b; bgt 2f;" + " mftb %0; cmplw %0,%2; blt 1b; 2:" + :: "r"(scratch), "r"(tbh), "r"(tbl)); +} + +/* + * Nothing to do. + */ +void +setstatclockrate(int newhz) +{ + int minint; + int intrstate; + + intrstate = ppc_intr_disable(); + + statint = ticks_per_sec / newhz; + statvar = 0x40000000; /* really big power of two */ + /* find largest 2^n which is nearly smaller than statint/2 */ + minint = statint / 2 + 100; + while (statvar > minint) + statvar >>= 1; + + statmin = statint - (statvar >> 1); + ppc_intr_enable(intrstate); + + /* + * XXX this allows the next stat timer to occur then it switches + * to the new frequency. Rather than switching instantly. + */ +} + +u_int +tb_get_timecount(struct timecounter *tc) +{ + return ppc_mftbl(); +} diff --git a/sys/arch/socppc/socppc/conf.c b/sys/arch/socppc/socppc/conf.c new file mode 100644 index 00000000000..db8ce25396c --- /dev/null +++ b/sys/arch/socppc/socppc/conf.c @@ -0,0 +1,287 @@ +/* $OpenBSD: conf.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 1997 Per Fogelstrom + * Copyright (c) 1997 RTMX Inc, North Carolina + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD for RTMX Inc, + * North Carolina, USA, by Per Fogelstrom, Opsycon AB, Sweden. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/tty.h> + +#include <machine/conf.h> + +#include "sd.h" +#include "cd.h" +#include "rd.h" +#include "wd.h" +bdev_decl(wd); +cdev_decl(wd); + +#include "vnd.h" + +struct bdevsw bdevsw[] = { + bdev_disk_init(NWD,wd), /* 0: ST506/ESDI/IDE disk */ + bdev_swap_init(1,sw), /* 1 swap pseudo device */ + bdev_disk_init(NSD,sd), /* 2 SCSI Disk */ + bdev_disk_init(NCD,cd), /* 3 SCSI CD-ROM */ + bdev_notdef(), /* 4 unknown*/ + bdev_notdef(), /* 5 unknown*/ + bdev_notdef(), /* 6 unknown*/ + bdev_notdef(), /* 7 unknown*/ + bdev_lkm_dummy(), /* 8 */ + bdev_lkm_dummy(), /* 9 */ + bdev_lkm_dummy(), /* 10 */ + bdev_lkm_dummy(), /* 11 */ + bdev_lkm_dummy(), /* 12 */ + bdev_lkm_dummy(), /* 13 */ + bdev_disk_init(NVND,vnd), /* 14 vnode disk driver*/ + bdev_notdef(), /* 15 unknown*/ + bdev_notdef(), /* 16 unknown*/ + bdev_disk_init(NRD,rd), /* 17 ram disk driver*/ +}; +int nblkdev = sizeof bdevsw / sizeof bdevsw[0]; + +#include "pty.h" + +#include "com.h" +cdev_decl(com); + +#include "bpfilter.h" + +#include "tun.h" + +#ifdef USER_PCICONF +#include "pci.h" +cdev_decl(pci); +#endif + +#include "pf.h" + +#include "systrace.h" + +#ifdef LKM +#define NLKM 1 +#else +#define NLKM 0 +#endif + +#include "ksyms.h" +#include "usb.h" + +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_notdef(), /* 7 */ + cdev_disk_init(NSD,sd), /* 8: SCSI disk */ + cdev_disk_init(NCD,cd), /* 9: SCSI CD-ROM */ + cdev_notdef(), /* 10 */ + cdev_disk_init(NWD,wd), /* 11: ST506/ESDI/IDE disk */ + cdev_notdef(), /* 12 */ + cdev_notdef(), /* 13 */ + cdev_notdef(), /* 14 */ + cdev_notdef(), /* 15 */ + cdev_notdef(), /* 16 */ + cdev_disk_init(NRD,rd), /* 17 ram disk driver*/ + cdev_notdef(), /* 18 */ + cdev_disk_init(NVND,vnd), /* 19: vnode disk */ + cdev_notdef(), /* 20 */ + cdev_fd_init(1,filedesc), /* 21: file descriptor pseudo-dev */ + cdev_bpf_init(NBPFILTER,bpf), /* 22: berkeley packet filter */ + cdev_tun_init(NTUN,tun), /* 23: network tunnel */ + cdev_lkm_init(NLKM,lkm), /* 24: loadable module driver */ + cdev_notdef(), /* 25 */ + cdev_tty_init(NCOM,com), /* 26: serial port */ + cdev_notdef(), /* 27 */ + cdev_notdef(), /* 28 */ + cdev_notdef(), /* 29 */ + cdev_notdef(), /* 30 */ + cdev_notdef(), /* 31 */ + cdev_notdef(), /* 32 */ + cdev_lkm_dummy(), /* 33 */ + cdev_lkm_dummy(), /* 34 */ + cdev_lkm_dummy(), /* 35 */ + cdev_lkm_dummy(), /* 36 */ + cdev_lkm_dummy(), /* 37 */ + cdev_lkm_dummy(), /* 38 */ + cdev_pf_init(NPF,pf), /* 39: packet filter */ + cdev_random_init(1,random), /* 40: random data source */ + cdev_notdef(), /* 41 */ + cdev_notdef(), /* 42 */ + cdev_ksyms_init(NKSYMS,ksyms), /* 43: Kernel symbols device */ + cdev_notdef(), /* 44 */ + cdev_notdef(), /* 45 */ + cdev_notdef(), /* 46 */ + cdev_notdef(), /* 47 */ + cdev_notdef(), /* 48 */ + cdev_notdef(), /* 49 */ + cdev_systrace_init(NSYSTRACE,systrace), /* 50 system call tracing */ + cdev_notdef(), /* 51 */ + cdev_notdef(), /* 52 */ + cdev_notdef(), /* 53 */ + cdev_notdef(), /* 54 */ + cdev_notdef(), /* 55 */ + cdev_notdef(), /* 56 */ + cdev_notdef(), /* 57 */ + cdev_notdef(), /* 58 */ + cdev_notdef(), /* 59 */ + cdev_notdef(), /* 60 */ + cdev_usb_init(NUSB,usb), /* 61: USB controller */ + cdev_notdef(), /* 62 */ + cdev_notdef(), /* 63 */ + cdev_notdef(), /* 64 */ + cdev_notdef(), /* 65 */ + cdev_notdef(), /* 66 */ + cdev_notdef(), /* 67 */ + cdev_notdef(), /* 68 */ + cdev_notdef(), /* 69 */ + cdev_notdef(), /* 70 */ +#ifdef USER_PCICONF + cdev_pci_init(NPCI,pci), /* 71: PCI user */ +#else + cdev_notdef(), +#endif + cdev_notdef(), /* 72 */ + cdev_notdef(), /* 73 */ + cdev_notdef(), /* 74 */ + cdev_notdef(), /* 75 */ + cdev_notdef(), /* 76 */ + cdev_ptm_init(NPTY,ptm), /* 77: pseudo-tty ptm device */ +}; +int nchrdev = sizeof cdevsw / sizeof cdevsw[0]; + +int mem_no = 2; /* major number of /dev/mem */ + +/* + * Swapdev is a fake device implemented in sw.c. + * It is used only internally to get to swstrategy. + */ +dev_t swapdev = makedev(1, 0); + +/* + * Check whether dev is /dev/mem or /dev/kmem. + */ +int +iskmemdev(dev_t dev) +{ + return major(dev) == mem_no && minor(dev) < 2; +} + +/* + * Check whether dev is /dev/zero. + */ +int +iszerodev(dev_t dev) +{ + return major(dev) == mem_no && minor(dev) == 12; +} + +dev_t +getnulldev() +{ + return makedev(mem_no, 2); +} + +int chrtoblktbl[] = { + /*VCHR*/ /*VBLK*/ + /* 0 */ NODEV, + /* 1 */ NODEV, + /* 2 */ NODEV, + /* 3 */ NODEV, + /* 4 */ NODEV, + /* 5 */ NODEV, + /* 6 */ NODEV, + /* 7 */ NODEV, + /* 8 */ 2, + /* 9 */ NODEV, + /* 10 */ NODEV, + /* 11 */ 0, + /* 12 */ NODEV, + /* 13 */ 4, + /* 14 */ NODEV, + /* 15 */ NODEV, + /* 16 */ NODEV, + /* 17 */ 17, + /* 18 */ NODEV, + /* 19 */ NODEV, + /* 20 */ NODEV, + /* 21 */ NODEV, + /* 22 */ NODEV, + /* 23 */ NODEV, + /* 24 */ NODEV, + /* 25 */ NODEV, + /* 26 */ NODEV, + /* 27 */ NODEV, + /* 28 */ NODEV, + /* 29 */ NODEV, + /* 30 */ NODEV, + /* 31 */ NODEV, + /* 32 */ NODEV, + /* 33 */ NODEV, + /* 34 */ NODEV, + /* 35 */ NODEV, + /* 36 */ NODEV, + /* 37 */ NODEV, + /* 38 */ NODEV, + /* 39 */ NODEV, + /* 40 */ NODEV, + /* 41 */ NODEV, + /* 42 */ NODEV, + /* 43 */ NODEV, + /* 44 */ NODEV, + /* 45 */ NODEV, + /* 46 */ NODEV, + /* 47 */ NODEV, + /* 48 */ NODEV, + /* 49 */ NODEV, + /* 50 */ NODEV, + /* 51 */ NODEV, + /* 52 */ NODEV, + /* 53 */ NODEV, + /* 54 */ 19, +}; +int nchrtoblktbl = sizeof(chrtoblktbl) / sizeof(chrtoblktbl[0]); + +#include <dev/cons.h> + +cons_decl(com); + +struct consdev constab[] = { +#if NCOM > 0 + cons_init(com), +#endif + { 0 }, +}; diff --git a/sys/arch/socppc/socppc/cpu.c b/sys/arch/socppc/socppc/cpu.c new file mode 100644 index 00000000000..72c4c59ee73 --- /dev/null +++ b/sys/arch/socppc/socppc/cpu.c @@ -0,0 +1,115 @@ +/* $OpenBSD: cpu.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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> + +#define HID0_DOZE (1 << (31-8)) +#define HID0_NAP (1 << (31-9)) +#define HID0_SLEEP (1 << (31-10)) +#define HID0_DPM (1 << (31-11)) +#define HID0_ICE (1 << (31-16)) +#define HID0_DCE (1 << (31-17)) +#define HID0_ICFI (1 << (31-20)) +#define HID0_DCFI (1 << (31-21)) + +extern u_int32_t hid0_idle; + + +struct cpu_info cpu_info[PPC_MAXPROCS] = { { NULL } }; /* XXX */ + +char *cpu_model = "8347"; +char machine[] = MACHINE; /* cpu architecture */ + +int cpu_match(struct device *, void *, void *); +void cpu_attach(struct device *, struct device *, void *); + +struct cfattach cpu_ca = { + sizeof(struct device), cpu_match, cpu_attach +}; + +struct cfdriver cpu_cd = { + NULL, "cpu", DV_DULL +}; + +int +cpu_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + +void +cpu_attach(struct device *parent, struct device *self, void *aux) +{ + struct cpu_info *ci; + u_int32_t hid0; + + ci = &cpu_info[0]; + ci->ci_cpuid = 0; + ci->ci_intrdepth = -1; + ci->ci_randseed = 1; + ci->ci_dev = self; + + printf(": %s\n", cpu_model); + + /* Enable data cache. */ + hid0 = ppc_mfhid0(); + if ((hid0 & HID0_DCE) == 0) { + __asm __volatile ( + "sync; mtspr 1008,%0; mtspr 1008,%1" + :: "r" (hid0 | HID0_DCFI), "r" (hid0 | HID0_DCE)); + } + + /* Enable instruction cache. */ + hid0 = ppc_mfhid0(); + if ((hid0 & HID0_ICE) == 0) { + __asm __volatile ( + "isync; mtspr 1008,%0; mtspr 1008,%1" + :: "r" (hid0 | HID0_ICFI), "r" (hid0 | HID0_ICE)); + } + + /* Select DOZE mode. */ + hid0 = ppc_mfhid0(); + hid0 &= ~(HID0_NAP | HID0_DOZE | HID0_SLEEP); + hid0_idle = HID0_DOZE; + hid0 |= HID0_DPM; + ppc_mthid0(hid0); +} + +int ppc_proc_is_64b; +extern u_int32_t nop_inst; +struct patch { + u_int32_t *s; + u_int32_t *e; +}; +extern struct patch nop32_start; + +void +ppc_check_procid() +{ + u_int32_t *inst; + struct patch *p; + + ppc_proc_is_64b = 0; + for (p = &nop32_start; p->s; p++) { + for (inst = p->s; inst < p->e; inst++) + *inst = nop_inst; + syncicache(p->s, (p->e - p->s) * sizeof(p->e)); + } +} diff --git a/sys/arch/socppc/socppc/db_interface.c b/sys/arch/socppc/socppc/db_interface.c new file mode 100644 index 00000000000..02a44a53a76 --- /dev/null +++ b/sys/arch/socppc/socppc/db_interface.c @@ -0,0 +1,44 @@ +/* $OpenBSD: db_interface.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: db_interface.c,v 1.12 2001/07/22 11:29:46 wiz Exp $ */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> + +#include <dev/cons.h> + +#include <machine/db_machdep.h> +#include <ddb/db_extern.h> + +int ddb_trap_glue(struct trapframe *frame); /* called from locore */ + +void +Debugger() +{ + ddb_trap(); +} + +int +ddb_trap_glue(struct trapframe *frame) +{ + if (!(frame->srr1 & PSL_PR) + && (frame->exc == EXC_TRC + || (frame->exc == EXC_PGM && (frame->srr1 & 0x20000)) + || frame->exc == EXC_BPT)) { + + bcopy(frame->fixreg, DDB_REGS->tf.fixreg, + 32 * sizeof(u_int32_t)); + DDB_REGS->tf.srr0 = frame->srr0; + DDB_REGS->tf.srr1 = frame->srr1; + + cnpollc(TRUE); + db_trap(T_BREAKPOINT, 0); + cnpollc(FALSE); + + bcopy(DDB_REGS->tf.fixreg, frame->fixreg, + 32 * sizeof(u_int32_t)); + + return 1; + } + return 0; +} diff --git a/sys/arch/socppc/socppc/disksubr.c b/sys/arch/socppc/socppc/disksubr.c new file mode 100644 index 00000000000..f41bd161701 --- /dev/null +++ b/sys/arch/socppc/socppc/disksubr.c @@ -0,0 +1,214 @@ +/* $OpenBSD: disksubr.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */ + +/* + * 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. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/disklabel.h> +#include <sys/disk.h> + +char *readdpmelabel(struct buf *, void (*)(struct buf *), + struct disklabel *, int *, int); + +/* + * 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. + * + * If dos partition table requested, attempt to load it and + * find disklabel inside a DOS partition. Return buffer + * for use in signalling errors if requested. + * + * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but + * we cannot because it doesn't always exist. So.. we assume the + * MBR is valid. + * + * Returns null on success and an error string on failure. + */ +char * +readdisklabel(dev_t dev, void (*strat)(struct buf *), + struct disklabel *lp, int spoofonly) +{ + struct buf *bp = NULL; + char *msg; + + if ((msg = initdisklabel(lp))) + goto done; + + /* get a buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + msg = readdpmelabel(bp, strat, lp, NULL, spoofonly); + if (msg == NULL) + goto done; + + msg = readdoslabel(bp, strat, lp, NULL, spoofonly); + if (msg == NULL) + goto done; + +#if defined(CD9660) + if (iso_disklabelspoof(dev, strat, lp) == 0) { + msg = NULL; + goto done; + } +#endif +#if defined(UDF) + if (udf_disklabelspoof(dev, strat, lp) == 0) { + msg = NULL; + goto done; + } +#endif + +done: + if (bp) { + bp->b_flags |= B_INVAL; + brelse(bp); + } + return (msg); +} + +char * +readdpmelabel(struct buf *bp, void (*strat)(struct buf *), + struct disklabel *lp, int *partoffp, int spoofonly) +{ + int i, part_cnt, n, hfspartoff = -1; + struct part_map_entry *part; + + /* First check for a DPME (HFS) disklabel */ + bp->b_blkno = 1; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp)) + return ("DPME partition I/O error"); + + /* if successful, wander through DPME partition table */ + part = (struct part_map_entry *)bp->b_data; + /* if first partition is not valid, assume not HFS/DPME partitioned */ + if (part->pmSig != PART_ENTRY_MAGIC) + return ("not a DPMI partition"); + part_cnt = part->pmMapBlkCnt; + n = 0; + for (i = 0; i < part_cnt; i++) { + struct partition *pp = &lp->d_partitions[8+n]; + char *s; + + bp->b_blkno = 1+i; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp)) + return ("DPME partition I/O error"); + + part = (struct part_map_entry *)bp->b_data; + /* toupper the string, in case caps are different... */ + for (s = part->pmPartType; *s; s++) + if ((*s >= 'a') && (*s <= 'z')) + *s = (*s - 'a' + 'A'); + + if (strcmp(part->pmPartType, PART_TYPE_OPENBSD) == 0) + hfspartoff = part->pmPyPartStart - LABELSECTOR; + + /* currently we ignore all but HFS partitions */ + if (strcmp(part->pmPartType, PART_TYPE_MAC) == 0) { + DL_SETPOFFSET(pp, part->pmPyPartStart); + DL_SETPSIZE(pp, part->pmPartBlkCnt); + pp->p_fstype = FS_HFS; + n++; + } + } + lp->d_npartitions = MAXPARTITIONS; + + if (hfspartoff == -1) + return ("no OpenBSD parition inside DPME label"); + + if (partoffp) + *partoffp = hfspartoff; + + if (spoofonly) + return (NULL); + + /* next, dig out disk label */ + bp->b_blkno = hfspartoff + LABELSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if (biowait(bp)) + return("disk label I/O error"); + + return checkdisklabel(bp->b_data + LABELOFFSET, lp); +} + +/* + * Write disk label back to device after modification. + */ +int +writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp) +{ + int error = EIO, partoff = -1; + struct disklabel *dlp; + struct buf *bp = NULL; + + /* get a buffer and initialize it */ + bp = geteblk((int)lp->d_secsize); + bp->b_dev = dev; + + if (readdpmelabel(bp, strat, lp, &partoff, 1) != NULL && + readdoslabel(bp, strat, lp, &partoff, 1) != NULL) + goto done; + + /* Read it in, slap the new label in, and write it back out */ + bp->b_blkno = partoff + LABELSECTOR; + bp->b_bcount = lp->d_secsize; + bp->b_flags = B_BUSY | B_READ; + (*strat)(bp); + if ((error = biowait(bp)) != 0) + goto done; + + dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); + *dlp = *lp; + bp->b_flags = B_BUSY | B_WRITE; + (*strat)(bp); + error = biowait(bp); + +done: + if (bp) { + bp->b_flags |= B_INVAL; + brelse(bp); + } + return (error); +} diff --git a/sys/arch/socppc/socppc/dma.c b/sys/arch/socppc/socppc/dma.c new file mode 100644 index 00000000000..49f2d951595 --- /dev/null +++ b/sys/arch/socppc/socppc/dma.c @@ -0,0 +1,608 @@ +/* $OpenBSD: dma.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ + +/*- + * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/extent.h> +#include <sys/buf.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/mount.h> + +#include <uvm/uvm.h> +#include <uvm/uvm_page.h> + +#include <machine/bus.h> +int _dmamem_alloc_range( bus_dma_tag_t t, bus_size_t size, + bus_size_t alignment, bus_size_t boundary, bus_dma_segment_t *segs, + int nsegs, int *rsegs, int flags, vaddr_t low, vaddr_t high); +int _dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, + struct proc *, int, bus_addr_t *, int *, int); +/* + * Common function for DMA map creation. May be called by bus-specific + * DMA map creation functions. + */ +int +_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments, + bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) +{ + struct powerpc_bus_dmamap *map; + void *mapstore; + size_t mapsize; + + /* + * Allocate and initialize the DMA map. The end of the map + * is a variable-sized array of segments, so we allocate enough + * room for them in one shot. + * + * Note we don't preserve the WAITOK or NOWAIT flags. Preservation + * of ALLOCNOW notifies others that we've reserved these resources, + * and they are not to be freed. + * + * The bus_dmamap_t includes one bus_dma_segment_t, hence + * the (nsegments - 1). + */ + mapsize = sizeof(struct powerpc_bus_dmamap) + + (sizeof(bus_dma_segment_t) * (nsegments - 1)); + if ((mapstore = malloc(mapsize, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ? + (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO))) == NULL) + return (ENOMEM); + + map = (struct powerpc_bus_dmamap *)mapstore; + 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_nsegs = 0; /* no valid mappings */ + map->dm_mapsize = 0; + + *dmamp = map; + return (0); +} + +/* + * Common function for DMA map destruction. May be called by bus-specific + * DMA map destruction functions. + */ +void +_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map) +{ + + free(map, M_DEVBUF); +} + + +int +_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, + bus_size_t buflen, struct proc *p, int flags, bus_addr_t *lastaddrp, + int *segp, int first) +{ + bus_size_t sgsize; + bus_addr_t curaddr, lastaddr, baddr, bmask; + vaddr_t vaddr = (vaddr_t)buf; + pmap_t pmap; + int seg; + + lastaddr = *lastaddrp; + bmask = ~(map->_dm_boundary - 1); + + if (p != NULL) + pmap = p->p_vmspace->vm_map.pmap; + else + pmap = pmap_kernel(); + + for (seg = *segp; buflen > 0; ) { + /* + * Get the physical address for this segment. + */ + if (pmap_extract(pmap, vaddr, (paddr_t *)&curaddr) != TRUE) { + panic("dmamap_load_buffer pmap %p vaddr %lx " + "pmap_extract failed", pmap, vaddr); + } + + /* + * Compute the segment size, and adjust counts. + */ + sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET); + 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 the + * previous segment if possible. + */ + if (first) { + map->dm_segs[seg].ds_addr = curaddr; + map->dm_segs[seg].ds_len = sgsize; + 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; + } + } + + lastaddr = curaddr + sgsize; + vaddr += sgsize; + buflen -= sgsize; + } + + *segp = seg; + *lastaddrp = lastaddr; + + /* + * Did we fit? + */ + if (buflen != 0) + return (EFBIG); /* XX better return value here? */ + + return (0); +} + +/* + * Common function for loading a DMA map with a linear buffer. May + * be called by bus-specific DMA map load functions. + */ +int +_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen, + struct proc *p, int flags) +{ + bus_addr_t lastaddr; + int seg, error; + + /* + * Make sure that on error condition we return "no valid mappings". + */ + map->dm_mapsize = 0; + map->dm_nsegs = 0; + + if (buflen > map->_dm_size) + return (EINVAL); + + seg = 0; + error = _dmamap_load_buffer(t, map, buf, buflen, p, flags, + &lastaddr, &seg, 1); + if (error == 0) { + map->dm_mapsize = buflen; + map->dm_nsegs = seg + 1; + } + return (error); +} + +/* + * Like _bus_dmamap_load(), but for mbufs. + */ +int +_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0, + int flags) +{ + bus_addr_t lastaddr; + int seg, error, first; + struct mbuf *m; + + /* + * Make sure that on error condition we return "no valid mappings". + */ + 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; + for (m = m0; m != NULL && error == 0; m = m->m_next) { + if (m->m_len == 0) + continue; + error = _dmamap_load_buffer(t, 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); +} + +/* + * Like _bus_dmamap_load(), but for uios. + */ +int +_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio, int flags) +{ + bus_addr_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; + 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 = _dmamap_load_buffer(t, 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); +} + +/* + * Like _bus_dmamap_load(), but for raw memory allocated with + * bus_dmamem_alloc(). + */ +int +_dmamap_load_raw(bus_dma_tag_t t, 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); +} + +/* + * Common function for unloading a DMA map. May be called by + * bus-specific DMA map unload functions. + */ +void +_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map) +{ + + /* + * No resources to free; just mark the mappings as + * invalid. + */ + map->dm_nsegs = 0; + map->dm_mapsize = 0; +} + +/* + * Common function for DMA map synchronization. May be called + * by bus-specific DMA map synchronization functions. + */ +void +_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset, +bus_size_t len, int op) +{ + int i; + bus_size_t minlen, wlen; + bus_addr_t pa, addr; + struct vm_page *pg; + + for (i = 0; i < map->dm_nsegs && len != 0; i++) { + /* Find the beginning segment. */ + if (offset >= map->dm_segs[i].ds_len) { + offset -= map->dm_segs[i].ds_len; + continue; + } + + minlen = len < map->dm_segs[i].ds_len - offset ? + len : map->dm_segs[i].ds_len - offset; + + addr = map->dm_segs[i].ds_addr + offset; + + switch (op) { + case BUS_DMASYNC_POSTWRITE: + for (pa = trunc_page(addr), wlen = 0; + pa < round_page(addr + minlen); + pa += PAGE_SIZE) { + pg = PHYS_TO_VM_PAGE(pa); + if (pg != NULL) + atomic_clearbits_int(&pg->pg_flags, + PG_PMAP_EXE); + } + } + + } +} + +/* + * Common function for DMA-safe memory allocation. May be called + * by bus-specific DMA memory allocation functions. + */ +int +_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, + bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, + int flags) +{ + return (_dmamem_alloc_range(t, size, alignment, boundary, + segs, nsegs, rsegs, flags, 0, 0xf0000000)); +} + +/* + * Common function for freeing DMA-safe memory. May be called by + * bus-specific DMA memory free functions. + */ +void +_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs) +{ + struct vm_page *m; + bus_addr_t addr; + struct pglist mlist; + int curseg; + + /* + * Build a list of pages to free back to the VM system. + */ + TAILQ_INIT(&mlist); + for (curseg = 0; curseg < nsegs; curseg++) { + for (addr = segs[curseg].ds_addr; + addr < (segs[curseg].ds_addr + segs[curseg].ds_len); + addr += PAGE_SIZE) { + m = PHYS_TO_VM_PAGE(addr); + TAILQ_INSERT_TAIL(&mlist, m, pageq); + } + } + + uvm_pglistfree(&mlist); +} + +/* + * Common function for mapping DMA-safe memory. May be called by + * bus-specific DMA memory map functions. + */ +int +_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, + caddr_t *kvap, int flags) +{ + vaddr_t va; + bus_addr_t addr; + int curseg; + + size = round_page(size); + va = uvm_km_valloc(kernel_map, size); + if (va == 0) + return (ENOMEM); + + *kvap = (caddr_t)va; + + for (curseg = 0; curseg < nsegs; curseg++) { + for (addr = segs[curseg].ds_addr; + addr < (segs[curseg].ds_addr + segs[curseg].ds_len); + addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) { + if (size == 0) + panic("_bus_dmamem_map: size botch"); + pmap_enter(pmap_kernel(), va, addr, + VM_PROT_READ | VM_PROT_WRITE, + VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED); + } + } + pmap_update(pmap_kernel()); + + return (0); +} + +/* + * Common function for unmapping DMA-safe memory. May be called by + * bus-specific DMA memory unmapping functions. + */ +void +_dmamem_unmap(bus_dma_tag_t t, caddr_t kva, size_t size) +{ + +#ifdef DIAGNOSTIC + if ((u_long)kva & PGOFSET) + panic("_bus_dmamem_unmap"); +#endif + + size = round_page(size); + uvm_km_free(kernel_map, (vaddr_t)kva, size); +} + +/* + * Common function for mmap(2)'ing DMA-safe memory. May be called by + * bus-specific DMA mmap(2)'ing functions. + */ +paddr_t +_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, off_t off, + int prot, int flags) +{ + int i; + + for (i = 0; i < nsegs; i++) { +#ifdef DIAGNOSTIC + if (off & PGOFSET) + panic("_bus_dmamem_mmap: offset unaligned"); + if (segs[i].ds_addr & PGOFSET) + panic("_bus_dmamem_mmap: segment unaligned"); + if (segs[i].ds_len & PGOFSET) + panic("_bus_dmamem_mmap: segment size not multiple" + " of page size"); +#endif + if (off >= segs[i].ds_len) { + off -= segs[i].ds_len; + continue; + } + + return (atop(segs[i].ds_addr + off)); + } + + /* Page not found. */ + return (-1); +} + +/********************************************************************** + * DMA utility functions + **********************************************************************/ + +/* + * Allocate physical memory from the given physical address range. + * Called by DMA-safe memory allocation methods. + */ +int +_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, + bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs, + int flags, vaddr_t low, vaddr_t high) +{ + vaddr_t curaddr, lastaddr; + struct vm_page *m; + struct pglist mlist; + int curseg, error; + + /* Always round the size. */ + size = round_page(size); + + /* + * Allocate pages from the VM system. + */ + TAILQ_INIT(&mlist); + error = uvm_pglistalloc(size, low, high, + alignment, boundary, &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0); + if (error) + return (error); + + /* + * Compute the location, size, and number of segments actually + * returned by the VM code. + */ + m = TAILQ_FIRST(&mlist); + curseg = 0; + lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m); + segs[curseg].ds_len = PAGE_SIZE; + m = TAILQ_NEXT(m, pageq); + + for (; m != NULL; m = TAILQ_NEXT(m, pageq)) { + curaddr = VM_PAGE_TO_PHYS(m); +#ifdef DIAGNOSTIC + if (curaddr < low || curaddr >= high) { + printf("vm_page_alloc_memory returned non-sensical" + " address 0x%lx\n", curaddr); + panic("dmamem_alloc_range"); + } +#endif + if (curaddr == (lastaddr + PAGE_SIZE)) + segs[curseg].ds_len += PAGE_SIZE; + else { + curseg++; + segs[curseg].ds_addr = curaddr; + segs[curseg].ds_len = PAGE_SIZE; + } + lastaddr = curaddr; + } + + *rsegs = curseg + 1; + + return (0); +} diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c new file mode 100644 index 00000000000..d95c625e504 --- /dev/null +++ b/sys/arch/socppc/socppc/machdep.c @@ -0,0 +1,1147 @@ +/* $OpenBSD: machdep.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ + +/* + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/exec.h> +#include <sys/extent.h> +#include <sys/malloc.h> +#include <sys/mount.h> +#ifdef SYSVMSG +#include <sys/msg.h> +#endif +#include <sys/msgbuf.h> +#include <sys/proc.h> +#include <sys/reboot.h> +#include <sys/signalvar.h> +#include <sys/syscallargs.h> +#include <sys/sysctl.h> +#include <sys/tty.h> +#include <sys/user.h> + +#include <uvm/uvm_extern.h> + +#include <machine/bat.h> +#include <machine/bus.h> +#include <machine/pio.h> +#include <machine/powerpc.h> +#include <machine/trap.h> + +#include <net/netisr.h> + +#include <dev/cons.h> + +#include <dev/ic/comvar.h> + +/* + * Global variables used here and there + */ +extern struct user *proc0paddr; + +/* + * Declare these as initialized data so we can patch them. + */ +#ifndef BUFCACHEPERCENT +#define BUFCACHEPERCENT 5 +#endif + +#ifdef BUFPAGES +int bufpages = BUFPAGES; +#else +int bufpages = 0; +#endif +int bufcachepercent = BUFCACHEPERCENT; + +struct bat battable[16]; + +struct vm_map *exec_map = NULL; +struct vm_map *phys_map = NULL; + +int ppc_malloc_ok = 0; + +void uboot_mem_regions(struct mem_region **, struct mem_region **); +void uboot_vmon(void); + +struct firmware uboot_firmware = { + uboot_mem_regions, + NULL, + NULL, + uboot_vmon +}; + +struct firmware *fw = &uboot_firmware; + +#ifdef APERTURE +#ifdef INSECURE +int allowaperture = 1; +#else +int allowaperture = 0; +#endif +#endif + +caddr_t allocsys(caddr_t); +void dumpsys(void); +int lcsplx(int ipl); +int bus_mem_add_mapping(bus_addr_t, bus_size_t, int, bus_space_handle_t *); +bus_addr_t bus_space_unmap_p(bus_space_tag_t, bus_space_handle_t, bus_size_t); +void bus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t); + +/* + * Extent maps to manage I/O. Allocate storage for 8 regions in each, + * initially. Later devio_malloc_safe will indicate that it's safe to + * use malloc() to dynamically allocate region descriptors. + */ +static long devio_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof (long)]; +struct extent *devio_ex; +static int devio_malloc_safe = 0; + +void initppc(u_int, u_int, char *); + +void prom_printf(const char *, ...); + +extern struct ppc_bus_space mainbus_bus_space; + +void +initppc(u_int startkernel, u_int endkernel, char *args) +{ + extern void *trapcode; extern int trapsize; + extern void *extint; extern int extsize; + extern void *dsitrap; extern int dsisize; + extern void *isitrap; extern int isisize; + extern void *alitrap; extern int alisize; + extern void *decrint; extern int decrsize; + extern void *tlbimiss; extern int tlbimsize; + extern void *tlbdlmiss; extern int tlbdlmsize; + extern void *tlbdsmiss; extern int tlbdsmsize; +#ifdef DDB + extern void *ddblow; extern int ddbsize; +#endif + extern void *msgbuf_addr; + int exc, scratch; + + extern char __bss_start[], __end[]; + bzero(__bss_start, __end - __bss_start); + + proc0.p_cpu = &cpu_info[0]; + proc0.p_addr = proc0paddr; + bzero(proc0.p_addr, sizeof *proc0.p_addr); + + curpcb = &proc0paddr->u_pcb; + + curpm = curpcb->pcb_pmreal = curpcb->pcb_pm = pmap_kernel(); + + ppc_check_procid(); + +#if 0 + { + prom_printf("AER: 0x%08x\n", *(uint32_t *)0xe000080c); + prom_printf("AIDR: 0x%08x\n", *(uint32_t *)0xe0000810); + prom_printf("AEATR: 0x%08x\n", *(uint32_t *)0xe0000818); + prom_printf("AEADR: 0x%08x\n", *(uint32_t *)0xe000081c); + *(uint32_t *)0xe0000810 = 0x00000001; + *(uint32_t *)0xe0000814 = 0x00000001; + *(uint32_t *)0xe0000818 = 0x00000000; + *(uint32_t *)0xe000081c = 0x00000000; + } +#endif + + /* + * Initialize BAT registers to unmapped to not generate + * overlapping mappings below. + */ + ppc_mtibat0u(0); + ppc_mtibat1u(0); + ppc_mtibat2u(0); + ppc_mtibat3u(0); + ppc_mtdbat0u(0); + ppc_mtdbat1u(0); + ppc_mtdbat2u(0); + ppc_mtdbat3u(0); + + /* + * Set up initial BAT table to only map the lowest 256 MB area + */ + battable[0].batl = BATL(0x00000000, BAT_M); +#if 0 + battable[0].batu = BATU(0x00000000); +#else + battable[0].batu = 0x0ffe; /* XXX only map 128MB for now */ +#endif + + /* + * Now setup fixed bat registers + * + * Note that we still run in real mode, and the BAT + * registers were cleared above. + */ + /* IBAT0 used for initial 256 MB segment */ + ppc_mtibat0l(battable[0].batl); + ppc_mtibat0u(battable[0].batu); + + /* DBAT0 used similar */ + ppc_mtdbat0l(battable[0].batl); + ppc_mtdbat0u(battable[0].batu); + + /* + * Set up trap vectors + */ + for (exc = EXC_RSVD; exc <= EXC_LAST; exc += 0x100) { + switch (exc) { + default: + bcopy(&trapcode, (void *)exc, (size_t)&trapsize); + break; + case EXC_EXI: + bcopy(&extint, (void *)EXC_EXI, (size_t)&extsize); + break; + case EXC_DSI: + bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); + break; + case EXC_ISI: + bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); + break; + case EXC_ALI: + bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize); + break; + case EXC_DECR: + bcopy(&decrint, (void *)EXC_DECR, (size_t)&decrsize); + break; + case EXC_IMISS: + bcopy(&tlbimiss, (void *)EXC_IMISS, (size_t)&tlbimsize); + break; + case EXC_DLMISS: + bcopy(&tlbdlmiss, (void *)EXC_DLMISS, (size_t)&tlbdlmsize); + break; + case EXC_DSMISS: + bcopy(&tlbdsmiss, (void *)EXC_DSMISS, (size_t)&tlbdsmsize); + break; + case EXC_PGM: + case EXC_TRC: + case EXC_BPT: +#if defined(DDB) + bcopy(&ddblow, (void *)exc, (size_t)&ddbsize); +#endif + break; + } + } + + syncicache((void *)EXC_RST, EXC_LAST - EXC_RST + 0x100); + + + uvmexp.pagesize = 4096; + uvm_setpagesize(); + + /* + * Initialize pmap module. + */ + pmap_bootstrap(startkernel, endkernel); + + /* now that we know physmem size, map physical memory with BATs */ + if (physmem > atop(0x10000000)) { + battable[0x1].batl = BATL(0x10000000, BAT_M); + battable[0x1].batu = BATU(0x10000000); + } + if (physmem > atop(0x20000000)) { + battable[0x2].batl = BATL(0x20000000, BAT_M); + battable[0x2].batu = BATU(0x20000000); + } + if (physmem > atop(0x30000000)) { + battable[0x3].batl = BATL(0x30000000, BAT_M); + battable[0x3].batu = BATU(0x30000000); + } + if (physmem > atop(0x40000000)) { + battable[0x4].batl = BATL(0x40000000, BAT_M); + battable[0x4].batu = BATU(0x40000000); + } + if (physmem > atop(0x50000000)) { + battable[0x5].batl = BATL(0x50000000, BAT_M); + battable[0x5].batu = BATU(0x50000000); + } + if (physmem > atop(0x60000000)) { + battable[0x6].batl = BATL(0x60000000, BAT_M); + battable[0x6].batu = BATU(0x60000000); + } + if (physmem > atop(0x70000000)) { + battable[0x7].batl = BATL(0x70000000, BAT_M); + battable[0x7].batu = BATU(0x70000000); + } + + /* + * Now enable translation (and machine checks/recoverable interrupts). + */ + (fw->vmon)(); + +#if 0 + ppc_mtdbat1l(BATL(0xe0000000, BAT_M | BAT_I | BAT_G)); + ppc_mtdbat1u(0xe000000e); +#endif + + __asm__ volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; sync;isync" + : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); + + /* + * use the memory provided by pmap_bootstrap for message buffer + */ + initmsgbuf(msgbuf_addr, MSGBUFSIZE); + + /* + * Look at arguments passed to us and compute boothowto. + */ + boothowto = RB_AUTOBOOT; + + devio_ex = extent_create("devio", 0x80000000, 0xffffffff, M_DEVBUF, + (caddr_t)devio_ex_storage, sizeof(devio_ex_storage), + EX_NOCOALESCE|EX_NOWAIT); + + /* + * Replace with real console. + */ + extern int comconsrate; + comconsfreq = 266666666; + comconsrate = 115200; + comconsaddr = 0x00004500; + comconsiot = &mainbus_bus_space; + consinit(); +} + +void +dumpsys(void) +{ +} + +int imask[IPL_NUM]; + +int netisr; + +/* + * Soft networking interrupts. + */ +void +softnet(int isr) +{ +#define DONETISR(flag, func) \ + if (isr & (1 << flag))\ + func(); + +#include <net/netisr_dispatch.h> +} + +int +lcsplx(int ipl) +{ + return spllower(ipl); +} + +/* BUS functions */ +int +bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, + int cacheable, bus_space_handle_t *bshp) +{ + int error; + + if (POWERPC_BUS_TAG_BASE(t) == 0) { + /* if bus has base of 0 fail. */ + return 1; + } + bpa |= POWERPC_BUS_TAG_BASE(t); + if ((error = extent_alloc_region(devio_ex, bpa, size, EX_NOWAIT | + (ppc_malloc_ok ? EX_MALLOCOK : 0)))) + return error; + + if ((error = bus_mem_add_mapping(bpa, size, cacheable, bshp))) { + if (extent_free(devio_ex, bpa, size, EX_NOWAIT | + (ppc_malloc_ok ? EX_MALLOCOK : 0))) + { + printf("bus_space_map: pa 0x%lx, size 0x%x\n", + bpa, size); + printf("bus_space_map: can't free region\n"); + } + } + return 0; +} + +bus_addr_t +bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) +{ + bus_addr_t paddr; + + pmap_extract(pmap_kernel(), bsh, &paddr); + bus_space_unmap((t), (bsh), (size)); + return paddr ; +} + +void +bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) +{ + bus_addr_t sva; + bus_size_t off, len; + bus_addr_t bpa; + + /* should this verify that the proper size is freed? */ + sva = trunc_page(bsh); + off = bsh - sva; + len = size+off; + + if (pmap_extract(pmap_kernel(), sva, &bpa) == TRUE) { + if (extent_free(devio_ex, bpa | (bsh & PAGE_MASK), size, EX_NOWAIT | + (ppc_malloc_ok ? EX_MALLOCOK : 0))) + { + printf("bus_space_map: pa 0x%lx, size 0x%x\n", + bpa, size); + printf("bus_space_map: can't free region\n"); + } + } + /* do not free memory which was stolen from the vm system */ + if (ppc_malloc_ok && + ((sva >= VM_MIN_KERNEL_ADDRESS) && (sva < VM_MAX_KERNEL_ADDRESS))) + uvm_km_free(phys_map, sva, len); + else { + pmap_remove(pmap_kernel(), sva, sva+len); + pmap_update(pmap_kernel()); + } +} + +vaddr_t ppc_kvm_stolen = VM_KERN_ADDRESS_SIZE; + +int +bus_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int cacheable, + bus_space_handle_t *bshp) +{ + bus_addr_t vaddr; + bus_addr_t spa, epa; + bus_size_t off; + int len; + + spa = trunc_page(bpa); + epa = bpa + size; + off = bpa - spa; + len = size+off; + +#if 0 + if (epa <= spa) { + panic("bus_mem_add_mapping: overflow"); + } +#endif + if (ppc_malloc_ok == 0) { + bus_size_t alloc_size; + + /* need to steal vm space before kernel vm is initialized */ + alloc_size = round_page(len); + + vaddr = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen; + ppc_kvm_stolen += alloc_size; + if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) { + panic("ppc_kvm_stolen, out of space"); + } + } else { + vaddr = uvm_km_kmemalloc(phys_map, NULL, len, + UVM_KMF_NOWAIT|UVM_KMF_VALLOC); + if (vaddr == 0) + panic("bus_mem_add_mapping: kvm alloc of 0x%x failed", + len); + } + *bshp = vaddr + off; +#ifdef DEBUG_BUS_MEM_ADD_MAPPING + printf("mapping %x size %x to %x vbase %x\n", + bpa, size, *bshp, spa); +#endif + for (; len > 0; len -= PAGE_SIZE) { + pmap_kenter_cache(vaddr, spa, + VM_PROT_READ | VM_PROT_WRITE, + cacheable ? PMAP_CACHE_WT : PMAP_CACHE_CI); + spa += PAGE_SIZE; + vaddr += PAGE_SIZE; + } + return 0; +} + +int +bus_space_alloc(bus_space_tag_t tag, bus_addr_t rstart, bus_addr_t rend, + bus_size_t size, bus_size_t alignment, bus_size_t boundary, int cacheable, + bus_addr_t *addrp, bus_space_handle_t *handlep) +{ + + panic("bus_space_alloc: unimplemented"); +} + +void +bus_space_free(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size) +{ + + panic("bus_space_free: unimplemented"); +} + +void * +mapiodev(paddr_t pa, psize_t len) +{ + paddr_t spa; + vaddr_t vaddr, va; + int off; + int size; + + spa = trunc_page(pa); + off = pa - spa; + size = round_page(off+len); + if (ppc_malloc_ok == 0) { + /* need to steal vm space before kernel vm is initialized */ + va = VM_MIN_KERNEL_ADDRESS + ppc_kvm_stolen; + ppc_kvm_stolen += size; + if (ppc_kvm_stolen > PPC_SEGMENT_LENGTH) { + panic("ppc_kvm_stolen, out of space"); + } + } else { + va = uvm_km_kmemalloc(phys_map, NULL, size, + UVM_KMF_NOWAIT|UVM_KMF_VALLOC); + } + + if (va == 0) + return NULL; + + for (vaddr = va; size > 0; size -= PAGE_SIZE) { + pmap_kenter_cache(vaddr, spa, + VM_PROT_READ | VM_PROT_WRITE, PMAP_CACHE_DEFAULT); + spa += PAGE_SIZE; + vaddr += PAGE_SIZE; + } + return (void *) (va+off); +} + +void +unmapiodev(void *kva, psize_t p_size) +{ + vaddr_t vaddr; + int size; + + size = p_size; + + vaddr = trunc_page((vaddr_t)kva); + + uvm_km_free_wakeup(phys_map, vaddr, size); + + for (; size > 0; size -= PAGE_SIZE) { + pmap_remove(pmap_kernel(), vaddr, vaddr+PAGE_SIZE-1); + vaddr += PAGE_SIZE; + } + pmap_update(pmap_kernel()); +} + + +/* + * probably should be ppc_space_copy + */ + +#define _CONCAT(A,B) A ## B +#define __C(A,B) _CONCAT(A,B) + +#define BUS_SPACE_COPY_N(BYTES,TYPE) \ +void \ +__C(bus_space_copy_,BYTES)(void *v, bus_space_handle_t h1, \ + bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, \ + bus_size_t c) \ +{ \ + TYPE *src, *dst; \ + int i; \ + \ + src = (TYPE *) (h1+o1); \ + dst = (TYPE *) (h2+o2); \ + \ + if (h1 == h2 && o2 > o1) \ + for (i = c-1; i >= 0; i--) \ + dst[i] = src[i]; \ + else \ + for (i = 0; i < c; i++) \ + dst[i] = src[i]; \ +} +BUS_SPACE_COPY_N(1,u_int8_t) +BUS_SPACE_COPY_N(2,u_int16_t) +BUS_SPACE_COPY_N(4,u_int32_t) + +void +bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int8_t val, bus_size_t c) +{ + u_int8_t *dst; + int i; + + dst = (u_int8_t *) (h+o); + + for (i = 0; i < c; i++) + dst[i] = val; +} + +void +bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int16_t val, bus_size_t c) +{ + u_int16_t *dst; + int i; + + dst = (u_int16_t *) (h+o); + val = swap16(val); + + for (i = 0; i < c; i++) + dst[i] = val; +} +void +bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int32_t val, bus_size_t c) +{ + u_int32_t *dst; + int i; + + dst = (u_int32_t *) (h+o); + val = swap32(val); + + for (i = 0; i < c; i++) + dst[i] = val; +} + +#define BUS_SPACE_READ_RAW_MULTI_N(BYTES,SHIFT,TYPE) \ +void \ +__C(bus_space_read_raw_multi_,BYTES)(bus_space_tag_t bst, \ + bus_space_handle_t h, bus_addr_t o, u_int8_t *dst, bus_size_t size) \ +{ \ + TYPE *src; \ + TYPE *rdst = (TYPE *)dst; \ + int i; \ + int count = size >> SHIFT; \ + \ + src = (TYPE *)(h+o); \ + for (i = 0; i < count; i++) { \ + rdst[i] = *src; \ + __asm__("eieio"); \ + } \ +} +BUS_SPACE_READ_RAW_MULTI_N(2,1,u_int16_t) +BUS_SPACE_READ_RAW_MULTI_N(4,2,u_int32_t) + +#define BUS_SPACE_WRITE_RAW_MULTI_N(BYTES,SHIFT,TYPE) \ +void \ +__C(bus_space_write_raw_multi_,BYTES)( bus_space_tag_t bst, \ + bus_space_handle_t h, bus_addr_t o, const u_int8_t *src, \ + bus_size_t size) \ +{ \ + int i; \ + TYPE *dst; \ + TYPE *rsrc = (TYPE *)src; \ + int count = size >> SHIFT; \ + \ + dst = (TYPE *)(h+o); \ + for (i = 0; i < count; i++) { \ + *dst = rsrc[i]; \ + __asm__("eieio"); \ + } \ +} + +BUS_SPACE_WRITE_RAW_MULTI_N(2,1,u_int16_t) +BUS_SPACE_WRITE_RAW_MULTI_N(4,2,u_int32_t) + +int +bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) +{ + *nbshp = bsh + offset; + return (0); +} + +/* + * Machine dependent startup code. + */ +void +cpu_startup() +{ + int sz; + caddr_t v; + vaddr_t minaddr, maxaddr; + + v = (caddr_t)proc0paddr + USPACE; + proc0.p_addr = proc0paddr; + + printf("%s", version); + + printf("real mem = %u (%uMB)\n", ptoa(physmem), + ptoa(physmem)/1024/1024); + + /* + * Find out how much space we need, allocate it, + * and then give everything true virtual addresses. + */ + sz = (int)allocsys((caddr_t)0); + if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0) + panic("startup: no room for tables"); + if (allocsys(v) - v != sz) + panic("startup: table size inconsistency"); + + /* + * Determine how many buffers to allocate. + * We allocate bufcachepercent% of memory for buffer space. + */ + if (bufpages == 0) + bufpages = physmem * bufcachepercent / 100; + + /* Restrict to at most 25% filled kvm */ + if (bufpages > + (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4) + bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / + PAGE_SIZE / 4; + + /* + * Allocate a submap for exec arguments. This map effectively + * limits the number of processes exec'ing at any time. + */ + minaddr = vm_map_min(kernel_map); + exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 16 * NCARGS, + VM_MAP_PAGEABLE, FALSE, NULL); + + /* + * Allocate a submap for physio + */ + phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, + VM_PHYS_SIZE, 0, FALSE, NULL); + ppc_malloc_ok = 1; + + printf("avail mem = %lu (%luMB)\n", ptoa(uvmexp.free), + ptoa(uvmexp.free) / 1024 / 1024); + + /* + * Set up the buffers. + */ + bufinit(); + + devio_malloc_safe = 1; +} + +/* + * Allocate space for system data structures. + */ +caddr_t +allocsys(caddr_t v) +{ +#define valloc(name, type, num) \ + v = (caddr_t)(((name) = (type *)v) + (num)) + +#ifdef SYSVMSG + valloc(msgpool, char, msginfo.msgmax); + valloc(msgmaps, struct msgmap, msginfo.msgseg); + valloc(msghdrs, struct msg, msginfo.msgtql); + valloc(msqids, struct msqid_ds, msginfo.msgmni); +#endif + + return v; +} + +/* + * consinit + * Initialize system console. + */ +void +consinit() +{ + static int cons_initted = 0; + + if (cons_initted) + return; + cninit(); + cons_initted = 1; +} + +/* + * Clear registers on exec + */ +void +setregs(struct proc *p, struct exec_package *pack, u_long stack, + register_t *retval) +{ + u_int32_t newstack; + u_int32_t pargs; + u_int32_t args[4]; + + struct trapframe *tf = trapframe(p); + pargs = -roundup(-stack + 8, 16); + newstack = (u_int32_t)(pargs - 32); + + copyin ((void *)(VM_MAX_ADDRESS-0x10), &args, 0x10); + + bzero(tf, sizeof *tf); + tf->fixreg[1] = newstack; + tf->fixreg[3] = retval[0] = args[1]; /* XXX */ + tf->fixreg[4] = retval[1] = args[0]; /* XXX */ + tf->fixreg[5] = args[2]; /* XXX */ + tf->fixreg[6] = args[3]; /* XXX */ + tf->srr0 = pack->ep_entry; + tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; + p->p_addr->u_pcb.pcb_flags = 0; +} + +/* + * Send a signal to process. + */ +void +sendsig(sig_t catcher, int sig, int mask, u_long code, int type, + union sigval val) +{ + struct proc *p = curproc; + struct trapframe *tf; + struct sigframe *fp, frame; + struct sigacts *psp = p->p_sigacts; + int oldonstack; + + frame.sf_signum = sig; + + tf = trapframe(p); + oldonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; + + /* + * Allocate stack space for signal handler. + */ + if ((psp->ps_flags & SAS_ALTSTACK) + && !oldonstack + && (psp->ps_sigonstack & sigmask(sig))) { + fp = (struct sigframe *)(psp->ps_sigstk.ss_sp + + psp->ps_sigstk.ss_size); + psp->ps_sigstk.ss_flags |= SS_ONSTACK; + } else + fp = (struct sigframe *)tf->fixreg[1]; + + fp = (struct sigframe *)((int)(fp - 1) & ~0xf); + + /* + * Generate signal context for SYS_sigreturn. + */ + frame.sf_sc.sc_onstack = oldonstack; + frame.sf_sc.sc_mask = mask; + frame.sf_sip = NULL; + bcopy(tf, &frame.sf_sc.sc_frame, sizeof *tf); + if (psp->ps_siginfo & sigmask(sig)) { + frame.sf_sip = &fp->sf_si; + initsiginfo(&frame.sf_si, sig, code, type, val); + } + if (copyout(&frame, fp, sizeof frame) != 0) + sigexit(p, SIGILL); + + + tf->fixreg[1] = (int)fp; + tf->lr = (int)catcher; + tf->fixreg[3] = (int)sig; + tf->fixreg[4] = (psp->ps_siginfo & sigmask(sig)) ? (int)&fp->sf_si : 0; + tf->fixreg[5] = (int)&fp->sf_sc; + tf->srr0 = p->p_sigcode; + +#if WHEN_WE_ONLY_FLUSH_DATA_WHEN_DOING_PMAP_ENTER + pmap_extract(vm_map_pmap(&p->p_vmspace->vm_map),tf->srr0, &pa); + syncicache(pa, (p->p_emul->e_esigcode - p->p_emul->e_sigcode)); +#endif +} + +/* + * System call to cleanup state after a signal handler returns. + */ +int +sys_sigreturn(struct proc *p, void *v, register_t *retval) +{ + struct sys_sigreturn_args /* { + syscallarg(struct sigcontext *) sigcntxp; + } */ *uap = v; + struct sigcontext sc; + struct trapframe *tf; + int error; + + if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc))) + return error; + tf = trapframe(p); + if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) + return EINVAL; + bcopy(&sc.sc_frame, tf, sizeof *tf); + if (sc.sc_onstack & 1) + p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; + p->p_sigmask = sc.sc_mask & ~sigcantmask; + return EJUSTRETURN; +} + +/* + * Machine dependent system variables. + * None for now. + */ +int +cpu_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen, struct proc *p) +{ + /* all sysctl names at this level are terminal */ + if (namelen != 1) + return ENOTDIR; + switch (name[0]) { + case CPU_ALLOWAPERTURE: +#ifdef APERTURE + if (securelevel > 0) + return (sysctl_int_lower(oldp, oldlenp, newp, newlen, + &allowaperture)); + else + return (sysctl_int(oldp, oldlenp, newp, newlen, + &allowaperture)); +#else + return (sysctl_rdint(oldp, oldlenp, newp, 0)); +#endif + case CPU_ALTIVEC: + return (sysctl_rdint(oldp, oldlenp, newp, 0)); + default: + return EOPNOTSUPP; + } +} + +u_long dumpmag = 0x04959fca; /* magic number */ +int dumpsize = 0; /* size of dump in pages */ +long dumplo = -1; /* blocks */ + +/* + * This is called by configure to set dumplo and dumpsize. + * Dumps always skip the first CLBYTES of disk space + * in case there might be a disk label stored there. + * If there is extra space, put dump at the end to + * reduce the chance that swapping trashes it. + */ +void dumpconf(void); + +void +dumpconf(void) +{ + int nblks; /* size of dump area */ + int i; + + if (dumpdev == NODEV || + (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0) + return; + if (nblks <= ctod(1)) + return; + + /* Always skip the first block, in case there is a label there. */ + if (dumplo < ctod(1)) + dumplo = ctod(1); + + for (i = 0; i < ndumpmem; i++) + dumpsize = max(dumpsize, dumpmem[i].end); + + /* Put dump at end of partition, and make it fit. */ + if (dumpsize > dtoc(nblks - dumplo - 1)) + dumpsize = dtoc(nblks - dumplo - 1); + if (dumplo < nblks - ctod(dumpsize) - 1) + dumplo = nblks - ctod(dumpsize) - 1; + +} + +#define BYTES_PER_DUMP (PAGE_SIZE) /* must be a multiple of pagesize */ +vaddr_t dumpspace; + +int +reserve_dumppages(caddr_t p) +{ + dumpspace = (vaddr_t)p; + return BYTES_PER_DUMP; +} + +/* + * Halt or reboot the machine after syncing/dumping according to howto. + */ +void +boot(int howto) +{ + static int syncing; + + boothowto = howto; + if (!cold && !(howto & RB_NOSYNC) && !syncing) { + syncing = 1; + vfs_shutdown(); /* sync */ + + /* + * 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"); + } + } + + uvm_shutdown(); + splhigh(); + if (howto & RB_HALT) { + doshutdownhooks(); + if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { + ; + } + + printf("halted\n\n"); + (fw->exit)(); + } + if (!cold && (howto & RB_DUMP)) + dumpsys(); + doshutdownhooks(); + printf("rebooting\n\n"); + + { + volatile int32_t *reset; + int32_t v; + + reset = mapiodev(0xe0000900, 0x100); + reset[6] = 0x52535445; + v = reset[6]; + reset[7] = 0x00000002; + } + + printf("boot failed, spinning\n"); + while(1) /* forever */; +} + +extern void ipic_do_pending_int(void); + +void +do_pending_int(void) +{ + struct cpu_info *ci = curcpu(); + int pcpl, s; + + if (ci->ci_iactive) + return; + + ci->ci_iactive = 1; + s = ppc_intr_disable(); + pcpl = ci->ci_cpl; + + ipic_do_pending_int(); + + do { + if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) { + ci->ci_ipending &= ~SINT_CLOCK; + ci->ci_cpl = SINT_CLOCK|SINT_NET|SINT_TTY; + ppc_intr_enable(1); + KERNEL_LOCK(); + softclock(); + KERNEL_UNLOCK(); + ppc_intr_disable(); + continue; + } + if((ci->ci_ipending & SINT_NET) & ~pcpl) { + extern int netisr; + int pisr; + + ci->ci_ipending &= ~SINT_NET; + ci->ci_cpl = SINT_NET|SINT_TTY; + while ((pisr = netisr) != 0) { + atomic_clearbits_int(&netisr, pisr); + ppc_intr_enable(1); + KERNEL_LOCK(); + softnet(pisr); + KERNEL_UNLOCK(); + ppc_intr_disable(); + } + continue; + } +#if 0 + if((ci->ci_ipending & SINT_TTY) & ~pcpl) { + ci->ci_ipending &= ~SINT_TTY; + ci->ci_cpl = SINT_TTY; + ppc_intr_enable(1); + KERNEL_LOCK(); + softtty(); + KERNEL_UNLOCK(); + ppc_intr_disable(); + continue; + } +#endif + } while ((ci->ci_ipending & SINT_MASK) & ~pcpl); + ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */ + + ci->ci_iactive = 0; + ppc_intr_enable(s); +} + +/* + * Notify the current process (p) that it has a signal pending, + * process as soon as possible. + */ +void +signotify(struct proc *p) +{ + aston(p); +} + +/* bcopy(), error on fault */ +int +kcopy(const void *from, void *to, size_t size) +{ + faultbuf env; + void *oldh = curproc->p_addr->u_pcb.pcb_onfault; + + if (setfault(&env)) { + curproc->p_addr->u_pcb.pcb_onfault = oldh; + return EFAULT; + } + bcopy(from, to, size); + curproc->p_addr->u_pcb.pcb_onfault = oldh; + + return 0; +} + +struct mem_region uboot_mem[2] = { + { 0x00000000, 0x04000000 }, + { 0, 0 } +}; + +struct mem_region uboot_avail[2] = { + { 0x00800000, 0x04000000 }, + { 0, 0 } +}; + +void +uboot_mem_regions(struct mem_region **memp, struct mem_region **availp) +{ + *memp = uboot_mem; + *availp = uboot_avail; +} + +void +uboot_vmon(void) +{ +} + +/* prototype for locore function */ +void cpu_switchto_asm(struct proc *oldproc, struct proc *newproc); + +void cpu_switchto(struct proc *oldproc, struct proc *newproc) +{ + cpu_switchto_asm(oldproc, newproc); +} diff --git a/sys/arch/socppc/socppc/mainbus.c b/sys/arch/socppc/socppc/mainbus.c new file mode 100644 index 00000000000..ecd92ab7389 --- /dev/null +++ b/sys/arch/socppc/socppc/mainbus.c @@ -0,0 +1,77 @@ +/* $OpenBSD: mainbus.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ + +/* + * Copyright (c) 2008 Mark Kettenis + * + * 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 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 <machine/autoconf.h> + +int mainbus_match(struct device *, void *, void *); +void mainbus_attach(struct device *, struct device *, void *); + +struct cfattach mainbus_ca = { + sizeof(struct device), mainbus_match, mainbus_attach +}; + +struct cfdriver mainbus_cd = { + NULL, "mainbus", DV_DULL +}; + +int mainbus_search(struct device *, void *, void *); +int mainbus_print(void *, const char *); + +int +mainbus_match(struct device *parent, void *cfdata, void *aux) +{ + return (1); +} + +void +mainbus_attach(struct device *parent, struct device *self, void *aux) +{ + printf("\n"); + + config_search(mainbus_search, self, self); +} + +struct ppc_bus_space mainbus_bus_space = { 0xe0000000, 0x1000000, 1 }; + +int +mainbus_search(struct device *parent, void *cfdata, void *aux) +{ + struct mainbus_attach_args ma; + struct cfdata *cf = cfdata; + + ma.ma_iot = &mainbus_bus_space; + ma.ma_name = cf->cf_driver->cd_name; + config_found(parent, &ma, mainbus_print); + + return (1); +} + +int +mainbus_print(void *aux, const char *name) +{ + struct mainbus_attach_args *ma = aux; + + if (name) + printf("%s at %s", ma->ma_name, name); + + return (UNCONF); +} diff --git a/sys/arch/socppc/socppc/mem.c b/sys/arch/socppc/socppc/mem.c new file mode 100644 index 00000000000..add5fc64368 --- /dev/null +++ b/sys/arch/socppc/socppc/mem.c @@ -0,0 +1,179 @@ +/* $OpenBSD: mem.c,v 1.1 2008/05/10 12:02:21 kettenis Exp $ */ +/* $NetBSD: mem.c,v 1.1 1996/09/30 16:34:50 ws Exp $ */ + +/* + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mem.c 8.3 (Berkeley) 1/12/94 + */ + +/* + * Memory special file + */ + +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/systm.h> +#include <sys/ioccom.h> +#include <sys/uio.h> +#include <sys/malloc.h> +#include <sys/types.h> + +#include <machine/cpu.h> + +#include <uvm/uvm_extern.h> + +#include <machine/conf.h> + +/*ARGSUSED*/ +int +mmopen(dev_t dev, int flag, int mode, struct proc *p) +{ + + switch (minor(dev)) { + case 0: + case 1: + case 2: + case 12: + break; +#ifdef xAPERTURE + case 4: + if (suser(p, 0) != 0 || !allowaperture) + return (EPERM); + + /* authorize only one simultaneous open() */ + if (ap_open_count > 0) + return(EPERM); + ap_open_count++; + break; +#endif + default: + return (ENXIO); + } + return (0); +} + +/*ARGSUSED*/ +int +mmclose(dev_t dev, int flag, int mode, struct proc *p) +{ +#ifdef xAPERTURE + if (minor(dev) == 4) + ap_open_count--; +#endif + return 0; +} + +/*ARGSUSED*/ +int +mmrw(dev_t dev, struct uio *uio, int flags) +{ + vaddr_t v; + vsize_t c; + struct iovec *iov; + int error = 0; + static caddr_t zeropage; + + while (uio->uio_resid > 0 && error == 0) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("mmrw"); + continue; + } + switch (minor(dev)) { + + /* minor device 0 is physical memory */ + case 0: + v = uio->uio_offset; + c = uio->uio_resid; + /* This doesn't allow device mapping! XXX */ + pmap_real_memory(&v, &c); + error = uiomove((caddr_t)v, c, uio); + continue; + + /* minor device 1 is kernel memory */ + case 1: + v = uio->uio_offset; + c = min(iov->iov_len, MAXPHYS); + error = uiomove((caddr_t)v, c, uio); + continue; + + /* minor device 2 is EOF/RATHOLE */ + case 2: + if (uio->uio_rw == UIO_WRITE) + uio->uio_resid = 0; + return 0; + + /* minor device 12 (/dev/zero) is source of nulls on read, + * rathole on write + */ + case 12: + if (uio->uio_rw == UIO_WRITE) { + c = iov->iov_len; + break; + } + if (zeropage == NULL) + zeropage = malloc(PAGE_SIZE, M_TEMP, + M_WAITOK | M_ZERO); + c = min(iov->iov_len, PAGE_SIZE); + error = uiomove(zeropage, c, uio); + continue; + + default: + return ENXIO; + } + if (error) + break; + iov->iov_base += c; + iov->iov_len -= c; + uio->uio_offset += c; + uio->uio_resid -= c; + } + return error; +} + +paddr_t +mmmmap(dev_t dev, off_t off, int prot) +{ + return (-1); +} + +/*ARGSUSED*/ +int +mmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + return (EOPNOTSUPP); +} |