diff -u --recursive --new-file v2.1.79/linux/CREDITS linux/CREDITS --- v2.1.79/linux/CREDITS Tue Jan 6 09:37:32 1998 +++ linux/CREDITS Tue Jan 20 16:44:57 1998 @@ -1335,11 +1335,12 @@ S: USA N: Stefan Reinauer -E: stepan@home.culture.mipt.ru -W: http://home.culture.mipt.ru/~stepan -D: Modularized affs and ufs. Minor fixes. -S: Rebmannsweg 34h -S: 79539 Loerrach +E: stepan@linux.de +W: http://www.freiburg.linux.de/~stepan/ +D: Modularization of some filesystems +D: /proc/sound, minor fixes +S: Schlossbergring 9 +S: 79098 Freiburg S: Germany N: Joerg Reuter diff -u --recursive --new-file v2.1.79/linux/Documentation/ARM-README linux/Documentation/ARM-README --- v2.1.79/linux/Documentation/ARM-README Wed Dec 31 16:00:00 1969 +++ linux/Documentation/ARM-README Tue Jan 20 16:39:41 1998 @@ -0,0 +1,169 @@ + ARM Linux 2.1.78 + ================ + + ** The ARM support contained within is NOT complete - it will not build. ** + ** If you want to build it, then please obtain a full copy of the ARM ** + ** patches from ftp://ftp.arm.uk.linux.org/pub/armlinux/kernel-sources/v2.1 ** + + Since this is a development kernel, it will not be as stable as the 2.0 + series, and can cause very nasty problems (eg, trashing your hard disk). + When running one of these kernels, I advise you to back up the complete + contents of all your hard disks. + +Contributors +------------ + + Here is a list of people actively working on the project (If you + wish to be added to the list, please email me): + + Name: Russell King + Mail: linux@arm.uk.linux.org + Desc: Original developer of ARM Linux, project co-ordinator. + + Name: Dave Gilbert + Mail: linux@treblig.org + Desc: A3/4/5xx floppy and hard disk code maintainer. + + Name: Philip Blundell + Mail: Philip.Blundell@pobox.com + Desc: Architecture and processor selection during make config. + +Todo list +--------- + + This is the list of changes to be done (roughly prioritorised): + + * fully test new A5000 & older MEMC translation code + * fully test new AcornSCSI driver. + * reply to email ;) + +Bugs +---- + + Fixed bugs in this version 2.1.76: + + Modules believed to be buggy (please report your successes/failures): + + * AcornSCSI believed to occasionally corrupt hard drives. + * All NCR5380-based SCSI devices [Cumana I, Oak, EcoSCSI] are slow, + and may not allow write access. + * A5000 and older machine kernel builds may not be as stable as they were. + + Notes + ===== + +Compilation of kernel +--------------------- + + In order to compile ARM Linux, you will need a compiler capable of + generating ARM ELF code with GNU extensions. GCC-2.7.2.2 is good. + + To build ARM Linux natively, you shouldn't have to alter the ARCH = line in + the top level Makefile. However, if you don't have the ARM Linux ELF tools + installed as default, then you should change the CROSS_COMPILE line as + detailed below. + + If you wish to cross-compile, then alter the following lines in the top + level make file: + + ARCH = + with + ARCH = arm + + and + + CROSS_COMPILE= + to + CROSS_COMPILE= + eg. + CROSS_COMPILE=/usr/src/bin/arm/arm-linuxelf- + + Do a 'make config', followed by 'make dep', and finally 'make all' to + build the kernel (vmlinux). A compressed image can be built by doing + a 'make zImage' instead of 'make all'. + +Bug reports etc +--------------- + + Please send patches, bug reports and code for the ARM Linux project + to linux@arm.uk.linux.org. Patches will not be included into future + kernels unless they come to me (or the relevant person concerned). + + When sending bug reports, please ensure that they contain all relevent + information, eg. the kernel messages that were printed before/during + the problem, what you were doing, etc. + + For patches, please include some explaination as to what the patch does + and why (if relevent). + +Modules +------- + + Although modularisation is supported (and required for the FP emulator), + each module on an arm2/arm250/arm3 machine when is loaded will take + memory up to the next 32k boundary due to the size of the pages. Hence is + modularisation on these machines really worth it? + + However, arm6 and up machines allow modules to take multiples of 4k, and + as such Acorn RiscPCs and other architectures using these processors can + make good use of modularisation. + +ADFS Image files +---------------- + + You can access image files on your ADFS partitions by mounting the ADFS + partition, and then using the loopback device driver. You must have + losetup installed. + + Please note that the PCEmulator DOS partitions have a partition table at + the start, and as such, you will have to give '-o offset' to losetup. + +Kernel initialisation abort codes +--------------------------------- + + When the kernel is unable to boot, it will if possible display a colour + at the top of the screen. The colours have the following significance + when run in a 16 colour mode with the default palette: + + Stripes of White,Red,Yellow,Green: + Kernel does not support the processor architecture detected. + +Request to developers +--------------------- + + When writing device drivers which include a separate assember file, please + include it in with the C file, and not the arch/arm/lib directory. This + allows the driver to be compiled as a loadable module without requiring + half the code to be needlessly compiled into the kernel image. + + In general, try to avoid using assembler unless it is really necessary. It + makes drivers far less easy to port to other hardware. + +ST506 hard drives +----------------- + + The ST506 hard drive controllers seem to be working fine (if a little + slowly). At the moment they will only work off the controllers on an + A4x0's motherboard, but for it to work off a Podule just requires + someone with a podule to add the addresses for the IRQ mask and the + HDC base to the source. + + As of 31/3/96 it works with two drives (you should get the ADFS + *configure harddrive set to 2). I've got an internal 20MB and a great + big external 5.25" FH 64MB drive (who could ever want more :-) ). + + I've just got 240K/s off it (a dd with bs=128k); thats about half of what + RiscOS gets; but its a heck of a lot better than the 50K/s I was getting + last week :-) + + Known bug: Drive data errors can cause a hang; including cases where + the controller has fixed the error using ECC. (Possibly ONLY + in that case...hmm). + + +1772 Floppy +----------- + This also seems to work OK, but hasn't been stressed much lately. It + hasn't got any code for disc change detection in there at the moment which + could be a bit of a problem! Suggestions on the correct way to do this + are welcome. diff -u --recursive --new-file v2.1.79/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.79/linux/Documentation/Configure.help Mon Jan 12 22:09:07 1998 +++ linux/Documentation/Configure.help Thu Jan 15 14:33:05 1998 @@ -725,6 +725,29 @@ see http://www.inka.de/sites/lina/linux/NetTools/index_en.html for details. +Fast switching (read help!) +CONFIG_NET_FASTROUTE + Enable direct NIC-to-NIC data transfers. + *** This option is NOT COMPATIBLE with several important *** + *** networking options: especially CONFIG*FIREWALL. *** + However, it will work with all options in CONFIG_IP_ADVANCED_ROUTER + section (except for CONFIG_IP_ROUTE_TOS). At the moment few of devices + supports it (tulip is one of them, modified 8390 can be found at + ftp://ftp.inr.ac.ru/ip-routing/fastroute-8390.tar.gz). + Remember, short cuts make long delays :-), say N. + +Forwarding between high speed interfaces +CONFIG_NET_HW_FLOWCONTROL + This option enables NIC hardware throttling during periods of + extremal congestion. At the moment only couple of device drivers + support it (really, one --- tulip, modified 8390 can be found + at ftp://ftp.inr.ac.ru/ip-routing/fastroute-8390.tar.gz). + Really, this option is applicable to any machine attached + to enough fast network, and even 10Mb NIC + is able to kill not very slow box, sort of 120MHz Pentium. + However, do not enable this option, if you did not experienced + any serious problems. + Network aliasing CONFIG_NET_ALIAS This will allow you to set multiple network addresses on the same diff -u --recursive --new-file v2.1.79/linux/Makefile linux/Makefile --- v2.1.79/linux/Makefile Mon Jan 12 22:09:07 1998 +++ linux/Makefile Wed Jan 14 11:25:15 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 79 +SUBLEVEL = 80 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) diff -u --recursive --new-file v2.1.79/linux/Rules.make linux/Rules.make --- v2.1.79/linux/Rules.make Tue Jan 6 09:37:32 1998 +++ linux/Rules.make Tue Jan 13 11:47:55 1998 @@ -56,7 +56,7 @@ echo 'ifeq ($(strip $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@)),$$(strip $$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@)))' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'endif' \ - ) > .$@.flags + ) > $(dir $@)/.$(notdir $@).flags %.o: %.s $(AS) $(ASFLAGS) $(EXTRA_CFLAGS) -o $@ $< @@ -82,7 +82,7 @@ echo 'ifeq ($(strip $(EXTRA_LDFLAGS) $(ALL_O)),$$(strip $$(EXTRA_LDFLAGS) $$(ALL_O)))' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'endif' \ - ) > .$@.flags + ) > $(dir $@)/.$(notdir $@).flags endif # O_TARGET # @@ -96,7 +96,7 @@ echo 'ifeq ($(strip $(EXTRA_ARFLAGS) $(LX_OBJS) $(L_OBJS)),$$(strip $$(EXTRA_ARFLAGS) $$(LX_OBJS) $$(L_OBJS)))' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'endif' \ - ) > .$@.flags + ) > $(dir $@)/.$(notdir $@).flags endif # @@ -218,7 +218,7 @@ echo 'ifeq ($(strip $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -DEXPORT_SYMTAB),$$(strip $$(CFLAGS) $$(EXTRA_CFLAGS) $$(CFLAGS_$@) -DEXPORT_SYMTAB))' ; \ echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \ echo 'endif' \ - ) > .$@.flags + ) > $(dir $@)/.$(notdir $@).flags endif endif # CONFIG_MODULES diff -u --recursive --new-file v2.1.79/linux/arch/arm/Makefile linux/arch/arm/Makefile --- v2.1.79/linux/arch/arm/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/Makefile Tue Jan 20 16:39:41 1998 @@ -0,0 +1,198 @@ +# +# arch/arm/Makefile +# +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. Remember to do have actions +# for "archclean" and "archdep" for cleaning up and making dependencies for +# this architecture +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1995, 1996 by Russell King + +ifeq ($(CONFIG_CPU_ARM2),y) +PROCESSOR = armo +ASFLAGS_PROC += -m2 +ifeq ($(CONFIG_BINUTILS_NEW),y) +CFLAGS_PROC += -mcpu=arm2 +ASFLAGS_PROC += -m2 +else +CFLAGS_PROC += -m2 +ASFLAGS_PROC += -m2 +endif +endif + +ifeq ($(CONFIG_CPU_ARM3),y) +PROCESSOR = armo +ifeq ($(CONFIG_BINUTILS_NEW),y) +CFLAGS_PROC += -mcpu=arm3 +ASFLAGS_PROC += -m3 +else +CFLAGS_PROC += -m3 +ASFLAGS_PROC += -m3 +endif +endif + +ifeq ($(CONFIG_CPU_ARM6),y) +PROCESSOR = armv +ifeq ($(CONFIG_BINUTILS_NEW),y) +CFLAGS_PROC += -mcpu=arm6 +ASFLAGS_PROC += -m6 +else +CFLAGS_PROC += -m6 +ASFLAGS_PROC += -m6 +endif +endif + +ifeq ($(CONFIG_CPU_SA110),y) +PROCESSOR = armv +ifeq ($(CONFIG_BINUTILS_NEW),y) +CFLAGS_PROC += -mcpu=strongarm110 +ASFLAGS_PROC += -m6 +else +CFLAGS_PROC += -m6 +ASFLAGS_PROC += -m6 +endif +endif + +# Processor Architecture +# CFLAGS_PROC - processor dependent CFLAGS +# PROCESSOR - processor type +# TEXTADDR - Uncompressed kernel link text address +# ZTEXTADDR - Compressed kernel link text address +# ZRELADDR - Compressed kernel relocating address (point at which uncompressed kernel is loaded). +# + +HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o +COMPRESSED_HEAD = head.o + +ifeq ($(PROCESSOR),armo) +ifeq ($(CONFIG_BINUTILS_NEW),y) +CFLAGS_PROC += -mapcs-26 -mshort-load-bytes +endif +TEXTADDR = 0x02080000 +ZTEXTADDR = 0x01800000 +ZRELADDR = 0x02080000 +endif + +ifeq ($(CONFIG_ARCH_A5K),y) +MACHINE = a5k +COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o +endif + +ifeq ($(CONFIG_ARCH_ARC),y) +MACHINE = arc +COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o +endif + +ifeq ($(PROCESSOR),armv) +ifeq ($(CONFIG_BINUTILS_NEW),y) +CFLAGS_PROC += -mapcs-32 -mshort-load-bytes +endif +TEXTADDR = 0xC0008000 +endif + +ifeq ($(CONFIG_ARCH_RPC),y) +MACHINE = rpc +COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr.o +ZTEXTADDR = 0x10008000 +ZRELADDR = 0x10008000 +endif + +ifeq ($(CONFIG_ARCH_EBSA110),y) +MACHINE = ebsa110 +ZTEXTADDR = 0x00008000 +ZRELADDR = 0x00008000 +endif + +ifeq ($(CONFIG_ARCH_NEXUSPCI),y) +MACHINE = nexuspci +TEXTADDR = 0xc0000000 +ZTEXTADDR = 0x40200000 +ZRELADDR = 0x40000000 +COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr_scc.o +COMPRESSED_HEAD = head-nexuspci.o +endif + +OBJDUMP = $(CROSS_COMPILE)objdump +PERL = perl +LD = $(CROSS_COMPILE)ld -m elf_arm +CPP = $(CC) -E +OBJCOPY = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S +ARCHCC := $(word 1,$(CC)) +GCCLIB := `$(ARCHCC) $(CFLAGS_PROC) --print-libgcc-file-name` +GCCARCH := -B/usr/src/bin/arm/arm-linuxelf- +HOSTCFLAGS := $(CFLAGS:-fomit-frame-pointer=) +ifeq ($(CONFIG_FRAME_POINTER),y) +CFLAGS := $(CFLAGS:-fomit-frame-pointer=) +endif +CFLAGS := $(CFLAGS_PROC) $(CFLAGS) -pipe +ASFLAGS := $(ASFLAGS_PROC) $(ASFLAGS) -D__ASSEMBLY__ +LINKFLAGS = -T $(TOPDIR)/arch/arm/vmlinux.lds -e stext -Ttext $(TEXTADDR) +ZLINKFLAGS = -Ttext $(ZTEXTADDR) + +SUBDIRS := $(SUBDIRS:drivers=) arch/arm/lib arch/arm/kernel arch/arm/mm arch/arm/drivers +CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) +LIBS := arch/arm/lib/lib.a $(LIBS) $(GCCLIB) + +DRIVERS := arch/arm/drivers/block/block.a \ + arch/arm/drivers/char/char.a \ + drivers/misc/misc.a \ + arch/arm/drivers/net/net.a + +ifeq ($(CONFIG_SCSI),y) +DRIVERS := $(DRIVERS) arch/arm/drivers/scsi/scsi.a +endif + +ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR),) +DRIVERS := $(DRIVERS) drivers/cdrom/cdrom.a +endif + +ifeq ($(CONFIG_SOUND),y) +DRIVERS := $(DRIVERS) arch/arm/drivers/sound/sound.a +endif + +symlinks:: + $(RM) include/asm-arm/arch include/asm-arm/proc + (cd include/asm-arm; ln -sf arch-$(MACHINE) arch; ln -sf proc-$(PROCESSOR) proc) + +mrproper:: + rm -f include/asm-arm/arch include/asm-arm/proc + @$(MAKE) -C arch/$(ARCH)/drivers mrproper + +arch/arm/kernel: dummy + $(MAKE) linuxsubdirs SUBDIRS=arch/arm/kernel + +arch/arm/mm: dummy + $(MAKE) linuxsubdirs SUBDIRS=arch/arm/mm + +MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot + +zImage: vmlinux + @$(MAKEBOOT) zImage + +zinstall: vmlinux + @$(MAKEBOOT) zinstall + +Image: vmlinux + @$(MAKEBOOT) Image + +install: vmlinux + @$(MAKEBOOT) install + +# My testing targets (that short circuit a few dependencies) +# +zImg:; @$(MAKEBOOT) zImage +Img:; @$(MAKEBOOT) Image +i:; @$(MAKEBOOT) install +zi:; @$(MAKEBOOT) zinstall + +archclean: + @$(MAKEBOOT) clean + @$(MAKE) -C arch/arm/lib clean + +archdep: + @$(MAKEBOOT) dep +sed -e /^MACHINE..*=/s,= .*,= rpc,;/^PROCESSOR..*=/s,= .*,= armv, linux/arch/arm/Makefile.normal diff -u --recursive --new-file v2.1.79/linux/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile --- v2.1.79/linux/arch/arm/boot/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/Makefile Tue Jan 20 16:39:41 1998 @@ -0,0 +1,35 @@ +# +# arch/arm/boot/Makefile +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1995, 1996 Russell King +# + +SYSTEM =$(TOPDIR)/vmlinux + +Image: $(CONFIGURE) $(SYSTEM) + $(OBJCOPY) $(SYSTEM) $@ + +zImage: $(CONFIGURE) compressed/vmlinux + $(OBJCOPY) compressed/vmlinux $@ + +compressed/vmlinux: $(TOPDIR)/vmlinux dep + @$(MAKE) -C compressed vmlinux + +install: $(CONFIGURE) Image + sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) Image $(TOPDIR)/System.map "$(INSTALL_PATH)" + +zinstall: $(CONFIGURE) zImage + sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" + +tools/build: tools/build.c + $(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include + +clean: + rm -f Image zImage tools/build + @$(MAKE) -C compressed clean + +dep: diff -u --recursive --new-file v2.1.79/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile --- v2.1.79/linux/arch/arm/boot/compressed/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/compressed/Makefile Tue Jan 20 16:39:41 1998 @@ -0,0 +1,33 @@ +# +# linux/arch/arm/boot/compressed/Makefile +# +# create a compressed vmlinuz image from the original vmlinux +# +# With this config, max compressed image size = 640k +# Uncompressed image size = 1.3M (text+data) + +SYSTEM =$(TOPDIR)/vmlinux +HEAD =$(COMPRESSED_HEAD) +OBJS =$(HEAD) misc.o $(COMPRESSED_EXTRA) +CFLAGS =-O2 -DSTDC_HEADERS $(CFLAGS_PROC) +ARFLAGS =rc + +all: vmlinux + +vmlinux: piggy.o $(OBJS) + $(LD) $(ZLINKFLAGS) -o vmlinux $(OBJS) piggy.o + +$(HEAD): $(HEAD:.o=.S) + $(CC) -traditional -DLOADADDR=$(ZRELADDR) -c $(HEAD:.o=.S) + +piggy.o: $(SYSTEM) + tmppiggy=_tmp_$$$$piggy; \ + rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \ + $(OBJCOPY) $(SYSTEM) $$tmppiggy; \ + gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \ + echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \ + $(LD) -m elf_arm -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-arm -T $$tmppiggy.lnk; \ + rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; + +clean:; rm -f vmlinux core + diff -u --recursive --new-file v2.1.79/linux/arch/arm/boot/compressed/Makefile.debug linux/arch/arm/boot/compressed/Makefile.debug --- v2.1.79/linux/arch/arm/boot/compressed/Makefile.debug Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/compressed/Makefile.debug Tue Jan 20 16:39:41 1998 @@ -0,0 +1,16 @@ +# +# linux/arch/arm/boot/compressed/Makefile +# +# create a compressed vmlinux image from the original vmlinux +# + +COMPRESSED_EXTRA=../../lib/ll_char_wr.o +OBJECTS=misc-debug.o $(COMPRESSED_EXTRA) + +CFLAGS=-D__KERNEL__ -O2 -DSTDC_HEADERS -DSTANDALONE_DEBUG -Wall -I../../../../include -c + +test-gzip: piggy.o $(OBJECTS) + $(CC) -o $@ $(OBJECTS) piggy.o + +misc-debug.o: misc.c + $(CC) $(CFLAGS) -o $@ misc.c diff -u --recursive --new-file v2.1.79/linux/arch/arm/boot/compressed/head-nexuspci.S linux/arch/arm/boot/compressed/head-nexuspci.S --- v2.1.79/linux/arch/arm/boot/compressed/head-nexuspci.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/compressed/head-nexuspci.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,95 @@ +/* + * linux/arch/arm/boot/compressed/head-nexuspci.S + * + * Copyright (C) 1996 Philip Blundell + */ + +#define ARM_CP p15 +#define ARM610_REG_CONTROL cr1 +#define ARM_REG_ZERO cr0 + + .text + +start: b skip1 + b go_uncompress + b go_uncompress + b go_uncompress + b go_uncompress + b go_uncompress + b go_uncompress + b go_uncompress + b go_uncompress + b go_uncompress +skip1: mov sp, #0x40000000 + add sp, sp, #0x200000 + mov r2, #0x20000000 + mov r1, #0x1a + str r1, [r2] + + MOV r0, #0x30 + MCR ARM_CP, 0, r0, ARM610_REG_CONTROL, ARM_REG_ZERO + + mov r2, #0x10000000 + + mov r1, #42 + strb r1, [r2, #8] + + mov r1, #48 + strb r1, [r2, #8] + + mov r1, #16 + strb r1, [r2, #8] + + mov r1, #0x93 + strb r1, [r2, #0] + mov r1, #0x17 + strb r1, [r2, #0] + + mov r1, #0xbb + strb r1, [r2, #0x4] + + mov r1, #0x78 + strb r1, [r2, #0x10] + + mov r1, #160 + strb r1, [r2, #0x8] + + mov r1, #5 + strb r1, [r2, #0x8] + + mov r0, #0x50 + bl _ll_write_char + + mov r4, #0x40000000 + mov r1, #0x00200000 + add r4, r4, r1 +copylp: + ldr r3, [r1] + str r3, [r4, r1] + subs r1, r1, #4 + bne copylp + + add pc, r4, #0x28 + + +/* + * Uncompress the kernel + */ +go_uncompress: + mov r0, #0x40000000 + add r0, r0, #0x300000 + bl _decompress_kernel + + mov r0, #0x40000000 + add r1, r0, #0x300000 + mov r2, #0x100000 + +clp2: ldr r3, [r1, r2] + str r3, [r0, r2] + subs r2, r2, #4 + bne clp2 + + mov r2, #0x40000000 + mov r0, #0 + mov r1, #3 + add pc, r2, #0x20 @ call via EXEC entry diff -u --recursive --new-file v2.1.79/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S --- v2.1.79/linux/arch/arm/boot/compressed/head.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/compressed/head.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,124 @@ +/* + * linux/arch/arm/boot/compressed/head.S + * + * Copyright (C) 1996,1997,1998 Russell King + */ +#include + + .text +/* + * sort out different calling conventions + */ + .align + .globl _start +_start: +start: mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + mov r0, r0 + teq r0, #0 + beq 2f + mov r4, #0x02000000 + add r4, r4, #0x7C000 + mov r3, #0x4000 + sub r3, r3, #4 +1: ldmia r0!, {r5 - r12} + stmia r4!, {r5 - r12} + subs r3, r3, #32 + bpl 1b +2: adr r2, LC0 + ldmia r2, {r2, r3, r4, r5, r6, sp} + add r2, r2, #3 + add r3, r3, #3 + add sp, sp, #3 + bic r2, r2, #3 + bic r3, r3, #3 + bic sp, sp, #3 + adr r7, start + sub r6, r7, r6 +/* + * Relocate pointers + */ + add r2, r2, r6 + add r3, r3, r6 + add r5, r5, r6 + add sp, sp, r6 +/* + * Clear zero-init + */ + mov r6, #0 +1: str r6, [r2], #4 + cmp r2, r3 + blt 1b + str r1, [r5] @ save architecture +/* + * Uncompress the kernel + */ + mov r1, #0x8000 + add r2, r2, r1, lsl #1 @ Add 64k for malloc + sub r1, r1, #1 + add r2, r2, r1 + bic r5, r2, r1 @ decompress kernel to after end of the compressed + mov r0, r5 + bl SYMBOL_NAME(decompress_kernel) + add r0, r0, #7 + bic r2, r0, #7 +/* + * Now move the kernel to the correct location (r5 -> r4, len r0) + */ + mov r0, r4 @ r0 = start of real kernel + mov r1, r5 @ r1 = start of kernel image + add r3, r5, r2 @ r3 = end of kernel + adr r4, movecode + adr r5, movecodeend +1: ldmia r4!, {r6 - r12, lr} + stmia r3!, {r6 - r12, lr} + cmp r4, r5 + blt 1b + mrc p15, 0, r5, c0, c0 + eor r5, r5, #0x44 << 24 + eor r5, r5, #0x01 << 16 + eor r5, r5, #0xa1 << 8 + movs r5, r5, lsr #4 + mov r5, #0 + mcreq p15, 0, r5, c7, c5, 0 @ flush I cache + ldr r5, LC0 + 12 @ get architecture + ldr r5, [r5] + add pc, r1, r2 @ Call move code + +/* + * r0 = length, r1 = to, r2 = from + */ +movecode: add r3, r1, r2 + mov r4, r0 +1: ldmia r1!, {r6 - r12, lr} + stmia r0!, {r6 - r12, lr} + cmp r1, r3 + blt 1b + mrc p15, 0, r0, c0, c0 + eor r0, r0, #0x44 << 24 + eor r0, r0, #0x01 << 16 + eor r0, r0, #0xa1 << 8 + movs r0, r0, lsr #4 + mov r0, #0 + mcreq p15, 0, r0, c7, c5, 0 @ flush I cache + mov r1, r5 @ call kernel correctly + mov pc, r4 @ call via EXEC entry +movecodeend: + +LC0: .word SYMBOL_NAME(_edata) + .word SYMBOL_NAME(_end) + .word LOADADDR + .word SYMBOL_NAME(architecture) + .word start + .word SYMBOL_NAME(user_stack)+4096 + .align + + .bss +SYMBOL_NAME(architecture): + .space 4 + .align diff -u --recursive --new-file v2.1.79/linux/arch/arm/boot/compressed/misc.c linux/arch/arm/boot/compressed/misc.c --- v2.1.79/linux/arch/arm/boot/compressed/misc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/compressed/misc.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,308 @@ +/* + * misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * + * Modified for ARM Linux by Russell King + */ + +#include +#include +#include + +#ifdef STANDALONE_DEBUG +#define puts printf +#endif + +#define __ptr_t void * + +/* + * Optimised C version of memzero for the ARM. + */ +extern __inline__ __ptr_t __memzero (__ptr_t s, size_t n) +{ + union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; + int i; + + u.vp = s; + + for (i = n >> 5; i > 0; i--) { + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + } + + if (n & 1 << 4) { + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + *u.ulp++ = 0; + } + + if (n & 1 << 3) { + *u.ulp++ = 0; + *u.ulp++ = 0; + } + + if (n & 1 << 2) + *u.ulp++ = 0; + + if (n & 1 << 1) { + *u.ucp++ = 0; + *u.ucp++ = 0; + } + + if (n & 1) + *u.ucp++ = 0; + return s; +} + +#define memzero(s,n) __memzero(s,n) + +extern __inline__ __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, + size_t __n) +{ + int i = 0; + unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; + + for (i = __n >> 3; i > 0; i--) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 2) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1 << 1) { + *d++ = *s++; + *d++ = *s++; + } + + if (__n & 1) + *d++ = *s++; + + return __dest; +} + +/* + * gzip delarations + */ +#define OF(args) args +#define STATIC static + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define WSIZE 0x8000 /* Window size must be at least 32k, */ + /* and a power of two */ + +static uch *inbuf; /* input buffer */ +static uch window[WSIZE]; /* Sliding window buffer */ + +static unsigned insize; /* valid bytes in inbuf */ +static unsigned inptr; /* index of next byte to be processed in inbuf */ +static unsigned outcnt; /* bytes in output buffer */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +static int fill_inbuf(void); +static void flush_window(void); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +extern char input_data[]; +extern int input_len; + +static uch *output_data; +static ulg output_ptr; +static ulg bytes_out = 0; + +static void *malloc(int size); +static void free(void *where); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +static void puts(const char *); + +extern int end; +static ulg free_mem_ptr; +static ulg free_mem_ptr_end; + +#define HEAP_SIZE 0x2000 + +#include "../../../../lib/inflate.c" + +#ifndef STANDALONE_DEBUG +static void *malloc(int size) +{ + void *p; + + if (size <0) error("Malloc error\n"); + if (free_mem_ptr <= 0) error("Memory error\n"); + + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + + p = (void *)free_mem_ptr; + free_mem_ptr += size; + + if (free_mem_ptr >= free_mem_ptr_end) + error("Out of memory"); + return p; +} + +static void free(void *where) +{ /* gzip_mark & gzip_release do the free */ +} + +static void gzip_mark(void **ptr) +{ + *ptr = (void *) free_mem_ptr; +} + +static void gzip_release(void **ptr) +{ + free_mem_ptr = (long) *ptr; +} +#else +static void gzip_mark(void **ptr) +{ +} + +static void gzip_release(void **ptr) +{ +} +#endif + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty + * and at least one byte is really needed. + */ +int fill_inbuf() +{ + if (insize != 0) + error("ran out of input data\n"); + + inbuf = input_data; + insize = input_len; + inptr = 1; + return inbuf[0]; +} + +/* =========================================================================== + * Write the output window window[0..outcnt-1] and update crc and bytes_out. + * (Used for the decompressed data only.) + */ +void flush_window() +{ + ulg c = crc; + unsigned n; + uch *in, *out, ch; + + in = window; + out = &output_data[output_ptr]; + for (n = 0; n < outcnt; n++) { + ch = *out++ = *in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + output_ptr += (ulg)outcnt; + outcnt = 0; +} + +static void error(char *x) +{ + int ptr; + + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + + while(1); /* Halt */ +} + +#define STACK_SIZE (4096) + +ulg user_stack [STACK_SIZE]; + +#ifndef STANDALONE_DEBUG + +ulg decompress_kernel(ulg output_start) +{ + free_mem_ptr = (ulg)&end; + free_mem_ptr_end = output_start; + + proc_decomp_setup (); + arch_decomp_setup (); + + output_data = (uch *)output_start; /* Points to kernel start */ + + makecrc(); + puts("Uncompressing Linux..."); + gunzip(); + puts("done.\nNow booting the kernel\n"); + return output_ptr; +} +#else + +char output_buffer[1500*1024]; + +int main() +{ + output_data = output_buffer; + + makecrc(); + puts("Uncompressing Linux..."); + gunzip(); + puts("done.\n"); + return 0; +} +#endif + diff -u --recursive --new-file v2.1.79/linux/arch/arm/boot/install.sh linux/arch/arm/boot/install.sh --- v2.1.79/linux/arch/arm/boot/install.sh Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/install.sh Tue Jan 20 16:39:41 1998 @@ -0,0 +1,61 @@ +#!/bin/sh +# +# arch/arm/boot/install.sh +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1995 by Linus Torvalds +# +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin +# Adapted from code in arch/i386/boot/install.sh by Russell King +# +# "make install" script for arm architecture +# +# Arguments: +# $1 - kernel version +# $2 - kernel image file +# $3 - kernel map file +# $4 - default install path (blank if root directory) +# + +# User may have a custom install script + +if [ -x /sbin/installkernel ]; then + exec /sbin/installkernel "$@" +fi + +if [ "$2" = "zImage" ]; then +# Compressed install + echo "Installing compressed kernel" + if [ -f $4/vmlinuz-$1 ]; then + mv $4/vmlinuz-$1 $4/vmlinuz.old + fi + + if [ -f $4/System.map-$1 ]; then + mv $4/System.map-$1 $4/System.old + fi + + cat $2 > $4/vmlinuz-$1 + cp $3 $4/System.map-$1 +else +# Normal install + echo "Installing normal kernel" + if [ -f $4/vmlinux-$1 ]; then + mv $4/vmlinux-$1 $4/vmlinux.old + fi + + if [ -f $4/System.map ]; then + mv $4/System.map $4/System.old + fi + + cat $2 > $4/vmlinux-$1 + cp $3 $4/System.map +fi + +if [ -x /sbin/loadmap ]; then + /sbin/loadmap --rdev /dev/ima +else + echo "You have to install it yourself" +fi diff -u --recursive --new-file v2.1.79/linux/arch/arm/boot/tools/build.c linux/arch/arm/boot/tools/build.c --- v2.1.79/linux/arch/arm/boot/tools/build.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/boot/tools/build.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long u32; + +void die(const char * str, ...) +{ + va_list args; + va_start(args, str); + vfprintf(stderr, str, args); + fputc('\n', stderr); + exit (1); +} + +int main(int argc, char **argv) +{ + void *data; + struct exec ex; + FILE *f; + int totlen; + + if (argc < 2) { + fprintf(stderr, "Usage: build kernel-name\n"); + exit(1); + } + + f = fopen(argv[1], "rb"); + if (!f) + die("Unable to open `%s': %m", argv[1]); + + fread(&ex, 1, sizeof(ex), f); + + if(N_MAGIC(ex) == ZMAGIC) { + fseek(f, 4096, SEEK_SET); + totlen = ex.a_text + ex.a_data; + } else + if(N_MAGIC(ex) == QMAGIC) { + unsigned long my_header; + + fseek(f, 4, SEEK_SET); + + my_header = 0xea000006; + + fwrite(&my_header, 4, 1, stdout); + + totlen = ex.a_text + ex.a_data - 4; + } else { + fprintf(stderr, "Unacceptable a.out header on kernel\n"); + fclose(f); + exit(1); + } + + fprintf(stderr, "Kernel is %dk (%dk text, %dk data, %dk bss)\n", + (ex.a_text + ex.a_data + ex.a_bss)/1024, + ex.a_text/1024, ex.a_data/1024, ex.a_bss/1024); + + data = malloc(totlen); + fread(data, 1, totlen, f); + fwrite(data, 1, totlen, stdout); + + free(data); + fclose(f); + fflush(stdout); + return 0; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/config.in linux/arch/arm/config.in --- v2.1.79/linux/arch/arm/config.in Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/config.in Tue Jan 20 16:39:41 1998 @@ -0,0 +1,145 @@ +# +# For a description of the syntax of this configuration file, +# see the Configure script. +# +mainmenu_name "Linux Kernel Configuration" + +define_bool CONFIG_ARM y + +mainmenu_option next_comment +comment 'Code maturity level options' +bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL +endmenu + +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD +fi +endmenu + +mainmenu_option next_comment +comment 'General setup' +choice 'ARM system type' \ + "Archimedes CONFIG_ARCH_ARC \ + A5000 CONFIG_ARCH_A5K \ + RiscPC CONFIG_ARCH_RPC \ + EBSA-110 CONFIG_ARCH_EBSA110 \ + NexusPCI CONFIG_ARCH_NEXUSPCI" RiscPC +if [ "$CONFIG_ARCH_ARC" = "y" -o "$CONFIG_ARCH_A5K" = "y" -o "$CONFIG_ARCH_RPC" = "y" ]; then + define_bool CONFIG_ARCH_ACORN y +else + define_bool CONFIG_ARCH_ACORN n +fi +if [ "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then + define_bool CONFIG_PCI y +else + define_bool CONFIG_PCI n +fi +if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" ]; then + define_bool CONFIG_CPU_SA110 y +else + if [ "$CONFIG_ARCH_A5K" = "y" ]; then + define_bool CONFIG_CPU_ARM3 y + else + choice 'ARM cpu type' \ + "ARM2 CONFIG_CPU_ARM2 \ + ARM3 CONFIG_CPU_ARM3 \ + ARM6/7 CONFIG_CPU_ARM6 \ + StrongARM CONFIG_CPU_SA110" StrongARM + fi +fi +bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER +bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW +bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS +bool 'Networking support' CONFIG_NET +bool 'System V IPC' CONFIG_SYSVIPC +bool 'Sysctl support' CONFIG_SYSCTL +tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT +tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then +# tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA + define_bool CONFIG_BINFMT_JAVA n +fi +tristate 'Parallel port support' CONFIG_PARPORT +if [ "$CONFIG_PARPORT" != "n" ]; then + dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT +fi +endmenu + +source arch/arm/drivers/block/Config.in + +if [ "$CONFIG_NET" = "y" ]; then + source net/Config.in +fi + +mainmenu_option next_comment +comment 'SCSI support' + +tristate 'SCSI support?' CONFIG_SCSI + +if [ "$CONFIG_SCSI" != "n" ]; then + source arch/arm/drivers/scsi/Config.in +fi +endmenu + +if [ "$CONFIG_NET" = "y" ]; then + mainmenu_option next_comment + comment 'Network device support' + + bool 'Network device support?' CONFIG_NETDEVICES + if [ "$CONFIG_NETDEVICES" = "y" ]; then + source arch/arm/drivers/net/Config.in + fi + endmenu +fi + +# mainmenu_option next_comment +# comment 'ISDN subsystem' +# +# tristate 'ISDN support' CONFIG_ISDN +# if [ "$CONFIG_ISDN" != "n" ]; then +# source drivers/isdn/Config.in +# fi +# endmenu + +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + +source fs/Config.in + +source fs/nls/Config.in + +source arch/arm/drivers/char/Config.in + +if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + mainmenu_option next_comment + comment 'Sound' + + tristate 'Sound support' CONFIG_SOUND + if [ "$CONFIG_SOUND" != "n" ]; then + source arch/arm/drivers/sound/Config.in + fi + endmenu +fi + +mainmenu_option next_comment +comment 'Kernel hacking' + +#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC +bool 'Kernel profiling support' CONFIG_PROFILE +if [ "$CONFIG_PROFILE" = "y" ]; then + int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 +fi +bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +endmenu diff -u --recursive --new-file v2.1.79/linux/arch/arm/defconfig linux/arch/arm/defconfig --- v2.1.79/linux/arch/arm/defconfig Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/defconfig Tue Jan 20 16:39:41 1998 @@ -0,0 +1,264 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KERNELD=y + +# +# General setup +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +CONFIG_ARCH_RPC=y +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_NEXUSPCI is not set +CONFIG_ARCH_ACORN=y +# CONFIG_PCI is not set +# CONFIG_CPU_ARM2 is not set +# CONFIG_CPU_ARM3 is not set +# CONFIG_CPU_ARM6 is not set +CONFIG_CPU_SA110=y +CONFIG_FRAME_POINTER=y +# CONFIG_BINUTILS_NEW is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +CONFIG_SYSCTL=y +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=m +# CONFIG_BINFMT_JAVA is not set +CONFIG_PARPORT=y +CONFIG_PARPORT_PC=y + +# +# Floppy, IDE, and other block devices +# +CONFIG_BLK_DEV_FD=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_IDE_PCMCIA is not set +CONFIG_BLK_DEV_IDE_CARDS=y +CONFIG_BLK_DEV_IDE_ICSIDE=y +# CONFIG_BLK_DEV_IDE_RAPIDE is not set +# CONFIG_BLK_DEV_XD is not set + +# +# Additional Block Devices +# +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_PARIDE_PARPORT=y +# CONFIG_PARIDE is not set +CONFIG_BLK_DEV_PART=y +# CONFIG_BLK_DEV_HD is not set + +# +# Networking options +# +CONFIG_PACKET=m +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +# CONFIG_NET_ALIAS is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ACCT is not set +# CONFIG_IP_MASQUERADE is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_RARP is not set +CONFIG_IP_NOSR=y +# CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_CPU_IS_SLOW is not set +# CONFIG_NET_SCHED is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +CONFIG_SCSI_ACORNSCSI_3=m +CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y +CONFIG_SCSI_ACORNSCSI_SYNC=y +CONFIG_SCSI_CUMANA_2=m +CONFIG_SCSI_POWERTECSCSI=m + +# +# The following drives are not fully supported +# +CONFIG_SCSI_CUMANA_1=m +CONFIG_SCSI_ECOSCSI=m +CONFIG_SCSI_OAK1=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_PPA_HAVE_PEDANTIC=2 + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +CONFIG_PPP=m + +# +# CCP compressors for PPP are only built as modules. +# +# CONFIG_SLIP is not set +CONFIG_ETHER1=m +CONFIG_ETHER3=m +CONFIG_ETHERH=m +CONFIG_CDROM=y + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_MINIX_FS is not set +CONFIG_EXT2_FS=y +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_PROC_FS=y +CONFIG_NFS_FS=y +CONFIG_NFSD=y +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_CODA_FS is not set +# CONFIG_SMB_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_ADFS_FS=y +# CONFIG_MAC_PARTITION is not set +CONFIG_NLS=y + +# +# Native Language Support +# +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_KOI8_R is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_ATOMWIDE_SERIAL=y +CONFIG_DUALSP_SERIAL=y +CONFIG_MOUSE=y +CONFIG_PRINTER=m +CONFIG_PRINTER_READBACK=y +# CONFIG_UMISC is not set +# CONFIG_WATCHDOG is not set +CONFIG_RPCMOUSE=y + +# +# Sound +# +# CONFIG_SOUND is not set +# CONFIG_VIDC is not set +# CONFIG_AUDIO is not set +# DSP_BUFFSIZE is not set + +# +# Kernel hacking +# +# CONFIG_PROFILE is not set +CONFIG_MAGIC_SYSRQ=y diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile --- v2.1.79/linux/arch/arm/kernel/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/Makefile Tue Jan 20 16:39:41 1998 @@ -0,0 +1,47 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +HEAD_OBJ = head-$(PROCESSOR).o +ENTRY_OBJ = entry-$(PROCESSOR).o + +O_TARGET := kernel.o +O_OBJS := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o signal.o sys_arm.o time.o traps.o + +all: kernel.o $(HEAD_OBJ) init_task.o + +ifeq ($(CONFIG_MODULES),y) +OX_OBJS = armksyms.o +else +O_OBJS += armksyms.o +endif + +ifdef CONFIG_ARCH_ACORN + O_OBJS += setup.o ecard.o iic.o dma.o + ifdef CONFIG_ARCH_ARC + O_OBJS += oldlatches.o + endif +endif + +ifeq ($(MACHINE),ebsa110) + O_OBJS += setup-ebsa110.o dma.o +endif + +ifeq ($(MACHINE),nexuspci) + O_OBJS += setup-ebsa110.o +endif + +$(HEAD_OBJ): $(HEAD_OBJ:.o=.S) + $(CC) -D__ASSEMBLY__ -traditional -c $(HEAD_OBJ:.o=.S) -o $@ + +include $(TOPDIR)/Rules.make + +$(ENTRY_OBJ:.o=.S): ../lib/constants.h + +.PHONY: ../lib/constants.h + +../lib/constants.h: + $(MAKE) -C ../lib constants.h diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c --- v2.1.79/linux/arch/arm/kernel/armksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/armksyms.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern void dump_thread(struct pt_regs *, struct user *); +extern int dump_fpu(struct pt_regs *, struct user_fp_struct *); + +/* + * libgcc functions - functions that are used internally by the + * compiler... (prototypes are not correct though, but that + * doesn't really matter since they're not versioned). + */ +extern void __gcc_bcmp(void); +extern void __ashldi3(void); +extern void __ashrdi3(void); +extern void __cmpdi2(void); +extern void __divdi3(void); +extern void __divsi3(void); +extern void __lshrdi3(void); +extern void __moddi3(void); +extern void __modsi3(void); +extern void __muldi3(void); +extern void __negdi2(void); +extern void __ucmpdi2(void); +extern void __udivdi3(void); +extern void __udivmoddi4(void); +extern void __udivsi3(void); +extern void __umoddi3(void); +extern void __umodsi3(void); + +extern void inswb(unsigned int port, void *to, int len); +extern void outswb(unsigned int port, const void *to, int len); + +/* + * floating point math emulator support. + * These will not change. If they do, then a new version + * of the emulator will have to be compiled... + * fp_current is never actually dereferenced - it is just + * used as a pointer to pass back for send_sig(). + */ +extern void (*fp_save)(unsigned char *); +extern void (*fp_restore)(unsigned char *); +extern void fp_setup(void); +extern void fpreturn(void); +extern void fpundefinstr(void); +extern void fp_enter(void); +extern void fp_printk(void); +extern struct task_struct *fp_current; +extern void fp_send_sig(int); + +/* platform dependent support */ +EXPORT_SYMBOL(dump_thread); +EXPORT_SYMBOL(dump_fpu); +EXPORT_SYMBOL(udelay); +EXPORT_SYMBOL(dma_str); +EXPORT_SYMBOL(xchg_str); + +/* expansion card support */ +#ifdef CONFIG_ARCH_ACORN +EXPORT_SYMBOL(ecard_startfind); +EXPORT_SYMBOL(ecard_find); +EXPORT_SYMBOL(ecard_readchunk); +EXPORT_SYMBOL(ecard_address); +#endif + +/* processor dependencies */ +EXPORT_SYMBOL(processor); + +/* io */ +EXPORT_SYMBOL(outswb); +EXPORT_SYMBOL(outsw); +EXPORT_SYMBOL(inswb); +EXPORT_SYMBOL(insw); + +#ifdef CONFIG_ARCH_RPC +EXPORT_SYMBOL(drambank); +#endif + +/* dma */ +EXPORT_SYMBOL(enable_dma); +EXPORT_SYMBOL(set_dma_mode); +EXPORT_SYMBOL(set_dma_addr); +EXPORT_SYMBOL(set_dma_count); +EXPORT_SYMBOL(get_dma_residue); + +/* + * floating point math emulator support. + * These symbols will never change their calling convention... + */ +EXPORT_SYMBOL_NOVERS(fpreturn); +EXPORT_SYMBOL_NOVERS(fpundefinstr); +EXPORT_SYMBOL_NOVERS(fp_enter); +EXPORT_SYMBOL_NOVERS(fp_save); +EXPORT_SYMBOL_NOVERS(fp_restore); +EXPORT_SYMBOL_NOVERS(fp_setup); + +const char __kstrtab_fp_printk[] __attribute__((section(".kstrtab"))) = __MODULE_STRING(fp_printk); +const struct module_symbol __ksymtab_fp_printk __attribute__((section("__ksymtab"))) = +{ (unsigned long)&printk, __kstrtab_fp_printk }; + +const char __kstrtab_fp_send_sig[] __attribute__((section(".kstrtab"))) = __MODULE_STRING(fp_send_sig); +const struct module_symbol __ksymtab_fp_send_sig __attribute__((section("__ksymtab"))) = +{ (unsigned long)&send_sig, __kstrtab_fp_send_sig }; + +//EXPORT_SYMBOL_NOVERS(fp_current); + + /* + * string / mem functions + */ +EXPORT_SYMBOL_NOVERS(strcpy); +EXPORT_SYMBOL_NOVERS(strncpy); +EXPORT_SYMBOL_NOVERS(strcat); +EXPORT_SYMBOL_NOVERS(strncat); +EXPORT_SYMBOL_NOVERS(strcmp); +EXPORT_SYMBOL_NOVERS(strncmp); +EXPORT_SYMBOL_NOVERS(strchr); +EXPORT_SYMBOL_NOVERS(strlen); +EXPORT_SYMBOL_NOVERS(strnlen); +EXPORT_SYMBOL_NOVERS(strspn); +EXPORT_SYMBOL_NOVERS(strpbrk); +EXPORT_SYMBOL_NOVERS(strtok); +EXPORT_SYMBOL_NOVERS(strrchr); +EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL_NOVERS(memmove); +EXPORT_SYMBOL_NOVERS(memcmp); +EXPORT_SYMBOL_NOVERS(memscan); +EXPORT_SYMBOL_NOVERS(memzero); + + /* user mem (segment) */ +#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) +EXPORT_SYMBOL(__arch_copy_from_user); +EXPORT_SYMBOL(__arch_copy_to_user); +EXPORT_SYMBOL(__arch_clear_user); +EXPORT_SYMBOL(__arch_strlen_user); +#elif defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) +EXPORT_SYMBOL(uaccess_kernel); +EXPORT_SYMBOL(uaccess_user); +#endif + + /* gcc lib functions */ +EXPORT_SYMBOL_NOVERS(__gcc_bcmp); +EXPORT_SYMBOL_NOVERS(__ashldi3); +EXPORT_SYMBOL_NOVERS(__ashrdi3); +EXPORT_SYMBOL_NOVERS(__cmpdi2); +EXPORT_SYMBOL_NOVERS(__divdi3); +EXPORT_SYMBOL_NOVERS(__divsi3); +EXPORT_SYMBOL_NOVERS(__lshrdi3); +EXPORT_SYMBOL_NOVERS(__moddi3); +EXPORT_SYMBOL_NOVERS(__modsi3); +EXPORT_SYMBOL_NOVERS(__muldi3); +EXPORT_SYMBOL_NOVERS(__negdi2); +EXPORT_SYMBOL_NOVERS(__ucmpdi2); +EXPORT_SYMBOL_NOVERS(__udivdi3); +EXPORT_SYMBOL_NOVERS(__udivmoddi4); +EXPORT_SYMBOL_NOVERS(__udivsi3); +EXPORT_SYMBOL_NOVERS(__umoddi3); +EXPORT_SYMBOL_NOVERS(__umodsi3); + + /* bitops */ +EXPORT_SYMBOL(set_bit); +EXPORT_SYMBOL(test_and_set_bit); +EXPORT_SYMBOL(clear_bit); +EXPORT_SYMBOL(test_and_clear_bit); +EXPORT_SYMBOL(change_bit); +EXPORT_SYMBOL(test_and_change_bit); +EXPORT_SYMBOL(find_first_zero_bit); +EXPORT_SYMBOL(find_next_zero_bit); diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S --- v2.1.79/linux/arch/arm/kernel/calls.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/calls.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,194 @@ +/* + * linux/arch/arm/lib/calls.h + * + * Copyright (C) 1995, 1996 Russell King + */ +#ifndef NR_SYSCALLS +#define NR_syscalls 256 +#define NR_SYSCALLS 182 +#else + +/* 0 */ .long SYMBOL_NAME(sys_setup) + .long SYMBOL_NAME(sys_exit) + .long SYMBOL_NAME(sys_fork_wrapper) + .long SYMBOL_NAME(sys_read) + .long SYMBOL_NAME(sys_write) +/* 5 */ .long SYMBOL_NAME(sys_open) + .long SYMBOL_NAME(sys_close) + .long SYMBOL_NAME(sys_waitpid) + .long SYMBOL_NAME(sys_creat) + .long SYMBOL_NAME(sys_link) +/* 10 */ .long SYMBOL_NAME(sys_unlink) + .long SYMBOL_NAME(sys_execve_wrapper) + .long SYMBOL_NAME(sys_chdir) + .long SYMBOL_NAME(sys_time) + .long SYMBOL_NAME(sys_mknod) +/* 15 */ .long SYMBOL_NAME(sys_chmod) + .long SYMBOL_NAME(sys_chown) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_break */ + .long SYMBOL_NAME(sys_stat) + .long SYMBOL_NAME(sys_lseek) +/* 20 */ .long SYMBOL_NAME(sys_getpid) + .long SYMBOL_NAME(sys_mount_wrapper) + .long SYMBOL_NAME(sys_umount) + .long SYMBOL_NAME(sys_setuid) + .long SYMBOL_NAME(sys_getuid) +/* 25 */ .long SYMBOL_NAME(sys_stime) + .long SYMBOL_NAME(sys_ptrace) + .long SYMBOL_NAME(sys_alarm) + .long SYMBOL_NAME(sys_fstat) + .long SYMBOL_NAME(sys_pause) +/* 30 */ .long SYMBOL_NAME(sys_utime) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_stty */ + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_getty */ + .long SYMBOL_NAME(sys_access) + .long SYMBOL_NAME(sys_nice) +/* 35 */ .long SYMBOL_NAME(sys_ni_syscall) /* was sys_ftime */ + .long SYMBOL_NAME(sys_sync) + .long SYMBOL_NAME(sys_kill) + .long SYMBOL_NAME(sys_rename) + .long SYMBOL_NAME(sys_mkdir) +/* 40 */ .long SYMBOL_NAME(sys_rmdir) + .long SYMBOL_NAME(sys_dup) + .long SYMBOL_NAME(sys_pipe) + .long SYMBOL_NAME(sys_times) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_prof */ +/* 45 */ .long SYMBOL_NAME(sys_brk) + .long SYMBOL_NAME(sys_setgid) + .long SYMBOL_NAME(sys_getgid) + .long SYMBOL_NAME(sys_signal) + .long SYMBOL_NAME(sys_geteuid) +/* 50 */ .long SYMBOL_NAME(sys_getegid) + .long SYMBOL_NAME(sys_acct) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_phys */ + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_lock */ + .long SYMBOL_NAME(sys_ioctl) +/* 55 */ .long SYMBOL_NAME(sys_fcntl) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_mpx */ + .long SYMBOL_NAME(sys_setpgid) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_ulimit */ + .long SYMBOL_NAME(sys_olduname) +/* 60 */ .long SYMBOL_NAME(sys_umask) + .long SYMBOL_NAME(sys_chroot) + .long SYMBOL_NAME(sys_ustat) + .long SYMBOL_NAME(sys_dup2) + .long SYMBOL_NAME(sys_getppid) +/* 65 */ .long SYMBOL_NAME(sys_getpgrp) + .long SYMBOL_NAME(sys_setsid) + .long SYMBOL_NAME(sys_sigaction) + .long SYMBOL_NAME(sys_sgetmask) + .long SYMBOL_NAME(sys_ssetmask) +/* 70 */ .long SYMBOL_NAME(sys_setreuid) + .long SYMBOL_NAME(sys_setregid) + .long SYMBOL_NAME(sys_sigsuspend_wrapper) + .long SYMBOL_NAME(sys_sigpending) + .long SYMBOL_NAME(sys_sethostname) +/* 75 */ .long SYMBOL_NAME(sys_setrlimit) + .long SYMBOL_NAME(sys_getrlimit) + .long SYMBOL_NAME(sys_getrusage) + .long SYMBOL_NAME(sys_gettimeofday) + .long SYMBOL_NAME(sys_settimeofday) +/* 80 */ .long SYMBOL_NAME(sys_getgroups) + .long SYMBOL_NAME(sys_setgroups) + .long SYMBOL_NAME(old_select) + .long SYMBOL_NAME(sys_symlink) + .long SYMBOL_NAME(sys_lstat) +/* 85 */ .long SYMBOL_NAME(sys_readlink) + .long SYMBOL_NAME(sys_uselib) + .long SYMBOL_NAME(sys_swapon) + .long SYMBOL_NAME(sys_reboot) + .long SYMBOL_NAME(old_readdir) +/* 90 */ .long SYMBOL_NAME(old_mmap) + .long SYMBOL_NAME(sys_munmap) + .long SYMBOL_NAME(sys_truncate) + .long SYMBOL_NAME(sys_ftruncate) + .long SYMBOL_NAME(sys_fchmod) +/* 95 */ .long SYMBOL_NAME(sys_fchown) + .long SYMBOL_NAME(sys_getpriority) + .long SYMBOL_NAME(sys_setpriority) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */ + .long SYMBOL_NAME(sys_statfs) +/* 100 */ .long SYMBOL_NAME(sys_fstatfs) + .long SYMBOL_NAME(sys_ni_syscall) /* .long _sys_ioperm */ + .long SYMBOL_NAME(sys_socketcall) + .long SYMBOL_NAME(sys_syslog) + .long SYMBOL_NAME(sys_setitimer) +/* 105 */ .long SYMBOL_NAME(sys_getitimer) + .long SYMBOL_NAME(sys_newstat) + .long SYMBOL_NAME(sys_newlstat) + .long SYMBOL_NAME(sys_newfstat) + .long SYMBOL_NAME(sys_uname) +/* 110 */ .long SYMBOL_NAME(sys_iopl) + .long SYMBOL_NAME(sys_vhangup) + .long SYMBOL_NAME(sys_idle) + .long SYMBOL_NAME(sys_syscall) /* call a syscall */ + .long SYMBOL_NAME(sys_wait4) +/* 115 */ .long SYMBOL_NAME(sys_swapoff) + .long SYMBOL_NAME(sys_sysinfo) + .long SYMBOL_NAME(sys_ipc) + .long SYMBOL_NAME(sys_fsync) + .long SYMBOL_NAME(sys_sigreturn_wrapper) + .long SYMBOL_NAME(sys_clone_wapper) + .long SYMBOL_NAME(sys_setdomainname) + .long SYMBOL_NAME(sys_newuname) + .long SYMBOL_NAME(sys_ni_syscall) /* .long SYMBOL_NAME(sys_modify_ldt) */ + .long SYMBOL_NAME(sys_adjtimex) +/* 125 */ .long SYMBOL_NAME(sys_mprotect) + .long SYMBOL_NAME(sys_sigprocmask) + .long SYMBOL_NAME(sys_create_module) + .long SYMBOL_NAME(sys_init_module) + .long SYMBOL_NAME(sys_delete_module) +/* 130 */ .long SYMBOL_NAME(sys_get_kernel_syms) + .long SYMBOL_NAME(sys_quotactl) + .long SYMBOL_NAME(sys_getpgid) + .long SYMBOL_NAME(sys_fchdir) + .long SYMBOL_NAME(sys_bdflush) +/* 135 */ .long SYMBOL_NAME(sys_sysfs) + .long SYMBOL_NAME(sys_personality) + .long SYMBOL_NAME(sys_ni_syscall) /* .long _sys_afs_syscall */ + .long SYMBOL_NAME(sys_setfsuid) + .long SYMBOL_NAME(sys_setfsgid) +/* 140 */ .long SYMBOL_NAME(sys_llseek_wrapper) + .long SYMBOL_NAME(sys_getdents) + .long SYMBOL_NAME(sys_select) + .long SYMBOL_NAME(sys_flock) + .long SYMBOL_NAME(sys_msync) +/* 145 */ .long SYMBOL_NAME(sys_readv) + .long SYMBOL_NAME(sys_writev) + .long SYMBOL_NAME(sys_getsid) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) +/* 150 */ .long SYMBOL_NAME(sys_mlock) + .long SYMBOL_NAME(sys_munlock) + .long SYMBOL_NAME(sys_mlockall) + .long SYMBOL_NAME(sys_munlockall) + .long SYMBOL_NAME(sys_sched_setparam) +/* 155 */ .long SYMBOL_NAME(sys_sched_getparam) + .long SYMBOL_NAME(sys_sched_setscheduler) + .long SYMBOL_NAME(sys_sched_getscheduler) + .long SYMBOL_NAME(sys_sched_yield) + .long SYMBOL_NAME(sys_sched_get_priority_max) +/* 160 */ .long SYMBOL_NAME(sys_sched_get_priority_min) + .long SYMBOL_NAME(sys_sched_rr_get_interval) + .long SYMBOL_NAME(sys_nanosleep) + .long SYMBOL_NAME(sys_mremap) + .long SYMBOL_NAME(sys_setresuid) +/* 165 */ .long SYMBOL_NAME(sys_getresuid) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_query_module) + .long SYMBOL_NAME(sys_poll) + .long SYMBOL_NAME(sys_nfsservctl) +/* 170 */ .long SYMBOL_NAME(sys_setresgid) + .long SYMBOL_NAME(sys_getresgid) + .long SYMBOL_NAME(sys_prctl) + .long SYMBOL_NAME(sys_rt_sigreturn_wrapper) + .long SYMBOL_NAME(sys_rt_sigaction) +/* 175 */ .long SYMBOL_NAME(sys_rt_sigprocmask) + .long SYMBOL_NAME(sys_rt_sigpending) + .long SYMBOL_NAME(sys_rt_sigtimedwait) + .long SYMBOL_NAME(sys_rt_sigqueueinfo) + .long SYMBOL_NAME(sys_rt_sigsuspend_wrapper) +/* 180 */ .long SYMBOL_NAME(sys_pread) + .long SYMBOL_NAME(sys_pwrite) + .space (NR_syscalls - 182) * 4 +#endif diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c --- v2.1.79/linux/arch/arm/kernel/dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/dma.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,199 @@ +/* + * linux/arch/arm/kernel/dma.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#define KERNEL_ARCH_DMA +#include + +static unsigned long dma_address[8]; +static unsigned long dma_count[8]; +static char dma_direction[8] = { -1, -1, -1, -1, -1, -1, -1}; + +#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_RPC) +#define DMA_PCIO +#endif +#if defined(CONFIG_ARCH_ARC) && defined(CONFIG_BLK_DEV_FD) +#define DMA_OLD +#endif + +void enable_dma (unsigned int dmanr) +{ + switch (dmanr) { +#ifdef DMA_PCIO + case 2: { + void *fiqhandler_start; + unsigned int fiqhandler_length; + extern void floppy_fiqsetup (unsigned long len, unsigned long addr, + unsigned long port); + switch (dma_direction[dmanr]) { + case 1: { + extern unsigned char floppy_fiqin_start, floppy_fiqin_end; + fiqhandler_start = &floppy_fiqin_start; + fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start; + break; + } + case 0: { + extern unsigned char floppy_fiqout_start, floppy_fiqout_end; + fiqhandler_start = &floppy_fiqout_start; + fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start; + break; + } + default: + printk ("enable_dma: dma%d not initialised\n", dmanr); + return; + } + memcpy ((void *)0x1c, fiqhandler_start, fiqhandler_length); + flush_page_to_ram(0); + floppy_fiqsetup (dma_count[dmanr], dma_address[dmanr], (int)PCIO_FLOPPYDMABASE); + enable_irq (64); + return; + } +#endif +#ifdef DMA_OLD + case 0: { /* Data DMA */ + switch (dma_direction[dmanr]) { + case 1: /* read */ + { + extern unsigned char fdc1772_dma_read, fdc1772_dma_read_end; + extern void fdc1772_setupdma(unsigned int count,unsigned int addr); + unsigned long flags; +#ifdef DEBUG + printk("enable_dma fdc1772 data read\n"); +#endif + save_flags(flags); + cliIF(); + + memcpy ((void *)0x1c, (void *)&fdc1772_dma_read, + &fdc1772_dma_read_end - &fdc1772_dma_read); + fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */ + enable_irq (64); + restore_flags(flags); + } + break; + + case 0: /* write */ + { + extern unsigned char fdc1772_dma_write, fdc1772_dma_write_end; + extern void fdc1772_setupdma(unsigned int count,unsigned int addr); + unsigned long flags; + +#ifdef DEBUG + printk("enable_dma fdc1772 data write\n"); +#endif + save_flags(flags); + cliIF(); + memcpy ((void *)0x1c, (void *)&fdc1772_dma_write, + &fdc1772_dma_write_end - &fdc1772_dma_write); + fdc1772_setupdma(dma_count[dmanr],dma_address[dmanr]); /* Sets data pointer up */ + enable_irq (64); + + restore_flags(flags); + } + break; + default: + printk ("enable_dma: dma%d not initialised\n", dmanr); + return; + } + } + break; + + case 1: { /* Command end FIQ - actually just sets a flag */ + /* Need to build a branch at the FIQ address */ + extern void fdc1772_comendhandler(void); + unsigned long flags; + + /*printk("enable_dma fdc1772 command end FIQ\n");*/ + save_flags(flags); + cliIF(); + + *((unsigned int *)0x1c)=0xea000000 | (((unsigned int)fdc1772_comendhandler-(0x1c+8))/4); /* B fdc1772_comendhandler */ + + restore_flags(flags); + } + break; +#endif + case DMA_0: + case DMA_1: + case DMA_2: + case DMA_3: + case DMA_S0: + case DMA_S1: + arch_enable_dma (dmanr - DMA_0); + break; + + default: + printk ("enable_dma: dma %d not supported\n", dmanr); + } +} + +void set_dma_mode (unsigned int dmanr, char mode) +{ + if (dmanr < 8) { + if (mode == DMA_MODE_READ) + dma_direction[dmanr] = 1; + else if (mode == DMA_MODE_WRITE) + dma_direction[dmanr] = 0; + else + printk ("set_dma_mode: dma%d: invalid mode %02X not supported\n", + dmanr, mode); + } else if (dmanr < MAX_DMA_CHANNELS) + arch_set_dma_mode (dmanr - DMA_0, mode); + else + printk ("set_dma_mode: dma %d not supported\n", dmanr); +} + +void set_dma_addr (unsigned int dmanr, unsigned int addr) +{ + if (dmanr < 8) + dma_address[dmanr] = (unsigned long)addr; + else if (dmanr < MAX_DMA_CHANNELS) + arch_set_dma_addr (dmanr - DMA_0, addr); + else + printk ("set_dma_addr: dma %d not supported\n", dmanr); +} + +void set_dma_count (unsigned int dmanr, unsigned int count) +{ + if (dmanr < 8) + dma_count[dmanr] = (unsigned long)count; + else if (dmanr < MAX_DMA_CHANNELS) + arch_set_dma_count (dmanr - DMA_0, count); + else + printk ("set_dma_count: dma %d not supported\n", dmanr); +} + +int get_dma_residue (unsigned int dmanr) +{ + if (dmanr < 8) { + switch (dmanr) { +#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_RPC) + case 2: { + extern int floppy_fiqresidual (void); + return floppy_fiqresidual (); + } +#endif +#if defined(CONFIG_ARCH_ARC) && defined(CONFIG_BLK_DEV_FD) + case 0: { + extern unsigned int fdc1772_bytestogo; + return fdc1772_bytestogo; + } +#endif + default: + return -1; + } + } else if (dmanr < MAX_DMA_CHANNELS) + return arch_dma_count (dmanr - DMA_0); + return -1; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c --- v2.1.79/linux/arch/arm/kernel/ecard.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/ecard.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,604 @@ +/* + * linux/arch/arm/kernel/ecard.c + * + * Find all installed expansion cards, and handle interrupts from them. + * + * Copyright 1995,1996,1997 Russell King + * + * Created from information from Acorns RiscOS3 PRMs + * + * 08-Dec-1996 RMK Added code for the 9'th expansion card - the ether podule slot. + * 06-May-1997 RMK Added blacklist for cards whose loader doesn't work. + * 12-Sep-1997 RMK Created new handling of interrupt enables/disables - cards can + * now register their own routine to control interrupts (recommended). + * 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled on reset from + * Linux. (Caused cards not to respond under RiscOS without hard reset). + */ + +#define ECARD_C + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ARCH_ARC +#include +#else +#define oldlatch_init() +#endif + +#define BLACKLIST_NAME(m,p,s) { m, p, NULL, s } +#define BLACKLIST_LOADER(m,p,l) { m, p, l, NULL } +#define BLACKLIST_NOLOADER(m,p) { m, p, noloader, blacklisted_str } +#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE) + +extern unsigned long atomwide_serial_loader[], oak_scsi_loader[], noloader[]; +static const char blacklisted_str[] = "*loader blacklisted - not 32-bit compliant*"; + +static const struct expcard_blacklist { + unsigned short manufacturer; + unsigned short product; + const loader_t loader; + const char *type; +} blacklist[] = { +/* Cards without names */ + BLACKLIST_NAME(MANU_ACORN, PROD_ACORN_ETHER1, "Acorn Ether1"), + +/* Cards with corrected loader */ + BLACKLIST_LOADER(MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, atomwide_serial_loader), + BLACKLIST_LOADER(MANU_OAK, PROD_OAK_SCSI, oak_scsi_loader), + +/* Unsupported cards with no loader */ +BLACKLIST_NOLOADER(MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI), +BLACKLIST_NOLOADER(MANU_MCS, PROD_MCS_CONNECT32) +}; + +extern int setup_arm_irq(int, struct irqaction *); + +/* + * from linux/arch/arm/kernel/irq.c + */ +extern void do_ecard_IRQ(int irq, struct pt_regs *); + +static ecard_t expcard[MAX_ECARDS]; +static signed char irqno_to_expcard[16]; +static unsigned int ecard_numcards, ecard_numirqcards; +static unsigned int have_expmask; +static unsigned long kmem; + +static void ecard_def_irq_enable (ecard_t *ec, int irqnr) +{ +#ifdef HAS_EXPMASK + if (irqnr < 4 && have_expmask) { + have_expmask |= 1 << irqnr; + EXPMASK_ENABLE = have_expmask; + } +#endif +} + +static void ecard_def_irq_disable (ecard_t *ec, int irqnr) +{ +#ifdef HAS_EXPMASK + if (irqnr < 4 && have_expmask) { + have_expmask &= ~(1 << irqnr); + EXPMASK_ENABLE = have_expmask; + } +#endif +} + +static void ecard_def_fiq_enable (ecard_t *ec, int fiqnr) +{ + panic ("ecard_def_fiq_enable called - impossible"); +} + +static void ecard_def_fiq_disable (ecard_t *ec, int fiqnr) +{ + panic ("ecard_def_fiq_disable called - impossible"); +} + +static expansioncard_ops_t ecard_default_ops = { + ecard_def_irq_enable, + ecard_def_irq_disable, + ecard_def_fiq_enable, + ecard_def_fiq_disable +}; + +/* + * Enable and disable interrupts from expansion cards. + * (interrupts are disabled for these functions). + * + * They are not meant to be called directly, but via enable/disable_irq. + */ +void ecard_enableirq (unsigned int irqnr) +{ + if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) { + ecard_t *ec = expcard + irqno_to_expcard[irqnr]; + + if (!ec->ops) + ec->ops = &ecard_default_ops; + + if (ec->claimed && ec->ops->irqenable) + ec->ops->irqenable (ec, irqnr); + else + printk (KERN_ERR "ecard: rejecting request to " + "enable IRQs for %d\n", irqnr); + } +} + +void ecard_disableirq (unsigned int irqnr) +{ + if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) { + ecard_t *ec = expcard + irqno_to_expcard[irqnr]; + + if (!ec->ops) + ec->ops = &ecard_default_ops; + + if (ec->ops && ec->ops->irqdisable) + ec->ops->irqdisable (ec, irqnr); + } +} + +void ecard_enablefiq (unsigned int fiqnr) +{ + if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) { + ecard_t *ec = expcard + irqno_to_expcard[fiqnr]; + + if (!ec->ops) + ec->ops = &ecard_default_ops; + + if (ec->claimed && ec->ops->fiqenable) + ec->ops->fiqenable (ec, fiqnr); + else + printk (KERN_ERR "ecard: rejecting request to " + "enable FIQs for %d\n", fiqnr); + } +} + +void ecard_disablefiq (unsigned int fiqnr) +{ + if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) { + ecard_t *ec = expcard + irqno_to_expcard[fiqnr]; + + if (!ec->ops) + ec->ops = &ecard_default_ops; + + if (ec->ops->fiqdisable) + ec->ops->fiqdisable (ec, fiqnr); + } +} + +static void *ecard_malloc(int len) +{ + int r; + + len = (len + 3) & ~3; + + if (kmem) { + r = kmem; + kmem += len; + return (void *)r; + } else + return kmalloc(len, GFP_KERNEL); +} + +static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs) +{ + const int num_cards = ecard_numirqcards; + int i, called = 0; + + mask_irq (IRQ_EXPANSIONCARD); + for (i = 0; i < num_cards; i++) { + if (expcard[i].claimed && expcard[i].irq && + (!expcard[i].irqmask || + expcard[i].irqaddr[0] & expcard[i].irqmask)) { + do_ecard_IRQ(expcard[i].irq, regs); + called ++; + } + } + cli (); + unmask_irq (IRQ_EXPANSIONCARD); + if (called == 0) + printk (KERN_WARNING "Wild interrupt from backplane?\n"); +} + +#ifdef HAS_EXPMASK +static unsigned char priority_masks[] = +{ + 0xf0, 0xf1, 0xf3, 0xf7, 0xff, 0xff, 0xff, 0xff +}; + +static unsigned char first_set[] = +{ + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00 +}; + +static void ecard_irq_expmask (int intr_no, void *dev_id, struct pt_regs *regs) +{ + const unsigned int statusmask = 15; + unsigned int status; + + status = EXPMASK_STATUS & statusmask; + if (status) { + unsigned int irqno; + ecard_t *ec; +again: + irqno = first_set[status]; + ec = expcard + irqno_to_expcard[irqno]; + if (ec->claimed) { + unsigned int oldexpmask; + /* + * this ugly code is so that we can operate a prioritorising system. + * Card 0 highest priority + * Card 1 + * Card 2 + * Card 3 lowest priority + * Serial cards should go in 0/1, ethernet/scsi in 2/3 + * otherwise you will lose serial data at high speeds! + */ + oldexpmask = have_expmask; + EXPMASK_ENABLE = (have_expmask &= priority_masks[irqno]); + sti (); + do_ecard_IRQ (ec->irq, regs); + cli (); + EXPMASK_ENABLE = have_expmask = oldexpmask; + status = EXPMASK_STATUS & statusmask; + if (status) + goto again; + } else { + printk (KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno); + EXPMASK_ENABLE = (have_expmask &= ~(1 << irqno)); + } + } else + printk (KERN_WARNING "Wild interrupt from backplane (masks)\n"); +} + +static int ecard_checkirqhw (void) +{ + int found; + + EXPMASK_ENABLE = 0x00; + EXPMASK_STATUS = 0xff; + found = ((EXPMASK_STATUS & 15) == 0); + EXPMASK_ENABLE = 0xff; + + return found; +} +#endif + +static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int useld) +{ + extern int ecard_loader_read(int off, volatile unsigned int pa, loader_t loader); + unsigned char *a = (unsigned char *)addr; + + if (ec->slot_no == 8) { + static unsigned int lowaddress; + unsigned int laddr, haddr; + unsigned char byte = 0; /* keep gcc quiet */ + + laddr = off & 4095; /* number of bytes to read from offset + base addr */ + haddr = off >> 12; /* offset into card from base addr */ + + if (haddr > 256) + return; + + /* + * If we require a low address or address 0, then reset, and start again... + */ + if (!off || lowaddress > laddr) { + outb (0, ec->podaddr); + lowaddress = 0; + } + while (lowaddress <= laddr) { + byte = inb (ec->podaddr + haddr); + lowaddress += 1; + } + while (len--) { + *a++ = byte; + if (len) { + byte = inb (ec->podaddr + haddr); + lowaddress += 1; + } + } + } else { + if (!useld || !ec->loader) { + while(len--) + *a++ = inb(ec->podaddr + (off++)); + } else { + while(len--) { + *(unsigned long *)0x108 = 0; /* hack for some loaders!!! */ + *a++ = ecard_loader_read(off++, BUS_ADDR(ec->podaddr), ec->loader); + } + } + } +} + +/* + * This is called to reset the loaders for each expansion card on reboot. + * + * This is required to make sure that the card is in the correct state + * that RiscOS expects it to be. + */ +void ecard_reset (int card) +{ + extern int ecard_loader_reset (volatile unsigned int pa, loader_t loader); + + if (card >= ecard_numcards) + return; + + if (card < 0) { + for (card = 0; card < ecard_numcards; card++) + if (expcard[card].loader) + ecard_loader_reset (BUS_ADDR(expcard[card].podaddr), + expcard[card].loader); + } else + if (expcard[card].loader) + ecard_loader_reset (BUS_ADDR(expcard[card].podaddr), + expcard[card].loader); + +#ifdef HAS_EXPMASK + if (have_expmask) { + have_expmask |= ~0; + EXPMASK_ENABLE = have_expmask; + } +#endif +} + +static unsigned int ecard_startcard; + +void ecard_startfind (void) +{ + ecard_startcard = 0; +} + +ecard_t *ecard_find (int cld, const card_ids *cids) +{ + int card; + if (!cids) { + for (card = ecard_startcard; card < ecard_numcards; card++) + if (!expcard[card].claimed && + ((expcard[card].cld.ecld ^ cld) & 0x78) == 0) + break; + } else { + for (card = ecard_startcard; card < ecard_numcards; card++) { + unsigned int manufacturer, product; + int i; + + if (expcard[card].claimed) + continue; + + manufacturer = expcard[card].cld.manufacturer; + product = expcard[card].cld.product; + + for (i = 0; cids[i].manufacturer != 65535; i++) + if (manufacturer == cids[i].manufacturer && + product == cids[i].product) + break; + + if (cids[i].manufacturer != 65535) + break; + } + } + ecard_startcard = card + 1; + return card < ecard_numcards ? &expcard[card] : NULL; +} + +int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num) +{ + struct ex_chunk_dir excd; + int index = 16; + int useld = 0; + + while(1) { + ecard_readbytes(&excd, ec, index, 8, useld); + index += 8; + if (c_id(&excd) == 0) { + if (!useld && ec->loader) { + useld = 1; + index = 0; + continue; + } + return 0; + } + if (c_id(&excd) == 0xf0) { /* link */ + index = c_start(&excd); + continue; + } + if (c_id(&excd) == 0x80) { /* loader */ + if (!ec->loader) { + ec->loader = (loader_t)ecard_malloc(c_len(&excd)); + ecard_readbytes(ec->loader, ec, (int)c_start(&excd), c_len(&excd), useld); + } + continue; + } + if (c_id(&excd) == id && num-- == 0) + break; + } + + if (c_id(&excd) & 0x80) { + switch (c_id(&excd) & 0x70) { + case 0x70: + ecard_readbytes((unsigned char *)excd.d.string, ec, + (int)c_start(&excd), c_len(&excd), useld); + break; + case 0x00: + break; + } + } + cd->start_offset = c_start(&excd); + memcpy (cd->d.string, excd.d.string, 256); + return 1; +} + +unsigned int ecard_address (ecard_t *ec, card_type_t memc, card_speed_t speed) +{ + switch (ec->slot_no) { + case 0: + case 1: + case 2: + case 3: + return (memc ? MEMCECIO_BASE : IOCECIO_BASE + (speed << 17)) + (ec->slot_no << 12); +#ifdef IOCEC4IO_BASE + case 4: + case 5: + case 6: + case 7: + return (memc ? 0 : IOCEC4IO_BASE + (speed << 17)) + ((ec->slot_no - 4) << 12); +#endif +#ifdef MEMCEC8IO_BASE + case 8: + return MEMCEC8IO_BASE; +#endif + } + return 0; +} + +/* + * Probe for an expansion card. + * + * If bit 1 of the first byte of the card is set, + * then the card does not exist. + */ +static int ecard_probe (int card, int freeslot) +{ + ecard_t *ec = expcard + freeslot; + struct ex_ecld excld; + const char *card_desc = NULL; + int i; + + irqno_to_expcard[card] = -1; + + ec->slot_no = card; + if ((ec->podaddr = ecard_address (ec, 0, ECARD_SYNC)) == 0) + return 0; + + excld.r_ecld = 2; + ecard_readbytes (&excld, ec, 0, 16, 0); + if (excld.r_ecld & 2) + return 0; + + irqno_to_expcard[card] = freeslot; + + ec->irq = -1; + ec->fiq = -1; + ec->cld.ecld = e_ecld(&excld); + ec->cld.manufacturer = e_manu(&excld); + ec->cld.product = e_prod(&excld); + ec->cld.country = e_country(&excld); + ec->cld.fiqmask = e_fiqmask(&excld); + ec->cld.irqmask = e_irqmask(&excld); + ec->cld.fiqaddr = e_fiqaddr(&excld); + ec->cld.irqaddr = e_irqaddr(&excld); + ec->fiqaddr = + ec->irqaddr = (unsigned char *)BUS_ADDR(ec->podaddr); + ec->fiqmask = 4; + ec->irqmask = 1; + ec->ops = &ecard_default_ops; + + for (i = 0; i < sizeof (blacklist) / sizeof (*blacklist); i++) + if (blacklist[i].manufacturer == ec->cld.manufacturer && + blacklist[i].product == ec->cld.product) { + ec->loader = blacklist[i].loader; + card_desc = blacklist[i].type; + break; + } + + if (card != 8) { + ec->irq = 32 + card; +#if 0 + ec->fiq = 96 + card; +#endif + } else { + ec->irq = 11; + ec->fiq = -1; + } + + if ((ec->cld.ecld & 0x78) == 0) { + struct in_chunk_dir incd; + printk ("\n %d: [%04X:%04X] ", card, ec->cld.manufacturer, ec->cld.product); + if (e_is (&excld)) { + ec->fiqmask = e_fiqmask (&excld); + ec->irqmask = e_irqmask (&excld); + ec->fiqaddr += e_fiqaddr (&excld); + ec->irqaddr += e_irqaddr (&excld); + } + if (!card_desc && e_cd (&excld) && ecard_readchunk (&incd, ec, 0xf5, 0)) + card_desc = incd.d.string; + if (card_desc) + printk ("%s", card_desc); + else + printk ("*Unknown*"); + } else + printk("\n %d: Simple card %d\n", card, (ec->cld.ecld >> 3) & 15); + return 1; +} + +static struct irqaction irqexpansioncard = { ecard_irq_noexpmask, SA_INTERRUPT, 0, "expansion cards", NULL, NULL }; + +/* + * Initialise the expansion card system. + * Locate all hardware - interrupt management and + * actual cards. + */ +unsigned long ecard_init(unsigned long start_mem) +{ + int i, nc = 0; + + kmem = (start_mem | 3) & ~3; + memset (expcard, 0, sizeof (expcard)); + +#ifdef HAS_EXPMASK + if (ecard_checkirqhw()) { + printk (KERN_DEBUG "Expansion card interrupt management hardware found\n"); + irqexpansioncard.handler = ecard_irq_expmask; + have_expmask = -1; + } +#endif + printk("Installed expansion cards:"); + + /* + * First of all, probe all cards on the expansion card interrupt line + */ + for (i = 0; i < 4; i++) + if (ecard_probe (i, nc)) + nc += 1; + else + have_expmask &= ~(1< +#include + +#include +#include +#include + +#include "../lib/constants.h" + + .text + +@ Offsets into task structure +@ --------------------------- +@ +#define STATE 0 +#define COUNTER 4 +#define PRIORITY 8 +#define FLAGS 12 +#define SIGPENDING 16 + +#define PF_TRACESYS 0x20 + +@ Bad Abort numbers +@ ----------------- +@ +#define BAD_PREFETCH 0 +#define BAD_DATA 1 +#define BAD_ADDREXCPTN 2 +#define BAD_IRQ 3 +#define BAD_UNDEFINSTR 4 + +@ OS version number used in SWIs +@ RISC OS is 0 +@ RISC iX is 8 +@ +#define OS_NUMBER 9 + +@ +@ Stack format (ensured by USER_* and SVC_*) +@ +#define S_OLD_R0 64 +#define S_PSR 60 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#ifdef IOC_BASE +/* IOC / IOMD based hardware */ + .equ ioc_base_high, IOC_BASE & 0xff000000 + .equ ioc_base_low, IOC_BASE & 0x00ff0000 + .macro disable_fiq + mov r12, #ioc_base_high + .if ioc_base_low + orr r12, r12, #ioc_base_low + .endif + strb r12, [r12, #0x38] @ Disable FIQ register + .endm + + .macro get_irqnr_and_base, irqnr, base + mov r4, #ioc_base_high @ point at IOC + .if ioc_base_low + orr r4, r4, #ioc_base_low + .endif + ldrb \irqnr, [r4, #0x24] @ get high priority first + adr \base, irq_prio_h + teq \irqnr, #0 + ldreqb \irqnr, [r4, #0x14] @ get low priority + adreq \base, irq_prio_l + .endm + +/* + * Interrupt table (incorporates priority) + */ + .macro irq_prio_table +irq_prio_l: .byte 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .endm +#else +#error Unknown architecture +#endif + +/*============================================================================= + * For entry-common.S + */ + + .macro save_user_regs + str r0, [sp, #-4]! + str lr, [sp, #-4]! + sub sp, sp, #15*4 + stmia sp, {r0 - lr}^ + mov r0, r0 + .endm + + .macro restore_user_regs + ldmia sp, {r0 - lr}^ + mov r0, r0 + add sp, sp, #15*4 + ldr lr, [sp], #8 + movs pc, lr + .endm + + .macro mask_pc, rd, rm + bic \rd, \rm, #PCMASK + .endm + + .macro arm700_bug_check, instr, temp + .endm + + .macro enable_irqs, temp + teqp pc, #0x00000003 + .endm + + .macro initialise_traps_extra + .endm + + .macro get_current_task, rd + mov \rd, sp, lsr #13 + mov \rd, \rd, lsl #13 + .endm + + /* + * Like adr, but force SVC mode (if required) + */ + .macro adrsvc, cond, reg, label + adr\cond \reg, \label + orr\cond \reg, \reg, #3 + .endm + +#if 0 +/* + * Uncomment these if you wish to get more debugging into about data aborts. + */ +#define FAULT_CODE_LDRSTRPOST 0x80 +#define FAULT_CODE_LDRSTRPRE 0x40 +#define FAULT_CODE_LDRSTRREG 0x20 +#define FAULT_CODE_LDMSTM 0x10 +#define FAULT_CODE_LDCSTC 0x08 +#endif +#define FAULT_CODE_PREFETCH 0x04 +#define FAULT_CODE_WRITE 0x02 +#define FAULT_CODE_USER 0x01 + + +#define SVC_SAVE_ALL \ + str sp, [sp, #-16]! ;\ + str lr, [sp, #8] ;\ + str lr, [sp, #4] ;\ + stmfd sp!, {r0 - r12} ;\ + mov r0, #-1 ;\ + str r0, [sp, #S_OLD_R0] ;\ + mov fp, #0 + +#define SVC_IRQ_SAVE_ALL \ + str sp, [sp, #-16]! ;\ + str lr, [sp, #4] ;\ + ldr lr, .LCirq ;\ + ldr lr, [lr] ;\ + str lr, [sp, #8] ;\ + stmfd sp!, {r0 - r12} ;\ + mov r0, #-1 ;\ + str r0, [sp, #S_OLD_R0] ;\ + mov fp, #0 + +#define USER_RESTORE_ALL \ + ldmia sp, {r0 - lr}^ ;\ + mov r0, r0 ;\ + add sp, sp, #15*4 ;\ + ldr lr, [sp], #8 ;\ + movs pc, lr + +#define SVC_RESTORE_ALL \ + ldmfd sp, {r0 - pc}^ + +/*============================================================================= + * Undefined FIQs + *----------------------------------------------------------------------------- + */ +_unexp_fiq: ldr sp, .LCfiq + mov r12, #IOC_BASE + strb r12, [r12, #0x38] @ Disable FIQ register + teqp pc, #0x0c000003 + mov r0, r0 + stmfd sp!, {r0 - r3, ip, lr} + adr r0, Lfiqmsg + bl SYMBOL_NAME(printk) + ldmfd sp!, {r0 - r3, ip, lr} + teqp pc, #0x0c000001 + mov r0, r0 + movs pc, lr + +Lfiqmsg: .ascii "*** Unexpeced FIQ\n\0" + .align + +.LCfiq: .word __temp_fiq +.LCirq: .word __temp_irq + +/*============================================================================= + * Undefined instruction handler + *----------------------------------------------------------------------------- + * Handles floating point instructions + */ +vector_undefinstr: + tst lr,#3 + bne __und_svc + save_user_regs + mov fp, #0 + teqp pc, #I_BIT | MODE_SVC +.Lbug_undef: + adr r1, .LC2 + ldmia r1, {r1, r4} + ldr r1, [r1] + get_current_task r2 + teq r1, r2 + stmnefd sp!, {ip, lr} + blne SYMBOL_NAME(math_state_restore) + ldmnefd sp!, {ip, lr} + ldr pc, [r4] @ Call FP module USR entry point + + .globl SYMBOL_NAME(fpundefinstr) +SYMBOL_NAME(fpundefinstr): @ Called by FP module on undefined instr +SYMBOL_NAME(fpundefinstrsvc): + mov r0, lr + mov r1, sp + teqp pc, #MODE_SVC + bl SYMBOL_NAME(do_undefinstr) + b ret_from_exception @ Normal FP exit + +__und_svc: SVC_SAVE_ALL @ Non-user mode + mask_pc r0, lr + and r2, lr, #3 + sub r0, r0, #4 + mov r1, sp + bl SYMBOL_NAME(do_undefinstr) + SVC_RESTORE_ALL + +.LC2: .word SYMBOL_NAME(last_task_used_math) + .word SYMBOL_NAME(fp_enter) + +/*============================================================================= + * Prefetch abort handler + *----------------------------------------------------------------------------- + */ + +vector_prefetch: + sub lr, lr, #4 + tst lr, #3 + bne __pabt_invalid + save_user_regs + teqp pc, #0x00000003 @ NOT a problem - doesnt change mode + mask_pc r0, lr @ Address of abort + mov r1, #FAULT_CODE_PREFETCH|FAULT_CODE_USER @ Error code + mov r2, sp @ Tasks registers + bl SYMBOL_NAME(do_PrefetchAbort) + teq r0, #0 @ If non-zero, we believe this abort.. + bne ret_from_sys_call +#ifdef DEBUG_UNDEF + adr r0, t + bl SYMBOL_NAME(printk) +#endif + ldr lr, [sp,#S_PC] @ program to test this on. I think its + b .Lbug_undef @ broken at the moment though!) + +__pabt_invalid: SVC_SAVE_ALL + mov r0, sp @ Prefetch aborts are definitely *not* + mov r1, #BAD_PREFETCH @ allowed in non-user modes. We cant + and r2, lr, #3 @ recover from this problem. + b SYMBOL_NAME(bad_mode) + +#ifdef DEBUG_UNDEF +t: .ascii "*** undef ***\r\n\0" + .align +#endif + +/*============================================================================= + * Address exception handler + *----------------------------------------------------------------------------- + * These aren't too critical. + * (they're not supposed to happen). + * In order to debug the reason for address exceptions in non-user modes, + * we have to obtain all the registers so that we can see what's going on. + */ + +vector_addrexcptn: + sub lr, lr, #8 + tst lr, #3 + bne Laddrexcptn_not_user + save_user_regs + teq pc, #0x00000003 + mask_pc r0, lr @ Point to instruction + mov r1, sp @ Point to registers + mov r2, #0x400 + mov lr, pc + bl SYMBOL_NAME(do_excpt) + b ret_from_exception + +Laddrexcptn_not_user: + SVC_SAVE_ALL + and r2, lr, #3 + teq r2, #3 + bne Laddrexcptn_illegal_mode + teqp pc, #0x00000003 @ NOT a problem - doesnt change mode + mask_pc r0, lr + mov r1, sp + orr r2, r2, #0x400 + bl SYMBOL_NAME(do_excpt) + ldmia sp, {r0 - lr} @ I cant remember the reason I changed this... + add sp, sp, #15*4 + movs pc, lr + +Laddrexcptn_illegal_mode: + mov r0, sp + str lr, [sp, #-4]! + orr r1, r2, #0x0c000000 + teqp r1, #0 @ change into mode (wont be user mode) + mov r0, r0 + mov r1, r8 @ Any register from r8 - r14 can be banked + mov r2, r9 + mov r3, r10 + mov r4, r11 + mov r5, r12 + mov r6, r13 + mov r7, r14 + teqp pc, #0x04000003 @ back to svc + mov r0, r0 + stmfd sp!, {r1-r7} + ldmia r0, {r0-r7} + stmfd sp!, {r0-r7} + mov r0, sp + mov r1, #BAD_ADDREXCPTN + b SYMBOL_NAME(bad_mode) + +/*============================================================================= + * Interrupt (IRQ) handler + *----------------------------------------------------------------------------- + * Note: if in user mode, then *no* kernel routine is running, so dont have + * to save svc lr + * (r13 points to irq temp save area) + */ + +vector_IRQ: ldr r13, .LCirq @ Ill leave this one in just in case... + sub lr, lr, #4 + str lr, [r13] + tst lr, #3 + bne __irq_svc + teqp pc, #0x08000003 + mov r0, r0 + ldr lr, .LCirq + ldr lr, [lr] + save_user_regs + +1: get_irqnr_and_base r6, r5 + teq r6, #0 + ldrneb r0, [r5, r6] @ get IRQ number + movne r1, sp + @ + @ routine called with r0 = irq number, r1 = struct pt_regs * + @ + adr lr, 1b + orr lr, lr, #3 @ Force SVC + bne do_IRQ + b ret_with_reschedule + + irq_prio_table + +__irq_svc: teqp pc, #0x08000003 + mov r0, r0 + SVC_IRQ_SAVE_ALL + and r2, lr, #3 + teq r2, #3 + bne __irq_invalid +1: get_irqnr_and_base r6, r5 + teq r6, #0 + ldrneb r0, [r5, r6] @ get IRQ number + movne r1, sp + @ + @ routine called with r0 = irq number, r1 = struct pt_regs * + @ + adr lr, 1b + orr lr, lr, #3 @ Force SVC + bne do_IRQ @ Returns to 1b + SVC_RESTORE_ALL + +__irq_invalid: mov r0, sp + mov r1, #BAD_IRQ + b SYMBOL_NAME(bad_mode) + +/*============================================================================= + * Data abort handler code + *----------------------------------------------------------------------------- + * + * This handles both exceptions from user and SVC modes, computes the address + * range of the problem, and does any correction that is required. It then + * calls the kernel data abort routine. + * + * This is where I wish that the ARM would tell you which address aborted. + */ + +vector_data: sub lr, lr, #8 @ Correct lr + tst lr, #3 + bne Ldata_not_user + save_user_regs + teqp pc, #0x00000003 @ NOT a problem - doesnt change mode + mask_pc r0, lr + mov r2, #FAULT_CODE_USER + bl Ldata_do + b ret_from_exception + +Ldata_not_user: + SVC_SAVE_ALL + and r2, lr, #3 + teq r2, #3 + bne Ldata_illegal_mode + tst lr, #0x08000000 + teqeqp pc, #0x00000003 @ NOT a problem - doesnt change mode + mask_pc r0, lr + mov r2, #0 + bl Ldata_do + SVC_RESTORE_ALL + +Ldata_illegal_mode: + mov r0, sp + mov r1, #BAD_DATA + b SYMBOL_NAME(bad_mode) + +Ldata_do: mov r3, sp + ldr r4, [r0] @ Get instruction + tst r4, #1 << 20 @ Check to see if it is a write instruction + orreq r2, r2, #FAULT_CODE_WRITE @ Indicate write instruction + mov r1, r4, lsr #22 @ Now branch to the relevent processing routine + and r1, r1, #15 << 2 + add pc, pc, r1 + movs pc, lr + b Ldata_unknown + b Ldata_unknown + b Ldata_unknown + b Ldata_unknown + b Ldata_ldrstr_post @ ldr rd, [rn], #m + b Ldata_ldrstr_numindex @ ldr rd, [rn, #m] @ RegVal + b Ldata_ldrstr_post @ ldr rd, [rn], rm + b Ldata_ldrstr_regindex @ ldr rd, [rn, rm] + b Ldata_ldmstm @ ldm*a rn, + b Ldata_ldmstm @ ldm*b rn, + b Ldata_unknown + b Ldata_unknown + b Ldata_ldrstr_post @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m + b Ldata_ldcstc_pre @ ldc rd, [rn, #m] + b Ldata_unknown +Ldata_unknown: @ Part of jumptable + ldr r3, [sp, #15 * 4] + str r3, [sp, #-4]! + mov r1, r1, lsr #2 + mov r2, r0 + mov r3, r4 + adr r0, Ltt + bl SYMBOL_NAME(printk) +Llpxx: b Llpxx + +Ltt: .ascii "Unknown data abort code %d [pc=%p, *pc=%p]\nLR=%p\0" + .align + +Ldata_ldrstr_post: + mov r0, r4, lsr #14 @ Get Rn + and r0, r0, #15 << 2 @ Mask out reg. + teq r0, #15 << 2 + ldr r0, [r3, r0] @ Get register + biceq r0, r0, #PCMASK + mov r1, r0 +#ifdef FAULT_CODE_LDRSTRPOST + orr r2, r2, #FAULT_CODE_LDRSTRPOST +#endif + b SYMBOL_NAME(do_DataAbort) + +Ldata_ldrstr_numindex: + mov r0, r4, lsr #14 @ Get Rn + and r0, r0, #15 << 2 @ Mask out reg. + teq r0, #15 << 2 + ldr r0, [r3, r0] @ Get register + biceq r0, r0, #PCMASK + mov r1, r4, lsl #20 + tst r4, #1 << 23 + addne r0, r0, r1, lsr #20 + subeq r0, r0, r1, lsr #20 + mov r1, r0 +#ifdef FAULT_CODE_LDRSTRPRE + orr r2, r2, #FAULT_CODE_LDRSTRPRE +#endif + b SYMBOL_NAME(do_DataAbort) + +Ldata_ldrstr_regindex: + mov r0, r4, lsr #14 @ Get Rn + and r0, r0, #15 << 2 @ Mask out reg. + teq r0, #15 << 2 + ldr r0, [r3, r0] @ Get register + biceq r0, r0, #PCMASK + and r7, r4, #15 + teq r7, #15 @ Check for PC + ldr r7, [r3, r7, lsl #2] @ Get Rm + biceq r7, r7, #PCMASK + and r8, r4, #0x60 @ Get shift types + mov r9, r4, lsr #7 @ Get shift amount + and r9, r9, #31 + teq r8, #0 + moveq r7, r7, lsl r9 + teq r8, #0x20 @ LSR shift + moveq r7, r7, lsr r9 + teq r8, #0x40 @ ASR shift + moveq r7, r7, asr r9 + teq r8, #0x60 @ ROR shift + moveq r7, r7, ror r9 + tst r4, #1 << 23 + addne r0, r0, r7 + subeq r0, r0, r7 @ Apply correction + mov r1, r0 +#ifdef FAULT_CODE_LDRSTRREG + orr r2, r2, #FAULT_CODE_LDRSTRREG +#endif + b SYMBOL_NAME(do_DataAbort) + +Ldata_ldmstm: + mov r7, #0x11 + orr r7, r7, r7, lsl #8 + and r0, r4, r7 + and r1, r4, r7, lsl #1 + add r0, r0, r1, lsr #1 + and r1, r4, r7, lsl #2 + add r0, r0, r1, lsr #2 + and r1, r4, r7, lsl #3 + add r0, r0, r1, lsr #3 + add r0, r0, r0, lsr #8 + add r0, r0, r0, lsr #4 + and r7, r0, #15 @ r7 = no. of registers to transfer. + mov r5, r4, lsr #14 @ Get Rn + and r5, r5, #15 << 2 + ldr r0, [r3, r5] @ Get reg + eor r6, r4, r4, lsl #2 + tst r6, #1 << 23 @ Check inc/dec ^ writeback + rsbeq r7, r7, #0 + add r7, r0, r7, lsl #2 @ Do correction (signed) + subne r1, r7, #1 + subeq r1, r0, #1 + moveq r0, r7 + tst r4, #1 << 21 @ Check writeback + strne r7, [r3, r5] + eor r6, r4, r4, lsl #1 + tst r6, #1 << 24 @ Check Pre/Post ^ inc/dec + addeq r0, r0, #4 + addeq r1, r1, #4 + teq r5, #15*4 @ CHECK FOR PC + biceq r1, r1, #PCMASK + biceq r0, r0, #PCMASK +#ifdef FAULT_CODE_LDMSTM + orr r2, r2, #FAULT_CODE_LDMSTM +#endif + b SYMBOL_NAME(do_DataAbort) + +Ldata_ldcstc_pre: + mov r0, r4, lsr #14 @ Get Rn + and r0, r0, #15 << 2 @ Mask out reg. + teq r0, #15 << 2 + ldr r0, [r3, r0] @ Get register + biceq r0, r0, #PCMASK + mov r1, r4, lsl #24 @ Get offset + tst r4, #1 << 23 + addne r0, r0, r1, lsr #24 + subeq r0, r0, r1, lsr #24 + mov r1, r0 +#ifdef FAULT_CODE_LDCSTC + orr r2, r2, #FAULT_CODE_LDCSTC +#endif + b SYMBOL_NAME(do_DataAbort) + +#include "entry-common.S" + + .data + +__temp_irq: .word 0 @ saved lr_irq +__temp_fiq: .space 128 diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- v2.1.79/linux/arch/arm/kernel/entry-armv.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/entry-armv.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,670 @@ +/* + * linux/arch/arm/kernel/entry-armv.S + * + * Copyright (C) 1996,1997,1998 Russell King. + * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk) + * + * Low-level vector interface routines + * + * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes + * it to save wrong values... Be aware! + */ +#include +#include + +#include +#include +#include + +#include "../lib/constants.h" + + .text + +@ Offsets into task structure +@ --------------------------- +@ +#define STATE 0 +#define COUNTER 4 +#define PRIORITY 8 +#define FLAGS 12 +#define SIGPENDING 16 + +#define PF_TRACESYS 0x20 + +@ Bad Abort numbers +@ ----------------- +@ +#define BAD_PREFETCH 0 +#define BAD_DATA 1 +#define BAD_ADDREXCPTN 2 +#define BAD_IRQ 3 +#define BAD_UNDEFINSTR 4 + +@ OS version number used in SWIs +@ RISC OS is 0 +@ RISC iX is 8 +@ +#define OS_NUMBER 9 + +@ +@ Stack format (ensured by USER_* and SVC_*) +@ +#define S_FRAME_SIZE 72 +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#ifdef IOC_BASE +/* IOC / IOMD based hardware */ + .equ ioc_base_high, IOC_BASE & 0xff000000 + .equ ioc_base_low, IOC_BASE & 0x00ff0000 + .macro disable_fiq + mov r12, #ioc_base_high + .if ioc_base_low + orr r12, r12, #ioc_base_low + .endif + strb r12, [r12, #0x38] @ Disable FIQ register + .endm + + .macro get_irqnr_and_base, irqnr, base + mov r4, #ioc_base_high @ point at IOC + .if ioc_base_low + orr r4, r4, #ioc_base_low + .endif + ldrb \irqnr, [r4, #0x24] @ get high priority first + adr \base, irq_prio_h + teq \irqnr, #0 +#ifdef IOMD_BASE + ldreqb \irqnr, [r4, #0x1f4] @ get dma + adreq \base, irq_prio_d + teqeq \irqnr, #0 +#endif + ldreqb \irqnr, [r4, #0x14] @ get low priority + adreq \base, irq_prio_l + .endm + +/* + * Interrupt table (incorporates priority) + */ + .macro irq_prio_table +irq_prio_l: .byte 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + .byte 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +#ifdef IOMD_BASE +irq_prio_d: .byte 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 + .byte 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16 +#endif +irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .byte 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10 + .endm + +#elif defined(CONFIG_ARCH_EBSA110) + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, base + mov r4, #0xf3000000 + ldrb \irqnr, [r4] @ get interrupts + adr \base, irq_prio_ebsa110 + .endm + + .macro irq_prio_table +irq_prio_ebsa110: + .byte 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 + .byte 4, 4, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 + .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 + .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 + + .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 + .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 + .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 + .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 + + .byte 7, 0, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 + .byte 4, 4, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 + .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 + .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 + + .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 + .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 + .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 + .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 + .endm + +#else +#error Unknown architecture +#endif + +/*============================================================================ + * For entry-common.S + */ + + .macro save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0 - r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling sp, lr + mov r7, r0 + mrs r6, spsr + mov r5, lr + stmia r8, {r5, r6, r7} @ Save calling PC, CPSR, OLD_R0 + .endm + + .macro restore_user_regs + mrs r0, cpsr @ disable IRQs + orr r0, r0, #I_BIT + msr cpsr, r0 + ldr r0, [sp, #S_PSR] @ Get calling cpsr + msr spsr, r0 @ save in spsr_svc + ldmia sp, {r0 - lr}^ @ Get calling r0 - lr + mov r0, r0 + add sp, sp, #S_PC + ldr lr, [sp], #S_FRAME_SIZE - S_PC @ Get PC and jump over PC, PSR, OLD_R0 + movs pc, lr @ return & move spsr_svc into cpsr + .endm + + .macro mask_pc, rd, rm + .endm + + .macro arm700_bug_check, instr, temp + and \temp, \instr, #0x0f000000 @ check for SWI + teq \temp, #0x0f000000 + bne .Larm700bug + .endm + + .macro enable_irqs, temp + mrs \temp, cpsr + bic \temp, \temp, #I_BIT + msr cpsr, \temp + .endm + + .macro initialise_traps_extra + mrs r0, cpsr + bic r0, r0, #31 + orr r0, r0, #0xd3 + msr cpsr, r0 + .endm + + +.Larm700bug: str lr, [r8] + ldr r0, [sp, #S_PSR] @ Get calling cpsr + msr spsr, r0 + ldmia sp, {r0 - lr}^ @ Get calling r0 - lr + mov r0, r0 + add sp, sp, #S_PC + ldr lr, [sp], #S_FRAME_SIZE - S_PC @ Get PC and jump over PC, PSR, OLD_R0 + movs pc, lr + + + .macro get_current_task, rd + mov \rd, sp, lsr #13 + mov \rd, \rd, lsl #13 + .endm + + /* + * Like adr, but force SVC mode (if required) + */ + .macro adrsvc, cond, reg, label + adr\cond \reg, \label + .endm + +/*============================================================================= + * Undefined FIQs + *----------------------------------------------------------------------------- + * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC + * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg. + * Basically to switch modes, we *HAVE* to clobber one register... brain + * damage alert! I don't think that we can execute any code in here in any + * other mode than FIQ... Ok you can switch to another mode, but you can't + * get out of that mode without clobbering one register. + */ +_unexp_fiq: disable_fiq + subs pc, lr, #4 + +/*============================================================================= + * Interrupt entry dispatcher + *----------------------------------------------------------------------------- + * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC + */ +vector_IRQ: @ + @ save mode specific registers + @ + ldr r13, .LCirq + sub lr, lr, #4 + str lr, [r13] @ save lr_IRQ + mrs lr, spsr + str lr, [r13, #4] @ save spsr_IRQ + @ + @ now branch to the relevent MODE handling routine + @ + mrs sp, cpsr @ switch to SVC mode + bic sp, sp, #31 + orr sp, sp, #0x13 + msr spsr, sp + and lr, lr, #15 + cmp lr, #4 + addlts pc, pc, lr, lsl #2 @ Changes mode and branches + b __irq_invalid @ 4 - 15 + b __irq_usr @ 0 (USR_26 / USR_32) + b __irq_invalid @ 1 (FIQ_26 / FIQ_32) + b __irq_invalid @ 2 (IRQ_26 / IRQ_32) + b __irq_svc @ 3 (SVC_26 / SVC_32) +/* + *------------------------------------------------------------------------------------------------ + * Undef instr entry dispatcher - dispatches it to the correct handler for the processor mode + *------------------------------------------------------------------------------------------------ + * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC + */ +.LCirq: .word __temp_irq +.LCund: .word __temp_und +.LCabt: .word __temp_abt + +vector_undefinstr: + @ + @ save mode specific registers + @ + ldr r13, [pc, #.LCund - . - 8] + str lr, [r13] + mrs lr, spsr + str lr, [r13, #4] + @ + @ now branch to the relevent MODE handling routine + @ + mrs sp, cpsr + bic sp, sp, #31 + orr sp, sp, #0x13 + msr spsr, sp + and lr, lr, #15 + cmp lr, #4 + addlts pc, pc, lr, lsl #2 @ Changes mode and branches + b __und_invalid @ 4 - 15 + b __und_usr @ 0 (USR_26 / USR_32) + b __und_invalid @ 1 (FIQ_26 / FIQ_32) + b __und_invalid @ 2 (IRQ_26 / IRQ_32) + b __und_svc @ 3 (SVC_26 / SVC_32) +/* + *------------------------------------------------------------------------------------------------ + * Prefetch abort dispatcher - dispatches it to the correct handler for the processor mode + *------------------------------------------------------------------------------------------------ + * Enter in ABT mode, spsr = USR CPSR, lr = USR PC + */ +vector_prefetch: + @ + @ save mode specific registers + @ + sub lr, lr, #4 + ldr r13, .LCabt + str lr, [r13] + mrs lr, spsr + str lr, [r13, #4] + @ + @ now branch to the relevent MODE handling routine + @ + mrs sp, cpsr + bic sp, sp, #31 + orr sp, sp, #0x13 + msr spsr, sp + and lr, lr, #15 + adds pc, pc, lr, lsl #2 @ Changes mode and branches + b __pabt_invalid @ 4 - 15 + b __pabt_usr @ 0 (USR_26 / USR_32) + b __pabt_invalid @ 1 (FIQ_26 / FIQ_32) + b __pabt_invalid @ 2 (IRQ_26 / IRQ_32) + b __pabt_invalid @ 3 (SVC_26 / SVC_32) +/* + *------------------------------------------------------------------------------------------------ + * Data abort dispatcher - dispatches it to the correct handler for the processor mode + *------------------------------------------------------------------------------------------------ + * Enter in ABT mode, spsr = USR CPSR, lr = USR PC + */ +vector_data: @ + @ save mode specific registers + @ + sub lr, lr, #8 + ldr r13, .LCabt + str lr, [r13] + mrs lr, spsr + str lr, [r13, #4] + @ + @ now branch to the relevent MODE handling routine + @ + mrs sp, cpsr + bic sp, sp, #31 + orr sp, sp, #0x13 + msr spsr, sp + and lr, lr, #15 + cmp lr, #4 + addlts pc, pc, lr, lsl #2 @ Changes mode & branches + b __dabt_invalid @ 4 - 15 + b __dabt_usr @ 0 (USR_26 / USR_32) + b __dabt_invalid @ 1 (FIQ_26 / FIQ_32) + b __dabt_invalid @ 2 (IRQ_26 / IRQ_32) + b __dabt_svc @ 3 (SVC_26 / SVC_32) + +/*============================================================================= + * Undefined instruction handler + *----------------------------------------------------------------------------- + * Handles floating point instructions + */ +__und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - r12} @ Save r0 - r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Save user r0 - r12 + ldr r4, .LCund + ldmia r4, {r5 - r7} + stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 + mov fp, #0 + + adr r1, .LC2 + ldmia r1, {r1, r4} + ldr r1, [r1] + get_current_task r2 + teq r1, r2 + blne SYMBOL_NAME(math_state_restore) + adrsvc, al, r9, SYMBOL_NAME(fpreturn) + adrsvc al, lr, SYMBOL_NAME(fpundefinstr) + ldr pc, [r4] @ Call FP module USR entry point + + .globl SYMBOL_NAME(fpundefinstr) +SYMBOL_NAME(fpundefinstr): @ Called by FP module on undefined instr + mov r0, lr + mov r1, sp + mrs r4, cpsr @ Enable interrupts + bic r4, r4, #I_BIT + msr cpsr, r4 + bl SYMBOL_NAME(do_undefinstr) + b ret_from_exception @ Normal FP exit + +__und_svc: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + mov r6, lr + ldr r7, .LCund + ldmia r7, {r7 - r9} + add r5, sp, #S_FRAME_SIZE + add r4, sp, #S_SP + stmia r4, {r5 - r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + + adr r1, .LC2 + ldmia r1, {r1, r4} + ldr r1, [r1] + mov r2, sp, lsr #13 + mov r2, r2, lsl #13 + teq r1, r2 + blne SYMBOL_NAME(math_state_restore) + adrsvc al, r9, SYMBOL_NAME(fpreturnsvc) + adrsvc al, lr, SYMBOL_NAME(fpundefinstrsvc) + ldr pc, [r4] @ Call FP module SVC entry point + + .globl SYMBOL_NAME(fpundefinstrsvc) +SYMBOL_NAME(fpundefinstrsvc): + mov r0, r5 @ unsigned long pc + mov r1, sp @ struct pt_regs *regs + bl SYMBOL_NAME(do_undefinstr) + + .globl SYMBOL_NAME(fpreturnsvc) +SYMBOL_NAME(fpreturnsvc): + ldr lr, [sp, #S_PSR] @ Get SVC cpsr + msr spsr, lr + ldmia sp, {r0 - pc}^ @ Restore SVC registers + +.LC2: .word SYMBOL_NAME(last_task_used_math) + .word SYMBOL_NAME(fp_enter) + +__und_invalid: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - lr} + mov r7, r0 + ldr r4, .LCund + ldmia r4, {r5, r6} @ Get UND/IRQ/FIQ/ABT pc, cpsr + add r4, sp, #S_PC + stmia r4, {r5, r6, r7} @ Save UND/IRQ/FIQ/ABT pc, cpsr, old_r0 + mov r0, sp @ struct pt_regs *regs + mov r1, #BAD_UNDEFINSTR @ int reason + and r2, r6, #31 @ int mode + b SYMBOL_NAME(bad_mode) @ Does not ever return... +/*============================================================================= + * Prefetch abort handler + *----------------------------------------------------------------------------- + */ +pabtmsg: .ascii "Pabt: %08lX\n\0" + .align +__pabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - r12} @ Save r0 - r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Save sp_usr lr_usr + ldr r4, .LCabt + ldmia r4, {r5 - r7} @ Get USR pc, cpsr + stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 + + mrs r7, cpsr @ Enable interrupts if they were + bic r7, r7, #I_BIT @ previously + msr cpsr, r7 + mov r0, r5 @ address (pc) + mov r1, sp @ regs + bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler + teq r0, #0 @ Does this still apply??? + bne ret_from_exception @ Return from exception +#ifdef DEBUG_UNDEF + adr r0, t + bl SYMBOL_NAME(printk) +#endif + mov r0, r5 + mov r1, sp + and r2, r6, #31 + bl SYMBOL_NAME(do_undefinstr) + ldr lr, [sp, #S_PSR] @ Get USR cpsr + msr spsr, lr + ldmia sp, {r0 - pc}^ @ Restore USR registers + +__pabt_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - lr} @ Save XXX r0 - lr + mov r7, r0 @ OLD R0 + ldr r4, .LCabt + ldmia r4, {r5 - r7} @ Get XXX pc, cpsr + add r4, sp, #S_PC + stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0 + mov r0, sp @ Prefetch aborts are definitely *not* + mov r1, #BAD_PREFETCH @ allowed in non-user modes. We cant + and r2, r6, #31 @ recover from this problem. + b SYMBOL_NAME(bad_mode) + +#ifdef DEBUG_UNDEF +t: .ascii "*** undef ***\r\n\0" + .align +#endif + +/*============================================================================= + * Address exception handler + *----------------------------------------------------------------------------- + * These aren't too critical. + * (they're not supposed to happen, and won't happen in 32-bit mode). + */ + +vector_addrexcptn: + b vector_addrexcptn + +/*============================================================================= + * Interrupt (IRQ) handler + *----------------------------------------------------------------------------- + */ +__irq_usr: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ + ldr r4, .LCirq + ldmia r4, {r5 - r7} @ get saved PC, SPSR + stmia r8, {r5 - r7} @ save pc, psr, old_r0 +1: get_irqnr_and_base r6, r5 + teq r6, #0 + ldrneb r0, [r5, r6] @ get IRQ number + movne r1, sp + @ + @ routine called with r0 = irq number, r1 = struct pt_regs * + @ + adrsvc ne, lr, 1b + bne do_IRQ + b ret_with_reschedule + + irq_prio_table + +__irq_svc: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + mov r6, lr + ldr r7, .LCirq + ldmia r7, {r7 - r9} + add r5, sp, #S_FRAME_SIZE + add r4, sp, #S_SP + stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro +1: get_irqnr_and_base r6, r5 + teq r6, #0 + ldrneb r0, [r5, r6] @ get IRQ number + movne r1, sp + @ + @ routine called with r0 = irq number, r1 = struct pt_regs * + @ + adrsvc ne, lr, 1b + bne do_IRQ + ldr r0, [sp, #S_PSR] + msr spsr, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + +__irq_invalid: sub sp, sp, #S_FRAME_SIZE @ Allocate space on stack for frame + stmfd sp, {r0 - lr} @ Save r0 - lr + mov r7, #-1 + ldr r4, .LCirq + ldmia r4, {r5, r6} @ get saved pc, psr + add r4, sp, #S_PC + stmia r4, {r5, r6, r7} + mov fp, #0 + mov r0, sp + mov r1, #BAD_IRQ + b SYMBOL_NAME(bad_mode) + +/*============================================================================= + * Data abort handler code + *----------------------------------------------------------------------------- + */ +.LCprocfns: .word SYMBOL_NAME(processor) + +__dabt_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go + stmia sp, {r0 - r12} @ save r0 - r12 + add r3, sp, #S_PC + stmdb r3, {sp, lr}^ + ldr r0, .LCabt + ldmia r0, {r0 - r2} @ Get USR pc, cpsr + stmia r3, {r0 - r2} @ Save USR pc, cpsr, old_r0 + mov fp, #0 + mrs r2, cpsr @ Enable interrupts if they were + bic r2, r2, #I_BIT @ previously + msr cpsr, r2 + ldr r2, .LCprocfns + mov lr, pc + ldr pc, [r2, #8] @ call processor specific code + mov r3, sp + bl SYMBOL_NAME(do_DataAbort) + b ret_from_sys_call + +__dabt_svc: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + ldr r2, .LCabt + add r0, sp, #S_FRAME_SIZE + add r5, sp, #S_SP + mov r1, lr + ldmia r2, {r2 - r4} @ get pc, cpsr + stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + tst r3, #I_BIT + mrseq r0, cpsr @ Enable interrupts if they were + biceq r0, r0, #I_BIT @ previously + msreq cpsr, r0 + mov r0, r2 + ldr r2, .LCprocfns + mov lr, pc + ldr pc, [r2, #8] @ call processor specific code + mov r3, sp + bl SYMBOL_NAME(do_DataAbort) + ldr r0, [sp, #S_PSR] + msr spsr, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + +__dabt_invalid: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - lr} @ Save SVC r0 - lr [lr *should* be intact] + mov r7, r0 + ldr r4, .LCabt + ldmia r4, {r5, r6} @ Get SVC pc, cpsr + add r4, sp, #S_PC + stmia r4, {r5, r6, r7} @ Save SVC pc, cpsr, old_r0 + mov r0, sp + mov r1, #BAD_DATA + and r2, r6, #31 + b SYMBOL_NAME(bad_mode) + + +#include "entry-common.S" + + .data + +__temp_irq: .word 0 @ saved lr_irq + .word 0 @ saved spsr_irq + .word -1 @ old_r0 +__temp_und: .word 0 @ Saved lr_und + .word 0 @ Saved spsr_und + .word -1 @ old_r0 +__temp_abt: .word 0 @ Saved lr_abt + .word 0 @ Saved spsr_abt + .word -1 @ old_r0 diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S --- v2.1.79/linux/arch/arm/kernel/entry-common.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/entry-common.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,283 @@ +/* + *============================================================================= + * Low-level interface code + *----------------------------------------------------------------------------- + * Trap initialisation + *----------------------------------------------------------------------------- + * + * Note - FIQ code has changed. The default is a couple of words in 0x1c, 0x20 + * that call _unexp_fiq. Nowever, we now copy the FIQ routine to 0x1c (removes + * some excess cycles). + * + * What we need to put into 0-0x1c are ldrs to branch to 0xC0000000 + * (the kernel). + * 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for + * the actuall address to jump to. + */ +/* + * these go into 0x00 + */ +.Lbranches: swi SYS_ERROR0 + ldr pc, .Lbranches + 0xe4 + ldr pc, .Lbranches + 0xe8 + ldr pc, .Lbranches + 0xec + ldr pc, .Lbranches + 0xf0 + ldr pc, .Lbranches + 0xf4 + ldr pc, .Lbranches + 0xf8 + ldr pc, .Lbranches + 0xfc +/* + * this is put into 0xe4 and above + */ +.Ljump_addresses: + .word vector_undefinstr @ 0xe4 + .word vector_swi @ 0xe8 + .word vector_prefetch @ 0xec + .word vector_data @ 0xf0 + .word vector_addrexcptn @ 0xf4 + .word vector_IRQ @ 0xf8 + .word _unexp_fiq @ 0xfc +/* + * initialise the trap system + */ +ENTRY(trap_init) + stmfd sp!, {r4 - r7, lr} + initialise_traps_extra + mov r0, #0xe4 + adr r1, .Ljump_addresses + ldmia r1, {r1 - r6} + stmia r0, {r1 - r6} + mov r0, #0 + adr r1, .Lbranches + ldmia r1, {r1 - r7} + stmia r0, {r1 - r7} + LOADREGS(fd, sp!, {r4 - r7, pc}) + +/*============================================================================= + * SWI handler + *----------------------------------------------------------------------------- + * + * We now handle sys-call tracing, and the errno in the task structure. + * Still have a problem with >4 arguments for functions. Theres only + * a couple of functions in the code that have 5 arguments, so Im not + * too worried. + */ + +#include "calls.S" + +vector_swi: save_user_regs + mov fp, #0 + mask_pc lr, lr + ldr r6, [lr, #-4]! @ get SWI instruction + arm700_bug_check r6, r7 + enable_irqs r7 + + bic r6, r6, #0xff000000 @ mask off SWI op-code + eor r6, r6, #OS_NUMBER<<20 @ check OS number + cmp r6, #NR_SYSCALLS @ check upper syscall limit + bcs 2f + + get_current_task r5 + ldr ip, [r5, #FLAGS] @ check for syscall tracing + tst ip, #PF_TRACESYS + bne 1f + + adr ip, SYMBOL_NAME(sys_call_table) + str r4, [sp, #-4]! @ new style: (r0 = arg1, r5 = arg5) + mov lr, pc + ldr pc, [ip, r6, lsl #2] @ call sys routine + add sp, sp, #4 + str r0, [sp, #S_R0] @ returned r0 + b ret_from_sys_call + +1: ldr r7, [sp, #S_IP] @ save old IP + mov r0, #0 + str r7, [sp, #S_IP] @ trace entry [IP = 0] + bl SYMBOL_NAME(syscall_trace) + str r7, [sp, #S_IP] + ldmia sp, {r0 - r3} @ have to reload r0 - r3 + adr ip, SYMBOL_NAME(sys_call_table) + str r4, [sp, #-4]! @ new style: (r0 = arg1, r5 = arg5) + mov lr, pc + ldr pc, [ip, r6, lsl #2] @ call sys routine + add sp, sp, #4 + str r0, [sp, #S_R0] @ returned r0 + mov r0, #1 + str r0, [sp, #S_IP] @ trace exit [IP = 1] + bl SYMBOL_NAME(syscall_trace) + str r7, [sp, #S_IP] + b ret_from_sys_call + +2: tst r6, #0x00f00000 @ is it a Unix SWI? + bne 3f + cmp r6, #(KSWI_SYS_BASE - KSWI_BASE) + bcc 4f @ not private func + bic r0, r6, #0x000f0000 + mov r1, sp + bl SYMBOL_NAME(arm_syscall) + b ret_from_sys_call + +3: eor r0, r6, #OS_NUMBER<<20 @ Put OS number back + mov r1, sp + bl SYMBOL_NAME(deferred) + ldmfd sp, {r0 - r3} + b ret_from_sys_call + +4: bl SYMBOL_NAME(sys_ni_syscall) + str r0, [sp, #0] @ returned r0 + b ret_from_sys_call + +@ r0 = syscall number +@ r1 = syscall r0 +@ r5 = syscall r4 +@ ip = syscall table +SYMBOL_NAME(sys_syscall): + mov r6, r0 + eor r6, r6, #OS_NUMBER << 20 + cmp r6, #NR_SYSCALLS @ check range + movgt r0, #-ENOSYS + movgt pc, lr + add sp, sp, #4 @ take of the save of our r4 + ldmib sp, {r0 - r4} @ get our args + str r4, [sp, #-4]! @ Put our arg on the stack + ldr pc, [ip, r6, lsl #2] + +ENTRY(sys_call_table) +#include "calls.S" + +/*============================================================================ + * Special system call wrappers + */ +sys_fork_wrapper: + add r0, sp, #4 + b SYMBOL_NAME(sys_fork) + +sys_execve_wrapper: + add r3, sp, #4 + b SYMBOL_NAME(sys_execve) + +sys_mount_wrapper: + mov r6, lr + add r5, sp, #4 + str r5, [sp] + str r4, [sp, #-4]! + bl SYMBOL_NAME(sys_compat_mount) + add sp, sp, #4 + RETINSTR(mov,pc,r6) + +sys_clone_wapper: + add r2, sp, #4 + b SYMBOL_NAME(sys_clone) + +sys_llseek_wrapper: + mov r6, lr + add r5, sp, #4 + str r5, [sp] + str r4, [sp, #-4]! + bl SYMBOL_NAME(sys_compat_llseek) + add sp, sp, #4 + RETINSTR(mov,pc,r6) + +sys_sigsuspend_wrapper: + add r3, sp, #4 + b SYMBOL_NAME(sys_sigsuspend) + +sys_rt_sigsuspend_wrapper: + add r2, sp, #4 + b SYMBOL_NAME(sys_rt_sigsuspend) + +sys_sigreturn_wrapper: + add r0, sp, #4 + b SYMBOL_NAME(sys_sigreturn) + +sys_rt_sigreturn_wrapper: + add r0, sp, #4 + b SYMBOL_NAME(sys_rt_sigreturn) + +/*============================================================================ + * All exits to user mode from the kernel go through this code. + */ + + .globl ret_from_sys_call + + .globl SYMBOL_NAME(fpreturn) +SYMBOL_NAME(fpreturn): +ret_from_exception: + adr r0, 1f + ldmia r0, {r0, r1} + ldr r0, [r0] + ldr r1, [r1] + tst r0, r1 + blne SYMBOL_NAME(do_bottom_half) +ret_from_intr: ldr r0, [sp, #S_PSR] + tst r0, #3 + beq ret_with_reschedule + b ret_from_all + +ret_signal: mov r1, sp + adrsvc al, lr, ret_from_all + b SYMBOL_NAME(do_signal) + +2: bl SYMBOL_NAME(schedule) + +ret_from_sys_call: + adr r0, 1f + ldmia r0, {r0, r1} + ldr r0, [r0] + ldr r1, [r1] + tst r0, r1 + adrsvc ne, lr, ret_from_intr + bne SYMBOL_NAME(do_bottom_half) + +ret_with_reschedule: + ldr r0, 1f + 8 + ldr r0, [r0] + teq r0, #0 + bne 2b + + get_current_task r1 + ldr r1, [r1, #SIGPENDING] + teq r1, #0 + bne ret_signal + +ret_from_all: restore_user_regs + +1: .word SYMBOL_NAME(bh_mask) + .word SYMBOL_NAME(bh_active) + .word SYMBOL_NAME(need_resched) + +/*============================================================================ + * FP support + */ + +1: .word SYMBOL_NAME(fp_save) + .word SYMBOL_NAME(fp_restore) + +.Lfpnull: mov pc, lr + + +/* + * Function to call when switching tasks to save FP state + */ +ENTRY(fpe_save) + ldr r1, 1b + ldr pc, [r1] + +/* + * Function to call when switching tasks to restore FP state + */ +ENTRY(fpe_restore) + ldr r1, 1b + 4 + ldr pc, [r1] + + + .data + +ENTRY(fp_enter) + .word SYMBOL_NAME(fpundefinstr) + .word SYMBOL_NAME(fpundefinstrsvc) + +ENTRY(fp_save) + .word .Lfpnull +ENTRY(fp_restore) + .word .Lfpnull + diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/head-armo.S linux/arch/arm/kernel/head-armo.S --- v2.1.79/linux/arch/arm/kernel/head-armo.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/head-armo.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,64 @@ +/* + * linux/arch/arm/kernel/head.S + * + * Copyright (C) 1994, 1995, 1996, 1997 Russell King + * + * 26-bit kernel startup code + */ +#include +#include + + .text + .align +/* + * Entry point. + */ +ENTRY(stext) +ENTRY(_stext) +__entry: cmp pc, #0x02000000 + ldrlt pc, LC1 @ if 0x01800000, call at 0x02080000 + teq r0, #0 @ Check for old calling method + blne Loldparams @ Move page if old + adr r5, LC0 + ldmia r5, {r5, r6, sl, sp} @ Setup stack + mov r4, #0 +1: cmp r5, sl @ Clear BSS + strcc r4, [r5], #4 + bcc 1b + mov r0, #0xea000000 @ Point undef instr to continuation + adr r5, Lcontinue - 12 + orr r5, r0, r5, lsr #2 + str r5, [r4, #4] + mov r2, r4 + ldr r5, Larm2_id + swp r0, r0, [r2] @ check for swp (ARM2 can't) + ldr r5, Larm250_id + mrc 15, 0, r0, c0, c0 @ check for CP#15 (ARM250 can't) + mov r5, r0 @ Use processor ID if we do have CP#15 +Lcontinue: str r5, [r6] + mov r5, #0xeb000000 @ Point undef instr vector to itself + sub r5, r5, #2 + str r5, [r4, #4] + mov fp, #0 + b SYMBOL_NAME(start_kernel) + +LC1: .word SYMBOL_NAME(_stext) +LC0: .word SYMBOL_NAME(_edata) + .word SYMBOL_NAME(arm_id) + .word SYMBOL_NAME(_end) + .word SYMBOL_NAME(init_task_union)+8192 +Larm2_id: .long 0x41560200 +Larm250_id: .long 0x41560250 + .align + +Loldparams: mov r4, #0x02000000 + add r3, r4, #0x00080000 + add r4, r4, #0x0007c000 +1: ldmia r0!, {r5 - r12} + stmia r4!, {r5 - r12} + cmp r4, r3 + blt 1b + movs pc, lr + + .align 13 +ENTRY(this_must_match_init_task) diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S --- v2.1.79/linux/arch/arm/kernel/head-armv.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/head-armv.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,312 @@ +/* + * linux/arch/arm/kernel/head32.S + * + * Copyright (C) 1994, 1995, 1996, 1997 Russell King + * + * Kernel 32 bit startup code for ARM6 / ARM7 / StrongARM + */ +#include +#include + .text + .align + + .globl SYMBOL_NAME(swapper_pg_dir) + .equ SYMBOL_NAME(swapper_pg_dir), 0xc0004000 + + .globl __stext +/* + * Entry point and restart point. Entry *must* be called with r0 == 0, + * MMU off. + * + * r1 = 0 -> ebsa (Ram @ 0x00000000) + * r1 = 1 -> RPC (Ram @ 0x10000000) + * r1 = 2 -> ebsit (???) + * r1 = 3 -> nexuspci + */ +ENTRY(stext) +ENTRY(_stext) +__entry: + teq r0, #0 @ check for illegal entry... + bne .Lerror @ loop indefinitely + cmp r1, #4 @ Unknown machine architecture + bge .Lerror +@ +@ First thing to do is to get the page tables set up so that we can call the kernel +@ in the correct place. This is relocatable code... +@ + mrc p15, 0, r9, c0, c0 @ get Processor ID +@ +@ Read processor ID register (CP#15, CR0). +@ NOTE: ARM2 & ARM250 cause an undefined instruction exception... +@ Values are: +@ XX01XXXX = ARMv4 architecture (StrongARM) +@ XX00XXXX = ARMv3 architecture +@ 4156061X = ARM 610 +@ 4156030X = ARM 3 +@ 4156025X = ARM 250 +@ 4156020X = ARM 2 +@ + adr r10, .LCProcTypes +1: ldmia r10!, {r5, r6, r8} @ Get Set, Mask, MMU Flags + teq r5, #0 @ End of list? + beq .Lerror + eor r5, r5, r9 + tst r5, r6 + addne r10, r10, #8 + bne 1b + + adr r4, .LCMachTypes + add r4, r4, r1, lsl #4 + ldmia r4, {r4, r5, r6} @ r4 = page dir in physical ram + + mov r0, r4 + mov r1, #0 + add r2, r0, #0x4000 +1: str r1, [r0], #4 @ Clear page table + teq r0, r2 + bne 1b +@ +@ Add enough entries to allow the kernel to be called. +@ It will sort out the real mapping in paging_init +@ + add r0, r4, #0x3000 + mov r1, #0x0000000c @ SECT_CACHEABLE | SECT_BUFFERABLE + orr r1, r1, r8 + add r1, r1, r5 + str r1, [r0], #4 + add r1, r1, #1 << 20 + str r1, [r0], #4 + add r1, r1, #1 << 20 +@ +@ Map in IO space +@ + add r0, r4, #0x3800 + orr r1, r6, r8 + add r2, r0, #0x0800 +1: str r1, [r0], #4 + add r1, r1, #1 << 20 + teq r0, r2 + bne 1b +@ +@ Map in screen at 0x02000000 & SCREEN2_BASE +@ + teq r5, #0 + addne r0, r4, #0x80 @ 02000000 + movne r1, #0x02000000 + orrne r1, r1, r8 + strne r1, [r0] + addne r0, r4, #0x3600 @ d8000000 + strne r1, [r0] +@ +@ The following should work on both v3 and v4 implementations +@ + mov lr, pc + mov pc, r10 @ Call processor flush (returns ctrl reg) + adr r5, __entry + sub r10, r10, r5 @ Make r10 PIC + ldr lr, .Lbranch + mcr p15, 0, r0, c1, c0 @ Enable MMU & caches. In 3 instructions + @ we lose this page! + mov pc, lr + +.Lerror: mov r0, #0x02000000 + mov r1, #0x11 + orr r1, r1, r1, lsl #8 + orr r1, r1, r1, lsl #16 + str r1, [r0], #4 + str r1, [r0], #4 + str r1, [r0], #4 + str r1, [r0], #4 + b .Lerror + +.Lbranch: .long .Lalready_done_mmap @ Real address of routine + + @ EBSA (pg dir phys, phys ram start, phys i/o) +.LCMachTypes: .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 @ Address of page tables (physical) + .long 0 @ Address of RAM + .long 0xe0000000 @ I/O address + .long 0 + + @ RPC + .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x10000000 + .long 0x10000000 + .long 0x03000000 + .long 0 + + @ EBSIT ??? + .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + .long 0 + .long 0xe0000000 + .long 0 + + @ NexusPCI + .long SYMBOL_NAME(swapper_pg_dir) - 0xc0000000 + 0x40000000 + .long 0x40000000 + .long 0x10000000 + .long 0 + +.LCProcTypes: @ ARM6 / 610 + .long 0x41560600 + .long 0xffffff00 + .long 0x00000c12 + b .Larmv3_flush_early @ arm v3 flush & ctrl early setup + mov pc, lr + + @ ARM7 / 710 + .long 0x41007000 + .long 0xfffff000 + .long 0x00000c12 + b .Larmv3_flush_late @ arm v3 flush & ctrl late setup + mov pc, lr + + @ StrongARM + .long 0x4401a100 + .long 0xfffffff0 + .long 0x00000c02 + b .Larmv4_flush_early + b .Lsa_fastclock + + .long 0 + +.LC0: .long SYMBOL_NAME(_edata) + .long SYMBOL_NAME(arm_id) + .long SYMBOL_NAME(_end) + .long SYMBOL_NAME(init_task_union)+8192 + .align + +.Larmv3_flush_early: + mov r0, #0 + mcr p15, 0, r0, c7, c0 @ flush caches on v3 + mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mov r0, #0x3d @ ....S..DPWC.M + orr r0, r0, #0x100 + mov pc, lr + +.Larmv3_flush_late: + mov r0, #0 + mcr p15, 0, r0, c7, c0 @ flush caches on v3 + mcr p15, 0, r0, c5, c0 @ flush TLBs on v3 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mov r0, #0x7d @ ....S.LDPWC.M + orr r0, r0, #0x100 + mov pc, lr + +.Larmv4_flush_early: + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ flush I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ flush I,D TLBs on v4 + mcr p15, 0, r4, c2, c0 @ load page table pointer + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mrc p15, 0, r0, c1, c0 @ get control register v4 + bic r0, r0, #0x0e00 + bic r0, r0, #0x0002 + orr r0, r0, #0x003d @ I...S..DPWC.M + orr r0, r0, #0x1100 @ v4 supports separate I cache + mov pc, lr + +.Lsa_fastclock: mcr p15, 0, r4, c15, c1, 2 @ Enable clock switching + mov pc, lr + +.Lalready_done_mmap: + adr r5, __entry @ Add base back in + add r10, r10, r5 + adr r5, .LC0 + ldmia r5, {r5, r6, r8, sp} @ Setup stack + mov r4, #0 +1: cmp r5, r8 @ Clear BSS + strcc r4, [r5],#4 + bcc 1b + + str r9, [r6] @ Save processor ID + mov lr, pc + add pc, r10, #4 @ Call post-processor init + mov fp, #0 + b SYMBOL_NAME(start_kernel) + +#if 1 +/* + * Useful debugging routines + */ + .globl _printhex8 +_printhex8: mov r1, #8 + b printhex + + .globl _printhex4 +_printhex4: mov r1, #4 + b printhex + + .globl _printhex2 +_printhex2: mov r1, #2 +printhex: ldr r2, =hexbuf + add r3, r2, r1 + mov r1, #0 + strb r1, [r3] +1: and r1, r0, #15 + mov r0, r0, lsr #4 + cmp r1, #10 + addlt r1, r1, #'0' + addge r1, r1, #'a' - 10 + strb r1, [r3, #-1]! + teq r3, r2 + bne 1b + mov r0, r2 + + .globl _printascii +_printascii: +#ifdef CONFIG_ARCH_RPC + mov r3, #0xe0000000 + orr r3, r3, #0x00010000 + orr r3, r3, #0x00000fe0 +#else + mov r3, #0xf0000000 + orr r3, r3, #0x0be0 +#endif + b 3f +1: ldrb r2, [r3, #0x18] + tst r2, #0x10 + beq 1b + strb r1, [r3] +2: ldrb r2, [r3, #0x14] + and r2, r2, #0x60 + teq r2, #0x60 + bne 2b + teq r1, #'\n' + moveq r1, #'\r' + beq 1b +3: teq r0, #0 + ldrneb r1, [r0], #1 + teqne r1, #0 + bne 1b + mov pc, lr + + .ltorg + + .globl _printch +_printch: +#ifdef CONFIG_ARCH_RPC + mov r3, #0xe0000000 + orr r3, r3, #0x00010000 + orr r3, r3, #0x00000fe0 +#else + mov r3, #0xf0000000 + orr r3, r3, #0x0be0 +#endif + mov r1, r0 + mov r0, #0 + b 1b + + .bss +hexbuf: .space 16 + +#endif + + .text + .align 13 +ENTRY(this_must_match_init_task) diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/iic.c linux/arch/arm/kernel/iic.c --- v2.1.79/linux/arch/arm/kernel/iic.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/iic.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,160 @@ +/* + * linux/arch/arm/kernel/iic.c + * + * Copyright (C) 1995, 1996 Russell King + * + * IIC is used to get the current time from the CMOS rtc. + */ + +#include +#include +#include +#include + +/* + * if delay loop has been calibrated then us that, + * else use IOC timer 1. + */ +static void iic_delay (void) +{ + extern unsigned long loops_per_sec; + if (loops_per_sec != (1 << 12)) { + udelay(10); + return; + } else { + unsigned long flags; + save_flags_cli(flags); + + outb(254, IOC_T1LTCHL); + outb(255, IOC_T1LTCHH); + outb(0, IOC_T1GO); + outb(1<<6, IOC_IRQCLRA); /* clear T1 irq */ + outb(4, IOC_T1LTCHL); + outb(0, IOC_T1LTCHH); + outb(0, IOC_T1GO); + while ((inb(IOC_IRQSTATA) & (1<<6)) == 0); + restore_flags(flags); + } +} + +static inline void iic_start (void) +{ + unsigned char out; + + out = inb(IOC_CONTROL) | 0xc2; + + outb(out, IOC_CONTROL); + iic_delay(); + + outb(out ^ 1, IOC_CONTROL); + iic_delay(); +} + +static inline void iic_stop (void) +{ + unsigned char out; + + out = inb(IOC_CONTROL) | 0xc3; + + iic_delay(); + outb(out ^ 1, IOC_CONTROL); + + iic_delay(); + outb(out, IOC_CONTROL); +} + +static int iic_sendbyte (unsigned char b) +{ + unsigned char out, in; + int i; + + out = (inb(IOC_CONTROL) & 0xfc) | 0xc0; + + outb(out, IOC_CONTROL); + for (i = 7; i >= 0; i--) { + unsigned char c; + c = out | ((b & (1 << i)) ? 1 : 0); + + outb(c, IOC_CONTROL); + iic_delay(); + + outb(c | 2, IOC_CONTROL); + iic_delay(); + + outb(c, IOC_CONTROL); + } + outb(out | 1, IOC_CONTROL); + iic_delay(); + + outb(out | 3, IOC_CONTROL); + iic_delay(); + + in = inb(IOC_CONTROL) & 1; + + outb(out | 1, IOC_CONTROL); + iic_delay(); + + outb(out, IOC_CONTROL); + iic_delay(); + + if(in) { + printk("No acknowledge from RTC\n"); + return 1; + } else + return 0; +} + +static unsigned char iic_recvbyte (void) +{ + unsigned char out, in; + int i; + + out = (inb(IOC_CONTROL) & 0xfc) | 0xc0; + + outb(out, IOC_CONTROL); + in = 0; + for (i = 7; i >= 0; i--) { + outb(out | 1, IOC_CONTROL); + iic_delay(); + outb(out | 3, IOC_CONTROL); + iic_delay(); + in = (in << 1) | (inb(IOC_CONTROL) & 1); + outb(out | 1, IOC_CONTROL); + iic_delay(); + } + outb(out, IOC_CONTROL); + iic_delay(); + outb(out | 2, IOC_CONTROL); + iic_delay(); + + return in; +} + +void iic_control (unsigned char addr, unsigned char loc, unsigned char *buf, int len) +{ + iic_start(); + + if (iic_sendbyte(addr & 0xfe)) + goto error; + + if (iic_sendbyte(loc)) + goto error; + + if (addr & 1) { + int i; + + for (i = 0; i < len; i++) + if (iic_sendbyte (buf[i])) + break; + } else { + int i; + + iic_stop(); + iic_start(); + iic_sendbyte(addr|1); + for (i = 0; i < len; i++) + buf[i] = iic_recvbyte (); + } +error: + iic_stop(); +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/init_task.c linux/arch/arm/kernel/init_task.c --- v2.1.79/linux/arch/arm/kernel/init_task.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/init_task.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,23 @@ +#include +#include + +#include +#include + +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; +struct mm_struct init_mm = INIT_MM; + +/* + * Initial task structure. + * + * We need to make sure that this is 8192-byte aligned due to the + * way process stacks are handled. This is done by making sure + * the linker maps this in the .text segment right after head.S, + * and making head.S ensure the proper alignment. + * + * The things we do for performance.. + */ +union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK }; diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/ioport.c linux/arch/arm/kernel/ioport.c --- v2.1.79/linux/arch/arm/kernel/ioport.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/ioport.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,98 @@ +/* + * linux/arch/arm/kernel/ioport.c + * + * This contains the io-permission bitmap code - written by obz, with changes + * by Linus. + * + * Modifications for ARM processor Copyright (C) 1995, 1996 Russell King + */ + +#include +#include +#include +#include +#include + +/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ +asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) +{ + int mask; + unsigned long *bitmap_base = bitmap + (base >> 5); + unsigned short low_index = base & 0x1f; + int length = low_index + extent; + + if (low_index != 0) { + mask = (~0 << low_index); + if (length < 32) + mask &= ~(~0 << length); + if (new_value) + *bitmap_base++ |= mask; + else + *bitmap_base++ &= ~mask; + length -= 32; + } + + mask = (new_value ? ~0 : 0); + while (length >= 32) { + *bitmap_base++ = mask; + length -= 32; + } + + if (length > 0) { + mask = ~(~0 << length); + if (new_value) + *bitmap_base++ |= mask; + else + *bitmap_base++ &= ~mask; + } +} + +/* + * this changes the io permissions bitmap in the current task. + */ +asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) +{ + if (from + num <= from) + return -EINVAL; +#ifndef __arm__ + if (from + num > IO_BITMAP_SIZE*32) + return -EINVAL; +#endif + if (!suser()) + return -EPERM; + +#ifdef IODEBUG + printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off")); +#endif +#ifndef __arm__ + set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on); +#endif + return 0; +} + +unsigned int *stack; + +/* + * sys_iopl has to be used when you want to access the IO ports + * beyond the 0x3ff range: to get the full 65536 ports bitmapped + * you'd need 8kB of bitmaps/process, which is a bit excessive. + * + * Here we just change the eflags value on the stack: we allow + * only the super-user to do it. This depends on the stack-layout + * on system-call entry - see also fork() and the signal handling + * code. + */ +asmlinkage int sys_iopl(long ebx,long ecx,long edx, + long esi, long edi, long ebp, long eax, long ds, + long es, long fs, long gs, long orig_eax, + long eip,long cs,long eflags,long esp,long ss) +{ + unsigned int level = ebx; + + if (level > 3) + return -EINVAL; + if (!suser()) + return -EPERM; + *(&eflags) = (eflags & 0xffffcfff) | (level << 12); + return 0; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c --- v2.1.79/linux/arch/arm/kernel/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/irq.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,330 @@ +/* + * linux/arch/arm/kernel/irq.c + * + * Copyright (C) 1992 Linus Torvalds + * Modifications for ARM processor Copyright (C) 1995, 1996 Russell King. + * + * This file contains the code used by various IRQ handling routines: + * asking for different IRQ's should be done through these routines + * instead of just grabbing them. Thus setups with different IRQ numbers + * shouldn't result in any weird surprises, and installing new handlers + * should be easier. + */ + +/* + * IRQ's are in fact implemented a bit like signal handlers for the kernel. + * Naturally it's not a 1:1 relation, but there are similarities. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef __SMP_PROF__ +extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]; +#endif + +unsigned int local_irq_count[NR_CPUS]; +#ifdef __SMP__ +atomic_t __arm_bh_counter; +#else +int __arm_bh_counter; +#endif + +spinlock_t irq_controller_lock; + +#ifndef SMP +#define irq_enter(cpu, irq) (++local_irq_count[cpu]) +#define irq_exit(cpu, irq) (--local_irq_count[cpu]) +#else +#error SMP not supported +#endif + +void disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + spin_lock_irqsave(&irq_controller_lock, flags); +#ifdef cliIF + save_flags(flags); + cliIF(); +#endif + mask_irq(irq_nr); + spin_unlock_irqrestore(&irq_controller_lock, flags); +} + +void enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + spin_lock_irqsave(&irq_controller_lock, flags); +#ifdef cliIF + save_flags (flags); + cliIF(); +#endif + unmask_irq(irq_nr); + spin_unlock_irqrestore(&irq_controller_lock, flags); +} + +struct irqaction *irq_action[NR_IRQS]; + +/* + * Bitmask indicating valid interrupt numbers + */ +unsigned long validirqs[NR_IRQS / 32] = { + 0x003fffff, 0x000001ff, 0x000000ff, 0x00000000 +}; + +int get_irq_list(char *buf) +{ + int i; + struct irqaction * action; + char *p = buf; + + for (i = 0 ; i < NR_IRQS ; i++) { + action = irq_action[i]; + if (!action) + continue; + p += sprintf(p, "%3d: %10u %s", + i, kstat.interrupts[i], action->name); + for (action = action->next; action; action = action->next) { + p += sprintf(p, ", %s", action->name); + } + *p++ = '\n'; + } + return p - buf; +} + +/* + * do_IRQ handles all normal device IRQ's + */ +asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +{ + struct irqaction * action; + int status, cpu; + +#if defined(HAS_IOMD) || defined(HAS_IOC) + if (irq != IRQ_EXPANSIONCARD) +#endif + { + spin_lock(&irq_controller_lock); + mask_and_ack_irq(irq); + spin_unlock(&irq_controller_lock); + } + + cpu = smp_processor_id(); + irq_enter(cpu, irq); + kstat.interrupts[irq]++; + + /* Return with this interrupt masked if no action */ + status = 0; + action = *(irq + irq_action); + if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + + do { + status |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + __cli(); +#if defined(HAS_IOMD) || defined(HAS_IOC) + if (irq != IRQ_KEYBOARDTX && irq != IRQ_EXPANSIONCARD) +#endif + { + spin_lock(&irq_controller_lock); + unmask_irq(irq); + spin_unlock(&irq_controller_lock); + } + } + + irq_exit(cpu, irq); + /* + * This should be conditional: we should really get + * a return code from the irq handler to tell us + * whether the handler wants us to do software bottom + * half handling or not.. + * + * ** IMPORTANT NOTE: do_bottom_half() ENABLES IRQS!!! ** + * ** WE MUST DISABLE THEM AGAIN, ELSE IDE DISKS GO ** + * ** AWOL ** + */ + if (1) { + if (bh_active & bh_mask) + do_bottom_half(); + __cli(); + } +} + +#if defined(HAS_IOMD) || defined(HAS_IOC) +void do_ecard_IRQ(int irq, struct pt_regs *regs) +{ + struct irqaction * action; + + action = *(irq + irq_action); + if (action) { + do { + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + } else { + spin_lock(&irq_controller_lock); + mask_irq (irq); + spin_unlock(&irq_controller_lock); + } +} +#endif + +int setup_arm_irq(int irq, struct irqaction * new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + save_flags_cli(flags); + *p = new; + + if (!shared) { + spin_lock(&irq_controller_lock); + unmask_irq(irq); + spin_unlock(&irq_controller_lock); + } + restore_flags(flags); + return 0; +} + +/* + * Using "struct sigaction" is slightly silly, but there + * are historical reasons and it works well, so.. + */ +int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long irq_flags, const char * devname, void *dev_id) +{ + unsigned long retval; + struct irqaction *action; + + if (irq >= NR_IRQS || !(validirqs[irq >> 5] & (1 << (irq & 31)))) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irq_flags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_arm_irq(irq, action); + + if (retval) + kfree(action); + return retval; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction * action, **p; + unsigned long flags; + + if (irq >= NR_IRQS || !(validirqs[irq >> 5] & (1 << (irq & 31)))) { + printk(KERN_ERR "Trying to free IRQ%d\n",irq); +#ifdef CONFIG_DEBUG_ERRORS + __backtrace(); +#endif + return; + } + for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + save_flags_cli (flags); + *p = action->next; + restore_flags (flags); + kfree(action); + return; + } + printk(KERN_ERR "Trying to free free IRQ%d\n",irq); +#ifdef CONFIG_DEBUG_ERRORS + __backtrace(); +#endif +} + +unsigned long probe_irq_on (void) +{ + unsigned int i, irqs = 0; + unsigned long delay; + + /* first snaffle up any unassigned irqs */ + for (i = 15; i > 0; i--) { + if (!irq_action[i]) { + enable_irq(i); + irqs |= 1 << i; + } + } + + /* wait for spurious interrupts to mask themselves out again */ + for (delay = jiffies + HZ/10; delay > jiffies; ) + /* min 100ms delay */; + + /* now filter out any obviously spurious interrupts */ + return irqs & get_enabled_irqs(); +} + +int probe_irq_off (unsigned long irqs) +{ + unsigned int i; + + irqs &= ~get_enabled_irqs(); + if (!irqs) + return 0; + i = ffz (~irqs); + if (irqs != (irqs & (1 << i))) + i = -i; + return i; +} + +__initfunc(void init_IRQ(void)) +{ + irq_init_irq(); +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/oldlatches.c linux/arch/arm/kernel/oldlatches.c --- v2.1.79/linux/arch/arm/kernel/oldlatches.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/oldlatches.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,53 @@ +/* Support for the latches on the old Archimedes which control the floppy, + * hard disc and printer + * + * (c) David Alan Gilbert 1995/1996 + */ +#include + +#include +#include + +#ifdef LATCHAADDR +/* + * They are static so that everyone who accesses them has to go through here + */ +static unsigned char LatchACopy; + +/* newval=(oldval & ~mask)|newdata */ +void oldlatch_aupdate(unsigned char mask,unsigned char newdata) +{ + LatchACopy=(LatchACopy & ~mask)|newdata; + outb(LatchACopy, LATCHAADDR); +#ifdef DEBUG + printk("oldlatch_A:0x%2x\n",LatchACopy); +#endif + +} +#endif + +#ifdef LATCHBADDR +static unsigned char LatchBCopy; + +/* newval=(oldval & ~mask)|newdata */ +void oldlatch_bupdate(unsigned char mask,unsigned char newdata) +{ + LatchBCopy=(LatchBCopy & ~mask)|newdata; + outb(LatchBCopy, LATCHBADDR); +#ifdef DEBUG + printk("oldlatch_B:0x%2x\n",LatchBCopy); +#endif +} +#endif + +void oldlatch_init(void) +{ + printk("oldlatch: init\n"); +#ifdef LATCHAADDR + oldlatch_aupdate(0xff,0xff); +#endif +#ifdef LATCHBADDR + oldlatch_bupdate(0xff,0x8); /* Thats no FDC reset...*/ +#endif + return ; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c --- v2.1.79/linux/arch/arm/kernel/process.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/process.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,239 @@ +/* + * linux/arch/arm/kernel/process.c + * + * Copyright (C) 1996 Russell King - Converted to ARM. + * Origional Copyright (C) 1995 Linus Torvalds + */ + +/* + * This file handles the architecture-dependent parts of process handling.. + */ + +#define __KERNEL_SYSCALLS__ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern void fpe_save(struct fp_soft_struct *); +extern char *processor_modes[]; + +asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call"); + +static int hlt_counter=0; + +void disable_hlt(void) +{ + hlt_counter++; +} + +void enable_hlt(void) +{ + hlt_counter--; +} + +/* + * The idle loop on an arm.. + */ +asmlinkage int sys_idle(void) +{ + int ret = -EPERM; + + lock_kernel(); + if (current->pid != 0) + goto out; + /* endless idle loop with no priority at all */ + current->priority = -100; + for (;;) + { + if (!hlt_counter && !need_resched) + proc_idle (); + run_task_queue(&tq_scheduler); + schedule(); + } + ret = 0; +out: + unlock_kernel(); + return ret; +} + +__initfunc(void reboot_setup(char *str, int *ints)) +{ +} + +/* + * This routine reboots the machine by resetting the expansion cards via + * their loaders, turning off the processor cache (if ARM3), copying the + * first instruction of the ROM to 0, and executing it there. + */ +void machine_restart(char * __unused) +{ + proc_hard_reset (); + arch_hard_reset (); +} + +void machine_halt(void) +{ +} + +void machine_power_off(void) +{ +} + + +void show_regs(struct pt_regs * regs) +{ + unsigned long flags; + + flags = condition_codes(regs); + + printk("\n" + "pc : [<%08lx>]\n" + "lr : [<%08lx>]\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + instruction_pointer(regs), + regs->ARM_lr, regs->ARM_sp, + regs->ARM_ip, regs->ARM_fp); + printk( "r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, + regs->ARM_r8); + printk( "r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, + regs->ARM_r5, regs->ARM_r4); + printk( "r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, + regs->ARM_r1, regs->ARM_r0); + printk("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', + flags & CC_V_BIT ? 'V' : 'v'); + printk(" IRQs %s FIQs %s Mode %s\n", + interrupts_enabled(regs) ? "on" : "off", + fast_interrupts_enabled(regs) ? "on" : "off", + processor_modes[processor_mode(regs)]); +#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) +{ int ctrl, transbase, dac; + __asm__ ( +" mrc p15, 0, %0, c1, c0\n" +" mrc p15, 0, %1, c2, c0\n" +" mrc p15, 0, %2, c3, c0\n" + : "=r" (ctrl), "=r" (transbase), "=r" (dac)); + printk("Control: %04X Table: %08X DAC: %08X", + ctrl, transbase, dac); + } +#endif + printk ("Segment %s\n", get_fs() == get_ds() ? "kernel" : "user"); +} + +/* + * Free current thread data structures etc.. + */ +void exit_thread(void) +{ + if (last_task_used_math == current) + last_task_used_math = NULL; +} + +void flush_thread(void) +{ + int i; + + for (i = 0; i < 8; i++) + current->debugreg[i] = 0; + if (last_task_used_math == current) + last_task_used_math = NULL; + current->used_math = 0; + current->flags &= ~PF_USEDFPU; +} + +void release_thread(struct task_struct *dead_task) +{ +} + +int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, + struct task_struct * p, struct pt_regs * regs) +{ + struct pt_regs * childregs; + struct context_save_struct * save; + + childregs = ((struct pt_regs *)((unsigned long)p + 8192)) - 1; + *childregs = *regs; + childregs->ARM_r0 = 0; + + save = ((struct context_save_struct *)(childregs)) - 1; + copy_thread_css (save); + p->tss.save = save; + /* + * Save current math state in p->tss.fpe_save if not already there. + */ + if (last_task_used_math == current) + fpe_save (&p->tss.fpstate.soft); + + return 0; +} + +/* + * fill in the fpe structure for a core dump... + */ +int dump_fpu (struct pt_regs *regs, struct user_fp *fp) +{ + int fpvalid = 0; + + if (current->used_math) { + if (last_task_used_math == current) + fpe_save (¤t->tss.fpstate.soft); + + memcpy (fp, ¤t->tss.fpstate.soft, sizeof (fp)); + } + + return fpvalid; +} + +/* + * fill in the user structure for a core dump.. + */ +void dump_thread(struct pt_regs * regs, struct user * dump) +{ + int i; + + dump->magic = CMAGIC; + dump->start_code = current->mm->start_code; + dump->start_stack = regs->ARM_sp & ~(PAGE_SIZE - 1); + + dump->u_tsize = (current->mm->end_code - current->mm->start_code) >> PAGE_SHIFT; + dump->u_dsize = (current->mm->brk - current->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT; + dump->u_ssize = 0; + + for (i = 0; i < 8; i++) + dump->u_debugreg[i] = current->debugreg[i]; + + if (dump->start_stack < 0x04000000) + dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT; + + dump->regs = *regs; + dump->u_fpvalid = dump_fpu (regs, &dump->u_fp); +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c --- v2.1.79/linux/arch/arm/kernel/ptrace.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/ptrace.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,745 @@ +/* ptrace.c */ +/* By Ross Biro 1/23/92 */ +/* edited by Linus Torvalds */ +/* edited for ARM by Russell King */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * does not yet catch signals sent when the child dies. + * in exit.c or in signal.c. + */ + +/* + * Breakpoint SWI instruction: SWI &9F0001 + */ +#define BREAKINST 0xef9f0001 + +/* change a pid into a task struct. */ +static inline struct task_struct * get_task(int pid) +{ + int i; + + for (i = 1; i < NR_TASKS; i++) { + if (task[i] != NULL && (task[i]->pid == pid)) + return task[i]; + } + return NULL; +} + +/* + * this routine will get a word off of the processes privileged stack. + * the offset is how far from the base addr as stored in the TSS. + * this routine assumes that all the privileged stacks are in our + * data space. + */ +static inline long get_stack_long(struct task_struct *task, int offset) +{ + unsigned char *stack; + + stack = (unsigned char *)((unsigned long)task + 8192 - sizeof(struct pt_regs)); + stack += offset << 2; + return *(unsigned long *)stack; +} + +/* + * this routine will put a word on the processes privileged stack. + * the offset is how far from the base addr as stored in the TSS. + * this routine assumes that all the privileged stacks are in our + * data space. + */ +static inline long put_stack_long(struct task_struct *task, int offset, + unsigned long data) +{ + unsigned char *stack; + + stack = (unsigned char *)((unsigned long)task + 8192 - sizeof(struct pt_regs)); + stack += offset << 2; + *(unsigned long *) stack = data; + return 0; +} + +/* + * This routine gets a long from any process space by following the page + * tables. NOTE! You should check that the long isn't on a page boundary, + * and that it is in the task area before calling this: this routine does + * no checking. + */ +static unsigned long get_long(struct task_struct * tsk, + struct vm_area_struct * vma, unsigned long addr) +{ + pgd_t *pgdir; + pmd_t *pgmiddle; + pte_t *pgtable; + unsigned long page; + +repeat: + pgdir = pgd_offset(vma->vm_mm, addr); + if (pgd_none(*pgdir)) { + handle_mm_fault(tsk, vma, addr, 0); + goto repeat; + } + if (pgd_bad(*pgdir)) { + printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); + pgd_clear(pgdir); + return 0; + } + pgmiddle = pmd_offset(pgdir, addr); + if (pmd_none(*pgmiddle)) { + handle_mm_fault(tsk, vma, addr, 0); + goto repeat; + } + if (pmd_bad(*pgmiddle)) { + printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); + pmd_clear(pgmiddle); + return 0; + } + pgtable = pte_offset(pgmiddle, addr); + if (!pte_present(*pgtable)) { + handle_mm_fault(tsk, vma, addr, 0); + goto repeat; + } + page = pte_page(*pgtable); + + if(MAP_NR(page) >= max_mapnr) + return 0; + page += addr & ~PAGE_MASK; + return *(unsigned long *)page; +} + +/* + * This routine puts a long into any process space by following the page + * tables. NOTE! You should check that the long isn't on a page boundary, + * and that it is in the task area before calling this: this routine does + * no checking. + * + * Now keeps R/W state of the page so that a text page stays readonly + * even if a debugger scribbles breakpoints into it. -M.U- + */ +static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr, + unsigned long data) +{ + pgd_t *pgdir; + pmd_t *pgmiddle; + pte_t *pgtable; + unsigned long page; + +repeat: + pgdir = pgd_offset(vma->vm_mm, addr); + if (!pgd_present(*pgdir)) { + handle_mm_fault(tsk, vma, addr, 1); + goto repeat; + } + if (pgd_bad(*pgdir)) { + printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); + pgd_clear(pgdir); + return; + } + pgmiddle = pmd_offset(pgdir, addr); + if (pmd_none(*pgmiddle)) { + handle_mm_fault(tsk, vma, addr, 1); + goto repeat; + } + if (pmd_bad(*pgmiddle)) { + printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); + pmd_clear(pgmiddle); + return; + } + pgtable = pte_offset(pgmiddle, addr); + if (!pte_present(*pgtable)) { + handle_mm_fault(tsk, vma, addr, 1); + goto repeat; + } + page = pte_page(*pgtable); + if (!pte_write(*pgtable)) { + handle_mm_fault(tsk, vma, addr, 1); + goto repeat; + } + + if (MAP_NR(page) < max_mapnr) { + page += addr & ~PAGE_MASK; + *(unsigned long *)page = data; + __flush_entry_to_ram(page); + } + set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); + flush_tlb(); +} + +static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr) +{ + struct vm_area_struct * vma; + + addr &= PAGE_MASK; + vma = find_vma(tsk->mm,addr); + if (!vma) + return NULL; + if (vma->vm_start <= addr) + return vma; + if (!(vma->vm_flags & VM_GROWSDOWN)) + return NULL; + if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur) + return NULL; + vma->vm_offset -= vma->vm_start - addr; + vma->vm_start = addr; + return vma; +} + +/* + * This routine checks the page boundaries, and that the offset is + * within the task area. It then calls get_long() to read a long. + */ +static int read_long(struct task_struct * tsk, unsigned long addr, + unsigned long * result) +{ + struct vm_area_struct * vma = find_extend_vma(tsk, addr); + + if (!vma) + return -EIO; + if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { + unsigned long low,high; + struct vm_area_struct * vma_high = vma; + + if (addr + sizeof(long) >= vma->vm_end) { + vma_high = vma->vm_next; + if (!vma_high || vma_high->vm_start != vma->vm_end) + return -EIO; + } + low = get_long(tsk, vma, addr & ~(sizeof(long)-1)); + high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); + switch (addr & (sizeof(long)-1)) { + case 1: + low >>= 8; + low |= high << 24; + break; + case 2: + low >>= 16; + low |= high << 16; + break; + case 3: + low >>= 24; + low |= high << 8; + break; + } + *result = low; + } else + *result = get_long(tsk, vma, addr); + return 0; +} + +/* + * This routine checks the page boundaries, and that the offset is + * within the task area. It then calls put_long() to write a long. + */ +static int write_long(struct task_struct * tsk, unsigned long addr, + unsigned long data) +{ + struct vm_area_struct * vma = find_extend_vma(tsk, addr); + + if (!vma) + return -EIO; + if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { + unsigned long low,high; + struct vm_area_struct * vma_high = vma; + + if (addr + sizeof(long) >= vma->vm_end) { + vma_high = vma->vm_next; + if (!vma_high || vma_high->vm_start != vma->vm_end) + return -EIO; + } + low = get_long(tsk, vma, addr & ~(sizeof(long)-1)); + high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); + switch (addr & (sizeof(long)-1)) { + case 0: /* shouldn't happen, but safety first */ + low = data; + break; + case 1: + low &= 0x000000ff; + low |= data << 8; + high &= ~0xff; + high |= data >> 24; + break; + case 2: + low &= 0x0000ffff; + low |= data << 16; + high &= ~0xffff; + high |= data >> 16; + break; + case 3: + low &= 0x00ffffff; + low |= data << 24; + high &= ~0xffffff; + high |= data >> 8; + break; + } + put_long(tsk, vma, addr & ~(sizeof(long)-1),low); + put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high); + } else + put_long(tsk, vma, addr, data); + return 0; +} + +/* + * Get value of register `rn' (in the instruction) + */ +static unsigned long ptrace_getrn (struct task_struct *child, unsigned long insn) +{ + unsigned int reg = (insn >> 16) & 15; + unsigned long val; + + if (reg == 15) + val = pc_pointer (get_stack_long (child, reg)); + else + val = get_stack_long (child, reg); + +printk ("r%02d=%08lX ", reg, val); + return val; +} + +/* + * Get value of operand 2 (in an ALU instruction) + */ +static unsigned long ptrace_getaluop2 (struct task_struct *child, unsigned long insn) +{ + unsigned long val; + int shift; + int type; + +printk ("op2="); + if (insn & 1 << 25) { + val = insn & 255; + shift = (insn >> 8) & 15; + type = 3; +printk ("(imm)"); + } else { + val = get_stack_long (child, insn & 15); + + if (insn & (1 << 4)) + shift = (int)get_stack_long (child, (insn >> 8) & 15); + else + shift = (insn >> 7) & 31; + + type = (insn >> 5) & 3; +printk ("(r%02ld)", insn & 15); + } +printk ("sh%dx%d", type, shift); + switch (type) { + case 0: val <<= shift; break; + case 1: val >>= shift; break; + case 2: + val = (((signed long)val) >> shift); + break; + case 3: + __asm__ __volatile__("mov %0, %0, ror %1" : "=r" (val) : "0" (val), "r" (shift)); + break; + } +printk ("=%08lX ", val); + return val; +} + +/* + * Get value of operand 2 (in a LDR instruction) + */ +static unsigned long ptrace_getldrop2 (struct task_struct *child, unsigned long insn) +{ + unsigned long val; + int shift; + int type; + + val = get_stack_long (child, insn & 15); + shift = (insn >> 7) & 31; + type = (insn >> 5) & 3; + +printk ("op2=r%02ldsh%dx%d", insn & 15, shift, type); + switch (type) { + case 0: val <<= shift; break; + case 1: val >>= shift; break; + case 2: + val = (((signed long)val) >> shift); + break; + case 3: + __asm__ __volatile__("mov %0, %0, ror %1" : "=r" (val) : "0" (val), "r" (shift)); + break; + } +printk ("=%08lX ", val); + return val; +} +#undef pc_pointer +#define pc_pointer(x) ((x) & 0x03fffffc) +int ptrace_set_bpt (struct task_struct *child) +{ + unsigned long insn, pc, alt; + int i, nsaved = 0, res; + + pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/)); + + res = read_long (child, pc, &insn); + if (res < 0) + return res; + + child->debugreg[nsaved++] = alt = pc + 4; +printk ("ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc); + switch (insn & 0x0e100000) { + case 0x00000000: + case 0x00100000: + case 0x02000000: + case 0x02100000: /* data processing */ + printk ("data "); + switch (insn & 0x01e0f000) { + case 0x0000f000: + alt = ptrace_getrn(child, insn) & ptrace_getaluop2(child, insn); + break; + case 0x0020f000: + alt = ptrace_getrn(child, insn) ^ ptrace_getaluop2(child, insn); + break; + case 0x0040f000: + alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn); + break; + case 0x0060f000: + alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn); + break; + case 0x0080f000: + alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn); + break; + case 0x00a0f000: + alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn) + + (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0); + break; + case 0x00c0f000: + alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn) + + (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0); + break; + case 0x00e0f000: + alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn) + + (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0); + break; + case 0x0180f000: + alt = ptrace_getrn(child, insn) | ptrace_getaluop2(child, insn); + break; + case 0x01a0f000: + alt = ptrace_getaluop2(child, insn); + break; + case 0x01c0f000: + alt = ptrace_getrn(child, insn) & ~ptrace_getaluop2(child, insn); + break; + case 0x01e0f000: + alt = ~ptrace_getaluop2(child, insn); + break; + } + break; + + case 0x04100000: /* ldr */ + if ((insn & 0xf000) == 0xf000) { +printk ("ldr "); + alt = ptrace_getrn(child, insn); + if (insn & 1 << 24) { + if (insn & 1 << 23) + alt += ptrace_getldrop2 (child, insn); + else + alt -= ptrace_getldrop2 (child, insn); + } + if (read_long (child, alt, &alt) < 0) + alt = pc + 4; /* not valid */ + else + alt = pc_pointer (alt); + } + break; + + case 0x06100000: /* ldr imm */ + if ((insn & 0xf000) == 0xf000) { +printk ("ldrimm "); + alt = ptrace_getrn(child, insn); + if (insn & 1 << 24) { + if (insn & 1 << 23) + alt += insn & 0xfff; + else + alt -= insn & 0xfff; + } + if (read_long (child, alt, &alt) < 0) + alt = pc + 4; /* not valid */ + else + alt = pc_pointer (alt); + } + break; + + case 0x08100000: /* ldm */ + if (insn & (1 << 15)) { + unsigned long base; + int nr_regs; +printk ("ldm "); + + if (insn & (1 << 23)) { + nr_regs = insn & 65535; + + nr_regs = (nr_regs & 0x5555) + ((nr_regs & 0xaaaa) >> 1); + nr_regs = (nr_regs & 0x3333) + ((nr_regs & 0xcccc) >> 2); + nr_regs = (nr_regs & 0x0707) + ((nr_regs & 0x7070) >> 4); + nr_regs = (nr_regs & 0x000f) + ((nr_regs & 0x0f00) >> 8); + nr_regs <<= 2; + + if (!(insn & (1 << 24))) + nr_regs -= 4; + } else { + if (insn & (1 << 24)) + nr_regs = -4; + else + nr_regs = 0; + } + + base = ptrace_getrn (child, insn); + + if (read_long (child, base + nr_regs, &alt) < 0) + alt = pc + 4; /* not valid */ + else + alt = pc_pointer (alt); + break; + } + break; + + case 0x0a000000: + case 0x0a100000: { /* bl or b */ + signed long displ; +printk ("b/bl "); + /* It's a branch/branch link: instead of trying to + * figure out whether the branch will be taken or not, + * we'll put a breakpoint at either location. This is + * simpler, more reliable, and probably not a whole lot + * slower than the alternative approach of emulating the + * branch. + */ + displ = (insn & 0x00ffffff) << 8; + displ = (displ >> 6) + 8; + if (displ != 0 && displ != 4) + alt = pc + displ; + } + break; + } +printk ("=%08lX\n", alt); + if (alt != pc + 4) + child->debugreg[nsaved++] = alt; + + for (i = 0; i < nsaved; i++) { + res = read_long (child, child->debugreg[i], &insn); + if (res >= 0) { + child->debugreg[i + 2] = insn; + res = write_long (child, child->debugreg[i], BREAKINST); + } + if (res < 0) { + child->debugreg[4] = 0; + return res; + } + } + child->debugreg[4] = nsaved; + return 0; +} + +/* Ensure no single-step breakpoint is pending. Returns non-zero + * value if child was being single-stepped. + */ +int ptrace_cancel_bpt (struct task_struct *child) +{ + int i, nsaved = child->debugreg[4]; + + child->debugreg[4] = 0; + + if (nsaved > 2) { + printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); + nsaved = 2; + } + for (i = 0; i < nsaved; i++) + write_long (child, child->debugreg[i], child->debugreg[i + 2]); + return nsaved != 0; +} + +asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + int ret; + + lock_kernel(); + ret = -EPERM; + if (request == PTRACE_TRACEME) { + /* are we already being traced? */ + if (current->flags & PF_PTRACED) + goto out; + /* set the ptrace bit in the process flags. */ + current->flags |= PF_PTRACED; + ret = 0; + goto out; + } + if (pid == 1) /* you may not mess with init */ + goto out; + ret = -ESRCH; + if (!(child = get_task(pid))) + goto out; + ret = -EPERM; + if (request == PTRACE_ATTACH) { + if (child == current) + goto out; + if ((!child->dumpable || + (current->uid != child->euid) || + (current->uid != child->suid) || + (current->uid != child->uid) || + (current->gid != child->egid) || + (current->gid != child->sgid) || + (current->gid != child->gid)) && !suser()) + goto out; + /* the same process cannot be attached many times */ + if (child->flags & PF_PTRACED) + goto out; + child->flags |= PF_PTRACED; + if (child->p_pptr != current) { + REMOVE_LINKS(child); + child->p_pptr = current; + SET_LINKS(child); + } + send_sig(SIGSTOP, child, 1); + ret = 0; + goto out; + } + ret = -ESRCH; + if (!(child->flags & PF_PTRACED)) + goto out; + if (child->state != TASK_STOPPED) { + if (request != PTRACE_KILL) + goto out; + } + if (child->p_pptr != current) + goto out; + + switch (request) { + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned long tmp; + + ret = read_long(child, addr, &tmp); + if (ret >= 0) + ret = put_user(tmp, (unsigned long *)data); + goto out; + } + + case PTRACE_PEEKUSR: { /* read the word at location addr in the USER area. */ + unsigned long tmp; + + ret = -EIO; + if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + goto out; + + tmp = 0; /* Default return condition */ + if (addr < sizeof (struct pt_regs)) + tmp = get_stack_long(child, (int)addr >> 2); + ret = put_user(tmp, (unsigned long *)data); + goto out; + } + + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = write_long(child,addr,data); + goto out; + + case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + ret = -EIO; + if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + goto out; + + if (addr < sizeof (struct pt_regs)) + ret = put_stack_long(child, (int)addr >> 2, data); + goto out; + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: /* restart after signal. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + goto out; + if (request == PTRACE_SYSCALL) + child->flags |= PF_TRACESYS; + else + child->flags &= ~PF_TRACESYS; + child->exit_code = data; + wake_up_process (child); + /* make sure single-step breakpoint is gone. */ + ptrace_cancel_bpt (child); + ret = 0; + goto out; + + /* make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ + case PTRACE_KILL: + if (child->state == TASK_ZOMBIE) /* already dead */ + return 0; + wake_up_process (child); + child->exit_code = SIGKILL; + ptrace_cancel_bpt (child); + /* make sure single-step breakpoint is gone. */ + ptrace_cancel_bpt (child); + ret = 0; + goto out; + + case PTRACE_SINGLESTEP: /* execute single instruction. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + goto out; + child->debugreg[4] = -1; + child->flags &= ~PF_TRACESYS; + wake_up_process(child); + child->exit_code = data; + /* give it a chance to run. */ + ret = 0; + goto out; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + goto out; + child->flags &= ~(PF_PTRACED|PF_TRACESYS); + wake_up_process (child); + child->exit_code = data; + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + /* make sure single-step breakpoint is gone. */ + ptrace_cancel_bpt (child); + ret = 0; + goto out; + + default: + ret = -EIO; + goto out; + } +out: + unlock_kernel(); + return ret; +} + +asmlinkage void syscall_trace(void) +{ + if ((current->flags & (PF_PTRACED|PF_TRACESYS)) + != (PF_PTRACED|PF_TRACESYS)) + return; + current->exit_code = SIGTRAP; + current->state = TASK_STOPPED; + notify_parent(current, SIGCHLD); + schedule(); + /* + * this isn't the same as continuing with a signal, but it will do + * for normal use. strace only continues with a signal if the + * stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/setup-ebsa110.c linux/arch/arm/kernel/setup-ebsa110.c --- v2.1.79/linux/arch/arm/kernel/setup-ebsa110.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/setup-ebsa110.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,143 @@ +/* + * linux/arch/arm/kernel/setup-sa.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +/* + * This file obtains various parameters about the system that the kernel + * is running on. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef CONFIG_CMDLINE +#define CONFIG_CMDLINE "root=nfs rw console=ttyS1,38400n8" +#endif +#define MEM_SIZE (16*1024*1024) + +#define COMMAND_LINE_SIZE 256 + +unsigned char aux_device_present; +unsigned long arm_id; +extern int root_mountflags; +extern int _etext, _edata, _end; + +#ifdef CONFIG_BLK_DEV_RAM +extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ +extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ +extern int rd_image_start; /* starting block # of image */ + +static inline void setup_ramdisk (void) +{ + rd_image_start = 0; + rd_prompt = 1; + rd_doload = 1; +} +#else +#define setup_ramdisk() +#endif + +static char default_command_line[] = CONFIG_CMDLINE; +static char command_line[COMMAND_LINE_SIZE] = { 0, }; + char saved_command_line[COMMAND_LINE_SIZE]; + +struct processor processor; +extern const struct processor sa110_processor_functions; + +void setup_arch(char **cmdline_p, + unsigned long * memory_start_p, unsigned long * memory_end_p) +{ + unsigned long memory_start, memory_end; + char c = ' ', *to = command_line, *from; + int len = 0; + + memory_start = (unsigned long)&_end; + memory_end = 0xc0000000 + MEM_SIZE; + from = default_command_line; + + processor = sa110_processor_functions; + processor._proc_init (); + + ROOT_DEV = 0x00ff; + setup_ramdisk(); + + init_task.mm->start_code = TASK_SIZE; + init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext; + init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata; + init_task.mm->brk = TASK_SIZE + (unsigned long) &_end; + + /* Save unparsed command line copy for /proc/cmdline */ + memcpy(saved_command_line, from, COMMAND_LINE_SIZE); + saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; + + for (;;) { + if (c == ' ' && + from[0] == 'm' && + from[1] == 'e' && + from[2] == 'm' && + from[3] == '=') { + memory_end = simple_strtoul(from+4, &from, 0); + if ( *from == 'K' || *from == 'k' ) { + memory_end = memory_end << 10; + from++; + } else if ( *from == 'M' || *from == 'm' ) { + memory_end = memory_end << 20; + from++; + } + memory_end = memory_end + PAGE_OFFSET; + } + c = *from++; + if (!c) + break; + if (COMMAND_LINE_SIZE <= ++len) + break; + *to++ = c; + } + + *to = '\0'; + *cmdline_p = command_line; + *memory_start_p = memory_start; + *memory_end_p = memory_end; + strcpy (system_utsname.machine, "sa110"); +} + +int get_cpuinfo(char * buffer) +{ + int len; + + len = sprintf (buffer, "CPU:\n" + "Type\t\t: %s\n" + "Revision\t: %d\n" + "Manufacturer\t: %s\n" + "32bit modes\t: %s\n" + "BogoMips\t: %lu.%02lu\n", + "sa110", + (int)arm_id & 15, + "DEC", + "yes", + (loops_per_sec+2500) / 500000, + ((loops_per_sec+2500) / 5000) % 100); + return len; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c --- v2.1.79/linux/arch/arm/kernel/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/setup.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,292 @@ +/* + * linux/arch/arm/kernel/setup.c + * + * Copyright (C) 1995, 1996, 1997 Russell King + */ + +/* + * This file obtains various parameters about the system that the kernel + * is running on. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct drive_info_struct { char dummy[32]; } drive_info; +struct screen_info screen_info; +struct processor processor; +unsigned char aux_device_present; + +extern const struct processor arm2_processor_functions; +extern const struct processor arm250_processor_functions; +extern const struct processor arm3_processor_functions; +extern const struct processor arm6_processor_functions; +extern const struct processor arm7_processor_functions; +extern const struct processor sa110_processor_functions; + +struct armversions armidlist[] = { +#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) + { 0x41560200, 0xfffffff0, F_MEMC , "ARM/VLSI", "arm2" , &arm2_processor_functions }, + { 0x41560250, 0xfffffff0, F_MEMC , "ARM/VLSI", "arm250" , &arm250_processor_functions }, + { 0x41560300, 0xfffffff0, F_MEMC|F_CACHE, "ARM/VLSI", "arm3" , &arm3_processor_functions }, +#endif +#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) + { 0x41560600, 0xfffffff0, F_MMU|F_32BIT , "ARM/VLSI", "arm6" , &arm6_processor_functions }, + { 0x41560610, 0xfffffff0, F_MMU|F_32BIT , "ARM/VLSI", "arm610" , &arm6_processor_functions }, + { 0x41007000, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI", "arm7" , &arm7_processor_functions }, + { 0x41007100, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI", "arm710" , &arm7_processor_functions }, + { 0x4401a100, 0xfffffff0, F_MMU|F_32BIT , "DEC", "sa110" , &sa110_processor_functions }, +#endif + { 0x00000000, 0x00000000, 0 , "***", "*unknown*" , NULL } +}; + +static struct param_struct *params = (struct param_struct *)PARAMS_BASE; + +unsigned long arm_id; +unsigned int vram_half_sam; +int armidindex; +int ioebpresent; +int memc_ctrl_reg; +int number_ide_drives; +int number_mfm_drives; + +extern int bytes_per_char_h; +extern int bytes_per_char_v; +extern int root_mountflags; +extern int _etext, _edata, _end; +extern unsigned long real_end_mem; + +/*------------------------------------------------------------------------- + * Early initialisation routines for various configurable items in the + * kernel. Each one either supplies a setup_ function, or defines this + * symbol to be empty if not configured. + */ + +/* + * Risc-PC specific initialisation + */ +#ifdef CONFIG_ARCH_RPC + +extern void init_dram_banks(struct param_struct *params); + +static void setup_rpc (struct param_struct *params) +{ + init_dram_banks(params); + + switch (params->u1.s.pages_in_vram) { + case 256: + vram_half_sam = 1024; + break; + case 512: + default: + vram_half_sam = 2048; + } + + /* + * Set ROM speed to maximum + */ + outb (0x1d, IOMD_ROMCR0); +} +#else +#define setup_rpc(x) +#endif + +/* + * ram disk + */ +#ifdef CONFIG_BLK_DEV_RAM +extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ +extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ +extern int rd_image_start; /* starting block # of image */ + +static void setup_ramdisk (struct param_struct *params) +{ + rd_image_start = params->u1.s.rd_start; + rd_prompt = (params->u1.s.flags & FLAG_RDPROMPT) == 0; + rd_doload = (params->u1.s.flags & FLAG_RDLOAD) == 0; +} +#else +#define setup_ramdisk(p) +#endif + +/* + * initial ram disk + */ +#ifdef CONFIG_BLK_DEV_INITRD +static void setup_initrd (struct param_struct *params, unsigned long memory_end) +{ + initrd_start = params->u1.s.initrd_start; + initrd_end = params->u1.s.initrd_start + params->u1.s.initrd_size; + + if (initrd_end > memory_end) { + printk ("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx) - disabling initrd\n", + initrd_end, memory_end); + initrd_start = 0; + } +} +#else +#define setup_initrd(p,m) +#endif + +static inline void check_ioeb_present(void) +{ + if (((*IOEB_BASE) & 15) == 5) + armidlist[armidindex].features |= F_IOEB; +} + +static void get_processor_type (void) +{ + for (armidindex = 0; ; armidindex ++) + if (!((armidlist[armidindex].id ^ arm_id) & + armidlist[armidindex].mask)) + break; + + if (armidlist[armidindex].id == 0) { + int i; + + for (i = 0; i < 3200; i++) + ((unsigned long *)SCREEN2_BASE)[i] = 0x77113322; + + while (1); + } + processor = *armidlist[armidindex].proc; +} + +#define COMMAND_LINE_SIZE 256 + +static char command_line[COMMAND_LINE_SIZE] = { 0, }; + char saved_command_line[COMMAND_LINE_SIZE]; + +void setup_arch(char **cmdline_p, + unsigned long * memory_start_p, unsigned long * memory_end_p) +{ + static unsigned char smptrap; + unsigned long memory_start, memory_end; + char c = ' ', *to = command_line, *from; + int len = 0; + + if (smptrap == 1) + return; + smptrap = 1; + + get_processor_type (); + check_ioeb_present (); + processor._proc_init (); + + bytes_per_char_h = params->u1.s.bytes_per_char_h; + bytes_per_char_v = params->u1.s.bytes_per_char_v; + from = params->commandline; + ROOT_DEV = to_kdev_t (params->u1.s.rootdev); + ORIG_X = params->u1.s.video_x; + ORIG_Y = params->u1.s.video_y; + ORIG_VIDEO_COLS = params->u1.s.video_num_cols; + ORIG_VIDEO_LINES = params->u1.s.video_num_rows; + memc_ctrl_reg = params->u1.s.memc_control_reg; + number_ide_drives = (params->u1.s.adfsdrives >> 6) & 3; + number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3; + + setup_rpc (params); + setup_ramdisk (params); + + if (!(params->u1.s.flags & FLAG_READONLY)) + root_mountflags &= ~MS_RDONLY; + + memory_start = MAPTOPHYS((unsigned long)&_end); + memory_end = GET_MEMORY_END(params); + + init_task.mm->start_code = TASK_SIZE; + init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext; + init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata; + init_task.mm->brk = TASK_SIZE + (unsigned long) &_end; + + /* Save unparsed command line copy for /proc/cmdline */ + memcpy(saved_command_line, from, COMMAND_LINE_SIZE); + saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; + + for (;;) { + if (c == ' ' && + from[0] == 'm' && + from[1] == 'e' && + from[2] == 'm' && + from[3] == '=') { + memory_end = simple_strtoul(from+4, &from, 0); + if (*from == 'K' || *from == 'k') { + memory_end = memory_end << 10; + from++; + } else if (*from == 'M' || *from == 'm') { + memory_end = memory_end << 20; + from++; + } + memory_end = memory_end + PAGE_OFFSET; + } + c = *from++; + if (!c) + break; + if (COMMAND_LINE_SIZE <= ++len) + break; + *to++ = c; + } + + *to = '\0'; + *cmdline_p = command_line; + *memory_start_p = memory_start; + *memory_end_p = memory_end; + + setup_initrd (params, memory_end); + + strcpy (system_utsname.machine, armidlist[armidindex].name); +} + +#define ISSET(bit) (armidlist[armidindex].features & bit) + +int get_cpuinfo(char * buffer) +{ + int len; + + len = sprintf (buffer, "CPU:\n" + "Type\t\t: %s\n" + "Revision\t: %d\n" + "Manufacturer\t: %s\n" + "32bit modes\t: %s\n" + "BogoMips\t: %lu.%02lu\n", + armidlist[armidindex].name, + (int)arm_id & 15, + armidlist[armidindex].manu, + ISSET (F_32BIT) ? "yes" : "no", + (loops_per_sec+2500) / 500000, + ((loops_per_sec+2500) / 5000) % 100); + len += sprintf (buffer + len, + "\nHardware:\n" + "Mem System\t: %s\n" + "IOEB\t\t: %s\n", + ISSET(F_MEMC) ? "MEMC" : + ISSET(F_MMU) ? "MMU" : "*unknown*", + ISSET(F_IOEB) ? "present" : "absent" + ); + return len; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c --- v2.1.79/linux/arch/arm/kernel/signal.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/signal.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,514 @@ +/* + * linux/arch/arm/kernel/signal.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)) +#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)) + +asmlinkage int sys_wait4(pid_t pid, unsigned long * stat_addr, + int options, unsigned long *ru); +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs); +extern int ptrace_cancel_bpt (struct task_struct *); +extern int ptrace_set_bpt (struct task_struct *); + +/* + * atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs) +{ + + sigset_t saveset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + regs->ARM_r0 = -EINTR; + + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&saveset, regs)) + return regs->ARM_r0; + } +} + +asmlinkage int +sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs) +{ + sigset_t saveset, newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); + + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + current->blocked = newset; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + regs->ARM_r0 = -EINTR; + + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&saveset, regs)) + return regs->ARM_r0; + } +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +/* + * Do a signal return; undo the signal stack. + */ +struct sigframe +{ + struct sigcontext sc; + unsigned long extramask[_NSIG_WORDS-1]; + unsigned long retcode; +}; + +struct rt_sigframe +{ + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + unsigned long retcode; +}; + +static int +restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +{ + __get_user(regs->ARM_r0, &sc->arm_r0); + __get_user(regs->ARM_r1, &sc->arm_r1); + __get_user(regs->ARM_r2, &sc->arm_r2); + __get_user(regs->ARM_r3, &sc->arm_r3); + __get_user(regs->ARM_r4, &sc->arm_r4); + __get_user(regs->ARM_r5, &sc->arm_r5); + __get_user(regs->ARM_r6, &sc->arm_r6); + __get_user(regs->ARM_r7, &sc->arm_r7); + __get_user(regs->ARM_r8, &sc->arm_r8); + __get_user(regs->ARM_r9, &sc->arm_r9); + __get_user(regs->ARM_r10, &sc->arm_r10); + __get_user(regs->ARM_fp, &sc->arm_fp); + __get_user(regs->ARM_ip, &sc->arm_ip); + __get_user(regs->ARM_sp, &sc->arm_sp); + __get_user(regs->ARM_lr, &sc->arm_lr); + __get_user(regs->ARM_pc, &sc->arm_pc); /* security! */ +#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) + __get_user(regs->ARM_cpsr, &sc->arm_cpsr); /* security! */ +#endif + + /* send SIGTRAP if we're single-stepping */ + if (ptrace_cancel_bpt (current)) + send_sig (SIGTRAP, current, 1); + + return regs->ARM_r0; +} + +asmlinkage int sys_sigreturn(struct pt_regs *regs) +{ + struct sigframe *frame; + sigset_t set; + + frame = (struct sigframe *)regs->ARM_sp; + + if (verify_area(VERIFY_READ, frame, sizeof (*frame))) + goto badframe; + if (__get_user(set.sig[0], &frame->sc.oldmask) + || (_NSIG_WORDS > 1 + && __copy_from_user(&set.sig[1], &frame->extramask, + sizeof(frame->extramask)))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + return restore_sigcontext(regs, &frame->sc); + +badframe: + lock_kernel(); + do_exit(SIGSEGV); +} + +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) +{ + struct rt_sigframe *frame; + sigset_t set; + + frame = (struct rt_sigframe *)regs->ARM_sp; + + if (verify_area(VERIFY_READ, frame, sizeof (*frame))) + goto badframe; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + return restore_sigcontext(regs, &frame->uc.uc_mcontext); + +badframe: + lock_kernel(); + do_exit(SIGSEGV); +} + +static void +setup_sigcontext(struct sigcontext *sc, /*struct _fpstate *fpstate,*/ + struct pt_regs *regs, unsigned long mask) +{ + __put_user (regs->ARM_r0, &sc->arm_r0); + __put_user (regs->ARM_r1, &sc->arm_r1); + __put_user (regs->ARM_r2, &sc->arm_r2); + __put_user (regs->ARM_r3, &sc->arm_r3); + __put_user (regs->ARM_r4, &sc->arm_r4); + __put_user (regs->ARM_r5, &sc->arm_r5); + __put_user (regs->ARM_r6, &sc->arm_r6); + __put_user (regs->ARM_r7, &sc->arm_r7); + __put_user (regs->ARM_r8, &sc->arm_r8); + __put_user (regs->ARM_r9, &sc->arm_r9); + __put_user (regs->ARM_r10, &sc->arm_r10); + __put_user (regs->ARM_fp, &sc->arm_fp); + __put_user (regs->ARM_ip, &sc->arm_ip); + __put_user (regs->ARM_sp, &sc->arm_sp); + __put_user (regs->ARM_lr, &sc->arm_lr); + __put_user (regs->ARM_pc, &sc->arm_pc); /* security! */ +#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110) + __put_user (regs->ARM_cpsr, &sc->arm_cpsr); /* security! */ +#endif + + __put_user (current->tss.trap_no, &sc->trap_no); + __put_user (current->tss.error_code, &sc->error_code); + __put_user (mask, &sc->oldmask); +} + +static void setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs) +{ + struct sigframe *frame; + unsigned long retcode; + + frame = (struct sigframe *)regs->ARM_sp - 1; + + if (!access_ok(VERIFT_WRITE, frame, sizeof (*frame))) + goto segv_and_exit; + + setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]); + + if (_NSIG_WORDS > 1) { + __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + } + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + retcode = (unsigned long)ka->sa.sa_restorer; /* security! */ + } else { + retcode = (unsigned long)&frame->retcode; + __put_user(SWI_SYS_SIGRETURN, &frame->retcode); + __flush_entry_to_ram (&frame->retcode); + } + + if (current->exec_domain && current->exec_domain->signal_invmap && sig < 32) + regs->ARM_r0 = current->exec_domain->signal_invmap[sig]; + else + regs->ARM_r0 = sig; + regs->ARM_sp = (unsigned long)frame; + regs->ARM_lr = retcode; + regs->ARM_pc = (unsigned long)ka->sa.sa_handler; /* security! */ + return; + +segv_and_exit: + lock_kernel(); + do_exit (SIGSEGV); +} + +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + struct rt_sigframe *frame; + unsigned long retcode; + + frame = (struct rt_sigframe *)regs->ARM_sp - 1; + if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) + goto segv_and_exit; + + __put_user(&frame->info, &frame->pinfo); + __put_user(&frame->uc, &frame->puc); + __copy_to_user(&frame->info, info, sizeof(*info)); + + /* Clear all the bits of the ucontext we don't use. */ + __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); + + setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ + regs, set->sig[0]); + __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + retcode = (unsigned long)ka->sa.sa_restorer; /* security! */ + } else { + retcode = (unsigned long)&frame->retcode; + __put_user(SWI_SYS_RT_SIGRETURN, &frame->retcode); + __flush_entry_to_ram (&frame->retcode); + } + + if (current->exec_domain && current->exec_domain->signal_invmap && sig < 32) + regs->ARM_r0 = current->exec_domain->signal_invmap[sig]; + else + regs->ARM_r0 = sig; + regs->ARM_sp = (unsigned long)frame; + regs->ARM_lr = retcode; + regs->ARM_pc = (unsigned long)ka->sa.sa_handler; /* security! */ + return; + +segv_and_exit: + lock_kernel(); + do_exit (SIGSEGV); +} + +/* + * OK, we're invoking a handler + */ +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +{ + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs); + else + setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sigmask_lock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals that + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) +{ + unsigned long instr, *pc = (unsigned long *)(instruction_pointer(regs)-4); + struct k_sigaction *ka; + siginfo_t info; + int single_stepping, swi_instr; + + if (!oldset) + oldset = ¤t->blocked; + + single_stepping = ptrace_cancel_bpt (current); + swi_instr = (!get_user (instr, pc) && (instr & 0x0f000000) == 0x0f000000); + + for (;;) { + unsigned long signr; + + spin_lock_irq (¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq (¤t->sigmask_lock); + + if (!signr) + break; + + if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ + current->exit_code = signr; + current->state = TASK_STOPPED; + notify_parent(current, SIGCHLD); + schedule(); + single_stepping |= ptrace_cancel_bpt (current); + + /* We're back. Did the debugger cancel the sig? */ + if (!(signr = current->exit_code)) + continue; + current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ + if (signr == SIGSTOP) + continue; + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); + continue; + } + } + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { + if (signr != SIGCHLD) + continue; + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) + /* nothing */; + continue; + } + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ + if (current->pid == 1) + continue; + + switch (signr) { + case SIGCONT: case SIGCHLD: case SIGWINCH: + continue; + + case SIGTSTP: case SIGTTIN: case SIGTTOU: + if (is_orphaned_pgrp(current->pgrp)) + continue; + /* FALLTHRU */ + + case SIGSTOP: + current->state = TASK_STOPPED; + current->exit_code = signr; + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + notify_parent(current, SIGCHLD); + schedule(); + continue; + + case SIGQUIT: case SIGILL: case SIGTRAP: + case SIGABRT: case SIGFPE: case SIGSEGV: + lock_kernel(); + if (current->binfmt + && current->binfmt->core_dump + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; + unlock_kernel(); + /* FALLTHRU */ + + default: + lock_kernel(); + sigaddset(¤t->signal, signr); + current->flags |= PF_SIGNALED; + do_exit(exit_code); + /* NOTREACHED */ + } + } + + /* Are we from a system call? */ + if (swi_instr) { + switch (regs->ARM_r0) { + case -ERESTARTNOHAND: + regs->ARM_r0 = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->ARM_r0 = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + regs->ARM_r0 = regs->ARM_ORIG_r0; + regs->ARM_pc -= 4; + } + } + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); + if (single_stepping) + ptrace_set_bpt (current); + return 1; + } + + if (swi_instr && + (regs->ARM_r0 == -ERESTARTNOHAND || + regs->ARM_r0 == -ERESTARTSYS || + regs->ARM_r0 == -ERESTARTNOINTR)) { + regs->ARM_r0 = regs->ARM_ORIG_r0; + regs->ARM_pc -= 4; + } + if (single_stepping) + ptrace_set_bpt (current); + return 0; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c --- v2.1.79/linux/arch/arm/kernel/sys_arm.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/sys_arm.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,372 @@ +/* + * linux/arch/arm/kernel/sys_arm.c + * + * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c + * Copyright (C) 1995, 1996 Russell King. + * + * This file contains various random system calls that + * have a non-standard calling sequence on the Linux/arm + * platform. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Constant strings used in inlined functions in header files + */ +/* proc/system.h */ +const char xchg_str[] = "xchg"; +/* arch/dma.h */ +const char dma_str[] = "%s: dma %d not supported\n"; + +/* + * sys_pipe() is the normal C calling standard for creating + * a pipe. It's not the way unix traditionally does this, though. + */ +asmlinkage int sys_pipe(unsigned long * fildes) +{ + int fd[2]; + int error; + + lock_kernel(); + error = do_pipe(fd); + unlock_kernel(); + if (!error) { + if (copy_to_user(fildes, fd, 2*sizeof(int))) + error = -EFAULT; + } + return error; +} + +/* + * Perform the select(nd, in, out, ex, tv) and mmap() system + * calls. ARM Linux didn't use to be able to handle more than + * 4 system call parameters, so these system calls used a memory + * block for parameter passing.. + */ + +struct mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +asmlinkage int old_mmap(struct mmap_arg_struct *arg) +{ + int error = -EFAULT; + struct file * file = NULL; + struct mmap_arg_struct a; + + lock_kernel(); + if (copy_from_user(&a, arg, sizeof(a))) + goto out; + if (!(a.flags & MAP_ANONYMOUS)) { + error = -EBADF; + if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd])) + goto out; + } + a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); +out: + unlock_kernel(); + return error; +} + + +extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); + +struct sel_arg_struct { + unsigned long n; + fd_set *inp, *outp, *exp; + struct timeval *tvp; +}; + +asmlinkage int old_select(struct sel_arg_struct *arg) +{ + struct sel_arg_struct a; + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; + /* sys_select() does the appropriate kernel locking */ + return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); +} + +/* + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. + */ +asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) +{ + int version, ret; + + lock_kernel(); + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; + + if (call <= SEMCTL) + switch (call) { + case SEMOP: + ret = sys_semop (first, (struct sembuf *)ptr, second); + goto out; + case SEMGET: + ret = sys_semget (first, second, third); + goto out; + case SEMCTL: { + union semun fourth; + ret = -EINVAL; + if (!ptr) + goto out; + ret = -EFAULT; + if (get_user(fourth.__pad, (void **) ptr)) + goto out; + ret = sys_semctl (first, second, third, fourth); + goto out; + } + default: + ret = -EINVAL; + goto out; + } + if (call <= MSGCTL) + switch (call) { + case MSGSND: + ret = sys_msgsnd (first, (struct msgbuf *) ptr, + second, third); + goto out; + case MSGRCV: + switch (version) { + case 0: { + struct ipc_kludge tmp; + ret = -EINVAL; + if (!ptr) + goto out; + ret = -EFAULT; + if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, + sizeof (tmp))) + goto out; + ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); + goto out; + } + case 1: default: + ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); + goto out; + } + case MSGGET: + ret = sys_msgget ((key_t) first, second); + goto out; + case MSGCTL: + ret = sys_msgctl (first, second, (struct msqid_ds *) ptr); + goto out; + default: + ret = -EINVAL; + goto out; + } + if (call <= SHMCTL) + switch (call) { + case SHMAT: + switch (version) { + case 0: default: { + ulong raddr; + ret = sys_shmat (first, (char *) ptr, second, &raddr); + if (ret) + goto out; + ret = put_user (raddr, (ulong *) third); + goto out; + } + case 1: /* iBCS2 emulator entry point */ + ret = -EINVAL; + if (!segment_eq(get_fs(), get_ds())) + goto out; + ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); + goto out; + } + case SHMDT: + ret = sys_shmdt ((char *)ptr); + goto out; + case SHMGET: + ret = sys_shmget (first, second, third); + goto out; + case SHMCTL: + ret = sys_shmctl (first, second, (struct shmid_ds *) ptr); + goto out; + default: + ret = -EINVAL; + goto out; + } + else + ret = -EINVAL; +out: + unlock_kernel(); + return ret; +} + +/* Fork a new task - this creates a new program thread. + * This is called indirectly via a small wrapper + */ +asmlinkage int sys_fork(struct pt_regs *regs) +{ + int ret; + + lock_kernel(); + ret = do_fork(SIGCHLD, regs->ARM_sp, regs); + unlock_kernel(); + + return ret; +} + +/* Clone a task - this clones the calling program thread. + * This is called indirectly via a small wrapper + */ +asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs) +{ + int ret; + + lock_kernel(); + if (!newsp) + newsp = regs->ARM_sp; + + ret = do_fork(clone_flags, newsp, regs); + unlock_kernel(); + return ret; +} + +/* sys_execve() executes a new program. + * This is called indirectly via a small wrapper + */ +asmlinkage int sys_execve(char *filenamei, char **argv, char **envp, struct pt_regs *regs) +{ + int error; + char * filename; + + lock_kernel(); + filename = getname(filenamei); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename, argv, envp, regs); + putname(filename); +out: + unlock_kernel(); + return error; +} + +/* + * Detect the old function calling standard + */ +static inline unsigned long old_calling_standard (struct pt_regs *regs) +{ + unsigned long instr, *pcv = (unsigned long *)(instruction_pointer(regs) - 8); + return (!get_user (instr, pcv) && instr == 0xe1a0300d); +} + +/* Compatability functions - we used to pass 5 parameters as r0, r1, r2, *r3, *(r3+4) + * We now use r0 - r4, and return an error if the old style calling standard is used. + * Eventually these functions will disappear. + */ +asmlinkage int +sys_compat_llseek (unsigned int fd, unsigned long offset_high, unsigned long offset_low, + loff_t *result, unsigned int origin, struct pt_regs *regs) +{ + extern int sys_llseek (unsigned int, unsigned long, unsigned long, loff_t *, unsigned int); + + if (old_calling_standard (regs)) { + printk (KERN_NOTICE "%s (%d): unsupported llseek call standard\n", + current->comm, current->pid); + return -EINVAL; + } + return sys_llseek (fd, offset_high, offset_low, result, origin); +} + +asmlinkage int +sys_compat_mount (char *devname, char *dirname, char *type, unsigned long flags, void *data, + struct pt_regs *regs) +{ + extern int sys_mount (char *, char *, char *, unsigned long, void *); + + if (old_calling_standard (regs)) { + printk (KERN_NOTICE "%s (%d): unsupported mount call standard\n", + current->comm, current->pid); + return -EINVAL; + } + return sys_mount (devname, dirname, type, flags, data); +} + +asmlinkage int sys_uname (struct old_utsname * name) +{ + static int warned = 0; + + if (warned == 0) { + warned ++; + printk (KERN_NOTICE "%s (%d): obsolete uname call\n", + current->comm, current->pid); + } + + if (name && !copy_to_user (name, &system_utsname, sizeof (*name))) + return 0; + return -EFAULT; +} + +asmlinkage int sys_olduname(struct oldold_utsname * name) +{ + int error; + static int warned = 0; + + if (warned == 0) { + warned ++; + printk (KERN_NOTICE "%s (%d): obsolete olduname call\n", + current->comm, current->pid); + } + + if (!name) + return -EFAULT; + + if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) + return -EFAULT; + + error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); + error -= __put_user(0,name->sysname+__OLD_UTS_LEN); + error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); + error -= __put_user(0,name->nodename+__OLD_UTS_LEN); + error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); + error -= __put_user(0,name->release+__OLD_UTS_LEN); + error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); + error -= __put_user(0,name->version+__OLD_UTS_LEN); + error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); + error -= __put_user(0,name->machine+__OLD_UTS_LEN); + error = error ? -EFAULT : 0; + + return error; +} + +asmlinkage int sys_pause(void) +{ + static int warned = 0; + + if (warned == 0) { + warned ++; + printk (KERN_NOTICE "%s (%d): obsolete pause call\n", + current->comm, current->pid); + } + + current->state = TASK_INTERRUPTIBLE; + schedule(); + return -ERESTARTNOHAND; +} + diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c --- v2.1.79/linux/arch/arm/kernel/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/time.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,154 @@ +/* + * linux/arch/arm/kernel/time.c + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King + * + * This file contains the ARM-specific time handling details: + * reading the RTC at bootup, etc... + * + * 1994-07-02 Alan Modra + * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime + * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +extern int setup_arm_irq(int, struct irqaction *); +extern volatile unsigned long lost_ticks; + +/* change this if you have some constant time drift */ +#define USECS_PER_JIFFY (1000000/HZ) + +#ifndef BCD_TO_BIN +#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) +#endif + +#ifndef BIN_TO_BCD +#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) +#endif + +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines were long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +static inline unsigned long mktime(unsigned int year, unsigned int mon, + unsigned int day, unsigned int hour, + unsigned int min, unsigned int sec) +{ + if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + return ((( + (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) + + year*365 - 719499 + )*24 + hour /* now have hours */ + )*60 + min /* now have minutes */ + )*60 + sec; /* finally seconds */ +} + +#include + +static unsigned long do_gettimeoffset(void) +{ + return gettimeoffset (); +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + save_flags_cli (flags); + *tv = xtime; + tv->tv_usec += do_gettimeoffset(); + + /* + * xtime is atomically updated in timer_bh. lost_ticks is + * nonzero if the tiemr bottom half hasnt executed yet. + */ + if (lost_ticks) + tv->tv_usec += USECS_PER_JIFFY; + + restore_flags(flags); + + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } +} + +void do_settimeofday(struct timeval *tv) +{ + cli (); + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + + if (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime = *tv; + time_state = TIME_BAD; + time_maxerror = MAXPHASE; + time_esterror = MAXPHASE; + sti (); +} + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick. + */ +static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (reset_timer ()) + do_timer(regs); + + update_rtc (); +} + +static struct irqaction irqtimer0 = { timer_interrupt, 0, 0, "timer", NULL, NULL}; + +void time_init(void) +{ + xtime.tv_sec = setup_timer(); + xtime.tv_usec = 0; + + setup_arm_irq(IRQ_TIMER0, &irqtimer0); +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.1.79/linux/arch/arm/kernel/traps.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/kernel/traps.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,306 @@ +/* + * linux/arch/arm/kernel/traps.c + * + * Copyright (C) 1995, 1996 Russell King + * Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds + */ + +/* + * 'traps.c' handles hardware exceptions after we have saved some state in + * 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably + * kill the offending process. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern void fpe_save(struct fp_soft_struct *); +extern void fpe_restore(struct fp_soft_struct *); +extern void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret); +extern void c_backtrace (unsigned long fp, int pmode); +extern int ptrace_cancel_bpt (struct task_struct *); + +char *processor_modes[]= +{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , + "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", + "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , + "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" +}; + +static char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; + +static inline void console_verbose(void) +{ + extern int console_loglevel; + console_loglevel = 15; +} + +int kstack_depth_to_print = 200; + +static int verify_stack_pointer (unsigned long stackptr, int size) +{ +#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) + if (stackptr < 0x02048000 || stackptr + size > 0x03000000) + return -EFAULT; +#else + if (stackptr < 0xc0000000 || stackptr + size > (unsigned long)high_memory) + return -EFAULT; +#endif + return 0; +} + +static void dump_stack (unsigned long *start, unsigned long *end, int offset, int max) +{ + unsigned long *p; + int i; + + for (p = start + offset, i = 0; i < max && p < end; i++, p++) { + if (i && (i & 7) == 0) + printk ("\n "); + printk ("%08lx ", *p); + } + printk ("\n"); +} + +/* + * These constants are for searching for possible module text + * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is + * a guess of how much space is likely to be vmalloced. + */ +#define VMALLOC_OFFSET (8*1024*1024) +#define MODULE_RANGE (8*1024*1024) + +static void dump_instr (unsigned long pc) +{ + unsigned long module_start, module_end; + int pmin = -2, pmax = 3, ok = 0; + extern char start_kernel, _etext; + + module_start = VMALLOC_START; + module_end = module_start + MODULE_RANGE; + + if ((pc >= (unsigned long) &start_kernel) && + (pc <= (unsigned long) &_etext)) { + if (pc + pmin < (unsigned long) &start_kernel) + pmin = ((unsigned long) &start_kernel) - pc; + if (pc + pmax > (unsigned long) &_etext) + pmax = ((unsigned long) &_etext) - pc; + ok = 1; + } else if (pc >= module_start && pc <= module_end) { + if (pc + pmin < module_start) + pmin = module_start - pc; + if (pc + pmax > module_end) + pmax = module_end - pc; + ok = 1; + } + printk ("Code: "); + if (ok) { + int i; + for (i = pmin; i < pmax; i++) + printk("%08lx ", ((unsigned long *)pc)[i]); + printk ("\n"); + } else + printk ("pc not in code space\n"); +} + +/* + * This function is protected against kernel-mode re-entrancy. If it + * is re-entered it will hang the system since we can't guarantee in + * this case that any of the functions that it calls are safe any more. + * Even the panic function could be a problem, but we'll give it a go. + */ +void die_if_kernel(char *str, struct pt_regs *regs, int err, int ret) +{ + static int died = 0; + unsigned long cstack, sstack, frameptr; + + if (user_mode(regs)) + return; + + switch (died) { + case 2: + while (1); + case 1: + died ++; + panic ("die_if_kernel re-entered. Major kernel corruption. Please reboot me!"); + break; + case 0: + died ++; + break; + } + + console_verbose (); + printk ("Internal error: %s: %x\n", str, err); + printk ("CPU: %d", smp_processor_id()); + show_regs (regs); + printk ("Process %s (pid: %d, stackpage=%08lx)\nStack: ", + current->comm, current->pid, 4096+(unsigned long)current); + + cstack = (unsigned long)(regs + 1); + sstack = 4096+(unsigned long)current; + + if (*(unsigned long *)sstack != STACK_MAGIC) + printk ("*** corrupted stack page\n "); + + if (verify_stack_pointer (cstack, 4)) + printk ("%08lx invalid kernel stack pointer\n", cstack); + else if(cstack > sstack + 4096) + printk("(sp overflow)\n"); + else if(cstack < sstack) + printk("(sp underflow)\n"); + else + dump_stack ((unsigned long *)sstack, (unsigned long *)sstack + 1024, + cstack - sstack, kstack_depth_to_print); + + frameptr = regs->ARM_fp; + if (frameptr) { + if (verify_stack_pointer (frameptr, 4)) + printk ("Backtrace: invalid frame pointer\n"); + else { + printk("Backtrace: \n"); + c_backtrace (frameptr, processor_mode(regs)); + } + } + + dump_instr (instruction_pointer(regs)); + died = 0; + if (ret != -1) + do_exit (ret); + else { + cli (); + while (1); + } +} + +void bad_user_access_alignment (const void *ptr) +{ + void *pc; + __asm__("mov %0, lr\n": "=r" (pc)); + printk (KERN_ERR "bad_user_access_alignment called: ptr = %p, pc = %p\n", ptr, pc); + current->tss.error_code = 0; + current->tss.trap_no = 11; + force_sig (SIGBUS, current); +/* die_if_kernel("Oops - bad user access alignment", regs, mode, SIGBUS);*/ +} + +asmlinkage void do_undefinstr (int address, struct pt_regs *regs, int mode) +{ + current->tss.error_code = 0; + current->tss.trap_no = 6; + force_sig (SIGILL, current); + die_if_kernel("Oops - undefined instruction", regs, mode, SIGILL); +} + +asmlinkage void do_excpt (int address, struct pt_regs *regs, int mode) +{ + current->tss.error_code = 0; + current->tss.trap_no = 11; + force_sig (SIGBUS, current); + die_if_kernel("Oops - address exception", regs, mode, SIGBUS); +} + +asmlinkage void do_unexp_fiq (struct pt_regs *regs) +{ +#ifndef CONFIG_IGNORE_FIQ + printk ("Hmm. Unexpected FIQ received, but trying to continue\n"); + printk ("You may have a hardware problem...\n"); +#endif +} + +asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode) +{ + printk (KERN_CRIT "Bad mode in %s handler detected: mode %s\n", + handler[reason], + processor_modes[proc_mode]); + die_if_kernel ("Oops", regs, 0, -1); +} + +/* + * 'math_state_restore()' saves the current math information in the + * old math state array, and gets the new ones from the current task. + * + * We no longer save/restore the math state on every context switch + * any more. We only do this now if it actually gets used. + */ +asmlinkage void math_state_restore (void) +{ + if (last_task_used_math == current) + return; + if (last_task_used_math) + /* + * Save current fp state into last_task_used_math->tss.fpe_save + */ + fpe_save (&last_task_used_math->tss.fpstate.soft); + last_task_used_math = current; + if (current->used_math) { + /* + * Restore current fp state from current->tss.fpe_save + */ + fpe_restore (¤t->tss.fpstate.soft); + } else { + /* + * initialise fp state + */ + fpe_restore (&init_task.tss.fpstate.soft); + current->used_math = 1; + } +} + +asmlinkage void arm_syscall (int no, struct pt_regs *regs) +{ + switch (no) { + case 0: /* branch through 0 */ + printk ("[%d] %s: branch through zero\n", current->pid, current->comm); + force_sig (SIGILL, current); + if (user_mode(regs)) { + show_regs (regs); + c_backtrace (regs->ARM_fp, processor_mode(regs)); + } + die_if_kernel ("Oops", regs, 0, SIGILL); + break; + + case 1: /* SWI_BREAK_POINT */ + regs->ARM_pc -= 4; /* Decrement PC by one instruction */ + ptrace_cancel_bpt (current); + force_sig (SIGTRAP, current); + break; + + default: + printk ("[%d] %s: arm syscall %d\n", current->pid, current->comm, no); + force_sig (SIGILL, current); + if (user_mode(regs)) { + show_regs (regs); + c_backtrace (regs->ARM_fp, processor_mode(regs)); + } + die_if_kernel ("Oops", regs, no, SIGILL); + break; + } +} + +asmlinkage void deferred(int n, struct pt_regs *regs) +{ + printk ("[%d] %s: old system call %X\n", current->pid, current->comm, n); + show_regs (regs); + force_sig (SIGILL, current); +} + +asmlinkage void arm_malalignedptr(const char *str, void *pc, volatile void *ptr) +{ + printk ("Mal-aligned pointer in %s: %p (PC=%p)\n", str, ptr, pc); +} + +asmlinkage void arm_invalidptr (const char *function, int size) +{ + printk ("Invalid pointer size in %s (PC=%p) size %d\n", + function, __builtin_return_address(0), size); +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile --- v2.1.79/linux/arch/arm/lib/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/Makefile Tue Jan 20 16:39:41 1998 @@ -0,0 +1,55 @@ +# +# linux/arch/arm/lib/Makefile +# +# Copyright (C) 1995-1998 Russell King +# + +L_TARGET := lib.a +L_OBJS := backtrace.o bitops.o delay.o fp_support.o \ + loaders.o memcpy.o memfastset.o system.o string.o uaccess.o + +ifeq ($(PROCESSOR),armo) + L_OBJS += uaccess-armo.o +endif + +ifdef CONFIG_INET + L_OBJS += checksum.o +endif + +ifdef CONFIG_ARCH_ACORN + L_OBJS += ll_char_wr.o io-acorn.o + ifdef CONFIG_ARCH_A5K + L_OBJS += floppydma.o + endif + ifdef CONFIG_ARCH_RPC + L_OBJS += floppydma.o + endif +endif + +ifdef CONFIG_ARCH_EBSA110 + L_OBJS += io-ebsa110.o +endif + +include $(TOPDIR)/Rules.make + +constants.h: getconstants + ./getconstants > constants.h + +getconstants: getconstants.c getconstants.h + $(HOSTCC) -D__KERNEL__ -o getconstants getconstants.c + +getconstants.h: getconsdata.c + $(CC) $(CFLAGS) -c getconsdata.c + $(PERL) extractinfo.perl $(OBJDUMP) > $@ + +%.o: %.S +ifndef $(CONFIG_BINUTILS_NEW) + $(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..tmp.$<.s + $(CC) $(CFLAGS:-pipe=) -c -o $@ ..tmp.$<.s + $(RM) ..tmp.$<.s +else + $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< +endif + +clean: + $(RM) getconstants constants.h getconstants.h diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/backtrace.S linux/arch/arm/lib/backtrace.S --- v2.1.79/linux/arch/arm/lib/backtrace.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/backtrace.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,100 @@ +/* + * linux/arch/arm/lib/backtrace.S + * + * Copyright (C) 1995, 1996 Russell King + */ +#include +#include + .text + +@ fp is 0 or stack frame + +#define frame r4 +#define next r5 +#define save r6 +#define mask r7 +#define offset r8 + +ENTRY(__backtrace) + mov r1, #0x10 + mov r0, fp + +ENTRY(c_backtrace) + stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... + tst r1, #0x10 @ 26 or 32-bit? + moveq mask, #0xfc000003 + movne mask, #0 + tst mask, r0 + movne r0, #0 + movs frame, r0 +1: moveq r0, #-2 + LOADREGS(eqfd, sp!, {r4 - r8, pc}) + +2: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction + ldr r0, [sp], #4 + adr r1, 2b - 4 + sub offset, r0, r1 + +3: tst frame, mask @ Check for address exceptions... + bne 1b + + ldmda frame, {r0, r1, r2, r3} @ fp, sp, lr, pc + mov next, r0 + + sub save, r3, offset @ Correct PC for prefetching + bic save, save, mask + adr r0, .Lfe + mov r1, save + bic r2, r2, mask + bl SYMBOL_NAME(printk) + + sub r0, frame, #16 + ldr r1, [save, #4] + mov r3, r1, lsr #10 + ldr r2, .Ldsi+4 + teq r3, r2 @ Check for stmia sp!, {args} + addeq save, save, #4 @ next instruction + bleq .Ldumpstm + + ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction + mov r3, r1, lsr #10 + ldr r2, .Ldsi + teq r3, r2 + bleq .Ldumpstm + + teq frame, next + movne frame, next + teqne frame, #0 + bne 3b + LOADREGS(fd, sp!, {r4 - r8, pc}) + + +#define instr r4 +#define reg r5 +#define stack r6 + +.Ldumpstm: stmfd sp!, {instr, reg, stack, lr} + mov stack, r0 + mov instr, r1 + mov reg, #9 + +1: mov r3, #1 + tst instr, r3, lsl reg + beq 2f + ldr r2, [stack], #-4 + mov r1, reg + adr r0, .Lfp + bl SYMBOL_NAME(printk) +2: subs reg, reg, #1 + bpl 1b + + mov r0, stack + LOADREGS(fd, sp!, {instr, reg, stack, pc}) + +.Lfe: .ascii "Function entered at [<%p>] from [<%p>]\n" + .byte 0 +.Lfp: .ascii " r%d = %p\n" + .byte 0 + .align +.Ldsi: .word 0x00e92dd8 >> 2 + .word 0x00e92d00 >> 2 diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/bitops.S linux/arch/arm/lib/bitops.S --- v2.1.79/linux/arch/arm/lib/bitops.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/bitops.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,152 @@ +/* + * linux/arch/arm/lib/bitops.S + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include + .text + +@ Purpose : Function to set a bit +@ Prototype: int set_bit(int bit,int *addr) + +ENTRY(set_bit) + and r2, r0, #7 + mov r3, #1 + mov r3, r3, lsl r2 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1, r0, lsr #3] + orr r2, r2, r3 + strb r2, [r1, r0, lsr #3] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + +ENTRY(test_and_set_bit) + add r1, r1, r0, lsr #3 @ Get byte offset + and r3, r0, #7 @ Get bit offset + mov r0, #1 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1] + tst r2, r0, lsl r3 + orr r2, r2, r0, lsl r3 + moveq r0, #0 + strb r2, [r1] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + +@ Purpose : Function to clear a bit +@ Prototype: int clear_bit(int bit,int *addr) + +ENTRY(clear_bit) + and r2, r0, #7 + mov r3, #1 + mov r3, r3, lsl r2 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1, r0, lsr #3] + bic r2, r2, r3 + strb r2, [r1, r0, lsr #3] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + +ENTRY(test_and_clear_bit) + add r1, r1, r0, lsr #3 @ Get byte offset + and r3, r0, #7 @ Get bit offset + mov r0, #1 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1] + tst r2, r0, lsl r3 + bic r2, r2, r0, lsl r3 + moveq r0, #0 + strb r2, [r1] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + +/* Purpose : Function to change a bit + * Prototype: int change_bit(int bit,int *addr) + */ +ENTRY(change_bit) + and r2, r0, #7 + mov r3, #1 + mov r3, r3, lsl r2 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1, r0, lsr #3] + eor r2, r2, r3 + strb r2, [r1, r0, lsr #3] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + +ENTRY(test_and_change_bit) + add r1, r1, r0, lsr #3 + and r3, r0, #7 + mov r0, #1 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1] + tst r2, r0, lsl r3 + eor r2, r2, r0, lsl r3 + moveq r0, #0 + strb r2, [r1] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + +@ Purpose : Find a 'zero' bit +@ Prototype: int find_first_zero_bit(char *addr,int maxbit); + +ENTRY(find_first_zero_bit) + mov r2, #0 @ Initialise bit position +Lfindzbit1lp: ldrb r3, [r0, r2, lsr #3] @ Check byte, if 0xFF, then all bits set + teq r3, #0xFF + bne Lfoundzbit + add r2, r2, #8 + cmp r2, r1 @ Check to see if we have come to the end + bcc Lfindzbit1lp + add r0, r1, #1 @ Make sure that we flag an error + RETINSTR(mov,pc,lr) +Lfoundzbit: tst r3, #1 @ Check individual bits + moveq r0, r2 + RETINSTR(moveq,pc,lr) + tst r3, #2 + addeq r0, r2, #1 + RETINSTR(moveq,pc,lr) + tst r3, #4 + addeq r0, r2, #2 + RETINSTR(moveq,pc,lr) + tst r3, #8 + addeq r0, r2, #3 + RETINSTR(moveq,pc,lr) + tst r3, #16 + addeq r0, r2, #4 + RETINSTR(moveq,pc,lr) + tst r3, #32 + addeq r0, r2, #5 + RETINSTR(moveq,pc,lr) + tst r3, #64 + addeq r0, r2, #6 + RETINSTR(moveq,pc,lr) + add r0, r2, #7 + RETINSTR(mov,pc,lr) + +@ Purpose : Find next 'zero' bit +@ Prototype: int find_next_zero_bit(char *addr,int maxbit,int offset) + +ENTRY(find_next_zero_bit) + tst r2, #7 + beq Lfindzbit1lp @ If new byte, goto old routine + ldrb r3, [r0, r2, lsr#3] + orr r3, r3, #0xFF00 @ Set top bits so we wont get confused + stmfd sp!, {r4} + and r4, r2, #7 + mov r3, r3, lsr r4 @ Shift right by no. of bits + ldmfd sp!, {r4} + and r3, r3, #0xFF + teq r3, #0xFF + orreq r2, r2, #7 + addeq r2, r2, #1 + beq Lfindzbit1lp @ If all bits are set, goto old routine + b Lfoundzbit diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/checksum.S linux/arch/arm/lib/checksum.S --- v2.1.79/linux/arch/arm/lib/checksum.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/checksum.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,600 @@ +/* + * linux/arch/arm/lib/iputils.S + * + * Copyright (C) 1995, 1996, 1997, 1998 Russell King + */ +#include +#include +#include + + .text + +/* Function: __u32 csum_partial(const char *src, int len, __u32) + * Params : r0 = buffer, r1 = len, r2 = checksum + * Returns : r0 = new checksum + */ + +ENTRY(csum_partial) + tst r0, #2 + beq 1f + subs r1, r1, #2 + addmi r1, r1, #2 + bmi 3f + bic r0, r0, #3 + ldr r3, [r0], #4 + adds r2, r2, r3, lsr #16 + adcs r2, r2, #0 +1: adds r2, r2, #0 + bics ip, r1, #31 + beq 3f + stmfd sp!, {r4 - r6} +2: ldmia r0!, {r3 - r6} + adcs r2, r2, r3 + adcs r2, r2, r4 + adcs r2, r2, r5 + adcs r2, r2, r6 + ldmia r0!, {r3 - r6} + adcs r2, r2, r3 + adcs r2, r2, r4 + adcs r2, r2, r5 + adcs r2, r2, r6 + sub ip, ip, #32 + teq ip, #0 + bne 2b + adcs r2, r2, #0 + ldmfd sp!, {r4 - r6} +3: ands ip, r1, #0x1c + beq 5f +4: ldr r3, [r0], #4 + adcs r2, r2, r3 + sub ip, ip, #4 + teq ip, #0 + bne 4b + adcs r2, r2, #0 +5: ands ip, r1, #3 + moveq r0, r2 + RETINSTR(moveq,pc,lr) + mov ip, ip, lsl #3 + rsb ip, ip, #32 + ldr r3, [r0] + mov r3, r3, lsl ip + adds r2, r2, r3, lsr ip + adc r0, r2, #0 + RETINSTR(mov,pc,lr) + +/* Function: __u32 csum_partial_copy_from_user (const char *src, char *dst, int len, __u32 sum, int *err_ptr) + * Params : r0 = src, r1 = dst, r2 = len, r3 = sum, [sp, #0] = &err + * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT + */ + +#define USER_LDR(instr...) \ +9999: instr; \ + .section __ex_table, "a"; \ + .align 3; \ + .long 9999b, 6001f; \ + .previous; + +ENTRY(csum_partial_copy_from_user) + mov ip, sp + stmfd sp!, {r4 - r8, fp, ip, lr, pc} + sub fp, ip, #4 + cmp r2, #4 + blt .too_small_user + tst r1, #2 @ Test destination alignment + beq .dst_aligned_user + subs r2, r2, #2 @ We dont know if SRC is aligned... +USER_LDR( ldrbt ip, [r0], #1) +USER_LDR( ldrbt r8, [r0], #1) + orr ip, ip, r8, lsl #8 + adds r3, r3, ip + adcs r3, r3, #0 + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 @ Destination now aligned +.dst_aligned_user: + tst r0, #3 + bne .src_not_aligned_user + adds r3, r3, #0 + bics ip, r2, #15 @ Routine for src & dst aligned + beq 2f +1: +USER_LDR( ldrt r4, [r0], #4) +USER_LDR( ldrt r5, [r0], #4) +USER_LDR( ldrt r6, [r0], #4) +USER_LDR( ldrt r7, [r0], #4) + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f +USER_LDR( ldrt r4, [r0], #4) +USER_LDR( ldrt r5, [r0], #4) + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + tst ip, #4 + beq 4f +3: +USER_LDR( ldrt r4, [r0], #4) + str r4, [r1], #4 + adcs r3, r3, r4 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) +USER_LDR( ldrt r4, [r0], #4) + tst r2, #2 + beq .exit + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 + mov r4, r4, lsr #8 +.exit: tst r2, #1 + strneb r4, [r1], #1 + andne r4, r4, #255 + adcnes r3, r3, r4 + adcs r0, r3, #0 + LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) + +.too_small_user: + teq r2, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + cmp r2, #2 + blt .too_small_user1 +USER_LDR( ldrbt ip, [r0], #1) +USER_LDR( ldrbt r8, [r0], #1) + orr ip, ip, r8, lsl #8 + adds r3, r3, ip + strb ip, [r1], #1 + strb r8, [r1], #1 + tst r2, #1 +.too_small_user1: +USER_LDR( ldrnebt ip, [r0], #1) + strneb ip, [r1], #1 + adcnes r3, r3, ip + adcs r0, r3, #0 + LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) + +.src_not_aligned_user: + cmp r2, #4 + blt .too_small_user + and ip, r0, #3 + bic r0, r0, #3 +USER_LDR( ldrt r4, [r0], #4) + cmp ip, #2 + beq .src2_aligned_user + bhi .src3_aligned_user + mov r4, r4, lsr #8 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: +USER_LDR( ldrt r5, [r0], #4) +USER_LDR( ldrt r6, [r0], #4) +USER_LDR( ldrt r7, [r0], #4) +USER_LDR( ldrt r8, [r0], #4) + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + mov r7, r7, lsr #8 + orr r7, r7, r8, lsl #24 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #8 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f +USER_LDR( ldrt r5, [r0], #4) +USER_LDR( ldrt r6, [r0], #4) + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #8 + tst ip, #4 + beq 4f +3: +USER_LDR( ldrt r5, [r0], #4) + orr r4, r4, r5, lsl #24 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #8 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq .exit + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + b .exit + +.src2_aligned_user: + mov r4, r4, lsr #16 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: +USER_LDR( ldrt r5, [r0], #4) +USER_LDR( ldrt r6, [r0], #4) +USER_LDR( ldrt r7, [r0], #4) +USER_LDR( ldrt r8, [r0], #4) + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7, lsl #16 + mov r7, r7, lsr #16 + orr r7, r7, r8, lsl #16 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #16 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f +USER_LDR( ldrt r5, [r0], #4) +USER_LDR( ldrt r6, [r0], #4) + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #16 + tst ip, #4 + beq 4f +3: +USER_LDR( ldrt r5, [r0], #4) + orr r4, r4, r5, lsl #16 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #16 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq .exit + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 +USER_LDR( ldrb r4, [r0], #1) + b .exit + +.src3_aligned_user: + mov r4, r4, lsr #24 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: +USER_LDR( ldrt r5, [r0], #4) +USER_LDR( ldrt r6, [r0], #4) +USER_LDR( ldrt r7, [r0], #4) +USER_LDR( ldrt r8, [r0], #4) + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + mov r7, r7, lsr #24 + orr r7, r7, r8, lsl #8 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #24 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f +USER_LDR( ldrt r5, [r0], #4) +USER_LDR( ldrt r6, [r0], #4) + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #24 + tst ip, #4 + beq 4f +3: +USER_LDR( ldrt r5, [r0], #4) + orr r4, r4, r5, lsl #8 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #24 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq .exit + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 +USER_LDR( ldrt r4, [r0], #4) + strb r4, [r1], #1 + adcs r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + b .exit + + .section .fixup,"ax" + .align 4 +6001: mov r4, #-EFAULT + ldr r5, [sp, #4*8] + str r4, [r5] + LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) + +/* Function: __u32 csum_partial_copy (const char *src, char *dst, int len, __u32 sum) + * Params : r0 = src, r1 = dst, r2 = len, r3 = checksum + * Returns : r0 = new checksum + */ +ENTRY(csum_partial_copy) + mov ip, sp + stmfd sp!, {r4 - r8, fp, ip, lr, pc} + sub fp, ip, #4 + cmp r2, #4 + blt Ltoo_small + tst r1, #2 @ Test destination alignment + beq Ldst_aligned + subs r2, r2, #2 @ We dont know if SRC is aligned... + ldrb ip, [r0], #1 + ldrb r8, [r0], #1 + orr ip, ip, r8, lsl #8 + adds r3, r3, ip + adcs r3, r3, #0 + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 @ Destination now aligned +Ldst_aligned: tst r0, #3 + bne Lsrc_not_aligned + adds r3, r3, #0 + bics ip, r2, #15 @ Routine for src & dst aligned + beq 3f +1: ldmia r0!, {r4, r5, r6, r7} + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + sub ip, ip, #16 + teq ip, #0 + bne 1b +3: ands ip, r2, #12 + beq 5f + tst ip, #8 + beq 4f + ldmia r0!, {r4, r5} + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + tst ip, #4 + beq 5f +4: ldr r4, [r0], #4 + str r4, [r1], #4 + adcs r3, r3, r4 +5: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + ldr r4, [r0], #4 + tst r2, #2 + beq Lexit + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + b Lexit + +Ltoo_small: teq r2, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + cmp r2, #2 + blt Ltoo_small1 + ldrb ip, [r0], #1 + ldrb r8, [r0], #1 + orr ip, ip, r8, lsl #8 + adds r3, r3, ip + strb ip, [r1], #1 + strb r8, [r1], #1 +Lexit: tst r2, #1 +Ltoo_small1: ldrneb ip, [r0], #1 + strneb ip, [r1], #1 + adcnes r3, r3, ip + adcs r0, r3, #0 + LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) + +Lsrc_not_aligned: + cmp r2, #4 + blt Ltoo_small + and ip, r0, #3 + bic r0, r0, #3 + ldr r4, [r0], #4 + cmp ip, #2 + beq Lsrc2_aligned + bhi Lsrc3_aligned + mov r4, r4, lsr #8 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: ldmia r0!, {r5, r6, r7, r8} + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + mov r7, r7, lsr #8 + orr r7, r7, r8, lsl #24 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #8 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f + ldmia r0!, {r5, r6} + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #8 + tst ip, #4 + beq 4f +3: ldr r5, [r0], #4 + orr r4, r4, r5, lsl #24 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #8 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq Lexit + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + b Lexit + +Lsrc2_aligned: mov r4, r4, lsr #16 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: ldmia r0!, {r5, r6, r7, r8} + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7, lsl #16 + mov r7, r7, lsr #16 + orr r7, r7, r8, lsl #16 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #16 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f + ldmia r0!, {r5, r6} + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #16 + tst ip, #4 + beq 4f +3: ldr r5, [r0], #4 + orr r4, r4, r5, lsl #16 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #16 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq Lexit + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 + ldrb r4, [r0], #1 + b Lexit + +Lsrc3_aligned: mov r4, r4, lsr #24 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: ldmia r0!, {r5, r6, r7, r8} + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + mov r7, r7, lsr #24 + orr r7, r7, r8, lsl #8 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #24 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f + ldmia r0!, {r5, r6} + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #24 + tst ip, #4 + beq 4f +3: ldr r5, [r0], #4 + orr r4, r4, r5, lsl #8 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #24 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq Lexit + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + ldr r4, [r0], #4 + strb r4, [r1], #1 + adcs r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + b Lexit diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/delay.S linux/arch/arm/lib/delay.S --- v2.1.79/linux/arch/arm/lib/delay.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/delay.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,43 @@ +/* + * linux/arch/arm/lib/delay.S + * + * Copyright (C) 1995, 1996 Russell King + */ +#include +#include + .text + +LC0: .word SYMBOL_NAME(loops_per_sec) + +ENTRY(udelay) + mov r2, #0x1000 + orr r2, r2, #0x00c6 + mul r1, r0, r2 + ldr r2, LC0 + ldr r2, [r2] + mov r1, r1, lsr #11 + mov r2, r2, lsr #11 + mul r0, r1, r2 + movs r0, r0, lsr #10 + RETINSTR(moveq,pc,lr) + +@ Delay routine +ENTRY(__delay) + subs r0, r0, #1 + RETINSTR(movcc,pc,lr) + subs r0, r0, #1 + RETINSTR(movcc,pc,lr) + subs r0, r0, #1 + RETINSTR(movcc,pc,lr) + subs r0, r0, #1 + RETINSTR(movcc,pc,lr) + subs r0, r0, #1 + RETINSTR(movcc,pc,lr) + subs r0, r0, #1 + RETINSTR(movcc,pc,lr) + subs r0, r0, #1 + RETINSTR(movcc,pc,lr) + subs r0, r0, #1 + bcs SYMBOL_NAME(__delay) + RETINSTR(mov,pc,lr) + diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/extractinfo.perl linux/arch/arm/lib/extractinfo.perl --- v2.1.79/linux/arch/arm/lib/extractinfo.perl Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/extractinfo.perl Tue Jan 20 16:39:41 1998 @@ -0,0 +1,45 @@ +#!/usr/bin/perl + +$OBJDUMP=$ARGV[0]; + +sub swapdata { + local ($num) = @_; + + return substr($num, 6, 2).substr($num, 4, 2).substr ($num, 2, 2).substr ($num, 0, 2); +} + +open (DATA, $OBJDUMP.' --full-contents --section=.data getconsdata.o | grep \'^ 00\' |') || + die ('Cant objdump!'); +while () { + ($addr, $data0, $data1, $data2, $data3) = split (' '); + $dat[hex($addr)] = hex(&swapdata($data0)); + $dat[hex($addr)+4] = hex(&swapdata($data1)); + $dat[hex($addr)+8] = hex(&swapdata($data2)); + $dat[hex($addr)+12] = hex(&swapdata($data3)); +} +close (DATA); + +open (DATA, $OBJDUMP.' --syms getconsdata.o |') || die ('Cant objdump!'); +while () { + /elf32/ && ( $elf = 1 ); + /a.out/ && ( $aout = 1 ); + next if ($aout && ! / 07 /); + next if ($elf && ! (/^00...... g/ && /.data/)); + next if (!$aout && !$elf); + + ($addr, $flags, $sect, $a1, $a2, $a3, $name) = split (' ') if $aout; + $nam[hex($addr)] = substr($name, 1) if $aout; + if ($elf) { + chomp; + $addr = substr ($_, 0, 8); + $name = substr ($_, 32); + $nam[hex($addr)] = $name; + } +} +close (DATA); + +print "/*\n * *** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! ***\n */\n"; +for ($i = 0; $i < hex($addr)+12; $i ++) { + print "unsigned long $nam[$i] = $dat[$i];\n" if $dat[$i]; + print "#define __HAS_$nam[$i]\n" if $dat[$i]; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/floppydma.S linux/arch/arm/lib/floppydma.S --- v2.1.79/linux/arch/arm/lib/floppydma.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/floppydma.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,57 @@ +/* + * linux/arch/arm/lib/floppydma.S + * + * Copyright (C) 1995, 1996 Russell King + */ +#include +#include + .text + + .global SYMBOL_NAME(floppy_fiqin_end) +ENTRY(floppy_fiqin_start) + subs r9, r9, #1 + ldrgtb r12, [r11, #-4] + ldrleb r12, [r11], #0 + strb r12, [r10], #1 + subs pc, lr, #4 +SYMBOL_NAME(floppy_fiqin_end): + + .global SYMBOL_NAME(floppy_fiqout_end) +ENTRY(floppy_fiqout_start) + subs r9, r9, #1 + ldrgeb r12, [r10], #1 + movlt r12, #0 + strleb r12, [r11], #0 + subles pc, lr, #4 + strb r12, [r11, #-4] + subs pc, lr, #4 +SYMBOL_NAME(floppy_fiqout_end): + +@ Params: +@ r0 = length +@ r1 = address +@ r2 = floppy port +@ Puts these into R9_fiq, R10_fiq, R11_fiq +ENTRY(floppy_fiqsetup) + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + MODE(r3,ip,I_BIT|F_BIT|DEFAULT_FIQ) @ disable FIQs, IRQs, FIQ mode + mov r0, r0 + mov r9, r0 + mov r10, r1 + mov r11, r2 + RESTOREMODE(r3) @ back to normal + mov r0, r0 + LOADREGS(ea,fp,{fp, sp, pc}) + +ENTRY(floppy_fiqresidual) + mov ip, sp + stmfd sp!, {fp, ip, lr, pc} + sub fp, ip, #4 + MODE(r3,ip,I_BIT|F_BIT|DEFAULT_FIQ) @ disable FIQs, IRQs, FIQ mode + mov r0, r0 + mov r0, r9 + RESTOREMODE(r3) + mov r0, r0 + LOADREGS(ea,fp,{fp, sp, pc}) diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/fp_support.c linux/arch/arm/lib/fp_support.c --- v2.1.79/linux/arch/arm/lib/fp_support.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/fp_support.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,22 @@ +/* + * linux/arch/arm/lib/fp_support.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include + +extern void (*fp_save)(struct fp_soft_struct *); + +asmlinkage void fp_setup(void) +{ + struct task_struct *p; + + p = &init_task; + do { + fp_save(&p->tss.fpstate.soft); + p = p->next_task; + } + while (p != &init_task); +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/getconsdata.c linux/arch/arm/lib/getconsdata.c --- v2.1.79/linux/arch/arm/lib/getconsdata.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/getconsdata.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,31 @@ +/* + * linux/arch/arm/lib/getconsdata.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include +#include +#include +#include +#include + +#define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n) +#define OFF_MM(n) (unsigned long)&(((struct mm_struct *)0)->n) + +#ifdef KERNEL_DOMAIN +unsigned long kernel_domain = KERNEL_DOMAIN; +#endif +#ifdef USER_DOMAIN +unsigned long user_domain = USER_DOMAIN; +#endif +unsigned long addr_limit = OFF_TSK(addr_limit); +unsigned long tss_memmap = OFF_TSK(tss.memmap); +unsigned long mm = OFF_TSK(mm); +unsigned long pgd = OFF_MM(pgd); +unsigned long tss_save = OFF_TSK(tss.save); +unsigned long tss_fpesave = OFF_TSK(tss.fpstate.soft.save); +#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) +unsigned long tss_memcmap = OFF_TSK(tss.memcmap); +#endif diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/getconstants.c linux/arch/arm/lib/getconstants.c --- v2.1.79/linux/arch/arm/lib/getconstants.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/getconstants.c Tue Jan 20 16:39:41 1998 @@ -0,0 +1,74 @@ +/* + * linux/arch/arm/lib/getconstants.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include +#include +#include + +void printdef(char *def, int no) +{ + printf("#define %s\t%d\n", def, no); +} + +#include "getconstants.h" + +int main() +{ + printf("/*\n * contants.h generated by getconstants\n * DO NOT EDIT!\n */\n"); + + printf("#define _current\t_%s\n", "current_set"); + +#ifdef _PAGE_PRESENT + printdef("PAGE_PRESENT", _PAGE_PRESENT); +#endif +#ifdef _PAGE_RW + printdef("PAGE_RW", _PAGE_RW); +#endif +#ifdef _PAGE_USER + printdef("PAGE_USER", _PAGE_USER); +#endif +#ifdef _PAGE_ACCESSED + printdef("PAGE_ACCESSED", _PAGE_ACCESSED); +#endif +#ifdef _PAGE_DIRTY + printdef("PAGE_DIRTY", _PAGE_DIRTY); +#endif +#ifdef _PAGE_READONLY + printdef("PAGE_READONLY", _PAGE_READONLY); +#endif +#ifdef _PAGE_NOT_USER + printdef("PAGE_NOT_USER", _PAGE_NOT_USER); +#endif +#ifdef _PAGE_OLD + printdef("PAGE_OLD", _PAGE_OLD); +#endif +#ifdef _PAGE_CLEAN + printdef("PAGE_CLEAN", _PAGE_CLEAN); +#endif + printdef("TSS_MEMMAP", (int)tss_memmap); + printdef("TSS_SAVE", (int)tss_save); +#ifdef __HAS_tss_memcmap + printdef("TSS_MEMCMAP", (int)tss_memcmap); +#endif +#ifdef __HAS_addr_limit + printdef("ADDR_LIMIT", (int)addr_limit); +#endif +#ifdef __HAS_kernel_domain + printdef("KERNEL_DOMAIN", kernel_domain); +#endif +#ifdef __HAS_user_domain + printdef("USER_DOMAIN", user_domain); +#endif + printdef("TSS_FPESAVE", (int)tss_fpesave); + printdef("MM", (int)mm); + printdef("PGD", (int)pgd); + + printf("#define KSWI_BASE 0x900000\n"); + printf("#define KSWI_SYS_BASE 0x9F0000\n"); + printf("#define SYS_ERROR0 0x9F0000\n"); + return 0; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/getconstants.h linux/arch/arm/lib/getconstants.h --- v2.1.79/linux/arch/arm/lib/getconstants.h Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/getconstants.h Tue Jan 20 16:39:41 1998 @@ -0,0 +1,17 @@ +/* + * *** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! *** + */ +unsigned long addr_limit = 56; +#define __HAS_addr_limit +unsigned long tss_memmap = 640; +#define __HAS_tss_memmap +unsigned long mm = 1676; +#define __HAS_mm +unsigned long pgd = 8; +#define __HAS_pgd +unsigned long tss_save = 636; +#define __HAS_tss_save +unsigned long tss_fpesave = 492; +#define __HAS_tss_fpesave +unsigned long tss_memcmap = 644; +#define __HAS_tss_memcmap diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/io-acorn.S linux/arch/arm/lib/io-acorn.S --- v2.1.79/linux/arch/arm/lib/io-acorn.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-acorn.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,214 @@ +/* + * linux/arch/arm/lib/io.S + * + * Copyright (C) 1995, 1996 Russell King + */ +#include +#include +#include +#include + + .text + .align + +#define OUT(reg) \ + mov r8, reg, lsl $16 ;\ + orr r8, r8, r8, lsr $16 ;\ + str r8, [r3, r0, lsl $2] ;\ + mov r8, reg, lsr $16 ;\ + orr r8, r8, r8, lsl $16 ;\ + str r8, [r3, r0, lsl $2] + +#define IN(reg) \ + ldr reg, [r0] ;\ + and reg, reg, ip ;\ + ldr lr, [r0] ;\ + orr reg, reg, lr, lsl $16 + + .equ pcio_base_high, PCIO_BASE & 0xff000000 + .equ pcio_base_low, PCIO_BASE & 0x00ff0000 + .equ io_base_high, IO_BASE & 0xff000000 + .equ io_base_low, IO_BASE & 0x00ff0000 + + .equ addr_io_diff_hi, pcio_base_high - io_base_high + .equ addr_io_diff_lo, pcio_base_low - io_base_low + + .macro addr reg, off + tst \off, #0x80000000 + .if addr_io_diff_hi + movne \reg, #IO_BASE + moveq \reg, #pcio_base_high + .if pcio_base_low + addeq \reg, \reg, #pcio_base_low + .endif + .else + mov \reg, #IO_BASE + addeq \reg, \reg, #addr_io_diff_lo + .endif + .endm + +@ Purpose: read a block of data from a hardware register to memory. +@ Proto : insw(int from_port, void *to, int len_in_words); +@ Proto : inswb(int from_port, void *to, int len_in_bytes); +@ Notes : increment to + +ENTRY(insw) + mov r2, r2, lsl#1 +ENTRY(inswb) + mov ip, sp + stmfd sp!, {r4 - r10 ,fp ,ip ,lr ,pc} + sub fp, ip, #4 + addr r3, r0 + add r0, r3, r0, lsl #2 + tst r1, #3 + beq Linswok + tst r1, #1 + bne Linsw_notaligned + cmp r2, #1 + ldrge r4, [r0] + strgeb r4, [r1], #1 + movgt r4, r4, LSR#8 + strgtb r4, [r1], #1 + ldmleea fp, {r4 - r10, fp, sp, pc}^ + sub r2, r2, #2 +Linswok: mov ip, #0xFF + orr ip, ip, ip, lsl #8 +Linswlp: subs r2, r2, #64 + bmi Linsw_toosmall + IN(r3) + IN(r4) + IN(r5) + IN(r6) + IN(r7) + IN(r8) + IN(r9) + IN(r10) + stmia r1!, {r3 - r10} + IN(r3) + IN(r4) + IN(r5) + IN(r6) + IN(r7) + IN(r8) + IN(r9) + IN(r10) + stmia r1!, {r3 - r10} + bne Linswlp + LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) +Linsw_toosmall: + adds r2, r2, #32 + bmi Linsw_toosmall2 +Linsw2lp: IN(r3) + IN(r4) + IN(r5) + IN(r6) + IN(r7) + IN(r8) + IN(r9) + IN(r10) + stmia r1!, {r3 - r10} + LOADREGS(eqea, fp, {r4 - r10, fp, sp, pc}) + b Linsw_notaligned +Linsw_toosmall2: + add r2, r2, #32 +Linsw_notaligned: + cmp r2, #1 + LOADREGS(ltea, fp, {r4 - r10, fp, sp, pc}) + ldr r4, [r0] + strb r4, [r1], #1 + movgt r4, r4, LSR#8 + strgtb r4, [r1], #1 + subs r2, r2, #2 + bgt Linsw_notaligned + LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) + +@ Purpose: write a block of data from memory to a hardware register. +@ Proto : outsw(int to_reg, void *from, int len_in_words); +@ Proto : outswb(int to_reg, void *from, int len_in_bytes); +@ Notes : increments from + +ENTRY(outsw) + mov r2, r2, LSL#1 +ENTRY(outswb) + mov ip, sp + stmfd sp!, {r4 - r8, fp, ip, lr, pc} + sub fp, ip, #4 + addr r3, r0 + tst r1, #2 + beq 1f + ldr r4, [r1], #2 + mov r4, r4, lsl #16 + orr r4, r4, r4, lsr #16 + str r4, [r3, r0, lsl #2] + subs r2, r2, #2 + LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) +1: subs r2, r2, #32 + blt 2f + ldmia r1!, {r4, r5, r6, r7} + OUT(r4) + OUT(r5) + OUT(r6) + OUT(r7) + ldmia r1!, {r4, r5, r6, r7} + OUT(r4) + OUT(r5) + OUT(r6) + OUT(r7) + bne 1b + LOADREGS(ea, fp, {r4 - r8, fp, sp, pc}) +2: adds r2, r2, #32 + LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) +3: ldr r4, [r1],#2 + mov r4, r4, lsl#16 + orr r4, r4, r4, lsr#16 + str r4, [r3, r0, lsl#2] + subs r2, r2, #2 + bgt 3b + LOADREGS(ea, fp, {r4 - r8, fp, sp, pc}) + +@ Purpose: write a memc register +@ Proto : void memc_write(int register, int value); +@ Returns: nothing + +#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3) +ENTRY(memc_write) + cmp r0, #7 + RETINSTR(movgt,pc,lr) + mov r0, r0, lsl #17 + mov r1, r1, lsl #15 + mov r1, r1, lsr #17 + orr r0, r0, r1, lsl #2 + add r0, r0, #0x03600000 + strb r0, [r0] + RETINSTR(mov,pc,lr) +#define CPSR2SPSR(rt) +#else +#define CPSR2SPSR(rt) \ + mrs rt, cpsr; \ + msr spsr, rt +#endif + +@ Purpose: call an expansion card loader to read bytes. +@ Proto : char read_loader(int offset, char *card_base, char *loader); +@ Returns: byte read + +ENTRY(ecard_loader_read) + stmfd sp!, {r4 - r12, lr} + mov r11, r1 + mov r1, r0 + CPSR2SPSR(r0) + mov lr, pc + mov pc, r2 + LOADREGS(fd, sp!, {r4 - r12, pc}) + +@ Purpose: call an expansion card loader to reset the card +@ Proto : void read_loader(int card_base, char *loader); +@ Returns: byte read + +ENTRY(ecard_loader_reset) + stmfd sp!, {r4 - r12, lr} + mov r11, r0 + CPSR2SPSR(r0) + mov lr, pc + add pc, r1, #8 + LOADREGS(fd, sp!, {r4 - r12, pc}) diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/io-ebsa110.S linux/arch/arm/lib/io-ebsa110.S --- v2.1.79/linux/arch/arm/lib/io-ebsa110.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-ebsa110.S Tue Jan 20 16:39:41 1998 @@ -0,0 +1,149 @@ +/* + * linux/arch/arm/lib/io-ebsa.S + * + * Copyright (C) 1995, 1996 Russell King + */ +#include +#include + .text + .align + +#define OUT(reg) \ + mov r8, reg, lsl $16 ;\ + orr r8, r8, r8, lsr $16 ;\ + str r8, [r3, r0, lsl $2] ;\ + mov r8, reg, lsr $16 ;\ + orr r8, r8, r8, lsl $16 ;\ + str r8, [r3, r0, lsl $2] + +#define IN(reg) \ + ldr reg, [r0] ;\ + and reg, reg, ip ;\ + ldr lr, [r0] ;\ + orr reg, reg, lr, lsl $16 + +@ Purpose: read a block of data from a hardware register to memory. +@ Proto : insw(int from_port, void *to, int len_in_words); +@ Proto : inswb(int from_port, void *to, int len_in_bytes); +@ Notes : increment to + +ENTRY(insw) + mov r2, r2, lsl#1 +ENTRY(inswb) + mov ip, sp + stmfd sp!, {r4 - r10 ,fp ,ip ,lr ,pc} + sub fp, ip, #4 + cmp r0, #0x00c00000 + movge r3, #0 + movlt r3, #0xf0000000 + add r0, r3, r0, lsl #2 + tst r1, #3 + beq Linswok + tst r1, #1 + bne Linsw_notaligned + cmp r2, #1 + ldrge r4, [r0] + strgeb r4, [r1], #1 + movgt r4, r4, LSR#8 + strgtb r4, [r1], #1 + ldmleea fp, {r4 - r10, fp, sp, pc}^ + sub r2, r2, #2 +Linswok: mov ip, #0xFF + orr ip, ip, ip, lsl #8 +Linswlp: subs r2, r2, #64 + bmi Linsw_toosmall + IN(r3) + IN(r4) + IN(r5) + IN(r6) + IN(r7) + IN(r8) + IN(r9) + IN(r10) + stmia r1!, {r3 - r10} + IN(r3) + IN(r4) + IN(r5) + IN(r6) + IN(r7) + IN(r8) + IN(r9) + IN(r10) + stmia r1!, {r3 - r10} + bne Linswlp + LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) +Linsw_toosmall: + add r2, r2, #32 + bmi Linsw_toosmall2 +Linsw2lp: IN(r3) + IN(r4) + IN(r5) + IN(r6) + IN(r7) + IN(r8) + IN(r9) + IN(r10) + stmia r1!, {r3 - r10} + LOADREGS(eqea, fp, {r4 - r10, fp, sp, pc}) + b Linsw_notaligned +Linsw_toosmall2: + add r2, r2, #32 +Linsw_notaligned: + cmp r2, #1 + LOADREGS(ltea, fp, {r4 - r10, fp, sp, pc}) + ldr r4, [r0] + strb r4, [r1], #1 + movgt r4, r4, LSR#8 + strgtb r4, [r1], #1 + subs r2, r2, #2 + bgt Linsw_notaligned + LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) + +@ Purpose: write a block of data from memory to a hardware register. +@ Proto : outsw(int to_reg, void *from, int len_in_words); +@ Proto : outswb(int to_reg, void *from, int len_in_bytes); +@ Notes : increments from + +ENTRY(outsw) + mov r2, r2, LSL#1 +ENTRY(outswb) + mov ip, sp + stmfd sp!, {r4 - r8, fp, ip, lr, pc} + sub fp, ip, #4 + cmp r0, #0x00c00000 + movge r3, #0 + movlt r3, #0xf0000000 + tst r1, #2 + beq Loutsw32lp + ldr r4, [r1], #2 + mov r4, r4, lsl #16 + orr r4, r4, r4, lsr #16 + str r4, [r3, r0, lsl #2] + sub r2, r2, #2 + teq r2, #0 + LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) +Loutsw32lp: subs r2,r2,#32 + blt Loutsw_toosmall + ldmia r1!,{r4,r5,r6,r7} + OUT(r4) + OUT(r5) + OUT(r6) + OUT(r7) + ldmia r1!,{r4,r5,r6,r7} + OUT(r4) + OUT(r5) + OUT(r6) + OUT(r7) + LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) + b Loutsw32lp +Loutsw_toosmall: + adds r2,r2,#32 + LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) +Llpx: ldr r4,[r1],#2 + mov r4,r4,LSL#16 + orr r4,r4,r4,LSR#16 + str r4,[r3,r0,LSL#2] + subs r2,r2,#2 + bgt Llpx + LOADREGS(ea, fp, {r4 - r8, fp, sp, pc}) + diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/ll_char_wr.S linux/arch/arm/lib/ll_char_wr.S --- v2.1.79/linux/arch/arm/lib/ll_char_wr.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/ll_char_wr.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,157 @@ +/* + * linux/arch/arm/lib/ll_char_wr.S + * + * Copyright (C) 1995, 1996 Russell King. + * + * Speedups & 1bpp code (C) 1996 Philip Blundel & Russell King. + * + * 10-04-96 RMK Various cleanups & reduced register usage. + */ + +@ Regs: [] = corruptable +@ {} = used +@ () = dont use + +#include +#include + .text + +#define BOLD 0x01 +#define ITALIC 0x02 +#define UNDERLINE 0x04 +#define FLASH 0x08 +#define INVERSE 0x10 + +LC0: .word SYMBOL_NAME(bytes_per_char_h) + .word SYMBOL_NAME(video_size_row) + .word SYMBOL_NAME(cmap_80) + .word SYMBOL_NAME(con_charconvtable) + +ENTRY(ll_write_char) + stmfd sp!, {r4 - r7, lr} +@ +@ Smashable regs: {r0 - r3}, [r4 - r7], (r8 - fp), [ip], (sp), [lr], (pc) +@ + eor ip, r1, #UNDERLINE << 24 +/* + * calculate colours + */ + tst r1, #INVERSE << 24 + moveq r2, r1, lsr #8 + moveq r3, r1, lsr #16 + movne r2, r1, lsr #16 + movne r3, r1, lsr #8 + and r3, r3, #255 + and r2, r2, #255 +/* + * calculate offset into character table + */ + and r1, r1, #255 + mov r1, r1, lsl #3 +/* + * calculate offset required for each row [maybe I should make this an argument to this fn. + * Have to see what the register usage is like in the calling routines. + */ + adr r4, LC0 + ldmia r4, {r4, r5, r6, lr} + ldr r4, [r4] + ldr r5, [r5] +/* + * Go to resolution-dependent routine... + */ + cmp r4, #4 + blt Lrow1bpp + eor r2, r3, r2 @ Create eor mask to change colour from bg + orr r3, r3, r3, lsl #8 @ to fg. + orr r3, r3, r3, lsl #16 + add r0, r0, r5, lsl #3 @ Move to bottom of character + add r1, r1, #7 + ldrb r7, [r6, r1] + tst ip, #UNDERLINE << 24 + eoreq r7, r7, #255 + teq r4, #8 + beq Lrow8bpplp +@ +@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) +@ + orr r3, r3, r3, lsl #4 +Lrow4bpplp: ldr r7, [lr, r7, lsl #2] + mul r7, r2, r7 + tst r1, #7 @ avoid using r7 directly after + eor ip, r3, r7 + str ip, [r0, -r5]! + LOADREGS(eqfd, sp!, {r4 - r7, pc}) + sub r1, r1, #1 + ldrb r7, [r6, r1] + ldr r7, [lr, r7, lsl #2] + mul r7, r2, r7 + tst r1, #7 @ avoid using r7 directly after + eor ip, r3, r7 + str ip, [r0, -r5]! + subne r1, r1, #1 + ldrneb r7, [r6, r1] + bne Lrow4bpplp + LOADREGS(fd, sp!, {r4 - r7, pc}) + +@ +@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc) +@ +Lrow8bpplp: mov ip, r7, lsr #4 + ldr ip, [lr, ip, lsl #2] + mul r4, r2, ip + and ip, r7, #15 + eor r4, r3, r4 + ldr ip, [lr, ip, lsl #2] + mul ip, r2, ip + tst r1, #7 + eor ip, r3, ip + sub r0, r0, r5 + stmia r0, {r4, ip} + LOADREGS(eqfd, sp!, {r4 - r7, pc}) + sub r1, r1, #1 + ldrb r7, [r6, r1] + mov ip, r7, lsr #4 + ldr ip, [lr, ip, lsl #2] + mul r4, r2, ip + and ip, r7, #15 + eor r4, r3, r4 + ldr ip, [lr, ip, lsl #2] + mul ip, r2, ip + tst r1, #7 + eor ip, r3, ip + sub r0, r0, r5 + stmia r0, {r4, ip} + subne r1, r1, #1 + ldrneb r7, [r6, r1] + bne Lrow8bpplp + LOADREGS(fd, sp!, {r4 - r7, pc}) + +@ +@ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc) +@ +Lrow1bpp: add r6, r6, r1 + ldmia r6, {r4, r7} + tst ip, #INVERSE << 24 + mvnne r4, r4 + mvnne r7, r7 + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + mov r4, r4, lsr #8 + strb r4, [r0], r5 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + strb r7, [r0], r5 + mov r7, r7, lsr #8 + tst ip, #UNDERLINE << 24 + mvneq r7, r7 + strb r7, [r0], r5 + LOADREGS(fd, sp!, {r4 - r7, pc}) + + .bss +ENTRY(con_charconvtable) + .space 1024 diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/loaders.S linux/arch/arm/lib/loaders.S --- v2.1.79/linux/arch/arm/lib/loaders.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/loaders.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,53 @@ +/* + * linux/arch/arm/lib/loaders.S + * + * This file contains the ROM loaders for buggy cards + */ +#include +#include + +/* + * Oak SCSI + */ + +ENTRY(oak_scsi_loader) + b Loak_scsi_read + .word 0 +Loak_scsi_reset: bic r10, r11, #0x00ff0000 + ldr r2, [r10] + RETINSTR(mov,pc,lr) + +Loak_scsi_read: mov r2, r1, lsr #3 + and r2, r2, #15 << 9 + bic r10, r11, #0x00ff0000 + ldr r2, [r10, r2] + mov r2, r1, lsl #20 + ldrb r0, [r11, r2, lsr #18] + ldr r2, [r10] + RETINSTR(mov,pc,lr) + +ENTRY(atomwide_serial_loader) + b Latomwide_serial_read + .word 0 +Latomwide_serial_reset: mov r2, #0x3c00 + strb r2, [r11, r2] + RETINSTR(mov,pc,lr) + +Latomwide_serial_read: cmp r1, #0x8000 + RETINSTR(movhi,pc,lr) + add r0, r1, #0x800 + mov r0, r0, lsr #11 + mov r3, #0x3c00 + strb r0, [r11, r3] + mov r2, r1, lsl #21 + ldrb r0, [r11, r2, lsr #19] + strb r2, [r11, r3] + RETINSTR(mov,pc,lr) + +/* + * Cards we don't know about yet + */ +ENTRY(noloader) + mov r0, r0 + mov r0, #0 + RETINSTR(mov,pc,lr) diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/memcpy.S linux/arch/arm/lib/memcpy.S --- v2.1.79/linux/arch/arm/lib/memcpy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/memcpy.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,312 @@ +/* + * linux/arch/arm/lib/segment.S + * + * Copyright (C) 1995, 1996 Russell King + * Except memcpy/memmove routine. + */ + +#include +#include + + .text +#define ENTER \ + mov ip,sp ;\ + stmfd sp!,{r4-r9,fp,ip,lr,pc} ;\ + sub fp,ip,#4 + +#define EXIT \ + LOADREGS(ea, fp, {r4 - r9, fp, sp, pc}) + +#define EXITEQ \ + LOADREGS(eqea, fp, {r4 - r9, fp, sp, pc}) + +# Prototype: void memcpy(void *to,const void *from,unsigned long n); +# ARM3: cant use memcopy here!!! + +ENTRY(memcpy) +ENTRY(memmove) + ENTER + cmp r1, r0 + bcc 19f + subs r2, r2, #4 + blt 6f + ands ip, r0, #3 + bne 7f + ands ip, r1, #3 + bne 8f + +1: subs r2, r2, #8 + blt 5f + subs r2, r2, #0x14 + blt 3f +2: ldmia r1!,{r3 - r9, ip} + stmia r0!,{r3 - r9, ip} + subs r2, r2, #32 + bge 2b + cmn r2, #16 + ldmgeia r1!, {r3 - r6} + stmgeia r0!, {r3 - r6} + subge r2, r2, #0x10 +3: adds r2, r2, #0x14 +4: ldmgeia r1!, {r3 - r5} + stmgeia r0!, {r3 - r5} + subges r2, r2, #12 + bge 4b +5: adds r2, r2, #8 + blt 6f + subs r2, r2, #4 + ldrlt r3, [r1], #4 + strlt r3, [r0], #4 + ldmgeia r1!, {r3, r4} + stmgeia r0!, {r3, r4} + subge r2, r2, #4 + +6: adds r2, r2, #4 + EXITEQ + cmp r2, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 + EXIT + +7: rsb ip, ip, #4 + cmp ip, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 + subs r2, r2, ip + blt 6b + ands ip, r1, #3 + beq 1b +8: bic r1, r1, #3 + ldr r7, [r1], #4 + cmp ip, #2 + bgt 15f + beq 11f + cmp r2, #12 + blt 10f + sub r2, r2, #12 +9: mov r3, r7, lsr #8 + ldmia r1!, {r4 - r7} + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + stmia r0!, {r3 - r6} + subs r2, r2, #16 + bge 9b + adds r2, r2, #12 + blt 1b +10: mov r3, r7, lsr #8 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl #24 + str r3, [r0], #4 + subs r2, r2, #4 + bge 10b + sub r1, r1, #3 + b 6b + +11: cmp r2, #12 + blt 13f /* */ + sub r2, r2, #12 +12: mov r3, r7, lsr #16 + ldmia r1!, {r4 - r7} + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7,LSL#16 + stmia r0!, {r3 - r6} + subs r2, r2, #16 + bge 12b + adds r2, r2, #12 + blt 14f +13: mov r3, r7, lsr #16 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl #16 + str r3, [r0], #4 + subs r2, r2, #4 + bge 13b +14: sub r1, r1, #2 + b 6b + +15: cmp r2, #12 + blt 17f + sub r2, r2, #12 +16: mov r3, r7, lsr #24 + ldmia r1!,{r4 - r7} + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + stmia r0!, {r3 - r6} + subs r2, r2, #16 + bge 16b + adds r2, r2, #12 + blt 18f +17: mov r3, r7, lsr #24 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl#8 + str r3, [r0], #4 + subs r2, r2, #4 + bge 17b +18: sub r1, r1, #1 + b 6b + + +19: add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt 24f + ands ip, r0, #3 + bne 25f + ands ip, r1, #3 + bne 26f + +20: subs r2, r2, #8 + blt 23f + subs r2, r2, #0x14 + blt 22f +21: ldmdb r1!, {r3 - r9, ip} + stmdb r0!, {r3 - r9, ip} + subs r2, r2, #32 + bge 21b +22: cmn r2, #16 + ldmgedb r1!, {r3 - r6} + stmgedb r0!, {r3 - r6} + subge r2, r2, #16 + adds r2, r2, #20 + ldmgedb r1!, {r3 - r5} + stmgedb r0!, {r3 - r5} + subge r2, r2, #12 +23: adds r2, r2, #8 + blt 24f + subs r2, r2, #4 + ldrlt r3, [r1, #-4]! + strlt r3, [r0, #-4]! + ldmgedb r1!, {r3, r4} + stmgedb r0!, {r3, r4} + subge r2, r2, #4 + +24: adds r2, r2, #4 + EXITEQ + cmp r2, #2 + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! + EXIT + +25: cmp ip, #2 + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! + subs r2, r2, ip + blt 24b + ands ip, r1, #3 + beq 20b + +26: bic r1, r1, #3 + ldr r3, [r1], #0 + cmp ip, #2 + blt 34f + beq 30f + cmp r2, #12 + blt 28f + sub r2, r2, #12 +27: mov r7, r3, lsl #8 + ldmdb r1!, {r3, r4, r5, r6} + orr r7, r7, r6, lsr #24 + mov r6, r6, lsl #8 + orr r6, r6, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r3, lsr #24 + stmdb r0!, {r4, r5, r6, r7} + subs r2, r2, #16 + bge 27b + adds r2, r2, #12 + blt 29f +28: mov ip, r3, lsl #8 + ldr r3, [r1, #-4]! + orr ip, ip, r3, lsr #24 + str ip, [r0, #-4]! + subs r2, r2, #4 + bge 28b +29: add r1, r1, #3 + b 24b + +30: cmp r2, #12 + blt 32f + sub r2, r2, #12 +31: mov r7, r3, lsl #16 + ldmdb r1!, {r3, r4, r5, r6} + orr r7, r7, r6, lsr #16 + mov r6, r6, lsl #16 + orr r6, r6, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r3, lsr #16 + stmdb r0!, {r4, r5, r6, r7} + subs r2, r2, #16 + bge 31b + adds r2, r2, #12 + blt 33f +32: mov ip, r3, lsl #16 + ldr r3, [r1, #-4]! + orr ip, ip, r3, lsr #16 + str ip, [r0, #-4]! + subs r2, r2, #4 + bge 32b +33: add r1, r1, #2 + b 24b + +34: cmp r2, #12 + blt 36f + sub r2, r2, #12 +35: mov r7, r3, lsl #24 + ldmdb r1!, {r3, r4, r5, r6} + orr r7, r7, r6, lsr #8 + mov r6, r6, lsl #24 + orr r6, r6, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r3, lsr #8 + stmdb r0!, {r4, r5, r6, r7} + subs r2, r2, #16 + bge 35b + adds r2, r2, #12 + blt 37f +36: mov ip, r3, lsl #24 + ldr r3, [r1, #-4]! + orr ip, ip, r3, lsr #8 + str ip, [r0, #-4]! + subs r2, r2, #4 + bge 36b +37: add r1, r1, #1 + b 24b + + .align + diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/memfastset.S linux/arch/arm/lib/memfastset.S --- v2.1.79/linux/arch/arm/lib/memfastset.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/memfastset.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,35 @@ +/* + * linux/arch/arm/lib/memfastset.S + * + * Copyright (C) 1995, 1996 Russell King + */ +#include +#include + .text +@ Prototype: void memsetl (unsigned long *d, unsigned long c, size_t n); + +ENTRY(memsetl) + stmfd sp!, {lr} + cmp r2, #16 + blt 5f + mov r3, r1 + mov ip, r1 + mov lr, r1 + subs r2, r2, #32 + bmi 2f +1: stmia r0!, {r1, r3, ip, lr} + stmia r0!, {r1, r3, ip, lr} + LOADREGS(eqfd, sp!, {pc}) + subs r2, r2, #32 + bpl 1b +2: adds r2, r2, #16 + bmi 4f +3: stmia r0!, {r1, r3, ip, lr} + LOADREGS(eqfd, sp!, {pc}) + subs r2, r2, #16 + bpl 3b +4: add r2, r2, #16 +5: subs r2, r2, #4 + strge r1, [r0], #4 + bgt 5b + LOADREGS(fd, sp!, {pc}) diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/string.S linux/arch/arm/lib/string.S --- v2.1.79/linux/arch/arm/lib/string.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/string.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,139 @@ +/* + * linux/arch/arm/lib/string.S + * + * Copyright (C) 1995, 1996 Russell King + */ +#include +#include + .text +# Prototype: char *strrchr(const char *s,char c); + +@ r0 = pointer, r1 = length + .global memzero +memzero: stmfd sp!, {lr} + mov r2, #0 + mov r3, #0 + mov ip, #0 + mov lr, #0 +1: subs r1, r1, #4*8 + stmgeia r0!, {r2, r3, ip, lr} + stmgeia r0!, {r2, r3, ip, lr} + bgt 1b + LOADREGS(fd, sp!, {pc}) + + .global __page_memcpy +__page_memcpy: stmfd sp!, {r4, r5, lr} +1: subs r2, r2, #4*8 + ldmgeia r1!, {r3, r4, r5, ip} + stmgeia r0!, {r3, r4, r5, ip} + ldmgeia r1!, {r3, r4, r5, ip} + stmgeia r0!, {r3, r4, r5, ip} + bgt 1b + LOADREGS(fd, sp!, {r4, r5, pc}) + + .global memset +memset: mov r3, r0 + cmp r2, #16 + blt 6f + ands ip, r3, #3 + beq 1f + cmp ip, #2 + strltb r1, [r3], #1 @ Align destination + strleb r1, [r3], #1 + strb r1, [r3], #1 + rsb ip, ip, #4 + sub r2, r2, ip +1: orr r1, r1, r1, lsl #8 + orr r1, r1, r1, lsl #16 + cmp r2, #256 + blt 4f + stmfd sp!, {r4, r5, lr} + mov r4, r1 + mov r5, r1 + mov lr, r1 + mov ip, r2, lsr #6 + sub r2, r2, ip, lsl #6 +2: stmia r3!, {r1, r4, r5, lr} @ 64 bytes at a time. + stmia r3!, {r1, r4, r5, lr} + stmia r3!, {r1, r4, r5, lr} + stmia r3!, {r1, r4, r5, lr} + subs ip, ip, #1 + bne 2b + teq r2, #0 + LOADREGS(eqfd, sp!, {r4, r5, pc}) @ Now <64 bytes to go. + tst r2, #32 + stmneia r3!, {r1, r4, r5, lr} + stmneia r3!, {r1, r4, r5, lr} + tst r2, #16 + stmneia r3!, {r1, r4, r5, lr} + ldmia sp!, {r4, r5} +3: tst r2, #8 + stmneia r3!, {r1, lr} + tst r2, #4 + strne r1, [r3], #4 + tst r2, #2 + strneb r1, [r3], #1 + strneb r1, [r3], #1 + tst r2, #1 + strneb r1, [r3], #1 + LOADREGS(fd, sp!, {pc}) + +4: movs ip, r2, lsr #3 + beq 3b + sub r2, r2, ip, lsl #3 + stmfd sp!, {lr} + mov lr, r1 + subs ip, ip, #4 +5: stmgeia r3!, {r1, lr} + stmgeia r3!, {r1, lr} + stmgeia r3!, {r1, lr} + stmgeia r3!, {r1, lr} + subges ip, ip, #4 + bge 5b + tst ip, #2 + stmneia r3!, {r1, lr} + stmneia r3!, {r1, lr} + tst ip, #1 + stmneia r3!, {r1, lr} + teq r2, #0 + LOADREGS(eqfd, sp!, {pc}) + b 3b + +6: subs r2, r2, #1 + strgeb r1, [r3], #1 + bgt 6b + RETINSTR(mov, pc, lr) + +ENTRY(strrchr) + stmfd sp!, {lr} + mov r3, #0 +1: ldrb r2, [r0], #1 + teq r2, r1 + moveq r3, r0 + teq r2, #0 + bne 1b + mov r0, r3 + LOADREGS(fd, sp!, {pc}) + +ENTRY(strchr) + stmfd sp!,{lr} + mov r3, #0 +1: ldrb r2, [r0], #1 + teq r2, r1 + teqne r2, #0 + bne 1b + teq r2, #0 + moveq r0, #0 + subne r0, r0, #1 + LOADREGS(fd, sp!, {pc}) + +ENTRY(memchr) + stmfd sp!, {lr} +1: ldrb r3, [r0], #1 + teq r3, r1 + beq 2f + subs r2, r2, #1 + bpl 1b +2: movne r0, #0 + subeq r0, r0, #1 + LOADREGS(fd, sp!, {pc}) diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/system.S linux/arch/arm/lib/system.S --- v2.1.79/linux/arch/arm/lib/system.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/system.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,21 @@ +/* + * linux/arch/arm/lib/system.S + * + * Copyright (C) 1995, 1996 Russell King + * + * 07/06/96: Now support tasks running in SVC mode. + */ +#include +#include +#include + + .text + +ENTRY(abort) + adr r0, .abort_msg + mov r1, lr + b SYMBOL_NAME(panic) + +.abort_msg: .ascii "Eek! Got to an abort() from %p! " + .ascii "(Please report to rmk@ecs.soton.ac.uk)\n\0" + .align diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/testm.c linux/arch/arm/lib/testm.c --- v2.1.79/linux/arch/arm/lib/testm.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/testm.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,81 @@ +char buffer[1036]; +char buffer2[1036]; + +int main () +{ + char *p; + int i, o, o2, l; + + printf ("Testing memset\n"); + for (l = 1; l < 1020; l ++) { + for (o = 0; o < 4; o++) { + p = buffer + o + 4; + for (i = 0; i < l + 12; i++) + buffer[i] = 0x55; + + memset (p, 0xaa, l); + + for (i = 0; i < l; i++) + if (p[i] != 0xaa) + printf ("Error: %X+%d\n", p, i); + if (p[-1] != 0x55 || p[-2] != 0x55 || p[-3] != 0x55 || p[-4] != 0x55) + printf ("Error before %X\n", p); + if (p[l] != 0x55 || p[l+1] != 0x55 || p[l+2] != 0x55 || p[l+3] != 0x55) + printf ("Error at end: %p: %02X %02X %02X %02X\n", p+l, p[l], p[l+1], p[l+2], p[l+3]); + } + } + + printf ("Testing memcpy s > d\n"); + for (l = 1; l < 1020; l++) { + for (o = 0; o < 4; o++) { + for (o2 = 0; o2 < 4; o2++) { + char *d, *s; + + for (i = 0; i < l + 12; i++) + buffer[i] = (i & 0x3f) + 0x40; + for (i = 0; i < 1036; i++) + buffer2[i] = 0; + + s = buffer + o; + d = buffer2 + o2 + 4; + + memcpy (d, s, l); + + for (i = 0; i < l; i++) + if (s[i] != d[i]) + printf ("Error at %X+%d -> %X+%d (%02X != %02X)\n", s, i, d, i, s[i], d[i]); + if (d[-1] || d[-2] || d[-3] || d[-4]) + printf ("Error before %X\n", d); + if (d[l] || d[l+1] || d[l+2] || d[l+3]) + printf ("Error after %X\n", d+l); + } + } + } + + printf ("Testing memcpy s < d\n"); + for (l = 1; l < 1020; l++) { + for (o = 0; o < 4; o++) { + for (o2 = 0; o2 < 4; o2++) { + char *d, *s; + + for (i = 0; i < l + 12; i++) + buffer2[i] = (i & 0x3f) + 0x40; + for (i = 0; i < 1036; i++) + buffer[i] = 0; + + s = buffer2 + o; + d = buffer + o2 + 4; + + memcpy (d, s, l); + + for (i = 0; i < l; i++) + if (s[i] != d[i]) + printf ("Error at %X+%d -> %X+%d (%02X != %02X)\n", s, i, d, i, s[i], d[i]); + if (d[-1] || d[-2] || d[-3] || d[-4]) + printf ("Error before %X\n", d); + if (d[l] || d[l+1] || d[l+2] || d[l+3]) + printf ("Error after %X\n", d+l); + } + } + } +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/uaccess-armo.S linux/arch/arm/lib/uaccess-armo.S --- v2.1.79/linux/arch/arm/lib/uaccess-armo.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/uaccess-armo.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,230 @@ +/* + * arch/arm/lib/uaccess-armo.S + * + * Copyright (C) 1998 Russell King + * + * Note! Some code fragments found in here have a special calling + * convention - they are not APCS compliant! + */ +#include +#include + + .text + +#define USER(x...) \ +9999: x; \ + .section __ex_table,"a"; \ + .align 3; \ + .long 9999b,9001f; \ + .previous + + .globl SYMBOL_NAME(uaccess_user) +SYMBOL_NAME(uaccess_user): + .word uaccess_user_put_byte + .word uaccess_user_get_byte + .word uaccess_user_put_half + .word uaccess_user_get_half + .word uaccess_user_put_word + .word uaccess_user_get_word + .word __arch_copy_from_user + .word __arch_copy_to_user + .word __arch_clear_user + .word __arch_strncpy_from_user + .word __arch_strlen_user + + +@ In : r0 = x, r1 = addr, r2 = error +@ Out: r2 = error +uaccess_user_put_byte: + stmfd sp!, {lr} +USER( strbt r0, [r1]) + ldmfd sp!, {pc}^ + +@ In : r0 = x, r1 = addr, r2 = error +@ Out: r2 = error +uaccess_user_put_half: + stmfd sp!, {lr} +USER( strbt r0, [r1], #1) + mov r0, r0, lsr #8 +USER( strbt r0, [r1]) + ldmfd sp!, {pc}^ + +@ In : r0 = x, r1 = addr, r2 = error +@ Out: r2 = error +uaccess_user_put_word: + stmfd sp!, {lr} +USER( strt r0, [r1]) + ldmfd sp!, {pc}^ + +9001: mov r2, #-EFAULT + ldmfd sp!, {pc}^ + +@ In : r0 = addr, r1 = error +@ Out: r0 = x, r1 = error +uaccess_user_get_byte: + stmfd sp!, {lr} +USER( ldrbt r0, [r0]) + ldmfd sp!, {pc}^ + +@ In : r0 = addr, r1 = error +@ Out: r0 = x, r1 = error +uaccess_user_get_half: + stmfd sp!, {lr} +USER( ldrt r0, [r0]) + mov r0, r0, lsl #16 + mov r0, r0, lsr #16 + ldmfd sp!, {pc}^ + +@ In : r0 = addr, r1 = error +@ Out: r0 = x, r1 = error +uaccess_user_get_word: + stmfd sp!, {lr} +USER( ldrt r0, [r0]) + ldmfd sp!, {pc}^ + +9001: mov r1, #-EFAULT + ldmfd sp!, {pc}^ + + + + .globl SYMBOL_NAME(uaccess_kernel) +SYMBOL_NAME(uaccess_kernel): + .word uaccess_kernel_put_byte + .word uaccess_kernel_get_byte + .word uaccess_kernel_put_half + .word uaccess_kernel_get_half + .word uaccess_kernel_put_word + .word uaccess_kernel_get_word + .word uaccess_kernel_copy + .word uaccess_kernel_copy + .word uaccess_kernel_clear + .word uaccess_kernel_strncpy_from + .word uaccess_kernel_strlen + +@ In : r0 = x, r1 = addr, r2 = error +@ Out: r2 = error +uaccess_kernel_put_byte: + stmfd sp!, {lr} + strb r0, [r1] + ldmfd sp!, {pc}^ + +@ In : r0 = x, r1 = addr, r2 = error +@ Out: r2 = error +uaccess_kernel_put_half: + stmfd sp!, {lr} + strb r0, [r1] + mov r0, r0, lsr #8 + strb r0, [r1, #1] + ldmfd sp!, {pc}^ + +@ In : r0 = x, r1 = addr, r2 = error +@ Out: r2 = error +uaccess_kernel_put_word: + stmfd sp!, {lr} + str r0, [r1] + ldmfd sp!, {pc}^ + +@ In : r0 = addr, r1 = error +@ Out: r0 = x, r1 = error +uaccess_kernel_get_byte: + stmfd sp!, {lr} + ldrb r0, [r0] + ldmfd sp!, {pc}^ + +@ In : r0 = addr, r1 = error +@ Out: r0 = x, r1 = error +uaccess_kernel_get_half: + stmfd sp!, {lr} + ldr r0, [r0] + mov r0, r0, lsl #16 + mov r0, r0, lsr #16 + ldmfd sp!, {pc}^ + +@ In : r0 = addr, r1 = error +@ Out: r0 = x, r1 = error +uaccess_kernel_get_word: + stmfd sp!, {lr} + ldr r0, [r0] + ldmfd sp!, {pc}^ + + +/* Prototype: int uaccess_kernel_copy(void *to, const char *from, size_t n) + * Purpose : copy a block to kernel memory from kernel memory + * Params : to - kernel memory + * : from - kernel memory + * : n - number of bytes to copy + * Returns : Number of bytes NOT copied. + */ +uaccess_kernel_copy: + stmfd sp!, {lr} + bl SYMBOL_NAME(memcpy) + mov r0, #0 + ldmfd sp!, {pc}^ + +/* Prototype: int uaccess_kernel_clear(void *addr, size_t sz) + * Purpose : clear some kernel memory + * Params : addr - kernel memory address to clear + * : sz - number of bytes to clear + * Returns : number of bytes NOT cleared + */ +uaccess_kernel_clear: + stmfd sp!, {lr} + mov r2, #0 + cmp r1, #4 + blt 2f + ands ip, r0, #3 + beq 1f + cmp ip, #1 + strb r2, [r0], #1 + strleb r2, [r0], #1 + strltb r2, [r0], #1 + rsb ip, ip, #4 + sub r1, r1, ip @ 7 6 5 4 3 2 1 +1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7 + bmi 2f + str r2, [r0], #4 + str r2, [r0], #4 + b 1b +2: adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3 + strpl r2, [r0], #4 + tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x + strneb r2, [r0], #1 + strneb r2, [r0], #1 + tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1 + strneb r2, [r0], #1 + mov r0, #0 + ldmfd sp!, {pc}^ + +/* Prototype: size_t uaccess_kernel_strncpy_from(char *dst, char *src, size_t len) + * Purpose : copy a string from kernel memory to kernel memory + * Params : dst - kernel memory destination + * : src - kernel memory source + * : len - maximum length of string + * Returns : number of characters copied + */ +uaccess_kernel_strncpy_from: + stmfd sp!, {lr} + mov ip, r2 +1: subs r2, r2, #1 + bmi 2f + ldrb r3, [r1], #1 + strb r3, [r0], #1 + teq r3, #0 + bne 1b +2: subs r0, ip, r2 + ldmfd sp!, {pc}^ + +/* Prototype: int uaccess_kernel_strlen(char *str) + * Purpose : get length of a string in kernel memory + * Params : str - address of string in kernel memory + * Returns : length of string *including terminator*, or zero on error + */ +uaccess_kernel_strlen: + stmfd sp!, {lr} + mov r2, r0 +1: ldrb r1, [r0], #1 + teq r1, #0 + bne 1b + sub r0, r0, r2 + ldmfd sp!, {pc}^ + diff -u --recursive --new-file v2.1.79/linux/arch/arm/lib/uaccess.S linux/arch/arm/lib/uaccess.S --- v2.1.79/linux/arch/arm/lib/uaccess.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/uaccess.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,631 @@ +/* + * linux/arch/arm/lib/uaccess.S + * + * Copyright (C) 1995, 1996,1997,1998 Russell King + * + * Routines to block copy data to/from user memory + * These are highly optimised both for the 4k page size + * and for various alignments. + */ +#include +#include +#include +#include + + .text + +#define USER(x...) \ +9999: x; \ + .section __ex_table,"a"; \ + .align 3; \ + .long 9999b,9001f; \ + .previous + +#define PAGE_SHIFT 12 + +/* Prototype: int __arch_copy_to_user(void *to, const char *from, size_t n) + * Purpose : copy a block to user memory from kernel memory + * Params : to - user memory + * : from - kernel memory + * : n - number of bytes to copy + * Returns : Number of bytes NOT copied. + */ + +.c2u_dest_not_aligned: + rsb ip, ip, #4 + cmp ip, #2 + ldrb r3, [r1], #1 +USER( strbt r3, [r0], #1) // May fault + ldrgeb r3, [r1], #1 +USER( strgebt r3, [r0], #1) // May fault + ldrgtb r3, [r1], #1 +USER( strgtbt r3, [r0], #1) // May fault + sub r2, r2, ip + b .c2u_dest_aligned + +ENTRY(__arch_copy_to_user) + stmfd sp!, {r2, r4 - r7, lr} + cmp r2, #4 + blt .c2u_not_enough + ands ip, r0, #3 + bne .c2u_dest_not_aligned +.c2u_dest_aligned: + + ands ip, r1, #3 + bne .c2u_src_not_aligned +/* + * Seeing as there has to be at least 8 bytes to copy, we can + * copy one word, and force a user-mode page fault... + */ + +.c2u_0fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .c2u_0nowords + ldr r3, [r1], #4 +USER( strt r3, [r0], #4) // May fault + mov ip, r0, lsl #32 - PAGE_SHIFT // On each page, use a ld/st??t instruction + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .c2u_0fupi +/* + * ip = max no. of bytes to copy before needing another "strt" insn + */ + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #32 + blt .c2u_0rem8lp + +.c2u_0cpy8lp: ldmia r1!, {r3 - r6} + stmia r0!, {r3 - r6} // Shouldn't fault + ldmia r1!, {r3 - r6} + stmia r0!, {r3 - r6} // Shouldn't fault + subs ip, ip, #32 + bpl .c2u_0cpy8lp +.c2u_0rem8lp: cmn ip, #16 + ldmgeia r1!, {r3 - r6} + stmgeia r0!, {r3 - r6} // Shouldn't fault + tst ip, #8 + ldmneia r1!, {r3 - r4} + stmneia r0!, {r3 - r4} // Shouldn't fault + tst ip, #4 + ldrne r3, [r1], #4 + strnet r3, [r0], #4 // Shouldn't fault + ands ip, ip, #3 + beq .c2u_0fupi +.c2u_0nowords: teq ip, #0 + beq .c2u_finished +.c2u_nowords: cmp ip, #2 + ldrb r3, [r1], #1 +USER( strbt r3, [r0], #1) // May fault + ldrgeb r3, [r1], #1 +USER( strgebt r3, [r0], #1) // May fault + ldrgtb r3, [r1], #1 +USER( strgtbt r3, [r0], #1) // May fault + b .c2u_finished + +.c2u_not_enough: + movs ip, r2 + bne .c2u_nowords +.c2u_finished: mov r0, #0 + LOADREGS(fd,sp!,{r2, r4 - r7, pc}) + +.c2u_src_not_aligned: + bic r1, r1, #3 + ldr r7, [r1], #4 + cmp ip, #2 + bgt .c2u_3fupi + beq .c2u_2fupi +.c2u_1fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .c2u_1nowords + mov r3, r7, lsr #8 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl #24 +USER( strt r3, [r0], #4) // May fault + mov ip, r0, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .c2u_1fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .c2u_1rem8lp + +.c2u_1cpy8lp: mov r3, r7, lsr #8 + ldmia r1!, {r4 - r7} + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + stmia r0!, {r3 - r6} // Shouldn't fault + subs ip, ip, #16 + bpl .c2u_1cpy8lp +.c2u_1rem8lp: tst ip, #8 + movne r3, r7, lsr #8 + ldmneia r1!, {r4, r7} + orrne r3, r3, r4, lsl #24 + movne r4, r4, lsr #8 + orrne r4, r4, r7, lsl #24 + stmneia r0!, {r3 - r4} // Shouldn't fault + tst ip, #4 + movne r3, r7, lsr #8 + ldrne r7, [r1], #4 + orrne r3, r3, r7, lsl #24 + strnet r3, [r0], #4 // Shouldn't fault + ands ip, ip, #3 + beq .c2u_1fupi +.c2u_1nowords: mov r3, r7, lsr #8 + teq ip, #0 + beq .c2u_finished + cmp ip, #2 +USER( strbt r3, [r0], #1) // May fault + movge r3, r3, lsr #8 +USER( strgebt r3, [r0], #1) // May fault + movgt r3, r3, lsr #8 +USER( strgtbt r3, [r0], #1) // May fault + b .c2u_finished + +.c2u_2fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .c2u_2nowords + mov r3, r7, lsr #16 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl #16 +USER( strt r3, [r0], #4) // May fault + mov ip, r0, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .c2u_2fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .c2u_2rem8lp + +.c2u_2cpy8lp: mov r3, r7, lsr #16 + ldmia r1!, {r4 - r7} + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7, lsl #16 + stmia r0!, {r3 - r6} // Shouldn't fault + subs ip, ip, #16 + bpl .c2u_2cpy8lp +.c2u_2rem8lp: tst ip, #8 + movne r3, r7, lsr #16 + ldmneia r1!, {r4, r7} + orrne r3, r3, r4, lsl #16 + movne r4, r4, lsr #16 + orrne r4, r4, r7, lsl #16 + stmneia r0!, {r3 - r4} // Shouldn't fault + tst ip, #4 + movne r3, r7, lsr #16 + ldrne r7, [r1], #4 + orrne r3, r3, r7, lsl #16 + strnet r3, [r0], #4 // Shouldn't fault + ands ip, ip, #3 + beq .c2u_2fupi +.c2u_2nowords: mov r3, r7, lsr #16 + teq ip, #0 + beq .c2u_finished + cmp ip, #2 +USER( strbt r3, [r0], #1) // May fault + movge r3, r3, lsr #8 +USER( strgebt r3, [r0], #1) // May fault + ldrgtb r3, [r1], #0 +USER( strgtbt r3, [r0], #1) // May fault + b .c2u_finished + +.c2u_3fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .c2u_3nowords + mov r3, r7, lsr #24 + ldr r7, [r1], #4 + orr r3, r3, r7, lsl #8 +USER( strt r3, [r0], #4) // May fault + mov ip, r0, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .c2u_3fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .c2u_3rem8lp + +.c2u_3cpy8lp: mov r3, r7, lsr #24 + ldmia r1!, {r4 - r7} + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + stmia r0!, {r3 - r6} // Shouldn't fault + subs ip, ip, #16 + bpl .c2u_3cpy8lp +.c2u_3rem8lp: tst ip, #8 + movne r3, r7, lsr #24 + ldmneia r1!, {r4, r7} + orrne r3, r3, r4, lsl #8 + movne r4, r4, lsr #24 + orrne r4, r4, r7, lsl #8 + stmneia r0!, {r3 - r4} // Shouldn't fault + tst ip, #4 + movne r3, r7, lsr #24 + ldrne r7, [r1], #4 + orrne r3, r3, r7, lsl #8 + strnet r3, [r0], #4 // Shouldn't fault + ands ip, ip, #3 + beq .c2u_3fupi +.c2u_3nowords: mov r3, r7, lsr #24 + teq ip, #0 + beq .c2u_finished + cmp ip, #2 +USER( strbt r3, [r0], #1) // May fault + ldrge r3, [r1], #0 +USER( strgebt r3, [r0], #1) // May fault + movgt r3, r3, lsr #8 +USER( strgtbt r3, [r0], #1) // May fault + b .c2u_finished + + .section .fixup,"ax" + .align 0 +9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc}) + .previous + + + +/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n); + * Purpose : copy a block from user memory to kernel memory + * Params : to - kernel memory + * : from - user memory + * : n - number of bytes to copy + * Returns : Number of bytes NOT copied. + */ +.cfu_dest_not_aligned: + rsb ip, ip, #4 + cmp ip, #2 +USER( ldrbt r3, [r1], #1) // May fault + strb r3, [r0], #1 +USER( ldrgebt r3, [r1], #1) // May fault + strgeb r3, [r0], #1 +USER( ldrgtbt r3, [r1], #1) // May fault + strgtb r3, [r0], #1 + sub r2, r2, ip + b .cfu_dest_aligned + +ENTRY(__arch_copy_from_user) + stmfd sp!, {r2, r4 - r7, lr} + cmp r2, #4 + blt .cfu_not_enough + ands ip, r0, #3 + bne .cfu_dest_not_aligned +.cfu_dest_aligned: + ands ip, r1, #3 + bne .cfu_src_not_aligned +/* + * Seeing as there has to be at least 8 bytes to copy, we can + * copy one word, and force a user-mode page fault... + */ + +.cfu_0fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .cfu_0nowords +USER( ldrt r3, [r1], #4) + str r3, [r0], #4 + mov ip, r1, lsl #32 - PAGE_SHIFT // On each page, use a ld/st??t instruction + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .cfu_0fupi +/* + * ip = max no. of bytes to copy before needing another "strt" insn + */ + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #32 + blt .cfu_0rem8lp + +.cfu_0cpy8lp: ldmia r1!, {r3 - r6} // Shouldn't fault + stmia r0!, {r3 - r6} + ldmia r1!, {r3 - r6} // Shouldn't fault + stmia r0!, {r3 - r6} + subs ip, ip, #32 + bpl .cfu_0cpy8lp +.cfu_0rem8lp: cmn ip, #16 + ldmgeia r1!, {r3 - r6} // Shouldn't fault + stmgeia r0!, {r3 - r6} + tst ip, #8 + ldmneia r1!, {r3 - r4} // Shouldn't fault + stmneia r0!, {r3 - r4} + tst ip, #4 + ldrnet r3, [r1], #4 // Shouldn't fault + strne r3, [r0], #4 + ands ip, ip, #3 + beq .cfu_0fupi +.cfu_0nowords: teq ip, #0 + beq .cfu_finished +.cfu_nowords: cmp ip, #2 +USER( ldrbt r3, [r1], #1) // May fault + strb r3, [r0], #1 +USER( ldrgebt r3, [r1], #1) // May fault + strgeb r3, [r0], #1 +USER( ldrgtbt r3, [r1], #1) // May fault + strgtb r3, [r0], #1 + b .cfu_finished + +.cfu_not_enough: + movs ip, r2 + bne .cfu_nowords +.cfu_finished: mov r0, #0 + LOADREGS(fd,sp!,{r2, r4 - r7, pc}) + +.cfu_src_not_aligned: + bic r1, r1, #3 +USER( ldrt r7, [r1], #4) // May fault + cmp ip, #2 + bgt .cfu_3fupi + beq .cfu_2fupi +.cfu_1fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .cfu_1nowords + mov r3, r7, lsr #8 +USER( ldrt r7, [r1], #4) // May fault + orr r3, r3, r7, lsl #24 + str r3, [r0], #4 + mov ip, r1, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .cfu_1fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .cfu_1rem8lp + +.cfu_1cpy8lp: mov r3, r7, lsr #8 + ldmia r1!, {r4 - r7} // Shouldn't fault + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + stmia r0!, {r3 - r6} + subs ip, ip, #16 + bpl .cfu_1cpy8lp +.cfu_1rem8lp: tst ip, #8 + movne r3, r7, lsr #8 + ldmneia r1!, {r4, r7} // Shouldn't fault + orrne r3, r3, r4, lsl #24 + movne r4, r4, lsr #8 + orrne r4, r4, r7, lsl #24 + stmneia r0!, {r3 - r4} + tst ip, #4 + movne r3, r7, lsr #8 +USER( ldrnet r7, [r1], #4) // May fault + orrne r3, r3, r7, lsl #24 + strne r3, [r0], #4 + ands ip, ip, #3 + beq .cfu_1fupi +.cfu_1nowords: mov r3, r7, lsr #8 + teq ip, #0 + beq .cfu_finished + cmp ip, #2 + strb r3, [r0], #1 + movge r3, r3, lsr #8 + strgeb r3, [r0], #1 + movgt r3, r3, lsr #8 + strgtb r3, [r0], #1 + b .cfu_finished + +.cfu_2fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .cfu_2nowords + mov r3, r7, lsr #16 +USER( ldrt r7, [r1], #4) // May fault + orr r3, r3, r7, lsl #16 + str r3, [r0], #4 + mov ip, r1, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .cfu_2fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .cfu_2rem8lp + +.cfu_2cpy8lp: mov r3, r7, lsr #16 + ldmia r1!, {r4 - r7} // Shouldn't fault + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7, lsl #16 + stmia r0!, {r3 - r6} + subs ip, ip, #16 + bpl .cfu_2cpy8lp +.cfu_2rem8lp: tst ip, #8 + movne r3, r7, lsr #16 + ldmneia r1!, {r4, r7} // Shouldn't fault + orrne r3, r3, r4, lsl #16 + movne r4, r4, lsr #16 + orrne r4, r4, r7, lsl #16 + stmneia r0!, {r3 - r4} + tst ip, #4 + movne r3, r7, lsr #16 +USER( ldrnet r7, [r1], #4) // May fault + orrne r3, r3, r7, lsl #16 + strne r3, [r0], #4 + ands ip, ip, #3 + beq .cfu_2fupi +.cfu_2nowords: mov r3, r7, lsr #16 + teq ip, #0 + beq .cfu_finished + cmp ip, #2 + strb r3, [r0], #1 + movge r3, r3, lsr #8 + strgeb r3, [r0], #1 +USER( ldrgtbt r3, [r1], #0) // May fault + strgtb r3, [r0], #1 + b .cfu_finished + +.cfu_3fupi: subs r2, r2, #4 + addmi ip, r2, #4 + bmi .cfu_3nowords + mov r3, r7, lsr #24 +USER( ldrt r7, [r1], #4) // May fault + orr r3, r3, r7, lsl #8 + str r3, [r0], #4 + mov ip, r1, lsl #32 - PAGE_SHIFT + rsb ip, ip, #0 + movs ip, ip, lsr #32 - PAGE_SHIFT + beq .cfu_3fupi + cmp r2, ip + movlt ip, r2 + sub r2, r2, ip + subs ip, ip, #16 + blt .cfu_3rem8lp + +.cfu_3cpy8lp: mov r3, r7, lsr #24 + ldmia r1!, {r4 - r7} // Shouldn't fault + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + stmia r0!, {r3 - r6} + subs ip, ip, #16 + bpl .cfu_3cpy8lp +.cfu_3rem8lp: tst ip, #8 + movne r3, r7, lsr #24 + ldmneia r1!, {r4, r7} // Shouldn't fault + orrne r3, r3, r4, lsl #8 + movne r4, r4, lsr #24 + orrne r4, r4, r7, lsl #8 + stmneia r0!, {r3 - r4} + tst ip, #4 + movne r3, r7, lsr #24 +USER( ldrnet r7, [r1], #4) // May fault + orrne r3, r3, r7, lsl #8 + strne r3, [r0], #4 + ands ip, ip, #3 + beq .cfu_3fupi +.cfu_3nowords: mov r3, r7, lsr #24 + teq ip, #0 + beq .cfu_finished + cmp ip, #2 + strb r3, [r0], #1 +USER( ldrget r3, [r1], #0) // May fault + strgeb r3, [r0], #1 + movgt r3, r3, lsr #8 + strgtb r3, [r0], #1 + b .cfu_finished + + .section .fixup,"ax" + .align 0 +9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc}) + .previous + +/* Prototype: int __arch_clear_user(void *addr, size_t sz) + * Purpose : clear some user memory + * Params : addr - user memory address to clear + * : sz - number of bytes to clear + * Returns : number of bytes NOT cleared + */ +ENTRY(__arch_clear_user) + stmfd sp!, {r1, lr} + mov r2, #0 + cmp r1, #4 + blt 2f + ands ip, r0, #3 + beq 1f + cmp ip, #1 +USER( strbt r2, [r0], #1) +USER( strlebt r2, [r0], #1) +USER( strltbt r2, [r0], #1) + rsb ip, ip, #4 + sub r1, r1, ip @ 7 6 5 4 3 2 1 +1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7 +USER( strplt r2, [r0], #4) +USER( strplt r2, [r0], #4) + bpl 1b +2: adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3 +USER( strplt r2, [r0], #4) + tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x +USER( strnebt r2, [r0], #1) +USER( strnebt r2, [r0], #1) + tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1 +USER( strnebt r2, [r0], #1) + mov r0, #0 + LOADREGS(fd,sp!, {r1, pc}) + + .section .fixup,"ax" + .align 0 +9001: LOADREGS(fd,sp!, {r0, pc}) + .previous + +/* Prototype: int __arch_strlen_user(char *str) + * Purpose : get length of a string in user memory + * Params : str - address of string in user memory + * Returns : length of string *including terminator*, or zero on error + */ +ENTRY(__arch_strlen_user) + stmfd sp!, {lr} + mov r2, r0 +1: +USER( ldrbt r1, [r0], #1) + teq r1, #0 + bne 1b + sub r0, r0, r2 + LOADREGS(fd,sp!, {pc}) + + .section .fixup,"ax" + .align 0 +9001: mov r0, #0 + LOADREGS(fd,sp!,{pc}) + .previous + +/* Prototype: size_t __arch_strncpy_from_user(char *dst, char *src, size_t len) + * Purpose : copy a string from user memory to kernel memory + * Params : dst - kernel memory destination + * : src - user memory source + * : len - maximum length of string + * Returns : number of characters copied + */ +ENTRY(__arch_strncpy_from_user) + stmfd sp!, {lr} + mov ip, r2 +1: subs r2, r2, #1 + bmi 2f +USER( ldrbt r3, [r1], #1) + strb r3, [r0], #1 + teq r3, #0 + bne 1b +2: subs r0, ip, r2 + LOADREGS(fd,sp!, {pc}) + + .section .fixup,"ax" + .align 0 +9001: mov r0, #-EFAULT + LOADREGS(fd,sp!, {pc}) + .previous + + .align + diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile --- v2.1.79/linux/arch/arm/mm/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/Makefile Tue Jan 20 16:39:42 1998 @@ -0,0 +1,36 @@ +# +# Makefile for the linux arm-specific parts of the memory manager. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +O_TARGET := mm.o +O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(MACHINE).o + +ifeq ($(PROCESSOR),armo) + O_OBJS += proc-arm2,3.o +endif + +ifeq ($(PROCESSOR),armv) + O_OBJS += small_page.o proc-arm6,7.o proc-sa110.o +endif + +include $(TOPDIR)/Rules.make + +proc-arm2,3.o: ../lib/constants.h +proc-arm6,7.o: ../lib/constants.h +proc-sa110.o: ../lib/constants.h + +.PHONY: ../lib/constants.h +../lib/constants.h: + @$(MAKE) -C ../lib constants.h + +%.o: %.S +ifndef $(CONFIG_BINUTILS_NEW) + $(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..tmp.s + $(CC) $(CFLAGS:-pipe=) -c -o $@ ..tmp.s + $(RM) ..tmp.s +endif diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/extable.c linux/arch/arm/mm/extable.c --- v2.1.79/linux/arch/arm/mm/extable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/extable.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,55 @@ +/* + * linux/arch/arm/mm/extable.c + */ + +#include +#include +#include + +extern const struct exception_table_entry __start___ex_table[]; +extern const struct exception_table_entry __stop___ex_table[]; + +static inline unsigned long +search_one_table(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) +{ + while (first <= last) { + const struct exception_table_entry *mid; + long diff; + + mid = (last - first) / 2 + first; + diff = mid->insn - value; + if (diff == 0) + return mid->fixup; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } + return 0; +} + +unsigned long +search_exception_table(unsigned long addr) +{ + unsigned long ret; + +#ifndef CONFIG_MODULES + /* There is only the kernel to search. */ + ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); + if (ret) return ret; +#else + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + for (mp = module_list; mp != NULL; mp = mp->next) { + if (mp->ex_table_start == NULL) + continue; + ret = search_one_table(mp->ex_table_start, + mp->ex_table_end - 1, addr); + if (ret) return ret; + } +#endif + + return 0; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/fault-armo.c linux/arch/arm/mm/fault-armo.c --- v2.1.79/linux/arch/arm/mm/fault-armo.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/fault-armo.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,159 @@ +/* + * linux/arch/arm/mm/fault.c + * + * Copyright (C) 1995 Linus Torvalds + * Modifications for ARM processor (c) 1995, 1996 Russell King + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define FAULT_CODE_FORCECOW 0x80 +#define FAULT_CODE_PREFETCH 0x04 +#define FAULT_CODE_WRITE 0x02 +#define FAULT_CODE_USER 0x01 + +extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret); + +static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs, + struct task_struct *tsk, struct mm_struct *mm) +{ + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + pgd_t *pgd; + if (addr < PAGE_SIZE) + printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + else + printk (KERN_ALERT "Unable to handle kernel paging request"); + printk (" at virtual address %08lx\n", addr); + printk (KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap); + pgd = pgd_offset (mm, addr); + printk (KERN_ALERT "*pgd = %08lx", pgd_val (*pgd)); + if (!pgd_none (*pgd)) { + pmd_t *pmd; + pmd = pmd_offset (pgd, addr); + printk (", *pmd = %08lx", pmd_val (*pmd)); + if (!pmd_none (*pmd)) + printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr))); + } + printk ("\n"); + die_if_kernel ("Oops", regs, mode, SIGKILL); + do_exit (SIGKILL); +} + +static void +handle_dataabort (unsigned long addr, int mode, struct pt_regs *regs) +{ + struct task_struct *tsk; + struct mm_struct *mm; + struct vm_area_struct *vma; + unsigned long fixup; + + lock_kernel(); + tsk = current; + mm = tsk->mm; + + down(&mm->mmap_sem); + vma = find_vma (mm, addr); + if (!vma) + goto bad_area; + if (addr >= vma->vm_start) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack (vma, addr)) + goto bad_area; + + /* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + if (!(mode & FAULT_CODE_WRITE)) { /* write? */ + if (!(vma->vm_flags & (VM_READ|VM_EXEC))) + goto bad_area; + } else { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } + handle_mm_fault (tsk, vma, addr, mode & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW)); + up(&mm->mmap_sem); + goto out; + + /* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + up(&mm->mmap_sem); + if (mode & FAULT_CODE_USER) { +extern int console_loglevel; +cli(); + tsk->tss.error_code = mode; + tsk->tss.trap_no = 14; +console_loglevel = 9; + printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n", + tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); +//#ifdef DEBUG + show_regs (regs); + c_backtrace (regs->ARM_fp, 0); +//#endif + force_sig(SIGSEGV, tsk); +while (1); + goto out; + } + + /* Are we prepared to handle this kernel fault? */ + if ((fixup = search_exception_table(regs->ARM_pc)) != 0) { + printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", + tsk->comm, regs->ARM_pc, addr, fixup); + regs->ARM_pc = fixup; + goto out; + } + + + kernel_page_fault (addr, mode, regs, tsk, mm); +out: + unlock_kernel(); +} + +/* + * Handle a data abort. Note that we have to handle a range of addresses + * on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force + * a copy-on-write + */ +asmlinkage void +do_DataAbort (unsigned long min_addr, unsigned long max_addr, int mode, struct pt_regs *regs) +{ + handle_dataabort (min_addr, mode, regs); + + if ((min_addr ^ max_addr) >> PAGE_SHIFT) + handle_dataabort (max_addr, mode | FAULT_CODE_FORCECOW, regs); +} + +asmlinkage int +do_PrefetchAbort (unsigned long addr, int mode, struct pt_regs *regs) +{ +#if 0 + if (the memc mapping for this page exists - can check now...) { + printk ("Page in, but got abort (undefined instruction?)\n"); + return 0; + } +#endif + handle_dataabort (addr, mode, regs); + return 1; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c --- v2.1.79/linux/arch/arm/mm/fault-armv.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/fault-armv.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,200 @@ +/* + * linux/arch/arm/mm/fault.c + * + * Copyright (C) 1995 Linus Torvalds + * Modifications for ARM processor (c) 1995, 1996 Russell King + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define FAULT_CODE_READ 0x02 +#define FAULT_CODE_USER 0x01 + +extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret); + +static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs, + struct task_struct *tsk, struct mm_struct *mm) +{ + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + pgd_t *pgd; + if (addr < PAGE_SIZE) + printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + else + printk (KERN_ALERT "Unable to handle kernel paging request"); + printk (" at virtual address %08lx\n", addr); + printk (KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap); + pgd = pgd_offset (mm, addr); + printk (KERN_ALERT "*pgd = %08lx", pgd_val (*pgd)); + if (!pgd_none (*pgd)) { + pmd_t *pmd; + pmd = pmd_offset (pgd, addr); + printk (", *pmd = %08lx", pmd_val (*pmd)); + if (!pmd_none (*pmd)) + printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr))); + } + printk ("\n"); + die_if_kernel ("Oops", regs, mode, SIGKILL); + do_exit (SIGKILL); +} + +static void page_fault (unsigned long addr, int mode, struct pt_regs *regs) +{ + struct task_struct *tsk; + struct mm_struct *mm; + struct vm_area_struct *vma; + unsigned long fixup; + + lock_kernel(); + tsk = current; + mm = tsk->mm; + + down(&mm->mmap_sem); + vma = find_vma (mm, addr); + if (!vma) + goto bad_area; + if (vma->vm_start <= addr) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack (vma, addr)) + goto bad_area; + + /* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + if (mode & FAULT_CODE_READ) { /* read? */ + if (!(vma->vm_flags & (VM_READ|VM_EXEC))) + goto bad_area; + } else { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } + handle_mm_fault (tsk, vma, addr & PAGE_MASK, !(mode & FAULT_CODE_READ)); + up(&mm->mmap_sem); + goto out; + + /* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + up(&mm->mmap_sem); + if (mode & FAULT_CODE_USER) { + tsk->tss.error_code = mode; + tsk->tss.trap_no = 14; + printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n", + tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); +#ifdef DEBUG + show_regs (regs); + c_backtrace (regs->ARM_fp, regs->ARM_cpsr); +#endif + force_sig(SIGSEGV, tsk); + goto out; + } + + /* Are we prepared to handle this kernel fault? */ + if ((fixup = search_exception_table(regs->ARM_pc)) != 0) { + printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n", + tsk->comm, regs->ARM_pc, addr, fixup); + regs->ARM_pc = fixup; + goto out; + } + + kernel_page_fault (addr, mode, regs, tsk, mm); +out: + unlock_kernel(); +} + +/* + * Handle a data abort. Note that we have to handle a range of addresses + * on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force + * a copy-on-write + */ +asmlinkage void +do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs) +{ + if (user_mode(regs)) + error_code |= FAULT_CODE_USER; + +#define DIE(signr,nam)\ + force_sig(signr, current);\ + die_if_kernel(nam, regs, fsr, signr);\ + break; + + switch (fsr & 15) { + case 2: + DIE(SIGKILL, "Terminal exception") + case 0: + DIE(SIGSEGV, "Vector exception") + case 1: + case 3: + DIE(SIGBUS, "Alignment exception") + case 12: + case 14: + DIE(SIGBUS, "External abort on translation") + case 9: + case 11: + DIE(SIGSEGV, "Domain fault") + case 13:/* permission fault on section */ +#ifndef DEBUG + { + unsigned int i, j, a; +static int count=2; +if (count-- == 0) while (1); + a = regs->ARM_sp; + for (j = 0; j < 10; j++) { + printk ("%08x: ", a); + for (i = 0; i < 8; i += 1, a += 4) + printk ("%08lx ", *(unsigned long *)a); + printk ("\n"); + } + } +#endif + DIE(SIGSEGV, "Permission fault") + + case 15:/* permission fault on page */ + case 5: /* page-table entry descriptor fault */ + case 7: /* first-level descriptor fault */ + page_fault (addr, error_code, regs); + break; + case 4: + case 6: + DIE(SIGBUS, "External abort on linefetch") + case 8: + case 10: + DIE(SIGBUS, "External abort on non-linefetch") + } +} + +asmlinkage int +do_PrefetchAbort (unsigned long addr, struct pt_regs *regs) +{ +#if 0 + /* does this still apply ? */ + if (the memc mapping for this page exists - can check now...) { + printk ("Page in, but got abort (undefined instruction?)\n"); + return 0; + } +#endif + page_fault (addr, FAULT_CODE_USER|FAULT_CODE_READ, regs); + return 1; +} + diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c --- v2.1.79/linux/arch/arm/mm/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/init.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,215 @@ +/* + * linux/arch/arm/mm/init.c + * + * Copyright (C) 1995, 1996 Russell King + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_BLK_DEV_INITRD +#include +#endif + +#include +#include +#include +#include +#include +#include + +pgd_t swapper_pg_dir[PTRS_PER_PGD]; + +const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n"; +extern char _etext, _stext, _edata, __bss_start, _end; +extern char __init_begin, __init_end; + +/* + * BAD_PAGE is the page that is used for page faults when linux + * is out-of-memory. Older versions of linux just did a + * do_exit(), but using this instead means there is less risk + * for a process dying in kernel mode, possibly leaving a inode + * unused etc.. + * + * BAD_PAGETABLE is the accompanying page-table: it is initialized + * to point to BAD_PAGE entries. + * + * ZERO_PAGE is a special page that is used for zero-initialized + * data and COW. + */ +#if PTRS_PER_PTE != 1 +unsigned long *empty_bad_page_table; + +pte_t *__bad_pagetable(void) +{ + int i; + pte_t bad_page; + + bad_page = BAD_PAGE; + for (i = 0; i < PTRS_PER_PTE; i++) + empty_bad_page_table[i] = (unsigned long)pte_val(bad_page); + return (pte_t *) empty_bad_page_table; +} +#endif + +unsigned long *empty_zero_page; +unsigned long *empty_bad_page; + +pte_t __bad_page(void) +{ + memzero (empty_bad_page, PAGE_SIZE); + return pte_nocache(pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED))); +} + +void show_mem(void) +{ + extern void show_net_buffers(void); + int i,free = 0,total = 0,reserved = 0; + int shared = 0; + + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + i = MAP_NR(high_memory); + while (i-- > 0) { + total++; + if (PageReserved(mem_map+i)) + reserved++; + else if (!atomic_read(&mem_map[i].count)) + free++; + else + shared += atomic_read(&mem_map[i].count) - 1; + } + printk("%d pages of RAM\n",total); + printk("%d free pages\n",free); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + show_buffers(); +#ifdef CONFIG_NET + show_net_buffers(); +#endif +} + +/* + * paging_init() sets up the page tables... + */ +unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) +{ + extern unsigned long free_area_init(unsigned long, unsigned long); + + start_mem = PAGE_ALIGN(start_mem); + empty_zero_page = (unsigned long *)start_mem; + start_mem += PAGE_SIZE; + empty_bad_page = (unsigned long *)start_mem; + start_mem += PAGE_SIZE; +#if PTRS_PER_PTE != 1 + empty_bad_page_table = (unsigned long *)start_mem; + start_mem += PTRS_PER_PTE * sizeof (void *); +#endif + memzero (empty_zero_page, PAGE_SIZE); + start_mem = setup_pagetables (start_mem, end_mem); + + flush_tlb_all (); + update_mm_cache_all (); + + return free_area_init (start_mem, end_mem); +} + +/* + * mem_init() marks the free areas in the mem_map and tells us how much + * memory is free. This is done after various parts of the system have + * claimed their memory after the kernel image. + */ +void mem_init(unsigned long start_mem, unsigned long end_mem) +{ + extern void sound_init(void); + int codepages = 0; + int reservedpages = 0; + int datapages = 0; + int initpages = 0; + unsigned long tmp; + + end_mem &= PAGE_MASK; + high_memory = (void *)end_mem; + max_mapnr = num_physpages = MAP_NR(end_mem); + + /* mark usable pages in the mem_map[] */ + mark_usable_memory_areas(&start_mem, end_mem); + + for (tmp = PAGE_OFFSET; tmp < end_mem ; tmp += PAGE_SIZE) { + if (PageReserved(mem_map+MAP_NR(tmp))) { + if (tmp >= KERNTOPHYS(_stext) && + tmp < KERNTOPHYS(_edata)) { + if (tmp < KERNTOPHYS(_etext)) + codepages++; + else + datapages++; + } else if (tmp >= KERNTOPHYS(__init_begin) + && tmp < KERNTOPHYS(__init_end)) + initpages++; + else if (tmp >= KERNTOPHYS(__bss_start) + && tmp < (unsigned long) start_mem) + datapages++; + else + reservedpages++; + continue; + } + atomic_set(&mem_map[MAP_NR(tmp)].count, 1); +#ifdef CONFIG_BLK_DEV_INITRD + if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end)) +#endif + free_page(tmp); + } + printk ("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n", + (unsigned long) nr_free_pages << (PAGE_SHIFT-10), + max_mapnr << (PAGE_SHIFT-10), + codepages << (PAGE_SHIFT-10), + reservedpages << (PAGE_SHIFT-10), + datapages << (PAGE_SHIFT-10), + initpages << (PAGE_SHIFT-10)); +} + +void free_initmem (void) +{ + unsigned long addr; + + addr = (unsigned long)(&__init_begin); + for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { + mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved); + atomic_set(&mem_map[MAP_NR(addr)].count, 1); + free_page(addr); + } + printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); +} + +void si_meminfo(struct sysinfo *val) +{ + int i; + + i = MAP_NR(high_memory); + val->totalram = 0; + val->sharedram = 0; + val->freeram = nr_free_pages << PAGE_SHIFT; + val->bufferram = buffermem; + while (i-- > 0) { + if (PageReserved(mem_map+i)) + continue; + val->totalram++; + if (!atomic_read(&mem_map[i].count)) + continue; + val->sharedram += atomic_read(&mem_map[i].count) - 1; + } + val->totalram <<= PAGE_SHIFT; + val->sharedram <<= PAGE_SHIFT; +} + diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/mm-a5k.c linux/arch/arm/mm/mm-a5k.c --- v2.1.79/linux/arch/arm/mm/mm-a5k.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/mm-a5k.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,7 @@ +/* + * arch/arm/mm/mm-a5k.c + * + * Extra MM routines for the Archimedes architecture + * + * Copyright (C) 1998 Russell King + */ diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/mm-arc.c linux/arch/arm/mm/mm-arc.c --- v2.1.79/linux/arch/arm/mm/mm-arc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/mm-arc.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,7 @@ +/* + * arch/arm/mm/mm-arc.c + * + * Extra MM routines for the Archimedes architecture + * + * Copyright (C) 1998 Russell King + */ diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/mm-ebsa110.c linux/arch/arm/mm/mm-ebsa110.c --- v2.1.79/linux/arch/arm/mm/mm-ebsa110.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/mm-ebsa110.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,7 @@ +/* + * arch/arm/mm/mm-ebsa110.c + * + * Extra MM routines for the Archimedes architecture + * + * Copyright (C) 1998 Russell King + */ diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/mm-nexuspci.c linux/arch/arm/mm/mm-nexuspci.c --- v2.1.79/linux/arch/arm/mm/mm-nexuspci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/mm-nexuspci.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,7 @@ +/* + * arch/arm/mm/mm-nexuspci.c + * + * Extra MM routines for the Archimedes architecture + * + * Copyright (C) 1998 Russell King + */ diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/mm-rpc.c linux/arch/arm/mm/mm-rpc.c --- v2.1.79/linux/arch/arm/mm/mm-rpc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/mm-rpc.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,80 @@ +/* + * arch/arm/mm/mm-rpc.c + * + * Extra MM routines for RiscPC architecture + * + * Copyright (C) 1998 Russell King + */ + +#include + +#define NR_DRAM_BANKS 4 +#define NR_VRAM_BANKS 1 + +#define NR_BANKS (NR_DRAM_BANKS + NR_VRAM_BANKS) + +#define FIRST_BANK 0 +#define FIRST_DRAM_BANK 0 +#define FIRST_VRAM_BANK NR_DRAM_BANKS + +#define BANK_SHIFT 26 +#define FIRST_DRAM_ADDR 0x10000000 + +#define PHYS_TO_BANK(x) (((x) >> BANK_SHIFT) & (NR_DRAM_BANKS - 1)) +#define BANK_TO_PHYS(x) ((FIRST_DRAM_ADDR) + + (((x) - FIRST_DRAM_BANK) << BANK_SHIFT) + +struct ram_bank { + unsigned int virt_addr; /* virtual address of the *end* of this bank + 1 */ + signed int phys_offset; /* offset to physical address of this bank */ +}; + +static struct ram_bank rambank[NR_BANKS]; + +/* + * Return the physical (0x10000000 -> 0x20000000) address of + * the virtual (0xc0000000 -> 0xd0000000) address + */ +unsigned long __virt_to_phys(unsigned long vpage) +{ + unsigned int bank = FIRST_BANK; + + while (vpage >= rambank[bank].virt_addr && bank < NR_BANKS) + bank ++; + + return vpage - rambank[bank].phys_offset; +} + +/* + * Return the virtual (0xc0000000 -> 0xd0000000) address of + * the physical (0x10000000 -> 0x20000000) address + */ +unsigned long __phys_to_virt(unsigned long phys) +{ + unsigned int bank; + + if (phys > FIRST_DRAM_ADDR) + bank = PHYS_TO_BANK(phys); + else + bank = FIRST_VRAM_BANK; + + return phys + rambank[bank].phys_offset; +} + +void init_dram_banks(struct param_struct *params) +{ + unsigned int bank; + unsigned int bytes = 0; + + for (bank = FIRST_DRAM_BANK; bank < NR_DRAM_BANKS; bank++) { + rambank[bank].phys_offset = PAGE_OFFSET + bytes + - BANK_TO_PHYS(bank); + + bytes += params->u1.s.pages_in_bank[bank - FIRST_DRAM_BANK] * PAGE_SIZE; + + rambank[bank].virt_addr = PAGE_OFFSET + bytes; + } + + drambank[4].phys_offset = 0xd6000000; + drambank[4].virt_addr = 0xd8000000; +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/proc-arm2,3.S linux/arch/arm/mm/proc-arm2,3.S --- v2.1.79/linux/arch/arm/mm/proc-arm2,3.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/proc-arm2,3.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,494 @@ +/* + * linux/arch/arm/mm/arm2,3.S: MMU functions for ARM2,3 + * + * (C) 1997 Russell King + * + * These are the low level assembler for performing cache + * and memory functions on ARM2, ARM250 and ARM3 processors. + */ +#include + +#include +#include "../lib/constants.h" + +/* + * Code common to all processors - MEMC specific not processor + * specific! + */ + +LC1: .word SYMBOL_NAME(page_nr) +/* + * Function: arm2_3_update_map (struct task_struct *tsk) + * + * Params : tsk Task structure to be updated + * + * Purpose : Re-generate memc maps for task from its pseudo page tables + */ +_arm2_3_update_map: + mov ip, sp + stmfd sp!, {r4 - r6, fp, ip, lr, pc} + sub fp, ip, #4 + add r1, r0, #TSS_MEMCMAP + ldr r2, LC1 + ldr r2, [r2] + mov r3, #0x03f00000 + orr r3, r3, #0x00000f00 + orr r4, r3, #1 + orr r5, r3, #2 + orr r6, r3, #3 +1: stmia r1!, {r3, r4, r5, r6} @ Default mapping (null mapping) + add r3, r3, #4 + add r4, r4, #4 + add r5, r5, #4 + add r6, r6, #4 + stmia r1!, {r3, r4, r5, r6} @ Default mapping (null mapping) + add r3, r3, #4 + add r4, r4, #4 + add r5, r5, #4 + add r6, r6, #4 + subs r2, r2, #8 + bhi 1b + + adr r2, Lphystomemc32 @ r2 = conversion table to logical page number + ldr r4, [r0, #TSS_MEMMAP] @ r4 = active mem map + add r5, r4, #32 << 2 @ r5 = end of active mem map + add r0, r0, #TSS_MEMCMAP @ r0 = memc map + + mov r6, #0 +2: ldmia r4!, {r1, r3} + tst r1, #PAGE_PRESENT + blne update_map_pgd + add r6, r6, #32 << 2 + tst r3, #PAGE_PRESENT + blne update_map_pgd3 + add r6, r6, #32 << 2 + cmp r4, r5 + blt 2b + ldmea fp, {r4 - r6, fp, sp, pc}^ + +@ r0,r2,r3,r4,r5 = preserve +@ r1,ip = available +@ r0 = memc map +@ r1 = pgd entry +@ r2 = conversion table +@ r6 = logical page no << 2 + +update_map_pgd3: + mov r1, r3 +update_map_pgd: stmfd sp!, {r3, r4, r5, lr} + bic r4, r1, #3 @ r4 = page table + sub r5, r6, #1 << 2 + add ip, r4, #32 << 2 @ ip = end of page table + +1: ldr r1, [r4], #4 @ get entry + add r5, r5, #1 << 2 + tst r1, #PAGE_PRESENT @ page present? + blne Lconvertmemc @ yes + ldr r1, [r4], #4 @ get entry + add r5, r5, #1 << 2 + tst r1, #PAGE_PRESENT @ page present? + blne Lconvertmemc @ yes + ldr r1, [r4], #4 @ get entry + add r5, r5, #1 << 2 + tst r1, #PAGE_PRESENT @ page present? + blne Lconvertmemc @ yes + ldr r1, [r4], #4 @ get entry + add r5, r5, #1 << 2 + tst r1, #PAGE_PRESENT @ page present? + blne Lconvertmemc @ yes + cmp r4, ip + blt 1b + ldmfd sp!, {r3, r4, r5, pc}^ + +Lconvertmemc: mov r3, r1, lsr #13 @ + and r3, r3, #0x3fc @ Convert to memc physical page no + ldr r3, [r2, r3] @ + + tst r1, #PAGE_OLD|PAGE_NOT_USER @ check for MEMC read + biceq r3, r3, #0x200 @ + tsteq r1, #PAGE_READONLY|PAGE_CLEAN @ check for MEMC write + biceq r3, r3, #0x300 @ + + orr r3, r3, r5, lsl #13 + and r1, r5, #0x01800000 >> 13 + orr r3, r3, r1 + + and r1, r3, #255 + str r3, [r0, r1, lsl #2] + movs pc, lr + +/* + * Function: arm2_3_update_cache (struct task_struct *tsk, unsigned long addr, pte_t pte) + * Params : tsk Task to update + * address Address of fault. + * pte New PTE at address + * Purpose : Update the mapping for this address. + * Notes : does the ARM3 run faster if you dont use the result in the next instruction? + */ +_arm2_3_update_cache: + tst r2, #PAGE_PRESENT + moveqs pc, lr + mov r3, r2, lsr #13 @ Physical page no. + adr ip, Lphystomemc32 @ Convert to logical page number + and r3, r3, #0x3fc + mov r1, r1, lsr #15 + ldr r3, [ip, r3] @ Convert to memc phys page no. + tst r2, #PAGE_OLD|PAGE_NOT_USER + biceq r3, r3, #0x200 + tsteq r2, #PAGE_READONLY|PAGE_CLEAN + biceq r3, r3, #0x300 + mov ip, sp, lsr #13 + orr r3, r3, r1, lsl #15 + mov ip, ip, lsl #13 + and r1, r1, #0x300 + teq ip, r0 + orr r3, r3, r1, lsl #2 + add r0, r0, #TSS_MEMCMAP + and r2, r3, #255 + streqb r3, [r3] + str r3, [r0, r2, lsl #2] + movs pc, lr + +#define PCD(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \ + .long a0| 0x03800300; .long a1| 0x03800300;\ + .long a2| 0x03800300; .long a3| 0x03800300;\ + .long a4| 0x03800300; .long a5| 0x03800300;\ + .long a6| 0x03800300; .long a7| 0x03800300;\ + .long a8| 0x03800300; .long a9| 0x03800300;\ + .long aa| 0x03800300; .long ab| 0x03800300;\ + .long ac| 0x03800300; .long ad| 0x03800300;\ + .long ae| 0x03800300; .long af| 0x03800300 + +@ Table to map from page number to vidc page number +Lphystomemc32: PCD(0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78) + PCD(0x01,0x09,0x11,0x19,0x21,0x29,0x31,0x39,0x41,0x49,0x51,0x59,0x61,0x69,0x71,0x79) + PCD(0x04,0x0C,0x14,0x1C,0x24,0x2C,0x34,0x3C,0x44,0x4C,0x54,0x5C,0x64,0x6C,0x74,0x7C) + PCD(0x05,0x0D,0x15,0x1D,0x25,0x2D,0x35,0x3D,0x45,0x4D,0x55,0x5D,0x65,0x6D,0x75,0x7D) + PCD(0x02,0x0A,0x12,0x1A,0x22,0x2A,0x32,0x3A,0x42,0x4A,0x52,0x5A,0x62,0x6A,0x72,0x7A) + PCD(0x03,0x0B,0x13,0x1B,0x23,0x2B,0x33,0x3B,0x43,0x4B,0x53,0x5B,0x63,0x6B,0x73,0x7B) + PCD(0x06,0x0E,0x16,0x1E,0x26,0x2E,0x36,0x3E,0x46,0x4E,0x56,0x5E,0x66,0x6E,0x76,0x7E) + PCD(0x07,0x0F,0x17,0x1F,0x27,0x2F,0x37,0x3F,0x47,0x4F,0x57,0x5F,0x67,0x6F,0x77,0x7F) + PCD(0x80,0x88,0x90,0x98,0xA0,0xA8,0xB0,0xB8,0xC0,0xC8,0xD0,0xD8,0xE0,0xE8,0xF0,0xF8) + PCD(0x81,0x89,0x91,0x99,0xA1,0xA9,0xB1,0xB9,0xC1,0xC9,0xD1,0xD9,0xE1,0xE9,0xF1,0xF9) + PCD(0x84,0x8C,0x94,0x9C,0xA4,0xAC,0xB4,0xBC,0xC4,0xCC,0xD4,0xDC,0xE4,0xEC,0xF4,0xFC) + PCD(0x85,0x8D,0x95,0x9D,0xA5,0xAD,0xB5,0xBD,0xC5,0xCD,0xD5,0xDD,0xE5,0xED,0xF5,0xFD) + PCD(0x82,0x8A,0x92,0x9A,0xA2,0xAA,0xB2,0xBA,0xC2,0xCA,0xD2,0xDA,0xE2,0xEA,0xF2,0xFA) + PCD(0x83,0x8B,0x93,0x9B,0xA3,0xAB,0xB3,0xBB,0xC3,0xCB,0xD3,0xDB,0xE3,0xEB,0xF3,0xFB) + PCD(0x86,0x8E,0x96,0x9E,0xA6,0xAE,0xB6,0xBE,0xC6,0xCE,0xD6,0xDE,0xE6,0xEE,0xF6,0xFE) + PCD(0x87,0x8F,0x97,0x9F,0xA7,0xAF,0xB7,0xBF,0xC7,0xCF,0xD7,0xDF,0xE7,0xEF,0xF7,0xFF) + +/* + * Function: arm2_3_data_abort () + * + * Params : r0 = address of aborted instruction + * + * Purpose : + * + * Returns : r0 = address of abort + * : r1 = FSR + * : r2 != 0 if writing + */ + +_arm2_3_data_abort: + movs pc, lr + +_arm2_3_check_bugs: + movs pc, lr + +/* + * Processor specific - ARM2 + */ + +LC0: .word SYMBOL_NAME(page_nr) +/* + * Function: arm2_switch_to (struct task_struct *prev, struct task_struct *next) + * + * Params : prev Old task structure + * : next New task structure for process to run + * + * Purpose : Perform a task switch, saving the old processes state, and restoring + * the new. + * + * Notes : We don't fiddle with the FP registers here - we postpone this until + * the new task actually uses FP. This way, we don't swap FP for tasks + * that do not require it. + */ +_arm2_switch_to: + stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack + str sp, [r0, #TSS_SAVE] @ Save sp_SVC + ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC + mov r4, r1 + add r0, r1, #TSS_MEMCMAP @ Remap MEMC + ldr r1, LC0 + ldr r1, [r1] +1: ldmia r0!, {r2, r3, r5, r6} + strb r2, [r2] + strb r3, [r3] + strb r5, [r5] + strb r6, [r6] + ldmia r0!, {r2, r3, r5, r6} + strb r2, [r2] + strb r3, [r3] + strb r5, [r5] + strb r6, [r6] + subs r1, r1, #8 + bhi 1b + ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously + +/* + * Function: arm2_remap_memc (struct task_struct *tsk) + * + * Params : tsk Task structure specifing the new mapping structure + * + * Purpose : remap MEMC tables + */ +_arm2_remap_memc: + stmfd sp!, {lr} + add r0, r0, #TSS_MEMCMAP + ldr r1, LC0 + ldr r1, [r1] +1: ldmia r0!, {r2, r3, ip, lr} + strb r2, [r2] + strb r3, [r3] + strb ip, [ip] + strb lr, [lr] + ldmia r0!, {r2, r3, ip, lr} + strb r2, [r2] + strb r3, [r3] + strb ip, [ip] + strb lr, [lr] + subs r1, r1, #8 + bhi 1b + ldmfd sp!, {pc}^ + +/* + * Function: arm2_xchg_1 (int new, volatile void *ptr) + * + * Params : new New value to store at... + * : ptr pointer to byte-wide location + * + * Purpose : Performs an exchange operation + * + * Returns : Original byte data at 'ptr' + * + * Notes : This will have to be changed if we ever use multi-processing using these + * processors, but that is very unlikely... + */ +_arm2_xchg_1: mov r2, pc + orr r2, r2, #I_BIT + teqp r2, #0 + ldrb r2, [r1] + strb r0, [r1] + mov r0, r2 + movs pc, lr + +/* + * Function: arm2_xchg_4 (int new, volatile void *ptr) + * + * Params : new New value to store at... + * : ptr pointer to word-wide location + * + * Purpose : Performs an exchange operation + * + * Returns : Original word data at 'ptr' + * + * Notes : This will have to be changed if we ever use multi-processing using these + * processors, but that is very unlikely... + */ +_arm2_xchg_4: mov r2, pc + orr r2, r2, #I_BIT + teqp r2, #0 + ldr r2, [r1] + str r0, [r1] + mov r0, r2 +/* + * fall through + */ +/* + * Function: arm2_proc_init (void) + * : arm2_proc_fin (void) + * + * Purpose : Initialise / finalise processor specifics (none required) + */ +_arm2_proc_init: +_arm2_proc_fin: movs pc, lr +/* + * Function: arm3_switch_to (struct task_struct *prev, struct task_struct *next) + * + * Params : prev Old task structure + * : next New task structure for process to run + * + * Purpose : Perform a task switch, saving the old processes state, and restoring + * the new. + * + * Notes : We don't fiddle with the FP registers here - we postpone this until + * the new task actually uses FP. This way, we don't swap FP for tasks + * that do not require it. + */ +_arm3_switch_to: + stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack + str sp, [r0, #TSS_SAVE] @ Save sp_SVC + ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC + mov r4, r1 + add r0, r1, #TSS_MEMCMAP @ Remap MEMC + ldr r1, LC0 + ldr r1, [r1] +1: ldmia r0!, {r2, r3, r5, r6} + strb r2, [r2] + strb r3, [r3] + strb r5, [r5] + strb r6, [r6] + ldmia r0!, {r2, r3, r5, r6} + strb r2, [r2] + strb r3, [r3] + strb r5, [r5] + strb r6, [r6] + subs r1, r1, #8 + bhi 1b + mcr p15, 0, r0, c1, c0, 0 @ flush cache + ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously +/* + * Function: arm3_remap_memc (struct task_struct *tsk) + * + * Params : tsk Task structure specifing the new mapping structure + * + * Purpose : remap MEMC tables + */ +_arm3_remap_memc: + stmfd sp!, {lr} + add r0, r0, #TSS_MEMCMAP + ldr r1, LC0 + ldr r1, [r1] +1: ldmia r0!, {r2, r3, ip, lr} + strb r2, [r2] + strb r3, [r3] + strb ip, [ip] + strb lr, [lr] + ldmia r0!, {r2, r3, ip, lr} + strb r2, [r2] + strb r3, [r3] + strb ip, [ip] + strb lr, [lr] + subs r1, r1, #8 + bhi 1b + mcr p15, 0, r0, c1, c0, 0 @ flush cache + ldmfd sp!, {pc}^ + +/* + * Function: arm3_proc_init (void) + * + * Purpose : Initialise the cache control registers + */ +_arm3_proc_init: + mov r0, #0x001f0000 + orr r0, r0, #0x0000ff00 + orr r0, r0, #0x000000ff + mcr p15, 0, r0, c3, c0 + mcr p15, 0, r0, c4, c0 + mov r0, #0 + mcr p15, 0, r0, c5, c0 + mov r0, #3 + mcr p15, 0, r0, c1, c0 + mcr p15, 0, r0, c2, c0 + movs pc, lr + +/* + * Function: arm3_proc_fin (void) + * + * Purpose : Finalise processor (disable caches) + */ +_arm3_proc_fin: mov r0, #2 + mcr p15, 0, r0, c2, c0 + movs pc, lr + +/* + * Function: arm3_xchg_1 (int new, volatile void *ptr) + * + * Params : new New value to store at... + * : ptr pointer to byte-wide location + * + * Purpose : Performs an exchange operation + * + * Returns : Original byte data at 'ptr' + */ +_arm3_xchg_1: swpb r0, r0, [r1] + movs pc, lr + +/* + * Function: arm3_xchg_4 (int new, volatile void *ptr) + * + * Params : new New value to store at... + * : ptr pointer to word-wide location + * + * Purpose : Performs an exchange operation + * + * Returns : Original word data at 'ptr' + */ +_arm3_xchg_4: swp r0, r0, [r1] + movs pc, lr + + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ +_arm2_name: + .ascii "arm2\0" + .align + + .globl SYMBOL_NAME(arm2_processor_functions) +SYMBOL_NAME(arm2_processor_functions): + .word _arm2_name @ 0 + .word _arm2_switch_to @ 4 + .word _arm2_3_data_abort @ 8 + .word _arm2_3_check_bugs @ 12 + .word _arm2_proc_init @ 16 + .word _arm2_proc_fin @ 20 + + .word _arm2_remap_memc @ 24 + .word _arm2_3_update_map @ 28 + .word _arm2_3_update_cache @ 32 + .word _arm2_xchg_1 @ 36 + .word SYMBOL_NAME(abort) @ 40 + .word _arm2_xchg_4 @ 44 + +_arm250_name: + .ascii "arm250\0" + .align + + .globl SYMBOL_NAME(arm250_processor_functions) +SYMBOL_NAME(arm250_processor_functions): + .word _arm250_name @ 0 + .word _arm2_switch_to @ 4 + .word _arm2_3_data_abort @ 8 + .word _arm2_3_check_bugs @ 12 + .word _arm2_proc_init @ 16 + .word _arm2_proc_fin @ 20 + + .word _arm2_remap_memc @ 24 + .word _arm2_3_update_map @ 28 + .word _arm2_3_update_cache @ 32 + .word _arm3_xchg_1 @ 36 + .word SYMBOL_NAME(abort) @ 40 + .word _arm3_xchg_4 @ 44 + +_arm3_name: + .ascii "arm3\0" + .align + + .globl SYMBOL_NAME(arm3_processor_functions) +SYMBOL_NAME(arm3_processor_functions): + .word _arm3_name @ 0 + .word _arm3_switch_to @ 4 + .word _arm2_3_data_abort @ 8 + .word _arm2_3_check_bugs @ 12 + .word _arm3_proc_init @ 16 + .word _arm3_proc_fin @ 20 + + .word _arm3_remap_memc @ 24 + .word _arm2_3_update_map @ 28 + .word _arm2_3_update_cache @ 32 + .word _arm3_xchg_1 @ 36 + .word SYMBOL_NAME(abort) @ 40 + .word _arm3_xchg_4 @ 44 + diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S --- v2.1.79/linux/arch/arm/mm/proc-arm6,7.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/proc-arm6,7.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,436 @@ +/* + * linux/arch/arm/mm/arm6.S: MMU functions for ARM6 + * + * (C) 1997 Russell King + * + * These are the low level assembler for performing cache and TLB + * functions on the ARM6 & ARM7. + */ +#include +#include +#include "../lib/constants.h" + +/* + * Function: arm6_7_flush_cache_all (void) + * : arm6_7_flush_cache_page (unsigned long address, int size, int flags) + * + * Params : address Area start address + * : size size of area + * : flags b0 = I cache as well + * + * Purpose : Flush all cache lines + */ +_arm6_7_flush_cache: + mov r0, #0 + mcr p15, 0, r0, c7, c0, 0 @ flush cache +_arm6_7_null: + mov pc, lr + +/* + * Function: arm6_7_flush_tlb_all (void) + * + * Purpose : flush all TLB entries in all caches + */ +_arm6_7_flush_tlb_all: + mov r0, #0 + mcr p15, 0, r0, c5, c0, 0 @ flush TLB + mov pc, lr + +/* + * Function: arm6_7_flush_tlb_page (unsigned long address, int end, int flags) + * + * Params : address Area start address + * : end Area end address + * : flags b0 = I cache as well + * + * Purpose : flush a TLB entry + */ +_arm6_7_flush_tlb_area: +1: mcr p15, 0, r0, c6, c0, 0 @ flush TLB + add r0, r0, #4096 + cmp r0, r1 + blt 1b + mov pc, lr + +@LC0: .word _current +/* + * Function: arm6_7_switch_to (struct task_struct *prev, struct task_struct *next) + * + * Params : prev Old task structure + * : next New task structure for process to run + * + * Purpose : Perform a task switch, saving the old processes state, and restoring + * the new. + * + * Notes : We don't fiddle with the FP registers here - we postpone this until + * the new task actually uses FP. This way, we don't swap FP for tasks + * that do not require it. + */ +_arm6_7_switch_to: + stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack + mrs ip, cpsr + stmfd sp!, {ip} @ Save cpsr_SVC + str sp, [r0, #TSS_SAVE] @ Save sp_SVC + ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC + ldr r0, [r1, #ADDR_LIMIT] + teq r0, #0 + moveq r0, #KERNEL_DOMAIN + movne r0, #USER_DOMAIN + mcr p15, 0, r0, c3, c0 @ Set domain reg + ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer + mov r1, #0 + mcr p15, 0, r1, c7, c0, 0 @ flush cache + mcr p15, 0, r0, c2, c0, 0 @ update page table ptr + mcr p15, 0, r1, c5, c0, 0 @ flush TLBs + ldmfd sp!, {ip} + msr spsr, ip @ Save tasks CPSR into SPSR for this return + ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously + +/* + * Function: arm6_7_data_abort () + * + * Params : r0 = address of aborted instruction + * + * Purpose : obtain information about current aborted instruction + * + * Returns : r0 = address of abort + * : r1 = FSR + * : r2 != 0 if writing + * : sp = pointer to registers + */ + +Lukabttxt: .ascii "Unknown data abort code %d [pc=%p, *pc=%p] LR=%p\0" + .align + +msg: .ascii "DA*%p=%p\n\0" + .align + +_arm6_data_abort: + ldr r4, [r0] @ read instruction causing problem + mov r2, r4, lsr #19 @ r2 b1 = L + and r1, r4, #15 << 24 + add pc, pc, r1, lsr #22 @ Now branch to the relevent processing routine + movs pc, lr + b Ldata_unknown + b Ldata_unknown + b Ldata_unknown + b Ldata_unknown + b Ldata_earlyldrpost @ ldr rd, [rn], #m + b Ldata_simple @ ldr rd, [rn, #m] @ RegVal + b Ldata_earlyldrpost @ ldr rd, [rn], rm + b Ldata_simple @ ldr rd, [rn, rm] + b Ldata_ldmstm @ ldm*a rn, + b Ldata_ldmstm @ ldm*b rn, + b Ldata_unknown + b Ldata_unknown + b Ldata_simple @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m + b Ldata_simple @ ldc rd, [rn, #m] + b Ldata_unknown +Ldata_unknown: @ Part of jumptable + ldr r3, [sp, #15 * 4] @ Get PC + str r3, [sp, #-4]! + mov r1, r1, lsr #2 + mov r3, r4 + mov r2, r0 + adr r0, Lukabttxt + bl SYMBOL_NAME(panic) +Lstop: b Lstop + +_arm7_data_abort: + ldr r4, [r0] @ read instruction causing problem + mov r2, r4, lsr #19 @ r2 b1 = L + and r1, r4, #15 << 24 + add pc, pc, r1, lsr #22 @ Now branch to the relevent processing routine + movs pc, lr + b Ldata_unknown + b Ldata_unknown + b Ldata_unknown + b Ldata_unknown + b Ldata_lateldrpostconst @ ldr rd, [rn], #m + b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal + b Ldata_lateldrpostreg @ ldr rd, [rn], rm + b Ldata_lateldrprereg @ ldr rd, [rn, rm] + b Ldata_ldmstm @ ldm*a rn, + b Ldata_ldmstm @ ldm*b rn, + b Ldata_unknown + b Ldata_unknown + b Ldata_simple @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m + b Ldata_simple @ ldc rd, [rn, #m] + b Ldata_unknown + b Ldata_unknown + +Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit + beq Ldata_simple + + mov r7, #0x11 + orr r7, r7, r7, lsl #8 + and r0, r4, r7 + and r1, r4, r7, lsl #1 + add r0, r0, r1, lsr #1 + and r1, r4, r7, lsl #2 + add r0, r0, r1, lsr #2 + and r1, r4, r7, lsl #3 + add r0, r0, r1, lsr #3 + add r0, r0, r0, lsr #8 + add r0, r0, r0, lsr #4 + and r7, r0, #15 @ r7 = no. of registers to transfer. + and r5, r4, #15 << 16 @ Get Rn + ldr r0, [sp, r5, lsr #14] @ Get register + eor r6, r4, r4, lsl #2 + tst r6, #1 << 23 @ Check inc/dec ^ writeback + rsbeq r7, r7, #0 + add r7, r0, r7, lsl #2 @ Do correction (signed) + str r7, [sp, r5, lsr #14] @ Put register + +Ldata_simple: and r2, r2, #2 @ check read/write bit + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mrc p15, 0, r1, c5, c0, 0 @ get FSR + and r1, r1, #15 + mov pc, lr + +Ldata_earlyldrpost: + tst r2, #4 + and r2, r2, #2 @ check read/write bit + orrne r2, r2, #1 @ T bit + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mrc p15, 0, r1, c5, c0, 0 @ get FSR + and r1, r1, #15 + mov pc, lr + +Ldata_lateldrpostconst: + movs r1, r4, lsl #20 @ Get offset + beq Ldata_earlyldrpost @ if offset is zero, no effect + and r5, r4, #15 << 16 @ Get Rn + ldr r0, [sp, r5, lsr #14] + tst r4, #1 << 23 @ U bit + subne r0, r0, r1, lsr #20 + addeq r0, r0, r1, lsr #20 + str r0, [sp, r5, lsr #14] @ Put register + b Ldata_earlyldrpost + +Ldata_lateldrpreconst: + tst r4, #1 << 21 @ check writeback bit + movnes r1, r4, lsl #20 @ Get offset + beq Ldata_simple + and r5, r4, #15 << 16 @ Get Rn + ldr r0, [sp, r5, lsr #14] + tst r4, #1 << 23 @ U bit + subne r0, r0, r1, lsr #20 + addeq r0, r0, r1, lsr #20 + str r0, [sp, r5, lsr #14] @ Put register + b Ldata_simple + +Ldata_lateldrpostreg: + and r5, r4, #15 + ldr r1, [sp, r5, lsl #2] @ Get Rm + mov r3, r4, lsr #7 + ands r3, r3, #31 + and r6, r4, #0x70 + orreq r6, r6, #8 + add pc, pc, r6 + mov r0, r0 + + mov r1, r1, lsl r3 @ 0: LSL #!0 + b 1f + b 1f @ 1: LSL #0 + mov r0, r0 + b 1f @ 2: MUL? + mov r0, r0 + b 1f @ 3: MUL? + mov r0, r0 + mov r1, r1, lsr r3 @ 4: LSR #!0 + b 1f + mov r1, r1, lsr #32 @ 5: LSR #32 + b 1f + b 1f @ 6: MUL? + mov r0, r0 + b 1f @ 7: MUL? + mov r0, r0 + mov r1, r1, asr r3 @ 8: ASR #!0 + b 1f + mov r1, r1, asr #32 @ 9: ASR #32 + b 1f + b 1f @ A: MUL? + mov r0, r0 + b 1f @ B: MUL? + mov r0, r0 + mov r1, r1, ror r3 @ C: ROR #!0 + b 1f + mov r1, r1, rrx @ D: RRX + b 1f + mov r0, r0 @ E: MUL? + mov r0, r0 + mov r0, r0 @ F: MUL? + + +1: and r5, r4, #15 << 16 @ Get Rn + ldr r0, [sp, r5, lsr #14] + tst r4, #1 << 23 @ U bit + subne r0, r0, r1 + addeq r0, r0, r1 + str r0, [sp, r5, lsr #14] @ Put register + b Ldata_earlyldrpost + +Ldata_lateldrprereg: + tst r4, #1 << 21 @ check writeback bit + beq Ldata_simple + and r5, r4, #15 + ldr r1, [sp, r5, lsl #2] @ Get Rm + mov r3, r4, lsr #7 + ands r3, r3, #31 + and r6, r4, #0x70 + orreq r6, r6, #8 + add pc, pc, r6 + mov r0, r0 + + mov r1, r1, lsl r3 @ 0: LSL #!0 + b 1f + b 1f @ 1: LSL #0 + mov r0, r0 + b 1f @ 2: MUL? + mov r0, r0 + b 1f @ 3: MUL? + mov r0, r0 + mov r1, r1, lsr r3 @ 4: LSR #!0 + b 1f + mov r1, r1, lsr #32 @ 5: LSR #32 + b 1f + b 1f @ 6: MUL? + mov r0, r0 + b 1f @ 7: MUL? + mov r0, r0 + mov r1, r1, asr r3 @ 8: ASR #!0 + b 1f + mov r1, r1, asr #32 @ 9: ASR #32 + b 1f + b 1f @ A: MUL? + mov r0, r0 + b 1f @ B: MUL? + mov r0, r0 + mov r1, r1, ror r3 @ C: ROR #!0 + b 1f + mov r1, r1, rrx @ D: RRX + b 1f + mov r0, r0 @ E: MUL? + mov r0, r0 + mov r0, r0 @ F: MUL? + + +1: and r5, r4, #15 << 16 @ Get Rn + ldr r0, [sp, r5, lsr #14] + tst r4, #1 << 23 @ U bit + subne r0, r0, r1 + addeq r0, r0, r1 + str r0, [sp, r5, lsr #14] @ Put register + b Ldata_simple + +/* + * Function: arm6_7_check_bugs (void) + * : arm6_7_proc_init (void) + * : arm6_7_proc_fin (void) + * + * Notes : This processor does not require these + */ +_arm6_7_check_bugs: + mrs ip, cpsr + bic ip, ip, #F_BIT + msr cpsr, ip +_arm6_7_proc_init: +_arm6_7_proc_fin: + mov pc, lr + +/* + * Function: arm6_set_pmd () + * + * Params : r0 = Address to set + * : r1 = value to set + * + * Purpose : Set a PMD and flush it out of any WB cache + */ +_arm6_set_pmd: and r2, r1, #3 + teq r2, #2 + andeq r2, r1, #8 + orreq r1, r1, r2, lsl #1 @ Updatable = Cachable + teq r2, #1 + orreq r1, r1, #16 @ Updatable = 1 if Page table + str r1, [r0] + mov pc, lr + +/* + * Function: arm7_set_pmd () + * + * Params : r0 = Address to set + * : r1 = value to set + * + * Purpose : Set a PMD and flush it out of any WB cache + */ +_arm7_set_pmd: orr r1, r1, #16 @ Updatable bit is always set on ARM7 + str r1, [r0] + mov pc, lr + +/* + * Function: _arm6_7_reset + * + * Notes : This sets up everything for a reset + */ +_arm6_7_reset: mrs r1, cpsr + orr r1, r1, #F_BIT|I_BIT + msr cpsr, r1 + mov r0, #0 + mcr p15, 0, r0, c7, c0, 0 @ flush cache + mcr p15, 0, r0, c5, c0, 0 @ flush TLB + mov r1, #F_BIT | I_BIT | 3 + mov pc, lr + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ +_arm6_name: .ascii "arm6\0" + .align + +ENTRY(arm6_processor_functions) + .word _arm6_name @ 0 + .word _arm6_7_switch_to @ 4 + .word _arm6_data_abort @ 8 + .word _arm6_7_check_bugs @ 12 + .word _arm6_7_proc_init @ 16 + .word _arm6_7_proc_fin @ 20 + + .word _arm6_7_flush_cache @ 24 + .word _arm6_7_flush_cache @ 28 + .word _arm6_7_flush_cache @ 32 + .word _arm6_7_null @ 36 + .word _arm6_7_flush_cache @ 40 + .word _arm6_7_flush_tlb_all @ 44 + .word _arm6_7_flush_tlb_area @ 48 + .word _arm6_set_pmd @ 52 + .word _arm6_7_reset @ 54 + .word _arm6_7_flush_cache @ 58 + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ +_arm7_name: .ascii "arm7\0" + .align + +ENTRY(arm7_processor_functions) + .word _arm7_name @ 0 + .word _arm6_7_switch_to @ 4 + .word _arm7_data_abort @ 8 + .word _arm6_7_check_bugs @ 12 + .word _arm6_7_proc_init @ 16 + .word _arm6_7_proc_fin @ 20 + + .word _arm6_7_flush_cache @ 24 + .word _arm6_7_flush_cache @ 28 + .word _arm6_7_flush_cache @ 32 + .word _arm6_7_null @ 36 + .word _arm6_7_flush_cache @ 40 + .word _arm6_7_flush_tlb_all @ 44 + .word _arm6_7_flush_tlb_area @ 48 + .word _arm7_set_pmd @ 52 + .word _arm6_7_reset @ 54 + .word _arm6_7_flush_cache @ 58 + diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S --- v2.1.79/linux/arch/arm/mm/proc-sa110.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/proc-sa110.S Tue Jan 20 16:39:42 1998 @@ -0,0 +1,305 @@ +/* + * linux/arch/arm/mm/sa110.S: MMU functions for SA110 + * + * (C) 1997 Russell King + * + * These are the low level assembler for performing cache and TLB + * functions on the sa110. + */ +#include +#include +#include "../lib/constants.h" + + .data +Lclean_switch: .long 0 + .text + +/* + * Function: sa110_flush_cache_all (void) + * + * Purpose : Flush all cache lines + */ + .align 5 +_sa110_flush_cache_all: @ preserves r0 + ldr r3, =Lclean_switch + ldr r2, [r3] + ands r2, r2, #1 + eor r2, r2, #1 + str r2, [r3] + ldr ip, =0xdf000000 + addne ip, ip, #32768 + add r1, ip, #16384 @ only necessary for 16k +1: ldr r2, [ip], #32 + teq r1, ip + bne 1b + mov ip, #0 + mcr p15, 0, ip, c7, c5, 0 @ flush I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * Function: sa110_flush_cache_area (unsigned long address, int end, int flags) + * + * Params : address Area start address + * : end Area end address + * : flags b0 = I cache as well + * + * Purpose : clean & flush all cache lines associated with this area of memory + */ + .align 5 +_sa110_flush_cache_area: + sub r3, r1, r0 + cmp r3, #32768 + bgt _sa110_flush_cache_all +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ flush D entry + add r0, r0, #32 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ flush D entry + add r0, r0, #32 + cmp r0, r1 + blt 1b + tst r2, #1 + movne r0, #0 + mcrne p15, 0, r0, c7, c5, 0 @ flush I cache + mov pc, lr + +/* + * Function: sa110_flush_cache_entry (unsigned long address) + * + * Params : address Address of cache line to flush + * + * Purpose : clean & flush an entry + */ + .align 5 +_sa110_flush_cache_entry: + mov r1, #0 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mcr p15, 0, r1, c7, c5, 0 @ flush I cache + mov pc, lr + +/* + * Function: sa110_flush_cache_pte (unsigned long address) + * + * Params : address Address of cache line to clean + * + * Purpose : Ensure that physical memory reflects cache at this location + * for page table purposes. + */ +_sa110_flush_cache_pte: + mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) + mov pc, lr + +/* + * Function: sa110_flush_ram_page (unsigned long page) + * + * Params : address Area start address + * : size size of area + * : flags b0 = I cache as well + * + * Purpose : clean & flush all cache lines associated with this area of memory + */ + .align 5 +_sa110_flush_ram_page: + mov r1, #4096 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ flush D entry + add r0, r0, #32 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c6, 1 @ flush D entry + add r0, r0, #32 + subs r1, r1, #64 + bne 1b + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c7, c5, 0 @ flush I cache + mov pc, lr + +/* + * Function: sa110_flush_tlb_all (void) + * + * Purpose : flush all TLB entries in all caches + */ + .align 5 +_sa110_flush_tlb_all: + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c8, c7, 0 @ flush I & D tlbs + mov pc, lr + +/* + * Function: sa110_flush_tlb_area (unsigned long address, int end, int flags) + * + * Params : address Area start address + * : end Area end address + * : flags b0 = I cache as well + * + * Purpose : flush a TLB entry + */ + .align 5 +_sa110_flush_tlb_area: + mov r3, #0 + mcr p15, 0, r3, c7, c10, 4 @ drain WB +1: cmp r0, r1 + mcrlt p15, 0, r0, c8, c6, 1 @ flush D TLB entry + addlt r0, r0, #4096 + cmp r0, r1 + mcrlt p15, 0, r0, c8, c6, 1 @ flush D TLB entry + addlt r0, r0, #4096 + blt 1b + tst r2, #1 + mcrne p15, 0, r3, c8, c5, 0 @ flush I TLB + mov pc, lr + + .align 5 +_sa110_flush_icache_area: + mov r3, #0 +1: mcr p15, 0, r0, c7, c10, 1 @ Clean D entry + add r0, r0, #32 + cmp r0, r1 + blt 1b + mcr p15, 0, r0, c7, c5, 0 @ flush I cache + mov pc, lr + +@LC0: .word _current +/* + * Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next) + * + * Params : prev Old task structure + * : next New task structure for process to run + * + * Purpose : Perform a task switch, saving the old processes state, and restoring + * the new. + * + * Notes : We don't fiddle with the FP registers here - we postpone this until + * the new task actually uses FP. This way, we don't swap FP for tasks + * that do not require it. + */ + .align 5 +_sa110_switch_to: + stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack + mrs ip, cpsr + stmfd sp!, {ip} @ Save cpsr_SVC + str sp, [r0, #TSS_SAVE] @ Save sp_SVC + ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC + ldr r0, [r1, #ADDR_LIMIT] + teq r0, #0 + moveq r0, #KERNEL_DOMAIN + movne r0, #USER_DOMAIN + mcr p15, 0, r0, c3, c0 @ Set segment + ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer + ldr r3, =Lclean_switch + ldr r2, [r3] + ands r2, r2, #1 + eor r2, r2, #1 + str r2, [r3] + ldr r2, =0xdf000000 + addne r2, r2, #32768 + add r1, r2, #16384 @ only necessary for 16k +1: ldr r3, [r2], #32 + teq r1, r2 + bne 1b + mov r1, #0 + mcr p15, 0, r1, c7, c5, 0 @ flush I cache + mcr p15, 0, r1, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, r1, c8, c7, 0 @ flush TLBs + ldmfd sp!, {ip} + msr spsr, ip @ Save tasks CPSR into SPSR for this return + ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously + +/* + * Function: sa110_data_abort () + * + * Params : r0 = address of aborted instruction + * + * Purpose : obtain information about current aborted instruction + * + * Returns : r0 = address of abort + * : r1 = FSR + * : r2 != 0 if writing + */ + .align 5 +_sa110_data_abort: + ldr r2, [r0] @ read instruction causing problem + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mov r2, r2, lsr #19 @ b1 = L + and r3, r2, #0x69 << 2 + and r2, r2, #2 +// teq r3, #0x21 << 2 +// orreq r2, r2, #1 @ b0 = {LD,ST}RT + mrc p15, 0, r1, c5, c0, 0 @ get FSR + and r1, r1, #255 + mov pc, lr + +/* + * Function: sa110_set_pmd () + * + * Params : r0 = Address to set + * : r1 = value to set + * + * Purpose : Set a PMD and flush it out of any WB cache + */ + .align 5 +_sa110_set_pmd: str r1, [r0] + mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) + mov pc, lr + +/* + * Function: sa110_check_bugs (void) + * : sa110_proc_init (void) + * : sa110_proc_fin (void) + * + * Notes : This processor does not require these + */ +_sa110_check_bugs: + mrs ip, cpsr + bic ip, ip, #F_BIT + msr cpsr, ip +_sa110_proc_init: +_sa110_proc_fin: + mov pc, lr + +/* + * Function: sa110_reset + * + * Notes : This sets up everything for a reset + */ +_sa110_reset: mrs r1, cpsr + orr r1, r1, #F_BIT | I_BIT + msr cpsr, r1 + stmfd sp!, {r1, lr} + bl _sa110_flush_cache_all + bl _sa110_flush_tlb_all + mcr p15, 0, ip, c7, c7, 0 @ flush I,D caches + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1800 + bic r0, r0, #0x000f + ldmfd sp!, {r1, pc} +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ +_sa110_name: .ascii "sa110\0" + .align + +ENTRY(sa110_processor_functions) + .word _sa110_name @ 0 + .word _sa110_switch_to @ 4 + .word _sa110_data_abort @ 8 + .word _sa110_check_bugs @ 12 + .word _sa110_proc_init @ 16 + .word _sa110_proc_fin @ 20 + + .word _sa110_flush_cache_all @ 24 + .word _sa110_flush_cache_area @ 28 + .word _sa110_flush_cache_entry @ 32 + .word _sa110_flush_cache_pte @ 36 + .word _sa110_flush_ram_page @ 40 + .word _sa110_flush_tlb_all @ 44 + .word _sa110_flush_tlb_area @ 48 + + .word _sa110_set_pmd @ 52 + .word _sa110_reset @ 54 + .word _sa110_flush_icache_area @ 58 diff -u --recursive --new-file v2.1.79/linux/arch/arm/mm/small_page.c linux/arch/arm/mm/small_page.c --- v2.1.79/linux/arch/arm/mm/small_page.c Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/mm/small_page.c Tue Jan 20 16:39:42 1998 @@ -0,0 +1,201 @@ +/* + * linux/arch/arm/mm/small_page.c + * + * Copyright (C) 1996 Russell King + * + * Changelog: + * 26/01/1996 RMK Cleaned up various areas to make little more generic + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SMALL_ALLOC_SHIFT (10) +#define SMALL_ALLOC_SIZE (1 << SMALL_ALLOC_SHIFT) +#define NR_BLOCKS (PAGE_SIZE / SMALL_ALLOC_SIZE) + +#if NR_BLOCKS != 4 +#error I only support 4 blocks per page! +#endif + +#define USED(pg) ((atomic_read(&(pg)->count) >> 8) & 15) +#define SET_USED(pg,off) (atomic_read(&(pg)->count) |= 256 << off) +#define CLEAR_USED(pg,off) (atomic_read(&(pg)->count) &= ~(256 << off)) +#define IS_FREE(pg,off) (!(atomic_read(&(pg)->count) & (256 << off))) +#define PAGE_PTR(page,block) ((struct free_small_page *)((page) + \ + ((block) << SMALL_ALLOC_SHIFT))) + +struct free_small_page { + unsigned long next; + unsigned long prev; +}; + +/* + * To handle allocating small pages, we use the main get_free_page routine, + * and split the page up into 4. The page is marked in mem_map as reserved, + * so it can't be free'd by free_page. The count field is used to keep track + * of which sections of this page are allocated. + */ +static unsigned long small_page_ptr; + +static unsigned char offsets[1<next = fsp->prev = 0; + } +} + +static inline void set_page_links_prev(unsigned long page, unsigned long prev) +{ + struct free_small_page *fsp; + unsigned int mask; + int i; + + if (!page) + return; + + mask = USED(&mem_map[MAP_NR(page)]); + for (i = 0; i < NR_BLOCKS; i++) { + if (mask & (1 << i)) + continue; + fsp = PAGE_PTR(page, i); + fsp->prev = prev; + } +} + +static inline void set_page_links_next(unsigned long page, unsigned long next) +{ + struct free_small_page *fsp; + unsigned int mask; + int i; + + if (!page) + return; + + mask = USED(&mem_map[MAP_NR(page)]); + for (i = 0; i < NR_BLOCKS; i++) { + if (mask & (1 << i)) + continue; + fsp = PAGE_PTR(page, i); + fsp->next = next; + } +} + +unsigned long get_small_page(int priority) +{ + struct free_small_page *fsp; + unsigned long new_page; + unsigned long flags; + struct page *page; + int offset; + + save_flags(flags); + if (!small_page_ptr) + goto need_new_page; + cli(); +again: + page = mem_map + MAP_NR(small_page_ptr); + offset = offsets[USED(page)]; + SET_USED(page, offset); + new_page = (unsigned long)PAGE_PTR(small_page_ptr, offset); + if (USED(page) == 15) { + fsp = (struct free_small_page *)new_page; + set_page_links_prev (fsp->next, 0); + small_page_ptr = fsp->next; + } + restore_flags(flags); + return new_page; + +need_new_page: + new_page = __get_free_page(priority); + if (!small_page_ptr) { + if (new_page) { + set_bit (PG_reserved, &mem_map[MAP_NR(new_page)].flags); + clear_page_links (new_page); + cli(); + small_page_ptr = new_page; + goto again; + } + restore_flags(flags); + return 0; + } + free_page(new_page); + cli(); + goto again; +} + +void free_small_page(unsigned long spage) +{ + struct free_small_page *ofsp, *cfsp; + unsigned long flags; + struct page *page; + int offset, oldoffset; + + offset = (spage >> SMALL_ALLOC_SHIFT) & (NR_BLOCKS - 1); + spage -= offset << SMALL_ALLOC_SHIFT; + + page = mem_map + MAP_NR(spage); + if (!PageReserved(page) || !USED(page)) { + printk ("Trying to free non-small page from %p\n", __builtin_return_address(0)); + return; + } + if (IS_FREE(page, offset)) { + printk ("Trying to free free small page from %p\n", __builtin_return_address(0)); + return; + } + save_flags_cli (flags); + oldoffset = offsets[USED(page)]; + CLEAR_USED(page, offset); + ofsp = PAGE_PTR(spage, oldoffset); + cfsp = PAGE_PTR(spage, offset); + + if (oldoffset == NR_BLOCKS) { /* going from totally used to mostly used */ + cfsp->prev = 0; + cfsp->next = small_page_ptr; + set_page_links_prev (small_page_ptr, spage); + small_page_ptr = spage; + } else if (!USED(page)) { + set_page_links_prev (ofsp->next, ofsp->prev); + set_page_links_next (ofsp->prev, ofsp->next); + if (spage == small_page_ptr) + small_page_ptr = ofsp->next; + clear_bit (PG_reserved, &page->flags); + restore_flags(flags); + free_page (spage); + } else + *cfsp = *ofsp; + restore_flags(flags); +} diff -u --recursive --new-file v2.1.79/linux/arch/arm/vmlinux.lds linux/arch/arm/vmlinux.lds --- v2.1.79/linux/arch/arm/vmlinux.lds Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/vmlinux.lds Tue Jan 20 16:39:42 1998 @@ -0,0 +1,58 @@ +/* ld script to make i386 Linux kernel + * Written by Martin Mares + */ +OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } = 0x9090 + .text.lock : { *(.text.lock) } /* out-of-line lock text */ + .rodata : { *(.rodata) } + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + _etext = .; /* End of text section */ + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } + + _edata = .; /* End of data section */ + + . = ALIGN(4096); /* Init code and data */ + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + } + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff -u --recursive --new-file v2.1.79/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.1.79/linux/arch/i386/config.in Tue Jan 6 09:37:32 1998 +++ linux/arch/i386/config.in Tue Jan 20 16:44:57 1998 @@ -42,6 +42,7 @@ fi bool 'MCA support' CONFIG_MCA bool 'System V IPC' CONFIG_SYSVIPC +bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF diff -u --recursive --new-file v2.1.79/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.1.79/linux/arch/i386/defconfig Mon Jan 12 22:09:07 1998 +++ linux/arch/i386/defconfig Tue Jan 20 16:51:22 1998 @@ -32,6 +32,7 @@ CONFIG_PCI_DIRECT=y # CONFIG_MCA is not set CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y @@ -84,6 +85,7 @@ # CONFIG_NETLINK is not set # CONFIG_FIREWALL is not set # CONFIG_NET_ALIAS is not set +# CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -265,8 +267,6 @@ # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set # CONFIG_VIDEO_DEV is not set -# CONFIG_VIDEO_BT848 is not set -# CONFIG_VIDEO_PMS is not set # CONFIG_NVRAM is not set # CONFIG_JOYSTICK is not set # CONFIG_MISC_RADIO is not set @@ -284,6 +284,7 @@ # # Kernel hacking # -# CONFIG_PROFILE is not set +CONFIG_PROFILE=y +CONFIG_PROFILE_SHIFT=2 # CONFIG_MAGIC_SYSRQ is not set CONFIG_VGA_CONSOLE=y diff -u --recursive --new-file v2.1.79/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile --- v2.1.79/linux/arch/i386/kernel/Makefile Sun Dec 21 22:36:12 1997 +++ linux/arch/i386/kernel/Makefile Tue Jan 20 12:52:09 1998 @@ -30,9 +30,10 @@ O_OBJS += mca.o endif + ifdef SMP -O_OBJS += smp.o trampoline.o +O_OBJS += io_apic.o smp.o trampoline.o head.o: head.S $(TOPDIR)/include/linux/tasks.h $(CC) -D__ASSEMBLY__ -D__SMP__ -traditional -c $*.S -o $*.o diff -u --recursive --new-file v2.1.79/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.1.79/linux/arch/i386/kernel/io_apic.c Wed Dec 31 16:00:00 1969 +++ linux/arch/i386/kernel/io_apic.c Tue Jan 20 12:52:09 1998 @@ -0,0 +1,513 @@ +/* + * Intel IO-APIC support for multi-pentium hosts. + * + * (c) 1997 Ingo Molnar, Hajnalka Szabo + * + * Many thanks to Stig Venaas for trying out countless experimental + * patches and reporting/debugging problems patiently! + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "irq.h" + +#define IO_APIC_BASE 0xfec00000 + +/* + * volatile is justified in this case, it might change + * spontaneously, GCC should not cache it + */ +volatile unsigned int * io_apic_reg = NULL; + +/* + * The structure of the IO-APIC: + */ +struct IO_APIC_reg_00 { + __u32 __reserved_2 : 24, + ID : 4, + __reserved_1 : 4; +} __attribute__ ((packed)); + +struct IO_APIC_reg_01 { + __u32 version : 8, + __reserved_2 : 8, + entries : 8, + __reserved_1 : 8; +} __attribute__ ((packed)); + +struct IO_APIC_reg_02 { + __u32 __reserved_2 : 24, + arbitration : 4, + __reserved_1 : 4; +} __attribute__ ((packed)); + +struct IO_APIC_route_entry { + __u32 vector : 8, + delivery_mode : 3, /* 000: FIXED + * 001: lowest prio + * 111: ExtInt + */ + dest_mode : 1, /* 0: physical, 1: logical */ + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, /* 0: edge, 1: level */ + mask : 1, /* 0: enabled, 1: disabled */ + __reserved_2 : 15; + + union { struct { __u32 + __reserved_1 : 24, + physical_dest : 4, + __reserved_2 : 4; + } physical; + + struct { __u32 + __reserved_1 : 24, + logical_dest : 8; + } logical; + } dest; + +} __attribute__ ((packed)); + +#define UNEXPECTED_IO_APIC() \ + { \ + printk(" WARNING: unexpected IO-APIC, please mail\n"); \ + printk(" to linux-smp@vger.rutgers.edu\n"); \ + } + +int nr_ioapic_registers = 0; /* # of IRQ routing registers */ +int mp_irq_entries = 0; /* # of MP IRQ source entries */ +struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; + /* MP IRQ source entries */ + +unsigned int io_apic_read (unsigned int reg) +{ + *io_apic_reg = reg; + return *(io_apic_reg+4); +} + +void io_apic_write (unsigned int reg, unsigned int value) +{ + *io_apic_reg = reg; + *(io_apic_reg+4) = value; +} + +void enable_IO_APIC_irq (int irq) +{ + struct IO_APIC_route_entry entry; + + /* + * Enable it in the IO-APIC irq-routing table: + */ + *(((int *)&entry)+0) = io_apic_read(0x10+irq*2); + entry.mask = 0; + io_apic_write(0x10+2*irq, *(((int *)&entry)+0)); +} + +void disable_IO_APIC_irq (int irq) +{ + struct IO_APIC_route_entry entry; + + /* + * Disable it in the IO-APIC irq-routing table: + */ + *(((int *)&entry)+0) = io_apic_read(0x10+irq*2); + entry.mask = 1; + io_apic_write(0x10+2*irq, *(((int *)&entry)+0)); +} + +void clear_IO_APIC_irq (int irq) +{ + struct IO_APIC_route_entry entry; + + /* + * Disable it in the IO-APIC irq-routing table: + */ + memset(&entry, 0, sizeof(entry)); + entry.mask = 1; + io_apic_write(0x10+2*irq, *(((int *)&entry)+0)); + io_apic_write(0x11+2*irq, *(((int *)&entry)+1)); +} + +/* + * support for broken MP BIOSes, enables hand-redirection of PIRQ0-3 to + * specific CPU-side IRQs. + */ + +#define MAX_PIRQS 4 +int pirq_entries [MAX_PIRQS]; + +void ioapic_pirq_setup(char *str, int *ints) +{ + int i, max; + + for (i=0; i IRQ %d\n", i, ints[i+1]); + /* + * PIRQs are mapped upside down, usually. + */ + pirq_entries[MAX_PIRQS-i-1]=ints[i+1]; + } + } +} + +int find_irq_entry(int pin) +{ + int i; + + for (i=mp_irq_entries-1; i>=0; i--) { + if (mp_irqs[i].mpc_dstirq == pin) + return i; + } + return -1; +} + +void setup_IO_APIC_irqs (void) +{ + struct IO_APIC_route_entry entry; + int i, idx, bus, irq, first_notcon=1; + + printk("init IO_APIC IRQs\n"); + + for (i=0; i> 2; + if (irq>=16) + printk("WARNING: MP BIOS says PIRQ%d is redirected to %d, suspicious.\n",idx-16, irq); + break; + } + default: + { + printk("unknown bus type %d.\n",bus); + irq = 0; + break; + } + } + + /* + * PCI IRQ redirection. Yes, limits are hardcoded. + */ + if ((i>=16) && (i<=19)) { + if (pirq_entries[i-16] != -1) { + if (!pirq_entries[i-16]) { + printk("disabling PIRQ%d\n", i-16); + } else { + irq = pirq_entries[i-16]; + printk("using PIRQ%d -> IRQ %d\n", + i-16, irq); + } + } + } + + if (!IO_APIC_IRQ(irq)) + continue; + + entry.vector = IO_APIC_GATE_OFFSET + (irq<<3); + + /* + * Determine IRQ line polarity (high active or low active): + */ + switch (mp_irqs[idx].mpc_irqflag & 3) + { + case 0: /* conforms, ie. bus-type dependent polarity */ + { + switch (mp_bus_id_to_type[bus]) + { + case MP_BUS_ISA: /* ISA pin */ + { + entry.polarity = 0; + break; + } + case MP_BUS_PCI: /* PCI pin */ + { + entry.polarity = 1; + break; + } + default: + { + printk("broken BIOS!!\n"); + break; + } + } + break; + } + case 1: /* high active */ + { + entry.polarity = 0; + break; + } + case 2: /* reserved */ + { + printk("broken BIOS!!\n"); + break; + } + case 3: /* low active */ + { + entry.polarity = 1; + break; + } + } + + /* + * Determine IRQ trigger mode (edge or level sensitive): + */ + switch ((mp_irqs[idx].mpc_irqflag>>2) & 3) + { + case 0: /* conforms, ie. bus-type dependent */ + { + switch (mp_bus_id_to_type[bus]) + { + case MP_BUS_ISA: /* ISA pin, edge */ + { + entry.trigger = 0; + break; + } + case MP_BUS_PCI: /* PCI pin, level */ + { + entry.trigger = 1; + break; + } + default: + { + printk("broken BIOS!!\n"); + break; + } + } + break; + } + case 1: /* edge */ + { + entry.trigger = 0; + break; + } + case 2: /* reserved */ + { + printk("broken BIOS!!\n"); + break; + } + case 3: /* level */ + { + entry.trigger = 1; + break; + } + } + + io_apic_write(0x10+2*i, *(((int *)&entry)+0)); + io_apic_write(0x11+2*i, *(((int *)&entry)+1)); + } + + if (!first_notcon) + printk(" not connected.\n"); +} + +void setup_IO_APIC_irq_ISA_default (int irq) +{ + struct IO_APIC_route_entry entry; + + /* + * add it to the IO-APIC irq-routing table: + */ + memset(&entry,0,sizeof(entry)); + + entry.delivery_mode = 1; /* lowest prio */ + entry.dest_mode = 1; /* logical delivery */ + entry.mask = 1; /* unmask IRQ now */ + entry.dest.logical.logical_dest = 0xff; /* all CPUs */ + + entry.vector = IO_APIC_GATE_OFFSET + (irq<<3); + + entry.polarity=0; + entry.trigger=0; + + io_apic_write(0x10+2*irq, *(((int *)&entry)+0)); + io_apic_write(0x11+2*irq, *(((int *)&entry)+1)); +} + +void setup_IO_APIC_irq (int irq) +{ +} + +void print_IO_APIC (void) +{ + int i; + struct IO_APIC_reg_00 reg_00; + struct IO_APIC_reg_01 reg_01; + struct IO_APIC_reg_02 reg_02; + + *(int *)®_00 = io_apic_read(0); + *(int *)®_01 = io_apic_read(1); + *(int *)®_02 = io_apic_read(2); + + /* + * We are a bit conservative about what we expect, we have to + * know about every HW change ASAP ... + */ + printk("testing the IO APIC.......................\n"); + + printk(".... register #00: %08X\n", *(int *)®_00); + printk("....... : physical APIC id: %02X\n", reg_00.ID); + if (reg_00.__reserved_1 || reg_00.__reserved_2) + UNEXPECTED_IO_APIC(); + + printk(".... register #01: %08X\n", *(int *)®_01); + printk("....... : max redirection entries: %04X\n", reg_01.entries); + if ( (reg_01.entries != 0x0f) && /* ISA-only Neptune boards */ + (reg_01.entries != 0x17) /* ISA+PCI boards */ + ) + UNEXPECTED_IO_APIC(); + if (reg_01.entries == 0x0f) + printk("....... [IO-APIC cannot route PCI PIRQ 0-3]\n"); + + printk("....... : IO APIC version: %04X\n", reg_01.version); + if ( (reg_01.version != 0x10) && /* oldest IO-APICs */ + (reg_01.version != 0x11) /* my IO-APIC */ + ) + UNEXPECTED_IO_APIC(); + if (reg_01.__reserved_1 || reg_01.__reserved_2) + UNEXPECTED_IO_APIC(); + + printk(".... register #02: %08X\n", *(int *)®_02); + printk("....... : arbitration: %02X\n", reg_02.arbitration); + if (reg_02.__reserved_1 || reg_02.__reserved_2) + UNEXPECTED_IO_APIC(); + + printk(".... IRQ redirection table:\n"); + + printk(" NR Log Phy "); + printk("Mask Trig IRR Pol Stat Dest Deli Vect: \n"); + + for (i=0; i<=reg_01.entries; i++) { + struct IO_APIC_route_entry entry; + + *(((int *)&entry)+0) = io_apic_read(0x10+i*2); + *(((int *)&entry)+1) = io_apic_read(0x11+i*2); + + printk(" %02x %03X %02X ", + i, + entry.dest.logical.logical_dest, + entry.dest.physical.physical_dest + ); + + printk("%1d %1d %1d %1d %1d %1d %1d %02X\n", + entry.mask, + entry.trigger, + entry.irr, + entry.polarity, + entry.delivery_status, + entry.dest_mode, + entry.delivery_mode, + entry.vector + ); + } + + printk(".................................... done.\n"); + + return; +} + +void init_sym_mode (void) +{ + printk("enabling Symmetric IO mode ... "); + outb (0x70, 0x22); + outb (0x01, 0x23); + printk("...done.\n"); +} + +void setup_IO_APIC (void) +{ + int i; + /* + * Map the IO APIC into kernel space + */ + + printk("mapping IO APIC from standard address.\n"); + io_apic_reg = ioremap_nocache(IO_APIC_BASE,4096); + printk("new virtual address: %p.\n",io_apic_reg); + + init_sym_mode(); + { + struct IO_APIC_reg_01 reg_01; + + *(int *)®_01 = io_apic_read(1); + nr_ioapic_registers = reg_01.entries+1; + } + + init_IO_APIC_traps(); + + /* + * do not trust the IO-APIC being empty at bootup + */ + for (i=0; i #include #include +#include #include #include @@ -36,11 +37,35 @@ #include #include #include +#include #include "irq.h" -#ifdef __SMP_PROF__ -extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]; +/* + * I had a lockup scenario where a tight loop doing + * spin_unlock()/spin_lock() on CPU#1 was racing with + * spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but + * apparently the spin_unlock() information did not make it + * through to CPU#0 ... nasty, is this by design, do we haveto limit + * 'memory update oscillation frequency' artificially like here? + * + * Such 'high frequency update' races can be avoided by careful design, but + * some of our major constructs like spinlocks use similar techniques, + * it would be nice to clarify this issue. Set this define to 0 if you + * want to check wether your system freezes. I suspect the delay done + * by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but + * i thought that such things are guaranteed by design, since we use + * the 'LOCK' prefix. + */ +#define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 1 + +#if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND +# define SYNC_OTHER_CORES(x) udelay(x+1) +#else +/* + * We have to allow irqs to arrive between __sti and __cli + */ +# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop") #endif unsigned int local_irq_count[NR_CPUS]; @@ -50,52 +75,115 @@ int __intel_bh_counter; #endif -#ifdef __SMP_PROF__ -static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},}; -#endif - atomic_t nmi_counter; /* - * This contains the irq mask for both irq controllers + * About the IO-APIC, the architecture is 'merged' into our + * current irq architecture, seemlessly. (i hope). It is only + * visible through 8 more hardware interrupt lines, but otherwise + * drivers are unaffected. The main code is believed to be + * NR_IRQS-safe (nothing anymore thinks we have 16 + * irq lines only), but there might be some places left ... + */ + +/* + * This contains the irq mask for both 8259A irq controllers, + * and on SMP the extended IO-APIC IRQs 16-23. The IO-APIC + * uses this mask too, in probe_irq*(). + * + * (0x0000ffff for NR_IRQS==16, 0x00ffffff for NR_IRQS=24) */ -static unsigned int cached_irq_mask = 0xffff; +static unsigned int cached_irq_mask = (1<> 8) & 0xff) spinlock_t irq_controller_lock; +static int irq_events [NR_IRQS] = { -1, }; +static int disabled_irq [NR_IRQS] = { 0, }; +#ifdef __SMP__ +static int irq_owner [NR_IRQS] = { NO_PROC_ID, }; +#endif + /* - * This is always called from an interrupt context - * with local interrupts disabled. Don't worry about - * irq-safe locks. - * - * Note that we always ack the primary irq controller, - * even if the interrupt came from the secondary, as - * the primary will still have routed it. Oh, the joys - * of PC hardware. + * Not all IRQs can be routed through the IO-APIC, eg. on certain (older) + * boards the timer interrupt and sometimes the keyboard interrupt is + * not connected to any IO-APIC pin, it's fed to the CPU ExtInt IRQ line + * directly. + * + * Any '1' bit in this mask means the IRQ is routed through the IO-APIC. + * this 'mixed mode' IRQ handling costs us one more branch in do_IRQ, + * but we have _much_ higher compatibility and robustness this way. */ -static inline void mask_and_ack_irq(int irq_nr) + +#ifndef __SMP__ + static const unsigned int io_apic_irqs = 0; +#else + /* + * the timer interrupt is not connected to the IO-APIC on all boards + * (mine is such ;), and since it is not performance critical anyway, + * we route it through the INTA pin and win lots of design simplicity. + * Ditto the obsolete EISA dma chaining irq. All other interrupts are + * routed through the IO-APIC, distributed amongst all CPUs, dependent + * on irq traffic and CPU load. + */ + const unsigned int io_apic_irqs = ~((1<<0)|(1<<2)|(1<<13)); +#endif + +static inline int ack_irq(int irq) { + /* + * The IO-APIC part will be moved to assembly, nested + * interrupts will be ~5 instructions from entry to iret ... + */ + int should_handle_irq = 0; + int cpu = smp_processor_id(); + + /* + * We always call this with local irqs disabled + */ spin_lock(&irq_controller_lock); - cached_irq_mask |= 1 << irq_nr; - if (irq_nr & 8) { - inb(0xA1); /* DUMMY */ - outb(cached_A1,0xA1); - outb(0x62,0x20); /* Specific EOI to cascade */ - outb(0x20,0xA0); - } else { - inb(0x21); /* DUMMY */ - outb(cached_21,0x21); - outb(0x20,0x20); + + if (!irq_events[irq]++ && !disabled_irq[irq]) { + should_handle_irq = 1; +#ifdef __SMP__ + irq_owner[irq] = cpu; +#endif + hardirq_enter(cpu); + } + + if (IO_APIC_IRQ(irq)) + ack_APIC_irq (); + else { + /* + * 8259-triggered INTA-cycle interrupt + */ + if (should_handle_irq) + mask_irq(irq); + + if (irq & 8) { + inb(0xA1); /* DUMMY */ + outb(0x62,0x20); /* Specific EOI to cascade */ + outb(0x20,0xA0); + } else { + inb(0x21); /* DUMMY */ + outb(0x20,0x20); + } } + spin_unlock(&irq_controller_lock); + + return (should_handle_irq); } -static inline void set_irq_mask(int irq_nr) +void set_8259A_irq_mask(int irq) { - if (irq_nr & 8) { + if (irq >= 16) { + printk ("HUH #3 (%d)?\n", irq); + return; + } + if (irq & 8) { outb(cached_A1,0xA1); } else { outb(cached_21,0x21); @@ -106,80 +194,105 @@ * These have to be protected by the spinlock * before being called. */ -static inline void mask_irq(unsigned int irq_nr) +void mask_irq(unsigned int irq) { - cached_irq_mask |= 1 << irq_nr; - set_irq_mask(irq_nr); + if (IO_APIC_IRQ(irq)) + disable_IO_APIC_irq(irq); + else { + cached_irq_mask |= 1 << irq; + set_8259A_irq_mask(irq); + } } -static inline void unmask_irq(unsigned int irq_nr) +void unmask_irq(unsigned int irq) { - cached_irq_mask &= ~(1 << irq_nr); - set_irq_mask(irq_nr); + if (IO_APIC_IRQ(irq)) + enable_IO_APIC_irq(irq); + else { + cached_irq_mask &= ~(1 << irq); + set_8259A_irq_mask(irq); + } } -void disable_irq(unsigned int irq_nr) -{ - unsigned long flags; +/* + * This builds up the IRQ handler stubs using some ugly macros in irq.h + * + * These macros create the low-level assembly IRQ routines that save + * register context and call do_IRQ(). do_IRQ() then does all the + * operations that are needed to keep the AT (or SMP IOAPIC) + * interrupt-controller happy. + */ - spin_lock_irqsave(&irq_controller_lock, flags); - mask_irq(irq_nr); - spin_unlock_irqrestore(&irq_controller_lock, flags); - synchronize_irq(); -} -void enable_irq(unsigned int irq_nr) -{ - unsigned long flags; +BUILD_COMMON_IRQ() +/* + * ISA PIC or IO-APIC triggered (INTA-cycle or APIC) interrupts: + */ +BUILD_IRQ(0) BUILD_IRQ(1) BUILD_IRQ(2) BUILD_IRQ(3) +BUILD_IRQ(4) BUILD_IRQ(5) BUILD_IRQ(6) BUILD_IRQ(7) +BUILD_IRQ(8) BUILD_IRQ(9) BUILD_IRQ(10) BUILD_IRQ(11) +BUILD_IRQ(12) BUILD_IRQ(13) BUILD_IRQ(14) BUILD_IRQ(15) - spin_lock_irqsave(&irq_controller_lock, flags); - unmask_irq(irq_nr); - spin_unlock_irqrestore(&irq_controller_lock, flags); -} +#ifdef __SMP__ /* - * This builds up the IRQ handler stubs using some ugly macros in irq.h + * The IO-APIC (persent only in SMP boards) has 8 more hardware + * interrupt pins, for all of them we define an IRQ vector: * - * These macros create the low-level assembly IRQ routines that do all - * the operations that are needed to keep the AT interrupt-controller - * happy. They are also written to be fast - and to disable interrupts - * as little as humanly possible. + * raw PCI interrupts 0-3, basically these are the ones used + * heavily: */ +BUILD_IRQ(16) BUILD_IRQ(17) BUILD_IRQ(18) BUILD_IRQ(19) -#if NR_IRQS != 16 -#error make irq stub building NR_IRQS dependent and remove me. -#endif +/* + * [FIXME: anyone with 2 separate PCI buses and 2 IO-APICs, + * please speak up and request experimental patches. + * --mingo ] + */ -BUILD_COMMON_IRQ() -BUILD_IRQ(FIRST,0,0x01) -BUILD_IRQ(FIRST,1,0x02) -BUILD_IRQ(FIRST,2,0x04) -BUILD_IRQ(FIRST,3,0x08) -BUILD_IRQ(FIRST,4,0x10) -BUILD_IRQ(FIRST,5,0x20) -BUILD_IRQ(FIRST,6,0x40) -BUILD_IRQ(FIRST,7,0x80) -BUILD_IRQ(SECOND,8,0x01) -BUILD_IRQ(SECOND,9,0x02) -BUILD_IRQ(SECOND,10,0x04) -BUILD_IRQ(SECOND,11,0x08) -BUILD_IRQ(SECOND,12,0x10) -BUILD_IRQ(SECOND,13,0x20) -BUILD_IRQ(SECOND,14,0x40) -BUILD_IRQ(SECOND,15,0x80) +/* + * MIRQ (motherboard IRQ) interrupts 0-1: + */ +BUILD_IRQ(20) BUILD_IRQ(21) -#ifdef __SMP__ +/* + * 'nondefined general purpose interrupt'. + */ +BUILD_IRQ(22) +/* + * optionally rerouted SMI interrupt: + */ +BUILD_IRQ(23) + +/* + * The following vectors are part of the Linux architecture, there + * is no hardware IRQ pin equivalent for them, they are triggered + * through the ICC by us (IPIs), via smp_message_pass(): + */ BUILD_SMP_INTERRUPT(reschedule_interrupt) BUILD_SMP_INTERRUPT(invalidate_interrupt) BUILD_SMP_INTERRUPT(stop_cpu_interrupt) + +/* + * every pentium local APIC has two 'local interrupts', with a + * soft-definable vector attached to both interrupts, one of + * which is a timer interrupt, the other one is error counter + * overflow. Linux uses the local APIC timer interrupt to get + * a much simpler SMP time architecture: + */ BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt) + #endif -static void (*interrupt[17])(void) = { +static void (*interrupt[NR_IRQS])(void) = { IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt, IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt, IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt, - IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt + IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt +#ifdef __SMP__ + ,IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt, + IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt +#endif }; /* @@ -215,135 +328,58 @@ */ static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; -static struct irqaction *irq_action[16] = { +static struct irqaction *irq_action[NR_IRQS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +#ifdef __SMP__ + ,NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL +#endif }; int get_irq_list(char *buf) { - int i; + int i, j; struct irqaction * action; char *p = buf; + p += sprintf(p, " "); + for (j=0; jname); + p += sprintf(p, "%3d: ",i); +#ifndef __SMP__ + p += sprintf(p, "%10u ", kstat.interrupts[0][i]); +#else + for (j=0; jname); + for (action=action->next; action; action = action->next) { p += sprintf(p, ", %s", action->name); } *p++ = '\n'; } p += sprintf(p, "NMI: %10u\n", atomic_read(&nmi_counter)); -#ifdef __SMP_PROF__ +#ifdef __SMP__ p += sprintf(p, "IPI: %10lu\n", ipi_count); #endif return p - buf; } -#ifdef __SMP_PROF__ - -extern unsigned int prof_multiplier[NR_CPUS]; -extern unsigned int prof_counter[NR_CPUS]; - -int get_smp_prof_list(char *buf) { - int i,j, len = 0; - struct irqaction * action; - unsigned long sum_spins = 0; - unsigned long sum_spins_syscall = 0; - unsigned long sum_spins_sys_idle = 0; - unsigned long sum_smp_idle_count = 0; - unsigned long sum_local_timer_ticks = 0; - - for (i=0;ihandler) - continue; - len += sprintf(buf+len, "%3d: %10d ", - i, kstat.interrupts[i]); - for (j=0;jname); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ", %s", action->name); - } - len += sprintf(buf+len, "\n"); - } - len+=sprintf(buf+len, "LCK: %10lu", - sum_spins); - - for (i=0;iflags & SA_INTERRUPT)) __sti(); +#endif do { status |= action->flags; - action->handler(irq, action->dev_id, ®s); + action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); __cli(); - spin_lock(&irq_controller_lock); - unmask_irq(irq); + } + + spin_lock(&irq_controller_lock); + +#ifdef __SMP__ + release_irqlock(cpu); +#endif + + if ((--irq_events[irq]) && (!disabled_irq[irq])) { + spin_unlock(&irq_controller_lock); + goto again; + } +#ifdef __SMP__ + /* FIXME: move this into hardirq.h */ + irq_owner[irq] = NO_PROC_ID; +#endif + hardirq_exit(cpu); + + spin_unlock(&irq_controller_lock); +} + + +/* + * disable/enable_irq() wait for all irq contexts to finish + * executing. Also it's recursive. + */ +void disable_irq(unsigned int irq) +{ +#ifdef __SMP__ + int cpu = smp_processor_id(); +#endif + unsigned long f, flags; + + save_flags(flags); + __save_flags(f); + __cli(); + spin_lock(&irq_controller_lock); + + disabled_irq[irq]++; + +#ifdef __SMP__ + /* + * We have to wait for all irq handlers belonging to this IRQ + * vector to finish executing. + */ + if ((irq_owner[irq] == NO_PROC_ID) || (irq_owner[irq] == cpu) || + (disabled_irq[irq] > 1)) { + spin_unlock(&irq_controller_lock); + __restore_flags(f); + restore_flags(flags); + if (disabled_irq[irq] > 100) + printk("disable_irq(%d), infinit recursion!\n",irq); + return; + } +#endif + + spin_unlock(&irq_controller_lock); + +#ifdef __SMP__ + synchronize_one_irq(irq); +#endif + + __restore_flags(f); + restore_flags(flags); +} + +void enable_irq(unsigned int irq) +{ + unsigned long flags; + int cpu = smp_processor_id(); + + spin_lock_irqsave(&irq_controller_lock,flags); + + if (!disabled_irq[irq]) { + spin_unlock_irqrestore(&irq_controller_lock,flags); + printk("more enable_irq(%d)'s than disable_irq(%d)'s!!",irq,irq); + return; + } + + disabled_irq[irq]--; + +#ifndef __SMP__ + if (disabled_irq[irq]) { + spin_unlock_irqrestore(&irq_controller_lock,flags); + return; + } +#else + if (disabled_irq[irq] || (irq_owner[irq] != NO_PROC_ID)) { + spin_unlock_irqrestore(&irq_controller_lock,flags); + return; + } +#endif + + /* + * Nobody is executing this irq handler currently, lets check + * wether we have outstanding events to be handled. + */ + + if (irq_events[irq]) { + struct pt_regs regs; + +#ifdef __SMP__ + irq_owner[irq] = cpu; +#endif + hardirq_enter(cpu); +#ifdef __SMP__ + release_irqlock(cpu); +#endif + spin_unlock(&irq_controller_lock); + + handle_IRQ_event(irq,®s); + __restore_flags(flags); + return; } + spin_unlock_irqrestore(&irq_controller_lock,flags); +} + +/* + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). + * + * the biggest change on SMP is the fact that we no more mask + * interrupts in hardware, please believe me, this is unavoidable, + * the hardware is largely message-oriented, i tried to force our + * state-driven irq handling scheme onto the IO-APIC, but no avail. + * + * so we soft-disable interrupts via 'event counters', the first 'incl' + * will do the IRQ handling. This also has the nice side effect of increased + * overlapping ... i saw no driver problem so far. + */ +asmlinkage void do_IRQ(struct pt_regs regs) +{ + /* + * We ack quickly, we don't want the irq controller + * thinking we're snobs just because some other CPU has + * disabled global interrupts (we have already done the + * INT_ACK cycles, it's too late to try to pretend to the + * controller that we aren't taking the interrupt). + * + * 0 return value means that this irq is already being + * handled by some other CPU. (or is disabled) + */ + int irq = regs.orig_eax & 0xff; + +/* + printk("<%d>",irq); + */ + if (!ack_irq(irq)) + return; + + handle_IRQ_event(irq,®s); + + unmask_irq(irq); - irq_exit(cpu, irq); /* * This should be conditional: we should really get * a return code from the irq handler to tell us @@ -581,6 +811,15 @@ if (!shared) { spin_lock(&irq_controller_lock); + if (IO_APIC_IRQ(irq)) { + /* + * First disable it in the 8259A: + */ + cached_irq_mask |= 1 << irq; + if (irq < 16) + set_8259A_irq_mask(irq); + setup_IO_APIC_irq(irq); + } unmask_irq(irq); spin_unlock(&irq_controller_lock); } @@ -597,12 +836,13 @@ int retval; struct irqaction * action; - if (irq > 15) + if (irq >= NR_IRQS) return -EINVAL; if (!handler) return -EINVAL; - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; @@ -625,7 +865,7 @@ struct irqaction * action, **p; unsigned long flags; - if (irq > 15) { + if (irq >= NR_IRQS) { printk("Trying to free IRQ%d\n",irq); return; } @@ -644,41 +884,100 @@ printk("Trying to free free IRQ%d\n",irq); } +/* + * probing is always single threaded [FIXME: is this true?] + */ +static unsigned int probe_irqs[NR_CPUS][NR_IRQS]; + unsigned long probe_irq_on (void) { - unsigned int i, irqs = 0; + unsigned int i, j, irqs = 0; unsigned long delay; - /* first, enable any unassigned irqs */ - for (i = 15; i > 0; i--) { + /* + * save current irq counts + */ + memcpy(probe_irqs,kstat.interrupts,NR_CPUS*NR_IRQS*sizeof(int)); + + /* + * first, enable any unassigned irqs + */ + for (i = NR_IRQS-1; i > 0; i--) { if (!irq_action[i]) { - enable_irq(i); + spin_lock(&irq_controller_lock); + unmask_irq(i); irqs |= (1 << i); + spin_unlock(&irq_controller_lock); } } - /* wait for spurious interrupts to mask themselves out again */ + /* + * wait for spurious interrupts to increase counters + */ for (delay = jiffies + HZ/10; delay > jiffies; ) - /* about 100ms delay */; + /* about 100ms delay */ synchronize_irq(); + + /* + * now filter out any obviously spurious interrupts + */ + for (i=0; i> 8 , 0x40); /* MSB */ - for (i = 0; i < NR_IRQS ; i++) + printk("INIT IRQ\n"); + for (i=0; impc_busid, str)); + if ((strncmp(m->mpc_bustype,"ISA",3) == 0) || + (strncmp(m->mpc_bustype,"EISA",4) == 0)) + mp_bus_id_to_type[m->mpc_busid] = + MP_BUS_ISA; + else + if (strncmp(m->mpc_bustype,"PCI",3) == 0) + mp_bus_id_to_type[m->mpc_busid] = + MP_BUS_PCI; mpt+=sizeof(*m); count+=sizeof(*m); break; @@ -363,6 +360,21 @@ struct mpc_config_intsrc *m= (struct mpc_config_intsrc *)mpt; + mp_irqs [mp_irq_entries] = *m; + if (++mp_irq_entries == MAX_IRQ_SOURCES) { + printk("Max irq sources exceeded!!\n"); + printk("Skipping remaining sources.\n"); + --mp_irq_entries; + } + +printk(" Itype:%d Iflag:%d srcbus:%d srcbusI:%d dstapic:%d dstI:%d.\n", + m->mpc_irqtype, + m->mpc_irqflag, + m->mpc_srcbus, + m->mpc_srcbusirq, + m->mpc_dstapic, + m->mpc_dstirq); + mpt+=sizeof(*m); count+=sizeof(*m); break; @@ -622,7 +634,7 @@ /* * Set up our APIC timer. */ - setup_APIC_clock (); + setup_APIC_clock(); sti(); /* @@ -1344,7 +1356,7 @@ else system=1; - irq_enter(cpu, 0); + irq_enter(cpu, 0); if (p->pid) { update_one_process(p, 1, user, system, cpu); @@ -1361,20 +1373,11 @@ kstat.cpu_system += system; kstat.per_cpu_system[cpu] += system; - } else { -#ifdef __SMP_PROF__ - if (test_bit(cpu,&smp_idle_map)) - smp_idle_count[cpu]++; -#endif } prof_counter[cpu]=prof_multiplier[cpu]; - irq_exit(cpu, 0); } -#ifdef __SMP_PROF__ - smp_local_timer_ticks[cpu]++; -#endif /* * We take the 'long' return path, and there every subsystem * grabs the apropriate locks (kernel lock/ irq lock). @@ -1420,6 +1423,7 @@ * This looks silly, but we actually do need to wait * for the global interrupt lock. */ + printk("huh, this is used, where???\n"); irq_enter(cpu, 0); need_resched = 1; irq_exit(cpu, 0); diff -u --recursive --new-file v2.1.79/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.1.79/linux/arch/i386/mm/fault.c Mon Jan 12 22:09:08 1998 +++ linux/arch/i386/mm/fault.c Tue Jan 20 12:52:09 1998 @@ -20,6 +20,7 @@ #include #include #include +#include extern void die_if_kernel(const char *,struct pt_regs *,long); @@ -99,6 +100,8 @@ /* get the address */ __asm__("movl %%cr2,%0":"=r" (address)); + if (local_irq_count[smp_processor_id()]) + die_if_kernel("page fault from irq handler",regs,error_code); lock_kernel(); tsk = current; mm = tsk->mm; diff -u --recursive --new-file v2.1.79/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c --- v2.1.79/linux/arch/ppc/kernel/idle.c Mon Jan 12 22:09:08 1998 +++ linux/arch/ppc/kernel/idle.c Fri Jan 16 20:34:18 1998 @@ -236,7 +236,7 @@ * If we're interrupted we keep this page and our place in it * since we validly hold it and it's reserved for us. */ - pageptr = __get_free_pages(GFP_ATOMIC, 0, 0 ); + pageptr = __get_free_pages(GFP_ATOMIC, 0); if ( !pageptr ) goto retry; diff -u --recursive --new-file v2.1.79/linux/arch/sparc/ap1000/apmmu.c linux/arch/sparc/ap1000/apmmu.c --- v2.1.79/linux/arch/sparc/ap1000/apmmu.c Sun Jan 26 02:07:06 1997 +++ linux/arch/sparc/ap1000/apmmu.c Fri Jan 16 20:39:23 1998 @@ -593,7 +593,7 @@ static unsigned long apmmu_alloc_kernel_stack(struct task_struct *tsk) { - unsigned long kstk = __get_free_pages(GFP_KERNEL, 1, 0); + unsigned long kstk = __get_free_pages(GFP_KERNEL, 1); if(!kstk) kstk = (unsigned long) vmalloc(PAGE_SIZE << 1); diff -u --recursive --new-file v2.1.79/linux/arch/sparc/ap1000/msc.c linux/arch/sparc/ap1000/msc.c --- v2.1.79/linux/arch/sparc/ap1000/msc.c Mon Jan 12 22:09:09 1998 +++ linux/arch/sparc/ap1000/msc.c Fri Jan 16 20:39:41 1998 @@ -237,7 +237,7 @@ MSC_OUT(MSC_SQRAM + i * 8, -1); if (!qof_base) { - qof_base = (struct qof_elt *) __get_free_pages(GFP_ATOMIC, QOF_ORDER, 0); + qof_base = (struct qof_elt *) __get_free_pages(GFP_ATOMIC, QOF_ORDER); for (i = MAP_NR(qof_base); i <= MAP_NR(((char*)qof_base)+QOF_SIZE-1);++i) set_bit(PG_reserved, &mem_map[i].flags); } @@ -285,7 +285,7 @@ if (!system_ringbuf.ringbuf) { system_ringbuf.ringbuf = - (void *)__get_free_pages(GFP_ATOMIC,SYSTEM_RINGBUF_ORDER,0); + (void *)__get_free_pages(GFP_ATOMIC,SYSTEM_RINGBUF_ORDER); for (i=MAP_NR(system_ringbuf.ringbuf); i<=MAP_NR(system_ringbuf.ringbuf+SYSTEM_RINGBUF_SIZE-1);i++) set_bit(PG_reserved, &mem_map[i].flags); @@ -294,7 +294,7 @@ if (!dummy_ringbuf.ringbuf) { dummy_ringbuf.ringbuf = - (void *)__get_free_pages(GFP_ATOMIC,DUMMY_RINGBUF_ORDER,0); + (void *)__get_free_pages(GFP_ATOMIC,DUMMY_RINGBUF_ORDER); for (i=MAP_NR(dummy_ringbuf.ringbuf); i<=MAP_NR(dummy_ringbuf.ringbuf+DUMMY_RINGBUF_SIZE-1);i++) set_bit(PG_reserved, &mem_map[i].flags); diff -u --recursive --new-file v2.1.79/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.1.79/linux/arch/sparc/mm/srmmu.c Mon Jan 12 22:09:10 1998 +++ linux/arch/sparc/mm/srmmu.c Fri Jan 16 20:38:45 1998 @@ -904,7 +904,7 @@ */ struct task_struct *srmmu_alloc_task_struct(void) { - return (struct task_struct *) __get_free_pages(GFP_KERNEL, 1, 0); + return (struct task_struct *) __get_free_pages(GFP_KERNEL, 1); } static void srmmu_free_task_struct(struct task_struct *tsk) diff -u --recursive --new-file v2.1.79/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.1.79/linux/arch/sparc/mm/sun4c.c Mon Aug 4 16:25:37 1997 +++ linux/arch/sparc/mm/sun4c.c Fri Jan 16 20:38:57 1998 @@ -1185,7 +1185,7 @@ unsigned long addr, pages; int entry; - pages = __get_free_pages(GFP_KERNEL, 1, 0); + pages = __get_free_pages(GFP_KERNEL, 1); if(!pages) return (struct task_struct *) 0; diff -u --recursive --new-file v2.1.79/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.1.79/linux/arch/sparc64/mm/init.c Mon Jan 12 22:09:11 1998 +++ linux/arch/sparc64/mm/init.c Fri Jan 16 20:34:00 1998 @@ -265,7 +265,7 @@ ((dvma_pages_current_offset + len) > (1 << 16))) { struct linux_sbus *sbus; unsigned long *iopte; - unsigned long newpages = __get_free_pages(GFP_KERNEL, 3, 0); + unsigned long newpages = __get_free_pages(GFP_KERNEL, 3); int i; if(!newpages) diff -u --recursive --new-file v2.1.79/linux/drivers/ap1000/ringbuf.c linux/drivers/ap1000/ringbuf.c --- v2.1.79/linux/drivers/ap1000/ringbuf.c Mon Jun 16 16:35:54 1997 +++ linux/drivers/ap1000/ringbuf.c Fri Jan 16 20:38:21 1998 @@ -49,7 +49,7 @@ /* preallocate some ringbuffers */ for (i=0;iinfo; - if (p->type == IDE_DRIVER_MODULE && driver) - out += sprintf(out, "%s version %s\n", driver->name, driver->version); - p = p->next; - } - len = out - page; - PROC_IDE_READ_RETURN(page,start,off,count,eof,len); -} - static int proc_ide_read_config (char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -310,6 +282,34 @@ PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } #endif /* CONFIG_PCI */ + +static int ide_getdigit(char c) +{ + int digit; + if (isdigit(c)) + digit = c - '0'; + else + digit = -1; + return digit; +} + +static int proc_ide_read_drivers + (char *page, char **start, off_t off, int count, int *eof, void *data) +{ + char *out = page; + int len; + ide_module_t *p = ide_modules; + ide_driver_t *driver; + + while (p) { + driver = (ide_driver_t *) p->info; + if (p->type == IDE_DRIVER_MODULE && driver) + out += sprintf(out, "%s version %s\n", driver->name, driver->version); + p = p->next; + } + len = out - page; + PROC_IDE_READ_RETURN(page,start,off,count,eof,len); +} static int proc_ide_read_type (char *page, char **start, off_t off, int count, int *eof, void *data) diff -u --recursive --new-file v2.1.79/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.1.79/linux/drivers/block/md.c Tue Dec 2 16:45:18 1997 +++ linux/drivers/block/md.c Thu Jan 15 14:33:05 1998 @@ -493,7 +493,7 @@ /* * ioctl : one open channel */ - printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", + printk ("STOP_MD md%x failed : i_count=%ld, busy=%d\n", minor, inode->i_count, md_dev[minor].busy); return -EBUSY; } diff -u --recursive --new-file v2.1.79/linux/drivers/block/raid5.c linux/drivers/block/raid5.c --- v2.1.79/linux/drivers/block/raid5.c Tue Dec 23 16:30:59 1997 +++ linux/drivers/block/raid5.c Fri Jan 16 20:34:51 1998 @@ -1372,7 +1372,7 @@ memset (raid_conf, 0, sizeof (*raid_conf)); raid_conf->mddev = mddev; - if ((raid_conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER, 0)) == NULL) + if ((raid_conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) goto abort; memset(raid_conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); diff -u --recursive --new-file v2.1.79/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.1.79/linux/drivers/char/Config.in Mon Jan 12 22:09:12 1998 +++ linux/drivers/char/Config.in Tue Jan 20 16:44:57 1998 @@ -109,12 +109,14 @@ bool 'Tadpole ANA H8 Support' CONFIG_H8 fi tristate 'Video For Linux' CONFIG_VIDEO_DEV -dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV -if [ "$CONFIG_PARPORT" != "n" ]; then - dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV - dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV +if [ "$CONFIG_VIDEO_DEV" != n ]; then + dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV + if [ "$CONFIG_PARPORT" != "n" ]; then + dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV + dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV + fi + dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV fi -dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV tristate '/dev/nvram support' CONFIG_NVRAM tristate 'PC joystick support' CONFIG_JOYSTICK bool 'Radio Device Support' CONFIG_MISC_RADIO diff -u --recursive --new-file v2.1.79/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.1.79/linux/drivers/char/bttv.c Mon Jan 12 22:09:12 1998 +++ linux/drivers/char/bttv.c Thu Jan 15 14:33:05 1998 @@ -1478,7 +1478,20 @@ unsigned char bus, devfn; unsigned char b, bo; - /* nothing wrong with this one, just checking buffer control config */ + /* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */ + + if (!pcibios_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, index, &bus, &devfn)) + { + printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n"); + } + + if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, + index, &bus, &devfn)) + { + pcibios_read_config_byte(bus, devfn, 0x53, &b); + DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, ")); + DEBUG(printk("bufcon=0x%02x\n",b)); + } if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, index, &bus, &devfn)) diff -u --recursive --new-file v2.1.79/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c --- v2.1.79/linux/drivers/char/dsp56k.c Mon Jun 16 16:35:55 1997 +++ linux/drivers/char/dsp56k.c Mon Jan 19 13:43:25 1998 @@ -425,7 +425,7 @@ * but how do I then check device minor number? * Do I need this function at all??? */ -#ifdef 0 +#if 0 static int dsp56k_select(struct inode *inode, struct file *file, int sel_type, select_table *wait) { diff -u --recursive --new-file v2.1.79/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.1.79/linux/drivers/char/epca.c Wed Sep 24 20:05:46 1997 +++ linux/drivers/char/epca.c Thu Jan 15 14:33:06 1998 @@ -29,7 +29,9 @@ #ifdef MODVERSIONS +#ifndef MODULE #define MODULE +#endif #endif /* ----------------------------------------------------------------------- diff -u --recursive --new-file v2.1.79/linux/drivers/char/tuner.h linux/drivers/char/tuner.h --- v2.1.79/linux/drivers/char/tuner.h Sat Nov 29 11:25:09 1997 +++ linux/drivers/char/tuner.h Tue Jan 13 20:14:36 1998 @@ -54,6 +54,7 @@ unchar UHF; unchar config; unchar I2C; + ushort IFPCoff; }; #endif diff -u --recursive --new-file v2.1.79/linux/drivers/isdn/Makefile linux/drivers/isdn/Makefile --- v2.1.79/linux/drivers/isdn/Makefile Thu May 29 21:53:05 1997 +++ linux/drivers/isdn/Makefile Fri Jan 16 11:18:09 1998 @@ -47,7 +47,7 @@ endif ifeq ($(CONFIG_ISDN_DRV_ICN),y) - L_OBJS += icn/icn.o + L_OBJS += icn/icn_obj.o SUB_DIRS += icn MOD_SUB_DIRS += icn else diff -u --recursive --new-file v2.1.79/linux/drivers/isdn/hisax/buffers.c linux/drivers/isdn/hisax/buffers.c --- v2.1.79/linux/drivers/isdn/hisax/buffers.c Thu Feb 27 10:57:29 1997 +++ linux/drivers/isdn/hisax/buffers.c Fri Jan 16 20:35:48 1998 @@ -53,7 +53,7 @@ printk(KERN_DEBUG "BufPoolAdd bp %x\n", bp); #endif - ptr = (struct Pages *) __get_free_pages(priority, bp->pageorder, 0); + ptr = (struct Pages *) __get_free_pages(priority, bp->pageorder); if (!ptr) { printk(KERN_WARNING "BufPoolAdd couldn't get pages!\n"); return (-1); diff -u --recursive --new-file v2.1.79/linux/drivers/isdn/icn/Makefile linux/drivers/isdn/icn/Makefile --- v2.1.79/linux/drivers/isdn/icn/Makefile Mon Feb 26 01:58:04 1996 +++ linux/drivers/isdn/icn/Makefile Fri Jan 16 11:18:09 1998 @@ -1,11 +1,8 @@ -L_OBJS := -M_OBJS := - ifeq ($(CONFIG_ISDN_DRV_ICN),y) - L_OBJS += icn.o + O_TARGET := icn_obj.o + O_OBJS := icn.o else - M_OBJS += icn.o + M_OBJS := icn.o endif include $(TOPDIR)/Rules.make - diff -u --recursive --new-file v2.1.79/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.1.79/linux/drivers/net/Config.in Tue Jan 6 09:37:34 1998 +++ linux/drivers/net/Config.in Thu Jan 15 14:33:06 1998 @@ -183,7 +183,7 @@ bool 'WAN drivers' CONFIG_WAN_DRIVERS if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then dep_tristate 'Sangoma WANPIPE(tm) multiprotocol cards' CONFIG_VENDOR_SANGOMA $CONFIG_WAN_DRIVERS - if [ "$CONFIG_VENDOR_SANGOMA" = "y" ]; then + if [ "$CONFIG_VENDOR_SANGOMA" != "n" ]; then int ' Maximum number of cards' CONFIG_WANPIPE_CARDS 1 bool ' WANPIPE X.25 support' CONFIG_WANPIPE_X25 bool ' WANPIPE Frame Relay support' CONFIG_WANPIPE_FR diff -u --recursive --new-file v2.1.79/linux/drivers/net/hamradio/dmascc.c linux/drivers/net/hamradio/dmascc.c --- v2.1.79/linux/drivers/net/hamradio/dmascc.c Tue Jan 6 09:37:34 1998 +++ linux/drivers/net/hamradio/dmascc.c Thu Jan 15 14:33:06 1998 @@ -41,7 +41,6 @@ #include #include #include -#include #include "z8530.h" diff -u --recursive --new-file v2.1.79/linux/drivers/net/hp.c linux/drivers/net/hp.c --- v2.1.79/linux/drivers/net/hp.c Tue Jan 6 09:37:34 1998 +++ linux/drivers/net/hp.c Thu Jan 15 14:33:06 1998 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.1.79/linux/drivers/net/ipddp.c linux/drivers/net/ipddp.c --- v2.1.79/linux/drivers/net/ipddp.c Mon Jan 12 22:09:15 1998 +++ linux/drivers/net/ipddp.c Thu Jan 15 14:33:06 1998 @@ -256,7 +256,6 @@ memcpy(skb->data,(void *)&at,sizeof(at)); skb->dev = rt->dev; /* set skb->dev to appropriate device */ - skb->arp = 1; /* so the actual device doesn't try to arp it... */ skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */ return 0; diff -u --recursive --new-file v2.1.79/linux/drivers/net/ni52.c linux/drivers/net/ni52.c --- v2.1.79/linux/drivers/net/ni52.c Sat Nov 29 11:25:10 1997 +++ linux/drivers/net/ni52.c Mon Jan 19 13:43:36 1998 @@ -989,7 +989,7 @@ } #endif -#ifdef 0 +#if 0 if(!at_least_one) { int i; diff -u --recursive --new-file v2.1.79/linux/drivers/net/sdla_fr.c linux/drivers/net/sdla_fr.c --- v2.1.79/linux/drivers/net/sdla_fr.c Mon Jan 12 22:09:15 1998 +++ linux/drivers/net/sdla_fr.c Thu Jan 15 14:33:06 1998 @@ -1,4 +1,4 @@ -/***************************************************************************** + * sdla_fr.c WANPIPE(tm) Multiprotocol WAN Link Driver. Frame relay module. * * Author(s): Gene Kozin @@ -673,9 +673,8 @@ /* Set transmit buffer queue length */ dev->tx_queue_len = 30; - /* Initialize socket buffers */ - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); + dev_init_buffers(dev); + set_chan_state(dev, WAN_DISCONNECTED); return 0; } diff -u --recursive --new-file v2.1.79/linux/drivers/net/sdla_ppp.c linux/drivers/net/sdla_ppp.c --- v2.1.79/linux/drivers/net/sdla_ppp.c Mon Jan 12 22:09:15 1998 +++ linux/drivers/net/sdla_ppp.c Thu Jan 15 14:33:06 1998 @@ -478,9 +478,8 @@ dev->tx_queue_len = 100; /* Initialize socket buffers */ - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); - + dev_init_buffers(dev); + return 0; } diff -u --recursive --new-file v2.1.79/linux/drivers/net/sdla_x25.c linux/drivers/net/sdla_x25.c --- v2.1.79/linux/drivers/net/sdla_x25.c Mon Jan 12 22:09:15 1998 +++ linux/drivers/net/sdla_x25.c Thu Jan 15 14:33:06 1998 @@ -572,9 +572,8 @@ dev->tx_queue_len = 10; /* Initialize socket buffers */ - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]) - ; + dev_init_buffers(dev); + set_chan_state(dev, WAN_DISCONNECTED); return 0; } diff -u --recursive --new-file v2.1.79/linux/drivers/net/shaper.c linux/drivers/net/shaper.c --- v2.1.79/linux/drivers/net/shaper.c Sat Nov 29 11:25:10 1997 +++ linux/drivers/net/shaper.c Thu Jan 15 14:33:06 1998 @@ -254,7 +254,6 @@ if(newskb) { newskb->dev=shaper->dev; - newskb->arp=1; newskb->priority=2; if(sh_debug) printk("Kick new frame to %s, %d\n", @@ -448,17 +447,17 @@ return v; } -static int shaper_cache(struct dst_entry *dst, struct neighbour *neigh, struct hh_cache *hh) +static int shaper_cache(struct neighbour *neigh, struct hh_cache *hh) { - struct shaper *sh=dst->dev->priv; + struct shaper *sh=neigh->dev->priv; struct device *tmp; int ret; if(sh_debug) printk("Shaper header cache bind\n"); - tmp=dst->dev; - dst->dev=sh->dev; - ret=sh->hard_header_cache(dst,neigh,hh); - dst->dev=tmp; + tmp=neigh->dev; + neigh->dev=sh->dev; + ret=sh->hard_header_cache(neigh,hh); + neigh->dev=tmp; return ret; } diff -u --recursive --new-file v2.1.79/linux/drivers/net/strip.c linux/drivers/net/strip.c --- v2.1.79/linux/drivers/net/strip.c Mon Dec 1 12:04:13 1997 +++ linux/drivers/net/strip.c Thu Jan 15 14:33:06 1998 @@ -82,7 +82,6 @@ #include #endif -#include #include #include #include diff -u --recursive --new-file v2.1.79/linux/drivers/net/tulip.c linux/drivers/net/tulip.c --- v2.1.79/linux/drivers/net/tulip.c Mon Jan 12 22:09:15 1998 +++ linux/drivers/net/tulip.c Tue Jan 20 16:44:57 1998 @@ -1100,11 +1100,7 @@ outl(0x00200000 | 0x4800, ioaddr + CSR0); #else #ifndef ORIGINAL_TEXT -#ifndef __SMP__ -#define x86 ((struct cpuinfo_x86*)cpu_data)->x86 -#else -#error What should we make here? -#endif +#define x86 (boot_cpu_data.x86) #endif outl(0x00200000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0); if (x86 <= 4) @@ -1753,7 +1749,15 @@ #ifdef CONFIG_NET_FASTROUTE cli(); - dev->tx_semaphore = 0; + if (xchg(&dev->tx_semaphore,0) == 0) { + sti(); + /* With new queueing algorithm returning 1 when dev->tbusy == 0 + should not result in lockups, but I am still not sure. --ANK + */ + if (net_ratelimit()) + printk(KERN_CRIT "Please check: are you still alive?\n"); + return 1; + } #endif /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ @@ -1764,7 +1768,7 @@ if (jiffies - dev->trans_start >= TX_TIMEOUT) tulip_tx_timeout(dev); #ifdef CONFIG_NET_FASTROUTE - dev->tx_semaphore = 0; + dev->tx_semaphore = 1; #endif return 1; } @@ -1796,6 +1800,7 @@ flag |= 0xe2000000; tp->tx_ring[entry].length = skb->len | flag; + tp->stats.tx_bytes += skb->len; tp->tx_ring[entry].status = 0x80000000; /* Pass ownership to the chip. */ tp->cur_tx++; /* Trigger an immediate transmit demand. */ @@ -1803,7 +1808,7 @@ dev->trans_start = jiffies; #ifdef CONFIG_NET_FASTROUTE - dev->tx_semaphore = 0; + dev->tx_semaphore = 1; sti(); #endif diff -u --recursive --new-file v2.1.79/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.1.79/linux/drivers/scsi/BusLogic.c Mon Aug 11 14:47:04 1997 +++ linux/drivers/scsi/BusLogic.c Tue Jan 20 15:02:21 1998 @@ -2337,11 +2337,16 @@ /* Issue the Test Command Complete Interrupt commands. */ - InitialInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; + + InitialInterruptCount = 0; + for (i=0; iIRQ_Channel]; for (i = 0; i < TestCount; i++) BusLogic_Command(HostAdapter, BusLogic_TestCommandCompleteInterrupt, NULL, 0, NULL, 0); - FinalInterruptCount = kstat.interrupts[HostAdapter->IRQ_Channel]; + FinalInterruptCount = 0; + for (i=0; iIRQ_Channel]; /* Verify that BusLogic_InterruptHandler was called at least TestCount times. Shared IRQ Channels could cause more than TestCount interrupts to diff -u --recursive --new-file v2.1.79/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c --- v2.1.79/linux/drivers/scsi/scsi.c Tue Jan 6 09:37:35 1998 +++ linux/drivers/scsi/scsi.c Thu Jan 15 21:11:01 1998 @@ -1910,7 +1910,7 @@ int scsi_loadable_module_flag; /* Set after we scan builtin drivers */ -void * scsi_init_malloc(unsigned int size, int priority) +void * scsi_init_malloc(unsigned int size, int gfp_mask) { void * retval; @@ -1923,10 +1923,9 @@ for (order = 0, a_size = PAGE_SIZE; a_size < size; order++, a_size <<= 1) ; - retval = (void *) __get_dma_pages(priority & GFP_LEVEL_MASK, - order); + retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order); } else - retval = kmalloc(size, priority); + retval = kmalloc(size, gfp_mask); if (retval) memset(retval, 0, size); diff -u --recursive --new-file v2.1.79/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c --- v2.1.79/linux/drivers/scsi/scsi_error.c Mon Jan 12 22:09:16 1998 +++ linux/drivers/scsi/scsi_error.c Mon Jan 19 22:13:17 1998 @@ -1785,7 +1785,7 @@ * This needs to be attached to task[0] instead. */ - siginitsetinv(¤t->blocked, SHUTDOWN_SIGS); + sigfillset(¤t->blocked); current->fs->umask = 0; /* diff -u --recursive --new-file v2.1.79/linux/drivers/sound/Defines linux/drivers/sound/Defines --- v2.1.79/linux/drivers/sound/Defines Tue Dec 23 16:31:00 1997 +++ linux/drivers/sound/Defines Tue Jan 13 21:12:57 1998 @@ -97,10 +97,18 @@ endif endif -ifdef CONFIG_SB -ifneq ($(CONFIG_UART401),Y) -CONFIG_UART401=y -endif + + +ifdef CONFIG_SB + ifeq ($(CONFIG_SB),m) + ifneq ($(CONFIG_UART401),Y) + CONFIG_UART401=m + endif + else + ifneq ($(CONFIG_UART401),Y) + CONFIG_UART401=y + endif + endif endif ifdef CONFIG_TRIX diff -u --recursive --new-file v2.1.79/linux/drivers/sound/adlib_card.c linux/drivers/sound/adlib_card.c --- v2.1.79/linux/drivers/sound/adlib_card.c Sat Nov 29 11:25:10 1997 +++ linux/drivers/sound/adlib_card.c Tue Jan 20 16:44:57 1998 @@ -28,7 +28,6 @@ int probe_adlib(struct address_info *hw_config) { - if (check_region(hw_config->io_base, 4)) { DDB(printk("opl3.c: I/O port %x already in use\n", hw_config->io_base)); return 0; diff -u --recursive --new-file v2.1.79/linux/drivers/sound/audio.c linux/drivers/sound/audio.c --- v2.1.79/linux/drivers/sound/audio.c Fri Jan 2 14:37:02 1998 +++ linux/drivers/sound/audio.c Tue Jan 20 16:44:57 1998 @@ -362,144 +362,151 @@ /* else printk(KERN_DEBUG"/dev/dsp%d: No coprocessor for this device\n", dev); */ return -ENXIO; - } else switch (cmd) { - case SNDCTL_DSP_SYNC: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return 0; - if (audio_devs[dev]->dmap_out->fragment_size == 0) + } + else switch (cmd) + { + case SNDCTL_DSP_SYNC: + if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) + return 0; + if (audio_devs[dev]->dmap_out->fragment_size == 0) + return 0; + sync_output(dev); + DMAbuf_sync(dev); + DMAbuf_reset(dev); return 0; - sync_output(dev); - DMAbuf_sync(dev); - DMAbuf_reset(dev); - return 0; - case SNDCTL_DSP_POST: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return 0; - if (audio_devs[dev]->dmap_out->fragment_size == 0) + case SNDCTL_DSP_POST: + if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) + return 0; + if (audio_devs[dev]->dmap_out->fragment_size == 0) + return 0; + audio_devs[dev]->dmap_out->flags |= DMA_POST | DMA_DIRTY; + sync_output(dev); + dma_ioctl(dev, SNDCTL_DSP_POST, (caddr_t) 0); return 0; - audio_devs[dev]->dmap_out->flags |= DMA_POST | DMA_DIRTY; - sync_output(dev); - dma_ioctl(dev, SNDCTL_DSP_POST, (caddr_t) 0); - return 0; - - case SNDCTL_DSP_RESET: - audio_mode[dev] = AM_NONE; - DMAbuf_reset(dev); - return 0; - - case SNDCTL_DSP_GETFMTS: - val = audio_devs[dev]->format_mask; - return __put_user(val, (int *)arg); - - case SNDCTL_DSP_SETFMT: - if (__get_user(val, (int *)arg)) - return -EFAULT; - val = set_format(dev, val); - return __put_user(val, (int *)arg); - case SNDCTL_DSP_GETISPACE: - if (!(audio_devs[dev]->open_mode & OPEN_READ)) + case SNDCTL_DSP_RESET: + audio_mode[dev] = AM_NONE; + DMAbuf_reset(dev); return 0; - if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) - return -EBUSY; - return dma_ioctl(dev, cmd, arg); - - case SNDCTL_DSP_GETOSPACE: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EPERM; - if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) - return -EBUSY; - return dma_ioctl(dev, cmd, arg); + + case SNDCTL_DSP_GETFMTS: + val = audio_devs[dev]->format_mask; + break; + + case SNDCTL_DSP_SETFMT: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = set_format(dev, val); + break; + + case SNDCTL_DSP_GETISPACE: + if (!(audio_devs[dev]->open_mode & OPEN_READ)) + return 0; + if ((audio_mode[dev] & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX)) + return -EBUSY; + return dma_ioctl(dev, cmd, arg); + + case SNDCTL_DSP_GETOSPACE: + if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) + return -EPERM; + if ((audio_mode[dev] & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX)) + return -EBUSY; + return dma_ioctl(dev, cmd, arg); - case SNDCTL_DSP_NONBLOCK: - dev_nblock[dev] = 1; - return 0; - - case SNDCTL_DSP_GETCAPS: - info = 1 | DSP_CAP_MMAP; /* Revision level of this ioctl() */ - if (audio_devs[dev]->flags & DMA_DUPLEX && - audio_devs[dev]->open_mode == OPEN_READWRITE) - info |= DSP_CAP_DUPLEX; - if (audio_devs[dev]->coproc) - info |= DSP_CAP_COPROC; - if (audio_devs[dev]->d->local_qlen) /* Device has hidden buffers */ - info |= DSP_CAP_BATCH; - if (audio_devs[dev]->d->trigger) /* Supports SETTRIGGER */ - info |= DSP_CAP_TRIGGER; - return __put_user(info, (int *)arg); + case SNDCTL_DSP_NONBLOCK: + dev_nblock[dev] = 1; + return 0; + + case SNDCTL_DSP_GETCAPS: + info = 1 | DSP_CAP_MMAP; /* Revision level of this ioctl() */ + if (audio_devs[dev]->flags & DMA_DUPLEX && + audio_devs[dev]->open_mode == OPEN_READWRITE) + info |= DSP_CAP_DUPLEX; + if (audio_devs[dev]->coproc) + info |= DSP_CAP_COPROC; + if (audio_devs[dev]->d->local_qlen) /* Device has hidden buffers */ + info |= DSP_CAP_BATCH; + if (audio_devs[dev]->d->trigger) /* Supports SETTRIGGER */ + info |= DSP_CAP_TRIGGER; + break; - case SOUND_PCM_WRITE_RATE: - if (__get_user(val, (int *)arg)) - return -EFAULT; - val = audio_devs[dev]->d->set_speed(dev, val); - return __put_user(val, (int *)arg); - - case SOUND_PCM_READ_RATE: - val = audio_devs[dev]->d->set_speed(dev, 0); - return __put_user(val, (int *)arg); - - case SNDCTL_DSP_STEREO: - if (__get_user(val, (int *)arg)) - return -EFAULT; - if (val > 1 || val < 0) - return -EINVAL; - val = audio_devs[dev]->d->set_channels(dev, val + 1) - 1; - return __put_user(val, (int *)arg); - - case SOUND_PCM_WRITE_CHANNELS: - if (__get_user(val, (int *)arg)) - return -EFAULT; - val = audio_devs[dev]->d->set_channels(dev, val); - return __put_user(val, (int *)arg); - - case SOUND_PCM_READ_CHANNELS: - val = audio_devs[dev]->d->set_channels(dev, 0); - return __put_user(val, (int *)arg); + case SOUND_PCM_WRITE_RATE: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = audio_devs[dev]->d->set_speed(dev, val); + break; + + case SOUND_PCM_READ_RATE: + val = audio_devs[dev]->d->set_speed(dev, 0); + break; + + case SNDCTL_DSP_STEREO: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val > 1 || val < 0) + return -EINVAL; + val = audio_devs[dev]->d->set_channels(dev, val + 1) - 1; + break; + + case SOUND_PCM_WRITE_CHANNELS: + if (get_user(val, (int *)arg)) + return -EFAULT; + val = audio_devs[dev]->d->set_channels(dev, val); + break; + + case SOUND_PCM_READ_CHANNELS: + val = audio_devs[dev]->d->set_channels(dev, 0); + break; - case SOUND_PCM_READ_BITS: - val = audio_devs[dev]->d->set_bits(dev, 0); - return __put_user(val, (int *)arg); - - case SNDCTL_DSP_SETDUPLEX: - if (audio_devs[dev]->open_mode != OPEN_READWRITE) - return -EPERM; - return (audio_devs[dev]->flags & DMA_DUPLEX) ? 0 : -EIO; - - case SNDCTL_DSP_PROFILE: - if (__get_user(val, (int *)arg)) - return -EFAULT; - if (audio_devs[dev]->open_mode & OPEN_WRITE) - audio_devs[dev]->dmap_out->applic_profile = val; - if (audio_devs[dev]->open_mode & OPEN_READ) - audio_devs[dev]->dmap_in->applic_profile = val; - return 0; + case SOUND_PCM_READ_BITS: + val = audio_devs[dev]->d->set_bits(dev, 0); + break; + + case SNDCTL_DSP_SETDUPLEX: + if (audio_devs[dev]->open_mode != OPEN_READWRITE) + return -EPERM; + return (audio_devs[dev]->flags & DMA_DUPLEX) ? 0 : -EIO; + + case SNDCTL_DSP_PROFILE: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (audio_devs[dev]->open_mode & OPEN_WRITE) + audio_devs[dev]->dmap_out->applic_profile = val; + if (audio_devs[dev]->open_mode & OPEN_READ) + audio_devs[dev]->dmap_in->applic_profile = val; + return 0; - case SNDCTL_DSP_GETODELAY: - dmap = audio_devs[dev]->dmap_out; - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EINVAL; - if (!(dmap->flags & DMA_ALLOC_DONE)) - return __put_user(0, (int *)arg); + case SNDCTL_DSP_GETODELAY: + dmap = audio_devs[dev]->dmap_out; + if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) + return -EINVAL; + if (!(dmap->flags & DMA_ALLOC_DONE)) + { + val=0; + break; + } - save_flags (flags); - cli(); - /* Compute number of bytes that have been played */ - count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT); - if (count < dmap->fragment_size && dmap->qhead != 0) - count += dmap->bytes_in_use; /* Pointer wrap not handled yet */ - count += dmap->byte_counter; + save_flags (flags); + cli(); + /* Compute number of bytes that have been played */ + count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT); + if (count < dmap->fragment_size && dmap->qhead != 0) + count += dmap->bytes_in_use; /* Pointer wrap not handled yet */ + count += dmap->byte_counter; - /* Substract current count from the number of bytes written by app */ - count = dmap->user_counter - count; - if (count < 0) - count = 0; - restore_flags (flags); - return __put_user(count, (int *)arg); + /* Substract current count from the number of bytes written by app */ + count = dmap->user_counter - count; + if (count < 0) + count = 0; + restore_flags (flags); + val = count; + break; - default: - return dma_ioctl(dev, cmd, arg); + default: + return dma_ioctl(dev, cmd, arg); } + return put_user(val, (int *)arg); } void audio_init_devices(void) @@ -641,7 +648,8 @@ static int dma_subdivide(int dev, struct dma_buffparms *dmap, int fact) { - if (fact == 0) { + if (fact == 0) + { fact = dmap->subdivision; if (fact == 0) fact = 1; @@ -722,210 +730,222 @@ int fact, ret, changed, bits, count, err; unsigned long flags; - switch (cmd) { - case SNDCTL_DSP_SUBDIVIDE: - ret = 0; - if (__get_user(fact, (int *)arg)) - return -EFAULT; - if (audio_devs[dev]->open_mode & OPEN_WRITE) - ret = dma_subdivide(dev, dmap_out, fact); - if (ret < 0) - return ret; - if (audio_devs[dev]->open_mode != OPEN_WRITE || - (audio_devs[dev]->flags & DMA_DUPLEX && - audio_devs[dev]->open_mode & OPEN_READ)) - ret = dma_subdivide(dev, dmap_in, fact); - if (ret < 0) - return ret; - return __put_user(ret, (int *)arg); - - case SNDCTL_DSP_GETISPACE: - case SNDCTL_DSP_GETOSPACE: - dmap = dmap_out; - if (cmd == SNDCTL_DSP_GETISPACE && !(audio_devs[dev]->open_mode & OPEN_READ)) - return -EINVAL; - if (cmd == SNDCTL_DSP_GETOSPACE && !(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EINVAL; - if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX) - dmap = dmap_in; - if (dmap->mapping_flags & DMA_MAP_MAPPED) - return -EINVAL; - if (!(dmap->flags & DMA_ALLOC_DONE)) - reorganize_buffers(dev, dmap, (cmd == SNDCTL_DSP_GETISPACE)); - info.fragstotal = dmap->nbufs; - if (cmd == SNDCTL_DSP_GETISPACE) - info.fragments = dmap->qlen; - else { - if (!DMAbuf_space_in_queue(dev)) - info.fragments = 0; - else { - info.fragments = DMAbuf_space_in_queue(dev); - if (audio_devs[dev]->d->local_qlen) { - int tmp = audio_devs[dev]->d->local_qlen(dev); - if (tmp && info.fragments) - tmp--; /* - * This buffer has been counted twice - */ - info.fragments -= tmp; + switch (cmd) + { + case SNDCTL_DSP_SUBDIVIDE: + ret = 0; + if (get_user(fact, (int *)arg)) + return -EFAULT; + if (audio_devs[dev]->open_mode & OPEN_WRITE) + ret = dma_subdivide(dev, dmap_out, fact); + if (ret < 0) + return ret; + if (audio_devs[dev]->open_mode != OPEN_WRITE || + (audio_devs[dev]->flags & DMA_DUPLEX && + audio_devs[dev]->open_mode & OPEN_READ)) + ret = dma_subdivide(dev, dmap_in, fact); + if (ret < 0) + return ret; + break; + + case SNDCTL_DSP_GETISPACE: + case SNDCTL_DSP_GETOSPACE: + dmap = dmap_out; + if (cmd == SNDCTL_DSP_GETISPACE && !(audio_devs[dev]->open_mode & OPEN_READ)) + return -EINVAL; + if (cmd == SNDCTL_DSP_GETOSPACE && !(audio_devs[dev]->open_mode & OPEN_WRITE)) + return -EINVAL; + if (cmd == SNDCTL_DSP_GETISPACE && audio_devs[dev]->flags & DMA_DUPLEX) + dmap = dmap_in; + if (dmap->mapping_flags & DMA_MAP_MAPPED) + return -EINVAL; + if (!(dmap->flags & DMA_ALLOC_DONE)) + reorganize_buffers(dev, dmap, (cmd == SNDCTL_DSP_GETISPACE)); + info.fragstotal = dmap->nbufs; + if (cmd == SNDCTL_DSP_GETISPACE) + info.fragments = dmap->qlen; + else + { + if (!DMAbuf_space_in_queue(dev)) + info.fragments = 0; + else + { + info.fragments = DMAbuf_space_in_queue(dev); + if (audio_devs[dev]->d->local_qlen) + { + int tmp = audio_devs[dev]->d->local_qlen(dev); + if (tmp && info.fragments) + tmp--; /* + * This buffer has been counted twice + */ + info.fragments -= tmp; + } } } - } - if (info.fragments < 0) + if (info.fragments < 0) info.fragments = 0; - else if (info.fragments > dmap->nbufs) - info.fragments = dmap->nbufs; + else if (info.fragments > dmap->nbufs) + info.fragments = dmap->nbufs; - info.fragsize = dmap->fragment_size; - info.bytes = info.fragments * dmap->fragment_size; + info.fragsize = dmap->fragment_size; + info.bytes = info.fragments * dmap->fragment_size; - if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen) - info.bytes -= dmap->counts[dmap->qhead]; - else { - info.fragments = info.bytes / dmap->fragment_size; - info.bytes -= dmap->user_counter % dmap->fragment_size; - } - return __copy_to_user(arg, &info, sizeof(info)); + if (cmd == SNDCTL_DSP_GETISPACE && dmap->qlen) + info.bytes -= dmap->counts[dmap->qhead]; + else + { + info.fragments = info.bytes / dmap->fragment_size; + info.bytes -= dmap->user_counter % dmap->fragment_size; + } + return copy_to_user(arg, &info, sizeof(info)); - case SNDCTL_DSP_SETTRIGGER: - if (__get_user(bits, (int *)arg)) - return -EFAULT; - bits &= audio_devs[dev]->open_mode; - if (audio_devs[dev]->d->trigger == NULL) - return -EINVAL; - if (!(audio_devs[dev]->flags & DMA_DUPLEX) && (bits & PCM_ENABLE_INPUT) && - (bits & PCM_ENABLE_OUTPUT)) - return -EINVAL; - save_flags(flags); - cli(); - changed = audio_devs[dev]->enable_bits ^ bits; - if ((changed & bits) & PCM_ENABLE_INPUT && audio_devs[dev]->go) { - reorganize_buffers(dev, dmap_in, 1); - if ((err = audio_devs[dev]->d->prepare_for_input(dev, + case SNDCTL_DSP_SETTRIGGER: + if (get_user(bits, (int *)arg)) + return -EFAULT; + bits &= audio_devs[dev]->open_mode; + if (audio_devs[dev]->d->trigger == NULL) + return -EINVAL; + if (!(audio_devs[dev]->flags & DMA_DUPLEX) && (bits & PCM_ENABLE_INPUT) && + (bits & PCM_ENABLE_OUTPUT)) + return -EINVAL; + save_flags(flags); + cli(); + changed = audio_devs[dev]->enable_bits ^ bits; + if ((changed & bits) & PCM_ENABLE_INPUT && audio_devs[dev]->go) + { + reorganize_buffers(dev, dmap_in, 1); + if ((err = audio_devs[dev]->d->prepare_for_input(dev, dmap_in->fragment_size, dmap_in->nbufs)) < 0) - return -err; - dmap_in->dma_mode = DMODE_INPUT; + return -err; + dmap_in->dma_mode = DMODE_INPUT; + audio_devs[dev]->enable_bits = bits; + DMAbuf_activate_recording(dev, dmap_in); + } + if ((changed & bits) & PCM_ENABLE_OUTPUT && + (dmap_out->mapping_flags & DMA_MAP_MAPPED || dmap_out->qlen > 0) && + audio_devs[dev]->go) + { + if (!(dmap_out->flags & DMA_ALLOC_DONE)) + reorganize_buffers(dev, dmap_out, 0); + dmap_out->dma_mode = DMODE_OUTPUT; + audio_devs[dev]->enable_bits = bits; + dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size; + DMAbuf_launch_output(dev, dmap_out); + } audio_devs[dev]->enable_bits = bits; - DMAbuf_activate_recording(dev, dmap_in); - } - if ((changed & bits) & PCM_ENABLE_OUTPUT && - (dmap_out->mapping_flags & DMA_MAP_MAPPED || dmap_out->qlen > 0) && - audio_devs[dev]->go) { + if (changed && audio_devs[dev]->d->trigger) + audio_devs[dev]->d->trigger(dev, bits * audio_devs[dev]->go); + restore_flags(flags); + /* Falls through... */ + + case SNDCTL_DSP_GETTRIGGER: + ret = audio_devs[dev]->enable_bits; + break; + + case SNDCTL_DSP_SETSYNCRO: + if (!audio_devs[dev]->d->trigger) + return -EINVAL; + audio_devs[dev]->d->trigger(dev, 0); + audio_devs[dev]->go = 0; + return 0; + + case SNDCTL_DSP_GETIPTR: + if (!(audio_devs[dev]->open_mode & OPEN_READ)) + return -EINVAL; + save_flags(flags); + cli(); + cinfo.bytes = dmap_in->byte_counter; + cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_in, DMODE_INPUT) & ~3; + if (cinfo.ptr < dmap_in->fragment_size && dmap_in->qtail != 0) + cinfo.bytes += dmap_in->bytes_in_use; /* Pointer wrap not handled yet */ + cinfo.blocks = dmap_in->qlen; + cinfo.bytes += cinfo.ptr; + if (dmap_in->mapping_flags & DMA_MAP_MAPPED) + dmap_in->qlen = 0; /* Reset interrupt counter */ + restore_flags(flags); + return copy_to_user(arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_GETOPTR: + if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) + return -EINVAL; + + save_flags(flags); + cli(); + cinfo.bytes = dmap_out->byte_counter; + cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_out, DMODE_OUTPUT) & ~3; + if (cinfo.ptr < dmap_out->fragment_size && dmap_out->qhead != 0) + cinfo.bytes += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */ + cinfo.blocks = dmap_out->qlen; + cinfo.bytes += cinfo.ptr; + if (dmap_out->mapping_flags & DMA_MAP_MAPPED) + dmap_out->qlen = 0; /* Reset interrupt counter */ + restore_flags(flags); + return copy_to_user(arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_GETODELAY: + if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) + return -EINVAL; if (!(dmap_out->flags & DMA_ALLOC_DONE)) - reorganize_buffers(dev, dmap_out, 0); - dmap_out->dma_mode = DMODE_OUTPUT; - audio_devs[dev]->enable_bits = bits; - dmap_out->counts[dmap_out->qhead] = dmap_out->fragment_size; - DMAbuf_launch_output(dev, dmap_out); - } - audio_devs[dev]->enable_bits = bits; - if (changed && audio_devs[dev]->d->trigger) - audio_devs[dev]->d->trigger(dev, bits * audio_devs[dev]->go); - restore_flags(flags); - /* Falls through... */ - - case SNDCTL_DSP_GETTRIGGER: - ret = audio_devs[dev]->enable_bits; - return __put_user(ret, (int *)arg); - - case SNDCTL_DSP_SETSYNCRO: - if (!audio_devs[dev]->d->trigger) - return -EINVAL; - audio_devs[dev]->d->trigger(dev, 0); - audio_devs[dev]->go = 0; - return 0; - - case SNDCTL_DSP_GETIPTR: - if (!(audio_devs[dev]->open_mode & OPEN_READ)) - return -EINVAL; - save_flags(flags); - cli(); - cinfo.bytes = dmap_in->byte_counter; - cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_in, DMODE_INPUT) & ~3; - if (cinfo.ptr < dmap_in->fragment_size && dmap_in->qtail != 0) - cinfo.bytes += dmap_in->bytes_in_use; /* Pointer wrap not handled yet */ - cinfo.blocks = dmap_in->qlen; - cinfo.bytes += cinfo.ptr; - if (dmap_in->mapping_flags & DMA_MAP_MAPPED) - dmap_in->qlen = 0; /* Reset interrupt counter */ - restore_flags(flags); - return __copy_to_user(arg, &cinfo, sizeof(cinfo)); - - case SNDCTL_DSP_GETOPTR: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EINVAL; - - save_flags(flags); - cli(); - cinfo.bytes = dmap_out->byte_counter; - cinfo.ptr = DMAbuf_get_buffer_pointer(dev, dmap_out, DMODE_OUTPUT) & ~3; - if (cinfo.ptr < dmap_out->fragment_size && dmap_out->qhead != 0) - cinfo.bytes += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */ - cinfo.blocks = dmap_out->qlen; - cinfo.bytes += cinfo.ptr; - if (dmap_out->mapping_flags & DMA_MAP_MAPPED) - dmap_out->qlen = 0; /* Reset interrupt counter */ - restore_flags(flags); - return __copy_to_user(arg, &cinfo, sizeof(cinfo)); - - case SNDCTL_DSP_GETODELAY: - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return -EINVAL; - if (!(dmap_out->flags & DMA_ALLOC_DONE)) - return __put_user(0, (int *)arg); - save_flags(flags); - cli(); - /* Compute number of bytes that have been played */ - count = DMAbuf_get_buffer_pointer (dev, dmap_out, DMODE_OUTPUT); - if (count < dmap_out->fragment_size && dmap_out->qhead != 0) - count += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */ - count += dmap_out->byte_counter; - /* Substract current count from the number of bytes written by app */ - count = dmap_out->user_counter - count; - if (count < 0) - count = 0; - restore_flags (flags); - return __put_user(count, (int *)arg); - - case SNDCTL_DSP_POST: - if (audio_devs[dev]->dmap_out->qlen > 0) - if (!(audio_devs[dev]->dmap_out->flags & DMA_ACTIVE)) - DMAbuf_launch_output(dev, audio_devs[dev]->dmap_out); - return 0; - - case SNDCTL_DSP_GETBLKSIZE: - dmap = dmap_out; - if (audio_devs[dev]->open_mode & OPEN_WRITE) - reorganize_buffers(dev, dmap_out, (audio_devs[dev]->open_mode == OPEN_READ)); - if (audio_devs[dev]->open_mode == OPEN_READ || - (audio_devs[dev]->flags & DMA_DUPLEX && - audio_devs[dev]->open_mode & OPEN_READ)) - reorganize_buffers(dev, dmap_in, (audio_devs[dev]->open_mode == OPEN_READ)); - if (audio_devs[dev]->open_mode == OPEN_READ) - dmap = dmap_in; - ret = dmap->fragment_size; - return __put_user(ret, (int *)arg); - - case SNDCTL_DSP_SETFRAGMENT: - ret = 0; - if (__get_user(fact, (int *)arg)) - return -EFAULT; - if (audio_devs[dev]->open_mode & OPEN_WRITE) - ret = dma_set_fragment(dev, dmap_out, fact); - if (ret < 0) - return ret; - if (audio_devs[dev]->open_mode == OPEN_READ || - (audio_devs[dev]->flags & DMA_DUPLEX && - audio_devs[dev]->open_mode & OPEN_READ)) - ret = dma_set_fragment(dev, dmap_in, fact); - if (ret < 0) - return ret; - if (!arg) /* don't know what this is good for, but preserve old semantics */ + { + ret=0; + break; + } + save_flags(flags); + cli(); + /* Compute number of bytes that have been played */ + count = DMAbuf_get_buffer_pointer (dev, dmap_out, DMODE_OUTPUT); + if (count < dmap_out->fragment_size && dmap_out->qhead != 0) + count += dmap_out->bytes_in_use; /* Pointer wrap not handled yet */ + count += dmap_out->byte_counter; + /* Substract current count from the number of bytes written by app */ + count = dmap_out->user_counter - count; + if (count < 0) + count = 0; + restore_flags (flags); + ret = count; + break; + + case SNDCTL_DSP_POST: + if (audio_devs[dev]->dmap_out->qlen > 0) + if (!(audio_devs[dev]->dmap_out->flags & DMA_ACTIVE)) + DMAbuf_launch_output(dev, audio_devs[dev]->dmap_out); return 0; - return __put_user(ret, (int *)arg); - default: - if (!audio_devs[dev]->d->ioctl) - return -EINVAL; - return audio_devs[dev]->d->ioctl(dev, cmd, arg); + case SNDCTL_DSP_GETBLKSIZE: + dmap = dmap_out; + if (audio_devs[dev]->open_mode & OPEN_WRITE) + reorganize_buffers(dev, dmap_out, (audio_devs[dev]->open_mode == OPEN_READ)); + if (audio_devs[dev]->open_mode == OPEN_READ || + (audio_devs[dev]->flags & DMA_DUPLEX && + audio_devs[dev]->open_mode & OPEN_READ)) + reorganize_buffers(dev, dmap_in, (audio_devs[dev]->open_mode == OPEN_READ)); + if (audio_devs[dev]->open_mode == OPEN_READ) + dmap = dmap_in; + ret = dmap->fragment_size; + break; + + case SNDCTL_DSP_SETFRAGMENT: + ret = 0; + if (get_user(fact, (int *)arg)) + return -EFAULT; + if (audio_devs[dev]->open_mode & OPEN_WRITE) + ret = dma_set_fragment(dev, dmap_out, fact); + if (ret < 0) + return ret; + if (audio_devs[dev]->open_mode == OPEN_READ || + (audio_devs[dev]->flags & DMA_DUPLEX && + audio_devs[dev]->open_mode & OPEN_READ)) + ret = dma_set_fragment(dev, dmap_in, fact); + if (ret < 0) + return ret; + if (!arg) /* don't know what this is good for, but preserve old semantics */ + return 0; + break; + + default: + if (!audio_devs[dev]->d->ioctl) + return -EINVAL; + return audio_devs[dev]->d->ioctl(dev, cmd, arg); } + return put_user(ret, (int *)arg); } diff -u --recursive --new-file v2.1.79/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c --- v2.1.79/linux/drivers/sound/cs4232.c Sat Nov 29 11:25:10 1997 +++ linux/drivers/sound/cs4232.c Tue Jan 20 16:44:57 1998 @@ -31,23 +31,22 @@ #define KEY_PORT 0x279 /* Same as LPT1 status port */ #define CSN_NUM 0x99 /* Just a random number */ -static void -CS_OUT(unsigned char a) +static void CS_OUT(unsigned char a) { - outb((a), KEY_PORT); + outb(a, KEY_PORT); } + #define CS_OUT2(a, b) {CS_OUT(a);CS_OUT(b);} #define CS_OUT3(a, b, c) {CS_OUT(a);CS_OUT(b);CS_OUT(c);} -static int mpu_base = 0, mpu_irq = 0; -static int mpu_detected = 0; +static int mpu_base = 0, mpu_irq = 0; +static int mpu_detected = 0; -int -probe_cs4232_mpu(struct address_info *hw_config) +int probe_cs4232_mpu(struct address_info *hw_config) { -/* - * Just write down the config values. - */ + /* + * Just write down the config values. + */ mpu_base = hw_config->io_base; mpu_irq = hw_config->irq; @@ -55,9 +54,9 @@ return 1; } -void -attach_cs4232_mpu(struct address_info *hw_config) +void attach_cs4232_mpu(struct address_info *hw_config) { + /* Nothing needs doing */ } static unsigned char crystal_key[] = /* A 32 byte magic key sequence */ @@ -68,190 +67,158 @@ 0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a }; -int -probe_cs4232(struct address_info *hw_config) +int probe_cs4232(struct address_info *hw_config) { - int i, n; - int base = hw_config->io_base, irq = hw_config->irq; - int dma1 = hw_config->dma, dma2 = hw_config->dma2; + int i, n; + int base = hw_config->io_base, irq = hw_config->irq; + int dma1 = hw_config->dma, dma2 = hw_config->dma2; + unsigned long tlimit; static struct wait_queue *cs_sleeper = NULL; - static volatile struct snd_wait cs_sleep_flag = - {0}; - - -/* - * Verify that the I/O port range is free. - */ + static volatile struct snd_wait cs_sleep_flag = { + 0 + }; + + /* + * Verify that the I/O port range is free. + */ if (check_region(base, 4)) - { - printk("cs4232.c: I/O port 0x%03x not free\n", base); - return 0; - } + { + printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base); + return 0; + } if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) return 1; /* The card is already active */ -/* - * This version of the driver doesn't use the PnP method when configuring - * the card but a simplified method defined by Crystal. This means that - * just one CS4232 compatible device can exist on the system. Also this - * method conflicts with possible PnP support in the OS. For this reason - * driver is just a temporary kludge. - */ - -/* - * Repeat initialization few times since it doesn't always succeed in - * first time. - */ + /* + * This version of the driver doesn't use the PnP method when configuring + * the card but a simplified method defined by Crystal. This means that + * just one CS4232 compatible device can exist on the system. Also this + * method conflicts with possible PnP support in the OS. For this reason + * driver is just a temporary kludge. + */ + + /* + * Repeat initialization few times since it doesn't always succeed in + * first time. + */ for (n = 0; n < 4; n++) - { - cs_sleep_flag.opts = WK_NONE; -/* - * Wake up the card by sending a 32 byte Crystal key to the key port. - */ - for (i = 0; i < 32; i++) - CS_OUT(crystal_key[i]); - - - { - unsigned long tlimit; - - if (HZ / 10) - current->timeout = tlimit = jiffies + (HZ / 10); - else - tlimit = (unsigned long) -1; - cs_sleep_flag.opts = WK_SLEEP; - interruptible_sleep_on(&cs_sleeper); - if (!(cs_sleep_flag.opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - cs_sleep_flag.opts |= WK_TIMEOUT; - } - cs_sleep_flag.opts &= ~WK_SLEEP; - }; /* Delay */ - -/* - * Now set the CSN (Card Select Number). - */ - - CS_OUT2(0x06, CSN_NUM); - - -/* - * Then set some config bytes. First logical device 0 - */ - - CS_OUT2(0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */ - CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff); /* WSS base */ - - if (check_region(0x388, 4)) /* Not free */ - CS_OUT3(0x48, 0x00, 0x00) /* FM base off */ - else - CS_OUT3(0x48, 0x03, 0x88); /* FM base 0x388 */ - - CS_OUT3(0x42, 0x00, 0x00); /* SB base off */ - CS_OUT2(0x22, irq); /* SB+WSS IRQ */ - CS_OUT2(0x2a, dma1); /* SB+WSS DMA */ - - if (dma2 != -1) - CS_OUT2(0x25, dma2) /* WSS DMA2 */ - else - CS_OUT2(0x25, 4); /* No WSS DMA2 */ - - CS_OUT2(0x33, 0x01); /* Activate logical dev 0 */ - - - { - unsigned long tlimit; - - if (HZ / 10) - current->timeout = tlimit = jiffies + (HZ / 10); - else - tlimit = (unsigned long) -1; - cs_sleep_flag.opts = WK_SLEEP; - interruptible_sleep_on(&cs_sleeper); - if (!(cs_sleep_flag.opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - cs_sleep_flag.opts |= WK_TIMEOUT; - } - cs_sleep_flag.opts &= ~WK_SLEEP; - }; /* Delay */ - -/* - * Initialize logical device 3 (MPU) - */ + { + cs_sleep_flag.opts = WK_NONE; + + /* + * Wake up the card by sending a 32 byte Crystal key to the key port. + */ + + for (i = 0; i < 32; i++) + CS_OUT(crystal_key[i]); + + current->timeout = tlimit = jiffies + (HZ / 10); + cs_sleep_flag.opts = WK_SLEEP; + interruptible_sleep_on(&cs_sleeper); + if (!(cs_sleep_flag.opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + cs_sleep_flag.opts |= WK_TIMEOUT; + } + cs_sleep_flag.opts &= ~WK_SLEEP; + + /* + * Now set the CSN (Card Select Number). + */ + + CS_OUT2(0x06, CSN_NUM); + + /* + * Then set some config bytes. First logical device 0 + */ + + CS_OUT2(0x15, 0x00); /* Select logical device 0 (WSS/SB/FM) */ + CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff); /* WSS base */ + + if (check_region(0x388, 4)) /* Not free */ + CS_OUT3(0x48, 0x00, 0x00) /* FM base off */ + else + CS_OUT3(0x48, 0x03, 0x88); /* FM base 0x388 */ + + CS_OUT3(0x42, 0x00, 0x00); /* SB base off */ + CS_OUT2(0x22, irq); /* SB+WSS IRQ */ + CS_OUT2(0x2a, dma1); /* SB+WSS DMA */ + + if (dma2 != -1) + CS_OUT2(0x25, dma2) /* WSS DMA2 */ + else + CS_OUT2(0x25, 4); /* No WSS DMA2 */ + + CS_OUT2(0x33, 0x01); /* Activate logical dev 0 */ + + current->timeout = tlimit = jiffies + (HZ / 10); + cs_sleep_flag.opts = WK_SLEEP; + interruptible_sleep_on(&cs_sleeper); + if (!(cs_sleep_flag.opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + cs_sleep_flag.opts |= WK_TIMEOUT; + } + cs_sleep_flag.opts &= ~WK_SLEEP; + + /* + * Initialize logical device 3 (MPU) + */ #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) - if (mpu_base != 0 && mpu_irq != 0) - { - CS_OUT2(0x15, 0x03); /* Select logical device 3 (MPU) */ - CS_OUT3(0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff); /* MPU base */ - CS_OUT2(0x22, mpu_irq); /* MPU IRQ */ - CS_OUT2(0x33, 0x01); /* Activate logical dev 3 */ - } + if (mpu_base != 0 && mpu_irq != 0) + { + CS_OUT2(0x15, 0x03); /* Select logical device 3 (MPU) */ + CS_OUT3(0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff); /* MPU base */ + CS_OUT2(0x22, mpu_irq); /* MPU IRQ */ + CS_OUT2(0x33, 0x01); /* Activate logical dev 3 */ + } #endif -/* - * Finally activate the chip - */ - CS_OUT(0x79); - - - { - unsigned long tlimit; - - if (HZ / 5) - current->timeout = tlimit = jiffies + (HZ / 5); - else - tlimit = (unsigned long) -1; - cs_sleep_flag.opts = WK_SLEEP; - interruptible_sleep_on(&cs_sleeper); - if (!(cs_sleep_flag.opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - cs_sleep_flag.opts |= WK_TIMEOUT; - } - cs_sleep_flag.opts &= ~WK_SLEEP; - }; /* Delay */ - -/* - * Then try to detect the codec part of the chip - */ - - if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) - return 1; - - - { - unsigned long tlimit; - - if (HZ) - current->timeout = tlimit = jiffies + (HZ); - else - tlimit = (unsigned long) -1; - cs_sleep_flag.opts = WK_SLEEP; - interruptible_sleep_on(&cs_sleeper); - if (!(cs_sleep_flag.opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - cs_sleep_flag.opts |= WK_TIMEOUT; - } - cs_sleep_flag.opts &= ~WK_SLEEP; - }; /* Longer delay */ - } - + /* + * Finally activate the chip + */ + + CS_OUT(0x79); + + current->timeout = tlimit = jiffies + (HZ / 5); + cs_sleep_flag.opts = WK_SLEEP; + interruptible_sleep_on(&cs_sleeper); + if (!(cs_sleep_flag.opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + cs_sleep_flag.opts |= WK_TIMEOUT; + } + cs_sleep_flag.opts &= ~WK_SLEEP; + + /* + * Then try to detect the codec part of the chip + */ + + if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) + return 1; + + current->timeout = tlimit = jiffies + (HZ); + cs_sleep_flag.opts = WK_SLEEP; + interruptible_sleep_on(&cs_sleeper); + if (!(cs_sleep_flag.opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + cs_sleep_flag.opts |= WK_TIMEOUT; + } + cs_sleep_flag.opts &= ~WK_SLEEP; + } return 0; } -void -attach_cs4232(struct address_info *hw_config) +void attach_cs4232(struct address_info *hw_config) { - int base = hw_config->io_base, irq = hw_config->irq; - int dma1 = hw_config->dma, dma2 = hw_config->dma2; - int old_num_mixers = num_mixers; + int base = hw_config->io_base, irq = hw_config->irq; + int dma1 = hw_config->dma, dma2 = hw_config->dma2; + int old_num_mixers = num_mixers; if (dma2 == -1) dma2 = dma1; @@ -264,45 +231,47 @@ hw_config->osp); if (num_mixers > old_num_mixers) - { /* Assume the mixer map is as suggested in the CS4232 databook */ - AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE); - AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD); - AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH); /* FM synth */ - } + { + /* Assume the mixer map is as suggested in the CS4232 databook */ + AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE); + AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD); + AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH); /* FM synth */ + } #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) if (mpu_base != 0 && mpu_irq != 0) - { - static struct address_info hw_config2 = - {0}; /* Ensure it's initialized */ - - hw_config2.io_base = mpu_base; - hw_config2.irq = mpu_irq; - hw_config2.dma = -1; - hw_config2.dma2 = -1; - hw_config2.always_detect = 0; - hw_config2.name = NULL; - hw_config2.driver_use_1 = 0; - hw_config2.driver_use_2 = 0; - hw_config2.card_subtype = 0; - - if (probe_uart401(&hw_config2)) - { - mpu_detected = 1; - attach_uart401(&hw_config2); - } else - { - mpu_base = mpu_irq = 0; - } - hw_config->slots[1] = hw_config2.slots[1]; - } + { + static struct address_info hw_config2 = { + 0 + }; /* Ensure it's initialized */ + + hw_config2.io_base = mpu_base; + hw_config2.irq = mpu_irq; + hw_config2.dma = -1; + hw_config2.dma2 = -1; + hw_config2.always_detect = 0; + hw_config2.name = NULL; + hw_config2.driver_use_1 = 0; + hw_config2.driver_use_2 = 0; + hw_config2.card_subtype = 0; + + if (probe_uart401(&hw_config2)) + { + mpu_detected = 1; + attach_uart401(&hw_config2); + } + else + { + mpu_base = mpu_irq = 0; + } + hw_config->slots[1] = hw_config2.slots[1]; + } #endif } -void -unload_cs4232(struct address_info *hw_config) +void unload_cs4232(struct address_info *hw_config) { - int base = hw_config->io_base, irq = hw_config->irq; - int dma1 = hw_config->dma, dma2 = hw_config->dma2; + int base = hw_config->io_base, irq = hw_config->irq; + int dma1 = hw_config->dma, dma2 = hw_config->dma2; if (dma2 == -1) dma2 = dma1; @@ -315,28 +284,29 @@ sound_unload_audiodev(hw_config->slots[0]); #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) if (mpu_base != 0 && mpu_irq != 0 && mpu_detected) - { - static struct address_info hw_config2 = - {0}; /* Ensure it's initialized */ - - hw_config2.io_base = mpu_base; - hw_config2.irq = mpu_irq; - hw_config2.dma = -1; - hw_config2.dma2 = -1; - hw_config2.always_detect = 0; - hw_config2.name = NULL; - hw_config2.driver_use_1 = 0; - hw_config2.driver_use_2 = 0; - hw_config2.card_subtype = 0; - hw_config2.slots[1] = hw_config->slots[1]; + { + static struct address_info hw_config2 = + { + 0 + }; /* Ensure it's initialized */ + + hw_config2.io_base = mpu_base; + hw_config2.irq = mpu_irq; + hw_config2.dma = -1; + hw_config2.dma2 = -1; + hw_config2.always_detect = 0; + hw_config2.name = NULL; + hw_config2.driver_use_1 = 0; + hw_config2.driver_use_2 = 0; + hw_config2.card_subtype = 0; + hw_config2.slots[1] = hw_config->slots[1]; - unload_uart401(&hw_config2); - } + unload_uart401(&hw_config2); + } #endif } -void -unload_cs4232_mpu(struct address_info *hw_config) +void unload_cs4232_mpu(struct address_info *hw_config) { /* Not required. Handled by cs4232_unload */ } @@ -348,21 +318,26 @@ int dma = -1; int dma2 = -1; +MODULE_PARM(io,"i"); +MODULE_PARM(irq,"i"); +MODULE_PARM(dma,"i"); +MODULE_PARM(dma2,"i"); + struct address_info cfg; /* - * Install a CS4232 based card. Need to have ad1848 and mpu401 - * loaded ready. + * Install a CS4232 based card. Need to have ad1848 and mpu401 + * loaded ready. */ int init_module(void) { if (io == -1 || irq == -1 || dma == -1 || dma2 == -1) - { - printk(KERN_ERR "cs4232: dma, dma2, irq and io must be set.\n"); - return -EINVAL; - } + { + printk(KERN_ERR "cs4232: dma, dma2, irq and io must be set.\n"); + return -EINVAL; + } cfg.io_base = io; cfg.irq = irq; cfg.dma = dma; @@ -379,13 +354,12 @@ return 0; } -void -cleanup_module(void) +void cleanup_module(void) { unload_cs4232_mpu(&cfg); unload_cs4232(&cfg); SOUND_LOCK_END; } -#endif +#endif #endif diff -u --recursive --new-file v2.1.79/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c --- v2.1.79/linux/drivers/sound/dev_table.c Tue Jan 6 09:37:35 1998 +++ linux/drivers/sound/dev_table.c Tue Jan 20 16:44:57 1998 @@ -3,6 +3,7 @@ * * Device call tables. */ + /* * Copyright (C) by Hannu Savolainen 1993-1997 * @@ -10,22 +11,21 @@ * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ + #include #define _DEV_TABLE_C_ #include "sound_config.h" -int sb_be_quiet = 0; -int softoss_dev = 0; - -int sound_started = 0; -int sndtable_get_cardcount(void); +int sb_be_quiet = 0; +int softoss_dev = 0; +int sound_started = 0; +int sndtable_get_cardcount(void); -int -snd_find_driver(int type) +int snd_find_driver(int type) { - int i, n = num_sound_drivers; + int i, n = num_sound_drivers; for (i = 0; i < n; i++) if (sound_drivers[i].card_type == type) @@ -34,10 +34,9 @@ return -1; } -static void -start_services(void) +static void start_services(void) { - int soundcards_installed; + int soundcards_installed; #ifdef FIXME if (!(soundcards_installed = sndtable_get_cardcount())) @@ -46,13 +45,12 @@ #ifdef CONFIG_AUDIO if (num_audiodevs) /* Audio devices present */ - { - int dev; - - for (dev = 0; dev < num_audiodevs; dev++) - { - } - audio_init_devices(); + { + int dev; + for (dev = 0; dev < num_audiodevs; dev++) + { + } + audio_init_devices(); } #endif @@ -62,17 +60,16 @@ static void start_cards(void) { - int i, n = num_sound_cards; - int drv; + int i, n = num_sound_cards; + int drv; sound_started = 1; if (trace_init) - printk("Sound initialization started\n"); + printk(KERN_DEBUG "Sound initialization started\n"); #ifdef CONFIG_LOWLEVEL_SOUND { - extern void sound_preinit_lowlevel_drivers(void); - + extern void sound_preinit_lowlevel_drivers(void); sound_preinit_lowlevel_drivers(); } #endif @@ -85,251 +82,244 @@ num_sound_cards = i + 1; for (i = 0; i < n && snd_installed_cards[i].card_type; i++) + { if (snd_installed_cards[i].enabled) - { - snd_installed_cards[i].for_driver_use = NULL; - - if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) == -1) - { - snd_installed_cards[i].enabled = 0; /* - * Mark as not detected - */ - continue; - } - snd_installed_cards[i].config.card_subtype = - sound_drivers[drv].card_subtype; + { + snd_installed_cards[i].for_driver_use = NULL; - if (sound_drivers[drv].probe(&snd_installed_cards[i].config)) - { - - sound_drivers[drv].attach(&snd_installed_cards[i].config); - - } else - snd_installed_cards[i].enabled = 0; /* + if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) == -1) + { + snd_installed_cards[i].enabled = 0; /* + * Mark as not detected + */ + continue; + } + snd_installed_cards[i].config.card_subtype = + sound_drivers[drv].card_subtype; + + if (sound_drivers[drv].probe(&snd_installed_cards[i].config)) + sound_drivers[drv].attach(&snd_installed_cards[i].config); + else + snd_installed_cards[i].enabled = 0; /* * Mark as not detected */ - } + } + } #ifdef CONFIG_LOWLEVEL_SOUND { extern void sound_init_lowlevel_drivers(void); - sound_init_lowlevel_drivers(); } #endif - if (trace_init) - printk("Sound initialization complete\n"); + printk(KERN_DEBUG "Sound initialization complete\n"); } -void -sndtable_init(void) +void sndtable_init(void) { start_cards(); } -void -sound_unload_drivers(void) +void sound_unload_drivers(void) { - int i, n = num_sound_cards; - int drv; + int i, n = num_sound_cards; + int drv; if (!sound_started) return; if (trace_init) - printk("Sound unload started\n"); + printk(KERN_DEBUG "Sound unload started\n"); for (i = 0; i < n && snd_installed_cards[i].card_type; i++) + { if (snd_installed_cards[i].enabled) - { - if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) != -1) - { - if (sound_drivers[drv].unload) - { - sound_drivers[drv].unload(&snd_installed_cards[i].config); - snd_installed_cards[i].enabled = 0; - } - } - } + { + if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) != -1) + { + if (sound_drivers[drv].unload) + { + sound_drivers[drv].unload(&snd_installed_cards[i].config); + snd_installed_cards[i].enabled = 0; + } + } + } + } + for (i=0;iio_base; - snd_installed_cards[sel].config.irq = hw_config->irq; - snd_installed_cards[sel].config.dma = hw_config->dma; - snd_installed_cards[sel].config.dma2 = hw_config->dma2; - snd_installed_cards[sel].config.name = hw_config->name; - snd_installed_cards[sel].config.always_detect = hw_config->always_detect; - snd_installed_cards[sel].config.driver_use_1 = hw_config->driver_use_1; - snd_installed_cards[sel].config.driver_use_2 = hw_config->driver_use_2; - snd_installed_cards[sel].config.card_subtype = hw_config->card_subtype; - - if ((drv = snd_find_driver(snd_installed_cards[sel].card_type)) == -1) - { - snd_installed_cards[sel].enabled = 0; - DEB(printk("Failed to find driver\n")); - return 0; - } - DEB(printk("Driver name '%s'\n", sound_drivers[drv].name)); - - hw_config->card_subtype = - snd_installed_cards[sel].config.card_subtype = - sound_drivers[drv].card_subtype; - - if (sound_drivers[drv].probe(hw_config)) - { - DEB(printk("Hardware probed OK\n")); - return 1; - } - DEB(printk("Failed to find hardware\n")); - snd_installed_cards[sel].enabled = 0; /* + snd_installed_cards[sel].for_driver_use = NULL; + snd_installed_cards[sel].config.io_base = hw_config->io_base; + snd_installed_cards[sel].config.irq = hw_config->irq; + snd_installed_cards[sel].config.dma = hw_config->dma; + snd_installed_cards[sel].config.dma2 = hw_config->dma2; + snd_installed_cards[sel].config.name = hw_config->name; + snd_installed_cards[sel].config.always_detect = hw_config->always_detect; + snd_installed_cards[sel].config.driver_use_1 = hw_config->driver_use_1; + snd_installed_cards[sel].config.driver_use_2 = hw_config->driver_use_2; + snd_installed_cards[sel].config.card_subtype = hw_config->card_subtype; + + if ((drv = snd_find_driver(snd_installed_cards[sel].card_type)) == -1) + { + snd_installed_cards[sel].enabled = 0; + DEB(printk(KERN_DEBUG "Failed to find driver\n")); + return 0; + } + DEB(printk(KERN_DEBUG "Driver name '%s'\n", sound_drivers[drv].name)); + + hw_config->card_subtype = snd_installed_cards[sel].config.card_subtype = sound_drivers[drv].card_subtype; + + if (sound_drivers[drv].probe(hw_config)) + { + DEB(printk(KERN_DEBUG "Hardware probed OK\n")); + return 1; + } + DEB(printk("Failed to find hardware\n")); + snd_installed_cards[sel].enabled = 0; /* * Mark as not detected */ - return 0; - } + return 0; + } return 0; } -int -sndtable_init_card(int unit, struct address_info *hw_config) +int sndtable_init_card(int unit, struct address_info *hw_config) { - int i, n = num_sound_cards; + int i, n = num_sound_cards; DEB(printk("sndtable_init_card(%d) entered\n", unit)); if (!unit) - { - sndtable_init(); - return 1; - } + { + sndtable_init(); + return 1; + } for (i = 0; i < n && snd_installed_cards[i].card_type; i++) + { if (snd_installed_cards[i].card_type == unit) - { - int drv; + { + int drv; - snd_installed_cards[i].config.io_base = hw_config->io_base; - snd_installed_cards[i].config.irq = hw_config->irq; - snd_installed_cards[i].config.dma = hw_config->dma; - snd_installed_cards[i].config.dma2 = hw_config->dma2; - snd_installed_cards[i].config.name = hw_config->name; - snd_installed_cards[i].config.always_detect = hw_config->always_detect; - snd_installed_cards[i].config.driver_use_1 = hw_config->driver_use_1; - snd_installed_cards[i].config.driver_use_2 = hw_config->driver_use_2; - snd_installed_cards[i].config.card_subtype = hw_config->card_subtype; + snd_installed_cards[i].config.io_base = hw_config->io_base; + snd_installed_cards[i].config.irq = hw_config->irq; + snd_installed_cards[i].config.dma = hw_config->dma; + snd_installed_cards[i].config.dma2 = hw_config->dma2; + snd_installed_cards[i].config.name = hw_config->name; + snd_installed_cards[i].config.always_detect = hw_config->always_detect; + snd_installed_cards[i].config.driver_use_1 = hw_config->driver_use_1; + snd_installed_cards[i].config.driver_use_2 = hw_config->driver_use_2; + snd_installed_cards[i].config.card_subtype = hw_config->card_subtype; - if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) == -1) - snd_installed_cards[i].enabled = 0; /* + if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) == -1) + snd_installed_cards[i].enabled = 0; /* * Mark as not detected */ - else - { - - DEB(printk("Located card - calling attach routine\n")); - sound_drivers[drv].attach(hw_config); - - DEB(printk("attach routine finished\n")); - } - start_services(); - return 1; - } + else + { + DEB(printk(KERN_DEBUG "Located card - calling attach routine\n")); + sound_drivers[drv].attach(hw_config); + + DEB(printk("attach routine finished\n")); + } + start_services(); + return 1; + } + } DEB(printk("sndtable_init_card: No card defined with type=%d, num cards: %d\n", unit, num_sound_cards)); return 0; } -int -sndtable_get_cardcount(void) +int sndtable_get_cardcount(void) { return num_audiodevs + num_mixers + num_synths + num_midis; } -int -sndtable_identify_card(char *name) +int sndtable_identify_card(char *name) { - int i, n = num_sound_drivers; + int i, n = num_sound_drivers; if (name == NULL) return 0; for (i = 0; i < n; i++) + { if (sound_drivers[i].driver_id != NULL) - { - char *id = sound_drivers[i].driver_id; - int j; - - for (j = 0; j < 80 && name[j] == id[j]; j++) - if (id[j] == 0 && name[j] == 0) /* Match */ - return sound_drivers[i].card_type; - } + { + char *id = sound_drivers[i].driver_id; + int j; + + for (j = 0; j < 80 && name[j] == id[j]; j++) + if (id[j] == 0 && name[j] == 0) /* Match */ + return sound_drivers[i].card_type; + } + } return 0; } -void -sound_setup(char *str, int *ints) +void sound_setup(char *str, int *ints) { - int i, n = num_sound_cards; + int i, n = num_sound_cards; /* - * First disable all drivers + * First disable all drivers */ for (i = 0; i < n && snd_installed_cards[i].card_type; i++) @@ -338,70 +328,69 @@ if (ints[0] == 0 || ints[1] == 0) return; /* - * Then enable them one by time + * Then enable them one by time */ for (i = 1; i <= ints[0]; i++) - { - int card_type, ioaddr, irq, dma, dma2, - ptr, j; - unsigned int val; - - val = (unsigned int) ints[i]; - - card_type = (val & 0x0ff00000) >> 20; - - if (card_type > 127) - { - /* - * Add any future extensions here - */ - return; - } - ioaddr = (val & 0x000fff00) >> 8; - irq = (val & 0x000000f0) >> 4; - dma = (val & 0x0000000f); - dma2 = (val & 0xf0000000) >> 28; - - ptr = -1; - for (j = 0; j < n && ptr == -1; j++) - if (snd_installed_cards[j].card_type == card_type && - !snd_installed_cards[j].enabled) /* + { + int card_type, ioaddr, irq, dma, dma2, ptr, j; + unsigned int val; + + val = (unsigned int) ints[i]; + card_type = (val & 0x0ff00000) >> 20; + + if (card_type > 127) + { + /* + * Add any future extensions here + */ + return; + } + ioaddr = (val & 0x000fff00) >> 8; + irq = (val & 0x000000f0) >> 4; + dma = (val & 0x0000000f); + dma2 = (val & 0xf0000000) >> 28; + + ptr = -1; + for (j = 0; j < n && ptr == -1; j++) + { + if (snd_installed_cards[j].card_type == card_type && + !snd_installed_cards[j].enabled)/* * Not already found */ - ptr = j; + ptr = j; + } - if (ptr == -1) - printk("Sound: Invalid setup parameter 0x%08x\n", val); - else - { - snd_installed_cards[ptr].enabled = 1; - snd_installed_cards[ptr].config.io_base = ioaddr; - snd_installed_cards[ptr].config.irq = irq; - snd_installed_cards[ptr].config.dma = dma; - snd_installed_cards[ptr].config.dma2 = dma2; - snd_installed_cards[ptr].config.name = NULL; - snd_installed_cards[ptr].config.always_detect = 0; - snd_installed_cards[ptr].config.driver_use_1 = 0; - snd_installed_cards[ptr].config.driver_use_2 = 0; - snd_installed_cards[ptr].config.card_subtype = 0; - } - } + if (ptr == -1) + printk(KERN_ERR "Sound: Invalid setup parameter 0x%08x\n", val); + else + { + snd_installed_cards[ptr].enabled = 1; + snd_installed_cards[ptr].config.io_base = ioaddr; + snd_installed_cards[ptr].config.irq = irq; + snd_installed_cards[ptr].config.dma = dma; + snd_installed_cards[ptr].config.dma2 = dma2; + snd_installed_cards[ptr].config.name = NULL; + snd_installed_cards[ptr].config.always_detect = 0; + snd_installed_cards[ptr].config.driver_use_1 = 0; + snd_installed_cards[ptr].config.driver_use_2 = 0; + snd_installed_cards[ptr].config.card_subtype = 0; + } + } } -struct address_info - * -sound_getconf(int card_type) +struct address_info * sound_getconf(int card_type) { - int j, ptr; - int n = num_sound_cards; + int j, ptr; + int n = num_sound_cards; ptr = -1; for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++) + { if (snd_installed_cards[j].card_type == card_type) ptr = j; - + } if (ptr == -1) return (struct address_info *) NULL; @@ -410,60 +399,51 @@ -int -sound_install_audiodrv(int vers, - char *name, - struct audio_driver *driver, - int driver_size, - int flags, - unsigned int format_mask, - void *devc, - int dma1, - int dma2) +int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, + int driver_size, int flags, unsigned int format_mask, + void *devc, int dma1, int dma2) { #ifdef CONFIG_AUDIO struct audio_driver *d; struct audio_operations *op; - int l, num; + int l, num; - if (vers != AUDIO_DRIVER_VERSION || - driver_size > sizeof(struct audio_driver)) - { - printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name); - return -(EINVAL); - } + if (vers != AUDIO_DRIVER_VERSION || driver_size > sizeof(struct audio_driver)) + { + printk(KERN_ERR "Sound: Incompatible audio driver for %s\n", name); + return -(EINVAL); + } num = sound_alloc_audiodev(); if (num == -1) - { - printk(KERN_ERR "sound: Too many audio drivers\n"); - return -(EBUSY); - } + { + printk(KERN_ERR "sound: Too many audio drivers\n"); + return -(EBUSY); + } d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver))); sound_mem_sizes[sound_nblocks] = sizeof(struct audio_driver); if (sound_nblocks < 1024) - sound_nblocks++;; + sound_nblocks++; op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_operations))); sound_mem_sizes[sound_nblocks] = sizeof(struct audio_operations); if (sound_nblocks < 1024) - sound_nblocks++;; + sound_nblocks++; if (d == NULL || op == NULL) - { - printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); - sound_unload_audiodev(num); - return -(ENOMEM); - } + { + printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); + sound_unload_audiodev(num); + return -(ENOMEM); + } memset((char *) op, 0, sizeof(struct audio_operations)); if (driver_size < sizeof(struct audio_driver)) - memset((char *) d, 0, sizeof(struct audio_driver)); + memset((char *) d, 0, sizeof(struct audio_driver)); memcpy((char *) d, (char *) driver, driver_size); op->d = d; - l = strlen(name) + 1; if (l > sizeof(op->name)) l = sizeof(op->name); @@ -473,9 +453,9 @@ op->format_mask = format_mask; op->devc = devc; -/* - * Hardcoded defaults - */ + /* + * Hardcoded defaults + */ audio_devs[num] = op; DMAbuf_init(num, dma1, dma2); @@ -487,41 +467,40 @@ #endif } -int -sound_install_mixer(int vers, - char *name, - struct mixer_operations *driver, - int driver_size, - void *devc) +int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, + int driver_size, void *devc) { struct mixer_operations *op; - int l; + int l; - int n = sound_alloc_mixerdev(); + int n = sound_alloc_mixerdev(); if (n == -1) - { - printk(KERN_ERR "Sound: Too many mixer drivers\n"); - return -(EBUSY); - } + { + printk(KERN_ERR "Sound: Too many mixer drivers\n"); + return -EBUSY; + } if (vers != MIXER_DRIVER_VERSION || - driver_size > sizeof(struct mixer_operations)) - { - printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); - return -(EINVAL); - } + driver_size > sizeof(struct mixer_operations)) + { + printk(KERN_ERR "Sound: Incompatible mixer driver for %s\n", name); + return -EINVAL; + } + + /* FIXME: This leaks a mixer_operations struct every time its called + until you unload sound! */ + op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); sound_mem_sizes[sound_nblocks] = sizeof(struct mixer_operations); if (sound_nblocks < 1024) - sound_nblocks++;; + sound_nblocks++; if (op == NULL) - { - printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); - return -(ENOMEM); - } + { + printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); + return -ENOMEM; + } memset((char *) op, 0, sizeof(struct mixer_operations)); - memcpy((char *) op, (char *) driver, driver_size); l = strlen(name) + 1; @@ -535,108 +514,99 @@ return n; } -void -sound_unload_audiodev(int dev) +void sound_unload_audiodev(int dev) { if (dev != -1) audio_devs[dev] = NULL; } -int -sound_alloc_audiodev(void) +int sound_alloc_audiodev(void) { - int i; + int i; for (i = 0; i < MAX_AUDIO_DEV; i++) - { - if (audio_devs[i] == NULL) - { - if (i >= num_audiodevs) - num_audiodevs = i + 1; - return i; - } - } + { + if (audio_devs[i] == NULL) + { + if (i >= num_audiodevs) + num_audiodevs = i + 1; + return i; + } + } return -1; } -int -sound_alloc_mididev(void) +int sound_alloc_mididev(void) { - int i; + int i; for (i = 0; i < MAX_MIDI_DEV; i++) - { - if (midi_devs[i] == NULL) - { - if (i >= num_midis) - num_midis++; - return i; - } - } - + { + if (midi_devs[i] == NULL) + { + if (i >= num_midis) + num_midis++; + return i; + } + } return -1; } -int -sound_alloc_synthdev(void) +int sound_alloc_synthdev(void) { - int i; + int i; for (i = 0; i < MAX_SYNTH_DEV; i++) - { - if (synth_devs[i] == NULL) - { - if (i >= num_synths) - num_synths++; - return i; - } - } + { + if (synth_devs[i] == NULL) + { + if (i >= num_synths) + num_synths++; + return i; + } + } return -1; } -int -sound_alloc_mixerdev(void) +int sound_alloc_mixerdev(void) { - int i; + int i; for (i = 0; i < MAX_MIXER_DEV; i++) - { - if (mixer_devs[i] == NULL) - { - if (i >= num_mixers) - num_mixers++; - return i; - } - } + { + if (mixer_devs[i] == NULL) + { + if (i >= num_mixers) + num_mixers++; + return i; + } + } return -1; } -int -sound_alloc_timerdev(void) +int sound_alloc_timerdev(void) { - int i; + int i; for (i = 0; i < MAX_TIMER_DEV; i++) - { - if (sound_timer_devs[i] == NULL) - { - if (i >= num_sound_timers) - num_sound_timers++; - return i; - } - } + { + if (sound_timer_devs[i] == NULL) + { + if (i >= num_sound_timers) + num_sound_timers++; + return i; + } + } return -1; } -void -sound_unload_mixerdev(int dev) +void sound_unload_mixerdev(int dev) { if (dev != -1) mixer_devs[dev] = NULL; } -void -sound_unload_mididev(int dev) +void sound_unload_mididev(int dev) { #ifdef CONFIG_MIDI if (dev != -1) @@ -644,16 +614,15 @@ #endif } -void -sound_unload_synthdev(int dev) +void sound_unload_synthdev(int dev) { if (dev != -1) synth_devs[dev] = NULL; } -void -sound_unload_timerdev(int dev) +void sound_unload_timerdev(int dev) { if (dev != -1) sound_timer_devs[dev] = NULL; } + diff -u --recursive --new-file v2.1.79/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h --- v2.1.79/linux/drivers/sound/dev_table.h Tue Dec 23 16:31:00 1997 +++ linux/drivers/sound/dev_table.h Tue Jan 20 16:44:57 1998 @@ -2,8 +2,8 @@ * dev_table.h * * Global definitions for device call tables - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) @@ -21,6 +21,7 @@ * Sound card numbers 27 to 999. (1 to 26 are defined in soundcard.h) * Numbers 1000 to N are reserved for driver's internal use. */ + #define SNDCARD_DESKPROXL 27 /* Compaq Deskpro XL */ #define SNDCARD_SBPNP 29 #define SNDCARD_OPL3SA1 38 @@ -52,7 +53,8 @@ extern int sound_started; -struct driver_info { +struct driver_info +{ char *driver_id; int card_subtype; /* Driver specific. Usually 0 */ int card_type; /* From soundcard.h */ @@ -62,7 +64,8 @@ void (*unload) (struct address_info *hw_config); }; -struct card_info { +struct card_info +{ int card_type; /* Link (search key) to the driver list */ struct address_info config; int enabled; @@ -79,7 +82,8 @@ #define DMODE_OUTPUT PCM_ENABLE_OUTPUT #define DMODE_INPUT PCM_ENABLE_INPUT -struct dma_buffparms { +struct dma_buffparms +{ int dma_mode; /* DMODE_INPUT, DMODE_OUTPUT or DMODE_NONE */ int closing; @@ -156,17 +160,19 @@ * Structure for use with various microcontrollers and DSP processors * in the recent soundcards. */ -typedef struct coproc_operations { - char name[64]; - int (*open) (void *devc, int sub_device); - void (*close) (void *devc, int sub_device); - int (*ioctl) (void *devc, unsigned int cmd, caddr_t arg, int local); - void (*reset) (void *devc); +typedef struct coproc_operations +{ + char name[64]; + int (*open) (void *devc, int sub_device); + void (*close) (void *devc, int sub_device); + int (*ioctl) (void *devc, unsigned int cmd, caddr_t arg, int local); + void (*reset) (void *devc); - void *devc; /* Driver specific info */ - } coproc_operations; + void *devc; /* Driver specific info */ +} coproc_operations; -struct audio_driver { +struct audio_driver +{ int (*open) (int dev, int mode); void (*close) (int dev); void (*output_block) (int dev, unsigned long buf, @@ -190,7 +196,8 @@ void (*preprocess_read)(int dev); /* Device spesific preprocessing for read data */ }; -struct audio_operations { +struct audio_operations +{ char name[128]; int flags; #define NOTHING_SPECIAL 0x00 @@ -218,7 +225,8 @@ int *load_mixer_volumes(char *name, int *levels, int present); -struct mixer_operations { +struct mixer_operations +{ char id[16]; char name[64]; int (*ioctl) (int dev, unsigned int cmd, caddr_t arg); @@ -227,7 +235,8 @@ int modify_counter; }; -struct synth_operations { +struct synth_operations +{ char *id; /* Unique identifier (ASCII) max 29 char */ struct synth_info *info; int midi_dev; @@ -263,20 +272,23 @@ int sysex_ptr; }; -struct midi_input_info { /* MIDI input scanner variables */ +struct midi_input_info +{ + /* MIDI input scanner variables */ #define MI_MAX 10 - int m_busy; - unsigned char m_buf[MI_MAX]; - unsigned char m_prev_status; /* For running status */ - int m_ptr; + int m_busy; + unsigned char m_buf[MI_MAX]; + unsigned char m_prev_status; /* For running status */ + int m_ptr; #define MST_INIT 0 #define MST_DATA 1 #define MST_SYSEX 2 - int m_state; - int m_left; - }; + int m_state; + int m_left; +}; -struct midi_operations { +struct midi_operations +{ struct midi_info info; struct synth_operations *converter; struct midi_input_info in_info; @@ -297,15 +309,17 @@ void *devc; }; -struct sound_lowlev_timer { - int dev; - int priority; - unsigned int (*tmr_start)(int dev, unsigned int usecs); - void (*tmr_disable)(int dev); - void (*tmr_restart)(int dev); - }; +struct sound_lowlev_timer +{ + int dev; + int priority; + unsigned int (*tmr_start)(int dev, unsigned int usecs); + void (*tmr_disable)(int dev); + void (*tmr_restart)(int dev); +}; -struct sound_timer_operations { +struct sound_timer_operations +{ struct sound_timer_info info; int priority; int devlink; @@ -319,91 +333,94 @@ #ifdef _DEV_TABLE_C_ - struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0; - struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0; - struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0; - struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0; +struct audio_operations *audio_devs[MAX_AUDIO_DEV] = {NULL}; int num_audiodevs = 0; +struct mixer_operations *mixer_devs[MAX_MIXER_DEV] = {NULL}; int num_mixers = 0; +struct synth_operations *synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV] = {NULL}; int num_synths = 0; +struct midi_operations *midi_devs[MAX_MIDI_DEV] = {NULL}; int num_midis = 0; #if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS) && !defined(VMIDI) - extern struct sound_timer_operations default_sound_timer; - struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = - {&default_sound_timer, NULL}; - int num_sound_timers = 1; +extern struct sound_timer_operations default_sound_timer; +struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { + &default_sound_timer, NULL +}; +int num_sound_timers = 1; #else - struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = - {NULL}; - int num_sound_timers = 0; +struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { + NULL +}; +int num_sound_timers = 0; #endif /* * List of low level drivers compiled into the kernel. */ - struct driver_info sound_drivers[] = { +struct driver_info sound_drivers[] = +{ #if defined(CONFIG_PSS) && !defined(CONFIG_PSS_MODULE) - {"PSS", 0, SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss, unload_pss}, - {"PSSMPU", 0, SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu, unload_pss_mpu}, - {"PSSMSS", 0, SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss, unload_pss_mss}, + {"PSS", 0, SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss, unload_pss}, + {"PSSMPU", 0, SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu, unload_pss_mpu}, + {"PSSMSS", 0, SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss, unload_pss_mss}, #endif #if defined(CONFIG_GUS) && !defined(CONFIG_GUS_MODULE) #ifdef CONFIG_GUS16 - {"GUS16", 0, SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16, unload_gus_db16}, + {"GUS16", 0, SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16, unload_gus_db16}, #endif #ifdef CONFIG_GUSHW - {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus, unload_gus}, - {"GUSPNP", 1, SNDCARD_GUSPNP, "GUS PnP", attach_gus_card, probe_gus, unload_gus}, + {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus, unload_gus}, + {"GUSPNP", 1, SNDCARD_GUSPNP, "GUS PnP", attach_gus_card, probe_gus, unload_gus}, #endif #endif #if defined(CONFIG_MSS) && !defined(CONFIG_MSS_MODULE) - {"MSS", 0, SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound, unload_ms_sound}, + {"MSS", 0, SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound, unload_ms_sound}, /* Compaq Deskpro XL */ - {"DESKPROXL", 2, SNDCARD_DESKPROXL, "Compaq Deskpro XL", attach_ms_sound, probe_ms_sound, unload_ms_sound}, + {"DESKPROXL", 2, SNDCARD_DESKPROXL, "Compaq Deskpro XL", attach_ms_sound, probe_ms_sound, unload_ms_sound}, #endif #ifdef CONFIG_MAD16 - {"MAD16", 0, SNDCARD_MAD16, "MAD16/Mozart (MSS)", attach_mad16, probe_mad16, unload_mad16}, - {"MAD16MPU", 0, SNDCARD_MAD16_MPU, "MAD16/Mozart (MPU)", attach_mad16_mpu, probe_mad16_mpu, unload_mad16_mpu}, + {"MAD16", 0, SNDCARD_MAD16, "MAD16/Mozart (MSS)", attach_mad16, probe_mad16, unload_mad16}, + {"MAD16MPU", 0, SNDCARD_MAD16_MPU, "MAD16/Mozart (MPU)", attach_mad16_mpu, probe_mad16_mpu, unload_mad16_mpu}, #endif #ifdef CONFIG_CS4232 - {"CS4232", 0, SNDCARD_CS4232, "CS4232", attach_cs4232, probe_cs4232, unload_cs4232}, - {"CS4232MPU", 0, SNDCARD_CS4232_MPU, "CS4232 MIDI", attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu}, + {"CS4232", 0, SNDCARD_CS4232, "CS4232", attach_cs4232, probe_cs4232, unload_cs4232}, + {"CS4232MPU", 0, SNDCARD_CS4232_MPU, "CS4232 MIDI", attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu}, #endif #if defined(CONFIG_YM3812) && !defined(CONFIG_YM3812_MODULE) - {"OPL3", 0, SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib, unload_adlib}, + {"OPL3", 0, SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib, unload_adlib}, #endif #if defined(CONFIG_PAS) && !defined(CONFIG_PAS_MODULE) - {"PAS16", 0, SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas, unload_pas}, + {"PAS16", 0, SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas, unload_pas}, #endif #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI) && !defined(CONFIG_MPU401_MODULE) - {"MPU401", 0, SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401, unload_mpu401}, + {"MPU401", 0, SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401, unload_mpu401}, #endif #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) && !defined(CONFIG_UART401_MODULE) {"UART401", 0, SNDCARD_UART401,"MPU-401 (UART)", attach_uart401, probe_uart401, unload_uart401}, #endif #if defined(CONFIG_MAUI) && !defined(CONFIG_MAUI_MODULE) - {"MAUI", 0, SNDCARD_MAUI,"TB Maui", attach_maui, probe_maui, unload_maui}, + {"MAUI", 0, SNDCARD_MAUI,"TB Maui", attach_maui, probe_maui, unload_maui}, #endif #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) && !defined(CONFIG_UART6850_MODULE) - {"MIDI6850", 0, SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850, unload_uart6850}, + {"MIDI6850", 0, SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850, unload_uart6850}, #endif #if defined(CONFIG_SBDSP) && !defined(CONFIG_SBDSP_MODULE) - {"SBLAST", 0, SNDCARD_SB, "Sound Blaster", attach_sb_card, probe_sb, unload_sb}, - {"SBPNP", 6, SNDCARD_SBPNP, "Sound Blaster PnP", attach_sb_card, probe_sb, unload_sb}, + {"SBLAST", 0, SNDCARD_SB, "Sound Blaster", attach_sb_card, probe_sb, unload_sb}, + {"SBPNP", 6, SNDCARD_SBPNP, "Sound Blaster PnP", attach_sb_card, probe_sb, unload_sb}, -# ifdef CONFIG_MIDI - {"SBMPU", 0, SNDCARD_SB16MIDI,"SB MPU-401", attach_sbmpu, probe_sbmpu, unload_sbmpu}, -# endif +#ifdef CONFIG_MIDI + {"SBMPU", 0, SNDCARD_SB16MIDI,"SB MPU-401", attach_sbmpu, probe_sbmpu, unload_sbmpu}, +#endif #endif #ifdef CONFIG_SSCAPEHW - {"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq SoundScape", attach_sscape, probe_sscape, unload_sscape}, - {"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound}, + {"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq SoundScape", attach_sscape, probe_sscape, unload_sscape}, + {"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound}, #endif #ifdef CONFIG_OPL3SA1 @@ -413,149 +430,146 @@ #endif #if defined (CONFIG_TRIX) && !defined(CONFIG_TRIX_MODULE) - {"TRXPRO", 0, SNDCARD_TRXPRO, "MediaTrix AudioTrix Pro", attach_trix_wss, probe_trix_wss, unload_trix_wss}, - {"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTrix (SB mode)", attach_trix_sb, probe_trix_sb, unload_trix_sb}, - {"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTrix MIDI", attach_trix_mpu, probe_trix_mpu, unload_trix_mpu}, + {"TRXPRO", 0, SNDCARD_TRXPRO, "MediaTrix AudioTrix Pro", attach_trix_wss, probe_trix_wss, unload_trix_wss}, + {"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTrix (SB mode)", attach_trix_sb, probe_trix_sb, unload_trix_sb}, + {"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTrix MIDI", attach_trix_mpu, probe_trix_mpu, unload_trix_mpu}, #endif #if defined(CONFIG_SOFTOSS) && !defined(CONFIG_SOFTOSS_MODULE) - {"SOFTSYN", 0, SNDCARD_SOFTOSS, "SoftOSS Virtual Wave Table", + {"SOFTSYN", 0, SNDCARD_SOFTOSS, "SoftOSS Virtual Wave Table", attach_softsyn_card, probe_softsyn, unload_softsyn}, #endif #if defined(CONFIG_VMIDI) && defined(CONFIG_MIDI) && !defined(CONFIG_VMIDI_MODULE) - {"VMIDI", 0, SNDCARD_VMIDI,"Loopback MIDI Device", attach_v_midi, probe_v_midi, unload_v_midi}, + {"VMIDI", 0, SNDCARD_VMIDI,"Loopback MIDI Device", attach_v_midi, probe_v_midi, unload_v_midi}, #endif + {NULL, 0, 0, "*?*", NULL, NULL, NULL} +}; - - - - {NULL, 0, 0, "*?*", NULL, NULL, NULL} - }; - - int num_sound_drivers = - sizeof(sound_drivers) / sizeof (struct driver_info); +int num_sound_drivers = sizeof(sound_drivers) / sizeof (struct driver_info); #ifndef FULL_SOUND + /* * List of devices actually configured in the system. * * Note! The detection order is significant. Don't change it. */ - struct card_info snd_installed_cards[] = { +struct card_info snd_installed_cards[] = +{ #ifdef CONFIG_PSS - {SNDCARD_PSS, {PSS_BASE, 0, -1, -1}, SND_DEFAULT_ENABLE}, -# ifdef PSS_MPU_BASE - {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -# endif -# ifdef PSS_MSS_BASE - {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE}, -# endif + {SNDCARD_PSS, {PSS_BASE, 0, -1, -1}, SND_DEFAULT_ENABLE}, +#ifdef PSS_MPU_BASE + {SNDCARD_PSS_MPU, {PSS_MPU_BASE, PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, +#endif +#ifdef PSS_MSS_BASE + {SNDCARD_PSS_MSS, {PSS_MSS_BASE, PSS_MSS_IRQ, PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE}, +#endif #endif #ifdef CONFIG_TRIX #ifndef TRIX_DMA2 #define TRIX_DMA2 TRIX_DMA #endif - {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA, TRIX_DMA2}, SND_DEFAULT_ENABLE}, -# ifdef TRIX_SB_BASE - {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA, -1}, SND_DEFAULT_ENABLE}, -# endif -# ifdef TRIX_MPU_BASE - {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -# endif + {SNDCARD_TRXPRO, {TRIX_BASE, TRIX_IRQ, TRIX_DMA, TRIX_DMA2}, SND_DEFAULT_ENABLE}, +#ifdef TRIX_SB_BASE + {SNDCARD_TRXPRO_SB, {TRIX_SB_BASE, TRIX_SB_IRQ, TRIX_SB_DMA, -1}, SND_DEFAULT_ENABLE}, +#endif +#ifdef TRIX_MPU_BASE + {SNDCARD_TRXPRO_MPU, {TRIX_MPU_BASE, TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, +#endif #endif #ifdef CONFIG_OPL3SA1 - {SNDCARD_OPL3SA1, {OPL3SA1_BASE, OPL3SA1_IRQ, OPL3SA1_DMA, OPL3SA1_DMA2}, SND_DEFAULT_ENABLE}, -# ifdef OPL3SA1_MPU_BASE - {SNDCARD_OPL3SA1_MPU, {OPL3SA1_MPU_BASE, OPL3SA1_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -# endif + {SNDCARD_OPL3SA1, {OPL3SA1_BASE, OPL3SA1_IRQ, OPL3SA1_DMA, OPL3SA1_DMA2}, SND_DEFAULT_ENABLE}, +#ifdef OPL3SA1_MPU_BASE + {SNDCARD_OPL3SA1_MPU, {OPL3SA1_MPU_BASE, OPL3SA1_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, +#endif #endif #ifdef CONFIG_SOFTOSS - {SNDCARD_SOFTOSS, {0, 0, -1, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_SOFTOSS, {0, 0, -1, -1}, SND_DEFAULT_ENABLE}, #endif #ifdef CONFIG_SSCAPE - {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE}, - {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_SSCAPE, {SSCAPE_BASE, SSCAPE_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_SSCAPE_MSS, {SSCAPE_MSS_BASE, SSCAPE_MSS_IRQ, SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE}, #endif #ifdef CONFIG_MAD16 #ifndef MAD16_DMA2 #define MAD16_DMA2 MAD16_DMA #endif - {SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA, MAD16_DMA2}, SND_DEFAULT_ENABLE}, -# ifdef MAD16_MPU_BASE - {SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -# endif + {SNDCARD_MAD16, {MAD16_BASE, MAD16_IRQ, MAD16_DMA, MAD16_DMA2}, SND_DEFAULT_ENABLE}, +#ifdef MAD16_MPU_BASE + {SNDCARD_MAD16_MPU, {MAD16_MPU_BASE, MAD16_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, +#endif #endif #ifdef CONFIG_CS4232 #ifndef CS4232_DMA2 #define CS4232_DMA2 CS4232_DMA #endif -# ifdef CS4232_MPU_BASE - {SNDCARD_CS4232_MPU, {CS4232_MPU_BASE, CS4232_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -# endif - {SNDCARD_CS4232, {CS4232_BASE, CS4232_IRQ, CS4232_DMA, CS4232_DMA2}, SND_DEFAULT_ENABLE}, +#ifdef CS4232_MPU_BASE + {SNDCARD_CS4232_MPU, {CS4232_MPU_BASE, CS4232_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, +#endif + {SNDCARD_CS4232, {CS4232_BASE, CS4232_IRQ, CS4232_DMA, CS4232_DMA2}, SND_DEFAULT_ENABLE}, #endif #ifdef CONFIG_MSS -# ifndef MSS_DMA2 -# define MSS_DMA2 -1 -# endif - -# ifdef DESKPROXL - {SNDCARD_DESKPROXL, {MSS_BASE, MSS_IRQ, MSS_DMA, MSS_DMA2}, SND_DEFAULT_ENABLE}, -# else - {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, MSS_DMA2}, SND_DEFAULT_ENABLE}, -# endif -# ifdef MSS2_BASE - {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA, MSS2_DMA2}, SND_DEFAULT_ENABLE}, -# endif +#ifndef MSS_DMA2 +#define MSS_DMA2 -1 +#endif + +#ifdef DESKPROXL + {SNDCARD_DESKPROXL, {MSS_BASE, MSS_IRQ, MSS_DMA, MSS_DMA2}, SND_DEFAULT_ENABLE}, +#else + {SNDCARD_MSS, {MSS_BASE, MSS_IRQ, MSS_DMA, MSS_DMA2}, SND_DEFAULT_ENABLE}, +#endif +#ifdef MSS2_BASE + {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA, MSS2_DMA2}, SND_DEFAULT_ENABLE}, +#endif #endif #ifdef CONFIG_PAS - {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_PAS, {PAS_BASE, PAS_IRQ, PAS_DMA, -1}, SND_DEFAULT_ENABLE}, #endif #ifdef CONFIG_SB -# ifndef SBC_DMA -# define SBC_DMA 1 -# endif -# ifndef SB_DMA2 -# define SB_DMA2 -1 -# endif - {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA, SB_DMA2}, SND_DEFAULT_ENABLE}, -# ifdef SB2_BASE - {SNDCARD_SB, {SB2_BASE, SB2_IRQ, SB2_DMA, SB2_DMA2}, SND_DEFAULT_ENABLE}, -# endif +#ifndef SBC_DMA +#define SBC_DMA 1 +#endif +#ifndef SB_DMA2 +#define SB_DMA2 -1 +#endif + {SNDCARD_SB, {SBC_BASE, SBC_IRQ, SBC_DMA, SB_DMA2}, SND_DEFAULT_ENABLE}, +#ifdef SB2_BASE + {SNDCARD_SB, {SB2_BASE, SB2_IRQ, SB2_DMA, SB2_DMA2}, SND_DEFAULT_ENABLE}, +#endif #endif #if defined(CONFIG_MAUI) - {SNDCARD_MAUI, {MAUI_BASE, MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_MAUI, {MAUI_BASE, MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #if defined(CONFIG_MPU401) && defined(CONFIG_MIDI) - {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_MPU401, {MPU_BASE, MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #ifdef MPU2_BASE - {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #ifdef MPU3_BASE - {SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_MPU401, {MPU3_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #endif #if defined(CONFIG_UART6850) && defined(CONFIG_MIDI) - {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_UART6850, {U6850_BASE, U6850_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #if defined(CONFIG_SB) #if defined(CONFIG_MIDI) && defined(SB_MPU_BASE) - {SNDCARD_SB16MIDI,{SB_MPU_BASE, SB_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_SB16MIDI,{SB_MPU_BASE, SB_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, #endif #endif @@ -564,54 +578,51 @@ #define GUS_DMA2 GUS_DMA #endif #ifdef CONFIG_GUS16 - {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_GUS16, {GUS16_BASE, GUS16_IRQ, GUS16_DMA, -1}, SND_DEFAULT_ENABLE}, #endif - {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA2}, SND_DEFAULT_ENABLE}, + {SNDCARD_GUS, {GUS_BASE, GUS_IRQ, GUS_DMA, GUS_DMA2}, SND_DEFAULT_ENABLE}, #endif #if defined(CONFIG_YM3812) - {SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE}, #endif #if defined(CONFIG_VMIDI) && defined(CONFIG_MIDI) - {SNDCARD_VMIDI, {0, 0, 0, -1}, SND_DEFAULT_ENABLE}, + {SNDCARD_VMIDI, {0, 0, 0, -1}, SND_DEFAULT_ENABLE}, #endif - {0, {0}, 0} - }; + {0, {0}, 0} +}; - int num_sound_cards = - sizeof(snd_installed_cards) / sizeof (struct card_info); - static int max_sound_cards = - sizeof(snd_installed_cards) / sizeof (struct card_info); +int num_sound_cards = sizeof(snd_installed_cards) / sizeof (struct card_info); +static int max_sound_cards = sizeof(snd_installed_cards) / sizeof (struct card_info); #else - int num_sound_cards = 0; - struct card_info snd_installed_cards[20] = {{0}}; - static int max_sound_cards = 20; +int num_sound_cards = 0; +struct card_info snd_installed_cards[20] = {{0}}; +static int max_sound_cards = 20; #endif #if defined(MODULE) || (!defined(linux) && !defined(_AIX)) - int trace_init = 0; -# else - int trace_init = 1; -# endif +int trace_init = 0; +#else +int trace_init = 1; +#endif #else - extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs; - extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers; - extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths; - extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis; - extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV]; extern int num_sound_timers; - - extern struct driver_info sound_drivers[]; - extern int num_sound_drivers; - extern struct card_info snd_installed_cards[]; - extern int num_sound_cards; +extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs; +extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixers; +extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths; +extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis; +extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV]; extern int num_sound_timers; + +extern struct driver_info sound_drivers[]; +extern int num_sound_drivers; +extern struct card_info snd_installed_cards[]; +extern int num_sound_cards; - extern int trace_init; +extern int trace_init; #endif /* _DEV_TABLE_C_ */ - void sndtable_init(void); int sndtable_get_cardcount (void); struct address_info *sound_getconf(int card_type); @@ -629,27 +640,17 @@ int sndtable_init_card (int unit, struct address_info *hw_config); int sndtable_start_card (int unit, struct address_info *hw_config); void sound_timer_init (struct sound_lowlev_timer *t, char *name); -int sound_start_dma ( int dev, struct dma_buffparms *dmap, int chan, - unsigned long physaddr, - int count, int dma_mode, int autoinit); +int sound_start_dma(int dev, struct dma_buffparms *dmap, int chan, + unsigned long physaddr, int count, int dma_mode, int autoinit); void sound_dma_intr (int dev, struct dma_buffparms *dmap, int chan); #define AUDIO_DRIVER_VERSION 2 #define MIXER_DRIVER_VERSION 2 -int sound_install_audiodrv(int vers, - char *name, - struct audio_driver *driver, - int driver_size, - int flags, - unsigned int format_mask, - void *devc, - int dma1, - int dma2); -int sound_install_mixer(int vers, - char *name, - struct mixer_operations *driver, - int driver_size, - void *devc); +int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, + int driver_size, int flags, unsigned int format_mask, + void *devc, int dma1, int dma2); +int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, + int driver_size, void *devc); void sound_unload_audiodev(int dev); void sound_unload_mixerdev(int dev); diff -u --recursive --new-file v2.1.79/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c --- v2.1.79/linux/drivers/sound/dmabuf.c Fri Jan 2 14:37:02 1998 +++ linux/drivers/sound/dmabuf.c Tue Jan 20 16:44:57 1998 @@ -19,33 +19,36 @@ #if defined(CONFIG_AUDIO) || defined(CONFIG_GUSHW) -static struct wait_queue *in_sleeper[MAX_AUDIO_DEV] = -{NULL}; -static volatile struct snd_wait in_sleep_flag[MAX_AUDIO_DEV] = -{ - {0}}; -static struct wait_queue *out_sleeper[MAX_AUDIO_DEV] = -{NULL}; -static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] = -{ - {0}}; +static struct wait_queue *in_sleeper[MAX_AUDIO_DEV] = { + NULL +}; + +static volatile struct snd_wait in_sleep_flag[MAX_AUDIO_DEV] = { + {0} +}; + +static struct wait_queue *out_sleeper[MAX_AUDIO_DEV] = { + NULL +}; + +static volatile struct snd_wait out_sleep_flag[MAX_AUDIO_DEV] = { + {0} +}; -static int ndmaps = 0; +static int ndmaps = 0; #define MAX_DMAP (MAX_AUDIO_DEV*2) -static struct dma_buffparms dmaps[MAX_DMAP] = -{ - {0}}; - -static void dma_reset_output(int dev); -static void dma_reset_input(int dev); -static int local_start_dma(int dev, unsigned long physaddr, int count, int dma_mode); +static struct dma_buffparms dmaps[MAX_DMAP] = { + {0} +}; + +static void dma_reset_output(int dev); +static void dma_reset_input(int dev); +static int local_start_dma(int dev, unsigned long physaddr, int count, int dma_mode); -static void -dma_init_buffers(int dev, struct dma_buffparms *dmap) +static void dma_init_buffers(int dev, struct dma_buffparms *dmap) { - dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; dmap->byte_counter = 0; dmap->max_byte_counter = 8000 * 60 * 60; @@ -61,29 +64,25 @@ dmap->flags = DMA_BUSY; /* Other flags off */ } -static int -open_dmap(int dev, int mode, struct dma_buffparms *dmap, int chan) +static int open_dmap(int dev, int mode, struct dma_buffparms *dmap, int chan) { + int err; + if (dmap->flags & DMA_BUSY) return -EBUSY; + if ((err = sound_alloc_dmap(dev, dmap, chan)) < 0) + return err; + if (dmap->raw_buf == NULL) { - int err; - - if ((err = sound_alloc_dmap(dev, dmap, chan)) < 0) - return err; + printk(KERN_WARNING "Sound: DMA buffers not available\n"); + return -ENOSPC; /* Memory allocation failed during boot */ } - - if (dmap->raw_buf == NULL) - { - printk("Sound: DMA buffers not available\n"); - return -ENOSPC; /* Memory allocation failed during boot */ - } if (sound_open_dma(chan, audio_devs[dev]->name)) - { - printk("Unable to grab(2) DMA%d for the audio driver\n", chan); - return -EBUSY; - } + { + printk(KERN_WARNING "Unable to grab(2) DMA%d for the audio driver\n", chan); + return -EBUSY; + } dma_init_buffers(dev, dmap); dmap->open_mode = mode; dmap->subdivision = dmap->underrun_count = 0; @@ -98,25 +97,19 @@ if (dmap->dma_mode & DMODE_OUTPUT) - { - out_sleep_flag[dev].opts = WK_NONE; - } else - { - in_sleep_flag[dev].opts = WK_NONE; - } - + out_sleep_flag[dev].opts = WK_NONE; + else + in_sleep_flag[dev].opts = WK_NONE; return 0; } -static void -close_dmap(int dev, struct dma_buffparms *dmap, int chan) +static void close_dmap(int dev, struct dma_buffparms *dmap, int chan) { sound_close_dma(chan); if (dmap->flags & DMA_BUSY) dmap->dma_mode = DMODE_NONE; dmap->flags &= ~DMA_BUSY; - disable_dma(dmap->dma); } @@ -155,8 +148,7 @@ return r; } -static void -check_driver(struct audio_driver *d) +static void check_driver(struct audio_driver *d) { if (d->set_speed == NULL) d->set_speed = default_set_speed; @@ -166,26 +158,23 @@ d->set_channels = default_set_channels; } -int -DMAbuf_open(int dev, int mode) +int DMAbuf_open(int dev, int mode) { - int retval; + int retval; struct dma_buffparms *dmap_in = NULL; struct dma_buffparms *dmap_out = NULL; if (dev >= num_audiodevs || audio_devs[dev] == NULL) - { - return -ENXIO; - } + return -ENXIO; + if (!audio_devs[dev]) - { return -ENXIO; - } + if (!(audio_devs[dev]->flags & DMA_DUPLEX)) - { - audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out; - audio_devs[dev]->dmap_in->dma = audio_devs[dev]->dmap_out->dma; - } + { + audio_devs[dev]->dmap_in = audio_devs[dev]->dmap_out; + audio_devs[dev]->dmap_in->dma = audio_devs[dev]->dmap_out->dma; + } check_driver(audio_devs[dev]->d); if ((retval = audio_devs[dev]->d->open(dev, mode)) < 0) @@ -198,29 +187,28 @@ audio_devs[dev]->flags &= ~DMA_DUPLEX; if (mode & OPEN_WRITE) - { - if ((retval = open_dmap(dev, mode, dmap_out, audio_devs[dev]->dmap_out->dma)) < 0) - { - audio_devs[dev]->d->close(dev); - return retval; - } - } + { + if ((retval = open_dmap(dev, mode, dmap_out, audio_devs[dev]->dmap_out->dma)) < 0) + { + audio_devs[dev]->d->close(dev); + return retval; + } + } audio_devs[dev]->enable_bits = mode; if (mode == OPEN_READ || (mode != OPEN_WRITE && - audio_devs[dev]->flags & DMA_DUPLEX)) - { - if ((retval = open_dmap(dev, mode, dmap_in, audio_devs[dev]->dmap_in->dma)) < 0) - { - audio_devs[dev]->d->close(dev); - - if (mode & OPEN_WRITE) - { - close_dmap(dev, dmap_out, audio_devs[dev]->dmap_out->dma); - } - return retval; - } - } + audio_devs[dev]->flags & DMA_DUPLEX)) + { + if ((retval = open_dmap(dev, mode, dmap_in, audio_devs[dev]->dmap_in->dma)) < 0) + { + audio_devs[dev]->d->close(dev); + if (mode & OPEN_WRITE) + { + close_dmap(dev, dmap_out, audio_devs[dev]->dmap_out->dma); + } + return retval; + } + } audio_devs[dev]->open_mode = mode; audio_devs[dev]->go = 1; @@ -235,16 +223,15 @@ audio_devs[dev]->d->set_speed(dev, DSP_DEFAULT_SPEED); if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT) - { - memset(audio_devs[dev]->dmap_out->raw_buf, - audio_devs[dev]->dmap_out->neutral_byte, - audio_devs[dev]->dmap_out->bytes_in_use); - } + { + memset(audio_devs[dev]->dmap_out->raw_buf, + audio_devs[dev]->dmap_out->neutral_byte, + audio_devs[dev]->dmap_out->bytes_in_use); + } return 0; } -void -DMAbuf_reset(int dev) +void DMAbuf_reset(int dev) { if (audio_devs[dev]->open_mode & OPEN_WRITE) dma_reset_output(dev); @@ -253,29 +240,24 @@ dma_reset_input(dev); } -static void -dma_reset_output(int dev) +static void dma_reset_output(int dev) { - unsigned long flags; - int tmout; - + unsigned long flags; + int tmout; struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - if (!(dmap->flags & DMA_STARTED)) /* DMA is not active */ return; -/* - * First wait until the current fragment has been played completely - */ + /* + * First wait until the current fragment has been played completely + */ save_flags(flags); cli(); - tmout = - (dmap->fragment_size * HZ) / dmap->data_rate; + tmout = (dmap->fragment_size * HZ) / dmap->data_rate; tmout += HZ / 5; /* Some safety distance */ - if (tmout < (HZ / 2)) tmout = HZ / 2; if (tmout > 20 * HZ) @@ -287,33 +269,30 @@ if (!signal_pending(current) && audio_devs[dev]->dmap_out->qlen && audio_devs[dev]->dmap_out->underrun_count == 0) - { - - { - unsigned long tlimit; + { + unsigned long tlimit; - if (tmout) - current->timeout = tlimit = jiffies + (tmout); - else - tlimit = (unsigned long) -1; - out_sleep_flag[dev].opts = WK_SLEEP; - interruptible_sleep_on(&out_sleeper[dev]); - if (!(out_sleep_flag[dev].opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - out_sleep_flag[dev].opts |= WK_TIMEOUT; - } - out_sleep_flag[dev].opts &= ~WK_SLEEP; - }; - } + if (tmout) + current->timeout = tlimit = jiffies + (tmout); + else + tlimit = (unsigned long) -1; + out_sleep_flag[dev].opts = WK_SLEEP; + interruptible_sleep_on(&out_sleeper[dev]); + if (!(out_sleep_flag[dev].opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + out_sleep_flag[dev].opts |= WK_TIMEOUT; + } + out_sleep_flag[dev].opts &= ~WK_SLEEP; + } audio_devs[dev]->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); -/* - * Finally shut the device off - */ + /* + * Finally shut the device off + */ if (!(audio_devs[dev]->flags & DMA_DUPLEX) || - !audio_devs[dev]->d->halt_output) + !audio_devs[dev]->d->halt_output) audio_devs[dev]->d->halt_io(dev); else audio_devs[dev]->d->halt_output(dev); @@ -327,16 +306,15 @@ dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0; } -static void -dma_reset_input(int dev) +static void dma_reset_input(int dev) { - unsigned long flags; + unsigned long flags; struct dma_buffparms *dmap = audio_devs[dev]->dmap_in; save_flags(flags); cli(); if (!(audio_devs[dev]->flags & DMA_DUPLEX) || - !audio_devs[dev]->d->halt_input) + !audio_devs[dev]->d->halt_input) audio_devs[dev]->d->halt_io(dev); else audio_devs[dev]->d->halt_input(dev); @@ -348,151 +326,125 @@ reorganize_buffers(dev, audio_devs[dev]->dmap_in, 1); } -void -DMAbuf_launch_output(int dev, struct dma_buffparms *dmap) +void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap) { if (!((audio_devs[dev]->enable_bits * audio_devs[dev]->go) & PCM_ENABLE_OUTPUT)) return; /* Don't start DMA yet */ - dmap->dma_mode = DMODE_OUTPUT; if (!(dmap->flags & DMA_ACTIVE) || !(audio_devs[dev]->flags & DMA_AUTOMODE) || dmap->flags & DMA_NODMA) - { - if (!(dmap->flags & DMA_STARTED)) - { - reorganize_buffers(dev, dmap, 0); - - if (audio_devs[dev]->d->prepare_for_output(dev, - dmap->fragment_size, dmap->nbufs)) - return; - - if (!(dmap->flags & DMA_NODMA)) - { - local_start_dma(dev, dmap->raw_buf_phys, dmap->bytes_in_use, - DMA_MODE_WRITE); - } - dmap->flags |= DMA_STARTED; - } - if (dmap->counts[dmap->qhead] == 0) - dmap->counts[dmap->qhead] = dmap->fragment_size; - - dmap->dma_mode = DMODE_OUTPUT; - audio_devs[dev]->d->output_block(dev, dmap->raw_buf_phys + - dmap->qhead * dmap->fragment_size, - dmap->counts[dmap->qhead], 1); - if (audio_devs[dev]->d->trigger) - audio_devs[dev]->d->trigger(dev, - audio_devs[dev]->enable_bits * audio_devs[dev]->go); - } + { + if (!(dmap->flags & DMA_STARTED)) + { + reorganize_buffers(dev, dmap, 0); + if (audio_devs[dev]->d->prepare_for_output(dev, + dmap->fragment_size, dmap->nbufs)) + return; + if (!(dmap->flags & DMA_NODMA)) + local_start_dma(dev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_WRITE); + dmap->flags |= DMA_STARTED; + } + if (dmap->counts[dmap->qhead] == 0) + dmap->counts[dmap->qhead] = dmap->fragment_size; + + dmap->dma_mode = DMODE_OUTPUT; + audio_devs[dev]->d->output_block(dev, dmap->raw_buf_phys + dmap->qhead * dmap->fragment_size, + dmap->counts[dmap->qhead], 1); + if (audio_devs[dev]->d->trigger) + audio_devs[dev]->d->trigger(dev,audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } dmap->flags |= DMA_ACTIVE; } -int -DMAbuf_sync(int dev) +int DMAbuf_sync(int dev) { - unsigned long flags; - int tmout, n = 0; + unsigned long flags; + int tmout, n = 0; if (!audio_devs[dev]->go && (!audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT)) return 0; if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT) - { - - struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - - save_flags(flags); - cli(); - - tmout = - (dmap->fragment_size * HZ) / dmap->data_rate; - - tmout += HZ / 5; /* Some safety distance */ - - if (tmout < (HZ / 2)) - tmout = HZ / 2; - if (tmout > 20 * HZ) - tmout = 20 * HZ; - - ; - if (dmap->qlen > 0) - if (!(dmap->flags & DMA_ACTIVE)) - DMAbuf_launch_output(dev, dmap); - ; - - audio_devs[dev]->dmap_out->flags |= DMA_SYNCING; - - audio_devs[dev]->dmap_out->underrun_count = 0; - while (!signal_pending(current) - && n++ <= audio_devs[dev]->dmap_out->nbufs - && audio_devs[dev]->dmap_out->qlen - && audio_devs[dev]->dmap_out->underrun_count == 0) - { - - { - unsigned long tlimit; - - if (tmout) - current->timeout = tlimit = jiffies + (tmout); - else - tlimit = (unsigned long) -1; - out_sleep_flag[dev].opts = WK_SLEEP; - interruptible_sleep_on(&out_sleeper[dev]); - if (!(out_sleep_flag[dev].opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - out_sleep_flag[dev].opts |= WK_TIMEOUT; - } - out_sleep_flag[dev].opts &= ~WK_SLEEP; - }; - if ((out_sleep_flag[dev].opts & WK_TIMEOUT)) - { - audio_devs[dev]->dmap_out->flags &= ~DMA_SYNCING; - restore_flags(flags); - return audio_devs[dev]->dmap_out->qlen; - } - } - audio_devs[dev]->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); - restore_flags(flags); - /* - * Some devices such as GUS have huge amount of on board RAM for the - * audio data. We have to wait until the device has finished playing. - */ - - save_flags(flags); - cli(); - if (audio_devs[dev]->d->local_qlen) /* Device has hidden buffers */ - { - while (!signal_pending(current) - && audio_devs[dev]->d->local_qlen(dev)) - { - - { - unsigned long tlimit; - - if (tmout) - current->timeout = tlimit = jiffies + (tmout); - else - tlimit = (unsigned long) -1; - out_sleep_flag[dev].opts = WK_SLEEP; - interruptible_sleep_on(&out_sleeper[dev]); - if (!(out_sleep_flag[dev].opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - out_sleep_flag[dev].opts |= WK_TIMEOUT; - } - out_sleep_flag[dev].opts &= ~WK_SLEEP; - }; - } - } - restore_flags(flags); - } + { + struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; + save_flags(flags); + cli(); + + tmout = (dmap->fragment_size * HZ) / dmap->data_rate; + tmout += HZ / 5; /* Some safety distance */ + + if (tmout < (HZ / 2)) + tmout = HZ / 2; + if (tmout > 20 * HZ) + tmout = 20 * HZ; + + if (dmap->qlen > 0) + if (!(dmap->flags & DMA_ACTIVE)) + DMAbuf_launch_output(dev, dmap); + + audio_devs[dev]->dmap_out->flags |= DMA_SYNCING; + audio_devs[dev]->dmap_out->underrun_count = 0; + while (!signal_pending(current) && n++ <= audio_devs[dev]->dmap_out->nbufs && audio_devs[dev]->dmap_out->qlen + && audio_devs[dev]->dmap_out->underrun_count == 0) + { + unsigned long tlimit; + + if (tmout) + current->timeout = tlimit = jiffies + (tmout); + else + tlimit = (unsigned long) -1; + out_sleep_flag[dev].opts = WK_SLEEP; + interruptible_sleep_on(&out_sleeper[dev]); + if (!(out_sleep_flag[dev].opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + out_sleep_flag[dev].opts |= WK_TIMEOUT; + } + out_sleep_flag[dev].opts &= ~WK_SLEEP; + + if ((out_sleep_flag[dev].opts & WK_TIMEOUT)) + { + audio_devs[dev]->dmap_out->flags &= ~DMA_SYNCING; + restore_flags(flags); + return audio_devs[dev]->dmap_out->qlen; + } + } + audio_devs[dev]->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE); + restore_flags(flags); + + /* + * Some devices such as GUS have huge amount of on board RAM for the + * audio data. We have to wait until the device has finished playing. + */ + + save_flags(flags); + cli(); + if (audio_devs[dev]->d->local_qlen) /* Device has hidden buffers */ + { + while (!signal_pending(current) && audio_devs[dev]->d->local_qlen(dev)) + { + unsigned long tlimit; + + if (tmout) + current->timeout = tlimit = jiffies + (tmout); + else + tlimit = (unsigned long) -1; + out_sleep_flag[dev].opts = WK_SLEEP; + interruptible_sleep_on(&out_sleeper[dev]); + if (!(out_sleep_flag[dev].opts & WK_WAKEUP)) + { if (jiffies >= tlimit) + out_sleep_flag[dev].opts |= WK_TIMEOUT; + } + out_sleep_flag[dev].opts &= ~WK_SLEEP; + } + } + restore_flags(flags); + } audio_devs[dev]->dmap_out->dma_mode = DMODE_NONE; return audio_devs[dev]->dmap_out->qlen; } -int -DMAbuf_release(int dev, int mode) +int DMAbuf_release(int dev, int mode) { unsigned long flags; @@ -505,15 +457,13 @@ if (!(audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)) if (!signal_pending(current) && (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT)) - { - DMAbuf_sync(dev); - } + { + DMAbuf_sync(dev); + } if (audio_devs[dev]->dmap_out->dma_mode == DMODE_OUTPUT) - { - memset(audio_devs[dev]->dmap_out->raw_buf, - audio_devs[dev]->dmap_out->neutral_byte, - audio_devs[dev]->dmap_out->bytes_in_use); - } + { + memset(audio_devs[dev]->dmap_out->raw_buf, audio_devs[dev]->dmap_out->neutral_byte, audio_devs[dev]->dmap_out->bytes_in_use); + } save_flags(flags); cli(); @@ -526,16 +476,15 @@ if (audio_devs[dev]->open_mode == OPEN_READ || (audio_devs[dev]->open_mode != OPEN_WRITE && audio_devs[dev]->flags & DMA_DUPLEX)) + { close_dmap(dev, audio_devs[dev]->dmap_in, audio_devs[dev]->dmap_in->dma); + } audio_devs[dev]->open_mode = 0; - restore_flags(flags); - return 0; } -int -DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap) +int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap) { if (!(audio_devs[dev]->open_mode & OPEN_READ)) return 0; @@ -544,45 +493,40 @@ return 0; if (dmap->dma_mode == DMODE_OUTPUT) /* Direction change */ - { - DMAbuf_sync(dev); - DMAbuf_reset(dev); - dmap->dma_mode = DMODE_NONE; - } + { + DMAbuf_sync(dev); + DMAbuf_reset(dev); + dmap->dma_mode = DMODE_NONE; + } if (!dmap->dma_mode) - { - int err; + { + int err; - reorganize_buffers(dev, dmap, 1); - if ((err = audio_devs[dev]->d->prepare_for_input(dev, - dmap->fragment_size, dmap->nbufs)) < 0) - { - return err; - } - dmap->dma_mode = DMODE_INPUT; - } + reorganize_buffers(dev, dmap, 1); + if ((err = audio_devs[dev]->d->prepare_for_input(dev, + dmap->fragment_size, dmap->nbufs)) < 0) + return err; + dmap->dma_mode = DMODE_INPUT; + } if (!(dmap->flags & DMA_ACTIVE)) - { - if (dmap->needs_reorg) - reorganize_buffers(dev, dmap, 0); - local_start_dma(dev, dmap->raw_buf_phys, dmap->bytes_in_use, - DMA_MODE_READ); - audio_devs[dev]->d->start_input(dev, dmap->raw_buf_phys + - dmap->qtail * dmap->fragment_size, - dmap->fragment_size, 0); - dmap->flags |= DMA_ACTIVE; - if (audio_devs[dev]->d->trigger) - audio_devs[dev]->d->trigger(dev, - audio_devs[dev]->enable_bits * audio_devs[dev]->go); - } + { + if (dmap->needs_reorg) + reorganize_buffers(dev, dmap, 0); + local_start_dma(dev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ); + audio_devs[dev]->d->start_input(dev, dmap->raw_buf_phys + + dmap->qtail * dmap->fragment_size, + dmap->fragment_size, 0); + dmap->flags |= DMA_ACTIVE; + if (audio_devs[dev]->d->trigger) + audio_devs[dev]->d->trigger(dev, audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } return 0; } -int -DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock) +int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock) { - unsigned long flags; - int err = 0, n = 0; + unsigned long flags; + int err = 0, n = 0; struct dma_buffparms *dmap = audio_devs[dev]->dmap_in; if (!(audio_devs[dev]->open_mode & OPEN_READ)) @@ -593,153 +537,149 @@ save_flags(flags); cli(); if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED) - { - printk("Sound: Can't read from mmapped device (1)\n"); + { +/* printk(KERN_WARNING "Sound: Can't read from mmapped device (1)\n");*/ restore_flags(flags); return -EINVAL; - } else - while (dmap->qlen <= 0 && n++ < 10) - { - int tmout; - - if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) || - !audio_devs[dev]->go) - { - restore_flags(flags); - return -EAGAIN; - } - if ((err = DMAbuf_activate_recording(dev, dmap)) < 0) - { - restore_flags(flags); - return err; - } - /* Wait for the next block */ - - if (dontblock) - { - restore_flags(flags); - return -EAGAIN; - } - if (!audio_devs[dev]->go) - tmout = 0; - else - { - tmout = - (dmap->fragment_size * HZ) / dmap->data_rate; - - tmout += HZ / 5; /* Some safety distance */ - - if (tmout < (HZ / 2)) - tmout = HZ / 2; - if (tmout > 20 * HZ) - tmout = 20 * HZ; - } - - - { - unsigned long tlimit; - - if (tmout) - current->timeout = tlimit = jiffies + (tmout); - else - tlimit = (unsigned long) -1; - in_sleep_flag[dev].opts = WK_SLEEP; - interruptible_sleep_on(&in_sleeper[dev]); - if (!(in_sleep_flag[dev].opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - in_sleep_flag[dev].opts |= WK_TIMEOUT; - } - in_sleep_flag[dev].opts &= ~WK_SLEEP; - }; - if ((in_sleep_flag[dev].opts & WK_TIMEOUT)) - { - err = -EIO; - printk("Sound: DMA (input) timed out - IRQ/DRQ config error?\n"); - dma_reset_input(dev); - ; - } else - err = -EINTR; - } + } + else while (dmap->qlen <= 0 && n++ < 10) + { + int tmout; + unsigned long tlimit; + + if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT) || !audio_devs[dev]->go) + { + restore_flags(flags); + return -EAGAIN; + } + if ((err = DMAbuf_activate_recording(dev, dmap)) < 0) + { + restore_flags(flags); + return err; + } + /* Wait for the next block */ + + if (dontblock) + { + restore_flags(flags); + return -EAGAIN; + } + if (!audio_devs[dev]->go) + tmout = 0; + else + { + tmout = (dmap->fragment_size * HZ) / dmap->data_rate; + tmout += HZ / 5; /* Some safety distance */ + + if (tmout < (HZ / 2)) + tmout = HZ / 2; + if (tmout > 20 * HZ) + tmout = 20 * HZ; + } + + if (tmout) + current->timeout = tlimit = jiffies + (tmout); + else + tlimit = (unsigned long) -1; + in_sleep_flag[dev].opts = WK_SLEEP; + interruptible_sleep_on(&in_sleeper[dev]); + if (!(in_sleep_flag[dev].opts & WK_WAKEUP)) + { + if (jiffies >= tlimit) + in_sleep_flag[dev].opts |= WK_TIMEOUT; + } + in_sleep_flag[dev].opts &= ~WK_SLEEP; + + if ((in_sleep_flag[dev].opts & WK_TIMEOUT)) + { + /* FIXME: include device name */ + err = -EIO; + printk(KERN_WARNING "Sound: DMA (input) timed out - IRQ/DRQ config error?\n"); + dma_reset_input(dev); + } + else + err = -EINTR; + } restore_flags(flags); if (dmap->qlen <= 0) - { - if (err == 0) - err = -EINTR; - return err; - } + { + if (err == 0) + err = -EINTR; + return err; + } *buf = &dmap->raw_buf[dmap->qhead * dmap->fragment_size + dmap->counts[dmap->qhead]]; *len = dmap->fragment_size - dmap->counts[dmap->qhead]; return dmap->qhead; } -int -DMAbuf_rmchars(int dev, int buff_no, int c) +int DMAbuf_rmchars(int dev, int buff_no, int c) { struct dma_buffparms *dmap = audio_devs[dev]->dmap_in; - - int p = dmap->counts[dmap->qhead] + c; + int p = dmap->counts[dmap->qhead] + c; if (dmap->mapping_flags & DMA_MAP_MAPPED) - { - printk("Sound: Can't read from mmapped device (2)\n"); - return -EINVAL; - } else if (dmap->qlen <= 0) + { +/* printk("Sound: Can't read from mmapped device (2)\n");*/ + return -EINVAL; + } + else if (dmap->qlen <= 0) return -EIO; else if (p >= dmap->fragment_size) - { /* This buffer is completely empty */ - dmap->counts[dmap->qhead] = 0; - dmap->qlen--; - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - } else - dmap->counts[dmap->qhead] = p; + { /* This buffer is completely empty */ + dmap->counts[dmap->qhead] = 0; + dmap->qlen--; + dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; + } + else dmap->counts[dmap->qhead] = p; return 0; } -int -DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction) +int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction) { -/* - * Try to approximate the active byte position of the DMA pointer within the - * buffer area as well as possible. - */ - int pos; - unsigned long flags; + /* + * Try to approximate the active byte position of the DMA pointer within the + * buffer area as well as possible. + */ + + int pos; + unsigned long flags; save_flags(flags); cli(); if (!(dmap->flags & DMA_ACTIVE)) pos = 0; else - { - int chan = dmap->dma; - - clear_dma_ff(chan); - disable_dma(dmap->dma); - pos = get_dma_residue(chan); - pos = dmap->bytes_in_use - pos; - - if (!(dmap->mapping_flags & DMA_MAP_MAPPED)) - if (direction == DMODE_OUTPUT) - { - if (dmap->qhead == 0) - if (pos > dmap->fragment_size) - pos = 0; - } else - { - if (dmap->qtail == 0) - if (pos > dmap->fragment_size) - pos = 0; - } - if (pos < 0) - pos = 0; - if (pos >= dmap->bytes_in_use) - pos = 0; - enable_dma(dmap->dma); - } + { + int chan = dmap->dma; + clear_dma_ff(chan); + disable_dma(dmap->dma); + pos = get_dma_residue(chan); + pos = dmap->bytes_in_use - pos; + + if (!(dmap->mapping_flags & DMA_MAP_MAPPED)) + { + if (direction == DMODE_OUTPUT) + { + if (dmap->qhead == 0) + if (pos > dmap->fragment_size) + pos = 0; + } + else + { + if (dmap->qtail == 0) + if (pos > dmap->fragment_size) + pos = 0; + } + } + if (pos < 0) + pos = 0; + if (pos >= dmap->bytes_in_use) + pos = 0; + enable_dma(dmap->dma); + } restore_flags(flags); /* printk( "%04x ", pos); */ @@ -747,42 +687,39 @@ } /* - * DMAbuf_start_devices() is called by the /dev/music driver to start - * one or more audio devices at desired moment. + * DMAbuf_start_devices() is called by the /dev/music driver to start + * one or more audio devices at desired moment. */ -static void -DMAbuf_start_device(int dev) + +static void DMAbuf_start_device(int dev) { if (audio_devs[dev]->open_mode != 0) + { if (!audio_devs[dev]->go) - { - /* OK to start the device */ - audio_devs[dev]->go = 1; - - if (audio_devs[dev]->d->trigger) - audio_devs[dev]->d->trigger(dev, - audio_devs[dev]->enable_bits * audio_devs[dev]->go); - } + { + /* OK to start the device */ + audio_devs[dev]->go = 1; + + if (audio_devs[dev]->d->trigger) + audio_devs[dev]->d->trigger(dev,audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } + } } -void -DMAbuf_start_devices(unsigned int devmask) +void DMAbuf_start_devices(unsigned int devmask) { - int dev; + int dev; for (dev = 0; dev < num_audiodevs; dev++) if ((devmask & (1 << dev)) && audio_devs[dev] != NULL) DMAbuf_start_device(dev); } -int -DMAbuf_space_in_queue(int dev) +int DMAbuf_space_in_queue(int dev) { - int len, max, tmp; + int len, max, tmp; struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - - int lim = dmap->nbufs; - + int lim = dmap->nbufs; if (lim < 2) lim = 2; @@ -791,8 +728,8 @@ return 0; /* - * Verify that there are no more pending buffers than the limit - * defined by the process. + * Verify that there are no more pending buffers than the limit + * defined by the process. */ max = dmap->max_fragments; @@ -801,14 +738,14 @@ len = dmap->qlen; if (audio_devs[dev]->d->local_qlen) - { - tmp = audio_devs[dev]->d->local_qlen(dev); - if (tmp && len) - tmp--; /* - * This buffer has been counted twice - */ - len += tmp; - } + { + tmp = audio_devs[dev]->d->local_qlen(dev); + if (tmp && len) + tmp--; /* + * This buffer has been counted twice + */ + len += tmp; + } if (dmap->byte_counter % dmap->fragment_size) /* There is a partial fragment */ len = len + 1; @@ -817,87 +754,74 @@ return max - len; } -static int -output_sleep(int dev, int dontblock) +static int output_sleep(int dev, int dontblock) { - int tmout; - int err = 0; + int tmout; + int err = 0; struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; + unsigned long tlimit; if (dontblock) - { - return -EAGAIN; - } + return -EAGAIN; if (!(audio_devs[dev]->enable_bits & PCM_ENABLE_OUTPUT)) - { - return -EAGAIN; - } + return -EAGAIN; + /* * Wait for free space */ + if (!audio_devs[dev]->go || dmap->flags & DMA_NOTIMEOUT) tmout = 0; else - { - tmout = - (dmap->fragment_size * HZ) / dmap->data_rate; - - tmout += HZ / 5; /* Some safety distance */ - - if (tmout < (HZ / 2)) - tmout = HZ / 2; - if (tmout > 20 * HZ) - tmout = 20 * HZ; - } + { + tmout = (dmap->fragment_size * HZ) / dmap->data_rate; + tmout += HZ / 5; /* Some safety distance */ + + if (tmout < (HZ / 2)) + tmout = HZ / 2; + if (tmout > 20 * HZ) + tmout = 20 * HZ; + } if (signal_pending(current)) return -EIO; - + if (tmout) + current->timeout = tlimit = jiffies + (tmout); + else + tlimit = (unsigned long) -1; + out_sleep_flag[dev].opts = WK_SLEEP; + interruptible_sleep_on(&out_sleeper[dev]); + if (!(out_sleep_flag[dev].opts & WK_WAKEUP)) { - unsigned long tlimit; + if (jiffies >= tlimit) + out_sleep_flag[dev].opts |= WK_TIMEOUT; + } + out_sleep_flag[dev].opts &= ~WK_SLEEP; - if (tmout) - current->timeout = tlimit = jiffies + (tmout); - else - tlimit = (unsigned long) -1; - out_sleep_flag[dev].opts = WK_SLEEP; - interruptible_sleep_on(&out_sleeper[dev]); - if (!(out_sleep_flag[dev].opts & WK_WAKEUP)) - { - if (jiffies >= tlimit) - out_sleep_flag[dev].opts |= WK_TIMEOUT; - } - out_sleep_flag[dev].opts &= ~WK_SLEEP; - }; if ((out_sleep_flag[dev].opts & WK_TIMEOUT)) - { - printk("Sound: DMA (output) timed out - IRQ/DRQ config error?\n"); - ; - dma_reset_output(dev); - } else if (signal_pending(current)) - { - err = -EINTR; - } + { + printk(KERN_WARNING "Sound: DMA (output) timed out - IRQ/DRQ config error?\n"); + dma_reset_output(dev); + } + else if (signal_pending(current)) + err = -EINTR; return err; } -static int -find_output_space(int dev, char **buf, int *size) +static int find_output_space(int dev, char **buf, int *size) { struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - unsigned long flags; - unsigned long active_offs; - long len, offs; - int maxfrags; - int occupied_bytes = (dmap->user_counter % dmap->fragment_size); + unsigned long flags; + unsigned long active_offs; + long len, offs; + int maxfrags; + int occupied_bytes = (dmap->user_counter % dmap->fragment_size); *buf = dmap->raw_buf; if (!(maxfrags = DMAbuf_space_in_queue(dev)) && !occupied_bytes) - { - return 0; - } + return 0; save_flags(flags); cli(); @@ -913,100 +837,89 @@ offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP; if (offs < 0 || offs >= dmap->bytes_in_use) - { - printk("OSS: Got unexpected offs %ld. Giving up.\n", offs); - printk("Counter = %ld, bytes=%d\n", dmap->user_counter, dmap->bytes_in_use); - return 0; - } + { + printk(KERN_ERR "Sound: Got unexpected offs %ld. Giving up.\n", offs); + printk("Counter = %ld, bytes=%d\n", dmap->user_counter, dmap->bytes_in_use); + return 0; + } *buf = dmap->raw_buf + offs; len = active_offs + dmap->bytes_in_use - dmap->user_counter; /* Number of unused bytes in buffer */ if ((offs + len) > dmap->bytes_in_use) - { - len = dmap->bytes_in_use - offs; - } + len = dmap->bytes_in_use - offs; if (len < 0) - { - restore_flags(flags); - return 0; - } + { + restore_flags(flags); + return 0; + } if (len > ((maxfrags * dmap->fragment_size) - occupied_bytes)) - { - len = (maxfrags * dmap->fragment_size) - occupied_bytes; - } + len = (maxfrags * dmap->fragment_size) - occupied_bytes; + *size = len & ~SAMPLE_ROUNDUP; restore_flags(flags); return (*size > 0); } -int -DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock) +int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock) { - unsigned long flags; - int err = -EIO; + unsigned long flags; + int err = -EIO; struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; if (dmap->needs_reorg) reorganize_buffers(dev, dmap, 0); if (dmap->mapping_flags & DMA_MAP_MAPPED) - { - printk("Sound: Can't write to mmapped device (3)\n"); - return -EINVAL; - } + { +/* printk(KERN_DEBUG "Sound: Can't write to mmapped device (3)\n");*/ + return -EINVAL; + } if (dmap->dma_mode == DMODE_INPUT) /* Direction change */ - { + { DMAbuf_reset(dev); dmap->dma_mode = DMODE_NONE; - } + } dmap->dma_mode = DMODE_OUTPUT; save_flags(flags); cli(); while (find_output_space(dev, buf, size) <= 0) - { - if ((err = output_sleep(dev, dontblock)) < 0) - { - restore_flags(flags); - return err; - } - } + { + if ((err = output_sleep(dev, dontblock)) < 0) + { + restore_flags(flags); + return err; + } + } restore_flags(flags); return 0; } -int -DMAbuf_move_wrpointer(int dev, int l) +int DMAbuf_move_wrpointer(int dev, int l) { struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - unsigned long ptr = (dmap->user_counter / dmap->fragment_size) - * dmap->fragment_size; - - unsigned long end_ptr, p; - int post = (dmap->flags & DMA_POST); - - ; + unsigned long ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; + unsigned long end_ptr, p; + int post = (dmap->flags & DMA_POST); dmap->flags &= ~DMA_POST; - dmap->cfrag = -1; - dmap->user_counter += l; dmap->flags |= DMA_DIRTY; if (dmap->user_counter >= dmap->max_byte_counter) - { /* Wrap the byte counters */ - long decr = dmap->user_counter; + { /* Wrap the byte counters */ + long decr = dmap->user_counter; - dmap->user_counter = (dmap->user_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->user_counter; - dmap->byte_counter -= decr; - } + dmap->user_counter = (dmap->user_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + decr -= dmap->user_counter; + dmap->byte_counter -= decr; + } end_ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size; p = (dmap->user_counter - 1) % dmap->bytes_in_use; @@ -1014,53 +927,53 @@ /* Update the fragment based bookkeeping too */ while (ptr < end_ptr) - { - dmap->counts[dmap->qtail] = dmap->fragment_size; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - dmap->qlen++; - ptr += dmap->fragment_size; - } + { + dmap->counts[dmap->qtail] = dmap->fragment_size; + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + dmap->qlen++; + ptr += dmap->fragment_size; + } dmap->counts[dmap->qtail] = dmap->user_counter - ptr; -/* - * Let the low level driver to perform some postprocessing to - * the written data. - */ + /* + * Let the low level driver to perform some postprocessing to + * the written data. + */ if (audio_devs[dev]->d->postprocess_write) audio_devs[dev]->d->postprocess_write(dev); if (!(dmap->flags & DMA_ACTIVE)) + { if (dmap->qlen > 1 || (dmap->qlen > 0 && (post || dmap->qlen >= dmap->nbufs - 1))) - { DMAbuf_launch_output(dev, dmap); - }; + } return 0; } -int -DMAbuf_start_dma(int dev, unsigned long physaddr, int count, int dma_mode) +int DMAbuf_start_dma(int dev, unsigned long physaddr, int count, int dma_mode) { int chan; struct dma_buffparms *dmap; if (dma_mode == DMA_MODE_WRITE) - { - chan = audio_devs[dev]->dmap_out->dma; - dmap = audio_devs[dev]->dmap_out; - } else - { - chan = audio_devs[dev]->dmap_in->dma; - dmap = audio_devs[dev]->dmap_in; - } + { + chan = audio_devs[dev]->dmap_out->dma; + dmap = audio_devs[dev]->dmap_out; + } + else + { + chan = audio_devs[dev]->dmap_in->dma; + dmap = audio_devs[dev]->dmap_in; + } if (dmap->raw_buf == NULL) - { - printk("sound: DMA buffer(1) == NULL\n"); - printk("Device %d, chn=%s\n", dev, (dmap == audio_devs[dev]->dmap_out) ? "out" : "in"); - return 0; - } + { + printk(KERN_ERR "sound: DMA buffer(1) == NULL\n"); + printk("Device %d, chn=%s\n", dev, (dmap == audio_devs[dev]->dmap_out) ? "out" : "in"); + return 0; + } if (chan < 0) return 0; @@ -1069,32 +982,32 @@ return count; } -static int -local_start_dma(int dev, unsigned long physaddr, int count, int dma_mode) +static int local_start_dma(int dev, unsigned long physaddr, int count, int dma_mode) { - int chan; + int chan; struct dma_buffparms *dmap; if (dma_mode == DMA_MODE_WRITE) - { - chan = audio_devs[dev]->dmap_out->dma; - dmap = audio_devs[dev]->dmap_out; - } else - { - chan = audio_devs[dev]->dmap_in->dma; - dmap = audio_devs[dev]->dmap_in; - } + { + chan = audio_devs[dev]->dmap_out->dma; + dmap = audio_devs[dev]->dmap_out; + } + else + { + chan = audio_devs[dev]->dmap_in->dma; + dmap = audio_devs[dev]->dmap_in; + } if (dmap->raw_buf == NULL) - { - printk("sound: DMA buffer(2) == NULL\n"); - printk("Device %d, chn=%s\n", dev, (dmap == audio_devs[dev]->dmap_out) ? "out" : "in"); - return 0; - } + { + printk(KERN_ERR "sound: DMA buffer(2) == NULL\n"); + printk(KERN_ERR "Device %d, chn=%s\n", dev, (dmap == audio_devs[dev]->dmap_out) ? "out" : "in"); + return 0; + } if (dmap->flags & DMA_NODMA) - { - return 1; - } + { + return 1; + } if (chan < 0) return 0; @@ -1104,10 +1017,9 @@ return count; } -static void -finish_output_interrupt(int dev, struct dma_buffparms *dmap) +static void finish_output_interrupt(int dev, struct dma_buffparms *dmap) { - unsigned long flags; + unsigned long flags; if (dmap->audio_callback != NULL) dmap->audio_callback(dev, dmap->callback_parm); @@ -1115,21 +1027,18 @@ save_flags(flags); cli(); if ((out_sleep_flag[dev].opts & WK_SLEEP)) - { - { - out_sleep_flag[dev].opts = WK_WAKEUP; - wake_up(&out_sleeper[dev]); - }; - } + { + out_sleep_flag[dev].opts = WK_WAKEUP; + wake_up(&out_sleeper[dev]); + } restore_flags(flags); } -static void -do_outputintr(int dev, int dummy) +static void do_outputintr(int dev, int dummy) { - unsigned long flags; + unsigned long flags; struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; - int this_fragment; + int this_fragment; #ifdef OS_DMA_INTR if (audio_devs[dev]->dmap_out->dma >= 0) @@ -1137,35 +1046,35 @@ #endif if (dmap->raw_buf == NULL) - { - printk("Sound: Fatal error. Audio interrupt (%d) after freeing buffers.\n", dev); - return; - } + { + printk(KERN_ERR "Sound: Error. Audio interrupt (%d) after freeing buffers.\n", dev); + return; + } if (dmap->mapping_flags & DMA_MAP_MAPPED) /* Virtual memory mapped access */ - { - /* mmapped access */ - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - if (dmap->qhead == 0) /* Wrapped */ - { - dmap->byte_counter += dmap->bytes_in_use; - if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */ - { - long decr = dmap->byte_counter; - - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - } - dmap->qlen++; /* Yes increment it (don't decrement) */ - if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) - dmap->flags &= ~DMA_ACTIVE; - dmap->counts[dmap->qhead] = dmap->fragment_size; - - DMAbuf_launch_output(dev, dmap); - finish_output_interrupt(dev, dmap); - return; - } + { + /* mmapped access */ + dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; + if (dmap->qhead == 0) /* Wrapped */ + { + dmap->byte_counter += dmap->bytes_in_use; + if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */ + { + long decr = dmap->byte_counter; + + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + decr -= dmap->byte_counter; + dmap->user_counter -= decr; + } + } + dmap->qlen++; /* Yes increment it (don't decrement) */ + if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) + dmap->flags &= ~DMA_ACTIVE; + dmap->counts[dmap->qhead] = dmap->fragment_size; + + DMAbuf_launch_output(dev, dmap); + finish_output_interrupt(dev, dmap); + return; + } save_flags(flags); cli(); @@ -1174,35 +1083,34 @@ dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; if (dmap->qhead == 0) /* Wrapped */ - { - dmap->byte_counter += dmap->bytes_in_use; - if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */ - { - long decr = dmap->byte_counter; - - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - } + { + dmap->byte_counter += dmap->bytes_in_use; + if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */ + { + long decr = dmap->byte_counter; + + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + decr -= dmap->byte_counter; + dmap->user_counter -= decr; + } + } if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) dmap->flags &= ~DMA_ACTIVE; while (dmap->qlen <= 0) - { - dmap->underrun_count++; - - dmap->qlen++; - if (dmap->flags & DMA_DIRTY && dmap->applic_profile != APF_CPUINTENS) - { - dmap->flags &= ~DMA_DIRTY; - memset(audio_devs[dev]->dmap_out->raw_buf, - audio_devs[dev]->dmap_out->neutral_byte, - audio_devs[dev]->dmap_out->buffsize); - } - dmap->user_counter += dmap->fragment_size; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - } + { + dmap->underrun_count++; + dmap->qlen++; + if (dmap->flags & DMA_DIRTY && dmap->applic_profile != APF_CPUINTENS) + { + dmap->flags &= ~DMA_DIRTY; + memset(audio_devs[dev]->dmap_out->raw_buf, + audio_devs[dev]->dmap_out->neutral_byte, + audio_devs[dev]->dmap_out->buffsize); + } + dmap->user_counter += dmap->fragment_size; + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + } if (dmap->qlen > 0) DMAbuf_launch_output(dev, dmap); @@ -1211,43 +1119,37 @@ finish_output_interrupt(dev, dmap); } -void -DMAbuf_outputintr(int dev, int notify_only) +void DMAbuf_outputintr(int dev, int notify_only) { - unsigned long flags; + unsigned long flags; struct dma_buffparms *dmap = audio_devs[dev]->dmap_out; save_flags(flags); cli(); if (!(dmap->flags & DMA_NODMA)) - { - int chan = dmap->dma, pos, n; - - clear_dma_ff(chan); - disable_dma(dmap->dma); - pos = dmap->bytes_in_use - get_dma_residue(chan); - enable_dma(dmap->dma); - - pos = pos / dmap->fragment_size; /* Actual qhead */ - if (pos < 0 || pos >= dmap->nbufs) - pos = 0; - - n = 0; - while (dmap->qhead != pos && n++ < dmap->nbufs) - { - do_outputintr(dev, notify_only); - } - } else + { + int chan = dmap->dma, pos, n; + clear_dma_ff(chan); + disable_dma(dmap->dma); + pos = dmap->bytes_in_use - get_dma_residue(chan); + enable_dma(dmap->dma); + pos = pos / dmap->fragment_size; /* Actual qhead */ + if (pos < 0 || pos >= dmap->nbufs) + pos = 0; + n = 0; + while (dmap->qhead != pos && n++ < dmap->nbufs) + do_outputintr(dev, notify_only); + } + else do_outputintr(dev, notify_only); restore_flags(flags); } -static void -do_inputintr(int dev) +static void do_inputintr(int dev) { struct dma_buffparms *dmap = audio_devs[dev]->dmap_in; - unsigned long flags; + unsigned long flags; #ifdef OS_DMA_INTR if (audio_devs[dev]->dmap_in->dma >= 0) @@ -1255,302 +1157,280 @@ #endif if (dmap->raw_buf == NULL) - { - printk("Sound: Fatal error. Audio interrupt after freeing buffers.\n"); - return; - } + { + printk(KERN_ERR "Sound: Fatal error. Audio interrupt after freeing buffers.\n"); + return; + } if (dmap->mapping_flags & DMA_MAP_MAPPED) - { - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - if (dmap->qtail == 0) /* Wrapped */ - { - dmap->byte_counter += dmap->bytes_in_use; - if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */ - { - long decr = dmap->byte_counter; - - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - } - dmap->qlen++; - - if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) - { - if (dmap->needs_reorg) - reorganize_buffers(dev, dmap, 0); - local_start_dma(dev, dmap->raw_buf_phys, dmap->bytes_in_use, - DMA_MODE_READ); - audio_devs[dev]->d->start_input(dev, dmap->raw_buf_phys + - dmap->qtail * dmap->fragment_size, - dmap->fragment_size, 1); - if (audio_devs[dev]->d->trigger) - audio_devs[dev]->d->trigger(dev, - audio_devs[dev]->enable_bits * audio_devs[dev]->go); - } - dmap->flags |= DMA_ACTIVE; - } else if (dmap->qlen >= (dmap->nbufs - 1)) - { - printk("Sound: Recording overrun\n"); - dmap->underrun_count++; - - /* Just throw away the oldest fragment but keep the engine running */ - dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - } else if (dmap->qlen >= 0 && dmap->qlen < dmap->nbufs) - { - dmap->qlen++; - dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; - if (dmap->qtail == 0) /* Wrapped */ - { - dmap->byte_counter += dmap->bytes_in_use; - if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */ - { - long decr = dmap->byte_counter; - - dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; - decr -= dmap->byte_counter; - dmap->user_counter -= decr; - } - } - } + { + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + if (dmap->qtail == 0) /* Wrapped */ + { + dmap->byte_counter += dmap->bytes_in_use; + if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */ + { + long decr = dmap->byte_counter; + + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + decr -= dmap->byte_counter; + dmap->user_counter -= decr; + } + } + dmap->qlen++; + + if (!(audio_devs[dev]->flags & DMA_AUTOMODE)) + { + if (dmap->needs_reorg) + reorganize_buffers(dev, dmap, 0); + local_start_dma(dev, dmap->raw_buf_phys, dmap->bytes_in_use,DMA_MODE_READ); + audio_devs[dev]->d->start_input(dev, dmap->raw_buf_phys + + dmap->qtail * dmap->fragment_size, + dmap->fragment_size, 1); + if (audio_devs[dev]->d->trigger) + audio_devs[dev]->d->trigger(dev,audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } + dmap->flags |= DMA_ACTIVE; + } + else if (dmap->qlen >= (dmap->nbufs - 1)) + { + printk(KERN_WARNING "Sound: Recording overrun\n"); + dmap->underrun_count++; + + /* Just throw away the oldest fragment but keep the engine running */ + dmap->qhead = (dmap->qhead + 1) % dmap->nbufs; + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + } + else if (dmap->qlen >= 0 && dmap->qlen < dmap->nbufs) + { + dmap->qlen++; + dmap->qtail = (dmap->qtail + 1) % dmap->nbufs; + if (dmap->qtail == 0) /* Wrapped */ + { + dmap->byte_counter += dmap->bytes_in_use; + if (dmap->byte_counter >= dmap->max_byte_counter) /* Overflow */ + { + long decr = dmap->byte_counter; + + dmap->byte_counter = (dmap->byte_counter % dmap->bytes_in_use) + dmap->bytes_in_use; + decr -= dmap->byte_counter; + dmap->user_counter -= decr; + } + } + } if (!(audio_devs[dev]->flags & DMA_AUTOMODE) || dmap->flags & DMA_NODMA) - { - local_start_dma(dev, dmap->raw_buf_phys, dmap->bytes_in_use, - DMA_MODE_READ); - audio_devs[dev]->d->start_input(dev, dmap->raw_buf_phys + - dmap->qtail * dmap->fragment_size, - dmap->fragment_size, 1); - if (audio_devs[dev]->d->trigger) - audio_devs[dev]->d->trigger(dev, - audio_devs[dev]->enable_bits * audio_devs[dev]->go); - } + { + local_start_dma(dev, dmap->raw_buf_phys, dmap->bytes_in_use, DMA_MODE_READ); + audio_devs[dev]->d->start_input(dev, dmap->raw_buf_phys + dmap->qtail * dmap->fragment_size, dmap->fragment_size, 1); + if (audio_devs[dev]->d->trigger) + audio_devs[dev]->d->trigger(dev,audio_devs[dev]->enable_bits * audio_devs[dev]->go); + } dmap->flags |= DMA_ACTIVE; save_flags(flags); cli(); if (dmap->qlen > 0) + { if ((in_sleep_flag[dev].opts & WK_SLEEP)) - { - { - in_sleep_flag[dev].opts = WK_WAKEUP; - wake_up(&in_sleeper[dev]); - }; - } + { + in_sleep_flag[dev].opts = WK_WAKEUP; + wake_up(&in_sleeper[dev]); + } + } restore_flags(flags); } -void -DMAbuf_inputintr(int dev) +void DMAbuf_inputintr(int dev) { struct dma_buffparms *dmap = audio_devs[dev]->dmap_in; - unsigned long flags; + unsigned long flags; save_flags(flags); cli(); if (!(dmap->flags & DMA_NODMA)) - { - int chan = dmap->dma, pos, n; + { + int chan = dmap->dma, pos, n; - clear_dma_ff(chan); - disable_dma(dmap->dma); - pos = dmap->bytes_in_use - get_dma_residue(chan); - enable_dma(dmap->dma); - - pos = pos / dmap->fragment_size; /* Actual qhead */ - if (pos < 0 || pos >= dmap->nbufs) - pos = 0; - - n = 0; - while (dmap->qtail != pos && ++n < dmap->nbufs) - { - do_inputintr(dev); - } - } else + clear_dma_ff(chan); + disable_dma(dmap->dma); + pos = dmap->bytes_in_use - get_dma_residue(chan); + enable_dma(dmap->dma); + + pos = pos / dmap->fragment_size; /* Actual qhead */ + if (pos < 0 || pos >= dmap->nbufs) + pos = 0; + + n = 0; + while (dmap->qtail != pos && ++n < dmap->nbufs) + do_inputintr(dev); + } + else do_inputintr(dev); restore_flags(flags); } -int -DMAbuf_open_dma(int dev) +int DMAbuf_open_dma(int dev) { -/* - * NOTE! This routine opens only the primary DMA channel (output). - */ + /* + * NOTE! This routine opens only the primary DMA channel (output). + */ - int chan = audio_devs[dev]->dmap_out->dma; - int err; + int chan = audio_devs[dev]->dmap_out->dma; + int err; if ((err = open_dmap(dev, OPEN_READWRITE, audio_devs[dev]->dmap_out, chan)) < 0) - { - return -EBUSY; - } + return -EBUSY; dma_init_buffers(dev, audio_devs[dev]->dmap_out); out_sleep_flag[dev].opts = WK_NONE; audio_devs[dev]->dmap_out->flags |= DMA_ALLOC_DONE; audio_devs[dev]->dmap_out->fragment_size = audio_devs[dev]->dmap_out->buffsize; if (chan >= 0) - { - unsigned long flags; + { + unsigned long flags; - save_flags(flags); - cli(); - disable_dma(audio_devs[dev]->dmap_out->dma); - clear_dma_ff(chan); - restore_flags(flags); - } + save_flags(flags); + cli(); + disable_dma(audio_devs[dev]->dmap_out->dma); + clear_dma_ff(chan); + restore_flags(flags); + } return 0; } -void -DMAbuf_close_dma(int dev) +void DMAbuf_close_dma(int dev) { close_dmap(dev, audio_devs[dev]->dmap_out, audio_devs[dev]->dmap_out->dma); } -void -DMAbuf_init(int dev, int dma1, int dma2) +void DMAbuf_init(int dev, int dma1, int dma2) { /* - * NOTE! This routine could be called several times. + * NOTE! This routine could be called several times. */ if (audio_devs[dev] && audio_devs[dev]->dmap_out == NULL) - { - if (audio_devs[dev]->d == NULL) - panic("OSS: audio_devs[%d]->d == NULL\n", dev); - - if (audio_devs[dev]->parent_dev) - { /* Use DMA map of the parent dev */ - int parent = audio_devs[dev]->parent_dev - 1; - - audio_devs[dev]->dmap_out = audio_devs[parent]->dmap_out; - audio_devs[dev]->dmap_in = audio_devs[parent]->dmap_in; - } else - { - audio_devs[dev]->dmap_out = - audio_devs[dev]->dmap_in = - &dmaps[ndmaps++]; - audio_devs[dev]->dmap_out->dma = dma1; - - if (audio_devs[dev]->flags & DMA_DUPLEX) - { - audio_devs[dev]->dmap_in = - &dmaps[ndmaps++]; - audio_devs[dev]->dmap_in->dma = dma2; - } - } - } + { + if (audio_devs[dev]->d == NULL) + panic("OSS: audio_devs[%d]->d == NULL\n", dev); + + if (audio_devs[dev]->parent_dev) + { /* Use DMA map of the parent dev */ + int parent = audio_devs[dev]->parent_dev - 1; + + audio_devs[dev]->dmap_out = audio_devs[parent]->dmap_out; + audio_devs[dev]->dmap_in = audio_devs[parent]->dmap_in; + } + else + { + audio_devs[dev]->dmap_out = audio_devs[dev]->dmap_in = &dmaps[ndmaps++]; + audio_devs[dev]->dmap_out->dma = dma1; + + if (audio_devs[dev]->flags & DMA_DUPLEX) + { + audio_devs[dev]->dmap_in = &dmaps[ndmaps++]; + audio_devs[dev]->dmap_in->dma = dma2; + } + } + } } -int -DMAbuf_select(int dev, struct fileinfo *file, int sel_type, poll_table * wait) +int DMAbuf_select(int dev, struct fileinfo *file, int sel_type, poll_table * wait) { struct dma_buffparms *dmap; unsigned long flags; switch (sel_type) - { - case SEL_IN: - if (!(audio_devs[dev]->open_mode & OPEN_READ)) - return 0; - - dmap = audio_devs[dev]->dmap_in; - - if (dmap->mapping_flags & DMA_MAP_MAPPED) - { - if (dmap->qlen) - return 1; - - save_flags(flags); - cli(); - - in_sleep_flag[dev].opts = WK_SLEEP; - poll_wait(&in_sleeper[dev], wait); - restore_flags(flags); - return 0; - } - if (dmap->dma_mode != DMODE_INPUT) - { - if (dmap->dma_mode == DMODE_NONE && - audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT && - !dmap->qlen && - audio_devs[dev]->go) - { - unsigned long flags; - - save_flags(flags); - cli(); - DMAbuf_activate_recording(dev, dmap); - restore_flags(flags); - } - return 0; - } - if (!dmap->qlen) - { - save_flags(flags); - cli(); - - in_sleep_flag[dev].opts = WK_SLEEP; - poll_wait(&in_sleeper[dev], wait); - restore_flags(flags); - return 0; - } - return 1; - break; - - case SEL_OUT: - dmap = audio_devs[dev]->dmap_out; - - if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) - return 0; - - if (dmap->mapping_flags & DMA_MAP_MAPPED) - { - if (dmap->qlen) - return 1; - - save_flags(flags); - cli(); - - out_sleep_flag[dev].opts = WK_SLEEP; - poll_wait(&out_sleeper[dev], wait); - restore_flags(flags); - return 0; - } - if (dmap->dma_mode == DMODE_INPUT) - { - return 0; - } - if (dmap->dma_mode == DMODE_NONE) - { - return 1; - } - if (!DMAbuf_space_in_queue(dev)) - { - save_flags(flags); - cli(); - - out_sleep_flag[dev].opts = WK_SLEEP; - poll_wait(&out_sleeper[dev], wait); - restore_flags(flags); - return 0; - } - return 1; - break; - - case SEL_EX: - return 0; - } + { + case SEL_IN: + if (!(audio_devs[dev]->open_mode & OPEN_READ)) + return 0; + dmap = audio_devs[dev]->dmap_in; + + if (dmap->mapping_flags & DMA_MAP_MAPPED) + { + if (dmap->qlen) + return 1; + save_flags(flags); + cli(); + in_sleep_flag[dev].opts = WK_SLEEP; + poll_wait(&in_sleeper[dev], wait); + restore_flags(flags); + return 0; + } + if (dmap->dma_mode != DMODE_INPUT) + { + if (dmap->dma_mode == DMODE_NONE && + audio_devs[dev]->enable_bits & PCM_ENABLE_INPUT && + !dmap->qlen && audio_devs[dev]->go) + { + unsigned long flags; + save_flags(flags); + cli(); + DMAbuf_activate_recording(dev, dmap); + restore_flags(flags); + } + return 0; + } + if (!dmap->qlen) + { + save_flags(flags); + cli(); + + in_sleep_flag[dev].opts = WK_SLEEP; + poll_wait(&in_sleeper[dev], wait); + restore_flags(flags); + return 0; + } + return 1; + + case SEL_OUT: + dmap = audio_devs[dev]->dmap_out; + + if (!(audio_devs[dev]->open_mode & OPEN_WRITE)) + return 0; + + if (dmap->mapping_flags & DMA_MAP_MAPPED) + { + if (dmap->qlen) + return 1; + + save_flags(flags); + cli(); + + out_sleep_flag[dev].opts = WK_SLEEP; + poll_wait(&out_sleeper[dev], wait); + restore_flags(flags); + return 0; + } + + if (dmap->dma_mode == DMODE_INPUT) + return 0; + + if (dmap->dma_mode == DMODE_NONE) + return 1; + + if (!DMAbuf_space_in_queue(dev)) + { + save_flags(flags); + cli(); + + out_sleep_flag[dev].opts = WK_SLEEP; + poll_wait(&out_sleeper[dev], wait); + restore_flags(flags); + return 0; + } + return 1; + break; + + case SEL_EX: + return 0; + } return 0; } -void -DMAbuf_deinit(int dev) +void DMAbuf_deinit(int dev) { /* This routine is called when driver is being unloaded */ #ifdef RUNTIME_DMA_ALLOC diff -u --recursive --new-file v2.1.79/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c --- v2.1.79/linux/drivers/sound/gus_wave.c Tue Jan 6 09:37:35 1998 +++ linux/drivers/sound/gus_wave.c Tue Jan 20 16:44:57 1998 @@ -3260,7 +3260,7 @@ if (hw_config->slots[4] != -1) sound_unload_audiodev(hw_config->slots[4]); if (hw_config->slots[5] != -1) - sound_unload_mixerdev(hw_config->slots[4]); + sound_unload_mixerdev(hw_config->slots[5]); if(samples) vfree(samples); diff -u --recursive --new-file v2.1.79/linux/drivers/sound/pas2_card.c linux/drivers/sound/pas2_card.c --- v2.1.79/linux/drivers/sound/pas2_card.c Mon Jan 12 22:09:16 1998 +++ linux/drivers/sound/pas2_card.c Tue Jan 20 16:44:57 1998 @@ -56,7 +56,7 @@ extern void mix_write(unsigned char data, int ioaddr); -unsigned charpas_read(int ioaddr) +unsigned char pas_read(int ioaddr) { return inb(ioaddr ^ translate_code); } diff -u --recursive --new-file v2.1.79/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v2.1.79/linux/drivers/sound/soundcard.c Fri Jan 2 14:37:02 1998 +++ linux/drivers/sound/soundcard.c Tue Jan 20 16:44:57 1998 @@ -12,7 +12,8 @@ */ /* * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) - * integrated sound_switch.c and made /proc/sound (equals to /dev/sndstat, + * integrated sound_switch.c + * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat, * which should disappear in the near future) */ #include @@ -1100,7 +1101,8 @@ dmap->buffsize = PAGE_SIZE * (1 << sz); - if ((start_addr = (char *) __get_free_pages(GFP_ATOMIC, sz, MAX_DMA_ADDRESS)) == NULL) + start_addr = (char *) __get_free_pages(GFP_ATOMIC | GFP_DMA, sz); + if (start_addr == NULL) dmap->buffsize /= 2; } diff -u --recursive --new-file v2.1.79/linux/fs/Config.in linux/fs/Config.in --- v2.1.79/linux/fs/Config.in Tue Jan 6 09:37:35 1998 +++ linux/fs/Config.in Tue Jan 20 16:44:57 1998 @@ -69,6 +69,9 @@ bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL bool 'Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION fi +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'ADFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_ADFS_FS +fi bool 'Macintosh partition map support' CONFIG_MAC_PARTITION endmenu diff -u --recursive --new-file v2.1.79/linux/fs/Makefile linux/fs/Makefile --- v2.1.79/linux/fs/Makefile Tue Jan 6 09:37:35 1998 +++ linux/fs/Makefile Tue Jan 20 16:44:57 1998 @@ -218,6 +218,14 @@ endif endif +ifeq ($(CONFIG_ADFS_FS),y) +SUB_DIRS += adfs +else + ifeq ($(CONFIG_ADFS_FS),m) + MOD_SUB_DIRS += adfs + endif +endif + ifeq ($(CONFIG_BINFMT_ELF),y) BINFMTS += binfmt_elf.o else diff -u --recursive --new-file v2.1.79/linux/fs/adfs/Makefile linux/fs/adfs/Makefile --- v2.1.79/linux/fs/adfs/Makefile Wed Dec 31 16:00:00 1969 +++ linux/fs/adfs/Makefile Tue Jan 20 16:44:58 1998 @@ -0,0 +1,14 @@ +# +# Makefile for the linux adfs-filesystem routines. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := adfs.o +O_OBJS := dir.o file.o inode.o map.o namei.o super.o +M_OBJS := $(O_TARGET) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.79/linux/fs/adfs/dir.c linux/fs/adfs/dir.c --- v2.1.79/linux/fs/adfs/dir.c Wed Dec 31 16:00:00 1969 +++ linux/fs/adfs/dir.c Tue Jan 20 16:44:58 1998 @@ -0,0 +1,328 @@ +/* + * linux/fs/adfs/dir.c + * + * Copyright (C) 1997 Russell King + */ + +#include +#include +#include +#include +#include + +static ssize_t adfs_dirread (struct file *filp, char *buf, + size_t siz, loff_t *ppos) +{ + return -EISDIR; +} + +static int adfs_readdir (struct file *, void *, filldir_t); + +static struct file_operations adfs_dir_operations = { + NULL, /* lseek - default */ + adfs_dirread, /* read */ + NULL, /* write - bad */ + adfs_readdir, /* readdir */ + NULL, /* select - default */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* no special open code */ + NULL, /* no special release code */ + file_fsync, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL /* revalidate */ +}; + +/* + * directories can handle most operations... + */ +struct inode_operations adfs_dir_inode_operations = { + &adfs_dir_operations, /* default directory file-ops */ + NULL, /* create */ + adfs_lookup, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* read link */ + NULL, /* follow link */ + NULL, /* read page */ + NULL, /* write page */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL, /* permission */ + NULL /* smap */ +}; + +unsigned int adfs_val (unsigned char *p, int len) +{ + unsigned int val = 0; + + switch (len) { + case 4: + val |= p[3] << 24; + case 3: + val |= p[2] << 16; + case 2: + val |= p[1] << 8; + default: + val |= p[0]; + } + return val; +} + +static unsigned int adfs_time (unsigned int load, unsigned int exec) +{ + unsigned int high, low; + + high = ((load << 24) | (exec >> 8)) - 0x336e996a; + low = exec & 255; + + /* 65537 = h256,l1 + * (h256 % 100) = 56 h256 / 100 = 2 + * 56 << 8 = 14336 2 * 256 = 512 + * + l1 = 14337 + * / 100 = 143 + * + 512 = 655 + */ + return (((high % 100) << 8) + low) / 100 + (high / 100 << 8); +} + +int adfs_readname (char *buf, char *ptr, int maxlen) +{ + int size = 0; + while (*ptr >= ' ' && maxlen--) { + switch (*ptr) { + case '/': + *buf++ = '.'; + break; + default: + *buf++ = *ptr; + break; + } + ptr++; + size ++; + } + *buf = '\0'; + return size; +} + +int adfs_dir_read_parent (struct inode *inode, struct buffer_head **bhp) +{ + struct super_block *sb; + int i, size; + + if (!inode) + return 0; + + sb = inode->i_sb; + + size = 2048 >> sb->s_blocksize_bits; + + for (i = 0; i < size; i++) { + int block; + + block = adfs_parent_bmap (inode, i); + if (block) + bhp[i] = bread (sb->s_dev, block, sb->s_blocksize); + else + adfs_error (sb, "adfs_dir_read_parent", + "directory %lu with a hole at offset %d", inode->i_ino, i); + if (!block || !bhp[i]) { + int j; + for (j = i - 1; j >= 0; j--) + brelse (bhp[j]); + return 0; + } + } + return i; +} + +int adfs_dir_read (struct inode *inode, struct buffer_head **bhp) +{ + struct super_block *sb; + int i, size; + + if (!inode || !S_ISDIR(inode->i_mode)) + return 0; + + sb = inode->i_sb; + + size = inode->i_size >> sb->s_blocksize_bits; + + for (i = 0; i < size; i++) { + int block; + + block = adfs_bmap (inode, i); + if (block) + bhp[i] = bread (sb->s_dev, block, sb->s_blocksize); + else + adfs_error (sb, "adfs_dir_read", + "directory %lX,%lX with a hole at offset %d", + inode->i_ino, inode->u.adfs_i.file_id, i); + if (!block || !bhp[i]) { + int j; + for (j = i - 1; j >= 0; j--) + brelse (bhp[j]); + return 0; + } + } + return i; +} + +int adfs_dir_check (struct inode *inode, struct buffer_head **bhp, int buffers, union adfs_dirtail *dtp) +{ + struct adfs_dirheader dh; + union adfs_dirtail dt; + + memcpy (&dh, bhp[0]->b_data, sizeof (dh)); + memcpy (&dt, bhp[3]->b_data + 471, sizeof(dt)); + + if (memcmp (&dh.startmasseq, &dt.new.endmasseq, 5) || + (memcmp (&dh.startname, "Nick", 4) && + memcmp (&dh.startname, "Hugo", 4))) { + adfs_error (inode->i_sb, "adfs_check_dir", + "corrupted directory inode %lX,%lX", + inode->i_ino, inode->u.adfs_i.file_id); + return 1; + } + if (dtp) + *dtp = dt; + return 0; +} + +void adfs_dir_free (struct buffer_head **bhp, int buffers) +{ + int i; + + for (i = buffers - 1; i >= 0; i--) + brelse (bhp[i]); +} + +int adfs_dir_get (struct super_block *sb, struct buffer_head **bhp, + int buffers, int pos, unsigned long parent_object_id, + struct adfs_idir_entry *ide) +{ + struct adfs_direntry de; + int thissize, buffer, offset; + + offset = pos & (sb->s_blocksize - 1); + buffer = pos >> sb->s_blocksize_bits; + + if (buffer > buffers) + return 0; + + thissize = sb->s_blocksize - offset; + if (thissize > 26) + thissize = 26; + + memcpy (&de, bhp[buffer]->b_data + offset, thissize); + if (thissize != 26) + memcpy (((char *)&de) + thissize, bhp[buffer + 1]->b_data, 26 - thissize); + + if (!de.dirobname[0]) + return 0; + + ide->name_len = adfs_readname (ide->name, de.dirobname, ADFS_NAME_LEN); + ide->inode_no = adfs_inode_generate (parent_object_id, pos); + ide->file_id = adfs_val (de.dirinddiscadd, 3); + ide->size = adfs_val (de.dirlen, 4); + ide->mode = de.newdiratts; + ide->mtime = adfs_time (adfs_val (de.dirload, 4), adfs_val (de.direxec, 4)); + ide->filetype = (adfs_val (de.dirload, 4) >> 8) & 0xfff; + return 1; +} + +int adfs_dir_find_entry (struct super_block *sb, struct buffer_head **bhp, + int buffers, unsigned int pos, + struct adfs_idir_entry *ide) +{ + struct adfs_direntry de; + int offset, buffer, thissize; + + offset = pos & (sb->s_blocksize - 1); + buffer = pos >> sb->s_blocksize_bits; + + if (buffer > buffers) + return 0; + + thissize = sb->s_blocksize - offset; + if (thissize > 26) + thissize = 26; + + memcpy (&de, bhp[buffer]->b_data + offset, thissize); + if (thissize != 26) + memcpy (((char *)&de) + thissize, bhp[buffer + 1]->b_data, 26 - thissize); + + if (!de.dirobname[0]) + return 0; + + ide->name_len = adfs_readname (ide->name, de.dirobname, ADFS_NAME_LEN); + ide->size = adfs_val (de.dirlen, 4); + ide->mode = de.newdiratts; + ide->file_id = adfs_val (de.dirinddiscadd, 3); + ide->mtime = adfs_time (adfs_val (de.dirload, 4), adfs_val (de.direxec, 4)); + ide->filetype = (adfs_val (de.dirload, 4) >> 8) & 0xfff; + return 1; +} + +static int adfs_readdir (struct file *filp, void *dirent, filldir_t filldir) +{ + struct inode *inode = filp->f_dentry->d_inode; + struct super_block *sb; + struct buffer_head *bh[4]; + union adfs_dirtail dt; + unsigned long parent_object_id, dir_object_id; + int buffers, pos; + + if (!inode || !S_ISDIR(inode->i_mode)) + return -EBADF; + sb = inode->i_sb; + + if (filp->f_pos > ADFS_NUM_DIR_ENTRIES + 2) + return -ENOENT; + + if (!(buffers = adfs_dir_read (inode, bh))) { + adfs_error (sb, "adfs_readdir", "unable to read directory"); + return -EINVAL; + } + + if (adfs_dir_check (inode, bh, buffers, &dt)) { + adfs_dir_free (bh, buffers); + return -ENOENT; + } + + parent_object_id = adfs_val (dt.new.dirparent, 3); + dir_object_id = adfs_inode_objid (inode); + + if (filp->f_pos < 2) { + if (filp->f_pos < 1) { + if (filldir (dirent, ".", 1, 0, inode->i_ino) < 0) + return 0; + filp->f_pos ++; + } + if (filldir (dirent, "..", 2, 1, + adfs_inode_generate (parent_object_id, 0)) < 0) + return 0; + filp->f_pos ++; + } + + pos = 5 + (filp->f_pos - 2) * 26; + while (filp->f_pos < 79) { + struct adfs_idir_entry ide; + + if (!adfs_dir_get (sb, bh, buffers, pos, dir_object_id, &ide)) + break; + + if (filldir (dirent, ide.name, ide.name_len, filp->f_pos, ide.inode_no) < 0) + return 0; + filp->f_pos ++; + pos += 26; + } + adfs_dir_free (bh, buffers); + return 0; +} diff -u --recursive --new-file v2.1.79/linux/fs/adfs/file.c linux/fs/adfs/file.c --- v2.1.79/linux/fs/adfs/file.c Wed Dec 31 16:00:00 1969 +++ linux/fs/adfs/file.c Tue Jan 20 16:44:58 1998 @@ -0,0 +1,69 @@ +/* + * linux/fs/adfs/file.c + * + * Copyright (C) 1997 Russell King + * from: + * + * linux/fs/ext2/file.c + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * from + * + * linux/fs/minix/file.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * adfs regular file handling primitives + */ + +#include +#include +#include +#include +#include +#include + +/* + * We have mostly NULL's here: the current defaults are ok for + * the adfs filesystem. + */ +static struct file_operations adfs_file_operations = { + NULL, /* lseek - default */ + generic_file_read, /* read */ + NULL, /* write */ + NULL, /* readdir - bad */ + NULL, /* select - default */ + NULL, /* ioctl */ + generic_file_mmap, /* mmap */ + NULL, /* open - not special */ + NULL, /* release */ + file_fsync, /* fsync */ + NULL, /* fasync */ + NULL, /* check_media_change */ + NULL /* revalidate */ +}; + +struct inode_operations adfs_file_inode_operations = { + &adfs_file_operations, /* default file operations */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + generic_readpage, /* readpage */ + NULL, /* writepage */ + adfs_bmap, /* bmap */ + NULL, /* truncate */ + NULL, /* permission */ + NULL /* smap */ +}; diff -u --recursive --new-file v2.1.79/linux/fs/adfs/inode.c linux/fs/adfs/inode.c --- v2.1.79/linux/fs/adfs/inode.c Wed Dec 31 16:00:00 1969 +++ linux/fs/adfs/inode.c Tue Jan 20 16:44:58 1998 @@ -0,0 +1,216 @@ +/* + * linux/fs/adfs/inode.c + * + * Copyright (C) 1997 Russell King + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Old Inode numbers: + * bit 30 - 16 FragID of parent object + * bit 15 0 1 + * bit 14 - 0 FragID of object Offset into parent FragID + * + * New Inode numbers: + * Inode = Frag ID of parent (14) + Frag Offset (8) + (index into directory + 1)(8) + */ +#define inode_frag(ino) ((ino) >> 8) +#define inode_idx(ino) ((ino) & 0xff) +#define inode_dirindex(idx) (((idx) & 0xff) * 26 - 21) + +#define frag_id(x) (((x) >> 8) & 0x7fff) +#define off(x) (((x) & 0xff) ? ((x) & 0xff) - 1 : 0) + +static inline int adfs_inode_validate_no (struct super_block *sb, unsigned int inode_no) +{ + unsigned long max_frag_id; + + max_frag_id = sb->u.adfs_sb.s_map_size * sb->u.adfs_sb.s_ids_per_zone; + + return (inode_no & 0x800000ff) || + (frag_id (inode_frag (inode_no)) > max_frag_id) || + (frag_id (inode_frag (inode_no)) < 2); +} + +int adfs_inode_validate (struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + + return adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00) || + adfs_inode_validate_no (sb, inode->u.adfs_i.file_id << 8); +} + +unsigned long adfs_inode_generate (unsigned long parent_id, int diridx) +{ + if (!parent_id) + return -1; + + if (diridx) + diridx = (diridx + 21) / 26; + + return (parent_id << 8) | diridx; +} + +unsigned long adfs_inode_objid (struct inode *inode) +{ + if (adfs_inode_validate (inode)) { + adfs_error (inode->i_sb, "adfs_inode_objid", + "bad inode number: %lu (%X,%X)", + inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id); + return 0; + } + + return inode->u.adfs_i.file_id; +} + +unsigned int adfs_bmap (struct inode *inode, int block) +{ + struct super_block *sb = inode->i_sb; + unsigned int blk; + + if (adfs_inode_validate (inode)) { + adfs_error (sb, "adfs_bmap", + "bad inode number: %lu (%X,%X)", + inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id); + return 0; + } + + if (frag_id(inode->u.adfs_i.file_id) == ADFS_ROOT_FRAG) + blk = sb->u.adfs_sb.s_map_block + off(inode_frag (inode->i_ino)) + block; + else + blk = adfs_map_lookup (sb, frag_id(inode->u.adfs_i.file_id), + off (inode->u.adfs_i.file_id) + block); + return blk; +} + +unsigned int adfs_parent_bmap (struct inode *inode, int block) +{ + struct super_block *sb = inode->i_sb; + unsigned int blk, fragment; + + if (adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00)) { + adfs_error (sb, "adfs_parent_bmap", + "bad inode number: %lu (%X,%X)", + inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id); + return 0; + } + + fragment = inode_frag (inode->i_ino); + if (frag_id (fragment) == ADFS_ROOT_FRAG) + blk = sb->u.adfs_sb.s_map_block + off (fragment) + block; + else + blk = adfs_map_lookup (sb, frag_id (fragment), off (fragment) + block); + return blk; +} + +static int adfs_atts2mode (unsigned char mode, unsigned int filetype) +{ + int omode = 0; + + if (filetype == 0xfc0 /* LinkFS */) { + omode = S_IFLNK|S_IRUSR|S_IWUSR|S_IXUSR| + S_IRGRP|S_IWGRP|S_IXGRP| + S_IROTH|S_IWOTH|S_IXOTH; + } else { + if (mode & ADFS_NDA_DIRECTORY) + omode |= S_IFDIR|S_IRUSR|S_IXUSR|S_IXGRP|S_IXOTH; + else + omode |= S_IFREG; + if (mode & ADFS_NDA_OWNER_READ) { + omode |= S_IRUSR; + if (filetype == 0xfe6 /* UnixExec */) + omode |= S_IXUSR; + } + if (mode & ADFS_NDA_OWNER_WRITE) + omode |= S_IWUSR; + if (mode & ADFS_NDA_PUBLIC_READ) { + omode |= S_IRGRP | S_IROTH; + if (filetype == 0xfe6) + omode |= S_IXGRP | S_IXOTH; + } + if (mode & ADFS_NDA_PUBLIC_WRITE) + omode |= S_IWGRP | S_IWOTH; + } + return omode; +} + +void adfs_read_inode (struct inode *inode) +{ + struct super_block *sb; + struct buffer_head *bh[4]; + struct adfs_idir_entry ide; + int buffers; + + sb = inode->i_sb; + inode->i_uid = 0; + inode->i_gid = 0; + inode->i_version = ++event; + + if (adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00)) { + adfs_error (sb, "adfs_read_inode", + "bad inode number: %lu", inode->i_ino); + goto bad; + } + + if (frag_id(inode_frag (inode->i_ino)) == ADFS_ROOT_FRAG && + inode_idx (inode->i_ino) == 0) { + /* root dir */ + inode->i_mode = S_IRWXUGO | S_IFDIR; + inode->i_nlink = 2; + inode->i_size = ADFS_NEWDIR_SIZE; + inode->i_blksize = PAGE_SIZE; + inode->i_blocks = inode->i_size / sb->s_blocksize; + inode->i_mtime = + inode->i_atime = + inode->i_ctime = 0; + inode->u.adfs_i.file_id = inode_frag (inode->i_ino); + } else { + if (!(buffers = adfs_dir_read_parent (inode, bh))) + goto bad; + + if (adfs_dir_check (inode, bh, buffers, NULL)) { + adfs_dir_free (bh, buffers); + goto bad; + } + + if (!adfs_dir_find_entry (sb, bh, buffers, inode_dirindex (inode->i_ino), &ide)) { + adfs_dir_free (bh, buffers); + goto bad; + } + adfs_dir_free (bh, buffers); + inode->i_mode = adfs_atts2mode (ide.mode, ide.filetype); + inode->i_nlink = 2; + inode->i_size = ide.size; + inode->i_blksize = PAGE_SIZE; + inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; + inode->i_mtime = + inode->i_atime = + inode->i_ctime = ide.mtime; + inode->u.adfs_i.file_id = ide.file_id; + } + + if (S_ISDIR(inode->i_mode)) + inode->i_op = &adfs_dir_inode_operations; + else if (S_ISREG(inode->i_mode)) + inode->i_op = &adfs_file_inode_operations; + return; + +bad: + inode->i_mode = 0; + inode->i_nlink = 1; + inode->i_size = 0; + inode->i_blksize = 0; + inode->i_blocks = 0; + inode->i_mtime = + inode->i_atime = + inode->i_ctime = 0; + inode->i_op = NULL; +} diff -u --recursive --new-file v2.1.79/linux/fs/adfs/map.c linux/fs/adfs/map.c --- v2.1.79/linux/fs/adfs/map.c Wed Dec 31 16:00:00 1969 +++ linux/fs/adfs/map.c Tue Jan 20 16:44:58 1998 @@ -0,0 +1,108 @@ +/* + * linux/fs/adfs/map.c + * + * Copyright (C) 1997 Russell King + */ + +#include +#include +#include + +static inline unsigned int +adfs_convert_map_to_sector (const struct super_block *sb, unsigned int mapoff) +{ + if (sb->u.adfs_sb.s_map2blk >= 0) + mapoff <<= sb->u.adfs_sb.s_map2blk; + else + mapoff >>= -sb->u.adfs_sb.s_map2blk; + return mapoff; +} + +static inline unsigned int +adfs_convert_sector_to_map (const struct super_block *sb, unsigned int secoff) +{ + if (sb->u.adfs_sb.s_map2blk >= 0) + secoff >>= sb->u.adfs_sb.s_map2blk; + else + secoff <<= -sb->u.adfs_sb.s_map2blk; + return secoff; +} + +static int lookup_zone (struct super_block *sb, int zone, int frag_id, int *offset) +{ + unsigned int mapptr, idlen, mapsize; + unsigned long *map; + + map = ((unsigned long *)sb->u.adfs_sb.s_map[zone]->b_data) + 1; + zone = + mapptr = zone == 0 ? (ADFS_DR_SIZE << 3) : 0; + idlen = sb->u.adfs_sb.s_idlen; + mapsize = sb->u.adfs_sb.s_zonesize; + + do { + unsigned long v1, v2; + unsigned int start; + + v1 = map[mapptr>>5]; + v2 = map[(mapptr>>5)+1]; + + v1 = (v1 >> (mapptr & 31)) | (v2 << (32 - (mapptr & 31))); + start = mapptr; + mapptr += idlen; + + v2 = map[mapptr >> 5] >> (mapptr & 31); + if (!v2) { + mapptr = (mapptr + 32) & ~31; + for (; (v2 = map[mapptr >> 5]) == 0 && mapptr < mapsize; mapptr += 32); + } + for (; (v2 & 255) == 0; v2 >>= 8, mapptr += 8); + for (; (v2 & 1) == 0; v2 >>= 1, mapptr += 1); + mapptr += 1; + + if ((v1 & ((1 << idlen) - 1)) == frag_id) { + int length = mapptr - start; + if (*offset >= length) + *offset -= length; + else + return start + *offset - zone; + } + } while (mapptr < mapsize); + return -1; +} + +int adfs_map_lookup (struct super_block *sb, int frag_id, int offset) +{ + unsigned int start_zone, zone, max_zone, mapoff, secoff; + + zone = start_zone = frag_id / sb->u.adfs_sb.s_ids_per_zone; + max_zone = sb->u.adfs_sb.s_map_size; + + if (start_zone >= max_zone) { + adfs_error (sb, "adfs_map_lookup", "fragment %X is invalid (zone = %d, max = %d)", + frag_id, start_zone, max_zone); + return 0; + } + + /* Convert sector offset to map offset */ + mapoff = adfs_convert_sector_to_map (sb, offset); + /* Calculate sector offset into map block */ + secoff = offset - adfs_convert_map_to_sector (sb, mapoff); + + do { + int result = lookup_zone (sb, zone, frag_id, &mapoff); + + if (result != -1) { + result += zone ? (zone * sb->u.adfs_sb.s_zonesize) - (ADFS_DR_SIZE << 3): 0; + return adfs_convert_map_to_sector (sb, result) + secoff; + } + + zone ++; + if (zone >= max_zone) + zone = 0; + + } while (zone != start_zone); + + adfs_error (sb, "adfs_map_lookup", "fragment %X at offset %d not found in map (start zone %d)", + frag_id, offset, start_zone); + return 0; +} diff -u --recursive --new-file v2.1.79/linux/fs/adfs/namei.c linux/fs/adfs/namei.c --- v2.1.79/linux/fs/adfs/namei.c Wed Dec 31 16:00:00 1969 +++ linux/fs/adfs/namei.c Tue Jan 20 16:44:58 1998 @@ -0,0 +1,119 @@ +/* + * linux/fs/adfs/namei.c + * + * Copyright (C) 1997 Russell King + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure + */ +static int adfs_match (int len, const char * const name, struct adfs_idir_entry *de) +{ + int i; + + if (!de || len > ADFS_NAME_LEN) + return 0; + /* + * "" means "." ---> so paths like "/usr/lib//libc.a" work + */ + if (!len && de->name_len == 1 && de->name[0] == '.' && + de->name[1] == '\0') + return 1; + if (len != de->name_len) + return 0; + + for (i = 0; i < len; i++) + if ((de->name[i] ^ name[i]) & 0x5f) + return 0; + return 1; +} + +static int adfs_find_entry (struct inode *dir, const char * const name, int namelen, + struct adfs_idir_entry *ide) +{ + struct super_block *sb; + struct buffer_head *bh[4]; + union adfs_dirtail dt; + unsigned long parent_object_id, dir_object_id; + int buffers, pos; + + if (!dir || !S_ISDIR(dir->i_mode)) + return 0; + + sb = dir->i_sb; + + if (adfs_inode_validate (dir)) { + adfs_error (sb, "adfs_find_entry", + "invalid inode number: %lu", dir->i_ino); + return 0; + } + + if (namelen > ADFS_NAME_LEN) + return 0; + + if (!(buffers = adfs_dir_read (dir, bh))) { + adfs_error (sb, "adfs_find_entry", "unable to read directory"); + return 0; + } + + if (adfs_dir_check (dir, bh, buffers, &dt)) { + adfs_dir_free (bh, buffers); + return 0; + } + + parent_object_id = adfs_val (dt.new.dirparent, 3); + dir_object_id = adfs_inode_objid (dir); + + if (namelen == 2 && name[0] == '.' && name[1] == '.') { + ide->name_len = 2; + ide->name[0] = ide->name[1] = '.'; + ide->name[2] = '\0'; + ide->inode_no = adfs_inode_generate (parent_object_id, 0); + adfs_dir_free (bh, buffers); + return 1; + } + + pos = 5; + + do { + if (!adfs_dir_get (sb, bh, buffers, pos, dir_object_id, ide)) + break; + + if (adfs_match (namelen, name, ide)) { + adfs_dir_free (bh, buffers); + return pos; + } + pos += 26; + } while (1); + adfs_dir_free (bh, buffers); + return 0; +} + +int adfs_lookup (struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = NULL; + struct adfs_idir_entry de; + unsigned long ino; + + if (dentry->d_name.len > ADFS_NAME_LEN) + return -ENAMETOOLONG; + + if (adfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de)) { + ino = de.inode_no; + inode = iget (dir->i_sb, ino); + + if (!inode) + return -EACCES; + } + d_add(dentry, inode); + return 0; +} diff -u --recursive --new-file v2.1.79/linux/fs/adfs/super.c linux/fs/adfs/super.c --- v2.1.79/linux/fs/adfs/super.c Wed Dec 31 16:00:00 1969 +++ linux/fs/adfs/super.c Tue Jan 20 16:44:58 1998 @@ -0,0 +1,345 @@ +/* + * linux/fs/adfs/super.c + * + * Copyright (C) 1997 Russell King + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +static void adfs_put_super (struct super_block *sb); +static int adfs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz); +void adfs_read_inode (struct inode *inode); + +void adfs_error (struct super_block *sb, const char *function, const char *fmt, ...) +{ + char error_buf[128]; + va_list args; + + va_start (args, fmt); + vsprintf (error_buf, fmt, args); + va_end (args); + + printk (KERN_CRIT "ADFS-fs error (device %s)%s%s: %s\n", + kdevname (sb->s_dev), function ? ": " : "", + function ? function : "", error_buf); +} + +unsigned char adfs_calccrosscheck (struct super_block *sb, char *map) +{ + unsigned int v0, v1, v2, v3; + int i; + + v0 = v1 = v2 = v3 = 0; + for (i = sb->s_blocksize - 4; i; i -= 4) { + v0 += map[i] + (v3 >> 8); + v3 &= 0xff; + v1 += map[i + 1] + (v0 >> 8); + v0 &= 0xff; + v2 += map[i + 2] + (v1 >> 8); + v1 &= 0xff; + v3 += map[i + 3] + (v2 >> 8); + v2 &= 0xff; + } + v0 += v3 >> 8; + v1 += map[1] + (v0 >> 8); + v2 += map[2] + (v1 >> 8); + v3 += map[3] + (v2 >> 8); + + return v0 ^ v1 ^ v2 ^ v3; +} + +static int adfs_checkmap (struct super_block *sb) +{ + unsigned char crosscheck = 0, zonecheck = 1; + int i; + + for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) { + char *map; + + map = sb->u.adfs_sb.s_map[i]->b_data; + if (adfs_calccrosscheck (sb, map) != map[0]) { + adfs_error (sb, "adfs_checkmap", "zone %d fails zonecheck", i); + zonecheck = 0; + } + crosscheck ^= map[3]; + } + if (crosscheck != 0xff) + adfs_error (sb, "adfs_checkmap", "crosscheck != 0xff"); + return crosscheck == 0xff && zonecheck; +} + +static struct super_operations adfs_sops = { + adfs_read_inode, + NULL, + NULL, + NULL, + NULL, + adfs_put_super, + NULL, + adfs_statfs, + NULL +}; + +static void adfs_put_super (struct super_block *sb) +{ + int i; + lock_super (sb); + sb->s_dev = 0; + for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) + brelse (sb->u.adfs_sb.s_map[i]); + kfree (sb->u.adfs_sb.s_map); + brelse (sb->u.adfs_sb.s_sbh); + unlock_super (sb); + MOD_DEC_USE_COUNT; +} + +struct super_block *adfs_read_super (struct super_block *sb, void *data, int silent) +{ + struct adfs_discrecord *dr; + struct buffer_head *bh; + unsigned char *b_data; + kdev_t dev = sb->s_dev; + int i, j; + + MOD_INC_USE_COUNT; + lock_super (sb); + set_blocksize (dev, BLOCK_SIZE); + if (!(bh = bread (dev, ADFS_DISCRECORD / BLOCK_SIZE, BLOCK_SIZE))) { + unlock_super (sb); + adfs_error (sb, NULL, "unable to read superblock"); + MOD_DEC_USE_COUNT; + return NULL; + } + + b_data = bh->b_data + (ADFS_DISCRECORD % BLOCK_SIZE); + + if (adfs_checkbblk (b_data)) { + if (!silent) + printk ("VFS: Can't find an adfs filesystem on dev " + "%s.\n", kdevname(dev)); +failed_mount: + unlock_super (sb); + if (bh) + brelse (bh); + MOD_DEC_USE_COUNT; + return NULL; + } + dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET); + + sb->s_blocksize_bits = dr->log2secsize; + sb->s_blocksize = 1 << sb->s_blocksize_bits; + if (sb->s_blocksize != BLOCK_SIZE && + (sb->s_blocksize == 512 || sb->s_blocksize == 1024 || + sb->s_blocksize == 2048 || sb->s_blocksize == 4096)) { + + brelse (bh); + set_blocksize (dev, sb->s_blocksize); + bh = bread (dev, ADFS_DISCRECORD / sb->s_blocksize, sb->s_blocksize); + if (!bh) { + adfs_error (sb, NULL, "couldn't read superblock on " + "2nd try."); + goto failed_mount; + } + b_data = bh->b_data + (ADFS_DISCRECORD % sb->s_blocksize); + if (adfs_checkbblk (b_data)) { + adfs_error (sb, NULL, "disc record mismatch, very weird!"); + goto failed_mount; + } + dr = (struct adfs_discrecord *)(b_data + ADFS_DR_OFFSET); + } + if (sb->s_blocksize != bh->b_size) { + if (!silent) + printk (KERN_ERR "VFS: Unsupported blocksize on dev " + "%s.\n", kdevname (dev)); + goto failed_mount; + } + /* blocksize on this device should now be set to the adfs log2secsize */ + + sb->u.adfs_sb.s_sbh = bh; + sb->u.adfs_sb.s_dr = dr; + + /* s_zone_size = size of 1 zone (1 sector) * bits_in_byte - zone_spare => + * number of map bits in a zone + */ + sb->u.adfs_sb.s_zone_size = (8 << dr->log2secsize) - dr->zone_spare; + + /* s_ids_per_zone = bit size of 1 zone / min. length of fragment block => + * number of ids in one zone + */ + sb->u.adfs_sb.s_ids_per_zone = sb->u.adfs_sb.s_zone_size / (dr->idlen + 1); + + /* s_idlen = length of 1 id */ + sb->u.adfs_sb.s_idlen = dr->idlen; + + /* map size (in sectors) = number of zones */ + sb->u.adfs_sb.s_map_size = dr->nzones; + + /* zonesize = size of sector - zonespare */ + sb->u.adfs_sb.s_zonesize = (sb->s_blocksize << 3) - dr->zone_spare; + + /* map start (in sectors) = start of zone (number of zones) / 2 */ + sb->u.adfs_sb.s_map_block = (dr->nzones >> 1) * sb->u.adfs_sb.s_zone_size - + ((dr->nzones > 1) ? 8 * ADFS_DR_SIZE : 0); + + /* (signed) number of bits to shift left a map address to a sector address */ + sb->u.adfs_sb.s_map2blk = dr->log2bpmb - dr->log2secsize; + + if (sb->u.adfs_sb.s_map2blk >= 0) + sb->u.adfs_sb.s_map_block <<= sb->u.adfs_sb.s_map2blk; + else + sb->u.adfs_sb.s_map_block >>= -sb->u.adfs_sb.s_map2blk; + + printk (KERN_DEBUG "ADFS: zone size %d, IDs per zone %d, map address %X size %d sectors\n", + sb->u.adfs_sb.s_zone_size, sb->u.adfs_sb.s_ids_per_zone, + sb->u.adfs_sb.s_map_block, sb->u.adfs_sb.s_map_size); + printk (KERN_DEBUG "ADFS: sector size %d, map bit size %d\n", + 1 << dr->log2secsize, 1 << dr->log2bpmb); + + sb->s_magic = ADFS_SUPER_MAGIC; + sb->s_flags |= MS_RDONLY; /* we don't support writing yet */ + + sb->u.adfs_sb.s_map = kmalloc (sb->u.adfs_sb.s_map_size * + sizeof (struct buffer_head *), GFP_KERNEL); + if (sb->u.adfs_sb.s_map == NULL) { + adfs_error (sb, NULL, "not enough memory"); + goto failed_mount; + } + + for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) { + sb->u.adfs_sb.s_map[i] = bread (dev, + sb->u.adfs_sb.s_map_block + i, + sb->s_blocksize); + if (!sb->u.adfs_sb.s_map[i]) { + for (j = 0; j < i; j++) + brelse (sb->u.adfs_sb.s_map[j]); + kfree (sb->u.adfs_sb.s_map); + adfs_error (sb, NULL, "unable to read map"); + goto failed_mount; + } + } + if (!adfs_checkmap (sb)) { + for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) + brelse (sb->u.adfs_sb.s_map[i]); + adfs_error (sb, NULL, "map corrupted"); + goto failed_mount; + } + + dr = (struct adfs_discrecord *)(sb->u.adfs_sb.s_map[0]->b_data + 4); + unlock_super (sb); + + /* + * set up enough so that it can read an inode + */ + sb->s_op = &adfs_sops; + sb->u.adfs_sb.s_root = adfs_inode_generate (dr->root, 0); + sb->s_root = d_alloc_root(iget(sb, sb->u.adfs_sb.s_root), NULL); + + if (!sb->s_root) { + sb->s_dev = 0; + for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) + brelse (sb->u.adfs_sb.s_map[i]); + brelse (bh); + adfs_error (sb, NULL, "get root inode failed\n"); + MOD_DEC_USE_COUNT; + return NULL; + } + return sb; +} + +static int adfs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz) +{ + struct statfs tmp; + const unsigned int nidlen = sb->u.adfs_sb.s_idlen + 1; + + tmp.f_type = ADFS_SUPER_MAGIC; + tmp.f_bsize = sb->s_blocksize; + tmp.f_blocks = (sb->u.adfs_sb.s_dr->disc_size) >> (sb->s_blocksize_bits); + tmp.f_files = tmp.f_blocks >> nidlen; + { + unsigned int i, j = 0; + const unsigned mask = (1 << (nidlen - 1)) - 1; + for (i = 0; i < sb->u.adfs_sb.s_map_size; i++) { + const char *map = sb->u.adfs_sb.s_map[i]->b_data; + unsigned freelink, mapindex = 24; + j -= nidlen; + do { + unsigned char k, l, m; + unsigned off = (mapindex - nidlen) >> 3; + unsigned rem; + const unsigned boff = mapindex & 7; + + /* get next freelink */ + + k = map[off++]; + l = map[off++]; + m = map[off++]; + freelink = (m << 16) | (l << 8) | k; + rem = freelink >> (boff + nidlen - 1); + freelink = (freelink >> boff) & mask; + mapindex += freelink; + + /* find its length and add it to running total */ + + while (rem == 0) { + j += 8; + rem = map[off++]; + } + if ((rem & 0xff) == 0) j+=8, rem>>=8; + if ((rem & 0xf) == 0) j+=4, rem>>=4; + if ((rem & 0x3) == 0) j+=2, rem>>=2; + if ((rem & 0x1) == 0) j+=1; + j += nidlen - boff; + if (freelink <= nidlen) break; + } while (mapindex < 8 * sb->s_blocksize); + if (mapindex > 8 * sb->s_blocksize) + adfs_error (sb, NULL, "oversized free fragment\n"); + else if (freelink) + adfs_error (sb, NULL, "undersized free fragment\n"); + } + tmp.f_bfree = tmp.f_bavail = j << + (sb->u.adfs_sb.s_dr->log2bpmb - sb->s_blocksize_bits); + } + tmp.f_ffree = tmp.f_bfree >> nidlen; + tmp.f_namelen = ADFS_NAME_LEN; + return copy_to_user (buf, &tmp, bufsiz) ? -EFAULT : 0; +} + +static struct file_system_type adfs_fs_type = { + "adfs", FS_REQUIRES_DEV, adfs_read_super, NULL +}; + +__initfunc(int init_adfs_fs (void)) +{ + return register_filesystem (&adfs_fs_type); +} + +#ifdef MODULE +int init_module (void) +{ + int status; + + if ((status = init_adfs_fs()) == 0) + register_symtab(0); + return status; +} + +void cleanup_module (void) +{ + unregister_filesystem (&adfs_fs_type); +} +#endif diff -u --recursive --new-file v2.1.79/linux/fs/buffer.c linux/fs/buffer.c --- v2.1.79/linux/fs/buffer.c Mon Jan 12 22:09:17 1998 +++ linux/fs/buffer.c Thu Jan 15 21:01:04 1998 @@ -1706,7 +1706,7 @@ void buffer_init(void) { hash_table = (struct buffer_head **) - __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER, 0); + __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER); if (!hash_table) panic("Failed to allocate buffer hash table\n"); memset(hash_table,0,NR_HASH*sizeof(struct buffer_head *)); diff -u --recursive --new-file v2.1.79/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.79/linux/fs/dcache.c Mon Jan 12 22:09:17 1998 +++ linux/fs/dcache.c Tue Jan 13 20:02:49 1998 @@ -67,6 +67,7 @@ struct inode *inode = dentry->d_inode; if (inode) { dentry->d_inode = NULL; + list_del(&dentry->d_alias); if (dentry->d_op && dentry->d_op->d_iput) dentry->d_op->d_iput(dentry, inode); else @@ -508,6 +509,7 @@ INIT_LIST_HEAD(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_subdirs); + INIT_LIST_HEAD(&dentry->d_alias); dentry->d_name.name = str; dentry->d_name.len = name->len; @@ -529,6 +531,8 @@ */ void d_instantiate(struct dentry *entry, struct inode * inode) { + if (inode) + list_add(&entry->d_alias, &inode->i_dentry); entry->d_inode = inode; } diff -u --recursive --new-file v2.1.79/linux/fs/fat/cache.c linux/fs/fat/cache.c --- v2.1.79/linux/fs/fat/cache.c Mon Jan 12 22:09:17 1998 +++ linux/fs/fat/cache.c Tue Jan 13 20:07:28 1998 @@ -122,7 +122,7 @@ } -void cache_init(void) +void fat_cache_init(void) { static int initialized = 0; int count; @@ -138,7 +138,7 @@ } -void cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu) +void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu) { struct fat_cache *walk; @@ -179,7 +179,7 @@ #endif -void cache_add(struct inode *inode,int f_clu,int d_clu) +void fat_cache_add(struct inode *inode,int f_clu,int d_clu) { struct fat_cache *walk,*last; @@ -252,12 +252,12 @@ if (!(nr = MSDOS_I(inode)->i_start)) return 0; if (!cluster) return nr; count = 0; - for (cache_lookup(inode,cluster,&count,&nr); count < cluster; + for (fat_cache_lookup(inode,cluster,&count,&nr); count < cluster; count++) { if ((nr = fat_access(inode->i_sb,nr,-1)) == -1) return 0; if (!nr) return 0; } - cache_add(inode,cluster,nr); + fat_cache_add(inode,cluster,nr); return nr; } diff -u --recursive --new-file v2.1.79/linux/fs/fat/dir.c linux/fs/fat/dir.c --- v2.1.79/linux/fs/fat/dir.c Mon Jan 12 22:09:17 1998 +++ linux/fs/fat/dir.c Tue Jan 13 20:07:28 1998 @@ -237,6 +237,7 @@ char bufname[14]; char *ptname = bufname; int dotoffset = 0; + int was_long = is_long; if (is_long) { unsigned char sum; @@ -247,6 +248,7 @@ if (sum != alias_checksum) { PRINTK(("Checksums don't match %d != %d\n", sum, alias_checksum)); is_long = 0; + long_slots = 0; } if (utf8) { long_len = utf8_wcstombs(longname, (__u16 *) unicode, sizeof(longname)); @@ -290,7 +292,7 @@ if (both) bufname[i+dotoffset] = '\0'; spos = oldpos; - if (is_long) { + if (was_long) { spos = filp->f_pos - sizeof(struct msdos_dir_entry); } else { long_slots = 0; diff -u --recursive --new-file v2.1.79/linux/fs/fat/inode.c linux/fs/fat/inode.c --- v2.1.79/linux/fs/fat/inode.c Mon Jan 12 22:09:17 1998 +++ linux/fs/fat/inode.c Tue Jan 13 20:07:28 1998 @@ -377,7 +377,7 @@ /* N.B. we should parse directly into the sb structure */ memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options)); - cache_init(); + fat_cache_init(); lock_super(sb); if( blksize > 1024 ) { diff -u --recursive --new-file v2.1.79/linux/fs/fat/misc.c linux/fs/fat/misc.c --- v2.1.79/linux/fs/fat/misc.c Mon Jan 12 22:09:17 1998 +++ linux/fs/fat/misc.c Tue Jan 13 20:07:28 1998 @@ -194,7 +194,7 @@ */ file_cluster = 0; if ((curr = MSDOS_I(inode)->i_start) != 0) { - cache_lookup(inode,INT_MAX,&last,&curr); + fat_cache_lookup(inode,INT_MAX,&last,&curr); file_cluster = last; while (curr && curr != -1){ PRINTK ((".")); @@ -242,7 +242,7 @@ printk ("file_cluster badly computed!!! %d <> %ld\n" ,file_cluster,inode->i_blocks/cluster_size); }else{ - cache_add(inode,file_cluster,nr); + fat_cache_add(inode,file_cluster,nr); } inode->i_blocks += cluster_size; if (S_ISDIR(inode->i_mode)) { diff -u --recursive --new-file v2.1.79/linux/fs/fat/mmap.c linux/fs/fat/mmap.c --- v2.1.79/linux/fs/fat/mmap.c Mon Jan 12 22:09:17 1998 +++ linux/fs/fat/mmap.c Tue Jan 13 20:07:28 1998 @@ -118,11 +118,13 @@ } -int fat_readpage(struct inode * inode, struct page * page) +int fat_readpage(struct dentry * dentry, struct page * page) { + struct inode * inode = dentry->d_inode; if(MSDOS_SB(inode->i_sb)->cvf_format) - if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage) - return MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage(inode,page); + if(MSDOS_SB(inode->i_sb)->cvf_format->cvf_readpage) + return MSDOS_SB(inode->i_sb)->cvf_format + ->cvf_readpage(inode,page); printk("fat_readpage called with no handler (shouldn't happen)\n"); return -1; diff -u --recursive --new-file v2.1.79/linux/fs/filesystems.c linux/fs/filesystems.c --- v2.1.79/linux/fs/filesystems.c Tue Jan 6 09:37:36 1998 +++ linux/fs/filesystems.c Tue Jan 20 16:44:58 1998 @@ -131,6 +131,10 @@ init_autofs_fs(); #endif +#ifdef CONFIG_ADFS_FS + init_adfs_fs(); +#endif + #ifdef CONFIG_NLS init_nls(); #endif diff -u --recursive --new-file v2.1.79/linux/fs/inode.c linux/fs/inode.c --- v2.1.79/linux/fs/inode.c Tue Jan 6 09:37:36 1998 +++ linux/fs/inode.c Fri Jan 16 11:24:09 1998 @@ -127,6 +127,7 @@ memset(inode, 0, sizeof(*inode)); init_waitqueue(&inode->i_wait); INIT_LIST_HEAD(&inode->i_hash); + INIT_LIST_HEAD(&inode->i_dentry); sema_init(&inode->i_sem, 1); } @@ -647,7 +648,17 @@ void insert_inode_hash(struct inode *inode) { struct list_head *head = inode_hashtable + hash(inode->i_sb, inode->i_ino); + spin_lock(&inode_lock); list_add(&inode->i_hash, head); + spin_unlock(&inode_lock); +} + +void remove_inode_hash(struct inode *inode) +{ + spin_lock(&inode_lock); + list_del(&inode->i_hash); + INIT_LIST_HEAD(&inode->i_hash); + spin_unlock(&inode_lock); } void iput(struct inode *inode) @@ -688,6 +699,9 @@ list_add(&inode->i_list, inode_in_use.prev); } #ifdef INODE_PARANOIA +if (!list_empty(&inode->i_dentry)) +printk("iput: device %s inode %ld still has aliases!\n", +kdevname(inode->i_dev), inode->i_ino); if (inode->i_count) printk("iput: device %s inode %ld count changed, count=%d\n", kdevname(inode->i_dev), inode->i_ino, inode->i_count); diff -u --recursive --new-file v2.1.79/linux/fs/nfs/dir.c linux/fs/nfs/dir.c --- v2.1.79/linux/fs/nfs/dir.c Mon Jan 12 22:09:18 1998 +++ linux/fs/nfs/dir.c Wed Jan 14 16:57:52 1998 @@ -494,49 +494,29 @@ NULL, /* d_hash */ NULL, /* d_compare */ nfs_dentry_delete, /* d_delete(struct dentry *) */ - nfs_dentry_iput, /* d_iput(struct dentry *, struct inode *) */ - nfs_dentry_release /* d_release(struct dentry *) */ + nfs_dentry_release, /* d_release(struct dentry *) */ + nfs_dentry_iput /* d_iput(struct dentry *, struct inode *) */ }; #ifdef NFS_PARANOIA /* * Display all dentries holding the specified inode. */ -static void show_dentry(struct inode * inode) +static void show_dentry(struct list_head * dlist) { - struct dentry *parent = inode->i_sb->s_root; - struct dentry *this_parent = parent; - struct list_head *next; - -repeat: - next = this_parent->d_subdirs.next; -resume: - while (next != &this_parent->d_subdirs) { - struct list_head *tmp = next; - struct dentry *dentry = list_entry(tmp, struct dentry, d_child); - next = tmp->next; - if (dentry->d_inode == inode) { - int unhashed = list_empty(&dentry->d_hash); - printk("show_dentry: %s/%s, d_count=%d%s\n", - dentry->d_parent->d_name.name, - dentry->d_name.name, dentry->d_count, - unhashed ? "(unhashed)" : ""); - } - /* - * Descend a level if the d_subdirs list is non-empty. - */ - if (!list_empty(&dentry->d_subdirs)) { - this_parent = dentry; - goto repeat; - } - } - /* - * All done at this level ... ascend and resume the search. - */ - if (this_parent != parent) { - next = this_parent->d_child.next; - this_parent = this_parent->d_parent; - goto resume; + struct list_head *tmp = dlist; + + while ((tmp = tmp->next) != dlist) { + struct dentry * dentry = list_entry(tmp, struct dentry, d_alias); + const char * unhashed = ""; + + if (list_empty(&dentry->d_hash)) + unhashed = "(unhashed)"; + + printk("show_dentry: %s/%s, d_count=%d%s\n", + dentry->d_parent->d_name.name, + dentry->d_name.name, dentry->d_count, + unhashed); } } #endif @@ -602,7 +582,7 @@ printk("nfs_lookup: %s/%s ino=%ld in use, count=%d, nlink=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, inode->i_count, inode->i_nlink); -show_dentry(inode); +show_dentry(&inode->i_dentry); } #endif no_entry: @@ -637,7 +617,7 @@ printk("nfs_instantiate: %s/%s ino=%ld in use, count=%d, nlink=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, inode->i_count, inode->i_nlink); -show_dentry(inode); +show_dentry(&inode->i_dentry); } #endif d_instantiate(dentry, inode); diff -u --recursive --new-file v2.1.79/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v2.1.79/linux/fs/nfs/inode.c Mon Jan 12 22:09:18 1998 +++ linux/fs/nfs/inode.c Fri Jan 16 11:24:09 1998 @@ -356,16 +356,49 @@ } /* + * Free all unused dentries in an inode's alias list. + * + * Subtle note: we have to be very careful not to cause + * any IO operations with the stale dentries, as this + * could cause file corruption. But since the dentry + * count is 0 and all pending IO for a dentry has been + * flushed when the count went to 0, we're safe here. + */ +void nfs_free_dentries(struct inode *inode) +{ + struct list_head *tmp, *head = &inode->i_dentry; + +restart: + tmp = head; + while ((tmp = tmp->next) != head) { + struct dentry *dentry = list_entry(tmp, struct dentry, d_alias); + if (!dentry->d_count) { +printk("nfs_free_dentries: freeing %s/%s, i_count=%d\n", +dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_count); + dget(dentry); + d_drop(dentry); + dput(dentry); + goto restart; + } + } +} + +/* * This is our own version of iget that looks up inodes by file handle * instead of inode number. We use this technique instead of using * the vfs read_inode function because there is no way to pass the * file handle or current attributes into the read_inode function. + * + * Note carefully the special handling of busy inodes (i_count > 1). + * With the Linux 2.1.xx dcache all inodes except hard links must + * have i_count == 1 after iget(). Otherwise, it indicates that the + * server has reused a fileid (i_ino) and we have a stale inode. */ struct inode * nfs_fhget(struct super_block *sb, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { - int error; + int error, max_count; struct inode *inode = NULL; struct nfs_fattr newfattr; @@ -377,6 +410,8 @@ if (error) goto out_bad_attr; } + +retry: inode = iget(sb, fattr->fileid); if (!inode) goto out_no_inode; @@ -387,6 +422,40 @@ if (inode->i_ino != fattr->fileid) goto out_bad_id; + + /* + * Check for busy inodes, and attempt to get rid of any + * unused local references. If successful, we release the + * inode and try again. + * + * Note that the busy test uses the values in the fattr, + * as the inode may have become a different object. + * (We can probably handle modes changes here, too.) + */ + max_count = S_ISDIR(fattr->mode) ? 1 : fattr->nlink; + if (inode->i_count > max_count) { +printk("nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n", +inode->i_ino, inode->i_count, inode->i_nlink); + nfs_free_dentries(inode); + if (inode->i_count > max_count) { +printk("nfs_fhget: inode %ld still busy, i_count=%d\n", +inode->i_ino, inode->i_count); + if (!list_empty(&inode->i_dentry)) { + struct dentry *dentry; + dentry = list_entry(inode->i_dentry.next, + struct dentry, d_alias); +printk("nfs_fhget: killing %s/%s filehandle\n", +dentry->d_parent->d_name.name, dentry->d_name.name); + memset(dentry->d_fsdata, 0, sizeof(*fhandle)); + } else + printk("NFS: inode %ld busy, no aliases?\n", + inode->i_ino); + make_bad_inode(inode); + remove_inode_hash(inode); + } + iput(inode); + goto retry; + } /* * Check whether the mode has been set, as we only want to diff -u --recursive --new-file v2.1.79/linux/fs/nfs/proc.c linux/fs/nfs/proc.c --- v2.1.79/linux/fs/nfs/proc.c Mon Jan 12 22:09:18 1998 +++ linux/fs/nfs/proc.c Tue Jan 13 10:03:40 1998 @@ -43,11 +43,6 @@ #include -/* - * If NFS_DEBUG is defined, you can toggle NFS debugging by causing - * a lookup of "__xyzzy__". Just cd to an NFS-mounted filesystem and type - * 'ls __xyzzy__' to turn on debugging. - */ #ifdef NFS_DEBUG # define NFSDBG_FACILITY NFSDBG_PROC #endif @@ -90,10 +85,6 @@ int status; dprintk("NFS call lookup %s\n", name); -#ifdef RPC_DEBUG - if (!strcmp(name, "__xyzzy__")) - nfs_debug = ~nfs_debug; -#endif status = rpc_call(server->client, NFSPROC_LOOKUP, &arg, &res, 0); dprintk("NFS reply lookup: %d\n", status); return status; diff -u --recursive --new-file v2.1.79/linux/fs/nfs/read.c linux/fs/nfs/read.c --- v2.1.79/linux/fs/nfs/read.c Tue Jan 6 09:37:37 1998 +++ linux/fs/nfs/read.c Mon Jan 19 21:13:59 1998 @@ -115,8 +115,10 @@ result = 0; io_error: - if (refresh) + /* Note: we don't refresh if the call returned error */ + if (refresh && result >= 0) nfs_refresh_inode(inode, &rqst.ra_fattr); + /* N.B. Use nfs_unlock_page here? */ clear_bit(PG_locked, &page->flags); wake_up(&page->wait); return result; @@ -131,17 +133,17 @@ { struct nfs_rreq *req = (struct nfs_rreq *) task->tk_calldata; struct page *page = req->ra_page; + unsigned long address = page_address(page); int result = task->tk_status; static int succ = 0, fail = 0; dprintk("NFS: %4d received callback for page %lx, result %d\n", - task->tk_pid, page_address(page), result); + task->tk_pid, address, result); if (result >= 0) { result = req->ra_res.count; if (result < PAGE_SIZE) { - memset((char *) page_address(page) + result, 0, - PAGE_SIZE - result); + memset((char *) address + result, 0, PAGE_SIZE - result); } nfs_refresh_inode(req->ra_inode, &req->ra_fattr); set_bit(PG_uptodate, &page->flags); @@ -151,10 +153,11 @@ fail++; dprintk("NFS: %d successful reads, %d failures\n", succ, fail); } + /* N.B. Use nfs_unlock_page here? */ clear_bit(PG_locked, &page->flags); wake_up(&page->wait); - free_page(page_address(page)); + free_page(address); rpc_release_task(task); kfree(req); @@ -164,38 +167,45 @@ nfs_readpage_async(struct dentry *dentry, struct inode *inode, struct page *page) { + unsigned long address = page_address(page); struct nfs_rreq *req; - int result, flags; + int result = -1, flags; dprintk("NFS: nfs_readpage_async(%p)\n", page); - flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); + if (NFS_CONGESTED(inode)) + goto out_defer; - if (NFS_CONGESTED(inode) - || !(req = (struct nfs_rreq *) rpc_allocate(flags, sizeof(*req)))) { - dprintk("NFS: deferring async READ request.\n"); - return -1; - } + /* N.B. Do we need to test? Never called for swapfile inode */ + flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); + req = (struct nfs_rreq *) rpc_allocate(flags, sizeof(*req)); + if (!req) + goto out_defer; /* Initialize request */ + /* N.B. Will the dentry remain valid for life of request? */ nfs_readreq_setup(req, NFS_FH(dentry), page->offset, - (void *) page_address(page), PAGE_SIZE); + (void *) address, PAGE_SIZE); req->ra_inode = inode; - req->ra_page = page; + req->ra_page = page; /* count has been incremented by caller */ /* Start the async call */ dprintk("NFS: executing async READ request.\n"); result = rpc_do_call(NFS_CLIENT(inode), NFSPROC_READ, &req->ra_args, &req->ra_res, flags, nfs_readpage_result, req); + if (result < 0) + goto out_free; + result = 0; +out: + return result; - if (result >= 0) { - atomic_inc(&page->count); - return 0; - } - +out_defer: + dprintk("NFS: deferring async READ request.\n"); + goto out; +out_free: dprintk("NFS: failed to enqueue async READ request.\n"); kfree(req); - return -1; + goto out; } /* @@ -214,20 +224,20 @@ nfs_readpage(struct dentry *dentry, struct page *page) { struct inode *inode = dentry->d_inode; - unsigned long address; int error = -1; - dprintk("NFS: nfs_readpage %08lx\n", page_address(page)); + dprintk("NFS: nfs_readpage (%p %ld@%ld)\n", + page, PAGE_SIZE, page->offset); set_bit(PG_locked, &page->flags); - address = page_address(page); atomic_inc(&page->count); if (!IS_SWAPFILE(inode) && !PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_SIZE) error = nfs_readpage_async(dentry, inode, page); - if (error < 0) /* couldn't enqueue */ + if (error < 0) { /* couldn't enqueue */ error = nfs_readpage_sync(dentry, inode, page); - if (error < 0 && IS_SWAPFILE(inode)) - printk("Aiee.. nfs swap-in of page failed!\n"); - free_page(address); + if (error < 0 && IS_SWAPFILE(inode)) + printk("Aiee.. nfs swap-in of page failed!\n"); + free_page(page_address(page)); + } return error; } diff -u --recursive --new-file v2.1.79/linux/fs/nfs/write.c linux/fs/nfs/write.c --- v2.1.79/linux/fs/nfs/write.c Mon Jan 12 22:09:18 1998 +++ linux/fs/nfs/write.c Tue Jan 20 12:11:58 1998 @@ -128,7 +128,7 @@ req->wb_flags |= NFS_WRITE_LOCKED; rpc_wake_up_task(&req->wb_task); - dprintk("nfs: wake up task %d (flags %x)\n", + dprintk("NFS: wake up task %d (flags %x)\n", req->wb_task.tk_pid, req->wb_flags); } @@ -182,8 +182,8 @@ } while (count); io_error: - /* N.B. do we want to refresh if there was an error?? (fattr valid?) */ - if (refresh) { + /* Note: we don't refresh if the call failed (fattr invalid) */ + if (refresh && result >= 0) { /* See comments in nfs_wback_result */ /* N.B. I don't think this is right -- sync writes in order */ if (fattr.size < inode->i_size) @@ -509,25 +509,16 @@ nfs_updatepage(struct dentry *dentry, struct page *page, const char *buffer, unsigned long offset, unsigned int count, int sync) { - struct inode *inode = dentry->d_inode; + struct inode *inode = dentry->d_inode; + u8 *page_addr = (u8 *) page_address(page); struct nfs_wreq *req; int status = 0, page_locked = 1; - u8 *page_addr; dprintk("NFS: nfs_updatepage(%s/%s %d@%ld, sync=%d)\n", dentry->d_parent->d_name.name, dentry->d_name.name, count, page->offset+offset, sync); set_bit(PG_locked, &page->flags); - page_addr = (u8 *) page_address(page); - - /* If wsize is smaller than page size, update and write - * page synchronously. - */ - if (NFS_SERVER(inode)->wsize < PAGE_SIZE) { - copy_from_user(page_addr + offset, buffer, count); - return nfs_writepage_sync(dentry, inode, page, offset, count); - } /* * Try to find a corresponding request on the writeback queue. @@ -541,6 +532,7 @@ */ if ((req = find_write_request(inode, page)) != NULL) { if (update_write_request(req, offset, count)) { + /* N.B. check for a fault here and cancel the req */ copy_from_user(page_addr + offset, buffer, count); goto updated; } @@ -549,16 +541,23 @@ return 0; } + /* Copy data to page buffer. */ + status = -EFAULT; + if (copy_from_user(page_addr + offset, buffer, count)) + goto done; + + /* If wsize is smaller than page size, update and write + * page synchronously. + */ + if (NFS_SERVER(inode)->wsize < PAGE_SIZE) + return nfs_writepage_sync(dentry, inode, page, offset, count); + /* Create the write request. */ status = -ENOBUFS; req = create_write_request(dentry, inode, page, offset, count); if (!req) goto done; - /* Copy data to page buffer. */ - /* N.B. should check for fault here ... */ - copy_from_user(page_addr + offset, buffer, count); - /* Schedule request */ page_locked = schedule_write_request(req, sync); @@ -588,8 +587,14 @@ if ((count = nfs_write_error(inode)) < 0) status = count; } - } else + } else { + if (status < 0) { +printk("NFS: %s/%s write failed, clearing bit\n", +dentry->d_parent->d_name.name, dentry->d_name.name); + clear_bit(PG_uptodate, &page->flags); + } nfs_unlock_page(page); + } } dprintk("NFS: nfs_updatepage returns %d (isize %ld)\n", @@ -641,21 +646,19 @@ req->wb_task.tk_pid, req->wb_inode->i_dev, req->wb_inode->i_ino, req->wb_page->offset, req->wb_flags); - if (!WB_INPROGRESS(req)) { - rqoffset = req->wb_page->offset + req->wb_offset; - rqend = rqoffset + req->wb_bytes; - - if (rqoffset < end && offset < rqend + rqoffset = req->wb_page->offset + req->wb_offset; + rqend = rqoffset + req->wb_bytes; + + if (rqoffset < end && offset < rqend && (pid == 0 || req->wb_pid == pid)) { - if (!WB_HAVELOCK(req)) { + if (!WB_INPROGRESS(req) && !WB_HAVELOCK(req)) { #ifdef NFS_DEBUG_VERBOSE printk("nfs_flush: flushing inode=%ld, %d @ %lu\n", req->wb_inode->i_ino, req->wb_bytes, rqoffset); #endif - nfs_flush_request(req); - } - last = req; + nfs_flush_request(req); } + last = req; } if (invalidate) req->wb_flags |= NFS_WRITE_INVALIDATE; @@ -815,32 +818,26 @@ struct page *page = req->wb_page; struct dentry *dentry = req->wb_dentry; - dprintk("NFS: %4d nfs_wback_lock (status %d flags %x)\n", - task->tk_pid, task->tk_status, req->wb_flags); + dprintk("NFS: %4d nfs_wback_lock (%s/%s, status=%d flags=%x)\n", + task->tk_pid, dentry->d_parent->d_name.name, + dentry->d_name.name, task->tk_status, req->wb_flags); if (!WB_HAVELOCK(req)) req->wb_flags |= NFS_WRITE_WANTLOCK; - if (WB_WANTLOCK(req) && test_and_set_bit(PG_locked, &page->flags)) { - printk("NFS: page already locked in writeback_lock!\n"); - task->tk_timeout = 2 * HZ; - rpc_sleep_on(&write_queue, task, NULL, NULL); - return; - } - task->tk_status = 0; + if (WB_WANTLOCK(req) && test_and_set_bit(PG_locked, &page->flags)) + goto out_locked; req->wb_flags &= ~NFS_WRITE_WANTLOCK; req->wb_flags |= NFS_WRITE_LOCKED; + task->tk_status = 0; if (req->wb_args == 0) { size_t size = sizeof(struct nfs_writeargs) + sizeof(struct nfs_fattr); void *ptr; - if (!(ptr = kmalloc(size, GFP_KERNEL))) { - task->tk_timeout = HZ; - rpc_sleep_on(&write_queue, task, NULL, NULL); - return; - } + if (!(ptr = kmalloc(size, GFP_KERNEL))) + goto out_no_args; req->wb_args = (struct nfs_writeargs *) ptr; req->wb_fattr = (struct nfs_fattr *) (req->wb_args + 1); } @@ -854,6 +851,18 @@ rpc_call_setup(task, NFSPROC_WRITE, req->wb_args, req->wb_fattr, 0); req->wb_flags |= NFS_WRITE_INPROGRESS; + return; + +out_locked: + printk("NFS: page already locked in writeback_lock!\n"); + task->tk_timeout = 2 * HZ; + rpc_sleep_on(&write_queue, task, NULL, NULL); + return; +out_no_args: + printk("NFS: can't alloc args, sleeping\n"); + task->tk_timeout = HZ; + rpc_sleep_on(&write_queue, task, NULL, NULL); + return; } /* @@ -867,9 +876,12 @@ struct page *page = req->wb_page; int status = task->tk_status; - dprintk("NFS: %4d nfs_wback_result (status %d)\n", - task->tk_pid, status); + dprintk("NFS: %4d nfs_wback_result (%s/%s, status=%d, flags=%x)\n", + task->tk_pid, req->wb_dentry->d_parent->d_name.name, + req->wb_dentry->d_name.name, status, req->wb_flags); + /* Set the WRITE_COMPLETE flag, but leave INPROGRESS set */ + req->wb_flags |= NFS_WRITE_COMPLETE; if (status < 0) { /* * An error occurred. Report the error back to the diff -u --recursive --new-file v2.1.79/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.1.79/linux/fs/proc/array.c Mon Jan 12 22:09:18 1998 +++ linux/fs/proc/array.c Tue Jan 20 12:52:08 1998 @@ -221,14 +221,21 @@ static int get_kstat(char * buffer) { - int i, len; + int i, j, len; unsigned sum = 0; extern unsigned long total_forks; unsigned long ticks; ticks = jiffies * smp_num_cpus; +#ifndef __SMP__ for (i = 0 ; i < NR_IRQS ; i++) - sum += kstat.interrupts[i]; + sum += kstat.interrupts[0][i]; +#else + for (j = 0 ; j < smp_num_cpus ; j++) + for (i = 0 ; i < NR_IRQS ; i++) + sum += kstat.interrupts[cpu_logical_map[j]][i]; +#endif + #ifdef __SMP__ len = sprintf(buffer, "cpu %u %u %u %lu\n", @@ -285,8 +292,17 @@ kstat.pswpin, kstat.pswpout, sum); - for (i = 0 ; i < NR_IRQS ; i++) - len += sprintf(buffer + len, " %u", kstat.interrupts[i]); + for (i = 0 ; i < NR_IRQS ; i++) { +#ifndef __SMP__ + len += sprintf(buffer + len, " %u", kstat.interrupts[0][i]); +#else + int sum=0; + + for (j = 0 ; j < smp_num_cpus ; j++) + sum += kstat.interrupts[cpu_logical_map[j]][i]; + len += sprintf(buffer + len, " %u", sum); +#endif + } len += sprintf(buffer + len, "\nctxt %u\n" "btime %lu\n" @@ -1153,9 +1169,6 @@ extern int get_rtc_status (char *); extern int get_locks_status (char *, char **, off_t, int); extern int get_swaparea_info (char *); -#ifdef __SMP_PROF__ -extern int get_smp_prof_list(char *); -#endif #ifdef CONFIG_ZORRO extern int zorro_get_list(char *); #endif @@ -1223,10 +1236,6 @@ #ifdef CONFIG_BLK_DEV_MD case PROC_MD: return get_md_status(page); -#endif -#ifdef __SMP_PROF__ - case PROC_SMP_PROF: - return get_smp_prof_list(page); #endif case PROC_CMDLINE: return get_cmdline(page); diff -u --recursive --new-file v2.1.79/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c --- v2.1.79/linux/fs/proc/openpromfs.c Sun Sep 7 13:10:43 1997 +++ linux/fs/proc/openpromfs.c Fri Jan 16 20:37:34 1998 @@ -901,7 +901,7 @@ unsigned long pages; if ((1 << alloced) * PAGE_SIZE < (n + 2) * sizeof(openpromfs_node)) { - pages = __get_free_pages (GFP_KERNEL, alloced + 1, 0); + pages = __get_free_pages (GFP_KERNEL, alloced + 1); if (!pages) return -1; @@ -1048,7 +1048,7 @@ if (!romvec->pv_romvers) return RET(ENODEV); #endif - nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0, 0); + nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0); if (!nodes) { printk (KERN_WARNING "/proc/openprom: can't get free page\n"); return RET(EIO); diff -u --recursive --new-file v2.1.79/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.79/linux/fs/proc/root.c Mon Jan 12 22:09:18 1998 +++ linux/fs/proc/root.c Tue Jan 20 12:52:08 1998 @@ -574,13 +574,6 @@ S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; -#ifdef __SMP_PROF__ -static struct proc_dir_entry proc_root_smp = { - PROC_SMP_PROF, 3,"smp", - S_IFREG | S_IRUGO, 1, 0, 0, - 0, &proc_array_inode_operations -}; -#endif static struct proc_dir_entry proc_root_filesystems = { PROC_FILESYSTEMS, 11,"filesystems", S_IFREG | S_IRUGO, 1, 0, 0, @@ -690,9 +683,6 @@ proc_register(&proc_root, &proc_root_stat); proc_register(&proc_root, &proc_root_devices); proc_register(&proc_root, &proc_root_interrupts); -#ifdef __SMP_PROF__ - proc_register(&proc_root, &proc_root_smp); -#endif proc_register(&proc_root, &proc_root_filesystems); proc_register(&proc_root, &proc_root_dma); proc_register(&proc_root, &proc_root_ioports); diff -u --recursive --new-file v2.1.79/linux/fs/vfat/namei.c linux/fs/vfat/namei.c --- v2.1.79/linux/fs/vfat/namei.c Fri Jan 2 14:37:02 1998 +++ linux/fs/vfat/namei.c Tue Jan 13 20:07:28 1998 @@ -57,6 +57,38 @@ static int vfat_valid_shortname(const char *,int, int, int); static int vfat_format_name(const char *, int, char *, int, int); static int vfat_valid_longname(const char *, int, int, int); +static int vfat_hashi(struct dentry *parent, struct qstr *qstr); +static int vfat_hash(struct dentry *parent, struct qstr *qstr); +static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b); +static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b); +static int vfat_revalidate(struct dentry *dentry); + +static struct dentry_operations vfat_dentry_ops[4] = { + { + NULL, /* d_revalidate */ + vfat_hashi, + vfat_cmpi, + NULL /* d_delete */ + }, + { + vfat_revalidate, + vfat_hashi, + vfat_cmpi, + NULL /* d_delete */ + }, + { + NULL, /* d_revalidate */ + vfat_hash, + vfat_cmp, + NULL /* d_delete */ + }, + { + vfat_revalidate, + vfat_hash, + vfat_cmp, + NULL /* d_delete */ + } +}; static int strnicmp(const char *s1, const char *s2, int len) { @@ -80,6 +112,13 @@ MOD_DEC_USE_COUNT; } +static int vfat_revalidate(struct dentry *dentry) +{ + if (dentry->d_time == dentry->d_parent->d_inode->i_version) { + return 1; + } + return 0; +} static struct super_operations vfat_sops = { vfat_read_inode, @@ -168,6 +207,27 @@ { const char *name; int len; + + len = qstr->len; + name = qstr->name; + while (len && name[len-1] == '.') + len--; + + qstr->hash = full_name_hash(name, len); + + return 0; +} + +/* + * Compute the hash for the vfat name corresponding to the dentry. + * Note: if the name is invalid, we leave the hash code unchanged so + * that the existing dentry can be used. The vfat fs routines will + * return ENOENT or EINVAL as appropriate. + */ +static int vfat_hashi(struct dentry *dentry, struct qstr *qstr) +{ + const char *name; + int len; char c; unsigned long hash; @@ -187,9 +247,9 @@ } /* - * Compare two vfat names. + * Case insensitive compare of two vfat names. */ -static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) +static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b) { int alen, blen; @@ -200,18 +260,33 @@ alen--; while (blen && b->name[blen-1] == '.') blen--; - if (alen != blen) - return 1; - - return strnicmp(a->name, b->name, alen); + if (alen == blen) { + if (strnicmp(a->name, b->name, alen) == 0) + return 0; + } + return 1; } -static struct dentry_operations vfat_dentry_operations = { - NULL, /* d_revalidate */ - vfat_hash, - vfat_cmp, - NULL /* d_delete */ -}; +/* + * Case sensitive compare of two vfat names. + */ +static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) +{ + int alen, blen; + + /* A filename cannot end in '.' or we treat it like it has none */ + alen = a->len; + blen = b->len; + while (alen && a->name[alen-1] == '.') + alen--; + while (blen && b->name[blen-1] == '.') + blen--; + if (alen == blen) { + if (strncmp(a->name, b->name, alen) == 0) + return 0; + } + return 1; +} struct super_block *vfat_read_super(struct super_block *sb,void *data, int silent) @@ -235,7 +310,9 @@ } else { MSDOS_SB(sb)->options.dotsOK = 0; if (MSDOS_SB(sb)->options.name_check != 's') { - sb->s_root->d_op = &vfat_dentry_operations; + sb->s_root->d_op = &vfat_dentry_ops[0]; + } else { + sb->s_root->d_op = &vfat_dentry_ops[2]; } } @@ -321,7 +398,7 @@ static int vfat_find(struct inode *dir,struct qstr* name, int find_long,int new_filename,int is_dir, - struct slot_info *sinfo_out); + struct vfat_slot_info *sinfo_out); /* Checks the validity of a long MS-DOS filename */ /* Returns negative number on error, 0 for a normal @@ -519,7 +596,7 @@ int res; int spaces; char buf[8]; - struct slot_info sinfo; + struct vfat_slot_info sinfo; const char *name_start; struct qstr qname; @@ -778,7 +855,6 @@ len--; op = outname; if (nls) { - /* XXX: i is incorrectly computed. */ for (i = 0, ip = name, op = outname, *outlen = 0; i < len && *outlen <= 260; i++, *outlen += 1) { @@ -992,7 +1068,7 @@ } static int vfat_find(struct inode *dir,struct qstr* qname, - int find_long, int new_filename,int is_dir,struct slot_info *sinfo_out) + int find_long, int new_filename,int is_dir,struct vfat_slot_info *sinfo_out) { struct super_block *sb = dir->i_sb; struct vfat_find_info vf; @@ -1118,37 +1194,36 @@ int vfat_lookup(struct inode *dir,struct dentry *dentry) { int res; - struct slot_info sinfo; + struct vfat_slot_info sinfo; struct inode *result; + int table; PRINTK (("vfat_lookup: name=%s, len=%d\n", dentry->d_name.name, dentry->d_name.len)); - if (MSDOS_SB(dir->i_sb)->options.name_check != 's') { - dentry->d_op = &vfat_dentry_operations; - } + table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0; + dentry->d_op = &vfat_dentry_ops[table]; result = NULL; if ((res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo)) < 0) { - d_add(dentry,NULL); - return 0; + result = NULL; + table++; + goto error; } PRINTK (("vfat_lookup 4.5\n")); if (!(result = iget(dir->i_sb,sinfo.ino))) return -EACCES; PRINTK (("vfat_lookup 5\n")); - if (!result->i_sb || - (result->i_sb->s_magic != MSDOS_SUPER_MAGIC)) { - /* crossed a mount point into a non-msdos fs */ - d_add(dentry,NULL); - return 0; - } if (MSDOS_I(result)->i_busy) { /* mkdir in progress */ iput(result); - d_add(dentry,NULL); - return 0; + result = NULL; + table++; + goto error; } PRINTK (("vfat_lookup 6\n")); +error: + dentry->d_op = &vfat_dentry_ops[table]; + dentry->d_time = dentry->d_parent->d_inode->i_version; d_add(dentry,result); return 0; } @@ -1162,7 +1237,7 @@ loff_t offset; struct buffer_head *bh; struct msdos_dir_entry *de; - struct slot_info sinfo; + struct vfat_slot_info sinfo; *result=0; PRINTK(("vfat_create_entry 1\n")); @@ -1210,6 +1285,7 @@ if (res < 0) { PRINTK(("vfat_create: unable to get new entry\n")); } else { + dentry->d_time = dentry->d_parent->d_inode->i_version; d_instantiate(dentry,result); } return res; @@ -1388,7 +1464,7 @@ return 0; } -static int vfat_remove_entry(struct inode *dir,struct slot_info *sinfo, +static int vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo, struct buffer_head **bh,struct dentry* dentry, int is_dir,int nospc) { @@ -1422,13 +1498,31 @@ return 0; } +static void vfat_delete_dentries(struct dentry *dentry) +{ + struct list_head *head, *next, *tmp; + struct dentry *alias; + + head = &dentry->d_inode->i_dentry; + if (dentry->d_inode) { + next = dentry->d_inode->i_dentry.next; + while (next != head) { + tmp = next; + next = tmp->next; + alias = list_entry(tmp, struct dentry, d_alias); + d_delete(alias); + } + } else { + d_delete(dentry); + } +} static int vfat_rmdirx(struct inode *dir,struct dentry* dentry) { struct super_block *sb = dir->i_sb; int res; struct buffer_head *bh; - struct slot_info sinfo; + struct vfat_slot_info sinfo; res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo); @@ -1450,7 +1544,7 @@ int res; res = vfat_rmdirx(dir, dentry); if (res >= 0) { - d_delete(dentry); + vfat_delete_dentries(dentry); } return res; } @@ -1463,7 +1557,7 @@ struct super_block *sb = dir->i_sb; int res; struct buffer_head *bh; - struct slot_info sinfo; + struct vfat_slot_info sinfo; bh = NULL; res = vfat_find(dir,&dentry->d_name,1,0,0,&sinfo); @@ -1498,6 +1592,7 @@ res = vfat_create_dotdirs(inode, dir); fat_unlock_creation(); MSDOS_I(inode)->i_busy = 0; + dentry->d_time = dentry->d_parent->d_inode->i_version; d_instantiate(dentry,inode); if (res < 0) { if (vfat_rmdir(dir,dentry) < 0) @@ -1513,7 +1608,7 @@ res = vfat_unlinkx (dir,dentry,1); if (res >= 0) { - d_delete(dentry); + vfat_delete_dentries(dentry); } return res; } @@ -1540,7 +1635,7 @@ struct dentry *walk; int res, is_dir, i; int locked = 0; - struct slot_info sinfo; + struct vfat_slot_info sinfo; PRINTK(("vfat_rename 1\n")); if (old_dir == new_dir && diff -u --recursive --new-file v2.1.79/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h --- v2.1.79/linux/include/asm-alpha/processor.h Tue Dec 2 09:49:40 1997 +++ linux/include/asm-alpha/processor.h Thu Jan 15 20:48:33 1998 @@ -93,7 +93,7 @@ /* NOTE: The task struct and the stack go together! */ #define alloc_task_struct() \ - ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) #define free_task_struct(p) free_pages((unsigned long)(p),1) #define init_task (init_task_union.task) diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/a.out.h linux/include/asm-arm/a.out.h --- v2.1.79/linux/include/asm-arm/a.out.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/a.out.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,28 @@ +#ifndef __ARM_A_OUT_H__ +#define __ARM_A_OUT_H__ + +struct exec +{ + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; + +/* + * This is always the same + */ +#define N_TXTADDR(a) (0x00008000) + +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +#define M_ARM 103 + +#include +#endif /* __A_OUT_GNU_H__ */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arcaudio.h linux/include/asm-arm/arcaudio.h --- v2.1.79/linux/include/asm-arm/arcaudio.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arcaudio.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,51 @@ +/* + * arcaudio.h + * + */ + +#ifndef _LINUX_ARCAUDIO_H +#define _LINUX_ARCAUDIO_H + +#define ARCAUDIO_MAXCHANNELS 8 + +enum ch_type +{ + ARCAUDIO_NONE, /* No sound (muted) */ + ARCAUDIO_8BITSIGNED, /* signed 8 bits per samples */ + ARCAUDIO_8BITUNSIGNED, /* unsigned 8 bits per samples */ + ARCAUDIO_16BITSIGNED, /* signed 16 bits per samples (little endian) */ + ARCAUDIO_16BITUNSIGNED, /* unsigned 16 bits per samples (little endian) */ + ARCAUDIO_LOG /* Vidc Log */ +}; + +/* + * Global information + */ +struct arcaudio +{ + int sample_rate; /* sample rate (Hz) */ + int num_channels; /* number of channels */ + int volume; /* overall system volume */ +}; + +/* + * Per channel information + */ +struct arcaudio_channel +{ + int stereo_position; /* Channel position */ + int channel_volume; /* Channel volume */ + enum ch_type channel_type; /* Type of channel */ + int buffer_size; /* Size of channel buffer */ +}; + +/* IOCTLS */ +#define ARCAUDIO_GETINFO 0x6101 +#define ARCAUDIO_SETINFO 0x6102 +#define ARCAUDIO_GETCHANNELINFO 0x6111 +#define ARCAUDIO_SETCHANNELINFO 0x6112 +#define ARCAUDIO_GETOPTS 0x61f0 +#define ARCAUDIO_SETOPTS 0x61f1 +#define ARCAUDIO_OPTSPKR 1<<0 + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/a.out.h linux/include/asm-arm/arch-a5k/a.out.h --- v2.1.79/linux/include/asm-arm/arch-a5k/a.out.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/a.out.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,16 @@ +/* + * linux/include/asm-arm/arch-a5k/a.out.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_ARCH_A_OUT_H +#define __ASM_ARCH_A_OUT_H + +#ifdef __KERNEL__ +#define STACK_TOP (0x01a00000) +#define LIBRARY_START_TEXT (0x00c00000) +#endif + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/dma.h linux/include/asm-arm/arch-a5k/dma.h --- v2.1.79/linux/include/asm-arm/arch-a5k/dma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/dma.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,101 @@ +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +#define MAX_DMA_ADDRESS 0x03000000 + +#ifdef KERNEL_ARCH_DMA + +static inline void arch_disable_dma (int dmanr) +{ + printk (dma_str, "arch_disable_dma", dmanr); +} + +static inline void arch_enable_dma (int dmanr) +{ + printk (dma_str, "arch_enable_dma", dmanr); +} + +static inline void arch_set_dma_addr (int dmanr, unsigned int addr) +{ + printk (dma_str, "arch_set_dma_addr", dmanr); +} + +static inline void arch_set_dma_count (int dmanr, unsigned int count) +{ + printk (dma_str, "arch_set_dma_count", dmanr); +} + +static inline void arch_set_dma_mode (int dmanr, char mode) +{ + printk (dma_str, "arch_set_dma_mode", dmanr); +} + +static inline int arch_dma_count (int dmanr) +{ + printk (dma_str, "arch_dma_count", dmanr); + return 0; +} + +#endif + +/* enable/disable a specific DMA channel */ +extern void enable_dma(unsigned int dmanr); + +static __inline__ void disable_dma(unsigned int dmanr) +{ + switch(dmanr) { + case 2: disable_irq(64); break; + default: printk (dma_str, "disable_dma", dmanr); break; + } +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + switch(dmanr) { + case 2: break; + default: printk (dma_str, "clear_dma_ff", dmanr); break; + } +} + +/* set mode (above) for a specific DMA channel */ +extern void set_dma_mode(unsigned int dmanr, char mode); + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + printk (dma_str, "set_dma_page", dmanr); +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +extern void set_dma_addr(unsigned int dmanr, unsigned int addr); + +/* Set transfer size for a specific DMA channel. + */ +extern void set_dma_count(unsigned int dmanr, unsigned int count); + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +extern int get_dma_residue(unsigned int dmanr); + +#endif /* _ASM_ARCH_DMA_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/hardware.h linux/include/asm-arm/arch-a5k/hardware.h --- v2.1.79/linux/include/asm-arm/arch-a5k/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/hardware.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,81 @@ +/* + * linux/include/asm-arm/arch-a5k/hardware.h + * + * Copyright (C) 1996 Russell King. + * + * This file contains the hardware definitions of the A5000 series machines. + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* + * What hardware must be present + */ +#define HAS_IOC +#define HAS_PCIO +#define HAS_MEMC +#define HAS_MEMC1A +#define HAS_VIDC + +/* + * Optional hardware + */ +#define HAS_EXPMASK + +#ifndef __ASSEMBLER__ + +/* + * for use with inb/outb + */ +#define VIDC_BASE 0x80100000 +#define IOCEC4IO_BASE 0x8009c000 +#define IOCECIO_BASE 0x80090000 +#define IOC_BASE 0x80080000 +#define MEMCECIO_BASE 0x80000000 + +/* + * IO definitions + */ +#define EXPMASK_BASE ((volatile unsigned char *)0x03360000) +#define IOEB_BASE ((volatile unsigned char *)0x03350050) +#define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0x0302a000) +#define PCIO_BASE 0x03010000 + +/* + * Mapping areas + */ +#define IO_END 0x03ffffff +#define IO_BASE 0x03000000 +#define IO_SIZE (IO_END - IO_BASE) +#define IO_START 0x03000000 + +/* + * Screen mapping information + */ +#define SCREEN2_END 0x02078000 +#define SCREEN2_BASE 0x02000000 +#define SCREEN1_END SCREEN2_BASE +#define SCREEN1_BASE 0x01f88000 +#define SCREEN_START 0x02000000 + +/* + * RAM definitions + */ +#define MAPTOPHYS(a) (((unsigned long)a & 0x007fffff) + PAGE_OFFSET) +#define KERNTOPHYS(a) ((((unsigned long)(&a)) & 0x007fffff) + PAGE_OFFSET) +#define GET_MEMORY_END(p) (PAGE_OFFSET + (p->u1.s.page_size) * (p->u1.s.nr_pages)) +#define PARAMS_BASE (PAGE_OFFSET + 0x7c000) +#define KERNEL_BASE (PAGE_OFFSET + 0x80000) + +#else + +#define IOEB_BASE 0x03350050 +#define IOC_BASE 0x03200000 +#define PCIO_FLOPPYDMABASE 0x0302a000 +#define PCIO_BASE 0x03010000 +#define IO_BASE 0x03000000 + +#endif +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/ide.h linux/include/asm-arm/arch-a5k/ide.h --- v2.1.79/linux/include/asm-arm/arch-a5k/ide.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/ide.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,44 @@ +/* + * linux/include/asm-arm/arch-a5k/ide.h + * + * Copyright (c) 1997 Russell King + */ + +static __inline__ int +ide_default_irq(ide_ioreg_t base) +{ + if (base == 0x1f0) + return 11; + return 0; +} + +static __inline__ ide_ioreg_t +ide_default_io_base(int index) +{ + if (index == 0) + return 0x1f0; + return 0; +} + +static __inline__ int +ide_default_stepping(int index) +{ + return 0; +} + +static __inline__ void +ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq) +{ + ide_ioreg_t port = base; + ide_ioreg_t ctrl = base + 0x206; + int i; + + i = 8; + while (i--) { + *p++ = port; + port += 1 << stepping; + } + *p++ = ctrl; + if (irq != NULL) + irq = 0; +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/io.h linux/include/asm-arm/arch-a5k/io.h --- v2.1.79/linux/include/asm-arm/arch-a5k/io.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/io.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,215 @@ +/* + * linux/include/asm-arm/arch-a5k/io.h + * + * Copyright (C) 1997 Russell King + * + * Modifications: + * 06-Dec-1997 RMK Created. + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an + * address suitable to be passed to set_dma_addr + * bus_to_virt: Used to convert an address for DMA operations + * to an address that the kernel can use. + */ +#define virt_to_bus(x) ((unsigned long)(x)) +#define bus_to_virt(x) ((void *)(x)) + +/* + * This architecture does not require any delayed IO, and + * has the constant-optimised IO + */ +#undef ARCH_IO_DELAY + +/* + * We use two different types of addressing - PC style addresses, and ARM + * addresses. PC style accesses the PC hardware with the normal PC IO + * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ + * and are translated to the start of IO. Note that all addresses are + * shifted left! + */ +#define __PORT_PCIO(x) (!((x) & 0x80000000)) + +/* + * Dynamic IO functions - let the compiler + * optimize the expressions + */ +extern __inline__ void __outb (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "strb %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +extern __inline__ void __outw (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "str %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +extern __inline__ void __outl (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "str %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +#define DECLARE_DYN_IN(sz,fnsuffix,instr) \ +extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \ +{ \ + unsigned long temp, value; \ + __asm__ __volatile__( \ + "tst %2, #0x80000000\n\t" \ + "mov %0, %4\n\t" \ + "addeq %0, %0, %3\n\t" \ + "ldr" ##instr## " %1, [%0, %2, lsl #2]" \ + : "=&r" (temp), "=r" (value) \ + : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ + : "cc"); \ + return (unsigned sz)value; \ +} + +extern __inline__ unsigned int __ioaddr (unsigned int port) \ +{ \ + if (__PORT_PCIO(port)) \ + return (unsigned int)(PCIO_BASE + (port << 2)); \ + else \ + return (unsigned int)(IO_BASE + (port << 2)); \ +} + +#define DECLARE_IO(sz,fnsuffix,instr) \ + DECLARE_DYN_IN(sz,fnsuffix,instr) + +DECLARE_IO(char,b,"b") +DECLARE_IO(short,w,"") +DECLARE_IO(long,l,"") + +#undef DECLARE_IO +#undef DECLARE_DYN_IN + +/* + * Constant address IO functions + * + * These have to be macros for the 'J' constraint to work - + * +/-4096 immediate operand. + */ +#define __outbc(value,port) \ +({ \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inbc(port) \ +({ \ + unsigned char result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __outwc(value,port) \ +({ \ + unsigned long v = value; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inwc(port) \ +({ \ + unsigned short result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result & 0xffff; \ +}) + +#define __outlc(v,p) __outwc((v),(p)) + +#define __inlc(port) \ +({ \ + unsigned long result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __ioaddrc(port) \ +({ \ + unsigned long addr; \ + if (__PORT_PCIO((port))) \ + addr = PCIO_BASE + ((port) << 2); \ + else \ + addr = IO_BASE + ((port) << 2); \ + addr; \ +}) + +/* + * Translated address IO functions + * + * IO address has already been translated to a virtual address + */ +#define outb_t(v,p) \ + (*(volatile unsigned char *)(p) = (v)) + +#define inb_t(p) \ + (*(volatile unsigned char *)(p)) + +#define outl_t(v,p) \ + (*(volatile unsigned long *)(p) = (v)) + +#define inl_t(p) \ + (*(volatile unsigned long *)(p)) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/irq.h linux/include/asm-arm/arch-a5k/irq.h --- v2.1.79/linux/include/asm-arm/arch-a5k/irq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/irq.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,130 @@ +/* + * include/asm-arm/arch-a5k/irq.h + * + * Copyright (C) 1996 Russell King + * + * Changelog: + * 24-09-1996 RMK Created + * 10-10-1996 RMK Brought up to date with arch-sa110eval + * 22-10-1996 RMK Changed interrupt numbers & uses new inb/outb macros + * 11-01-1998 RMK Added mask_and_ack_irq + */ + +#define BUILD_IRQ(s,n,m) \ + void IRQ##n##_interrupt(void); \ + void fast_IRQ##n##_interrupt(void); \ + void bad_IRQ##n##_interrupt(void); \ + void probe_IRQ##n##_interrupt(void); + +/* + * The timer is a special interrupt + */ +#define IRQ5_interrupt timer_IRQ_interrupt + +#define IRQ_INTERRUPT(n) IRQ##n##_interrupt +#define FAST_INTERRUPT(n) fast_IRQ##n##_interrupt +#define BAD_INTERRUPT(n) bad_IRQ##n##_interrupt +#define PROBE_INTERRUPT(n) probe_IRQ##n##_interrupt + +#define X(x) (x)|0x01, (x)|0x02, (x)|0x04, (x)|0x08, (x)|0x10, (x)|0x20, (x)|0x40, (x)|0x80 +#define Z(x) (x), (x), (x), (x), (x), (x), (x), (x) + +static __inline__ void mask_and_ack_irq(unsigned int irq) +{ + static const int addrmasks[] = { + X((IOC_IRQMASKA - IOC_BASE)<<18 | (1 << 15)), + X((IOC_IRQMASKB - IOC_BASE)<<18), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + X((IOC_FIQMASK - IOC_BASE)<<18), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0) + }; + unsigned int temp1, temp2; + + __asm__ __volatile__( +" ldr %1, [%5, %3, lsl #2]\n" +" teq %1, #0\n" +" beq 2f\n" +" ldrb %0, [%2, %1, lsr #16]\n" +" bic %0, %0, %1\n" +" strb %0, [%2, %1, lsr #16]\n" +" tst %1, #0x8000\n" /* do we need an IRQ clear? */ +" strneb %1, [%2, %4]\n" +"2:" + : "=&r" (temp1), "=&r" (temp2) + : "r" (ioaddr(IOC_BASE)), "r" (irq), + "I" ((IOC_IRQCLRA - IOC_BASE) << 2), "r" (addrmasks)); +} + +#undef X +#undef Z + +static __inline__ void mask_irq(unsigned int irq) +{ + extern void ecard_disableirq (unsigned int); + extern void ecard_disablefiq (unsigned int); + unsigned char mask = 1 << (irq & 7); + + switch (irq >> 3) { + case 0: + outb(inb(IOC_IRQMASKA) & ~mask, IOC_IRQMASKA); + break; + case 1: + outb(inb(IOC_IRQMASKB) & ~mask, IOC_IRQMASKB); + break; + case 4: + ecard_disableirq (irq & 7); + break; + case 8: + outb(inb(IOC_FIQMASK) & ~mask, IOC_FIQMASK); + break; + case 12: + ecard_disablefiq (irq & 7); + } +} + +static __inline__ void unmask_irq(unsigned int irq) +{ + extern void ecard_enableirq (unsigned int); + extern void ecard_enablefiq (unsigned int); + unsigned char mask = 1 << (irq & 7); + + switch (irq >> 3) { + case 0: + outb(inb(IOC_IRQMASKA) | mask, IOC_IRQMASKA); + break; + case 1: + outb(inb(IOC_IRQMASKB) | mask, IOC_IRQMASKB); + break; + case 4: + ecard_enableirq (irq & 7); + break; + case 8: + outb(inb(IOC_FIQMASK) | mask, IOC_FIQMASK); + break; + case 12: + ecard_enablefiq (irq & 7); + } +} + +static __inline__ unsigned long get_enabled_irqs(void) +{ + return inb(IOC_IRQMASKA) | inb(IOC_IRQMASKB) << 8; +} + +static __inline__ void irq_init_irq(void) +{ + outb(0, IOC_IRQMASKA); + outb(0, IOC_IRQMASKB); + outb(0, IOC_FIQMASK); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/irqs.h linux/include/asm-arm/arch-a5k/irqs.h --- v2.1.79/linux/include/asm-arm/arch-a5k/irqs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/irqs.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,28 @@ +/* + * linux/include/asm-arm/arch-a5k/irqs.h + * + * Copyright (C) 1996 Russell King + */ + +#define IRQ_PRINTER 0 +#define IRQ_BATLOW 1 +#define IRQ_FLOPPYINDEX 2 +#define IRQ_VSYNCPULSE 3 +#define IRQ_POWERON 4 +#define IRQ_TIMER0 5 +#define IRQ_TIMER1 6 +#define IRQ_IMMEDIATE 7 +#define IRQ_EXPCARDFIQ 8 +#define IRQ_SOUNDCHANGE 9 +#define IRQ_SERIALPORT 10 +#define IRQ_HARDDISK 11 +#define IRQ_FLOPPYDISK 12 +#define IRQ_EXPANSIONCARD 13 +#define IRQ_KEYBOARDTX 14 +#define IRQ_KEYBOARDRX 15 + +#define FIQ_FLOPPYDATA 0 +#define FIQ_ECONET 2 +#define FIQ_SERIALPORT 4 +#define FIQ_EXPANSIONCARD 6 +#define FIQ_FORCE 7 diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/mmu.h linux/include/asm-arm/arch-a5k/mmu.h --- v2.1.79/linux/include/asm-arm/arch-a5k/mmu.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/mmu.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-arm/arch-a5k/mmu.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 22-11-1996 RMK Created + */ +#ifndef __ASM_ARCH_MMU_H +#define __ASM_ARCH_MMU_H + +#define __virt_to_phys(vpage) vpage +#define __phys_to_virt(ppage) ppage + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/oldlatches.h linux/include/asm-arm/arch-a5k/oldlatches.h --- v2.1.79/linux/include/asm-arm/arch-a5k/oldlatches.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/oldlatches.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,9 @@ +/* + * Dummy oldlatches.h + * + * Copyright (C) 1996 Russell King + */ + +#ifdef __need_oldlatches +#error "Old latches not present in this (a5k) machine" +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/processor.h linux/include/asm-arm/arch-a5k/processor.h --- v2.1.79/linux/include/asm-arm/arch-a5k/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/processor.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,34 @@ +/* + * linux/include/asm-arm/arch-a5k/processor.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 10-09-1996 RMK Created + */ + +#ifndef __ASM_ARCH_PROCESSOR_H +#define __ASM_ARCH_PROCESSOR_H + +/* + * Bus types + */ +#define EISA_bus 0 +#define EISA_bus__is_a_macro /* for versions in ksyms.c */ +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* + * User space: 26MB + */ +#define TASK_SIZE (0x01a00000UL) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +#define INIT_MMAP \ +{ &init_mm, 0, 0x02000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/serial.h linux/include/asm-arm/arch-a5k/serial.h --- v2.1.79/linux/include/asm-arm/arch-a5k/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/serial.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,40 @@ +/* + * linux/include/asm-arm/arch-a5k/serial.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 15-10-1996 RMK Created + */ +#ifndef __ASM_ARCH_SERIAL_H +#define __ASM_ARCH_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD (1843200 / 16) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + + /* UART CLK PORT IRQ FLAGS */ +#define RS_UARTS \ + { 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/shmparam.h linux/include/asm-arm/arch-a5k/shmparam.h --- v2.1.79/linux/include/asm-arm/arch-a5k/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/shmparam.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,5 @@ +/* + * linux/include/asm-arm/arch-a5k/shmparam.h + * + * Copyright (c) 1996 Russell King. + */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/system.h linux/include/asm-arm/arch-a5k/system.h --- v2.1.79/linux/include/asm-arm/arch-a5k/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/system.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,30 @@ +/* + * linux/include/asm-arm/arch-a5k/system.h + * + * Copyright (c) 1996 Russell King + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +extern __inline__ void arch_hard_reset (void) +{ + extern void ecard_reset (int card); + + /* + * Reset all expansion cards. + */ + ecard_reset (-1); + + /* + * copy branch instruction to reset location and call it + */ + *(unsigned long *)0 = *(unsigned long *)0x03800000; + ((void(*)(void))0)(); + + /* + * If that didn't work, loop endlessly + */ + while (1); +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/time.h linux/include/asm-arm/arch-a5k/time.h --- v2.1.79/linux/include/asm-arm/arch-a5k/time.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/time.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,96 @@ +/* + * linux/include/asm-arm/arch-a5k/time.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 24-Sep-1996 RMK Created + * 10-Oct-1996 RMK Brought up to date with arch-sa110eval + * 04-Dec-1997 RMK Updated for new arch/arm/time.c + */ + +extern __inline__ unsigned long gettimeoffset (void) +{ + unsigned int count1, count2, status1, status2; + unsigned long offset = 0; + + status1 = IOC_IRQREQA; + barrier (); + outb (0, IOC_T0LATCH); + barrier (); + count1 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8); + barrier (); + status2 = inb(IOC_IRQREQA); + barrier (); + outb (0, IOC_T0LATCH); + barrier (); + count2 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8); + + if (count2 < count1) { + /* + * This means that we haven't just had an interrupt + * while reading into status2. + */ + if (status2 & (1 << 5)) + offset = tick; + count1 = count2; + } else if (count2 > count1) { + /* + * We have just had another interrupt while reading + * status2. + */ + offset += tick; + count1 = count2; + } + + count1 = LATCH - count1; + /* + * count1 = number of clock ticks since last interrupt + */ + offset += count1 * tick / LATCH; + return offset; +} + +/* + * No need to reset the timer at every irq + */ +#define reset_timer() 1 + +/* + * Updating of the RTC. We don't currently write the time to the + * CMOS clock. + */ +#define update_rtc() + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +extern __inline__ unsigned long setup_timer (void) +{ + extern int iic_control (unsigned char, int, char *, int); + unsigned int year, mon, day, hour, min, sec; + char buf[8]; + + outb(LATCH & 255, IOC_T0LTCHL); + outb(LATCH >> 8, IOC_T0LTCHH); + outb(0, IOC_T0GO); + + iic_control (0xa0, 0xc0, buf, 1); + year = buf[0]; + if ((year += 1900) < 1970) + year += 100; + + iic_control (0xa0, 2, buf, 5); + mon = buf[4] & 0x1f; + day = buf[3] & 0x3f; + hour = buf[2]; + min = buf[1]; + sec = buf[0]; + BCD_TO_BIN(mon); + BCD_TO_BIN(day); + BCD_TO_BIN(hour); + BCD_TO_BIN(min); + BCD_TO_BIN(sec); + + return mktime(year, mon, day, hour, min, sec); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/timex.h linux/include/asm-arm/arch-a5k/timex.h --- v2.1.79/linux/include/asm-arm/arch-a5k/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/timex.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,13 @@ +/* + * linux/include/asm-arm/arch-a5k/timex.h + * + * A5000 architecture timex specifications + * + * Copyright (C) 1997, 1998 Russell King + */ + +/* + * On the RiscPC, the clock ticks at 2MHz. + */ +#define CLOCK_TICK_RATE 2000000 + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-a5k/uncompress.h linux/include/asm-arm/arch-a5k/uncompress.h --- v2.1.79/linux/include/asm-arm/arch-a5k/uncompress.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-a5k/uncompress.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,104 @@ +/* + * linux/include/asm-arm/arch-a5k/uncompress.h + * + * Copyright (C) 1996 Russell King + */ +#define VIDMEM ((char *)0x02000000) + +#include "../arch/arm/drivers/char/font.h" + +int video_num_columns, video_num_lines, video_size_row; +int white, bytes_per_char_h; +extern unsigned long con_charconvtable[256]; + +struct param_struct { + unsigned long page_size; + unsigned long nr_pages; + unsigned long ramdisk_size; + unsigned long mountrootrdonly; + unsigned long rootdev; + unsigned long video_num_cols; + unsigned long video_num_rows; + unsigned long video_x; + unsigned long video_y; + unsigned long memc_control_reg; + unsigned char sounddefault; + unsigned char adfsdrives; + unsigned char bytes_per_char_h; + unsigned char bytes_per_char_v; + unsigned long unused[256/4-11]; +}; + +static struct param_struct *params = (struct param_struct *)0x0207c000; + +/* + * This does not append a newline + */ +static void puts(const char *s) +{ + extern void ll_write_char(char *, unsigned long); + int x,y; + unsigned char c; + char *ptr; + + x = params->video_x; + y = params->video_y; + + while ( ( c = *(unsigned char *)s++ ) != '\0' ) { + if ( c == '\n' ) { + x = 0; + if ( ++y >= video_num_lines ) { + y--; + } + } else { + ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h); + ll_write_char(ptr, c|(white<<8)); + if ( ++x >= video_num_columns ) { + x = 0; + if ( ++y >= video_num_lines ) { + y--; + } + } + } + } + + params->video_x = x; + params->video_y = y; +} + +static void error(char *x); + +/* + * Setup for decompression + */ +static void arch_decomp_setup(void) +{ + int i; + + video_num_lines = params->video_num_rows; + video_num_columns = params->video_num_cols; + bytes_per_char_h = params->bytes_per_char_h; + video_size_row = video_num_columns * bytes_per_char_h; + if (bytes_per_char_h == 4) + for (i = 0; i < 256; i++) + con_charconvtable[i] = + (i & 128 ? 1 << 0 : 0) | + (i & 64 ? 1 << 4 : 0) | + (i & 32 ? 1 << 8 : 0) | + (i & 16 ? 1 << 12 : 0) | + (i & 8 ? 1 << 16 : 0) | + (i & 4 ? 1 << 20 : 0) | + (i & 2 ? 1 << 24 : 0) | + (i & 1 ? 1 << 28 : 0); + else + for (i = 0; i < 16; i++) + con_charconvtable[i] = + (i & 8 ? 1 << 0 : 0) | + (i & 4 ? 1 << 8 : 0) | + (i & 2 ? 1 << 16 : 0) | + (i & 1 ? 1 << 24 : 0); + + white = bytes_per_char_h == 8 ? 0xfc : 7; + + if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n"); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/a.out.h linux/include/asm-arm/arch-arc/a.out.h --- v2.1.79/linux/include/asm-arm/arch-arc/a.out.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/a.out.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,16 @@ +/* + * linux/include/asm-arm/arch-arc/a.out.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_ARCH_A_OUT_H +#define __ASM_ARCH_A_OUT_H + +#ifdef __KERNEL__ +#define STACK_TOP (0x01a00000) +#define LIBRARY_START_TEXT (0x00c00000) +#endif + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/dma.h linux/include/asm-arm/arch-arc/dma.h --- v2.1.79/linux/include/asm-arm/arch-arc/dma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/dma.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,95 @@ +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +#define MAX_DMA_ADDRESS 0x03000000 + +#ifdef KERNEL_ARCH_DMA + +static inline void arch_disable_dma (int dmanr) +{ + printk (dma_str, "arch_disable_dma", dmanr); +} + +static inline void arch_enable_dma (int dmanr) +{ + printk (dma_str, "arch_enable_dma", dmanr); +} + +static inline void arch_set_dma_addr (int dmanr, unsigned int addr) +{ + printk (dma_str, "arch_set_dma_addr", dmanr); +} + +static inline void arch_set_dma_count (int dmanr, unsigned int count) +{ + printk (dma_str, "arch_set_dma_count", dmanr); +} + +static inline void arch_set_dma_mode (int dmanr, char mode) +{ + printk (dma_str, "arch_set_dma_mode", dmanr); +} + +static inline int arch_dma_count (int dmanr) +{ + printk (dma_str, "arch_dma_count", dmanr); + return 0; +} + +#endif + +/* enable/disable a specific DMA channel */ +extern void enable_dma(unsigned int dmanr); + +static __inline__ void disable_dma(unsigned int dmanr) +{ + switch(dmanr) { + case 0: disable_irq(64); break; + case 1: break; + default: printk (dma_str, "disable_dma", dmanr); break; + } +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +#define clear_dma_ff(dmanr) + +/* set mode (above) for a specific DMA channel */ +extern void set_dma_mode(unsigned int dmanr, char mode); + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + printk (dma_str, "set_dma_page", dmanr); +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +extern void set_dma_addr(unsigned int dmanr, unsigned int addr); + +/* Set transfer size for a specific DMA channel. + */ +extern void set_dma_count(unsigned int dmanr, unsigned int count); + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +extern int get_dma_residue(unsigned int dmanr); + +#endif /* _ASM_ARCH_DMA_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/hardware.h linux/include/asm-arm/arch-arc/hardware.h --- v2.1.79/linux/include/asm-arm/arch-arc/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/hardware.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,82 @@ +/* + * linux/include/asm-arm/arch-arc/hardware.h + * + * Copyright (C) 1996 Russell King. + * + * This file contains the hardware definitions of the A3/4/5xx series machines. + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* + * What hardware must be present + */ +#define HAS_IOC +#define HAS_MEMC +#define HAS_MEMC1A +#define HAS_VIDC + +/* + * Optional hardware + */ +#define HAS_EXPMASK + +#ifndef __ASSEMBLER__ + +/* + * for use with inb/outb + */ +#define VIDC_BASE 0x80100000 +#define IOCEC4IO_BASE 0x8009c000 +#define LATCHAADDR 0x80094010 +#define LATCHBADDR 0x80094006 +#define IOCECIO_BASE 0x80090000 +#define IOC_BASE 0x80080000 +#define MEMCECIO_BASE 0x80000000 + +/* + * IO definitions + */ +#define EXPMASK_BASE ((volatile unsigned char *)0x03360000) +#define IOEB_BASE ((volatile unsigned char *)0x03350050) +#define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0x0302a000) +#define PCIO_BASE 0x03010000 + +/* + * Mapping areas + */ +#define IO_END 0x03ffffff +#define IO_BASE 0x03000000 +#define IO_SIZE (IO_END - IO_BASE) +#define IO_START 0x03000000 + +/* + * Screen mapping information + */ +#define SCREEN2_END 0x02078000 +#define SCREEN2_BASE 0x02000000 +#define SCREEN1_END SCREEN2_BASE +#define SCREEN1_BASE 0x01f88000 +#define SCREEN_START 0x02000000 + +/* + * RAM definitions + */ +#define MAPTOPHYS(a) (((unsigned long)a & 0x007fffff) + PAGE_OFFSET) +#define KERNTOPHYS(a) ((((unsigned long)(&a)) & 0x007fffff) + PAGE_OFFSET) +#define GET_MEMORY_END(p) (PAGE_OFFSET + (p->u1.s.page_size) * (p->u1.s.nr_pages)) +#define PARAMS_BASE (PAGE_OFFSET + 0x7c000) +#define KERNEL_BASE (PAGE_OFFSET + 0x80000) + +#else + +#define IOEB_BASE 0x03350050 +#define IOC_BASE 0x03200000 +#define PCIO_FLOPPYDMABASE 0x0302a000 +#define PCIO_BASE 0x03010000 +#define IO_BASE 0x03000000 + +#endif +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/ide.h linux/include/asm-arm/arch-arc/ide.h --- v2.1.79/linux/include/asm-arm/arch-arc/ide.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/ide.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,40 @@ +/* + * linux/include/asm-arm/arch-arc/ide.h + * + * Copyright (c) 1997,1998 Russell King + */ + +static __inline__ int +ide_default_irq(ide_ioreg_t base) +{ + return 0; +} + +static __inline__ ide_ioreg_t +ide_default_io_base(int index) +{ + return 0; +} + +static __inline__ int +ide_default_stepping(int index) +{ + return 0; +} + +static __inline__ void +ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq) +{ + ide_ioreg_t port = base; + ide_ioreg_t ctrl = base + 0x206; + int i; + + i = 8; + while (i--) { + *p++ = port; + port += 1 << stepping; + } + *p++ = ctrl; + if (irq != NULL) + irq = 0; +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/io.h linux/include/asm-arm/arch-arc/io.h --- v2.1.79/linux/include/asm-arm/arch-arc/io.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/io.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,215 @@ +/* + * linux/include/asm-arm/arch-arc/io.h + * + * Copyright (C) 1997 Russell King + * + * Modifications: + * 06-Dec-1997 RMK Created. + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an + * address suitable to be passed to set_dma_addr + * bus_to_virt: Used to convert an address for DMA operations + * to an address that the kernel can use. + */ +#define virt_to_bus(x) ((unsigned long)(x)) +#define bus_to_virt(x) ((void *)(x)) + +/* + * This architecture does not require any delayed IO, and + * has the constant-optimised IO + */ +#undef ARCH_IO_DELAY + +/* + * We use two different types of addressing - PC style addresses, and ARM + * addresses. PC style accesses the PC hardware with the normal PC IO + * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ + * and are translated to the start of IO. Note that all addresses are + * shifted left! + */ +#define __PORT_PCIO(x) (!((x) & 0x80000000)) + +/* + * Dynamic IO functions - let the compiler + * optimize the expressions + */ +extern __inline__ void __outb (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "strb %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +extern __inline__ void __outw (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "strb %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +extern __inline__ void __outl (unsigned int value, unsigned int port) +{ + unsigned long temp; + __asm__ __volatile__( + "tst %2, #0x80000000\n\t" + "mov %0, %4\n\t" + "addeq %0, %0, %3\n\t" + "strb %1, [%0, %2, lsl #2]" + : "=&r" (temp) + : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) + : "cc"); +} + +#define DECLARE_DYN_IN(sz,fnsuffix,instr) \ +extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \ +{ \ + unsigned long temp, value; \ + __asm__ __volatile__( \ + "tst %2, #0x80000000\n\t" \ + "mov %0, %4\n\t" \ + "addeq %0, %0, %3\n\t" \ + "ldr" ##instr## " %1, [%0, %2, lsl #2]" \ + : "=&r" (temp), "=r" (value) \ + : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ + : "cc"); \ + return (unsigned sz)value; \ +} + +extern __inline__ unsigned int __ioaddr (unsigned int port) \ +{ \ + if (__PORT_PCIO(port)) \ + return (unsigned int)(PCIO_BASE + (port << 2)); \ + else \ + return (unsigned int)(IO_BASE + (port << 2)); \ +} + +#define DECLARE_IO(sz,fnsuffix,instr) \ + DECLARE_DYN_IN(sz,fnsuffix,instr) + +DECLARE_IO(char,b,"b") +DECLARE_IO(short,w,"") +DECLARE_IO(long,l,"") + +#undef DECLARE_IO +#undef DECLARE_DYN_IN + +/* + * Constant address IO functions + * + * These have to be macros for the 'J' constraint to work - + * +/-4096 immediate operand. + */ +#define __outbc(value,port) \ +({ \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inbc(port) \ +({ \ + unsigned char result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __outwc(value,port) \ +({ \ + unsigned long v = value; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inwc(port) \ +({ \ + unsigned short result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result & 0xffff; \ +}) + +#define __outlc(v,p) __outwc((v),(p)) + +#define __inlc(port) \ +({ \ + unsigned long result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __ioaddrc(port) \ +({ \ + unsigned long addr; \ + if (__PORT_PCIO((port))) \ + addr = PCIO_BASE + ((port) << 2); \ + else \ + addr = IO_BASE + ((port) << 2); \ + addr; \ +}) + +/* + * Translated address IO functions + * + * IO address has already been translated to a virtual address + */ +#define outb_t(v,p) \ + (*(volatile unsigned char *)(p) = (v)) + +#define inb_t(p) \ + (*(volatile unsigned char *)(p)) + +#define outl_t(v,p) \ + (*(volatile unsigned long *)(p) = (v)) + +#define inl_t(p) \ + (*(volatile unsigned long *)(p)) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/irq.h linux/include/asm-arm/arch-arc/irq.h --- v2.1.79/linux/include/asm-arm/arch-arc/irq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/irq.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,130 @@ +/* + * include/asm-arm/arch-arc/irq.h + * + * Copyright (C) 1996 Russell King + * + * Changelog: + * 24-09-1996 RMK Created + * 10-10-1996 RMK Brought up to date with arch-sa110eval + * 05-11-1996 RMK Changed interrupt numbers & uses new inb/outb macros + * 11-01-1998 RMK Added mask_and_ack_irq + */ + +#define BUILD_IRQ(s,n,m) \ + void IRQ##n##_interrupt(void); \ + void fast_IRQ##n##_interrupt(void); \ + void bad_IRQ##n##_interrupt(void); \ + void probe_IRQ##n##_interrupt(void); + +/* + * The timer is a special interrupt + */ +#define IRQ5_interrupt timer_IRQ_interrupt + +#define IRQ_INTERRUPT(n) IRQ##n##_interrupt +#define FAST_INTERRUPT(n) fast_IRQ##n##_interrupt +#define BAD_INTERRUPT(n) bad_IRQ##n##_interrupt +#define PROBE_INTERRUPT(n) probe_IRQ##n##_interrupt + +#define X(x) (x)|0x01, (x)|0x02, (x)|0x04, (x)|0x08, (x)|0x10, (x)|0x20, (x)|0x40, (x)|0x80 +#define Z(x) (x), (x), (x), (x), (x), (x), (x), (x) + +static __inline__ void mask_and_ack_irq(unsigned int irq) +{ + static const int addrmasks[] = { + X((IOC_IRQMASKA - IOC_BASE)<<18 | (1 << 15)), + X((IOC_IRQMASKB - IOC_BASE)<<18), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + X((IOC_FIQMASK - IOC_BASE)<<18), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0) + }; + unsigned int temp1, temp2; + + __asm__ __volatile__( +" ldr %1, [%5, %3, lsl #2]\n" +" teq %1, #0\n" +" beq 2f\n" +" ldrb %0, [%2, %1, lsr #16]\n" +" bic %0, %0, %1\n" +" strb %0, [%2, %1, lsr #16]\n" +" tst %1, #0x8000\n" /* do we need an IRQ clear? */ +" strneb %1, [%2, %4]\n" +"2:" + : "=&r" (temp1), "=&r" (temp2) + : "r" (ioaddr(IOC_BASE)), "r" (irq), + "I" ((IOC_IRQCLRA - IOC_BASE) << 2), "r" (addrmasks)); +} + +#undef X +#undef Z + +static __inline__ void mask_irq(unsigned int irq) +{ + extern void ecard_disableirq (unsigned int); + extern void ecard_disablefiq (unsigned int); + unsigned char mask = 1 << (irq & 7); + + switch (irq >> 3) { + case 0: + outb(inb(IOC_IRQMASKA) & ~mask, IOC_IRQMASKA); + break; + case 1: + outb(inb(IOC_IRQMASKB) & ~mask, IOC_IRQMASKB); + break; + case 4: + ecard_disableirq (irq & 7); + break; + case 8: + outb(inb(IOC_FIQMASK) & ~mask, IOC_FIQMASK); + break; + case 12: + ecard_disablefiq (irq & 7); + } +} + +static __inline__ void unmask_irq(unsigned int irq) +{ + extern void ecard_enableirq (unsigned int); + extern void ecard_enablefiq (unsigned int); + unsigned char mask = 1 << (irq & 7); + + switch (irq >> 3) { + case 0: + outb(inb(IOC_IRQMASKA) | mask, IOC_IRQMASKA); + break; + case 1: + outb(inb(IOC_IRQMASKB) | mask, IOC_IRQMASKB); + break; + case 4: + ecard_enableirq (irq & 7); + break; + case 8: + outb(inb(IOC_FIQMASK) | mask, IOC_FIQMASK); + break; + case 12: + ecard_enablefiq (irq & 7); + } +} + +static __inline__ unsigned long get_enabled_irqs(void) +{ + return inb(IOC_IRQMASKA) | inb(IOC_IRQMASKB) << 8; +} + +static __inline__ void irq_init_irq(void) +{ + outb(0, IOC_IRQMASKA); + outb(0, IOC_IRQMASKB); + outb(0, IOC_FIQMASK); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/irqs.h linux/include/asm-arm/arch-arc/irqs.h --- v2.1.79/linux/include/asm-arm/arch-arc/irqs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/irqs.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,30 @@ +/* + * linux/include/asm-arm/arch-arc/irqs.h + * + * Copyright (C) 1996 Russell King, Dave Gilbert (gilbertd@cs.man.ac.uk) + */ + +#define IRQ_PRINTERBUSY 0 +#define IRQ_SERIALRING 1 +#define IRQ_PRINTERACK 2 +#define IRQ_VSYNCPULSE 3 +#define IRQ_POWERON 4 +#define IRQ_TIMER0 5 +#define IRQ_TIMER1 6 +#define IRQ_IMMEDIATE 7 +#define IRQ_EXPCARDFIQ 8 +#define IRQ_SOUNDCHANGE 9 +#define IRQ_SERIALPORT 10 +#define IRQ_HARDDISK 11 +#define IRQ_FLOPPYCHANGED 12 +#define IRQ_EXPANSIONCARD 13 +#define IRQ_KEYBOARDTX 14 +#define IRQ_KEYBOARDRX 15 + +#define FIQ_FLOPPYDATA 0 +#define FIQ_FLOPPYIRQ 1 +#define FIQ_ECONET 2 +#define FIQ_EXPANSIONCARD 6 +#define FIQ_FORCE 7 + +#define FIQ_FD1772 FIQ_FLOPPYIRQ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/mmu.h linux/include/asm-arm/arch-arc/mmu.h --- v2.1.79/linux/include/asm-arm/arch-arc/mmu.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/mmu.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-arm/arch-arc/mmu.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 22-11-1996 RMK Created + */ +#ifndef __ASM_ARCH_MMU_H +#define __ASM_ARCH_MMU_H + +#define __virt_to_phys(vpage) vpage +#define __phys_to_virt(ppage) ppage + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/oldlatches.h linux/include/asm-arm/arch-arc/oldlatches.h --- v2.1.79/linux/include/asm-arm/arch-arc/oldlatches.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/oldlatches.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,24 @@ +#ifndef _ASM_ARM_ARCHARC_OLDLATCH_H +#define _ASM_ARM_ARCHARC_OLDLATCH_H + +#define LATCHA_FDSEL0 (1<<0) +#define LATCHA_FDSEL1 (1<<1) +#define LATCHA_FDSEL2 (1<<2) +#define LATCHA_FDSEL3 (1<<3) +#define LATCHA_FDSELALL (0xf) +#define LATCHA_SIDESEL (1<<4) +#define LATCHA_MOTOR (1<<5) +#define LATCHA_INUSE (1<<6) +#define LATCHA_CHANGERST (1<<7) + +#define LATCHB_FDCDENSITY (1<<1) +#define LATCHB_FDCRESET (1<<3) +#define LATCHB_PRINTSTROBE (1<<4) + +/* newval=(oldval & mask)|newdata */ +void oldlatch_bupdate(unsigned char mask,unsigned char newdata); + +/* newval=(oldval & mask)|newdata */ +void oldlatch_aupdate(unsigned char mask,unsigned char newdata); + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/processor.h linux/include/asm-arm/arch-arc/processor.h --- v2.1.79/linux/include/asm-arm/arch-arc/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/processor.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,34 @@ +/* + * linux/include/asm-arm/arch-arc/processor.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 10-09-1996 RMK Created + */ + +#ifndef __ASM_ARCH_PROCESSOR_H +#define __ASM_ARCH_PROCESSOR_H + +/* + * Bus types + */ +#define EISA_bus 0 +#define EISA_bus__is_a_macro /* for versions in ksyms.c */ +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* + * User space: 26MB + */ +#define TASK_SIZE (0x01a00000UL) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +#define INIT_MMAP \ +{ &init_mm, 0, 0x02000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/serial.h linux/include/asm-arm/arch-arc/serial.h --- v2.1.79/linux/include/asm-arm/arch-arc/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/serial.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,40 @@ +/* + * linux/include/asm-arm/arch-arc/serial.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 15-10-1996 RMK Created + */ +#ifndef __ASM_ARCH_SERIAL_H +#define __ASM_ARCH_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD (1843200 / 16) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + + /* UART CLK PORT IRQ FLAGS */ +#define RS_UARTS \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/shmparam.h linux/include/asm-arm/arch-arc/shmparam.h --- v2.1.79/linux/include/asm-arm/arch-arc/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/shmparam.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,5 @@ +/* + * linux/include/asm-arm/arch-arc/shmparam.h + * + * Copyright (c) 1996 Russell King. + */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/system.h linux/include/asm-arm/arch-arc/system.h --- v2.1.79/linux/include/asm-arm/arch-arc/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/system.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,41 @@ +/* + * linux/include/asm-arm/arch-arc/system.h + * + * Copyright (c) 1996 Russell King and Dave Gilbert + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#define cliIF() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" orr %0, %0, #0x0c000000\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : ); \ + } while(0) + +extern __inline__ void arch_hard_reset (void) +{ + extern void ecard_reset (int card); + + /* + * Reset all expansion cards. + */ + ecard_reset (-1); + + /* + * copy branch instruction to reset location and call it + */ + *(unsigned long *)0 = *(unsigned long *)0x03800000; + ((void(*)(void))0)(); + + /* + * If that didn't work, loop endlessly + */ + while (1); +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/time.h linux/include/asm-arm/arch-arc/time.h --- v2.1.79/linux/include/asm-arm/arch-arc/time.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/time.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,96 @@ +/* + * linux/include/asm-arm/arch-arc/time.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 24-Sep-1996 RMK Created + * 10-Oct-1996 RMK Brought up to date with arch-sa110eval + * 04-Dec-1997 RMK Updated for new arch/arm/time.c + */ + +extern __inline__ unsigned long gettimeoffset (void) +{ + unsigned int count1, count2, status1, status2; + unsigned long offset = 0; + + status1 = inb(IOC_IRQREQA); + barrier (); + outb (0, IOC_T0LATCH); + barrier (); + count1 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8); + barrier (); + status2 = inb(IOC_IRQREQA); + barrier (); + outb (0, IOC_T0LATCH); + barrier (); + count2 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8); + + if (count2 < count1) { + /* + * This means that we haven't just had an interrupt + * while reading into status2. + */ + if (status2 & (1 << 5)) + offset = tick; + count1 = count2; + } else if (count2 > count1) { + /* + * We have just had another interrupt while reading + * status2. + */ + offset += tick; + count1 = count2; + } + + count1 = LATCH - count1; + /* + * count1 = number of clock ticks since last interrupt + */ + offset += count1 * tick / LATCH; + return offset; +} + +/* + * No need to reset the timer at every irq + */ +#define reset_timer() 1 + +/* + * Updating of the RTC. We don't currently write the time to the + * CMOS clock. + */ +#define update_rtc() + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +extern __inline__ unsigned long setup_timer (void) +{ + extern int iic_control (unsigned char, int, char *, int); + unsigned int year, mon, day, hour, min, sec; + char buf[8]; + + outb(LATCH & 255, IOC_T0LTCHL); + outb(LATCH >> 8, IOC_T0LTCHH); + outb(0, IOC_T0GO); + + iic_control (0xa0, 0xc0, buf, 1); + year = buf[0]; + if ((year += 1900) < 1970) + year += 100; + + iic_control (0xa0, 2, buf, 5); + mon = buf[4] & 0x1f; + day = buf[3] & 0x3f; + hour = buf[2]; + min = buf[1]; + sec = buf[0]; + BCD_TO_BIN(mon); + BCD_TO_BIN(day); + BCD_TO_BIN(hour); + BCD_TO_BIN(min); + BCD_TO_BIN(sec); + + return mktime(year, mon, day, hour, min, sec); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/timex.h linux/include/asm-arm/arch-arc/timex.h --- v2.1.79/linux/include/asm-arm/arch-arc/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/timex.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,13 @@ +/* + * linux/include/asm-arm/arch-arc/timex.h + * + * Archimedes architecture timex specifications + * + * Copyright (C) 1997, 1998 Russell King + */ + +/* + * On the RiscPC, the clock ticks at 2MHz. + */ +#define CLOCK_TICK_RATE 2000000 + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-arc/uncompress.h linux/include/asm-arm/arch-arc/uncompress.h --- v2.1.79/linux/include/asm-arm/arch-arc/uncompress.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-arc/uncompress.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,104 @@ +/* + * linux/include/asm-arm/arch-a5k/uncompress.h + * + * Copyright (C) 1996 Russell King + */ +#define VIDMEM ((char *)0x02000000) + +#include "../arch/arm/drivers/char/font.h" + +int video_num_columns, video_num_lines, video_size_row; +int white, bytes_per_char_h; +extern unsigned long con_charconvtable[256]; + +struct param_struct { + unsigned long page_size; + unsigned long nr_pages; + unsigned long ramdisk_size; + unsigned long mountrootrdonly; + unsigned long rootdev; + unsigned long video_num_cols; + unsigned long video_num_rows; + unsigned long video_x; + unsigned long video_y; + unsigned long memc_control_reg; + unsigned char sounddefault; + unsigned char adfsdrives; + unsigned char bytes_per_char_h; + unsigned char bytes_per_char_v; + unsigned long unused[256/4-11]; +}; + +static struct param_struct *params = (struct param_struct *)0x0207c000; + +/* + * This does not append a newline + */ +static void puts(const char *s) +{ + extern void ll_write_char(char *, unsigned long); + int x,y; + unsigned char c; + char *ptr; + + x = params->video_x; + y = params->video_y; + + while ( ( c = *(unsigned char *)s++ ) != '\0' ) { + if ( c == '\n' ) { + x = 0; + if ( ++y >= video_num_lines ) { + y--; + } + } else { + ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h); + ll_write_char(ptr, c|(white<<8)); + if ( ++x >= video_num_columns ) { + x = 0; + if ( ++y >= video_num_lines ) { + y--; + } + } + } + } + + params->video_x = x; + params->video_y = y; +} + +static void error(char *x); + +/* + * Setup for decompression + */ +static void arch_decomp_setup(void) +{ + int i; + + video_num_lines = params->video_num_rows; + video_num_columns = params->video_num_cols; + bytes_per_char_h = params->bytes_per_char_h; + video_size_row = video_num_columns * bytes_per_char_h; + if (bytes_per_char_h == 4) + for (i = 0; i < 256; i++) + con_charconvtable[i] = + (i & 128 ? 1 << 0 : 0) | + (i & 64 ? 1 << 4 : 0) | + (i & 32 ? 1 << 8 : 0) | + (i & 16 ? 1 << 12 : 0) | + (i & 8 ? 1 << 16 : 0) | + (i & 4 ? 1 << 20 : 0) | + (i & 2 ? 1 << 24 : 0) | + (i & 1 ? 1 << 28 : 0); + else + for (i = 0; i < 16; i++) + con_charconvtable[i] = + (i & 8 ? 1 << 0 : 0) | + (i & 4 ? 1 << 8 : 0) | + (i & 2 ? 1 << 16 : 0) | + (i & 1 ? 1 << 24 : 0); + + white = bytes_per_char_h == 8 ? 0xfc : 7; + + if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n"); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/a.out.h linux/include/asm-arm/arch-ebsa110/a.out.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/a.out.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/a.out.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,16 @@ +/* + * linux/include/asm-arm/arch-ebsa110/a.out.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_ARCH_A_OUT_H +#define __ASM_ARCH_A_OUT_H + +#ifdef __KERNEL__ +#define STACK_TOP (0xc0000000) +#define LIBRARY_START_TEXT (0x00c00000) +#endif + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/dma.h linux/include/asm-arm/arch-ebsa110/dma.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/dma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/dma.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,100 @@ +/* + * linux/include/asm-arm/arch-ebsa110/dma.h + * + * Architecture DMA routes + * + * Copyright (C) 1997.1998 Russell King + */ +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +#ifdef KERNEL_ARCH_DMA + +static inline void arch_disable_dma (int dmanr) +{ + printk (dma_str, "arch_disable_dma", dmanr); +} + +static inline void arch_enable_dma (int dmanr) +{ + printk (dma_str, "arch_enable_dma", dmanr); +} + +static inline void arch_set_dma_addr (int dmanr, unsigned int addr) +{ + printk (dma_str, "arch_set_dma_addr", dmanr); +} + +static inline void arch_set_dma_count (int dmanr, unsigned int count) +{ + printk (dma_str, "arch_set_dma_count", dmanr); +} + +static inline void arch_set_dma_mode (int dmanr, char mode) +{ + printk (dma_str, "arch_set_dma_mode", dmanr); +} + +static inline int arch_dma_count (int dmanr) +{ + printk (dma_str, "arch_dma_count", dmanr); + return 0; +} + +#endif + +/* enable/disable a specific DMA channel */ +extern void enable_dma(unsigned int dmanr); + +static __inline__ void disable_dma(unsigned int dmanr) +{ + printk (dma_str, "disable_dma", dmanr); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + printk (dma_str, "clear_dma_ff", dmanr); +} + +/* set mode (above) for a specific DMA channel */ +extern void set_dma_mode(unsigned int dmanr, char mode); + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + printk (dma_str, "set_dma_page", dmanr); +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +extern void set_dma_addr(unsigned int dmanr, unsigned int addr); + +/* Set transfer size for a specific DMA channel. + */ +extern void set_dma_count(unsigned int dmanr, unsigned int count); + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +extern int get_dma_residue(unsigned int dmanr); + +#endif /* _ASM_ARCH_DMA_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/hardware.h linux/include/asm-arm/arch-ebsa110/hardware.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/hardware.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,50 @@ +/* + * linux/include/asm-arm/arch-ebsa110/hardware.h + * + * Copyright (C) 1996,1997,1998 Russell King. + * + * This file contains the hardware definitions of the EBSA-110. + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* + * What hardware must be present + */ +#define HAS_PCIO + +#ifndef __ASSEMBLER__ + +/* + * IO definitions + */ +#define PIT_CTRL ((volatile unsigned char *)0xf200000d) +#define PIT_T2 ((volatile unsigned char *)0xf2000009) +#define PIT_T1 ((volatile unsigned char *)0xf2000005) +#define PIT_T0 ((volatile unsigned char *)0xf2000001) +#define PCIO_BASE 0xf0000000 + +/* + * Mapping areas + */ +#define IO_END 0xffffffff +#define IO_BASE 0xe0000000 +#define IO_SIZE (IO_END - IO_BASE) +#define IO_START 0xe0000000 + +/* + * RAM definitions + */ +#define MAPTOPHYS(a) ((unsigned long)(a) - PAGE_OFFSET) +#define KERNTOPHYS(a) ((unsigned long)(&a)) +#define KERNEL_BASE (0xc0008000) + +#else + +#define PCIO_BASE 0xf0000000 +#define IO_BASE 0 + +#endif +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/ide.h linux/include/asm-arm/arch-ebsa110/ide.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/ide.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/ide.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1 @@ +/* no ide */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/io.h linux/include/asm-arm/arch-ebsa110/io.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/io.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/io.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,192 @@ +/* + * linux/include/asm-arm/arch-ebsa110/io.h + * + * Copyright (C) 1997,1998 Russell King + * + * Modifications: + * 06-Dec-1997 RMK Created. + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an + * address suitable to be passed to set_dma_addr + * bus_to_virt: Used to convert an address for DMA operations + * to an address that the kernel can use. + */ +#define virt_to_bus(x) ((unsigned long)(x)) +#define bus_to_virt(x) ((void *)(x)) + +/* + * This architecture does not require any delayed IO, and + * has the constant-optimised IO + */ +#undef ARCH_IO_DELAY + +/* + * We use two different types of addressing - PC style addresses, and ARM + * addresses. PC style accesses the PC hardware with the normal PC IO + * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ + * and are translated to the start of IO. Note that all addresses are + * shifted left! + */ +#define __PORT_PCIO(x) (!((x) & 0x80000000)) + +/* + * Dynamic IO functions - let the compiler + * optimize the expressions + */ +#define DECLARE_DYN_OUT(fnsuffix,instr) \ +extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \ +{ \ + unsigned long temp; \ + __asm__ __volatile__( \ + "tst %2, #0x80000000\n\t" \ + "mov %0, %4\n\t" \ + "addeq %0, %0, %3\n\t" \ + "str" ##instr## " %1, [%0, %2, lsl #2]" \ + : "=&r" (temp) \ + : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ + : "cc"); \ +} + +#define DECLARE_DYN_IN(sz,fnsuffix,instr) \ +extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \ +{ \ + unsigned long temp, value; \ + __asm__ __volatile__( \ + "tst %2, #0x80000000\n\t" \ + "mov %0, %4\n\t" \ + "addeq %0, %0, %3\n\t" \ + "ldr" ##instr## " %1, [%0, %2, lsl #2]" \ + : "=&r" (temp), "=r" (value) \ + : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ + : "cc"); \ + return (unsigned sz)value; \ +} + +extern __inline__ unsigned int __ioaddr (unsigned int port) \ +{ \ + if (__PORT_PCIO(port)) \ + return (unsigned int)(PCIO_BASE + (port << 2)); \ + else \ + return (unsigned int)(IO_BASE + (port << 2)); \ +} + +#define DECLARE_IO(sz,fnsuffix,instr) \ + DECLARE_DYN_OUT(fnsuffix,instr) \ + DECLARE_DYN_IN(sz,fnsuffix,instr) + +DECLARE_IO(char,b,"b") +DECLARE_IO(short,w,"") +DECLARE_IO(long,l,"") + +#undef DECLARE_IO +#undef DECLARE_DYN_OUT +#undef DECLARE_DYN_IN + +/* + * Constant address IO functions + * + * These have to be macros for the 'J' constraint to work - + * +/-4096 immediate operand. + */ +#define __outbc(value,port) \ +({ \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inbc(port) \ +({ \ + unsigned char result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __outwc(value,port) \ +({ \ + unsigned long v = value; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inwc(port) \ +({ \ + unsigned short result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result & 0xffff; \ +}) + +#define __outlc(v,p) __outwc((v),(p)) + +#define __inlc(port) \ +({ \ + unsigned long result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __ioaddrc(port) \ +({ \ + unsigned long addr; \ + if (__PORT_PCIO((port))) \ + addr = PCIO_BASE + ((port) << 2); \ + else \ + addr = IO_BASE + ((port) << 2); \ + addr; \ +}) + +/* + * Translated address IO functions + * + * IO address has already been translated to a virtual address + */ +#define outb_t(v,p) \ + (*(volatile unsigned char *)(p) = (v)) + +#define inb_t(p) \ + (*(volatile unsigned char *)(p)) + +#define outl_t(v,p) \ + (*(volatile unsigned long *)(p) = (v)) + +#define inl_t(p) \ + (*(volatile unsigned long *)(p)) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/irq.h linux/include/asm-arm/arch-ebsa110/irq.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/irq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/irq.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,46 @@ +/* + * include/asm-arm/arch-ebsa110/irq.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +#define IRQ_MCLR ((volatile unsigned char *)0xf3000000) +#define IRQ_MSET ((volatile unsigned char *)0xf2c00000) +#define IRQ_MASK ((volatile unsigned char *)0xf2c00000) + +static __inline__ void mask_and_ack_irq(unsigned int irq) +{ + if (irq < 8) + *IRQ_MCLR = 1 << irq; +} + +static __inline__ void mask_irq(unsigned int irq) +{ + if (irq < 8) + *IRQ_MCLR = 1 << irq; +} + +static __inline__ void unmask_irq(unsigned int irq) +{ + if (irq < 8) + *IRQ_MSET = 1 << irq; +} + +static __inline__ unsigned long get_enabled_irqs(void) +{ + return 0; +} + +static __inline__ void irq_init_irq(void) +{ + unsigned long flags; + + save_flags_cli (flags); + *IRQ_MCLR = 0xff; + *IRQ_MSET = 0x55; + *IRQ_MSET = 0x00; + if (*IRQ_MASK != 0x55) + while (1); + *IRQ_MCLR = 0xff; /* clear all interrupt enables */ + restore_flags (flags); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/irqs.h linux/include/asm-arm/arch-ebsa110/irqs.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/irqs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/irqs.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,14 @@ +/* + * linux/include/asm-arm/arch-sa100eval/irqs.h + * + * Copyright (C) 1996 Russell King + */ + +#define IRQ_PRINTER 0 +#define IRQ_COM1 1 +#define IRQ_COM2 2 +#define IRQ_ETHERNET 3 +#define IRQ_TIMER0 4 +#define IRQ_TIMER1 5 +#define IRQ_PCMCIA 6 +#define IRQ_IMMEDIATE 7 diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/mm-init.h linux/include/asm-arm/arch-ebsa110/mm-init.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/mm-init.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/mm-init.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,11 @@ +/* + * linux/include/asm-arm/arch-ebsa110/mm-init.h + * + * Copyright (C) 1997,1998 Russell King + * + * Description of the initial memory map for EBSA-110 + */ + +static init_mem_map_t init_mem_map[] = { + INIT_MEM_MAP_SENTINEL +}; diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/mmap.h linux/include/asm-arm/arch-ebsa110/mmap.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/mmap.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/mmap.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,10 @@ +/* + * linux/include/asm-arm/arch-ebsa110/mmap.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +/* + * Use SRAM for cache flushing + */ +#define SAFE_ADDR 0x40000000 diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/mmu.h linux/include/asm-arm/arch-ebsa110/mmu.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/mmu.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/mmu.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,19 @@ +/* + * linux/include/asm-arm/arch-ebsa110/mmu.h + * + * Copyright (c) 1996,1997,1998 Russell King. + * + * Changelog: + * 20-10-1996 RMK Created + * 31-12-1997 RMK Fixed definitions to reduce warnings + */ +#ifndef __ASM_ARCH_MMU_H +#define __ASM_ARCH_MMU_H + +/* + * On ebsa, the dram is contiguous + */ +#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET) +#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/oldlatches.h linux/include/asm-arm/arch-ebsa110/oldlatches.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/oldlatches.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/oldlatches.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,9 @@ +/* + * Dummy oldlatches.h + * + * Copyright (C) 1996 Russell King + */ + +#ifdef __need_oldlatches +#error "Old latches not present in this (rpc) machine" +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/processor.h linux/include/asm-arm/arch-ebsa110/processor.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/processor.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,31 @@ +/* + * linux/include/asm-arm/arch-ebsa110/processor.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +#ifndef __ASM_ARCH_PROCESSOR_H +#define __ASM_ARCH_PROCESSOR_H + +/* + * Bus types + */ +#define EISA_bus 0 +#define EISA_bus__is_a_macro /* for versions in ksyms.c */ +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* + * User space: 3GB + */ +#define TASK_SIZE (0xc0000000UL) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +#define INIT_MMAP \ +{ &init_mm, 0xc0000000, 0xc2000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/serial.h linux/include/asm-arm/arch-ebsa110/serial.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/serial.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,41 @@ +/* + * linux/include/asm-arm/arch-ebsa110/serial.h + * + * Copyright (c) 1996,1997,1998 Russell King. + * + * Changelog: + * 15-10-1996 RMK Created + */ +#ifndef __ASM_ARCH_SERIAL_H +#define __ASM_ARCH_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD (1843200 / 16) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + + /* UART CLK PORT IRQ FLAGS */ +#define RS_UARTS \ + { 0, BASE_BAUD, 0x3F8, 1, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 2, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/shmparam.h linux/include/asm-arm/arch-ebsa110/shmparam.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/shmparam.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,5 @@ +/* + * linux/include/asm-arm/arch-ebsa110/shmparam.h + * + * Copyright (c) 1996 Russell King. + */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/system.h linux/include/asm-arm/arch-ebsa110/system.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/system.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,18 @@ +/* + * linux/include/asm-arm/arch-ebsa110/system.h + * + * Copyright (c) 1996,1997,1998 Russell King. + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +extern __inline__ void arch_hard_reset (void) +{ + /* + * loop endlessly + */ + cli(); + while (1); +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/time.h linux/include/asm-arm/arch-ebsa110/time.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/time.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/time.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,89 @@ +/* + * linux/include/asm-arm/arch-ebsa110/time.h + * + * Copyright (c) 1996,1997,1998 Russell King. + * + * No real time clock on the evalulation board! + * + * Changelog: + * 10-Oct-1996 RMK Created + * 04-Dec-1997 RMK Updated for new arch/arm/time.c + */ + +#define MCLK_47_8 + +#if defined(MCLK_42_3) +#define PIT1_COUNT 0xecbe +#elif defined(MCLK_47_8) +/* + * This should be 0x10AE1, but that doesn't exactly fit. + * We run the timer interrupt at 5ms, and then divide it by + * two in software... This is so that the user processes + * see exactly the same model whichever ARM processor they're + * running on. + */ +#define PIT1_COUNT 0x8570 +#define DIVISOR 2 +#endif + +extern __inline__ unsigned long gettimeoffset (void) +{ + return 0; +} + +#ifndef DIVISOR +extern __inline__ int reset_timer (void) +{ + *PIT_T1 = (PIT1_COUNT) & 0xff; + *PIT_T1 = (PIT1_COUNT) >> 8; + return 1; +} +#else +extern __inline__ int reset_timer (void) +{ + static unsigned int divisor; + static int count = 50; + + *PIT_T1 = (PIT1_COUNT) & 0xff; + *PIT_T1 = (PIT1_COUNT) >> 8; + + if (--count == 0) { + count = 50; + *(volatile unsigned char *)0xf2400000 ^= 128; + } + + if (divisor == 0) { + divisor = DIVISOR - 1; + return 1; + } + divisor -= 1; + return 0; +} +#endif + +/* + * We don't have a RTC to update! + */ +#define update_rtc() + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +extern __inline__ unsigned long setup_timer (void) +{ + /* + * Timer 1, mode 0, 16-bit, autoreload + */ + *PIT_CTRL = 0x70; + /* + * Refresh counter clocked at 47.8MHz/7 = 146.4ns + * We want centi-second interrupts + */ + reset_timer (); + /* + * Default the date to 1 Jan 1970 0:0:0 + * You will have to run a time daemon to set the + * clock correctly at bootup + */ + return mktime(1970, 1, 1, 0, 0, 0); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/timex.h linux/include/asm-arm/arch-ebsa110/timex.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/timex.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-arm/arch-ebsa110/timex.h + * + * RiscPC architecture timex specifications + * + * Copyright (C) 1997, 1998 Russell King + */ + +/* + * On the EBSA, the clock ticks at weird rates. + * This is therefore not used to calculate the + * divisor. + */ +//#define CLOCK_TICK_RATE 2000000 + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-ebsa110/uncompress.h linux/include/asm-arm/arch-ebsa110/uncompress.h --- v2.1.79/linux/include/asm-arm/arch-ebsa110/uncompress.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-ebsa110/uncompress.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,33 @@ +/* + * linux/include/asm-arm/arch-ebsa110/uncompress.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +/* + * This does not append a newline + */ +static void puts(const char *s) +{ + __asm__ __volatile__(" + ldrb %0, [%2], #1 + teq %0, #0 + beq 3f +1: strb %0, [%3] +2: ldrb %1, [%3, #0x14] + and %1, %1, #0x60 + teq %1, #0x60 + bne 2b + teq %0, #'\n' + moveq %0, #'\r' + beq 1b + ldrb %0, [%2], #1 + teq %0, #0 + bne 1b +3: " : : "r" (0), "r" (0), "r" (s), "r" (0xf0000be0) : "cc"); +} + +/* + * nothing to do + */ +#define arch_decomp_setup() diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/a.out.h linux/include/asm-arm/arch-nexuspci/a.out.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/a.out.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/a.out.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,16 @@ +/* + * linux/include/asm-arm/arch-ebsa/a.out.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_ARCH_A_OUT_H +#define __ASM_ARCH_A_OUT_H + +#ifdef __KERNEL__ +#define STACK_TOP (0xc0000000) +#define LIBRARY_START_TEXT (0x00c00000) +#endif + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/dma.h linux/include/asm-arm/arch-nexuspci/dma.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/dma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/dma.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,100 @@ +/* + * linux/include/asm-arm/arch-ebsa110/dma.h + * + * Architecture DMA routes + * + * Copyright (C) 1997.1998 Russell King + */ +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +#ifdef KERNEL_ARCH_DMA + +static inline void arch_disable_dma (int dmanr) +{ + printk (dma_str, "arch_disable_dma", dmanr); +} + +static inline void arch_enable_dma (int dmanr) +{ + printk (dma_str, "arch_enable_dma", dmanr); +} + +static inline void arch_set_dma_addr (int dmanr, unsigned int addr) +{ + printk (dma_str, "arch_set_dma_addr", dmanr); +} + +static inline void arch_set_dma_count (int dmanr, unsigned int count) +{ + printk (dma_str, "arch_set_dma_count", dmanr); +} + +static inline void arch_set_dma_mode (int dmanr, char mode) +{ + printk (dma_str, "arch_set_dma_mode", dmanr); +} + +static inline int arch_dma_count (int dmanr) +{ + printk (dma_str, "arch_dma_count", dmanr); + return 0; +} + +#endif + +/* enable/disable a specific DMA channel */ +extern void enable_dma(unsigned int dmanr); + +static __inline__ void disable_dma(unsigned int dmanr) +{ + printk (dma_str, "disable_dma", dmanr); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + printk (dma_str, "clear_dma_ff", dmanr); +} + +/* set mode (above) for a specific DMA channel */ +extern void set_dma_mode(unsigned int dmanr, char mode); + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + printk (dma_str, "set_dma_page", dmanr); +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +extern void set_dma_addr(unsigned int dmanr, unsigned int addr); + +/* Set transfer size for a specific DMA channel. + */ +extern void set_dma_count(unsigned int dmanr, unsigned int count); + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +extern int get_dma_residue(unsigned int dmanr); + +#endif /* _ASM_ARCH_DMA_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/hardware.h linux/include/asm-arm/arch-nexuspci/hardware.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/hardware.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,40 @@ +/* + * linux/include/asm-arm/arch-nexuspci/hardware.h + * + * Copyright (C) 1997 Philip Blundell + * + * This file contains the hardware definitions of the Nexus PCI card. + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* + * What hardware must be present + */ + +#ifndef __ASSEMBLER__ + +/* + * Mapping areas + */ +#define IO_END 0xffffffff +#define IO_BASE 0xd0000000 +#define IO_SIZE (IO_END - IO_BASE) +#define IO_START 0xd0000000 + +/* + * RAM definitions + */ +#define RAM_BASE 0x40000000 +#define MAPTOPHYS(a) ((unsigned long)(a) - PAGE_OFFSET + RAM_BASE) +#define KERNTOPHYS(a) ((unsigned long)(&a)) +#define KERNEL_BASE (0xc0008000) + +#else + +#define IO_BASE 0 + +#endif +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/irq.h linux/include/asm-arm/arch-nexuspci/irq.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/irq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/irq.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,46 @@ +/* + * include/asm-arm/arch-ebsa110/irq.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +#define IRQ_MCLR ((volatile unsigned char *)0xf3000000) +#define IRQ_MSET ((volatile unsigned char *)0xf2c00000) +#define IRQ_MASK ((volatile unsigned char *)0xf2c00000) + +static __inline__ void mask_and_ack_irq(unsigned int irq) +{ + if (irq < 8) + *IRQ_MCLR = 1 << irq; +} + +static __inline__ void mask_irq(unsigned int irq) +{ + if (irq < 8) + *IRQ_MCLR = 1 << irq; +} + +static __inline__ void unmask_irq(unsigned int irq) +{ + if (irq < 8) + *IRQ_MSET = 1 << irq; +} + +static __inline__ unsigned long get_enabled_irqs(void) +{ + return 0; +} + +static __inline__ void irq_init_irq(void) +{ + unsigned long flags; + + save_flags_cli (flags); + *IRQ_MCLR = 0xff; + *IRQ_MSET = 0x55; + *IRQ_MSET = 0x00; + if (*IRQ_MASK != 0x55) + while (1); + *IRQ_MCLR = 0xff; /* clear all interrupt enables */ + restore_flags (flags); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/irqs.h linux/include/asm-arm/arch-nexuspci/irqs.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/irqs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/irqs.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,14 @@ +/* + * linux/include/asm-arm/arch-nexuspci/irqs.h + * + * Copyright (C) 1997 Philip Blundell + */ + +#define IRQ_DUART 0 +#define IRQ_TIMER0 0 /* timer is part of the DUART */ +#define IRQ_PLX 1 +#define IRQ_PCI_D 2 +#define IRQ_PCI_C 3 +#define IRQ_PCI_B 4 +#define IRQ_PCI_A 5 +#define IRQ_SYSERR 6 /* must ask JB about this one */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/mmap.h linux/include/asm-arm/arch-nexuspci/mmap.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/mmap.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/mmap.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,10 @@ +/* + * linux/include/asm-arm/arch-ebsa110/mmap.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +/* + * Use SRAM for cache flushing + */ +#define SAFE_ADDR 0x40000000 diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/mmu.h linux/include/asm-arm/arch-nexuspci/mmu.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/mmu.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/mmu.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,16 @@ +/* + * linux/include/asm-arm/arch-nexuspci/mmu.h + * + * Copyright (c) 1997 Philip Blundell. + * + */ +#ifndef __ASM_ARCH_MMU_H +#define __ASM_ARCH_MMU_H + +/* + * On NexusPCI, the dram is contiguous + */ +#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000) +#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/processor.h linux/include/asm-arm/arch-nexuspci/processor.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/processor.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,31 @@ +/* + * linux/include/asm-arm/arch-ebsa110/processor.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +#ifndef __ASM_ARCH_PROCESSOR_H +#define __ASM_ARCH_PROCESSOR_H + +/* + * Bus types + */ +#define EISA_bus 0 +#define EISA_bus__is_a_macro /* for versions in ksyms.c */ +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* + * User space: 3GB + */ +#define TASK_SIZE (0xc0000000UL) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +#define INIT_MMAP \ +{ &init_mm, 0xc0000000, 0xc2000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/serial.h linux/include/asm-arm/arch-nexuspci/serial.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/serial.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,41 @@ +/* + * linux/include/asm-arm/arch-ebsa110/serial.h + * + * Copyright (c) 1996,1997,1998 Russell King. + * + * Changelog: + * 15-10-1996 RMK Created + */ +#ifndef __ASM_ARCH_SERIAL_H +#define __ASM_ARCH_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD (1843200 / 16) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + + /* UART CLK PORT IRQ FLAGS */ +#define RS_UARTS \ + { 0, BASE_BAUD, 0x3F8, 1, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 2, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/shmparam.h linux/include/asm-arm/arch-nexuspci/shmparam.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/shmparam.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,5 @@ +/* + * linux/include/asm-arm/arch-ebsa110/shmparam.h + * + * Copyright (c) 1996 Russell King. + */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/system.h linux/include/asm-arm/arch-nexuspci/system.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/system.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,18 @@ +/* + * linux/include/asm-arm/arch-ebsa110/system.h + * + * Copyright (c) 1996,1997,1998 Russell King. + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +extern __inline__ void arch_hard_reset (void) +{ + /* + * loop endlessly + */ + cli(); + while (1); +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/time.h linux/include/asm-arm/arch-nexuspci/time.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/time.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/time.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,29 @@ +/* + * linux/include/asm-arm/arch-nexuspci/time.h + * + * Copyright (c) 1997 Phil Blundell. + * + * Nexus PCI card has no real-time clock. + * + */ + +extern __inline__ unsigned long gettimeoffset (void) +{ + return 0; +} + +extern __inline__ int reset_timer (void) +{ + return 0; +} + +extern __inline__ unsigned long setup_timer (void) +{ + reset_timer (); + /* + * Default the date to 1 Jan 1970 0:0:0 + * You will have to run a time daemon to set the + * clock correctly at bootup + */ + return mktime(1970, 1, 1, 0, 0, 0); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-nexuspci/uncompress.h linux/include/asm-arm/arch-nexuspci/uncompress.h --- v2.1.79/linux/include/asm-arm/arch-nexuspci/uncompress.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-nexuspci/uncompress.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,17 @@ +/* + * linux/include/asm-arm/arch-ebsa110/uncompress.h + * + * Copyright (C) 1996,1997,1998 Russell King + */ + +/* + * This does not append a newline + */ +static void puts(const char *s) +{ +} + +/* + * nothing to do + */ +#define arch_decomp_setup() diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/a.out.h linux/include/asm-arm/arch-rpc/a.out.h --- v2.1.79/linux/include/asm-arm/arch-rpc/a.out.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/a.out.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,16 @@ +/* + * linux/include/asm-arm/arch-rpc/a.out.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_ARCH_A_OUT_H +#define __ASM_ARCH_A_OUT_H + +#ifdef __KERNEL__ +#define STACK_TOP (0xc0000000) +#define LIBRARY_START_TEXT (0x00c00000) +#endif + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/dma.h linux/include/asm-arm/arch-rpc/dma.h --- v2.1.79/linux/include/asm-arm/arch-rpc/dma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/dma.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,128 @@ +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +#define MAX_DMA_ADDRESS 0xd0000000 + +#ifdef KERNEL_ARCH_DMA + +static unsigned char arch_dma_setup; +unsigned char arch_dma_ctrl[8]; +unsigned long arch_dma_addr[8]; +unsigned long arch_dma_cnt[8]; + +static inline void arch_enable_dma(int dmanr) +{ + if (!(arch_dma_setup & (1 << dmanr))) { + arch_dma_setup |= 1 << dmanr; +/* dma_interrupt (16 + dmanr);*/ + } + arch_dma_ctrl[dmanr] |= DMA_CR_E; + switch (dmanr) { + case 0: outb (arch_dma_ctrl[0], IOMD_IO0CR); break; + case 1: outb (arch_dma_ctrl[1], IOMD_IO1CR); break; + case 2: outb (arch_dma_ctrl[2], IOMD_IO2CR); break; + case 3: outb (arch_dma_ctrl[3], IOMD_IO3CR); break; + case 4: outb (arch_dma_ctrl[4], IOMD_SD0CR); break; + case 5: outb (arch_dma_ctrl[5], IOMD_SD1CR); break; + } +} + +static inline void arch_disable_dma(int dmanr) +{ + arch_dma_ctrl[dmanr] &= ~DMA_CR_E; + switch (dmanr) { + case 0: outb (arch_dma_ctrl[0], IOMD_IO0CR); break; + case 1: outb (arch_dma_ctrl[1], IOMD_IO1CR); break; + case 2: outb (arch_dma_ctrl[2], IOMD_IO2CR); break; + case 3: outb (arch_dma_ctrl[3], IOMD_IO3CR); break; + case 4: outb (arch_dma_ctrl[4], IOMD_SD0CR); break; + case 5: outb (arch_dma_ctrl[5], IOMD_SD1CR); break; + } +} + +static inline void arch_set_dma_addr(int dmanr, unsigned int addr) +{ + arch_dma_setup &= ~dmanr; + arch_dma_addr[dmanr] = addr; +} + +static inline void arch_set_dma_count(int dmanr, unsigned int count) +{ + arch_dma_setup &= ~dmanr; + arch_dma_cnt[dmanr] = count; +} + +static inline void arch_set_dma_mode(int dmanr, char mode) +{ + switch (mode) { + case DMA_MODE_READ: + arch_dma_ctrl[dmanr] |= DMA_CR_D; + break; + case DMA_MODE_WRITE: + arch_dma_ctrl[dmanr] &= ~DMA_CR_D; + break; + } +} + +static inline int arch_dma_count (int dmanr) +{ + return arch_dma_cnt[dmanr]; +} +#endif + +/* enable/disable a specific DMA channel */ +extern void enable_dma(unsigned int dmanr); + +static __inline__ void disable_dma(unsigned int dmanr) +{ + switch(dmanr) { + case 1: break; + case 2: disable_irq(64); break; + default: printk(dma_str, "disable_dma", dmanr); break; + } +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +#define clear_dma_ff(dmanr) + +/* set mode (above) for a specific DMA channel */ +extern void set_dma_mode(unsigned int dmanr, char mode); + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + printk (dma_str, "set_dma_page", dmanr); +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +extern void set_dma_addr(unsigned int dmanr, unsigned int addr); + +/* Set transfer size for a specific DMA channel. + */ +extern void set_dma_count(unsigned int dmanr, unsigned int count); + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +extern int get_dma_residue(unsigned int dmanr); + +#endif /* _ASM_ARCH_DMA_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/hardware.h linux/include/asm-arm/arch-rpc/hardware.h --- v2.1.79/linux/include/asm-arm/arch-rpc/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/hardware.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,101 @@ +/* + * linux/include/asm-arm/arch-rpc/hardware.h + * + * Copyright (C) 1996 Russell King. + * + * This file contains the hardware definitions of the RiscPC series machines. + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* + * What hardware must be present + */ +#define HAS_IOMD +#define HAS_PCIO +#define HAS_VIDC20 + +/* + * Optional hardware + */ +#define HAS_EXPMASK + +/* + * Physical definitions + */ +#define RAM_START 0x10000000 +#define IO_START 0x03000000 +#define SCREEN_START 0x02000000 /* VRAM */ + +#ifndef __ASSEMBLER__ + +/* + * for use with inb/outb + */ +#define VIDC_AUDIO_BASE 0x80140000 +#define VIDC_BASE 0x80100000 +#define IOCEC4IO_BASE 0x8009c000 +#define IOCECIO_BASE 0x80090000 +#define IOMD_BASE 0x80080000 +#define MEMCEC8IO_BASE 0x8000ac00 +#define MEMCECIO_BASE 0x80000000 + +/* + * IO definitions + */ +#define EXPMASK_BASE ((volatile unsigned char *)0xe0360000) +#define IOEB_BASE ((volatile unsigned char *)0xe0350050) +#define IOC_BASE ((volatile unsigned char *)0xe0200000) +#define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0xe002a000) +#define PCIO_BASE 0xe0010000 + +/* + * Mapping areas + */ +#define IO_END 0xe0ffffff +#define IO_BASE 0xe0000000 +#define IO_SIZE (IO_END - IO_BASE) + +/* + * Screen mapping information + */ +#define SCREEN2_END 0xe0000000 +#define SCREEN2_BASE 0xd8000000 +#define SCREEN1_END SCREEN2_BASE +#define SCREEN1_BASE 0xd0000000 + +/* + * Offsets from RAM base + */ +#define PARAMS_OFFSET 0x0100 +#define KERNEL_OFFSET 0x8000 + +/* + * RAM definitions + */ +#define MAPTOPHYS(x) (x) +#define KERNTOPHYS(x) ((unsigned long)(&x)) +#define GET_MEMORY_END(p) (PAGE_OFFSET + p->u1.s.page_size * \ + (p->u1.s.pages_in_bank[0] + \ + p->u1.s.pages_in_bank[1] + \ + p->u1.s.pages_in_bank[2] + \ + p->u1.s.pages_in_bank[3])) + +#define KERNEL_BASE (PAGE_OFFSET + KERNEL_OFFSET) +#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET) +#define Z_PARAMS_BASE (RAM_START + PARAMS_OFFSET) + +#else + +#define VIDC_SND_BASE 0xe0500000 +#define VIDC_BASE 0xe0400000 +#define IOMD_BASE 0xe0200000 +#define IOC_BASE 0xe0200000 +#define PCIO_FLOPPYDMABASE 0xe002a000 +#define PCIO_BASE 0xe0010000 +#define IO_BASE 0xe0000000 + +#endif +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/ide.h linux/include/asm-arm/arch-rpc/ide.h --- v2.1.79/linux/include/asm-arm/arch-rpc/ide.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/ide.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,44 @@ +/* + * linux/include/asm-arm/arch-rpc/ide.h + * + * Copyright (c) 1997 Russell King + */ + +static __inline__ int +ide_default_irq(ide_ioreg_t base) +{ + if (base == 0x1f0) + return 9; + return 0; +} + +static __inline__ ide_ioreg_t +ide_default_io_base(int index) +{ + if (index == 0) + return 0x1f0; + return 0; +} + +static __inline__ int +ide_default_stepping(int index) +{ + return 0; +} + +static __inline__ void +ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq) +{ + ide_ioreg_t port = base; + ide_ioreg_t ctrl = base + 0x206; + int i; + + i = 8; + while (i--) { + *p++ = port; + port += 1 << stepping; + } + *p++ = ctrl; + if (irq != NULL) + irq = 0; +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/io.h linux/include/asm-arm/arch-rpc/io.h --- v2.1.79/linux/include/asm-arm/arch-rpc/io.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/io.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,203 @@ +/* + * linux/include/asm-arm/arch-rpc/io.h + * + * Copyright (C) 1997 Russell King + * + * Modifications: + * 06-Dec-1997 RMK Created. + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +/* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an + * address suitable to be passed to set_dma_addr + * bus_to_virt: Used to convert an address for DMA operations + * to an address that the kernel can use. + */ +#define virt_to_bus(x) ((unsigned long)(x)) +#define bus_to_virt(x) ((void *)(x)) + +/* + * This architecture does not require any delayed IO, and + * has the constant-optimised IO + */ +#undef ARCH_IO_DELAY + +/* + * We use two different types of addressing - PC style addresses, and ARM + * addresses. PC style accesses the PC hardware with the normal PC IO + * addresses, eg 0x3f8 for serial#1. ARM addresses are 0x80000000+ + * and are translated to the start of IO. Note that all addresses are + * shifted left! + */ +#define __PORT_PCIO(x) (!((x) & 0x80000000)) + +/* + * Dynamic IO functions - let the compiler + * optimize the expressions + */ +#define DECLARE_DYN_OUT(fnsuffix,instr) \ +extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \ +{ \ + unsigned long temp; \ + __asm__ __volatile__( \ + "tst %2, #0x80000000\n\t" \ + "mov %0, %4\n\t" \ + "addeq %0, %0, %3\n\t" \ + "str" ##instr## " %1, [%0, %2, lsl #2]" \ + : "=&r" (temp) \ + : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ + : "cc"); \ +} + +#define DECLARE_DYN_IN(sz,fnsuffix,instr) \ +extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \ +{ \ + unsigned long temp, value; \ + __asm__ __volatile__( \ + "tst %2, #0x80000000\n\t" \ + "mov %0, %4\n\t" \ + "addeq %0, %0, %3\n\t" \ + "ldr" ##instr## " %1, [%0, %2, lsl #2]" \ + : "=&r" (temp), "=r" (value) \ + : "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \ + : "cc"); \ + return (unsigned sz)value; \ +} + +extern __inline__ unsigned int __ioaddr (unsigned int port) \ +{ \ + if (__PORT_PCIO(port)) \ + return (unsigned int)(PCIO_BASE + (port << 2)); \ + else \ + return (unsigned int)(IO_BASE + (port << 2)); \ +} + +#define DECLARE_IO(sz,fnsuffix,instr) \ + DECLARE_DYN_OUT(fnsuffix,instr) \ + DECLARE_DYN_IN(sz,fnsuffix,instr) + +DECLARE_IO(char,b,"b") +DECLARE_IO(short,w,"") +DECLARE_IO(long,l,"") + +#undef DECLARE_IO +#undef DECLARE_DYN_OUT +#undef DECLARE_DYN_IN + +/* + * Constant address IO functions + * + * These have to be macros for the 'J' constraint to work - + * +/-4096 immediate operand. + */ +#define __outbc(value,port) \ +({ \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "strb %0, [%1, %2]" \ + : : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inbc(port) \ +({ \ + unsigned char result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldrb %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __outwc(value,port) \ +({ \ + unsigned long v = value; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inwc(port) \ +({ \ + unsigned short result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result & 0xffff; \ +}) + +#define __outlc(value,port) \ +({ \ + unsigned long v = value; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "str %0, [%1, %2]" \ + : : "r" (v), "r" (IO_BASE), "r" ((port) << 2)); \ +}) + +#define __inlc(port) \ +({ \ + unsigned long result; \ + if (__PORT_PCIO((port))) \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \ + else \ + __asm__ __volatile__( \ + "ldr %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \ + result; \ +}) + +#define __ioaddrc(port) \ +({ \ + unsigned long addr; \ + if (__PORT_PCIO((port))) \ + addr = PCIO_BASE + ((port) << 2); \ + else \ + addr = IO_BASE + ((port) << 2); \ + addr; \ +}) + +/* + * Translated address IO functions + * + * IO address has already been translated to a virtual address + */ +#define outb_t(v,p) \ + (*(volatile unsigned char *)(p) = (v)) + +#define inb_t(p) \ + (*(volatile unsigned char *)(p)) + +#define outl_t(v,p) \ + (*(volatile unsigned long *)(p) = (v)) + +#define inl_t(p) \ + (*(volatile unsigned long *)(p)) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/irq.h linux/include/asm-arm/arch-rpc/irq.h --- v2.1.79/linux/include/asm-arm/arch-rpc/irq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/irq.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,138 @@ +/* + * include/asm-arm/arch-rpc/irq.h + * + * Copyright (C) 1996 Russell King + * + * Changelog: + * 10-10-1996 RMK Brought up to date with arch-sa110eval + */ + +#define BUILD_IRQ(s,n,m) \ + void IRQ##n##_interrupt(void); \ + void fast_IRQ##n##_interrupt(void); \ + void bad_IRQ##n##_interrupt(void); \ + void probe_IRQ##n##_interrupt(void); + +/* + * The timer is a special interrupt + */ +#define IRQ5_interrupt timer_IRQ_interrupt + +#define IRQ_INTERRUPT(n) IRQ##n##_interrupt +#define FAST_INTERRUPT(n) fast_IRQ##n##_interrupt +#define BAD_INTERRUPT(n) bad_IRQ##n##_interrupt +#define PROBE_INTERRUPT(n) probe_IRQ##n##_interrupt + +#define X(x) (x)|0x01, (x)|0x02, (x)|0x04, (x)|0x08, (x)|0x10, (x)|0x20, (x)|0x40, (x)|0x80 +#define Z(x) (x), (x), (x), (x), (x), (x), (x), (x) + +static __inline__ void mask_and_ack_irq(unsigned int irq) +{ + static const int addrmasks[] = { + X((IOMD_IRQMASKA - IOMD_BASE)<<18 | (1 << 15)), + X((IOMD_IRQMASKB - IOMD_BASE)<<18), + X((IOMD_DMAMASK - IOMD_BASE)<<18), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + X((IOMD_FIQMASK - IOMD_BASE)<<18), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0), + Z(0) + }; + unsigned int temp1, temp2; + + __asm__ __volatile__( +" ldr %1, [%5, %3, lsl #2]\n" +" teq %1, #0\n" +" beq 2f\n" +" ldrb %0, [%2, %1, lsr #16]\n" +" bic %0, %0, %1\n" +" strb %0, [%2, %1, lsr #16]\n" +" tst %1, #0x8000\n" /* do we need an IRQ clear? */ +" strneb %1, [%2, %4]\n" +"2:" + : "=&r" (temp1), "=&r" (temp2) + : "r" (ioaddr(IOMD_BASE)), "r" (irq), + "I" ((IOMD_IRQCLRA - IOMD_BASE) << 2), "r" (addrmasks)); +} + +#undef X +#undef Z + +static __inline__ void mask_irq(unsigned int irq) +{ + extern void ecard_disableirq (unsigned int); + extern void ecard_disablefiq (unsigned int); + unsigned char mask = 1 << (irq & 7); + + switch (irq >> 3) { + case 0: + outb(inb(IOMD_IRQMASKA) & ~mask, IOMD_IRQMASKA); + break; + case 1: + outb(inb(IOMD_IRQMASKB) & ~mask, IOMD_IRQMASKB); + break; + case 2: + outb(inb(IOMD_DMAMASK) & ~mask, IOMD_DMAMASK); + break; + case 4: + ecard_disableirq (irq & 7); + break; + case 8: + outb(inb(IOMD_FIQMASK) & ~mask, IOMD_FIQMASK); + break; + case 12: + ecard_disablefiq (irq & 7); + } +} + +static __inline__ void unmask_irq(unsigned int irq) +{ + extern void ecard_enableirq (unsigned int); + extern void ecard_enablefiq (unsigned int); + unsigned char mask = 1 << (irq & 7); + + switch (irq >> 3) { + case 0: + outb(inb(IOMD_IRQMASKA) | mask, IOMD_IRQMASKA); + break; + case 1: + outb(inb(IOMD_IRQMASKB) | mask, IOMD_IRQMASKB); + break; + case 2: + outb(inb(IOMD_DMAMASK) | mask, IOMD_DMAMASK); + break; + case 4: + ecard_enableirq (irq & 7); + break; + case 8: + outb(inb(IOMD_FIQMASK) | mask, IOMD_FIQMASK); + break; + case 12: + ecard_enablefiq (irq & 7); + } +} + +static __inline__ unsigned long get_enabled_irqs(void) +{ + return inb(IOMD_IRQMASKA) | inb(IOMD_IRQMASKB) << 8 | inb(IOMD_DMAMASK) << 16; +} + +static __inline__ void irq_init_irq(void) +{ + outb(0, IOMD_IRQMASKA); + outb(0, IOMD_IRQMASKB); + outb(0, IOMD_FIQMASK); + outb(0, IOMD_DMAMASK); + outb(0, IOMD_IO0CR); + outb(0, IOMD_IO1CR); + outb(0, IOMD_IO2CR); + outb(0, IOMD_IO3CR); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/irqs.h linux/include/asm-arm/arch-rpc/irqs.h --- v2.1.79/linux/include/asm-arm/arch-rpc/irqs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/irqs.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,28 @@ +/* + * linux/include/asm-arm/arch-a5k/irqs.h + * + * Copyright (C) 1996 Russell King + */ + +#define IRQ_PRINTER 0 +#define IRQ_BATLOW 1 +#define IRQ_FLOPPYINDEX 2 +#define IRQ_VSYNCPULSE 3 +#define IRQ_POWERON 4 +#define IRQ_TIMER0 5 +#define IRQ_TIMER1 6 +#define IRQ_IMMEDIATE 7 +#define IRQ_EXPCARDFIQ 8 +#define IRQ_SOUNDCHANGE 9 +#define IRQ_SERIALPORT 10 +#define IRQ_HARDDISK 11 +#define IRQ_FLOPPYDISK 12 +#define IRQ_EXPANSIONCARD 13 +#define IRQ_KEYBOARDTX 14 +#define IRQ_KEYBOARDRX 15 + +#define FIQ_FLOPPYDATA 0 +#define FIQ_ECONET 2 +#define FIQ_SERIALPORT 4 +#define FIQ_EXPANSIONCARD 6 +#define FIQ_FORCE 7 diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/mmap.h linux/include/asm-arm/arch-rpc/mmap.h --- v2.1.79/linux/include/asm-arm/arch-rpc/mmap.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/mmap.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,48 @@ +/* + * linux/include/asm-arm/arch-rpc/mmap.h + * + * Copyright (C) 1996 Russell King + */ + +#define HAVE_MAP_VID_MEM +#define SAFE_ADDR 0x00000000 /* ROM */ + +unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update) +{ + static int updated = 0; + unsigned long address; + pgd_t *pgd; + + if (updated) + return 0; + updated = update; + + address = SCREEN_START | PMD_TYPE_SECT | PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE; + pgd = swapper_pg_dir + (SCREEN2_BASE >> PGDIR_SHIFT); + pgd_val(pgd[0]) = address; + pgd_val(pgd[1]) = address + (1 << PGDIR_SHIFT); + + if (update) { + unsigned long pgtable = PAGE_ALIGN(kmem), *p; + int i; + + memzero ((void *)pgtable, 4096); + + pgd_val(pgd[-2]) = virt_to_phys(pgtable) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL); + pgd_val(pgd[-1]) = virt_to_phys(pgtable + PTRS_PER_PTE*4) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL); + p = (unsigned long *)pgtable; + + i = PTRS_PER_PTE * 2 - ((SCREEN1_END - log_start) >> PAGE_SHIFT); + address = SCREEN_START | PTE_TYPE_SMALL | PTE_AP_WRITE; + + while (i < PTRS_PER_PTE * 2) { + p[i++] = address; + address += PAGE_SIZE; + } + + flush_page_to_ram(pgtable); + + kmem = pgtable + PAGE_SIZE; + } + return kmem; +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/mmu.h linux/include/asm-arm/arch-rpc/mmu.h --- v2.1.79/linux/include/asm-arm/arch-rpc/mmu.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/mmu.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,17 @@ +/* + * linux/include/asm-arm/arch-rpc/mmu.h + * + * Copyright (c) 1996,1997,1998 Russell King. + * + * Changelog: + * 20-10-1996 RMK Created + * 31-12-1997 RMK Fixed definitions to reduce warnings + * 11-01-1998 RMK Uninlined to reduce hits on cache + */ +#ifndef __ASM_ARCH_MMU_H +#define __ASM_ARCH_MMU_H + +extern unsigned long __virt_to_phys(unsigned long vpage); +extern unsigned long __phys_to_virt(unsigned long ppage); + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/oldlatches.h linux/include/asm-arm/arch-rpc/oldlatches.h --- v2.1.79/linux/include/asm-arm/arch-rpc/oldlatches.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/oldlatches.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,9 @@ +/* + * Dummy oldlatches.h + * + * Copyright (C) 1996 Russell King + */ + +#ifdef __need_oldlatches +#error "Old latches not present in this (rpc) machine" +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/processor.h linux/include/asm-arm/arch-rpc/processor.h --- v2.1.79/linux/include/asm-arm/arch-rpc/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/processor.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,34 @@ +/* + * linux/include/asm-arm/arch-rpc/processor.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 10-09-1996 RMK Created + */ + +#ifndef __ASM_ARCH_PROCESSOR_H +#define __ASM_ARCH_PROCESSOR_H + +/* + * Bus types + */ +#define EISA_bus 0 +#define EISA_bus__is_a_macro /* for versions in ksyms.c */ +#define MCA_bus 0 +#define MCA_bus__is_a_macro /* for versions in ksyms.c */ + +/* + * User space: 3GB + */ +#define TASK_SIZE (0xc0000000UL) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +#define INIT_MMAP \ +{ &init_mm, 0xc0000000, 0xc2000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/serial.h linux/include/asm-arm/arch-rpc/serial.h --- v2.1.79/linux/include/asm-arm/arch-rpc/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/serial.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,40 @@ +/* + * linux/include/asm-arm/arch-rpc/serial.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 15-10-1996 RMK Created + */ +#ifndef __ASM_ARCH_SERIAL_H +#define __ASM_ARCH_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + */ +#define BASE_BAUD (1843200 / 16) + +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + + /* UART CLK PORT IRQ FLAGS */ +#define RS_UARTS \ + { 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS }, /* ttyS1 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS5 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS6 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS7 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS8 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS9 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS10 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS11 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS12 */ \ + { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS13 */ + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/shmparam.h linux/include/asm-arm/arch-rpc/shmparam.h --- v2.1.79/linux/include/asm-arm/arch-rpc/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/shmparam.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,5 @@ +/* + * linux/include/asm-arm/arch-rpc/shmparam.h + * + * Copyright (c) 1996 Russell King. + */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/system.h linux/include/asm-arm/arch-rpc/system.h --- v2.1.79/linux/include/asm-arm/arch-rpc/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/system.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,23 @@ +/* + * linux/include/asm-arm/arch-rpc/system.h + * + * Copyright (c) 1996 Russell King + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include + +#define arch_hard_reset() { \ + extern void ecard_reset (int card); \ + outb (0, IOMD_ROMCR0); \ + ecard_reset (-1); \ + cli(); \ + __asm__ __volatile__("msr spsr, r1;" \ + "mcr p15, 0, %0, c1, c0, 0;" \ + "movs pc, #0" \ + : \ + : "r" (processor.u.armv3v4.reset())); \ + } + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/time.h linux/include/asm-arm/arch-rpc/time.h --- v2.1.79/linux/include/asm-arm/arch-rpc/time.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/time.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,96 @@ +/* + * linux/include/asm-arm/arch-rpc/time.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 24-Sep-1996 RMK Created + * 10-Oct-1996 RMK Brought up to date with arch-sa110eval + * 04-Dec-1997 RMK Updated for new arch/arm/time.c + */ + +extern __inline__ unsigned long gettimeoffset (void) +{ + unsigned long offset = 0; + unsigned int count1, count2, status1, status2; + + status1 = IOMD_IRQREQA; + barrier (); + outb(0, IOMD_T0LATCH); + barrier (); + count1 = inb(IOMD_T0CNTL) | (inb(IOMD_T0CNTH) << 8); + barrier (); + status2 = inb(IOMD_IRQREQA); + barrier (); + outb(0, IOMD_T0LATCH); + barrier (); + count2 = inb(IOMD_T0CNTL) | (inb(IOMD_T0CNTH) << 8); + + if (count2 < count1) { + /* + * This means that we haven't just had an interrupt + * while reading into status2. + */ + if (status2 & (1 << 5)) + offset = tick; + count1 = count2; + } else if (count2 > count1) { + /* + * We have just had another interrupt while reading + * status2. + */ + offset += tick; + count1 = count2; + } + + count1 = LATCH - count1; + /* + * count1 = number of clock ticks since last interrupt + */ + offset += count1 * tick / LATCH; + return offset; +} + +/* + * No need to reset the timer at every irq + */ +#define reset_timer() 1 + +/* + * Updating of the RTC. We don't currently write the time to the + * CMOS clock. + */ +#define update_rtc() + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +extern __inline__ unsigned long setup_timer (void) +{ + extern int iic_control (unsigned char, int, char *, int); + unsigned int year, mon, day, hour, min, sec; + char buf[8]; + + outb(LATCH & 255, IOMD_T0LTCHL); + outb(LATCH >> 8, IOMD_T0LTCHH); + outb(0, IOMD_T0GO); + + iic_control (0xa0, 0xc0, buf, 1); + year = buf[0]; + if ((year += 1900) < 1970) + year += 100; + + iic_control (0xa0, 2, buf, 5); + mon = buf[4] & 0x1f; + day = buf[3] & 0x3f; + hour = buf[2]; + min = buf[1]; + sec = buf[0]; + BCD_TO_BIN(mon); + BCD_TO_BIN(day); + BCD_TO_BIN(hour); + BCD_TO_BIN(min); + BCD_TO_BIN(sec); + + return mktime(year, mon, day, hour, min, sec); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/timex.h linux/include/asm-arm/arch-rpc/timex.h --- v2.1.79/linux/include/asm-arm/arch-rpc/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/timex.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,13 @@ +/* + * linux/include/asm-arm/arch-rpc/timex.h + * + * RiscPC architecture timex specifications + * + * Copyright (C) 1997, 1998 Russell King + */ + +/* + * On the RiscPC, the clock ticks at 2MHz. + */ +#define CLOCK_TICK_RATE 2000000 + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/arch-rpc/uncompress.h linux/include/asm-arm/arch-rpc/uncompress.h --- v2.1.79/linux/include/asm-arm/arch-rpc/uncompress.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/arch-rpc/uncompress.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,143 @@ +/* + * linux/include/asm-arm/arch-a5k/uncompress.h + * + * Copyright (C) 1996 Russell King + */ +#define VIDMEM ((char *)SCREEN_START) + +#include "../arch/arm/drivers/char/font.h" +#include +#include + +int video_num_columns, video_num_lines, video_size_row; +int white, bytes_per_char_h; +extern unsigned long con_charconvtable[256]; + +struct param_struct { + unsigned long page_size; + unsigned long nr_pages; + unsigned long ramdisk_size; + unsigned long mountrootrdonly; + unsigned long rootdev; + unsigned long video_num_cols; + unsigned long video_num_rows; + unsigned long video_x; + unsigned long video_y; + unsigned long memc_control_reg; + unsigned char sounddefault; + unsigned char adfsdrives; + unsigned char bytes_per_char_h; + unsigned char bytes_per_char_v; + unsigned long unused[256/4-11]; +}; + +static const unsigned long palette_4[16] = { + 0x00000000, + 0x000000cc, + 0x0000cc00, /* Green */ + 0x0000cccc, /* Yellow */ + 0x00cc0000, /* Blue */ + 0x00cc00cc, /* Magenta */ + 0x00cccc00, /* Cyan */ + 0x00cccccc, /* White */ + 0x00000000, + 0x000000ff, + 0x0000ff00, + 0x0000ffff, + 0x00ff0000, + 0x00ff00ff, + 0x00ffff00, + 0x00ffffff +}; + +#define palette_setpixel(p) *(unsigned long *)(IO_START+0x00400000) = 0x10000000|((p) & 255) +#define palette_write(v) *(unsigned long *)(IO_START+0x00400000) = 0x00000000|((v) & 0x00ffffff) + +static struct param_struct * const params = (struct param_struct *)Z_PARAMS_BASE; + +#ifndef STANDALONE_DEBUG +/* + * This does not append a newline + */ +static void puts(const char *s) +{ + extern void ll_write_char(char *, unsigned long); + int x,y; + unsigned char c; + char *ptr; + + x = params->video_x; + y = params->video_y; + + while ( ( c = *(unsigned char *)s++ ) != '\0' ) { + if ( c == '\n' ) { + x = 0; + if ( ++y >= video_num_lines ) { + y--; + } + } else { + ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h); + ll_write_char(ptr, c|(white<<8)); + if ( ++x >= video_num_columns ) { + x = 0; + if ( ++y >= video_num_lines ) { + y--; + } + } + } + } + + params->video_x = x; + params->video_y = y; +} + +static void error(char *x); + +/* + * Setup for decompression + */ +static void arch_decomp_setup(void) +{ + int i; + + video_num_lines = params->video_num_rows; + video_num_columns = params->video_num_cols; + bytes_per_char_h = params->bytes_per_char_h; + video_size_row = video_num_columns * bytes_per_char_h; + if (bytes_per_char_h == 4) + for (i = 0; i < 256; i++) + con_charconvtable[i] = + (i & 128 ? 1 << 0 : 0) | + (i & 64 ? 1 << 4 : 0) | + (i & 32 ? 1 << 8 : 0) | + (i & 16 ? 1 << 12 : 0) | + (i & 8 ? 1 << 16 : 0) | + (i & 4 ? 1 << 20 : 0) | + (i & 2 ? 1 << 24 : 0) | + (i & 1 ? 1 << 28 : 0); + else + for (i = 0; i < 16; i++) + con_charconvtable[i] = + (i & 8 ? 1 << 0 : 0) | + (i & 4 ? 1 << 8 : 0) | + (i & 2 ? 1 << 16 : 0) | + (i & 1 ? 1 << 24 : 0); + + + palette_setpixel(0); + if (bytes_per_char_h == 1) { + palette_write (0); + palette_write (0x00ffffff); + for (i = 2; i < 256; i++) + palette_write (0); + white = 1; + } else { + for (i = 0; i < 256; i++) + palette_write (i < 16 ? palette_4[i] : 0); + white = 7; + } + + if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n"); +} +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/assembler.h linux/include/asm-arm/assembler.h --- v2.1.79/linux/include/asm-arm/assembler.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/assembler.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,34 @@ +/* + * linux/asm/assembler.h + * + * This file contains arm architecture specific defines + * for the different processors. + * + * Do not include any C declarations in this file - it is included by + * assembler source. + */ + +/* + * LOADREGS: multiple register load (ldm) with pc in register list + * (takes account of ARM6 not using ^) + * + * RETINSTR: return instruction: adds the 's' in at the end of the + * instruction if this is not an ARM6 + * + * SAVEIRQS: save IRQ state (not required on ARM2/ARM3 - done + * implicitly + * + * RESTOREIRQS: restore IRQ state (not required on ARM2/ARM3 - done + * implicitly with ldm ... ^ or movs. + * + * These next two need thinking about - can't easily use stack... (see system.S) + * DISABLEIRQS: disable IRQS in SVC mode + * + * ENABLEIRQS: enable IRQS in SVC mode + * + * USERMODE: switch to USER mode + * + * SVCMODE: switch to SVC mode + */ + +#include diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/atomic.h linux/include/asm-arm/atomic.h --- v2.1.79/linux/include/asm-arm/atomic.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/atomic.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,85 @@ +/* + * linux/include/asm-arm/atomic.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 27-06-1996 RMK Created + * 13-04-1997 RMK Made functions atomic! + * 07-12-1997 RMK Upgraded for v2.1. + */ +#ifndef __ASM_ARM_ATOMIC_H +#define __ASM_ARM_ATOMIC_H + +#include + +#ifdef __SMP__ +#error SMP not supported +#endif + +typedef struct { int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) (((v)->counter) = (i)) + +static __inline__ void atomic_add(int i, volatile atomic_t *v) +{ + unsigned long flags; + + save_flags_cli (flags); + v->counter += i; + restore_flags (flags); +} + +static __inline__ void atomic_sub(int i, volatile atomic_t *v) +{ + unsigned long flags; + + save_flags_cli (flags); + v->counter -= i; + restore_flags (flags); +} + +static __inline__ void atomic_inc(volatile atomic_t *v) +{ + unsigned long flags; + + save_flags_cli (flags); + v->counter += 1; + restore_flags (flags); +} + +static __inline__ void atomic_dec(volatile atomic_t *v) +{ + unsigned long flags; + + save_flags_cli (flags); + v->counter -= 1; + restore_flags (flags); +} + +static __inline__ int atomic_dec_and_test(volatile atomic_t *v) +{ + unsigned long flags; + int result; + + save_flags_cli (flags); + v->counter -= 1; + result = (v->counter == 0); + restore_flags (flags); + + return result; +} + +static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *addr) +{ + unsigned long flags; + + save_flags_cli (flags); + *addr &= ~mask; + restore_flags (flags); +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/bitops.h linux/include/asm-arm/bitops.h --- v2.1.79/linux/include/asm-arm/bitops.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/bitops.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,72 @@ +#ifndef __ASM_ARM_BITOPS_H +#define __ASM_ARM_BITOPS_H + +/* + * Copyright 1995, Russell King. + * Various bits and pieces copyrights include: + * Linus Torvalds (test_bit). + */ + +/* + * These should be done with inline assembly. + * All bit operations return 0 if the bit + * was cleared before the operation and != 0 if it was not. + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + */ + +/* + * Function prototypes to keep gcc -Wall happy + */ +extern void set_bit(int nr, volatile void * addr); +extern void clear_bit(int nr, volatile void * addr); +extern void change_bit(int nr, volatile void * addr); +extern int test_and_set_bit(int nr, volatile void * addr); +extern int test_and_clear_bit(int nr, volatile void * addr); +extern int test_and_change_bit(int nr, volatile void * addr); +extern int find_first_zero_bit(void * addr, unsigned size); +extern int find_next_zero_bit(void * addr, int size, int offset); + +/* + * This routine doesn't need to be atomic. + */ +extern __inline__ int test_bit(int nr, const void * addr) +{ + return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7)); +} + +/* + * ffz = Find First Zero in word. Undefined if no zero exists, + * so code should check against ~0UL first.. + */ +extern __inline__ unsigned long ffz(unsigned long word) +{ + int k; + + word = ~word; + k = 31; + if (word & 0x0000ffff) { k -= 16; word <<= 16; } + if (word & 0x00ff0000) { k -= 8; word <<= 8; } + if (word & 0x0f000000) { k -= 4; word <<= 4; } + if (word & 0x30000000) { k -= 2; word <<= 2; } + if (word & 0x40000000) { k -= 1; } + return k; +} + +#ifdef __KERNEL__ + +#define ext2_set_bit test_and_set_bit +#define ext2_clear_bit test_and_clear_bit +#define ext2_test_bit test_bit +#define ext2_find_first_zero_bit find_first_zero_bit +#define ext2_find_next_zero_bit find_next_zero_bit + +/* Bitmap functions for the minix filesystem. */ +#define minix_set_bit(nr,addr) test_and_set_bit(nr,addr) +#define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* __KERNEL__ */ + +#endif /* _ARM_BITOPS_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/bugs.h linux/include/asm-arm/bugs.h --- v2.1.79/linux/include/asm-arm/bugs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/bugs.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,13 @@ +/* + * include/asm-arm/bugs.h + * + * Copyright (C) 1995 Russell King + */ +#ifndef __ASM_BUGS_H +#define __ASM_BUGS_H + +#include + +#define check_bugs() processor._check_bugs() + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/byteorder.h linux/include/asm-arm/byteorder.h --- v2.1.79/linux/include/asm-arm/byteorder.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/byteorder.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,39 @@ +#ifndef __ASM_ARM_BYTEORDER_H +#define __ASM_ARM_BYTEORDER_H + +#include + +#ifdef __GNUC__ + +static __inline__ __const__ __u32 ___arch__swab32(__u32 x) +{ + unsigned long xx; + __asm__("eor\t%1, %0, %0, ror #16\n\t" + "bic\t%1, %1, #0xff0000\n\t" + "mov\t%0, %0, ror #8\n\t" + "eor\t%0, %0, %1, lsr #8\n\t" + : "=r" (x), "=&r" (xx) + : "0" (x)); + return x; +} + +static __inline__ __const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__("eor\t%0, %0, %0, lsr #8\n\t" + "eor\t%0, %0, %0, lsl #8\n\t" + "bic\t%0, %0, #0xff0000\n\t" + "eor\t%0, %0, %0, lsr #8\n\t" + : "=r" (x) + : "0" (x)); + return x; +} + +#define __arch__swab32(x) ___arch__swab32(x) +#define __arch__swab16(x) ___arch__swab16(x) + +#endif /* __GNUC__ */ + +#include + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/cache.h linux/include/asm-arm/cache.h --- v2.1.79/linux/include/asm-arm/cache.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/cache.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,10 @@ +/* + * include/asm-i386/cache.h + */ +#ifndef __ASMARM_CACHE_H +#define __ASMARM_CACHE_H + +#define L1_CACHE_BYTES 32 +#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/checksum.h linux/include/asm-arm/checksum.h --- v2.1.79/linux/include/asm-arm/checksum.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/checksum.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,154 @@ +/* + * linux/include/asm-arm/checksum.h + * + * IP checksum routines + * + * Copyright (C) Original authors of ../asm-i386/checksum.h + * Copyright (C) 1996,1997,1998 Russell King + */ +#ifndef __ASM_ARM_CHECKSUM_H +#define __ASM_ARM_CHECKSUM_H + +#ifndef __ASM_ARM_SEGMENT_H +#include +#endif + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); + +/* + * the same as csum_partial, but copies from src while it + * checksums, and handles user-space pointer exceptions correctly, when needed. + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + */ + +extern +unsigned int csum_partial_copy_from_user (const char *src, char *dst, int len, int sum, int *err_ptr); + +/* + * This combination is currently not used, but possible: + */ +extern +unsigned int csum_partial_copy_to_user (const char *src, char *dst, int len, int sum, int *err_ptr); + +/* + * These are the old (and unsafe) way of doing checksums, a warning message will be + * printed if they are used and an exception occurs. + * + * these functions should go away after some time. + */ +#define csum_partial_copy_fromuser csum_partial_copy +unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum); + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + * + * Converted and optimised for ARM by R. M. King. + * + * Note: the order that the LDM registers are loaded with respect to + * the adc's doesn't matter. + */ +static inline unsigned short ip_fast_csum(unsigned char * iph, + unsigned int ihl) { + unsigned int sum, tmp1; + + __asm__ __volatile__(" + sub %2, %2, #5 + ldr %0, [%1], #4 + ldr %3, [%1], #4 + adds %0, %0, %3 + ldr %3, [%1], #4 + adcs %0, %0, %3 + ldr %3, [%1], #4 + adcs %0, %0, %3 +1: ldr %3, [%1], #4 + adcs %0, %0, %3 + tst %2, #15 + subne %2, %2, #1 + bne 1b + adc %0, %0, #0 + adds %0, %0, %0, lsl #16 + addcs %0, %0, #0x10000 + mvn %0, %0 + mov %0, %0, lsr #16 + " + : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (tmp1) + : "1" (iph), "2" (ihl)); + return(sum); +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) { + __asm__ __volatile__(" + adds %0, %0, %1 + adcs %0, %0, %4 + adcs %0, %0, %5 + adc %0, %0, #0 + adds %0, %0, %0, lsl #16 + addcs %0, %0, #0x10000 + mvn %0, %0 + mov %0, %0, lsr #16 + " + : "=&r" (sum), "=&r" (saddr) + : "0" (daddr), "1"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum)); + return((unsigned short)sum); +} + +/* + * Fold a partial checksum without adding pseudo headers + */ +static inline unsigned int csum_fold(unsigned int sum) +{ + __asm__ __volatile__(" + adds %0, %0, %0, lsl #16 + addcs %0, %0, #0x10000 + mvn %0, %0 + mov %0, %0, lsr #16 + " + : "=r" (sum) + : "0" (sum)); + return sum; +} + + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ + +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) { + unsigned int sum; + + __asm__ __volatile__(" + adds %0, %0, %0, lsl #16 + addcs %0, %0, #0x10000 + mvn %0, %0 + mov %0, %0, lsr #16 + " + : "=r"(sum) + : "0" (csum_partial(buff, len, 0))); + return(sum); +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/current.h linux/include/asm-arm/current.h --- v2.1.79/linux/include/asm-arm/current.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/current.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,23 @@ +#ifndef _ASMARM_CURRENT_H +#define _ASMARM_CURRENT_H + +static inline unsigned long get_sp(void) +{ + unsigned long sp; + __asm__ ("mov %0,sp" : "=r" (sp)); + return sp; +} + +static inline struct task_struct *get_current(void) +{ + struct task_struct *ts; + __asm__ __volatile__(" + bic %0, sp, #0x1f00 + bic %0, %0, #0x00ff + " : "=r" (ts)); + return ts; +} + +#define current (get_current()) + +#endif /* _ASMARM_CURRENT_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/delay.h linux/include/asm-arm/delay.h --- v2.1.79/linux/include/asm-arm/delay.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/delay.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,32 @@ +#ifndef __ASM_ARM_DELAY_H +#define __ASM_ARM_DELAY_H + +/* + * Copyright (C) 1995 Russell King + * + * Delay routines, using a pre-computed "loops_per_second" value. + */ + +extern void __delay(int loops); + +/* + * division by multiplication: you don't have to worry about + * loss of precision. + * + * Use only for very small delays ( < 1 msec). Should probably use a + * lookup table, really, as the multiplications take much too long with + * short delays. This is a "reasonable" implementation, though (and the + * first constant multiplications gets optimized away if the delay is + * a constant) + */ +extern void udelay(unsigned long usecs); + +extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c) +{ + return a * b / c; +} + + + +#endif /* defined(_ARM_DELAY_H) */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/dma.h linux/include/asm-arm/dma.h --- v2.1.79/linux/include/asm-arm/dma.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/dma.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,28 @@ +#ifndef __ASM_ARM_DMA_H +#define __ASM_ARM_DMA_H + +#include + +#define MAX_DMA_CHANNELS 14 +#define DMA_0 8 +#define DMA_1 9 +#define DMA_2 10 +#define DMA_3 11 +#define DMA_S0 12 +#define DMA_S1 13 + +#define DMA_MODE_READ 0x44 +#define DMA_MODE_WRITE 0x48 + +extern const char dma_str[]; + +#include + +/* These are in kernel/dma.c: */ +/* reserve a DMA channel */ +extern int request_dma(unsigned int dmanr, const char * device_id); +/* release it again */ +extern void free_dma(unsigned int dmanr); + +#endif /* _ARM_DMA_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/ecard.h linux/include/asm-arm/ecard.h --- v2.1.79/linux/include/asm-arm/ecard.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/ecard.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,227 @@ +/* + * linux/include/asm-arm/ecard.h + * + * definitions for expansion cards + * + * This is a new system as from Linux 1.2.3 + * + * Changelog: + * 11-12-1996 RMK Further minor improvements + * 12-09-1997 RMK Added interrupt enable/disable for card level + * + * Reference: Acorns Risc OS 3 Programmers Reference Manuals. + */ + +#ifndef __ASM_ECARD_H +#define __ASM_ECARD_H + +/* + * Currently understood cards + * Manufacturer Product ID + */ +#define MANU_ACORN 0x0000 +#define PROD_ACORN_SCSI 0x0002 +#define PROD_ACORN_ETHER1 0x0003 +#define PROD_ACORN_MFM 0x000b + +#define MANU_ANT2 0x0011 +#define PROD_ANT_ETHER3 0x00a4 + +#define MANU_ATOMWIDE 0x0017 +#define PROD_ATOMWIDE_3PSERIAL 0x0090 + +#define MANU_OAK 0x0021 +#define PROD_OAK_SCSI 0x0058 + +#define MANU_MORLEY 0x002b +#define PROD_MORLEY_SCSI_UNCACHED 0x0067 + +#define MANU_CUMANA 0x003a +#define PROD_CUMANA_SCSI_1 0x00a0 +#define PROD_CUMANA_SCSI_2 0x003a + +#define MANU_ICS 0x003c +#define PROD_ICS_IDE 0x00ae + +#define MANU_SERPORT 0x003f +#define PROD_SERPORT_DSPORT 0x00b9 + +#define MANU_I3 0x0046 +#define PROD_I3_ETHERLAN500 0x00d4 +#define PROD_I3_ETHERLAN600 0x00ec +#define PROD_I3_ETHERLAN600A 0x011e + +#define MANU_ANT 0x0053 +#define PROD_ANT_ETHERB 0x00e4 + +#define MANU_ALSYSTEMS 0x005b +#define PROD_ALSYS_SCSIATAPI 0x0107 + +#define MANU_MCS 0x0063 +#define PROD_MCS_CONNECT32 0x0125 + + + +#ifdef ECARD_C +#define CONST +#else +#define CONST const +#endif + +#define MAX_ECARDS 8 + +/* Type of card's address space */ +typedef enum { + ECARD_IOC = 0, + ECARD_MEMC = 1 +} card_type_t; + +/* Speed of card for ECARD_IOC address space */ +typedef enum { + ECARD_SLOW = 0, + ECARD_MEDIUM = 1, + ECARD_FAST = 2, + ECARD_SYNC = 3 +} card_speed_t; + +/* Card ID structure */ +typedef struct { + unsigned short manufacturer; + unsigned short product; +} card_ids; + +/* External view of card ID information */ +struct in_ecld { + unsigned short product; + unsigned short manufacturer; + unsigned char ecld; + unsigned char country; + unsigned char fiqmask; + unsigned char irqmask; + unsigned long fiqaddr; + unsigned long irqaddr; +}; + +typedef struct expansion_card ecard_t; + +/* Card handler routines */ +typedef struct { + void (*irqenable)(ecard_t *ec, int irqnr); + void (*irqdisable)(ecard_t *ec, int irqnr); + void (*fiqenable)(ecard_t *ec, int fiqnr); + void (*fiqdisable)(ecard_t *ec, int fiqnr); +} expansioncard_ops_t; + +typedef unsigned long *loader_t; + +/* + * This contains all the info needed on an expansion card + */ +struct expansion_card { + /* Public data */ + volatile unsigned char *irqaddr; /* address of IRQ register */ + volatile unsigned char *fiqaddr; /* address of FIQ register */ + unsigned char irqmask; /* IRQ mask */ + unsigned char fiqmask; /* FIQ mask */ + unsigned char claimed; /* Card claimed? */ + CONST unsigned char slot_no; /* Slot number */ + CONST unsigned char irq; /* IRQ number (for request_irq) */ + CONST unsigned char fiq; /* FIQ number (for request_irq) */ + CONST unsigned short unused; + CONST struct in_ecld cld; /* Card Identification */ + void *irq_data; /* Data for use for IRQ by card */ + void *fiq_data; /* Data for use for FIQ by card */ + expansioncard_ops_t *ops; /* Enable/Disable Ops for card */ + + /* Private internal data */ + CONST unsigned int podaddr; /* Base Linux address for card */ + CONST loader_t loader; /* loader program */ +}; + +struct in_chunk_dir { + unsigned int start_offset; + union { + unsigned char string[256]; + unsigned char data[1]; + } d; +}; + +/* + * ecard_claim: claim an expansion card entry + */ +#define ecard_claim(ec) ((ec)->claimed = 1) + +/* + * ecard_release: release an expansion card entry + */ +#define ecard_release(ec) ((ec)->claimed = 0) + +/* + * Start finding cards from the top of the list + */ +extern void ecard_startfind (void); + +/* + * Find an expansion card with the correct cld, product and manufacturer code + */ +extern struct expansion_card *ecard_find (int cld, const card_ids *ids); + +/* + * Read a chunk from an expansion card + * cd : where to put read data + * ec : expansion card info struct + * id : id number to find + * num: (n+1)'th id to find. + */ +extern int ecard_readchunk (struct in_chunk_dir *cd, struct expansion_card *ec, int id, int num); + +/* + * Obtain the address of a card + */ +extern unsigned int ecard_address (struct expansion_card *ec, card_type_t card_type, card_speed_t speed); + +#ifdef ECARD_C +/* Definitions internal to ecard.c - for it's use only!! + * + * External expansion card header as read from the card + */ +struct ex_ecld { + unsigned char r_ecld; + unsigned char r_reserved[2]; + unsigned char r_product[2]; + unsigned char r_manufacturer[2]; + unsigned char r_country; + long r_fiqs; + long r_irqs; +#define e_ecld(x) ((x)->r_ecld) +#define e_cd(x) ((x)->r_reserved[0] & 1) +#define e_is(x) ((x)->r_reserved[0] & 2) +#define e_w(x) (((x)->r_reserved[0] & 12)>>2) +#define e_prod(x) ((x)->r_product[0]|((x)->r_product[1]<<8)) +#define e_manu(x) ((x)->r_manufacturer[0]|((x)->r_manufacturer[1]<<8)) +#define e_country(x) ((x)->r_country) +#define e_fiqmask(x) ((x)->r_fiqs & 0xff) +#define e_fiqaddr(x) ((x)->r_fiqs >> 8) +#define e_irqmask(x) ((x)->r_irqs & 0xff) +#define e_irqaddr(x) ((x)->r_irqs >> 8) +}; + +/* + * Chunk directory entry as read from the card + */ +struct ex_chunk_dir { + unsigned char r_id; + unsigned char r_len[3]; + unsigned long r_start; + union { + char string[256]; + char data[1]; + } d; +#define c_id(x) ((x)->r_id) +#define c_len(x) ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16)) +#define c_start(x) ((x)->r_start) +}; + +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/elf.h linux/include/asm-arm/elf.h --- v2.1.79/linux/include/asm-arm/elf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/elf.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,54 @@ +#ifndef __ASMARM_ELF_H +#define __ASMARM_ELF_H + +/* + * ELF register definitions.. + */ + +#include + +typedef unsigned long elf_greg_t; + +#define EM_ARM 40 + +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct { void *null; } elf_fpregset_t; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ( ((x) == EM_ARM) ) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB; +#define ELF_ARCH EM_ARM + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 32768 + +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) + +#define R_ARM_NONE (0) +#define R_ARM_32 (1) /* => ld 32 */ +#define R_ARM_PC26 (2) /* => ld b/bl branches */ +#define R_ARM_PC32 (3) +#define R_ARM_GOT32 (4) /* -> object relocation into GOT */ +#define R_ARM_PLT32 (5) +#define R_ARM_COPY (6) /* => dlink copy object */ +#define R_ARM_GLOB_DAT (7) /* => dlink 32bit absolute address for .got */ +#define R_ARM_JUMP_SLOT (8) /* => dlink 32bit absolute address for .got.plt */ +#define R_ARM_RELATIVE (9) /* => ld resolved 32bit absolute address requiring load address adjustment */ +#define R_ARM_GOTOFF (10) /* => ld calculates offset of data from base of GOT */ +#define R_ARM_GOTPC (11) /* => ld 32-bit relative offset */ + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/errno.h linux/include/asm-arm/errno.h --- v2.1.79/linux/include/asm-arm/errno.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/errno.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,132 @@ +#ifndef _ARM_ERRNO_H +#define _ARM_ERRNO_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/fcntl.h linux/include/asm-arm/fcntl.h --- v2.1.79/linux/include/asm-arm/fcntl.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/fcntl.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,59 @@ +#ifndef _ARM_FCNTL_H +#define _ARM_FCNTL_H + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define FASYNC 020000 /* fcntl, for BSD compatibility */ + +#define F_DUPFD 0 /* dup */ +#define F_GETFD 1 /* get f_flags */ +#define F_SETFD 2 /* set f_flags */ +#define F_GETFL 3 /* more flags (cloexec) */ +#define F_SETFL 4 +#define F_GETLK 5 +#define F_SETLK 6 +#define F_SETLKW 7 + +#define F_SETOWN 8 /* for sockets. */ +#define F_GETOWN 9 /* for sockets. */ + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* for posix fcntl() and lockf() */ +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +/* operations for bsd flock(), also used by the kernel implementation */ +#define LOCK_SH 1 /* shared lock */ +#define LOCK_EX 2 /* exclusive lock */ +#define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +#define LOCK_UN 8 /* remove lock */ + +struct flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; +}; + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/floppy.h linux/include/asm-arm/floppy.h --- v2.1.79/linux/include/asm-arm/floppy.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/floppy.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,113 @@ +/* + * linux/include/asm-arm/floppy.h + * + * (C) 1996 Russell King + */ +#ifndef __ASM_ARM_FLOPPY_H +#define __ASM_ARM_FLOPPY_H +#if 0 +#include +#endif + +#define fd_outb(val,port) outb((val),(port)) +#define fd_inb(port) inb((port)) +#define fd_request_irq() request_irq(IRQ_FLOPPYDISK,floppy_interrupt,\ + SA_INTERRUPT|SA_SAMPLE_RANDOM,"floppy",NULL) +#define fd_free_irq() free_irq(IRQ_FLOPPYDISK,NULL) +#define fd_disable_irq() disable_irq(IRQ_FLOPPYDISK) +#define fd_enable_irq() enable_irq(IRQ_FLOPPYDISK) + +#define fd_request_dma() request_dma(FLOPPY_DMA,"floppy") +#define fd_free_dma() free_dma(FLOPPY_DMA) +#define fd_disable_dma() disable_dma(FLOPPY_DMA) +#define fd_enable_dma() enable_dma(FLOPPY_DMA) +#define fd_clear_dma_ff() clear_dma_ff(FLOPPY_DMA) +#define fd_set_dma_mode(mode) set_dma_mode(FLOPPY_DMA, (mode)) +#define fd_set_dma_addr(addr) set_dma_addr(FLOPPY_DMA, virt_to_bus((addr))) +#define fd_set_dma_count(len) set_dma_count(FLOPPY_DMA, (len)) +#define fd_cacheflush(addr,sz) + +/* Floppy_selects is the list of DOR's to select drive fd + * + * On initialisation, the floppy list is scanned, and the drives allocated + * in the order that they are found. This is done by seeking the drive + * to a non-zero track, and then restoring it to track 0. If an error occurs, + * then there is no floppy drive present. [to be put back in again] + */ +static unsigned char floppy_selects[2][4] = +{ + { 0x10, 0x21, 0x23, 0x33 }, + { 0x10, 0x21, 0x23, 0x33 } +}; + +#define fd_setdor(dor) \ +do { \ + int new_dor = (dor); \ + if (new_dor & 0xf0) \ + fd_outb((new_dor & 0x0c) | floppy_selects[fdc][new_dor & 3], FD_DOR); \ + else \ + fd_outb((new_dor & 0x0c), FD_DOR); \ +} while (0) + +/* + * Someday, we'll automatically detect which drives are present... + */ +extern __inline__ void fd_scandrives (void) +{ +#if 0 + int floppy, drive_count; + + fd_disable_irq(); + raw_cmd = &default_raw_cmd; + raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_SEEK; + raw_cmd->track = 0; + raw_cmd->rate = ?; + drive_count = 0; + for (floppy = 0; floppy < 4; floppy ++) { + current_drive = drive_count; + /* + * Turn on floppy motor + */ + if (start_motor(redo_fd_request)) + continue; + /* + * Set up FDC + */ + fdc_specify(); + /* + * Tell FDC to recalibrate + */ + output_byte(FD_RECALIBRATE); + LAST_OUT(UNIT(floppy)); + /* wait for command to complete */ + if (!successful) { + int i; + for (i = drive_count; i < 3; i--) + floppy_selects[fdc][i] = floppy_selects[fdc][i + 1]; + floppy_selects[fdc][3] = 0; + floppy -= 1; + } else + drive_count++; + } +#else + floppy_selects[0][0] = 0x10; + floppy_selects[0][1] = 0x21; + floppy_selects[0][2] = 0x23; + floppy_selects[0][3] = 0x33; +#endif +} + +#define FDC1 (0x3f0) +static int FDC2 = -1; + +#define FLOPPY0_TYPE 4 +#define FLOPPY1_TYPE 4 + +#define N_FDC 1 +#define N_DRIVE 8 + +#define FLOPPY_MOTOR_MASK 0xf0 + +#define CROSS_64KB(a,s) (0) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/hardirq.h linux/include/asm-arm/hardirq.h --- v2.1.79/linux/include/asm-arm/hardirq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/hardirq.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,23 @@ +#ifndef __ASM_HARDIRQ_H +#define __ASM_HARDIRQ_H + +#include + +extern unsigned int local_irq_count[NR_CPUS]; +#define in_interrupt() (local_irq_count[smp_processor_id()] != 0) + +#ifndef __SMP__ + +#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0) +#define hardirq_endlock(cpu) do { } while (0) + +#define hardirq_enter(cpu) (local_irq_count[cpu]++) +#define hardirq_exit(cpu) (local_irq_count[cpu]--) + +#define synchronize_irq() do { } while (0) + +#else +#error SMP not supported +#endif /* __SMP__ */ + +#endif /* __ASM_HARDIRQ_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/hardware.h linux/include/asm-arm/hardware.h --- v2.1.79/linux/include/asm-arm/hardware.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/hardware.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,271 @@ +/* + * linux/include/asm-arm/hardware.h + * + * Copyright (C) 1996 Russell King + * + * Common hardware definitions + */ + +#ifndef __ASM_HARDWARE_H +#define __ASM_HARDWARE_H + +#include + +/* + * Use these macros to read/write the IOC. All it does is perform the actual + * read/write. + */ +#ifdef HAS_IOC +#ifndef __ASSEMBLER__ +#define __IOC(offset) (IOC_BASE + (offset >> 2)) +#else +#define __IOC(offset) offset +#endif + +#define IOC_CONTROL __IOC(0x00) +#define IOC_KARTTX __IOC(0x04) +#define IOC_KARTRX __IOC(0x04) + +#define IOC_IRQSTATA __IOC(0x10) +#define IOC_IRQREQA __IOC(0x14) +#define IOC_IRQCLRA __IOC(0x14) +#define IOC_IRQMASKA __IOC(0x18) + +#define IOC_IRQSTATB __IOC(0x20) +#define IOC_IRQREQB __IOC(0x24) +#define IOC_IRQMASKB __IOC(0x28) + +#define IOC_FIQSTAT __IOC(0x30) +#define IOC_FIQREQ __IOC(0x34) +#define IOC_FIQMASK __IOC(0x38) + +#define IOC_T0CNTL __IOC(0x40) +#define IOC_T0LTCHL __IOC(0x40) +#define IOC_T0CNTH __IOC(0x44) +#define IOC_T0LTCHH __IOC(0x44) +#define IOC_T0GO __IOC(0x48) +#define IOC_T0LATCH __IOC(0x4c) + +#define IOC_T1CNTL __IOC(0x50) +#define IOC_T1LTCHL __IOC(0x50) +#define IOC_T1CNTH __IOC(0x54) +#define IOC_T1LTCHH __IOC(0x54) +#define IOC_T1GO __IOC(0x58) +#define IOC_T1LATCH __IOC(0x5c) + +#define IOC_T2CNTL __IOC(0x60) +#define IOC_T2LTCHL __IOC(0x60) +#define IOC_T2CNTH __IOC(0x64) +#define IOC_T2LTCHH __IOC(0x64) +#define IOC_T2GO __IOC(0x68) +#define IOC_T2LATCH __IOC(0x6c) + +#define IOC_T3CNTL __IOC(0x70) +#define IOC_T3LTCHL __IOC(0x70) +#define IOC_T3CNTH __IOC(0x74) +#define IOC_T3LTCHH __IOC(0x74) +#define IOC_T3GO __IOC(0x78) +#define IOC_T3LATCH __IOC(0x7c) +#endif + +#ifdef HAS_MEMC +#define VDMA_ALIGNMENT PAGE_SIZE +#define VDMA_XFERSIZE 16 +#define VDMA_INIT 0 +#define VDMA_START 1 +#define VDMA_END 2 + +#define video_set_dma(start,end,offset) \ +do { \ + memc_write (VDMA_START, (start >> 2)); \ + memc_write (VDMA_END, (end - VDMA_XFERSIZE) >> 2); \ + memc_write (VDMA_INIT, (offset >> 2)); \ +} while (0) +#endif + +#ifdef HAS_IOMD +#ifndef __ASSEMBLER__ +#define __IOMD(offset) (IOMD_BASE + (offset >> 2)) +#else +#define __IOMD(offset) offset +#endif + +#define IOMD_CONTROL __IOMD(0x000) +#define IOMD_KARTTX __IOMD(0x004) +#define IOMD_KARTRX __IOMD(0x004) +#define IOMD_KCTRL __IOMD(0x008) + +#define IOMD_IRQSTATA __IOMD(0x010) +#define IOMD_IRQREQA __IOMD(0x014) +#define IOMD_IRQCLRA __IOMD(0x014) +#define IOMD_IRQMASKA __IOMD(0x018) + +#define IOMD_IRQSTATB __IOMD(0x020) +#define IOMD_IRQREQB __IOMD(0x024) +#define IOMD_IRQMASKB __IOMD(0x028) + +#define IOMD_FIQSTAT __IOMD(0x030) +#define IOMD_FIQREQ __IOMD(0x034) +#define IOMD_FIQMASK __IOMD(0x038) + +#define IOMD_T0CNTL __IOMD(0x040) +#define IOMD_T0LTCHL __IOMD(0x040) +#define IOMD_T0CNTH __IOMD(0x044) +#define IOMD_T0LTCHH __IOMD(0x044) +#define IOMD_T0GO __IOMD(0x048) +#define IOMD_T0LATCH __IOMD(0x04c) + +#define IOMD_T1CNTL __IOMD(0x050) +#define IOMD_T1LTCHL __IOMD(0x050) +#define IOMD_T1CNTH __IOMD(0x054) +#define IOMD_T1LTCHH __IOMD(0x054) +#define IOMD_T1GO __IOMD(0x058) +#define IOMD_T1LATCH __IOMD(0x05c) + +#define IOMD_ROMCR0 __IOMD(0x080) +#define IOMD_ROMCR1 __IOMD(0x084) +#define IOMD_DRAMCR __IOMD(0x088) +#define IOMD_VREFCR __IOMD(0x08C) + +#define IOMD_FSIZE __IOMD(0x090) +#define IOMD_ID0 __IOMD(0x094) +#define IOMD_ID1 __IOMD(0x098) +#define IOMD_VERSION __IOMD(0x09C) + +#define IOMD_MOUSEX __IOMD(0x0A0) +#define IOMD_MOUSEY __IOMD(0x0A4) + +#define IOMD_DMATCR __IOMD(0x0C0) +#define IOMD_IOTCR __IOMD(0x0C4) +#define IOMD_ECTCR __IOMD(0x0C8) +#define IOMD_DMAEXT __IOMD(0x0CC) + +#define IOMD_IO0CURA __IOMD(0x100) +#define IOMD_IO0ENDA __IOMD(0x104) +#define IOMD_IO0CURB __IOMD(0x108) +#define IOMD_IO0ENDB __IOMD(0x10C) +#define IOMD_IO0CR __IOMD(0x110) +#define IOMD_IO0ST __IOMD(0x114) + +#define IOMD_IO1CURA __IOMD(0x120) +#define IOMD_IO1ENDA __IOMD(0x124) +#define IOMD_IO1CURB __IOMD(0x128) +#define IOMD_IO1ENDB __IOMD(0x12C) +#define IOMD_IO1CR __IOMD(0x130) +#define IOMD_IO1ST __IOMD(0x134) + +#define IOMD_IO2CURA __IOMD(0x140) +#define IOMD_IO2ENDA __IOMD(0x144) +#define IOMD_IO2CURB __IOMD(0x148) +#define IOMD_IO2ENDB __IOMD(0x14C) +#define IOMD_IO2CR __IOMD(0x150) +#define IOMD_IO2ST __IOMD(0x154) + +#define IOMD_IO3CURA __IOMD(0x160) +#define IOMD_IO3ENDA __IOMD(0x164) +#define IOMD_IO3CURB __IOMD(0x168) +#define IOMD_IO3ENDB __IOMD(0x16C) +#define IOMD_IO3CR __IOMD(0x170) +#define IOMD_IO3ST __IOMD(0x174) + +#define IOMD_SD0CURA __IOMD(0x180) +#define IOMD_SD0ENDA __IOMD(0x184) +#define IOMD_SD0CURB __IOMD(0x188) +#define IOMD_SD0ENDB __IOMD(0x18C) +#define IOMD_SD0CR __IOMD(0x190) +#define IOMD_SD0ST __IOMD(0x194) + +#define IOMD_SD1CURA __IOMD(0x1A0) +#define IOMD_SD1ENDA __IOMD(0x1A4) +#define IOMD_SD1CURB __IOMD(0x1A8) +#define IOMD_SD1ENDB __IOMD(0x1AC) +#define IOMD_SD1CR __IOMD(0x1B0) +#define IOMD_SD1ST __IOMD(0x1B4) + +#define IOMD_CURSCUR __IOMD(0x1C0) +#define IOMD_CURSINIT __IOMD(0x1C4) + +#define IOMD_VIDCUR __IOMD(0x1D0) +#define IOMD_VIDEND __IOMD(0x1D4) +#define IOMD_VIDSTART __IOMD(0x1D8) +#define IOMD_VIDINIT __IOMD(0x1DC) +#define IOMD_VIDCR __IOMD(0x1E0) + +#define IOMD_DMASTAT __IOMD(0x1F0) +#define IOMD_DMAREQ __IOMD(0x1F4) +#define IOMD_DMAMASK __IOMD(0x1F8) + +#define DMA_CR_C 0x80 +#define DMA_CR_D 0x40 +#define DMA_CR_E 0x20 + +#define DMA_ST_OFL 4 +#define DMA_ST_INT 2 +#define DMA_ST_AB 1 +/* + * IOC compatability + */ +#define IOC_CONTROL IOMD_CONTROL +#define IOC_IRQSTATA IOMD_IRQSTATA +#define IOC_IRQREQA IOMD_IRQREQA +#define IOC_IRQCLRA IOMD_IRQCLRA +#define IOC_IRQMASKA IOMD_IRQMASKA + +#define IOC_IRQSTATB IOMD_IRQSTATB +#define IOC_IRQREQB IOMD_IRQREQB +#define IOC_IRQMASKB IOMD_IRQMASKB + +#define IOC_FIQSTAT IOMD_FIQSTAT +#define IOC_FIQREQ IOMD_FIQREQ +#define IOC_FIQMASK IOMD_FIQMASK + +#define IOC_T0CNTL IOMD_T0CNTL +#define IOC_T0LTCHL IOMD_T0LTCHL +#define IOC_T0CNTH IOMD_T0CNTH +#define IOC_T0LTCHH IOMD_T0LTCHH +#define IOC_T0GO IOMD_T0GO +#define IOC_T0LATCH IOMD_T0LATCH + +#define IOC_T1CNTL IOMD_T1CNTL +#define IOC_T1LTCHL IOMD_T1LTCHL +#define IOC_T1CNTH IOMD_T1CNTH +#define IOC_T1LTCHH IOMD_T1LTCHH +#define IOC_T1GO IOMD_T1GO +#define IOC_T1LATCH IOMD_T1LATCH + +/* + * DMA (MEMC) compatability + */ +#define HALF_SAM vram_half_sam +#define VDMA_ALIGNMENT (HALF_SAM * 2) +#define VDMA_XFERSIZE (HALF_SAM) +#define VDMA_INIT IOMD_VIDINIT +#define VDMA_START IOMD_VIDSTART +#define VDMA_END IOMD_VIDEND + +#ifndef __ASSEMBLER__ +extern unsigned int vram_half_sam; +#define video_set_dma(start,end,offset) \ +do { \ + outl (SCREEN_START + start, VDMA_START); \ + outl (SCREEN_START + end - VDMA_XFERSIZE, VDMA_END); \ + if (offset >= end - VDMA_XFERSIZE) \ + offset |= 0x40000000; \ + outl (SCREEN_START + offset, VDMA_INIT); \ +} while (0) +#endif +#endif + +#ifdef HAS_EXPMASK +#ifndef __ASSEMBLER__ +#define __EXPMASK(offset) (((volatile unsigned char *)EXPMASK_BASE)[offset]) +#else +#define __EXPMASK(offset) offset +#endif + +#define EXPMASK_STATUS __EXPMASK(0x00) +#define EXPMASK_ENABLE __EXPMASK(0x04) + +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/ide.h linux/include/asm-arm/ide.h --- v2.1.79/linux/include/asm-arm/ide.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/ide.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,85 @@ +/* + * linux/include/asm-arm/ide.h + * + * Copyright (C) 1994-1996 Linus Torvalds & authors + */ + +/* + * This file contains the i386 architecture specific IDE code. + */ + +#ifndef __ASMARM_IDE_H +#define __ASMARM_IDE_H + +#ifdef __KERNEL__ + +typedef unsigned long ide_ioreg_t; + +#ifndef MAX_HWIFS +#define MAX_HWIFS 4 +#endif + +#define ide_sti() sti() + +#include + +typedef union { + unsigned all : 8; /* all of the bits together */ + struct { + unsigned head : 4; /* always zeros here */ + unsigned unit : 1; /* drive select number, 0 or 1 */ + unsigned bit5 : 1; /* always 1 */ + unsigned lba : 1; /* using LBA instead of CHS */ + unsigned bit7 : 1; /* always 1 */ + } b; + } select_t; + +static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *device, void *dev_id) +{ + return request_irq(irq, handler, flags, device, dev_id); +} + +static __inline__ void ide_free_irq(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); +} + +static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent) +{ + return check_region(from, extent); +} + +static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name) +{ + request_region(from, extent, name); +} + +static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent) +{ + release_region(from, extent); +} + +/* + * The following are not needed for the non-m68k ports + */ +static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port) +{ + return(1); +} + +static __inline__ void ide_fix_driveid(struct hd_driveid *id) +{ +} + +static __inline__ void ide_release_lock (int *ide_lock) +{ +} + +static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data) +{ +} + +#endif /* __KERNEL__ */ + +#endif /* __ASMi386_IDE_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/init.h linux/include/asm-arm/init.h --- v2.1.79/linux/include/asm-arm/init.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/init.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,24 @@ +#ifndef _ASMARM_INIT_H +#define _ASMARM_INIT_H + +#if 0 +#define __init __attribute__ ((__section__ (".text.init"))) +#define __initdata __attribute__ ((__section__ (".data.init"))) +#define __initfunc(__arginit) \ + __arginit __init; \ + __arginit +/* For assembly routines */ +#define __INIT .section ".text.init",@alloc,@execinstr +#define __FINIT .previous +#define __INITDATA .section ".data.init",@alloc,@write +#else +#define __init +#define __initdata +#define __initfunc(__arginit) __arginit +/* For assembly routines */ +#define __INIT +#define __FINIT +#define __INITDATA +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/io.h linux/include/asm-arm/io.h --- v2.1.79/linux/include/asm-arm/io.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/io.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,203 @@ +/* + * linux/include/asm-arm/io.h + * + * Copyright (C) 1996 Russell King + * + * Modifications: + * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both + * constant addresses and variable addresses. + * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture + * specific IO header files. + */ +#ifndef __ASM_ARM_IO_H +#define __ASM_ARM_IO_H + +#include +#include +#include + +/* unsigned long virt_to_phys(void *x) */ +#define virt_to_phys(x) __virt_to_phys((unsigned long)(x)) + +/* void *phys_to_virt(unsigned long x) */ +#define phys_to_virt(x) ((void *)(__phys_to_virt((unsigned long)(x)))) + +/* + * These macros actually build the multi-value IO function prototypes + */ +#define __OUTS(s,i,x) extern void outs##s(unsigned int port, const void *from, int len); +#define __INS(s,i,x) extern void ins##s(unsigned int port, void *to, int len); + +#define __IO(s,i,x) \ + __OUTS(s,i,x) \ + __INS(s,i,x) + +__IO(b,"b",char) +__IO(w,"h",short) +__IO(l,"",long) + +/* + * Note that due to the way __builtin_constant_t() works, you + * - can't use it inside an inline function (it will never be true) + * - you don't have to worry about side effects withing the __builtin.. + */ +#ifdef __outbc +#define outb(val,port) \ + (__builtin_constant_p((port)) ? __outbc((val),(port)) : __outb((val),(port))) +#else +#define outb(val,port) __outb((val),(port)) +#endif + +#ifdef __outwc +#define outw(val,port) \ + (__builtin_constant_p((port)) ? __outwc((val),(port)) : __outw((val),(port))) +#else +#define outw(val,port) __outw((val),(port)) +#endif + +#ifdef __outlc +#define outl(val,port) \ + (__builtin_constant_p((port)) ? __outlc((val),(port)) : __outl((val),(port))) +#else +#define outl(val,port) __outl((val),(port)) +#endif + +#ifdef __inbc +#define inb(port) \ + (__builtin_constant_p((port)) ? __inbc((port)) : __inb((port))) +#else +#define inb(port) __inb((port)) +#endif + +#ifdef __inwc +#define inw(port) \ + (__builtin_constant_p((port)) ? __inwc((port)) : __inw((port))) +#else +#define inw(port) __inw((port)) +#endif + +#ifdef __inlc +#define inl(port) \ + (__builtin_constant_p((port)) ? __inlc((port)) : __inl((port))) +#else +#define inl(port) __inl((port)) +#endif + +/* + * This macro will give you the translated IO address for this particular + * architecture, which can be used with the out_t... functions. + */ +#define ioaddr(port) \ + (__builtin_constant_p((port)) ? __ioaddrc((port)) : __ioaddr((port))) + +#ifndef ARCH_IO_DELAY +/* + * This architecture does not require any delayed IO. + * It is handled in the hardware. + */ +#define outb_p(val,port) outb((val),(port)) +#define outw_p(val,port) outw((val),(port)) +#define outl_p(val,port) outl((val),(port)) +#define inb_p(port) inb((port)) +#define inw_p(port) inw((port)) +#define inl_p(port) inl((port)) +#define outsb_p(port,from,len) outsb(port,from,len) +#define outsw_p(port,from,len) outsw(port,from,len) +#define outsl_p(port,from,len) outsl(port,from,len) +#define insb_p(port,to,len) insb(port,to,len) +#define insw_p(port,to,len) insw(port,to,len) +#define insl_p(port,to,len) insl(port,to,len) + +#else + +/* + * We have to delay the IO... + */ +#ifdef __outbc_p +#define outb_p(val,port) \ + (__builtin_constant_p((port)) ? __outbc_p((val),(port)) : __outb_p((val),(port))) +#else +#define outb_p(val,port) __outb_p((val),(port)) +#endif + +#ifdef __outwc_p +#define outw_p(val,port) \ + (__builtin_constant_p((port)) ? __outwc_p((val),(port)) : __outw_p((val),(port))) +#else +#define outw_p(val,port) __outw_p((val),(port)) +#endif + +#ifdef __outlc_p +#define outl_p(val,port) \ + (__builtin_constant_p((port)) ? __outlc_p((val),(port)) : __outl_p((val),(port))) +#else +#define outl_p(val,port) __outl_p((val),(port)) +#endif + +#ifdef __inbc_p +#define inb_p(port) \ + (__builtin_constant_p((port)) ? __inbc_p((port)) : __inb_p((port))) +#else +#define inb_p(port) __inb_p((port)) +#endif + +#ifdef __inwc_p +#define inw_p(port) \ + (__builtin_constant_p((port)) ? __inwc_p((port)) : __inw_p((port))) +#else +#define inw_p(port) __inw_p((port)) +#endif + +#ifdef __inlc_p +#define inl_p(port) \ + (__builtin_constant_p((port)) ? __inlc_p((port)) : __inl_p((port))) +#else +#define inl_p(port) __inl_p((port)) +#endif + +#endif + +#undef ARCH_IO_DELAY +#undef ARCH_IO_CONSTANT + +/* + * Leftovers... + */ +#if 0 +#define __outwc(value,port) \ +({ \ + if (port < 256) \ + __asm__ __volatile__( \ + "strh %0, [%1, %2]" \ + : : "r" (value), "r" (PCIO_BASE), "J" (port << 2)); \ + else if (__PORT_PCIO(port)) \ + __asm__ __volatile__( \ + "strh %0, [%1, %2]" \ + : : "r" (value), "r" (PCIO_BASE), "r" (port << 2)); \ + else \ + __asm__ __volatile__( \ + "strh %0, [%1, %2]" \ + : : "r" (value), "r" (IO_BASE), "r" (port << 2)); \ +}) + +#define __inwc(port) \ +({ \ + unsigned short result; \ + if (port < 256) \ + __asm__ __volatile__( \ + "ldrh %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "J" (port << 2)); \ + else \ + if (__PORT_PCIO(port)) \ + __asm__ __volatile__( \ + "ldrh %0, [%1, %2]" \ + : "=r" (result) : "r" (PCIO_BASE), "r" (port << 2)); \ + else \ + __asm__ __volatile__( \ + "ldrh %0, [%1, %2]" \ + : "=r" (result) : "r" (IO_BASE), "r" (port << 2)); \ + result; \ +}) +#endif +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/ioctl.h linux/include/asm-arm/ioctl.h --- v2.1.79/linux/include/asm-arm/ioctl.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/ioctl.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,75 @@ +/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $ + * + * linux/ioctl.h for Linux by H.H. Bergman. + */ + +#ifndef _ASMARM_IOCTL_H +#define _ASMARM_IOCTL_H + +/* ioctl command encoding: 32 bits total, command in lower 16 bits, + * size of the parameter structure in the lower 14 bits of the + * upper 16 bits. + * Encoding the size of the parameter structure in the ioctl request + * is useful for catching programs compiled with old versions + * and to avoid overwriting user space outside the user buffer area. + * The highest 2 bits are reserved for indicating the ``access mode''. + * NOTE: This limits the max parameter size to 16kB -1 ! + */ + +/* + * The following is for compatibility across the various Linux + * platforms. The i386 ioctl numbering scheme doesn't really enforce + * a type field. De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here. Please be sure to use the decoding macros + * below from now on. + */ +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 14 +#define _IOC_DIRBITS 2 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits. + */ +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode ioctl numbers.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +#endif /* _ASMARM_IOCTL_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/ioctls.h linux/include/asm-arm/ioctls.h --- v2.1.79/linux/include/asm-arm/ioctls.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/ioctls.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,78 @@ +#ifndef __ASM_ARM_IOCTLS_H +#define __ASM_ARM_IOCTLS_H + +#include + +/* 0x54 is just a magic number to make these relatively unique ('T') */ + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ + +#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/ipc.h linux/include/asm-arm/ipc.h --- v2.1.79/linux/include/asm-arm/ipc.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/ipc.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,28 @@ +#ifndef __ASMARM_IPC_H +#define __ASMARM_IPC_H + +/* + * These are used to wrap system calls on ARM. + * + * See arch/arm/kernel/sys-arm.c for ugly details.. + */ +struct ipc_kludge { + struct msgbuf *msgp; + long msgtyp; +}; + +#define SEMOP 1 +#define SEMGET 2 +#define SEMCTL 3 +#define MSGSND 11 +#define MSGRCV 12 +#define MSGGET 13 +#define MSGCTL 14 +#define SHMAT 21 +#define SHMDT 22 +#define SHMGET 23 +#define SHMCTL 24 + +#define IPCCALL(version,op) ((version)<<16 | (op)) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/irq-no.h linux/include/asm-arm/irq-no.h --- v2.1.79/linux/include/asm-arm/irq-no.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/irq-no.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,11 @@ +/* + * linux/include/asm-arm/irq-no.h + * + * Machine independent interrupt numbers + */ + +#include + +#ifndef NR_IRQS +#define NR_IRQS 128 +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/irq.h linux/include/asm-arm/irq.h --- v2.1.79/linux/include/asm-arm/irq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/irq.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,13 @@ +#ifndef __ASM_ARM_IRQ_H +#define __ASM_ARM_IRQ_H + +#include + +extern void disable_irq(unsigned int); +extern void enable_irq(unsigned int); + +#define __STR(x) #x +#define STR(x) __STR(x) + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/limits.h linux/include/asm-arm/limits.h --- v2.1.79/linux/include/asm-arm/limits.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/limits.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,11 @@ +#ifndef __ASM_PIPE_H +#define __ASM_PIPE_H + +#ifndef PAGE_SIZE +#include +#endif + +#define PIPE_BUF PAGE_SIZE + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/mm-init.h linux/include/asm-arm/mm-init.h --- v2.1.79/linux/include/asm-arm/mm-init.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/mm-init.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,46 @@ +/* + * linux/include/asm-arm/mm-init.h + * + * Copyright (C) 1997,1998 Russell King + * + * Contained within are structures to describe how to set up the + * initial memory map. It includes both a processor-specific header + * for parsing these structures, and an architecture-specific header + * to fill out the structures. + */ +#ifndef __ASM_MM_INIT_H +#define __ASM_MM_INIT_H + +typedef enum { + // physical address is absolute + init_mem_map_absolute, + /* physical address is relative to start_mem + * as passed in paging_init + */ + init_mem_map_relative_start_mem +} init_memmap_type_t; + +typedef struct { + init_memmap_type_t type; + unsigned long physical_address; + unsigned long virtual_address; + unsigned long size; +} init_memmap_t; + +#define INIT_MEM_MAP_SENTINEL { init_mem_map_absolute, 0, 0, 0 } +#define INIT_MEM_MAP_ABSOLUTE(p,l,s) { init_mem_map_absolute,p,l,s } +#define INIT_MEM_MAP_RELATIVE(o,l,s) { init_mem_map_relative_start_mem,o,l,s } + +/* + * Within this file, initialise an array of init_mem_map_t's + * to describe your initial memory mapping structure. + */ +#include + +/* + * Contained within this file is code to read the array + * of init_mem_map_t's created above. + */ +#include + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/mman.h linux/include/asm-arm/mman.h --- v2.1.79/linux/include/asm-arm/mman.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/mman.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,32 @@ +#ifndef __ARM_MMAN_H__ +#define __ARM_MMAN_H__ + +#define PROT_READ 0x1 /* page can be read */ +#define PROT_WRITE 0x2 /* page can be written */ +#define PROT_EXEC 0x4 /* page can be executed */ +#define PROT_NONE 0x0 /* page can not be accessed */ + +#define MAP_SHARED 0x01 /* Share changes */ +#define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_TYPE 0x0f /* Mask for type of mapping */ +#define MAP_FIXED 0x10 /* Interpret addr exactly */ +#define MAP_ANONYMOUS 0x20 /* don't use a file */ + +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ +#define MAP_LOCKED 0x2000 /* pages are locked */ +#define MAP_NORESERVE 0x4000 /* don't check for reservations */ + +#define MS_ASYNC 1 /* sync memory asynchronously */ +#define MS_INVALIDATE 2 /* invalidate the caches */ +#define MS_SYNC 4 /* synchronous memory sync */ + +#define MCL_CURRENT 1 /* lock all current mappings */ +#define MCL_FUTURE 2 /* lock all future mappings */ + +/* compatibility flags */ +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FILE 0 + +#endif /* __ARM_MMAN_H__ */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/mmu_context.h linux/include/asm-arm/mmu_context.h --- v2.1.79/linux/include/asm-arm/mmu_context.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/mmu_context.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,17 @@ +/* + * linux/include/asm-arm/mmu_context.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 27-06-1996 RMK Created + */ +#ifndef __ASM_ARM_MMU_CONTEXT_H +#define __ASM_ARM_MMU_CONTEXT_H + +#define get_mmu_context(x) do { } while (0) + +#define init_new_context(mm) do { } while(0) +#define destroy_context(mm) do { } while(0) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/namei.h linux/include/asm-arm/namei.h --- v2.1.79/linux/include/asm-arm/namei.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/namei.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,18 @@ +/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $ + * linux/include/asm-i386/namei.h + * + * Included from linux/fs/namei.c + */ + +#ifndef __ASMARM_NAMEI_H +#define __ASMARM_NAMEI_H + +/* This dummy routine maybe changed to something useful + * for /usr/gnemul/ emulation stuff. + * Look at asm-sparc/namei.h for details. + */ + +#define __prefix_namei(retrieve_mode, name, base, buf, res_dir, res_inode, \ + last_name, last_entry, last_error) 1 + +#endif /* __ASMARM_NAMEI_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/page.h linux/include/asm-arm/page.h --- v2.1.79/linux/include/asm-arm/page.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/page.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,20 @@ +#ifndef _ASMARM_PAGE_H +#define _ASMARM_PAGE_H + +#include +#include + +#ifdef __KERNEL__ + +#define clear_page(page) memzero((void *)(page), PAGE_SIZE) +#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) + +#endif + +/* unsigned long __pa(void *x) */ +#define __pa(x) __virt_to_phys((unsigned long)(x)) + +/* void *__va(unsigned long x) */ +#define __va(x) ((void *)(__phys_to_virt((unsigned long)(x)))) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/param.h linux/include/asm-arm/param.h --- v2.1.79/linux/include/asm-arm/param.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/param.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1 @@ +#include diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/pgtable.h linux/include/asm-arm/pgtable.h --- v2.1.79/linux/include/asm-arm/pgtable.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/pgtable.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,10 @@ +#ifndef _ASMARM_PGTABLE_H +#define _ASMARM_PGTABLE_H + +#include +#include + +#define module_map vmalloc +#define module_unmap vfree + +#endif /* _ASMARM_PGTABLE_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/poll.h linux/include/asm-arm/poll.h --- v2.1.79/linux/include/asm-arm/poll.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/poll.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,25 @@ +#ifndef __ASMARM_POLL_H +#define __ASMARM_POLL_H + +/* These are specified by iBCS2 */ +#define POLLIN 0x0001 +#define POLLPRI 0x0002 +#define POLLOUT 0x0004 +#define POLLERR 0x0008 +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 + +/* The rest seem to be more-or-less nonstandard. Check them! */ +#define POLLRDNORM 0x0040 +#define POLLRDBAND 0x0080 +#define POLLWRNORM 0x0100 +#define POLLWRBAND 0x0200 +#define POLLMSG 0x0400 + +struct pollfd { + int fd; + short events; + short revents; +}; + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/posix_types.h linux/include/asm-arm/posix_types.h --- v2.1.79/linux/include/asm-arm/posix_types.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/posix_types.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,60 @@ +/* + * linux/include/asm-arm/posix_types.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 27-06-1996 RMK Created + */ +#ifndef __ARCH_ARM_POSIX_TYPES_H +#define __ARCH_ARM_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#undef __FD_SET +#define __FD_SET(fd, fdsetp) \ + (((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31))) + +#undef __FD_CLR +#define __FD_CLR(fd, fdsetp) \ + (((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31))) + +#undef __FD_ISSET +#define __FD_ISSET(fd, fdsetp) \ + ((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0) + +#undef __FD_ZERO +#define __FD_ZERO(fdsetp) \ + (memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp))) + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/assembler.h linux/include/asm-arm/proc-armo/assembler.h --- v2.1.79/linux/include/asm-arm/proc-armo/assembler.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/assembler.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,88 @@ +/* + * linux/asm-arm/proc-armo/assembler.h + * + * Copyright (C) 1996 Russell King + * + * This file contains arm architecture specific defines + * for the different processors + */ + +/* + * LOADREGS: multiple register load (ldm) with pc in register list + * (takes account of ARM6 not using ^) + * + * RETINSTR: return instruction: adds the 's' in at the end of the + * instruction if this is not an ARM6 + * + * SAVEIRQS: save IRQ state (not required on ARM2/ARM3 - done + * implicitly + * + * RESTOREIRQS: restore IRQ state (not required on ARM2/ARM3 - done + * implicitly with ldm ... ^ or movs. + * + * These next two need thinking about - can't easily use stack... (see system.S) + * DISABLEIRQS: disable IRQS in SVC mode + * + * ENABLEIRQS: enable IRQS in SVC mode + * + * USERMODE: switch to USER mode + * + * SVCMODE: switch to SVC mode + */ + +#define N_BIT (1 << 31) +#define Z_BIT (1 << 30) +#define C_BIT (1 << 29) +#define V_BIT (1 << 28) + +#define PCMASK 0xfc000003 + +#ifdef __ASSEMBLER__ + +#define I_BIT (1 << 27) +#define F_BIT (1 << 26) + +#define MODE_USR 0 +#define MODE_FIQ 1 +#define MODE_IRQ 2 +#define MODE_SVC 3 + +#define DEFAULT_FIQ MODE_FIQ + +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist^ + +#define RETINSTR(instr, regs...)\ + instr##s regs + +#define MODENOP\ + mov r0, r0 + +#define MODE(savereg,tmpreg,mode) \ + mov savereg, pc; \ + bic tmpreg, savereg, $0x0c000003; \ + orr tmpreg, tmpreg, $mode; \ + teqp tmpreg, $0 + +#define RESTOREMODE(savereg) \ + teqp savereg, $0 + +#define SAVEIRQS(tmpreg) + +#define RESTOREIRQS(tmpreg) + +#define DISABLEIRQS(tmpreg)\ + teqp pc, $0x08000003 + +#define ENABLEIRQS(tmpreg)\ + teqp pc, $0x00000003 + +#define USERMODE(tmpreg)\ + teqp pc, $0x00000000;\ + mov r0, r0 + +#define SVCMODE(tmpreg)\ + teqp pc, $0x00000003;\ + mov r0, r0 + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/mm-init-flat.h linux/include/asm-arm/proc-armo/mm-init-flat.h --- v2.1.79/linux/include/asm-arm/proc-armo/mm-init-flat.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/mm-init-flat.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,82 @@ +/* + * linux/include/asm-arm/proc-armo/mmap.h + * + * Copyright (C) 1996 Russell King + * + * This contains the code to setup the memory map on an ARM2/ARM250/ARM3 + * machine. This is both processor & architecture specific, and requires + * some more work to get it to fit into our separate processor and + * architecture structure. + */ + +static unsigned long phys_screen_end; +int page_nr; + +#define setup_processor_functions() + +/* + * This routine needs more work to make it dynamically release/allocate mem! + */ +unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update) +{ + static int updated = 0; + unsigned long address = SCREEN_START, i; + pgd_t *pg_dir; + pmd_t *pm_dir; + pte_t *pt_entry; + + if (updated) + return 0; + updated = update; + + pg_dir = swapper_pg_dir + (SCREEN1_BASE >> PGDIR_SHIFT); + pm_dir = pmd_offset(pg_dir, SCREEN1_BASE); + pt_entry = pte_offset(pm_dir, SCREEN1_BASE); + + for (i = SCREEN1_BASE; i < SCREEN1_END; i += PAGE_SIZE) { + if (i >= log_start) { + *pt_entry = mk_pte(address, __pgprot(_PAGE_PRESENT)); + address += PAGE_SIZE; + } else + *pt_entry = mk_pte(0, __pgprot(0)); + pt_entry++; + } + phys_screen_end = address; + if (update) + flush_tlb_all (); + return kmem; +} + +static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem) +{ + unsigned long address; + unsigned int spi; + + page_nr = MAP_NR(end_mem); + + /* Allocate zero page */ + address = PAGE_OFFSET + 480*1024; + for (spi = 0; spi < 32768 >> PAGE_SHIFT; spi++) { + pgd_val(swapper_pg_dir[spi]) = pte_val(mk_pte(address, PAGE_READONLY)); + address += PAGE_SIZE; + } + + while (spi < (PAGE_OFFSET >> PGDIR_SHIFT)) + pgd_val(swapper_pg_dir[spi++]) = 0; + + map_screen_mem (SCREEN1_END - 480*1024, 0, 0); + return start_mem; +} + +static inline void mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem) +{ + unsigned long smem = PAGE_ALIGN(*start_mem); + + while (smem < end_mem) { + clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags); + smem += PAGE_SIZE; + } + + for (smem = phys_screen_end; smem < SCREEN2_END; smem += PAGE_SIZE) + clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/mm-init.h linux/include/asm-arm/proc-armo/mm-init.h --- v2.1.79/linux/include/asm-arm/proc-armo/mm-init.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/mm-init.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,130 @@ +/* + * linux/include/asm-arm/proc-armo/mm-init.h + * + * Copyright (C) 1996 Russell King + * + * This contains the code to setup the memory map on an ARM2/ARM250/ARM3 + * machine. This is both processor & architecture specific, and requires + * some more work to get it to fit into our separate processor and + * architecture structure. + */ + +static unsigned long phys_screen_end; +int page_nr; + +#define setup_processor_functions() +#define PTE_SIZE (PTRS_PER_PTE * BYTES_PER_PTR) + +static inline void setup_swapper_dir (int index, pte_t *ptep) +{ + set_pmd (pmd_offset (swapper_pg_dir + index, 0), mk_pmd (ptep)); +} + +/* + * This routine needs more work to make it dynamically release/allocate mem! + */ +unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update) +{ + static int updated = 0; + + if (updated) + return 0; + + updated = update; + + if (update) { + unsigned long address = log_start, offset; + pgd_t *pgdp; + + kmem = (kmem + 3) & ~3; + + pgdp = pgd_offset (&init_mm, address); /* +31 */ + offset = SCREEN_START; + while (address < SCREEN1_END) { + unsigned long addr_pmd, end_pmd; + pmd_t *pmdp; + + /* if (pgd_none (*pgdp)) alloc pmd */ + pmdp = pmd_offset (pgdp, address); /* +0 */ + addr_pmd = address & ~PGDIR_MASK; /* 088000 */ + end_pmd = addr_pmd + SCREEN1_END - address; /* 100000 */ + if (end_pmd > PGDIR_SIZE) + end_pmd = PGDIR_SIZE; + + do { + unsigned long addr_pte, end_pte; + pte_t *ptep; + + if (pmd_none (*pmdp)) { + pte_t *new_pte = (pte_t *)kmem; + kmem += PTRS_PER_PTE * BYTES_PER_PTR; + memzero (new_pte, PTRS_PER_PTE * BYTES_PER_PTR); + set_pmd (pmdp, mk_pmd(new_pte)); + } + + ptep = pte_offset (pmdp, addr_pmd); /* +11 */ + addr_pte = addr_pmd & ~PMD_MASK; /* 088000 */ + end_pte = addr_pte + end_pmd - addr_pmd; /* 100000 */ + if (end_pte > PMD_SIZE) + end_pte = PMD_SIZE; + + do { + set_pte (ptep, mk_pte(offset, PAGE_KERNEL)); + addr_pte += PAGE_SIZE; + offset += PAGE_SIZE; + ptep++; + } while (addr_pte < end_pte); + + pmdp++; + addr_pmd = (addr_pmd + PMD_SIZE) & PMD_MASK; + } while (addr_pmd < end_pmd); + + address = (address + PGDIR_SIZE) & PGDIR_MASK; + pgdp ++; + } + + phys_screen_end = offset; + flush_tlb_all (); + update_mm_cache_all (); + } + return kmem; +} + +static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem) +{ + unsigned int i; + union {unsigned long l; pte_t *pte; } u; + + page_nr = MAP_NR(end_mem); + + /* map in pages for (0x0000 - 0x8000) */ + u.l = ((start_mem + (PTE_SIZE-1)) & ~(PTE_SIZE-1)); + start_mem = u.l + PTE_SIZE; + memzero (u.pte, PTE_SIZE); + u.pte[0] = mk_pte(PAGE_OFFSET + 491520, PAGE_READONLY); + setup_swapper_dir (0, u.pte); + + for (i = 1; i < PTRS_PER_PGD; i++) + pgd_val(swapper_pg_dir[i]) = 0; + + /* now map screen mem in */ + phys_screen_end = SCREEN2_END; + map_screen_mem (SCREEN1_END - 480*1024, 0, 0); + + return start_mem; +} + +static inline void mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem) +{ + unsigned long smem; + + *start_mem = smem = PAGE_ALIGN(*start_mem); + + while (smem < end_mem) { + clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags); + smem += PAGE_SIZE; + } + + for (smem = phys_screen_end; smem < SCREEN2_END; smem += PAGE_SIZE) + clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/page.h linux/include/asm-arm/proc-armo/page.h --- v2.1.79/linux/include/asm-arm/proc-armo/page.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/page.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,69 @@ +/* + * linux/include/asm-arm/proc-armo/page.h + * + * Copyright (C) 1995, 1996 Russell King + */ + +#ifndef __ASM_PROC_PAGE_H +#define __ASM_PROC_PAGE_H + +/* PAGE_SHIFT determines the page size */ +#define PAGE_SHIFT 15 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#ifdef __KERNEL__ + +#define STRICT_MM_TYPECHECKS + +#ifdef STRICT_MM_TYPECHECKS +/* + * These are used to make use of C type-checking.. + */ +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long pmd; } pmd_t; +typedef struct { unsigned long pgd; } pgd_t; +typedef struct { unsigned long pgprot; } pgprot_t; + +#define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).pmd) +#define pgd_val(x) ((x).pgd) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pgd(x) ((pgd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +#else +/* + * .. while these make it easier on the compiler + */ +typedef unsigned long pte_t; +typedef unsigned long pmd_t; +typedef unsigned long pgd_t; +typedef unsigned long pgprot_t; + +#define pte_val(x) (x) +#define pmd_val(x) (x) +#define pgd_val(x) (x) +#define pgprot_val(x) (x) + +#define __pte(x) (x) +#define __pmd(x) (x) +#define __pgd(x) (x) +#define __pgprot(x) (x) + +#endif + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + +/* This handles the memory map.. */ +#define PAGE_OFFSET 0x02000000 +#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT) + +#endif /* __KERNEL__ */ + +#endif /* __ASM_PROC_PAGE_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/param.h linux/include/asm-arm/proc-armo/param.h --- v2.1.79/linux/include/asm-arm/proc-armo/param.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/param.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,27 @@ +/* + * linux/include/asm-arm/proc-armo/param.h + * + * Copyright (C) 1995, 1996 Russell King + */ + +#ifndef __ASM_PROC_PARAM_H +#define __ASM_PROC_PARAM_H + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 32768 + +#ifndef NGROUPS +#define NGROUPS 32 +#endif + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/pgtable-flat.h linux/include/asm-arm/proc-armo/pgtable-flat.h --- v2.1.79/linux/include/asm-arm/proc-armo/pgtable-flat.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/pgtable-flat.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,307 @@ +/* + * linux/include/asm-arm/proc-armo/pgtable.h + * + * Copyright (C) 1995, 1996 Russell King + */ +#ifndef __ASM_PROC_PGTABLE_H +#define __ASM_PROC_PGTABLE_H + +#include + +#define LIBRARY_TEXT_START 0x0c000000 + +/* + * Cache flushing... + */ +#define flush_cache_all() do { } while (0) +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_range(mm,start,end) do { } while (0) +#define flush_cache_page(vma,vmaddr) do { } while (0) +#define flush_page_to_ram(page) do { } while (0) + +/* + * TLB flushing: + * + * - flush_tlb() flushes the current mm struct TLBs + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(mm, start, end) flushes a range of pages + */ + +#define flush_tlb() flush_tlb_mm(current->mm) + +extern __inline__ void flush_tlb_all(void) +{ + struct task_struct *p; + + p = &init_task; + do { + processor.u.armv2._update_map(p); + p = p->next_task; + } while (p != &init_task); + + processor.u.armv2._remap_memc (current); +} + +extern __inline__ void flush_tlb_mm(struct mm_struct *mm) +{ + struct task_struct *p; + + p = &init_task; + do { + if (p->mm == mm) + processor.u.armv2._update_map(p); + p = p->next_task; + } while (p != &init_task); + + if (current->mm == mm) + processor.u.armv2._remap_memc (current); +} + +#define flush_tlb_range(mm, start, end) flush_tlb_mm(mm) +#define flush_tlb_page(vma, vmaddr) flush_tlb_mm(vma->vm_mm) + +#define __flush_entry_to_ram(entry) + +/* Certain architectures need to do special things when pte's + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define PMD_SHIFT PAGE_SHIFT +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT PAGE_SHIFT +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * entries per page directory level: the arm3 is one-level, so + * we don't really have any PMD or PTE directory physically. + */ +#define PTRS_PER_PTE 1 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 1024 + +/* Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ +#define VMALLOC_START 0x01a00000 +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) + +#define _PAGE_PRESENT 0x001 +#define _PAGE_RW 0x002 +#define _PAGE_USER 0x004 +#define _PAGE_PCD 0x010 +#define _PAGE_ACCESSED 0x020 +#define _PAGE_DIRTY 0x040 + +#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) + +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) + +/* + * The arm can't do page protection for execute, and considers that the same are read. + * Also, write permissions imply read permissions. This is the closest we can get.. + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY +#define __P101 PAGE_READONLY +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY +#define __S101 PAGE_READONLY +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED + +#undef TEST_VERIFY_AREA + +/* + * BAD_PAGE is used for a bogus page. + * + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern pte_t __bad_page(void); +extern unsigned long *empty_zero_page; + +#define BAD_PAGE __bad_page() +#define ZERO_PAGE ((unsigned long) empty_zero_page) + +/* number of bits that fit into a memory pointer */ +#define BYTES_PER_PTR (sizeof(unsigned long)) +#define BITS_PER_PTR (8*BYTES_PER_PTR) + +/* to align the pointer to a pointer address */ +#define PTR_MASK (~(sizeof(void*)-1)) + +/* sizeof(void*)==1<>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) + +/* to set the page-dir */ +#define SET_PAGE_DIR(tsk,pgdir) \ +do { \ + tsk->tss.memmap = (unsigned long)pgdir; \ + processor.u.armv2._update_map(tsk); \ + if ((tsk) == current) \ + processor.u.armv2._remap_memc (current); \ +} while (0) + +extern unsigned long physical_start; +extern unsigned long physical_end; + +extern inline int pte_none(pte_t pte) { return !pte_val(pte); } +extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; } +extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; } + +extern inline int pmd_none(pmd_t pmd) { return 0; } +extern inline int pmd_bad(pmd_t pmd) { return 0; } +extern inline int pmd_present(pmd_t pmd) { return 1; } +extern inline void pmd_clear(pmd_t * pmdp) { } + +/* + * The "pgd_xxx()" functions here are trivial for a folded two-level + * setup: the pgd is never bad, and a pmd always exists (as it's folded + * into the pgd entry) + */ +extern inline int pgd_none(pgd_t pgd) { return 0; } +extern inline int pgd_bad(pgd_t pgd) { return 0; } +extern inline int pgd_present(pgd_t pgd) { return 1; } +extern inline void pgd_clear(pgd_t * pgdp) { } + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } +extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; } +extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } +extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } +#define pte_cacheable(pte) 1 + +extern inline pte_t pte_nocache(pte_t pte) { return pte; } +extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; } +extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } +extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; } +extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } +extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } +extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; } +extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } +extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; } +extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } +extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot) +{ pte_t pte; pte_val(pte) = virt_to_phys(page) | pgprot_val(pgprot); return pte; } + +extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } + +extern inline unsigned long pte_page(pte_t pte) +{ return phys_to_virt(pte_val(pte) & PAGE_MASK); } + +extern inline unsigned long pmd_page(pmd_t pmd) +{ return phys_to_virt(pmd_val(pmd) & PAGE_MASK); } + +/* to find an entry in a page-table-directory */ +extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +{ + return mm->pgd + (address >> PGDIR_SHIFT); +} + +/* Find an entry in the second-level page table.. */ +#define pmd_offset(dir, address) ((pmd_t *)(dir)) + +/* Find an entry in the third-level page table.. */ +#define pte_offset(dir, address) ((pte_t *)(dir)) + +/* + * Allocate and free page tables. The xxx_kernel() versions are + * used to allocate a kernel page table - this turns on ASN bits + * if any. + */ +extern inline void pte_free_kernel(pte_t * pte) +{ + pte_val(*pte) = 0; +} + +extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address) +{ + return (pte_t *) pmd; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +#define pmd_free_kernel(pmdp) +#define pmd_alloc_kernel(pgd,address) ((pmd_t *)(pgd)) + +#define pte_free(ptep) +#define pte_alloc(pmd,address) ((pte_t *)(pmd)) + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +#define pmd_free(pmd) +#define pmd_alloc(pgd,address) ((pmd_t *)(pgd)) + +extern inline void pgd_free(pgd_t * pgd) +{ + extern void kfree(void *); + kfree((void *)pgd); +} + +extern inline pgd_t * pgd_alloc(void) +{ + pgd_t *pgd; + extern void *kmalloc(unsigned int, int); + + pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL); + if (pgd) + memset(pgd, 0, PTRS_PER_PGD * BYTES_PER_PTR); + return pgd; +} + +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + +#define update_mmu_cache(vma,address,pte) processor.u.armv2._update_mmu_cache(vma,address,pte) + +#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f) +#define SWP_OFFSET(entry) ((entry) >> 8) +#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) + +#endif /* __ASM_PROC_PAGE_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h --- v2.1.79/linux/include/asm-arm/proc-armo/pgtable.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/pgtable.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,403 @@ +/* + * linux/include/asm-arm/proc-armo/pgtable.h + * + * Copyright (C) 1995, 1996 Russell King + * Modified 18/19-Oct-1997 for two-level page table + */ +#ifndef __ASM_PROC_PGTABLE_H +#define __ASM_PROC_PGTABLE_H + +#include +#include + +#define LIBRARY_TEXT_START 0x0c000000 + +/* + * Cache flushing... + */ +#define flush_cache_all() do { } while (0) +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_range(mm,start,end) do { } while (0) +#define flush_cache_page(vma,vmaddr) do { } while (0) +#define flush_page_to_ram(page) do { } while (0) +#define flush_icache_range(start,end) do { } while (0) + +/* + * TLB flushing: + * + * - flush_tlb() flushes the current mm struct TLBs + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(mm, start, end) flushes a range of pages + */ +#define flush_tlb() do { } while (0) +#define flush_tlb_all() do { } while (0) +#define flush_tlb_mm(mm) do { } while (0) +#define flush_tlb_range(mm, start, end) do { } while (0) +#define flush_tlb_page(vma, vmaddr) do { } while (0) + +/* + * We have a mem map cache... + */ +extern __inline__ void update_mm_cache_all(void) +{ + struct task_struct *p; + + p = &init_task; + do { + processor.u.armv2._update_map(p); + p = p->next_task; + } while (p != &init_task); + + processor.u.armv2._remap_memc (current); +} + +extern __inline__ void update_mm_cache_task(struct task_struct *tsk) +{ + processor.u.armv2._update_map(tsk); + + if (tsk == current) + processor.u.armv2._remap_memc (tsk); +} + +extern __inline__ void update_mm_cache_mm(struct mm_struct *mm) +{ + struct task_struct *p; + + p = &init_task; + do { + if (p->mm == mm) + processor.u.armv2._update_map(p); + p = p->next_task; + } while (p != &init_task); + + if (current->mm == mm) + processor.u.armv2._remap_memc (current); +} + +extern __inline__ void update_mm_cache_mm_addr(struct mm_struct *mm, unsigned long addr, pte_t pte) +{ + struct task_struct *p; + + p = &init_task; + do { + if (p->mm == mm) + processor.u.armv2._update_mmu_cache(p, addr, pte); + p = p->next_task; + } while (p != &init_task); + + if (current->mm == mm) + processor.u.armv2._remap_memc (current); +} + +#define __flush_entry_to_ram(entry) + +/* Certain architectures need to do special things when pte's + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define PMD_SHIFT 20 +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT 20 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * entries per page directory level: the arm3 is one-level, so + * we don't really have any PMD or PTE directory physically. + * + * 18-Oct-1997 RMK Now two-level (32x32) + */ +#define PTRS_PER_PTE 32 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 32 + +/* Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ +#define VMALLOC_START 0x01a00000 +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) + +#define _PAGE_PRESENT 0x01 +#define _PAGE_READONLY 0x02 +#define _PAGE_NOT_USER 0x04 +#define _PAGE_OLD 0x08 +#define _PAGE_CLEAN 0x10 + +#define _PAGE_TABLE (_PAGE_PRESENT) +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_OLD | _PAGE_CLEAN) + +/* -- present -- -- !dirty -- --- !write --- ---- !user --- */ +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY | _PAGE_NOT_USER) +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_CLEAN ) +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY ) +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY ) +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_NOT_USER) + +/* + * The arm can't do page protection for execute, and considers that the same are read. + * Also, write permissions imply read permissions. This is the closest we can get.. + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY +#define __P101 PAGE_READONLY +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY +#define __S101 PAGE_READONLY +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED + +#undef TEST_VERIFY_AREA + +extern unsigned long *empty_zero_page; + +/* + * BAD_PAGETABLE is used when we need a bogus page-table, while + * BAD_PAGE is used for a bogus page. + * + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern pte_t __bad_page(void); +extern pte_t *__bad_pagetable(void); + +#define BAD_PAGETABLE __bad_pagetable() +#define BAD_PAGE __bad_page() +#define ZERO_PAGE ((unsigned long) empty_zero_page) + +/* number of bits that fit into a memory pointer */ +#define BYTES_PER_PTR (sizeof(unsigned long)) +#define BITS_PER_PTR (8*BYTES_PER_PTR) + +/* to align the pointer to a pointer address */ +#define PTR_MASK (~(sizeof(void*)-1)) + +/* sizeof(void*)==1<>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) + +/* to set the page-dir */ +#define SET_PAGE_DIR(tsk,pgdir) \ +do { \ + tsk->tss.memmap = (unsigned long)pgdir; \ + processor.u.armv2._update_map(tsk); \ + if ((tsk) == current) \ + processor.u.armv2._remap_memc (current); \ +} while (0) + +extern unsigned long physical_start; +extern unsigned long physical_end; + +#define pte_none(pte) (!pte_val(pte)) +#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) +#define pte_clear(ptep) set_pte((ptep), __pte(0)) + +#define pmd_none(pmd) (!pmd_val(pmd)) +#define pmd_bad(pmd) ((pmd_val(pmd) & 0xfc000002)) +#define pmd_present(pmd) (pmd_val(pmd) & _PAGE_PRESENT) +#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0)) + +/* + * The "pgd_xxx()" functions here are trivial for a folded two-level + * setup: the pgd is never bad, and a pmd always exists (as it's folded + * into the pgd entry) + */ +#define pgd_none(pgd) (0) +#define pgd_bad(pgd) (0) +#define pgd_present(pgd) (1) +#define pgd_clear(pgdp) + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +extern inline int pte_read(pte_t pte) { return !(pte_val(pte) & _PAGE_NOT_USER); } +extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_READONLY); } +extern inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_NOT_USER); } +extern inline int pte_dirty(pte_t pte) { return !(pte_val(pte) & _PAGE_CLEAN); } +extern inline int pte_young(pte_t pte) { return !(pte_val(pte) & _PAGE_OLD); } +#define pte_cacheable(pte) 1 + +extern inline pte_t pte_nocache(pte_t pte) { return pte; } +extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_READONLY; return pte; } +extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) |= _PAGE_NOT_USER; return pte; } +extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) |= _PAGE_NOT_USER; return pte; } +extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) |= _PAGE_CLEAN; return pte; } +extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) |= _PAGE_OLD; return pte; } + +extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_READONLY; return pte; } +extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) &= ~_PAGE_NOT_USER; return pte; } +extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= ~_PAGE_NOT_USER; return pte; } +extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) &= ~_PAGE_CLEAN; return pte; } +extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) &= ~_PAGE_OLD; return pte; } + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot) +{ + pte_t pte; + pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot); + return pte; +} + +/* This takes a physical page address that is used by the remapping functions */ +extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) +{ + pte_t pte; + pte_val(pte) = physpage + pgprot_val(pgprot); + return pte; +} + +extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); + return pte; +} + +#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) + +extern __inline__ unsigned long pte_page(pte_t pte) +{ + return __phys_to_virt(pte_val(pte) & PAGE_MASK); +} + +extern __inline__ pmd_t mk_pmd (pte_t *ptep) +{ + pmd_t pmd; + pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_TABLE; + return pmd; +} + +#define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd)) + +extern __inline__ unsigned long pmd_page(pmd_t pmd) +{ + return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE); +} + +/* to find an entry in a kernel page-table-directory */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) + +/* to find an entry in a page-table-directory */ +extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +{ + return mm->pgd + (address >> PGDIR_SHIFT); +} + +/* Find an entry in the second-level page table.. */ +#define pmd_offset(dir, address) ((pmd_t *)(dir)) + +/* Find an entry in the third-level page table.. */ +extern __inline__ pte_t * pte_offset(pmd_t *dir, unsigned long address) +{ + return (pte_t *)pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); +} + +/* + * Allocate and free page tables. The xxx_kernel() versions are + * used to allocate a kernel page table - this turns on ASN bits + * if any. + */ +#define pte_free_kernel(pte) pte_free((pte)) +#define pte_alloc_kernel(pmd,address) pte_alloc((pmd),(address)) + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +#define pmd_free_kernel(pmdp) +#define pmd_alloc_kernel(pgd,address) ((pmd_t *)(pgd)) + +extern __inline__ void pte_free(pte_t * pte) +{ + kfree (pte); +} + +extern const char bad_pmd_string[]; + +extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + + if (pmd_none (*pmd)) { + pte_t *page = (pte_t *) kmalloc (PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL); + if (pmd_none (*pmd)) { + if (page) { + memzero (page, PTRS_PER_PTE * BYTES_PER_PTR); + set_pmd(pmd, mk_pmd(page)); + return page + address; + } + set_pmd (pmd, mk_pmd (BAD_PAGETABLE)); + return NULL; + } + kfree (page); + } + if (pmd_bad (*pmd)) { + printk(bad_pmd_string, pmd_val(*pmd)); + set_pmd (pmd, mk_pmd (BAD_PAGETABLE)); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +#define pmd_free(pmd) +#define pmd_alloc(pgd,address) ((pmd_t *)(pgd)) + +/* + * Free a page directory. Takes the virtual address. + */ +extern __inline__ void pgd_free(pgd_t * pgd) +{ + kfree ((void *)pgd); +} + +/* + * Allocate a new page directory. Return the virtual address of it. + */ +extern __inline__ pgd_t * pgd_alloc(void) +{ + pgd_t *pgd; + + pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL); + if (pgd) + memzero (pgd, PTRS_PER_PGD * BYTES_PER_PTR); + return pgd; +} + +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + +#define update_mmu_cache(vma,address,pte) + +#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f) +#define SWP_OFFSET(entry) ((entry) >> 8) +#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) + +#endif /* __ASM_PROC_PAGE_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/processor.h linux/include/asm-arm/proc-armo/processor.h --- v2.1.79/linux/include/asm-arm/proc-armo/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/processor.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,118 @@ +/* + * linux/include/asm-arm/proc-armo/processor.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 27-06-1996 RMK Created + * 10-10-1996 RMK Brought up to date with SA110 + * 26-09-1996 RMK Added 'EXTRA_THREAD_STRUCT*' + * 28-09-1996 RMK Moved start_thread into the processor dependencies + * 11-01-1998 RMK Added new uaccess_t + */ +#ifndef __ASM_PROC_PROCESSOR_H +#define __ASM_PROC_PROCESSOR_H + +#ifdef __KERNEL__ + +#include +#include + +#define KERNEL_STACK_SIZE 4096 + +/* + * on arm2,3 wp does not work + */ +#define wp_works_ok 0 +#define wp_works_ok__is_a_macro /* for versions in ksyms.c */ + +struct context_save_struct { + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long fp; + unsigned long pc; +}; + +typedef struct { + void (*put_byte)(void); /* Special calling convention */ + void (*get_byte)(void); /* Special calling convention */ + void (*put_half)(void); /* Special calling convention */ + void (*get_half)(void); /* Special calling convention */ + void (*put_word)(void); /* Special calling convention */ + void (*get_word)(void); /* Special calling convention */ + unsigned long (*copy_from_user)(void *to, const void *from, unsigned long sz); + unsigned long (*copy_to_user)(void *to, const void *from, unsigned long sz); + unsigned long (*clear_user)(void *addr, unsigned long sz); + unsigned long (*strncpy_from_user)(char *to, const char *from, unsigned long sz); + unsigned long (*strlen_user)(const char *s); +} uaccess_t; + +extern uaccess_t uaccess_user, uaccess_kernel; + +#define EXTRA_THREAD_STRUCT \ + uaccess_t *uaccess; /* User access functions*/ \ + struct context_save_struct *save; \ + unsigned long memmap; \ + unsigned long memcmap[256]; + +#define EXTRA_THREAD_STRUCT_INIT \ + &uaccess_kernel, \ + 0, \ + (unsigned long) swapper_pg_dir, \ + { 0, } + +DECLARE_THREAD_STRUCT; + +/* + * Return saved PC of a blocked thread. + */ +extern __inline__ unsigned long thread_saved_pc (struct thread_struct *t) +{ + if (t->save) + return t->save->pc & ~PCMASK; + else + return 0; +} + +extern __inline__ unsigned long get_css_fp (struct thread_struct *t) +{ + if (t->save) + return t->save->fp; + else + return 0; +} + +asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call"); + +extern __inline__ void copy_thread_css (struct context_save_struct *save) +{ + save->r4 = + save->r5 = + save->r6 = + save->r7 = + save->r8 = + save->r9 = + save->fp = 0; + save->pc = ((unsigned long)ret_from_sys_call) | SVC26_MODE; +} + +#define start_thread(regs,pc,sp) \ +({ \ + unsigned long *stack = (unsigned long *)sp; \ + set_fs(USER_DS); \ + memzero(regs->uregs, sizeof (regs->uregs)); \ + regs->ARM_pc = pc; /* pc */ \ + regs->ARM_sp = sp; /* sp */ \ + regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ + regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ + regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ + flush_tlb_mm(current->mm); \ +}) + +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/ptrace.h linux/include/asm-arm/proc-armo/ptrace.h --- v2.1.79/linux/include/asm-arm/proc-armo/ptrace.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/ptrace.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,65 @@ +/* + * linux/include/asm-arm/proc-armo/ptrace.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PTRACE_H +#define __ASM_PROC_PTRACE_H + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct pt_regs { + long uregs[17]; +}; + +#define ARM_pc uregs[15] +#define ARM_lr uregs[14] +#define ARM_sp uregs[13] +#define ARM_ip uregs[12] +#define ARM_fp uregs[11] +#define ARM_r10 uregs[10] +#define ARM_r9 uregs[9] +#define ARM_r8 uregs[8] +#define ARM_r7 uregs[7] +#define ARM_r6 uregs[6] +#define ARM_r5 uregs[5] +#define ARM_r4 uregs[4] +#define ARM_r3 uregs[3] +#define ARM_r2 uregs[2] +#define ARM_r1 uregs[1] +#define ARM_r0 uregs[0] +#define ARM_ORIG_r0 uregs[16] /* -1 */ + +#define USR26_MODE 0x00 +#define FIQ26_MODE 0x01 +#define IRQ26_MODE 0x02 +#define SVC26_MODE 0x03 +#define MODE_MASK 0x03 +#define F_BIT (1 << 26) +#define I_BIT (1 << 27) +#define CC_V_BIT (1 << 28) +#define CC_C_BIT (1 << 29) +#define CC_Z_BIT (1 << 30) +#define CC_N_BIT (1 << 31) + +#define user_mode(regs) \ + (((regs)->ARM_pc & MODE_MASK) == USR26_MODE) + +#define processor_mode(regs) \ + ((regs)->ARM_pc & MODE_MASK) + +#define interrupts_enabled(regs) \ + (!((regs)->ARM_pc & I_BIT)) + +#define fast_interrupts_enabled(regs) \ + (!((regs)->ARM_pc & F_BIT)) + +#define condition_codes(regs) \ + ((regs)->ARM_pc & (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT)) + +#define instruction_pointer(regs) ((regs)->ARM_pc & 0x03fffffc) +#define pc_pointer(v) ((v) & 0x03fffffc) +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/semaphore.h linux/include/asm-arm/proc-armo/semaphore.h --- v2.1.79/linux/include/asm-arm/proc-armo/semaphore.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/semaphore.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,83 @@ +/* + * linux/include/asm-arm/proc-armo/semaphore.h + */ +#ifndef __ASM_PROC_SEMAPHORE_H +#define __ASM_PROC_SEMAPHORE_H + +/* + * This is ugly, but we want the default case to fall through. + * "__down" is the actual routine that waits... + */ +extern inline void down(struct semaphore * sem) +{ + __asm__ __volatile__ (" + @ atomic down operation + mov r0, pc + orr r1, r0, #0x08000000 + and r0, r0, #0x0c000003 + teqp r1, #0 + ldr r1, [%0] + subs r1, r1, #1 + str r1, [%0] + mov r1, pc, lsr #28 + teqp r0, r1, lsl #28 + movmi r0, %0 + blmi " SYMBOL_NAME_STR(__down) + : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc"); +} + +/* + * This is ugly, but we want the default case to fall through. + * "__down_interruptible" is the actual routine that waits... + */ +extern inline int down_interruptible (struct semaphore * sem) +{ + int result; + __asm__ __volatile__ (" + @ atomic down operation + mov r0, pc + orr r1, r0, #0x08000000 + and r0, r0, #0x0c000003 + teqp r1, #0 + ldr r1, [%1] + subs r1, r1, #1 + str r1, [%1] + mov r1, pc, lsr #28 + orrmi r0, r0, #0x80000000 @ set N + teqp r0, r1, lsl #28 + movmi r0, %1 + movpl r0, #0 + blmi " SYMBOL_NAME_STR(__down_interruptible) " + mov %0, r0" + : "=r" (result) + : "r" (sem) + : "r0", "r1", "r2", "r3", "ip", "lr", "cc"); + return result; +} + +/* + * Note! This is subtle. We jump to wake people up only if + * the semaphore was negative (== somebody was waiting on it). + * The default case (no contention) will result in NO + * jumps for both down() and up(). + */ +extern inline void up(struct semaphore * sem) +{ + __asm__ __volatile__ (" + @ atomic up operation + mov r0, pc + orr r1, r0, #0x08000000 + and r0, r0, #0x0c000003 + teqp r1, #0 + ldr r1, [%0] + adds r1, r1, #1 + str r1, [%0] + mov r1, pc, lsr #28 + orrls r0, r0, #0x80000000 @ set N + teqp r0, r1, lsl #28 + movmi r0, %0 + blmi " SYMBOL_NAME_STR(__up) + : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc"); +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/shmparam.h linux/include/asm-arm/proc-armo/shmparam.h --- v2.1.79/linux/include/asm-arm/proc-armo/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/shmparam.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,18 @@ +/* + * linux/include/asm-arm/proc-armo/shmparam.h + * + * Copyright (C) 1996 Russell King + * + * definitions for the shared process memory on the ARM3 + */ + +#ifndef __ASM_PROC_SHMPARAM_H +#define __ASM_PROC_SHMPARAM_H + +#ifndef SHM_RANGE_START +#define SHM_RANGE_START 0x00a00000 +#define SHM_RANGE_END 0x00c00000 +#define SHMMAX 0x003fa000 +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/system.h linux/include/asm-arm/proc-armo/system.h --- v2.1.79/linux/include/asm-arm/proc-armo/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/system.h Tue Jan 20 16:39:42 1998 @@ -0,0 +1,124 @@ +/* + * linux/include/asm-arm/proc-armo/system.h + * + * Copyright (C) 1995, 1996 Russell King + */ + +#ifndef __ASM_PROC_SYSTEM_H +#define __ASM_PROC_SYSTEM_H + +extern const char xchg_str[]; + +#include + +extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size) +{ + switch (size) { + case 1: return processor.u.armv2._xchg_1(x, ptr); + case 2: return processor.u.armv2._xchg_2(x, ptr); + case 4: return processor.u.armv2._xchg_4(x, ptr); + default: arm_invalidptr(xchg_str, size); + } +} + +/* + * We need to turn the caches off before calling the reset vector - RiscOS + * messes up if we don't + */ +#define proc_hard_reset() processor._proc_fin() + +/* + * This processor does not idle + */ +#define proc_idle() + +/* + * A couple of speedups for the ARM + */ + +/* + * Save the current interrupt enable state & disable IRQs + */ +#define __save_flags_cli(x) \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" orr %1, %0, #0x08000000\n" \ +" and %0, %0, #0x0c000000\n" \ +" teqp %1, #0\n" \ + : "=r" (x), "=r" (temp) \ + : \ + : "memory"); \ + } while (0) + +/* + * Enable IRQs + */ +#define __sti() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" bic %0, %0, #0x08000000\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : \ + : "memory"); \ + } while(0) + +/* + * Disable IRQs + */ +#define __cli() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" orr %0, %0, #0x08000000\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : \ + : "memory"); \ + } while(0) + +/* + * save current IRQ & FIQ state + */ +#define __save_flags(x) \ + do { \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" and %0, %0, #0x0c000000\n" \ + : "=r" (x)); \ + } while (0) + +/* + * restore saved IRQ & FIQ state + */ +#define __restore_flags(x) \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ +" mov %0, pc\n" \ +" bic %0, %0, #0x0c000000\n" \ +" orr %0, %0, %1\n" \ +" teqp %0, #0\n" \ + : "=r" (temp) \ + : "r" (x) \ + : "memory"); \ + } while (0) + +#ifdef __SMP__ +#error SMP not supported +#else + +#define cli() __cli() +#define sti() __sti() +#define save_flags(x) __save_flags(x) +#define restore_flags(x) __restore_flags(x) +#define save_flags_cli(x) __save_flags_cli(x) + +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/uaccess.h linux/include/asm-arm/proc-armo/uaccess.h --- v2.1.79/linux/include/asm-arm/proc-armo/uaccess.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/uaccess.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,140 @@ +/* + * linux/include/asm-arm/proc-armo/segment.h + * + * Copyright (C) 1996 Russell King + */ + +/* + * The fs functions are implemented on the ARM2 and ARM3 architectures + * manually. + * Use *_user functions to access user memory with faulting behaving + * as though the user is accessing the memory. + * Use set_fs(get_ds()) and then the *_user functions to allow them to + * access kernel memory. + */ + +/* + * These are the values used to represent the user `fs' and the kernel `ds' + */ +#define KERNEL_DS 0x03000000 +#define USER_DS 0x02000000 + +#define get_ds() (KERNEL_DS) +#define get_fs() (current->addr_limit) +#define segment_eq(a,b) ((a) == (b)) + +extern uaccess_t uaccess_user, uaccess_kernel; + +extern __inline__ void set_fs (mm_segment_t fs) +{ + current->addr_limit = fs; + current->tss.uaccess = fs == USER_DS ? &uaccess_user : &uaccess_kernel; +} + +#define __range_ok(addr,size) ({ \ + unsigned long flag, sum; \ + __asm__ __volatile__("adds %1, %2, %3; cmpls %1, %0; movls %0, #0" \ + : "=&r" (flag), "=&r" (sum) \ + : "r" (addr), "Ir" (size), "0" (current->addr_limit) \ + : "cc"); \ + flag; }) + +#define __addr_ok(addr) ({ \ + unsigned long flag; \ + __asm__ __volatile__("cmp %2, %0; movlo %0, #0" \ + : "=&r" (flag) \ + : "0" (current->addr_limit), "r" (addr) \ + : "cc"); \ + (flag == 0); }) + +#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) + +#define __put_user_asm_byte(x,addr,err) \ + __asm__ __volatile__( \ + " mov r0, %1\n" \ + " mov r1, %2\n" \ + " mov r2, %0\n" \ + " mov lr, pc\n" \ + " mov pc, %3\n" \ + " mov %0, r2\n" \ + : "=r" (err) \ + : "r" (x), "r" (addr), "r" (current->tss.uaccess->put_byte), \ + "0" (err) \ + : "r0", "r1", "r2", "lr") + +#define __put_user_asm_half(x,addr,err) \ + __asm__ __volatile__( \ + " mov r0, %1\n" \ + " mov r1, %2\n" \ + " mov r2, %0\n" \ + " mov lr, pc\n" \ + " mov pc, %3\n" \ + " mov %0, r2\n" \ + : "=r" (err) \ + : "r" (x), "r" (addr), "r" (current->tss.uaccess->put_half), \ + "0" (err) \ + : "r0", "r1", "r2", "lr") + +#define __put_user_asm_word(x,addr,err) \ + __asm__ __volatile__( \ + " mov r0, %1\n" \ + " mov r1, %2\n" \ + " mov r2, %0\n" \ + " mov lr, pc\n" \ + " mov pc, %3\n" \ + " mov %0, r2\n" \ + : "=r" (err) \ + : "r" (x), "r" (addr), "r" (current->tss.uaccess->put_word), \ + "0" (err) \ + : "r0", "r1", "r2", "lr") + +#define __get_user_asm_byte(x,addr,err) \ + __asm__ __volatile__( \ + " mov r0, %2\n" \ + " mov r1, %0\n" \ + " mov lr, pc\n" \ + " mov pc, %3\n" \ + " mov %0, r1\n" \ + " mov %1, r0\n" \ + : "=r" (err), "=r" (x) \ + : "r" (addr), "r" (current->tss.uaccess->get_byte), "0" (err) \ + : "r0", "r1", "r2", "lr") + +#define __get_user_asm_half(x,addr,err) \ + __asm__ __volatile__( \ + " mov r0, %2\n" \ + " mov r1, %0\n" \ + " mov lr, pc\n" \ + " mov pc, %3\n" \ + " mov %0, r1\n" \ + " mov %1, r0\n" \ + : "=r" (err), "=r" (x) \ + : "r" (addr), "r" (current->tss.uaccess->get_half), "0" (err) \ + : "r0", "r1", "r2", "lr") + +#define __get_user_asm_word(x,addr,err) \ + __asm__ __volatile__( \ + " mov r0, %2\n" \ + " mov r1, %0\n" \ + " mov lr, pc\n" \ + " mov pc, %3\n" \ + " mov %0, r1\n" \ + " mov %1, r0\n" \ + : "=r" (err), "=r" (x) \ + : "r" (addr), "r" (current->tss.uaccess->get_word), "0" (err) \ + : "r0", "r1", "r2", "lr") + +#define __do_copy_from_user(to,from,n) \ + (n) = current->tss.uaccess->copy_from_user((to),(from),(n)) + +#define __do_copy_to_user(to,from,n) \ + (n) = current->tss.uaccess->copy_to_user((to),(from),(n)) + +#define __do_clear_user(addr,sz) \ + (sz) = current->tss.uaccess->clear_user((addr),(sz)) + +#define __do_strncpy_from_user(dst,src,count,res) \ + (res) = current->tss.uaccess->strncpy_from_user(dst,src,count) + +#define __do_strlen_user(s,res) \ + (res) = current->tss.uaccess->strlen_user(s) diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armo/uncompress.h linux/include/asm-arm/proc-armo/uncompress.h --- v2.1.79/linux/include/asm-arm/proc-armo/uncompress.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armo/uncompress.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,7 @@ +/* + * linux/include/asm-arm/proc-armo/uncompress.h + * + * (c) 1997 Russell King + */ + +#define proc_decomp_setup() diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/assembler.h linux/include/asm-arm/proc-armv/assembler.h --- v2.1.79/linux/include/asm-arm/proc-armv/assembler.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/assembler.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,84 @@ +/* + * linux/asm-arm/proc-armv/assembler.h + * + * Copyright (C) 1996 Russell King + * + * This file contains arm architecture specific defines + * for the different processors + */ + +/* + * LOADREGS: multiple register load (ldm) with pc in register list + * (takes account of ARM6 not using ^) + * + * RETINSTR: return instruction: adds the 's' in at the end of the + * instruction if this is not an ARM6 + * + * SAVEIRQS: save IRQ state (not required on ARM2/ARM3 - done + * implicitly + * + * RESTOREIRQS: restore IRQ state (not required on ARM2/ARM3 - done + * implicitly with ldm ... ^ or movs. + * + * These next two need thinking about - can't easily use stack... (see system.S) + * DISABLEIRQS: disable IRQS in SVC mode + * + * ENABLEIRQS: enable IRQS in SVC mode + * + * USERMODE: switch to USER mode + * + * SVCMODE: switch to SVC mode + */ + +#define N_BIT (1 << 31) +#define Z_BIT (1 << 30) +#define C_BIT (1 << 29) +#define V_BIT (1 << 28) + +#define PCMASK 0 + +#ifdef __ASSEMBLER__ + +#define I_BIT (1 << 7) +#define F_BIT (1 << 6) + +#define MODE_FIQ26 0x01 +#define MODE_FIQ32 0x11 + +#define DEFAULT_FIQ MODE_FIQ32 + +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist + +#define RETINSTR(instr, regs...)\ + instr regs + +#define MODENOP + +#define MODE(savereg,tmpreg,mode) \ + mrs savereg, cpsr; \ + bic tmpreg, savereg, $0x1f; \ + orr tmpreg, tmpreg, $mode; \ + msr cpsr, tmpreg + +#define RESTOREMODE(savereg) \ + msr cpsr, savereg + +#define SAVEIRQS(tmpreg)\ + mrs tmpreg, cpsr; \ + str tmpreg, [sp, $-4]! + +#define RESTOREIRQS(tmpreg)\ + ldr tmpreg, [sp], $4; \ + msr cpsr, tmpreg + +#define DISABLEIRQS(tmpreg)\ + mrs tmpreg , cpsr; \ + orr tmpreg , tmpreg , $I_BIT; \ + msr cpsr, tmpreg + +#define ENABLEIRQS(tmpreg)\ + mrs tmpreg , cpsr; \ + bic tmpreg , tmpreg , $I_BIT; \ + msr cpsr, tmpreg +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/mm-init.h linux/include/asm-arm/proc-armv/mm-init.h --- v2.1.79/linux/include/asm-arm/proc-armv/mm-init.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/mm-init.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,118 @@ +/* + * linux/include/asm-arm/proc-armv/mm-init.h + * + * Copyright (C) 1996 Russell King + * + * This contains the code to setup the memory map on an ARM v3 or v4 machine. + * This is both processor & architecture specific, and requires some + * more work to get it to fit into our separate processor and architecture + * structure. + */ + +/* + * On ebsa, we want the memory map set up so: + * + * PHYS VIRT + * 00000000 00000000 Zero page + * 000003ff 000003ff Zero page end + * 00000000 c0000000 Kernel and all physical memory + * 01ffffff c1ffffff End of physical (32MB) + * e0000000 e0000000 IO start + * ffffffff ffffffff IO end + * + * On rpc, we want: + * + * PHYS VIRT + * 10000000 00000000 Zero page + * 100003ff 000003ff Zero page end + * 10000000 c0000000 Kernel and all physical memory + * 1fffffff cfffffff End of physical (32MB) + * 02000000 d?000000 Screen memory (first image) + * 02000000 d8000000 Screen memory (second image) + * 00000000 df000000 StrongARM cache invalidation area + * 03000000 e0000000 IO start + * 03ffffff e0ffffff IO end + * + * We set it up using the section page table entries. + */ + +#include +#include + +#define V2P(x) virt_to_phys(x) +#define PTE_SIZE (PTRS_PER_PTE * 4) + +#define PMD_SECT (PMD_TYPE_SECT | PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_CACHEABLE) + +static inline void setup_swapper_dir (int index, unsigned long entry) +{ + pmd_t pmd; + + pmd_val(pmd) = entry; + set_pmd (pmd_offset (swapper_pg_dir + index, 0), pmd); +} + +static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem) +{ + unsigned long address; + unsigned int spi; + union { unsigned long l; unsigned long *p; } u; + + /* map in zero page */ + u.l = ((start_mem + (PTE_SIZE-1)) & ~(PTE_SIZE-1)); + start_mem = u.l + PTE_SIZE; + memzero (u.p, PTE_SIZE); + *u.p = V2P(PAGE_OFFSET) | PTE_CACHEABLE | PTE_TYPE_SMALL; + setup_swapper_dir (0, V2P(u.l) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER)); + + for (spi = 1; spi < (PAGE_OFFSET >> PGDIR_SHIFT); spi++) + pgd_val(swapper_pg_dir[spi]) = 0; + + /* map in physical ram & kernel */ + address = PAGE_OFFSET; + while (spi < end_mem >> PGDIR_SHIFT) { + setup_swapper_dir (spi++, + V2P(address) | PMD_SECT | + PMD_SECT_BUFFERABLE | PMD_SECT_AP_WRITE); + address += PGDIR_SIZE; + } + while (spi < PTRS_PER_PGD) + pgd_val(swapper_pg_dir[spi++]) = 0; + + /* + * An area to invalidate the cache + */ + setup_swapper_dir (0xdf0, SAFE_ADDR | PMD_SECT | PMD_SECT_AP_READ); + + /* map in IO */ + address = IO_START; + spi = IO_BASE >> PGDIR_SHIFT; + pgd_val(swapper_pg_dir[spi-1]) = 0xc0000000 | PMD_TYPE_SECT | + PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE; + while (address < IO_START + IO_SIZE && address) { + pgd_val(swapper_pg_dir[spi++]) = address | + PMD_TYPE_SECT | PMD_DOMAIN(DOMAIN_IO) | + PMD_SECT_AP_WRITE; + address += PGDIR_SIZE; + } + +#ifdef HAVE_MAP_VID_MEM + map_screen_mem(0, 0, 0); +#endif + + flush_cache_all(); + return start_mem; +} + +static inline void mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem) +{ + unsigned long smem; + + *start_mem = smem = PAGE_ALIGN(*start_mem); + + while (smem < end_mem) { + clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags); + smem += PAGE_SIZE; + } +} + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/page.h linux/include/asm-arm/proc-armv/page.h --- v2.1.79/linux/include/asm-arm/proc-armv/page.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/page.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,68 @@ +/* + * linux/include/asm-arm/proc-armv/page.h + * + * Copyright (C) 1995, 1996 Russell King + */ + +#ifndef __ASM_PROC_PAGE_H +#define __ASM_PROC_PAGE_H + +/* PAGE_SHIFT determines the page size */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#ifdef __KERNEL__ + +#define STRICT_MM_TYPECHECKS + +#ifdef STRICT_MM_TYPECHECKS +/* + * These are used to make use of C type-checking.. + */ +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long pmd; } pmd_t; +typedef struct { unsigned long pgd; } pgd_t; +typedef struct { unsigned long pgprot; } pgprot_t; + +#define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).pmd) +#define pgd_val(x) ((x).pgd) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pgd(x) ((pgd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +#else +/* + * .. while these make it easier on the compiler + */ +typedef unsigned long pte_t; +typedef unsigned long pmd_t; +typedef unsigned long pgd_t; +typedef unsigned long pgprot_t; + +#define pte_val(x) (x) +#define pmd_val(x) (x) +#define pgd_val(x) (x) +#define pgprot_val(x) (x) + +#define __pte(x) (x) +#define __pmd(x) (x) +#define __pgd(x) (x) +#define __pgprot(x) (x) + +#endif + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + +/* This handles the memory map.. */ +#define PAGE_OFFSET 0xc0000000 +#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT) + +#endif /* __KERNEL__ */ + +#endif /* __ASM_PROC_PAGE_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/param.h linux/include/asm-arm/proc-armv/param.h --- v2.1.79/linux/include/asm-arm/proc-armv/param.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/param.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,27 @@ +/* + * linux/include/asm-arm/proc-armv/param.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PARAM_H +#define __ASM_PROC_PARAM_H + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 4096 + +#ifndef NGROUPS +#define NGROUPS 32 +#endif + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/pgtable.h linux/include/asm-arm/proc-armv/pgtable.h --- v2.1.79/linux/include/asm-arm/proc-armv/pgtable.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/pgtable.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,617 @@ +/* + * linux/include/asm-arm/proc-armv/pgtable.h + * + * Copyright (C) 1995, 1996, 1997 Russell King + * + * 12-01-1997 RMK Altered flushing routines to use function pointers + * now possible to combine ARM6, ARM7 and StrongARM versions. + */ +#ifndef __ASM_PROC_PGTABLE_H +#define __ASM_PROC_PGTABLE_H + +#include + +#define LIBRARY_TEXT_START 0x0c000000 + +/* + * Cache flushing... + */ +#define flush_cache_all() \ + processor.u.armv3v4._flush_cache_all() + +#define flush_cache_mm(_mm) \ + do { \ + if ((_mm) == current->mm) \ + processor.u.armv3v4._flush_cache_all(); \ + } while (0) + +#define flush_cache_range(_mm,_start,_end) \ + do { \ + if ((_mm) == current->mm) \ + processor.u.armv3v4._flush_cache_area \ + ((_start), (_end), 1); \ + } while (0) + +#define flush_cache_page(_vma,_vmaddr) \ + do { \ + if ((_vma)->vm_mm == current->mm) \ + processor.u.armv3v4._flush_cache_area \ + ((_vmaddr), (_vmaddr) + PAGE_SIZE, \ + ((_vma)->vm_flags & VM_EXEC) ? 1 : 0); \ + } while (0) + +#define flush_icache_range(_start,_end) \ + processor.u.armv3v4._flush_icache_area((_start), (_end)) + +/* + * We don't have a mem map cache... + */ +#define update_mm_cache_all() do { } while (0) +#define update_mm_cache_task(tsk) do { } while (0) +#define update_mm_cache_mm(mm) do { } while (0) +#define update_mm_cache_mm_addr(mm,addr,pte) do { } while (0) + +/* + * This flushes back any buffered write data. We have to clean and flush the entries + * in the cache for this page. Is it necessary to invalidate the I-cache? + */ +#define flush_page_to_ram(_page) \ + processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK); + +/* + * Make the page uncacheable (must flush page beforehand). + */ +#define uncache_page(_page) \ + processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK); + +/* + * TLB flushing: + * + * - flush_tlb() flushes the current mm struct TLBs + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(mm, start, end) flushes a range of pages + * + * GCC uses conditional instructions, and expects the assembler code to do so as well. + * + * We drain the write buffer in here to ensure that the page tables in ram + * are really up to date. It is more efficient to do this here... + */ +#define flush_tlb() flush_tlb_all() + +#define flush_tlb_all() \ + processor.u.armv3v4._flush_tlb_all() + +#define flush_tlb_mm(_mm) \ + do { \ + if ((_mm) == current->mm) \ + processor.u.armv3v4._flush_tlb_all(); \ + } while (0) + +#define flush_tlb_range(_mm,_start,_end) \ + do { \ + if ((_mm) == current->mm) \ + processor.u.armv3v4._flush_tlb_area \ + ((_start), (_end), 1); \ + } while (0) + +#define flush_tlb_page(_vma,_vmaddr) \ + do { \ + if ((_vma)->vm_mm == current->mm) \ + processor.u.armv3v4._flush_tlb_area \ + ((_vmaddr), (_vmaddr) + PAGE_SIZE, \ + ((_vma)->vm_flags & VM_EXEC) ? 1 : 0); \ + } while (0) + +/* + * Since the page tables are in cached memory, we need to flush the dirty + * data cached entries back before we flush the tlb... This is also useful + * to flush out the SWI instruction for signal handlers... + */ +#define __flush_entry_to_ram(entry) \ + processor.u.armv3v4._flush_cache_entry((unsigned long)(entry)) + +#define __flush_pte_to_ram(entry) \ + processor.u.armv3v4._flush_cache_pte((unsigned long)(entry)) + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define PMD_SHIFT 20 +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT 20 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * entries per page directory level: the sa110 is two-level, so + * we don't really have any PMD directory physically. + */ +#define PTRS_PER_PTE 256 +#define PTRS_PER_PMD 1 +#define PTRS_PER_PGD 4096 + +/* Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ +#define VMALLOC_OFFSET (8*1024*1024) +#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) +#define VMALLOC_VMADDR(x) ((unsigned long)(x)) + +/* PMD types (actually level 1 descriptor) */ +#define PMD_TYPE_MASK 0x0003 +#define PMD_TYPE_FAULT 0x0000 +#define PMD_TYPE_TABLE 0x0001 +#define PMD_TYPE_SECT 0x0002 +#define PMD_UPDATABLE 0x0010 +#define PMD_SECT_CACHEABLE 0x0008 +#define PMD_SECT_BUFFERABLE 0x0004 +#define PMD_SECT_AP_WRITE 0x0400 +#define PMD_SECT_AP_READ 0x0800 +#define PMD_DOMAIN(x) ((x) << 5) + +/* PTE types (actially level 2 descriptor) */ +#define PTE_TYPE_MASK 0x0003 +#define PTE_TYPE_FAULT 0x0000 +#define PTE_TYPE_LARGE 0x0001 +#define PTE_TYPE_SMALL 0x0002 +#define PTE_AP_READ 0x0aa0 +#define PTE_AP_WRITE 0x0550 +#define PTE_CACHEABLE 0x0008 +#define PTE_BUFFERABLE 0x0004 + +/* Domains */ +#define DOMAIN_USER 0 +#define DOMAIN_KERNEL 1 +#define DOMAIN_TABLE 1 +#define DOMAIN_IO 2 + +#define _PAGE_CHG_MASK (0xfffff00c | PTE_TYPE_MASK) + +/* + * We define the bits in the page tables as follows: + * PTE_BUFFERABLE page is dirty + * PTE_AP_WRITE page is writable + * PTE_AP_READ page is a young (unsetting this causes faults for any access) + * + * Any page that is mapped in is assumed to be readable... + */ +#define PAGE_NONE __pgprot(PTE_TYPE_SMALL) +#define PAGE_SHARED __pgprot(PTE_TYPE_SMALL | PTE_CACHEABLE | PTE_AP_READ | PTE_AP_WRITE) +#define PAGE_COPY __pgprot(PTE_TYPE_SMALL | PTE_CACHEABLE | PTE_AP_READ) +#define PAGE_READONLY __pgprot(PTE_TYPE_SMALL | PTE_CACHEABLE | PTE_AP_READ) +#define PAGE_KERNEL __pgprot(PTE_TYPE_SMALL | PTE_CACHEABLE | PTE_BUFFERABLE | PTE_AP_WRITE) + +#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER)) +#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL)) + +/* + * The arm can't do page protection for execute, and considers that the same are read. + * Also, write permissions imply read permissions. This is the closest we can get.. + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY +#define __P101 PAGE_READONLY +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY +#define __S101 PAGE_READONLY +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED + +#undef TEST_VERIFY_AREA + +/* + * BAD_PAGETABLE is used when we need a bogus page-table, while + * BAD_PAGE is used for a bogus page. + * + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern pte_t __bad_page(void); +extern pte_t * __bad_pagetable(void); +extern unsigned long *empty_zero_page; + +#define BAD_PAGETABLE __bad_pagetable() +#define BAD_PAGE __bad_page() +#define ZERO_PAGE ((unsigned long) empty_zero_page) + +/* number of bits that fit into a memory pointer */ +#define BYTES_PER_PTR (sizeof(unsigned long)) +#define BITS_PER_PTR (8*BYTES_PER_PTR) + +/* to align the pointer to a pointer address */ +#define PTR_MASK (~(sizeof(void*)-1)) + +/* sizeof(void*)==1<>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) + +/* to set the page-dir */ +#define SET_PAGE_DIR(tsk,pgdir) \ +do { \ + tsk->tss.memmap = __virt_to_phys(pgdir); \ + if ((tsk) == current) \ + __asm__ __volatile__( \ + "mcr%? p15, 0, %0, c2, c0, 0\n" \ + : : "r" (tsk->tss.memmap)); \ +} while (0) + +extern __inline__ int pte_none(pte_t pte) +{ + return !pte_val(pte); +} + +#define pte_clear(ptep) set_pte(ptep, __pte(0)) + +extern __inline__ int pte_present(pte_t pte) +{ + switch (pte_val(pte) & PTE_TYPE_MASK) { + case PTE_TYPE_LARGE: + case PTE_TYPE_SMALL: + return 1; + default: + return 0; + } +} + +extern __inline__ int pmd_none(pmd_t pmd) +{ + return !pmd_val(pmd); +} + +#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0)) + +extern __inline__ int pmd_bad(pmd_t pmd) +{ + switch (pmd_val(pmd) & PMD_TYPE_MASK) { + case PMD_TYPE_FAULT: + case PMD_TYPE_TABLE: + return 0; + default: + return 1; + } +} + +extern __inline__ int pmd_present(pmd_t pmd) +{ + switch (pmd_val(pmd) & PMD_TYPE_MASK) { + case PMD_TYPE_TABLE: + return 1; + default: + return 0; + } +} + +/* + * The "pgd_xxx()" functions here are trivial for a folded two-level + * setup: the pgd is never bad, and a pmd always exists (as it's folded + * into the pgd entry) + */ +#define pgd_none(pgd) (0) +#define pgd_bad(pgd) (0) +#define pgd_present(pgd) (1) +#define pgd_clear(pgdp) + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +#define pte_read(pte) (1) +#define pte_exec(pte) (1) + +extern __inline__ int pte_write(pte_t pte) +{ + return pte_val(pte) & PTE_AP_WRITE; +} + +extern __inline__ int pte_cacheable(pte_t pte) +{ + return pte_val(pte) & PTE_CACHEABLE; +} + +extern __inline__ int pte_dirty(pte_t pte) +{ + return pte_val(pte) & PTE_BUFFERABLE; +} + +extern __inline__ int pte_young(pte_t pte) +{ + return pte_val(pte) & PTE_AP_READ; +} + +extern __inline__ pte_t pte_wrprotect(pte_t pte) +{ + pte_val(pte) &= ~PTE_AP_WRITE; + return pte; +} + +extern __inline__ pte_t pte_nocache(pte_t pte) +{ + pte_val(pte) &= ~PTE_CACHEABLE; + return pte; +} + +extern __inline__ pte_t pte_mkclean(pte_t pte) +{ + pte_val(pte) &= ~PTE_BUFFERABLE; + return pte; +} + +extern __inline__ pte_t pte_mkold(pte_t pte) +{ + pte_val(pte) &= ~PTE_AP_READ; + return pte; +} + +extern __inline__ pte_t pte_mkwrite(pte_t pte) +{ + pte_val(pte) |= PTE_AP_WRITE; + return pte; +} + +extern __inline__ pte_t pte_mkdirty(pte_t pte) +{ + pte_val(pte) |= PTE_BUFFERABLE; + return pte; +} + +extern __inline__ pte_t pte_mkyoung(pte_t pte) +{ + pte_val(pte) |= PTE_AP_READ; + return pte; +} + +/* + * The following are unable to be implemented on this MMU + */ +#if 0 +extern __inline__ pte_t pte_rdprotect(pte_t pte) +{ + pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ); + return pte; +} + +extern __inline__ pte_t pte_exprotect(pte_t pte) +{ + pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ); + return pte; +} + +extern __inline__ pte_t pte_mkread(pte_t pte) +{ + pte_val(pte) |= PTE_CACHEABLE; + return pte; +} + +extern __inline__ pte_t pte_mkexec(pte_t pte) +{ + pte_val(pte) |= PTE_CACHEABLE; + return pte; +} +#endif + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot) +{ + pte_t pte; + pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot); + return pte; +} + +/* This takes a physical page address that is used by the remapping functions */ +extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) +{ + pte_t pte; + pte_val(pte) = physpage + pgprot_val(pgprot); + return pte; +} + +extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); + return pte; +} + +extern __inline__ void set_pte(pte_t *pteptr, pte_t pteval) +{ + *pteptr = pteval; + __flush_pte_to_ram(pteptr); +} + +extern __inline__ unsigned long pte_page(pte_t pte) +{ + return (unsigned long)phys_to_virt(pte_val(pte) & PAGE_MASK); +} + +extern __inline__ pmd_t mk_user_pmd(pte_t *ptep) +{ + pmd_t pmd; + pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_USER_TABLE; + return pmd; +} + +extern __inline__ pmd_t mk_kernel_pmd(pte_t *ptep) +{ + pmd_t pmd; + pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_KERNEL_TABLE; + return pmd; +} + +#if 1 +#define set_pmd(pmdp,pmd) processor.u.armv3v4._set_pmd(pmdp,pmd) +#else +extern __inline__ void set_pmd(pmd_t *pmdp, pmd_t pmd) +{ + *pmdp = pmd; + __flush_pte_to_ram(pmdp); +} +#endif + +extern __inline__ unsigned long pmd_page(pmd_t pmd) +{ + return (unsigned long)phys_to_virt(pmd_val(pmd) & 0xfffffc00); +} + +/* to find an entry in a kernel page-table-directory */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) + +/* to find an entry in a page-table-directory */ +extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) +{ + return mm->pgd + (address >> PGDIR_SHIFT); +} + +/* Find an entry in the second-level page table.. */ +#define pmd_offset(dir, address) ((pmd_t *)(dir)) + +/* Find an entry in the third-level page table.. */ +extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address) +{ + return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); +} + +extern unsigned long get_small_page(int priority); +extern void free_small_page(unsigned long page); + +/* + * Allocate and free page tables. The xxx_kernel() versions are + * used to allocate a kernel page table - this turns on ASN bits + * if any. + */ +extern __inline__ void pte_free_kernel(pte_t * pte) +{ + free_small_page((unsigned long) pte); +} + +extern const char bad_pmd_string[]; + +extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + if (pmd_none(*pmd)) { + pte_t *page = (pte_t *) get_small_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (page) { + memzero (page, PTRS_PER_PTE * BYTES_PER_PTR); + set_pmd(pmd, mk_kernel_pmd(page)); + return page + address; + } + set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE)); + return NULL; + } + free_small_page((unsigned long) page); + } + if (pmd_bad(*pmd)) { + printk(bad_pmd_string, pmd_val(*pmd)); + set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE)); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +#define pmd_free_kernel(pmdp) pmd_val(*(pmdp)) = 0; +#define pmd_alloc_kernel(pgdp, address) ((pmd_t *)(pgdp)) + +extern __inline__ void pte_free(pte_t * pte) +{ + free_small_page((unsigned long) pte); +} + +extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address) +{ + address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); + + if (pmd_none(*pmd)) { + pte_t *page = (pte_t *) get_small_page(GFP_KERNEL); + if (pmd_none(*pmd)) { + if (page) { + memzero (page, PTRS_PER_PTE * BYTES_PER_PTR); + set_pmd(pmd, mk_user_pmd(page)); + return page + address; + } + set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE)); + return NULL; + } + free_small_page ((unsigned long) page); + } + if (pmd_bad(*pmd)) { + printk(bad_pmd_string, pmd_val(*pmd)); + set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE)); + return NULL; + } + return (pte_t *) pmd_page(*pmd) + address; +} + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + */ +#define pmd_free(pmdp) pmd_val(*(pmdp)) = 0; +#define pmd_alloc(pgdp, address) ((pmd_t *)(pgdp)) + +/* + * Free a page directory. Takes the virtual address. + */ +extern __inline__ void pgd_free(pgd_t * pgd) +{ + free_pages((unsigned long) pgd, 2); +} + +/* + * Allocate a new page directory. Return the virtual address of it. + */ +extern __inline__ pgd_t * pgd_alloc(void) +{ + unsigned long pgd; + + /* + * need to get a 16k page for level 1 + */ + pgd = __get_free_pages(GFP_KERNEL,2,0); + if (pgd) + memzero ((void *)pgd, PTRS_PER_PGD * BYTES_PER_PTR); + return (pgd_t *)pgd; +} + +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + +/* + * The sa110 doesn't have any external MMU info: the kernel page + * tables contain all the necessary information. + */ +extern __inline__ void update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ +} + +#define SWP_TYPE(entry) (((entry) >> 2) & 0x7f) +#define SWP_OFFSET(entry) ((entry) >> 9) +#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9)) + +#endif /* __ASM_PROC_PAGE_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/processor.h linux/include/asm-arm/proc-armv/processor.h --- v2.1.79/linux/include/asm-arm/proc-armv/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/processor.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,103 @@ +/* + * linux/include/asm-arm/proc-armv/processor.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 20-09-1996 RMK Created + * 26-09-1996 RMK Added 'EXTRA_THREAD_STRUCT*' + * 28-09-1996 RMK Moved start_thread into the processor dependencies + */ +#ifndef __ASM_PROC_PROCESSOR_H +#define __ASM_PROC_PROCESSOR_H + +#ifdef __KERNEL__ + +#define KERNEL_STACK_SIZE PAGE_SIZE + +/* + * on arm2,3 wp does not work + */ +#define wp_works_ok 0 +#define wp_works_ok__is_a_macro /* for versions in ksyms.c */ + +struct context_save_struct { + unsigned long cpsr; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long fp; + unsigned long pc; +}; + +#define EXTRA_THREAD_STRUCT \ + struct context_save_struct *save; \ + unsigned long memmap; + +#define EXTRA_THREAD_STRUCT_INIT \ + 0, \ + ((unsigned long) swapper_pg_dir) - PAGE_OFFSET + +DECLARE_THREAD_STRUCT; + +/* + * Return saved PC of a blocked thread. + */ +extern __inline__ unsigned long thread_saved_pc (struct thread_struct *t) +{ + if (t->save) + return t->save->pc; + else + return 0; +} + +extern __inline__ unsigned long get_css_fp (struct thread_struct *t) +{ + if (t->save) + return t->save->fp; + else + return 0; +} + +asmlinkage void ret_from_sys_call(void) __asm__ ("ret_from_sys_call"); + +extern __inline__ void copy_thread_css (struct context_save_struct *save) +{ + save->cpsr = SVC_MODE; + save->r4 = + save->r5 = + save->r6 = + save->r7 = + save->r8 = + save->r9 = + save->fp = 0; + save->pc = (unsigned long) ret_from_sys_call; +} + +#define start_thread(regs,pc,sp) \ +({ \ + unsigned long *stack = (unsigned long *)sp; \ + set_fs(USER_DS); \ + memzero(regs->uregs, sizeof(regs->uregs)); \ + regs->ARM_cpsr = sp <= 0x04000000 ? USR26_MODE : USR_MODE; \ + regs->ARM_pc = pc; /* pc */ \ + regs->ARM_sp = sp; /* sp */ \ + regs->ARM_r2 = stack[2]; /* r2 (envp) */ \ + regs->ARM_r1 = stack[1]; /* r1 (argv) */ \ + regs->ARM_r0 = stack[0]; /* r0 (argc) */ \ +}) + +/* Allocation and freeing of basic task resources. */ +/* + * NOTE! The task struct and the stack go together + */ +#define alloc_task_struct() \ + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) +#define free_task_struct(p) free_pages((unsigned long)(p),1) + +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/ptrace.h linux/include/asm-arm/proc-armv/ptrace.h --- v2.1.79/linux/include/asm-arm/proc-armv/ptrace.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/ptrace.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,75 @@ +/* + * linux/include/asm-arm/proc-armv/ptrace.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_PTRACE_H +#define __ASM_PROC_PTRACE_H + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct pt_regs { + long uregs[18]; +}; + +#define ARM_cpsr uregs[16] +#define ARM_pc uregs[15] +#define ARM_lr uregs[14] +#define ARM_sp uregs[13] +#define ARM_ip uregs[12] +#define ARM_fp uregs[11] +#define ARM_r10 uregs[10] +#define ARM_r9 uregs[9] +#define ARM_r8 uregs[8] +#define ARM_r7 uregs[7] +#define ARM_r6 uregs[6] +#define ARM_r5 uregs[5] +#define ARM_r4 uregs[4] +#define ARM_r3 uregs[3] +#define ARM_r2 uregs[2] +#define ARM_r1 uregs[1] +#define ARM_r0 uregs[0] +#define ARM_ORIG_r0 uregs[17] /* -1 */ + +#define USR26_MODE 0x00 +#define FIQ26_MODE 0x01 +#define IRQ26_MODE 0x02 +#define SVC26_MODE 0x03 +#define USR_MODE 0x10 +#define FIQ_MODE 0x11 +#define IRQ_MODE 0x12 +#define SVC_MODE 0x13 +#define ABT_MODE 0x17 +#define UND_MODE 0x1b +#define SYSTEM_MODE 0x1f +#define MODE_MASK 0x1f +#define F_BIT 0x40 +#define I_BIT 0x80 +#define CC_V_BIT (1 << 28) +#define CC_C_BIT (1 << 29) +#define CC_Z_BIT (1 << 30) +#define CC_N_BIT (1 << 31) + +#define user_mode(regs) \ + ((((regs)->ARM_cpsr & MODE_MASK) == USR_MODE) || \ + (((regs)->ARM_cpsr & MODE_MASK) == USR26_MODE)) + +#define processor_mode(regs) \ + ((regs)->ARM_cpsr & MODE_MASK) + +#define interrupts_enabled(regs) \ + (!((regs)->ARM_cpsr & I_BIT)) + +#define fast_interrupts_enabled(regs) \ + (!((regs)->ARM_cpsr & F_BIT)) + +#define condition_codes(regs) \ + ((regs)->ARM_cpsr & (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT)) + +#define instruction_pointer(regs) ((regs)->ARM_pc) +#define pc_pointer(v) (v) + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/semaphore.h linux/include/asm-arm/proc-armv/semaphore.h --- v2.1.79/linux/include/asm-arm/proc-armv/semaphore.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/semaphore.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,81 @@ +/* + * linux/include/asm-arm/semaphore.h + */ +#ifndef __ASM_PROC_SEMAPHORE_H +#define __ASM_PROC_SEMAPHORE_H + +/* + * This is ugly, but we want the default case to fall through. + * "__down" is the actual routine that waits... + */ +extern inline void down(struct semaphore * sem) +{ + __asm__ __volatile__ (" + @ atomic down operation + mrs r0, cpsr + orr r1, r0, #128 @ disable IRQs + bic r0, r0, #0x80000000 @ clear N + msr cpsr, r1 + ldr r1, [%0] + subs r1, r1, #1 + str r1, [%0] + orrmi r0, r0, #0x80000000 @ set N + msr cpsr, r0 + movmi r0, %0 + blmi " SYMBOL_NAME_STR(__down) + : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc"); +} + +/* + * This is ugly, but we want the default case to fall through. + * "__down_interruptible" is the actual routine that waits... + */ +extern inline int down_interruptible (struct semaphore * sem) +{ + int result; + __asm__ __volatile__ (" + @ atomic down operation + mrs r0, cpsr + orr r1, r0, #128 @ disable IRQs + bic r0, r0, #0x80000000 @ clear N + msr cpsr, r1 + ldr r1, [%1] + subs r1, r1, #1 + str r1, [%1] + orrmi r0, r0, #0x80000000 @ set N + msr cpsr, r0 + movmi r0, %1 + movpl r0, #0 + blmi " SYMBOL_NAME_STR(__down_interruptible) " + mov %0, r0" + : "=r" (result) + : "r" (sem) + : "r0", "r1", "r2", "r3", "ip", "lr", "cc"); + return result; +} + +/* + * Note! This is subtle. We jump to wake people up only if + * the semaphore was negative (== somebody was waiting on it). + * The default case (no contention) will result in NO + * jumps for both down() and up(). + */ +extern inline void up(struct semaphore * sem) +{ + __asm__ __volatile__ (" + @ atomic up operation + mrs r0, cpsr + orr r1, r0, #128 @ disable IRQs + bic r0, r0, #0x80000000 @ clear N + msr cpsr, r1 + ldr r1, [%0] + adds r1, r1, #1 + str r1, [%0] + orrls r0, r0, #0x80000000 @ set N + msr cpsr, r0 + movmi r0, %0 + blmi " SYMBOL_NAME_STR(__up) + : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc"); +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/shmparam.h linux/include/asm-arm/proc-armv/shmparam.h --- v2.1.79/linux/include/asm-arm/proc-armv/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/shmparam.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,19 @@ +/* + * linux/include/asm-arm/proc-armv/shmparam.h + * + * Copyright (C) 1996 Russell King + * + * definitions for the shared process memory on ARM v3 or v4 + * processors + */ + +#ifndef __ASM_PROC_SHMPARAM_H +#define __ASM_PROC_SHMPARAM_H + +#ifndef SHM_RANGE_START +#define SHM_RANGE_START 0x50000000 +#define SHM_RANGE_END 0x60000000 +#define SHMMAX 0x01000000 +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/system.h linux/include/asm-arm/proc-armv/system.h --- v2.1.79/linux/include/asm-arm/proc-armv/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/system.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,137 @@ +/* + * linux/include/asm-arm/proc-armv/system.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROC_SYSTEM_H +#define __ASM_PROC_SYSTEM_H + +extern const char xchg_str[]; + +extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size) +{ + switch (size) { + case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]" : "=r" (x) : "r" (x), "r" (ptr) : "memory"); + break; + case 2: abort (); + case 4: __asm__ __volatile__ ("swp %0, %1, [%2]" : "=r" (x) : "r" (x), "r" (ptr) : "memory"); + break; + default: arm_invalidptr(xchg_str, size); + } + return x; +} + +/* + * This processor does not need anything special before reset, + * but RPC may do... + */ +extern __inline__ void proc_hard_reset(void) +{ +} + +/* + * We can wait for an interrupt... + */ +#if 0 +#define proc_idle() \ + do { \ + __asm__ __volatile__( \ +" mcr p15, 0, %0, c15, c8, 2" \ + : : "r" (0)); \ + } while (0) +#else +#define proc_idle() +#endif +/* + * A couple of speedups for the ARM + */ + +/* + * Save the current interrupt enable state & disable IRQs + */ +#define __save_flags_cli(x) \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ + "mrs %1, cpsr\n" \ +" and %0, %1, #192\n" \ +" orr %1, %1, #128\n" \ +" msr cpsr, %1" \ + : "=r" (x), "=r" (temp) \ + : \ + : "memory"); \ + } while (0) + +/* + * Enable IRQs + */ +#define __sti() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ + "mrs %0, cpsr\n" \ +" bic %0, %0, #128\n" \ +" msr cpsr, %0" \ + : "=r" (temp) \ + : \ + : "memory"); \ + } while(0) + +/* + * Disable IRQs + */ +#define __cli() \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ + "mrs %0, cpsr\n" \ +" orr %0, %0, #128\n" \ +" msr cpsr, %0" \ + : "=r" (temp) \ + : \ + : "memory"); \ + } while(0) + +/* + * save current IRQ & FIQ state + */ +#define __save_flags(x) \ + do { \ + __asm__ __volatile__( \ + "mrs %0, cpsr\n" \ +" and %0, %0, #192" \ + : "=r" (x) \ + : \ + : "memory"); \ + } while (0) + +/* + * restore saved IRQ & FIQ state + */ +#define __restore_flags(x) \ + do { \ + unsigned long temp; \ + __asm__ __volatile__( \ + "mrs %0, cpsr\n" \ +" bic %0, %0, #192\n" \ +" orr %0, %0, %1\n" \ +" msr cpsr, %0" \ + : "=r" (temp) \ + : "r" (x) \ + : "memory"); \ + } while (0) + +#ifdef __SMP__ +#error SMP not supported +#else + +#define cli() __cli() +#define sti() __sti() +#define save_flags(x) __save_flags(x) +#define restore_flags(x) __restore_flags(x) +#define save_flags_cli(x) __save_flags_cli(x) + +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/uaccess.h linux/include/asm-arm/proc-armv/uaccess.h --- v2.1.79/linux/include/asm-arm/proc-armv/uaccess.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/uaccess.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,204 @@ +/* + * linux/include/asm-arm/proc-armv/uaccess.h + */ + +/* + * The fs functions are implemented on the ARMV3 and V4 architectures + * using the domain register. + * + * DOMAIN_IO - domain 2 includes all IO only + * DOMAIN_KERNEL - domain 1 includes all kernel memory only + * DOMAIN_USER - domain 0 includes all user memory only + */ + +#define DOMAIN_CLIENT 1 +#define DOMAIN_MANAGER 3 + +#define DOMAIN_USER_CLIENT ((DOMAIN_CLIENT) << 0) +#define DOMAIN_USER_MANAGER ((DOMAIN_MANAGER) << 0) + +#define DOMAIN_KERNEL_CLIENT ((DOMAIN_CLIENT) << 2) +#define DOMAIN_KERNEL_MANAGER ((DOMAIN_MANAGER) << 2) + +#define DOMAIN_IO_CLIENT ((DOMAIN_CLIENT) << 4) +#define DOMAIN_IO_MANAGER ((DOMAIN_MANAGER) << 4) + +/* + * When we want to access kernel memory in the *_user functions, + * we change the domain register to KERNEL_DS, thus allowing + * unrestricted access + */ +#define KERNEL_DOMAIN (DOMAIN_USER_CLIENT | DOMAIN_KERNEL_MANAGER | DOMAIN_IO_CLIENT) +#define USER_DOMAIN (DOMAIN_USER_CLIENT | DOMAIN_KERNEL_CLIENT | DOMAIN_IO_CLIENT) + +/* + * Note that this is actually 0x1,0000,0000 + */ +#define KERNEL_DS 0x00000000 +#define USER_DS 0xc0000000 + +#define get_ds() (KERNEL_DS) +#define get_fs() (current->addr_limit) + +#define segment_eq(a,b) ((a) == (b)) + +extern __inline__ void set_fs (mm_segment_t fs) +{ + current->addr_limit = fs; + + __asm__ __volatile__("mcr p15, 0, %0, c3, c0" : + : "r" (fs ? USER_DOMAIN : KERNEL_DOMAIN)); +} + +/* + * a + s <= 2^32 -> C = 0 || Z = 0 (LS) + * (a + s) <= l -> C = 0 || Z = 0 (LS) + */ +#define __range_ok(addr,size) ({ \ + unsigned long flag, sum; \ + __asm__ __volatile__("adds %1, %2, %3; cmpls %1, %0; movls %0, #0" \ + : "=&r" (flag), "=&r" (sum) \ + : "r" (addr), "Ir" (size), "0" (current->addr_limit) \ + : "cc"); \ + flag; }) + +#define __addr_ok(addr) ({ \ + unsigned long flag; \ + __asm__ __volatile__("cmp %2, %0; movlo %0, #0" \ + : "=&r" (flag) \ + : "0" (current->addr_limit), "r" (addr) \ + : "cc"); \ + (flag == 0); }) + +#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) + +#define __put_user_asm_byte(x,addr,err) \ + __asm__ __volatile__( \ + "1: strbt %1,[%2],#0\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mvn %0, %3\n" \ + " b 2b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 3b\n" \ + " .previous" \ + : "=r" (err) \ + : "r" (x), "r" (addr), "i" (EFAULT), "0" (err)) + +#define __put_user_asm_half(x,addr,err) \ +({ \ + unsigned long __temp = (unsigned long)(x); \ + __asm__ __volatile__( \ + "1: strbt %1,[%3],#0\n" \ + "2: strbt %2,[%4],#0\n" \ + "3:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "4: mvn %0, %5\n" \ + " b 3b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 4b\n" \ + " .long 2b, 4b\n" \ + " .previous" \ + : "=r" (err) \ + : "r" (__temp), "r" (__temp >> 8), \ + "r" (addr), "r" ((int)(addr) + 1), \ + "i" (EFAULT), "0" (err)); \ +}) + +#define __put_user_asm_word(x,addr,err) \ + __asm__ __volatile__( \ + "1: strt %1,[%2],#0\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mvn %0, %3\n" \ + " b 2b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 3b\n" \ + " .previous" \ + : "=r" (err) \ + : "r" (x), "r" (addr), "i" (EFAULT), "0" (err)) + +#define __get_user_asm_byte(x,addr,err) \ + __asm__ __volatile__( \ + "1: ldrbt %1,[%2],#0\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mvn %0, %3\n" \ + " b 2b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 3b\n" \ + " .previous" \ + : "=r" (err), "=r" (x) \ + : "r" (addr), "i" (EFAULT), "0" (err)) + +#define __get_user_asm_half(x,addr,err) \ +({ \ + unsigned long __temp; \ + __asm__ __volatile__( \ + "1: ldrbt %1,[%3],#0\n" \ + "2: ldrbt %2,[%4],#0\n" \ + " orr %1, %1, %2, lsl #8\n" \ + "3:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "4: mvn %0, %5\n" \ + " b 3b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 4b\n" \ + " .long 2b, 4b\n" \ + " .previous" \ + : "=r" (err), "=r" (x), "=&r" (__temp) \ + : "r" (addr), "r" ((int)(addr) + 1), \ + "i" (EFAULT), "0" (err)); \ +}) + + +#define __get_user_asm_word(x,addr,err) \ + __asm__ __volatile__( \ + "1: ldrt %1,[%2],#0\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .align 2\n" \ + "3: mvn %0, %3\n" \ + " b 2b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .long 1b, 3b\n" \ + " .previous" \ + : "=r" (err), "=r" (x) \ + : "r" (addr), "i" (EFAULT), "0" (err)) + +extern unsigned long __arch_copy_from_user(void *to, const void *from, unsigned long n); +#define __do_copy_from_user(to,from,n) \ + (n) = __arch_copy_from_user(to,from,n) + +extern unsigned long __arch_copy_to_user(void *to, const void *from, unsigned long n); +#define __do_copy_to_user(to,from,n) \ + (n) = __arch_copy_to_user(to,from,n) + +extern unsigned long __arch_clear_user(void *addr, unsigned long n); +#define __do_clear_user(addr,sz) \ + (sz) = __arch_clear_user(addr,sz) + +extern unsigned long __arch_strncpy_from_user(char *to, const char *from, unsigned long count); +#define __do_strncpy_from_user(dst,src,count,res) \ + (res) = __arch_strncpy_from_user(dst,src,count) + +extern unsigned long __arch_strlen_user(const char *s); +#define __do_strlen_user(s,res) \ + (res) = __arch_strlen_user(s) diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-armv/uncompress.h linux/include/asm-arm/proc-armv/uncompress.h --- v2.1.79/linux/include/asm-arm/proc-armv/uncompress.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-armv/uncompress.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,22 @@ +/* + * linux/include/asm-arm/proc-armv/uncompress.h + * + * (c) 1997 Russell King + */ + +static inline void proc_decomp_setup (void) +{ + __asm__ __volatile__(" + mrc p15, 0, r0, c0, c0 + eor r0, r0, #0x44 << 24 + eor r0, r0, #0x01 << 16 + eor r0, r0, #0xA1 << 8 + movs r0, r0, lsr #4 + mcreq p15, 0, r0, c7, c5, 0 @ flush I cache + mrceq p15, 0, r0, c1, c0 + orreq r0, r0, #1 << 12 + mcreq p15, 0, r0, c1, c0 @ enable I cache + mov r0, #0 + mcreq p15, 0, r0, c15, c1, 2 @ enable clock switching + " : : : "r0", "cc", "memory"); +} diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/proc-fns.h linux/include/asm-arm/proc-fns.h --- v2.1.79/linux/include/asm-arm/proc-fns.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/proc-fns.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,111 @@ +/* + * linux/include/asm-arm/proc-fns.h + * + * Copyright (C) 1997 Russell King + */ +#ifndef __ASM_PROCFNS_H +#define __ASM_PROCFNS_H + +#include + +#ifdef __KERNEL__ +/* + * Don't change this structure + */ +extern struct processor { + const char *name; + /* MISC + * + * flush caches for task switch + */ + void (*_switch_to)(void *prev, void *next); + /* + * get data abort address/flags + */ + void (*_data_abort)(unsigned long pc); + /* + * check for any bugs + */ + void (*_check_bugs)(void); + /* + * Set up any processor specifics + */ + void (*_proc_init)(void); + /* + * Disable any processor specifics + */ + void (*_proc_fin)(void); + /* + * Processor architecture specific + */ + union { + struct { + /* CACHE + * + * flush all caches + */ + void (*_flush_cache_all)(void); + /* + * flush a specific page or pages + */ + void (*_flush_cache_area)(unsigned long address, unsigned long end, int flags); + /* + * flush cache entry for an address + */ + void (*_flush_cache_entry)(unsigned long address); + /* + * flush a virtual address used for a page table + * note D-cache only! + */ + void (*_flush_cache_pte)(unsigned long address); + /* + * flush a page to RAM + */ + void (*_flush_ram_page)(unsigned long page); + /* TLB + * + * flush all TLBs + */ + void (*_flush_tlb_all)(void); + /* + * flush a specific TLB + */ + void (*_flush_tlb_area)(unsigned long address, unsigned long end, int flags); + /* + * Set a PMD (handling IMP bit 4) + */ + void (*_set_pmd)(pmd_t *pmdp, pmd_t pmd); + /* + * Special stuff for a reset + */ + unsigned long (*reset)(void); + /* + * flush an icached page + */ + void (*_flush_icache_area)(unsigned long start, unsigned long end); + } armv3v4; + struct { + /* MEMC + * + * remap memc tables + */ + void (*_remap_memc)(void *tsk); + /* + * update task's idea of mmap + */ + void (*_update_map)(void *tsk); + /* + * update task's idea after abort + */ + void (*_update_mmu_cache)(void *vma, unsigned long addr, pte_t pte); + /* XCHG + */ + unsigned long (*_xchg_1)(unsigned long x, volatile void *ptr); + unsigned long (*_xchg_2)(unsigned long x, volatile void *ptr); + unsigned long (*_xchg_4)(unsigned long x, volatile void *ptr); + } armv2; + } u; +} processor; +#endif +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h --- v2.1.79/linux/include/asm-arm/processor.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/processor.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,51 @@ +/* + * include/asm-arm/processor.h + * + * Copyright (C) 1995 Russell King + */ + +#ifndef __ASM_ARM_PROCESSOR_H +#define __ASM_ARM_PROCESSOR_H + +struct fp_hard_struct { + unsigned int save[140/4]; /* as yet undefined */ +}; + +struct fp_soft_struct { + unsigned int save[140/4]; /* undefined information */ +}; + +union fp_state { + struct fp_hard_struct hard; + struct fp_soft_struct soft; +}; + +typedef unsigned long mm_segment_t; /* domain register */ + +#define DECLARE_THREAD_STRUCT \ +struct thread_struct { \ + unsigned long address; /* Address of fault */ \ + unsigned long trap_no; /* Trap number */ \ + unsigned long error_code; /* Error code of trap */ \ + union fp_state fpstate; /* FPE save state */ \ + EXTRA_THREAD_STRUCT \ +} + +#include +#include + +#define INIT_TSS { \ + 0, \ + 0, \ + 0, \ + { { { 0, }, }, }, \ + EXTRA_THREAD_STRUCT_INIT \ +} + +/* Free all resources held by a thread. */ +extern void release_thread(struct task_struct *); + +#define init_task (init_task_union.task) +#define init_stack (init_task_union.stack) + +#endif /* __ASM_ARM_PROCESSOR_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/procinfo.h linux/include/asm-arm/procinfo.h --- v2.1.79/linux/include/asm-arm/procinfo.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/procinfo.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,32 @@ +/* + * linux/include/asm-arm/procinfo.h + * + * Copyright (C) 1996 Russell King + */ + +#ifndef __ASM_PROCINFO_H +#define __ASM_PROCINFO_H + +#include + +#define F_MEMC (1<<0) +#define F_MMU (1<<1) +#define F_32BIT (1<<2) +#define F_CACHE (1<<3) +#define F_IOEB (1<<31) + +#ifndef __ASSEMBLER__ + +struct armversions { + unsigned long id; + unsigned long mask; + unsigned long features; + const char *manu; + const char *name; + const struct processor *proc; +}; + +#endif + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/ptrace.h linux/include/asm-arm/ptrace.h --- v2.1.79/linux/include/asm-arm/ptrace.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/ptrace.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,11 @@ +#ifndef __ASM_ARM_PTRACE_H +#define __ASM_ARM_PTRACE_H + +#include + +#ifdef __KERNEL__ +extern void show_regs(struct pt_regs *); +#endif + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/resource.h linux/include/asm-arm/resource.h --- v2.1.79/linux/include/asm-arm/resource.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/resource.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,39 @@ +#ifndef _ARM_RESOURCE_H +#define _ARM_RESOURCE_H + +/* + * Resource limits + */ + +#define RLIMIT_CPU 0 /* CPU time in ms */ +#define RLIMIT_FSIZE 1 /* Maximum filesize */ +#define RLIMIT_DATA 2 /* max data size */ +#define RLIMIT_STACK 3 /* max stack size */ +#define RLIMIT_CORE 4 /* max core file size */ +#define RLIMIT_RSS 5 /* max resident set size */ +#define RLIMIT_NPROC 6 /* max number of processes */ +#define RLIMIT_NOFILE 7 /* max number of open files */ +#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */ +#define RLIMIT_AS 9 /* address space limit */ + +#define RLIM_NLIMITS 10 + +#ifdef __KERNEL__ + +#define INIT_RLIMITS \ +{ \ + { LONG_MAX, LONG_MAX }, \ + { LONG_MAX, LONG_MAX }, \ + { LONG_MAX, LONG_MAX }, \ + { _STK_LIM, _STK_LIM }, \ + { 0, LONG_MAX }, \ + { LONG_MAX, LONG_MAX }, \ + { MAX_TASKS_PER_USER, MAX_TASKS_PER_USER }, \ + { NR_OPEN, NR_OPEN }, \ + { LONG_MAX, LONG_MAX }, \ + { LONG_MAX, LONG_MAX }, \ +} + +#endif /* __KERNEL__ */ + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/scatterlist.h linux/include/asm-arm/scatterlist.h --- v2.1.79/linux/include/asm-arm/scatterlist.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/scatterlist.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,13 @@ +#ifndef _ASMARM_SCATTERLIST_H +#define _ASMARM_SCATTERLIST_H + +struct scatterlist { + char * address; /* Location data is to be transferred to */ + char * alt_address; /* Location of actual if address is a + * dma indirect buffer. NULL otherwise */ + unsigned int length; +}; + +#define ISA_DMA_THRESHOLD (0xffffffff) + +#endif /* _ASMARM_SCATTERLIST_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/segment.h linux/include/asm-arm/segment.h --- v2.1.79/linux/include/asm-arm/segment.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/segment.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,11 @@ +#ifndef __ASM_ARM_SEGMENT_H +#define __ASM_ARM_SEGMENT_H + +#define __KERNEL_CS 0x0 +#define __KERNEL_DS 0x0 + +#define __USER_CS 0x1 +#define __USER_DS 0x1 + +#endif /* __ASM_ARM_SEGMENT_H */ + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h --- v2.1.79/linux/include/asm-arm/semaphore.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/semaphore.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,67 @@ +/* + * linux/include/asm-arm/semaphore.h + */ +#ifndef __ASM_ARM_SEMAPHORE_H +#define __ASM_ARM_SEMAPHORE_H + +#include +#include +#include + +struct semaphore { + atomic_t count; + int waking; + struct wait_queue * wait; +}; + +#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, NULL }) +#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL }) + +asmlinkage void __down_failed (void /* special register calling convention */); +asmlinkage int __down_failed_interruptible (void /* special register calling convention */); +asmlinkage void __up_wakeup (void /* special register calling convention */); + +extern void __down(struct semaphore * sem); +extern void __up(struct semaphore * sem); + +#define sema_init(sem, val) atomic_set(&((sem)->count), (val)) + +/* + * These two _must_ execute atomically wrt each other. + * + * This is trivially done with load_locked/store_cond, + * but on the x86 we need an external synchronizer. + * Currently this is just the global interrupt lock, + * bah. Go for a smaller spinlock some day. + * + * (On the other hand this shouldn't be in any critical + * path, so..) + */ +static inline void wake_one_more(struct semaphore * sem) +{ + unsigned long flags; + + save_flags(flags); + cli(); + sem->waking++; + restore_flags(flags); +} + +static inline int waking_non_zero(struct semaphore *sem) +{ + unsigned long flags; + int ret = 0; + + save_flags(flags); + cli(); + if (sem->waking > 0) { + sem->waking--; + ret = 1; + } + restore_flags(flags); + return ret; +} + +#include + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/serial.h linux/include/asm-arm/serial.h --- v2.1.79/linux/include/asm-arm/serial.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/serial.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,15 @@ +/* + * linux/include/asm-arm/serial.h + * + * Copyright (c) 1996 Russell King. + * + * Changelog: + * 15-10-1996 RMK Created + */ + +#ifndef __ASM_SERIAL_H +#define __ASM_SERIAL_H + +#include + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/setup.h linux/include/asm-arm/setup.h --- v2.1.79/linux/include/asm-arm/setup.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/setup.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,49 @@ +/* + * include/asm/setup.h + * + * Structure passed to kernel to tell it about the hardware it's running on + * + * Copyright (C) 1997,1998 Russell King + */ +#ifndef __ASMARM_SETUP_H +#define __ASMARM_SETUP_H + +struct param_struct { + union { + struct { + unsigned long page_size; /* 0 */ + unsigned long nr_pages; /* 4 */ + unsigned long ramdisk_size; /* 8 */ + unsigned long flags; /* 12 */ +#define FLAG_READONLY 1 +#define FLAG_RDLOAD 4 +#define FLAG_RDPROMPT 8 + unsigned long rootdev; /* 16 */ + unsigned long video_num_cols; /* 20 */ + unsigned long video_num_rows; /* 24 */ + unsigned long video_x; /* 28 */ + unsigned long video_y; /* 32 */ + unsigned long memc_control_reg; /* 36 */ + unsigned char sounddefault; /* 40 */ + unsigned char adfsdrives; /* 41 */ + unsigned char bytes_per_char_h; /* 42 */ + unsigned char bytes_per_char_v; /* 43 */ + unsigned long pages_in_bank[4]; /* 44 */ + unsigned long pages_in_vram; /* 60 */ + unsigned long initrd_start; /* 64 */ + unsigned long initrd_size; /* 68 */ + unsigned long rd_start; /* 72 */ + } s; + char unused[256]; + } u1; + union { + char paths[8][128]; + struct { + unsigned long magic; + char n[1024 - sizeof(unsigned long)]; + } s; + } u2; + char commandline[256]; +}; + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/shmparam.h linux/include/asm-arm/shmparam.h --- v2.1.79/linux/include/asm-arm/shmparam.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/shmparam.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,47 @@ +#ifndef _ASMARM_SHMPARAM_H +#define _ASMARM_SHMPARAM_H + +/* + * Include the machine specific shm parameters before the processor + * dependent parameters so that the machine parameters can override + * the processor parameters + */ +#include +#include + +/* + * Format of a swap-entry for shared memory pages currently out in + * swap space (see also mm/swap.c). + * + * SWP_TYPE = SHM_SWP_TYPE + * SWP_OFFSET is used as follows: + * + * bits 0..6 : id of shared memory segment page belongs to (SHM_ID) + * bits 7..21: index of page within shared memory segment (SHM_IDX) + * (actually fewer bits get used since SHMMAX is so low) + */ + +/* + * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and + * there is a static array of size SHMMNI. + */ +#define _SHM_ID_BITS 7 +#define SHM_ID_MASK ((1<<_SHM_ID_BITS)-1) + +#define SHM_IDX_SHIFT (_SHM_ID_BITS) +#define _SHM_IDX_BITS 15 +#define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1) + +/* + * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and + * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS). + */ + +#define SHMMIN 1 /* really PAGE_SIZE */ /* min shared seg size (bytes) */ +#define SHMMNI (1<<_SHM_ID_BITS) /* max num of segs system wide */ +#define SHMALL /* max shm system wide (pages) */ \ + (1<<(_SHM_IDX_BITS+_SHM_ID_BITS)) +#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ +#define SHMSEG SHMMNI /* max shared segs per process */ + +#endif /* _ASMARM_SHMPARAM_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/sigcontext.h linux/include/asm-arm/sigcontext.h --- v2.1.79/linux/include/asm-arm/sigcontext.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/sigcontext.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,33 @@ +#ifndef _ASMARM_SIGCONTEXT_H +#define _ASMARM_SIGCONTEXT_H + +/* + * Signal context structure - contains all info to do with the state + * before the signal handler was invoked. Note: only add new entries + * to the end of the structure. + */ +struct sigcontext { + unsigned long trap_no; + unsigned long error_code; + unsigned long oldmask; + unsigned long arm_r0; + unsigned long arm_r1; + unsigned long arm_r2; + unsigned long arm_r3; + unsigned long arm_r4; + unsigned long arm_r5; + unsigned long arm_r6; + unsigned long arm_r7; + unsigned long arm_r8; + unsigned long arm_r9; + unsigned long arm_r10; + unsigned long arm_fp; + unsigned long arm_ip; + unsigned long arm_sp; + unsigned long arm_lr; + unsigned long arm_pc; + unsigned long arm_cpsr; +}; + + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/siginfo.h linux/include/asm-arm/siginfo.h --- v2.1.79/linux/include/asm-arm/siginfo.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/siginfo.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,195 @@ +#ifndef _ASMARM_SIGINFO_H +#define _ASMARM_SIGINFO_H + +#include + +/* XXX: This structure was copied from the Alpha; is there an iBCS version? */ + +typedef union sigval { + int sival_int; + void *sival_ptr; +} sigval_t; + +#define SI_MAX_SIZE 128 +#define SI_PAD_SIZE ((SI_MAX_SIZE/sizeof(int)) - 3) + +typedef struct siginfo { + int si_signo; + int si_errno; + int si_code; + + union { + int _pad[SI_PAD_SIZE]; + + /* kill() */ + struct { + pid_t _pid; /* sender's pid */ + uid_t _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + unsigned int _timer1; + unsigned int _timer2; + } _timer; + + /* POSIX.1b signals */ + struct { + pid_t _pid; /* sender's pid */ + uid_t _uid; /* sender's uid */ + sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + pid_t _pid; /* which child */ + int _status; /* exit code */ + clock_t _utime; + clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + void *_addr; /* faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} siginfo_t; + +/* + * How these fields are to be accessed. + */ +#define si_pid _sifields._kill._pid +#define si_uid _sifields._kill._uid +#define si_status _sifields._sigchld._status +#define si_utime _sifields._sigchld._utime +#define si_stime _sifields._sigchld._stime +#define si_value _sifields._rt._sigval +#define si_int _sifields._rt._sigval.sival_int +#define si_ptr _sifields._rt._sigval.sival_ptr +#define si_addr _sifields._sigfault._addr +#define si_band _sifields._sigpoll._band +#define si_fd _sifields._sigpoll._fd + +/* + * si_code values + * Digital reserves positive values for kernel-generated signals. + */ +#define SI_USER 0 /* sent by kill, sigsend, raise */ +#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */ +#define SI_QUEUE -1 /* sent by sigqueue */ +#define SI_TIMER -2 /* sent by timer expiration */ +#define SI_MESGQ -3 /* sent by real time mesq state change */ +#define SI_ASYNCIO -4 /* sent by AIO completion */ + +#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0) +#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0) + +/* + * SIGILL si_codes + */ +#define ILL_ILLOPC 1 /* illegal opcode */ +#define ILL_ILLOPN 2 /* illegal operand */ +#define ILL_ILLADR 3 /* illegal addressing mode */ +#define ILL_ILLTRP 4 /* illegal trap */ +#define ILL_PRVOPC 5 /* privileged opcode */ +#define ILL_PRVREG 6 /* privileged register */ +#define ILL_COPROC 7 /* coprocessor error */ +#define ILL_BADSTK 8 /* internal stack error */ +#define NSIGILL 8 + +/* + * SIGFPE si_codes + */ +#define FPE_INTDIV 1 /* integer divide by zero */ +#define FPE_INTOVF 2 /* integer overflow */ +#define FPE_FLTDIV 3 /* floating point divide by zero */ +#define FPE_FLTOVF 4 /* floating point overflow */ +#define FPE_FLTUND 5 /* floating point underflow */ +#define FPE_FLTRES 6 /* floating point inexact result */ +#define FPE_FLTINV 7 /* floating point invalid operation */ +#define FPE_FLTSUB 8 /* subscript out of range */ +#define NSIGFPE 8 + +/* + * SIGSEGV si_codes + */ +#define SEGV_MAPERR 1 /* address not mapped to object */ +#define SEGV_ACCERR 2 /* invalid permissions for mapped object */ +#define NSIGSEGV 2 + +/* + * SIGBUS si_codes + */ +#define BUS_ADRALN 1 /* invalid address alignment */ +#define BUS_ADRERR 2 /* non-existant physical address */ +#define BUS_OBJERR 3 /* object specific hardware error */ +#define NSIGBUS 3 + +/* + * SIGTRAP si_codes + */ +#define TRAP_BRKPT 1 /* process breakpoint */ +#define TRAP_TRACE 2 /* process trace trap */ +#define NSIGTRAP + +/* + * SIGCHLD si_codes + */ +#define CLD_EXITED 1 /* child has exited */ +#define CLD_KILLED 2 /* child was killed */ +#define CLD_DUMPED 3 /* child terminated abnormally */ +#define CLD_TRAPPED 4 /* traced child has trapped */ +#define CLD_STOPPED 5 /* child has stopped */ +#define CLD_CONTINUED 6 /* stopped child has continued */ +#define NSIGCHLD + +/* + * SIGPOLL si_codes + */ +#define POLL_IN 1 /* data input available */ +#define POLL_OUT 2 /* output buffers available */ +#define POLL_MSG 3 /* input message available */ +#define POLL_ERR 4 /* i/o error */ +#define POLL_PRI 5 /* high priority input available */ +#define POLL_HUP 6 /* device disconnected */ +#define NSIGPOLL 6 + +/* + * sigevent definitions + * + * It seems likely that SIGEV_THREAD will have to be handled from + * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the + * thread manager then catches and does the appropriate nonsense. + * However, everything is written out here so as to not get lost. + */ +#define SIGEV_SIGNAL 0 /* notify via signal */ +#define SIGEV_NONE 1 /* other notification: meaningless */ +#define SIGEV_THREAD 2 /* deliver via thread creation */ + +#define SIGEV_MAX_SIZE 64 +#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3) + +typedef struct sigevent { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + union { + int _pad[SIGEV_PAD_SIZE]; + + struct { + void (*_function)(sigval_t); + void *_attribute; /* really pthread_attr_t */ + } _sigev_thread; + } _sigev_un; +} sigevent_t; + +#define sigev_notify_function _sigev_un._sigev_thread._function +#define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/signal.h linux/include/asm-arm/signal.h --- v2.1.79/linux/include/asm-arm/signal.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/signal.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,147 @@ +#ifndef _ASMARM_SIGNAL_H +#define _ASMARM_SIGNAL_H + +#include + +/* Avoid too many header ordering problems. */ +struct siginfo; + +/* Most things should be clean enough to redefine this at will, if care + is taken to make libc match. */ + +#define _NSIG 64 +#define _NSIG_BPW 32 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +typedef unsigned long old_sigset_t; /* at least 32 bits */ + +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +/* +#define SIGLOST 29 +*/ +#define SIGPWR 30 +#define SIGUNUSED 31 + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#define SIGRTMAX (_NSIG-1) + +/* + * SA_FLAGS values: + * + * SA_ONSTACK is not currently supported, but will allow sigaltstack(2). + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001 +#define SA_NOCLDWAIT 0x00000002 /* not supported yet */ +#define SA_SIGINFO 0x00000004 +#define SA_ONSTACK 0x08000000 +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ + +#define SA_RESTORER 0x04000000 + +#ifdef __KERNEL__ + +/* + * These values of sa_flags are used only by the kernel as part of the + * irq handling routines. + * + * SA_INTERRUPT is also used by the irq handling routines. + * SA_SHIRQ is for shared interrupt support on PCI and EISA. + */ +#define SA_PROBE SA_ONESHOT +#define SA_SAMPLE_RANDOM SA_RESTART +#define SA_SHIRQ 0x04000000 +#endif + +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ + +/* Type of a signal handler. */ +typedef void (*__sighandler_t)(int); + +#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ +#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ +#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ + +struct old_sigaction { + __sighandler_t sa_handler; + old_sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + +struct sigaction { + __sighandler_t sa_handler; + unsigned long sa_flags; + void (*sa_restorer)(void); + sigset_t sa_mask; /* mask last for extensibility */ +}; + +struct k_sigaction { + struct sigaction sa; +}; + +typedef struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +#ifdef __KERNEL__ +#include + +#define sigmask(sig) (1UL << ((sig) - 1)) + +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/smp.h linux/include/asm-arm/smp.h --- v2.1.79/linux/include/asm-arm/smp.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/smp.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,7 @@ +#ifndef __ASM_SMP_H +#define __ASM_SMP_H + +#ifdef __SMP__ +#error SMP not supported +#endif +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/smp_lock.h linux/include/asm-arm/smp_lock.h --- v2.1.79/linux/include/asm-arm/smp_lock.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/smp_lock.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,17 @@ +#ifndef __I386_SMPLOCK_H +#define __I386_SMPLOCK_H + +#define __STR(x) #x + +#ifndef __SMP__ + +#define lock_kernel() do { } while(0) +#define unlock_kernel() do { } while(0) +#define release_kernel_lock(task, cpu, depth) ((depth) = 1) +#define reacquire_kernel_lock(task, cpu, depth) do { } while(0) + +#else +#error SMP not supported +#endif /* __SMP__ */ + +#endif /* __I386_SMPLOCK_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/socket.h linux/include/asm-arm/socket.h --- v2.1.79/linux/include/asm-arm/socket.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/socket.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,33 @@ +#ifndef _ASMARM_SOCKET_H +#define _ASMARM_SOCKET_H + +#include + +/* For setsockoptions(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 + +#define SO_BINDTODEVICE 25 + +#endif /* _ASM_SOCKET_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/sockios.h linux/include/asm-arm/sockios.h --- v2.1.79/linux/include/asm-arm/sockios.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/sockios.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,12 @@ +#ifndef __ARCH_ARM_SOCKIOS_H +#define __ARCH_ARM_SOCKIOS_H + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp */ + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/softirq.h linux/include/asm-arm/softirq.h --- v2.1.79/linux/include/asm-arm/softirq.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/softirq.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,68 @@ +#ifndef __ASM_SOFTIRQ_H +#define __ASM_SOFTIRQ_H + +#include +#include + +#define get_active_bhs() (bh_mask & bh_active) +#define clear_active_bhs(x) atomic_clear_mask((int)(x),&bh_active) + +extern inline void init_bh(int nr, void (*routine)(void)) +{ + bh_base[nr] = routine; + bh_mask_count[nr] = 0; + bh_mask |= 1 << nr; +} + +extern inline void remove_bh(int nr) +{ + bh_base[nr] = NULL; + bh_mask &= ~(1 << nr); +} + +extern inline void mark_bh(int nr) +{ + set_bit(nr, &bh_active); +} + +/* + * These use a mask count to correctly handle + * nested disable/enable calls + */ +extern inline void disable_bh(int nr) +{ + bh_mask &= ~(1 << nr); + bh_mask_count[nr]++; +} + +extern inline void enable_bh(int nr) +{ + if (!--bh_mask_count[nr]) + bh_mask |= 1 << nr; +} + +#ifdef __SMP__ +#error SMP not supported +#else + +extern int __arm_bh_counter; + +extern inline void start_bh_atomic(void) +{ + __arm_bh_counter++; + barrier(); +} + +extern inline void end_bh_atomic(void) +{ + barrier(); + __arm_bh_counter--; +} + +/* These are for the irq's testing the lock */ +#define softirq_trylock() (__arm_bh_counter ? 0 : (__arm_bh_counter=1)) +#define softirq_endlock() (__arm_bh_counter = 0) + +#endif /* SMP */ + +#endif /* __ASM_SOFTIRQ_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/spinlock.h linux/include/asm-arm/spinlock.h --- v2.1.79/linux/include/asm-arm/spinlock.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/spinlock.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,59 @@ +#ifndef __ASM_SPINLOCK_H +#define __ASM_SPINLOCK_H + +#ifndef __SMP__ + +/* + * Your basic spinlocks, allowing only a single CPU anywhere + */ +typedef struct { } spinlock_t; +#define SPIN_LOCK_UNLOCKED { } + +#define spin_lock_init(lock) do { } while(0) +#define spin_lock(lock) do { } while(0) +#define spin_trylock(lock) do { } while(0) +#define spin_unlock_wait(lock) do { } while(0) +#define spin_unlock(lock) do { } while(0) +#define spin_lock_irq(lock) cli() +#define spin_unlock_irq(lock) sti() + +#define spin_lock_irqsave(lock, flags) \ + do { save_flags(flags); cli(); } while (0) +#define spin_unlock_irqrestore(lock, flags) \ + restore_flags(flags) + +/* + * Read-write spinlocks, allowing multiple readers + * but only one writer. + * + * NOTE! it is quite common to have readers in interrupts + * but no interrupt writers. For those circumstances we + * can "mix" irq-safe locks - any writer needs to get a + * irq-safe write-lock, but readers can get non-irqsafe + * read-locks. + */ +typedef struct { } rwlock_t; +#define RW_LOCK_UNLOCKED { } + +#define read_lock(lock) do { } while(0) +#define read_unlock(lock) do { } while(0) +#define write_lock(lock) do { } while(0) +#define write_unlock(lock) do { } while(0) +#define read_lock_irq(lock) cli() +#define read_unlock_irq(lock) sti() +#define write_lock_irq(lock) cli() +#define write_unlock_irq(lock) sti() + +#define read_lock_irqsave(lock, flags) \ + do { save_flags(flags); cli(); } while (0) +#define read_unlock_irqrestore(lock, flags) \ + restore_flags(flags) +#define write_lock_irqsave(lock, flags) \ + do { save_flags(flags); cli(); } while (0) +#define write_unlock_irqrestore(lock, flags) \ + restore_flags(flags) + +#else +#error ARM architecture does not support spin locks +#endif /* SMP */ +#endif /* __ASM_SPINLOCK_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/stat.h linux/include/asm-arm/stat.h --- v2.1.79/linux/include/asm-arm/stat.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/stat.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,41 @@ +#ifndef _ASMARM_STAT_H +#define _ASMARM_STAT_H + +struct __old_kernel_stat { + unsigned short st_dev; + unsigned short st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; +}; + +struct stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; + unsigned long st_mtime; + unsigned long __unused2; + unsigned long st_ctime; + unsigned long __unused3; + unsigned long __unused4; + unsigned long __unused5; +}; + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/statfs.h linux/include/asm-arm/statfs.h --- v2.1.79/linux/include/asm-arm/statfs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/statfs.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,25 @@ +#ifndef _ASMARM_STATFS_H +#define _ASMARM_STATFS_H + +#ifndef __KERNEL_STRICT_NAMES + +#include + +typedef __kernel_fsid_t fsid_t; + +#endif + +struct statfs { + long f_type; + long f_bsize; + long f_blocks; + long f_bfree; + long f_bavail; + long f_files; + long f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_spare[6]; +}; + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/string.h linux/include/asm-arm/string.h --- v2.1.79/linux/include/asm-arm/string.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/string.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,24 @@ +#ifndef __ASM_ARM_STRING_H +#define __ASM_ARM_STRING_H + +/* + * inline versions, hmm... + */ + +#define __HAVE_ARCH_STRRCHR +extern char * strrchr(const char * s, int c); + +#define __HAVE_ARCH_STRCHR +extern char * strchr(const char * s, int c); + +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE +#define __HAVE_ARCH_MEMSET + +#define __HAVE_ARCH_MEMZERO +extern void memzero(void *ptr, int n); + +extern void memsetl (unsigned long *, unsigned long, int n); + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/system.h linux/include/asm-arm/system.h --- v2.1.79/linux/include/asm-arm/system.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/system.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,33 @@ +#ifndef __ASM_ARM_SYSTEM_H +#define __ASM_ARM_SYSTEM_H + +#include +#include + +extern void arm_malalignedptr(const char *, void *, volatile void *); +extern void arm_invalidptr(const char *, int); + +#define xchg(ptr,x) \ + ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) + +#define tas(ptr) (xchg((ptr),1)) + +/* + * switch_to(prev, next) should switch from task `prev' to `next' + * `prev' will never be the same as `next'. + * + * `next' and `prev' should be struct task_struct, but it isn't always defined + */ +#define switch_to(prev,next) processor._switch_to(prev,next) + +/* + * Include processor dependent parts + */ +#include +#include + +#define mb() __asm__ __volatile__ ("" : : : "memory") +#define nop() __asm__ __volatile__("mov r0,r0\n\t"); + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/termbits.h linux/include/asm-arm/termbits.h --- v2.1.79/linux/include/asm-arm/termbits.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/termbits.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,161 @@ +#ifndef __ASM_ARM_TERMBITS_H +#define __ASM_ARM_TERMBITS_H + +#include + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 19 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ +}; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#define NLDLY 0000400 +#define NL0 0000000 +#define NL1 0000400 +#define CRDLY 0003000 +#define CR0 0000000 +#define CR1 0001000 +#define CR2 0002000 +#define CR3 0003000 +#define TABDLY 0014000 +#define TAB0 0000000 +#define TAB1 0004000 +#define TAB2 0010000 +#define TAB3 0014000 +#define XTABS 0014000 +#define BSDLY 0020000 +#define BS0 0000000 +#define BS1 0020000 +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 +#define FFDLY 0100000 +#define FF0 0000000 +#define FF1 0100000 + +/* c_cflag bit meaning */ +#define CBAUD 0010017 +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#define EXTA B19200 +#define EXTB B38400 +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#define CBAUDEX 0010000 +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define CIBAUD 002003600000 /* input baud rate (not used) */ +#define CMSPAR 010000000000 /* mark or space (stick) parity */ +#define CRTSCTS 020000000000 /* flow control */ + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#define XCASE 0000004 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#endif /* __ASM_ARM_TERMBITS_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/termios.h linux/include/asm-arm/termios.h --- v2.1.79/linux/include/asm-arm/termios.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/termios.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,98 @@ +#ifndef __ASM_ARM_TERMIOS_H +#define __ASM_ARM_TERMIOS_H + +#include +#include + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 8 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +#ifdef __KERNEL__ +/* intr=^C quit=^| erase=del kill=^U + eof=^D vtime=\0 vmin=\1 sxtc=\0 + start=^Q stop=^S susp=^Z eol=\0 + reprint=^R discard=^U werase=^W lnext=^V + eol2=\0 +*/ +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" +#endif + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + +/* line disciplines */ +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 /* X.25 async */ + +#ifdef __KERNEL__ + +#include + +/* + * Translate a "termio" structure into a "termios". Ugh. + */ +#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ + unsigned short __tmp; \ + get_user(__tmp,&(termio)->x); \ + *(unsigned short *) &(termios)->x = __tmp; \ +} + +#define user_termio_to_kernel_termios(termios, termio) \ +({ \ + SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ + copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ +}) + +/* + * Translate a "termios" structure into a "termio". Ugh. + */ +#define kernel_termios_to_user_termio(termio, termios) \ +({ \ + put_user((termios)->c_iflag, &(termio)->c_iflag); \ + put_user((termios)->c_oflag, &(termio)->c_oflag); \ + put_user((termios)->c_cflag, &(termio)->c_cflag); \ + put_user((termios)->c_lflag, &(termio)->c_lflag); \ + put_user((termios)->c_line, &(termio)->c_line); \ + copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ +}) + +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) + +#endif /* __KERNEL__ */ + +#endif /* __ASM_ARM_TERMIOS_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/timex.h linux/include/asm-arm/timex.h --- v2.1.79/linux/include/asm-arm/timex.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/timex.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,13 @@ +/* + * linux/include/asm-arm/timex.h + * + * Architecture Specific TIME specifications + * + * Copyright (C) 1997,1998 Russell King + */ +#ifndef _ASMARM_TIMEX_H +#define _ASMARM_TIMEX_H + +#include + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/types.h linux/include/asm-arm/types.h --- v2.1.79/linux/include/asm-arm/types.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/types.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,45 @@ +#ifndef __ASM_ARM_TYPES_H +#define __ASM_ARM_TYPES_H + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#endif /* __KERNEL__ */ + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/uaccess.h linux/include/asm-arm/uaccess.h --- v2.1.79/linux/include/asm-arm/uaccess.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/uaccess.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,194 @@ +#ifndef _ASMARM_UACCESS_H +#define _ASMARM_UACCESS_H + +/* + * User space memory access functions + */ +#include + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry +{ + unsigned long insn, fixup; +}; + +/* Returns 0 if exception not found and fixup otherwise. */ +extern unsigned long search_exception_table(unsigned long); + +#include + +extern inline int verify_area(int type, const void * addr, unsigned long size) +{ + return access_ok(type,addr,size) ? 0 : -EFAULT; +} + +/* + * Single-value transfer routines. They automatically use the right + * size if we just have the right pointer type. + * + * The "__xxx" versions of the user access functions do not verify the + * address space - it must have been done previously with a separate + * "access_ok()" call. + * + * The "xxx_ret" versions return constant specified in the third + * argument if something bad happens. + */ +#define get_user(x,p) __get_user_check((x),(p),sizeof(*(p))) +#define __get_user(x,p) __get_user_nocheck((x),(p),sizeof(*(p))) +#define get_user_ret(x,p,r) ({ if (get_user(x,p)) return r; }) +#define __get_user_ret(x,p,r) ({ if (__get_user(x,p)) return r; }) + +#define put_user(x,p) __put_user_check((__typeof(*(p)))(x),(p),sizeof(*(p))) +#define __put_user(x,p) __put_user_nocheck((__typeof(*(p)))(x),(p),sizeof(*(p))) +#define put_user_ret(x,p,r) ({ if (put_user(x,p)) return r; }) +#define __put_user_ret(x,p,r) ({ if (__put_user(x,p)) return r; }) + +static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n) +{ + if (access_ok(VERIFY_READ, from, n)) + __do_copy_from_user(to, from, n); + return n; +} + +static __inline__ unsigned long __copy_from_user(void *to, const void *from, unsigned long n) +{ + __do_copy_from_user(to, from, n); + return n; +} + +#define copy_from_user_ret(t,f,n,r) \ + ({ if (copy_from_user(t,f,n)) return r; }) + +static __inline__ unsigned long copy_to_user(void *to, const void *from, unsigned long n) +{ + if (access_ok(VERIFY_WRITE, to, n)) + __do_copy_to_user(to, from, n); + return n; +} + +static __inline__ unsigned long __copy_to_user(void *to, const void *from, unsigned long n) +{ + __do_copy_to_user(to, from, n); + return n; +} + +#define copy_to_user_ret(t,f,n,r) \ + ({ if (copy_to_user(t,f,n)) return r; }) + +static __inline__ unsigned long clear_user (void *to, unsigned long n) +{ + if (access_ok(VERIFY_WRITE, to, n)) + __do_clear_user(to, n); + return n; +} + +static __inline__ unsigned long __clear_user (void *to, unsigned long n) +{ + __do_clear_user(to, n); + return n; +} + +static __inline__ long strncpy_from_user (char *dst, const char *src, long count) +{ + long res = -EFAULT; + if (access_ok(VERIFY_READ, src, 1)) + __do_strncpy_from_user(dst, src, count, res); + return res; +} + +static __inline__ long __strncpy_from_user (char *dst, const char *src, long count) +{ + long res; + __do_strncpy_from_user(dst, src, count, res); + return res; +} + +extern __inline__ long strlen_user (const char *s) +{ + unsigned long res = 0; + + if (__addr_ok(s)) + __do_strlen_user (s, res); + + return res; +} + +/* + * These are the work horses of the get/put_user functions + */ +#define __get_user_check(x,ptr,size) \ +({ \ + long __gu_err = -EFAULT, __gu_val = 0; \ + const __typeof__(*(ptr)) *__gu_addr = (ptr); \ + if (access_ok(VERIFY_READ,__gu_addr,size)) \ + __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +#define __get_user_nocheck(x,ptr,size) \ +({ \ + long __gu_err = 0, __gu_val = 0; \ + __get_user_size(__gu_val,(ptr),(size),__gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +#define __put_user_check(x,ptr,size) \ +({ \ + long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ + __put_user_size((x),__pu_addr,(size),__pu_err); \ + __pu_err; \ +}) + +#define __put_user_nocheck(x,ptr,size) \ +({ \ + long __pu_err = 0; \ + __put_user_size((x),(ptr),(size),__pu_err); \ + __pu_err; \ +}) + +extern long __get_user_bad(void); + +#define __get_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __get_user_asm_byte(x,ptr,retval); break; \ + case 2: __get_user_asm_half(x,ptr,retval); break; \ + case 4: __get_user_asm_word(x,ptr,retval); break; \ + default: (x) = __get_user_bad(); \ + } \ +} while (0) + +extern long __put_user_bad(void); + +#define __put_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __put_user_asm_byte(x,ptr,retval); break; \ + case 2: __put_user_asm_half(x,ptr,retval); break; \ + case 4: __put_user_asm_word(x,ptr,retval); break; \ + default: __put_user_bad(); \ + } \ +} while (0) + +#endif /* _ASMARM_UACCESS_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/ucontext.h linux/include/asm-arm/ucontext.h --- v2.1.79/linux/include/asm-arm/ucontext.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/ucontext.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,12 @@ +#ifndef _ASMARM_UCONTEXT_H +#define _ASMARM_UCONTEXT_H + +struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +}; + +#endif /* !_ASMARM_UCONTEXT_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/unaligned.h linux/include/asm-arm/unaligned.h --- v2.1.79/linux/include/asm-arm/unaligned.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/unaligned.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,59 @@ +#ifndef __ARM_UNALIGNED_H +#define __ARM_UNALIGNED_H + +#define get_unaligned(ptr) \ + ((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr)))) + +#define put_unaligned(val, ptr) \ + __put_unaligned((unsigned long)(val), (ptr), sizeof(*(ptr))) + +extern void bad_unaligned_access_length (void); + +extern inline unsigned long __get_unaligned(const void *ptr, size_t size) +{ + unsigned long val; + switch (size) { + case 1: + val = *(const unsigned char *)ptr; + break; + + case 2: + val = ((const unsigned char *)ptr)[0] | (((const unsigned char *)ptr)[1] << 8); + break; + + case 4: + val = ((const unsigned char *)ptr)[0] | (((const unsigned char *)ptr)[1] << 8) | + (((const unsigned char *)ptr)[2]) << 16 | (((const unsigned char *)ptr)[3] << 24); + break; + + default: + bad_unaligned_access_length (); + } + return val; +} + +extern inline void __put_unaligned(unsigned long val, void *ptr, size_t size) +{ + switch (size) { + case 1: + *(unsigned char *)ptr = val; + break; + + case 2: + ((unsigned char *)ptr)[0] = val; + ((unsigned char *)ptr)[1] = val >> 8; + break; + + case 4: + ((unsigned char *)ptr)[0] = val; + ((unsigned char *)ptr)[1] = val >> 8; + ((unsigned char *)ptr)[2] = val >> 16; + ((unsigned char *)ptr)[3] = val >> 24; + break; + + default: + bad_unaligned_access_length (); + } +} + +#endif diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/unistd.h linux/include/asm-arm/unistd.h --- v2.1.79/linux/include/asm-arm/unistd.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/unistd.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,371 @@ +#ifndef __ASM_ARM_UNISTD_H +#define __ASM_ARM_UNISTD_H + +#define __NR_SYSCALL_BASE 0x900000 + +/* + * This file contains the system call numbers. + */ + +#define __NR_setup (__NR_SYSCALL_BASE+ 0) /* used only by init, to get system going */ +#define __NR_exit (__NR_SYSCALL_BASE+ 1) +#define __NR_fork (__NR_SYSCALL_BASE+ 2) +#define __NR_read (__NR_SYSCALL_BASE+ 3) +#define __NR_write (__NR_SYSCALL_BASE+ 4) +#define __NR_open (__NR_SYSCALL_BASE+ 5) +#define __NR_close (__NR_SYSCALL_BASE+ 6) +#define __NR_waitpid (__NR_SYSCALL_BASE+ 7) +#define __NR_creat (__NR_SYSCALL_BASE+ 8) +#define __NR_link (__NR_SYSCALL_BASE+ 9) +#define __NR_unlink (__NR_SYSCALL_BASE+ 10) +#define __NR_execve (__NR_SYSCALL_BASE+ 11) +#define __NR_chdir (__NR_SYSCALL_BASE+ 12) +#define __NR_time (__NR_SYSCALL_BASE+ 13) +#define __NR_mknod (__NR_SYSCALL_BASE+ 14) +#define __NR_chmod (__NR_SYSCALL_BASE+ 15) +#define __NR_chown (__NR_SYSCALL_BASE+ 16) +#define __NR_break (__NR_SYSCALL_BASE+ 17) +#define __NR_oldstat (__NR_SYSCALL_BASE+ 18) +#define __NR_lseek (__NR_SYSCALL_BASE+ 19) +#define __NR_getpid (__NR_SYSCALL_BASE+ 20) +#define __NR_mount (__NR_SYSCALL_BASE+ 21) +#define __NR_umount (__NR_SYSCALL_BASE+ 22) +#define __NR_setuid (__NR_SYSCALL_BASE+ 23) +#define __NR_getuid (__NR_SYSCALL_BASE+ 24) +#define __NR_stime (__NR_SYSCALL_BASE+ 25) +#define __NR_ptrace (__NR_SYSCALL_BASE+ 26) +#define __NR_alarm (__NR_SYSCALL_BASE+ 27) +#define __NR_oldfstat (__NR_SYSCALL_BASE+ 28) +#define __NR_pause (__NR_SYSCALL_BASE+ 29) +#define __NR_utime (__NR_SYSCALL_BASE+ 30) +#define __NR_stty (__NR_SYSCALL_BASE+ 31) +#define __NR_gtty (__NR_SYSCALL_BASE+ 32) +#define __NR_access (__NR_SYSCALL_BASE+ 33) +#define __NR_nice (__NR_SYSCALL_BASE+ 34) +#define __NR_ftime (__NR_SYSCALL_BASE+ 35) +#define __NR_sync (__NR_SYSCALL_BASE+ 36) +#define __NR_kill (__NR_SYSCALL_BASE+ 37) +#define __NR_rename (__NR_SYSCALL_BASE+ 38) +#define __NR_mkdir (__NR_SYSCALL_BASE+ 39) +#define __NR_rmdir (__NR_SYSCALL_BASE+ 40) +#define __NR_dup (__NR_SYSCALL_BASE+ 41) +#define __NR_pipe (__NR_SYSCALL_BASE+ 42) +#define __NR_times (__NR_SYSCALL_BASE+ 43) +#define __NR_prof (__NR_SYSCALL_BASE+ 44) +#define __NR_brk (__NR_SYSCALL_BASE+ 45) +#define __NR_setgid (__NR_SYSCALL_BASE+ 46) +#define __NR_getgid (__NR_SYSCALL_BASE+ 47) +#define __NR_signal (__NR_SYSCALL_BASE+ 48) +#define __NR_geteuid (__NR_SYSCALL_BASE+ 49) +#define __NR_getegid (__NR_SYSCALL_BASE+ 50) +#define __NR_acct (__NR_SYSCALL_BASE+ 51) +#define __NR_phys (__NR_SYSCALL_BASE+ 52) +#define __NR_lock (__NR_SYSCALL_BASE+ 53) +#define __NR_ioctl (__NR_SYSCALL_BASE+ 54) +#define __NR_fcntl (__NR_SYSCALL_BASE+ 55) +#define __NR_mpx (__NR_SYSCALL_BASE+ 56) +#define __NR_setpgid (__NR_SYSCALL_BASE+ 57) +#define __NR_ulimit (__NR_SYSCALL_BASE+ 58) +#define __NR_oldolduname (__NR_SYSCALL_BASE+ 59) +#define __NR_umask (__NR_SYSCALL_BASE+ 60) +#define __NR_chroot (__NR_SYSCALL_BASE+ 61) +#define __NR_ustat (__NR_SYSCALL_BASE+ 62) +#define __NR_dup2 (__NR_SYSCALL_BASE+ 63) +#define __NR_getppid (__NR_SYSCALL_BASE+ 64) +#define __NR_getpgrp (__NR_SYSCALL_BASE+ 65) +#define __NR_setsid (__NR_SYSCALL_BASE+ 66) +#define __NR_sigaction (__NR_SYSCALL_BASE+ 67) +#define __NR_sgetmask (__NR_SYSCALL_BASE+ 68) +#define __NR_ssetmask (__NR_SYSCALL_BASE+ 69) +#define __NR_setreuid (__NR_SYSCALL_BASE+ 70) +#define __NR_setregid (__NR_SYSCALL_BASE+ 71) +#define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72) +#define __NR_sigpending (__NR_SYSCALL_BASE+ 73) +#define __NR_sethostname (__NR_SYSCALL_BASE+ 74) +#define __NR_setrlimit (__NR_SYSCALL_BASE+ 75) +#define __NR_getrlimit (__NR_SYSCALL_BASE+ 76) +#define __NR_getrusage (__NR_SYSCALL_BASE+ 77) +#define __NR_gettimeofday (__NR_SYSCALL_BASE+ 78) +#define __NR_settimeofday (__NR_SYSCALL_BASE+ 79) +#define __NR_getgroups (__NR_SYSCALL_BASE+ 80) +#define __NR_setgroups (__NR_SYSCALL_BASE+ 81) +#define __NR_select (__NR_SYSCALL_BASE+ 82) +#define __NR_symlink (__NR_SYSCALL_BASE+ 83) +#define __NR_oldlstat (__NR_SYSCALL_BASE+ 84) +#define __NR_readlink (__NR_SYSCALL_BASE+ 85) +#define __NR_uselib (__NR_SYSCALL_BASE+ 86) +#define __NR_swapon (__NR_SYSCALL_BASE+ 87) +#define __NR_reboot (__NR_SYSCALL_BASE+ 88) +#define __NR_readdir (__NR_SYSCALL_BASE+ 89) +#define __NR_mmap (__NR_SYSCALL_BASE+ 90) +#define __NR_munmap (__NR_SYSCALL_BASE+ 91) +#define __NR_truncate (__NR_SYSCALL_BASE+ 92) +#define __NR_ftruncate (__NR_SYSCALL_BASE+ 93) +#define __NR_fchmod (__NR_SYSCALL_BASE+ 94) +#define __NR_fchown (__NR_SYSCALL_BASE+ 95) +#define __NR_getpriority (__NR_SYSCALL_BASE+ 96) +#define __NR_setpriority (__NR_SYSCALL_BASE+ 97) +#define __NR_profil (__NR_SYSCALL_BASE+ 98) +#define __NR_statfs (__NR_SYSCALL_BASE+ 99) +#define __NR_fstatfs (__NR_SYSCALL_BASE+100) +#define __NR_ioperm (__NR_SYSCALL_BASE+101) +#define __NR_socketcall (__NR_SYSCALL_BASE+102) +#define __NR_syslog (__NR_SYSCALL_BASE+103) +#define __NR_setitimer (__NR_SYSCALL_BASE+104) +#define __NR_getitimer (__NR_SYSCALL_BASE+105) +#define __NR_stat (__NR_SYSCALL_BASE+106) +#define __NR_lstat (__NR_SYSCALL_BASE+107) +#define __NR_fstat (__NR_SYSCALL_BASE+108) +#define __NR_olduname (__NR_SYSCALL_BASE+109) +#define __NR_iopl (__NR_SYSCALL_BASE+110) +#define __NR_vhangup (__NR_SYSCALL_BASE+111) +#define __NR_idle (__NR_SYSCALL_BASE+112) +#define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */ +#define __NR_wait4 (__NR_SYSCALL_BASE+114) +#define __NR_swapoff (__NR_SYSCALL_BASE+115) +#define __NR_sysinfo (__NR_SYSCALL_BASE+116) +#define __NR_ipc (__NR_SYSCALL_BASE+117) +#define __NR_fsync (__NR_SYSCALL_BASE+118) +#define __NR_sigreturn (__NR_SYSCALL_BASE+119) +#define __NR_clone (__NR_SYSCALL_BASE+120) +#define __NR_setdomainname (__NR_SYSCALL_BASE+121) +#define __NR_uname (__NR_SYSCALL_BASE+122) +#define __NR_modify_ldt (__NR_SYSCALL_BASE+123) +#define __NR_adjtimex (__NR_SYSCALL_BASE+124) +#define __NR_mprotect (__NR_SYSCALL_BASE+125) +#define __NR_sigprocmask (__NR_SYSCALL_BASE+126) +#define __NR_create_module (__NR_SYSCALL_BASE+127) +#define __NR_init_module (__NR_SYSCALL_BASE+128) +#define __NR_delete_module (__NR_SYSCALL_BASE+129) +#define __NR_get_kernel_syms (__NR_SYSCALL_BASE+130) +#define __NR_quotactl (__NR_SYSCALL_BASE+131) +#define __NR_getpgid (__NR_SYSCALL_BASE+132) +#define __NR_fchdir (__NR_SYSCALL_BASE+133) +#define __NR_bdflush (__NR_SYSCALL_BASE+134) +#define __NR_sysfs (__NR_SYSCALL_BASE+135) +#define __NR_personality (__NR_SYSCALL_BASE+136) +#define __NR_afs_syscall (__NR_SYSCALL_BASE+137) /* Syscall for Andrew File System */ +#define __NR_setfsuid (__NR_SYSCALL_BASE+138) +#define __NR_setfsgid (__NR_SYSCALL_BASE+139) +#define __NR__llseek (__NR_SYSCALL_BASE+140) +#define __NR_getdents (__NR_SYSCALL_BASE+141) +#define __NR__newselect (__NR_SYSCALL_BASE+142) +#define __NR_flock (__NR_SYSCALL_BASE+143) +#define __NR_msync (__NR_SYSCALL_BASE+144) +#define __NR_readv (__NR_SYSCALL_BASE+145) +#define __NR_writev (__NR_SYSCALL_BASE+146) +#define __NR_getsid (__NR_SYSCALL_BASE+147) +#define __NR_fdatasync (__NR_SYSCALL_BASE+148) +#define __NR__sysctl (__NR_SYSCALL_BASE+149) +#define __NR_mlock (__NR_SYSCALL_BASE+150) +#define __NR_munlock (__NR_SYSCALL_BASE+151) +#define __NR_mlockall (__NR_SYSCALL_BASE+152) +#define __NR_munlockall (__NR_SYSCALL_BASE+153) +#define __NR_sched_setparam (__NR_SYSCALL_BASE+154) +#define __NR_sched_getparam (__NR_SYSCALL_BASE+155) +#define __NR_sched_setscheduler (__NR_SYSCALL_BASE+156) +#define __NR_sched_getscheduler (__NR_SYSCALL_BASE+157) +#define __NR_sched_yield (__NR_SYSCALL_BASE+158) +#define __NR_sched_get_priority_max (__NR_SYSCALL_BASE+159) +#define __NR_sched_get_priority_min (__NR_SYSCALL_BASE+160) +#define __NR_sched_rr_get_interval (__NR_SYSCALL_BASE+161) +#define __NR_nanosleep (__NR_SYSCALL_BASE+162) +#define __NR_mremap (__NR_SYSCALL_BASE+163) +#define __NR_setresuid (__NR_SYSCALL_BASE+164) +#define __NR_getresuid (__NR_SYSCALL_BASE+165) +#define __NR_vm86 (__NR_SYSCALL_BASE+166) +#define __NR_query_module (__NR_SYSCALL_BASE+167) +#define __NR_poll (__NR_SYSCALL_BASE+168) +#define __NR_nfsservctl (__NR_SYSCALL_BASE+169) +#define __NR_setresgid (__NR_SYSCALL_BASE+170) +#define __NR_getresgid (__NR_SYSCALL_BASE+171) +#define __NR_prctl (__NR_SYSCALL_BASE+172) +#define __NR_rt_sigreturn (__NR_SYSCALL_BASE+173) +#define __NR_rt_sigaction (__NR_SYSCALL_BASE+174) +#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE+175) +#define __NR_rt_sigpending (__NR_SYSCALL_BASE+176) +#define __NR_rt_sigtimedwait (__NR_SYSCALL_BASE+177) +#define __NR_rt_sigqueueinfo (__NR_SYSCALL_BASE+178) +#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE+179) +#define __NR_pread (__NR_SYSCALL_BASE+180) +#define __NR_pwrite (__NR_SYSCALL_BASE+181) + +#define __sys2(x) #x +#define __sys1(x) __sys2(x) + +#ifndef __syscall +#define __syscall(name) "swi\t" __sys1(__NR_##name) "\n\t" +#endif + +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + errno = -(res); \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +#define _syscall0(type,name) \ +type name(void) { \ + long __res; \ + __asm__ __volatile__ ( \ + __syscall(name) \ + "mov %0,r0" \ + :"=r" (__res) : : "r0","lr"); \ + __syscall_return(type,__res); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + __syscall(name) \ + "mov %0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)) \ + : "r0","lr"); \ + __syscall_return(type,__res); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + "mov\tr1,%2\n\t" \ + __syscall(name) \ + "mov\t%0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)) \ + : "r0","r1","lr"); \ + __syscall_return(type,__res); \ +} + + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + "mov\tr1,%2\n\t" \ + "mov\tr2,%3\n\t" \ + __syscall(name) \ + "mov\t%0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)) \ + : "r0","r1","r2","lr"); \ + __syscall_return(type,__res); \ +} + + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + "mov\tr1,%2\n\t" \ + "mov\tr2,%3\n\t" \ + "mov\tr3,%4\n\t" \ + __syscall(name) \ + "mov\t%0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)) \ + : "r0","r1","r2","r3","lr"); \ + __syscall_return(type,__res); \ +} + + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + "mov\tr1,%2\n\t" \ + "mov\tr2,%3\n\t" \ + "mov\tr3,%4\n\t" \ + "mov\tr4,%5\n\t" \ + __syscall(name) \ + "mov\t%0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)), \ + "r" ((long)(arg5)) \ + : "r0","r1","r2","r3","r4","lr"); \ + __syscall_return(type,__res); \ +} + +#ifdef __KERNEL_SYSCALLS__ + +/* + * we need this inline - forking from kernel space will result + * in NO COPY ON WRITE (!!!), until an execve is executed. This + * is no problem, but for the stack. This is handled by not letting + * main() use the stack at all after fork(). Thus, no function + * calls - which means inline code for fork too, as otherwise we + * would use the stack upon exit from 'fork()'. + * + * Actually only pause and fork are needed inline, so that there + * won't be any messing with the stack from main(), but we define + * some others too. + */ +#define __NR__exit __NR_exit +static inline _syscall0(int,idle); +static inline _syscall0(int,fork); +static inline _syscall2(int,clone,unsigned long,flags,char *,esp); +static inline _syscall0(int,pause); +static inline _syscall1(int,setup,int,magic); +static inline _syscall0(int,sync); +static inline _syscall0(pid_t,setsid); +static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count); +static inline _syscall3(int,read,int,fd,char *,buf,off_t,count) +static inline _syscall1(int,dup,int,fd); +static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp); +static inline _syscall3(int,open,const char *,file,int,flag,int,mode); +static inline _syscall1(int,close,int,fd); +static inline _syscall1(int,_exit,int,exitcode); +static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options); + +static inline pid_t wait(int * wait_stat) +{ + return waitpid(-1,wait_stat,0); +} + + + +/* + * This is the mechanism for creating a new kernel thread. + * + * NOTE! Only a kernel-only process(ie the swapper or direct descendants + * who haven't done an "execve()") should use this: it will work within + * a system call from a "real" process, but the process memory space will + * not be free'd until both the parent and the child have exited. + */ +static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + + __asm__ __volatile__(" + mov r0,%1 + mov r1,%2 + "__syscall(clone)" + teq r0, #0 + bne 1f + mov r0,%4 + mov lr, pc + mov pc, %3 + "__syscall(exit)" +1: mov %0,r0" + : "=r" (retval) + : "Ir" (flags | CLONE_VM), "Ir" (NULL), "r" (fn), "Ir" (arg) + : "r0","r1","r2","r3","lr"); + + return retval; +} + +#endif + +#endif /* __ASM_ARM_UNISTD_H */ + + + diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/user.h linux/include/asm-arm/user.h --- v2.1.79/linux/include/asm-arm/user.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/user.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,82 @@ +#ifndef _ARM_USER_H +#define _ARM_USER_H + +#include +#include +/* Core file format: The core file is written in such a way that gdb + can understand it and provide useful information to the user (under + linux we use the 'trad-core' bfd). There are quite a number of + obstacles to being able to view the contents of the floating point + registers, and until these are solved you will not be able to view the + contents of them. Actually, you can read in the core file and look at + the contents of the user struct to find out what the floating point + registers contain. + The actual file contents are as follows: + UPAGE: 1 page consisting of a user struct that tells gdb what is present + in the file. Directly after this is a copy of the task_struct, which + is currently not used by gdb, but it may come in useful at some point. + All of the registers are stored as part of the upage. The upage should + always be only one page. + DATA: The data area is stored. We use current->end_text to + current->brk to pick up all of the user variables, plus any memory + that may have been malloced. No attempt is made to determine if a page + is demand-zero or if a page is totally unused, we just cover the entire + range. All of the addresses are rounded in such a way that an integral + number of pages is written. + STACK: We need the stack information in order to get a meaningful + backtrace. We need to write the data from (esp) to + current->start_stack, so we round each of these off in order to be able + to write an integer number of pages. + The minimum core file size is 3 pages, or 12288 bytes. +*/ + +struct user_fp { + struct fp_reg { + unsigned int sign1:1; + unsigned int unused:15; + unsigned int sign2:1; + unsigned int exponent:14; + unsigned int j:1; + unsigned int mantissa1:31; + unsigned int mantissa0:32; + } fpregs[8]; + unsigned int fpsr:32; + unsigned int fpcr:32; +}; + +/* When the kernel dumps core, it starts by dumping the user struct - + this will be used by gdb to figure out where the data and stack segments + are within the file, and what virtual addresses to use. */ +struct user{ +/* We start with the registers, to mimic the way that "memory" is returned + from the ptrace(3,...) function. */ + struct pt_regs regs; /* Where the registers are actually stored */ +/* ptrace does not yet supply these. Someday.... */ + int u_fpvalid; /* True if math co-processor being used. */ + /* for this mess. Not yet used. */ +/* The rest of this junk is to help gdb figure out what goes where */ + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack area. + This is actually the bottom of the stack, + the top of the stack is always found in the + esp register. */ + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + struct pt_regs * u_ar0; /* Used by gdb to help find the values for */ + /* the registers. */ + unsigned long magic; /* To uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ + int u_debugreg[8]; + struct user_fp u_fp; /* FP state */ + struct user_fp_struct * u_fp0;/* Used by gdb to help find the values for */ + /* the FP registers. */ +}; +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _ARM_USER_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-arm/vt.h linux/include/asm-arm/vt.h --- v2.1.79/linux/include/asm-arm/vt.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/vt.h Tue Jan 20 16:39:43 1998 @@ -0,0 +1,8 @@ +#ifndef _ASMARM_VT_H +#define _ASMARM_VT_H + +#define VT_GETSCRINFO 0x56FD /* get screen info */ +#define VT_GETPALETTE 0x56FE /* get palette */ +#define VT_SETPALETTE 0x56FF /* set palette */ + +#endif /* _ASMARM_VT_H */ diff -u --recursive --new-file v2.1.79/linux/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h --- v2.1.79/linux/include/asm-i386/hardirq.h Tue May 13 22:41:17 1997 +++ linux/include/asm-i386/hardirq.h Tue Jan 20 12:52:08 1998 @@ -15,6 +15,7 @@ #define hardirq_exit(cpu) (local_irq_count[cpu]--) #define synchronize_irq() do { } while (0) +#define synchronize_one_irq(x) do { } while (0) #else @@ -69,6 +70,7 @@ } extern void synchronize_irq(void); +extern void synchronize_one_irq(unsigned int irq); #endif /* __SMP__ */ diff -u --recursive --new-file v2.1.79/linux/include/asm-i386/irq.h linux/include/asm-i386/irq.h --- v2.1.79/linux/include/asm-i386/irq.h Tue Dec 2 09:49:40 1997 +++ linux/include/asm-i386/irq.h Tue Jan 20 12:56:17 1998 @@ -4,12 +4,17 @@ /* * linux/include/asm/irq.h * - * (C) 1992, 1993 Linus Torvalds + * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar * - * IRQ/IPI changes taken from work by Thomas Radke + * IRQ/IPI changes taken from work by Thomas Radke + * */ +#ifndef __SMP__ #define NR_IRQS 16 +#else +#define NR_IRQS 24 +#endif #define TIMER_IRQ 0 diff -u --recursive --new-file v2.1.79/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- v2.1.79/linux/include/asm-i386/processor.h Mon Jan 12 22:09:18 1998 +++ linux/include/asm-i386/processor.h Thu Jan 15 20:47:55 1998 @@ -205,7 +205,7 @@ * NOTE! The task struct and the stack go together */ #define alloc_task_struct() \ - ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) #define free_task_struct(p) free_pages((unsigned long)(p),1) #define init_task (init_task_union.task) diff -u --recursive --new-file v2.1.79/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h --- v2.1.79/linux/include/asm-i386/softirq.h Thu Jun 12 15:28:33 1997 +++ linux/include/asm-i386/softirq.h Tue Jan 20 12:57:40 1998 @@ -33,6 +33,7 @@ { bh_mask &= ~(1 << nr); bh_mask_count[nr]++; + synchronize_irq(); } extern inline void enable_bh(int nr) diff -u --recursive --new-file v2.1.79/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h --- v2.1.79/linux/include/asm-i386/uaccess.h Mon Jan 12 22:09:18 1998 +++ linux/include/asm-i386/uaccess.h Tue Jan 20 16:51:57 1998 @@ -51,6 +51,7 @@ #define access_ok(type,addr,size) ( (__range_ok(addr,size) == 0) && \ ((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || \ + segment_eq(get_fs(),KERNEL_DS) || \ __verify_write((void *)(addr),(size)))) #endif /* CPU */ @@ -124,25 +125,108 @@ extern void __put_user_2(void); extern void __put_user_4(void); +extern void __put_user_bad(void); + #define __put_user_x(size,ret,x,ptr) \ __asm__ __volatile__("call __put_user_" #size \ :"=a" (ret) \ :"0" (ptr),"d" (x) \ :"cx") -#define put_user(x,ptr) \ -({ int __ret_pu; \ - switch(sizeof (*(ptr))) { \ - case 1: __put_user_x(1,__ret_pu,(char)(x),ptr); break; \ - case 2: __put_user_x(2,__ret_pu,(short)(x),ptr); break; \ - case 4: __put_user_x(4,__ret_pu,(int)(x),ptr); break; \ - default: __put_user_x(X,__ret_pu,x,ptr); break; \ +#define put_user(x,ptr) \ +({ int __ret_pu; \ + switch(sizeof (*(ptr))) { \ + case 1: __put_user_x(1,__ret_pu,(__typeof__(*(ptr)))(x),ptr); break; \ + case 2: __put_user_x(2,__ret_pu,(__typeof__(*(ptr)))(x),ptr); break; \ + case 4: __put_user_x(4,__ret_pu,(__typeof__(*(ptr)))(x),ptr); break; \ + default: __put_user_x(X,__ret_pu,x,ptr); break; \ + } \ + __ret_pu; \ +}) + +#define __get_user(x,ptr) \ + __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __put_user(x,ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) + +#define __put_user_nocheck(x,ptr,size) \ +({ \ + long __pu_err; \ + __put_user_size((x),(ptr),(size),__pu_err); \ + __pu_err; \ +}) + +#define __put_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break; \ + case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break; \ + case 4: __put_user_asm(x,ptr,retval,"l","","ir"); break; \ + default: __put_user_bad(); \ } \ - __ret_pu; \ +} while (0) + +struct __large_struct { unsigned long buf[100]; }; +#define __m(x) (*(struct __large_struct *)(x)) + +/* + * Tell gcc we read from memory instead of writing: this is because + * we do not write to any memory gcc knows about, so there are no + * aliasing issues. + */ +#define __put_user_asm(x, addr, err, itype, rtype, ltype) \ + __asm__ __volatile__( \ + "1: mov"itype" %"rtype"1,%2\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %3,%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,3b\n" \ + ".previous" \ + : "=r"(err) \ + : ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err)) + + +#define __get_user_nocheck(x,ptr,size) \ +({ \ + long __gu_err, __gu_val; \ + __get_user_size(__gu_val,(ptr),(size),__gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ }) -#define __get_user(x,ptr) get_user(x,ptr) -#define __put_user(x,ptr) put_user(x,ptr) +extern long __get_user_bad(void); + +#define __get_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break; \ + case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break; \ + case 4: __get_user_asm(x,ptr,retval,"l","","=r"); break; \ + default: (x) = __get_user_bad(); \ + } \ +} while (0) + +#define __get_user_asm(x, addr, err, itype, rtype, ltype) \ + __asm__ __volatile__( \ + "1: mov"itype" %2,%"rtype"1\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %3,%0\n" \ + " xor"itype" %"rtype"1,%"rtype"1\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,3b\n" \ + ".previous" \ + : "=r"(err), ltype (x) \ + : "m"(__m(addr)), "i"(-EFAULT), "0"(err)) /* * The "xxx_ret" versions return constant specified in third argument, if diff -u --recursive --new-file v2.1.79/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h --- v2.1.79/linux/include/asm-m68k/processor.h Sat May 24 09:10:24 1997 +++ linux/include/asm-m68k/processor.h Fri Jan 16 20:37:01 1998 @@ -94,7 +94,7 @@ /* Allocation and freeing of basic task resources. */ #define alloc_task_struct() \ - ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) #define free_task_struct(p) free_pages((unsigned long)(p),1) #define init_task (init_task_union.task) diff -u --recursive --new-file v2.1.79/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h --- v2.1.79/linux/include/asm-mips/processor.h Fri Dec 19 15:53:04 1997 +++ linux/include/asm-mips/processor.h Fri Jan 16 20:32:53 1998 @@ -183,7 +183,7 @@ * NOTE! The task struct and the stack go together */ #define alloc_task_struct() \ - ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) #define free_task_struct(p) free_pages((unsigned long)(p),1) #define init_task (init_task_union.task) diff -u --recursive --new-file v2.1.79/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h --- v2.1.79/linux/include/asm-ppc/processor.h Mon Jan 12 22:09:19 1998 +++ linux/include/asm-ppc/processor.h Fri Jan 16 20:36:39 1998 @@ -245,7 +245,7 @@ * NOTE! The task struct and the stack go together */ #define alloc_task_struct() \ - ((struct task_struct *) __get_free_pages(GFP_KERNEL,1,0)) + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) #define free_task_struct(p) free_pages((unsigned long)(p),1) /* in process.c - for early bootup debug -- Cort */ diff -u --recursive --new-file v2.1.79/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h --- v2.1.79/linux/include/asm-sparc64/processor.h Mon Jan 12 22:09:22 1998 +++ linux/include/asm-sparc64/processor.h Fri Jan 16 20:36:17 1998 @@ -204,7 +204,7 @@ #ifdef __KERNEL__ /* Allocation and freeing of task_struct and kernel stack. */ -#define alloc_task_struct() ((struct task_struct *)__get_free_pages(GFP_KERNEL, 1, 0)) +#define alloc_task_struct() ((struct task_struct *)__get_free_pages(GFP_KERNEL, 1)) #define free_task_struct(tsk) free_pages((unsigned long)(tsk),1) #define init_task (init_task_union.task) diff -u --recursive --new-file v2.1.79/linux/include/linux/adfs_fs.h linux/include/linux/adfs_fs.h --- v2.1.79/linux/include/linux/adfs_fs.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/adfs_fs.h Tue Jan 20 16:44:58 1998 @@ -0,0 +1,183 @@ +#ifndef _ADFS_FS_H +#define _ADFS_FS_H + +#include +/* + * Structures of data on the disk + */ + +/* + * Disc Record at disc address 0xc00 + */ +struct adfs_discrecord { + unsigned char log2secsize; + unsigned char secspertrack; + unsigned char heads; + unsigned char density; + unsigned char idlen; + unsigned char log2bpmb; + unsigned char skew; + unsigned char bootoption; + unsigned char lowsector; + unsigned char nzones; + unsigned short zone_spare; + unsigned long root; + unsigned long disc_size; + unsigned short disc_id; + unsigned char disc_name[10]; + unsigned long disc_type; + unsigned long disc_size_high; + unsigned char log2sharesize:4; + unsigned char unused:4; + unsigned char big_flag:1; +}; + +#define ADFS_DISCRECORD (0xc00) +#define ADFS_DR_OFFSET (0x1c0) +#define ADFS_DR_SIZE 60 +#define ADFS_SUPER_MAGIC 0xadf5 +#define ADFS_FREE_FRAG 0 +#define ADFS_BAD_FRAG 1 +#define ADFS_ROOT_FRAG 2 + +/* + * Directory header + */ +struct adfs_dirheader { + unsigned char startmasseq; + unsigned char startname[4]; +}; + +#define ADFS_NEWDIR_SIZE 2048 +#define ADFS_OLDDIR_SIZE 1024 +#define ADFS_NUM_DIR_ENTRIES 77 + +/* + * Directory entries + */ +struct adfs_direntry { + char dirobname[10]; +#define ADFS_NAME_LEN 10 + __u8 dirload[4]; + __u8 direxec[4]; + __u8 dirlen[4]; + __u8 dirinddiscadd[3]; + __u8 newdiratts; +#define ADFS_NDA_OWNER_READ (1 << 0) +#define ADFS_NDA_OWNER_WRITE (1 << 1) +#define ADFS_NDA_LOCKED (1 << 2) +#define ADFS_NDA_DIRECTORY (1 << 3) +#define ADFS_NDA_EXECUTE (1 << 4) +#define ADFS_NDA_PUBLIC_READ (1 << 5) +#define ADFS_NDA_PUBLIC_WRITE (1 << 6) +}; + +#define ADFS_MAX_NAME_LEN 255 +struct adfs_idir_entry { + __u32 inode_no; /* Address */ + __u32 file_id; /* file id */ + __u32 name_len; /* name length */ + __u32 size; /* size */ + __u32 mtime; /* modification time */ + __u32 filetype; /* RiscOS file type */ + __u8 mode; /* internal mode */ + char name[ADFS_MAX_NAME_LEN]; /* file name */ +}; + +/* + * Directory tail + */ +union adfs_dirtail { + struct { + unsigned char dirlastmask; + char dirname[10]; + unsigned char dirparent[3]; + char dirtitle[19]; + unsigned char reserved[14]; + unsigned char endmasseq; + unsigned char endname[4]; + unsigned char dircheckbyte; + } old; + struct { + unsigned char dirlastmask; + unsigned char reserved[2]; + unsigned char dirparent[3]; + char dirtitle[19]; + char dirname[10]; + unsigned char endmasseq; + unsigned char endname[4]; + unsigned char dircheckbyte; + } new; +}; + +#ifdef __KERNEL__ + + +/* + * Calculate the boot block checksum on an ADFS drive. Note that this will + * appear to be correct if the sector contains all zeros, so also check that + * the disk size is non-zero!!! + */ + +extern inline int adfs_checkbblk(unsigned char *ptr) +{ + int i = 511; + + int result = 0; + + do { + result = (result & 0xff) + (result >> 8); + result = result + ptr[i]; + i--; + } + while (i != 0); + + result &= 0xff; + return result != ptr[511]; + return 0; +} + +/* dir.c */ +extern unsigned int adfs_val (unsigned char *p, int len); +extern int adfs_dir_read_parent (struct inode *inode, struct buffer_head **bhp); +extern int adfs_dir_read (struct inode *inode, struct buffer_head **bhp); +extern int adfs_dir_check (struct inode *inode, struct buffer_head **bhp, + int buffers, union adfs_dirtail *dtp); +extern void adfs_dir_free (struct buffer_head **bhp, int buffers); +extern int adfs_dir_get (struct super_block *sb, struct buffer_head **bhp, + int buffers, int pos, unsigned long parent_object_id, + struct adfs_idir_entry *ide); +extern int adfs_dir_find_entry (struct super_block *sb, struct buffer_head **bhp, + int buffers, unsigned int index, + struct adfs_idir_entry *ide); + +/* inode.c */ +extern int adfs_inode_validate (struct inode *inode); +extern unsigned long adfs_inode_generate (unsigned long parent_id, int diridx); +extern unsigned long adfs_inode_objid (struct inode *inode); +extern unsigned int adfs_parent_bmap (struct inode *inode, int block); +extern unsigned int adfs_bmap (struct inode *inode, int block); +extern void adfs_read_inode (struct inode *inode); + +/* map.c */ +extern int adfs_map_lookup (struct super_block *sb, int frag_id, int offset); + +/* namei.c */ +extern int adfs_lookup (struct inode *dir, struct dentry *dentry); + +/* super.c */ +extern int init_adfs_fs (void); +extern void adfs_error (struct super_block *, const char *, const char *, ...); + +/* + * Inodes and file operations + */ + +/* dir.c */ +extern struct inode_operations adfs_dir_inode_operations; + +/* file.c */ +extern struct inode_operations adfs_file_inode_operations; +#endif + +#endif diff -u --recursive --new-file v2.1.79/linux/include/linux/adfs_fs_fs.h linux/include/linux/adfs_fs_fs.h --- v2.1.79/linux/include/linux/adfs_fs_fs.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/adfs_fs_fs.h Tue Jan 20 16:44:58 1998 @@ -0,0 +1,177 @@ +#ifndef _ADFS_FS_H +#define _ADFS_FS_H + +#include +/* + * Structures of data on the disk + */ + +/* + * Disc Record at disc address 0xc00 + */ +struct adfs_discrecord { + unsigned char log2secsize; + unsigned char secspertrack; + unsigned char heads; + unsigned char density; + unsigned char idlen; + unsigned char log2bpmb; + unsigned char skew; + unsigned char bootoption; + unsigned char lowsector; + unsigned char nzones; + unsigned short zone_spare; + unsigned long root; + unsigned long disc_size; + unsigned short disc_id; + unsigned char disc_name[10]; + unsigned long disc_type; + unsigned long disc_size_high; + unsigned char log2sharesize:4; + unsigned char unused:4; + unsigned char big_flag:1; +}; + +#define ADFS_DISCRECORD (0xc00) +#define ADFS_DR_OFFSET (0x1c0) +#define ADFS_DR_SIZE 60 +#define ADFS_SUPER_MAGIC 0xadf5 +#define ADFS_FREE_FRAG 0 +#define ADFS_BAD_FRAG 1 +#define ADFS_ROOT_FRAG 2 + +/* + * Directory header + */ +struct adfs_dirheader { + unsigned char startmasseq; + unsigned char startname[4]; +}; + +#define ADFS_NEWDIR_SIZE 2048 +#define ADFS_OLDDIR_SIZE 1024 +#define ADFS_NUM_DIR_ENTRIES 77 + +/* + * Directory entries + */ +struct adfs_direntry { + char dirobname[10]; +#define ADFS_NAME_LEN 10 + __u8 dirload[4]; + __u8 direxec[4]; + __u8 dirlen[4]; + __u8 dirinddiscadd[3]; + __u8 newdiratts; +#define ADFS_NDA_OWNER_READ (1 << 0) +#define ADFS_NDA_OWNER_WRITE (1 << 1) +#define ADFS_NDA_LOCKED (1 << 2) +#define ADFS_NDA_DIRECTORY (1 << 3) +#define ADFS_NDA_EXECUTE (1 << 4) +#define ADFS_NDA_PUBLIC_READ (1 << 5) +#define ADFS_NDA_PUBLIC_WRITE (1 << 6) +}; + +#define ADFS_MAX_NAME_LEN 255 +struct adfs_idir_entry { + __u32 inode_no; /* Address */ + __u32 file_id; /* file id */ + __u32 name_len; /* name length */ + __u32 size; /* size */ + __u32 mtime; /* modification time */ + __u32 filetype; /* RiscOS file type */ + __u8 mode; /* internal mode */ + char name[ADFS_MAX_NAME_LEN]; /* file name */ +}; + +/* + * Directory tail + */ +union adfs_dirtail { + struct { + unsigned char dirlastmask; + char dirname[10]; + unsigned char dirparent[3]; + char dirtitle[19]; + unsigned char reserved[14]; + unsigned char endmasseq; + unsigned char endname[4]; + unsigned char dircheckbyte; + } old; + struct { + unsigned char dirlastmask; + unsigned char reserved[2]; + unsigned char dirparent[3]; + char dirtitle[19]; + char dirname[10]; + unsigned char endmasseq; + unsigned char endname[4]; + unsigned char dircheckbyte; + } new; +}; + +#ifdef __KERNEL__ +/* + * Calculate the boot block checksum on an ADFS drive. Note that this will + * appear to be correct if the sector contains all zeros, so also check that + * the disk size is non-zero!!! + */ +extern inline int adfs_checkbblk (unsigned char *ptr) +{ + unsigned int result = 0; + unsigned char *p = ptr + 511; + + do { + result = (result & 0xff) + (result >> 8); + result = result + *--p; + } while (p != ptr); + + return (result & 0xff) != ptr[511]; +} + +/* dir.c */ +extern unsigned int adfs_val (unsigned char *p, int len); +extern int adfs_dir_read_parent (struct inode *inode, struct buffer_head **bhp); +extern int adfs_dir_read (struct inode *inode, struct buffer_head **bhp); +extern int adfs_dir_check (struct inode *inode, struct buffer_head **bhp, + int buffers, union adfs_dirtail *dtp); +extern void adfs_dir_free (struct buffer_head **bhp, int buffers); +extern int adfs_dir_get (struct super_block *sb, struct buffer_head **bhp, + int buffers, int pos, unsigned long parent_object_id, + struct adfs_idir_entry *ide); +extern int adfs_dir_find_entry (struct super_block *sb, struct buffer_head **bhp, + int buffers, unsigned int index, + struct adfs_idir_entry *ide); + +/* inode.c */ +extern int adfs_inode_validate (struct inode *inode); +extern unsigned long adfs_inode_generate (unsigned long parent_id, int diridx); +extern unsigned long adfs_inode_objid (struct inode *inode); +extern unsigned int adfs_parent_bmap (struct inode *inode, int block); +extern unsigned int adfs_bmap (struct inode *inode, int block); +extern void adfs_read_inode (struct inode *inode); + +/* map.c */ +extern int adfs_map_lookup (struct super_block *sb, int frag_id, int offset); + +/* namei.c */ +extern int adfs_lookup (struct inode * dir, const char * name, int len, + struct inode ** result); + +/* super.c */ +extern int init_adfs_fs (void); +extern void adfs_error (struct super_block *, const char *, const char *, ...); + +/* + * Inodes and file operations + */ + +/* dir.c */ +extern struct inode_operations adfs_dir_inode_operations; + +/* file.c */ +extern struct inode_operations adfs_file_inode_operations; +#endif + +#endif + diff -u --recursive --new-file v2.1.79/linux/include/linux/adfs_fs_i.h linux/include/linux/adfs_fs_i.h --- v2.1.79/linux/include/linux/adfs_fs_i.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/adfs_fs_i.h Tue Jan 20 16:44:58 1998 @@ -0,0 +1,17 @@ +/* + * linux/include/linux/adfs_fs_i.h + * + * Copyright (C) 1997 Russell King + */ + +#ifndef _ADFS_FS_I +#define _ADFS_FS_I + +/* + * adfs file system inode data in memory + */ +struct adfs_inode_info { + unsigned long file_id; /* id of fragments containing actual data */ +}; + +#endif diff -u --recursive --new-file v2.1.79/linux/include/linux/adfs_fs_sb.h linux/include/linux/adfs_fs_sb.h --- v2.1.79/linux/include/linux/adfs_fs_sb.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/adfs_fs_sb.h Tue Jan 20 16:44:58 1998 @@ -0,0 +1,29 @@ +/* + * linux/include/linux/adfs_fs_sb.h + * + * Copyright (C) 1997 Russell King + */ + +#ifndef _ADFS_FS_SB +#define _ADFS_FS_SB + +#include + +/* + * adfs file system superblock data in memory + */ +struct adfs_sb_info { + struct buffer_head *s_sbh; /* buffer head containing disc record */ + struct adfs_discrecord *s_dr; /* pointer to disc record in s_sbh */ + __u16 s_zone_size; /* size of a map zone in bits */ + __u16 s_ids_per_zone; /* max. no ids in one zone */ + __u32 s_idlen; /* length of ID in map */ + __u32 s_map_size; /* size of a map */ + __u32 s_zonesize; /* zone size (in map bits) */ + __u32 s_map_block; /* block address of map */ + struct buffer_head **s_map; /* bh list containing map */ + __u32 s_root; /* root disc address */ + __s8 s_map2blk; /* shift left by this for map->sector */ +}; + +#endif diff -u --recursive --new-file v2.1.79/linux/include/linux/console.h linux/include/linux/console.h --- v2.1.79/linux/include/linux/console.h Wed Dec 10 11:12:46 1997 +++ linux/include/linux/console.h Tue Jan 20 16:44:58 1998 @@ -99,6 +99,7 @@ }; extern void register_console(struct console *); +extern int unregister_console(struct console *); extern struct console *console_drivers; #endif /* linux/console.h */ diff -u --recursive --new-file v2.1.79/linux/include/linux/dcache.h linux/include/linux/dcache.h --- v2.1.79/linux/include/linux/dcache.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/dcache.h Wed Jan 14 16:57:09 1998 @@ -61,6 +61,7 @@ struct list_head d_lru; /* d_count = 0 LRU list */ struct list_head d_child; /* child of parent list */ struct list_head d_subdirs; /* our children */ + struct list_head d_alias; /* inode alias list */ struct qstr d_name; unsigned long d_time; /* used by d_revalidate */ struct dentry_operations *d_op; @@ -74,8 +75,8 @@ int (*d_hash) (struct dentry *, struct qstr *); int (*d_compare) (struct dentry *, struct qstr *, struct qstr *); void (*d_delete)(struct dentry *); - void (*d_iput)(struct dentry *, struct inode *); void (*d_release)(struct dentry *); + void (*d_iput)(struct dentry *, struct inode *); }; /* the dentry parameter passed to d_hash and d_compare is the parent diff -u --recursive --new-file v2.1.79/linux/include/linux/fd.h linux/include/linux/fd.h --- v2.1.79/linux/include/linux/fd.h Sun Sep 7 13:10:43 1997 +++ linux/include/linux/fd.h Tue Jan 20 16:44:58 1998 @@ -116,7 +116,7 @@ * Drive parameters (user modifiable) */ struct floppy_drive_params { - char cmos; /* cmos type */ + signed char cmos; /* cmos type */ /* Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms * etc) and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA). diff -u --recursive --new-file v2.1.79/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.79/linux/include/linux/fs.h Tue Jan 6 09:37:38 1998 +++ linux/include/linux/fs.h Tue Jan 20 16:51:56 1998 @@ -267,6 +267,7 @@ #include #include #include +#include /* * Attribute flags. These should be or-ed together to figure out what @@ -318,10 +319,11 @@ struct inode { struct list_head i_hash; struct list_head i_list; + struct list_head i_dentry; unsigned long i_ino; + unsigned int i_count; kdev_t i_dev; - unsigned short i_count; umode_t i_mode; nlink_t i_nlink; uid_t i_uid; @@ -368,6 +370,7 @@ struct romfs_inode_info romfs_i; struct smb_inode_info smbfs_i; struct hfs_inode_info hfs_i; + struct adfs_inode_info adfs_i; struct socket socket_i; void *generic_ip; } u; @@ -506,6 +509,7 @@ #include #include #include +#include struct super_block { kdev_t s_dev; @@ -542,6 +546,7 @@ struct romfs_sb_info romfs_sb; struct smb_sb_info smbfs_sb; struct hfs_sb_info hfs_sb; + struct adfs_sb_info adfs_sb; void *generic_sbp; } u; }; @@ -774,6 +779,7 @@ extern struct inode * get_empty_inode(void); extern void insert_inode_hash(struct inode *); +extern void remove_inode_hash(struct inode *); extern int get_unused_fd(void); extern void put_unused_fd(int); extern struct file * get_empty_filp(void); diff -u --recursive --new-file v2.1.79/linux/include/linux/ip.h linux/include/linux/ip.h --- v2.1.79/linux/include/linux/ip.h Mon Jul 7 16:04:02 1997 +++ linux/include/linux/ip.h Tue Jan 20 16:53:59 1998 @@ -124,6 +124,10 @@ unsigned char __data[0]; }; +#ifdef __KERNEL__ +#define optlength(opt) (sizeof(struct ip_options) + opt->optlen) +#endif + struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD) __u8 ihl:4, diff -u --recursive --new-file v2.1.79/linux/include/linux/kernel_stat.h linux/include/linux/kernel_stat.h --- v2.1.79/linux/include/linux/kernel_stat.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/kernel_stat.h Tue Jan 20 12:57:40 1998 @@ -2,6 +2,7 @@ #define _LINUX_KERNEL_STAT_H #include +#include #include /* @@ -24,7 +25,7 @@ unsigned int dk_drive_wblk[DK_NDRIVE]; unsigned int pgpgin, pgpgout; unsigned int pswpin, pswpout; - unsigned int interrupts[NR_IRQS]; + unsigned int interrupts[NR_CPUS][NR_IRQS]; unsigned int ipackets, opackets; unsigned int ierrors, oerrors; unsigned int collisions; diff -u --recursive --new-file v2.1.79/linux/include/linux/linkage.h linux/include/linux/linkage.h --- v2.1.79/linux/include/linux/linkage.h Mon Jun 16 16:36:00 1997 +++ linux/include/linux/linkage.h Tue Jan 20 16:45:03 1998 @@ -15,6 +15,10 @@ #define SYMBOL_NAME_LABEL(X) X/**/: #endif +#ifdef __arm__ +#define __ALIGN .align 0 +#define __ALIGN_STR ".align 0" +#else #ifdef __mc68000__ #define __ALIGN .align 4 #define __ALIGN_STR ".align 4" @@ -27,6 +31,7 @@ #define __ALIGN_STR ".align 16,0x90" #endif /* __i486__/__i586__ */ #endif /* __mc68000__ */ +#endif /* __arm__ */ #ifdef __ASSEMBLY__ diff -u --recursive --new-file v2.1.79/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.1.79/linux/include/linux/mm.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/mm.h Tue Jan 20 16:51:56 1998 @@ -237,15 +237,15 @@ * goes to clearing the page. If you want a page without the clearing * overhead, just use __get_free_page() directly.. */ -#define __get_free_page(priority) __get_free_pages((priority),0,0) -#define __get_dma_pages(priority, order) __get_free_pages((priority),(order),1) -extern unsigned long FASTCALL(__get_free_pages(int priority, unsigned long gfporder, int dma)); +#define __get_free_page(gfp_mask) __get_free_pages((gfp_mask),0) +#define __get_dma_pages(gfp_mask, order) __get_free_pages((gfp_mask) | GFP_DMA,(order)) +extern unsigned long FASTCALL(__get_free_pages(int gfp_mask, unsigned long gfp_order)); -extern inline unsigned long get_free_page(int priority) +extern inline unsigned long get_free_page(int gfp_mask) { unsigned long page; - page = __get_free_page(priority); + page = __get_free_page(gfp_mask); if (page) clear_page(page); return page; @@ -297,19 +297,27 @@ extern unsigned long get_cached_page(struct inode *, unsigned long, int); extern void put_cached_page(unsigned long); -#define GFP_BUFFER 0x00 -#define GFP_ATOMIC 0x01 -#define GFP_USER 0x02 -#define GFP_KERNEL 0x03 -#define GFP_NOBUFFER 0x04 -#define GFP_NFS 0x05 +/* + * GFP bitmasks.. + */ +#define __GFP_WAIT 0x01 +#define __GFP_IO 0x02 +#define __GFP_LOW 0x00 +#define __GFP_MED 0x04 +#define __GFP_HIGH 0x08 + +#define __GFP_DMA 0x80 + +#define GFP_BUFFER (__GFP_LOW | __GFP_WAIT) +#define GFP_ATOMIC (__GFP_HIGH) +#define GFP_USER (__GFP_LOW | __GFP_WAIT | __GFP_IO) +#define GFP_KERNEL (__GFP_LOW | __GFP_WAIT | __GFP_IO) +#define GFP_NFS (__GFP_MED | __GFP_WAIT | __GFP_IO) /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */ -#define GFP_DMA 0x80 - -#define GFP_LEVEL_MASK 0xf +#define GFP_DMA __GFP_DMA /* vma is the first one with address < vma->vm_end, * and even address < vma->vm_start. Have to extend vma. */ diff -u --recursive --new-file v2.1.79/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h --- v2.1.79/linux/include/linux/msdos_fs.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/msdos_fs.h Tue Jan 20 16:53:52 1998 @@ -163,7 +163,6 @@ struct vfat_slot_info { int is_long; /* was the found entry long */ - int is_alias; /* was the found entry an alias */ int long_slots; /* number of long slots in filename */ int total_slots; /* total slots (long and short) */ loff_t longname_offset; /* dir offset for longname start */ @@ -219,10 +218,10 @@ extern int fat_free(struct inode *inode,int skip); void fat_cache_inval_inode(struct inode *inode); void fat_cache_inval_dev(kdev_t device); -extern void cache_init(void); -void cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu); -void cache_add(struct inode *inode,int f_clu,int d_clu); -int get_cluster(struct inode *inode,int cluster); +extern void fat_cache_init(void); +void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu); +void fat_cache_add(struct inode *inode,int f_clu,int d_clu); +int fat_get_cluster(struct inode *inode,int cluster); /* inode.c */ extern int fat_bmap(struct inode *inode,int block); @@ -256,7 +255,7 @@ /* mmap.c */ extern int fat_mmap(struct file *, struct vm_area_struct *); -extern int fat_readpage(struct inode *, struct page *); +extern int fat_readpage(struct dentry *, struct page *); /* vfat.c */ diff -u --recursive --new-file v2.1.79/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h --- v2.1.79/linux/include/linux/nfs_fs.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/nfs_fs.h Tue Jan 20 16:52:02 1998 @@ -118,7 +118,8 @@ #define NFS_WRITE_CANCELLED 0x0004 /* has been cancelled */ #define NFS_WRITE_UNCOMMITTED 0x0008 /* written but uncommitted (NFSv3) */ #define NFS_WRITE_INVALIDATE 0x0010 /* invalidate after write */ -#define NFS_WRITE_INPROGRESS 0x0020 /* RPC call in progress */ +#define NFS_WRITE_INPROGRESS 0x0100 /* RPC call in progress */ +#define NFS_WRITE_COMPLETE 0x0200 /* RPC call completed */ #define WB_WANTLOCK(req) ((req)->wb_flags & NFS_WRITE_WANTLOCK) #define WB_HAVELOCK(req) ((req)->wb_flags & NFS_WRITE_LOCKED) @@ -126,6 +127,7 @@ #define WB_UNCOMMITTED(req) ((req)->wb_flags & NFS_WRITE_UNCOMMITTED) #define WB_INVALIDATE(req) ((req)->wb_flags & NFS_WRITE_INVALIDATE) #define WB_INPROGRESS(req) ((req)->wb_flags & NFS_WRITE_INPROGRESS) +#define WB_COMPLETE(req) ((req)->wb_flags & NFS_WRITE_COMPLETE) /* * linux/fs/nfs/proc.c diff -u --recursive --new-file v2.1.79/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.79/linux/include/linux/proc_fs.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/proc_fs.h Tue Jan 20 16:51:57 1998 @@ -36,9 +36,6 @@ PROC_KSYMS, PROC_DMA, PROC_IOPORTS, -#ifdef __SMP_PROF__ - PROC_SMP_PROF, -#endif PROC_PROFILE, /* whether enabled or not */ PROC_CMDLINE, PROC_SYS, diff -u --recursive --new-file v2.1.79/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.1.79/linux/include/linux/sched.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/sched.h Tue Jan 20 16:51:56 1998 @@ -140,10 +140,13 @@ NULL, NULL \ } +/* Maximum number of active map areas.. This is a random (large) number */ +#define MAX_MAP_COUNT (65536) + struct mm_struct { struct vm_area_struct *mmap, *mmap_cache; pgd_t * pgd; - int count; + int count, map_count; struct semaphore mmap_sem; unsigned long context; unsigned long start_code, end_code, start_data, end_data; @@ -155,7 +158,7 @@ }; #define INIT_MM { \ - &init_mmap, NULL, swapper_pg_dir, 1, \ + &init_mmap, NULL, swapper_pg_dir, 1, 1, \ MUTEX, \ 0, \ 0, 0, 0, 0, \ diff -u --recursive --new-file v2.1.79/linux/include/linux/skbuff.h linux/include/linux/skbuff.h --- v2.1.79/linux/include/linux/skbuff.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/skbuff.h Tue Jan 20 16:51:57 1998 @@ -78,7 +78,12 @@ } mac; struct dst_entry *dst; + +#if (defined(__alpha__) || defined(__sparc64__)) && (defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) + char cb[48]; /* sorry. 64bit pointers have a price */ +#else char cb[32]; +#endif __u32 seq; /* TCP sequence number */ __u32 end_seq; /* seq [+ fin] [+ syn] + datalen */ @@ -217,6 +222,14 @@ return list; } +extern __inline__ struct sk_buff *skb_peek_tail(struct sk_buff_head *list_) +{ + struct sk_buff *list = ((struct sk_buff *)list_)->prev; + if (list == (struct sk_buff *)list_) + list = NULL; + return list; +} + /* * Return the length of an sk_buff queue */ @@ -406,6 +419,28 @@ __skb_unlink(skb, skb->list); restore_flags(flags); } + +/* XXX: more streamlined implementation */ +extern __inline__ struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list) +{ + struct sk_buff *skb = skb_peek_tail(list); + if (skb) + __skb_unlink(skb, list); + return skb; +} + +extern __inline__ struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list) +{ + long flags; + struct sk_buff *result; + + save_flags(flags); + cli(); + result = __skb_dequeue_tail(list); + restore_flags(flags); + return result; +} + extern const char skb_put_errstr[]; extern const char skb_push_errstr[]; diff -u --recursive --new-file v2.1.79/linux/include/linux/slab.h linux/include/linux/slab.h --- v2.1.79/linux/include/linux/slab.h Thu Jul 17 10:06:08 1997 +++ linux/include/linux/slab.h Tue Jan 20 16:51:56 1998 @@ -15,14 +15,14 @@ #include /* flags for kmem_cache_alloc() */ -#define SLAB_BUFFER GFP_BUFFER /* 0x00 */ -#define SLAB_ATOMIC GFP_ATOMIC /* 0x01 */ -#define SLAB_USER GFP_USER /* 0x02 */ -#define SLAB_KERNEL GFP_KERNEL /* 0x03 */ -#define SLAB_NOBUFFER GFP_NOBUFFER /* 0x04 */ -#define SLAB_NFS GFP_NFS /* 0x05 */ -#define SLAB_DMA GFP_DMA /* 0x08 */ -#define SLAB_LEVEL_MASK GFP_LEVEL_MASK /* 0x0f */ +#define SLAB_BUFFER GFP_BUFFER +#define SLAB_ATOMIC GFP_ATOMIC +#define SLAB_USER GFP_USER +#define SLAB_KERNEL GFP_KERNEL +#define SLAB_NFS GFP_NFS +#define SLAB_DMA GFP_DMA + +#define SLAB_LEVEL_MASK 0x0000007fUL #define SLAB_NO_GROW 0x00001000UL /* don't grow a cache */ /* flags to pass to kmem_cache_create(). @@ -59,7 +59,7 @@ extern void kfree(const void *); extern void kfree_s(const void *, size_t); -extern int kmem_cache_reap(int, int, int); +extern void kmem_cache_reap(int); extern int get_slabinfo(char *); /* System wide caches */ diff -u --recursive --new-file v2.1.79/linux/include/linux/smp.h linux/include/linux/smp.h --- v2.1.79/linux/include/linux/smp.h Tue May 13 22:41:19 1997 +++ linux/include/linux/smp.h Tue Jan 20 12:52:08 1998 @@ -8,36 +8,46 @@ #ifdef __SMP__ #include - + +/* + * main IPI interface, handles INIT, TLB flush, STOP, etc.: + */ extern void smp_message_pass(int target, int msg, unsigned long data, int wait); -extern void smp_boot_cpus(void); /* Boot processor call to load the other CPU's */ -extern void smp_callin(void); /* Processor call in. Must hold processors until .. */ -extern void smp_commence(void); /* Multiprocessors may now schedule */ -extern int smp_num_cpus; -extern int smp_threads_ready; /* True once the per process idle is forked */ -#ifdef __SMP_PROF__ -extern volatile unsigned long smp_spins[NR_CPUS]; /* count of interrupt spins */ -extern volatile unsigned long smp_spins_sys_idle[]; /* count of idle spins */ -extern volatile unsigned long smp_spins_syscall[]; /* count of syscall spins */ -extern volatile unsigned long smp_spins_syscall_cur[]; /* count of syscall spins for the current - call */ -extern volatile unsigned long smp_idle_count[1+NR_CPUS];/* count idle ticks */ -extern volatile unsigned long smp_idle_map; /* map with idle cpus */ -#else -extern volatile unsigned long smp_spins; -#endif +/* + * Boot processor call to load the other CPU's + */ +extern void smp_boot_cpus(void); + +/* + * Processor call in. Must hold processors until .. + */ +extern void smp_callin(void); + +/* + * Multiprocessors may now schedule + */ +extern void smp_commence(void); + +/* + * True once the per process idle is forked + */ +extern int smp_threads_ready; + +extern int smp_num_cpus; extern volatile unsigned long smp_msg_data; extern volatile int smp_src_cpu; extern volatile int smp_msg_id; -#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */ +#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */ #define MSG_ALL 0x8001 -#define MSG_INVALIDATE_TLB 0x0001 /* Remote processor TLB invalidate */ -#define MSG_STOP_CPU 0x0002 /* Sent to shut down slave CPU's when rebooting */ -#define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU */ +#define MSG_INVALIDATE_TLB 0x0001 /* Remote processor TLB invalidate */ +#define MSG_STOP_CPU 0x0002 /* Sent to shut down slave CPU's + * when rebooting + */ +#define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU */ #else diff -u --recursive --new-file v2.1.79/linux/include/linux/swap.h linux/include/linux/swap.h --- v2.1.79/linux/include/linux/swap.h Mon Jan 12 22:09:23 1998 +++ linux/include/linux/swap.h Thu Jan 15 20:13:21 1998 @@ -49,7 +49,7 @@ extern int shm_swap (int, int); /* linux/mm/vmscan.c */ -extern int try_to_free_page(int, int, int); +extern int try_to_free_page(int); /* linux/mm/page_io.c */ extern void rw_swap_page(int, unsigned long, char *, int); diff -u --recursive --new-file v2.1.79/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.1.79/linux/include/net/tcp.h Fri Dec 19 15:53:05 1997 +++ linux/include/net/tcp.h Tue Jan 20 16:54:01 1998 @@ -132,6 +132,7 @@ #define BASE_ACK_SIZE (NETHDR_SIZE + MAX_HEADER + 15) #define MAX_ACK_SIZE (NETHDR_SIZE + sizeof(struct tcphdr) + MAX_HEADER + 15) #define MAX_RESET_SIZE (NETHDR_SIZE + sizeof(struct tcphdr) + MAX_HEADER + 15) +#define MAX_TCPHEADER_SIZE (NETHDR_SIZE + sizeof(struct tcphdr) + 20 + MAX_HEADER + 15) #define MAX_WINDOW 32767 /* Never offer a window over 32767 without using window scaling (not yet supported). Some poor @@ -435,7 +436,6 @@ struct sockaddr *uaddr, int addr_len); - /* From syncookies.c */ extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt); @@ -455,7 +455,7 @@ extern void tcp_write_wakeup(struct sock *); extern void tcp_send_fin(struct sock *sk); extern int tcp_send_synack(struct sock *); -extern int tcp_send_skb(struct sock *, struct sk_buff *); +extern void tcp_send_skb(struct sock *, struct sk_buff *); extern void tcp_send_ack(struct sock *sk); extern void tcp_send_delayed_ack(struct sock *sk, int max_timeout); @@ -585,6 +585,57 @@ if (state == TCP_TIME_WAIT || state == TCP_CLOSE) sk->prot->rehash(sk); } +} + +static __inline__ void tcp_build_options(__u32 *ptr, struct tcp_opt *tp) +{ + /* FIXME: We will still need to do SACK here. */ + if (tp->tstamp_ok) { + *ptr = ntohl((TCPOPT_NOP << 24) + | (TCPOPT_NOP << 16) + | (TCPOPT_TIMESTAMP << 8) + | TCPOLEN_TIMESTAMP); + /* rest filled in by tcp_update_options */ + } +} + +static __inline__ void tcp_update_options(__u32 *ptr, struct tcp_opt *tp) +{ + /* FIXME: We will still need to do SACK here. */ + if (tp->tstamp_ok) { + *++ptr = htonl(jiffies); + *++ptr = htonl(tp->ts_recent); + } +} + +/* + * This routines builds a generic TCP header. + * They also build the RFC1323 Timestamp, but don't fill the + * actual timestamp in (you need to call tcp_update_options for this). + * It can't (unfortunately) do SACK as well. + * XXX: pass tp instead of sk here. + */ + +static inline void tcp_build_header_data(struct tcphdr *th, struct sock *sk, int push) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + + memcpy(th,(void *) &(sk->dummy_th), sizeof(*th)); + th->seq = htonl(sk->write_seq); + if (!push) + th->psh = 1; + tcp_build_options((__u32*)(th+1), tp); +} + +static inline void tcp_build_header(struct tcphdr *th, struct sock *sk) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + + memcpy(th,(void *) &(sk->dummy_th), sizeof(*th)); + th->seq = htonl(sk->write_seq); + th->ack_seq = htonl(tp->last_ack_sent = tp->rcv_nxt); + th->window = htons(tcp_select_window(sk)); + tcp_build_options((__u32 *)(th+1), tp); } /* diff -u --recursive --new-file v2.1.79/linux/init/main.c linux/init/main.c --- v2.1.79/linux/init/main.c Tue Jan 6 09:37:38 1998 +++ linux/init/main.c Tue Jan 20 12:52:08 1998 @@ -76,6 +76,7 @@ extern void dquot_init(void); extern void smp_setup(char *str, int *ints); +extern void ioapic_pirq_setup(char *str, int *ints); extern void no_scroll(char *str, int *ints); extern void swap_setup(char *str, int *ints); extern void buff_setup(char *str, int *ints); @@ -459,6 +460,7 @@ #ifdef __SMP__ { "nosmp", smp_setup }, { "maxcpus=", smp_setup }, + { "pirq=", ioapic_pirq_setup }, #endif #ifdef CONFIG_BLK_DEV_RAM { "ramdisk_start=", ramdisk_start_setup }, @@ -925,6 +927,8 @@ #else +extern void setup_IO_APIC(void); + /* * Multiprocessor idle thread is in arch/... */ @@ -979,6 +983,7 @@ memory_start = paging_init(memory_start,memory_end); trap_init(); init_IRQ(); + memory_start = console_init(memory_start,memory_end); sched_init(); time_init(); parse_options(command_line); @@ -1004,7 +1009,9 @@ #if defined(CONFIG_PCI) && defined(CONFIG_PCI_CONSOLE) memory_start = pci_init(memory_start,memory_end); #endif +#if HACK memory_start = console_init(memory_start,memory_end); +#endif #if defined(CONFIG_PCI) && !defined(CONFIG_PCI_CONSOLE) memory_start = pci_init(memory_start,memory_end); #endif @@ -1044,6 +1051,7 @@ printk("POSIX conformance testing by UNIFIX\n"); #ifdef __SMP__ smp_init(); + setup_IO_APIC(); #endif #ifdef CONFIG_SYSCTL sysctl_init(); diff -u --recursive --new-file v2.1.79/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.79/linux/kernel/fork.c Mon Jan 12 22:09:24 1998 +++ linux/kernel/fork.c Wed Jan 14 13:21:14 1998 @@ -220,6 +220,7 @@ *tmp = *mpnt; tmp->vm_flags &= ~VM_LOCKED; tmp->vm_mm = mm; + mm->map_count++; tmp->vm_next = NULL; dentry = tmp->vm_dentry; if (dentry) { @@ -272,6 +273,7 @@ *mm = *current->mm; init_new_context(mm); mm->count = 1; + mm->map_count = 0; mm->def_flags = 0; mm->mmap_sem = MUTEX; /* diff -u --recursive --new-file v2.1.79/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.79/linux/kernel/ksyms.c Tue Dec 23 16:31:00 1997 +++ linux/kernel/ksyms.c Tue Jan 20 16:45:08 1998 @@ -50,6 +50,7 @@ #include #include #include +#include extern unsigned char aux_device_present, kbd_read_mask; @@ -119,6 +120,8 @@ EXPORT_SYMBOL(do_munmap); EXPORT_SYMBOL(exit_mm); EXPORT_SYMBOL(exit_files); +EXPORT_SYMBOL(exit_fs); +EXPORT_SYMBOL(exit_sighand); /* internal kernel memory management */ EXPORT_SYMBOL(__get_free_pages); @@ -380,6 +383,7 @@ EXPORT_SYMBOL(get_hash_table); EXPORT_SYMBOL(get_empty_inode); EXPORT_SYMBOL(insert_inode_hash); +EXPORT_SYMBOL(remove_inode_hash); EXPORT_SYMBOL(make_bad_inode); EXPORT_SYMBOL(is_bad_inode); EXPORT_SYMBOL(event); @@ -404,3 +408,7 @@ /* binfmt_aout */ EXPORT_SYMBOL(get_write_access); EXPORT_SYMBOL(put_write_access); + +/* dynamic registering of consoles */ +EXPORT_SYMBOL(register_console); +EXPORT_SYMBOL(unregister_console); diff -u --recursive --new-file v2.1.79/linux/kernel/printk.c linux/kernel/printk.c --- v2.1.79/linux/kernel/printk.c Sun Dec 21 22:36:17 1997 +++ linux/kernel/printk.c Tue Jan 20 16:45:08 1998 @@ -218,6 +218,7 @@ return error; } +spinlock_t console_lock; asmlinkage int printk(const char *fmt, ...) { @@ -230,6 +231,7 @@ __save_flags(flags); __cli(); + spin_lock(&console_lock); va_start(args, fmt); i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */ buf_end = buf + 3 + i; @@ -277,8 +279,9 @@ if (line_feed) msg_level = -1; } + spin_unlock(&console_lock); __restore_flags(flags); - wake_up_interruptible(&log_wait); +/* wake_up_interruptible(&log_wait);*/ return i; } @@ -394,6 +397,26 @@ } } + +int unregister_console(struct console * console) +{ + struct console *a,*b; + + if (console_drivers == console) { + console_drivers=console->next; + return (0); + } + for (a=console_drivers->next, b=console_drivers ; + a; b=a, a=b->next) { + if (a == console) { + b->next = a->next; + return 0; + } + } + + return (1); +} + /* * Write a message to a certain tty, not just the console. This is used for * messages that need to be redirected to a specific tty. diff -u --recursive --new-file v2.1.79/linux/mm/filemap.c linux/mm/filemap.c --- v2.1.79/linux/mm/filemap.c Mon Jan 12 22:09:24 1998 +++ linux/mm/filemap.c Mon Jan 19 13:47:27 1998 @@ -115,7 +115,7 @@ } } -int shrink_mmap(int priority, int dma) +int shrink_mmap(int priority, int gfp_mask) { static unsigned long clock = 0; struct page * page; @@ -134,7 +134,7 @@ if (PageLocked(page)) goto next; - if (dma && !PageDMA(page)) + if ((gfp_mask & __GFP_DMA) && !PageDMA(page)) goto next; /* First of all, regenerate the page's referenced bit from any buffers in the page */ @@ -173,7 +173,7 @@ } /* is it a buffer cache page? */ - if (bh && try_to_free_buffer(bh, &bh, 6)) + if ((gfp_mask & __GFP_IO) && bh && try_to_free_buffer(bh, &bh, 6)) return 1; break; @@ -1349,11 +1349,10 @@ if (!(page = __find_page(inode, pgpos, *hash))) { if (!page_cache) { page_cache = __get_free_page(GFP_KERNEL); - if (!page_cache) { - status = -ENOMEM; - break; - } - continue; + if (page_cache) + continue; + status = -ENOMEM; + break; } page = mem_map + MAP_NR(page_cache); add_to_page_cache(page, inode, pgpos, hash); @@ -1361,34 +1360,45 @@ } /* - * WSH 06/05/97: restructured slightly to make sure we release - * the page on an error exit. Removed explicit setting of - * PG_locked, as that's handled below the i_op->xxx interface. + * Note: setting of the PG_locked bit is handled + * below the i_op->xxx interface. */ didread = 0; page_wait: wait_on_page(page); + if (PageUptodate(page)) + goto do_update_page; /* - * If the page is not uptodate, and we're writing less + * The page is not up-to-date ... if we're writing less * than a full page of data, we may have to read it first. - * However, don't bother with reading the page when it's - * after the current end of file. + * But if the page is past the current end of file, we must + * clear it before updating. */ - if (!PageUptodate(page)) { - if (bytes < PAGE_SIZE && pgpos < inode->i_size) { - status = -EIO; /* two tries ... error out */ - if (didread < 2) - status = inode->i_op->readpage(dentry, - page); + if (bytes < PAGE_SIZE) { + if (pgpos < inode->i_size) { + status = -EIO; + if (didread >= 2) + goto done_with_page; + status = inode->i_op->readpage(dentry, page); if (status < 0) goto done_with_page; didread++; goto page_wait; + } else { + /* Must clear for partial writes */ + memset((void *) page_address(page), 0, + PAGE_SIZE); } - set_bit(PG_uptodate, &page->flags); } + /* + * N.B. We should defer setting PG_uptodate at least until + * the data is copied. A failure in i_op->updatepage() could + * leave the page with garbage data. + */ + set_bit(PG_uptodate, &page->flags); +do_update_page: /* Alright, the page is there. Now update it. */ status = inode->i_op->updatepage(dentry, page, buf, offset, bytes, sync); @@ -1408,9 +1418,7 @@ if (page_cache) free_page(page_cache); - if (written) - return written; - return status; + return written ? written : status; } /* @@ -1429,7 +1437,7 @@ { struct page * page; struct page ** hash; - unsigned long page_cache; + unsigned long page_cache = 0; hash = page_hash(inode, offset); page = __find_page(inode, offset, *hash); @@ -1443,14 +1451,15 @@ add_to_page_cache(page, inode, offset, hash); } if (atomic_read(&page->count) != 2) - printk("get_cached_page: page count=%d\n", + printk(KERN_ERR "get_cached_page: page count=%d\n", atomic_read(&page->count)); if (test_bit(PG_locked, &page->flags)) - printk("get_cached_page: page already locked!\n"); + printk(KERN_ERR "get_cached_page: page already locked!\n"); set_bit(PG_locked, &page->flags); + page_cache = page_address(page); out: - return page_address(page); + return page_cache; } /* diff -u --recursive --new-file v2.1.79/linux/mm/mmap.c linux/mm/mmap.c --- v2.1.79/linux/mm/mmap.c Sat Nov 1 11:04:27 1997 +++ linux/mm/mmap.c Wed Jan 14 14:52:44 1998 @@ -173,6 +173,10 @@ if (off + len < off) return -EINVAL; + /* Too many mappings? */ + if (mm->map_count > MAX_MAP_COUNT) + return -ENOMEM; + /* mlock MCL_FUTURE? */ if (mm->def_flags & VM_LOCKED) { unsigned long locked = mm->locked_vm << PAGE_SHIFT; @@ -452,6 +456,7 @@ */ int do_munmap(unsigned long addr, size_t len) { + struct mm_struct * mm; struct vm_area_struct *mpnt, *next, *free, *extra; int freed; @@ -466,7 +471,8 @@ * every area affected in some way (by any overlap) is put * on the list. If nothing is put on, nothing is affected. */ - mpnt = current->mm->mmap; + mm = current->mm; + mpnt = mm->mmap; while(mpnt && mpnt->vm_end <= addr) mpnt = mpnt->vm_next; if (!mpnt) @@ -496,6 +502,13 @@ mpnt = next; } + if (free && (free->vm_start < addr) && (free->vm_end > addr+len)) { + if (mm->map_count > MAX_MAP_COUNT) { + kmem_cache_free(vm_area_cachep, extra); + return -ENOMEM; + } + } + /* Ok - we have the memory areas we should free on the 'free' list, * so release them, and unmap the page range.. * If the one of the segments is only being partially unmapped, @@ -508,6 +521,7 @@ free = free->vm_next; freed = 1; + mm->map_count--; remove_shared_vm_struct(mpnt); st = addr < mpnt->vm_start ? mpnt->vm_start : addr; @@ -518,9 +532,9 @@ if (mpnt->vm_ops && mpnt->vm_ops->unmap) mpnt->vm_ops->unmap(mpnt, st, size); - flush_cache_range(current->mm, st, end); - zap_page_range(current->mm, st, size); - flush_tlb_range(current->mm, st, end); + flush_cache_range(mm, st, end); + zap_page_range(mm, st, size); + flush_tlb_range(mm, st, end); /* * Fix the mapping, and free the old area if it wasn't reused. @@ -534,7 +548,7 @@ kmem_cache_free(vm_area_cachep, extra); if (freed) - current->mm->mmap_cache = NULL; /* Kill the cache. */ + mm->mmap_cache = NULL; /* Kill the cache. */ return 0; } @@ -560,6 +574,7 @@ if (mpnt->vm_ops->close) mpnt->vm_ops->close(mpnt); } + mm->map_count--; remove_shared_vm_struct(mpnt); zap_page_range(mm, start, size); if (mpnt->vm_dentry) @@ -567,6 +582,10 @@ kmem_cache_free(vm_area_cachep, mpnt); mpnt = next; } + + /* This is just debugging */ + if (mm->map_count) + printk("exit_mmap: map count is %d\n", mm->map_count); } /* Insert vm structure into process list sorted by address @@ -577,6 +596,8 @@ struct vm_area_struct **pprev = &mm->mmap; struct dentry * dentry; + mm->map_count++; + /* Find where to link it in. */ while(*pprev && (*pprev)->vm_start <= vmp->vm_start) pprev = &(*pprev)->vm_next; @@ -668,6 +689,7 @@ mpnt->vm_start = mpnt->vm_end; mpnt->vm_ops->close(mpnt); } + mm->map_count--; remove_shared_vm_struct(mpnt); if (mpnt->vm_dentry) dput(mpnt->vm_dentry); diff -u --recursive --new-file v2.1.79/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.1.79/linux/mm/page_alloc.c Mon Jan 12 22:09:24 1998 +++ linux/mm/page_alloc.c Thu Jan 15 21:35:49 1998 @@ -204,7 +204,7 @@ map->age = PAGE_INITIAL_AGE; \ } while (0) -unsigned long __get_free_pages(int priority, unsigned long order, int dma) +unsigned long __get_free_pages(int gfp_mask, unsigned long order) { unsigned long flags, maxorder; @@ -216,28 +216,25 @@ * to empty in order to find a free page.. */ maxorder = order + NR_MEM_LISTS/3; - switch (priority) { - case GFP_ATOMIC: - maxorder = NR_MEM_LISTS; - /* fallthrough - no need to jump around */ - case GFP_NFS: + if (gfp_mask & __GFP_MED) maxorder += NR_MEM_LISTS/3; - } + if ((gfp_mask & __GFP_HIGH) || maxorder > NR_MEM_LISTS) + maxorder = NR_MEM_LISTS; - if (in_interrupt() && priority != GFP_ATOMIC) { + if (in_interrupt() && (gfp_mask & __GFP_WAIT)) { static int count = 0; if (++count < 5) { printk("gfp called nonatomically from interrupt %p\n", __builtin_return_address(0)); - priority = GFP_ATOMIC; + gfp_mask &= ~__GFP_WAIT; } } repeat: spin_lock_irqsave(&page_alloc_lock, flags); - RMQUEUE(order, maxorder, dma); + RMQUEUE(order, maxorder, (gfp_mask & GFP_DMA)); spin_unlock_irqrestore(&page_alloc_lock, flags); - if (priority != GFP_BUFFER && priority != GFP_ATOMIC && try_to_free_page(priority, dma, 1)) + if ((gfp_mask & __GFP_WAIT) && try_to_free_page(gfp_mask)) goto repeat; nopage: return 0; diff -u --recursive --new-file v2.1.79/linux/mm/simp.c linux/mm/simp.c --- v2.1.79/linux/mm/simp.c Mon Aug 4 16:25:40 1997 +++ linux/mm/simp.c Thu Jan 15 20:44:18 1998 @@ -115,7 +115,7 @@ if(!global) { #ifdef __SMP__ - global = (struct global_data*)__get_free_pages(GFP_KERNEL, ORDER, 0); + global = (struct global_data*)__get_free_pages(GFP_KERNEL, ORDER); memset(global, 0, CHUNK_SIZE); #else global = (struct global_data*)get_free_page(GFP_KERNEL); @@ -167,7 +167,7 @@ spin_unlock(&simp->lock); for(;;) { - hdr = (struct header*)__get_free_pages(GFP_KERNEL, ORDER, 0); + hdr = (struct header*)__get_free_pages(GFP_KERNEL, ORDER); if(hdr) break; if(!simp_garbage()) diff -u --recursive --new-file v2.1.79/linux/mm/slab.c linux/mm/slab.c --- v2.1.79/linux/mm/slab.c Thu Aug 14 20:49:18 1997 +++ linux/mm/slab.c Thu Jan 15 21:08:36 1998 @@ -502,8 +502,7 @@ void *addr; *dma = flags & SLAB_DMA; - addr = (void*) __get_free_pages(flags & SLAB_LEVEL_MASK, - cachep->c_gfporder, *dma); + addr = (void*) __get_free_pages(flags, cachep->c_gfporder); /* Assume that now we have the pages no one else can legally * messes with the 'struct page's. * However vm_scan() might try to test the structure to see if @@ -1716,19 +1715,18 @@ * This function _cannot_ be called within a int, but it * can be interrupted. */ -int -kmem_cache_reap(int pri, int dma, int wait) +void +kmem_cache_reap(int gfp_mask) { kmem_slab_t *slabp; kmem_cache_t *searchp; kmem_cache_t *best_cachep; unsigned int scan; unsigned int reap_level; - static unsigned long call_count = 0; if (in_interrupt()) { printk("kmem_cache_reap() called within int!\n"); - return 0; + return; } /* We really need a test semphore op so we can avoid sleeping when @@ -1736,28 +1734,8 @@ */ down(&cache_chain_sem); - scan = 10-pri; - if (pri == 6 && !dma) { - if (++call_count == 199) { - /* Hack Alert! - * Occassionally we try hard to reap a slab. - */ - call_count = 0UL; - reap_level = 0; - scan += 2; - } else - reap_level = 3; - } else { - if (pri >= 5) { - /* We also come here for dma==1 at pri==6, just - * to try that bit harder (assumes that there are - * less DMAable pages in a system - not always true, - * but this doesn't hurt). - */ - reap_level = 2; - } else - reap_level = 0; - } + scan = 10; + reap_level = 0; best_cachep = NULL; searchp = clock_searchp; @@ -1796,7 +1774,7 @@ } spin_unlock_irq(&searchp->c_spinlock); - if (dma && !dma_flag) + if ((gfp_mask & GFP_DMA) && !dma_flag) goto next; if (full_free) { @@ -1809,10 +1787,6 @@ * more than one page per slab (as it can be difficult * to get high orders from gfp()). */ - if (pri == 6) { /* magic '6' from try_to_free_page() */ - if (searchp->c_gfporder || searchp->c_ctor) - full_free--; - } if (full_free >= reap_level) { reap_level = full_free; best_cachep = searchp; @@ -1830,12 +1804,12 @@ if (!best_cachep) { /* couldn't find anthying to reap */ - return 0; + return; } spin_lock_irq(&best_cachep->c_spinlock); if (!best_cachep->c_growing && !(slabp = best_cachep->c_lastp)->s_inuse && slabp != kmem_slab_end(best_cachep)) { - if (dma) { + if (gfp_mask & GFP_DMA) { do { if (slabp->s_dma) goto good_dma; @@ -1858,11 +1832,11 @@ */ spin_unlock_irq(&best_cachep->c_spinlock); kmem_slab_destroy(best_cachep, slabp); - return 1; + return; } dma_fail: spin_unlock_irq(&best_cachep->c_spinlock); - return 0; + return; } #if SLAB_SELFTEST diff -u --recursive --new-file v2.1.79/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.1.79/linux/mm/vmscan.c Mon Jan 12 22:09:24 1998 +++ linux/mm/vmscan.c Thu Jan 15 21:07:58 1998 @@ -61,7 +61,7 @@ * have died while we slept). */ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struct* vma, - unsigned long address, pte_t * page_table, int dma, int wait) + unsigned long address, pte_t * page_table, int gfp_mask) { pte_t pte; unsigned long entry; @@ -78,7 +78,7 @@ page_map = mem_map + MAP_NR(page); if (PageReserved(page_map) || PageLocked(page_map) - || (dma && !PageDMA(page_map))) + || ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))) return 0; /* Deal with page aging. Pages age from being unused; they * rejuvenate on being accessed. Only swap old pages (age==0 @@ -112,7 +112,7 @@ set_pte(page_table, __pte(entry)); flush_tlb_page(vma, address); tsk->nswap++; - rw_swap_page(WRITE, entry, (char *) page, wait); + rw_swap_page(WRITE, entry, (char *) page, (gfp_mask & __GFP_WAIT)); } /* * For now, this is safe, because the test above makes @@ -166,7 +166,7 @@ */ static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct * vma, - pmd_t *dir, unsigned long address, unsigned long end, int dma, int wait) + pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask) { pte_t * pte; unsigned long pmd_end; @@ -188,7 +188,7 @@ do { int result; tsk->swap_address = address + PAGE_SIZE; - result = try_to_swap_out(tsk, vma, address, pte, dma, wait); + result = try_to_swap_out(tsk, vma, address, pte, gfp_mask); if (result) return result; address += PAGE_SIZE; @@ -198,7 +198,7 @@ } static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct * vma, - pgd_t *dir, unsigned long address, unsigned long end, int dma, int wait) + pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask) { pmd_t * pmd; unsigned long pgd_end; @@ -218,7 +218,7 @@ end = pgd_end; do { - int result = swap_out_pmd(tsk, vma, pmd, address, end, dma, wait); + int result = swap_out_pmd(tsk, vma, pmd, address, end, gfp_mask); if (result) return result; address = (address + PMD_SIZE) & PMD_MASK; @@ -228,7 +228,7 @@ } static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma, - pgd_t *pgdir, unsigned long start, int dma, int wait) + pgd_t *pgdir, unsigned long start, int gfp_mask) { unsigned long end; @@ -239,7 +239,7 @@ end = vma->vm_end; while (start < end) { - int result = swap_out_pgd(tsk, vma, pgdir, start, end, dma, wait); + int result = swap_out_pgd(tsk, vma, pgdir, start, end, gfp_mask); if (result) return result; start = (start + PGDIR_SIZE) & PGDIR_MASK; @@ -248,7 +248,7 @@ return 0; } -static int swap_out_process(struct task_struct * p, int dma, int wait) +static int swap_out_process(struct task_struct * p, int gfp_mask) { unsigned long address; struct vm_area_struct* vma; @@ -269,7 +269,7 @@ address = vma->vm_start; for (;;) { - int result = swap_out_vma(p, vma, pgd_offset(p->mm, address), address, dma, wait); + int result = swap_out_vma(p, vma, pgd_offset(p->mm, address), address, gfp_mask); if (result) return result; vma = vma->vm_next; @@ -286,7 +286,7 @@ * N.B. This function returns only 0 or 1. Return values != 1 from * the lower level routines result in continued processing. */ -static int swap_out(unsigned int priority, int dma, int wait) +static int swap_out(unsigned int priority, int gfp_mask) { struct task_struct * p, * pbest; int counter, assign, max_cnt; @@ -337,7 +337,7 @@ } pbest->swap_cnt--; - switch (swap_out_process(pbest, dma, wait)) { + switch (swap_out_process(pbest, gfp_mask)) { case 0: /* * Clear swap_cnt so we don't look at this task @@ -361,7 +361,7 @@ * to be. This works out OK, because we now do proper aging on page * contents. */ -static inline int do_try_to_free_page(int priority, int dma, int wait) +static inline int do_try_to_free_page(int gfp_mask) { static int state = 0; int i=6; @@ -369,25 +369,27 @@ /* Let the dcache know we're looking for memory ... */ shrink_dcache_memory(); + /* Always trim SLAB caches when memory gets low. */ - (void) kmem_cache_reap(0, dma, wait); + kmem_cache_reap(gfp_mask); - /* we don't try as hard if we're not waiting.. */ + /* We try harder if we are waiting .. */ stop = 3; - if (wait) + if (gfp_mask & __GFP_WAIT) stop = 0; + switch (state) { do { case 0: - if (shrink_mmap(i, dma)) + if (shrink_mmap(i, gfp_mask)) return 1; state = 1; case 1: - if (shm_swap(i, dma)) + if ((gfp_mask & __GFP_IO) && shm_swap(i, gfp_mask)) return 1; state = 2; default: - if (swap_out(i, dma, wait)) + if (swap_out(i, gfp_mask)) return 1; state = 0; i--; @@ -403,12 +405,12 @@ * now we need this so that we can do page allocations * without holding the kernel lock etc. */ -int try_to_free_page(int priority, int dma, int wait) +int try_to_free_page(int gfp_mask) { int retval; lock_kernel(); - retval = do_try_to_free_page(priority,dma,wait); + retval = do_try_to_free_page(gfp_mask); unlock_kernel(); return retval; } @@ -476,15 +478,17 @@ * go back to sleep to let other tasks run. */ for (fail = 0; fail++ < MAX_SWAP_FAIL;) { - int pages, wait; + int pages, gfp_mask; pages = nr_free_pages; if (nr_free_pages >= min_free_pages) pages += atomic_read(&nr_async_pages); if (pages >= free_pages_high) break; - wait = (pages < free_pages_low); - if (try_to_free_page(GFP_KERNEL, 0, wait)) + gfp_mask = __GFP_IO; + if (pages < free_pages_low) + gfp_mask |= __GFP_WAIT; + if (try_to_free_page(gfp_mask)) fail = 0; } /* diff -u --recursive --new-file v2.1.79/linux/net/Config.in linux/net/Config.in --- v2.1.79/linux/net/Config.in Mon Jan 12 22:09:24 1998 +++ linux/net/Config.in Tue Jan 13 20:15:35 1998 @@ -11,6 +11,7 @@ fi bool 'Network firewalls' CONFIG_FIREWALL bool 'Network aliasing' CONFIG_NET_ALIAS +bool 'Socket Filtering' CONFIG_FILTER tristate 'Unix domain sockets' CONFIG_UNIX bool 'TCP/IP networking' CONFIG_INET if [ "$CONFIG_INET" = "y" ]; then diff -u --recursive --new-file v2.1.79/linux/net/bridge/br.c linux/net/bridge/br.c --- v2.1.79/linux/net/bridge/br.c Thu Sep 11 09:02:24 1997 +++ linux/net/bridge/br.c Thu Jan 15 14:33:06 1998 @@ -1000,16 +1000,16 @@ static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu) { -struct sk_buff *skb; -struct device *dev = port_info[port_no].dev; -int size; -unsigned long flags; -struct ethhdr *eth; + struct sk_buff *skb; + struct device *dev = port_info[port_no].dev; + int size; + struct ethhdr *eth; if (port_info[port_no].state == Disabled) { printk(KERN_DEBUG "send_config_bpdu: port %i not valid\n",port_no); return(-1); - } + } + if (br_stats.flags & BR_DEBUG) printk("send_config_bpdu: "); /* @@ -1017,10 +1017,11 @@ */ size = dev->hard_header_len + sizeof(Config_bpdu); skb = alloc_skb(size, GFP_ATOMIC); - if (skb == NULL) { + if (skb == NULL) + { printk(KERN_DEBUG "send_config_bpdu: no skb available\n"); return(-1); - } + } skb->dev = dev; skb->mac.raw = skb->h.raw = skb_put(skb, size); eth = skb->mac.ethernet; @@ -1049,21 +1050,17 @@ /* won't get bridged again... */ skb->pkt_bridged = IS_BRIDGED; - skb->arp = 1; /* do not resolve... */ - save_flags(flags); - cli(); - skb_queue_tail(dev->buffs, skb); - restore_flags(flags); + skb->dev=dev; + dev_queue_xmit(skb); return(0); } static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu) { -struct sk_buff *skb; -struct device *dev = port_info[port_no].dev; -int size; -unsigned long flags; -struct ethhdr *eth; + struct sk_buff *skb; + struct device *dev = port_info[port_no].dev; + int size; + struct ethhdr *eth; if (port_info[port_no].state == Disabled) { printk(KERN_DEBUG "send_tcn_bpdu: port %i not valid\n",port_no); @@ -1105,11 +1102,8 @@ /* mark that we've been here... */ skb->pkt_bridged = IS_BRIDGED; - skb->arp = 1; /* do not resolve... */ - save_flags(flags); - cli(); - skb_queue_tail(dev->buffs, skb); - restore_flags(flags); + skb->dev=dev; + dev_queue_xmit(skb); return(0); } @@ -1199,7 +1193,6 @@ port = find_port(skb->dev); - skb->arp = 1; /* Received frame so it is resolved */ skb->h.raw = skb->mac.raw; eth = skb->mac.ethernet; if (br_stats.flags & BR_DEBUG) @@ -1519,7 +1512,6 @@ nskb->dev= port_info[i].dev; /* To get here we must have done ARP already, or have a received valid MAC header */ - nskb->arp = 1; /* printk("Flood to port %d\n",i);*/ nskb->h.raw = nskb->data + ETH_HLEN; diff -u --recursive --new-file v2.1.79/linux/net/core/Makefile linux/net/core/Makefile --- v2.1.79/linux/net/core/Makefile Mon Jan 12 22:09:24 1998 +++ linux/net/core/Makefile Tue Jan 13 20:15:33 1998 @@ -16,6 +16,10 @@ O_OBJS += sysctl_net_core.o endif +ifdef CONFIG_FILTER +O_OBJS += filter.o +endif + ifdef CONFIG_NET O_OBJS += dev.o dev_mcast.o diff -u --recursive --new-file v2.1.79/linux/net/core/dev.c linux/net/core/dev.c --- v2.1.79/linux/net/core/dev.c Mon Jan 12 22:09:24 1998 +++ linux/net/core/dev.c Tue Jan 20 16:45:08 1998 @@ -724,7 +724,7 @@ } #ifdef CONFIG_BRIDGE -static inline void handle_bridge(struct skbuff *skb, unsigned short type) +static inline void handle_bridge(struct sk_buff *skb, unsigned short type) { if (br_stats.flags & BR_UP && br_protocol_ok(ntohs(type))) { @@ -739,7 +739,7 @@ if(br_receive_frame(skb)) { sti(); - continue; + return; } /* * Pull the MAC header off for the copy going to @@ -1500,6 +1500,16 @@ ifr->ifr_ifindex = dev->ifindex; return 0; + case SIOCGIFTXQLEN: + ifr->ifr_qlen = dev->tx_queue_len; + return 0; + + case SIOCSIFTXQLEN: + if(ifr->ifr_qlen<2 || ifr->ifr_qlen>1024) + return -EINVAL; + dev->tx_queue_len = ifr->ifr_qlen; + return 0; + /* * Unknown or private ioctl */ @@ -1591,6 +1601,7 @@ case SIOCGIFSLAVE: case SIOCGIFMAP: case SIOCGIFINDEX: + case SIOCGIFTXQLEN: ret = dev_ifsioc(&ifr, cmd); if (!ret) { #ifdef CONFIG_NET_ALIAS @@ -1618,6 +1629,7 @@ case SIOCADDMULTI: case SIOCDELMULTI: case SIOCSIFHWBROADCAST: + case SIOCSIFTXQLEN: if (!suser()) return -EPERM; rtnl_lock(); diff -u --recursive --new-file v2.1.79/linux/net/core/neighbour.c linux/net/core/neighbour.c --- v2.1.79/linux/net/core/neighbour.c Mon Jan 12 22:09:24 1998 +++ linux/net/core/neighbour.c Thu Jan 15 14:33:07 1998 @@ -432,7 +432,7 @@ if (state&(NUD_PERMANENT|NUD_IN_TIMER)) goto next_elt; - if (n->used - n->confirmed < 0) + if ((long)(n->used - n->confirmed) < 0) n->used = n->confirmed; if (atomic_read(&n->refcnt) == 0 && @@ -795,17 +795,17 @@ while (skb != (struct sk_buff*)&tbl->proxy_queue) { struct sk_buff *back = skb; + long tdif = back->stamp.tv_usec - now; + skb = skb->next; - if (back->stamp.tv_usec - now <= 0) { + if (tdif <= 0) { __skb_unlink(back, &tbl->proxy_queue); if (tbl->proxy_redo) tbl->proxy_redo(back); else kfree_skb(back, FREE_WRITE); - } else { - if (!sched_next || back->stamp.tv_usec - now < sched_next) - sched_next = back->stamp.tv_usec - now; - } + } else if (!sched_next || tdif < sched_next) + sched_next = tdif; } del_timer(&tbl->proxy_timer); if (sched_next) { diff -u --recursive --new-file v2.1.79/linux/net/core/skbuff.c linux/net/core/skbuff.c --- v2.1.79/linux/net/core/skbuff.c Mon Jan 12 22:09:24 1998 +++ linux/net/core/skbuff.c Thu Jan 15 21:12:27 1998 @@ -113,18 +113,18 @@ * to be a good idea. */ -struct sk_buff *alloc_skb(unsigned int size,int priority) +struct sk_buff *alloc_skb(unsigned int size,int gfp_mask) { struct sk_buff *skb; unsigned char *bptr; int len; - if (in_interrupt() && priority!=GFP_ATOMIC) { + if (in_interrupt() && (gfp_mask & __GFP_WAIT)) { static int count = 0; if (++count < 5) { printk(KERN_ERR "alloc_skb called nonatomically " "from interrupt %p\n", __builtin_return_address(0)); - priority = GFP_ATOMIC; + gfp_mask &= ~__GFP_WAIT; } } @@ -144,7 +144,7 @@ * Allocate some space */ - bptr = kmalloc(size,priority); + bptr = kmalloc(size,gfp_mask); if (bptr == NULL) { atomic_inc(&net_fails); return NULL; @@ -226,7 +226,7 @@ * Duplicate an sk_buff. The new one is not owned by a socket. */ -struct sk_buff *skb_clone(struct sk_buff *skb, int priority) +struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask) { struct sk_buff *n; int inbuff = 0; @@ -237,7 +237,7 @@ skb->inclone = SKB_CLONE_ORIG; inbuff = SKB_CLONE_INLINE; } else { - n = kmalloc(sizeof(*n), priority); + n = kmalloc(sizeof(*n), gfp_mask); if (!n) return NULL; } @@ -263,7 +263,7 @@ * This is slower, and copies the whole data area */ -struct sk_buff *skb_copy(struct sk_buff *skb, int priority) +struct sk_buff *skb_copy(struct sk_buff *skb, int gfp_mask) { struct sk_buff *n; unsigned long offset; @@ -272,7 +272,7 @@ * Allocate the copy buffer */ - n=alloc_skb(skb->end - skb->head, priority); + n=alloc_skb(skb->end - skb->head, gfp_mask); if(n==NULL) return NULL; diff -u --recursive --new-file v2.1.79/linux/net/core/sock.c linux/net/core/sock.c --- v2.1.79/linux/net/core/sock.c Mon Jan 12 22:09:24 1998 +++ linux/net/core/sock.c Thu Jan 15 14:33:07 1998 @@ -76,6 +76,7 @@ * Steve Whitehouse: Added various other default routines * common to several socket families. * Chris Evans : Call suser() check last on F_SETOWN + * Jay Schulist : Added SO_ATTACH_FILTER and SO_DETACH_FILTER. * Andi Kleen : Add sock_kmalloc()/sock_kfree_s() * * To Fix: @@ -123,6 +124,10 @@ #include #include +#ifdef CONFIG_FILTER +#include +#endif + #define min(a,b) ((a)<(b)?(a):(b)) /* Run time adjustable parameters. */ @@ -148,6 +153,10 @@ struct linger ling; struct ifreq req; int ret = 0; + +#ifdef CONFIG_FILTER + struct sock_fprog fprog; +#endif /* * Options without arguments @@ -279,48 +288,6 @@ break; -#ifdef CONFIG_NET_SECURITY - /* - * FIXME: make these error things that are not - * available! - */ - - case SO_SECURITY_AUTHENTICATION: - if(val<=IPSEC_LEVEL_DEFAULT) - { - sk->authentication=val; - return 0; - } - if(net_families[sock->ops->family]->authentication) - sk->authentication=val; - else - return -EINVAL; - break; - - case SO_SECURITY_ENCRYPTION_TRANSPORT: - if(val<=IPSEC_LEVEL_DEFAULT) - { - sk->encryption=val; - return 0; - } - if(net_families[sock->ops->family]->encryption) - sk->encryption = val; - else - return -EINVAL; - break; - - case SO_SECURITY_ENCRYPTION_NETWORK: - if(val<=IPSEC_LEVEL_DEFAULT) - { - sk->encrypt_net=val; - return 0; - } - if(net_families[sock->ops->family]->encrypt_net) - sk->encrypt_net = val; - else - return -EINVAL; - break; -#endif case SO_BINDTODEVICE: /* Bind this socket to a particular device like "eth0", * as specified in an ifreq structure. If the device @@ -361,6 +328,33 @@ return 0; +#ifdef CONFIG_FILTER + case SO_ATTACH_FILTER: + if(optlen < sizeof(struct sock_fprog)) + return -EINVAL; + + if(copy_from_user(&fprog, optval, sizeof(fprog))) + { + ret = -EFAULT; + break; + } + + ret = sk_attach_filter(&fprog, sk); + break; + + case SO_DETACH_FILTER: + if(sk->filter) + { + fprog.filter = sk->filter_data; + kfree_s(fprog.filter, (sizeof(fprog.filter) * sk->filter)); + sk->filter_data = NULL; + sk->filter = 0; + return 0; + } + else + return -EINVAL; + break; +#endif /* We implement the SO_SNDLOWAT etc to not be settable (1003.1g 5.3) */ default: @@ -471,20 +465,6 @@ return -EFAULT; goto lenout; -#ifdef CONFIG_NET_SECURITY - - case SO_SECURITY_AUTHENTICATION: - v.val = sk->authentication; - break; - - case SO_SECURITY_ENCRYPTION_TRANSPORT: - v.val = sk->encryption; - break; - - case SO_SECURITY_ENCRYPTION_NETWORK: - v.val = sk->encrypt_net; - break; -#endif default: return(-ENOPROTOOPT); } diff -u --recursive --new-file v2.1.79/linux/net/ipv4/Config.in linux/net/ipv4/Config.in --- v2.1.79/linux/net/ipv4/Config.in Mon Jan 12 22:09:25 1998 +++ linux/net/ipv4/Config.in Thu Jan 15 14:33:07 1998 @@ -27,6 +27,9 @@ if [ "$CONFIG_IP_FIREWALL" = "y" ]; then if [ "$CONFIG_NETLINK" = "y" ]; then bool 'IP: firewall packet netlink device' CONFIG_IP_FIREWALL_NETLINK + if [ "$CONFIG_IP_FIREWALL_NETLINK" = "y" ]; then + define_bool CONFIG_NETLINK_DEV y + fi fi bool 'IP: firewall packet logging' CONFIG_IP_FIREWALL_VERBOSE bool 'IP: transparent proxy support' CONFIG_IP_TRANSPARENT_PROXY diff -u --recursive --new-file v2.1.79/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c --- v2.1.79/linux/net/ipv4/ip_forward.c Mon Jan 12 22:09:25 1998 +++ linux/net/ipv4/ip_forward.c Thu Jan 15 14:33:07 1998 @@ -178,7 +178,8 @@ { #endif maddr = inet_select_addr(dev2, rt->rt_gateway, RT_SCOPE_UNIVERSE); - if (fw_res = ip_fw_masq_icmp(&skb, maddr) < 0) { + fw_res = ip_fw_masq_icmp(&skb, maddr); + if (fw_res < 0) { kfree_skb(skb, FREE_READ); return -1; } diff -u --recursive --new-file v2.1.79/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c --- v2.1.79/linux/net/ipv4/ip_output.c Mon Jan 12 22:09:25 1998 +++ linux/net/ipv4/ip_output.c Sun Jan 18 12:28:34 1998 @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) output module. * - * Version: $Id: ip_output.c,v 1.44 1997/12/27 20:41:14 kuznet Exp $ + * Version: $Id: ip_output.c,v 1.45 1998/01/15 22:06:35 freitag Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -332,12 +332,9 @@ /* - * Queues a packet to be sent, and starts the transmitter - * if necessary. if free = 1 then we free the block after - * transmit, otherwise we don't. If free==2 we not only - * free the block but also don't assign a new ip seq number. - * This routine also needs to put in the total length, - * and compute the checksum + * Queues a packet to be sent, and starts the transmitter if necessary. + * This routine also needs to put in the total length and compute the + * checksum */ void ip_queue_xmit(struct sk_buff *skb) @@ -352,15 +349,23 @@ iph->tot_len = htons(tot_len); iph->id = htons(ip_id_count++); - if (rt->u.dst.obsolete) - goto check_route; -after_check_route: + if (rt->u.dst.obsolete) { + /* Ugly... ugly... but what can I do? + Essentially it is "ip_reroute_output" function. --ANK + */ + struct rtable *nrt; + if (ip_route_output(&nrt, rt->key.dst, rt->key.src, rt->key.tos, + sk?sk->bound_dev_if:0)) + goto drop; + skb->dst = &nrt->u.dst; + ip_rt_put(rt); + rt = nrt; + } + dev = rt->u.dst.dev; - if (call_out_firewall(PF_INET, dev, iph, NULL,&skb) < FW_ACCEPT) { - kfree_skb(skb, FREE_WRITE); - return; - } + if (call_out_firewall(PF_INET, dev, iph, NULL,&skb) < FW_ACCEPT) + goto drop; #ifdef CONFIG_NET_SECURITY /* @@ -371,10 +376,7 @@ ip_send_check(iph); if (call_out_firewall(PF_SECURITY, NULL, NULL, (void *) 4, &skb)nh.iph; /* don't update tot_len, as the dev->mtu is already decreased */ @@ -404,46 +406,33 @@ if (tot_len > rt->u.dst.pmtu) goto fragment; +#ifndef CONFIG_NET_SECURITY /* * Add an IP checksum */ ip_send_check(iph); +#endif if (sk) skb->priority = sk->priority; skb->dst->output(skb); return; -check_route: - /* Ugly... ugly... but what can I do? - - Essentially it is "ip_reroute_output" function. --ANK - */ - { - struct rtable *nrt; - if (ip_route_output(&nrt, rt->key.dst, rt->key.src, rt->key.tos, sk?sk->bound_dev_if:0)) { - kfree_skb(skb, 0); - return; - } - skb->dst = &nrt->u.dst; - ip_rt_put(rt); - rt = nrt; - } - goto after_check_route; - fragment: if ((iph->frag_off & htons(IP_DF))) { printk(KERN_DEBUG "sending pkt_too_big to self\n"); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(rt->u.dst.pmtu)); - - kfree_skb(skb, FREE_WRITE); - return; + goto drop; } ip_fragment(skb, skb->dst->output); + return; + +drop: + kfree_skb(skb, FREE_WRITE); } /* @@ -612,11 +601,12 @@ mf = 0; /* - * Can't fragment raw packets + * Don't fragment packets for path mtu discovery. */ - if (offset > 0 && df) + if (offset > 0 && df) { return(-EMSGSIZE); + } /* * Lock the device lists. diff -u --recursive --new-file v2.1.79/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c --- v2.1.79/linux/net/ipv4/ipconfig.c Mon Jan 12 22:09:25 1998 +++ linux/net/ipv4/ipconfig.c Tue Jan 20 12:11:57 1998 @@ -767,7 +767,7 @@ /* * Process BOOTP extension. */ -__initfunc(static void ic_do_bootp_ext(u8 *ext)) +__initfunc(static void ic_do_bootp_ext(struct bootp_pkt *b, u8 *ext)) { #ifdef IPCONFIG_DEBUG u8 *c; @@ -799,9 +799,6 @@ ic_bootp_string(root_server_path, ext+1, *ext, sizeof(root_server_path)); break; } - - if (ic_gateway == INADDR_NONE && b->relay_ip) - ic_gateway = b->relay_ip; } @@ -867,7 +864,7 @@ opt = ext; ext += ext[1] + 2; if (ext <= end) - ic_do_bootp_ext(opt); + ic_do_bootp_ext(b, opt); } } } diff -u --recursive --new-file v2.1.79/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c --- v2.1.79/linux/net/ipv4/rarp.c Mon Dec 1 12:04:16 1997 +++ linux/net/ipv4/rarp.c Thu Jan 15 14:33:07 1998 @@ -190,6 +190,8 @@ rarp_pkt_inited=1; } +#ifdef MODULE + static void rarp_end_pkt(void) { if(!rarp_pkt_inited) @@ -199,6 +201,7 @@ rarp_pkt_inited=0; } +#endif /* * Receive an arp request by the device layer. Maybe it should be diff -u --recursive --new-file v2.1.79/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- v2.1.79/linux/net/ipv4/sysctl_net_ipv4.c Mon Jan 12 22:09:25 1998 +++ linux/net/ipv4/sysctl_net_ipv4.c Sun Jan 18 12:28:35 1998 @@ -1,7 +1,7 @@ /* * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem. * - * $Id: sysctl_net_ipv4.c,v 1.23 1997/12/13 21:52:57 kuznet Exp $ + * $Id: sysctl_net_ipv4.c,v 1.25 1998/01/15 22:40:57 freitag Exp $ * * Begun April 1, 1996, Mike Shaver. * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS] @@ -54,7 +54,6 @@ extern int sysctl_tcp_max_ka_probes; extern int sysctl_tcp_retries1; extern int sysctl_tcp_retries2; -extern int sysctl_tcp_max_delay_acks; extern int sysctl_tcp_fin_timeout; extern int sysctl_tcp_syncookies; extern int sysctl_tcp_syn_retries; @@ -104,9 +103,11 @@ int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp, void *buffer, size_t *lenp) { - if (write) + if (write) { rt_cache_flush(0); - return 0; + return 0; + } else + return -EINVAL; } ctl_table ipv4_table[] = { @@ -197,8 +198,6 @@ &sysctl_intvec, NULL, NULL, &tcp_retr1_max}, {NET_IPV4_TCP_RETRIES2, "tcp_retries2", &sysctl_tcp_retries2, sizeof(int), 0644, NULL, &proc_dointvec}, - {NET_IPV4_TCP_MAX_DELAY_ACKS, "tcp_max_delay_acks", - &sysctl_tcp_max_delay_acks, sizeof(int), 0644, NULL, &proc_dointvec}, {NET_IPV4_TCP_FIN_TIMEOUT, "tcp_fin_timeout", &sysctl_tcp_fin_timeout, sizeof(int), 0644, NULL, &proc_dointvec_jiffies}, diff -u --recursive --new-file v2.1.79/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.1.79/linux/net/ipv4/tcp.c Mon Jan 12 22:09:25 1998 +++ linux/net/ipv4/tcp.c Sun Jan 18 12:28:34 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.76 1997/12/30 19:43:17 kuznet Exp $ + * Version: $Id: tcp.c,v 1.77 1998/01/15 22:40:18 freitag Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -491,9 +491,7 @@ /* - * Walk down the receive queue counting readable data until we hit the - * end or we find a gap in the received data queue (ie a frame missing - * that needs sending to us). + * Walk down the receive queue counting readable data. */ static int tcp_readable(struct sock *sk) @@ -520,7 +518,7 @@ /* Do until a push or until we are out of data. */ do { /* Found a hole so stops here. */ - if (before(counted, skb->seq)) + if (before(counted, skb->seq)) /* should not happen */ break; /* Length - header but start from where we are up to @@ -604,24 +602,30 @@ mask = POLLERR; /* Connected? */ if ((1 << sk->state) & ~(TCPF_SYN_SENT|TCPF_SYN_RECV)) { + int space; + if (sk->shutdown & RCV_SHUTDOWN) mask |= POLLHUP; - + if ((tp->rcv_nxt != sk->copied_seq) && (sk->urg_seq != sk->copied_seq || tp->rcv_nxt != sk->copied_seq+1 || sk->urginline || !sk->urg_data)) mask |= POLLIN | POLLRDNORM; - /* FIXME: this assumed sk->mtu is correctly maintained. - * I see no evidence this is the case. -- erics - */ - if (!(sk->shutdown & SEND_SHUTDOWN) && - (sock_wspace(sk) >= sk->mtu+128+sk->prot->max_header)) +#if 1 /* This needs benchmarking and real world tests */ + space = sk->dst_cache->pmtu + 128; + if (space < 2048) /* XXX */ + space = 2048; +#else /* 2.0 way */ + /* More than half of the socket queue free? */ + space = atomic_read(&sk->wmem_alloc) / 2; +#endif + /* Always wake the user up when an error occured */ + if (sock_wspace(sk) >= space) mask |= POLLOUT | POLLWRNORM; - if (sk->urg_data) - mask |= POLLPRI; + mask |= POLLPRI; } return mask; } @@ -659,42 +663,10 @@ return put_user(amount, (int *)arg); } default: - return(-ENOIOCTLCMD); + return(-EINVAL); }; } - -/* - * This routine builds a generic TCP header. - * It also builds in the RFC1323 Timestamp. - * It can't (unfortunately) do SACK as well. - */ - -extern __inline void tcp_build_header(struct tcphdr *th, struct sock *sk, int push) -{ - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - - memcpy(th,(void *) &(sk->dummy_th), sizeof(*th)); - th->seq = htonl(sk->write_seq); - th->psh =(push == 0) ? 1 : 0; - th->ack_seq = htonl(tp->rcv_nxt); - th->window = htons(tcp_select_window(sk)); - - /* FIXME: could use the inline found in tcp_output.c as well. - * Probably that means we should move these up to an include file. --erics - */ - if (tp->tstamp_ok) { - __u32 *ptr = (__u32 *)(th+1); - *ptr++ = ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) - | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); - /* FIXME: Not sure it's worth setting these here already, but I'm - * also not sure we replace them on all paths later. --erics - */ - *ptr++ = jiffies; - *ptr++ = tp->ts_recent; - } -} - /* * Wait for a socket to get into the connected state */ @@ -942,7 +914,7 @@ skb_put(skb,tp->tcp_header_len); seglen -= copy; - tcp_build_header(skb->h.th, sk, seglen || iovlen); + tcp_build_header_data(skb->h.th, sk, seglen || iovlen); /* FIXME: still need to think about SACK options here. */ if (flags & MSG_OOB) { @@ -1077,7 +1049,8 @@ static void cleanup_rbuf(struct sock *sk) { struct sk_buff *skb; - + struct tcp_opt *tp; + /* NOTE! The socket must be locked, so that we don't get * a messed-up receive queue. */ @@ -1089,11 +1062,12 @@ SOCK_DEBUG(sk, "sk->rspace = %lu\n", sock_rspace(sk)); + tp = &(sk->tp_pinfo.af_tcp); + /* We send a ACK if the sender is blocked * else let tcp_data deal with the acking policy. */ - if (sk->tp_pinfo.af_tcp.delayed_acks) { - struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + if (tp->delayed_acks) { __u32 rcv_wnd; /* FIXME: double check this rule, then check against @@ -1536,43 +1510,45 @@ struct sock *newsk = NULL; int error; + lock_sock(sk); + /* We need to make sure that this socket is listening, * and that it has something pending. */ error = EINVAL; if (sk->state != TCP_LISTEN) - goto no_listen; - - lock_sock(sk); + goto out; + /* Find already established connection */ req = tcp_find_established(tp, &prev); - if (req) { -got_new_connect: - tcp_synq_unlink(tp, req, prev); - newsk = req->sk; - tcp_openreq_free(req); - sk->ack_backlog--; - /* FIXME: need to check here if socket has already - * an soft_err or err set. - * We have two options here then: reply (this behaviour matches - * Solaris) or return the error to the application (old Linux) - */ - error = 0; -out: - release_sock(sk); -no_listen: - sk->err = error; - return newsk; + if (!req) { + /* If this is a non blocking socket don't sleep */ + error = EAGAIN; + if (flags & O_NONBLOCK) + goto out; + + error = ERESTARTSYS; + req = wait_for_connect(sk, &prev); + if (!req) + goto out; + error = 0; } - error = EAGAIN; - if (flags & O_NONBLOCK) - goto out; - req = wait_for_connect(sk, &prev); - if (req) - goto got_new_connect; - error = ERESTARTSYS; - goto out; + tcp_synq_unlink(tp, req, prev); + newsk = req->sk; + tcp_openreq_free(req); + sk->ack_backlog--; /* XXX */ + + /* FIXME: need to check here if newsk has already + * an soft_err or err set. + * We have two options here then: reply (this behaviour matches + * Solaris) or return the error to the application (old Linux) + */ + error = 0; + out: + release_sock(sk); + sk->err = error; + return newsk; } /* diff -u --recursive --new-file v2.1.79/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.1.79/linux/net/ipv4/tcp_input.c Mon Jan 12 22:09:25 1998 +++ linux/net/ipv4/tcp_input.c Sun Jan 18 12:28:34 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.65 1997/12/13 21:52:58 kuznet Exp $ + * Version: $Id: tcp_input.c,v 1.66 1998/01/15 22:40:29 freitag Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -41,6 +41,7 @@ * next packet on ack of previous packet. * Andi Kleen : Moved open_request checking here * and process RSTs for open_requests. + * Andi Kleen : Better prune_queue, and other fixes. */ #include @@ -73,7 +74,6 @@ int sysctl_tcp_timestamps; int sysctl_tcp_window_scaling; int sysctl_tcp_syncookies = SYNC_INIT; -int sysctl_tcp_max_delay_acks = MAX_DELAY_ACK; int sysctl_tcp_stdurg; static tcp_sys_cong_ctl_t tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj; @@ -379,6 +379,7 @@ */ static __inline__ int tcp_fast_parse_options(struct tcphdr *th, struct tcp_opt *tp) { + /* If we didn't send out any options ignore them all */ if (tp->tcp_header_len == sizeof(struct tcphdr)) return 0; if (th->doff == sizeof(struct tcphdr)>>2) { @@ -744,8 +745,10 @@ if (after(skb->end_seq, ack)) break; +#if 0 SOCK_DEBUG(sk, "removing seg %x-%x from retransmit queue\n", skb->seq, skb->end_seq); +#endif acked = FLAG_DATA_ACKED; @@ -1057,13 +1060,12 @@ struct sk_buff *skb; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - /* FIXME: out_of_order_queue is a strong tcp_opt candidate... -DaveM */ while ((skb = skb_peek(&sk->out_of_order_queue))) { if (after(skb->seq, tp->rcv_nxt)) break; if (!after(skb->end_seq, tp->rcv_nxt)) { - SOCK_DEBUG(sk, "ofo packet was allready received \n"); + SOCK_DEBUG(sk, "ofo packet was already received \n"); skb_unlink(skb); kfree_skb(skb, FREE_READ); continue; @@ -1088,7 +1090,7 @@ */ if (skb->seq == tp->rcv_nxt) { /* Ok. In sequence. */ -queue_and_out: + queue_and_out: dst_confirm(sk->dst_cache); skb_queue_tail(&sk->receive_queue, skb); tp->rcv_nxt = skb->end_seq; @@ -1098,12 +1100,12 @@ return; } - /* Not in sequence, either a retransmit or some packet got lost. */ + /* An old packet, either a retransmit or some packet got lost. */ if (!after(skb->end_seq, tp->rcv_nxt)) { /* A retransmit, 2nd most common case. Force an imediate ack. */ SOCK_DEBUG(sk, "retransmit received: seq %X\n", skb->seq); - tp->delayed_acks = sysctl_tcp_max_delay_acks; + tp->delayed_acks = MAX_DELAY_ACK; kfree_skb(skb, FREE_READ); return; } @@ -1117,7 +1119,7 @@ } /* Ok. This is an out_of_order segment, force an ack. */ - tp->delayed_acks = sysctl_tcp_max_delay_acks; + tp->delayed_acks = MAX_DELAY_ACK; /* Disable header predition. */ tp->pred_flags = 0; @@ -1224,7 +1226,10 @@ } } -static __inline__ void tcp_ack_snd_check(struct sock *sk) +/* + * Check if sending an ack is needed. + */ +static __inline__ void __tcp_ack_snd_check(struct sock *sk) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); @@ -1236,17 +1241,24 @@ * - we don't have a window update to send * - must send at least every 2 full sized packets */ - if (tp->delayed_acks == 0) { - /* We sent a data segment already. */ - return; - } - if (tp->delayed_acks >= sysctl_tcp_max_delay_acks || tcp_raise_window(sk)) + if (tp->delayed_acks >= MAX_DELAY_ACK || tcp_raise_window(sk)) tcp_send_ack(sk); else tcp_send_delayed_ack(sk, HZ/2); } +static __inline__ void tcp_ack_snd_check(struct sock *sk) +{ + struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); + if (tp->delayed_acks == 0) { + /* We sent a data segment already. */ + return; + } + __tcp_ack_snd_check(sk); +} + + /* * This routine is only called when we have urgent data * signalled. Its the 'slow' part of tcp_urg. It could be @@ -1317,13 +1329,43 @@ } } +/* + * Clean first the out_of_order queue, then the receive queue until + * the socket is in its memory limits again. + */ static void prune_queue(struct sock *sk) { + struct tcp_opt *tp; struct sk_buff * skb; - /* Clean the out_of_order queue. */ - while ((skb = skb_dequeue(&sk->out_of_order_queue))) + SOCK_DEBUG(sk, "prune_queue: c=%x\n", sk->copied_seq); + + /* First Clean the out_of_order queue. */ + /* Start with the end because there are probably the least + * useful packets (crossing fingers). + */ + while ((skb = skb_dequeue_tail(&sk->out_of_order_queue))) { kfree_skb(skb, FREE_READ); + if (atomic_read(&sk->rmem_alloc) <= sk->rcvbuf) + return; + } + + tp = &sk->tp_pinfo.af_tcp; + + /* Now continue with the receive queue if it wasn't enough */ + while ((skb = skb_peek_tail(&sk->receive_queue))) { + /* Never remove packets that have been already acked */ + if (before(skb->end_seq, tp->last_ack_sent+1)) { + printk(KERN_DEBUG "prune_queue: hit acked data c=%x,%x,%x\n", + sk->copied_seq, skb->end_seq, tp->last_ack_sent); + break; + } + skb_unlink(skb); + tp->rcv_nxt = skb->seq; + kfree_skb(skb, FREE_READ); + if (atomic_read(&sk->rmem_alloc) <= sk->rcvbuf) + break; + } } int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, @@ -1356,8 +1398,7 @@ if (tcp_paws_discard(tp)) { if (!th->rst) { tcp_send_ack(sk); - kfree_skb(skb, FREE_READ); - return 0; + goto discard; } } tcp_replace_ts_recent(tp,skb->end_seq); @@ -1378,18 +1419,22 @@ if (len <= th->doff*4) { /* Bulk data transfer: sender */ if (len == th->doff*4) { - tcp_ack(sk, th, skb->seq, skb->ack_seq, len); + tcp_ack(sk, th, skb->seq, skb->ack_seq, len); + kfree_skb(skb, FREE_READ); tcp_data_snd_check(sk); + return 0; + } else { /* Header too small */ + tcp_statistics.TcpInErrs++; + goto discard; } - - tcp_statistics.TcpInErrs++; - kfree_skb(skb, FREE_READ); - return 0; } else if (skb->ack_seq == tp->snd_una) { /* Bulk data transfer: receiver */ - skb_pull(skb,th->doff*4); + if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf) + goto discard; + skb_pull(skb,th->doff*4); + /* DO NOT notify forward progress here. * It saves dozen of CPU instructions in fast path. --ANK */ @@ -1399,10 +1444,15 @@ sk->data_ready(sk, 0); tcp_delack_estimator(tp); +#if 1 /* This checks for required window updates too. */ + tp->delayed_acks++; + __tcp_ack_snd_check(sk); +#else if (tp->delayed_acks++ == 0) tcp_send_delayed_ack(sk, HZ/2); else tcp_send_ack(sk); +#endif return 0; } } @@ -1415,8 +1465,7 @@ tp->rcv_wup, tp->rcv_wnd); } tcp_send_ack(sk); - kfree_skb(skb, FREE_READ); - return 0; + goto discard; } } @@ -1429,10 +1478,9 @@ if(th->rst) { tcp_reset(sk,skb); - kfree_skb(skb, FREE_READ); - return 0; + goto discard; } - + if(th->ack) tcp_ack(sk, th, skb->seq, skb->ack_seq, len); @@ -1447,16 +1495,17 @@ (void) tcp_fin(skb, sk, th); tcp_data_snd_check(sk); - tcp_ack_snd_check(sk); - /* If our receive queue has grown past its limits, - * try to prune away duplicates etc.. - */ + /* If our receive queue has grown past its limits shrink it */ if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf) prune_queue(sk); - if (!queued) + tcp_ack_snd_check(sk); + + if (!queued) { + discard: kfree_skb(skb, FREE_READ); + } return 0; } @@ -1860,8 +1909,12 @@ } } - case TCP_ESTABLISHED: + case TCP_ESTABLISHED: queued = tcp_data(skb, sk, len); + + /* This can only happen when MTU+skbheader > rcvbuf */ + if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf) + prune_queue(sk); break; } @@ -1886,22 +1939,20 @@ { int val = sysctl_tcp_cong_avoidance; int retv; + static tcp_sys_cong_ctl_t tab[] = { + tcp_cong_avoid_vanj, + tcp_cong_avoid_vegas + }; retv = proc_dointvec(ctl, write, filp, buffer, lenp); if (write) { - switch (sysctl_tcp_cong_avoidance) { - case 0: - tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj; - break; - case 1: - tcp_sys_cong_ctl_f = &tcp_cong_avoid_vegas; - break; - default: + if ((unsigned)sysctl_tcp_cong_avoidance > 1) { retv = -EINVAL; sysctl_tcp_cong_avoidance = val; - }; + } else { + tcp_sys_cong_ctl_f = tab[sysctl_tcp_cong_avoidance]; + } } - return retv; } diff -u --recursive --new-file v2.1.79/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.79/linux/net/ipv4/tcp_ipv4.c Mon Jan 12 22:09:25 1998 +++ linux/net/ipv4/tcp_ipv4.c Sun Jan 18 12:28:35 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.77 1997/12/13 21:53:00 kuznet Exp $ + * Version: $Id: tcp_ipv4.c,v 1.79 1998/01/15 22:40:47 freitag Exp $ * * IPv4 specific functions * @@ -41,6 +41,7 @@ * Added new listen sematics (ifdefed by * NEW_LISTEN for now) * Juan Jose Ciarlante: ip_dynaddr bits + * Andi Kleen: various fixes. */ #include @@ -809,8 +810,11 @@ * dropped. This is the new "fast" path mtu * discovery. */ - if (!sk->sock_readers) + if (!sk->sock_readers) { + lock_sock(sk); tcp_simple_retransmit(sk); + release_sock(sk); + } /* else let the usual retransmit timer handle it */ } } } @@ -822,6 +826,12 @@ * it's just the icmp type << 8 | icmp code. After adjustment * header points to the first 8 bytes of the tcp header. We need * to find the appropriate port. + * + * The locking strategy used here is very "optimistic". When + * someone else accesses the socket the ICMP is just dropped + * and for some paths there is no check at all. + * A more general error queue to queue errors for later handling + * is probably better. */ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len) @@ -865,13 +875,15 @@ switch (type) { case ICMP_SOURCE_QUENCH: +#ifndef OLD_SOURCE_QUENCH /* This is deprecated */ tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2); tp->snd_cwnd = tp->snd_ssthresh; tp->high_seq = tp->snd_nxt; +#endif return; case ICMP_PARAMETERPROB: sk->err=EPROTO; - sk->error_report(sk); + sk->error_report(sk); /* This isn't serialized on SMP! */ break; case ICMP_DEST_UNREACH: if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ @@ -901,7 +913,7 @@ */ return; } - + if (!th->syn && !th->ack) return; req = tcp_v4_search_req(tp, iph, th, &prev); @@ -931,6 +943,7 @@ } if(icmp_err_convert[code].fatal || opening) { + /* This code isn't serialized with the socket code */ sk->err = icmp_err_convert[code].errno; if (opening) { tcp_statistics.TcpAttemptFails++; @@ -1111,8 +1124,7 @@ static void tcp_v4_or_free(struct open_request *req) { if(!req->sk && req->af.v4_req.opt) - kfree_s(req->af.v4_req.opt, - sizeof(struct ip_options) + req->af.v4_req.opt->optlen); + kfree_s(req->af.v4_req.opt, optlength(req->af.v4_req.opt)); } static inline void syn_flood_warning(struct sk_buff *skb) @@ -1127,6 +1139,28 @@ } } +/* + * Save and compile IPv4 options into the open_request if needed. + */ +static inline struct ip_options * +tcp_v4_save_options(struct sock *sk, struct sk_buff *skb, + struct ip_options *opt) +{ + struct ip_options *dopt = NULL; + + if (opt && opt->optlen) { + int opt_size = optlength(opt); + dopt = kmalloc(opt_size, GFP_ATOMIC); + if (dopt) { + if (ip_options_echo(dopt, skb)) { + kfree_s(dopt, opt_size); + dopt = NULL; + } + } + } + return dopt; +} + int sysctl_max_syn_backlog = 1024; int sysctl_tcp_syn_taildrop = 1; @@ -1147,7 +1181,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr, __u32 isn) { - struct ip_options *opt = (struct ip_options *) ptr; struct tcp_opt tp; struct open_request *req; struct tcphdr *th = skb->h.th; @@ -1217,20 +1250,8 @@ req->snt_isn = isn; - /* IPv4 options */ - req->af.v4_req.opt = NULL; + req->af.v4_req.opt = tcp_v4_save_options(sk, skb, ptr); - if (opt && opt->optlen) { - int opt_size = sizeof(struct ip_options) + opt->optlen; - - req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC); - if (req->af.v4_req.opt) { - if (ip_options_echo(req->af.v4_req.opt, skb)) { - kfree_s(req->af.v4_req.opt, opt_size); - req->af.v4_req.opt = NULL; - } - } - } req->class = &or_ipv4; req->retrans = 0; req->sk = NULL; @@ -1238,26 +1259,27 @@ tcp_v4_send_synack(sk, req); if (want_cookie) { - if (req->af.v4_req.opt) - kfree(req->af.v4_req.opt); + if (req->af.v4_req.opt) + kfree(req->af.v4_req.opt); + tcp_v4_or_free(req); tcp_openreq_free(req); - } else { + } else { req->expires = jiffies + TCP_TIMEOUT_INIT; tcp_inc_slow_timer(TCP_SLT_SYNACK); tcp_synq_queue(&sk->tp_pinfo.af_tcp, req); } sk->data_ready(sk, 0); -exit: return 0; dead: SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n",sk); tcp_statistics.TcpAttemptFails++; - return -ENOTCONN; + return -ENOTCONN; /* send reset */ + error: tcp_statistics.TcpAttemptFails++; - goto exit; + return 0; } struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, @@ -1283,7 +1305,7 @@ /* Or else we die! -DaveM */ newsk->sklist_next = NULL; - newsk->opt = req->af.v4_req.opt; + newsk->opt = req->af.v4_req.opt; skb_queue_head_init(&newsk->write_queue); skb_queue_head_init(&newsk->receive_queue); @@ -1468,7 +1490,13 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) { - skb_set_owner_r(skb, sk); +#ifdef CONFIG_FILTER + if (sk->filter) + { + if (sk_filter(skb, sk->filter_data, sk->filter)) + goto discard; + } +#endif /* CONFIG_FILTER */ /* * socket locking is here for SMP purposes as backlog rcv @@ -1476,6 +1504,13 @@ */ lock_sock(sk); + /* + * This doesn't check if the socket has enough room for the packet. + * Either process the packet _without_ queueing it and then free it, + * or do the check later. + */ + skb_set_owner_r(skb, sk); + if (sk->state == TCP_ESTABLISHED) { /* Fast path */ if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) goto reset; @@ -1495,8 +1530,7 @@ sk = nsk; } - if (tcp_rcv_state_process(sk, skb, skb->h.th, - &(IPCB(skb)->opt), skb->len)) + if (tcp_rcv_state_process(sk, skb, skb->h.th, &(IPCB(skb)->opt), skb->len)) goto reset; release_sock(sk); return 0; diff -u --recursive --new-file v2.1.79/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.1.79/linux/net/ipv4/tcp_output.c Mon Dec 1 12:04:17 1997 +++ linux/net/ipv4/tcp_output.c Sun Jan 18 12:28:34 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.50 1997/10/15 19:13:02 freitag Exp $ + * Version: $Id: tcp_output.c,v 1.51 1998/01/15 22:40:39 freitag Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -87,40 +87,12 @@ tp->retransmits == 0); } -static __inline__ void tcp_build_options(__u32 *ptr, struct tcp_opt *tp) -{ - /* FIXME: We will still need to do SACK here. */ - if (tp->tstamp_ok) { - *ptr++ = ntohl((TCPOPT_NOP << 24) - | (TCPOPT_NOP << 16) - | (TCPOPT_TIMESTAMP << 8) - | TCPOLEN_TIMESTAMP); - /* WARNING: If HZ is ever larger than 1000 on some system, - * then we will be violating RFC1323 here because our timestamps - * will be moving too fast. - * FIXME: code TCP so it uses at most ~ 1000 ticks a second? - * (I notice alpha is 1024 ticks now). -- erics - */ - *ptr++ = htonl(jiffies); - *ptr = htonl(tp->ts_recent); - } -} - -static __inline__ void tcp_update_options(__u32 *ptr, struct tcp_opt *tp) -{ - /* FIXME: We will still need to do SACK here. */ - if (tp->tstamp_ok) { - *++ptr = htonl(jiffies); - *++ptr = htonl(tp->ts_recent); - } -} - /* * This is the main buffer sending routine. We queue the buffer * having checked it is sane seeming. */ -int tcp_send_skb(struct sock *sk, struct sk_buff *skb) +void tcp_send_skb(struct sock *sk, struct sk_buff *skb) { struct tcphdr * th = skb->h.th; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); @@ -135,7 +107,7 @@ "(skb = %p, data = %p, th = %p, len = %u)\n", skb, skb->data, th, skb->len); kfree_skb(skb, FREE_WRITE); - return 0; + return; } /* If we have queued a header size packet.. (these crash a few @@ -147,7 +119,7 @@ if(!th->syn && !th->fin) { printk(KERN_DEBUG "tcp_send_skb: attempt to queue a bogon.\n"); kfree_skb(skb,FREE_WRITE); - return 0; + return; } } @@ -161,7 +133,8 @@ struct sk_buff * buff; /* This is going straight out. */ - tp->last_ack_sent = th->ack_seq = htonl(tp->rcv_nxt); + tp->last_ack_sent = tp->rcv_nxt; + th->ack_seq = htonl(tp->rcv_nxt); th->window = htons(tcp_select_window(sk)); tcp_update_options((__u32 *)(th+1),tp); @@ -185,7 +158,7 @@ if (!tcp_timer_is_set(sk, TIME_RETRANS)) tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto); - return 0; + return; } queue: @@ -196,7 +169,7 @@ tp->pending = TIME_PROBE0; tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto); } - return 0; + return; } /* @@ -468,7 +441,7 @@ { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; int mss = sk->mss; - long free_space = sock_rspace(sk)/2; + long free_space = sock_rspace(sk) / 2; long window, cur_win; if (tp->window_clamp) { @@ -714,7 +687,7 @@ break; } - SOCK_DEBUG(sk, "retransmit sending\n"); + SOCK_DEBUG(sk, "retransmit sending seq=%x\n", skb->seq); /* Update ack and window. */ tp->last_ack_sent = th->ack_seq = htonl(tp->rcv_nxt); @@ -817,6 +790,9 @@ /* The fin can only be transmited after the data. */ skb_queue_tail(&sk->write_queue, buff); if (tp->send_head == NULL) { + /* FIXME: BUG! we need to check if the fin fits into the window + * here. If not we need to do window probing (sick, but true) + */ struct sk_buff *skb1; tp->packets_out++; @@ -985,13 +961,16 @@ /* Swap the send and the receive. */ th->window = ntohs(tcp_select_window(sk)); th->seq = ntohl(tp->snd_nxt); - tp->last_ack_sent = th->ack_seq = ntohl(tp->rcv_nxt); + tp->last_ack_sent = tp->rcv_nxt; + th->ack_seq = htonl(tp->rcv_nxt); /* Fill in the packet and send it. */ tp->af_specific->send_check(sk, th, tp->tcp_header_len, buff); +#if 0 SOCK_DEBUG(sk, "\rtcp_send_ack: seq %x ack %x\n", tp->snd_nxt, tp->rcv_nxt); +#endif tp->af_specific->queue_xmit(buff); tcp_statistics.TcpOutSegs++; @@ -1103,9 +1082,6 @@ void tcp_send_probe0(struct sock *sk) { struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - - if (sk->zapped) - return; /* After a valid reset we can send no more. */ tcp_write_wakeup(sk); tp->pending = TIME_PROBE0; diff -u --recursive --new-file v2.1.79/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c --- v2.1.79/linux/net/ipv6/ndisc.c Mon Jan 12 22:09:25 1998 +++ linux/net/ipv6/ndisc.c Thu Jan 15 14:33:07 1998 @@ -1199,7 +1199,9 @@ void ndisc_cleanup(void) { #ifdef CONFIG_PROC_FS +#ifndef CONFIG_RTNETLINK proc_net_unregister(ndisc_proc_entry.low_ino); +#endif #endif neigh_table_clear(&nd_tbl); } diff -u --recursive --new-file v2.1.79/linux/net/netsyms.c linux/net/netsyms.c --- v2.1.79/linux/net/netsyms.c Mon Jan 12 22:09:26 1998 +++ linux/net/netsyms.c Tue Jan 20 16:45:15 1998 @@ -121,6 +121,10 @@ EXPORT_SYMBOL(sock_kmalloc); EXPORT_SYMBOL(sock_kfree_s); +#ifdef CONFIG_FILTER +EXPORT_SYMBOL(sk_run_filter); +#endif + EXPORT_SYMBOL(neigh_table_init); EXPORT_SYMBOL(neigh_table_clear); EXPORT_SYMBOL(__neigh_lookup); @@ -283,20 +287,27 @@ EXPORT_SYMBOL(tcp_simple_retransmit); EXPORT_SYMBOL(xrlim_allow); -EXPORT_SYMBOL(dev_mc_delete); +#endif + +#ifdef CONFIG_RTNETLINK +EXPORT_SYMBOL(rtnetlink_links); +EXPORT_SYMBOL(__rta_fill); +EXPORT_SYMBOL(rtnetlink_dump_ifinfo); +EXPORT_SYMBOL(netlink_set_err); +EXPORT_SYMBOL(netlink_broadcast); +EXPORT_SYMBOL(rtnl_wlockct); +EXPORT_SYMBOL(rtnl); +EXPORT_SYMBOL(neigh_delete); +EXPORT_SYMBOL(neigh_add); +EXPORT_SYMBOL(neigh_dump_info); #endif #ifdef CONFIG_PACKET_MODULE EXPORT_SYMBOL(dev_set_allmulti); EXPORT_SYMBOL(dev_set_promiscuity); -EXPORT_SYMBOL(dev_mc_delete); EXPORT_SYMBOL(sklist_remove_socket); EXPORT_SYMBOL(rtnl_wait); EXPORT_SYMBOL(rtnl_rlockct); -#ifdef CONFIG_RTNETLINK -EXPORT_SYMBOL(rtnl); -EXPORT_SYMBOL(rtnl_wlockct); -#endif #endif #if defined(CONFIG_IPV6_MODULE) || defined(CONFIG_PACKET_MODULE) @@ -379,6 +390,7 @@ EXPORT_SYMBOL(kill_fasync); EXPORT_SYMBOL(ip_rcv); EXPORT_SYMBOL(arp_rcv); +EXPORT_SYMBOL(dev_mc_delete); EXPORT_SYMBOL(rtnl_lock); EXPORT_SYMBOL(rtnl_unlock); diff -u --recursive --new-file v2.1.79/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c --- v2.1.79/linux/net/sunrpc/sched.c Mon Jan 12 22:09:26 1998 +++ linux/net/sunrpc/sched.c Mon Jan 19 13:57:37 1998 @@ -46,6 +46,11 @@ static struct rpc_wait_queue childq = RPC_INIT_WAITQ("childq"); /* + * RPC tasks sit here while waiting for conditions to improve. + */ +static struct rpc_wait_queue delay_queue = RPC_INIT_WAITQ("delayq"); + +/* * All RPC tasks are linked into this list */ static struct rpc_task * all_tasks = NULL; @@ -318,8 +323,6 @@ void rpc_delay(struct rpc_task *task, unsigned long delay) { - static struct rpc_wait_queue delay_queue; - task->tk_timeout = delay; rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); } @@ -440,10 +443,15 @@ static int executing = 0; int incr = RPC_IS_ASYNC(task)? 1 : 0; - if (incr && (executing || rpc_inhibit)) { - printk("RPC: rpc_execute called recursively!\n"); - return; + if (incr) { + if (rpc_inhibit) { + printk("RPC: execution inhibited!\n"); + return; + } + if (executing) + printk("RPC: %d tasks executed\n", executing); } + executing += incr; __rpc_execute(task); executing -= incr; @@ -712,6 +720,7 @@ save_flags(oldflags); cli(); rpc_make_runnable(child); restore_flags(oldflags); + /* N.B. Is it possible for the child to have already finished? */ rpc_sleep_on(&childq, task, func, NULL); } @@ -725,6 +734,7 @@ struct rpc_task **q, *rovr; dprintk("RPC: killing all tasks for client %p\n", clnt); + /* N.B. Why bother to inhibit? Nothing blocks here ... */ rpc_inhibit++; for (q = &all_tasks; (rovr = *q); q = &rovr->tk_next_task) { if (!clnt || rovr->tk_client == clnt) { @@ -917,14 +927,16 @@ if (!t) return; - printk("-pid- proc flgs status -client- --rqstp- -timeout " + printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " "-rpcwait -action- --exit--\n"); for (; t; t = next) { next = t->tk_next_task; - printk("%05d %04d %04x %06d %8p %8p %08ld %8p %8p %8p\n", + printk("%05d %04d %04x %06d %8p %6d %8p %08ld %8s %8p %8p\n", t->tk_pid, t->tk_proc, t->tk_flags, t->tk_status, - t->tk_client, t->tk_rqstp, t->tk_timeout, - t->tk_rpcwait, t->tk_action, t->tk_exit); + t->tk_client, t->tk_client->cl_prog, + t->tk_rqstp, t->tk_timeout, + t->tk_rpcwait ? rpc_qname(t->tk_rpcwait) : " ", + t->tk_action, t->tk_exit); if (!(t->tk_flags & RPC_TASK_NFSWRITE)) continue; diff -u --recursive --new-file v2.1.79/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c --- v2.1.79/linux/net/sunrpc/svcsock.c Sun Dec 21 16:17:45 1997 +++ linux/net/sunrpc/svcsock.c Sat Jan 17 12:32:42 1998 @@ -131,10 +131,10 @@ { struct svc_sock *svsk; - disable_bh(NET_BH); + start_bh_atomic(); if ((svsk = serv->sv_sockets) != NULL) rpc_remove_list(&serv->sv_sockets, svsk); - enable_bh(NET_BH); + end_bh_atomic(); if (svsk) { dprintk("svc: socket %p dequeued\n", svsk->sk_sk); @@ -151,7 +151,7 @@ static inline void svc_sock_received(struct svc_sock *svsk, int count) { - disable_bh(NET_BH); + start_bh_atomic(); if ((svsk->sk_data -= count) < 0) { printk(KERN_NOTICE "svc: sk_data negative!\n"); svsk->sk_data = 0; @@ -163,7 +163,7 @@ svsk->sk_sk); svc_sock_enqueue(svsk); } - enable_bh(NET_BH); + end_bh_atomic(); } /* @@ -172,7 +172,7 @@ static inline void svc_sock_accepted(struct svc_sock *svsk) { - disable_bh(NET_BH); + start_bh_atomic(); svsk->sk_busy = 0; svsk->sk_conn--; if (svsk->sk_conn || svsk->sk_data || svsk->sk_close) { @@ -180,7 +180,7 @@ svsk->sk_sk); svc_sock_enqueue(svsk); } - enable_bh(NET_BH); + end_bh_atomic(); } /* @@ -739,9 +739,9 @@ if (signalled()) return -EINTR; - disable_bh(NET_BH); + start_bh_atomic(); if ((svsk = svc_sock_dequeue(serv)) != NULL) { - enable_bh(NET_BH); + end_bh_atomic(); rqstp->rq_sock = svsk; svsk->sk_inuse++; /* N.B. where is this decremented? */ } else { @@ -756,7 +756,7 @@ */ current->state = TASK_INTERRUPTIBLE; add_wait_queue(&rqstp->rq_wait, &wait); - enable_bh(NET_BH); + end_bh_atomic(); schedule(); if (!(svsk = rqstp->rq_sock)) { diff -u --recursive --new-file v2.1.79/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c --- v2.1.79/linux/net/sunrpc/xprt.c Tue Dec 2 09:49:41 1997 +++ linux/net/sunrpc/xprt.c Sat Jan 17 12:33:41 1998 @@ -397,14 +397,14 @@ task->tk_pid, status, xprt->connected); task->tk_timeout = 60 * HZ; - disable_bh(NET_BH); + start_bh_atomic(); if (!xprt->connected) { rpc_sleep_on(&xprt->reconn, task, xprt_reconn_status, xprt_reconn_timeout); - enable_bh(NET_BH); + end_bh_atomic(); return; } - enable_bh(NET_BH); + end_bh_atomic(); } xprt->connecting = 0; @@ -870,10 +870,10 @@ /* For fast networks/servers we have to put the request on * the pending list now: */ - disable_bh(NET_BH); + start_bh_atomic(); rpc_add_wait_queue(&xprt->pending, task); task->tk_callback = NULL; - enable_bh(NET_BH); + end_bh_atomic(); /* Continue transmitting the packet/record. We must be careful * to cope with writespace callbacks arriving _after_ we have @@ -891,16 +891,16 @@ task->tk_pid, xprt->snd_buf.io_len, req->rq_slen); task->tk_status = 0; - disable_bh(NET_BH); + start_bh_atomic(); if (!xprt->write_space) { /* Remove from pending */ rpc_remove_wait_queue(task); rpc_sleep_on(&xprt->sending, task, xprt_transmit_status, NULL); - enable_bh(NET_BH); + end_bh_atomic(); return; } - enable_bh(NET_BH); + end_bh_atomic(); } } @@ -943,12 +943,12 @@ */ task->tk_timeout = req->rq_timeout.to_current; - disable_bh(NET_BH); + start_bh_atomic(); if (!req->rq_gotit) { rpc_sleep_on(&xprt->pending, task, xprt_receive_status, xprt_timer); } - enable_bh(NET_BH); + end_bh_atomic(); dprintk("RPC: %4d xprt_receive returns %d\n", task->tk_pid, task->tk_status); @@ -1079,7 +1079,7 @@ dprintk("RPC: %4d release request %p\n", task->tk_pid, req); /* remove slot from queue of pending */ - disable_bh(NET_BH); + start_bh_atomic(); if (task->tk_rpcwait) { printk("RPC: task of released request still queued!\n"); #ifdef RPC_DEBUG @@ -1088,7 +1088,7 @@ rpc_del_timer(task); rpc_remove_wait_queue(task); } - enable_bh(NET_BH); + end_bh_atomic(); /* Decrease congestion value. If congestion threshold is not yet * reached, pass on the request slot. diff -u --recursive --new-file v2.1.79/linux/scripts/patch-kernel linux/scripts/patch-kernel --- v2.1.79/linux/scripts/patch-kernel Tue Mar 26 11:22:14 1996 +++ linux/scripts/patch-kernel Sat Jan 17 13:38:29 1998 @@ -11,6 +11,11 @@ # successful. If it is, then all of the "*.orig" files are removed. # # Nick Holloway , 2nd January 1995. +# +# Added support for handling multiple types of compression. What includes +# gzip, bzip, bzip2, zip, compress, and plaintext. +# +# Adam Sulmicki , 1st January 1997. # Set directories from arguments, or use defaults. sourcedir=${1-/usr/src/linux} @@ -29,16 +34,39 @@ while : do SUBLEVEL=`expr $SUBLEVEL + 1` - patch=patch-$VERSION.$PATCHLEVEL.$SUBLEVEL.gz - if [ ! -r $patchdir/$patch ] - then - break + patch=patch-$VERSION.$PATCHLEVEL.$SUBLEVEL + if [ -r $patchdir/${patch}.gz ]; then + ext=".gz" + name="gzip" + uncomp="gunzip -dc" + elif [ -r $patchdir/${patch}.bz ]; then + ext=".bz" + name="bzip" + uncomp="bunzip -dc" + elif [ -r $patchdir/${patch}.bz2 ]; then + ext=".bz2" + name="bzip2" + uncomp="bunzip2 -dc" + elif [ -r $patchdir/${patch}.zip ]; then + ext=".zip" + name="zip" + uncomp="unzip -d" + elif [ -r $patchdir/${patch}.Z ]; then + ext=".Z" + name="uncompress" + uncomp="uncompress -c" + elif [ -r $patchdir/${patch} ]; then + ext="" + name="plaintext" + uncomp="cat" + else + break fi - echo -n "Applying $patch... " - if gunzip -dc $patchdir/$patch | patch -p1 -s -N -E -d $sourcedir + echo -n "Applying ${patch} (${name})... " + if $uncomp ${patchdir}/${patch}${ext} | patch -p1 -s -N -E -d $sourcedir then - echo "done." + echo "done." else echo "failed. Clean up yourself." break