summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/Makefile12
-rw-r--r--arch/alpha/config.in15
-rw-r--r--arch/alpha/kernel/core_cia.c13
-rw-r--r--arch/alpha/kernel/pci.c214
-rw-r--r--arch/alpha/kernel/pci_iommu.c4
-rw-r--r--arch/alpha/kernel/sys_ruffian.c4
-rw-r--r--arch/alpha/lib/Makefile65
-rw-r--r--arch/alpha/lib/checksum.c32
-rw-r--r--arch/alpha/lib/csum_partial_copy.c35
-rw-r--r--arch/alpha/lib/ev6-clear_user.S228
-rw-r--r--arch/alpha/lib/ev6-copy_user.S262
-rw-r--r--arch/alpha/lib/ev6-csum_ipv6_magic.S126
-rw-r--r--arch/alpha/lib/ev6-divide.S259
-rw-r--r--arch/alpha/lib/ev6-memchr.S191
-rw-r--r--arch/alpha/lib/ev6-memcpy.S248
-rw-r--r--arch/alpha/lib/ev6-memset.S596
-rw-r--r--arch/alpha/lib/ev6-strncpy_from_user.S425
-rw-r--r--arch/alpha/lib/ev6-stxcpy.S321
-rw-r--r--arch/alpha/lib/ev6-stxncpy.S399
-rw-r--r--arch/alpha/lib/ev67-strcat.S54
-rw-r--r--arch/alpha/lib/ev67-strchr.S88
-rw-r--r--arch/alpha/lib/ev67-strlen.S49
-rw-r--r--arch/alpha/lib/ev67-strlen_user.S109
-rw-r--r--arch/alpha/lib/ev67-strncat.S94
-rw-r--r--arch/alpha/lib/memcpy.c21
-rw-r--r--arch/alpha/lib/memmove.S103
-rw-r--r--arch/alpha/lib/strcpy.S1
-rw-r--r--arch/alpha/lib/strncpy.S4
-rw-r--r--arch/alpha/lib/stxcpy.S3
-rw-r--r--arch/alpha/lib/stxncpy.S3
-rw-r--r--arch/alpha/mm/init.c2
-rw-r--r--arch/arm/boot/Makefile22
-rw-r--r--arch/arm/boot/compressed/Makefile6
-rw-r--r--arch/arm/def-configs/a5k435
-rw-r--r--arch/arm/def-configs/assabet94
-rw-r--r--arch/arm/def-configs/brutus36
-rw-r--r--arch/arm/def-configs/cerf85
-rw-r--r--arch/arm/def-configs/ebsa110135
-rw-r--r--arch/arm/def-configs/footbridge767
-rw-r--r--arch/arm/def-configs/graphicsclient486
-rw-r--r--arch/arm/def-configs/integrator511
-rw-r--r--arch/arm/def-configs/neponset576
-rw-r--r--arch/arm/def-configs/pangolin (renamed from arch/arm/def-configs/thinclient)389
-rw-r--r--arch/arm/def-configs/rpc493
-rw-r--r--arch/arm/def-configs/sherman210
-rw-r--r--arch/arm/kernel/bios32.c22
-rw-r--r--arch/arm/kernel/dec21285.c10
-rw-r--r--arch/arm/kernel/dma-arc.c4
-rw-r--r--arch/arm/kernel/entry-armv.S152
-rw-r--r--arch/arm/kernel/fiq.c18
-rw-r--r--arch/arm/kernel/head-armo.S1
-rw-r--r--arch/arm/kernel/head-armv.S31
-rw-r--r--arch/arm/kernel/oldlatches.c10
-rw-r--r--arch/arm/kernel/traps.c181
-rw-r--r--arch/arm/kernel/via82c505.c2
-rw-r--r--arch/arm/lib/Makefile32
-rw-r--r--arch/arm/lib/ecard.S47
-rw-r--r--arch/arm/lib/io-acorn.S549
-rw-r--r--arch/arm/lib/io-ebsa110.S169
-rw-r--r--arch/arm/lib/io-footbridge.S202
-rw-r--r--arch/arm/lib/io-pcio.S38
-rw-r--r--arch/arm/lib/io-readsb.S111
-rw-r--r--arch/arm/lib/io-readsl.S65
-rw-r--r--arch/arm/lib/io-readsw-armv3.S102
-rw-r--r--arch/arm/lib/io-readsw-armv4.S87
-rw-r--r--arch/arm/lib/io-writesb.S115
-rw-r--r--arch/arm/lib/io-writesl.S55
-rw-r--r--arch/arm/lib/io-writesw-armv3.S125
-rw-r--r--arch/arm/lib/io-writesw-armv4.S79
-rw-r--r--arch/arm/mach-footbridge/netwinder-hw.c6
-rw-r--r--arch/arm/mm/fault-common.c50
-rw-r--r--arch/arm/mm/init.c45
-rw-r--r--arch/arm/mm/mm-armv.c2
-rw-r--r--arch/arm/mm/proc-arm720.S35
-rw-r--r--arch/arm/nwfpe/double_cpdo.c4
-rw-r--r--arch/arm/nwfpe/extended_cpdo.c2
-rw-r--r--arch/arm/nwfpe/fpa11_cpdo.c2
-rw-r--r--arch/arm/nwfpe/fpa11_cpdt.c6
-rw-r--r--arch/arm/nwfpe/fpa11_cprt.c20
-rw-r--r--arch/arm/nwfpe/fpmodule.c15
-rw-r--r--arch/arm/nwfpe/softfloat.c7
-rw-r--r--arch/arm/tools/mach-types23
-rw-r--r--arch/arm/vmlinux-armo.lds.in1
-rw-r--r--arch/arm/vmlinux-armv.lds.in1
-rw-r--r--arch/i386/boot/setup.S12
-rw-r--r--arch/i386/config.in2
-rw-r--r--arch/i386/defconfig53
-rw-r--r--arch/i386/kernel/apic.c118
-rw-r--r--arch/i386/kernel/apm.c188
-rw-r--r--arch/i386/kernel/dmi_scan.c182
-rw-r--r--arch/i386/kernel/head.S2
-rw-r--r--arch/i386/kernel/i386_ksyms.c2
-rw-r--r--arch/i386/kernel/irq.c2
-rw-r--r--arch/i386/kernel/microcode.c122
-rw-r--r--arch/i386/kernel/mtrr.c378
-rw-r--r--arch/i386/kernel/pci-irq.c128
-rw-r--r--arch/i386/kernel/process.c4
-rw-r--r--arch/i386/kernel/setup.c59
-rw-r--r--arch/i386/kernel/smpboot.c8
-rw-r--r--arch/i386/kernel/traps.c12
-rw-r--r--arch/i386/mm/init.c8
-rw-r--r--arch/ia64/kernel/irq.c2
-rw-r--r--arch/ia64/mm/init.c6
-rw-r--r--arch/m68k/amiga/amiga_ksyms.c1
-rw-r--r--arch/m68k/amiga/amiints.c66
-rw-r--r--arch/m68k/amiga/amisound.c10
-rw-r--r--arch/m68k/amiga/chipram.c216
-rw-r--r--arch/m68k/amiga/cia.c7
-rw-r--r--arch/m68k/amiga/config.c56
-rw-r--r--arch/m68k/atari/atakeyb.c17
-rw-r--r--arch/m68k/atari/config.c4
-rw-r--r--arch/m68k/atari/stram.c485
-rw-r--r--arch/m68k/fpsp040/bindec.S2
-rw-r--r--arch/m68k/fpsp040/decbin.S6
-rw-r--r--arch/m68k/fpsp040/do_func.S2
-rw-r--r--arch/m68k/fpsp040/get_op.S2
-rw-r--r--arch/m68k/fpsp040/util.S8
-rw-r--r--arch/m68k/fpsp040/x_store.S2
-rw-r--r--arch/m68k/ifpsp060/os.S68
-rw-r--r--arch/m68k/kernel/entry.S21
-rw-r--r--arch/m68k/kernel/ints.c8
-rw-r--r--arch/m68k/kernel/m68k_defs.c1
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c2
-rw-r--r--arch/m68k/kernel/ptrace.c22
-rw-r--r--arch/m68k/kernel/setup.c2
-rw-r--r--arch/m68k/kernel/signal.c2
-rw-r--r--arch/m68k/kernel/sys_m68k.c6
-rw-r--r--arch/m68k/kernel/traps.c241
-rw-r--r--arch/m68k/lib/Makefile2
-rw-r--r--arch/m68k/lib/muldi3.c63
-rw-r--r--arch/m68k/mac/baboon.c2
-rw-r--r--arch/m68k/mac/config.c156
-rw-r--r--arch/m68k/mac/macints.c2
-rw-r--r--arch/m68k/mac/oss.c1
-rw-r--r--arch/m68k/mac/psc.c2
-rw-r--r--arch/m68k/mac/via.c1
-rw-r--r--arch/m68k/mm/fault.c164
-rw-r--r--arch/m68k/mvme147/config.c37
-rw-r--r--arch/m68k/q40/README20
-rw-r--r--arch/m68k/q40/config.c87
-rw-r--r--arch/m68k/q40/q40ints.c308
-rw-r--r--arch/mips/Makefile4
-rw-r--r--arch/mips/arc/Makefile12
-rw-r--r--arch/mips/defconfig2
-rw-r--r--arch/mips/defconfig-atlas4
-rw-r--r--arch/mips/defconfig-cp70002
-rw-r--r--arch/mips/defconfig-ddb54762
-rw-r--r--arch/mips/defconfig-decstation2
-rw-r--r--arch/mips/defconfig-ev641202
-rw-r--r--arch/mips/defconfig-ev961002
-rw-r--r--arch/mips/defconfig-ip222
-rw-r--r--arch/mips/defconfig-malta5
-rw-r--r--arch/mips/defconfig-rm2002
-rw-r--r--arch/mips/kernel/Makefile93
-rw-r--r--arch/mips/kernel/irixsig.c2
-rw-r--r--arch/mips/kernel/traps.c13
-rw-r--r--arch/mips/lib/Makefile25
-rw-r--r--arch/mips/mm/Makefile50
-rw-r--r--arch/mips/sgi/kernel/Makefile13
-rw-r--r--arch/mips64/arc/Makefile12
-rw-r--r--arch/mips64/defconfig2
-rw-r--r--arch/mips64/defconfig-ip222
-rw-r--r--arch/mips64/defconfig-ip272
-rw-r--r--arch/mips64/kernel/traps.c13
-rw-r--r--arch/mips64/lib/Makefile5
-rw-r--r--arch/mips64/mm/Makefile31
-rw-r--r--arch/mips64/sgi-ip22/Makefile8
-rw-r--r--arch/mips64/sgi-ip27/Makefile9
-rw-r--r--arch/mips64/tools/Makefile1
-rw-r--r--arch/parisc/Makefile91
-rw-r--r--arch/parisc/config.in208
-rw-r--r--arch/parisc/defconfig363
-rw-r--r--arch/parisc/hpux/Makefile16
-rw-r--r--arch/parisc/hpux/entry_hpux.S537
-rw-r--r--arch/parisc/hpux/fs.c250
-rw-r--r--arch/parisc/hpux/gate.S72
-rw-r--r--arch/parisc/hpux/ioctl.c63
-rw-r--r--arch/parisc/hpux/sys_hpux.c334
-rw-r--r--arch/parisc/hpux/wrappers.S244
-rw-r--r--arch/parisc/kernel/Makefile52
-rw-r--r--arch/parisc/kernel/cache.c253
-rw-r--r--arch/parisc/kernel/ccio-dma.c1209
-rw-r--r--arch/parisc/kernel/ccio-rm-dma.c212
-rw-r--r--arch/parisc/kernel/drivers.c134
-rw-r--r--arch/parisc/kernel/entry.S1867
-rw-r--r--arch/parisc/kernel/hardware.c1446
-rw-r--r--arch/parisc/kernel/head.S156
-rw-r--r--arch/parisc/kernel/hpmc.S319
-rw-r--r--arch/parisc/kernel/init_task.c29
-rw-r--r--arch/parisc/kernel/inventory.c397
-rw-r--r--arch/parisc/kernel/iosapic.c1100
-rw-r--r--arch/parisc/kernel/iosapic_private.h165
-rw-r--r--arch/parisc/kernel/irq.c538
-rw-r--r--arch/parisc/kernel/keyboard.c82
-rw-r--r--arch/parisc/kernel/lasimap.map322
-rw-r--r--arch/parisc/kernel/lba_pci.c1346
-rw-r--r--arch/parisc/kernel/led.c451
-rw-r--r--arch/parisc/kernel/pa7300lc.c54
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c138
-rw-r--r--arch/parisc/kernel/pci-dma.c547
-rw-r--r--arch/parisc/kernel/pci.c535
-rw-r--r--arch/parisc/kernel/pdc.c217
-rw-r--r--arch/parisc/kernel/pdc_cons.c179
-rw-r--r--arch/parisc/kernel/process.c250
-rw-r--r--arch/parisc/kernel/ptrace.c305
-rw-r--r--arch/parisc/kernel/real1.c154
-rw-r--r--arch/parisc/kernel/real2.S274
-rw-r--r--arch/parisc/kernel/sba_iommu.c1752
-rw-r--r--arch/parisc/kernel/semaphore.c239
-rw-r--r--arch/parisc/kernel/setup.c614
-rw-r--r--arch/parisc/kernel/signal.c653
-rw-r--r--arch/parisc/kernel/sys_parisc.c88
-rw-r--r--arch/parisc/kernel/syscall.S563
-rw-r--r--arch/parisc/kernel/time.c98
-rw-r--r--arch/parisc/kernel/traps.c895
-rw-r--r--arch/parisc/lib/Makefile13
-rw-r--r--arch/parisc/lib/bitops.c60
-rw-r--r--arch/parisc/lib/checksum.c130
-rw-r--r--arch/parisc/lib/lusercopy.S242
-rw-r--r--arch/parisc/mm/Makefile13
-rw-r--r--arch/parisc/mm/extable.c69
-rw-r--r--arch/parisc/mm/fault.c283
-rw-r--r--arch/parisc/mm/init.c479
-rw-r--r--arch/parisc/mm/kmap.c143
-rw-r--r--arch/parisc/mm/pa11.c170
-rw-r--r--arch/parisc/mm/pa20.c170
-rw-r--r--arch/parisc/tools/Makefile28
-rw-r--r--arch/parisc/tools/offset.c326
-rw-r--r--arch/parisc/vmlinux.lds79
-rw-r--r--arch/ppc/8260_io/uart.c12
-rw-r--r--arch/ppc/8xx_io/fec.c4
-rw-r--r--arch/ppc/8xx_io/uart.c12
-rw-r--r--arch/ppc/amiga/config.c93
-rw-r--r--arch/ppc/mm/init.c2
-rw-r--r--arch/s390/kernel/traps.c6
-rw-r--r--arch/s390/mm/init.c6
-rw-r--r--arch/sh/kernel/traps.c6
-rw-r--r--arch/sh/mm/init.c6
-rw-r--r--arch/sparc/boot/piggyback.c49
-rw-r--r--arch/sparc/config.in2
-rw-r--r--arch/sparc/kernel/ioport.c7
-rw-r--r--arch/sparc/kernel/pcic.c14
-rw-r--r--arch/sparc/kernel/smp.c1
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c7
-rw-r--r--arch/sparc/kernel/sun4d_smp.c1
-rw-r--r--arch/sparc/kernel/sun4m_smp.c1
-rw-r--r--arch/sparc/kernel/sys_sparc.c25
-rw-r--r--arch/sparc/mm/init.c9
-rw-r--r--arch/sparc/mm/srmmu.c76
-rw-r--r--arch/sparc/mm/sun4c.c79
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c3
-rw-r--r--arch/sparc64/kernel/sys_sparc.c24
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c10
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c2
-rw-r--r--arch/sparc64/kernel/traps.c14
-rw-r--r--arch/sparc64/mm/init.c13
-rw-r--r--arch/sparc64/solaris/ioctl.c2
-rw-r--r--arch/sparc64/solaris/socket.c2
258 files changed, 32466 insertions, 4401 deletions
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 44ae94a99..c07b25764 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -36,6 +36,10 @@ ifeq ($(have_mcpu),y)
CFLAGS := $(CFLAGS) -mcpu=ev5
mcpu_done := y
endif
+ ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy)
+ CFLAGS := $(CFLAGS) -mcpu=pca56
+ mcpu_done := y
+ endif
ifeq ($(mcpu_done)$(CONFIG_ALPHA_PYXIS),ny)
CFLAGS := $(CFLAGS) -mcpu=ev56
mcpu_done := y
@@ -48,14 +52,14 @@ ifeq ($(have_mcpu),y)
endif
mcpu_done := y
endif
- ifeq ($(mcpu_done)$(CONFIG_ALPHA_NAUTILUS)$(have_mcpu_ev67),nyy)
- CFLAGS := $(CFLAGS) -mcpu=ev67
- mcpu_done := y
- endif
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny)
CFLAGS := $(CFLAGS) -mcpu=ev4
mcpu_done := y
endif
+ ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy)
+ CFLAGS := $(CFLAGS) -mcpu=ev67
+ mcpu_done := y
+ endif
ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny)
ifeq ($(have_mcpu_ev6),y)
CFLAGS := $(CFLAGS) -mcpu=ev6
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index da5c361c9..649047e66 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -56,7 +56,7 @@ choice 'Alpha system type' \
Wildfire CONFIG_ALPHA_WILDFIRE" Generic
# clear all implied options (don't want default values for those):
-unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
+unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 CONFIG_ALPHA_EV67
unset CONFIG_ALPHA_EISA
unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS
@@ -138,16 +138,12 @@ if [ "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_EIGER" = "y" ]
then
define_bool CONFIG_ALPHA_EV6 y
define_bool CONFIG_ALPHA_TSUNAMI y
+ bool 'EV67 (or later) CPU (speed > 600MHz)?' CONFIG_ALPHA_EV67
fi
-if [ "$CONFIG_ALPHA_WILDFIRE" = "y" ]
+if [ "$CONFIG_ALPHA_WILDFIRE" = "y" -o "$CONFIG_ALPHA_TITAN" = "y" ]
then
- define_bool CONFIG_PCI y
- define_bool CONFIG_ALPHA_EV6 y
-fi
-if [ "$CONFIG_ALPHA_TITAN" = "y" ]
-then
- define_bool CONFIG_PCI y
define_bool CONFIG_ALPHA_EV6 y
+ define_bool CONFIG_ALPHA_EV67 y
fi
if [ "$CONFIG_ALPHA_RAWHIDE" = "y" ]
then
@@ -165,8 +161,9 @@ then
fi
if [ "$CONFIG_ALPHA_NAUTILUS" = "y" ]
then
- define_bool CONFIG_ALPHA_EV6 y
define_bool CONFIG_ALPHA_IRONGATE y
+ define_bool CONFIG_ALPHA_EV6 y
+ define_bool CONFIG_ALPHA_EV67 y
fi
if [ "$CONFIG_ALPHA_JENSEN" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
index 1b1f46867..6203b0247 100644
--- a/arch/alpha/kernel/core_cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -119,6 +119,7 @@ conf_read(unsigned long addr, unsigned char type1)
stat0 = *(vip)CIA_IOC_CIA_ERR;
*(vip)CIA_IOC_CIA_ERR = stat0;
mb();
+ *(vip)CIA_IOC_CIA_ERR; /* re-read to force write */
/* If Type1 access, must set CIA CFG. */
if (type1) {
@@ -128,6 +129,7 @@ conf_read(unsigned long addr, unsigned char type1)
*(vip)CIA_IOC_CFG;
}
+ mb();
draina();
mcheck_expected(0) = 1;
mcheck_taken(0) = 0;
@@ -171,6 +173,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
stat0 = *(vip)CIA_IOC_CIA_ERR;
*(vip)CIA_IOC_CIA_ERR = stat0;
mb();
+ *(vip)CIA_IOC_CIA_ERR; /* re-read to force write */
/* If Type1 access, must set CIA CFG. */
if (type1) {
@@ -180,6 +183,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
*(vip)CIA_IOC_CFG;
}
+ mb();
draina();
mcheck_expected(0) = 1;
mcheck_taken(0) = 0;
@@ -188,7 +192,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1)
/* Access configuration space. */
*(vip)addr = value;
mb();
- mb(); /* magic */
+ *(vip)addr; /* read back to force the write */
mcheck_expected(0) = 0;
mb();
@@ -606,7 +610,8 @@ do_init_arch(int is_pyxis)
*(vip)CIA_IOC_ERR_MASK = temp;
/* Clear all currently pending errors. */
- *(vip)CIA_IOC_CIA_ERR = 0;
+ temp = *(vip)CIA_IOC_CIA_ERR;
+ *(vip)CIA_IOC_CIA_ERR = temp;
/* Turn on mchecks. */
temp = *(vip)CIA_IOC_CIA_CTRL;
@@ -695,11 +700,11 @@ do_init_arch(int is_pyxis)
*(vip)CIA_IOC_PCI_W1_BASE = 0x40000000 | 1;
*(vip)CIA_IOC_PCI_W1_MASK = (0x40000000 - 1) & 0xfff00000;
- *(vip)CIA_IOC_PCI_T1_BASE = 0;
+ *(vip)CIA_IOC_PCI_T1_BASE = 0 >> 2;
*(vip)CIA_IOC_PCI_W2_BASE = 0x80000000 | 1;
*(vip)CIA_IOC_PCI_W2_MASK = (0x40000000 - 1) & 0xfff00000;
- *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000;
+ *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000 >> 2;
*(vip)CIA_IOC_PCI_W3_BASE = 0;
}
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 1b83bdfb9..ddf3d9755 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -8,6 +8,11 @@
/* 2.3.x PCI/resources, 1999 Andrea Arcangeli <andrea@suse.de> */
+/*
+ * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+ * PCI-PCI bridges cleanup
+ */
+
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -51,13 +56,13 @@ struct pci_controler *pci_isa_hose;
static void __init
quirk_eisa_bridge(struct pci_dev *dev)
{
- dev->class = PCI_CLASS_BRIDGE_EISA;
+ dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
static void __init
quirk_isa_bridge(struct pci_dev *dev)
{
- dev->class = PCI_CLASS_BRIDGE_ISA;
+ dev->class = PCI_CLASS_BRIDGE_ISA << 8;
}
static void __init
@@ -71,6 +76,24 @@ quirk_ali_ide_ports(struct pci_dev *dev)
dev->resource[3].end = dev->resource[3].start + 7;
}
+/*
+ * Notorious Cy82C693 chip. One of its numerous bugs: although
+ * Cypress IDE controller doesn't support native mode, it has
+ * programmable addresses of IDE command/control registers.
+ * This violates PCI specifications, confuses IDE subsystem
+ * and causes resource conflict between primary HD_CMD register
+ * and floppy controller. Ugh.
+ * Fix that.
+ */
+static void __init
+quirk_cypress_ide_ports(struct pci_dev *dev)
+{
+ if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE)
+ return;
+ dev->resource[0].flags = 0;
+ dev->resource[1].flags = 0;
+}
+
static void __init
quirk_vga_enable_rom(struct pci_dev *dev)
{
@@ -78,7 +101,6 @@ quirk_vga_enable_rom(struct pci_dev *dev)
But if its a Cirrus 543x/544x DISABLE it, since
enabling ROM disables the memory... */
if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA &&
- /* But if its a Cirrus 543x/544x DISABLE it */
(dev->vendor != PCI_VENDOR_ID_CIRRUS ||
(dev->device < 0x00a0) || (dev->device > 0x00ac)))
{
@@ -98,6 +120,8 @@ struct pci_fixup pcibios_fixups[] __initdata = {
quirk_isa_bridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229,
quirk_ali_ide_ports },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
+ quirk_cypress_ide_ports },
{ PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_vga_enable_rom },
{ 0 }
};
@@ -122,18 +146,12 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size)
start = PCIBIOS_MIN_IO + hose->io_space->start;
/*
- * Aligning to 0x800 rather than the minimum base of
- * 0x400 is an attempt to avoid having devices in
- * any 0x?C?? range, which is where the de4x5 driver
- * probes for EISA cards.
- *
- * Adaptecs, especially, resent such intrusions.
- *
- * The de4x5 driver has the eisa probe conditionalized
- * out for Alpha, so lower the minimum base back to 0x400.
+ * Put everything into 0x00-0xff region modulo 0x400
*/
- alignto = MAX(0x400, size);
- start = ALIGN(start, alignto);
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
}
else if (res->flags & IORESOURCE_MEM) {
/* Make sure we start at our min on all hoses */
@@ -181,44 +199,6 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size)
#undef MB
#undef GB
-/*
- * Pre-layout host-independant device initialization.
- */
-
-static void __init
-pcibios_assign_special(struct pci_dev * dev)
-{
- int i;
-
- /* The first three resources of an IDE controler are often magic,
- so leave them unchanged. This is true, for instance, of the
- Contaq 82C693 as seen on SX164 and DP264. */
-
- if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
- /* Resource 1 of IDE controller is the address of HD_CMD
- register which actually occupies a single byte (0x3f6
- for ide0) in reported 0x3f4-3f7 range. We have to fix
- that to avoid resource conflict with AT-style floppy
- controller. */
- dev->resource[1].start += 2;
- dev->resource[1].end = dev->resource[1].start;
- for (i = 0; i < PCI_NUM_RESOURCES; i++)
- if (dev->resource[i].flags && dev->resource[i].start)
- pci_claim_resource(dev, i);
- }
- /*
- * We don't have code that will init the CYPRESS bridge correctly
- * so we do the next best thing, and depend on the previous
- * console code to do the right thing, and ignore it here... :-\
- */
- else if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
- dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
- for (i = 0; i < PCI_NUM_RESOURCES; i++)
- if (dev->resource[i].flags && dev->resource[i].start)
- pci_claim_resource(dev, i);
-}
-
-
void __init
pcibios_init(void)
{
@@ -257,7 +237,6 @@ pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
pcibios_fixup_resource(&dev->resource[i],
hose->mem_space);
}
- pcibios_assign_special(dev);
}
void __init
@@ -265,17 +244,33 @@ pcibios_fixup_bus(struct pci_bus *bus)
{
/* Propogate hose info into the subordinate devices. */
- struct pci_controler *hose = (struct pci_controler *) bus->sysdata;
+ struct pci_controler *hose = bus->sysdata;
struct list_head *ln;
+ struct pci_dev *dev = bus->self;
- /* ???? */
- bus->resource[0] = hose->io_space;
- bus->resource[1] = hose->mem_space;
+ if (!dev) {
+ /* Root bus */
+ bus->resource[0] = hose->io_space;
+ bus->resource[1] = hose->mem_space;
+ } else {
+ /* This is a bridge. Do not care how it's initialized,
+ just link its resources to the bus ones */
+ int i;
- /* If this is a bridge, get the current bases */
- if (bus->self) {
- pci_read_bridge_bases(bus);
- pcibios_fixup_device_resources(bus->self, bus->parent);
+ for(i=0; i<3; i++) {
+ bus->resource[i] =
+ &dev->resource[PCI_BRIDGE_RESOURCES+i];
+ bus->resource[i]->name = bus->name;
+ }
+ bus->resource[0]->flags |= pci_bridge_check_io(dev);
+ bus->resource[1]->flags |= IORESOURCE_MEM;
+ /* For now, propogate hose limits to the bus;
+ we'll adjust them later. */
+ bus->resource[0]->end = hose->io_space->end;
+ bus->resource[1]->end = hose->mem_space->end;
+ /* Turn off downstream PF memory address range by default */
+ bus->resource[2]->start = 1024*1024;
+ bus->resource[2]->end = bus->resource[2]->start - 1;
}
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
@@ -285,7 +280,7 @@ pcibios_fixup_bus(struct pci_bus *bus)
}
}
-void __init
+void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
@@ -385,99 +380,6 @@ pcibios_set_master(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
}
-#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
-
-static void __init
-pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
-{
- struct pbus_set_ranges_data inner;
- struct pci_dev *dev;
- struct pci_dev *bridge = bus->self;
- struct pci_controler *hose = bus->sysdata;
- struct list_head *ln;
-
- if (!bridge)
- return; /* host bridge, nothing to do */
-
- /* set reasonable default locations for pcibios_align_resource */
- inner.io_start = hose->io_space->start + PCIBIOS_MIN_IO;
- inner.mem_start = hose->mem_space->start + PCIBIOS_MIN_MEM;
- inner.io_end = inner.io_start;
- inner.mem_end = inner.mem_start;
-
- /* Collect information about how our direct children are layed out. */
- for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
- int i;
- dev = pci_dev_b(ln);
-
- /* Skip bridges for now */
- if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
- continue;
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource res;
- unsigned long size;
-
- memcpy(&res, &dev->resource[i], sizeof(res));
- size = res.end - res.start + 1;
-
- if (res.flags & IORESOURCE_IO) {
- res.start = inner.io_end;
- pcibios_align_resource(dev, &res, size);
- inner.io_end = res.start + size;
- } else if (res.flags & IORESOURCE_MEM) {
- res.start = inner.mem_end;
- pcibios_align_resource(dev, &res, size);
- inner.mem_end = res.start + size;
- }
- }
- }
-
- /* And for all of the subordinate busses. */
- for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
- pcibios_size_bridge(pci_bus_b(ln), &inner);
-
- /* turn the ending locations into sizes (subtract start) */
- inner.io_end -= inner.io_start;
- inner.mem_end -= inner.mem_start;
-
- /* Align the sizes up by bridge rules */
- inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1;
- inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1;
-
- /* Adjust the bridge's allocation requirements */
- bridge->resource[0].end = bridge->resource[0].start + inner.io_end;
- bridge->resource[1].end = bridge->resource[1].start + inner.mem_end;
-
- bridge->resource[PCI_BRIDGE_RESOURCES].end =
- bridge->resource[PCI_BRIDGE_RESOURCES].start + inner.io_end;
- bridge->resource[PCI_BRIDGE_RESOURCES+1].end =
- bridge->resource[PCI_BRIDGE_RESOURCES+1].start + inner.mem_end;
-
- /* adjust parent's resource requirements */
- if (outer) {
- outer->io_end = ROUND_UP(outer->io_end, 4*1024);
- outer->io_end += inner.io_end;
-
- outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024);
- outer->mem_end += inner.mem_end;
- }
-}
-
-#undef ROUND_UP
-
-static void __init
-pcibios_size_bridges(void)
-{
- struct list_head *ln1, *ln2;
-
- for(ln1=pci_root_buses.next; ln1 != &pci_root_buses; ln1=ln1->next)
- for(ln2 = pci_bus_b(ln1)->children.next;
- ln2 != &pci_bus_b(ln1)->children;
- ln2 = ln2->next)
- pcibios_size_bridge(pci_bus_b(ln2), NULL);
-}
-
void __init
common_init_pci(void)
{
@@ -495,10 +397,8 @@ common_init_pci(void)
next_busno += 1;
}
- pcibios_size_bridges();
pci_assign_unassigned_resources();
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
- pci_set_bus_ranges();
}
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 3b727631a..d4eb6a5d9 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -613,10 +613,10 @@ pci_dma_supported(struct pci_dev *pdev, dma_addr_t mask)
/* Check that we have a scatter-gather arena that fits. */
hose = pdev ? pdev->sysdata : pci_isa_hose;
arena = hose->sg_isa;
- if (arena && arena->dma_base + arena->size <= mask)
+ if (arena && arena->dma_base + arena->size - 1 <= mask)
return 1;
arena = hose->sg_pci;
- if (arena && arena->dma_base + arena->size <= mask)
+ if (arena && arena->dma_base + arena->size - 1 <= mask)
return 1;
return 0;
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 54fc93387..c9a2e79a4 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -56,9 +56,9 @@ ruffian_init_irq(void)
init_i8259a_irqs();
- /* Not interested in the bogus interrupts (0,3,4,6),
+ /* Not interested in the bogus interrupts (0,3,6),
NMI (1), HALT (2), flash (5), or 21142 (8). */
- init_pyxis_irqs(0x17f0000);
+ init_pyxis_irqs(0x16f0000);
common_init_isa_dma();
}
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 913331a95..cb23a987d 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -3,32 +3,63 @@
#
.S.s:
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+ $(CPP) -D__ASSEMBLY__ $(CFLAGS) -o $*.s $<
.S.o:
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
-
-OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
- checksum.o csum_partial_copy.o strlen.o \
- strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
- strchr.o strrchr.o memchr.o \
- copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
- csum_ipv6_magic.o strcasecmp.o fpreg.o \
+ $(CC) -D__ASSEMBLY__ $(CFLAGS) -c -o $*.o $<
+
+# Many of these routines have implementations tuned for ev6.
+# Choose them iff we're targeting ev6 specifically.
+ev6 :=
+ifeq ($(CONFIG_ALPHA_EV6),y)
+ ev6 := ev6-
+endif
+
+# Several make use of the cttz instruction introduced in ev67.
+ev67 :=
+ifeq ($(CONFIG_ALPHA_EV67),y)
+ ev67 := ev67-
+endif
+
+OBJS = __divqu.o __remqu.o __divlu.o __remlu.o \
+ $(ev6)memset.o \
+ $(ev6)memcpy.o \
+ memmove.o \
+ io.o \
+ checksum.o \
+ csum_partial_copy.o \
+ $(ev67)strlen.o \
+ $(ev67)strcat.o \
+ strcpy.o \
+ $(ev67)strncat.o \
+ strncpy.o \
+ $(ev6)stxcpy.o \
+ $(ev6)stxncpy.o \
+ $(ev67)strchr.o \
+ strrchr.o \
+ $(ev6)memchr.o \
+ $(ev6)copy_user.o \
+ $(ev6)clear_user.o \
+ $(ev6)strncpy_from_user.o \
+ $(ev67)strlen_user.o \
+ $(ev6)csum_ipv6_magic.o \
+ strcasecmp.o \
+ fpreg.o \
callback_srm.o srm_puts.o srm_printk.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
-__divqu.o: divide.S
- $(CC) $(AFLAGS) -DDIV -c -o __divqu.o divide.S
+__divqu.o: $(ev6)divide.S
+ $(CC) $(AFLAGS) -DDIV -c -o __divqu.o $(ev6)divide.S
-__remqu.o: divide.S
- $(CC) $(AFLAGS) -DREM -c -o __remqu.o divide.S
+__remqu.o: $(ev6)divide.S
+ $(CC) $(AFLAGS) -DREM -c -o __remqu.o $(ev6)divide.S
-__divlu.o: divide.S
- $(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o divide.S
+__divlu.o: $(ev6)divide.S
+ $(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o $(ev6)divide.S
-__remlu.o: divide.S
- $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o divide.S
+__remlu.o: $(ev6)divide.S
+ $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o $(ev6)divide.S
dep:
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
index 5165279f0..7f29ac81c 100644
--- a/arch/alpha/lib/checksum.c
+++ b/arch/alpha/lib/checksum.c
@@ -3,6 +3,10 @@
*
* This file contains network checksum routines that are better done
* in an architecture-specific manner due to speed..
+ * Comments in other versions indicate that the algorithms are from RFC1071
+ *
+ * accellerated versions (and 21264 assembly versions ) contributed by
+ * Rick Gorton <rick.gorton@alpha-processor.com>
*/
#include <linux/string.h>
@@ -11,15 +15,25 @@
static inline unsigned short from64to16(unsigned long x)
{
- /* add up 32-bit words for 33 bits */
- x = (x & 0xffffffff) + (x >> 32);
- /* add up 16-bit and 17-bit words for 17+c bits */
- x = (x & 0xffff) + (x >> 16);
- /* add up 16-bit and 2-bit for 16+c bit */
- x = (x & 0xffff) + (x >> 16);
- /* add up carry.. */
- x = (x & 0xffff) + (x >> 16);
- return x;
+ /* Using extract instructions is a bit more efficient
+ than the original shift/bitmask version. */
+
+ union {
+ unsigned long ul;
+ unsigned int ui[2];
+ unsigned short us[4];
+ } in_v, tmp_v, out_v;
+
+ in_v.ul = x;
+ tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1];
+
+ /* Since the bits of tmp_v.sh[3] are going to always be zero,
+ we don't have to bother to add that in. */
+ out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1]
+ + (unsigned long) tmp_v.us[2];
+
+ /* Similarly, out_v.us[2] is always zero for the final add. */
+ return out_v.us[0] + out_v.us[1];
}
/*
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
index 5638a1a0c..f8129b5f5 100644
--- a/arch/alpha/lib/csum_partial_copy.c
+++ b/arch/alpha/lib/csum_partial_copy.c
@@ -2,6 +2,8 @@
* csum_partial_copy - do IP checksumming and copy
*
* (C) Copyright 1996 Linus Torvalds
+ * accellerated versions (and 21264 assembly versions ) contributed by
+ * Rick Gorton <rick.gorton@alpha-processor.com>
*
* Don't look at this too closely - you'll go mad. The things
* we do for performance..
@@ -68,6 +70,31 @@ __asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y))
})
+static inline unsigned short from64to16(unsigned long x)
+{
+ /* Using extract instructions is a bit more efficient
+ than the original shift/bitmask version. */
+
+ union {
+ unsigned long ul;
+ unsigned int ui[2];
+ unsigned short us[4];
+ } in_v, tmp_v, out_v;
+
+ in_v.ul = x;
+ tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1];
+
+ /* Since the bits of tmp_v.sh[3] are going to always be zero,
+ we don't have to bother to add that in. */
+ out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1]
+ + (unsigned long) tmp_v.us[2];
+
+ /* Similarly, out_v.us[2] is always zero for the final add. */
+ return out_v.us[0] + out_v.us[1];
+}
+
+
+
/*
* Ok. This isn't fun, but this is the EASY case.
*/
@@ -335,13 +362,7 @@ do_csum_partial_copy_from_user(const char *src, char *dst, int len,
soff, doff, len-8, checksum,
partial_dest, errp);
}
- /* 64 -> 33 bits */
- checksum = (checksum & 0xffffffff) + (checksum >> 32);
- /* 33 -> < 32 bits */
- checksum = (checksum & 0xffff) + (checksum >> 16);
- /* 32 -> 16 bits */
- checksum = (checksum & 0xffff) + (checksum >> 16);
- checksum = (checksum & 0xffff) + (checksum >> 16);
+ checksum = from64to16 (checksum);
}
return checksum;
}
diff --git a/arch/alpha/lib/ev6-clear_user.S b/arch/alpha/lib/ev6-clear_user.S
new file mode 100644
index 000000000..090f06063
--- /dev/null
+++ b/arch/alpha/lib/ev6-clear_user.S
@@ -0,0 +1,228 @@
+/*
+ * arch/alpha/lib/ev6-clear_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Zero user space, handling exceptions as we go.
+ *
+ * We have to make sure that $0 is always up-to-date and contains the
+ * right "bytes left to zero" value (and that it is updated only _after_
+ * a successful copy). There is also some rather minor exception setup
+ * stuff.
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics
+ * are different:
+ *
+ * Inputs:
+ * length in $0
+ * destination address in $6
+ * exception pointer in $7
+ * return address in $28 (exceptions expect it there)
+ *
+ * Outputs:
+ * bytes left to copy in $0
+ *
+ * Clobbers:
+ * $1,$2,$3,$4,$5,$6
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Determining actual stalls (other than slotting) doesn't appear to be easy to do.
+ * From perusing the source code context where this routine is called, it is
+ * a fair assumption that significant fractions of entire pages are zeroed, so
+ * it's going to be worth the effort to hand-unroll a big loop, and use wh64.
+ * ASSUMPTION:
+ * The believed purpose of only updating $0 after a store is that a signal
+ * may come along during the execution of this chunk of code, and we don't
+ * want to leave a hole (and we also want to avoid repeating lots of work)
+ */
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EX(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda $31, $exception-99b($31); \
+ .previous
+
+ .set noat
+ .set noreorder
+ .align 4
+
+ .globl __do_clear_user
+ .ent __do_clear_user
+ .frame $30, 0, $28
+ .prologue 0
+
+ # Pipeline info : Slotting & Comments
+__do_clear_user:
+ ldgp $29,0($27) # we do exceptions -- we need the gp.
+ # Macro instruction becomes ldah/lda
+ # .. .. E E :
+ and $6, 7, $4 # .. E .. .. : find dest head misalignment
+ beq $0, $zerolength # U .. .. .. : U L U L
+
+ addq $0, $4, $1 # .. .. .. E : bias counter
+ and $1, 7, $2 # .. .. E .. : number of misaligned bytes in tail
+# Note - we never actually use $2, so this is a moot computation
+# and we can rewrite this later...
+ srl $1, 3, $1 # .. E .. .. : number of quadwords to clear
+ beq $4, $headalign # U .. .. .. : U L U L
+
+/*
+ * Head is not aligned. Write (8 - $4) bytes to head of destination
+ * This means $6 is known to be misaligned
+ */
+ EX( ldq_u $5, 0($6) ) # .. .. .. L : load dst word to mask back in
+ beq $1, $onebyte # .. .. U .. : sub-word store?
+ mskql $5, $6, $5 # .. U .. .. : take care of misaligned head
+ addq $6, 8, $6 # E .. .. .. : L U U L
+
+ EX( stq_u $5, -8($6) ) # .. .. .. L :
+ subq $1, 1, $1 # .. .. E .. :
+ addq $0, $4, $0 # .. E .. .. : bytes left -= 8 - misalignment
+ subq $0, 8, $0 # E .. .. .. : U L U L
+
+ .align 4
+/*
+ * (The .align directive ought to be a moot point)
+ * values upon initial entry to the loop
+ * $1 is number of quadwords to clear (zero is a valid value)
+ * $2 is number of trailing bytes (0..7) ($2 never used...)
+ * $6 is known to be aligned 0mod8
+ */
+$headalign:
+ subq $1, 16, $4 # .. .. .. E : If < 16, we can not use the huge loop
+ and $6, 0x3f, $2 # .. .. E .. : Forward work for huge loop
+ subq $2, 0x40, $3 # .. E .. .. : bias counter (huge loop)
+ blt $4, $trailquad # U .. .. .. : U L U L
+
+/*
+ * We know that we're going to do at least 16 quads, which means we are
+ * going to be able to use the large block clear loop at least once.
+ * Figure out how many quads we need to clear before we are 0mod64 aligned
+ * so we can use the wh64 instruction.
+ */
+
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ beq $3, $bigalign # U .. .. .. : U L U L : Aligned 0mod64
+
+$alignmod64:
+ EX( stq_u $31, 0($6) ) # .. .. .. L
+ addq $3, 8, $3 # .. .. E ..
+ subq $0, 8, $0 # .. E .. ..
+ nop # E .. .. .. : U L U L
+
+ nop # .. .. .. E
+ subq $1, 1, $1 # .. .. E ..
+ addq $6, 8, $6 # .. E .. ..
+ blt $3, $alignmod64 # U .. .. .. : U L U L
+
+$bigalign:
+/*
+ * $0 is the number of bytes left
+ * $1 is the number of quads left
+ * $6 is aligned 0mod64
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * We are _not_ going to update $0 after every single store. That
+ * would be silly, because there will be cross-cluster dependencies
+ * no matter how the code is scheduled. By doing it in slightly
+ * staggered fashion, we can still do this loop in 5 fetches
+ * The worse case will be doing two extra quads in some future execution,
+ * in the event of an interrupted clear.
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+ nop # E :
+ nop # E :
+ nop # E :
+ bis $6,$6,$3 # E : U L U L : Initial wh64 address is dest
+ /* This might actually help for the current trip... */
+
+$do_wh64:
+ wh64 ($3) # .. .. .. L1 : memory subsystem hint
+ subq $1, 16, $4 # .. .. E .. : Forward calculation - repeat the loop?
+ EX( stq_u $31, 0($6) ) # .. L .. ..
+ subq $0, 8, $0 # E .. .. .. : U L U L
+
+ addq $6, 128, $3 # E : Target address of wh64
+ EX( stq_u $31, 8($6) ) # L :
+ EX( stq_u $31, 16($6) ) # L :
+ subq $0, 16, $0 # E : U L L U
+
+ nop # E :
+ EX( stq_u $31, 24($6) ) # L :
+ EX( stq_u $31, 32($6) ) # L :
+ subq $0, 168, $5 # E : U L L U : two trips through the loop left?
+ /* 168 = 192 - 24, since we've already completed some stores */
+
+ subq $0, 16, $0 # E :
+ EX( stq_u $31, 40($6) ) # L :
+ EX( stq_u $31, 48($6) ) # L :
+ cmovlt $5, $6, $3 # E : U L L U : Latency 2, extra mapping cycle
+
+ subq $1, 8, $1 # E :
+ subq $0, 16, $0 # E :
+ EX( stq_u $31, 56($6) ) # L :
+ nop # E : U L U L
+
+ nop # E :
+ subq $0, 8, $0 # E :
+ addq $6, 64, $6 # E :
+ bge $4, $do_wh64 # U : U L U L
+
+$trailquad:
+ # zero to 16 quadwords left to store, plus any trailing bytes
+ # $1 is the number of quadwords left to go.
+ #
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ beq $1, $trailbytes # U .. .. .. : U L U L : Only 0..7 bytes to go
+
+$onequad:
+ EX( stq_u $31, 0($6) ) # .. .. .. L
+ subq $1, 1, $1 # .. .. E ..
+ subq $0, 8, $0 # .. E .. ..
+ nop # E .. .. .. : U L U L
+
+ nop # .. .. .. E
+ nop # .. .. E ..
+ addq $6, 8, $6 # .. E .. ..
+ bgt $1, $onequad # U .. .. .. : U L U L
+
+ # We have an unknown number of bytes left to go.
+$trailbytes:
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ beq $0, $zerolength # U .. .. .. : U L U L
+
+ # $0 contains the number of bytes left to copy (0..31)
+ # so we will use $0 as the loop counter
+ # We know for a fact that $0 > 0 zero due to previous context
+$onebyte:
+ EX( stb $31, 0($6) ) # .. .. .. L
+ subq $0, 1, $0 # .. .. E .. :
+ addq $6, 1, $6 # .. E .. .. :
+ bgt $0, $onebyte # U .. .. .. : U L U L
+
+$zerolength:
+$exception: # Destination for exception recovery(?)
+ nop # .. .. .. E :
+ nop # .. .. E .. :
+ nop # .. E .. .. :
+ ret $31, ($28), 1 # L0 .. .. .. : L U L U
+ .end __do_clear_user
+
diff --git a/arch/alpha/lib/ev6-copy_user.S b/arch/alpha/lib/ev6-copy_user.S
new file mode 100644
index 000000000..a30f7324c
--- /dev/null
+++ b/arch/alpha/lib/ev6-copy_user.S
@@ -0,0 +1,262 @@
+/*
+ * arch/alpha/lib/ev6-copy_user.S
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Copy to/from user space, handling exceptions as we go.. This
+ * isn't exactly pretty.
+ *
+ * This is essentially the same as "memcpy()", but with a few twists.
+ * Notably, we have to make sure that $0 is always up-to-date and
+ * contains the right "bytes left to copy" value (and that it is updated
+ * only _after_ a successful copy). There is also some rather minor
+ * exception setup stuff..
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics are
+ * different:
+ *
+ * Inputs:
+ * length in $0
+ * destination address in $6
+ * source address in $7
+ * return address in $28
+ *
+ * Outputs:
+ * bytes left to copy in $0
+ *
+ * Clobbers:
+ * $1,$2,$3,$4,$5,$6,$7
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ */
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EXI(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda $31, $exitin-99b($31); \
+ .previous
+
+#define EXO(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda $31, $exitout-99b($31); \
+ .previous
+
+ .set noat
+ .align 4
+ .globl __copy_user
+ .ent __copy_user
+ # Pipeline info: Slotting & Comments
+__copy_user:
+ ldgp $29,0($27) # we do exceptions -- we need the gp.
+ # Macro instruction becomes ldah/lda
+ # .. .. E E
+ .prologue 1
+ subq $0, 32, $1 # .. E .. .. : Is this going to be a small copy?
+ beq $0, $zerolength # U .. .. .. : U L U L
+
+ and $6,7,$3 # .. .. .. E : is leading dest misalignment
+ ble $1, $onebyteloop # .. .. U .. : 1st branch : small amount of data
+ beq $3, $destaligned # .. U .. .. : 2nd (one cycle fetcher stall)
+ subq $3, 8, $3 # E .. .. .. : L U U L : trip counter
+/*
+ * The fetcher stall also hides the 1 cycle cross-cluster stall for $3 (L --> U)
+ * This loop aligns the destination a byte at a time
+ * We know we have at least one trip through this loop
+ */
+$aligndest:
+ EXI( ldbu $1,0($7) ) # .. .. .. L : Keep loads separate from stores
+ addq $6,1,$6 # .. .. E .. : Section 3.8 in the CWG
+ addq $3,1,$3 # .. E .. .. :
+ nop # E .. .. .. : U L U L
+
+/*
+ * the -1 is to compensate for the inc($6) done in a previous quadpack
+ * which allows us zero dependencies within either quadpack in the loop
+ */
+ EXO( stb $1,-1($6) ) # .. .. .. L :
+ addq $7,1,$7 # .. .. E .. : Section 3.8 in the CWG
+ subq $0,1,$0 # .. E .. .. :
+ bne $3, $aligndest # U .. .. .. : U L U L
+
+/*
+ * If we fell through into here, we have a minimum of 33 - 7 bytes
+ * If we arrived via branch, we have a minimum of 32 bytes
+ */
+$destaligned:
+ and $7,7,$1 # .. .. .. E : Check _current_ source alignment
+ bic $0,7,$4 # .. .. E .. : number bytes as a quadword loop
+ EXI( ldq_u $3,0($7) ) # .. L .. .. : Forward fetch for fallthrough code
+ beq $1,$quadaligned # U .. .. .. : U L U L
+
+/*
+ * In the worst case, we've just executed an ldq_u here from 0($7)
+ * and we'll repeat it once if we take the branch
+ */
+
+/* Misaligned quadword loop - not unrolled. Leave it that way. */
+$misquad:
+ EXI( ldq_u $2,8($7) ) # .. .. .. L :
+ subq $4,8,$4 # .. .. E .. :
+ extql $3,$7,$3 # .. U .. .. :
+ extqh $2,$7,$1 # U .. .. .. : U U L L
+
+ bis $3,$1,$1 # .. .. .. E :
+ EXO( stq $1,0($6) ) # .. .. L .. :
+ addq $7,8,$7 # .. E .. .. :
+ subq $0,8,$0 # E .. .. .. : U L L U
+
+ addq $6,8,$6 # .. .. .. E :
+ bis $2,$2,$3 # .. .. E .. :
+ nop # .. E .. .. :
+ bne $4,$misquad # U .. .. .. : U L U L
+
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ beq $0,$zerolength # U .. .. .. : U L U L
+
+/* We know we have at least one trip through the byte loop */
+ EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad
+ addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG)
+ nop # .. E .. .. :
+ br $31, $dirtyentry # L0 .. .. .. : L U U L
+/* Do the trailing byte loop load, then hop into the store part of the loop */
+
+/*
+ * A minimum of (33 - 7) bytes to do a quad at a time.
+ * Based upon the usage context, it's worth the effort to unroll this loop
+ * $0 - number of bytes to be moved
+ * $4 - number of bytes to move as quadwords
+ * $6 is current destination address
+ * $7 is current source address
+ */
+$quadaligned:
+ subq $4, 32, $2 # .. .. .. E : do not unroll for small stuff
+ nop # .. .. E ..
+ nop # .. E .. ..
+ blt $2, $onequad # U .. .. .. : U L U L
+
+/*
+ * There is a significant assumption here that the source and destination
+ * addresses differ by more than 32 bytes. In this particular case, a
+ * sparsity of registers further bounds this to be a minimum of 8 bytes.
+ * But if this isn't met, then the output result will be incorrect.
+ * Furthermore, due to a lack of available registers, we really can't
+ * unroll this to be an 8x loop (which would enable us to use the wh64
+ * instruction memory hint instruction).
+ */
+$unroll4:
+ EXI( ldq $1,0($7) ) # .. .. .. L
+ EXI( ldq $2,8($7) ) # .. .. L ..
+ subq $4,32,$4 # .. E .. ..
+ nop # E .. .. .. : U U L L
+
+ addq $7,16,$7 # .. .. .. E
+ EXO( stq $1,0($6) ) # .. .. L ..
+ EXO( stq $2,8($6) ) # .. L .. ..
+ subq $0,16,$0 # E .. .. .. : U L L U
+
+ addq $6,16,$6 # .. .. .. E
+ EXI( ldq $1,0($7) ) # .. .. L ..
+ EXI( ldq $2,8($7) ) # .. L .. ..
+ subq $4, 32, $3 # E .. .. .. : U U L L : is there enough for another trip?
+
+ EXO( stq $1,0($6) ) # .. .. .. L
+ EXO( stq $2,8($6) ) # .. .. L ..
+ subq $0,16,$0 # .. E .. ..
+ addq $7,16,$7 # E .. .. .. : U L L U
+
+ nop # .. .. .. E
+ nop # .. .. E ..
+ addq $6,16,$6 # .. E .. ..
+ bgt $3,$unroll4 # U .. .. .. : U L U L
+
+ nop
+ nop
+ nop
+ beq $4, $noquads
+
+$onequad:
+ EXI( ldq $1,0($7) )
+ subq $4,8,$4
+ addq $7,8,$7
+ nop
+
+ EXO( stq $1,0($6) )
+ subq $0,8,$0
+ addq $6,8,$6
+ bne $4,$onequad
+
+$noquads:
+ nop
+ nop
+ nop
+ beq $0,$zerolength
+
+/*
+ * For small copies (or the tail of a larger copy), do a very simple byte loop.
+ * There's no point in doing a lot of complex alignment calculations to try to
+ * to quadword stuff for a small amount of data.
+ * $0 - remaining number of bytes left to copy
+ * $6 - current dest addr
+ * $7 - current source addr
+ */
+
+$onebyteloop:
+ EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad
+ addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG)
+ nop # .. E .. .. :
+ nop # E .. .. .. : U L U L
+
+$dirtyentry:
+/*
+ * the -1 is to compensate for the inc($6) done in a previous quadpack
+ * which allows us zero dependencies within either quadpack in the loop
+ */
+ EXO ( stb $2,-1($6) ) # .. .. .. L :
+ addq $7,1,$7 # .. .. E .. : quadpack as the load
+ subq $0,1,$0 # .. E .. .. : change count _after_ copy
+ bgt $0,$onebyteloop # U .. .. .. : U L U L
+
+$zerolength:
+$exitout: # Destination for exception recovery(?)
+ nop # .. .. .. E
+ nop # .. .. E ..
+ nop # .. E .. ..
+ ret $31,($28),1 # L0 .. .. .. : L U L U
+
+$exitin:
+
+ /* A stupid byte-by-byte zeroing of the rest of the output
+ buffer. This cures security holes by never leaving
+ random kernel data around to be copied elsewhere. */
+
+ nop
+ nop
+ nop
+ mov $0,$1
+
+$101:
+ EXO ( stb $31,0($6) ) # L
+ subq $1,1,$1 # E
+ addq $6,1,$6 # E
+ bgt $1,$101 # U
+
+ nop
+ nop
+ nop
+ ret $31,($28),1 # L0
+
+ .end __copy_user
+
diff --git a/arch/alpha/lib/ev6-csum_ipv6_magic.S b/arch/alpha/lib/ev6-csum_ipv6_magic.S
new file mode 100644
index 000000000..de1948a69
--- /dev/null
+++ b/arch/alpha/lib/ev6-csum_ipv6_magic.S
@@ -0,0 +1,126 @@
+/*
+ * arch/alpha/lib/ev6-csum_ipv6_magic.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
+ * struct in6_addr *daddr,
+ * __u32 len,
+ * unsigned short proto,
+ * unsigned int csum);
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Determining actual stalls (other than slotting) doesn't appear to be easy to do.
+ *
+ * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
+ * struct in6_addr *daddr,
+ * __u32 len,
+ * unsigned short proto,
+ * unsigned int csum);
+ *
+ * Swap <proto> (takes form 0xaabb)
+ * Then shift it left by 48, so result is:
+ * 0xbbaa0000 00000000
+ * Then turn it back into a sign extended 32-bit item
+ * 0xbbaa0000
+ *
+ * Swap <len> (an unsigned int) using Mike Burrows' 7-instruction sequence
+ * (we can't hide the 3-cycle latency of the unpkbw in the 6-instruction sequence)
+ * Assume input takes form 0xAABBCCDD
+ *
+ * Finally, original 'folding' approach is to split the long into 4 unsigned shorts
+ * add 4 ushorts, resulting in ushort/carry
+ * add carry bits + ushort --> ushort
+ * add carry bits + ushort --> ushort (in case the carry results in an overflow)
+ * Truncate to a ushort. (took 13 instructions)
+ * From doing some testing, using the approach in checksum.c:from64to16()
+ * results in the same outcome:
+ * split into 2 uints, add those, generating a ulong
+ * add the 3 low ushorts together, generating a uint
+ * a final add of the 2 lower ushorts
+ * truncating the result.
+ */
+
+ .globl csum_ipv6_magic
+ .align 4
+ .ent csum_ipv6_magic
+ .frame $30,0,$26,0
+csum_ipv6_magic:
+ .prologue 0
+
+ ldq $0,0($16) # L : Latency: 3
+ inslh $18,7,$4 # U : 0000000000AABBCC
+ ldq $1,8($16) # L : Latency: 3
+ sll $19,8,$7 # U : U L U L : 0x00000000 00aabb00
+
+ zapnot $20,15,$20 # U : zero extend incoming csum
+ ldq $2,0($17) # L : Latency: 3
+ sll $19,24,$19 # U : U L L U : 0x000000aa bb000000
+ inswl $18,3,$18 # U : 000000CCDD000000
+
+ ldq $3,8($17) # L : Latency: 3
+ bis $18,$4,$18 # E : 000000CCDDAABBCC
+ addl $19,$7,$19 # E : <sign bits>bbaabb00
+ nop # E : U L U L
+
+ addq $20,$0,$20 # E : begin summing the words
+ srl $18,16,$4 # U : 0000000000CCDDAA
+ zap $19,0x3,$19 # U : <sign bits>bbaa0000
+ nop # E : L U U L
+
+ cmpult $20,$0,$0 # E :
+ addq $20,$1,$20 # E :
+ zapnot $18,0xa,$18 # U : 00000000DD00BB00
+ zap $4,0xa,$4 # U : U U L L : 0000000000CC00AA
+
+ or $18,$4,$18 # E : 00000000DDCCBBAA
+ nop # E :
+ cmpult $20,$1,$1 # E :
+ addq $20,$2,$20 # E : U L U L
+
+ cmpult $20,$2,$2 # E :
+ addq $20,$3,$20 # E :
+ cmpult $20,$3,$3 # E : (1 cycle stall on $20)
+ addq $20,$18,$20 # E : U L U L (1 cycle stall on $20)
+
+ cmpult $20,$18,$18 # E :
+ addq $20,$19,$20 # E : (1 cycle stall on $20)
+ addq $0,$1,$0 # E : merge the carries back into the csum
+ addq $2,$3,$2 # E :
+
+ cmpult $20,$19,$19 # E :
+ addq $18,$19,$18 # E : (1 cycle stall on $19)
+ addq $0,$2,$0 # E :
+ addq $20,$18,$20 # E : U L U L :
+ /* (1 cycle stall on $18, 2 cycles on $20) */
+
+ addq $0,$20,$0 # E :
+ zapnot $0,15,$1 # U : Start folding output (1 cycle stall on $0)
+ nop # E :
+ srl $0,32,$0 # U : U L U L : (1 cycle stall on $0)
+
+ addq $1,$0,$1 # E : Finished generating ulong
+ extwl $1,2,$2 # U : ushort[1] (1 cycle stall on $1)
+ zapnot $1,3,$0 # U : ushort[0] (1 cycle stall on $1)
+ extwl $1,4,$1 # U : ushort[2] (1 cycle stall on $1)
+
+ addq $0,$2,$0 # E
+ addq $0,$1,$3 # E : Finished generating uint
+ /* (1 cycle stall on $0) */
+ extwl $3,2,$1 # U : ushort[1] (1 cycle stall on $3)
+ nop # E : L U L U
+
+ addq $1,$3,$0 # E : Final carry
+ not $0,$4 # E : complement (1 cycle stall on $0)
+ zapnot $4,3,$0 # U : clear upper garbage bits
+ /* (1 cycle stall on $4) */
+ ret # L0 : L U L U
+
+ .end csum_ipv6_magic
diff --git a/arch/alpha/lib/ev6-divide.S b/arch/alpha/lib/ev6-divide.S
new file mode 100644
index 000000000..2a82b9be9
--- /dev/null
+++ b/arch/alpha/lib/ev6-divide.S
@@ -0,0 +1,259 @@
+/*
+ * arch/alpha/lib/ev6-divide.S
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Alpha division..
+ */
+
+/*
+ * The alpha chip doesn't provide hardware division, so we have to do it
+ * by hand. The compiler expects the functions
+ *
+ * __divqu: 64-bit unsigned long divide
+ * __remqu: 64-bit unsigned long remainder
+ * __divqs/__remqs: signed 64-bit
+ * __divlu/__remlu: unsigned 32-bit
+ * __divls/__remls: signed 32-bit
+ *
+ * These are not normal C functions: instead of the normal
+ * calling sequence, these expect their arguments in registers
+ * $24 and $25, and return the result in $27. Register $28 may
+ * be clobbered (assembly temporary), anything else must be saved.
+ *
+ * In short: painful.
+ *
+ * This is a rather simple bit-at-a-time algorithm: it's very good
+ * at dividing random 64-bit numbers, but the more usual case where
+ * the divisor is small is handled better by the DEC algorithm
+ * using lookup tables. This uses much less memory, though, and is
+ * nicer on the cache.. Besides, I don't know the copyright status
+ * of the DEC code.
+ */
+
+/*
+ * My temporaries:
+ * $0 - current bit
+ * $1 - shifted divisor
+ * $2 - modulus/quotient
+ *
+ * $23 - return address
+ * $24 - dividend
+ * $25 - divisor
+ *
+ * $27 - quotient/modulus
+ * $28 - compare status
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#define halt .long 0
+
+/*
+ * Select function type and registers
+ */
+#define mask $0
+#define divisor $1
+#define compare $28
+#define tmp1 $3
+#define tmp2 $4
+
+#ifdef DIV
+#define DIV_ONLY(x,y...) x,##y
+#define MOD_ONLY(x,y...)
+#define func(x) __div##x
+#define modulus $2
+#define quotient $27
+#define GETSIGN(x) xor $24,$25,x
+#define STACK 48
+#else
+#define DIV_ONLY(x,y...)
+#define MOD_ONLY(x,y...) x,##y
+#define func(x) __rem##x
+#define modulus $27
+#define quotient $2
+#define GETSIGN(x) bis $24,$24,x
+#define STACK 32
+#endif
+
+/*
+ * For 32-bit operations, we need to extend to 64-bit
+ */
+#ifdef INTSIZE
+#define ufunction func(lu)
+#define sfunction func(l)
+#define LONGIFY(x) zapnot x,15,x
+#define SLONGIFY(x) addl x,0,x
+#else
+#define ufunction func(qu)
+#define sfunction func(q)
+#define LONGIFY(x)
+#define SLONGIFY(x)
+#endif
+
+.set noat
+.align 4
+.globl ufunction
+.ent ufunction
+ufunction:
+ subq $30,STACK,$30 # E :
+ .frame $30,STACK,$23
+ .prologue 0
+
+7: stq $1, 0($30) # L :
+ bis $25,$25,divisor # E :
+ stq $2, 8($30) # L : L U L U
+
+ bis $24,$24,modulus # E :
+ stq $0,16($30) # L :
+ bis $31,$31,quotient # E :
+ LONGIFY(divisor) # E : U L L U
+
+ stq tmp1,24($30) # L :
+ LONGIFY(modulus) # E :
+ bis $31,1,mask # E :
+ DIV_ONLY(stq tmp2,32($30)) # L : L U U L
+
+ beq divisor, 9f /* div by zero */
+ /*
+ * In spite of the DIV_ONLY being either a non-instruction
+ * or an actual stq, the addition of the .align directive
+ * below ensures that label 1 is going to be nicely aligned
+ */
+
+ .align 4
+#ifdef INTSIZE
+ /*
+ * shift divisor left, using 3-bit shifts for
+ * 32-bit divides as we can't overflow. Three-bit
+ * shifts will result in looping three times less
+ * here, but can result in two loops more later.
+ * Thus using a large shift isn't worth it (and
+ * s8add pairs better than a sll..)
+ */
+1: cmpult divisor,modulus,compare # E :
+ s8addq divisor,$31,divisor # E :
+ s8addq mask,$31,mask # E :
+ bne compare,1b # U : U L U L
+#else
+1: cmpult divisor,modulus,compare # E :
+ nop # E :
+ nop # E :
+ blt divisor, 2f # U : U L U L
+
+ addq divisor,divisor,divisor # E :
+ addq mask,mask,mask # E :
+ unop # E :
+ bne compare,1b # U : U L U L
+#endif
+
+ /* ok, start to go right again.. */
+2:
+ /*
+ * Keep things nicely bundled... use a nop instead of not
+ * having an instruction for DIV_ONLY
+ */
+#ifdef DIV
+ DIV_ONLY(addq quotient,mask,tmp2) # E :
+#else
+ nop # E :
+#endif
+ srl mask,1,mask # U :
+ cmpule divisor,modulus,compare # E :
+ subq modulus,divisor,tmp1 # E :
+
+#ifdef DIV
+ DIV_ONLY(cmovne compare,tmp2,quotient) # E : Latency 2, extra map slot
+ nop # E : as part of the cmovne
+ srl divisor,1,divisor # U :
+ nop # E : L U L U
+
+ nop # E :
+ cmovne compare,tmp1,modulus # E : Latency 2, extra map slot
+ nop # E : as part of the cmovne
+ bne mask,2b # U : U L U L
+#else
+ srl divisor,1,divisor # U :
+ cmovne compare,tmp1,modulus # E : Latency 2, extra map slot
+ nop # E : as part of the cmovne
+ bne mask,2b # U : U L L U
+#endif
+
+9: ldq $1, 0($30) # L :
+ ldq $2, 8($30) # L :
+ nop # E :
+ nop # E : U U L L
+
+ ldq $0,16($30) # L :
+ ldq tmp1,24($30) # L :
+ nop # E :
+ nop # E :
+
+#ifdef DIV
+ DIV_ONLY(ldq tmp2,32($30)) # L :
+#else
+ nop # E :
+#endif
+ addq $30,STACK,$30 # E :
+ ret $31,($23),1 # L0 : L U U L
+ .end ufunction
+
+/*
+ * Uhh.. Ugly signed division. I'd rather not have it at all, but
+ * it's needed in some circumstances. There are different ways to
+ * handle this, really. This does:
+ * -a / b = a / -b = -(a / b)
+ * -a % b = -(a % b)
+ * a % -b = a % b
+ * which is probably not the best solution, but at least should
+ * have the property that (x/y)*y + (x%y) = x.
+ */
+.align 4
+.globl sfunction
+.ent sfunction
+sfunction:
+ subq $30,STACK,$30 # E :
+ .frame $30,STACK,$23
+ .prologue 0
+ bis $24,$25,$28 # E :
+ SLONGIFY($28) # E :
+ bge $28,7b # U :
+
+ stq $24,0($30) # L :
+ subq $31,$24,$28 # E :
+ stq $25,8($30) # L :
+ nop # E : U L U L
+
+ cmovlt $24,$28,$24 /* abs($24) */ # E : Latency 2, extra map slot
+ nop # E : as part of the cmov
+ stq $23,16($30) # L :
+ subq $31,$25,$28 # E : U L U L
+
+ stq tmp1,24($30) # L :
+ cmovlt $25,$28,$25 /* abs($25) */ # E : Latency 2, extra map slot
+ nop # E :
+ bsr $23,ufunction # L0: L U L U
+
+ ldq $24,0($30) # L :
+ ldq $25,8($30) # L :
+ GETSIGN($28) # E :
+ subq $31,$27,tmp1 # E : U U L L
+
+ SLONGIFY($28) # E :
+ ldq $23,16($30) # L :
+ cmovlt $28,tmp1,$27 # E : Latency 2, extra map slot
+ nop # E : U L L U : as part of the cmov
+
+ ldq tmp1,24($30) # L :
+ nop # E : as part of the cmov
+ addq $30,STACK,$30 # E :
+ ret $31,($23),1 # L0 : L U U L
+ .end sfunction
diff --git a/arch/alpha/lib/ev6-memchr.S b/arch/alpha/lib/ev6-memchr.S
new file mode 100644
index 000000000..a8e843dbc
--- /dev/null
+++ b/arch/alpha/lib/ev6-memchr.S
@@ -0,0 +1,191 @@
+/*
+ * arch/alpha/lib/ev6-memchr.S
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Finds characters in a memory area. Optimized for the Alpha:
+ *
+ * - memory accessed as aligned quadwords only
+ * - uses cmpbge to compare 8 bytes in parallel
+ * - does binary search to find 0 byte in last
+ * quadword (HAKMEM needed 12 instructions to
+ * do this instead of the 9 instructions that
+ * binary search needs).
+ *
+ * For correctness consider that:
+ *
+ * - only minimum number of quadwords may be accessed
+ * - the third argument is an unsigned long
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+ .set noreorder
+ .set noat
+
+ .align 4
+ .globl memchr
+ .ent memchr
+memchr:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ # Hack -- if someone passes in (size_t)-1, hoping to just
+ # search til the end of the address space, we will overflow
+ # below when we find the address of the last byte. Given
+ # that we will never have a 56-bit address space, cropping
+ # the length is the easiest way to avoid trouble.
+ zap $18, 0x80, $5 # U : Bound length
+ beq $18, $not_found # U :
+ ldq_u $1, 0($16) # L : load first quadword Latency=3
+ and $17, 0xff, $17 # E : L L U U : 00000000000000ch
+
+ insbl $17, 1, $2 # U : 000000000000ch00
+ cmpult $18, 9, $4 # E : small (< 1 quad) string?
+ or $2, $17, $17 # E : 000000000000chch
+ lda $3, -1($31) # E : U L L U
+
+ sll $17, 16, $2 # U : 00000000chch0000
+ addq $16, $5, $5 # E : Max search address
+ or $2, $17, $17 # E : 00000000chchchch
+ sll $17, 32, $2 # U : U L L U : chchchch00000000
+
+ or $2, $17, $17 # E : chchchchchchchch
+ extql $1, $16, $7 # U : $7 is upper bits
+ beq $4, $first_quad # U :
+ ldq_u $6, -1($5) # L : L U U L : eight or less bytes to search Latency=3
+
+ extqh $6, $16, $6 # U : 2 cycle stall for $6
+ mov $16, $0 # E :
+ nop # E :
+ or $7, $6, $1 # E : L U L U $1 = quadword starting at $16
+
+ # Deal with the case where at most 8 bytes remain to be searched
+ # in $1. E.g.:
+ # $18 = 6
+ # $1 = ????c6c5c4c3c2c1
+$last_quad:
+ negq $18, $6 # E :
+ xor $17, $1, $1 # E :
+ srl $3, $6, $6 # U : $6 = mask of $18 bits set
+ cmpbge $31, $1, $2 # E : L U L U
+
+ nop
+ nop
+ and $2, $6, $2 # E :
+ beq $2, $not_found # U : U L U L
+
+$found_it:
+#if defined(__alpha_fix__) && defined(__alpha_cix__)
+ /*
+ * Since we are guaranteed to have set one of the bits, we don't
+ * have to worry about coming back with a 0x40 out of cttz...
+ */
+ cttz $2, $3 # U0 :
+ addq $0, $3, $0 # E : All done
+ nop # E :
+ ret # L0 : L U L U
+#else
+ /*
+ * Slow and clunky. It can probably be improved.
+ * An exercise left for others.
+ */
+ negq $2, $3 # E :
+ and $2, $3, $2 # E :
+ and $2, 0x0f, $1 # E :
+ addq $0, 4, $3 # E :
+
+ cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
+ nop # E : keep with cmov
+ and $2, 0x33, $1 # E :
+ addq $0, 2, $3 # E : U L U L : 2 cycle stall on $0
+
+ cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
+ nop # E : keep with cmov
+ and $2, 0x55, $1 # E :
+ addq $0, 1, $3 # E : U L U L : 2 cycle stall on $0
+
+ cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
+ nop
+ nop
+ ret # L0 : L U L U
+#endif
+
+ # Deal with the case where $18 > 8 bytes remain to be
+ # searched. $16 may not be aligned.
+ .align 4
+$first_quad:
+ andnot $16, 0x7, $0 # E :
+ insqh $3, $16, $2 # U : $2 = 0000ffffffffffff ($16<0:2> ff)
+ xor $1, $17, $1 # E :
+ or $1, $2, $1 # E : U L U L $1 = ====ffffffffffff
+
+ cmpbge $31, $1, $2 # E :
+ bne $2, $found_it # U :
+ # At least one byte left to process.
+ ldq $1, 8($0) # L :
+ subq $5, 1, $18 # E : U L U L
+
+ addq $0, 8, $0 # E :
+ # Make $18 point to last quad to be accessed (the
+ # last quad may or may not be partial).
+ andnot $18, 0x7, $18 # E :
+ cmpult $0, $18, $2 # E :
+ beq $2, $final # U : U L U L
+
+ # At least two quads remain to be accessed.
+
+ subq $18, $0, $4 # E : $4 <- nr quads to be processed
+ and $4, 8, $4 # E : odd number of quads?
+ bne $4, $odd_quad_count # U :
+ # At least three quads remain to be accessed
+ mov $1, $4 # E : L U L U : move prefetched value to correct reg
+
+ .align 4
+$unrolled_loop:
+ ldq $1, 8($0) # L : prefetch $1
+ xor $17, $4, $2 # E :
+ cmpbge $31, $2, $2 # E :
+ bne $2, $found_it # U : U L U L
+
+ addq $0, 8, $0 # E :
+ nop # E :
+ nop # E :
+ nop # E :
+
+$odd_quad_count:
+ xor $17, $1, $2 # E :
+ ldq $4, 8($0) # L : prefetch $4
+ cmpbge $31, $2, $2 # E :
+ addq $0, 8, $6 # E :
+
+ bne $2, $found_it # U :
+ cmpult $6, $18, $6 # E :
+ addq $0, 8, $0 # E :
+ nop # E :
+
+ bne $6, $unrolled_loop # U :
+ mov $4, $1 # E : move prefetched value into $1
+ nop # E :
+ nop # E :
+
+$final: subq $5, $0, $18 # E : $18 <- number of bytes left to do
+ nop # E :
+ nop # E :
+ bne $18, $last_quad # U :
+
+$not_found:
+ mov $31, $0 # E :
+ nop # E :
+ nop # E :
+ ret # L0 :
+
+ .end memchr
diff --git a/arch/alpha/lib/ev6-memcpy.S b/arch/alpha/lib/ev6-memcpy.S
new file mode 100644
index 000000000..7ebcbc27b
--- /dev/null
+++ b/arch/alpha/lib/ev6-memcpy.S
@@ -0,0 +1,248 @@
+/*
+ * arch/alpha/lib/ev6-memcpy.S
+ * 21264 version by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Reasonably optimized memcpy() routine for the Alpha 21264
+ *
+ * - memory accessed as aligned quadwords only
+ * - uses bcmpge to compare 8 bytes in parallel
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ *
+ * Temp usage notes:
+ * $1,$2, - scratch
+ */
+
+ .set noreorder
+ .set noat
+
+ .align 4
+ .globl memcpy
+ .ent memcpy
+memcpy:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ mov $16, $0 # E : copy dest to return
+ ble $18, $nomoredata # U : done with the copy?
+ xor $16, $17, $1 # E : are source and dest alignments the same?
+ and $1, 7, $1 # E : are they the same mod 8?
+
+ bne $1, $misaligned # U : Nope - gotta do this the slow way
+ /* source and dest are same mod 8 address */
+ and $16, 7, $1 # E : Are both 0mod8?
+ beq $1, $both_0mod8 # U : Yes
+ nop # E :
+
+ /*
+ * source and dest are same misalignment. move a byte at a time
+ * until a 0mod8 alignment for both is reached.
+ * At least one byte more to move
+ */
+
+$head_align:
+ ldbu $1, 0($17) # L : grab a byte
+ subq $18, 1, $18 # E : count--
+ addq $17, 1, $17 # E : src++
+ stb $1, 0($16) # L :
+ addq $16, 1, $16 # E : dest++
+ and $16, 7, $1 # E : Are we at 0mod8 yet?
+ ble $18, $nomoredata # U : done with the copy?
+ bne $1, $head_align # U :
+
+$both_0mod8:
+ cmple $18, 127, $1 # E : Can we unroll the loop?
+ bne $1, $no_unroll # U :
+ and $16, 63, $1 # E : get mod64 alignment
+ beq $1, $do_unroll # U : no single quads to fiddle
+
+$single_head_quad:
+ ldq $1, 0($17) # L : get 8 bytes
+ subq $18, 8, $18 # E : count -= 8
+ addq $17, 8, $17 # E : src += 8
+ nop # E :
+
+ stq $1, 0($16) # L : store
+ addq $16, 8, $16 # E : dest += 8
+ and $16, 63, $1 # E : get mod64 alignment
+ bne $1, $single_head_quad # U : still not fully aligned
+
+$do_unroll:
+ addq $16, 64, $7 # E : Initial (+1 trip) wh64 address
+ cmple $18, 63, $1 # E : Can we go through the unrolled loop?
+ bne $1, $tail_quads # U : Nope
+ nop # E :
+
+$unroll_body:
+ wh64 ($7) # L1 : memory subsystem hint: 64 bytes at
+ # ($7) are about to be over-written
+ ldq $6, 0($17) # L0 : bytes 0..7
+ nop # E :
+ nop # E :
+
+ ldq $4, 8($17) # L : bytes 8..15
+ ldq $5, 16($17) # L : bytes 16..23
+ addq $7, 64, $7 # E : Update next wh64 address
+ nop # E :
+
+ ldq $3, 24($17) # L : bytes 24..31
+ addq $16, 64, $1 # E : fallback value for wh64
+ nop # E :
+ nop # E :
+
+ addq $17, 32, $17 # E : src += 32 bytes
+ stq $6, 0($16) # L : bytes 0..7
+ nop # E :
+ nop # E :
+
+ stq $4, 8($16) # L : bytes 8..15
+ stq $5, 16($16) # L : bytes 16..23
+ subq $18, 192, $2 # E : At least two more trips to go?
+ nop # E :
+
+ stq $3, 24($16) # L : bytes 24..31
+ addq $16, 32, $16 # E : dest += 32 bytes
+ nop # E :
+ nop # E :
+
+ ldq $6, 0($17) # L : bytes 0..7
+ ldq $4, 8($17) # L : bytes 8..15
+ cmovlt $2, $1, $7 # E : Latency 2, extra map slot - Use
+ # fallback wh64 address if < 2 more trips
+ nop # E :
+
+ ldq $5, 16($17) # L : bytes 16..23
+ ldq $3, 24($17) # L : bytes 24..31
+ addq $16, 32, $16 # E : dest += 32
+ subq $18, 64, $18 # E : count -= 64
+
+ addq $17, 32, $17 # E : src += 32
+ stq $6, -32($16) # L : bytes 0..7
+ stq $4, -24($16) # L : bytes 8..15
+ cmple $18, 63, $1 # E : At least one more trip?
+
+ stq $5, -16($16) # L : bytes 16..23
+ stq $3, -8($16) # L : bytes 24..31
+ nop # E :
+ beq $1, $unroll_body
+
+$tail_quads:
+$no_unroll:
+ .align 4
+ subq $18, 8, $18 # E : At least a quad left?
+ blt $18, $less_than_8 # U : Nope
+ nop # E :
+ nop # E :
+
+$move_a_quad:
+ ldq $1, 0($17) # L : fetch 8
+ subq $18, 8, $18 # E : count -= 8
+ addq $17, 8, $17 # E : src += 8
+ nop # E :
+
+ stq $1, 0($16) # L : store 8
+ addq $16, 8, $16 # E : dest += 8
+ bge $18, $move_a_quad # U :
+ nop # E :
+
+$less_than_8:
+ .align 4
+ addq $18, 8, $18 # E : add back for trailing bytes
+ ble $18, $nomoredata # U : All-done
+ nop # E :
+ nop # E :
+
+ /* Trailing bytes */
+$tail_bytes:
+ subq $18, 1, $18 # E : count--
+ ldbu $1, 0($17) # L : fetch a byte
+ addq $17, 1, $17 # E : src++
+ nop # E :
+
+ stb $1, 0($16) # L : store a byte
+ addq $16, 1, $16 # E : dest++
+ bgt $18, $tail_bytes # U : more to be done?
+ nop # E :
+
+ /* branching to exit takes 3 extra cycles, so replicate exit here */
+ ret $31, ($26), 1 # L0 :
+ nop # E :
+ nop # E :
+ nop # E :
+
+$misaligned:
+ mov $0, $4 # E : dest temp
+ and $0, 7, $1 # E : dest alignment mod8
+ beq $1, $dest_0mod8 # U : life doesnt totally suck
+ nop
+
+$aligndest:
+ ble $18, $nomoredata # U :
+ ldbu $1, 0($17) # L : fetch a byte
+ subq $18, 1, $18 # E : count--
+ addq $17, 1, $17 # E : src++
+
+ stb $1, 0($4) # L : store it
+ addq $4, 1, $4 # E : dest++
+ and $4, 7, $1 # E : dest 0mod8 yet?
+ bne $1, $aligndest # U : go until we are aligned.
+
+ /* Source has unknown alignment, but dest is known to be 0mod8 */
+$dest_0mod8:
+ subq $18, 8, $18 # E : At least a quad left?
+ blt $18, $misalign_tail # U : Nope
+ ldq_u $3, 0($17) # L : seed (rotating load) of 8 bytes
+ nop # E :
+
+$mis_quad:
+ ldq_u $16, 8($17) # L : Fetch next 8
+ extql $3, $17, $3 # U : masking
+ extqh $16, $17, $1 # U : masking
+ bis $3, $1, $1 # E : merged bytes to store
+
+ subq $18, 8, $18 # E : count -= 8
+ addq $17, 8, $17 # E : src += 8
+ stq $1, 0($4) # L : store 8 (aligned)
+ mov $16, $3 # E : "rotate" source data
+
+ addq $4, 8, $4 # E : dest += 8
+ bge $18, $mis_quad # U : More quads to move
+ nop
+ nop
+
+$misalign_tail:
+ addq $18, 8, $18 # E : account for tail stuff
+ ble $18, $nomoredata # U :
+ nop
+ nop
+
+$misalign_byte:
+ ldbu $1, 0($17) # L : fetch 1
+ subq $18, 1, $18 # E : count--
+ addq $17, 1, $17 # E : src++
+ nop # E :
+
+ stb $1, 0($4) # L : store
+ addq $4, 1, $4 # E : dest++
+ bgt $18, $misalign_byte # U : more to go?
+ nop
+
+
+$nomoredata:
+ ret $31, ($26), 1 # L0 :
+ nop # E :
+ nop # E :
+ nop # E :
+
+ .end memcpy
+
+/* For backwards module compatability. */
+__memcpy = memcpy
+.globl __memcpy
diff --git a/arch/alpha/lib/ev6-memset.S b/arch/alpha/lib/ev6-memset.S
new file mode 100644
index 000000000..626929fc5
--- /dev/null
+++ b/arch/alpha/lib/ev6-memset.S
@@ -0,0 +1,596 @@
+/*
+ * arch/alpha/lib/ev6-memset.S
+ *
+ * This is an efficient (and relatively small) implementation of the C library
+ * "memset()" function for the 21264 implementation of Alpha.
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * The algorithm for the leading and trailing quadwords remains the same,
+ * however the loop has been unrolled to enable better memory throughput,
+ * and the code has been replicated for each of the entry points: __memset
+ * and __memsetw to permit better scheduling to eliminate the stalling
+ * encountered during the mask replication.
+ * A future enhancement might be to put in a byte store loop for really
+ * small (say < 32 bytes) memset()s. Whether or not that change would be
+ * a win in the kernel would depend upon the contextual usage.
+ * WARNING: Maintaining this is going to be more work than the above version,
+ * as fixes will need to be made in multiple places. The performance gain
+ * is worth it.
+ */
+
+ .set noat
+ .set noreorder
+.text
+ .globl __memset
+ .globl __memsetw
+ .globl __constant_c_memset
+ .globl memset
+
+ .ent __memset
+.align 5
+__memset:
+memset:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ /*
+ * Serious stalling happens. The only way to mitigate this is to
+ * undertake a major re-write to interleave the constant materialization
+ * with other parts of the fall-through code. This is important, even
+ * though it makes maintenance tougher.
+ * Do this later.
+ */
+ and $17,255,$1 # E : 00000000000000ch
+ insbl $17,1,$2 # U : 000000000000ch00
+ bis $16,$16,$0 # E : return value
+ ble $18,end_b # U : zero length requested?
+
+ addq $18,$16,$6 # E : max address to write to
+ bis $1,$2,$17 # E : 000000000000chch
+ insbl $1,2,$3 # U : 0000000000ch0000
+ insbl $1,3,$4 # U : 00000000ch000000
+
+ or $3,$4,$3 # E : 00000000chch0000
+ inswl $17,4,$5 # U : 0000chch00000000
+ xor $16,$6,$1 # E : will complete write be within one quadword?
+ inswl $17,6,$2 # U : chch000000000000
+
+ or $17,$3,$17 # E : 00000000chchchch
+ or $2,$5,$2 # E : chchchch00000000
+ bic $1,7,$1 # E : fit within a single quadword?
+ and $16,7,$3 # E : Target addr misalignment
+
+ or $17,$2,$17 # E : chchchchchchchch
+ beq $1,within_quad_b # U :
+ nop # E :
+ beq $3,aligned_b # U : target is 0mod8
+
+ /*
+ * Target address is misaligned, and won't fit within a quadword
+ */
+ ldq_u $4,0($16) # L : Fetch first partial
+ bis $16,$16,$5 # E : Save the address
+ insql $17,$16,$2 # U : Insert new bytes
+ subq $3,8,$3 # E : Invert (for addressing uses)
+
+ addq $18,$3,$18 # E : $18 is new count ($3 is negative)
+ mskql $4,$16,$4 # U : clear relevant parts of the quad
+ subq $16,$3,$16 # E : $16 is new aligned destination
+ bis $2,$4,$1 # E : Final bytes
+
+ nop
+ stq_u $1,0($5) # L : Store result
+ nop
+ nop
+
+.align 4
+aligned_b:
+ /*
+ * We are now guaranteed to be quad aligned, with at least
+ * one partial quad to write.
+ */
+
+ sra $18,3,$3 # U : Number of remaining quads to write
+ and $18,7,$18 # E : Number of trailing bytes to write
+ bis $16,$16,$5 # E : Save dest address
+ beq $3,no_quad_b # U : tail stuff only
+
+ /*
+ * it's worth the effort to unroll this and use wh64 if possible
+ * Lifted a bunch of code from clear_user.S
+ * At this point, entry values are:
+ * $16 Current destination address
+ * $5 A copy of $16
+ * $6 The max quadword address to write to
+ * $18 Number trailer bytes
+ * $3 Number quads to write
+ */
+
+ and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
+ subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
+ subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
+ blt $4, loop_b # U :
+
+ /*
+ * We know we've got at least 16 quads, minimum of one trip
+ * through unrolled loop. Do a quad at a time to get us 0mod64
+ * aligned.
+ */
+
+ nop # E :
+ nop # E :
+ nop # E :
+ beq $1, $bigalign_b # U :
+
+$alignmod64_b:
+ stq $17, 0($5) # L :
+ subq $3, 1, $3 # E : For consistency later
+ addq $1, 8, $1 # E : Increment towards zero for alignment
+ addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
+
+ nop
+ nop
+ addq $5, 8, $5 # E : Inc address
+ blt $1, $alignmod64_b # U :
+
+$bigalign_b:
+ /*
+ * $3 - number quads left to go
+ * $5 - target address (aligned 0mod64)
+ * $17 - mask of stuff to store
+ * Scratch registers available: $7, $2, $4, $1
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+
+$do_wh64_b:
+ wh64 ($4) # L1 : memory subsystem write hint
+ subq $3, 24, $2 # E : For determining future wh64 addresses
+ stq $17, 0($5) # L :
+ nop # E :
+
+ addq $5, 128, $4 # E : speculative target of next wh64
+ stq $17, 8($5) # L :
+ stq $17, 16($5) # L :
+ addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
+
+ stq $17, 24($5) # L :
+ stq $17, 32($5) # L :
+ cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
+ nop
+
+ stq $17, 40($5) # L :
+ stq $17, 48($5) # L :
+ subq $3, 16, $2 # E : Repeat the loop at least once more?
+ nop
+
+ stq $17, 56($5) # L :
+ addq $5, 64, $5 # E :
+ subq $3, 8, $3 # E :
+ bge $2, $do_wh64_b # U :
+
+ nop
+ nop
+ nop
+ beq $3, no_quad_b # U : Might have finished already
+
+.align 4
+ /*
+ * Simple loop for trailing quadwords, or for small amounts
+ * of data (where we can't use an unrolled loop and wh64)
+ */
+loop_b:
+ stq $17,0($5) # L :
+ subq $3,1,$3 # E : Decrement number quads left
+ addq $5,8,$5 # E : Inc address
+ bne $3,loop_b # U : more?
+
+no_quad_b:
+ /*
+ * Write 0..7 trailing bytes.
+ */
+ nop # E :
+ beq $18,end_b # U : All done?
+ ldq $7,0($5) # L :
+ mskqh $7,$6,$2 # U : Mask final quad
+
+ insqh $17,$6,$4 # U : New bits
+ bis $2,$4,$1 # E : Put it all together
+ stq $1,0($5) # L : And back to memory
+ ret $31,($26),1 # L0 :
+
+within_quad_b:
+ ldq_u $1,0($16) # L :
+ insql $17,$16,$2 # U : New bits
+ mskql $1,$16,$4 # U : Clear old
+ bis $2,$4,$2 # E : New result
+
+ mskql $2,$6,$4 # U :
+ mskqh $1,$6,$2 # U :
+ bis $2,$4,$1 # E :
+ stq_u $1,0($16) # L :
+
+end_b:
+ nop
+ nop
+ nop
+ ret $31,($26),1 # L0 :
+ .end __memset
+
+ /*
+ * This is the original body of code, prior to replication and
+ * rescheduling. Leave it here, as there may be calls to this
+ * entry point.
+ */
+.align 4
+ .ent __memset
+__constant_c_memset:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ addq $18,$16,$6 # E : max address to write to
+ bis $16,$16,$0 # E : return value
+ xor $16,$6,$1 # E : will complete write be within one quadword?
+ ble $18,end # U : zero length requested?
+
+ bic $1,7,$1 # E : fit within a single quadword
+ beq $1,within_one_quad # U :
+ and $16,7,$3 # E : Target addr misalignment
+ beq $3,aligned # U : target is 0mod8
+
+ /*
+ * Target address is misaligned, and won't fit within a quadword
+ */
+ ldq_u $4,0($16) # L : Fetch first partial
+ bis $16,$16,$5 # E : Save the address
+ insql $17,$16,$2 # U : Insert new bytes
+ subq $3,8,$3 # E : Invert (for addressing uses)
+
+ addq $18,$3,$18 # E : $18 is new count ($3 is negative)
+ mskql $4,$16,$4 # U : clear relevant parts of the quad
+ subq $16,$3,$16 # E : $16 is new aligned destination
+ bis $2,$4,$1 # E : Final bytes
+
+ nop
+ stq_u $1,0($5) # L : Store result
+ nop
+ nop
+
+.align 4
+aligned:
+ /*
+ * We are now guaranteed to be quad aligned, with at least
+ * one partial quad to write.
+ */
+
+ sra $18,3,$3 # U : Number of remaining quads to write
+ and $18,7,$18 # E : Number of trailing bytes to write
+ bis $16,$16,$5 # E : Save dest address
+ beq $3,no_quad # U : tail stuff only
+
+ /*
+ * it's worth the effort to unroll this and use wh64 if possible
+ * Lifted a bunch of code from clear_user.S
+ * At this point, entry values are:
+ * $16 Current destination address
+ * $5 A copy of $16
+ * $6 The max quadword address to write to
+ * $18 Number trailer bytes
+ * $3 Number quads to write
+ */
+
+ and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
+ subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
+ subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
+ blt $4, loop # U :
+
+ /*
+ * We know we've got at least 16 quads, minimum of one trip
+ * through unrolled loop. Do a quad at a time to get us 0mod64
+ * aligned.
+ */
+
+ nop # E :
+ nop # E :
+ nop # E :
+ beq $1, $bigalign # U :
+
+$alignmod64:
+ stq $17, 0($5) # L :
+ subq $3, 1, $3 # E : For consistency later
+ addq $1, 8, $1 # E : Increment towards zero for alignment
+ addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
+
+ nop
+ nop
+ addq $5, 8, $5 # E : Inc address
+ blt $1, $alignmod64 # U :
+
+$bigalign:
+ /*
+ * $3 - number quads left to go
+ * $5 - target address (aligned 0mod64)
+ * $17 - mask of stuff to store
+ * Scratch registers available: $7, $2, $4, $1
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+
+$do_wh64:
+ wh64 ($4) # L1 : memory subsystem write hint
+ subq $3, 24, $2 # E : For determining future wh64 addresses
+ stq $17, 0($5) # L :
+ nop # E :
+
+ addq $5, 128, $4 # E : speculative target of next wh64
+ stq $17, 8($5) # L :
+ stq $17, 16($5) # L :
+ addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
+
+ stq $17, 24($5) # L :
+ stq $17, 32($5) # L :
+ cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
+ nop
+
+ stq $17, 40($5) # L :
+ stq $17, 48($5) # L :
+ subq $3, 16, $2 # E : Repeat the loop at least once more?
+ nop
+
+ stq $17, 56($5) # L :
+ addq $5, 64, $5 # E :
+ subq $3, 8, $3 # E :
+ bge $2, $do_wh64 # U :
+
+ nop
+ nop
+ nop
+ beq $3, no_quad # U : Might have finished already
+
+.align 4
+ /*
+ * Simple loop for trailing quadwords, or for small amounts
+ * of data (where we can't use an unrolled loop and wh64)
+ */
+loop:
+ stq $17,0($5) # L :
+ subq $3,1,$3 # E : Decrement number quads left
+ addq $5,8,$5 # E : Inc address
+ bne $3,loop # U : more?
+
+no_quad:
+ /*
+ * Write 0..7 trailing bytes.
+ */
+ nop # E :
+ beq $18,end # U : All done?
+ ldq $7,0($5) # L :
+ mskqh $7,$6,$2 # U : Mask final quad
+
+ insqh $17,$6,$4 # U : New bits
+ bis $2,$4,$1 # E : Put it all together
+ stq $1,0($5) # L : And back to memory
+ ret $31,($26),1 # L0 :
+
+within_one_quad:
+ ldq_u $1,0($16) # L :
+ insql $17,$16,$2 # U : New bits
+ mskql $1,$16,$4 # U : Clear old
+ bis $2,$4,$2 # E : New result
+
+ mskql $2,$6,$4 # U :
+ mskqh $1,$6,$2 # U :
+ bis $2,$4,$1 # E :
+ stq_u $1,0($16) # L :
+
+end:
+ nop
+ nop
+ nop
+ ret $31,($26),1 # L0 :
+ .end __constant_c_memset
+
+ /*
+ * This is a replicant of the __constant_c_memset code, rescheduled
+ * to mask stalls. Note that entry point names also had to change
+ */
+ .align 5
+ .ent __memsetw
+
+__memsetw:
+ .frame $30,0,$26,0
+ .prologue 0
+
+ inswl $17,0,$5 # U : 000000000000c1c2
+ inswl $17,2,$2 # U : 00000000c1c20000
+ bis $16,$16,$0 # E : return value
+ addq $18,$16,$6 # E : max address to write to
+
+ ble $18, end_w # U : zero length requested?
+ inswl $17,4,$3 # U : 0000c1c200000000
+ inswl $17,6,$4 # U : c1c2000000000000
+ xor $16,$6,$1 # E : will complete write be within one quadword?
+
+ or $2,$5,$2 # E : 00000000c1c2c1c2
+ or $3,$4,$17 # E : c1c2c1c200000000
+ bic $1,7,$1 # E : fit within a single quadword
+ and $16,7,$3 # E : Target addr misalignment
+
+ or $17,$2,$17 # E : c1c2c1c2c1c2c1c2
+ beq $1,within_quad_w # U :
+ nop
+ beq $3,aligned_w # U : target is 0mod8
+
+ /*
+ * Target address is misaligned, and won't fit within a quadword
+ */
+ ldq_u $4,0($16) # L : Fetch first partial
+ bis $16,$16,$5 # E : Save the address
+ insql $17,$16,$2 # U : Insert new bytes
+ subq $3,8,$3 # E : Invert (for addressing uses)
+
+ addq $18,$3,$18 # E : $18 is new count ($3 is negative)
+ mskql $4,$16,$4 # U : clear relevant parts of the quad
+ subq $16,$3,$16 # E : $16 is new aligned destination
+ bis $2,$4,$1 # E : Final bytes
+
+ nop
+ stq_u $1,0($5) # L : Store result
+ nop
+ nop
+
+.align 4
+aligned_w:
+ /*
+ * We are now guaranteed to be quad aligned, with at least
+ * one partial quad to write.
+ */
+
+ sra $18,3,$3 # U : Number of remaining quads to write
+ and $18,7,$18 # E : Number of trailing bytes to write
+ bis $16,$16,$5 # E : Save dest address
+ beq $3,no_quad_w # U : tail stuff only
+
+ /*
+ * it's worth the effort to unroll this and use wh64 if possible
+ * Lifted a bunch of code from clear_user.S
+ * At this point, entry values are:
+ * $16 Current destination address
+ * $5 A copy of $16
+ * $6 The max quadword address to write to
+ * $18 Number trailer bytes
+ * $3 Number quads to write
+ */
+
+ and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
+ subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
+ subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
+ blt $4, loop_w # U :
+
+ /*
+ * We know we've got at least 16 quads, minimum of one trip
+ * through unrolled loop. Do a quad at a time to get us 0mod64
+ * aligned.
+ */
+
+ nop # E :
+ nop # E :
+ nop # E :
+ beq $1, $bigalign_w # U :
+
+$alignmod64_w:
+ stq $17, 0($5) # L :
+ subq $3, 1, $3 # E : For consistency later
+ addq $1, 8, $1 # E : Increment towards zero for alignment
+ addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
+
+ nop
+ nop
+ addq $5, 8, $5 # E : Inc address
+ blt $1, $alignmod64_w # U :
+
+$bigalign_w:
+ /*
+ * $3 - number quads left to go
+ * $5 - target address (aligned 0mod64)
+ * $17 - mask of stuff to store
+ * Scratch registers available: $7, $2, $4, $1
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+
+$do_wh64_w:
+ wh64 ($4) # L1 : memory subsystem write hint
+ subq $3, 24, $2 # E : For determining future wh64 addresses
+ stq $17, 0($5) # L :
+ nop # E :
+
+ addq $5, 128, $4 # E : speculative target of next wh64
+ stq $17, 8($5) # L :
+ stq $17, 16($5) # L :
+ addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
+
+ stq $17, 24($5) # L :
+ stq $17, 32($5) # L :
+ cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
+ nop
+
+ stq $17, 40($5) # L :
+ stq $17, 48($5) # L :
+ subq $3, 16, $2 # E : Repeat the loop at least once more?
+ nop
+
+ stq $17, 56($5) # L :
+ addq $5, 64, $5 # E :
+ subq $3, 8, $3 # E :
+ bge $2, $do_wh64_w # U :
+
+ nop
+ nop
+ nop
+ beq $3, no_quad_w # U : Might have finished already
+
+.align 4
+ /*
+ * Simple loop for trailing quadwords, or for small amounts
+ * of data (where we can't use an unrolled loop and wh64)
+ */
+loop_w:
+ stq $17,0($5) # L :
+ subq $3,1,$3 # E : Decrement number quads left
+ addq $5,8,$5 # E : Inc address
+ bne $3,loop_w # U : more?
+
+no_quad_w:
+ /*
+ * Write 0..7 trailing bytes.
+ */
+ nop # E :
+ beq $18,end_w # U : All done?
+ ldq $7,0($5) # L :
+ mskqh $7,$6,$2 # U : Mask final quad
+
+ insqh $17,$6,$4 # U : New bits
+ bis $2,$4,$1 # E : Put it all together
+ stq $1,0($5) # L : And back to memory
+ ret $31,($26),1 # L0 :
+
+within_quad_w:
+ ldq_u $1,0($16) # L :
+ insql $17,$16,$2 # U : New bits
+ mskql $1,$16,$4 # U : Clear old
+ bis $2,$4,$2 # E : New result
+
+ mskql $2,$6,$4 # U :
+ mskqh $1,$6,$2 # U :
+ bis $2,$4,$1 # E :
+ stq_u $1,0($16) # L :
+
+end_w:
+ nop
+ nop
+ nop
+ ret $31,($26),1 # L0 :
+
+ .end __memsetw
diff --git a/arch/alpha/lib/ev6-strncpy_from_user.S b/arch/alpha/lib/ev6-strncpy_from_user.S
new file mode 100644
index 000000000..8d446778b
--- /dev/null
+++ b/arch/alpha/lib/ev6-strncpy_from_user.S
@@ -0,0 +1,425 @@
+/*
+ * arch/alpha/lib/ev6-strncpy_from_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Just like strncpy except in the return value:
+ *
+ * -EFAULT if an exception occurs before the terminator is copied.
+ * N if the buffer filled.
+ *
+ * Otherwise the length of the string is returned.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * A bunch of instructions got moved and temp registers were changed
+ * to aid in scheduling. Control flow was also re-arranged to eliminate
+ * branches, and to provide longer code sequences to enable better scheduling.
+ * A total rewrite (using byte load/stores for start & tail sequences)
+ * is desirable, but very difficult to do without a from-scratch rewrite.
+ * Save that for the future.
+ */
+
+
+#include <asm/errno.h>
+#include <alpha/regdef.h>
+
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EX(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda $31, $exception-99b($0); \
+ .previous
+
+
+ .set noat
+ .set noreorder
+ .text
+
+ .globl __strncpy_from_user
+ .ent __strncpy_from_user
+ .frame $30, 0, $26
+ .prologue 1
+
+ .align 4
+__strncpy_from_user:
+ ldgp $29, 0($27) # E E : becomes 2 instructions (for exceptions)
+ and a0, 7, t3 # E : find dest misalignment
+ beq a2, $zerolength # U :
+
+ /* Are source and destination co-aligned? */
+ mov a0, v0 # E : save the string start
+ xor a0, a1, t4 # E :
+ EX( ldq_u t1, 0(a1) ) # L : Latency=3 load first quadword
+ ldq_u t0, 0(a0) # L : load first (partial) aligned dest quadword
+
+ addq a2, t3, a2 # E : bias count by dest misalignment
+ subq a2, 1, a3 # E :
+ addq zero, 1, t10 # E :
+ and t4, 7, t4 # E : misalignment between the two
+
+ and a3, 7, t6 # E : number of tail bytes
+ sll t10, t6, t10 # E : t10 = bitmask of last count byte
+ bne t4, $unaligned # U :
+ lda t2, -1 # E : build a mask against false zero
+
+ /*
+ * We are co-aligned; take care of a partial first word.
+ * On entry to this basic block:
+ * t0 == the first destination word for masking back in
+ * t1 == the first source word.
+ */
+
+ srl a3, 3, a2 # E : a2 = loop counter = (count - 1)/8
+ addq a1, 8, a1 # E :
+ mskqh t2, a1, t2 # U : detection in the src word
+ nop
+
+ /* Create the 1st output word and detect 0's in the 1st input word. */
+ mskqh t1, a1, t3 # U :
+ mskql t0, a1, t0 # U : assemble the first output word
+ ornot t1, t2, t2 # E :
+ nop
+
+ cmpbge zero, t2, t8 # E : bits set iff null found
+ or t0, t3, t0 # E :
+ beq a2, $a_eoc # U :
+ bne t8, $a_eos # U : 2nd branch in a quad. Bad.
+
+ /* On entry to this basic block:
+ * t0 == a source quad not containing a null.
+ * a0 - current aligned destination address
+ * a1 - current aligned source address
+ * a2 - count of quadwords to move.
+ * NOTE: Loop improvement - unrolling this is going to be
+ * a huge win, since we're going to stall otherwise.
+ * Fix this later. For _really_ large copies, look
+ * at using wh64 on a look-ahead basis. See the code
+ * in clear_user.S and copy_user.S.
+ * Presumably, since (a0) and (a1) do not overlap (by C definition)
+ * Lots of nops here:
+ * - Separate loads from stores
+ * - Keep it to 1 branch/quadpack so the branch predictor
+ * can train.
+ */
+$a_loop:
+ stq_u t0, 0(a0) # L :
+ addq a0, 8, a0 # E :
+ nop
+ subq a2, 1, a2 # E :
+
+ EX( ldq_u t0, 0(a1) ) # L :
+ addq a1, 8, a1 # E :
+ cmpbge zero, t0, t8 # E : Stall 2 cycles on t0
+ beq a2, $a_eoc # U :
+
+ beq t8, $a_loop # U :
+ nop
+ nop
+ nop
+
+ /* Take care of the final (partial) word store. At this point
+ * the end-of-count bit is set in t8 iff it applies.
+ *
+ * On entry to this basic block we have:
+ * t0 == the source word containing the null
+ * t8 == the cmpbge mask that found it.
+ */
+$a_eos:
+ negq t8, t12 # E : find low bit set
+ and t8, t12, t12 # E :
+
+ /* We're doing a partial word store and so need to combine
+ our source and original destination words. */
+ ldq_u t1, 0(a0) # L :
+ subq t12, 1, t6 # E :
+
+ or t12, t6, t8 # E :
+ zapnot t0, t8, t0 # U : clear src bytes > null
+ zap t1, t8, t1 # U : clear dst bytes <= null
+ or t0, t1, t0 # E :
+
+ stq_u t0, 0(a0) # L :
+ br $finish_up # L0 :
+ nop
+ nop
+
+ /* Add the end-of-count bit to the eos detection bitmask. */
+ .align 4
+$a_eoc:
+ or t10, t8, t8
+ br $a_eos
+ nop
+ nop
+
+
+/* The source and destination are not co-aligned. Align the destination
+ and cope. We have to be very careful about not reading too much and
+ causing a SEGV. */
+
+ .align 4
+$u_head:
+ /* We know just enough now to be able to assemble the first
+ full source word. We can still find a zero at the end of it
+ that prevents us from outputting the whole thing.
+
+ On entry to this basic block:
+ t0 == the first dest word, unmasked
+ t1 == the shifted low bits of the first source word
+ t6 == bytemask that is -1 in dest word bytes */
+
+ EX( ldq_u t2, 8(a1) ) # L : load second src word
+ addq a1, 8, a1 # E :
+ mskql t0, a0, t0 # U : mask trailing garbage in dst
+ extqh t2, a1, t4 # U :
+
+ or t1, t4, t1 # E : first aligned src word complete
+ mskqh t1, a0, t1 # U : mask leading garbage in src
+ or t0, t1, t0 # E : first output word complete
+ or t0, t6, t6 # E : mask original data for zero test
+
+ cmpbge zero, t6, t8 # E :
+ beq a2, $u_eocfin # U :
+ bne t8, $u_final # U : bad news - 2nd branch in a quad
+ lda t6, -1 # E : mask out the bits we have
+
+ mskql t6, a1, t6 # U : already seen
+ stq_u t0, 0(a0) # L : store first output word
+ or t6, t2, t2 # E :
+ cmpbge zero, t2, t8 # E : find nulls in second partial
+
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+ bne t8, $u_late_head_exit # U :
+ nop
+
+ /* Finally, we've got all the stupid leading edge cases taken care
+ of and we can set up to enter the main loop. */
+
+ extql t2, a1, t1 # U : position hi-bits of lo word
+ EX( ldq_u t2, 8(a1) ) # L : read next high-order source word
+ addq a1, 8, a1 # E :
+ cmpbge zero, t2, t8 # E :
+
+ beq a2, $u_eoc # U :
+ bne t8, $u_eos # U :
+ nop
+ nop
+
+ /* Unaligned copy main loop. In order to avoid reading too much,
+ the loop is structured to detect zeros in aligned source words.
+ This has, unfortunately, effectively pulled half of a loop
+ iteration out into the head and half into the tail, but it does
+ prevent nastiness from accumulating in the very thing we want
+ to run as fast as possible.
+
+ On entry to this basic block:
+ t1 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word
+
+ We further know that t2 does not contain a null terminator. */
+
+ /*
+ * Extra nops here:
+ * separate load quads from store quads
+ * only one branch/quad to permit predictor training
+ */
+
+ .align 4
+$u_loop:
+ extqh t2, a1, t0 # U : extract high bits for current word
+ addq a1, 8, a1 # E :
+ extql t2, a1, t3 # U : extract low bits for next time
+ addq a0, 8, a0 # E :
+
+ or t0, t1, t0 # E : current dst word now complete
+ EX( ldq_u t2, 0(a1) ) # L : load high word for next time
+ subq a2, 1, a2 # E :
+ nop
+
+ stq_u t0, -8(a0) # L : save the current word
+ mov t3, t1 # E :
+ cmpbge zero, t2, t8 # E : test new word for eos
+ beq a2, $u_eoc # U :
+
+ beq t8, $u_loop # U :
+ nop
+ nop
+ nop
+
+ /* We've found a zero somewhere in the source word we just read.
+ If it resides in the lower half, we have one (probably partial)
+ word to write out, and if it resides in the upper half, we
+ have one full and one partial word left to write out.
+
+ On entry to this basic block:
+ t1 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word. */
+ .align 4
+$u_eos:
+ extqh t2, a1, t0 # U :
+ or t0, t1, t0 # E : first (partial) source word complete
+ cmpbge zero, t0, t8 # E : is the null in this first bit?
+ nop
+
+ bne t8, $u_final # U :
+ stq_u t0, 0(a0) # L : the null was in the high-order bits
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+
+ .align 4
+$u_late_head_exit:
+ extql t2, a1, t0 # U :
+ cmpbge zero, t0, t8 # E :
+ or t8, t10, t6 # E :
+ cmoveq a2, t6, t8 # E :
+
+ /* Take care of a final (probably partial) result word.
+ On entry to this basic block:
+ t0 == assembled source word
+ t8 == cmpbge mask that found the null. */
+ .align 4
+$u_final:
+ negq t8, t6 # E : isolate low bit set
+ and t6, t8, t12 # E :
+ ldq_u t1, 0(a0) # L :
+ subq t12, 1, t6 # E :
+
+ or t6, t12, t8 # E :
+ zapnot t0, t8, t0 # U : kill source bytes > null
+ zap t1, t8, t1 # U : kill dest bytes <= null
+ or t0, t1, t0 # E :
+
+ stq_u t0, 0(a0) # E :
+ br $finish_up # U :
+ nop
+ nop
+
+ .align 4
+$u_eoc: # end-of-count
+ extqh t2, a1, t0 # U :
+ or t0, t1, t0 # E :
+ cmpbge zero, t0, t8 # E :
+ nop
+
+ .align 4
+$u_eocfin: # end-of-count, final word
+ or t10, t8, t8 # E :
+ br $u_final # U :
+ nop
+ nop
+
+ /* Unaligned copy entry point. */
+ .align 4
+$unaligned:
+
+ srl a3, 3, a2 # U : a2 = loop counter = (count - 1)/8
+ and a0, 7, t4 # E : find dest misalignment
+ and a1, 7, t5 # E : find src misalignment
+ mov zero, t0 # E :
+
+ /* Conditionally load the first destination word and a bytemask
+ with 0xff indicating that the destination byte is sacrosanct. */
+
+ mov zero, t6 # E :
+ beq t4, 1f # U :
+ ldq_u t0, 0(a0) # L :
+ lda t6, -1 # E :
+
+ mskql t6, a0, t6 # E :
+ nop
+ nop
+ nop
+
+ .align 4
+1:
+ subq a1, t4, a1 # E : sub dest misalignment from src addr
+ /* If source misalignment is larger than dest misalignment, we need
+ extra startup checks to avoid SEGV. */
+ cmplt t4, t5, t12 # E :
+ extql t1, a1, t1 # U : shift src into place
+ lda t2, -1 # E : for creating masks later
+
+ beq t12, $u_head # U :
+ mskqh t2, t5, t2 # U : begin src byte validity mask
+ cmpbge zero, t1, t8 # E : is there a zero?
+ nop
+
+ extql t2, a1, t2 # U :
+ or t8, t10, t5 # E : test for end-of-count too
+ cmpbge zero, t2, t3 # E :
+ cmoveq a2, t5, t8 # E : Latency=2, extra map slot
+
+ nop # E : goes with cmov
+ andnot t8, t3, t8 # E :
+ beq t8, $u_head # U :
+ nop
+
+ /* At this point we've found a zero in the first partial word of
+ the source. We need to isolate the valid source data and mask
+ it into the original destination data. (Incidentally, we know
+ that we'll need at least one byte of that original dest word.) */
+
+ ldq_u t0, 0(a0) # L :
+ negq t8, t6 # E : build bitmask of bytes <= zero
+ mskqh t1, t4, t1 # U :
+ and t6, t8, t12 # E :
+
+ subq t12, 1, t6 # E :
+ or t6, t12, t8 # E :
+ zapnot t2, t8, t2 # U : prepare source word; mirror changes
+ zapnot t1, t8, t1 # U : to source validity mask
+
+ andnot t0, t2, t0 # E : zero place for source to reside
+ or t0, t1, t0 # E : and put it there
+ stq_u t0, 0(a0) # L :
+ nop
+
+ .align 4
+$finish_up:
+ zapnot t0, t12, t4 # U : was last byte written null?
+ and t12, 0xf0, t3 # E : binary search for the address of the
+ cmovne t4, 1, t4 # E : Latency=2, extra map slot
+ nop # E : with cmovne
+
+ and t12, 0xcc, t2 # E : last byte written
+ and t12, 0xaa, t1 # E :
+ cmovne t3, 4, t3 # E : Latency=2, extra map slot
+ nop # E : with cmovne
+
+ bic a0, 7, t0
+ cmovne t2, 2, t2 # E : Latency=2, extra map slot
+ nop # E : with cmovne
+ nop
+
+ cmovne t1, 1, t1 # E : Latency=2, extra map slot
+ nop # E : with cmovne
+ addq t0, t3, t0 # E :
+ addq t1, t2, t1 # E :
+
+ addq t0, t1, t0 # E :
+ addq t0, t4, t0 # add one if we filled the buffer
+ subq t0, v0, v0 # find string length
+ ret # L0 :
+
+ .align 4
+$zerolength:
+ nop
+ nop
+ nop
+ clr v0
+
+$exception:
+ nop
+ nop
+ nop
+ ret
+
+ .end __strncpy_from_user
diff --git a/arch/alpha/lib/ev6-stxcpy.S b/arch/alpha/lib/ev6-stxcpy.S
new file mode 100644
index 000000000..f5b409e9a
--- /dev/null
+++ b/arch/alpha/lib/ev6-stxcpy.S
@@ -0,0 +1,321 @@
+/*
+ * arch/alpha/lib/ev6-stxcpy.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Copy a null-terminated string from SRC to DST.
+ *
+ * This is an internal routine used by strcpy, stpcpy, and strcat.
+ * As such, it uses special linkage conventions to make implementation
+ * of these public functions more efficient.
+ *
+ * On input:
+ * t9 = return address
+ * a0 = DST
+ * a1 = SRC
+ *
+ * On output:
+ * t12 = bitmask (with one bit set) indicating the last byte written
+ * a0 = unaligned address of the last *word* written
+ *
+ * Furthermore, v0, a3-a5, t11, and t12 are untouched.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+ .set noat
+ .set noreorder
+
+ .text
+
+/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
+ doesn't like putting the entry point for a procedure somewhere in the
+ middle of the procedure descriptor. Work around this by putting the
+ aligned copy in its own procedure descriptor */
+
+
+ .ent stxcpy_aligned
+ .align 4
+stxcpy_aligned:
+ .frame sp, 0, t9
+ .prologue 0
+
+ /* On entry to this basic block:
+ t0 == the first destination word for masking back in
+ t1 == the first source word. */
+
+ /* Create the 1st output word and detect 0's in the 1st input word. */
+ lda t2, -1 # E : build a mask against false zero
+ mskqh t2, a1, t2 # U : detection in the src word (stall)
+ mskqh t1, a1, t3 # U :
+ ornot t1, t2, t2 # E : (stall)
+
+ mskql t0, a1, t0 # U : assemble the first output word
+ cmpbge zero, t2, t8 # E : bits set iff null found
+ or t0, t3, t1 # E : (stall)
+ bne t8, $a_eos # U : (stall)
+
+ /* On entry to this basic block:
+ t0 == the first destination word for masking back in
+ t1 == a source word not containing a null. */
+ /* Nops here to separate store quads from load quads */
+
+$a_loop:
+ stq_u t1, 0(a0) # L :
+ addq a0, 8, a0 # E :
+ nop
+ nop
+
+ ldq_u t1, 0(a1) # L : Latency=3
+ addq a1, 8, a1 # E :
+ cmpbge zero, t1, t8 # E : (3 cycle stall)
+ beq t8, $a_loop # U : (stall for t8)
+
+ /* Take care of the final (partial) word store.
+ On entry to this basic block we have:
+ t1 == the source word containing the null
+ t8 == the cmpbge mask that found it. */
+$a_eos:
+ negq t8, t6 # E : find low bit set
+ and t8, t6, t12 # E : (stall)
+ /* For the sake of the cache, don't read a destination word
+ if we're not going to need it. */
+ and t12, 0x80, t6 # E : (stall)
+ bne t6, 1f # U : (stall)
+
+ /* We're doing a partial word store and so need to combine
+ our source and original destination words. */
+ ldq_u t0, 0(a0) # L : Latency=3
+ subq t12, 1, t6 # E :
+ zapnot t1, t6, t1 # U : clear src bytes >= null (stall)
+ or t12, t6, t8 # E : (stall)
+
+ zap t0, t8, t0 # E : clear dst bytes <= null
+ or t0, t1, t1 # E : (stall)
+ nop
+ nop
+
+1: stq_u t1, 0(a0) # L :
+ ret (t9) # L0 : Latency=3
+ nop
+ nop
+
+ .end stxcpy_aligned
+
+ .align 4
+ .ent __stxcpy
+ .globl __stxcpy
+__stxcpy:
+ .frame sp, 0, t9
+ .prologue 0
+
+ /* Are source and destination co-aligned? */
+ xor a0, a1, t0 # E :
+ unop # E :
+ and t0, 7, t0 # E : (stall)
+ bne t0, $unaligned # U : (stall)
+
+ /* We are co-aligned; take care of a partial first word. */
+ ldq_u t1, 0(a1) # L : load first src word
+ and a0, 7, t0 # E : take care not to load a word ...
+ addq a1, 8, a1 # E :
+ beq t0, stxcpy_aligned # U : ... if we wont need it (stall)
+
+ ldq_u t0, 0(a0) # L :
+ br stxcpy_aligned # L0 : Latency=3
+ nop
+ nop
+
+
+/* The source and destination are not co-aligned. Align the destination
+ and cope. We have to be very careful about not reading too much and
+ causing a SEGV. */
+
+ .align 4
+$u_head:
+ /* We know just enough now to be able to assemble the first
+ full source word. We can still find a zero at the end of it
+ that prevents us from outputting the whole thing.
+
+ On entry to this basic block:
+ t0 == the first dest word, for masking back in, if needed else 0
+ t1 == the low bits of the first source word
+ t6 == bytemask that is -1 in dest word bytes */
+
+ ldq_u t2, 8(a1) # L :
+ addq a1, 8, a1 # E :
+ extql t1, a1, t1 # U : (stall on a1)
+ extqh t2, a1, t4 # U : (stall on a1)
+
+ mskql t0, a0, t0 # U :
+ or t1, t4, t1 # E :
+ mskqh t1, a0, t1 # U : (stall on t1)
+ or t0, t1, t1 # E : (stall on t1)
+
+ or t1, t6, t6 # E :
+ cmpbge zero, t6, t8 # E : (stall)
+ lda t6, -1 # E : for masking just below
+ bne t8, $u_final # U : (stall)
+
+ mskql t6, a1, t6 # U : mask out the bits we have
+ or t6, t2, t2 # E : already extracted before (stall)
+ cmpbge zero, t2, t8 # E : testing eos (stall)
+ bne t8, $u_late_head_exit # U : (stall)
+
+ /* Finally, we've got all the stupid leading edge cases taken care
+ of and we can set up to enter the main loop. */
+
+ stq_u t1, 0(a0) # L : store first output word
+ addq a0, 8, a0 # E :
+ extql t2, a1, t0 # U : position ho-bits of lo word
+ ldq_u t2, 8(a1) # U : read next high-order source word
+
+ addq a1, 8, a1 # E :
+ cmpbge zero, t2, t8 # E : (stall for t2)
+ nop # E :
+ bne t8, $u_eos # U : (stall)
+
+ /* Unaligned copy main loop. In order to avoid reading too much,
+ the loop is structured to detect zeros in aligned source words.
+ This has, unfortunately, effectively pulled half of a loop
+ iteration out into the head and half into the tail, but it does
+ prevent nastiness from accumulating in the very thing we want
+ to run as fast as possible.
+
+ On entry to this basic block:
+ t0 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word
+
+ We further know that t2 does not contain a null terminator. */
+
+ .align 3
+$u_loop:
+ extqh t2, a1, t1 # U : extract high bits for current word
+ addq a1, 8, a1 # E : (stall)
+ extql t2, a1, t3 # U : extract low bits for next time (stall)
+ addq a0, 8, a0 # E :
+
+ or t0, t1, t1 # E : current dst word now complete
+ ldq_u t2, 0(a1) # L : Latency=3 load high word for next time
+ stq_u t1, -8(a0) # L : save the current word (stall)
+ mov t3, t0 # E :
+
+ cmpbge zero, t2, t8 # E : test new word for eos
+ beq t8, $u_loop # U : (stall)
+ nop
+ nop
+
+ /* We've found a zero somewhere in the source word we just read.
+ If it resides in the lower half, we have one (probably partial)
+ word to write out, and if it resides in the upper half, we
+ have one full and one partial word left to write out.
+
+ On entry to this basic block:
+ t0 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word. */
+$u_eos:
+ extqh t2, a1, t1 # U :
+ or t0, t1, t1 # E : first (partial) source word complete (stall)
+ cmpbge zero, t1, t8 # E : is the null in this first bit? (stall)
+ bne t8, $u_final # U : (stall)
+
+$u_late_head_exit:
+ stq_u t1, 0(a0) # L : the null was in the high-order bits
+ addq a0, 8, a0 # E :
+ extql t2, a1, t1 # U :
+ cmpbge zero, t1, t8 # E : (stall)
+
+ /* Take care of a final (probably partial) result word.
+ On entry to this basic block:
+ t1 == assembled source word
+ t8 == cmpbge mask that found the null. */
+$u_final:
+ negq t8, t6 # E : isolate low bit set
+ and t6, t8, t12 # E : (stall)
+ and t12, 0x80, t6 # E : avoid dest word load if we can (stall)
+ bne t6, 1f # U : (stall)
+
+ ldq_u t0, 0(a0) # E :
+ subq t12, 1, t6 # E :
+ or t6, t12, t8 # E : (stall)
+ zapnot t1, t6, t1 # U : kill source bytes >= null (stall)
+
+ zap t0, t8, t0 # U : kill dest bytes <= null (2 cycle data stall)
+ or t0, t1, t1 # E : (stall)
+ nop
+ nop
+
+1: stq_u t1, 0(a0) # L :
+ ret (t9) # L0 : Latency=3
+ nop
+ nop
+
+ /* Unaligned copy entry point. */
+ .align 4
+$unaligned:
+
+ ldq_u t1, 0(a1) # L : load first source word
+ and a0, 7, t4 # E : find dest misalignment
+ and a1, 7, t5 # E : find src misalignment
+ /* Conditionally load the first destination word and a bytemask
+ with 0xff indicating that the destination byte is sacrosanct. */
+ mov zero, t0 # E :
+
+ mov zero, t6 # E :
+ beq t4, 1f # U :
+ ldq_u t0, 0(a0) # L :
+ lda t6, -1 # E :
+
+ mskql t6, a0, t6 # U :
+ nop
+ nop
+ nop
+1:
+ subq a1, t4, a1 # E : sub dest misalignment from src addr
+ /* If source misalignment is larger than dest misalignment, we need
+ extra startup checks to avoid SEGV. */
+ cmplt t4, t5, t12 # E :
+ beq t12, $u_head # U :
+ lda t2, -1 # E : mask out leading garbage in source
+
+ mskqh t2, t5, t2 # U :
+ ornot t1, t2, t3 # E : (stall)
+ cmpbge zero, t3, t8 # E : is there a zero? (stall)
+ beq t8, $u_head # U : (stall)
+
+ /* At this point we've found a zero in the first partial word of
+ the source. We need to isolate the valid source data and mask
+ it into the original destination data. (Incidentally, we know
+ that we'll need at least one byte of that original dest word.) */
+
+ ldq_u t0, 0(a0) # L :
+ negq t8, t6 # E : build bitmask of bytes <= zero
+ and t6, t8, t12 # E : (stall)
+ and a1, 7, t5 # E :
+
+ subq t12, 1, t6 # E :
+ or t6, t12, t8 # E : (stall)
+ srl t12, t5, t12 # U : adjust final null return value
+ zapnot t2, t8, t2 # U : prepare source word; mirror changes (stall)
+
+ and t1, t2, t1 # E : to source validity mask
+ extql t2, a1, t2 # U :
+ extql t1, a1, t1 # U : (stall)
+ andnot t0, t2, t0 # .. e1 : zero place for source to reside (stall)
+
+ or t0, t1, t1 # e1 : and put it there
+ stq_u t1, 0(a0) # .. e0 : (stall)
+ ret (t9) # e1 :
+ nop
+
+ .end __stxcpy
+
diff --git a/arch/alpha/lib/ev6-stxncpy.S b/arch/alpha/lib/ev6-stxncpy.S
new file mode 100644
index 000000000..7848b4c80
--- /dev/null
+++ b/arch/alpha/lib/ev6-stxncpy.S
@@ -0,0 +1,399 @@
+/*
+ * arch/alpha/lib/ev6-stxncpy.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
+ *
+ * Copy no more than COUNT bytes of the null-terminated string from
+ * SRC to DST.
+ *
+ * This is an internal routine used by strncpy, stpncpy, and strncat.
+ * As such, it uses special linkage conventions to make implementation
+ * of these public functions more efficient.
+ *
+ * On input:
+ * t9 = return address
+ * a0 = DST
+ * a1 = SRC
+ * a2 = COUNT
+ *
+ * Furthermore, COUNT may not be zero.
+ *
+ * On output:
+ * t0 = last word written
+ * t10 = bitmask (with one bit set) indicating the byte position of
+ * the end of the range specified by COUNT
+ * t12 = bitmask (with one bit set) indicating the last byte written
+ * a0 = unaligned address of the last *word* written
+ * a2 = the number of full words left in COUNT
+ *
+ * Furthermore, v0, a3-a5, t11, t12, and $at are untouched.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+ .set noat
+ .set noreorder
+
+ .text
+
+/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
+ doesn't like putting the entry point for a procedure somewhere in the
+ middle of the procedure descriptor. Work around this by putting the
+ aligned copy in its own procedure descriptor */
+
+
+ .ent stxncpy_aligned
+ .align 4
+stxncpy_aligned:
+ .frame sp, 0, t9, 0
+ .prologue 0
+
+ /* On entry to this basic block:
+ t0 == the first destination word for masking back in
+ t1 == the first source word. */
+
+ /* Create the 1st output word and detect 0's in the 1st input word. */
+ lda t2, -1 # E : build a mask against false zero
+ mskqh t2, a1, t2 # U : detection in the src word (stall)
+ mskqh t1, a1, t3 # U :
+ ornot t1, t2, t2 # E : (stall)
+
+ mskql t0, a1, t0 # U : assemble the first output word
+ cmpbge zero, t2, t8 # E : bits set iff null found
+ or t0, t3, t0 # E : (stall)
+ beq a2, $a_eoc # U :
+
+ bne t8, $a_eos # U :
+ nop
+ nop
+ nop
+
+ /* On entry to this basic block:
+ t0 == a source word not containing a null. */
+
+ /*
+ * nops here to:
+ * separate store quads from load quads
+ * limit of 1 bcond/quad to permit training
+ */
+$a_loop:
+ stq_u t0, 0(a0) # L :
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+ nop
+
+ ldq_u t0, 0(a1) # L :
+ addq a1, 8, a1 # E :
+ cmpbge zero, t0, t8 # E :
+ beq a2, $a_eoc # U :
+
+ beq t8, $a_loop # U :
+ nop
+ nop
+ nop
+
+ /* Take care of the final (partial) word store. At this point
+ the end-of-count bit is set in t8 iff it applies.
+
+ On entry to this basic block we have:
+ t0 == the source word containing the null
+ t8 == the cmpbge mask that found it. */
+
+$a_eos:
+ negq t8, t12 # E : find low bit set
+ and t8, t12, t12 # E : (stall)
+ /* For the sake of the cache, don't read a destination word
+ if we're not going to need it. */
+ and t12, 0x80, t6 # E : (stall)
+ bne t6, 1f # U : (stall)
+
+ /* We're doing a partial word store and so need to combine
+ our source and original destination words. */
+ ldq_u t1, 0(a0) # L :
+ subq t12, 1, t6 # E :
+ or t12, t6, t8 # E : (stall)
+ zapnot t0, t8, t0 # U : clear src bytes > null (stall)
+
+ zap t1, t8, t1 # .. e1 : clear dst bytes <= null
+ or t0, t1, t0 # e1 : (stall)
+ nop
+ nop
+
+1: stq_u t0, 0(a0) # L :
+ ret (t9) # L0 : Latency=3
+ nop
+ nop
+
+ /* Add the end-of-count bit to the eos detection bitmask. */
+$a_eoc:
+ or t10, t8, t8 # E :
+ br $a_eos # L0 : Latency=3
+ nop
+ nop
+
+ .end stxncpy_aligned
+
+ .align 4
+ .ent __stxncpy
+ .globl __stxncpy
+__stxncpy:
+ .frame sp, 0, t9, 0
+ .prologue 0
+
+ /* Are source and destination co-aligned? */
+ xor a0, a1, t1 # E :
+ and a0, 7, t0 # E : find dest misalignment
+ and t1, 7, t1 # E : (stall)
+ addq a2, t0, a2 # E : bias count by dest misalignment (stall)
+
+ subq a2, 1, a2 # E :
+ and a2, 7, t2 # E : (stall)
+ srl a2, 3, a2 # U : a2 = loop counter = (count - 1)/8 (stall)
+ addq zero, 1, t10 # E :
+
+ sll t10, t2, t10 # U : t10 = bitmask of last count byte
+ bne t1, $unaligned # U :
+ /* We are co-aligned; take care of a partial first word. */
+ ldq_u t1, 0(a1) # L : load first src word
+ addq a1, 8, a1 # E :
+
+ beq t0, stxncpy_aligned # U : avoid loading dest word if not needed
+ ldq_u t0, 0(a0) # L :
+ nop
+ nop
+
+ br stxncpy_aligned # .. e1 :
+ nop
+ nop
+ nop
+
+
+
+/* The source and destination are not co-aligned. Align the destination
+ and cope. We have to be very careful about not reading too much and
+ causing a SEGV. */
+
+ .align 4
+$u_head:
+ /* We know just enough now to be able to assemble the first
+ full source word. We can still find a zero at the end of it
+ that prevents us from outputting the whole thing.
+
+ On entry to this basic block:
+ t0 == the first dest word, unmasked
+ t1 == the shifted low bits of the first source word
+ t6 == bytemask that is -1 in dest word bytes */
+
+ ldq_u t2, 8(a1) # L : Latency=3 load second src word
+ addq a1, 8, a1 # E :
+ mskql t0, a0, t0 # U : mask trailing garbage in dst
+ extqh t2, a1, t4 # U : (3 cycle stall on t2)
+
+ or t1, t4, t1 # E : first aligned src word complete (stall)
+ mskqh t1, a0, t1 # U : mask leading garbage in src (stall)
+ or t0, t1, t0 # E : first output word complete (stall)
+ or t0, t6, t6 # E : mask original data for zero test (stall)
+
+ cmpbge zero, t6, t8 # E :
+ beq a2, $u_eocfin # U :
+ nop
+ nop
+
+ bne t8, $u_final # U :
+ lda t6, -1 # E : mask out the bits we have
+ mskql t6, a1, t6 # U : already seen (stall)
+ stq_u t0, 0(a0) # L : store first output word
+
+ or t6, t2, t2 # E :
+ cmpbge zero, t2, t8 # E : find nulls in second partial (stall)
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+
+ bne t8, $u_late_head_exit # U :
+ /* Finally, we've got all the stupid leading edge cases taken care
+ of and we can set up to enter the main loop. */
+ extql t2, a1, t1 # U : position hi-bits of lo word
+ ldq_u t2, 8(a1) # L : read next high-order source word
+ addq a1, 8, a1 # E :
+
+ cmpbge zero, t2, t8 # E : (stall)
+ beq a2, $u_eoc # U :
+ nop
+ nop
+
+ bne t8, $u_eos # e1 :
+ nop
+ nop
+ nop
+
+ /* Unaligned copy main loop. In order to avoid reading too much,
+ the loop is structured to detect zeros in aligned source words.
+ This has, unfortunately, effectively pulled half of a loop
+ iteration out into the head and half into the tail, but it does
+ prevent nastiness from accumulating in the very thing we want
+ to run as fast as possible.
+
+ On entry to this basic block:
+ t1 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word
+
+ We further know that t2 does not contain a null terminator. */
+
+ .align 4
+$u_loop:
+ extqh t2, a1, t0 # U : extract high bits for current word
+ addq a1, 8, a1 # E :
+ extql t2, a1, t3 # U : extract low bits for next time
+ addq a0, 8, a0 # E :
+
+ or t0, t1, t0 # E : current dst word now complete
+ ldq_u t2, 0(a1) # U : Latency=3 load high word for next time
+ stq_u t0, -8(a0) # U : save the current word (stall)
+ mov t3, t1 # E :
+
+ subq a2, 1, a2 # E :
+ cmpbge zero, t2, t8 # E : test new word for eos (2 cycle stall for data)
+ beq a2, $u_eoc # U : (stall)
+ nop
+
+ beq t8, $u_loop # U :
+ nop
+ nop
+ nop
+
+ /* We've found a zero somewhere in the source word we just read.
+ If it resides in the lower half, we have one (probably partial)
+ word to write out, and if it resides in the upper half, we
+ have one full and one partial word left to write out.
+
+ On entry to this basic block:
+ t1 == the shifted high-order bits from the previous source word
+ t2 == the unshifted current source word. */
+$u_eos:
+ extqh t2, a1, t0 # U :
+ or t0, t1, t0 # E : first (partial) source word complete (stall)
+ cmpbge zero, t0, t8 # E : is the null in this first bit? (stall)
+ bne t8, $u_final # U : (stall)
+
+ stq_u t0, 0(a0) # L : the null was in the high-order bits
+ addq a0, 8, a0 # E :
+ subq a2, 1, a2 # E :
+ nop
+
+$u_late_head_exit:
+ extql t2, a1, t0 # U :
+ cmpbge zero, t0, t8 # E :
+ or t8, t10, t6 # E : (stall)
+ cmoveq a2, t6, t8 # E : Latency=2, extra map slot (stall)
+
+ /* Take care of a final (probably partial) result word.
+ On entry to this basic block:
+ t0 == assembled source word
+ t8 == cmpbge mask that found the null. */
+$u_final:
+ negq t8, t6 # E : isolate low bit set
+ and t6, t8, t12 # E : (stall)
+ and t12, 0x80, t6 # E : avoid dest word load if we can (stall)
+ bne t6, 1f # U : (stall)
+
+ ldq_u t1, 0(a0) # L :
+ subq t12, 1, t6 # E :
+ or t6, t12, t8 # E : (stall)
+ zapnot t0, t8, t0 # U : kill source bytes > null
+
+ zap t1, t8, t1 # U : kill dest bytes <= null
+ or t0, t1, t0 # E : (stall)
+ nop
+ nop
+
+1: stq_u t0, 0(a0) # L :
+ ret (t9) # L0 : Latency=3
+
+$u_eoc: # end-of-count
+ extqh t2, a1, t0 # U :
+ or t0, t1, t0 # E : (stall)
+ cmpbge zero, t0, t8 # E : (stall)
+ nop
+
+$u_eocfin: # end-of-count, final word
+ or t10, t8, t8 # E :
+ br $u_final # L0 : Latency=3
+ nop
+ nop
+
+ /* Unaligned copy entry point. */
+ .align 4
+$unaligned:
+
+ ldq_u t1, 0(a1) # L : load first source word
+ and a0, 7, t4 # E : find dest misalignment
+ and a1, 7, t5 # E : find src misalignment
+ /* Conditionally load the first destination word and a bytemask
+ with 0xff indicating that the destination byte is sacrosanct. */
+ mov zero, t0 # E :
+
+ mov zero, t6 # E :
+ beq t4, 1f # U :
+ ldq_u t0, 0(a0) # L :
+ lda t6, -1 # E :
+
+ mskql t6, a0, t6 # U :
+ nop
+ nop
+ nop
+1:
+ subq a1, t4, a1 # E : sub dest misalignment from src addr
+
+ /* If source misalignment is larger than dest misalignment, we need
+ extra startup checks to avoid SEGV. */
+
+ cmplt t4, t5, t12 # E :
+ extql t1, a1, t1 # U : shift src into place
+ lda t2, -1 # E : for creating masks later
+ beq t12, $u_head # U : (stall)
+
+ mskqh t2, t5, t2 # U : begin src byte validity mask
+ cmpbge zero, t1, t8 # E : is there a zero?
+ extql t2, a1, t2 # U :
+ or t8, t10, t5 # E : test for end-of-count too
+
+ cmpbge zero, t2, t3 # E :
+ cmoveq a2, t5, t8 # E : Latency=2, extra map slot
+ nop # E : keep with cmoveq
+ andnot t8, t3, t8 # E : (stall)
+
+ beq t8, $u_head # U :
+ /* At this point we've found a zero in the first partial word of
+ the source. We need to isolate the valid source data and mask
+ it into the original destination data. (Incidentally, we know
+ that we'll need at least one byte of that original dest word.) */
+ ldq_u t0, 0(a0) # L :
+ negq t8, t6 # E : build bitmask of bytes <= zero
+ mskqh t1, t4, t1 # U :
+
+ and t6, t8, t12 # E :
+ subq t12, 1, t6 # E : (stall)
+ or t6, t12, t8 # E : (stall)
+ zapnot t2, t8, t2 # U : prepare source word; mirror changes (stall)
+
+ zapnot t1, t8, t1 # U : to source validity mask
+ andnot t0, t2, t0 # E : zero place for source to reside
+ or t0, t1, t0 # E : and put it there (stall both t0, t1)
+ stq_u t0, 0(a0) # L : (stall)
+
+ ret (t9) # L0 : Latency=3
+ nop
+ nop
+ nop
+
+ .end __stxncpy
+
diff --git a/arch/alpha/lib/ev67-strcat.S b/arch/alpha/lib/ev67-strcat.S
new file mode 100644
index 000000000..c426fe3ed
--- /dev/null
+++ b/arch/alpha/lib/ev67-strcat.S
@@ -0,0 +1,54 @@
+/*
+ * arch/alpha/lib/ev67-strcat.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Append a null-terminated string from SRC to DST.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Commentary: It seems bogus to walk the input string twice - once
+ * to determine the length, and then again while doing the copy.
+ * A significant (future) enhancement would be to only read the input
+ * string once.
+ */
+
+
+ .text
+
+ .align 4
+ .globl strcat
+ .ent strcat
+strcat:
+ .frame $30, 0, $26
+ .prologue 0
+
+ mov $16, $0 # E : set up return value
+ /* Find the end of the string. */
+ ldq_u $1, 0($16) # L : load first quadword (a0 may be misaligned)
+ lda $2, -1 # E :
+ insqh $2, $16, $2 # U :
+
+ andnot $16, 7, $16 # E :
+ or $2, $1, $1 # E :
+ cmpbge $31, $1, $2 # E : bits set iff byte == 0
+ bne $2, $found # U :
+
+$loop: ldq $1, 8($16) # L :
+ addq $16, 8, $16 # E :
+ cmpbge $31, $1, $2 # E :
+ beq $2, $loop # U :
+
+$found: cttz $2, $3 # U0 :
+ addq $16, $3, $16 # E :
+ /* Now do the append. */
+ mov $26, $23 # E :
+ br __stxcpy # L0 :
+
+ .end strcat
diff --git a/arch/alpha/lib/ev67-strchr.S b/arch/alpha/lib/ev67-strchr.S
new file mode 100644
index 000000000..03c56d583
--- /dev/null
+++ b/arch/alpha/lib/ev67-strchr.S
@@ -0,0 +1,88 @@
+/*
+ * arch/alpha/lib/ev67-strchr.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Return the address of a given character within a null-terminated
+ * string, or null if it is not found.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+ .set noreorder
+ .set noat
+
+ .align 4
+ .globl strchr
+ .ent strchr
+strchr:
+ .frame sp, 0, ra
+ .prologue 0
+
+ ldq_u t0, 0(a0) # L : load first quadword Latency=3
+ and a1, 0xff, t3 # E : 00000000000000ch
+ insbl a1, 1, t5 # U : 000000000000ch00
+ insbl a1, 7, a2 # U : ch00000000000000
+
+ insbl t3, 6, a3 # U : 00ch000000000000
+ or t5, t3, a1 # E : 000000000000chch
+ andnot a0, 7, v0 # E : align our loop pointer
+ lda t4, -1 # E : build garbage mask
+
+ mskqh t4, a0, t4 # U : only want relevant part of first quad
+ or a2, a3, a2 # E : chch000000000000
+ inswl a1, 2, t5 # E : 00000000chch0000
+ inswl a1, 4, a3 # E : 0000chch00000000
+
+ or a1, a2, a1 # E : chch00000000chch
+ or a3, t5, t5 # E : 0000chchchch0000
+ cmpbge zero, t0, t2 # E : bits set iff byte == zero
+ cmpbge zero, t4, t4 # E : bits set iff byte is garbage
+
+ /* This quad is _very_ serialized. Lots of stalling happens */
+ or t5, a1, a1 # E : chchchchchchchch
+ xor t0, a1, t1 # E : make bytes == c zero
+ cmpbge zero, t1, t3 # E : bits set iff byte == c
+ or t2, t3, t0 # E : bits set iff char match or zero match
+
+ andnot t0, t4, t0 # E : clear garbage bits
+ cttz t0, a2 # U0 : speculative (in case we get a match)
+ nop # E :
+ bne t0, $found # U :
+
+ /*
+ * Yuk. This loop is going to stall like crazy waiting for the
+ * data to be loaded. Not much can be done about it unless it's
+ * unrolled multiple times - is that safe to do in kernel space?
+ * Or would exception handling recovery code do the trick here?
+ */
+$loop: ldq t0, 8(v0) # L : Latency=3
+ addq v0, 8, v0 # E :
+ xor t0, a1, t1 # E :
+ cmpbge zero, t0, t2 # E : bits set iff byte == 0
+
+ cmpbge zero, t1, t3 # E : bits set iff byte == c
+ or t2, t3, t0 # E :
+ cttz t3, a2 # U0 : speculative (in case we get a match)
+ beq t0, $loop # U :
+
+$found: negq t0, t1 # E : clear all but least set bit
+ and t0, t1, t0 # E :
+ and t0, t3, t1 # E : bit set iff byte was the char
+ addq v0, a2, v0 # E : Add in the bit number from above
+
+ cmoveq t1, $31, v0 # E : Two mapping slots, latency = 2
+ nop
+ nop
+ ret # L0 :
+
+ .end strchr
diff --git a/arch/alpha/lib/ev67-strlen.S b/arch/alpha/lib/ev67-strlen.S
new file mode 100644
index 000000000..503928072
--- /dev/null
+++ b/arch/alpha/lib/ev67-strlen.S
@@ -0,0 +1,49 @@
+/*
+ * arch/alpha/lib/ev67-strlen.S
+ * 21264 version by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Finds length of a 0-terminated string. Optimized for the
+ * Alpha architecture:
+ *
+ * - memory accessed as aligned quadwords only
+ * - uses bcmpge to compare 8 bytes in parallel
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ */
+
+ .set noreorder
+ .set noat
+
+ .globl strlen
+ .ent strlen
+ .align 4
+strlen:
+ ldq_u $1, 0($16) # L : load first quadword ($16 may be misaligned)
+ lda $2, -1($31) # E :
+ insqh $2, $16, $2 # U :
+ andnot $16, 7, $0 # E :
+
+ or $2, $1, $1 # E :
+ cmpbge $31, $1, $2 # E : $2 <- bitmask: bit i == 1 <==> i-th byte == 0
+ nop # E :
+ bne $2, $found # U :
+
+$loop: ldq $1, 8($0) # L :
+ addq $0, 8, $0 # E : addr += 8
+ cmpbge $31, $1, $2 # E :
+ beq $2, $loop # U :
+
+$found:
+ cttz $2, $3 # U0 :
+ addq $0, $3, $0 # E :
+ subq $0, $16, $0 # E :
+ ret $31, ($26) # L0 :
+
+ .end strlen
diff --git a/arch/alpha/lib/ev67-strlen_user.S b/arch/alpha/lib/ev67-strlen_user.S
new file mode 100644
index 000000000..67f1e9426
--- /dev/null
+++ b/arch/alpha/lib/ev67-strlen_user.S
@@ -0,0 +1,109 @@
+/*
+ * arch/alpha/lib/ev67-strlen_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
+ *
+ * Return the length of the string including the NULL terminator
+ * (strlen+1) or zero if an error occurred.
+ *
+ * In places where it is critical to limit the processing time,
+ * and the data is not trusted, strnlen_user() should be used.
+ * It will return a value greater than its second argument if
+ * that limit would be exceeded. This implementation is allowed
+ * to access memory beyond the limit, but will not cross a page
+ * boundary when doing so.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+
+/* Allow an exception for an insn; exit if we get one. */
+#define EX(x,y...) \
+ 99: x,##y; \
+ .section __ex_table,"a"; \
+ .gprel32 99b; \
+ lda v0, $exception-99b(zero); \
+ .previous
+
+
+ .set noreorder
+ .set noat
+ .text
+
+ .globl __strlen_user
+ .ent __strlen_user
+ .frame sp, 0, ra
+
+ .align 4
+__strlen_user:
+ ldah a1, 32767(zero) # do not use plain strlen_user() for strings
+ # that might be almost 2 GB long; you should
+ # be using strnlen_user() instead
+ nop
+ nop
+ nop
+
+ .globl __strnlen_user
+
+ .align 4
+__strnlen_user:
+ ldgp $29,0($27) # E E : we do exceptions -- we need the gp.
+ /* Decomposes into lda/ldah */
+ .prologue 1
+ EX( ldq_u t0, 0(a0) ) # L : load first quadword (a0 may be misaligned)
+ lda t1, -1(zero) # E :
+
+ insqh t1, a0, t1 # U :
+ andnot a0, 7, v0 # E :
+ or t1, t0, t0 # E :
+ subq a0, 1, a0 # E : get our +1 for the return
+
+ cmpbge zero, t0, t1 # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0
+ subq a1, 7, t2 # E :
+ subq a0, v0, t0 # E :
+ bne t1, $found # U :
+
+ addq t2, t0, t2 # E :
+ addq a1, 1, a1 # E :
+ nop # E :
+ nop # E :
+
+ .align 4
+$loop: ble t2, $limit # U :
+ EX( ldq t0, 8(v0) ) # L :
+ nop # E :
+ nop # E :
+
+ cmpbge zero, t0, t1 # E :
+ subq t2, 8, t2 # E :
+ addq v0, 8, v0 # E : addr += 8
+ beq t1, $loop # U :
+
+$found: cttz t1, t2 # U0 :
+ addq v0, t2, v0 # E :
+ subq v0, a0, v0 # E :
+ ret # L0 :
+
+$exception:
+ nop
+ nop
+ nop
+ ret
+
+ .align 4 # currently redundant
+$limit:
+ nop
+ nop
+ subq a1, t2, v0
+ ret
+
+ .end __strlen_user
diff --git a/arch/alpha/lib/ev67-strncat.S b/arch/alpha/lib/ev67-strncat.S
new file mode 100644
index 000000000..4ae716cd2
--- /dev/null
+++ b/arch/alpha/lib/ev67-strncat.S
@@ -0,0 +1,94 @@
+/*
+ * arch/alpha/lib/ev67-strncat.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
+ *
+ * Append no more than COUNT characters from the null-terminated string SRC
+ * to the null-terminated string DST. Always null-terminate the new DST.
+ *
+ * This differs slightly from the semantics in libc in that we never write
+ * past count, whereas libc may write to count+1. This follows the generic
+ * implementation in lib/string.c and is, IMHO, more sensible.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ * Compiler Writer's Guide for the Alpha 21264
+ * abbreviated as 'CWG' in other comments here
+ * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ * E - either cluster
+ * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+
+ .text
+
+ .align 4
+ .globl strncat
+ .ent strncat
+strncat:
+ .frame $30, 0, $26
+ .prologue 0
+
+ mov $16, $0 # set up return value
+ beq $18, $zerocount # U :
+ /* Find the end of the string. */
+ ldq_u $1, 0($16) # L : load first quadword ($16 may be misaligned)
+ lda $2, -1($31) # E :
+
+ insqh $2, $0, $2 # U :
+ andnot $16, 7, $16 # E :
+ nop # E :
+ or $2, $1, $1 # E :
+
+ nop # E :
+ nop # E :
+ cmpbge $31, $1, $2 # E : bits set iff byte == 0
+ bne $2, $found # U :
+
+$loop: ldq $1, 8($16) # L :
+ addq $16, 8, $16 # E :
+ cmpbge $31, $1, $2 # E :
+ beq $2, $loop # U :
+
+$found: cttz $2, $3 # U0 :
+ addq $16, $3, $16 # E :
+ nop # E :
+ bsr $23, __stxncpy # L0 :/* Now do the append. */
+
+ /* Worry about the null termination. */
+
+ zapnot $1, $27, $2 # U : was last byte a null?
+ cmplt $27, $24, $5 # E : did we fill the buffer completely?
+ bne $2, 0f # U :
+ ret # L0 :
+
+0: or $5, $18, $2 # E :
+ nop
+ bne $2, 2f # U :
+ and $24, 0x80, $3 # E : no zero next byte
+
+ nop # E :
+ bne $3, 1f # U :
+ /* Here there are bytes left in the current word. Clear one. */
+ addq $24, $24, $24 # E : end-of-count bit <<= 1
+ nop # E :
+
+2: zap $1, $24, $1 # U :
+ nop # E :
+ stq_u $1, 0($16) # L :
+ ret # L0 :
+
+1: /* Here we must clear the first byte of the next DST word */
+ stb $31, 8($16) # L :
+ nop # E :
+ nop # E :
+ ret # L0 :
+
+$zerocount:
+ nop # E :
+ nop # E :
+ nop # E :
+ ret # L0 :
+
+ .end strncat
diff --git a/arch/alpha/lib/memcpy.c b/arch/alpha/lib/memcpy.c
index d715f0219..64083fc73 100644
--- a/arch/alpha/lib/memcpy.c
+++ b/arch/alpha/lib/memcpy.c
@@ -161,24 +161,3 @@ void * memcpy(void * dest, const void *src, size_t n)
/* For backward modules compatibility, define __memcpy. */
asm("__memcpy = memcpy; .globl __memcpy");
-
-void *memmove (void *dest, const void *src, size_t n)
-{
- if (dest <= src) {
- if (!(((unsigned long) dest ^ (unsigned long) src) & 7))
- __memcpy_aligned_up ((unsigned long) dest,
- (unsigned long) src, n);
- else
- __memcpy_unaligned_up ((unsigned long) dest,
- (unsigned long) src, n);
- }
- else {
- if (!(((unsigned long) dest ^ (unsigned long) src) & 7))
- __memcpy_aligned_dn ((unsigned long) dest,
- (unsigned long) src, n);
- else
- __memcpy_unaligned_dn ((unsigned long) dest,
- (unsigned long) src, n);
- }
- return dest;
-}
diff --git a/arch/alpha/lib/memmove.S b/arch/alpha/lib/memmove.S
new file mode 100644
index 000000000..3c8567e4e
--- /dev/null
+++ b/arch/alpha/lib/memmove.S
@@ -0,0 +1,103 @@
+/*
+ * arch/alpha/lib/memmove.S
+ *
+ * Barely optimized memmove routine for Alpha EV5.
+ *
+ * This is hand-massaged output from the original memcpy.c. We defer to
+ * memcpy whenever possible; the backwards copy loops are not unrolled.
+ */
+
+ .set noat
+ .set noreorder
+ .text
+
+ .align 4
+ .globl memmove
+ .ent memmove
+memmove:
+ addq $16,$18,$4
+ addq $17,$18,$5
+ cmpule $4,$17,$1 /* dest + n <= src */
+ cmpule $5,$16,$2 /* dest >= src + n */
+
+ bis $1,$2,$1
+ mov $16,$0
+ xor $16,$17,$2
+ bne $1,memcpy
+
+ and $2,7,$2 /* Test for src/dest co-alignment. */
+ bne $2,$misaligned
+
+ and $4,7,$1
+ beq $1,$skip_aligned_byte_loop_head
+
+$aligned_byte_loop_head:
+ lda $4,-1($4)
+ lda $5,-1($5)
+ unop
+ ble $18,$egress
+
+ ldq_u $3,0($5)
+ ldq_u $2,0($4)
+ lda $18,-1($18)
+ extbl $3,$5,$1
+
+ insbl $1,$4,$1
+ mskbl $2,$4,$2
+ bis $1,$2,$1
+ and $4,7,$6
+
+ stq_u $1,0($4)
+ bne $6,$aligned_byte_loop_head
+
+$skip_aligned_byte_loop_head:
+ lda $18,-8($18)
+ blt $18,$skip_aligned_word_loop
+
+$aligned_word_loop:
+ ldq $1,-8($5)
+ nop
+ lda $5,-8($5)
+ lda $18,-8($18)
+
+ stq $1,-8($4)
+ nop
+ lda $4,-8($4)
+ bge $18,$aligned_word_loop
+
+$skip_aligned_word_loop:
+ lda $18,8($18)
+ bgt $18,$byte_loop_tail
+ unop
+ ret $31,($26),1
+
+ .align 4
+$misaligned:
+ nop
+ fnop
+ unop
+ beq $18,$egress
+
+$byte_loop_tail:
+ ldq_u $3,-1($5)
+ ldq_u $2,-1($4)
+ lda $5,-1($5)
+ lda $4,-1($4)
+
+ lda $18,-1($18)
+ extbl $3,$5,$1
+ insbl $1,$4,$1
+ mskbl $2,$4,$2
+
+ bis $1,$2,$1
+ stq_u $1,0($4)
+ nop
+ bgt $18,$byte_loop_tail
+
+$egress:
+ ret $31,($26),1
+ nop
+ nop
+ nop
+
+ .end memmove
diff --git a/arch/alpha/lib/strcpy.S b/arch/alpha/lib/strcpy.S
index dd21b5208..e0728e4ad 100644
--- a/arch/alpha/lib/strcpy.S
+++ b/arch/alpha/lib/strcpy.S
@@ -17,6 +17,7 @@ strcpy:
mov $16, $0 # set up return value
mov $26, $23 # set up return address
+ unop
br __stxcpy # do the copy
.end strcpy
diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S
index dbc011c34..7d64d21d5 100644
--- a/arch/alpha/lib/strncpy.S
+++ b/arch/alpha/lib/strncpy.S
@@ -27,6 +27,10 @@ strncpy:
beq $18, 0f
mov $26, $23 # set return address
br __stxncpy # do the work of the copy
+
0: ret
+ nop
+ nop
+ nop
.end strncpy
diff --git a/arch/alpha/lib/stxcpy.S b/arch/alpha/lib/stxcpy.S
index b7b9da482..5a427634d 100644
--- a/arch/alpha/lib/stxcpy.S
+++ b/arch/alpha/lib/stxcpy.S
@@ -1,4 +1,5 @@
-/* stxcpy.S
+/*
+ * arch/alpha/lib/stxcpy.S
* Contributed by Richard Henderson (rth@tamu.edu)
*
* Copy a null-terminated string from SRC to DST.
diff --git a/arch/alpha/lib/stxncpy.S b/arch/alpha/lib/stxncpy.S
index 5bab622e0..d7cddb074 100644
--- a/arch/alpha/lib/stxncpy.S
+++ b/arch/alpha/lib/stxncpy.S
@@ -1,4 +1,5 @@
-/* stxncpy.S
+/*
+ * arch/alpha/lib/stxncpy.S
* Contributed by Richard Henderson (rth@tamu.edu)
*
* Copy no more than COUNT bytes of the null-terminated string from
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 52e2b36f7..3b0ae7011 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -185,7 +185,7 @@ show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!atomic_read(&mem_map[i].count))
+ else if (!page_count(mem_map+i))
free++;
else
shared += atomic_read(&mem_map[i].count) - 1;
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 6fbdb5ea1..f74033b36 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -35,16 +35,21 @@ INITRD_PHYS = 0x00800000
INITRD_VIRT = 0xc0800000
endif
+ifeq ($(CONFIG_ARCH_SHARK),y)
+ZTEXTADDR = 0x08508000
+ZRELADDR = 0x08008000
+endif
+
ifeq ($(CONFIG_FOOTBRIDGE),y)
ZTEXTADDR = 0x00008000
-PARAMS = 0x00000100
+PARAMS_PHYS = 0x00000100
INITRD_PHYS = 0x00800000
INITRD_VIRT = 0xc0800000
endif
ifeq ($(CONFIG_ARCH_INTEGRATOR),y)
ZTEXTADDR = 0x00008000
-PARAMS = 0x00000100
+PARAMS_PHYS = 0x00000100
INITRD_PHYS = 0x00800000
INITRD_VIRT = 0xc0800000
endif
@@ -65,6 +70,14 @@ ZRELADDR = 0xf0008000
ZBSSADDR = 0xf03e0000
endif
+ifeq ($(CONFIG_ARCH_P720T),y)
+ZTEXTADDR = 0xc0018000
+ZRELADDR = 0xc0018000
+PARAMS_PHYS = 0xc0000100
+INITRD_PHYS = 0xc0400000
+INITRD_VIRT = 0xc0400000
+endif
+
ifeq ($(CONFIG_ARCH_SA1100),y)
ZTEXTADDR = 0xc0008000
ZRELADDR = 0xc0008000
@@ -72,8 +85,9 @@ ifeq ($(CONFIG_SA1100_VICTOR),y)
ZTEXTADDR = 0x00002000
ZBSSADDR = 0xc0100000
endif
-ifeq ($(CONFIG_SA1100_THINCLIENT),y)
- ZTEXTADDR = 0xC0200000
+ifeq ($(CONFIG_SA1100_SHERMAN),y)
+ ZTEXTADDR = 0x00050000
+ ZBSSADDR = 0xc0100000
endif
ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
ZTEXTADDR = 0xC0200000
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 46b754ec5..bf8f1c947 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -18,6 +18,7 @@ ZLDFLAGS = -p -X -T vmlinux.lds
#
ifeq ($(CONFIG_ARCH_ACORN),y)
OBJS += ll_char_wr.o font.o
+ZLDFLAGS += -defsym params=$(PARAMS_PHYS)
endif
ifeq ($(CONFIG_ARCH_NETWINDER),y)
@@ -36,6 +37,11 @@ ifeq ($(CONFIG_ARCH_L7200),y)
OBJS += head-l7200.o
endif
+ifeq ($(CONFIG_ARCH_P720T),y)
+# Borrow this code from SA1100
+OBJS += head-sa1100.o
+endif
+
ifeq ($(CONFIG_ARCH_SA1100),y)
OBJS += head-sa1100.o setup-sa1100.o
ifeq ($(CONFIG_SA1100_NANOENGINE),y)
diff --git a/arch/arm/def-configs/a5k b/arch/arm/def-configs/a5k
index 11a1dfd67..c8ede2f80 100644
--- a/arch/arm/def-configs/a5k
+++ b/arch/arm/def-configs/a5k
@@ -2,36 +2,72 @@
# Automatically generated make config: don't edit
#
CONFIG_ARM=y
+# CONFIG_SBUS is not set
+CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_OBSOLETE=y
#
-# System and processor type
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+CONFIG_ARCH_ARCA5K=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Archimedes/A5000 Implementations (select only ONE)
#
# CONFIG_ARCH_ARC is not set
CONFIG_ARCH_A5K=y
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_FOOTBRIDGE is not set
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
CONFIG_ARCH_ACORN=y
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
# CONFIG_CPU_32 is not set
CONFIG_CPU_26=y
# CONFIG_PAGESIZE_16 is not set
-# CONFIG_ISA_DMA is not set
#
-# Loadable module support
+# Processor Type
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_DISCONTIGMEM is not set
#
# General setup
#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
@@ -42,9 +78,15 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_ELF is not set
# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+
+#
+# Parallel port support
+#
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_PC_FIFO is not set
+CONFIG_PARPORT_PC_SUPERIO=y
# CONFIG_PARPORT_ARC is not set
# CONFIG_PARPORT_AMIGA is not set
# CONFIG_PARPORT_MFC3 is not set
@@ -54,14 +96,9 @@ CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_1284 is not set
#
-# I2O device support
+# Memory Technology Devices (MTD)
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+# CONFIG_MTD is not set
#
# Plug and Play configuration
@@ -73,37 +110,16 @@ CONFIG_PARPORT_PC=m
# 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_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-CONFIG_BLK_DEV_IDE_ICSIDE=y
-# CONFIG_BLK_DEV_IDEDMA_ICS is not set
-# CONFIG_BLK_DEV_IDE_RAPIDE is not set
-# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_MD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=m
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
#
# Acorn-specific block devices
@@ -113,100 +129,6 @@ CONFIG_BLK_DEV_MFM=m
CONFIG_BLK_DEV_MFM_AUTODETECT=y
#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_ATOMWIDE_SERIAL is not set
-# CONFIG_DUALSP_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-
-#
-# PCMCIA character device support
-#
-# CONFIG_PCMCIA_SERIAL_CS is not set
-# CONFIG_AGP is not set
-
-#
-# Support for USB
-#
-# CONFIG_USB is not set
-
-#
-# Console drivers
-#
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_ACORN=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-
-#
# Networking options
#
# CONFIG_PACKET is not set
@@ -218,16 +140,10 @@ CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP 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_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-# CONFIG_SKB_LARGE is not set
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
@@ -238,9 +154,9 @@ CONFIG_INET=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -253,16 +169,6 @@ CONFIG_INET=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -272,7 +178,9 @@ CONFIG_NETDEVICES=y
#
# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_NET_SB1000 is not set
#
@@ -286,19 +194,18 @@ CONFIG_ARM_ETHER3=y
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_DM9102 is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
-# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -312,7 +219,7 @@ CONFIG_ARM_ETHER3=y
# CONFIG_NET_RADIO is not set
#
-# Token Ring driver support
+# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
@@ -325,9 +232,62 @@ CONFIG_ARM_ETHER3=y
# CONFIG_WAN is not set
#
-# PCMCIA network device support
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+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_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
#
-# CONFIG_NET_PCMCIA is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+CONFIG_BLK_DEV_IDE_ICSIDE=y
+# CONFIG_BLK_DEV_IDEDMA_ICS is not set
+# CONFIG_IDEDMA_ICS_AUTO is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_BLK_DEV_IDE_RAPIDE is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
#
# SCSI support
@@ -335,16 +295,90 @@ CONFIG_ARM_ETHER3=y
# CONFIG_SCSI is not set
#
-# Sound
+# I2O device support
#
-# CONFIG_SOUND is not set
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_ATOMWIDE_SERIAL is not set
+# CONFIG_DUALSP_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_PHILIPSPAR is not set
+# CONFIG_I2C_ELV is not set
+# CONFIG_I2C_VELLEMAN is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_CHARDEV=y
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+# CONFIG_PSMOUSE is not set
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
#
-# Filesystems
+# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
CONFIG_ADFS_FS=y
+# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
@@ -353,37 +387,60 @@ CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
CONFIG_ACORN_PARTITION=y
CONFIG_ACORN_PARTITION_ADFS=y
CONFIG_ACORN_PARTITION_ICS=y
@@ -394,6 +451,7 @@ CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
@@ -410,6 +468,10 @@ CONFIG_NLS=y
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -422,6 +484,45 @@ CONFIG_NLS=y
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_ACORN=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
#
# Kernel hacking
diff --git a/arch/arm/def-configs/assabet b/arch/arm/def-configs/assabet
index 7a4cd1778..8cf335a9f 100644
--- a/arch/arm/def-configs/assabet
+++ b/arch/arm/def-configs/assabet
@@ -12,57 +12,75 @@ CONFIG_EXPERIMENTAL=y
# CONFIG_OBSOLETE is not set
#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
# System Type
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_RPC is not set
CONFIG_ARCH_SA1100=y
#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
# SA11x0 Implementations
#
CONFIG_SA1100_ASSABET=y
# CONFIG_ASSABET_NEPONSET is not set
# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_THINCLIENT is not set
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_PANGOLIN is not set
CONFIG_ANGELBOOT=y
-# CONFIG_SA1100_FREQUENCY_SCALE is not set
+CONFIG_SA1100_FREQUENCY_SCALE=y
# CONFIG_SA1100_VOLTAGE_SCALE is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA1100=y
# CONFIG_ARCH_ACORN is not set
# CONFIG_FOOTBRIDGE is not set
# CONFIG_FOOTBRIDGE_HOST is not set
# CONFIG_FOOTBRIDGE_ADDIN is not set
-CONFIG_DISCONTIGMEM=y
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
#
-# Loadable module support
+# Processor Type
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA1100=y
+CONFIG_DISCONTIGMEM=y
#
# General setup
#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
CONFIG_HOTPLUG=y
#
-# PC Card support
+# PCMCIA/CardBus support
#
CONFIG_PCMCIA=y
# CONFIG_PCMCIA_DEBUG is not set
@@ -135,16 +153,10 @@ CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP 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_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
@@ -181,13 +193,13 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_NET_SB1000 is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
@@ -320,13 +332,14 @@ CONFIG_BLK_DEV_IDECS=y
#
CONFIG_VT=y
# CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_TOUCHSCREEN_SA1100 is not set
-# CONFIG_TOUCHSCREEN_BITSY is not set
# CONFIG_SERIAL is not set
# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=9600
+CONFIG_TOUCHSCREEN_UCB1200=y
+# CONFIG_TOUCHSCREEN_BITSY is not set
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=32
@@ -345,6 +358,10 @@ CONFIG_UNIX98_PTY_COUNT=32
# Joysticks
#
# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
@@ -354,11 +371,6 @@ CONFIG_UNIX98_PTY_COUNT=32
# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -367,10 +379,9 @@ CONFIG_UNIX98_PTY_COUNT=32
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_PCMCIA_SERIAL is not set
-# CONFIG_AGP is not set
#
# File systems
@@ -451,12 +462,14 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
@@ -473,6 +486,10 @@ CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -485,6 +502,7 @@ CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
#
# Console drivers
@@ -497,7 +515,9 @@ CONFIG_FB=y
#
CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
CONFIG_FB_SA1100=y
+# CONFIG_FB_MQ200 is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB2=y
@@ -517,8 +537,10 @@ CONFIG_FONT_8x8=y
#
CONFIG_SOUND=y
CONFIG_SOUND_UDA1341=y
+# CONFIG_SOUND_SA1100_SSP is not set
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_ES1370 is not set
# CONFIG_SOUND_ES1371 is not set
# CONFIG_SOUND_ESSSOLO1 is not set
diff --git a/arch/arm/def-configs/brutus b/arch/arm/def-configs/brutus
index 34391812a..bdd14f552 100644
--- a/arch/arm/def-configs/brutus
+++ b/arch/arm/def-configs/brutus
@@ -12,10 +12,17 @@ CONFIG_EXPERIMENTAL=y
# CONFIG_OBSOLETE is not set
#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
# System Type
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
@@ -27,33 +34,30 @@ CONFIG_ARCH_SA1100=y
#
# CONFIG_SA1100_ASSABET is not set
CONFIG_SA1100_BRUTUS=y
+# CONFIG_SA1100_CERF is not set
# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
# CONFIG_SA1100_THINCLIENT is not set
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
CONFIG_ANGELBOOT=y
# CONFIG_SA1100_FREQUENCY_SCALE is not set
# CONFIG_SA1100_VOLTAGE_SCALE is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA1100=y
# CONFIG_ARCH_ACORN is not set
# CONFIG_FOOTBRIDGE is not set
# CONFIG_FOOTBRIDGE_HOST is not set
# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA1100=y
CONFIG_DISCONTIGMEM=y
# CONFIG_PCI is not set
# CONFIG_ISA is not set
# CONFIG_ISA_DMA is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_PC_KEYMAP=y
#
# General setup
@@ -147,7 +151,7 @@ CONFIG_VT=y
# CONFIG_VT_CONSOLE is not set
CONFIG_SERIAL_SA1100=y
CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_TOUCHSCREEN_SA1100 is not set
+# CONFIG_TOUCHSCREEN_UCB1200 is not set
# CONFIG_TOUCHSCREEN_BITSY is not set
# CONFIG_SERIAL is not set
# CONFIG_SERIAL_EXTENDED is not set
@@ -192,9 +196,8 @@ CONFIG_UNIX98_PTY_COUNT=32
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
+# CONFIG_DRM is not set
#
# File systems
@@ -256,6 +259,7 @@ CONFIG_FB=y
#
CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
CONFIG_FB_SA1100=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
diff --git a/arch/arm/def-configs/cerf b/arch/arm/def-configs/cerf
index accb50b3f..e2bf1e06a 100644
--- a/arch/arm/def-configs/cerf
+++ b/arch/arm/def-configs/cerf
@@ -21,8 +21,8 @@ CONFIG_MODULES=y
#
# System Type
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
@@ -35,34 +35,39 @@ CONFIG_ARCH_SA1100=y
# CONFIG_SA1100_ASSABET is not set
# CONFIG_SA1100_BRUTUS is not set
CONFIG_SA1100_CERF=y
+CONFIG_SA1100_CERF_32MB=y
# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
# CONFIG_SA1100_THINCLIENT is not set
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
# CONFIG_ANGELBOOT is not set
# CONFIG_SA1100_FREQUENCY_SCALE is not set
# CONFIG_SA1100_VOLTAGE_SCALE is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA1100=y
# CONFIG_ARCH_ACORN is not set
# CONFIG_FOOTBRIDGE is not set
# CONFIG_FOOTBRIDGE_HOST is not set
# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA1100=y
CONFIG_DISCONTIGMEM=y
# CONFIG_PCI is not set
# CONFIG_ISA is not set
# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
#
# General setup
#
+# CONFIG_SA1100_CERF_CMDLINE is not set
CONFIG_HOTPLUG=y
#
-# PC Card support
+# PCMCIA/CardBus support
#
CONFIG_PCMCIA=y
# CONFIG_PCMCIA_DEBUG is not set
@@ -70,7 +75,7 @@ CONFIG_SA1100_PCMCIA=y
CONFIG_VIRTUAL_BUS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
CONFIG_NWFPE=y
CONFIG_KCORE_ELF=y
@@ -80,7 +85,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="keepinitrd"
+CONFIG_CMDLINE="console=ttyS0,38400"
CONFIG_LEDS=y
CONFIG_LEDS_TIMER=y
CONFIG_LEDS_CPU=y
@@ -126,7 +131,9 @@ 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_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
@@ -282,10 +289,11 @@ CONFIG_BLK_DEV_IDECS=y
#
# Character devices
#
-# CONFIG_VT is not set
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
CONFIG_SERIAL_SA1100=y
CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_TOUCHSCREEN_UCB1200 is not set
+CONFIG_TOUCHSCREEN_UCB1200=y
# CONFIG_TOUCHSCREEN_BITSY is not set
# CONFIG_SERIAL is not set
# CONFIG_SERIAL_EXTENDED is not set
@@ -329,9 +337,9 @@ CONFIG_UNIX98_PTY_COUNT=32
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_PCMCIA_SERIAL is not set
-# CONFIG_AGP is not set
#
# File systems
@@ -345,6 +353,7 @@ CONFIG_UNIX98_PTY_COUNT=32
# CONFIG_BFS_FS is not set
# CONFIG_FAT_FS is not set
# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -367,6 +376,7 @@ CONFIG_EXT2_FS=y
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
@@ -376,36 +386,37 @@ CONFIG_LOCKD=y
#
# Partition Types
#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_SA1100=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
# Sound
#
-CONFIG_SOUND=y
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND is not set
#
# USB support
diff --git a/arch/arm/def-configs/ebsa110 b/arch/arm/def-configs/ebsa110
index c2c7e0dcc..8f7981934 100644
--- a/arch/arm/def-configs/ebsa110
+++ b/arch/arm/def-configs/ebsa110
@@ -1,53 +1,79 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
#
CONFIG_ARM=y
+# CONFIG_EISA is not set
# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CO285 is not set
CONFIG_ARCH_EBSA110=y
# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA110=y
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
# CONFIG_ARCH_ACORN is not set
# CONFIG_FOOTBRIDGE is not set
# CONFIG_FOOTBRIDGE_HOST is not set
# CONFIG_FOOTBRIDGE_ADDIN is not set
-# CONFIG_DISCONTIGMEM is not set
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
#
-# Loadable module support
+# Processor Type
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA110=y
+# CONFIG_DISCONTIGMEM is not set
#
# General setup
#
+# CONFIG_ANGELBOOT is not set
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
# CONFIG_HOTPLUG is not set
# CONFIG_PCMCIA is not set
CONFIG_NET=y
CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
# CONFIG_NWFPE is not set
CONFIG_KCORE_ELF=y
@@ -55,6 +81,7 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
CONFIG_CMDLINE="root=/dev/nfs rw mem=16M console=ttyS1,38400n8"
CONFIG_LEDS=y
@@ -66,7 +93,7 @@ CONFIG_LEDS_TIMER=y
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
CONFIG_PARPORT_PC_FIFO=y
-CONFIG_PARPORT_PC_SUPERIO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
# CONFIG_PARPORT_ARC is not set
# CONFIG_PARPORT_AMIGA is not set
# CONFIG_PARPORT_MFC3 is not set
@@ -76,6 +103,11 @@ CONFIG_PARPORT_PC_SUPERIO=y
CONFIG_PARPORT_1284=y
#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Plug and Play configuration
#
# CONFIG_PNP is not set
@@ -88,15 +120,12 @@ CONFIG_PARPORT_1284=y
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
#
@@ -126,14 +155,12 @@ CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
CONFIG_SYN_COOKIES=y
-# CONFIG_SKB_LARGE is not set
#
# IP: Netfilter Configuration
@@ -164,9 +191,25 @@ CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_COMPAT_IPCHAINS=m
CONFIG_IP_NF_NAT_NEEDED=y
# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_EUI64=y
+# CONFIG_IPV6_NO_PB is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
+
+#
+#
+#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
@@ -174,6 +217,7 @@ CONFIG_IP_NF_NAT_NEEDED=y
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
@@ -196,6 +240,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
# CONFIG_NET_SB1000 is not set
@@ -217,8 +262,9 @@ CONFIG_ARM_AM79C961A=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -287,6 +333,11 @@ CONFIG_PPP_BSDCOMP=m
# CONFIG_ISDN is not set
#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -299,7 +350,8 @@ CONFIG_SERIAL_EXTENDED=y
# CONFIG_SERIAL_MULTIPORT is not set
# CONFIG_HUB6 is not set
# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
@@ -319,6 +371,10 @@ CONFIG_PRINTER=m
# Joysticks
#
# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
# CONFIG_QIC02_TAPE is not set
#
@@ -326,19 +382,17 @@ CONFIG_PRINTER=m
#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SOFT_WATCHDOG=y
# CONFIG_WDT is not set
# CONFIG_WDTPCI is not set
-CONFIG_SOFT_WATCHDOG=y
# CONFIG_PCWATCHDOG is not set
# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_60XX_WDT is not set
# CONFIG_MIXCOMWD is not set
+# CONFIG_I810_TCO is not set
+# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -347,9 +401,13 @@ CONFIG_SOFT_WATCHDOG=y
# Ftape, the floppy tape device driver
#
# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
#
# File systems
@@ -367,6 +425,7 @@ CONFIG_AUTOFS4_FS=y
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
# CONFIG_ISO9660_FS is not set
@@ -400,7 +459,6 @@ CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
@@ -427,6 +485,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_MAC_PARTITION is not set
# CONFIG_MSDOS_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
@@ -438,7 +497,7 @@ CONFIG_PARTITION_ADVANCED=y
#
# Kernel hacking
#
-# CONFIG_FRAME_POINTER is not set
+CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_INFO is not set
diff --git a/arch/arm/def-configs/footbridge b/arch/arm/def-configs/footbridge
index af2ccd01a..255c99945 100644
--- a/arch/arm/def-configs/footbridge
+++ b/arch/arm/def-configs/footbridge
@@ -2,54 +2,82 @@
# Automatically generated make config: don't edit
#
CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
#
-# System and Processor Type
+# Loadable module support
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-# CONFIG_ARCH_RPC is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-CONFIG_FOOTBRIDGE=y
-CONFIG_HOST_FOOTBRIDGE=y
-# CONFIG_ADDIN_FOOTBRIDGE is not set
+CONFIG_ARCH_FOOTBRIDGE=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
#
# Footbridge Implementations
#
-CONFIG_ARCH_EBSA285=y
# CONFIG_ARCH_CATS is not set
-CONFIG_ARCH_NETWINDER=y
# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+CONFIG_ARCH_EBSA285_HOST=y
+CONFIG_ARCH_NETWINDER=y
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
# CONFIG_ARCH_ACORN is not set
+CONFIG_FOOTBRIDGE=y
+CONFIG_FOOTBRIDGE_HOST=y
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_ARCH_EBSA285=y
CONFIG_CPU_32=y
# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
-CONFIG_CPU_SA110=y
-CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
-CONFIG_ISA=y
-CONFIG_ISA_DMA=y
-# CONFIG_SBUS is not set
-# CONFIG_PCMCIA is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Loadable module support
+# Processor Type
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA110=y
+# CONFIG_DISCONTIGMEM is not set
#
# General setup
#
+# CONFIG_ANGELBOOT is not set
+CONFIG_PCI=y
+CONFIG_ISA=y
+CONFIG_ISA_DMA=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
@@ -60,7 +88,12 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
#
# Parallel port support
@@ -76,25 +109,11 @@ CONFIG_PARPORT_PC_FIFO=y
# CONFIG_PARPORT_SUNBPP is not set
# CONFIG_PARPORT_OTHER is not set
CONFIG_PARPORT_1284=y
-CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-# CONFIG_LEDS_CPU is not set
#
-# IEEE 1394 (FireWire) support
+# Memory Technology Devices (MTD)
#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+# CONFIG_MTD is not set
#
# Plug and Play configuration
@@ -137,185 +156,13 @@ CONFIG_PARIDE_KTTI=m
CONFIG_PARIDE_ON20=m
CONFIG_PARIDE_ON26=m
# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_LVM is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
CONFIG_BLK_DEV_RAM=y
-# CONFIG_BLK_DEV_INITRD is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
-CONFIG_SERIAL_NONSTANDARD=y
-# CONFIG_COMPUTONE is not set
-# CONFIG_ROCKETPORT is not set
-# CONFIG_CYCLADES is not set
-CONFIG_SERIAL_21285=y
-CONFIG_SERIAL_21285_CONSOLE=y
-# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
-# CONFIG_ESPSERIAL is not set
-# CONFIG_MOXA_INTELLIO is not set
-# CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
-# CONFIG_N_HDLC is not set
-# CONFIG_RISCOM8 is not set
-# CONFIG_SPECIALIX is not set
-# CONFIG_SX is not set
-# CONFIG_STALDRV is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=m
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_CHARDEV is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-CONFIG_SOFT_WATCHDOG=y
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_MIXCOMWD is not set
-CONFIG_21285_WATCHDOG=m
-CONFIG_977_WATCHDOG=m
-CONFIG_DS1620=y
-CONFIG_NWBUTTON=y
-CONFIG_NWBUTTON_REBOOT=y
-CONFIG_NWFLASH=m
-CONFIG_NVRAM=m
-CONFIG_RTC=y
-
-#
-# Video For Linux
-#
-CONFIG_VIDEO_DEV=y
-# CONFIG_I2C_PARPORT is not set
-
-#
-# Radio Adapters
-#
-# CONFIG_RADIO_CADET is not set
-# CONFIG_RADIO_RTRACK is not set
-# CONFIG_RADIO_RTRACK2 is not set
-# CONFIG_RADIO_AZTECH is not set
-# CONFIG_RADIO_GEMTEK is not set
-# CONFIG_RADIO_MIROPCM20 is not set
-# CONFIG_RADIO_SF16FMI is not set
-# CONFIG_RADIO_TERRATEC is not set
-# CONFIG_RADIO_TRUST is not set
-# CONFIG_RADIO_TYPHOON is not set
-# CONFIG_RADIO_ZOLTRIX is not set
-
-#
-# Video Adapters
-#
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_BWQCAM is not set
-# CONFIG_VIDEO_CQCAM is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_ZORAN is not set
-# CONFIG_VIDEO_BUZ is not set
-# CONFIG_VIDEO_ZR36120 is not set
-CONFIG_VIDEO_CYBERPRO=m
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-
-#
-# Console drivers
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
-CONFIG_FB_CYBER2000=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-CONFIG_FBCON_VGA=y
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
#
# Networking options
@@ -327,24 +174,21 @@ CONFIG_PACKET_MMAP=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-CONFIG_IP_ALIAS=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_INET_ECN is not set
CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
-# CONFIG_SKB_LARGE is not set
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
+CONFIG_ATM=y
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
#
#
@@ -352,10 +196,11 @@ CONFIG_SYN_COOKIES=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
@@ -367,55 +212,6 @@ CONFIG_SYN_COOKIES=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-CONFIG_IRDA_OPTIONS=y
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-# CONFIG_IRDA_COMPRESSION is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-# CONFIG_IRTTY_SIR is not set
-# CONFIG_IRPORT_SIR is not set
-
-#
-# FIR device drivers
-#
-# CONFIG_NSC_FIR is not set
-CONFIG_WINBOND_FIR=m
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -427,13 +223,13 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_NET_SB1000 is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
CONFIG_NET_VENDOR_3COM=y
# CONFIG_EL1 is not set
# CONFIG_EL2 is not set
@@ -441,12 +237,15 @@ CONFIG_NET_VENDOR_3COM=y
# CONFIG_EL16 is not set
# CONFIG_EL3 is not set
# CONFIG_3C515 is not set
+# CONFIG_ELMC is not set
+# CONFIG_ELMC_II is not set
CONFIG_VORTEX=y
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
# CONFIG_NET_ISA is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
@@ -454,28 +253,34 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
-# CONFIG_DE4X5 is not set
CONFIG_TULIP=m
+# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
# CONFIG_DM9102 is not set
# CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PM is not set
# CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
+# CONFIG_NATSEMI is not set
CONFIG_NE2K_PCI=y
-# CONFIG_RTL8129 is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
# CONFIG_8139TOO is not set
+# CONFIG_RTL8129 is not set
# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
-# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -511,6 +316,55 @@ CONFIG_SLIP_MODE_SLIP6=y
# CONFIG_WAN is not set
#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+CONFIG_IRDA_OPTIONS=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+# CONFIG_IRPORT_SIR is not set
+
+#
+# FIR device drivers
+#
+# CONFIG_NSC_FIR is not set
+CONFIG_WINBOND_FIR=m
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
# ATA/IDE/MFM/RLL support
#
CONFIG_IDE=y
@@ -527,6 +381,15 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
# CONFIG_BLK_DEV_IDECS is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
@@ -546,7 +409,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
CONFIG_BLK_DEV_OFFBOARD=y
CONFIG_IDEDMA_PCI_AUTO=y
CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
# CONFIG_BLK_DEV_AEC62XX is not set
@@ -556,26 +418,25 @@ CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_BLK_DEV_AMD7409 is not set
# CONFIG_AMD7409_OVERRIDE is not set
# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_CMD64X_RAID is not set
CONFIG_BLK_DEV_CY82C693=y
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_HPT34X_AUTODMA is not set
# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_HPT366_FIP is not set
-# CONFIG_HPT366_MODE3 is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_PDC202XX=y
# CONFIG_PDC202XX_BURST is not set
-# CONFIG_PDC202XX_MASTER is not set
+# CONFIG_BLK_DEV_OSB4 is not set
# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_VIA82CXXX_TUNING is not set
CONFIG_BLK_DEV_SL82C105=y
# CONFIG_IDE_CHIPSETS is not set
CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
CONFIG_BLK_DEV_IDE_MODES=y
#
@@ -584,52 +445,164 @@ CONFIG_BLK_DEV_IDE_MODES=y
# CONFIG_SCSI is not set
#
-# Sound
+# IEEE 1394 (FireWire) support
#
-CONFIG_SOUND=m
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-CONFIG_SOUND_ADLIB=m
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_SOFTOSS is not set
-CONFIG_SOUND_SB=m
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-# CONFIG_SOUND_VIDC is not set
-CONFIG_SOUND_WAVEARTIST=m
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_DIGI is not set
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINK is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+CONFIG_SERIAL_21285=y
+CONFIG_SERIAL_21285_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_ACQUIRE_WDT is not set
+# CONFIG_60XX_WDT is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_I810_TCO is not set
+CONFIG_21285_WATCHDOG=m
+CONFIG_977_WATCHDOG=m
+CONFIG_DS1620=y
+CONFIG_NWBUTTON=y
+CONFIG_NWBUTTON_REBOOT=y
+CONFIG_NWFLASH=m
+# CONFIG_INTEL_RNG is not set
+CONFIG_NVRAM=m
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+CONFIG_VIDEO_PROC_FS=y
+# CONFIG_I2C_PARPORT is not set
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_BUZ is not set
+# CONFIG_VIDEO_ZR36120 is not set
+CONFIG_VIDEO_CYBERPRO=m
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
#
# File systems
@@ -647,6 +620,7 @@ CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=m
@@ -713,12 +687,14 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
@@ -735,6 +711,10 @@ CONFIG_NLS_CODEPAGE_852=m
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
# CONFIG_NLS_ISO8859_3 is not set
@@ -747,6 +727,110 @@ CONFIG_NLS_ISO8859_2=m
# CONFIG_NLS_ISO8859_14 is not set
CONFIG_NLS_ISO8859_15=m
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_PC_KEYB=y
+CONFIG_PC_KEYMAP=y
+CONFIG_VGA_CONSOLE=y
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_CLGEN is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_ACORN is not set
+# CONFIG_FB_CLPS711X is not set
+CONFIG_FB_CYBER2000=y
+# CONFIG_FB_SA1100 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+# CONFIG_FBCON_CFB32 is not set
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA_PLANES is not set
+CONFIG_FBCON_VGA=y
+# CONFIG_FBCON_HGA is not set
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+CONFIG_SOUND_ADLIB=m
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
+# CONFIG_SOUND_PSS is not set
+CONFIG_SOUND_SB=m
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_WAVEARTIST=m
+# CONFIG_SOUND_TVMIXER is not set
#
# USB support
@@ -757,7 +841,8 @@ CONFIG_USB_DEBUG=y
#
# Miscellaneous USB options
#
-# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
#
# USB Controllers
@@ -770,7 +855,8 @@ CONFIG_USB_OHCI=m
# USB Devices
#
CONFIG_USB_PRINTER=m
-CONFIG_USB_SCANNER=m
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
CONFIG_USB_AUDIO=m
# CONFIG_USB_ACM is not set
# CONFIG_USB_SERIAL is not set
@@ -785,19 +871,16 @@ CONFIG_USB_AUDIO=m
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_DSBR is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_NET1080 is not set
+
+#
+# USB Human Interface Devices (HID)
+#
#
-# USB HID
+# Input core support is needed for USB HID
#
-# CONFIG_USB_HID is not set
-CONFIG_USB_KBD=m
-CONFIG_USB_MOUSE=m
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
#
# Kernel hacking
diff --git a/arch/arm/def-configs/graphicsclient b/arch/arm/def-configs/graphicsclient
index 11415b363..92079d370 100644
--- a/arch/arm/def-configs/graphicsclient
+++ b/arch/arm/def-configs/graphicsclient
@@ -2,48 +2,88 @@
# Automatically generated make config: don't edit
#
CONFIG_ARM=y
+# CONFIG_SBUS is not set
+CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
#
-# System and processor type
+# Loadable module support
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-# CONFIG_ARCH_RPC is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_FOOTBRIDGE is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
CONFIG_ARCH_SA1100=y
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_EMPEG is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_PLEB is not set
CONFIG_SA1100_GRAPHICSCLIENT=y
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_TIFON is not set
-CONFIG_DISCONTIGMEM=y
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_ANGELBOOT is not set
+# CONFIG_SA1100_FREQUENCY_SCALE is not set
+# CONFIG_SA1100_VOLTAGE_SCALE is not set
# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
CONFIG_CPU_32=y
# CONFIG_CPU_26 is not set
+
+#
+# Processor Type
+#
CONFIG_CPU_32v4=y
CONFIG_CPU_SA1100=y
-# CONFIG_ISA_DMA is not set
-CONFIG_ALIGNMENT_TRAP=y
+CONFIG_DISCONTIGMEM=y
#
-# Loadable module support
+# General setup
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
+CONFIG_HOTPLUG=y
#
-# General setup
+# PCMCIA/CardBus support
#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_SA1100_PCMCIA=y
+CONFIG_VIRTUAL_BUS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
@@ -51,22 +91,24 @@ CONFIG_SYSCTL=y
CONFIG_NWFPE=y
CONFIG_KCORE_ELF=y
# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=nfs"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
# CONFIG_PARPORT is not set
-CONFIG_CMDLINE="ip=off"
#
-# I2O device support
+# Memory Technology Devices (MTD)
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+# CONFIG_MTD is not set
#
# Plug and Play configuration
@@ -78,118 +120,28 @@ CONFIG_CMDLINE="ip=off"
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-
-#
-# PCMCIA character device support
-#
-# CONFIG_AGP is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Console drivers
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_SA1100=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_FONTWIDTH8_ONLY=y
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_BLK_DEV_FLASH is not set
#
# Networking options
#
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
# CONFIG_NETLINK is not set
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
@@ -200,16 +152,10 @@ CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP 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_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
@@ -220,9 +166,9 @@ CONFIG_SKB_LARGE=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -235,16 +181,6 @@ CONFIG_SKB_LARGE=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -254,7 +190,9 @@ CONFIG_NETDEVICES=y
#
# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_NET_SB1000 is not set
#
@@ -270,12 +208,10 @@ CONFIG_NET_VENDOR_SMC=y
# CONFIG_ULTRA32 is not set
CONFIG_SMC9194=y
# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_DM9102 is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
# CONFIG_NET_POCKET is not set
#
@@ -295,7 +231,7 @@ CONFIG_SMC9194=y
# CONFIG_NET_RADIO is not set
#
-# Token Ring driver support
+# Token Ring devices
#
# CONFIG_TR is not set
# CONFIG_NET_FC is not set
@@ -310,7 +246,70 @@ CONFIG_SMC9194=y
#
# PCMCIA network device support
#
-# CONFIG_NET_PCMCIA is not set
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=m
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+# CONFIG_NET_PCMCIA_RADIO is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=m
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
#
# SCSI support
@@ -318,54 +317,221 @@ CONFIG_SMC9194=y
# CONFIG_SCSI is not set
#
-# Filesystems
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=38400
+# CONFIG_TOUCHSCREEN_UCB1200 is not set
+# CONFIG_TOUCHSCREEN_BITSY is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=32
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_PCMCIA_SERIAL is not set
+
+#
+# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
+CONFIG_RAMFS=y
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
CONFIG_ROOT_NFS=y
# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# 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_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 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_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_FONTWIDTH8_ONLY=y
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
#
# Kernel hacking
@@ -373,6 +539,6 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/integrator b/arch/arm/def-configs/integrator
new file mode 100644
index 000000000..07133bff5
--- /dev/null
+++ b/arch/arm/def-configs/integrator
@@ -0,0 +1,511 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_INTEGRATOR=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ARM720=y
+CONFIG_CPU_ARM920=y
+CONFIG_CPU_ARM920_CPU_IDLE=y
+CONFIG_CPU_ARM920_I_CACHE_ON=y
+CONFIG_CPU_ARM920_D_CACHE_ON=y
+# CONFIG_CPU_ARM920_WRITETHROUGH is not set
+# CONFIG_DISCONTIGMEM is not set
+
+#
+# General setup
+#
+# CONFIG_ANGELBOOT is not set
+CONFIG_PCI_INTEGRATOR=y
+CONFIG_PCI=y
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_NWFPE=y
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=1f04 mem=32M"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_MTDRAM is not set
+
+#
+# MTD drivers for mapped chips
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_JEDEC is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_PHYSMAP is not set
+
+#
+# Drivers for chip mappings
+#
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_VMAX is not set
+
+#
+# User modules and translation layers for MTD devices
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+CONFIG_MTD_ARM=y
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER 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=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+CONFIG_EEPRO100=y
+CONFIG_EEPRO100_PM=y
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139TOO is not set
+# CONFIG_RTL8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_AMBA=y
+CONFIG_SERIAL_INTEGRATOR=y
+CONFIG_SERIAL_AMBA_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+CONFIG_ROMFS_FS=y
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_NLS is not set
+
+#
+# Console drivers
+#
+CONFIG_KMI_KEYB=y
+CONFIG_PC_KEYMAP=y
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/def-configs/neponset b/arch/arm/def-configs/neponset
new file mode 100644
index 000000000..b77cbd143
--- /dev/null
+++ b/arch/arm/def-configs/neponset
@@ -0,0 +1,576 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_SBUS is not set
+CONFIG_UID16=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
+CONFIG_ARCH_SA1100=y
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+CONFIG_SA1100_ASSABET=y
+CONFIG_ASSABET_NEPONSET=y
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_BITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_XP860 is not set
+CONFIG_ANGELBOOT=y
+CONFIG_SA1111=y
+CONFIG_SA1100_FREQUENCY_SCALE=y
+# CONFIG_SA1100_VOLTAGE_SCALE is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32v4=y
+CONFIG_CPU_SA1100=y
+CONFIG_DISCONTIGMEM=y
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_SA1100_PCMCIA=y
+CONFIG_VIRTUAL_BUS=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_NWFPE=y
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="keepinitrd"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_FLASH is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER 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_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+CONFIG_NET_VENDOR_SMC=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+CONFIG_SMC9194=y
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=y
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+# CONFIG_NET_PCMCIA_RADIO is not set
+CONFIG_PCMCIA_NETCARD=y
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+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_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=9600
+CONFIG_TOUCHSCREEN_UCB1200=y
+# CONFIG_TOUCHSCREEN_BITSY is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=32
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_PCMCIA_SERIAL is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# 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_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 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_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_MQ200 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_FONTWIDTH8_ONLY=y
+CONFIG_FBCON_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+CONFIG_SOUND_UDA1341=y
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/thinclient b/arch/arm/def-configs/pangolin
index 5ad898616..6aebc40f8 100644
--- a/arch/arm/def-configs/thinclient
+++ b/arch/arm/def-configs/pangolin
@@ -1,57 +1,86 @@
#
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
#
CONFIG_ARM=y
+# CONFIG_SBUS is not set
CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
#
-# System and processor type
+# Loadable module support
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-# CONFIG_ARCH_RPC is not set
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_FOOTBRIDGE is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
CONFIG_ARCH_SA1100=y
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
# CONFIG_SA1100_ASSABET is not set
# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_EMPEG is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_CERF is not set
# CONFIG_SA1100_BITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_PLEB is not set
-CONFIG_SA1100_THINCLIENT=y
# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_NANOENGINE is not set
# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_TIFON is not set
-CONFIG_DISCONTIGMEM=y
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_XP860 is not set
+CONFIG_SA1100_PANGOLIN=y
+# CONFIG_ANGELBOOT is not set
+# CONFIG_SA1100_FREQUENCY_SCALE is not set
+# CONFIG_SA1100_VOLTAGE_SCALE is not set
# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
CONFIG_CPU_32=y
# CONFIG_CPU_26 is not set
CONFIG_CPU_32v4=y
CONFIG_CPU_SA1100=y
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCMCIA is not set
-CONFIG_ALIGNMENT_TRAP=y
+CONFIG_DISCONTIGMEM=y
#
-# Loadable module support
+# General setup
#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_PC_KEYMAP=y
+CONFIG_HOTPLUG=y
#
-# General setup
+# PCMCIA/CardBus support
#
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_SA1100_PCMCIA=y
+CONFIG_VIRTUAL_BUS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
@@ -59,26 +88,48 @@ CONFIG_SYSCTL=y
CONFIG_NWFPE=y
CONFIG_KCORE_ELF=y
# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="keepinitrd"
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
#
# Parallel port support
#
# CONFIG_PARPORT is not set
-CONFIG_CMDLINE="root=nfs"
-# CONFIG_LEDS is not set
#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_JEDEC is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_VMAX is not set
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
#
# Plug and Play configuration
@@ -94,95 +145,20 @@ CONFIG_CMDLINE="root=nfs"
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_STRIPED is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
CONFIG_BLK_DEV_FLASH=y
#
-# Character devices
-#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-
-#
-# Console drivers
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_SA1100=y
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_FONTWIDTH8_ONLY=y
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-
-#
# Networking options
#
CONFIG_PACKET=y
@@ -194,32 +170,20 @@ CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
+# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
-
-#
-#
-#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
@@ -232,16 +196,6 @@ CONFIG_SKB_LARGE=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -250,9 +204,10 @@ CONFIG_NETDEVICES=y
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_NET_SB1000 is not set
#
@@ -262,11 +217,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_ARM_AM79C961A is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
-CONFIG_NET_VENDOR_SMC=y
-# CONFIG_WD80x3 is not set
-# CONFIG_ULTRA is not set
-# CONFIG_ULTRA32 is not set
-CONFIG_SMC9194=y
+# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -304,11 +255,65 @@ CONFIG_SMC9194=y
# CONFIG_WAN is not set
#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=y
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
+# CONFIG_ARCNET_COM20020_CS is not set
+# CONFIG_PCMCIA_IBMTR is not set
+# CONFIG_NET_PCMCIA_RADIO is not set
+CONFIG_PCMCIA_NETCARD=y
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
# ATA/IDE/MFM/RLL support
#
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
#
# SCSI support
@@ -316,6 +321,72 @@ CONFIG_SMC9194=y
# CONFIG_SCSI is not set
#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=115200
+# CONFIG_TOUCHSCREEN_UCB1200 is not set
+# CONFIG_TOUCHSCREEN_BITSY is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=32
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_PCMCIA_SERIAL is not set
+
+#
# File systems
#
# CONFIG_QUOTA is not set
@@ -331,8 +402,10 @@ CONFIG_SMC9194=y
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_RAMFS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=1
+CONFIG_CRAMFS=y
+CONFIG_RAMFS=y
# CONFIG_ISO9660_FS is not set
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
@@ -361,7 +434,7 @@ CONFIG_EXT2_FS=y
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
-CONFIG_ROOT_NFS=y
+# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
@@ -387,6 +460,22 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_FB is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
# USB support
#
# CONFIG_USB is not set
@@ -397,6 +486,6 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO is not set
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_DEBUG_LL is not set
diff --git a/arch/arm/def-configs/rpc b/arch/arm/def-configs/rpc
index afbfda2da..6d744d34d 100644
--- a/arch/arm/def-configs/rpc
+++ b/arch/arm/def-configs/rpc
@@ -2,45 +2,77 @@
# Automatically generated make config: don't edit
#
CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
#
-# System and Processor Type
+# Loadable module support
#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-CONFIG_ARCH_RPC=y
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_FOOTBRIDGE is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+CONFIG_ARCH_RPC=y
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_CLPS711X is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+
+#
+# Footbridge Implementations
+#
+
+#
+# SA11x0 Implementations
+#
+
+#
+# CLPS711X/EP721X Implementations
+#
CONFIG_ARCH_ACORN=y
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
CONFIG_CPU_32=y
# CONFIG_CPU_26 is not set
+
+#
+# Processor Type
+#
CONFIG_CPU_32v3=y
CONFIG_CPU_ARM6=y
CONFIG_CPU_ARM7=y
CONFIG_CPU_SA110=y
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_SBUS is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_ALIGNMENT_TRAP is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_DISCONTIGMEM is not set
#
# General setup
#
+# CONFIG_ANGELBOOT is not set
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
CONFIG_NET=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
@@ -51,7 +83,9 @@ CONFIG_KCORE_ELF=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
+# CONFIG_ALIGNMENT_TRAP is not set
#
# Parallel port support
@@ -69,13 +103,9 @@ CONFIG_PARPORT_PC_SUPERIO=y
# CONFIG_PARPORT_1284 is not set
#
-# I2O device support
+# Memory Technology Devices (MTD)
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+# CONFIG_MTD is not set
#
# Plug and Play configuration
@@ -90,15 +120,12 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
#
@@ -106,114 +133,6 @@ CONFIG_BLK_DEV_INITRD=y
#
#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ATOMWIDE_SERIAL=y
-CONFIG_DUALSP_SERIAL=y
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
-CONFIG_PRINTER=m
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_CHARDEV=y
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_LOGIBUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_MOUSE=y
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-CONFIG_RPCMOUSE=y
-
-#
-# Console drivers
-#
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_ACORN=y
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_VGA is not set
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-
-#
# Networking options
#
# CONFIG_PACKET is not set
@@ -222,19 +141,14 @@ CONFIG_FONT_ACORN_8x8=y
# CONFIG_FILTER is not set
CONFIG_UNIX=y
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP 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_IP_MROUTE is not set
+# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
@@ -245,10 +159,11 @@ CONFIG_SKB_LARGE=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
@@ -260,16 +175,6 @@ CONFIG_SKB_LARGE=y
# CONFIG_NET_SCHED is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -281,14 +186,15 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
# CONFIG_NET_SB1000 is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-CONFIG_ARM_ETHER1=m
-CONFIG_ARM_ETHER3=m
+CONFIG_ARM_ETHER1=y
+CONFIG_ARM_ETHER3=y
CONFIG_ARM_ETHERH=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
@@ -303,8 +209,9 @@ CONFIG_ARM_ETHERH=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_YELLOWFIN is not set
# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
# CONFIG_SK98LIN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -337,6 +244,16 @@ CONFIG_PPPOE=m
# CONFIG_WAN is not set
#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
# ATA/IDE/MFM/RLL support
#
CONFIG_IDE=y
@@ -353,6 +270,15 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
@@ -372,6 +298,8 @@ CONFIG_BLK_DEV_IDEDMA=y
CONFIG_BLK_DEV_IDE_RAPIDE=y
# CONFIG_IDE_CHIPSETS is not set
CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
# CONFIG_BLK_DEV_IDE_MODES is not set
#
@@ -427,14 +355,14 @@ CONFIG_SCSI_IMM=m
# CONFIG_SCSI_IZIP_EPP16 is not set
# CONFIG_SCSI_IZIP_SLOW_CTR is not set
# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_PSI240I is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_DEBUG is not set
@@ -444,7 +372,7 @@ CONFIG_SCSI_ACORNSCSI_SYNC=y
CONFIG_SCSI_ARXESCSI=m
CONFIG_SCSI_CUMANA_2=m
CONFIG_SCSI_EESOXSCSI=m
-CONFIG_SCSI_POWERTECSCSI=m
+CONFIG_SCSI_POWERTECSCSI=y
#
# The following drivers are not fully supported
@@ -453,52 +381,101 @@ CONFIG_SCSI_CUMANA_1=m
CONFIG_SCSI_OAK1=m
#
-# Sound
+# I2O device support
#
-CONFIG_SOUND=m
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
-# CONFIG_SOUND_PSS is not set
-CONFIG_SOUND_SOFTOSS=m
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-CONFIG_SOUND_VIDC=m
-# CONFIG_SOUND_WAVEARTIST is not set
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_ATOMWIDE_SERIAL=y
+CONFIG_DUALSP_SERIAL=y
+CONFIG_SERIAL_EXTENDED=y
+# CONFIG_SERIAL_MANY_PORTS is not set
+CONFIG_SERIAL_SHARE_IRQ=y
+# CONFIG_SERIAL_DETECT_IRQ is not set
+# CONFIG_SERIAL_MULTIPORT is not set
+# CONFIG_HUB6 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_PHILIPSPAR is not set
+# CONFIG_I2C_ELV is not set
+# CONFIG_I2C_VELLEMAN is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_CHARDEV=y
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
+# CONFIG_PSMOUSE is not set
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+CONFIG_RPCMOUSE=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
#
# File systems
@@ -516,6 +493,7 @@ CONFIG_ADFS_FS=y
# CONFIG_UMSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
@@ -582,12 +560,14 @@ CONFIG_BSD_DISKLABEL=y
CONFIG_SOLARIS_X86_PARTITION=y
# CONFIG_UNIXWARE_DISKLABEL is not set
CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
CONFIG_SUN_PARTITION=y
CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_737=m
CONFIG_NLS_CODEPAGE_775=m
@@ -604,6 +584,10 @@ CONFIG_NLS_CODEPAGE_865=m
CONFIG_NLS_CODEPAGE_866=m
CONFIG_NLS_CODEPAGE_869=m
CONFIG_NLS_CODEPAGE_874=m
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
CONFIG_NLS_ISO8859_3=m
@@ -616,6 +600,99 @@ CONFIG_NLS_ISO8859_9=m
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
CONFIG_NLS_KOI8_R=m
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_ACORN=y
+# CONFIG_FB_CLPS711X is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_SA1100 is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FBCON_ADVANCED=y
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA_PLANES is not set
+# CONFIG_FBCON_VGA is not set
+# CONFIG_FBCON_HGA is not set
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_VIDC=m
+# CONFIG_SOUND_TVMIXER is not set
#
# USB support
@@ -627,7 +704,7 @@ CONFIG_NLS_KOI8_R=m
#
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_INFO is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_LL=y
diff --git a/arch/arm/def-configs/sherman b/arch/arm/def-configs/sherman
new file mode 100644
index 000000000..453fbf20f
--- /dev/null
+++ b/arch/arm/def-configs/sherman
@@ -0,0 +1,210 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_ARM=y
+
+#
+# System and processor type
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_FOOTBRIDGE is not set
+CONFIG_ARCH_SA1100=y
+CONFIG_CPU_SA1100=y
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_EMPEG is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_VICTOR is not set
+CONFIG_SA1100_SHERMAN=y
+# CONFIG_VICTOR_BOARD1 is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_ARM2 is not set
+# CONFIG_CPU_ARM3 is not set
+# CONFIG_CPU_ARM6 is not set
+# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_SA110=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ALIGNMENT_TRAP is not set
+# CONFIG_TEXT_SECTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# General setup
+#
+# CONFIG_NET is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_NWFPE=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+# CONFIG_PARPORT is not set
+CONFIG_CMDLINE=""
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_IDE is not set
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE_PARPORT is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_FLASH=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ACORN_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_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+
+#
+# Kernel hacking
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index e79dd71e6..868fbd4a7 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -451,7 +451,6 @@ void __init pcibios_init(void)
*/
pci_assign_unassigned_resources();
pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq);
- pci_set_bus_ranges();
}
char * __init pcibios_setup(char *str)
@@ -463,8 +462,29 @@ char * __init pcibios_setup(char *str)
return str;
}
+/*
+ * From arch/i386/kernel/pci-i386.c:
+ *
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
{
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long start = res->start;
+
+ if (start & 0x300)
+ res->start = (start + 0x3ff) & ~0x3ff;
+ }
}
/**
diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c
index 8c427b379..bf265fab3 100644
--- a/arch/arm/kernel/dec21285.c
+++ b/arch/arm/kernel/dec21285.c
@@ -258,17 +258,21 @@ static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs)
void __init dc21285_init(struct arm_pci_sysdata *sysdata)
{
unsigned long cntl;
- unsigned int mem_size;
+ unsigned int mem_size, mem_mask;
unsigned int pci_cmd = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
int cfn_mode;
+ mem_size = (unsigned int)high_memory - PAGE_OFFSET;
+ for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
+ if (mem_mask >= mem_size)
+ break;
+
/*
* These registers need to be set up whether we're the
* central function or not.
*/
- mem_size = (unsigned int)high_memory - PAGE_OFFSET;
- *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000;
+ *CSR_SDRAMBASEMASK = (mem_mask - 1) & 0x0ffc0000;
*CSR_SDRAMBASEOFFSET = 0;
*CSR_ROMBASEMASK = 0x80000000;
*CSR_CSRBASEMASK = 0;
diff --git a/arch/arm/kernel/dma-arc.c b/arch/arm/kernel/dma-arc.c
index 2ad2edf3b..121a2792b 100644
--- a/arch/arm/kernel/dma-arc.c
+++ b/arch/arm/kernel/dma-arc.c
@@ -156,7 +156,7 @@ static void a5k_floppy_enable_dma(dmach_t channel, dma_t *dma)
memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length);
regs.ARM_r9 = dma->buf.length;
regs.ARM_r10 = dma->buf.address;
- regs.ARM_fp = (int)PCIO_FLOPPYDMABASE;
+ regs.ARM_fp = FLOPPYDMA_BASE;
set_fiq_regs(&regs);
enable_irq(dma->dma_irq);
}
@@ -191,7 +191,7 @@ static struct dma_ops sound_dma_ops = {
void __init arch_dma_init(dma_t *dma)
{
#if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE)
- if (machine_is_arc()) {
+ if (machine_is_archimedes()) {
dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
dma[DMA_VIRTUAL_FLOPPY0].d_ops = &arc_floppy_data_dma_ops;
dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index c8c737404..e659b966d 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -84,7 +84,7 @@
strb r12, [r12, #0x38] @ Disable FIQ register
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #ioc_base_high @ point at IOC
.if ioc_base_low
orr r4, r4, #ioc_base_low
@@ -165,36 +165,23 @@ irq_prio_h: .byte 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
- mov r4, #0xf3000000
- ldrb \irqstat, [r4] @ get interrupts
- adr \base, irq_prio_ebsa110
-
- teq \irqstat, #0
- ldrneb \irqnr, [\base, \irqstat] @ get IRQ number
+ .macro get_irqnr_and_base, irqnr, stat, base, tmp
+ mov \base, #IRQ_STAT
+ ldrb \stat, [\base] @ get interrupts
+ mov \irqnr, #0
+ tst \stat, #15
+ addeq \irqnr, \irqnr, #4
+ moveq \stat, \stat, lsr #4
+ tst \stat, #3
+ addeq \irqnr, \irqnr, #2
+ moveq \stat, \stat, lsr #2
+ tst \stat, #1
+ addeq \irqnr, \irqnr, #1
+ moveq \stat, \stat, lsr #1
+ tst \stat, #1 @ bit 0 should be set
.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
#elif defined(CONFIG_ARCH_SHARK)
@@ -202,7 +189,7 @@ irq_prio_ebsa110:
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #0xe0000000
orr r4, r4, #0x20
@@ -238,7 +225,7 @@ irq_prio_ebsa110:
.equ dc21285_high, ARMCSR_BASE & 0xff000000
.equ dc21285_low, ARMCSR_BASE & 0x00ffffff
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #dc21285_high
.if dc21285_low
orr r4, r4, #dc21285_low
@@ -334,7 +321,7 @@ irq_prio_ebsa110:
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \irqstat, =INTCONT_BASE
ldr \base, =soft_irq_mask
ldr \irqstat, [\irqstat] @ get interrupts
@@ -362,7 +349,7 @@ ENTRY(soft_irq_mask)
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
ldr \irqstat, =0xffff7000
ldr \irqstat, [\irqstat] @ get interrupts
ldr \base, =soft_irq_mask
@@ -390,7 +377,7 @@ ENTRY(soft_irq_mask)
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #0xfa000000 @ ICIP = 0xfa050000
add r4, r4, #0x00050000
ldr \irqstat, [r4] @ get irqs
@@ -428,7 +415,7 @@ ENTRY(soft_irq_mask)
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov \irqstat, #irq_base_addr @ Virt addr IRQ regs
add \irqstat, \irqstat, #0x00001000 @ Status reg
ldr \irqstat, [\irqstat, #0] @ get interrupts
@@ -449,7 +436,7 @@ ENTRY(soft_irq_mask)
.macro disable_fiq
.endm
- .macro get_irqnr_and_base, irqnr, irqstat, base
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
/* FIXME: should not be using soo many LDRs here */
ldr \irqnr, =IO_ADDRESS(INTEGRATOR_IC_BASE)
ldr \irqstat, [\irqnr, #IRQ_STATUS] @ get masked status
@@ -470,6 +457,50 @@ ENTRY(soft_irq_mask)
.macro irq_prio_table
.endm
+#elif defined(CONFIG_ARCH_P720T)
+
+ .macro disable_fiq
+ .endm
+
+#if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
+#error INTSR stride != INTMR stride
+#endif
+
+ .macro get_irqnr_and_base, irqnr, stat, base, mask
+ mov \base, #CLPS7111_BASE
+ ldr \stat, [\base, #INTSR1]
+ ldr \mask, [\base, #INTMR1]
+ mov \irqnr, #4
+ mov \mask, \mask, lsl #16
+ and \stat, \stat, \mask, lsr #16
+ movs \stat, \stat, lsr #4
+ bne 1001f
+
+ add \base, \base, #INTSR2 - INTSR1
+ ldr \stat, [\base, #INTSR1]
+ ldr \mask, [\base, #INTMR1]
+ mov \irqnr, #16
+ mov \mask, \mask, lsl #16
+ and \stat, \stat, \mask, lsr #16
+
+1001: tst \stat, #255
+ addeq \irqnr, \irqnr, #8
+ moveq \stat, \stat, lsr #8
+ tst \stat, #15
+ addeq \irqnr, \irqnr, #4
+ moveq \stat, \stat, lsr #4
+ tst \stat, #3
+ addeq \irqnr, \irqnr, #2
+ moveq \stat, \stat, lsr #2
+ tst \stat, #1
+ addeq \irqnr, \irqnr, #1
+ moveq \stat, \stat, lsr #1
+ tst \stat, #1 @ bit 0 should be set
+ .endm
+
+ .macro irq_prio_table
+ .endm
+
#else
#error Unknown architecture
#endif
@@ -594,7 +625,7 @@ fpe_not_present:
adr r10, wfs_mask_data
ldmia r10, {r4, r5, r6, r7, r8}
ldr r10, [sp, #S_PC] @ Load PC
- sub r10, r10, #-4
+ sub r10, r10, #4
mask_pc r10, r10
ldrt r10, [r10] @ get instruction
and r5, r10, r5
@@ -660,7 +691,7 @@ __irq_svc: sub sp, sp, #S_FRAME_SIZE
add r4, sp, #S_SP
mov r6, lr
stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
-1: get_irqnr_and_base r0, r6, r5
+1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@@ -695,6 +726,28 @@ __und_svc: sub sp, sp, #S_FRAME_SIZE
ldmia sp, {r0 - pc}^ @ Restore SVC registers
.align 5
+__pabt_svc: sub sp, sp, #S_FRAME_SIZE
+ stmia sp, {r0 - r12} @ save r0 - r12
+ ldr r2, .LCabt
+ add r0, sp, #S_FRAME_SIZE
+ ldmia r2, {r2 - r4} @ get pc, cpsr
+ add r5, sp, #S_SP
+ mov r1, lr
+ stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
+ mrs r9, cpsr @ Enable interrupts if they were
+ tst r3, #I_BIT
+ biceq r9, r9, #I_BIT @ previously
+ msr cpsr_c, r9
+ mov r0, r2 @ address (pc)
+ mov r1, sp @ regs
+ bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler
+ mov r0, #I_BIT | MODE_SVC
+ msr cpsr_c, r0
+ ldr r0, [sp, #S_PSR]
+ msr spsr, r0
+ ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+
+ .align 5
.LCirq: .word __temp_irq
.LCund: .word __temp_und
.LCabt: .word __temp_abt
@@ -744,7 +797,7 @@ __irq_usr: sub sp, sp, #S_FRAME_SIZE
stmdb r8, {sp, lr}^
alignment_trap r4, r7, __temp_irq
zero_fp
-1: get_irqnr_and_base r0, r6, r5
+1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
adrsvc ne, lr, 1b
@
@@ -762,7 +815,7 @@ __und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
add r8, sp, #S_PC
ldmia r4, {r5 - r7}
stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0
- stmdb r8, {sp, lr}^ @ Save user r0 - r12
+ stmdb r8, {sp, lr}^ @ Save user sp, lr
alignment_trap r4, r7, __temp_und
zero_fp
adrsvc al, r9, ret_from_sys_call @ r9 = normal FP return
@@ -960,12 +1013,25 @@ vector_prefetch:
msr spsr_c, r13 @ switch to SVC_32 mode
ands lr, lr, #15
- ldreq lr, .LCtab_pabt
- ldrne lr, .LCtab_pabt + 4
+ ldr lr, [pc, lr, lsl #2]
movs pc, lr
-.LCtab_pabt: .word __pabt_usr
- .word __pabt_invalid
+.LCtab_pabt: .word __pabt_usr @ 0 (USR_26 / USR_32)
+ .word __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
+ .word __pabt_invalid @ 2 (IRQ_26 / IRQ_32)
+ .word __pabt_svc @ 3 (SVC_26 / SVC_32)
+ .word __pabt_invalid @ 4
+ .word __pabt_invalid @ 5
+ .word __pabt_invalid @ 6
+ .word __pabt_invalid @ 7
+ .word __pabt_invalid @ 8
+ .word __pabt_invalid @ 9
+ .word __pabt_invalid @ a
+ .word __pabt_invalid @ b
+ .word __pabt_invalid @ c
+ .word __pabt_invalid @ d
+ .word __pabt_invalid @ e
+ .word __pabt_invalid @ f
.align 5
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index b74d7550f..1be23e8fb 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -131,15 +131,14 @@ void set_fiq_regs(struct pt_regs *regs)
#endif
#ifdef CONFIG_CPU_32
"mrs %0, cpsr
- bic %1, %0, #0xf
- orr %1, %1, #0xc1
- msr cpsr, %1 @ select FIQ mode
+ mov %1, #0xc1
+ msr cpsr_c, %1 @ select FIQ mode
mov r0, r0
ldmia %2, {r8 - r14}
- msr cpsr, %0 @ return to SVC mode
+ msr cpsr_c, %0 @ return to SVC mode
mov r0, r0"
#endif
- : "=r" (tmp), "=r" (tmp2)
+ : "=&r" (tmp), "=&r" (tmp2)
: "r" (&regs->ARM_r8)
/* These registers aren't modified by the above code in a way
visible to the compiler, but we mark them as clobbers anyway
@@ -164,15 +163,14 @@ void get_fiq_regs(struct pt_regs *regs)
#endif
#ifdef CONFIG_CPU_32
"mrs %0, cpsr
- bic %1, %0, #0xf
- orr %1, %1, #0xc1
- msr cpsr, %1 @ select FIQ mode
+ mov %1, #0xc1
+ msr cpsr_c, %1 @ select FIQ mode
mov r0, r0
stmia %2, {r8 - r14}
- msr cpsr, %0 @ return to SVC mode
+ msr cpsr_c, %0 @ return to SVC mode
mov r0, r0"
#endif
- : "=r" (tmp), "=r" (tmp2)
+ : "=&r" (tmp), "=&r" (tmp2)
: "r" (&regs->ARM_r8)
/* These registers aren't modified by the above code in a way
visible to the compiler, but we mark them as clobbers anyway
diff --git a/arch/arm/kernel/head-armo.S b/arch/arm/kernel/head-armo.S
index f42f3337d..13dd0d09e 100644
--- a/arch/arm/kernel/head-armo.S
+++ b/arch/arm/kernel/head-armo.S
@@ -21,7 +21,6 @@
*/
.section ".text.init",#alloc,#execinstr
ENTRY(stext)
-ENTRY(_stext)
__entry: cmp pc, #0x02000000
ldrlt pc, LC0 @ if 0x01800000, call at 0x02080000
teq r0, #0 @ Check for old calling method
diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S
index 5e141bf51..5e529e702 100644
--- a/arch/arm/kernel/head-armv.S
+++ b/arch/arm/kernel/head-armv.S
@@ -16,28 +16,33 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
-#if (TEXTADDR & 0xffff) != 0x8000
-#error TEXTADDR must start at 0xXXXX8000
-#endif
-
#define K(a,b,c) ((a) << 24 | (b) << 12 | (c))
/*
- * swapper_pg_dir is the virtual address of the "init_task" page tables.
- * SWAPPER_PGDIR_OFFSET is the offset from the start of memory of the
- * page tables.
+ * We place the page tables 16K below TEXTADDR. Therefore, we must make sure
+ * that TEXTADDR is correctly set. Currently, we expect the least significant
+ * "short" to be 0x8000, but we could probably relax this restriction to
+ * TEXTADDR > PAGE_OFFSET + 0x4000
*
- * Note that at the moment, we assume TEXTADDR is the virtual equivalent
- * of start of memory + 0x8000
+ * Note that swapper_pg_dir is the virtual address of the page tables, and
+ * pgtbl gives us a position-independent reference to these tables. We can
+ * do this because stext == TEXT_ADDR
*/
-#define SWAPPER_PGDIR_OFFSET 0x4000
+#if (TEXTADDR & 0xffff) != 0x8000
+#error TEXTADDR must start at 0xXXXX8000
+#endif
+
.globl SYMBOL_NAME(swapper_pg_dir)
- .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x8000 + SWAPPER_PGDIR_OFFSET
+ .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000
+
+ .macro pgtbl, reg
+ adr \reg, stext
+ sub \reg, \reg, #0x4000
+ .endm
.section ".text.init",#alloc,#execinstr
.type stext, #function
ENTRY(stext)
-ENTRY(_stext)
/*
* Entry point. The general rules are:
* should be called with r0 == 0
@@ -185,7 +190,7 @@ __mmap_switched:
* r8 = page table flags
*/
__create_page_tables:
- add r4, r5, #SWAPPER_PGDIR_OFFSET
+ pgtbl r4
mov r0, r4
mov r3, #0
add r2, r0, #0x4000 @ 16k of page table
diff --git a/arch/arm/kernel/oldlatches.c b/arch/arm/kernel/oldlatches.c
index fe40c58b5..7d8858b9e 100644
--- a/arch/arm/kernel/oldlatches.c
+++ b/arch/arm/kernel/oldlatches.c
@@ -26,12 +26,12 @@ static unsigned char latch_b_copy;
/* newval=(oldval & ~mask)|newdata */
void oldlatch_aupdate(unsigned char mask,unsigned char newdata)
{
- if (machine_is_arc()) {
+ if (machine_is_archimedes()) {
latch_a_copy = (latch_a_copy & ~mask) | newdata;
printk("Latch: A = 0x%02x\n", latch_a_copy);
- outb(latch_a_copy, LATCHAADDR);
+ __raw_writeb(latch_a_copy, LATCHA_BASE);
} else
BUG();
}
@@ -40,19 +40,19 @@ void oldlatch_aupdate(unsigned char mask,unsigned char newdata)
/* newval=(oldval & ~mask)|newdata */
void oldlatch_bupdate(unsigned char mask,unsigned char newdata)
{
- if (machine_is_arc()) {
+ if (machine_is_archimedes()) {
latch_b_copy = (latch_b_copy & ~mask) | newdata;
printk("Latch: B = 0x%02x\n", latch_b_copy);
- outb(latch_b_copy, LATCHBADDR);
+ __raw_writeb(latch_b_copy, LATCHB_BASE);
} else
BUG();
}
static void __init oldlatch_init(void)
{
- if (machine_is_arc()) {
+ if (machine_is_archimedes()) {
oldlatch_aupdate(0xff, 0xff);
/* Thats no FDC reset...*/
oldlatch_bupdate(0xff, LATCHB_FDCRESET);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 8e8e3675f..9d0cc5c69 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -31,6 +31,7 @@
#include "ptrace.h"
extern void c_backtrace (unsigned long fp, int pmode);
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
const char *processor_modes[]=
{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -41,12 +42,6 @@ const char *processor_modes[]=
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
-static inline void console_verbose(void)
-{
- extern int console_loglevel;
- console_loglevel = 15;
-}
-
/*
* Stack pointers should always be within the kernels view of
* physical memory. If it is not there, then we can't dump
@@ -72,10 +67,14 @@ void dump_mem(unsigned long bottom, unsigned long top)
printk("%08lx: ", p);
for (i = 0; i < 8; i++, p += 4) {
+ unsigned int val;
+
if (p < bottom || p >= top)
printk(" ");
- else
- printk("%08lx ", *(unsigned long *)p);
+ else {
+ __get_user(val, (unsigned long *)p);
+ printk("%08x ", val);
+ }
if (i == 3)
printk(" ");
}
@@ -91,45 +90,57 @@ void dump_mem(unsigned long bottom, unsigned long top)
#define VMALLOC_OFFSET (8*1024*1024)
#define MODULE_RANGE (8*1024*1024)
-static void dump_instr(unsigned long pc, int user)
+static void dump_instr(struct pt_regs *regs)
{
- int pmin = -2, pmax = 3, ok = 0;
- extern char start_kernel, _etext;
-
- if (!user) {
- unsigned long module_start, module_end;
- unsigned long kernel_start, kernel_end;
-
- module_start = VMALLOC_START;
- module_end = module_start + MODULE_RANGE;
-
- kernel_start = (unsigned long)&start_kernel;
- kernel_end = (unsigned long)&_etext;
-
- if (pc >= kernel_start && pc < kernel_end) {
- if (pc + pmin < kernel_start)
- pmin = kernel_start - pc;
- if (pc + pmax > kernel_end)
- pmax = kernel_end - 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;
+ unsigned long addr = instruction_pointer(regs);
+ const int thumb = thumb_mode(regs);
+ const int width = thumb ? 4 : 8;
+ int i;
+
+ printk("Code: ");
+ for (i = -2; i < 3; i++) {
+ unsigned int val, bad;
+
+ if (thumb)
+ bad = __get_user(val, &((u16 *)addr)[i]);
+ else
+ bad = __get_user(val, &((u32 *)addr)[i]);
+
+ if (!bad)
+ printk(i == 0 ? "(%0*x) " : "%0*x", width, val);
+ else {
+ printk("bad PC value.");
+ break;
}
- } else
- ok = verify_area(VERIFY_READ, (void *)(pc + pmin), pmax - pmin) == 0;
-
- printk ("Code: ");
- if (ok) {
- int i;
- for (i = pmin; i < pmax; i++)
- printk(i == 0 ? "(%08lx) " : "%08lx ", ((unsigned long *)pc)[i]);
- printk ("\n");
- } else
- printk ("pc not in code space\n");
+ }
+ printk("\n");
+}
+
+static void dump_stack(struct task_struct *tsk, unsigned long sp)
+{
+ printk("Stack:\n");
+ dump_mem(sp - 16, 8192+(unsigned long)tsk);
+}
+
+static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
+{
+ unsigned int fp;
+ int ok = 1;
+
+ printk("Backtrace: ");
+ fp = regs->ARM_fp;
+ if (!fp) {
+ printk("no frame pointer");
+ ok = 0;
+ } else if (verify_stack(fp)) {
+ printk("invalid frame pointer %08lx", fp);
+ ok = 0;
+ } else if (fp < 4096+(unsigned long)tsk)
+ printk("frame pointer underflow");
+ printk("\n");
+
+ if (ok)
+ c_backtrace(fp, processor_mode(regs));
}
spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
@@ -141,9 +152,9 @@ void die(const char *str, struct pt_regs *regs, int err)
{
struct task_struct *tsk = current;
+ console_verbose();
spin_lock_irq(&die_lock);
- console_verbose();
printk("Internal error: %s: %x\n", str, err);
printk("CPU: %d\n", smp_processor_id());
show_regs(regs);
@@ -151,39 +162,22 @@ void die(const char *str, struct pt_regs *regs, int err)
current->comm, current->pid, 4096+(unsigned long)tsk);
if (!user_mode(regs)) {
- unsigned long sp = (unsigned long)(regs + 1);
- unsigned long fp;
- int dump_info = 1;
-
- printk("Stack: ");
- if (verify_stack(sp)) {
- printk("invalid kernel stack pointer %08lx", sp);
- dump_info = 0;
- } else if (sp < 4096+(unsigned long)tsk)
- printk("kernel stack pointer underflow");
- printk("\n");
-
- if (dump_info)
- dump_mem(sp - 16, 8192+(unsigned long)tsk);
-
- dump_info = 1;
-
- printk("Backtrace: ");
- fp = regs->ARM_fp;
- if (!fp) {
- printk("no frame pointer");
- dump_info = 0;
- } else if (verify_stack(fp)) {
- printk("invalid frame pointer %08lx", fp);
- dump_info = 0;
- } else if (fp < 4096+(unsigned long)tsk)
- printk("frame pointer underflow");
- printk("\n");
-
- if (dump_info)
- c_backtrace(fp, processor_mode(regs));
-
- dump_instr(instruction_pointer(regs), 0);
+ mm_segment_t fs;
+
+ /*
+ * We need to switch to kernel mode so that we can
+ * use __get_user to safely read from kernel space.
+ * Note that we now dump the code first, just in case
+ * the backtrace kills us.
+ */
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ dump_instr(regs);
+ dump_stack(tsk, (unsigned long)(regs + 1));
+ dump_backtrace(regs, tsk);
+
+ set_fs(fs);
}
spin_unlock_irq(&die_lock);
@@ -206,6 +200,7 @@ asmlinkage void do_undefinstr(int address, struct pt_regs *regs, int mode)
#ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
current->comm, current->pid, addr);
+ dump_instr(regs);
#endif
current->thread.error_code = 0;
@@ -228,6 +223,7 @@ asmlinkage void do_excpt(int address, struct pt_regs *regs, int mode)
#ifdef CONFIG_DEBUG_USER
printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n",
current->comm, current->pid, instruction_pointer(regs));
+ dump_instr(regs);
#endif
current->thread.error_code = 0;
@@ -275,7 +271,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
die("Oops", regs, 0);
cli();
- while(1);
+ panic("bad mode");
}
/*
@@ -332,6 +328,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
* something catastrophic has happened
*/
printk("[%d] %s: arm syscall %d\n", current->pid, current->comm, no);
+ dump_instr(regs);
if (user_mode(regs)) {
show_regs(regs);
c_backtrace(regs->ARM_fp, processor_mode(regs));
@@ -359,8 +356,9 @@ asmlinkage void deferred(int n, struct pt_regs *regs)
}
#ifdef CONFIG_DEBUG_USER
- printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", current->pid,
- current->comm, n);
+ printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
+ current->pid, current->comm, n);
+ dump_instr(regs);
#endif
force_sig(SIGILL, current);
die_if_kernel("Oops", regs, n);
@@ -384,21 +382,10 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
siginfo_t info;
#ifdef CONFIG_DEBUG_USER
- dump_instr(addr, 1);
- {
- pgd_t *pgd;
-
- pgd = pgd_offset(current->mm, addr);
- printk ("*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");
- }
+ printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
+ current->pid, current->comm, code, instr);
+ dump_instr(regs);
+ show_pte(current->mm, addr);
#endif
info.si_signo = SIGILL;
diff --git a/arch/arm/kernel/via82c505.c b/arch/arm/kernel/via82c505.c
index 42a2bb448..ab97b6e80 100644
--- a/arch/arm/kernel/via82c505.c
+++ b/arch/arm/kernel/via82c505.c
@@ -76,7 +76,7 @@ static struct pci_ops via82c505_ops = {
#ifdef CONFIG_ARCH_SHARK
-static char size_wanted = 0;
+static char size_wanted;
static int
dummy_read_config_byte(struct pci_dev *dev, int where, u8 *value)
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index b7e29ca55..fa7f10117 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -13,19 +13,35 @@ L_OBJS := changebit.o csumipv6.o csumpartial.o csumpartialcopy.o \
strncpy_from_user.o strnlen_user.o strchr.o strrchr.o \
testchangebit.o testclearbit.o testsetbit.o uaccess.o
+l-obj-y :=
+l-obj-n :=
+
O_TARGET := lib.o
O_OBJS := backtrace.o delay.o
-L_OBJS_arc := io-acorn.o floppydma.o
-L_OBJS_rpc := io-acorn.o floppydma.o
+ifeq ($(CONFIG_ARCH_ACORN),y)
+ half := n
+ full := y
+else
+ half := y
+ full := n
+endif
+
+L_OBJS_arc := ecard.o io-acorn.o floppydma.o
+L_OBJS_rpc := ecard.o io-acorn.o floppydma.o
L_OBJS_clps7500 := io-acorn.o
-L_OBJS_ebsa110 := io-ebsa110.o
-L_OBJS_footbridge := io-footbridge.o
+L_OBJS_footbridge := io-pcio.o
L_OBJS_l7200 := io-acorn.o
-L_OBJS_nexuspci := io-footbridge.o
-L_OBJS_sa1100 := io-footbridge.o
+L_OBJS_nexuspci := io-pcio.o
+L_OBJS_sa1100 := io-pcio.o
L_OBJS_shark := io-shark.o
-L_OBJS_integrator := io-shark.o
+L_OBJS_integrator := io-pcio.o
+L_OBJS_clps711x := io-shark.o
+
+l-obj-y += io-readsb.o io-writesb.o
+l-obj-$(full) += io-readsw-armv3.o io-writesw-armv3.o
+l-obj-$(half) += io-readsw-armv4.o io-writesw-armv4.o
+l-obj-y += io-readsl.o io-writesl.o
ifeq ($(PROCESSOR),armo)
L_OBJS += uaccess-armo.o
@@ -35,7 +51,7 @@ ifneq ($(MACHINE),ebsa110)
OX_OBJS += io.o
endif
-L_OBJS += $(L_OBJS_$(MACHINE))
+L_OBJS += $(L_OBJS_$(MACHINE)) $(l-obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/arm/lib/ecard.S b/arch/arm/lib/ecard.S
new file mode 100644
index 000000000..9b0452d01
--- /dev/null
+++ b/arch/arm/lib/ecard.S
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/arm/lib/ecard.S
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/config.h> /* for CONFIG_CPU_nn */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+#if defined(CONFIG_CPU_26)
+#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 --git a/arch/arm/lib/io-acorn.S b/arch/arm/lib/io-acorn.S
index bc40496ac..a40272fdb 100644
--- a/arch/arm/lib/io-acorn.S
+++ b/arch/arm/lib/io-acorn.S
@@ -40,8 +40,6 @@
addeq \rd, \rd, #diff_pcio_base
.endm
-.iosw_bad_align_msg:
- .ascii "insw: bad buffer alignment (%p), called from %08lX\n\0"
.iosl_warning:
.ascii "<4>insl/outsl not implemented, called from %08lX\0"
.align
@@ -56,422 +54,38 @@ ENTRY(outsl)
mov r1, lr
b SYMBOL_NAME(printk)
-.iosw_bad_alignment:
- adr r0, .iosw_bad_align_msg
- mov r2, lr
- b SYMBOL_NAME(panic)
-
-
/* Purpose: read a block of data from a hardware register to memory.
* Proto : void insw(int from_port, void *to, int len_in_words);
* Notes : increment to, 'to' must be 16-bit aligned
*/
-.insw_align: tst r1, #1
- bne .iosw_bad_alignment
-
- ldr r3, [r0]
- strb r3, [r1], #1
- mov r3, r3, lsr #8
- strb r3, [r1], #1
-
- subs r2, r2, #1
- bne .insw_aligned
-
ENTRY(insw)
teq r2, #0
- RETINSTR(moveq,pc,lr)
+ RETINSTR(moveq, pc, lr)
addr r0
- tst r1, #3
- bne .insw_align
-
-.insw_aligned: mov ip, #0xff
- orr ip, ip, ip, lsl #8
- stmfd sp!, {r4, r5, r6, lr}
-
- subs r2, r2, #8
- bmi .no_insw_8
-
-.insw_8_lp: ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- ldr r4, [r0]
- and r4, r4, ip
- ldr r5, [r0]
- orr r4, r4, r5, lsl #16
-
- ldr r5, [r0]
- and r5, r5, ip
- ldr r6, [r0]
- orr r5, r5, r6, lsl #16
-
- ldr r6, [r0]
- and r6, r6, ip
- ldr lr, [r0]
- orr r6, r6, lr, lsl #16
-
- stmia r1!, {r3 - r6}
- subs r2, r2, #8
- bpl .insw_8_lp
- tst r2, #7
- LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
+ b __arch_readsw
-.no_insw_8: tst r2, #4
- beq .no_insw_4
-
- ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- ldr r4, [r0]
- and r4, r4, ip
- ldr r5, [r0]
- orr r4, r4, r5, lsl #16
-
- stmia r1!, {r3, r4}
-
-.no_insw_4: tst r2, #2
- beq .no_insw_2
-
- ldr r3, [r0]
- and r3, r3, ip
- ldr r4, [r0]
- orr r3, r3, r4, lsl #16
-
- str r3, [r1], #4
-
-.no_insw_2: tst r2, #1
- ldrne r3, [r0]
- strneb r3, [r1], #1
- movne r3, r3, lsr #8
- strneb r3, [r1]
- LOADREGS(fd, sp!, {r4, r5, r6, pc})
+ENTRY(insb)
+ teq r2, #0
+ RETINSTR(moveq, pc, lr)
+ addr r0
+ b __arch_readsb
@ Purpose: write a block of data from memory to a hardware register.
@ Proto : outsw(int to_reg, void *from, int len_in_words);
@ Notes : increments from
-.outsw_align: tst r1, #1
- bne .iosw_bad_alignment
-
- add r1, r1, #2
-
- ldr r3, [r1, #-4]
- mov r3, r3, lsr #16
- orr r3, r3, r3, lsl #16
- str r3, [r0]
- subs r2, r2, #1
- bne .outsw_aligned
-
ENTRY(outsw)
teq r2, #0
- RETINSTR(moveq,pc,lr)
- addr r0
- tst r1, #3
- bne .outsw_align
-
-.outsw_aligned: stmfd sp!, {r4, r5, r6, lr}
-
- subs r2, r2, #8
- bmi .no_outsw_8
-.outsw_8_lp: ldmia r1!, {r3, r4, r5, r6}
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r4, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r4, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r5, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r5, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r6, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r6, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- subs r2, r2, #8
- bpl .outsw_8_lp
- tst r2, #7
- LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
-
-.no_outsw_8: tst r2, #4
- beq .no_outsw_4
-
- ldmia r1!, {r3, r4}
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
- mov ip, r4, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r4, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
-.no_outsw_4: tst r2, #2
- beq .no_outsw_2
-
- ldr r3, [r1], #4
-
- mov ip, r3, lsl #16
- orr ip, ip, ip, lsr #16
- str ip, [r0]
-
- mov ip, r3, lsr #16
- orr ip, ip, ip, lsl #16
- str ip, [r0]
-
-.no_outsw_2: tst r2, #1
-
- ldrne r3, [r1]
-
- movne ip, r3, lsl #16
- orrne ip, ip, ip, lsr #16
- strne ip, [r0]
-
- LOADREGS(fd, sp!, {r4, r5, r6, pc})
-
-.insb_align: rsb ip, ip, #4
- cmp ip, r2
- movgt ip, r2
- cmp ip, #2
- ldrb r3, [r0]
- strb r3, [r1], #1
- ldrgeb r3, [r0]
- strgeb r3, [r1], #1
- ldrgtb r3, [r0]
- strgtb r3, [r1], #1
- subs r2, r2, ip
- bne .insb_aligned
-
-ENTRY(insb)
- teq r2, #0
- moveq pc, lr
+ RETINSTR(moveq, pc, lr)
addr r0
- ands ip, r1, #3
- bne .insb_align
-
-.insb_aligned: stmfd sp!, {r4 - r6, lr}
-
- subs r2, r2, #16
- bmi .insb_no_16
-
-.insb_16_lp: ldrb r3, [r0]
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #8
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #16
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #24
- ldrb r4, [r0]
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #8
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #16
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #24
- ldrb r5, [r0]
- ldrb r6, [r0]
- orr r5, r5, r6, lsl #8
- ldrb r6, [r0]
- orr r5, r5, r6, lsl #16
- ldrb r6, [r0]
- orr r5, r5, r6, lsl #24
- ldrb r6, [r0]
- ldrb ip, [r0]
- orr r6, r6, ip, lsl #8
- ldrb ip, [r0]
- orr r6, r6, ip, lsl #16
- ldrb ip, [r0]
- orr r6, r6, ip, lsl #24
- stmia r1!, {r3 - r6}
- subs r2, r2, #16
- bpl .insb_16_lp
-
- tst r2, #15
- LOADREGS(eqfd, sp!, {r4 - r6, pc})
-
-.insb_no_16: tst r2, #8
- beq .insb_no_8
-
- ldrb r3, [r0]
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #8
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #16
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #24
- ldrb r4, [r0]
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #8
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #16
- ldrb r5, [r0]
- orr r4, r4, r5, lsl #24
- stmia r1!, {r3, r4}
-
-.insb_no_8: tst r2, #4
- bne .insb_no_4
-
- ldrb r3, [r0]
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #8
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #16
- ldrb r4, [r0]
- orr r3, r3, r4, lsl #24
- str r3, [r1], #4
-
-.insb_no_4: ands r2, r2, #3
- LOADREGS(eqfd, sp!, {r4 - r6, pc})
- cmp r2, #2
- ldrb r3, [r0]
- strb r3, [r1], #1
- ldrgeb r3, [r0]
- strgeb r3, [r1], #1
- ldrgtb r3, [r0]
- strgtb r3, [r1]
- LOADREGS(fd, sp!, {r4 - r6, pc})
-
-
-
-.outsb_align: rsb ip, ip, #4
- cmp ip, r2
- mov ip, r2
- cmp ip, #2
- ldrb r3, [r1], #1
- strb r3, [r0]
- ldrgeb r3, [r1], #1
- strgeb r3, [r0]
- ldrgtb r3, [r1], #1
- strgtb r3, [r0]
- subs r2, r2, ip
- bne .outsb_aligned
+ b __arch_writesw
ENTRY(outsb)
teq r2, #0
- moveq pc, lr
+ RETINSTR(moveq, pc, lr)
addr r0
- ands ip, r1, #3
- bne .outsb_align
-
-.outsb_aligned: stmfd sp!, {r4 - r6, lr}
-
- subs r2, r2, #16
- bmi .outsb_no_16
-
-.outsb_16_lp: ldmia r1!, {r3 - r6}
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
-
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
-
- strb r5, [r0]
- mov r5, r5, lsr #8
- strb r5, [r0]
- mov r5, r5, lsr #8
- strb r5, [r0]
- mov r5, r5, lsr #8
- strb r5, [r0]
-
- strb r6, [r0]
- mov r6, r6, lsr #8
- strb r6, [r0]
- mov r6, r6, lsr #8
- strb r6, [r0]
- mov r6, r6, lsr #8
- strb r6, [r0]
- subs r2, r2, #16
- bpl .outsb_16_lp
-
- tst r2, #15
- LOADREGS(eqfd, sp!, {r4 - r6, pc})
-
-.outsb_no_16: tst r2, #8
- beq .outsb_no_8
-
- ldmia r1, {r3, r4}
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
-
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
- mov r4, r4, lsr #8
- strb r4, [r0]
-
-.outsb_no_8: tst r2, #4
- bne .outsb_no_4
-
- ldr r3, [r1], #4
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
- mov r3, r3, lsr #8
- strb r3, [r0]
-
-.outsb_no_4: ands r2, r2, #3
- LOADREGS(eqfd, sp!, {r4 - r6, pc})
- cmp r2, #2
- ldrb r3, [r1], #1
- strb r3, [r0]
- ldrgeb r3, [r1], #1
- strgeb r3, [r0]
- ldrgtb r3, [r1]
- strgtb r3, [r0]
- LOADREGS(fd, sp!, {r4 - r6, pc})
-
-
-
+ b __arch_writesb
@ Purpose: write a memc register
@ Proto : void memc_write(int register, int value);
@@ -488,146 +102,5 @@ ENTRY(memc_write)
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})
-
-
-#if 0
- mov r2, r2, lsl#1
- 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
- LOADREGS(leea, 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})
-
-
-ENTRY(outsw)
- mov r2, r2, lsl#1
- 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})
-
#endif
diff --git a/arch/arm/lib/io-ebsa110.S b/arch/arm/lib/io-ebsa110.S
deleted file mode 100644
index b1c507886..000000000
--- a/arch/arm/lib/io-ebsa110.S
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * linux/arch/arm/lib/io-ebsa.S
- *
- * Copyright (C) 1995, 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
- .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
-
-/*
- * These make no sense on these machines.
- * Print a warning message.
- */
-ENTRY(insl)
-ENTRY(outsl)
-ENTRY(insb)
-ENTRY(outsb)
- adr r0, io_long_warning
- mov r1, lr
- b SYMBOL_NAME(printk)
-
-io_long_warning:
- .ascii "<4>ins?/outs? not implemented on this architecture\0"
- .align
-
-@ 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 --git a/arch/arm/lib/io-footbridge.S b/arch/arm/lib/io-footbridge.S
deleted file mode 100644
index 98f751258..000000000
--- a/arch/arm/lib/io-footbridge.S
+++ /dev/null
@@ -1,202 +0,0 @@
-#include <linux/linkage.h>
-#include <asm/hardware.h>
-
- .equ pcio_high, PCIO_BASE & 0xff000000
- .equ pcio_low, PCIO_BASE & 0x00ffffff
-
- .macro ioaddr, rd,rn
- add \rd, \rn, #pcio_high
- .if pcio_low
- add \rd, \rd, #pcio_low
- .endif
- .endm
-
-ENTRY(insl)
- ioaddr r0, r0
- ands ip, r1, #3
- bne 2f
-
-1: ldr r3, [r0]
- str r3, [r1], #4
- subs r2, r2, #1
- bne 1b
- mov pc, lr
-
-2: cmp ip, #2
- ldr ip, [r0]
- blt 4f
- bgt 6f
-
- strh ip, [r1], #2
- mov ip, ip, lsr #16
-3: subs r2, r2, #1
- ldrne r3, [r0]
- orrne ip, ip, r3, lsl #16
- strne ip, [r1], #4
- movne ip, r3, lsr #16
- bne 3b
- strh ip, [r1], #2
- mov pc, lr
-
-4: strb ip, [r1], #1
- mov ip, ip, lsr #8
- strh ip, [r1], #2
- mov ip, ip, lsr #16
-5: subs r2, r2, #1
- ldrne r3, [r0]
- orrne ip, ip, r3, lsl #8
- strne ip, [r1], #4
- movne ip, r3, lsr #24
- bne 5b
- strb ip, [r1], #1
- mov pc, lr
-
-6: strb ip, [r1], #1
- mov ip, ip, lsr #8
-7: subs r2, r2, #1
- ldrne r3, [r0]
- orrne ip, ip, r3, lsl #24
- strne ip, [r1], #4
- movne ip, r3, lsr #8
- bne 7b
- strb ip, [r1], #1
- mov ip, ip, lsr #8
- strh ip, [r1], #2
- mov pc, lr
-
-ENTRY(outsl)
- ioaddr r0, r0
- ands ip, r1, #3
- bne 2f
-
-1: ldr r3, [r1], #4
- str r3, [r0]
- subs r2, r2, #1
- bne 1b
- mov pc, lr
-
-2: bic r1, r1, #3
- cmp ip, #2
- ldr ip, [r1], #4
- mov ip, ip, lsr #16
- blt 4f
- bgt 5f
-
-3: ldr r3, [r1], #4
- orr ip, ip, r3, lsl #16
- str ip, [r0]
- mov ip, r3, lsr #16
- subs r2, r2, #1
- bne 3b
- mov pc, lr
-
-4: ldr r3, [r1], #4
- orr ip, ip, r3, lsl #8
- str ip, [r0]
- mov ip, r3, lsr #24
- subs r2, r2, #1
- bne 4b
- mov pc, lr
-
-5: ldr r3, [r1], #4
- orr ip, ip, r3, lsl #24
- str ip, [r0]
- mov ip, r3, lsr #8
- subs r2, r2, #1
- bne 5b
- mov pc, lr
-
- /* Nobody could say these are optimal, but not to worry. */
-
-ENTRY(outswb)
- mov r2, r2, lsr #1
-ENTRY(outsw)
- ioaddr r0, r0
-1: subs r2, r2, #1
- ldrgeh r3, [r1], #2
- strgeh r3, [r0]
- bgt 1b
- mov pc, lr
-
-ENTRY(inswb)
- mov r2, r2, lsr #1
-ENTRY(insw)
- stmfd sp!, {r4, r5, lr}
- ioaddr r0, r0
- @ + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17
- subs ip, r2, #8
- blo too_little
- @ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
- ands lr, r1, #3 @ check alignment
- beq 1f
-
- ldrh r3, [r0]
- strh r3, [r1], #2
- sub ip, ip, #1
- cmn ip, #8
- blo too_little
-
-1: ldrh r2, [r0]
- ldrh r3, [r0]
- orr r2, r2, r3, lsl #16
- ldrh r3, [r0]
- ldrh r4, [r0]
- orr r3, r3, r4, lsl #16
- ldrh r4, [r0]
- ldrh r5, [r0]
- orr r4, r4, r5, lsl #16
- ldrh r5, [r0]
- ldrh lr, [r0]
- orr r5, r5, lr, lsl #16
- stmia r1!, {r2, r3, r4, r5}
- subs ip, ip, #8
- @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 + 0 + 1
- bhs 1b
- @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 8 - 7
- cmn ip, #4
- ldrhsh r2, [r0] @ ... ... ... ... - 4 - 3 - 2 - 1 ... ...
- ldrhsh r3, [r0]
- orrhs r2, r2, r3, lsl #16
- ldrhsh r3, [r0]
- ldrhsh r4, [r0]
- orrhs r3, r3, r4, lsl #16
- stmhsia r1!, {r2, r3}
-
- tst ip, #2
- ldrneh r2, [r0] @ ... ... - 6 - 5 ... ... - 2 - 1 ... ...
- ldrneh r3, [r0]
- orrne r2, r2, r3, lsl #16
- strne r2, [r1], #4
-
- tst ip, #1
- ldrneh r2, [r0]
- strneh r2, [r1], #2
-
- ldmfd sp!, {r4, r5, pc}
-
-too_little: subs r2, r2, #1
- ldrgeh r3, [r0]
- strgeh r3, [r1], #2
- bgt too_little
-
- ldmfd sp!, {r4, r5, pc}
-
-
-ENTRY(insb)
- ioaddr r0, r0
-1: teq r2, #0
- ldrneb r3, [r0]
- strneb r3, [r1], #1
- subne r2, r2, #1
- bne 1b
- mov pc, lr
-
-
-ENTRY(outsb)
- ioaddr r0, r0
-1: teq r2, #0
- ldrneb r3, [r1], #1
- strneb r3, [r0]
- subne r2, r2, #1
- bne 1b
- mov pc, lr
diff --git a/arch/arm/lib/io-pcio.S b/arch/arm/lib/io-pcio.S
new file mode 100644
index 000000000..f57abfc10
--- /dev/null
+++ b/arch/arm/lib/io-pcio.S
@@ -0,0 +1,38 @@
+#include <linux/linkage.h>
+#include <asm/hardware.h>
+
+ .equ pcio_high, PCIO_BASE & 0xff000000
+ .equ pcio_low, PCIO_BASE & 0x00ffffff
+
+ .macro ioaddr, rd,rn
+ add \rd, \rn, #pcio_high
+ .if pcio_low
+ add \rd, \rd, #pcio_low
+ .endif
+ .endm
+
+ENTRY(insl)
+ ioaddr r0, r0
+ b __arch_readsl
+
+ENTRY(outsl)
+ ioaddr r0, r0
+ b __arch_writesl
+
+ /* Nobody could say these are optimal, but not to worry. */
+
+ENTRY(outsw)
+ ioaddr r0, r0
+ b __arch_writesw
+
+ENTRY(insw)
+ ioaddr r0, r0
+ b __arch_readsw
+
+ENTRY(insb)
+ ioaddr r0, r0
+ b __arch_readsb
+
+ENTRY(outsb)
+ ioaddr r0, r0
+ b __arch_writesb
diff --git a/arch/arm/lib/io-readsb.S b/arch/arm/lib/io-readsb.S
new file mode 100644
index 000000000..23cca8929
--- /dev/null
+++ b/arch/arm/lib/io-readsb.S
@@ -0,0 +1,111 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.insb_align: rsb ip, ip, #4
+ cmp ip, r2
+ movgt ip, r2
+ cmp ip, #2
+ ldrb r3, [r0]
+ strb r3, [r1], #1
+ ldrgeb r3, [r0]
+ strgeb r3, [r1], #1
+ ldrgtb r3, [r0]
+ strgtb r3, [r1], #1
+ subs r2, r2, ip
+ bne .insb_aligned
+
+ENTRY(__arch_readsb)
+ ands ip, r1, #3
+ bne .insb_align
+
+.insb_aligned: stmfd sp!, {r4 - r6, lr}
+
+ subs r2, r2, #16
+ bmi .insb_no_16
+
+.insb_16_lp: ldrb r3, [r0]
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #8
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #16
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #24
+ ldrb r4, [r0]
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #8
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #16
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #24
+ ldrb r5, [r0]
+ ldrb r6, [r0]
+ orr r5, r5, r6, lsl #8
+ ldrb r6, [r0]
+ orr r5, r5, r6, lsl #16
+ ldrb r6, [r0]
+ orr r5, r5, r6, lsl #24
+ ldrb r6, [r0]
+ ldrb ip, [r0]
+ orr r6, r6, ip, lsl #8
+ ldrb ip, [r0]
+ orr r6, r6, ip, lsl #16
+ ldrb ip, [r0]
+ orr r6, r6, ip, lsl #24
+ stmia r1!, {r3 - r6}
+ subs r2, r2, #16
+ bpl .insb_16_lp
+
+ tst r2, #15
+ LOADREGS(eqfd, sp!, {r4 - r6, pc})
+
+.insb_no_16: tst r2, #8
+ beq .insb_no_8
+
+ ldrb r3, [r0]
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #8
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #16
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #24
+ ldrb r4, [r0]
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #8
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #16
+ ldrb r5, [r0]
+ orr r4, r4, r5, lsl #24
+ stmia r1!, {r3, r4}
+
+.insb_no_8: tst r2, #4
+ bne .insb_no_4
+
+ ldrb r3, [r0]
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #8
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #16
+ ldrb r4, [r0]
+ orr r3, r3, r4, lsl #24
+ str r3, [r1], #4
+
+.insb_no_4: ands r2, r2, #3
+ LOADREGS(eqfd, sp!, {r4 - r6, pc})
+ cmp r2, #2
+ ldrb r3, [r0]
+ strb r3, [r1], #1
+ ldrgeb r3, [r0]
+ strgeb r3, [r1], #1
+ ldrgtb r3, [r0]
+ strgtb r3, [r1]
+ LOADREGS(fd, sp!, {r4 - r6, pc})
diff --git a/arch/arm/lib/io-readsl.S b/arch/arm/lib/io-readsl.S
new file mode 100644
index 000000000..530175485
--- /dev/null
+++ b/arch/arm/lib/io-readsl.S
@@ -0,0 +1,65 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+ENTRY(__arch_readsl)
+ ands ip, r1, #3
+ bne 2f
+
+1: ldr r3, [r0]
+ str r3, [r1], #4
+ subs r2, r2, #1
+ bne 1b
+ mov pc, lr
+
+2: cmp ip, #2
+ ldr ip, [r0]
+ blt 4f
+ bgt 6f
+
+ strh ip, [r1], #2
+ mov ip, ip, lsr #16
+3: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #16
+ strne ip, [r1], #4
+ movne ip, r3, lsr #16
+ bne 3b
+ strh ip, [r1], #2
+ mov pc, lr
+
+4: strb ip, [r1], #1
+ mov ip, ip, lsr #8
+ strh ip, [r1], #2
+ mov ip, ip, lsr #16
+5: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #8
+ strne ip, [r1], #4
+ movne ip, r3, lsr #24
+ bne 5b
+ strb ip, [r1], #1
+ mov pc, lr
+
+6: strb ip, [r1], #1
+ mov ip, ip, lsr #8
+7: subs r2, r2, #1
+ ldrne r3, [r0]
+ orrne ip, ip, r3, lsl #24
+ strne ip, [r1], #4
+ movne ip, r3, lsr #8
+ bne 7b
+ strb ip, [r1], #1
+ mov ip, ip, lsr #8
+ strh ip, [r1], #2
+ mov pc, lr
+
diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S
new file mode 100644
index 000000000..65fb94e2f
--- /dev/null
+++ b/arch/arm/lib/io-readsw-armv3.S
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.insw_bad_alignment:
+ adr r0, .insw_bad_align_msg
+ mov r2, lr
+ b SYMBOL_NAME(panic)
+.insw_bad_align_msg:
+ .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
+ .align
+
+.insw_align: tst r1, #1
+ bne .insw_bad_alignment
+
+ ldr r3, [r0]
+ strb r3, [r1], #1
+ mov r3, r3, lsr #8
+ strb r3, [r1], #1
+
+ subs r2, r2, #1
+ RETINSTR(moveq, pc, lr)
+
+ENTRY(__arch_readsw)
+ tst r1, #3
+ bne .insw_align
+
+.insw_aligned: mov ip, #0xff
+ orr ip, ip, ip, lsl #8
+ stmfd sp!, {r4, r5, r6, lr}
+
+ subs r2, r2, #8
+ bmi .no_insw_8
+
+.insw_8_lp: ldr r3, [r0]
+ and r3, r3, ip
+ ldr r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ ldr r4, [r0]
+ and r4, r4, ip
+ ldr r5, [r0]
+ orr r4, r4, r5, lsl #16
+
+ ldr r5, [r0]
+ and r5, r5, ip
+ ldr r6, [r0]
+ orr r5, r5, r6, lsl #16
+
+ ldr r6, [r0]
+ and r6, r6, ip
+ ldr lr, [r0]
+ orr r6, r6, lr, lsl #16
+
+ stmia r1!, {r3 - r6}
+ subs r2, r2, #8
+ bpl .insw_8_lp
+ tst r2, #7
+ LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
+
+.no_insw_8: tst r2, #4
+ beq .no_insw_4
+
+ ldr r3, [r0]
+ and r3, r3, ip
+ ldr r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ ldr r4, [r0]
+ and r4, r4, ip
+ ldr r5, [r0]
+ orr r4, r4, r5, lsl #16
+
+ stmia r1!, {r3, r4}
+
+.no_insw_4: tst r2, #2
+ beq .no_insw_2
+
+ ldr r3, [r0]
+ and r3, r3, ip
+ ldr r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ str r3, [r1], #4
+
+.no_insw_2: tst r2, #1
+ ldrne r3, [r0]
+ strneb r3, [r1], #1
+ movne r3, r3, lsr #8
+ strneb r3, [r1]
+ LOADREGS(fd, sp!, {r4, r5, r6, pc})
+
+
diff --git a/arch/arm/lib/io-readsw-armv4.S b/arch/arm/lib/io-readsw-armv4.S
new file mode 100644
index 000000000..6f1750a49
--- /dev/null
+++ b/arch/arm/lib/io-readsw-armv4.S
@@ -0,0 +1,87 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.insw_bad_alignment:
+ adr r0, .insw_bad_align_msg
+ mov r2, lr
+ b SYMBOL_NAME(panic)
+.insw_bad_align_msg:
+ .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
+ .align
+
+.insw_align: tst r1, #1
+ bne .insw_bad_alignment
+
+ ldrh r3, [r0]
+ strh r3, [r1], #2
+
+ subs r2, r2, #1
+ RETINSTR(moveq, pc, lr)
+
+ENTRY(__arch_readsw)
+ tst r1, #3
+ bne .insw_align
+
+ stmfd sp!, {r4, r5, lr}
+
+ subs r2, r2, #8
+ bmi .no_insw_8
+
+.insw_8_lp: ldrh r3, [r0]
+ ldrh r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ ldrh r4, [r0]
+ ldrh r5, [r0]
+ orr r4, r4, r5, lsl #16
+
+ ldrh r5, [r0]
+ ldrh r6, [r0]
+ orr r5, r5, r6, lsl #16
+
+ ldrh ip, [r0]
+ ldrh lr, [r0]
+ orr ip, ip, lr, lsl #16
+
+ stmia r1!, {r3 - r5, ip}
+ subs r2, r2, #8
+ bpl .insw_8_lp
+ tst r2, #7
+ LOADREGS(eqfd, sp!, {r4, r5, pc})
+
+.no_insw_8: tst r2, #4
+ beq .no_insw_4
+
+ ldrh r3, [r0]
+ ldrh r4, [r0]
+ orr r3, r3, r4, lsl #16
+
+ ldrh r4, [r0]
+ ldrh ip, [r0]
+ orr r4, r4, ip, lsl #16
+
+ stmia r1!, {r3, r4}
+
+.no_insw_4: tst r2, #2
+ beq .no_insw_2
+
+ ldrh r3, [r0]
+ ldrh ip, [r0]
+ orr r3, r3, ip, lsl #16
+
+ str r3, [r1], #4
+
+.no_insw_2: tst r2, #1
+ ldrneh r3, [r0]
+ strneh r3, [r1]
+ LOADREGS(fd, sp!, {r4, r5, pc})
diff --git a/arch/arm/lib/io-writesb.S b/arch/arm/lib/io-writesb.S
new file mode 100644
index 000000000..b919fdaad
--- /dev/null
+++ b/arch/arm/lib/io-writesb.S
@@ -0,0 +1,115 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.outsb_align: rsb ip, ip, #4
+ cmp ip, r2
+ mov ip, r2
+ cmp ip, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0]
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0]
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0]
+ subs r2, r2, ip
+ bne .outsb_aligned
+
+ENTRY(__arch_writesb)
+ ands ip, r1, #3
+ bne .outsb_align
+
+.outsb_aligned: stmfd sp!, {r4 - r6, lr}
+
+ subs r2, r2, #16
+ bmi .outsb_no_16
+
+.outsb_16_lp: ldmia r1!, {r3 - r6}
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+
+ strb r5, [r0]
+ mov r5, r5, lsr #8
+ strb r5, [r0]
+ mov r5, r5, lsr #8
+ strb r5, [r0]
+ mov r5, r5, lsr #8
+ strb r5, [r0]
+
+ strb r6, [r0]
+ mov r6, r6, lsr #8
+ strb r6, [r0]
+ mov r6, r6, lsr #8
+ strb r6, [r0]
+ mov r6, r6, lsr #8
+ strb r6, [r0]
+ subs r2, r2, #16
+ bpl .outsb_16_lp
+
+ tst r2, #15
+ LOADREGS(eqfd, sp!, {r4 - r6, pc})
+
+.outsb_no_16: tst r2, #8
+ beq .outsb_no_8
+
+ ldmia r1, {r3, r4}
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+ mov r4, r4, lsr #8
+ strb r4, [r0]
+
+.outsb_no_8: tst r2, #4
+ bne .outsb_no_4
+
+ ldr r3, [r1], #4
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+ mov r3, r3, lsr #8
+ strb r3, [r0]
+
+.outsb_no_4: ands r2, r2, #3
+ LOADREGS(eqfd, sp!, {r4 - r6, pc})
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0]
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0]
+ ldrgtb r3, [r1]
+ strgtb r3, [r0]
+ LOADREGS(fd, sp!, {r4 - r6, pc})
diff --git a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S
new file mode 100644
index 000000000..ccda08c39
--- /dev/null
+++ b/arch/arm/lib/io-writesl.S
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+ENTRY(__arch_writesl)
+ ands ip, r1, #3
+ bne 2f
+
+1: ldr r3, [r1], #4
+ str r3, [r0]
+ subs r2, r2, #1
+ bne 1b
+ mov pc, lr
+
+2: bic r1, r1, #3
+ cmp ip, #2
+ ldr ip, [r1], #4
+ mov ip, ip, lsr #16
+ blt 4f
+ bgt 5f
+
+3: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #16
+ str ip, [r0]
+ mov ip, r3, lsr #16
+ subs r2, r2, #1
+ bne 3b
+ mov pc, lr
+
+4: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #8
+ str ip, [r0]
+ mov ip, r3, lsr #24
+ subs r2, r2, #1
+ bne 4b
+ mov pc, lr
+
+5: ldr r3, [r1], #4
+ orr ip, ip, r3, lsl #24
+ str ip, [r0]
+ mov ip, r3, lsr #8
+ subs r2, r2, #1
+ bne 5b
+ mov pc, lr
+
+
diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S
new file mode 100644
index 000000000..29c94cc3d
--- /dev/null
+++ b/arch/arm/lib/io-writesw-armv3.S
@@ -0,0 +1,125 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.outsw_bad_alignment:
+ adr r0, .outsw_bad_align_msg
+ mov r2, lr
+ b SYMBOL_NAME(panic)
+.outsw_bad_align_msg:
+ .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
+ .align
+
+.outsw_align: tst r1, #1
+ bne .outsw_bad_alignment
+
+ add r1, r1, #2
+
+ ldr r3, [r1, #-4]
+ mov r3, r3, lsr #16
+ orr r3, r3, r3, lsl #16
+ str r3, [r0]
+ subs r2, r2, #1
+ RETINSTR(moveq, pc, lr)
+
+ENTRY(__arch_writesw)
+ tst r1, #3
+ bne .outsw_align
+
+.outsw_aligned: stmfd sp!, {r4, r5, r6, lr}
+
+ subs r2, r2, #8
+ bmi .no_outsw_8
+.outsw_8_lp: ldmia r1!, {r3, r4, r5, r6}
+
+ mov ip, r3, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r3, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ mov ip, r4, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r4, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ mov ip, r5, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r5, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ mov ip, r6, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r6, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ subs r2, r2, #8
+ bpl .outsw_8_lp
+ tst r2, #7
+ LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
+
+.no_outsw_8: tst r2, #4
+ beq .no_outsw_4
+
+ ldmia r1!, {r3, r4}
+
+ mov ip, r3, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r3, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+ mov ip, r4, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r4, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+.no_outsw_4: tst r2, #2
+ beq .no_outsw_2
+
+ ldr r3, [r1], #4
+
+ mov ip, r3, lsl #16
+ orr ip, ip, ip, lsr #16
+ str ip, [r0]
+
+ mov ip, r3, lsr #16
+ orr ip, ip, ip, lsl #16
+ str ip, [r0]
+
+.no_outsw_2: tst r2, #1
+
+ ldrne r3, [r1]
+
+ movne ip, r3, lsl #16
+ orrne ip, ip, ip, lsr #16
+ strne ip, [r0]
+
+ LOADREGS(fd, sp!, {r4, r5, r6, pc})
+
+
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
new file mode 100644
index 000000000..0f96d1325
--- /dev/null
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -0,0 +1,79 @@
+/*
+ * linux/arch/arm/lib/io-readsb.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+.outsw_bad_alignment:
+ adr r0, .outsw_bad_align_msg
+ mov r2, lr
+ b SYMBOL_NAME(panic)
+.outsw_bad_align_msg:
+ .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
+ .align
+
+.outsw_align: tst r1, #1
+ bne .outsw_bad_alignment
+
+ ldrh r3, [r1], #2
+ strh r3, [r0]
+
+ subs r2, r2, #1
+ RETINSTR(moveq, pc, lr)
+
+ENTRY(__arch_writesw)
+ tst r1, #3
+ bne .outsw_align
+
+ subs r2, r2, #8
+ bmi .no_outsw_8
+
+ stmfd sp!, {r4, r5, lr}
+
+.outsw_8_lp: ldmia r1!, {r3, r4, r5, ip}
+
+ strh r3, [r0]
+ mov r3, r3, lsr #16
+ strh r3, [r0]
+ strh r4, [r0]
+ mov r4, r4, lsr #16
+ strh r4, [r0]
+ strh r5, [r0]
+ mov r5, r5, lsr #16
+ strh r5, [r0]
+ strh ip, [r0]
+ mov ip, ip, lsr #16
+ strh ip, [r0]
+
+ subs r2, r2, #8
+ bpl .outsw_8_lp
+ ldmfd sp!, {r4, r5, lr}
+ tst r2, #7
+ RETINSTR(moveq, pc, lr)
+
+.no_outsw_8: tst r2, #4
+ ldmneia r1!, {r3, ip}
+ strneh r3, [r0]
+ movne r3, r3, lsr #16
+ strneh r3, [r0]
+ strneh ip, [r0]
+ movne ip, ip, lsr #16
+ strneh ip, [r0]
+ tst r2, #2
+ ldrne r3, [r1], #4
+ strneh r3, [r0]
+ movne r3, r3, lsr #16
+ strneh r3, [r0]
+ tst r2, #1
+ ldrneh r3, [r1]
+ strneh r3, [r0]
+ RETINSTR(mov, pc, lr)
+
+
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index 4b47b6e47..1a7a790cc 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -65,9 +65,9 @@ static inline void wb977_ww(int reg, int val)
*/
spinlock_t gpio_lock = SPIN_LOCK_UNLOCKED;
-static unsigned int current_gpio_op = 0;
-static unsigned int current_gpio_io = 0;
-static unsigned int current_cpld = 0;
+static unsigned int current_gpio_op;
+static unsigned int current_gpio_io;
+static unsigned int current_cpld;
void gpio_modify_op(int mask, int set)
{
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index 0e198ab8a..1cbdd7790 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -126,6 +126,39 @@ out:
return fault;
}
+static int __do_vmalloc_fault(unsigned long addr, struct mm_struct *mm)
+{
+ /* Synchronise this task's top level page-table
+ * with the 'reference' page table.
+ */
+ int offset = __pgd_offset(addr);
+ pgd_t *pgd, *pgd_k;
+ pmd_t *pmd, *pmd_k;
+
+ pgd_k = init_mm.pgd + offset;
+ if (!pgd_present(*pgd_k))
+ goto bad_area;
+
+ pgd = mm->pgd + offset;
+#if 0 /* note that we are two-level */
+ if (!pgd_present(*pgd))
+ set_pgd(pgd, *pgd_k);
+#endif
+
+ pmd_k = pmd_offset(pgd_k, addr);
+ if (pmd_none(*pmd_k))
+ goto bad_area;
+
+ pmd = pmd_offset(pgd, addr);
+ if (!pmd_none(*pmd))
+ goto bad_area;
+ set_pmd(pmd, *pmd_k);
+ return 1;
+
+bad_area:
+ return -2;
+}
+
static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
{
struct task_struct *tsk;
@@ -137,6 +170,18 @@ static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
mm = tsk->mm;
/*
+ * We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ */
+ if (addr >= TASK_SIZE)
+ goto vmalloc_fault;
+
+ /*
* If we're in an interrupt or have no user
* context, we must not take the fault..
*/
@@ -147,6 +192,7 @@ static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
fault = __do_page_fault(mm, addr, mode, tsk);
up(&mm->mmap_sem);
+ret:
/*
* Handle the "normal" case first
*/
@@ -240,4 +286,8 @@ no_context:
do_exit(SIGKILL);
return 0;
+
+vmalloc_fault:
+ fault = __do_vmalloc_fault(addr, mm);
+ goto ret;
}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index ea833c58d..bfa085a52 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -377,34 +377,48 @@ static int __init check_initrd(struct meminfo *mi)
/*
* Reserve the various regions of node 0
*/
-static inline void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages)
+static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages)
{
+ pg_data_t *pgdat = NODE_DATA(0);
+
/*
* Register the kernel text and data with bootmem.
* Note that this can only be in node 0.
*/
- reserve_bootmem_node(NODE_DATA(0), __pa(&_stext), &_end - &_stext);
+ reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext);
#ifdef CONFIG_CPU_32
/*
* Reserve the page tables. These are already in use,
* and can only be in node 0.
*/
- reserve_bootmem_node(NODE_DATA(0), __pa(swapper_pg_dir),
+ reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
PTRS_PER_PGD * sizeof(void *));
-#else
- /*
- * Stop this memory from being grabbed - its special DMA
- * memory that is required for the screen.
- */
- reserve_bootmem_node(NODE_DATA(0), 0x02000000, 0x00080000);
#endif
/*
* And don't forget to reserve the allocator bitmap,
* which will be freed later.
*/
- reserve_bootmem_node(NODE_DATA(0), bootmap_pfn << PAGE_SHIFT,
+ reserve_bootmem_node(pgdat, bootmap_pfn << PAGE_SHIFT,
bootmap_pages << PAGE_SHIFT);
+
+ /*
+ * Hmm... This should go elsewhere, but we really really
+ * need to stop things allocating the low memory; we need
+ * a better implementation of GFP_DMA which does not assume
+ * that DMA-able memory starts at zero.
+ */
+ if (machine_is_integrator())
+ reserve_bootmem_node(pgdat, 0, __pa(swapper_pg_dir));
+ /*
+ * These should likewise go elsewhere. They pre-reserve
+ * the screen memory region at the start of main system
+ * memory.
+ */
+ if (machine_is_archimedes() || machine_is_a5k())
+ reserve_bootmem_node(pgdat, 0x02000000, 0x00080000);
+ if (machine_is_p720t())
+ reserve_bootmem_node(pgdat, 0xc0000000, 0x00014000);
}
/*
@@ -412,11 +426,12 @@ static inline void reserve_node_zero(unsigned int bootmap_pfn, unsigned int boot
*/
static inline void free_bootmem_node_bank(int node, struct meminfo *mi)
{
+ pg_data_t *pgdat = NODE_DATA(node);
int bank;
for (bank = 0; bank < mi->nr_banks; bank++)
if (mi->bank[bank].node == node)
- free_bootmem_node(NODE_DATA(node), mi->bank[bank].start,
+ free_bootmem_node(pgdat, mi->bank[bank].start,
mi->bank[bank].size);
}
@@ -632,9 +647,11 @@ static inline void free_area(unsigned long addr, unsigned long end, char *s)
void free_initmem(void)
{
- free_area((unsigned long)(&__init_begin),
- (unsigned long)(&__init_end),
- "init");
+ if (!machine_is_integrator()) {
+ free_area((unsigned long)(&__init_begin),
+ (unsigned long)(&__init_end),
+ "init");
+ }
}
#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 2ace55d47..d96fcbccb 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -361,6 +361,7 @@ void __init memtable_init(struct meminfo *mi)
p ++;
}
+#ifdef FLUSH_BASE
p->physical = FLUSH_BASE_PHYS;
p->virtual = FLUSH_BASE;
p->length = PGDIR_SIZE;
@@ -371,6 +372,7 @@ void __init memtable_init(struct meminfo *mi)
p->bufferable = 1;
p ++;
+#endif
#ifdef FLUSH_BASE_MINICACHE
p->physical = FLUSH_BASE_PHYS + PGDIR_SIZE;
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index 13620ad5f..e6fc86bd1 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -139,7 +139,7 @@ Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit
Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register
Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR
mrc p15, 0, r3, c5, c0, 0 @ get FSR
- and r3, r3, #15
+ and r3, r3, #255
mov pc, lr
ENTRY(cpu_arm720_data_abort)
@@ -155,7 +155,7 @@ ENTRY(cpu_arm720_data_abort)
b Ldata_unknown
b Ldata_unknown
b Ldata_lateldrpostconst @ ldr rd, [rn], #m
- b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal
+ b Ldata_lateldrpreconst @ ldr rd, [rn, #m]
b Ldata_lateldrpostreg @ ldr rd, [rn], rm
b Ldata_lateldrprereg @ ldr rd, [rn, rm]
b Ldata_ldmstm @ ldm*a rn, <rlist>
@@ -177,25 +177,14 @@ Ldata_lateldrhpre:
tst r4, #1 << 21 @ check writeback bit
beq Ldata_simple
Ldata_lateldrhpost:
- tst r4, #1 << 22 @ check if register or immediate offset
- beq Ldata_lateldrhpostreg
-Ldata_lateldrhpostconst:
- and r2, r4, #0xf @ load and clear low nibble of const offset
- and r5, r4, #0xf00 @ load and clear high nibble of const offset
- orrs r2, r2, r5, lsr #4 @ create offset
- beq Ldata_simple @ don't have to do anything if zero
- and r5, r4, #0xf << 16 @ get Rn
- ldr r0, [sp, r5, lsr #14]
+ and r5, r4, #0x00f @ get Rm / low nibble of immediate value
+ tst r4, #1 << 22 @ if (immediate offset)
+ andne r2, r4, #0xf00 @ { immediate high nibble
+ orrne r2, r5, r2, lsr #4 @ combine nibbles } else
+ ldreq r2, [sp, r5, lsl #2] @ { load Rm value }
+ and r5, r4, #15 << 16 @ get Rn
+ ldr r0, [sp, r5, lsr #14] @ load Rn value
tst r4, #1 << 23 @ U bit
- subne r7, r0, r2, lsr #20
- addeq r7, r0, r2, lsr #20
- b Ldata_saver7
-Ldata_lateldrhpostreg:
- and r5, r4, #0xf
- ldr r2, [sp, r5, lsl #2] @ get Rm
- and r5, r4, #0xf << 16
- ldr r0, [sp, r5, lsr #14] @ get Rn
- tst r4, #1 << 23
subne r7, r0, r2
addeq r7, r0, r2
b Ldata_saver7
@@ -385,7 +374,7 @@ ENTRY(cpu_arm720_reset)
cpu_armvlsi_name:
- .asciz "ARM/VLSI"
+ .asciz "ARM"
cpu_arm720_name:
.asciz "ARM720T"
.align
@@ -471,8 +460,8 @@ cpu_elf_name: .asciz "v4"
__arm720_proc_info:
.long 0x41807200 @ cpu_val
.long 0xffffff00 @ cpu_mask
- .long 0x00000c0e @ __cpu_mmu_flags
- b __arm720_setup @ --cpu_flush
+ .long 0x00000c1e @ section_mmu_flags
+ b __arm720_setup @ cpu_flush
.long cpu_arch_name @ arch_name
.long cpu_elf_name @ elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT @ elf_hwcap
diff --git a/arch/arm/nwfpe/double_cpdo.c b/arch/arm/nwfpe/double_cpdo.c
index 0415f31e0..5e5d4fdcf 100644
--- a/arch/arm/nwfpe/double_cpdo.c
+++ b/arch/arm/nwfpe/double_cpdo.c
@@ -44,7 +44,7 @@ unsigned int DoubleCPDO(const unsigned int opcode)
float64 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
- //fp_printk("DoubleCPDO(0x%08x)\n",opcode);
+ //printk("DoubleCPDO(0x%08x)\n",opcode);
Fm = getFm(opcode);
if (CONSTANT_FM(opcode))
@@ -65,7 +65,7 @@ unsigned int DoubleCPDO(const unsigned int opcode)
case typeExtended:
// !! patb
- //fp_printk("not implemented! why not?\n");
+ //printk("not implemented! why not?\n");
//!! ScottB
// should never get here, if extended involved
// then other operand should be promoted then
diff --git a/arch/arm/nwfpe/extended_cpdo.c b/arch/arm/nwfpe/extended_cpdo.c
index 810f57102..762b1a0ef 100644
--- a/arch/arm/nwfpe/extended_cpdo.c
+++ b/arch/arm/nwfpe/extended_cpdo.c
@@ -42,7 +42,7 @@ unsigned int ExtendedCPDO(const unsigned int opcode)
floatx80 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
- //fp_printk("ExtendedCPDO(0x%08x)\n",opcode);
+ //printk("ExtendedCPDO(0x%08x)\n",opcode);
Fm = getFm(opcode);
if (CONSTANT_FM(opcode))
diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c
index fd39a59f7..b2eaf1aad 100644
--- a/arch/arm/nwfpe/fpa11_cpdo.c
+++ b/arch/arm/nwfpe/fpa11_cpdo.c
@@ -30,7 +30,7 @@ unsigned int EmulateCPDO(const unsigned int opcode)
{
unsigned int Fd, nType, nDest, nRc = 1;
- //fp_printk("EmulateCPDO(0x%08x)\n",opcode);
+ //printk("EmulateCPDO(0x%08x)\n",opcode);
/* Get the destination size. If not valid let Linux perform
an invalid instruction trap. */
diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
index 0bad18769..d6a7bdc4a 100644
--- a/arch/arm/nwfpe/fpa11_cpdt.c
+++ b/arch/arm/nwfpe/fpa11_cpdt.c
@@ -189,7 +189,7 @@ unsigned int PerformLDF(const unsigned int opcode)
unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
write_back = WRITE_BACK(opcode);
- //fp_printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
+ //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
pBase = (unsigned int*)readRegister(getRn(opcode));
if (REG_PC == getRn(opcode))
@@ -223,7 +223,7 @@ unsigned int PerformSTF(const unsigned int opcode)
unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
write_back = WRITE_BACK(opcode);
- //fp_printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
+ //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
SetRoundingMode(ROUND_TO_NEAREST);
pBase = (unsigned int*)readRegister(getRn(opcode));
@@ -322,7 +322,7 @@ unsigned int EmulateCPDT(const unsigned int opcode)
{
unsigned int nRc = 0;
- //fp_printk("EmulateCPDT(0x%08x)\n",opcode);
+ //printk("EmulateCPDT(0x%08x)\n",opcode);
if (LDF_OP(opcode))
{
diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c
index d479ee932..c17c69465 100644
--- a/arch/arm/nwfpe/fpa11_cprt.c
+++ b/arch/arm/nwfpe/fpa11_cprt.c
@@ -44,7 +44,7 @@ unsigned int EmulateCPRT(const unsigned int opcode)
{
unsigned int nRc = 1;
- //fp_printk("EmulateCPRT(0x%08x)\n",opcode);
+ //printk("EmulateCPRT(0x%08x)\n",opcode);
if (opcode & 0x800000)
{
@@ -188,7 +188,7 @@ static unsigned int PerformComparison(const unsigned int opcode)
int n_flag = opcode & 0x200000; /* 1 if CNxx */
unsigned int flags = 0;
- //fp_printk("PerformComparison(0x%08x)\n",opcode);
+ //printk("PerformComparison(0x%08x)\n",opcode);
Fn = getFn(opcode);
Fm = getFm(opcode);
@@ -201,21 +201,21 @@ static unsigned int PerformComparison(const unsigned int opcode)
switch (fpa11->fType[Fn])
{
case typeSingle:
- //fp_printk("single.\n");
+ //printk("single.\n");
if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
goto unordered;
rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
break;
case typeDouble:
- //fp_printk("double.\n");
+ //printk("double.\n");
if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
goto unordered;
rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
break;
case typeExtended:
- //fp_printk("extended.\n");
+ //printk("extended.\n");
if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
goto unordered;
rFn = fpa11->fpreg[Fn].fExtended;
@@ -226,32 +226,32 @@ static unsigned int PerformComparison(const unsigned int opcode)
if (CONSTANT_FM(opcode))
{
- //fp_printk("Fm is a constant: #%d.\n",Fm);
+ //printk("Fm is a constant: #%d.\n",Fm);
rFm = getExtendedConstant(Fm);
if (floatx80_is_nan(rFm))
goto unordered;
}
else
{
- //fp_printk("Fm = r%d which contains a ",Fm);
+ //printk("Fm = r%d which contains a ",Fm);
switch (fpa11->fType[Fm])
{
case typeSingle:
- //fp_printk("single.\n");
+ //printk("single.\n");
if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
goto unordered;
rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
break;
case typeDouble:
- //fp_printk("double.\n");
+ //printk("double.\n");
if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
goto unordered;
rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
break;
case typeExtended:
- //fp_printk("extended.\n");
+ //printk("extended.\n");
if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
goto unordered;
rFm = fpa11->fpreg[Fm].fExtended;
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index 9d4f1570d..24fa2775f 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -46,7 +46,6 @@ extern FPA11 *fpa11;
typedef struct task_struct* PTASK;
#ifdef MODULE
-int fp_printk(const char *,...);
void fp_send_sig(unsigned long sig, PTASK p, int priv);
#if LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
@@ -54,7 +53,6 @@ MODULE_DESCRIPTION("NWFPE floating point emulator");
#endif
#else
-#define fp_printk printk
#define fp_send_sig send_sig
#define kern_fp_enter fp_enter
#endif
@@ -74,23 +72,14 @@ extern void nwfpe_enter(void);
/* Address of user registers on the kernel stack. */
unsigned int *userRegisters;
-void __init fpe_version(void)
-{
- static const char szTitle[] = "<4>NetWinder Floating Point Emulator ";
- static const char szVersion[] = "V0.95 ";
- static const char szCopyright[] = "(c) 1998-1999 Rebel.com\n";
- fp_printk(szTitle);
- fp_printk(szVersion);
- fp_printk(szCopyright);
-}
-
int __init fpe_init(void)
{
if (sizeof(FPA11) > sizeof(union fp_state))
printk(KERN_ERR "nwfpe: bad structure size\n");
else {
/* Display title, version and copyright information. */
- fpe_version();
+ printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 "
+ "(c) 1998-1999 Rebel.com\n");
/* Save pointer to the old FP handler and then patch ourselves in */
orig_fp_enter = kern_fp_enter;
diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c
index a7fc76cc8..a6e000011 100644
--- a/arch/arm/nwfpe/softfloat.c
+++ b/arch/arm/nwfpe/softfloat.c
@@ -39,7 +39,7 @@ and exception flags.
*/
int8 float_rounding_mode = float_round_nearest_even;
int8 floatx80_rounding_precision = 80;
-int8 float_exception_flags = 0;
+int8 float_exception_flags;
/*
-------------------------------------------------------------------------------
@@ -418,9 +418,8 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
|| ( ( zExp == 0x7FD )
&& ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
) {
- //register int lr;
- //__asm__("mov %0, lr" :: "g" (lr));
- //fp_printk("roundAndPackFloat64 called from 0x%08x\n",lr);
+ //register int lr = __builtin_return_address(0);
+ //printk("roundAndPackFloat64 called from 0x%08x\n",lr);
float_raise( float_flag_overflow | float_flag_inexact );
return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
}
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index f3d1fb0b1..ff7ccec77 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1,7 +1,10 @@
# Database of machine macros and numbers
#
-# To add an entry into this database, please see
-# Documentation/arm/README
+# Please do not send patches to this file; it is automatically generated!
+# To add an entry into this database, please see Documentation/arm/README,
+# or contact rmk@arm.linux.org.uk
+#
+# Last update: Mon Nov 20 22:59:11 2000
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -14,7 +17,7 @@ cats ARCH_CATS CATS 6
tbox ARCH_TBOX TBOX 7
co285 ARCH_CO285 CO285 8
clps7110 ARCH_CLPS7110 CLPS7110 9
-arc ARCH_ARC ARCHIMEDES 10
+archimedes ARCH_ARC ARCHIMEDES 10
a5k ARCH_A5K A5K 11
etoile ARCH_ETOILE ETOILE 12
lacie_nas ARCH_LACIE_NAS LACIE_NAS 13
@@ -28,7 +31,7 @@ pleb SA1100_PLEB PLEB 20
integrator ARCH_INTEGRATOR INTEGRATOR 21
bitsy SA1100_BITSY BITSY 22
ixp1200 ARCH_IXP1200 IXP1200 23
-thinclient SA1100_THINCLIENT THINCLIENT 24
+p720t ARCH_P720T P720T 24
assabet SA1100_ASSABET ASSABET 25
victor SA1100_VICTOR VICTOR 26
lart SA1100_LART LART 27
@@ -42,8 +45,16 @@ extenex1 SA1100_EXTENEX1 EXTENEX1 34
sherman SA1100_SHERMAN SHERMAN 35
accelent_sa SA1100_ACCELENT ACCELENT_SA 36
accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37
+netport SA1100_NETPORT NETPORT 38
+pangolin SA1100_PANGOLIN PANGOLIN 39
+yopy SA1100_YOPY YOPY 40
+sa1100 SA1100_SA1100 SA1100 41
+huw_webpanel ARCH_HUW_WEBPANEL HUW_WEBPANEL 42
+spotme ARCH_SPOTME SPOTME 43
+freebird ARCH_FREEBIRD FREEBIRD 44
+ti925 ARCH_TI925 TI925 45
+riscstation ARCH_RISCSTATION RISCSTATION 46
+cavy SA1100_CAVY CAVY 47
# The following are unallocated
empeg SA1100_EMPEG EMPEG
-tifon SA1100_TIFON TIFON
-penny SA1100_PENNY PENNY
diff --git a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
index 5353e7f8f..0c0e720aa 100644
--- a/arch/arm/vmlinux-armo.lds.in
+++ b/arch/arm/vmlinux-armo.lds.in
@@ -9,6 +9,7 @@ SECTIONS
. = TEXTADDR;
.init : {
+ _stext = .;
__init_begin = .; /* Init code and data */
*(.text.init)
__proc_info_begin = .;
diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
index b54f2bd92..b0398852d 100644
--- a/arch/arm/vmlinux-armv.lds.in
+++ b/arch/arm/vmlinux-armv.lds.in
@@ -8,6 +8,7 @@ SECTIONS
{
. = TEXTADDR;
.init : { /* Init code and data */
+ _stext = .;
__init_begin = .;
*(.text.init)
__proc_info_begin = .;
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 0da4e866e..c52b170ec 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -825,10 +825,18 @@ bootsect_panic_mess:
#
# Some machines have delusions that the keyboard buffer is always full
# with no keyboard attached...
+#
+# If there is no keyboard controller, we will usually get 0xff
+# to all the reads. With each IO taking a microsecond and
+# a timeout of 100,000 iterations, this can take about half a
+# second ("delay" == outb to port 0x80). That should be ok,
+# and should also be plenty of time for a real keyboard controller
+# to empty.
+#
empty_8042:
pushl %ecx
- movl $0x00FFFFFF, %ecx
+ movl $100000, %ecx
empty_8042_loop:
decl %ecx
@@ -867,7 +875,7 @@ gettime:
# Delay is needed after doing I/O
delay:
- jmp .+2 # jmp $+2
+ outb %al,$0x80
ret
# Descriptor tables
diff --git a/arch/i386/config.in b/arch/i386/config.in
index d6c63a8b8..87fc106f8 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -140,7 +140,7 @@ if [ "$CONFIG_MWINCHIP3D" = "y" ]; then
fi
tristate 'Toshiba Laptop support' CONFIG_TOSHIBA
-tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
+tristate '/dev/cpu/microcode - Intel IA32 CPU microcode support' CONFIG_MICROCODE
tristate '/dev/cpu/*/msr - Model-specific register support' CONFIG_X86_MSR
tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 9f8625c6e..bdcf8cf6b 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -649,20 +649,15 @@ CONFIG_USB_UHCI_ALT=y
# CONFIG_USB_OHCI is not set
#
-# USB Devices
+# USB Device Class drivers
#
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SCANNER is not set
# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_BLUETOOTH is not set
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_USS720 is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
# USB Human Interface Devices (HID)
@@ -673,6 +668,44 @@ CONFIG_USB_STORAGE=y
#
#
+# USB Imaging devices
+#
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_PLUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_NET1080 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB misc drivers
+#
+# CONFIG_USB_RIO500 is not set
+
+#
# Kernel hacking
#
# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index fc54896f8..4179c8f13 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -220,66 +220,19 @@ void __init setup_local_APIC (void)
BUG();
/*
- * Set up LVT0, LVT1:
- *
- * set up through-local-APIC on the BP's LINT0. This is not
- * strictly necessery in pure symmetric-IO mode, but sometimes
- * we delegate interrupts to the 8259A.
- */
- /*
- * TODO: set up through-local-APIC from through-I/O-APIC? --macro
- */
- value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
- if (!smp_processor_id() && (pic_mode || !value)) {
- value = APIC_DM_EXTINT;
- printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
- } else {
- value = APIC_DM_EXTINT | APIC_LVT_MASKED;
- printk("masked ExtINT on CPU#%d\n", smp_processor_id());
- }
- apic_write_around(APIC_LVT0, value);
-
- /*
- * only the BP should see the LINT1 NMI signal, obviously.
+ * Intel recommends to set DFR, LDR and TPR before enabling
+ * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
+ * document number 292116). So here it goes...
*/
- if (!smp_processor_id())
- value = APIC_DM_NMI;
- else
- value = APIC_DM_NMI | APIC_LVT_MASKED;
- if (!APIC_INTEGRATED(ver)) /* 82489DX */
- value |= APIC_LVT_LEVEL_TRIGGER;
- apic_write_around(APIC_LVT1, value);
-
- if (APIC_INTEGRATED(ver)) { /* !82489DX */
- maxlvt = get_maxlvt();
- if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
- apic_write(APIC_ESR, 0);
- value = apic_read(APIC_ESR);
- printk("ESR value before enabling vector: %08lx\n", value);
-
- value = ERROR_APIC_VECTOR; // enables sending errors
- apic_write_around(APIC_LVTERR, value);
- /*
- * spec says clear errors after enabling vector.
- */
- if (maxlvt > 3)
- apic_write(APIC_ESR, 0);
- value = apic_read(APIC_ESR);
- printk("ESR value after enabling vector: %08lx\n", value);
- } else
- printk("No ESR for 82489DX.\n");
/*
- * Set Task Priority to 'accept all'. We never change this
- * later on.
+ * Put the APIC into flat delivery mode.
+ * Must be "all ones" explicitly for 82489DX.
*/
- value = apic_read(APIC_TASKPRI);
- value &= ~APIC_TPRI_MASK;
- apic_write_around(APIC_TASKPRI, value);
+ apic_write_around(APIC_DFR, 0xffffffff);
/*
- * Set up the logical destination ID and put the
- * APIC into flat delivery mode.
+ * Set up the logical destination ID.
*/
value = apic_read(APIC_LDR);
value &= ~APIC_LDR_MASK;
@@ -287,9 +240,12 @@ void __init setup_local_APIC (void)
apic_write_around(APIC_LDR, value);
/*
- * Must be "all ones" explicitly for 82489DX.
+ * Set Task Priority to 'accept all'. We never change this
+ * later on.
*/
- apic_write_around(APIC_DFR, 0xffffffff);
+ value = apic_read(APIC_TASKPRI);
+ value &= ~APIC_TPRI_MASK;
+ apic_write_around(APIC_TASKPRI, value);
/*
* Now that we are all set up, enable the APIC
@@ -326,6 +282,56 @@ void __init setup_local_APIC (void)
*/
value |= SPURIOUS_APIC_VECTOR;
apic_write_around(APIC_SPIV, value);
+
+ /*
+ * Set up LVT0, LVT1:
+ *
+ * set up through-local-APIC on the BP's LINT0. This is not
+ * strictly necessery in pure symmetric-IO mode, but sometimes
+ * we delegate interrupts to the 8259A.
+ */
+ /*
+ * TODO: set up through-local-APIC from through-I/O-APIC? --macro
+ */
+ value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
+ if (!smp_processor_id() && (pic_mode || !value)) {
+ value = APIC_DM_EXTINT;
+ printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
+ } else {
+ value = APIC_DM_EXTINT | APIC_LVT_MASKED;
+ printk("masked ExtINT on CPU#%d\n", smp_processor_id());
+ }
+ apic_write_around(APIC_LVT0, value);
+
+ /*
+ * only the BP should see the LINT1 NMI signal, obviously.
+ */
+ if (!smp_processor_id())
+ value = APIC_DM_NMI;
+ else
+ value = APIC_DM_NMI | APIC_LVT_MASKED;
+ if (!APIC_INTEGRATED(ver)) /* 82489DX */
+ value |= APIC_LVT_LEVEL_TRIGGER;
+ apic_write_around(APIC_LVT1, value);
+
+ if (APIC_INTEGRATED(ver)) { /* !82489DX */
+ maxlvt = get_maxlvt();
+ if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
+ apic_write(APIC_ESR, 0);
+ value = apic_read(APIC_ESR);
+ printk("ESR value before enabling vector: %08lx\n", value);
+
+ value = ERROR_APIC_VECTOR; // enables sending errors
+ apic_write_around(APIC_LVTERR, value);
+ /*
+ * spec says clear errors after enabling vector.
+ */
+ if (maxlvt > 3)
+ apic_write(APIC_ESR, 0);
+ value = apic_read(APIC_ESR);
+ printk("ESR value after enabling vector: %08lx\n", value);
+ } else
+ printk("No ESR for 82489DX.\n");
}
void __init init_apic_mappings(void)
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index dc47528cd..9703e3304 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -37,6 +37,7 @@
* Nov 1999, Version 1.11
* Jan 2000, Version 1.12
* Feb 2000, Version 1.13
+ * Nov 2000, Version 1.14
*
* History:
* 0.6b: first version in official kernel, Linux 1.3.46
@@ -144,6 +145,9 @@
* <tmh@magenta-logic.com> and <zlatko@iskon.hr>) modified by sfr.
* Remove CONFIG_APM_SUSPEND_BOUNCE. The bounce ignore
* interval is now configurable.
+ * 1.14: Make connection version persist across module unload/load.
+ * Enable and engage power management earlier.
+ * Disengage power management on module unload.
*
* APM 1.1 Reference:
*
@@ -344,9 +348,9 @@ static int kapmd_running;
static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
-static struct apm_user * user_list = NULL;
+static struct apm_user * user_list;
-static char driver_version[] = "1.13"; /* no spaces */
+static char driver_version[] = "1.14"; /* no spaces */
static char * apm_event_name[] = {
"system standby",
@@ -527,7 +531,7 @@ static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
&dummy, &dummy))
return (eax >> 8) & 0xff;
*event = ebx;
- if (apm_bios_info.version < 0x0102)
+ if (apm_info.connection_version < 0x0102)
*info = ~0; /* indicate info not valid */
else
*info = ecx;
@@ -559,7 +563,7 @@ static int apm_do_idle(void)
#ifdef ALWAYS_CALL_BUSY
clock_slowed = 1;
#else
- clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
+ clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0;
#endif
return 1;
}
@@ -670,15 +674,15 @@ static int apm_enable_power_management(int enable)
{
u32 eax;
- if ((enable == 0) && (apm_bios_info.flags & APM_BIOS_DISENGAGED))
+ if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED))
return APM_NOT_ENGAGED;
if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
enable, &eax))
return (eax >> 8) & 0xff;
if (enable)
- apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+ apm_info.bios.flags &= ~APM_BIOS_DISABLED;
else
- apm_bios_info.flags |= APM_BIOS_DISABLED;
+ apm_info.bios.flags |= APM_BIOS_DISABLED;
return APM_SUCCESS;
}
#endif
@@ -691,6 +695,8 @@ static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
u32 edx;
u32 dummy;
+ if (apm_info.get_power_status_broken)
+ return APM_32_UNSUPPORTED;
if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0,
&eax, &ebx, &ecx, &edx, &dummy))
return (eax >> 8) & 0xff;
@@ -710,7 +716,7 @@ static int apm_get_battery_status(u_short which, u_short *status,
u32 edx;
u32 esi;
- if (apm_bios_info.version < 0x0102) {
+ if (apm_info.connection_version < 0x0102) {
/* pretend we only have one battery. */
if (which != 1)
return APM_BAD_DEVICE;
@@ -734,15 +740,15 @@ static int apm_engage_power_management(u_short device, int enable)
u32 eax;
if ((enable == 0) && (device == APM_DEVICE_ALL)
- && (apm_bios_info.flags & APM_BIOS_DISABLED))
+ && (apm_info.bios.flags & APM_BIOS_DISABLED))
return APM_DISABLED;
if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
return (eax >> 8) & 0xff;
if (device == APM_DEVICE_ALL) {
if (enable)
- apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+ apm_info.bios.flags &= ~APM_BIOS_DISENGAGED;
else
- apm_bios_info.flags |= APM_BIOS_DISENGAGED;
+ apm_info.bios.flags |= APM_BIOS_DISENGAGED;
}
return APM_SUCCESS;
}
@@ -890,7 +896,7 @@ static int send_event(apm_event_t event)
printk(KERN_CRIT "apm: Critical suspend was vetoed, expect armageddon\n" );
return 0;
}
- if (apm_bios_info.version > 0x100)
+ if (apm_info.connection_version > 0x100)
apm_set_power_state(APM_STATE_REJECT);
return 0;
}
@@ -993,13 +999,13 @@ static void check_events(void)
case APM_USER_SUSPEND:
#ifdef CONFIG_APM_IGNORE_USER_SUSPEND
- if (apm_bios_info.version > 0x100)
+ if (apm_info.connection_version > 0x100)
apm_set_power_state(APM_STATE_REJECT);
break;
#endif
case APM_SYS_SUSPEND:
if (ignore_bounce) {
- if (apm_bios_info.version > 0x100)
+ if (apm_info.connection_version > 0x100)
apm_set_power_state(APM_STATE_REJECT);
break;
}
@@ -1064,7 +1070,7 @@ static void apm_event_handler(void)
int err;
if ((standbys_pending > 0) || (suspends_pending > 0)) {
- if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
+ if ((apm_info.connection_version > 0x100) && (pending_count-- <= 0)) {
pending_count = 4;
if (debug)
printk(KERN_DEBUG "apm: setting state busy\n");
@@ -1334,7 +1340,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
unsigned short bx;
unsigned short cx;
unsigned short dx;
- unsigned short error;
+ int error;
unsigned short ac_line_status = 0xff;
unsigned short battery_status = 0xff;
unsigned short battery_flag = 0xff;
@@ -1351,7 +1357,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
if ((cx & 0xff) != 0xff)
percentage = cx & 0xff;
- if (apm_bios_info.version > 0x100) {
+ if (apm_info.connection_version > 0x100) {
battery_flag = (cx >> 8) & 0xff;
if (dx != 0xffff) {
units = (dx & 0x8000) ? "min" : "sec";
@@ -1399,9 +1405,9 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
driver_version,
- (apm_bios_info.version >> 8) & 0xff,
- apm_bios_info.version & 0xff,
- apm_bios_info.flags,
+ (apm_info.bios.version >> 8) & 0xff,
+ apm_info.bios.version & 0xff,
+ apm_info.bios.flags,
ac_line_status,
battery_status,
battery_flag,
@@ -1417,7 +1423,7 @@ static int apm(void *unused)
unsigned short bx;
unsigned short cx;
unsigned short dx;
- unsigned short error;
+ int error;
char * power_stat;
char * bat_stat;
@@ -1429,22 +1435,53 @@ static int apm(void *unused)
sigfillset(&current->blocked);
current->tty = NULL; /* get rid of controlling tty */
- if (apm_bios_info.version > 0x100) {
+ if (apm_info.connection_version == 0) {
+ apm_info.connection_version = apm_info.bios.version;
+ if (apm_info.connection_version > 0x100) {
+ /*
+ * We only support BIOSs up to version 1.2
+ */
+ if (apm_info.connection_version > 0x0102)
+ apm_info.connection_version = 0x0102;
+ error = apm_driver_version(&apm_info.connection_version);
+ if (error != APM_SUCCESS) {
+ apm_error("driver version", error);
+ /* Fall back to an APM 1.0 connection. */
+ apm_info.connection_version = 0x100;
+ }
+ }
+ }
+
+ if (debug)
+ printk(KERN_INFO "apm: Connection version %d.%d\n",
+ (apm_info.connection_version >> 8) & 0xff,
+ apm_info.connection_version & 0xff);
+
+#ifdef CONFIG_APM_DO_ENABLE
+ if (apm_info.bios.flags & APM_BIOS_DISABLED) {
/*
- * We only support BIOSs up to version 1.2
+ * This call causes my NEC UltraLite Versa 33/C to hang if it
+ * is booted with PM disabled but not in the docking station.
+ * Unfortunate ...
*/
- if (apm_bios_info.version > 0x0102)
- apm_bios_info.version = 0x0102;
- if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
- /* Fall back to an APM 1.0 connection. */
- apm_bios_info.version = 0x100;
+ error = apm_enable_power_management(1);
+ if (error) {
+ apm_error("enable power management", error);
+ return -1;
+ }
+ }
+#endif
+
+ if ((apm_info.bios.flags & APM_BIOS_DISENGAGED)
+ && (apm_info.connection_version > 0x0100)) {
+ error = apm_engage_power_management(APM_DEVICE_ALL, 1);
+ if (error) {
+ apm_error("engage power management", error);
+ return -1;
}
}
- if (debug && (smp_num_cpus == 1)) {
- printk(KERN_INFO "apm: Connection version %d.%d\n",
- (apm_bios_info.version >> 8) & 0xff,
- apm_bios_info.version & 0xff);
+ if (debug && (smp_num_cpus == 1)) {
error = apm_get_power_status(&bx, &cx, &dx);
if (error)
printk(KERN_INFO "apm: power status not available\n");
@@ -1469,7 +1506,7 @@ static int apm(void *unused)
printk("unknown\n");
else
printk("%d%%\n", cx & 0xff);
- if (apm_bios_info.version > 0x100) {
+ if (apm_info.connection_version > 0x100) {
printk(KERN_INFO
"apm: battery flag 0x%02x, battery life ",
(cx >> 8) & 0xff);
@@ -1483,29 +1520,6 @@ static int apm(void *unused)
}
}
-#ifdef CONFIG_APM_DO_ENABLE
- if (apm_bios_info.flags & APM_BIOS_DISABLED) {
- /*
- * This call causes my NEC UltraLite Versa 33/C to hang if it
- * is booted with PM disabled but not in the docking station.
- * Unfortunate ...
- */
- error = apm_enable_power_management(1);
- if (error) {
- apm_error("enable power management", error);
- return -1;
- }
- }
-#endif
- if ((apm_bios_info.flags & APM_BIOS_DISENGAGED)
- && (apm_bios_info.version > 0x0100)) {
- error = apm_engage_power_management(APM_DEVICE_ALL, 1);
- if (error) {
- apm_error("engage power management", error);
- return -1;
- }
- }
-
/* Install our power off handler.. */
if (power_off)
pm_power_off = apm_power_off;
@@ -1584,17 +1598,19 @@ static struct miscdevice apm_device = {
*/
static int __init apm_init(void)
{
- if (apm_bios_info.version == 0) {
+ struct proc_dir_entry *apm_proc;
+
+ if (apm_info.bios.version == 0) {
printk(KERN_INFO "apm: BIOS not found.\n");
return -ENODEV;
}
printk(KERN_INFO
"apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
- ((apm_bios_info.version >> 8) & 0xff),
- (apm_bios_info.version & 0xff),
- apm_bios_info.flags,
+ ((apm_info.bios.version >> 8) & 0xff),
+ (apm_info.bios.version & 0xff),
+ apm_info.bios.flags,
driver_version);
- if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
+ if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) {
printk(KERN_INFO "apm: no 32 bit BIOS support\n");
return -ENODEV;
}
@@ -1603,23 +1619,23 @@ static int __init apm_init(void)
* Fix for the Compaq Contura 3/25c which reports BIOS version 0.1
* but is reportedly a 1.0 BIOS.
*/
- if (apm_bios_info.version == 0x001)
- apm_bios_info.version = 0x100;
+ if (apm_info.bios.version == 0x001)
+ apm_info.bios.version = 0x100;
/* BIOS < 1.2 doesn't set cseg_16_len */
- if (apm_bios_info.version < 0x102)
- apm_bios_info.cseg_16_len = 0; /* 64k */
+ if (apm_info.bios.version < 0x102)
+ apm_info.bios.cseg_16_len = 0; /* 64k */
if (debug) {
printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x",
- apm_bios_info.cseg, apm_bios_info.offset,
- apm_bios_info.cseg_16, apm_bios_info.dseg);
- if (apm_bios_info.version > 0x100)
+ apm_info.bios.cseg, apm_info.bios.offset,
+ apm_info.bios.cseg_16, apm_info.bios.dseg);
+ if (apm_info.bios.version > 0x100)
printk(" cseg len %x, dseg len %x",
- apm_bios_info.cseg_len,
- apm_bios_info.dseg_len);
- if (apm_bios_info.version > 0x101)
- printk(" cseg16 len %x", apm_bios_info.cseg_16_len);
+ apm_info.bios.cseg_len,
+ apm_info.bios.dseg_len);
+ if (apm_info.bios.version > 0x101)
+ printk(" cseg16 len %x", apm_info.bios.cseg_16_len);
printk("\n");
}
@@ -1647,16 +1663,16 @@ static int __init apm_init(void)
__va((unsigned long)0x40 << 4));
_set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4));
- apm_bios_entry.offset = apm_bios_info.offset;
+ apm_bios_entry.offset = apm_info.bios.offset;
apm_bios_entry.segment = APM_CS;
set_base(gdt[APM_CS >> 3],
- __va((unsigned long)apm_bios_info.cseg << 4));
+ __va((unsigned long)apm_info.bios.cseg << 4));
set_base(gdt[APM_CS_16 >> 3],
- __va((unsigned long)apm_bios_info.cseg_16 << 4));
+ __va((unsigned long)apm_info.bios.cseg_16 << 4));
set_base(gdt[APM_DS >> 3],
- __va((unsigned long)apm_bios_info.dseg << 4));
+ __va((unsigned long)apm_info.bios.dseg << 4));
#ifndef APM_RELAX_SEGMENTS
- if (apm_bios_info.version == 0x100) {
+ if (apm_info.bios.version == 0x100) {
#endif
/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
@@ -1667,15 +1683,17 @@ static int __init apm_init(void)
#ifndef APM_RELAX_SEGMENTS
} else {
_set_limit((char *)&gdt[APM_CS >> 3],
- (apm_bios_info.cseg_len - 1) & 0xffff);
+ (apm_info.bios.cseg_len - 1) & 0xffff);
_set_limit((char *)&gdt[APM_CS_16 >> 3],
- (apm_bios_info.cseg_16_len - 1) & 0xffff);
+ (apm_info.bios.cseg_16_len - 1) & 0xffff);
_set_limit((char *)&gdt[APM_DS >> 3],
- (apm_bios_info.dseg_len - 1) & 0xffff);
+ (apm_info.bios.dseg_len - 1) & 0xffff);
}
#endif
- create_proc_info_entry("apm", 0, NULL, apm_get_info);
+ apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
+ if (apm_proc)
+ SET_MODULE_OWNER(apm_proc);
kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
@@ -1692,6 +1710,14 @@ static int __init apm_init(void)
static void __exit apm_exit(void)
{
+ int error;
+
+ if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
+ && (apm_info.connection_version > 0x0100)) {
+ error = apm_engage_power_management(APM_DEVICE_ALL, 0);
+ if (error)
+ apm_error("disengage power management", error);
+ }
misc_deregister(&apm_device);
remove_proc_entry("apm", NULL);
#ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
new file mode 100644
index 000000000..b439568c1
--- /dev/null
+++ b/arch/i386/kernel/dmi_scan.c
@@ -0,0 +1,182 @@
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/apm_bios.h>
+#include <asm/io.h>
+
+struct dmi_header
+{
+ u8 type;
+ u8 length;
+ u16 handle;
+};
+
+static char * __init dmi_string(struct dmi_header *dm, u8 s)
+{
+ u8 *bp=(u8 *)dm;
+ bp+=dm->length;
+ s--;
+ while(s>0)
+ {
+ bp+=strlen(bp);
+ bp++;
+ s--;
+ }
+ return bp;
+}
+
+static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
+{
+ u8 *buf;
+ struct dmi_header *dm;
+ u8 *data;
+ int i=1;
+ int last = 0;
+
+ buf = ioremap(base, len);
+ if(buf==NULL)
+ return -1;
+
+ data = buf;
+ while(i<num && (data - buf) < len)
+ {
+ dm=(struct dmi_header *)data;
+ if(dm->type < last)
+ break;
+ last = dm->type;
+ decode(dm);
+ data+=dm->length;
+ while(*data || data[1])
+ data++;
+ data+=2;
+ i++;
+ }
+ iounmap(buf);
+ return 0;
+}
+
+
+int __init dmi_iterate(void (*decode)(struct dmi_header *))
+{
+ unsigned char buf[20];
+ long fp=0xE0000L;
+ fp -= 16;
+
+ while( fp < 0xFFFFF)
+ {
+ fp+=16;
+ isa_memcpy_fromio(buf, fp, 20);
+ if(memcmp(buf, "_DMI_", 5)==0)
+ {
+ u16 num=buf[13]<<8|buf[12];
+ u16 len=buf[7]<<8|buf[6];
+ u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+
+ printk(KERN_INFO "DMI %d.%d present.\n",
+ buf[14]>>4, buf[14]&0x0F);
+ printk(KERN_INFO "%d structures occupying %d bytes.\n",
+ buf[13]<<8|buf[12],
+ buf[7]<<8|buf[6]);
+ printk(KERN_INFO "DMI table at 0x%08X.\n",
+ buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]);
+ if(dmi_table(base,len, num, decode)==0)
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+/*
+ * Process a DMI table entry. Right now all we care about are the BIOS
+ * and machine entries. For 2.4 we should pull the smbus controller info
+ * out of here.
+ */
+
+static void __init dmi_decode(struct dmi_header *dm)
+{
+ u8 *data = (u8 *)dm;
+ char *p;
+
+ switch(dm->type)
+ {
+ case 0:
+ p=dmi_string(dm,data[4]);
+
+ if(*p && *p!=' ')
+ {
+ printk("BIOS Vendor: %s\n", p);
+ printk("BIOS Version: %s\n",
+ dmi_string(dm, data[5]));
+ printk("BIOS Release: %s\n",
+ dmi_string(dm, data[8]));
+ }
+
+ /*
+ * Check for clue free BIOS implementations who use
+ * the following QA technique
+ *
+ * [ Write BIOS Code ]<------
+ * | ^
+ * < Does it Compile >----N--
+ * |Y ^
+ * < Does it Boot Win98 >-N--
+ * |Y
+ * [Ship It]
+ *
+ * Phoenix A04 08/24/2000 is known bad (Dell Inspiron 5000e)
+ * Phoenix A07 09/29/2000 is known good (Dell Inspiron 5000)
+ */
+
+ if(strcmp(dmi_string(dm, data[4]), "Phoenix Technologies LTD")==0)
+ {
+ if(strcmp(dmi_string(dm, data[5]), "A04")==0
+ && strcmp(dmi_string(dm, data[8]), "08/24/2000")==0)
+ {
+ apm_info.get_power_status_broken = 1;
+ printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
+ }
+ }
+ break;
+ case 1:
+ p=dmi_string(dm,data[4]);
+
+ if(*p && *p!=' ')
+ {
+ printk("System Vendor: %s.\n",p);
+ printk("Product Name: %s.\n",
+ dmi_string(dm, data[5]));
+ printk("Version %s.\n",
+ dmi_string(dm, data[6]));
+ printk("Serial Number %s.\n",
+ dmi_string(dm, data[7]));
+ }
+ break;
+ case 2:
+ p=dmi_string(dm,data[4]);
+
+ if(*p && *p!=' ')
+ {
+ printk("Board Vendor: %s.\n",p);
+ printk("Board Name: %s.\n",
+ dmi_string(dm, data[5]));
+ printk("Board Version: %s.\n",
+ dmi_string(dm, data[6]));
+ }
+ break;
+ case 3:
+ p=dmi_string(dm,data[8]);
+ if(*p && *p!=' ')
+ printk("Asset Tag: %s.\n", p);
+ break;
+ }
+}
+
+static int __init dmi_scan_machine(void)
+{
+ return dmi_iterate(dmi_decode);
+}
+
+module_init(dmi_scan_machine);
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index fdb488a15..c74b80135 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -119,12 +119,12 @@ startup_32:
/*
* Clear BSS first so that there are no surprises...
+ * No need to cld as DF is already clear from cld above...
*/
xorl %eax,%eax
movl $ SYMBOL_NAME(__bss_start),%edi
movl $ SYMBOL_NAME(_end),%ecx
subl %edi,%ecx
- cld
rep
stosb
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 3de4a76d1..071b3991a 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(pm_idle);
EXPORT_SYMBOL(pm_power_off);
EXPORT_SYMBOL(get_cmos_time);
-EXPORT_SYMBOL(apm_bios_info);
+EXPORT_SYMBOL(apm_info);
EXPORT_SYMBOL(gdt);
EXPORT_SYMBOL_NOVERS(__down_failed);
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 92ddd01f5..cf6878787 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -179,7 +179,7 @@ int get_irq_list(char *buf)
#ifdef CONFIG_SMP
unsigned char global_irq_holder = NO_PROC_ID;
-unsigned volatile int global_irq_lock;
+unsigned volatile long global_irq_lock; /* pendantic: long for set_bit --RR */
extern void show_stack(unsigned long* esp);
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 5f9925495..f0a88c20e 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -4,13 +4,13 @@
* Copyright (C) 2000 Tigran Aivazian
*
* This driver allows to upgrade microcode on Intel processors
- * belonging to P6 family - PentiumPro, Pentium II,
- * Pentium III, Xeon etc.
+ * belonging to IA-32 family - PentiumPro, Pentium II,
+ * Pentium III, Xeon, Pentium 4, etc.
*
- * Reference: Section 8.10 of Volume III, Intel Pentium III Manual,
- * Order Number 243192 or free download from:
+ * Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual,
+ * Order Number 245472 or free download from:
*
- * http://developer.intel.com/design/pentiumii/manuals/243192.htm
+ * http://developer.intel.com/design/pentium4/manuals/245472.htm
*
* For more information, go to http://www.urbanmyth.org/microcode
*
@@ -44,6 +44,9 @@
* to be 0 on my machine which is why it worked even when I
* disabled update by the BIOS)
* Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
+ * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
+ * Tigran Aivazian <tigran@veritas.com>
+ * Intel Pentium 4 processor support and bugfixes.
*/
#include <linux/init.h>
@@ -58,12 +61,20 @@
#include <asm/uaccess.h>
#include <asm/processor.h>
-#define MICROCODE_VERSION "1.07"
+#define MICROCODE_VERSION "1.08"
-MODULE_DESCRIPTION("Intel CPU (P6) microcode update driver");
+MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver");
MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
EXPORT_NO_SYMBOLS;
+#define MICRO_DEBUG 0
+
+#if MICRO_DEBUG
+#define printf(x...) printk(##x)
+#else
+#define printf(x...)
+#endif
+
/* VFS interface */
static int microcode_open(struct inode *, struct file *);
static ssize_t microcode_read(struct file *, char *, size_t, loff_t *);
@@ -81,6 +92,7 @@ static unsigned int microcode_num; /* number of chunks in microcode */
static char *mc_applied; /* array of applied microcode blocks */
static unsigned int mc_fsize; /* file size of /dev/cpu/microcode */
+/* we share file_operations between misc and devfs mechanisms */
static struct file_operations microcode_fops = {
owner: THIS_MODULE,
read: microcode_read,
@@ -99,23 +111,27 @@ static devfs_handle_t devfs_handle;
static int __init microcode_init(void)
{
- int error = 0;
+ int error;
- if (misc_register(&microcode_dev) < 0) {
+ error = misc_register(&microcode_dev);
+ if (error)
printk(KERN_WARNING
"microcode: can't misc_register on minor=%d\n",
MICROCODE_MINOR);
- error = 1;
- }
+
devfs_handle = devfs_register(NULL, "cpu/microcode",
DEVFS_FL_DEFAULT, 0, 0, S_IFREG | S_IRUSR | S_IWUSR,
&microcode_fops, NULL);
if (devfs_handle == NULL && error) {
printk(KERN_ERR "microcode: failed to devfs_register()\n");
- return -EINVAL;
+ goto out;
}
- printk(KERN_INFO "P6 Microcode Update Driver v%s\n", MICROCODE_VERSION);
- return 0;
+ printk(KERN_INFO
+ "IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n",
+ MICROCODE_VERSION);
+
+out:
+ return error;
}
static void __exit microcode_exit(void)
@@ -124,12 +140,12 @@ static void __exit microcode_exit(void)
devfs_unregister(devfs_handle);
if (mc_applied)
kfree(mc_applied);
- printk(KERN_INFO "P6 Microcode Update Driver v%s unregistered\n",
+ printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n",
MICROCODE_VERSION);
}
-module_init(microcode_init);
-module_exit(microcode_exit);
+module_init(microcode_init)
+module_exit(microcode_exit)
static int microcode_open(struct inode *unused1, struct file *unused2)
{
@@ -175,18 +191,19 @@ static void do_update_one(void *unused)
unsigned int pf = 0, val[2], rev, sig;
int i,found=0;
- req->err = 1; /* assume the worst */
+ req->err = 1; /* assume update will fail on this cpu */
- if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 != 6){
- printk(KERN_ERR "microcode: CPU%d not an Intel P6\n", cpu_num);
+ if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
+ test_bit(X86_FEATURE_IA64, &c->x86_capability)){
+ printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num);
return;
}
sig = c->x86_mask + (c->x86_model<<4) + (c->x86<<8);
- if (c->x86_model >= 5) {
- /* get processor flags from BBL_CR_OVRD MSR (0x17) */
- rdmsr(0x17, val[0], val[1]);
+ if ((c->x86_model >= 5) || (c->x86 > 6)) {
+ /* get processor flags from MSR 0x17 */
+ rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
pf = 1 << ((val[1] >> 18) & 7);
}
@@ -195,9 +212,28 @@ static void do_update_one(void *unused)
microcode[i].ldrver == 1 && microcode[i].hdrver == 1) {
found=1;
- wrmsr(0x8B, 0, 0);
+
+ printf("Microcode\n");
+ printf(" Header Revision %d\n",microcode[i].hdrver);
+ printf(" Date %x/%x/%x\n",
+ ((microcode[i].date >> 24 ) & 0xff),
+ ((microcode[i].date >> 16 ) & 0xff),
+ (microcode[i].date & 0xFFFF));
+ printf(" Type %x Family %x Model %x Stepping %x\n",
+ ((microcode[i].sig >> 12) & 0x3),
+ ((microcode[i].sig >> 8) & 0xf),
+ ((microcode[i].sig >> 4) & 0xf),
+ ((microcode[i].sig & 0xf)));
+ printf(" Checksum %x\n",microcode[i].cksum);
+ printf(" Loader Revision %x\n",microcode[i].ldrver);
+ printf(" Processor Flags %x\n\n",microcode[i].pf);
+
+ /* trick, to work even if there was no prior update by the BIOS */
+ wrmsr(MSR_IA32_UCODE_REV, 0, 0);
__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
- rdmsr(0x8B, val[0], rev);
+
+ /* get current (on-cpu) revision into rev (ignore val[0]) */
+ rdmsr(MSR_IA32_UCODE_REV, val[0], rev);
if (microcode[i].rev < rev) {
printk(KERN_ERR
"microcode: CPU%d not 'upgrading' to earlier revision"
@@ -219,13 +255,20 @@ static void do_update_one(void *unused)
break;
}
- wrmsr(0x79, (unsigned int)(m->bits), 0);
+ /* write microcode via MSR 0x79 */
+ wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0);
+
+ /* serialize */
__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
- rdmsr(0x8B, val[0], val[1]);
+ /* get the current revision from MSR 0x8B */
+ rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+
+ /* notify the caller of success on this cpu */
req->err = 0;
req->slot = i;
- printk(KERN_ERR "microcode: CPU%d updated from revision "
+
+ printk(KERN_INFO "microcode: CPU%d updated from revision "
"%d to %d, date=%08x\n",
cpu_num, rev, val[1], m->date);
}
@@ -239,18 +282,21 @@ static void do_update_one(void *unused)
static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
{
- if (*ppos >= mc_fsize)
- return 0;
+ ssize_t ret = 0;
+
down_read(&microcode_rwsem);
+ if (*ppos >= mc_fsize)
+ goto out;
if (*ppos + len > mc_fsize)
len = mc_fsize - *ppos;
- if (copy_to_user(buf, mc_applied + *ppos, len)) {
- up_read(&microcode_rwsem);
- return -EFAULT;
- }
+ ret = -EFAULT;
+ if (copy_to_user(buf, mc_applied + *ppos, len))
+ goto out;
*ppos += len;
+ ret = len;
+out:
up_read(&microcode_rwsem);
- return len;
+ return ret;
}
static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
@@ -267,8 +313,8 @@ static ssize_t microcode_write(struct file *file, const char *buf, size_t len, l
mc_applied = kmalloc(smp_num_cpus*sizeof(struct microcode),
GFP_KERNEL);
if (!mc_applied) {
- printk(KERN_ERR "microcode: out of memory for saved microcode\n");
up_write(&microcode_rwsem);
+ printk(KERN_ERR "microcode: out of memory for saved microcode\n");
return -ENOMEM;
}
}
@@ -307,10 +353,12 @@ static int microcode_ioctl(struct inode *inode, struct file *file,
case MICROCODE_IOCFREE:
down_write(&microcode_rwsem);
if (mc_applied) {
+ int bytes = smp_num_cpus * sizeof(struct microcode);
+
devfs_set_file_size(devfs_handle, 0);
kfree(mc_applied);
mc_applied = NULL;
- printk(KERN_INFO "microcode: freed %d bytes\n", mc_fsize);
+ printk(KERN_INFO "microcode: freed %d bytes\n", bytes);
mc_fsize = 0;
up_write(&microcode_rwsem);
return 0;
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index 47c83f58e..60764e3cd 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -480,12 +480,14 @@ static int have_wrcomb (void)
}
} /* End Function have_wrcomb */
+static u32 size_or_mask, size_and_mask;
+
static void intel_get_mtrr (unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type *type)
{
- unsigned long dummy, mask_lo, base_lo;
+ unsigned long mask_lo, mask_hi, base_lo, base_hi;
- rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy);
+ rdmsr (MTRRphysMask_MSR(reg), mask_lo, mask_hi);
if ( (mask_lo & 0x800) == 0 )
{
/* Invalid (i.e. free) range */
@@ -495,20 +497,17 @@ static void intel_get_mtrr (unsigned int reg, unsigned long *base,
return;
}
- rdmsr(MTRRphysBase_MSR(reg), base_lo, dummy);
+ rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi);
- /* We ignore the extra address bits (32-35). If someone wants to
- run x86 Linux on a machine with >4GB memory, this will be the
- least of their problems. */
+ /* Work out the shifted address mask. */
+ mask_lo = size_or_mask | mask_hi << (32 - PAGE_SHIFT)
+ | mask_lo >> PAGE_SHIFT;
- /* Clean up mask_lo so it gives the real address mask. */
- mask_lo = (mask_lo & 0xfffff000UL);
/* This works correctly if size is a power of two, i.e. a
contiguous range. */
- *size = ~(mask_lo - 1);
-
- *base = (base_lo & 0xfffff000UL);
- *type = (base_lo & 0xff);
+ *size = -mask_lo;
+ *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT;
+ *type = base_lo & 0xff;
} /* End Function intel_get_mtrr */
static void cyrix_get_arr (unsigned int reg, unsigned long *base,
@@ -533,13 +532,13 @@ static void cyrix_get_arr (unsigned int reg, unsigned long *base,
/* Enable interrupts if it was enabled previously */
__restore_flags (flags);
shift = ((unsigned char *) base)[1] & 0x0f;
- *base &= 0xfffff000UL;
+ *base >>= PAGE_SHIFT;
/* Power of two, at least 4K on ARR0-ARR6, 256K on ARR7
* Note: shift==0xf means 4G, this is unsupported.
*/
if (shift)
- *size = (reg < 7 ? 0x800UL : 0x20000UL) << shift;
+ *size = (reg < 7 ? 0x1UL : 0x40UL) << shift;
else
*size = 0;
@@ -576,7 +575,7 @@ static void amd_get_mtrr (unsigned int reg, unsigned long *base,
/* Upper dword is region 1, lower is region 0 */
if (reg == 1) low = high;
/* The base masks off on the right alignment */
- *base = low & 0xFFFE0000;
+ *base = (low & 0xFFFE0000) >> PAGE_SHIFT;
*type = 0;
if (low & 1) *type = MTRR_TYPE_UNCACHABLE;
if (low & 2) *type = MTRR_TYPE_WRCOMB;
@@ -601,7 +600,7 @@ static void amd_get_mtrr (unsigned int reg, unsigned long *base,
* *128K ...
*/
low = (~low) & 0x1FFFC;
- *size = (low + 4) << 15;
+ *size = (low + 4) << (15 - PAGE_SHIFT);
return;
} /* End Function amd_get_mtrr */
@@ -614,8 +613,8 @@ static struct
static void centaur_get_mcr (unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type *type)
{
- *base = centaur_mcr[reg].high & 0xfffff000;
- *size = (~(centaur_mcr[reg].low & 0xfffff000))+1;
+ *base = centaur_mcr[reg].high >> PAGE_SHIFT;
+ *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT;
*type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */
} /* End Function centaur_get_mcr */
@@ -645,8 +644,10 @@ static void intel_set_mtrr_up (unsigned int reg, unsigned long base,
}
else
{
- wrmsr (MTRRphysBase_MSR (reg), base | type, 0);
- wrmsr (MTRRphysMask_MSR (reg), ~(size - 1) | 0x800, 0);
+ wrmsr (MTRRphysBase_MSR (reg), base << PAGE_SHIFT | type,
+ (base & size_and_mask) >> (32 - PAGE_SHIFT));
+ wrmsr (MTRRphysMask_MSR (reg), -size << PAGE_SHIFT | 0x800,
+ (-size & size_and_mask) >> (32 - PAGE_SHIFT));
}
if (do_safe) set_mtrr_done (&ctxt);
} /* End Function intel_set_mtrr_up */
@@ -660,7 +661,9 @@ static void cyrix_set_arr_up (unsigned int reg, unsigned long base,
arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */
/* count down from 32M (ARR0-ARR6) or from 2G (ARR7) */
- size >>= (reg < 7 ? 12 : 18);
+ if (reg >= 7)
+ size >>= 6;
+
size &= 0x7fff; /* make sure arr_size <= 14 */
for(arr_size = 0; size; arr_size++, size >>= 1);
@@ -685,6 +688,7 @@ static void cyrix_set_arr_up (unsigned int reg, unsigned long base,
}
if (do_safe) set_mtrr_prepare (&ctxt);
+ base <<= PAGE_SHIFT;
setCx86(arr, ((unsigned char *) &base)[3]);
setCx86(arr+1, ((unsigned char *) &base)[2]);
setCx86(arr+2, (((unsigned char *) &base)[1]) | arr_size);
@@ -704,34 +708,36 @@ static void amd_set_mtrr_up (unsigned int reg, unsigned long base,
[RETURNS] Nothing.
*/
{
- u32 low, high;
+ u32 regs[2];
struct set_mtrr_context ctxt;
if (do_safe) set_mtrr_prepare (&ctxt);
/*
* Low is MTRR0 , High MTRR 1
*/
- rdmsr (0xC0000085, low, high);
+ rdmsr (0xC0000085, regs[0], regs[1]);
/*
* Blank to disable
*/
if (size == 0)
- *(reg ? &high : &low) = 0;
+ regs[reg] = 0;
else
- /* Set the register to the base (already shifted for us), the
- type (off by one) and an inverted bitmask of the size
- The size is the only odd bit. We are fed say 512K
- We invert this and we get 111 1111 1111 1011 but
- if you subtract one and invert you get the desired
- 111 1111 1111 1100 mask
- */
- *(reg ? &high : &low)=(((~(size-1))>>15)&0x0001FFFC)|base|(type+1);
+ /* Set the register to the base, the type (off by one) and an
+ inverted bitmask of the size The size is the only odd
+ bit. We are fed say 512K We invert this and we get 111 1111
+ 1111 1011 but if you subtract one and invert you get the
+ desired 111 1111 1111 1100 mask
+
+ But ~(x - 1) == ~x + 1 == -x. Two's complement rocks! */
+ regs[reg] = (-size>>(15-PAGE_SHIFT) & 0x0001FFFC)
+ | (base<<PAGE_SHIFT) | (type+1);
+
/*
* The writeback rule is quite specific. See the manual. Its
* disable local interrupts, write back the cache, set the mtrr
*/
__asm__ __volatile__ ("wbinvd" : : : "memory");
- wrmsr (0xC0000085, low, high);
+ wrmsr (0xC0000085, regs[0], regs[1]);
if (do_safe) set_mtrr_done (&ctxt);
} /* End Function amd_set_mtrr_up */
@@ -751,9 +757,8 @@ static void centaur_set_mcr_up (unsigned int reg, unsigned long base,
}
else
{
- high = base & 0xfffff000; /* base works on 4K pages... */
- low = ((~(size-1))&0xfffff000);
- low |= 0x1f; /* only support write-combining... */
+ high = base << PAGE_SHIFT;
+ low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */
}
centaur_mcr[reg].high = high;
centaur_mcr[reg].low = low;
@@ -1058,7 +1063,7 @@ static int generic_get_free_region (unsigned long base, unsigned long size)
for (i = 0; i < max; ++i)
{
(*get_mtrr) (i, &lbase, &lsize, &ltype);
- if (lsize < 1) return i;
+ if (lsize == 0) return i;
}
return -ENOSPC;
} /* End Function generic_get_free_region */
@@ -1075,10 +1080,10 @@ static int cyrix_get_free_region (unsigned long base, unsigned long size)
unsigned long lbase, lsize;
/* If we are to set up a region >32M then look at ARR7 immediately */
- if (size > 0x2000000UL)
+ if (size > 0x2000)
{
cyrix_get_arr (7, &lbase, &lsize, &ltype);
- if (lsize < 1) return 7;
+ if (lsize == 0) return 7;
/* Else try ARR0-ARR6 first */
}
else
@@ -1087,11 +1092,11 @@ static int cyrix_get_free_region (unsigned long base, unsigned long size)
{
cyrix_get_arr (i, &lbase, &lsize, &ltype);
if ((i == 3) && arr3_protected) continue;
- if (lsize < 1) return i;
+ if (lsize == 0) return i;
}
/* ARR0-ARR6 isn't free, try ARR7 but its size must be at least 256K */
cyrix_get_arr (i, &lbase, &lsize, &ltype);
- if ((lsize < 1) && (size >= 0x40000)) return i;
+ if ((lsize == 0) && (size >= 0x40)) return i;
}
return -ENOSPC;
} /* End Function cyrix_get_free_region */
@@ -1100,9 +1105,9 @@ static int (*get_free_region) (unsigned long base,
unsigned long size) = generic_get_free_region;
/**
- * mtrr_add - Add a memory type region
- * @base: Physical base address of region
- * @size: Physical size of region
+ * mtrr_add_page - Add a memory type region
+ * @base: Physical base address of region in pages (4 KB)
+ * @size: Physical size of region in pages (4 KB)
* @type: Type of MTRR desired
* @increment: If this is true do usage counting on the region
*
@@ -1135,11 +1140,11 @@ static int (*get_free_region) (unsigned long base,
* failures and do not wish system log messages to be sent.
*/
-int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char increment)
+int mtrr_add_page(unsigned long base, unsigned long size, unsigned int type, char increment)
{
/* [SUMMARY] Add an MTRR entry.
- <base> The starting (base) address of the region.
- <size> The size (in bytes) of the region.
+ <base> The starting (base, in pages) address of the region.
+ <size> The size of the region. (in pages)
<type> The type of the new region.
<increment> If true and the region already exists, the usage count will be
incremented.
@@ -1164,7 +1169,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
o Power of 2 block
o base suitably aligned to the power
*/
- if ( type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
+ if ( type > MTRR_TYPE_WRCOMB || size < (1 << (17-PAGE_SHIFT)) ||
(size & ~(size-1))-size || ( base & (size-1) ) )
return -EINVAL;
break;
@@ -1176,9 +1181,9 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
boot_cpu_data.x86_model == 1 &&
boot_cpu_data.x86_mask <= 7 )
{
- if ( base & ((1 << 22)-1) )
+ if ( base & ((1 << (22-PAGE_SHIFT))-1) )
{
- printk (KERN_WARNING "mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
+ printk (KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
return -EINVAL;
}
}
@@ -1186,12 +1191,6 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
case MTRR_IF_CYRIX_ARR:
case MTRR_IF_CENTAUR_MCR:
- if ( (base & 0xfff) || (size & 0xfff) )
- {
- printk ("mtrr: size and base must be multiples of 4 kiB\n");
- printk ("mtrr: size: %lx base: %lx\n", size, base);
- return -EINVAL;
- }
if ( mtrr_if == MTRR_IF_CENTAUR_MCR )
{
if (type != MTRR_TYPE_WRCOMB)
@@ -1200,9 +1199,9 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
return -EINVAL;
}
}
- else if (base + size < 0x100000)
+ else if (base + size < 0x100)
{
- printk (KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx,0x%lx)\n",
+ printk (KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
base, size);
return -EINVAL;
}
@@ -1213,7 +1212,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
lbase = lbase >> 1, last = last >> 1);
if (lbase != last)
{
- printk (KERN_WARNING "mtrr: base(0x%lx) is not aligned on a size(0x%lx) boundary\n",
+ printk (KERN_WARNING "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n",
base, size);
return -EINVAL;
}
@@ -1228,12 +1227,20 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
printk ("mtrr: type: %u illegal\n", type);
return -EINVAL;
}
+
/* If the type is WC, check that this processor supports it */
if ( (type == MTRR_TYPE_WRCOMB) && !have_wrcomb () )
{
printk (KERN_WARNING "mtrr: your processor doesn't support write-combining\n");
return -ENOSYS;
}
+
+ if ( base & size_or_mask || size & size_or_mask )
+ {
+ printk ("mtrr: base or size exceeds the MTRR width\n");
+ return -EINVAL;
+ }
+
increment = increment ? 1 : 0;
max = get_num_var_ranges ();
/* Search for existing MTRR */
@@ -1247,7 +1254,8 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
if ( (base < lbase) || (base + size > lbase + lsize) )
{
up(&main_lock);
- printk (KERN_WARNING "mtrr: 0x%lx,0x%lx overlaps existing 0x%lx,0x%lx\n",
+ printk (KERN_WARNING "mtrr: 0x%lx000,0x%lx000 overlaps existing"
+ " 0x%lx000,0x%lx000\n",
base, size, lbase, lsize);
return -EINVAL;
}
@@ -1256,7 +1264,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
{
if (type == MTRR_TYPE_UNCACHABLE) continue;
up(&main_lock);
- printk ( "mtrr: type mismatch for %lx,%lx old: %s new: %s\n",
+ printk ( "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
base, size, attrib_to_str (ltype), attrib_to_str (type) );
return -EINVAL;
}
@@ -1278,10 +1286,67 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
compute_ascii ();
up(&main_lock);
return i;
+} /* End Function mtrr_add_page */
+
+/**
+ * mtrr_add - Add a memory type region
+ * @base: Physical base address of region
+ * @size: Physical size of region
+ * @type: Type of MTRR desired
+ * @increment: If this is true do usage counting on the region
+ *
+ * Memory type region registers control the caching on newer Intel and
+ * non Intel processors. This function allows drivers to request an
+ * MTRR is added. The details and hardware specifics of each processor's
+ * implementation are hidden from the caller, but nevertheless the
+ * caller should expect to need to provide a power of two size on an
+ * equivalent power of two boundary.
+ *
+ * If the region cannot be added either because all regions are in use
+ * or the CPU cannot support it a negative value is returned. On success
+ * the register number for this entry is returned, but should be treated
+ * as a cookie only.
+ *
+ * On a multiprocessor machine the changes are made to all processors.
+ * This is required on x86 by the Intel processors.
+ *
+ * The available types are
+ *
+ * %MTRR_TYPE_UNCACHEABLE - No caching
+ *
+ * %MTRR_TYPE_WRITEBACK - Write data back in bursts whenever
+ *
+ * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
+ *
+ * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes
+ *
+ * BUGS: Needs a quiet flag for the cases where drivers do not mind
+ * failures and do not wish system log messages to be sent.
+ */
+
+int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char increment)
+{
+/* [SUMMARY] Add an MTRR entry.
+ <base> The starting (base) address of the region.
+ <size> The size (in bytes) of the region.
+ <type> The type of the new region.
+ <increment> If true and the region already exists, the usage count will be
+ incremented.
+ [RETURNS] The MTRR register on success, else a negative number indicating
+ the error code.
+*/
+
+ if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ return -EINVAL;
+ }
+ return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type, increment);
} /* End Function mtrr_add */
/**
- * mtrr_del - delete a memory type region
+ * mtrr_del_page - delete a memory type region
* @reg: Register returned by mtrr_add
* @base: Physical base address
* @size: Size of region
@@ -1295,7 +1360,7 @@ int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char inc
* code.
*/
-int mtrr_del (int reg, unsigned long base, unsigned long size)
+int mtrr_del_page (int reg, unsigned long base, unsigned long size)
/* [SUMMARY] Delete MTRR/decrement usage count.
<reg> The register. If this is less than 0 then <<base>> and <<size>> must
be supplied.
@@ -1320,7 +1385,7 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
for (i = 0; i < max; ++i)
{
(*get_mtrr) (i, &lbase, &lsize, &ltype);
- if ( (lbase == base) && (lsize == size) )
+ if (lbase == base && lsize == size)
{
reg = i;
break;
@@ -1329,7 +1394,7 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
if (reg < 0)
{
up(&main_lock);
- printk ("mtrr: no MTRR for %lx,%lx found\n", base, size);
+ printk ("mtrr: no MTRR for %lx000,%lx000 found\n", base, size);
return -EINVAL;
}
}
@@ -1365,12 +1430,46 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
compute_ascii ();
up (&main_lock);
return reg;
-} /* End Function mtrr_del */
+} /* End Function mtrr_del_page */
+
+/**
+ * mtrr_del - delete a memory type region
+ * @reg: Register returned by mtrr_add
+ * @base: Physical base address
+ * @size: Size of region
+ *
+ * If register is supplied then base and size are ignored. This is
+ * how drivers should call it.
+ *
+ * Releases an MTRR region. If the usage count drops to zero the
+ * register is freed and the region returns to default state.
+ * On success the register is returned, on failure a negative error
+ * code.
+ */
+
+int mtrr_del (int reg, unsigned long base, unsigned long size)
+/* [SUMMARY] Delete MTRR/decrement usage count.
+ <reg> The register. If this is less than 0 then <<base>> and <<size>> must
+ be supplied.
+ <base> The base address of the region. This is ignored if <<reg>> is >= 0.
+ <size> The size of the region. This is ignored if <<reg>> is >= 0.
+ [RETURNS] The register on success, else a negative number indicating
+ the error code.
+*/
+{
+ if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ return -EINVAL;
+ }
+ return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
+}
#ifdef USERSPACE_INTERFACE
static int mtrr_file_add (unsigned long base, unsigned long size,
- unsigned int type, char increment, struct file *file)
+ unsigned int type, char increment, struct file *file, int page)
{
int reg, max;
unsigned int *fcount = file->private_data;
@@ -1386,18 +1485,38 @@ static int mtrr_file_add (unsigned long base, unsigned long size,
memset (fcount, 0, max * sizeof *fcount);
file->private_data = fcount;
}
- reg = mtrr_add (base, size, type, 1);
+ if (!page) {
+ if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ return -EINVAL;
+ }
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
+ }
+ reg = mtrr_add_page (base, size, type, 1);
if (reg >= 0) ++fcount[reg];
return reg;
} /* End Function mtrr_file_add */
static int mtrr_file_del (unsigned long base, unsigned long size,
- struct file *file)
+ struct file *file, int page)
{
int reg;
unsigned int *fcount = file->private_data;
- reg = mtrr_del (-1, base, size);
+ if (!page) {
+ if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ return -EINVAL;
+ }
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
+ }
+ reg = mtrr_del_page (-1, base, size);
if (reg < 0) return reg;
if (fcount == NULL) return reg;
if (fcount[reg] < 1) return -EINVAL;
@@ -1418,12 +1537,13 @@ static ssize_t mtrr_read (struct file *file, char *buf, size_t len,
static ssize_t mtrr_write (struct file *file, const char *buf, size_t len,
loff_t *ppos)
/* Format of control line:
- "base=%lx size=%lx type=%s" OR:
+ "base=%Lx size=%Lx type=%s" OR:
"disable=%d"
*/
{
int i, err;
- unsigned long reg, base, size;
+ unsigned long reg;
+ unsigned long long base, size;
char *ptr;
char line[LINE_SIZE];
@@ -1438,7 +1558,7 @@ static ssize_t mtrr_write (struct file *file, const char *buf, size_t len,
if ( !strncmp (line, "disable=", 8) )
{
reg = simple_strtoul (line + 8, &ptr, 0);
- err = mtrr_del (reg, 0, 0);
+ err = mtrr_del_page (reg, 0, 0);
if (err < 0) return err;
return len;
}
@@ -1447,14 +1567,20 @@ static ssize_t mtrr_write (struct file *file, const char *buf, size_t len,
printk ("mtrr: no \"base=\" in line: \"%s\"\n", line);
return -EINVAL;
}
- base = simple_strtoul (line + 5, &ptr, 0);
+ base = simple_strtoull (line + 5, &ptr, 0);
for (; isspace (*ptr); ++ptr);
if ( strncmp (ptr, "size=", 5) )
{
printk ("mtrr: no \"size=\" in line: \"%s\"\n", line);
return -EINVAL;
}
- size = simple_strtoul (ptr + 5, &ptr, 0);
+ size = simple_strtoull (ptr + 5, &ptr, 0);
+ if ( (base & 0xfff) || (size & 0xfff) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: 0x%Lx base: 0x%Lx\n", size, base);
+ return -EINVAL;
+ }
for (; isspace (*ptr); ++ptr);
if ( strncmp (ptr, "type=", 5) )
{
@@ -1466,7 +1592,9 @@ static ssize_t mtrr_write (struct file *file, const char *buf, size_t len,
for (i = 0; i < MTRR_NUM_TYPES; ++i)
{
if ( strcmp (ptr, mtrr_strings[i]) ) continue;
- err = mtrr_add (base, size, i, 1);
+ base >>= PAGE_SHIFT;
+ size >>= PAGE_SHIFT;
+ err = mtrr_add_page ((unsigned long)base, (unsigned long)size, i, 1);
if (err < 0) return err;
return len;
}
@@ -1490,7 +1618,7 @@ static int mtrr_ioctl (struct inode *inode, struct file *file,
if ( !suser () ) return -EPERM;
if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
return -EFAULT;
- err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file);
+ err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file, 0);
if (err < 0) return err;
break;
case MTRRIOC_SET_ENTRY:
@@ -1504,7 +1632,7 @@ static int mtrr_ioctl (struct inode *inode, struct file *file,
if ( !suser () ) return -EPERM;
if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
return -EFAULT;
- err = mtrr_file_del (sentry.base, sentry.size, file);
+ err = mtrr_file_del (sentry.base, sentry.size, file, 0);
if (err < 0) return err;
break;
case MTRRIOC_KILL_ENTRY:
@@ -1519,7 +1647,54 @@ static int mtrr_ioctl (struct inode *inode, struct file *file,
return -EFAULT;
if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL;
(*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type);
+
+ /* Hide entries that go above 4GB */
+ if (gentry.base + gentry.size > 0x100000 || gentry.size == 0x100000)
+ gentry.base = gentry.size = gentry.type = 0;
+ else {
+ gentry.base <<= PAGE_SHIFT;
+ gentry.size <<= PAGE_SHIFT;
+ gentry.type = type;
+ }
+
+ if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) )
+ return -EFAULT;
+ break;
+ case MTRRIOC_ADD_PAGE_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file, 1);
+ if (err < 0) return err;
+ break;
+ case MTRRIOC_SET_PAGE_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0);
+ if (err < 0) return err;
+ break;
+ case MTRRIOC_DEL_PAGE_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_file_del (sentry.base, sentry.size, file, 1);
+ if (err < 0) return err;
+ break;
+ case MTRRIOC_KILL_PAGE_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_del_page (-1, sentry.base, sentry.size);
+ if (err < 0) return err;
+ break;
+ case MTRRIOC_GET_PAGE_ENTRY:
+ if ( copy_from_user (&gentry, (void *) arg, sizeof gentry) )
+ return -EFAULT;
+ if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL;
+ (*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type);
gentry.type = type;
+
if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) )
return -EFAULT;
break;
@@ -1578,24 +1753,24 @@ static void compute_ascii (void)
for (i = 0; i < max; i++)
{
(*get_mtrr) (i, &base, &size, &type);
- if (size < 1) usage_table[i] = 0;
+ if (size == 0) usage_table[i] = 0;
else
{
- if (size < 0x100000)
+ if (size < (0x100000 >> PAGE_SHIFT))
{
- /* 1MB */
- factor = 'k';
- size >>= 10;
+ /* less than 1MB */
+ factor = 'K';
+ size <<= PAGE_SHIFT - 10;
}
else
{
factor = 'M';
- size >>= 20;
+ size >>= 20 - PAGE_SHIFT;
}
sprintf
(ascii_buffer + ascii_buf_bytes,
- "reg%02i: base=0x%08lx (%4liMB), size=%4li%cB: %s, count=%d\n",
- i, base, base>>20, size, factor,
+ "reg%02i: base=0x%05lx000 (%4liMB), size=%4li%cB: %s, count=%d\n",
+ i, base, base >> (20 - PAGE_SHIFT), size, factor,
attrib_to_str (type), usage_table[i]);
ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes);
}
@@ -1762,11 +1937,38 @@ static int __init mtrr_setup(void)
mtrr_if = MTRR_IF_INTEL;
get_mtrr = intel_get_mtrr;
set_mtrr_up = intel_set_mtrr_up;
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ /* The original Athlon docs said that
+ total addressable memory is 44 bits wide.
+ It was not really clear whether its MTRRs
+ follow this or not. (Read: 44 or 36 bits).
+ However, "x86-64_overview.pdf" explicitly
+ states that "previous implementations support
+ 36 bit MTRRs" and also provides a way to
+ query the width (in bits) of the physical
+ addressable memory on the Hammer family.
+ */
+ if (boot_cpu_data.x86 == 7 && (cpuid_eax(0x80000000) >= 0x80000008)) {
+ u32 phys_addr;
+ phys_addr = cpuid_eax(0x80000008) & 0xff ;
+ size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1);
+ size_and_mask = ~size_or_mask & 0xfff00000;
+ break;
+ }
+ default:
+ /* Intel, etc. */
+ size_or_mask = 0xff000000; /* 36 bits */
+ size_and_mask = 0x00f00000;
+ break;
+ }
} else if ( test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ) {
/* Pre-Athlon (K6) AMD CPU MTRRs */
mtrr_if = MTRR_IF_AMD_K6;
get_mtrr = amd_get_mtrr;
set_mtrr_up = amd_set_mtrr_up;
+ size_or_mask = 0xfff00000; /* 32 bits */
+ size_and_mask = 0;
} else if ( test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ) {
/* Cyrix ARRs */
mtrr_if = MTRR_IF_CYRIX_ARR;
@@ -1774,12 +1976,16 @@ static int __init mtrr_setup(void)
set_mtrr_up = cyrix_set_arr_up;
get_free_region = cyrix_get_free_region;
cyrix_arr_init();
+ size_or_mask = 0xfff00000; /* 32 bits */
+ size_and_mask = 0;
} else if ( test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) ) {
/* Centaur MCRs */
mtrr_if = MTRR_IF_CENTAUR_MCR;
get_mtrr = centaur_get_mcr;
set_mtrr_up = centaur_set_mcr_up;
centaur_mcr_init();
+ size_or_mask = 0xfff00000; /* 32 bits */
+ size_and_mask = 0;
} else {
/* No supported MTRR interface */
mtrr_if = MTRR_IF_NONE;
diff --git a/arch/i386/kernel/pci-irq.c b/arch/i386/kernel/pci-irq.c
index 17a929bb2..cdf4fc827 100644
--- a/arch/i386/kernel/pci-irq.c
+++ b/arch/i386/kernel/pci-irq.c
@@ -176,7 +176,6 @@ static void pirq_ali_ide_interrupt(struct pci_dev *router, unsigned reg, unsigne
pci_read_config_byte(router, reg, &x);
x = (x & 0xe0) | val; /* clear the level->edge transform */
pci_write_config_byte(router, reg, x);
- eisa_set_level_irq(irq);
}
static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
@@ -196,7 +195,6 @@ static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
pirq_ali_ide_interrupt(router, 0x75, val, irq);
break;
}
- eisa_set_level_irq(irq);
return 1;
}
return 0;
@@ -279,6 +277,54 @@ static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
return 1;
}
+static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ u8 x;
+ int reg = 0x41 + (pirq - 'A') ;
+
+ pci_read_config_byte(router, reg, &x);
+ return (x & 0x80) ? 0 : (x & 0x0f);
+}
+
+static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+ u8 x;
+ int reg = 0x41 + (pirq - 'A') ;
+
+ pci_read_config_byte(router, reg, &x);
+ x = (pirq & 0x20) ? 0 : (irq & 0x0f);
+ pci_write_config_byte(router, reg, x);
+
+ return 1;
+}
+
+/*
+ * VLSI: nibble offset 0x74 - educated guess due to routing table and
+ * config space of VLSI 82C534 PCI-bridge/router (1004:0102)
+ * Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard
+ * devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6
+ * for the busbridge to the docking station.
+ */
+
+static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ if (pirq > 8) {
+ printk("VLSI router pirq escape (%d)\n", pirq);
+ return 0;
+ }
+ return read_config_nybble(router, 0x74, pirq-1);
+}
+
+static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+ if (pirq > 8) {
+ printk("VLSI router pirq escape (%d)\n", pirq);
+ return 0;
+ }
+ write_config_nybble(router, 0x74, pirq-1, irq);
+ return 1;
+}
+
#ifdef CONFIG_PCI_BIOS
static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
@@ -309,7 +355,8 @@ static struct irq_router pirq_routers[] = {
{ "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set },
{ "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set },
-
+ { "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set },
+ { "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set },
{ "default", 0, 0, NULL, NULL }
};
@@ -355,7 +402,7 @@ static void __init pirq_find_router(void)
pirq_router_dev->slot_name);
}
-static struct irq_info *pirq_get_info(struct pci_dev *dev, int pin)
+static struct irq_info *pirq_get_info(struct pci_dev *dev)
{
struct irq_routing_table *rt = pirq_table;
int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
@@ -373,25 +420,28 @@ static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs
static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
{
+ u8 pin;
struct irq_info *info;
- int i, pirq, pin, newirq;
+ int i, pirq, newirq;
int irq = 0;
u32 mask;
struct irq_router *r = pirq_router;
- struct pci_dev *dev2, *d;
+ struct pci_dev *dev2;
char *msg = NULL;
if (!pirq_table)
return 0;
/* Find IRQ routing entry */
- pin = pci_get_interrupt_pin(dev, &d);
- if (pin < 0) {
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (!pin) {
DBG(" -> no interrupt pin\n");
return 0;
}
- DBG("IRQ for %s(%d) via %s", dev->slot_name, pin, d->slot_name);
- info = pirq_get_info(d, pin);
+ pin = pin - 1;
+
+ DBG("IRQ for %s:%d", dev->slot_name, pin);
+ info = pirq_get_info(dev);
if (!info) {
DBG(" -> not found in routing table\n");
return 0;
@@ -405,9 +455,12 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
mask &= pcibios_irq_mask;
- /* Find the best IRQ to assign */
- newirq = 0;
- if (assign) {
+ /*
+ * Find the best IRQ to assign: use the one
+ * reported by the device if possible.
+ */
+ newirq = dev->irq;
+ if (!newirq && assign) {
for (i = 0; i < 16; i++) {
if (!(mask & (1 << i)))
continue;
@@ -417,16 +470,22 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
newirq = i;
}
}
- DBG(" -> newirq=%d", newirq);
}
+ DBG(" -> newirq=%d", newirq);
/* Try to get current IRQ */
- if (r->get && (irq = r->get(pirq_router_dev, d, pirq))) {
+ if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) {
DBG(" -> got IRQ %d\n", irq);
msg = "Found";
+ /* We refuse to override the dev->irq information. Give a warning! */
+ if (dev->irq && dev->irq != irq) {
+ printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n");
+ return 0;
+ }
} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
DBG(" -> assigning IRQ %d", newirq);
- if (r->set(pirq_router_dev, d, pirq, newirq)) {
+ if (r->set(pirq_router_dev, dev, pirq, newirq)) {
+ eisa_set_level_irq(newirq);
DBG(" ... OK\n");
msg = "Assigned";
irq = newirq;
@@ -445,9 +504,14 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
/* Update IRQ for all devices with the same pirq value */
pci_for_each_dev(dev2) {
- if ((pin = pci_get_interrupt_pin(dev2, &d)) >= 0 &&
- (info = pirq_get_info(d, pin)) &&
- info->irq[pin].link == pirq) {
+ pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
+ if (!pin)
+ continue;
+ pin--;
+ info = pirq_get_info(dev2);
+ if (!info)
+ continue;
+ if (info->irq[pin].link == pirq) {
dev2->irq = irq;
pirq_penalty[irq]++;
if (dev != dev2)
@@ -556,19 +620,17 @@ void pcibios_penalize_isa_irq(int irq)
void pcibios_enable_irq(struct pci_dev *dev)
{
- if (!dev->irq) {
- u8 pin;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
- if (pin && !pcibios_lookup_irq(dev, 1)) {
- char *msg;
- if (io_apic_assign_pci_irqs)
- msg = " Probably buggy MP table.";
- else if (pci_probe & PCI_BIOS_IRQ_SCAN)
- msg = "";
- else
- msg = " Please try using pci=biosirq.";
- printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
- 'A' + pin - 1, dev->slot_name, msg);
- }
+ u8 pin;
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+ char *msg;
+ if (io_apic_assign_pci_irqs)
+ msg = " Probably buggy MP table.";
+ else if (pci_probe & PCI_BIOS_IRQ_SCAN)
+ msg = "";
+ else
+ msg = " Please try using pci=biosirq.";
+ printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
+ 'A' + pin - 1, dev->slot_name, msg);
}
}
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 6d3cf4d9a..8e7176c32 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -496,9 +496,9 @@ void release_thread(struct task_struct *dead_task)
void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
{
struct mm_struct * old_mm = current->mm;
- void * old_ldt = old_mm->segments, * ldt = old_ldt;
+ void * old_ldt = old_mm->segments, * ldt;
- if (!old_mm->segments) {
+ if (!old_ldt) {
/*
* default LDT - use the one from init_task
*/
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 692965a06..fffe11398 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -126,7 +126,7 @@ unsigned int mca_pentium_flag;
*/
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
-struct apm_bios_info apm_bios_info;
+struct apm_info apm_info;
struct sys_desc_table_struct {
unsigned short length;
unsigned char table[0];
@@ -608,7 +608,7 @@ void __init setup_arch(char **cmdline_p)
ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
- apm_bios_info = APM_BIOS_INFO;
+ apm_info.bios = APM_BIOS_INFO;
if( SYS_DESC_TABLE.length != 0 ) {
MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
machine_id = SYS_DESC_TABLE.table[0];
@@ -1531,8 +1531,32 @@ static void __init init_intel(struct cpuinfo_x86 *c)
dh = des >> 4;
dl = des & 0x0F;
+ /* Black magic... */
+
switch ( dh )
{
+ case 0:
+ switch ( dl ) {
+ case 6:
+ /* L1 I cache */
+ l1i += 8;
+ break;
+ case 8:
+ /* L1 I cache */
+ l1i += 16;
+ break;
+ case 10:
+ /* L1 D cache */
+ l1d += 8;
+ break;
+ case 12:
+ /* L1 D cache */
+ l1d += 16;
+ break;
+ default:
+ /* TLB, or unknown */
+ }
+ break;
case 2:
if ( dl ) {
/* L3 cache */
@@ -1541,6 +1565,16 @@ static void __init init_intel(struct cpuinfo_x86 *c)
}
break;
case 4:
+ if ( c->x86 > 6 && dl ) {
+ /* P4 family */
+ if ( dl ) {
+ /* L3 cache */
+ cs = 128 << (dl-1);
+ l3 += cs;
+ break;
+ }
+ }
+ /* else same as 8 - fall through */
case 8:
if ( dl ) {
/* L2 cache */
@@ -1556,9 +1590,16 @@ static void __init init_intel(struct cpuinfo_x86 *c)
}
break;
case 7:
- /* L1 I cache */
- cs = dl ? (16 << (dl-1)) : 12;
- l1i += cs;
+ if ( dl >= 8 )
+ {
+ /* L2 cache */
+ cs = 64<<(dl-8);
+ l2 += cs;
+ } else {
+ /* L0 I cache, count as L1 */
+ cs = dl ? (16 << (dl-1)) : 12;
+ l1i += cs;
+ }
break;
default:
/* TLB, or something else we don't know about */
@@ -2066,8 +2107,8 @@ int get_cpuinfo(char * buffer)
/* Intel-defined */
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
- "pat", "pse36", "pn", "clflsh", NULL, "dtes", "acpi", "mmx",
- "fxsr", "sse", "sse2", "selfsnoop", NULL, "acc", "ia64", NULL,
+ "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
+ "fxsr", "sse", "sse2", "ss", NULL, "tm", "ia64", NULL,
/* AMD-defined */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -2113,7 +2154,7 @@ int get_cpuinfo(char * buffer)
p += sprintf(p, "stepping\t: unknown\n");
if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) {
- p += sprintf(p, "cpu MHz\t\t: %lu.%06lu\n",
+ p += sprintf(p, "cpu MHz\t\t: %lu.%03lu\n",
cpu_khz / 1000, (cpu_khz % 1000));
}
@@ -2131,7 +2172,7 @@ int get_cpuinfo(char * buffer)
"fpu_exception\t: %s\n"
"cpuid level\t: %d\n"
"wp\t\t: %s\n"
- "features\t:",
+ "flags\t\t:",
c->fdiv_bug ? "yes" : "no",
c->hlt_works_ok ? "no" : "yes",
c->f00f_bug ? "yes" : "no",
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 57a07765e..858e7dda0 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -886,8 +886,10 @@ void __init smp_boot_cpus(void)
/*
* If we couldn't find a local APIC, then get out of here now!
*/
- if (!verify_local_APIC()) {
- printk(KERN_ERR "BIOS bug, local APIC at 0x%lX not detected!...\n", mp_lapic_addr);
+ if (APIC_INTEGRATED(apic_version[boot_cpu_id]) &&
+ !test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)) {
+ printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+ boot_cpu_id);
printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
#ifndef CONFIG_VISWS
io_apic_irqs = 0;
@@ -897,6 +899,8 @@ void __init smp_boot_cpus(void)
goto smp_done;
}
+ verify_local_APIC();
+
/*
* If SMP should be disabled, then really disable it!
*/
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index b84421374..f2077f2f2 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -62,20 +62,8 @@ struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
*/
struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
-extern int console_loglevel;
extern void bust_spinlocks(void);
-static inline void console_silent(void)
-{
- console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
- if (console_loglevel)
- console_loglevel = 15;
-}
-
asmlinkage void divide_error(void);
asmlinkage void debug(void);
asmlinkage void nmi(void);
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 39a6ce0f8..b2e5a1bfc 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -198,7 +198,7 @@ void __init kmap_init(void)
void show_mem(void)
{
- int i,free = 0, total = 0, reserved = 0;
+ int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
int highmem = 0;
@@ -214,9 +214,7 @@ void show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!page_count(mem_map+i))
- free++;
- else
+ else if (page_count(mem_map+i))
shared += page_count(mem_map+i) - 1;
}
printk("%d pages of RAM\n", total);
@@ -437,7 +435,7 @@ void __init zap_low_mappings (void)
}
/*
- * paging_init() sets up the page tables - note that the first 4MB are
+ * paging_init() sets up the page tables - note that the first 8MB are
* already mapped by head.S.
*
* This routines also unmaps the page at virtual kernel address 0, so
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 30d4def40..b3646e275 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -181,7 +181,7 @@ int get_irq_list(char *buf)
#ifdef CONFIG_SMP
unsigned int global_irq_holder = NO_PROC_ID;
-volatile unsigned int global_irq_lock;
+volatile unsigned long global_irq_lock; /* long for set_bit --RR */
extern void show_stack(unsigned long* esp);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index b2cd880ad..bfbb2050e 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -245,7 +245,7 @@ si_meminfo (struct sysinfo *val)
void
show_mem (void)
{
- int i,free = 0,total = 0,reserved = 0;
+ int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
printk("Mem-info:\n");
@@ -258,9 +258,7 @@ show_mem (void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!page_count(mem_map + i))
- free++;
- else
+ else if (page_count(mem_map + i))
shared += page_count(mem_map + i) - 1;
}
printk("%d pages of RAM\n", total);
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
index e9fee546e..b7bd84c73 100644
--- a/arch/m68k/amiga/amiga_ksyms.c
+++ b/arch/m68k/amiga/amiga_ksyms.c
@@ -25,7 +25,6 @@ EXPORT_SYMBOL(amiga_audio_period);
EXPORT_SYMBOL(amiga_audio_min_period);
EXPORT_SYMBOL(amiga_do_irq);
EXPORT_SYMBOL(amiga_do_irq_list);
-EXPORT_SYMBOL(amiga_intena_vals);
#ifdef CONFIG_AMIGA_PCMCIA
EXPORT_SYMBOL(pcmcia_reset);
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index 58759ba36..0902518f9 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -58,7 +58,7 @@ extern int cia_get_irq_list(struct ciabase *base, char *buf);
/* irq node variables for amiga interrupt sources */
static irq_node_t *ami_irq_list[AMI_STD_IRQS];
-unsigned short amiga_intena_vals[AMI_STD_IRQS] = {
+static unsigned short amiga_intena_vals[AMI_STD_IRQS] = {
IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT,
IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER
};
@@ -106,7 +106,7 @@ void __init amiga_init_IRQ(void)
/* turn off PCMCIA interrupts */
if (AMIGAHW_PRESENT(PCMCIA))
- pcmcia_disable_irq();
+ gayle.inten = GAYLE_IRQ_IDE;
/* turn off all interrupts and enable the master interrupt bit */
custom.intena = 0x7fff;
@@ -352,67 +352,16 @@ inline void amiga_do_irq(int irq, struct pt_regs *fp)
ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
}
-void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
+void amiga_do_irq_list(int irq, struct pt_regs *fp)
{
- irq_node_t *node, *slow_nodes;
- unsigned short flags, intena;
+ irq_node_t *node;
kstat.irqs[0][SYS_IRQS + irq]++;
- if (server->count++)
- server->reentrance = 1;
-
- intena = amiga_intena_vals[irq];
- custom.intreq = intena;
-
- /* serve fast handler if present - there can only be one of these */
- node = ami_irq_list[irq];
- /*
- * Timer interrupts show up like this
- */
- if (!node) {
- server->count--;
- return;
- }
+ custom.intreq = amiga_intena_vals[irq];
- if (node && (node->flags & SA_INTERRUPT)) {
- save_flags(flags);
- cli();
+ for (node = ami_irq_list[irq]; node; node = node->next)
node->handler(irq, node->dev_id, fp);
- restore_flags(flags);
-
- server->count--;
- return;
- }
-
- /*
- * Disable the interrupt source in question and reenable all
- * other interrupts. No interrupt handler should ever touch
- * the intena flags directly!
- */
- custom.intena = intena;
- save_flags(flags);
-#if 0 /* def CPU_M68060_ONLY */
- sti();
-#else
- restore_flags((flags & ~0x0700) | (fp->sr & 0x0700));
-#endif
-
- slow_nodes = node;
- for (;;) {
- for (; node; node = node->next)
- node->handler(irq, node->dev_id, fp);
-
- if (!server->reentrance) {
- server->count--;
- restore_flags(flags);
- custom.intena = IF_SETCLR | intena;
- return;
- }
-
- server->reentrance = 0;
- node = slow_nodes;
- }
}
/*
@@ -445,7 +394,6 @@ static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
{
unsigned short ints = custom.intreqr & custom.intenar;
- static struct irq_server server = {0, 0};
/* if a blitter interrupt */
if (ints & IF_BLIT) {
@@ -461,7 +409,7 @@ static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
/* if a vertical blank interrupt */
if (ints & IF_VERTB)
- amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+ amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
}
static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index 2210d05d6..4c94f7862 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -8,6 +8,7 @@
* for more details.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/init.h>
@@ -42,7 +43,9 @@ static u_long clock_constant;
void __init amiga_init_sound(void)
{
- snd_data = amiga_chip_alloc(sizeof(sine_data), "Beep");
+ static struct resource beep_res = { "Beep" };
+
+ snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res);
if (!snd_data) {
printk (KERN_CRIT "amiga init_sound: failed to allocate chipmem\n");
return;
@@ -51,6 +54,11 @@ void __init amiga_init_sound(void)
/* setup divisor */
clock_constant = (amiga_colorclock+DATA_SIZE/2)/DATA_SIZE;
+
+ /* without amifb, turn video off and enable high quality sound */
+#ifndef CONFIG_FB_AMIGA
+ amifb_video_off();
+#endif
}
static void nosound( unsigned long ignored );
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index b7f9f0508..dfae2b43f 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -3,173 +3,127 @@
**
** Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org>
** - 64-bit aligned allocations for full AGA compatibility
+**
+** Rewritten 15/9/2000 by Geert to use resource management
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/slab.h>
#include <asm/amigahw.h>
-struct chip_desc {
- unsigned first : 1;
- unsigned last : 1;
- unsigned alloced : 1;
- unsigned length : 24;
- long pad; /* We suppose this makes this struct 64 bits long!! */
-};
-
-#define DP(ptr) ((struct chip_desc *)(ptr))
+unsigned long amiga_chip_size;
-u_long amiga_chip_size;
+static struct resource chipram_res = { "Chip RAM", CHIP_PHYSADDR };
static unsigned long chipavail;
-static struct resource chipram = { "Chip RAM", 0 };
-unsigned long amiga_chip_avail( void )
+void __init amiga_chip_init(void)
{
-#ifdef DEBUG
- printk("chip_avail : %ld bytes\n",chipavail);
+ if (!AMIGAHW_PRESENT(CHIP_RAM))
+ return;
+
+#ifndef CONFIG_APUS_FAST_EXCEPT
+ /*
+ * Remove the first 4 pages where PPC exception handlers will be located
+ */
+ amiga_chip_size -= 0x4000;
#endif
- return chipavail;
-}
+ chipram_res.end = amiga_chip_size-1;
+ request_resource(&iomem_resource, &chipram_res);
+ chipavail = amiga_chip_size;
+}
-void __init amiga_chip_init (void)
+
+void *amiga_chip_alloc(unsigned long size, const char *name)
{
- struct chip_desc *dp;
-
- if (!AMIGAHW_PRESENT(CHIP_RAM))
- return;
+ struct resource *res;
- chipram.end = amiga_chip_size-1;
- request_resource(&iomem_resource, &chipram);
-
- /* initialize start boundary */
-
- dp = DP(chipaddr);
- dp->first = 1;
-
- dp->alloced = 0;
- dp->length = amiga_chip_size - 2*sizeof(*dp);
-
- /* initialize end boundary */
- dp = DP(chipaddr + amiga_chip_size) - 1;
- dp->last = 1;
-
- dp->alloced = 0;
- dp->length = amiga_chip_size - 2*sizeof(*dp);
- chipavail = dp->length; /*MILAN*/
+ /* round up */
+ size = PAGE_ALIGN(size);
#ifdef DEBUG
- printk ("chipram end boundary is %p, length is %d\n", dp,
- dp->length);
+ printk("amiga_chip_alloc: allocate %ld bytes\n", size);
#endif
+ res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+ if (!res)
+ return NULL;
+ memset(res, 0, sizeof(struct resource));
+ res->name = name;
+
+ if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
+ kfree(res);
+ return NULL;
+ }
+ chipavail -= size;
+#ifdef DEBUG
+ printk("amiga_chip_alloc: returning %lx\n", res->start);
+#endif
+ return (void *)ZTWO_VADDR(res->start);
}
-void *amiga_chip_alloc(long size, const char *name)
-{
- /* last chunk */
- struct chip_desc *dp;
- void *ptr;
- /* round off */
- size = (size + 7) & ~7;
+ /*
+ * Warning:
+ * amiga_chip_alloc_res is meant only for drivers that need to allocate
+ * Chip RAM before kmalloc() is functional. As a consequence, those
+ * drivers must not free that Chip RAM afterwards.
+ */
-#ifdef DEBUG
- printk("amiga_chip_alloc: allocate %ld bytes\n", size);
-#endif
+void * __init amiga_chip_alloc_res(unsigned long size, struct resource *res)
+{
+ unsigned long start;
+
+ /* round up */
+ size = PAGE_ALIGN(size);
+ /* dmesg into chipmem prefers memory at the safe end */
+ start = CHIP_PHYSADDR + chipavail - size;
- /*
- * get pointer to descriptor for last chunk by
- * going backwards from end chunk
- */
- dp = DP(chipaddr + amiga_chip_size) - 1;
- dp = DP((unsigned long)dp - dp->length) - 1;
-
- while ((dp->alloced || dp->length < size)
- && !dp->first)
- dp = DP ((unsigned long)dp - dp[-1].length) - 2;
-
- if (dp->alloced || dp->length < size) {
- printk ("no chipmem available for %ld allocation\n", size);
- return NULL;
- }
-
- if (dp->length < (size + 2*sizeof(*dp))) {
- /* length too small to split; allocate the whole thing */
- dp->alloced = 1;
- ptr = (void *)(dp+1);
- dp = DP((unsigned long)ptr + dp->length);
- dp->alloced = 1;
#ifdef DEBUG
- printk ("amiga_chip_alloc: no split\n");
+ printk("amiga_chip_alloc_res: allocate %ld bytes\n", size);
#endif
- } else {
- /* split the extent; use the end part */
- long newsize = dp->length - (2*sizeof(*dp) + size);
-
+ if (allocate_resource(&chipram_res, res, size, start, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) {
+ printk("amiga_chip_alloc_res: first alloc failed!\n");
+ if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0)
+ return NULL;
+ }
+ chipavail -= size;
#ifdef DEBUG
- printk ("amiga_chip_alloc: splitting %d to %ld\n", dp->length,
- newsize);
+ printk("amiga_chip_alloc_res: returning %lx\n", res->start);
#endif
- dp->length = newsize;
- dp = DP((unsigned long)(dp+1) + newsize);
- dp->first = dp->last = 0;
- dp->alloced = 0;
- dp->length = newsize;
- dp++;
- dp->first = dp->last = 0;
- dp->alloced = 1;
- dp->length = size;
- ptr = (void *)(dp+1);
- dp = DP((unsigned long)ptr + size);
- dp->alloced = 1;
- dp->length = size;
- }
+ return (void *)ZTWO_VADDR(res->start);
+}
+void amiga_chip_free(void *ptr)
+{
+ unsigned long start = ZTWO_PADDR(ptr);
+ struct resource **p, *res;
+ unsigned long size;
+
+ for (p = &chipram_res.child; (res = *p); p = &res->sibling) {
+ if (res->start != start)
+ continue;
+ *p = res->sibling;
+ size = res->end-start;
#ifdef DEBUG
- printk ("amiga_chip_alloc: returning %p\n", ptr);
+ printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr);
#endif
-
- if ((unsigned long)ptr & 7)
- panic("amiga_chip_alloc: alignment violation\n");
-
- chipavail -= size + (2*sizeof(*dp)); /*MILAN*/
-
- if (!request_mem_region(ZTWO_PADDR(ptr), size, name))
- printk(KERN_WARNING "amiga_chip_alloc: region of size %ld at 0x%08lx "
- "is busy\n", size, ZTWO_PADDR(ptr));
-
- return ptr;
+ chipavail += size;
+ kfree(res);
+ return;
+ }
+ printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
}
-void amiga_chip_free (void *ptr)
-{
- struct chip_desc *sdp = DP(ptr) - 1, *dp2;
- struct chip_desc *edp = DP((unsigned long)ptr + sdp->length);
- chipavail += sdp->length + (2* sizeof(sdp)); /*MILAN*/
+unsigned long amiga_chip_avail(void)
+{
#ifdef DEBUG
- printk("chip_free: free %ld bytes at %p\n",sdp->length,ptr);
+ printk("amiga_chip_avail : %ld bytes\n", chipavail);
#endif
- /* deallocate the chunk */
- sdp->alloced = edp->alloced = 0;
- release_mem_region(ZTWO_PADDR(ptr), sdp->length);
-
- /* check if we should merge with the previous chunk */
- if (!sdp->first && !sdp[-1].alloced) {
- dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2;
- dp2->length += sdp->length + 2*sizeof(*sdp);
- edp->length = dp2->length;
- sdp = dp2;
- }
-
- /* check if we should merge with the following chunk */
- if (!edp->last && !edp[1].alloced) {
- dp2 = DP((unsigned long)edp + edp[1].length) + 2;
- dp2->length += edp->length + 2*sizeof(*sdp);
- sdp->length = dp2->length;
- edp = dp2;
- }
+ return chipavail;
}
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index cda898699..d72d8af9f 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -27,18 +27,17 @@ struct ciabase {
u_short int_mask;
int handler_irq, cia_irq, server_irq;
char *name;
- struct irq_server server;
irq_handler_t irq_list[CIA_IRQS];
} ciaa_base = {
&ciaa, 0, 0, IF_PORTS,
IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA,
IRQ_AMIGA_PORTS,
- "CIAA handler", {0, 0}
+ "CIAA handler"
}, ciab_base = {
&ciab, 0, 0, IF_EXTER,
IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB,
IRQ_AMIGA_EXTER,
- "CIAB handler", {0, 0}
+ "CIAB handler"
};
/*
@@ -136,7 +135,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
}
ints >>= 1;
}
- amiga_do_irq_list(base->server_irq, fp, &base->server);
+ amiga_do_irq_list(base->server_irq, fp);
}
void __init cia_init_IRQ(struct ciabase *base)
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 528f206ff..618d9a618 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -31,6 +31,7 @@
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/irq.h>
+#include <asm/keyboard.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -43,17 +44,36 @@ unsigned char amiga_vblank;
unsigned char amiga_psfreq;
struct amiga_hw_present amiga_hw_present;
-static const char *amiga_models[] = {
- "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000",
- "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco"
+static const char s_a500[] __initdata = "A500";
+static const char s_a500p[] __initdata = "A500+";
+static const char s_a600[] __initdata = "A600";
+static const char s_a1000[] __initdata = "A1000";
+static const char s_a1200[] __initdata = "A1200";
+static const char s_a2000[] __initdata = "A2000";
+static const char s_a2500[] __initdata = "A2500";
+static const char s_a3000[] __initdata = "A3000";
+static const char s_a3000t[] __initdata = "A3000T";
+static const char s_a3000p[] __initdata = "A3000+";
+static const char s_a4000[] __initdata = "A4000";
+static const char s_a4000t[] __initdata = "A4000T";
+static const char s_cdtv[] __initdata = "CDTV";
+static const char s_cd32[] __initdata = "CD32";
+static const char s_draco[] __initdata = "Draco";
+static const char *amiga_models[] __initdata = {
+ s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000,
+ s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco,
};
+static char amiga_model_name[13] = "Amiga ";
+
extern char m68k_debug_device[];
static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
/* amiga specific keyboard functions */
extern int amiga_keyb_init(void);
extern int amiga_kbdrate (struct kbd_repeat *);
+extern int amiga_kbd_translate(unsigned char keycode, unsigned char *keycodep,
+ char raw_mode);
/* amiga specific irq functions */
extern void amiga_init_IRQ (void);
extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
@@ -127,6 +147,8 @@ static struct resource rtc_resource = {
NULL, 0x00dc0000, 0x00dcffff
};
+static struct resource ram_resource[NUM_MEMINFO];
+
/*
* Parse an Amiga-specific record in the bootinfo
@@ -200,8 +222,10 @@ static void __init amiga_identify(void)
memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
printk("Amiga hardware found: ");
- if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+ strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
+ }
switch(amiga_model) {
case AMI_UNKNOWN:
@@ -367,6 +391,8 @@ void __init config_amiga(void)
mach_sched_init = amiga_sched_init;
mach_keyb_init = amiga_keyb_init;
mach_kbdrate = amiga_kbdrate;
+ mach_kbd_translate = amiga_kbd_translate;
+ SYSRQ_KEY = 0xff;
mach_init_IRQ = amiga_init_IRQ;
mach_default_handler = &amiga_default_handler;
mach_request_irq = amiga_request_irq;
@@ -447,6 +473,17 @@ void __init config_amiga(void)
disabled_z2mem>>10);
}
+ /* request all RAM */
+ for (i = 0; i < m68k_num_memory; i++) {
+ ram_resource[i].name =
+ (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
+ (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
+ "16-bit Slow RAM";
+ ram_resource[i].start = m68k_memory[i].addr;
+ ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
+ request_resource(&iomem_resource, &ram_resource[i]);
+ }
+
/* initialize chipram allocator */
amiga_chip_init ();
@@ -478,8 +515,11 @@ static unsigned short jiffy_ticks;
static void __init amiga_sched_init(void (*timer_routine)(int, void *,
struct pt_regs *))
{
+ static struct resource sched_res = { "timer" };
jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
+ if (!request_mem_region(CIAB_PHYSADDR+0x400, 0x200, "timer"))
+ printk("Cannot allocate ciab.ta{lo,hi}\n");
ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */
ciab.talo = jiffy_ticks % 256;
ciab.tahi = jiffy_ticks / 256;
@@ -827,7 +867,9 @@ static void amiga_mem_console_write(struct console *co, const char *s,
static void amiga_savekmsg_init(void)
{
- savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM, "Debug");
+ static struct resource debug_res = { "Debug" };
+
+ savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res);
savekmsg->magic1 = SAVEKMSG_MAGIC1;
savekmsg->magic2 = SAVEKMSG_MAGIC2;
savekmsg->magicptr = virt_to_phys(savekmsg);
@@ -933,9 +975,7 @@ static void amiga_heartbeat(int on)
static void amiga_get_model(char *model)
{
- strcpy(model, "Amiga ");
- if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
- strcat(model, amiga_models[amiga_model-AMI_500]);
+ strcpy(model, amiga_model_name);
}
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index d7a64faea..f4f284a9a 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -13,6 +13,7 @@
* enhanced by Bjoern Brauel and Roman Hodek
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
@@ -24,6 +25,7 @@
#include <linux/random.h>
#include <linux/init.h>
#include <linux/kbd_ll.h>
+#include <linux/kbd_kern.h>
#include <asm/atariints.h>
#include <asm/atarihw.h>
@@ -362,7 +364,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
if (acia_stat & ACIA_RDRF) /* received a character */
{
scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */
- mark_bh(KEYBOARD_BH);
+ tasklet_schedule(&keyboard_tasklet);
interpret_scancode:
switch (kb_state.state)
{
@@ -860,3 +862,16 @@ int atari_kbdrate( struct kbd_repeat *k )
return( 0 );
}
+
+int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
+{
+#ifdef CONFIG_MAGIC_SYSRQ
+ /* ALT+HELP pressed? */
+ if ((keycode == 98) && ((shift_state & 0xff) == 8))
+ *keycodep = 0xff;
+ else
+#endif
+ *keycodep = keycode;
+ return 1;
+}
+
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 3acfeff7a..70a32fb65 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -60,6 +60,8 @@ static int atari_get_hardware_list(char *buffer);
/* atari specific keyboard functions */
extern int atari_keyb_init(void);
extern int atari_kbdrate (struct kbd_repeat *);
+extern int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep,
+ char raw_mode);
extern void atari_kbd_leds (unsigned int);
/* atari specific irq functions */
extern void atari_init_IRQ (void);
@@ -253,6 +255,8 @@ void __init config_atari(void)
mach_sched_init = atari_sched_init;
mach_keyb_init = atari_keyb_init;
mach_kbdrate = atari_kbdrate;
+ mach_kbd_translate = atari_kbd_translate;
+ SYSRQ_KEY = 0xff;
mach_kbd_leds = atari_kbd_leds;
mach_init_IRQ = atari_init_IRQ;
mach_request_irq = atari_request_irq;
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index d0acdaaae..b4a797f2e 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -20,6 +20,7 @@
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/shm.h>
+#include <linux/bootmem.h>
#include <asm/setup.h>
#include <asm/machdep.h>
@@ -33,6 +34,7 @@
#ifdef CONFIG_STRAM_SWAP
#define MAJOR_NR Z2RAM_MAJOR
+#define do_z2_request do_stram_request
#include <linux/blk.h>
#undef DEVICE_NAME
#define DEVICE_NAME "stram"
@@ -123,6 +125,10 @@
unswap_by_move disabled because it does not handle swapped shm pages.
*/
+/* 2000-05-01: ++andreas
+ Integrated with bootmem. Remove all traces of unswap_by_move.
+*/
+
#ifdef CONFIG_STRAM_SWAP
#define ALIGN_IF_SWAP(x) PAGE_ALIGN(x)
#else
@@ -130,10 +136,10 @@
#endif
/* get index of swap page at address 'addr' */
-#define SWAP_NR(addr) (((unsigned long)(addr)-swap_start) >> PAGE_SHIFT)
+#define SWAP_NR(addr) (((addr) - swap_start) >> PAGE_SHIFT)
/* get address of swap page #'nr' */
-#define SWAP_ADDR(nr) ((void *)(swap_start + ((nr)<<PAGE_SHIFT)))
+#define SWAP_ADDR(nr) (swap_start + ((nr) << PAGE_SHIFT))
/* get number of pages for 'n' bytes (already page-aligned) */
#define N_PAGES(n) ((n) >> PAGE_SHIFT)
@@ -144,11 +150,8 @@
#define MAX_STRAM_FRACTION_NOM 1
#define MAX_STRAM_FRACTION_DENOM 3
-/* Start and end of the (pre-mem_init) reserved ST-RAM region */
-static unsigned long rsvd_stram_beg, rsvd_stram_end;
-
/* Start and end (virtual) of ST-RAM */
-static unsigned long stram_start, stram_end;
+static void *stram_start, *stram_end;
/* set after memory_init() executed and allocations via start_mem aren't
* possible anymore */
@@ -159,7 +162,7 @@ static int kernel_in_stram;
typedef struct stram_block {
struct stram_block *next;
- unsigned long start;
+ void *start;
unsigned long size;
unsigned flags;
const char *owner;
@@ -168,7 +171,6 @@ typedef struct stram_block {
/* values for flags field */
#define BLOCK_FREE 0x01 /* free structure in the BLOCKs pool */
#define BLOCK_KMALLOCED 0x02 /* structure allocated by kmalloc() */
-#define BLOCK_STATIC 0x04 /* pre-mem_init() allocated block */
#define BLOCK_GFP 0x08 /* block allocated with __get_dma_pages() */
#define BLOCK_INSWAP 0x10 /* block allocated in swap space */
@@ -191,7 +193,7 @@ static BLOCK static_blocks[N_STATIC_BLOCKS];
static int max_swap_size = -1;
/* start and end of swapping area */
-static unsigned long swap_start, swap_end;
+static void *swap_start, *swap_end;
/* The ST-RAM's swap info structure */
static struct swap_info_struct *stram_swap_info;
@@ -215,7 +217,6 @@ static DECLARE_MUTEX(stram_swap_sem);
#ifdef DO_PROC
static unsigned stat_swap_read = 0;
static unsigned stat_swap_write = 0;
-static unsigned stat_swap_move = 0;
static unsigned stat_swap_force = 0;
#endif /* DO_PROC */
@@ -224,21 +225,19 @@ static unsigned stat_swap_force = 0;
/***************************** Prototypes *****************************/
#ifdef CONFIG_STRAM_SWAP
-static int swap_init( unsigned long start_mem, unsigned long swap_data );
+static int swap_init(void *start_mem, void *swap_data);
static void *get_stram_region( unsigned long n_pages );
static void free_stram_region( unsigned long offset, unsigned long n_pages
);
-static int in_some_region( unsigned long addr );
+static int in_some_region(void *addr);
static unsigned long find_free_region( unsigned long n_pages, unsigned long
*total_free, unsigned long
*region_free );
-static void do_stram_request( void );
+static void do_stram_request(request_queue_t *);
static int stram_open( struct inode *inode, struct file *filp );
static int stram_release( struct inode *inode, struct file *filp );
-static void do_z2_request( void );
#endif
-static int get_gfp_order( unsigned long size );
-static void reserve_region( unsigned long addr, unsigned long end );
+static void reserve_region(void *start, void *end);
static BLOCK *add_region( void *addr, unsigned long size );
static BLOCK *find_region( void *addr );
static int remove_region( BLOCK *block );
@@ -264,14 +263,12 @@ void __init atari_stram_init(void)
/* determine whether kernel code resides in ST-RAM (then ST-RAM is the
* first memory block at virtual 0x0) */
- stram_start = (unsigned long)phys_to_virt(0);
+ stram_start = phys_to_virt(0);
kernel_in_stram = (stram_start == 0);
for( i = 0; i < m68k_num_memory; ++i ) {
if (m68k_memory[i].addr == 0) {
/* skip first 2kB or page (supervisor-only!) */
- rsvd_stram_beg = stram_start + ALIGN_IF_SWAP(0x800);
- rsvd_stram_end = rsvd_stram_beg;
stram_end = stram_start + m68k_memory[i].size;
return;
}
@@ -282,10 +279,10 @@ void __init atari_stram_init(void)
/*
- * This function is called from mem_init() to reserve the pages needed for
+ * This function is called from setup_arch() to reserve the pages needed for
* ST-RAM management.
*/
-void __init atari_stram_reserve_pages(unsigned long start_mem)
+void __init atari_stram_reserve_pages(void *start_mem)
{
#ifdef CONFIG_STRAM_SWAP
/* if max_swap_size is negative (i.e. no stram_swap= option given),
@@ -299,42 +296,24 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
max_swap_size =
(!MACH_IS_HADES &&
(N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <=
- max_mapnr*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
+ (high_memory>>PAGE_SHIFT)*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size );
#endif
/* always reserve first page of ST-RAM, the first 2 kB are
* supervisor-only! */
- set_bit( PG_reserved, &virt_to_page(stram_start)->flags );
+ if (!kernel_in_stram)
+ reserve_bootmem (0, PAGE_SIZE);
#ifdef CONFIG_STRAM_SWAP
- if (!max_swap_size) {
- fallback:
-#endif
- DPRINTK( "atari_stram_reserve_pages: swapping disabled\n" );
- if (!kernel_in_stram) {
- /* Reserve all pages that have been marked by pre-mem_init
- * stram_alloc() (e.g. for the screen memory). */
- reserve_region( rsvd_stram_beg, rsvd_stram_end );
- DPRINTK( "atari_stram_reserve_pages: reseverved %08lx-%08lx\n",
- rsvd_stram_beg, rsvd_stram_end );
- }
- /* else (kernel in ST-RAM): nothing to do, ST-RAM buffers are
- * kernel data */
-#ifdef CONFIG_STRAM_SWAP
- }
- else {
- unsigned long swap_data;
- BLOCK *p;
-
- /* determine first page to use as swap:
- * if the kernel is in TT-RAM, this is the first page of (usable)
- * ST-RAM; else if there were already some allocations (probable...),
- * use the lowest address of these (the list is sorted by address!);
- * otherwise just use the end of kernel data (= start_mem) */
- swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE :
- alloc_list ? alloc_list->start :
- start_mem;
+ {
+ void *swap_data;
+
+ start_mem = (void *) PAGE_ALIGN ((unsigned long) start_mem);
+ /* determine first page to use as swap: if the kernel is
+ in TT-RAM, this is the first page of (usable) ST-RAM;
+ otherwise just use the end of kernel data (= start_mem) */
+ swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : start_mem;
/* decrement by one page, rest of kernel assumes that first swap page
* is always reserved and maybe doesn't handle SWP_ENTRY == 0
* correctly */
@@ -343,7 +322,7 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
if (swap_end-swap_start > max_swap_size)
swap_end = swap_start + max_swap_size;
DPRINTK( "atari_stram_reserve_pages: swapping enabled; "
- "swap=%08lx-%08lx\n", swap_start, swap_end );
+ "swap=%p-%p\n", swap_start, swap_end);
/* reserve some amount of memory for maintainance of
* swapping itself: one page for each 2048 (PAGE_SIZE/2)
@@ -352,24 +331,18 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
>> (PAGE_SHIFT-1)) << PAGE_SHIFT;
/* correct swap_start if necessary */
- if (swap_start == swap_data)
- swap_start = start_mem;
+ if (swap_start + PAGE_SIZE == swap_data)
+ swap_start = start_mem - PAGE_SIZE;
if (!swap_init( start_mem, swap_data )) {
printk( KERN_ERR "ST-RAM swap space initialization failed\n" );
max_swap_size = 0;
- goto fallback;
+ return;
}
/* reserve region for swapping meta-data */
- reserve_region( swap_data, start_mem );
+ reserve_region(swap_data, start_mem);
/* reserve swapping area itself */
- reserve_region( swap_start+PAGE_SIZE, swap_end );
-
- /* Formerly static areas have been included in the swap area. */
- for( p = alloc_list; p; p = p->next ) {
- if (p->flags & BLOCK_STATIC)
- p->flags = (p->flags & ~BLOCK_STATIC) | BLOCK_INSWAP;
- }
+ reserve_region(swap_start + PAGE_SIZE, swap_end);
/*
* If the whole ST-RAM is used for swapping, there are no allocatable
@@ -387,15 +360,12 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
* You just will get non-DMA-able memory...
*/
mach_max_dma_address = 0xffffffff;
-
- /*
- * Ok, num_physpages needs not be really exact, but it's better to
- * subtract the pages set aside for swapping.
- */
- num_physpages -= SWAP_NR(swap_end)-1;
}
#endif
-
+}
+
+void atari_stram_mem_init_hook (void)
+{
mem_init_done = 1;
}
@@ -420,68 +390,33 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
* likely to fail :-(
*
*/
-void *atari_stram_alloc( long size, unsigned long *start_mem,
- const char *owner )
+void *atari_stram_alloc(long size, const char *owner)
{
void *addr = NULL;
BLOCK *block;
int flags;
- DPRINTK( "atari_stram_alloc(size=%08lx,*start_mem=%08lx,owner=%s)\n",
- size, start_mem ? *start_mem : 0xffffffff, owner );
-
- if (start_mem && mem_init_done) {
- printk( KERN_ERR "atari_stram_alloc called with start_mem!=NULL "
- "after mem_init() from %p\n", __builtin_return_address(0) );
- return( NULL );
- }
- if (!start_mem && !mem_init_done) {
- printk( KERN_ERR "atari_stram_alloc called with start_mem==NULL "
- "before mem_init() from %p\n", __builtin_return_address(0) );
- return( NULL );
- }
+ DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner);
size = ALIGN_IF_SWAP(size);
DPRINTK( "atari_stram_alloc: rounded size = %08lx\n", size );
- if (!mem_init_done) {
- /* before mem_init(): allocate "statically", i.e. either in the kernel
- * data space (current end in *start_mem), or at the end of currently
- * reserved ST-RAM. */
- if (kernel_in_stram) {
- /* Get memory from kernel data space */
- *start_mem = ALIGN_IF_SWAP(*start_mem);
- addr = (void *)*start_mem;
- *start_mem += size;
- DPRINTK( "atari_stram_alloc: pre-mem_init and k/ST: "
- "shifted start_mem to %08lx, addr=%p\n",
- *start_mem, addr );
- }
- else {
- /* Get memory from rsvd_stram_beg */
- if (rsvd_stram_end + size < stram_end) {
- addr = (void *) rsvd_stram_end;
- rsvd_stram_end += size;
- DPRINTK( "atari_stram_alloc: pre-mem_init and k/TT: "
- "shifted rsvd_stram_end to %08lx, addr=%p\n",
- rsvd_stram_end, addr );
- }
- }
- flags = BLOCK_STATIC;
- }
#ifdef CONFIG_STRAM_SWAP
- else if (max_swap_size) {
- /* If swapping is active (can only be the case after mem_init()!):
- * make some free space in the swap "device". */
+ if (max_swap_size) {
+ /* If swapping is active: make some free space in the swap
+ "device". */
DPRINTK( "atari_stram_alloc: after mem_init, swapping ok, "
"calling get_region\n" );
addr = get_stram_region( N_PAGES(size) );
flags = BLOCK_INSWAP;
}
+ else
#endif
+ if (!mem_init_done)
+ return alloc_bootmem_low(size);
else {
/* After mem_init() and no swapping: can only resort to
* __get_dma_pages() */
- addr = (void *)__get_dma_pages(GFP_KERNEL, get_gfp_order(size));
+ addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));
flags = BLOCK_GFP;
DPRINTK( "atari_stram_alloc: after mem_init, swapping off, "
"get_pages=%p\n", addr );
@@ -492,14 +427,12 @@ void *atari_stram_alloc( long size, unsigned long *start_mem,
/* out of memory for BLOCK structure :-( */
DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "
"freeing again\n" );
- if (flags == BLOCK_STATIC)
- rsvd_stram_end -= size;
#ifdef CONFIG_STRAM_SWAP
- else if (flags == BLOCK_INSWAP)
+ if (flags == BLOCK_INSWAP)
free_stram_region( SWAP_NR(addr), N_PAGES(size) );
-#endif
else
- free_pages( (unsigned long)addr, get_gfp_order(size));
+#endif
+ free_pages((unsigned long)addr, get_order(size));
return( NULL );
}
block->owner = owner;
@@ -527,15 +460,15 @@ void atari_stram_free( void *addr )
if (!max_swap_size) {
#endif
if (block->flags & BLOCK_GFP) {
- DPRINTK( "atari_stram_free: is kmalloced, order_size=%d\n",
- get_gfp_order(block->size) );
- free_pages( (unsigned long)addr, get_gfp_order(block->size) );
+ DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",
+ get_order(block->size));
+ free_pages((unsigned long)addr, get_order(block->size));
}
else
goto fail;
#ifdef CONFIG_STRAM_SWAP
}
- else if (block->flags & (BLOCK_INSWAP|BLOCK_STATIC)) {
+ else if (block->flags & BLOCK_INSWAP) {
DPRINTK( "atari_stram_free: is swap-alloced\n" );
free_stram_region( SWAP_NR(block->start), N_PAGES(block->size) );
}
@@ -563,17 +496,18 @@ void atari_stram_free( void *addr )
* Initialize ST-RAM swap device
* (lots copied and modified from sys_swapon() in mm/swapfile.c)
*/
-static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
+static int __init swap_init(void *start_mem, void *swap_data)
{
- static struct dentry fake_dentry[3];
+ static struct dentry fake_dentry;
+ static struct vfsmount fake_vfsmnt;
struct swap_info_struct *p;
struct inode swap_inode;
unsigned int type;
- unsigned long addr;
+ void *addr;
int i, j, k, prev;
- DPRINTK( "swap_init(start_mem=%08lx, swap_data=%08lx)\n",
- start_mem, swap_data );
+ DPRINTK("swap_init(start_mem=%p, swap_data=%p)\n",
+ start_mem, swap_data);
/* need at least one page for swapping to (and this also isn't very
* much... :-) */
@@ -598,18 +532,16 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
stram_swap_type = type;
/* fake some dir cache entries to give us some name in /dev/swaps */
- fake_dentry[0].d_covers = &fake_dentry[1];
- fake_dentry[0].d_parent = &fake_dentry[0];
- fake_dentry[1].d_parent = &fake_dentry[2];
- fake_dentry[1].d_name.name = "stram (internal)";
- fake_dentry[1].d_name.len = 16;
- fake_dentry[2].d_covers = &fake_dentry[2];
- fake_dentry[2].d_parent = &fake_dentry[2];
+ fake_dentry.d_parent = &fake_dentry;
+ fake_dentry.d_name.name = "stram (internal)";
+ fake_dentry.d_name.len = 16;
+ fake_vfsmnt.mnt_parent = &fake_vfsmnt;
p->flags = SWP_USED;
- p->swap_file = &fake_dentry[0];
+ p->swap_file = &fake_dentry;
+ p->swap_vfsmnt = &fake_vfsmnt;
p->swap_device = 0;
- p->swap_map = (unsigned short *)swap_data;
+ p->swap_map = swap_data;
p->cluster_nr = 0;
p->next = -1;
p->prio = 0x7ff0; /* a rather high priority, but not the higest
@@ -628,7 +560,7 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
k = 0; /* # of already allocated pages (from pre-mem_init stram_alloc()) */
p->lowest_bit = 0;
p->highest_bit = 0;
- for( i = 1, addr = (unsigned long)SWAP_ADDR(1); i < p->max;
+ for( i = 1, addr = SWAP_ADDR(1); i < p->max;
i++, addr += PAGE_SIZE ) {
if (in_some_region( addr )) {
p->swap_map[i] = SWAP_MAP_BAD;
@@ -685,8 +617,8 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
* what to do if a write is requested later.
*/
static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
- address, pte_t *dir, unsigned long entry,
- unsigned long page /*, int isswap */)
+ address, pte_t *dir, swp_entry_t entry,
+ struct page *page)
{
pte_t pte = *dir;
@@ -698,34 +630,25 @@ static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
memory */
if (pte_page(pte) != page)
return;
- if (0 /* isswap */)
- virt_to_page(pte_page(pte))->offset = page;
- else
- /* We will be removing the swap cache in a moment, so... */
- set_pte(dir, pte_mkdirty(pte));
+ /* We will be removing the swap cache in a moment, so... */
+ set_pte(dir, pte_mkdirty(pte));
return;
}
- if (pte_val(pte) != entry)
+ if (pte_val(pte) != entry.val)
return;
- if (0 /* isswap */) {
- DPRINTK( "unswap_pte: replacing entry %08lx by %08lx", entry, page );
- set_pte(dir, __pte(page));
- }
- else {
- DPRINTK( "unswap_pte: replacing entry %08lx by new page %08lx",
- entry, page );
- set_pte(dir, pte_mkdirty(__mk_pte(page,vma->vm_page_prot)));
- atomic_inc(&virt_to_page(page)->count);
- ++vma->vm_mm->rss;
- }
+ DPRINTK("unswap_pte: replacing entry %08lx by new page %p",
+ entry.val, page);
+ set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
swap_free(entry);
+ get_page(page);
+ ++vma->vm_mm->rss;
}
static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
unsigned long address, unsigned long size,
- unsigned long offset, unsigned long entry,
- unsigned long page /* , int isswap */)
+ unsigned long offset, swp_entry_t entry,
+ struct page *page)
{
pte_t * pte;
unsigned long end;
@@ -733,7 +656,7 @@ static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
if (pmd_none(*dir))
return;
if (pmd_bad(*dir)) {
- printk("unswap_pmd: bad pmd (%08lx)\n", pmd_val(*dir));
+ pmd_ERROR(*dir);
pmd_clear(dir);
return;
}
@@ -744,8 +667,7 @@ static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
if (end > PMD_SIZE)
end = PMD_SIZE;
do {
- unswap_pte(vma, offset+address-vma->vm_start, pte, entry,
- page /* , isswap */);
+ unswap_pte(vma, offset+address-vma->vm_start, pte, entry, page);
address += PAGE_SIZE;
pte++;
} while (address < end);
@@ -753,8 +675,7 @@ static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
unsigned long address, unsigned long size,
- unsigned long entry, unsigned long page
- /* , int isswap */)
+ swp_entry_t entry, struct page *page)
{
pmd_t * pmd;
unsigned long offset, end;
@@ -762,7 +683,7 @@ static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
if (pgd_none(*dir))
return;
if (pgd_bad(*dir)) {
- printk("unswap_pgd: bad pgd (%08lx)\n", pgd_val(*dir));
+ pgd_ERROR(*dir);
pgd_clear(dir);
return;
}
@@ -774,28 +695,26 @@ static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,
end = PGDIR_SIZE;
do {
unswap_pmd(vma, pmd, address, end - address, offset, entry,
- page /* , isswap */);
+ page);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
}
static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir,
- unsigned long entry, unsigned long page
- /* , int isswap */)
+ swp_entry_t entry, struct page *page)
{
unsigned long start = vma->vm_start, end = vma->vm_end;
- while (start < end) {
- unswap_pgd(vma, pgdir, start, end - start, entry, page
- /* , isswap */);
+ do {
+ unswap_pgd(vma, pgdir, start, end - start, entry, page);
start = (start + PGDIR_SIZE) & PGDIR_MASK;
pgdir++;
- }
+ } while (start < end);
}
-static void unswap_process(struct mm_struct * mm, unsigned long entry,
- unsigned long page /* , int isswap */)
+static void unswap_process(struct mm_struct * mm, swp_entry_t entry,
+ struct page *page)
{
struct vm_area_struct* vma;
@@ -806,110 +725,18 @@ static void unswap_process(struct mm_struct * mm, unsigned long entry,
return;
for (vma = mm->mmap; vma; vma = vma->vm_next) {
pgd_t * pgd = pgd_offset(mm, vma->vm_start);
- unswap_vma(vma, pgd, entry, page /* , isswap */);
+ unswap_vma(vma, pgd, entry, page);
}
}
-#if 0
-static int unswap_by_move(unsigned short *map, unsigned long max,
- unsigned long start, unsigned long n_pages)
-{
- struct task_struct *p;
- unsigned long entry, rover = (start == 1) ? n_pages+1 : 1;
- unsigned long i, j;
-
- DPRINTK( "unswapping %lu..%lu by moving in swap\n",
- start, start+n_pages-1 );
-
- /* can free the allocated pages by moving them to other swap pages */
- for( i = start; i < start+n_pages; ++i ) {
- if (!map[i]) {
- map[i] = SWAP_MAP_BAD;
- DPRINTK( "unswap: page %lu was free\n", i );
- continue;
- }
- else if (map[i] == SWAP_MAP_BAD) {
- printk( KERN_ERR "get_stram_region: page %lu already "
- "reserved??\n", i );
- }
- DPRINTK( "unswap: page %lu is alloced, count=%u\n", i, map[i] );
-
- /* find a free page not in our region */
- for( j = rover; j != rover-1; j = (j == max-1) ? 1 : j+1 ) {
- if (j >= start && j < start+n_pages)
- continue;
- if (!map[j]) {
- rover = j+1;
- break;
- }
- }
- if (j == rover-1) {
- printk( KERN_ERR "get_stram_region: not enough free swap "
- "pages now??\n" );
- return( -ENOMEM );
- }
- DPRINTK( "unswap: map[i=%lu]=%u map[j=%lu]=%u nr_swap=%u\n",
- i, map[i], j, map[j], nr_swap_pages );
-
- --nr_swap_pages;
- entry = SWP_ENTRY( stram_swap_type, j );
- if (stram_swap_info->lowest_bit == j)
- stram_swap_info->lowest_bit++;
- if (stram_swap_info->highest_bit == j)
- stram_swap_info->highest_bit--;
-
- memcpy( SWAP_ADDR(j), SWAP_ADDR(i), PAGE_SIZE );
-#ifdef DO_PROC
- stat_swap_move++;
-#endif
-
- while( map[i] ) {
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (unswap_process( p->mm, SWP_ENTRY( stram_swap_type, i ),
- entry, 1 )) {
- read_unlock(&tasklist_lock);
- map[j]++;
- goto repeat;
- }
- }
- read_unlock(&tasklist_lock);
- if (map[i] && map[i] != SWAP_MAP_MAX) {
- printk( KERN_ERR "get_stram_region: ST-RAM swap page %lu "
- "not used by any process\n", i );
- /* quit while loop and overwrite bad map entry */
- break;
- }
- else if (!map[i]) {
- /* somebody else must have swapped in that page, so free the
- * new one (we're moving to) */
- DPRINTK( "unswap: map[i] became 0, also clearing map[j]\n" );
- map[j] = 0;
- }
- repeat:
- }
-
- DPRINTK( "unswap: map[i=%lu]=%u map[j=%lu]=%u nr_swap=%u\n",
- i, map[i], j, map[j], nr_swap_pages );
- map[i] = SWAP_MAP_BAD;
- if (stram_swap_info->lowest_bit == i)
- stram_swap_info->lowest_bit++;
- if (stram_swap_info->highest_bit == i)
- stram_swap_info->highest_bit--;
- --nr_swap_pages;
- }
- return( 0 );
-}
-#endif
-
static int unswap_by_read(unsigned short *map, unsigned long max,
unsigned long start, unsigned long n_pages)
{
struct task_struct *p;
- unsigned long entry, page;
+ struct page *page;
+ swp_entry_t entry;
unsigned long i;
- struct page *page_map;
DPRINTK( "unswapping %lu..%lu by reading in\n",
start, start+n_pages-1 );
@@ -932,28 +759,24 @@ static int unswap_by_read(unsigned short *map, unsigned long max,
/* Get a page for the entry, using the existing
swap cache page if there is one. Otherwise,
get a clean page and read the swap into it. */
- page_map = read_swap_cache(entry);
- if (page_map) {
- page = (unsigned long) page_address(page_map);
- read_lock(&tasklist_lock);
- for_each_task(p)
- unswap_process(p->mm, entry, page
- /* , 0 */);
- read_unlock(&tasklist_lock);
- shm_unuse(entry, page);
- /* Now get rid of the extra reference to
- the temporary page we've been using. */
- if (PageSwapCache(page_map))
- delete_from_swap_cache(page_map);
- __free_page(page_map);
- #ifdef DO_PROC
- stat_swap_force++;
- #endif
- }
- else {
+ page = read_swap_cache(entry);
+ if (!page) {
swap_free(entry);
return -ENOMEM;
}
+ read_lock(&tasklist_lock);
+ for_each_task(p)
+ unswap_process(p->mm, entry, page);
+ read_unlock(&tasklist_lock);
+ shm_unuse(entry, page);
+ /* Now get rid of the extra reference to the
+ temporary page we've been using. */
+ if (PageSwapCache(page))
+ delete_from_swap_cache(page);
+ __free_page(page);
+ #ifdef DO_PROC
+ stat_swap_force++;
+ #endif
}
DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n",
@@ -998,14 +821,7 @@ static void *get_stram_region( unsigned long n_pages )
DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n",
start, region_free );
-#if 0
- err = ((total_free-region_free >= n_pages-region_free) ?
- unswap_by_move( map, max, start, n_pages ) :
- unswap_by_read( map, max, start, n_pages ));
-#else
err = unswap_by_read(map, max, start, n_pages);
-#endif
-
if (err)
goto end;
@@ -1062,7 +878,7 @@ static void free_stram_region( unsigned long offset, unsigned long n_pages )
/* is addr in some of the allocated regions? */
-static int in_some_region( unsigned long addr )
+static int in_some_region(void *addr)
{
BLOCK *p;
@@ -1164,17 +980,13 @@ static int stram_sizes[14] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static int refcnt = 0;
-static void do_stram_request( void )
+static void do_stram_request(request_queue_t *q)
{
- unsigned long start, len;
-
- while( !QUEUE_EMPTY ) {
- if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
- panic("stram: request list destroyed");
- if (CURRENT->bh) {
- if (!buffer_locked(CURRENT->bh))
- panic("stram: block not locked");
- }
+ void *start;
+ unsigned long len;
+
+ while (1) {
+ INIT_REQUEST;
start = swap_start + (CURRENT->sector << 9);
len = CURRENT->current_nr_sectors << 9;
@@ -1188,13 +1000,13 @@ static void do_stram_request( void )
}
if (CURRENT->cmd == READ) {
- memcpy( CURRENT->buffer, (char *)start, len );
+ memcpy(CURRENT->buffer, start, len);
#ifdef DO_PROC
stat_swap_read += N_PAGES(len);
#endif
}
else {
- memcpy( (char *)start, CURRENT->buffer, len );
+ memcpy(start, CURRENT->buffer, len);
#ifdef DO_PROC
stat_swap_write += N_PAGES(len);
#endif
@@ -1251,19 +1063,15 @@ int __init stram_device_init(void)
return( -ENXIO );
}
- blk_dev[STRAM_MAJOR].request_fn = do_stram_request;
+ blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request);
blksize_size[STRAM_MAJOR] = stram_blocksizes;
stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024;
blk_size[STRAM_MAJOR] = stram_sizes;
register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops,
(swap_end-swap_start)>>9);
- do_z2_request(); /* to avoid warning */
return( 0 );
}
-/* to avoid warning */
-static void do_z2_request( void ) { }
-
#endif /* CONFIG_STRAM_SWAP */
@@ -1271,30 +1079,10 @@ static void do_z2_request( void ) { }
/* Misc Utility Functions */
/* ------------------------------------------------------------------------ */
-
-/* return log2 of #pages for size */
-static int get_gfp_order( unsigned long size )
+/* reserve a range of pages */
+static void reserve_region(void *start, void *end)
{
- int order;
-
- size = N_PAGES( size + PAGE_SIZE -1 );
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
-
- return( order );
-}
-
-
-/* reserve a range of pages in mem_map[] */
-static void reserve_region( unsigned long addr, unsigned long end )
-{
- mem_map_t *mapp = virt_to_page(addr);
-
- for( ; addr < end; addr += PAGE_SIZE, ++mapp )
- set_bit( PG_reserved, &mapp->flags );
+ reserve_bootmem (virt_to_phys(start), end - start);
}
@@ -1328,11 +1116,11 @@ static BLOCK *add_region( void *addr, unsigned long size )
printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" );
return( NULL );
}
- n->start = (unsigned long)addr;
+ n->start = addr;
n->size = size;
for( p = &alloc_list; *p; p = &((*p)->next) )
- if ((*p)->start > (unsigned long)addr) break;
+ if ((*p)->start > addr) break;
n->next = *p;
*p = n;
@@ -1346,9 +1134,9 @@ static BLOCK *find_region( void *addr )
BLOCK *p;
for( p = alloc_list; p; p = p->next ) {
- if (p->start == (unsigned long)addr)
+ if (p->start == addr)
return( p );
- if (p->start > (unsigned long)addr)
+ if (p->start > addr)
break;
}
return( NULL );
@@ -1405,14 +1193,13 @@ int get_stram_list( char *buf )
++used;
}
PRINT_PROC(
- "Total ST-RAM: %8lu kB\n"
+ "Total ST-RAM: %8u kB\n"
"Total ST-RAM swap: %8lu kB\n"
"Free swap: %8u kB\n"
"Used swap: %8u kB\n"
"Allocated swap: %8u kB\n"
"Swap Reads: %8u\n"
"Swap Writes: %8u\n"
- "Swap Moves: %8u\n"
"Swap Forced Reads: %8u\n",
(stram_end - stram_start) >> 10,
(max-1) << (PAGE_SHIFT-10),
@@ -1421,17 +1208,13 @@ int get_stram_list( char *buf )
rsvd << (PAGE_SHIFT-10),
stat_swap_read,
stat_swap_write,
- stat_swap_move,
stat_swap_force );
}
else {
#endif
PRINT_PROC( "ST-RAM swapping disabled\n" );
- PRINT_PROC(
- "Total ST-RAM: %8lu kB\n"
- "Reserved ST-RAM: %8lu kB\n",
- (stram_end - stram_start) >> 10,
- (rsvd_stram_end - rsvd_stram_beg) >> 10 );
+ PRINT_PROC("Total ST-RAM: %8u kB\n",
+ (stram_end - stram_start) >> 10);
#ifdef CONFIG_STRAM_SWAP
}
#endif
@@ -1441,12 +1224,10 @@ int get_stram_list( char *buf )
if (len + 50 >= PAGE_SIZE)
break;
PRINT_PROC("0x%08lx-0x%08lx: %s (",
- virt_to_phys((void *)p->start),
- virt_to_phys((void *)p->start+p->size-1),
+ virt_to_phys(p->start),
+ virt_to_phys(p->start+p->size-1),
p->owner);
- if (p->flags & BLOCK_STATIC)
- PRINT_PROC( "static)\n" );
- else if (p->flags & BLOCK_GFP)
+ if (p->flags & BLOCK_GFP)
PRINT_PROC( "page-alloced)\n" );
else if (p->flags & BLOCK_INSWAP)
PRINT_PROC( "in swap)\n" );
diff --git a/arch/m68k/fpsp040/bindec.S b/arch/m68k/fpsp040/bindec.S
index ef3a627bf..9fb65e320 100644
--- a/arch/m68k/fpsp040/bindec.S
+++ b/arch/m68k/fpsp040/bindec.S
@@ -484,7 +484,7 @@ A9_str:
fmovex (%a0),%fp0 |load X from memory
fabsx %fp0 |use abs(X)
tstw %d5 |LAMBDA is in lower word of d5
- bnes sc_mul |if neg (LAMBDA = 1), scale by mul
+ bne sc_mul |if neg (LAMBDA = 1), scale by mul
fdivx %fp1,%fp0 |calculate X / SCALE -> Y to fp0
bras A10_st |branch to A10
diff --git a/arch/m68k/fpsp040/decbin.S b/arch/m68k/fpsp040/decbin.S
index af1279a4a..d2bf1b641 100644
--- a/arch/m68k/fpsp040/decbin.S
+++ b/arch/m68k/fpsp040/decbin.S
@@ -230,7 +230,7 @@ nextlw:
|
m_sign:
btst #31,(%a0) |test sign of the mantissa
- beqs ap_st_z |if clear, go to append/strip zeros
+ beq ap_st_z |if clear, go to append/strip zeros
fnegx %fp0 |if set, negate fp0
|
@@ -288,7 +288,7 @@ ap_st_z:
cmpl #27,%d1 |test is with 27
ble pwrten |if abs(expA) <28, skip ap/st zeros
btst #30,(%a0) |check sign of exp
- bnes ap_st_n |if neg, go to neg side
+ bne ap_st_n |if neg, go to neg side
clrl %d1 |zero count reg
movel (%a0),%d4 |load lword 1 to d4
bfextu %d4{#28:#4},%d0 |get M16 in d0
@@ -336,7 +336,7 @@ ap_p_en:
tstl %d0 |check if d0 is zero
bnes ap_p_el |if not, get next bit
fmulx %fp1,%fp0 |mul mantissa by 10**(no_bits_shifted)
- bras pwrten |go calc pwrten
+ bra pwrten |go calc pwrten
|
| This section handles a negative adjusted exponent.
|
diff --git a/arch/m68k/fpsp040/do_func.S b/arch/m68k/fpsp040/do_func.S
index 2df0c3700..0a9c776f0 100644
--- a/arch/m68k/fpsp040/do_func.S
+++ b/arch/m68k/fpsp040/do_func.S
@@ -77,7 +77,7 @@ not_fmovecr:
movew CMDREG1B(%a6),%d0
andl #0x7F,%d0
cmpil #0x38,%d0 |if the extension is >= $38,
- bges serror |it is illegal
+ bge serror |it is illegal
bfextu STAG(%a6){#0:#3},%d1
lsll #3,%d0 |make room for STAG
addl %d1,%d0 |combine for final index into table
diff --git a/arch/m68k/fpsp040/get_op.S b/arch/m68k/fpsp040/get_op.S
index 2bd236d45..480405d4f 100644
--- a/arch/m68k/fpsp040/get_op.S
+++ b/arch/m68k/fpsp040/get_op.S
@@ -171,7 +171,7 @@ PTENRP:
get_op:
clrb DY_MO_FLG(%a6)
tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
- beqs uni_getop
+ beq uni_getop
uns_getop:
btstb #direction_bit,CMDREG1B(%a6)
diff --git a/arch/m68k/fpsp040/util.S b/arch/m68k/fpsp040/util.S
index e59b352ab..cc9ae013b 100644
--- a/arch/m68k/fpsp040/util.S
+++ b/arch/m68k/fpsp040/util.S
@@ -138,20 +138,20 @@ ovf_e1_exc:
|
ovf_fsgl:
clrl %d0
- bras ovf_res
+ bra ovf_res
ovff_sgl:
movel #0x00000001,%d0 |set single
- bras ovf_res
+ bra ovf_res
ovff_dbl:
movel #0x00000002,%d0 |set double
- bras ovf_res
+ bra ovf_res
|
| The precision is in the fpcr.
|
ovf_fpcr:
bfextu FPCR_MODE(%a6){#0:#2},%d0 |set round precision
- bras ovf_res
+ bra ovf_res
|
|
diff --git a/arch/m68k/fpsp040/x_store.S b/arch/m68k/fpsp040/x_store.S
index a3468f338..b3357fd65 100644
--- a/arch/m68k/fpsp040/x_store.S
+++ b/arch/m68k/fpsp040/x_store.S
@@ -92,7 +92,7 @@ opc011:
cmpil #0,%d0 |if dest format is extended
beq dest_ext |then branch
cmpil #1,%d0 |if dest format is single
- beqs dest_sgl |then branch
+ beq dest_sgl |then branch
|
| fall through to dest_dbl
|
diff --git a/arch/m68k/ifpsp060/os.S b/arch/m68k/ifpsp060/os.S
index 4bbf86f96..037aa6c00 100644
--- a/arch/m68k/ifpsp060/os.S
+++ b/arch/m68k/ifpsp060/os.S
@@ -85,21 +85,20 @@
|
.global _060_dmem_write
_060_dmem_write:
+ subq.l #1,%d0
btst #0x5,0x4(%a6) | check for supervisor state
beqs user_write
super_write:
move.b (%a0)+,(%a1)+ | copy 1 byte
- subq.l #0x1,%d0 | decr byte counter
- bnes super_write | quit if ctr = 0
+ dbra %d0,super_write | quit if --ctr < 0
clr.l %d1 | return success
rts
user_write:
- move.l %d0,-(%sp) | pass: counter
- move.l %a1,-(%sp) | pass: user dst
- move.l %a0,-(%sp) | pass: supervisor src
- bsr.l _copyout | write byte to user mem
- move.l %d0,%d1 | return success
- add.l #0xc, %sp | clear 3 lw params
+ move.b (%a0)+,%d1 | copy 1 byte
+copyoutae:
+ movs.b %d1,(%a1)+
+ dbra %d0,user_write | quit if --ctr < 0
+ clr.l %d1 | return success
rts
|
@@ -119,21 +118,20 @@ user_write:
.global _060_dmem_read
_060_imem_read:
_060_dmem_read:
+ subq.l #1,%d0
btst #0x5,0x4(%a6) | check for supervisor state
beqs user_read
super_read:
move.b (%a0)+,(%a1)+ | copy 1 byte
- subq.l #0x1,%d0 | decr byte counter
- bnes super_read | quit if ctr = 0
+ dbra %d0,super_read | quit if --ctr < 0
clr.l %d1 | return success
rts
user_read:
- move.l %d0,-(%sp) | pass: counter
- move.l %a1,-(%sp) | pass: super dst
- move.l %a0,-(%sp) | pass: user src
- bsr.l _copyin | read byte from user mem
- move.l %d0,%d1 | return success
- add.l #0xc,%sp | clear 3 lw params
+copyinae:
+ movs.b (%a0)+,%d1
+ move.b %d1,(%a1)+ | copy 1 byte
+ dbra %d0,user_read | quit if --ctr < 0
+ clr.l %d1 | return success
rts
|
@@ -150,14 +148,13 @@ user_read:
|
.global _060_dmem_read_byte
_060_dmem_read_byte:
+ clr.l %d0 | clear whole longword
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrbs | supervisor
-dmrbu: clr.l %d0 | clear whole longword
dmrbuae:movs.b (%a0),%d0 | fetch user byte
- bras dmrbr
-dmrbs: clr.l %d0 | clear whole longword
- move.b (%a0),%d0 | fetch super byte
-dmrbr: clr.l %d1 | return success
+ rts
+dmrbs: move.b (%a0),%d0 | fetch super byte
rts
|
@@ -187,14 +184,13 @@ dmrbr: clr.l %d1 | return success
.global _060_imem_read_word
_060_dmem_read_word:
_060_imem_read_word:
+ clr.l %d1 | assume success
+ clr.l %d0 | clear whole longword
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrws | supervisor
-dmrwu: clr.l %d0 | clear whole longword
dmrwuae:movs.w (%a0), %d0 | fetch user word
- bras dmrwr
-dmrws: clr.l %d0 | clear whole longword
- move.w (%a0), %d0 | fetch super word
-dmrwr: clr.l %d1 | return success
+ rts
+dmrws: move.w (%a0), %d0 | fetch super word
rts
|
@@ -224,13 +220,12 @@ dmrwr: clr.l %d1 | return success
.global _060_imem_read_long
_060_dmem_read_long:
_060_imem_read_long:
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmrls | supervisor
-dmrlu:
dmrluae:movs.l (%a0),%d0 | fetch user longword
- bras dmrlr
+ rts
dmrls: move.l (%a0),%d0 | fetch super longword
-dmrlr: clr.l %d1 | return success
rts
|
@@ -247,13 +242,12 @@ dmrlr: clr.l %d1 | return success
|
.global _060_dmem_write_byte
_060_dmem_write_byte:
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwbs | supervisor
-dmwbu:
dmwbuae:movs.b %d0,(%a0) | store user byte
- bras dmwbr
+ rts
dmwbs: move.b %d0,(%a0) | store super byte
-dmwbr: clr.l %d1 | return success
rts
|
@@ -270,6 +264,7 @@ dmwbr: clr.l %d1 | return success
|
.global _060_dmem_write_word
_060_dmem_write_word:
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwws | supervisor
dmwwu:
@@ -293,16 +288,16 @@ dmwwr: clr.l %d1 | return success
|
.global _060_dmem_write_long
_060_dmem_write_long:
+ clr.l %d1 | assume success
btst #0x5,0x4(%a6) | check for supervisor state
bnes dmwls | supervisor
-dmwlu:
dmwluae:movs.l %d0,(%a0) | store user longword
- bra dmwlr
+ rts
dmwls: move.l %d0,(%a0) | store super longword
-dmwlr: clr.l %d1 | return success
rts
+#if 0
|###############################################
|
@@ -323,7 +318,7 @@ _copyout:
move.l 4(%sp),%a0 | source
move.l 8(%sp),%a1 | destination
move.l 12(%sp),%d0 | count
- subq.l #1,%d0
+ subq.l #1,%d0
moreout:
move.b (%a0)+,%d1 | fetch supervisor byte
copyoutae:
@@ -348,6 +343,7 @@ copyinae:
dbra %d0,morein | are we through yet?
moveq #0,%d0 | return success
rts
+#endif
|###########################################################################
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 165809c56..3e62e6fe1 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -28,6 +28,9 @@
* 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
* all pointers that used to be 'current' are now entry
* number 0 in the 'current_set' list.
+ *
+ * 6/05/00 RZ: addedd writeback completion after return from sighandler
+ * for 68040
*/
#include <linux/sys.h>
@@ -104,8 +107,18 @@ do_trace:
jbsr SYMBOL_NAME(syscall_trace)
SYMBOL_NAME_LABEL(ret_from_signal)
- RESTORE_SWITCH_STACK
+ RESTORE_SWITCH_STACK
addql #4,%sp
+/* on 68040 complete pending writebacks if any */
+#ifdef CONFIG_M68040
+ bfextu %sp@(PT_VECTOR){#0,#4},%d0
+ subql #7,%d0 | bus error frame ?
+ jbne 1f
+ movel %sp,%sp@-
+ jbsr SYMBOL_NAME(berr_040cleanup)
+ addql #4,%sp
+1:
+#endif
jra SYMBOL_NAME(ret_from_exception)
ENTRY(system_call)
@@ -115,7 +128,7 @@ ENTRY(system_call)
| save top of frame
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
- btst #PF_TRACESYS_BIT,%curptr@(TASK_FLAGS+PF_TRACESYS_OFF)
+ btst #PT_TRACESYS_BIT,%curptr@(TASK_PTRACE+PT_TRACESYS_OFF)
jne do_trace
cmpl #NR_syscalls,%d0
jcc badsys
@@ -136,7 +149,7 @@ SYMBOL_NAME_LABEL(ret_from_exception)
jeq 2f
#endif
| check for delayed trace
- bclr #PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF)
+ bclr #PT_DTRACE_BIT,%curptr@(TASK_PTRACE+PT_DTRACE_OFF)
jne do_delayed_trace
5:
tstl %curptr@(TASK_STATE) | state
@@ -578,7 +591,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_mremap)
.long SYMBOL_NAME(sys_setresuid16)
.long SYMBOL_NAME(sys_getresuid16) /* 165 */
- .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */
+ .long SYMBOL_NAME(sys_getpagesize)
.long SYMBOL_NAME(sys_query_module)
.long SYMBOL_NAME(sys_poll)
.long SYMBOL_NAME(sys_nfsservctl)
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 74e1e4c1e..805ce9b83 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -71,6 +71,8 @@ int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
unsigned long, const char *, void *) = dummy_request_irq;
void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
+void init_irq_proc(void);
+
/*
* void init_IRQ(void)
*
@@ -257,3 +259,9 @@ int get_irq_list(char *buf)
len += mach_get_irq_list(buf+len);
return len;
}
+
+void init_irq_proc(void)
+{
+ /* Insert /proc/irq driver here */
+}
+
diff --git a/arch/m68k/kernel/m68k_defs.c b/arch/m68k/kernel/m68k_defs.c
index 47cffcfa9..817583a7d 100644
--- a/arch/m68k/kernel/m68k_defs.c
+++ b/arch/m68k/kernel/m68k_defs.c
@@ -24,6 +24,7 @@ int main(void)
/* offsets into the task struct */
DEFINE(TASK_STATE, offsetof(struct task_struct, state));
DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, sigpending));
DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, need_resched));
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 7bf46149f..35d194623 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -21,6 +21,7 @@
asmlinkage long long __ashrdi3 (long long, int);
asmlinkage long long __lshrdi3 (long long, int);
+asmlinkage long long __muldi3 (long long, long long);
extern char m68k_debug_device[];
extern void dump_thread(struct pt_regs *, struct user *);
@@ -72,6 +73,7 @@ EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memcmp);
EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL_NOVERS(__muldi3);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 0dd5870f2..6b1f5f386 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -97,10 +97,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
- if (current->flags & PF_PTRACED)
+ if (current->ptrace & PT_PTRACED)
goto out;
/* set the ptrace bit in the process flags. */
- current->flags |= PF_PTRACED;
+ current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
@@ -126,9 +126,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED)
+ if (child->ptrace & PT_PTRACED)
goto out;
- child->flags |= PF_PTRACED;
+ child->ptrace |= PT_PTRACED;
write_lock_irqsave(&tasklist_lock, flags);
if (child->p_pptr != current) {
@@ -143,7 +143,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
}
ret = -ESRCH;
- if (!(child->flags & PF_PTRACED))
+ if (!(child->ptrace & PT_PTRACED))
goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
@@ -250,9 +250,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if ((unsigned long) data > _NSIG)
goto out;
if (request == PTRACE_SYSCALL)
- child->flags |= PF_TRACESYS;
+ child->ptrace |= PT_TRACESYS;
else
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
child->exit_code = data;
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
@@ -287,7 +287,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
goto out;
- child->flags &= ~PF_TRACESYS;
+ child->ptrace &= ~PT_TRACESYS;
tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
@@ -304,7 +304,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
if ((unsigned long) data > _NSIG)
goto out;
- child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
child->exit_code = data;
write_lock_irqsave(&tasklist_lock, flags);
REMOVE_LINKS(child);
@@ -384,8 +384,8 @@ out:
asmlinkage void syscall_trace(void)
{
lock_kernel();
- if ((current->flags & (PF_PTRACED|PF_TRACESYS))
- != (PF_PTRACED|PF_TRACESYS))
+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+ != (PT_PTRACED|PT_TRACESYS))
goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index a2e3f47f1..040f96d97 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -73,6 +73,8 @@ void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initd
int (*mach_keyb_init) (void) __initdata = NULL;
int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
void (*mach_kbd_leds) (unsigned int) = NULL;
+int (*mach_kbd_translate)(unsigned char scancode, unsigned char *keycode, char raw_mode) = NULL;
+unsigned int SYSRQ_KEY;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void) __initdata = NULL;
void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index fa13dc390..9d754f9b8 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -1043,7 +1043,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!signr)
break;
- if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
regs->sr &= ~PS_T;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 86637d4d6..f7386cbc6 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -24,6 +24,7 @@
#include <asm/cachectl.h>
#include <asm/traps.h>
#include <asm/ipc.h>
+#include <asm/page.h>
/*
* sys_pipe() is the normal C calling standard for creating
@@ -661,6 +662,11 @@ out:
return ret;
}
+asmlinkage int sys_getpagesize(void)
+{
+ return PAGE_SIZE;
+}
+
/*
* Old cruft
*/
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 5fd9dc0a7..d5d6753cb 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -5,6 +5,7 @@
*
* 68040 fixes by Michael Rausch
* 68040 fixes by Martin Apel
+ * 68040 fixes and writeback by Richard Zidlicky
* 68060 fixes by Roman Hodek
* 68060 fixes by Jesper Skov
*
@@ -34,7 +35,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/traps.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/machdep.h>
#include <asm/siginfo.h>
@@ -195,6 +196,7 @@ static char *space_names[] = {
void die_if_kernel(char *,struct pt_regs *,int);
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
+int send_fault_sig(struct pt_regs *regs);
asmlinkage void trap_c(struct frame *fp);
@@ -214,26 +216,33 @@ static inline void access_error060 (struct frame *fp)
"movec %/d0,%/cacr"
: : : "d0" );
/* return if there's no other error */
- if ((!(fslw & MMU060_ERR_BITS)) && !(fslw & MMU060_SEE))
+ if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
return;
}
if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
unsigned long errorcode;
unsigned long addr = fp->un.fmt4.effaddr;
- errorcode = ((fslw & MMU060_WP) ? 1 : 0) |
- ((fslw & MMU060_W) ? 2 : 0);
+
+ if (fslw & MMU060_MA)
+ addr = (addr + 7) & -8;
+
+ errorcode = 1;
+ if (fslw & MMU060_DESC_ERR) {
+ __flush_tlb040_one(addr);
+ errorcode = 0;
+ }
+ if (fslw & MMU060_W)
+ errorcode |= 2;
#ifdef DEBUG
printk("errorcode = %d\n", errorcode );
#endif
- if (fslw & MMU060_MA)
- addr = PAGE_ALIGN(addr);
do_page_fault(&fp->ptregs, addr, errorcode);
} else if (fslw & (MMU060_SEE)){
- /* Software Emulation Error. Probably an instruction
- * using an unsupported addressing mode
+ /* Software Emulation Error.
+ * fault during mem_read/mem_write in ifpsp060/os.S
*/
- send_sig (SIGSEGV, current, 1);
+ send_fault_sig(&fp->ptregs);
} else {
printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
printk( "68060 access error, fslw=%lx\n", fslw );
@@ -243,74 +252,113 @@ static inline void access_error060 (struct frame *fp)
#endif /* CONFIG_M68060 */
#if defined (CONFIG_M68040)
-static inline unsigned long probe040 (int iswrite, int fc, unsigned long addr)
+static inline unsigned long probe040(int iswrite, unsigned long addr)
{
unsigned long mmusr;
- mm_segment_t fs = get_fs();
- set_fs (MAKE_MM_SEG(fc));
+ asm volatile (".chip 68040");
if (iswrite)
- /* write */
- asm volatile (".chip 68040\n\t"
- "ptestw (%1)\n\t"
- "movec %%mmusr,%0\n\t"
- ".chip 68k"
- : "=r" (mmusr)
- : "a" (addr));
+ asm volatile ("ptestw (%0)" : : "a" (addr));
else
- asm volatile (".chip 68040\n\t"
- "ptestr (%1)\n\t"
- "movec %%mmusr,%0\n\t"
- ".chip 68k"
- : "=r" (mmusr)
- : "a" (addr));
+ asm volatile ("ptestr (%0)" : : "a" (addr));
+
+ asm volatile ("movec %%mmusr,%0" : "=r" (mmusr));
- set_fs (fs);
+ asm volatile (".chip 68k");
return mmusr;
}
-static inline void do_040writeback (unsigned short ssw,
- unsigned short wbs,
- unsigned long wba,
- unsigned long wbd,
- struct frame *fp)
+static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
+ unsigned long wbd)
{
- mm_segment_t fs = get_fs ();
- unsigned long mmusr;
- unsigned long errorcode;
+ int res = 0;
- /*
- * No special handling for the second writeback anymore.
- * It misinterpreted the misaligned status sometimes.
- * This way an extra page-fault may be caused (Martin Apel).
- */
-
- mmusr = probe040 (1, wbs & WBTM_040, wba);
- errorcode = (mmusr & MMU_R_040) ? 3 : 2;
- if (do_page_fault (&fp->ptregs, wba, errorcode))
- /* just return if we can't perform the writeback */
- return;
+ set_fs(MAKE_MM_SEG(wbs));
- set_fs (MAKE_MM_SEG(wbs & WBTM_040));
switch (wbs & WBSIZ_040) {
- case BA_SIZE_BYTE:
- put_user (wbd & 0xff, (char *)wba);
+ case BA_SIZE_BYTE:
+ res = put_user(wbd & 0xff, (char *)wba);
break;
- case BA_SIZE_WORD:
- put_user (wbd & 0xffff, (short *)wba);
+ case BA_SIZE_WORD:
+ res = put_user(wbd & 0xffff, (short *)wba);
break;
- case BA_SIZE_LONG:
- put_user (wbd, (int *)wba);
+ case BA_SIZE_LONG:
+ res = put_user(wbd, (int *)wba);
break;
}
- set_fs (fs);
+
+#ifdef DEBUG
+ printk("do_040writeback1, res=%d\n",res);
+#endif
+
+ return res;
+}
+
+/* after an exception in a writeback the stack frame coresponding
+ * to that exception is discarded, set a few bits in the old frame
+ * to simulate what it should look like
+ */
+static inline void fix_xframe040(struct frame *fp, unsigned short wbs)
+{
+ fp->un.fmt7.faddr = current->thread.faddr;
+ fp->un.fmt7.ssw = wbs & 0xff;
+}
+
+static inline void do_040writebacks(struct frame *fp)
+{
+ int res = 0;
+#if 0
+ if (fp->un.fmt7.wb1s & WBV_040)
+ printk("access_error040: cannot handle 1st writeback. oops.\n");
+#endif
+
+ if ((fp->un.fmt7.wb2s & WBV_040) &&
+ !(fp->un.fmt7.wb2s & WBTT_040)) {
+ res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
+ fp->un.fmt7.wb2d);
+ if (res)
+ fix_xframe040(fp, fp->un.fmt7.wb2s);
+ else
+ fp->un.fmt7.wb2s = 0;
+ }
+
+ /* do the 2nd wb only if the first one was succesful (except for a kernel wb) */
+ if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
+ res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
+ fp->un.fmt7.wb3d);
+ if (res)
+ fix_xframe040(fp, fp->un.fmt7.wb3s);
+ else
+ fp->un.fmt7.wb3s = 0;
+ }
+
+ if (res)
+ send_fault_sig(&fp->ptregs);
+}
+
+/*
+ * called from sigreturn(), must ensure userspace code didn't
+ * manipulate exception frame to circumvent protection, then complete
+ * pending writebacks
+ * we just clear TM2 to turn it into an userspace access
+ */
+asmlinkage void berr_040cleanup(struct frame *fp)
+{
+ mm_segment_t old_fs = get_fs();
+
+ fp->un.fmt7.wb2s &= ~4;
+ fp->un.fmt7.wb3s &= ~4;
+
+ do_040writebacks(fp);
+ set_fs(old_fs);
}
-static inline void access_error040 (struct frame *fp)
+static inline void access_error040(struct frame *fp)
{
unsigned short ssw = fp->un.fmt7.ssw;
+ mm_segment_t old_fs = get_fs();
unsigned long mmusr;
#ifdef DEBUG
@@ -322,7 +370,6 @@ static inline void access_error040 (struct frame *fp)
fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
#endif
-
if (ssw & ATC_040) {
unsigned long addr = fp->un.fmt7.faddr;
unsigned long errorcode;
@@ -332,56 +379,50 @@ static inline void access_error040 (struct frame *fp)
* has been corrected if there was a misaligned access (MA).
*/
if (ssw & MA_040)
- addr = PAGE_ALIGN (addr);
+ addr = (addr + 7) & -8;
+ set_fs(MAKE_MM_SEG(ssw));
/* MMU error, get the MMUSR info for this access */
- mmusr = probe040 (!(ssw & RW_040), ssw & TM_040, addr);
+ mmusr = probe040(!(ssw & RW_040), addr);
#ifdef DEBUG
printk("mmusr = %lx\n", mmusr);
#endif
- errorcode = ((mmusr & MMU_R_040) ? 1 : 0) |
- ((ssw & RW_040) ? 0 : 2);
-#ifdef CONFIG_FTRACE
- {
- unsigned long flags;
-
- save_flags(flags);
- cli();
- do_ftrace(0xfa000000 | errorcode);
- do_ftrace(mmusr);
- restore_flags(flags);
+ errorcode = 1;
+ if (!(mmusr & MMU_R_040)) {
+ /* clear the invalid atc entry */
+ __flush_tlb040_one(addr);
+ errorcode = 0;
}
+ if (!(ssw & RW_040))
+ errorcode |= 2;
+ if (do_page_fault(&fp->ptregs, addr, errorcode)) {
+#ifdef DEBUG
+ printk("do_page_fault() !=0 \n");
#endif
- do_page_fault (&fp->ptregs, addr, errorcode);
+ if (user_mode(&fp->ptregs)){
+ /* delay writebacks after signal delivery */
+#ifdef DEBUG
+ printk(".. was usermode - return\n");
+#endif
+ return;
+ }
+ /* disable writeback into user space from kernel
+ * (if do_page_fault didn't fix the mapping,
+ * the writeback won't do good)
+ */
+#ifdef DEBUG
+ printk(".. disabling wb2\n");
+#endif
+ if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
+ fp->un.fmt7.wb2s &= ~WBV_040;
+ }
} else {
- printk ("68040 access error, ssw=%x\n", ssw);
- trap_c (fp);
+ printk("68040 access error, ssw=%x\n", ssw);
+ trap_c(fp);
}
-#if 0
- if (fp->un.fmt7.wb1s & WBV_040)
- printk("access_error040: cannot handle 1st writeback. oops.\n");
-#endif
-
-/*
- * We may have to do a couple of writebacks here.
- *
- * MR: we can speed up the thing a little bit and let do_040writeback()
- * not produce another page fault as wb2 corresponds to the address that
- * caused the fault. on write faults no second fault is generated, but
- * on read faults for security reasons (although per definitionem impossible)
- */
-
- if (fp->un.fmt7.wb2s & WBV_040 && (fp->un.fmt7.wb2s &
- WBTT_040) != BA_TT_MOVE16)
- do_040writeback (ssw,
- fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
- fp->un.fmt7.wb2d, fp);
-
- if (fp->un.fmt7.wb3s & WBV_040)
- do_040writeback (ssw, fp->un.fmt7.wb3s,
- fp->un.fmt7.wb3a, fp->un.fmt7.wb3d,
- fp);
+ do_040writebacks(fp);
+ set_fs(old_fs);
}
#endif /* CONFIG_M68040 */
@@ -470,12 +511,14 @@ extern inline void bus_error030 (struct frame *fp)
else if (buserr_type & SUN3_BUSERR_INVALID)
errorcode = 0x00;
else {
+#ifdef DEBUG
printk ("*** unexpected busfault type=%#04x\n", buserr_type);
printk ("invalid %s access at %#lx from pc %#lx\n",
!(ssw & RW) ? "write" : "read", addr,
fp->ptregs.pc);
+#endif
die_if_kernel ("Oops", &fp->ptregs, buserr_type);
- force_sig (SIGSEGV, current);
+ force_sig (SIGBUS, current);
return;
}
@@ -596,7 +639,7 @@ static inline void bus_error030 (struct frame *fp)
printk ("mmusr is %#x for addr %#lx in task %p\n",
mmusr, addr, current);
printk ("descriptor address is %#lx, contents %#lx\n",
- mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
+ __va(desc), *(unsigned long *)__va(desc));
#endif
errorcode = (mmusr & MMU_I) ? 0 : 1;
@@ -694,7 +737,7 @@ static inline void bus_error030 (struct frame *fp)
printk ("mmusr is %#x for addr %#lx in task %p\n",
mmusr, addr, current);
printk ("descriptor address is %#lx, contents %#lx\n",
- mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
+ __va(desc), *(unsigned long *)__va(desc));
#endif
if (mmusr & MMU_I)
@@ -904,7 +947,7 @@ asmlinkage void trap_c(struct frame *fp)
if (fp->ptregs.sr & PS_S) {
if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
/* traced a trapping instruction */
- current->flags |= PF_DTRACE;
+ current->ptrace |= PT_DTRACE;
} else
bad_super_trap(fp);
return;
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index b9480aeb6..a230bad9e 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -6,6 +6,6 @@
$(CC) $(AFLAGS) -traditional -c $< -o $@
L_TARGET = lib.a
-L_OBJS = ashrdi3.o lshrdi3.o checksum.o memcpy.o memcmp.o memset.o semaphore.o
+L_OBJS = ashrdi3.o lshrdi3.o checksum.o memcpy.o memcmp.o memset.o semaphore.o muldi3.o
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
new file mode 100644
index 000000000..9ea8812fc
--- /dev/null
+++ b/arch/m68k/lib/muldi3.c
@@ -0,0 +1,63 @@
+/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
+ gcc-2.7.2.3/longlong.h which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define BITS_PER_UNIT 8
+
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mulu%.l %3,%1:%0" \
+ : "=d" ((USItype)(w0)), \
+ "=d" ((USItype)(w1)) \
+ : "%0" ((USItype)(u)), \
+ "dmi" ((USItype)(v)))
+
+#define __umulsidi3(u, v) \
+ ({DIunion __w; \
+ umul_ppmm (__w.s.high, __w.s.low, u, v); \
+ __w.ll; })
+
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef int word_type __attribute__ ((mode (__word__)));
+
+struct DIstruct {SItype high, low;};
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
+DItype
+__muldi3 (DItype u, DItype v)
+{
+ DIunion w;
+ DIunion uu, vv;
+
+ uu.ll = u,
+ vv.ll = v;
+
+ w.ll = __umulsidi3 (uu.s.low, vv.s.low);
+ w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+ + (USItype) uu.s.high * (USItype) vv.s.low);
+
+ return w.ll;
+}
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
index 445a99780..9b9bab2bd 100644
--- a/arch/m68k/mac/baboon.c
+++ b/arch/m68k/mac/baboon.c
@@ -27,8 +27,6 @@ volatile struct baboon *baboon;
void baboon_irq(int, void *, struct pt_regs *);
-extern int console_loglevel;
-
extern int macide_ack_intr(ide_hwif_t *);
/*
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index a0486cf95..1a1a38e60 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -61,10 +61,6 @@ void *mac_env; /* Loaded by the boot asm */
/* The phys. video addr. - might be bogus on some machines */
unsigned long mac_orig_videoaddr;
-/* Mac specific keyboard functions */
-extern int mackbd_init_hw(void);
-extern void mackbd_leds(unsigned int leds);
-
/* Mac specific timer functions */
extern void mac_gettod (int *, int *, int *, int *, int *, int *);
extern unsigned long mac_gettimeoffset (void);
@@ -91,20 +87,21 @@ extern void nubus_sweep_video(void);
extern void mac_debug_init(void);
extern void mac_debugging_long(int, long);
-#ifdef CONFIG_MAGIC_SYSRQ
-static char mac_sysrq_xlate[128] =
- "\000sdfghzxcv\000bqwer" /* 0x00 - 0x0f */
- "yt123465=97-80)o" /* 0x10 - 0x1f */
- "u(ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
- "\t `\000\033\000\000\000\000\000\000\000\000\000\000\000" /* 0x30 - 0x3f */
- "\000.\000*\000+\000\000\000\000\000/\r\000-\000" /* 0x40 - 0x4f */
- "\000\00001234567a89\000\000\000" /* 0x50 - 0x5f */
- "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x60 - 0x6f */
- "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */
-#endif
-
extern void (*kd_mksound)(unsigned int, unsigned int);
+extern int mackbd_init_hw(void);
+extern void mackbd_leds(unsigned int leds);
+extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode);
+
+extern void mac_hid_init_hw(void);
+extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode);
+
+#ifdef CONFIG_MAGIC_SYSRQ
+extern unsigned char mac_hid_kbd_sysrq_xlate[128];
+extern unsigned char pckbd_sysrq_xlate[128];
+extern unsigned char mackbd_sysrq_xlate[128];
+#endif /* CONFIG_MAGIC_SYSRQ */
+
static void mac_get_model(char *str);
void mac_bang(int irq, void *vector, struct pt_regs *p)
@@ -118,8 +115,6 @@ static void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
via_init_clock(vector);
}
-extern int console_loglevel;
-
#if 0
void mac_waitbut (void)
{
@@ -213,76 +208,93 @@ static void mac_cache_card_flush(int writeback)
void __init config_mac(void)
{
-
- if (!MACH_IS_MAC) {
- printk("ERROR: no Mac, but config_mac() called!! \n");
- }
-
- mach_sched_init = mac_sched_init;
- mach_keyb_init = mackbd_init_hw;
- mach_kbd_leds = mackbd_leds;
- mach_init_IRQ = mac_init_IRQ;
- mach_request_irq = mac_request_irq;
- mach_free_irq = mac_free_irq;
- enable_irq = mac_enable_irq;
- disable_irq = mac_disable_irq;
- mach_get_model = mac_get_model;
- mach_default_handler = &mac_handlers;
- mach_get_irq_list = mac_get_irq_list;
- mach_gettimeoffset = mac_gettimeoffset;
- mach_gettod = mac_gettod;
- mach_hwclk = mac_hwclk;
- mach_set_clock_mmss = mac_set_clock_mmss;
+ if (!MACH_IS_MAC) {
+ printk("ERROR: no Mac, but config_mac() called!! \n");
+ }
+
+#ifdef CONFIG_VT
+#ifdef CONFIG_INPUT_ADBHID
+ mach_keyb_init = mac_hid_init_hw;
+ mach_kbd_translate = mac_hid_kbd_translate;
+#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_MAC_ADBKEYCODES
+ if (!keyboard_sends_linux_keycodes) {
+ mach_sysrq_xlate = mac_hid_kbd_sysrq_xlate;
+ SYSRQ_KEY = 0x69;
+ } else
+#endif /* CONFIG_MAC_ADBKEYCODES */
+ {
+ mach_sysrq_xlate = pckbd_sysrq_xlate;
+ SYSRQ_KEY = 0x54;
+ }
+#endif /* CONFIG_MAGIC_SYSRQ */
+#elif defined(CONFIG_ADB_KEYBOARD)
+ mach_keyb_init = mackbd_init_hw;
+ mach_kbd_leds = mackbd_leds;
+ mach_kbd_translate = mackbd_translate;
+ mach_sysrq_xlate = mackbd_sysrq_xlate;
+ SYSRQ_KEY = 0x69;
+#endif /* CONFIG_INPUT_ADBHID */
+#endif /* CONFIG_VT */
+
+ mach_sched_init = mac_sched_init;
+ mach_init_IRQ = mac_init_IRQ;
+ mach_request_irq = mac_request_irq;
+ mach_free_irq = mac_free_irq;
+ enable_irq = mac_enable_irq;
+ disable_irq = mac_disable_irq;
+ mach_get_model = mac_get_model;
+ mach_default_handler = &mac_handlers;
+ mach_get_irq_list = mac_get_irq_list;
+ mach_gettimeoffset = mac_gettimeoffset;
+ mach_gettod = mac_gettod;
+ mach_hwclk = mac_hwclk;
+ mach_set_clock_mmss = mac_set_clock_mmss;
#if 0
- mach_mksound = mac_mksound;
+ mach_mksound = mac_mksound;
#endif
- mach_reset = mac_reset;
- mach_halt = mac_poweroff;
- mach_power_off = mac_poweroff;
- conswitchp = &dummy_con;
- mach_max_dma_address = 0xffffffff;
+ mach_reset = mac_reset;
+ mach_halt = mac_poweroff;
+ mach_power_off = mac_poweroff;
+ conswitchp = &dummy_con;
+ mach_max_dma_address = 0xffffffff;
#if 0
- mach_debug_init = mac_debug_init;
-#endif
- kd_mksound = mac_mksound;
-#ifdef CONFIG_MAGIC_SYSRQ
- mach_sysrq_key = 114; /* HELP */
- mach_sysrq_shift_state = 8; /* Alt */
- mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */
- mach_sysrq_xlate = mac_sysrq_xlate;
+ mach_debug_init = mac_debug_init;
#endif
+ kd_mksound = mac_mksound;
#ifdef CONFIG_HEARTBEAT
#if 0
- mach_heartbeat = mac_heartbeat;
- mach_heartbeat_irq = IRQ_MAC_TIMER;
+ mach_heartbeat = mac_heartbeat;
+ mach_heartbeat_irq = IRQ_MAC_TIMER;
#endif
#endif
- /*
- * Determine hardware present
- */
+ /*
+ * Determine hardware present
+ */
- mac_identify();
- mac_report_hardware();
+ mac_identify();
+ mac_report_hardware();
- /* AFAIK only the IIci takes a cache card. The IIfx has onboard
- cache ... someone needs to figure out how to tell if it's on or
- not. */
- if (macintosh_config->ident == MAC_MODEL_IICI
- || macintosh_config->ident == MAC_MODEL_IIFX) {
- mach_l2_flush = mac_cache_card_flush;
- }
+ /* AFAIK only the IIci takes a cache card. The IIfx has onboard
+ cache ... someone needs to figure out how to tell if it's on or
+ not. */
+
+ if (macintosh_config->ident == MAC_MODEL_IICI
+ || macintosh_config->ident == MAC_MODEL_IIFX) {
+ mach_l2_flush = mac_cache_card_flush;
+ }
#ifdef MAC_DEBUG_SOUND
- /* goes on forever if timers broken */
- mac_mksound(1000,10);
+ /* goes on forever if timers broken */
+ mac_mksound(1000,10);
#endif
- /*
- * Check for machine specific fixups.
- */
+ /*
+ * Check for machine specific fixups.
+ */
#ifdef OLD_NUBUS_CODE
- nubus_sweep_video();
+ nubus_sweep_video();
#endif
}
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index febba1982..061b01bd8 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -211,8 +211,6 @@ static void scc_irq_disable(int);
* console_loglevel determines NMI handler function
*/
-extern int console_loglevel;
-
extern void mac_bang(int, void *, struct pt_regs *);
void mac_nmi_handler(int, void *, struct pt_regs *);
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index c405fc0da..87d155ee0 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -35,7 +35,6 @@ void oss_nubus_irq(int, void *, struct pt_regs *);
extern void via1_irq(int, void *, struct pt_regs *);
extern void mac_scc_dispatch(int, void *, struct pt_regs *);
-extern int console_loglevel;
/*
* Initialize the OSS
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index 86bbf72cc..d792ef987 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -32,8 +32,6 @@ volatile __u8 *psc;
void psc_irq(int, void *, struct pt_regs *);
-extern int console_loglevel;
-
/*
* Debugging dump, used in various places to see what's going on.
*/
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index af001907d..ec0b2ce19 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -74,7 +74,6 @@ void via_irq_clear(int irq);
extern void mac_bang(int, void *, struct pt_regs *);
extern void mac_scc_dispatch(int, void *, struct pt_regs *);
-extern int console_loglevel;
extern int oss_present;
/*
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index 3eba3d13b..8dc87ebc1 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -19,6 +19,55 @@
extern void die_if_kernel(char *, struct pt_regs *, long);
extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
+int send_fault_sig(struct pt_regs *regs)
+{
+ siginfo_t siginfo = { 0, 0, 0, };
+
+ siginfo.si_signo = current->thread.signo;
+ siginfo.si_code = current->thread.code;
+ siginfo.si_addr = (void *)current->thread.faddr;
+ printk("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, siginfo.si_signo, siginfo.si_code);
+
+ if (user_mode(regs)) {
+ force_sig_info(siginfo.si_signo,
+ &siginfo, current);
+ } else {
+ unsigned long fixup;
+
+ /* Are we prepared to handle this kernel fault? */
+ if ((fixup = search_exception_table(regs->pc))) {
+ struct pt_regs *tregs;
+ /* Create a new four word stack frame, discarding the old
+ one. */
+ regs->stkadj = frame_extra_sizes[regs->format];
+ tregs = (struct pt_regs *)((ulong)regs + regs->stkadj);
+ tregs->vector = regs->vector;
+ tregs->format = 0;
+ tregs->pc = fixup;
+ tregs->sr = regs->sr;
+ return -1;
+ }
+
+ //if (siginfo.si_signo == SIGBUS)
+ // force_sig_info(siginfo.si_signo,
+ // &siginfo, current);
+
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+ if ((unsigned long)siginfo.si_addr < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel access");
+ printk(" at virtual address %p\n", siginfo.si_addr);
+ die_if_kernel("Oops", regs, 0 /*error_code*/);
+ do_exit(SIGKILL);
+ }
+
+ return 1;
+}
+
/*
* This routine handles page faults. It determines the problem, and
* then passes it off to one of the appropriate routines.
@@ -30,16 +79,15 @@ extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
* If this routine detects a bad access, it returns 1, otherwise it
* returns 0.
*/
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
+int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct * vma;
- unsigned long fixup;
int write, fault;
#ifdef DEBUG
- printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
+ printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
regs->sr, regs->pc, address, error_code,
current->mm->pgd);
#endif
@@ -55,43 +103,46 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
vma = find_vma(mm, address);
if (!vma)
- goto bad_area;
+ goto map_err;
if (vma->vm_flags & VM_IO)
- goto bad_area;
+ goto acc_err;
if (vma->vm_start <= address)
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
+ goto map_err;
if (user_mode(regs)) {
/* Accessing the stack below usp is always a bug. The
"+ 256" is there due to some instructions doing
pre-decrement on the stack and that doesn't show up
until later. */
if (address + 256 < rdusp())
- goto bad_area;
+ goto map_err;
}
if (expand_stack(vma, address))
- goto bad_area;
+ goto map_err;
/*
* Ok, we have a good vm_area for this memory access, so
* we can handle it..
*/
good_area:
+#ifdef DEBUG
+ printk("do_page_fault: good_area\n");
+#endif
write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
/* fall through */
case 2: /* write, not present */
if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
+ goto acc_err;
write++;
break;
case 1: /* read, present */
- goto bad_area;
+ goto acc_err;
case 0: /* read, not present */
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
- goto bad_area;
+ goto acc_err;
}
/*
@@ -100,87 +151,56 @@ good_area:
* the fault.
*/
fault = handle_mm_fault(mm, vma, address, write);
+#ifdef DEBUG
+ printk("handle_mm_fault returns %d\n",fault);
+#endif
if (fault < 0)
goto out_of_memory;
if (!fault)
- goto do_sigbus;
+ goto bus_err;
/* There seems to be a missing invalidate somewhere in do_no_page.
* Until I found it, this one cures the problem and makes
* 1.2 run on the 68040 (Martin Apel).
*/
+ #warning should be obsolete now...
if (CPU_IS_040_OR_060)
flush_tlb_page(vma, address);
up(&mm->mmap_sem);
return 0;
/*
- * 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);
-
- /* User mode accesses just cause a SIGSEGV */
- if (user_mode(regs)) {
- siginfo_t info;
- info.si_signo = SIGSEGV;
- info.si_code = SEGV_MAPERR;
- info.si_addr = (void *)address;
- force_sig_info(SIGSEGV, &info, current);
- return 1;
- }
-
-no_context:
- /* Are we prepared to handle this kernel fault? */
- if ((fixup = search_exception_table(regs->pc)) != 0) {
- struct pt_regs *tregs;
- /* Create a new four word stack frame, discarding the old
- one. */
- regs->stkadj = frame_extra_sizes[regs->format];
- tregs = (struct pt_regs *)((ulong)regs + regs->stkadj);
- tregs->vector = regs->vector;
- tregs->format = 0;
- tregs->pc = fixup;
- tregs->sr = regs->sr;
- return -1;
- }
-
-/*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
- if ((unsigned long) address < PAGE_SIZE) {
- printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- } else
- printk(KERN_ALERT "Unable to handle kernel access");
- printk(" at virtual address %08lx\n",address);
- die_if_kernel("Oops", regs, error_code);
- do_exit(SIGKILL);
-
-/*
* We ran out of memory, or some other thing happened to us that made
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- up(&mm->mmap_sem);
printk("VM: killing process %s\n", current->comm);
- if (error_code & 4)
+ if (user_mode(regs))
do_exit(SIGKILL);
- goto no_context;
-do_sigbus:
+no_context:
+ current->thread.signo = SIGBUS;
+ current->thread.faddr = address;
+ return send_fault_sig(regs);
+
+bus_err:
+ current->thread.signo = SIGBUS;
+ current->thread.code = BUS_ADRERR;
+ current->thread.faddr = address;
+ goto send_sig;
+
+map_err:
+ current->thread.signo = SIGSEGV;
+ current->thread.code = SEGV_MAPERR;
+ current->thread.faddr = address;
+ goto send_sig;
+
+acc_err:
+ current->thread.signo = SIGSEGV;
+ current->thread.code = SEGV_ACCERR;
+ current->thread.faddr = address;
+
+send_sig:
up(&mm->mmap_sem);
-
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- force_sig(SIGBUS, current);
-
- /* Kernel mode? Handle exceptions or die */
- if (!user_mode(regs))
- goto no_context;
-
- return 1;
+ return send_fault_sig(regs);
}
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index d48a0201b..06ffa5692 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -201,15 +201,6 @@ int mvme147_keyb_init (void)
/*------------------- Serial console stuff ------------------------*/
-void m147_scc_write(struct console *co, const char *str, unsigned cnt);
-
-
-void mvme147_init_console_port (struct console *co, int cflag)
-{
- co->write = m147_scc_write;
-}
-
-
static void scc_delay (void)
{
int n;
@@ -250,3 +241,31 @@ void m147_scc_write (struct console *co, const char *str, unsigned count)
restore_flags(flags);
}
+
+static int m147_scc_wait_key (struct console *co)
+{
+ volatile unsigned char *p = (volatile char *)M147_SCC_A_ADDR;
+ unsigned long flags;
+ int c;
+
+ /* wait for rx buf filled */
+ while ((*p & 0x01) == 0)
+ ;
+
+ save_flags(flags);
+ cli();
+
+ *p = 8;
+ scc_delay();
+ c = *p;
+
+ restore_flags(flags);
+ return c;
+}
+
+
+void mvme147_init_console_port (struct console *co, int cflag)
+{
+ co->write = m147_scc_write;
+ co->wait_key = m147_scc_wait_key;
+}
diff --git a/arch/m68k/q40/README b/arch/m68k/q40/README
index 60134d9de..b61ee9c6a 100644
--- a/arch/m68k/q40/README
+++ b/arch/m68k/q40/README
@@ -56,8 +56,7 @@ SRAM can also be used as additional console device, use debug=mem.
This will save kernel startup msgs into SRAM, the screen will display
only the penguin - and shell prompt if it gets that far..
-Serial console works and can also be used for debugging, provided serial
-initialisation works.
+Serial console works and can also be used for debugging, see loader_txt
Most problems seem to be caused by fawlty or badly configured io-cards or
harddrives anyway..there are so many things that can go wrong here.
@@ -82,8 +81,9 @@ The main interrupt register IIRQ_REG will indicate whether an IRQ was internal
or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs.
The Q40 custom chip is programmable to provide 2 periodic timers:
- - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!!
- - 10 or 20 KHz - level 4 (and possibly 6 - hardware decoding..)
+ - 50 or 200 Hz - level 2,
+ - 10 or 20 KHz - level 4
+ !!THIS CANT BE DISABLED!!
Linux uses the 200 Hz interrupt for timer and beep by default.
@@ -92,9 +92,6 @@ Interrupts
==========
q40 master chip handles only level triggered interrupts :-((
-further limitation is no disabling etc. There is NO WAY to remove
-an ISA irq request other than serve the HW specific control register,
-the ISA irq lines are connected straight to the CPU ipl1 pin..
IRQ sharing is not yet implemented but this should be only a minor
problem..
@@ -102,12 +99,17 @@ problem..
Linux has some requirements wrt interrupt architecture, these are
to my knowledge:
(a) interrupt handler must not be reentered even when sti() is called
+ from within handler
(b) working enable/disable_irq
Luckily these requirements are only important for drivers shared
with other architectures - ide,serial,parallel, ethernet..
-q40ints.c now contains a trivial hack for (a), however (b) could
-be only solved by driver-specific code
+q40ints.c now contains a trivial hack for (a), (b) is more difficult
+because only irq's 4-15 can be disabled - and only all o them at once.
+Thus disable_irq() can effectively block the machine if the driver goes
+asleep.
+One thing to keep in minde when hacking around the interrupt code is
+that there is no way to find out which IRQ caused a request.
Keyboard
========
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 2496aa9ba..294765dd2 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -13,6 +13,7 @@
*/
#include <linux/config.h>
+#include <stdarg.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -22,6 +23,7 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/major.h>
+#include <linux/serial_reg.h>
#include <asm/rtc.h>
#include <asm/bootinfo.h>
@@ -34,8 +36,8 @@
#include <asm/q40_master.h>
#include <asm/keyboard.h>
-extern void fd_floppy_eject(void);
-extern void fd_floppy_setup(char *str, int *ints);
+extern void floppy_eject(void);
+extern void floppy_setup(char *str, int *ints);
extern void q40_process_int (int level, struct pt_regs *regs);
extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
@@ -65,9 +67,12 @@ extern char *saved_command_line;
extern char m68k_debug_device[];
static void q40_mem_console_write(struct console *co, const char *b,
unsigned int count);
+#if 0
+extern int ql_ticks=0;
+extern int sound_ticks=0;
+#endif
-static int ql_ticks=0;
-static int sound_ticks=0;
+extern int ql_ticks;
static unsigned char bcd2bin (unsigned char b);
static unsigned char bin2bcd (unsigned char b);
@@ -81,16 +86,16 @@ static struct console q40_console_driver = {
};
-/* Save tick handler routine pointer, will point to do_timer() in
- * kernel/sched.c */
-
-/* static void (*tick_handler)(int, void *, struct pt_regs *); */
-
-
/* early debugging function:*/
extern char *q40_mem_cptr; /*=(char *)0xff020000;*/
static int _cpleft;
+int q40_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
+{
+ *keycodep = keycode;
+ return 1;
+}
+
static void q40_mem_console_write(struct console *co, const char *s,
unsigned int count)
{
@@ -140,6 +145,41 @@ static void q40_get_model(char *model)
sprintf(model, "Q40");
}
+/* pasted code to make parport_pc happy */
+extern __inline__ int __get_order(unsigned long size)
+{
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+void *pci_alloc_consistent(void *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ void *ret;
+ int gfp = GFP_ATOMIC;
+
+ ret = (void *)__get_free_pages(gfp, __get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_bus(ret);
+ }
+ return ret;
+}
+
+void pci_free_consistent(void *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, __get_order(size));
+}
+/* end pasted code */
+
/* No hardware options on Q40? */
@@ -149,12 +189,23 @@ static int q40_get_hardware_list(char *buffer)
return 0;
}
+static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0};
+void q40_disable_irqs(void)
+{
+ unsigned i,j;
+
+ j=0;
+ while((i=serports[j++])) outb(0,i+UART_IER);
+ master_outb(0,EXT_ENABLE_REG);
+ master_outb(0,KEY_IRQ_ENABLE_REG);
+}
void __init config_q40(void)
{
mach_sched_init = q40_sched_init; /* ok */
/*mach_kbdrate = q40_kbdrate;*/ /* unneeded ?*/
mach_keyb_init = q40_keyb_init; /* OK */
+ mach_kbd_translate = q40_kbd_translate;
mach_init_IRQ = q40_init_IRQ;
mach_gettimeoffset = q40_gettimeoffset;
mach_gettod = q40_gettod;
@@ -177,13 +228,14 @@ void __init config_q40(void)
mach_sysrq_key = 0x54;
#endif
conswitchp = &dummy_con;
-#ifdef CONFIG_BLK_DEV_FD
- mach_floppy_setup = fd_floppy_setup;
- mach_floppy_eject = fd_floppy_eject;
+#if 0 /*def CONFIG_BLK_DEV_FD*/
+ mach_floppy_setup = floppy_setup;
+ mach_floppy_eject = floppy_eject;
/**/
#endif
- mach_max_dma_address = 0; /* no DMA at all */
+ q40_disable_irqs();
+ mach_max_dma_address = 32*1024*1024; /* no DMA at all, but ide-scsi requires it.. */
/* userfull for early debuging stages writes kernel messages into SRAM */
@@ -203,6 +255,7 @@ int q40_parse_bootinfo(const struct bi_record *rec)
return 1; /* unknown */
}
+#if 0
#define DAC_LEFT ((unsigned char *)0xff008000)
#define DAC_RIGHT ((unsigned char *)0xff008004)
void q40_mksound(unsigned int hz, unsigned int ticks)
@@ -258,7 +311,11 @@ static void q40_timer_int (int irq, void *dev_id, struct pt_regs *fp)
#endif
q40_timer_routine(irq, dev_id, fp);
}
+#endif
+#if 0
+extern void (*q40_timer_routine)(int, void *, struct pt_regs *);
+extern void q40_timer_int();
void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
{
@@ -289,7 +346,7 @@ void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
#endif
#endif
}
-
+#endif
unsigned long q40_gettimeoffset (void)
{
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index c6625aad8..96d9414d3 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -7,18 +7,22 @@
* License. See the file COPYING in the main directory of this archive
* for more details.
*
- * losely based on bvme6000ints.c
+ * .. used to be losely based on bvme6000ints.c
*
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/sched.h>
+#include <asm/rtc.h>
#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/irq.h>
+#include <asm/hardirq.h>
#include <asm/traps.h>
#include <asm/q40_master.h>
@@ -71,13 +75,16 @@ short unsigned q40_ablecount[Q40_IRQ_MAX+1];
* the q40 IRQ handling routines.
*/
+static int disabled=0;
+
void q40_init_IRQ (void)
{
int i;
+ disabled=0;
for (i = 0; i <= Q40_IRQ_MAX; i++) {
irq_tab[i].handler = q40_defhand;
- irq_tab[i].flags = IRQ_FLG_STD;
+ irq_tab[i].flags = 0;
irq_tab[i].dev_id = NULL;
/* irq_tab[i].next = NULL;*/
irq_tab[i].devname[0] = 0;
@@ -87,14 +94,10 @@ void q40_init_IRQ (void)
}
/* setup handler for ISA ints */
- sys_request_irq(IRQ2,q40_irq2_handler, IRQ_FLG_LOCK, "q40 ISA and master chip", NULL);
+ sys_request_irq(IRQ2,q40_irq2_handler, 0, "q40 ISA and master chip", NULL);
/* now enable some ints.. */
-
-#if 0 /* has been abandoned */
- master_outb(1,SER_ENABLE_REG);
-#endif
- master_outb(1,EXT_ENABLE_REG);
+ master_outb(1,EXT_ENABLE_REG); /* hm, aint that too early? */
/* would be spurious ints by now, q40kbd_init_hw() does that */
master_outb(0,KEY_IRQ_ENABLE_REG);
@@ -124,24 +127,20 @@ int q40_request_irq(unsigned int irq,
default:
}
- if (irq<Q40_IRQ_TIMER)
+ if (irq<Q40_IRQ_SAMPLE)
{
- if (!(irq_tab[irq].flags & IRQ_FLG_STD))
- {
- if (irq_tab[irq].flags & IRQ_FLG_LOCK)
+ if (irq_tab[irq].dev_id != NULL)
{
printk("%s: IRQ %d from %s is not replaceable\n",
__FUNCTION__, irq, irq_tab[irq].devname);
return -EBUSY;
}
- if (flags & IRQ_FLG_REPLACE)
+ /*printk("IRQ %d set to handler %p\n",irq,handler);*/
+ if (dev_id==NULL)
{
- printk("%s: %s can't replace IRQ %d from %s\n",
- __FUNCTION__, devname, irq, irq_tab[irq].devname);
- return -EBUSY;
- }
+ printk("WARNING: dev_id == NULL in request_irq\n");
+ dev_id=1;
}
- /*printk("IRQ %d set to handler %p\n",irq,handler);*/
irq_tab[irq].handler = handler;
irq_tab[irq].flags = flags;
irq_tab[irq].dev_id = dev_id;
@@ -150,7 +149,7 @@ int q40_request_irq(unsigned int irq,
return 0;
}
else {
- /* Q40_IRQ_TIMER :somewhat special actions required here ..*/
+ /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/
sys_request_irq(4,handler,flags,devname,dev_id);
sys_request_irq(6,handler,flags,devname,dev_id);
return 0;
@@ -175,31 +174,120 @@ void q40_free_irq(unsigned int irq, void *dev_id)
default:
}
- if (irq<Q40_IRQ_TIMER)
+ if (irq<Q40_IRQ_SAMPLE)
{
if (irq_tab[irq].dev_id != dev_id)
printk("%s: Removing probably wrong IRQ %d from %s\n",
__FUNCTION__, irq, irq_tab[irq].devname);
irq_tab[irq].handler = q40_defhand;
- irq_tab[irq].flags = IRQ_FLG_STD;
+ irq_tab[irq].flags = 0;
irq_tab[irq].dev_id = NULL;
/* irq_tab[irq].devname = NULL; */
/* do not reset state !! */
}
else
- { /* == Q40_IRQ_TIMER */
+ { /* == Q40_IRQ_SAMPLE */
sys_free_irq(4,dev_id);
sys_free_irq(6,dev_id);
}
}
-#if 1
+
void q40_process_int (int level, struct pt_regs *fp)
{
printk("unexpected interrupt %x\n",level);
}
+
+/*
+ * this stuff doesn't really belong here..
+*/
+int ql_ticks=0;
+static int sound_ticks=0;
+
+#define SVOL 45
+
+void q40_mksound(unsigned int hz, unsigned int ticks)
+{
+ /* for now ignore hz, except that hz==0 switches off sound */
+ /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
+ if (hz==0)
+ {
+ if (sound_ticks)
+ sound_ticks=1; /* atomic - no irq spinlock used */
+
+ *DAC_LEFT=128;
+ *DAC_RIGHT=128;
+
+ return;
+ }
+ /* sound itself is done in q40_timer_int */
+ if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
+ sound_ticks=ticks<<1;
+}
+
+static void (*q40_timer_routine)(int, void *, struct pt_regs *);
+static short rtc_oldsecs=0;
+unsigned rtc_irq_flags=0;
+unsigned rtc_irq_ctrl=0;
+
+static void q40_timer_int (int irq, void * dev, struct pt_regs * regs)
+{
+
+
+#if (HZ==100)
+ ql_ticks = ql_ticks ? 0 : 1;
+ if (sound_ticks)
+ {
+ unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
+ sound_ticks--;
+ *DAC_LEFT=sval;
+ *DAC_RIGHT=sval;
+ }
+#ifdef CONFIG_Q40RTC
+ if (rtc_irq_ctrl && (rtc_oldsecs != RTC_SECS))
+ {
+ rtc_oldsecs = RTC_SECS;
+ rtc_irq_flags = RTC_UIE;
+ rtc_interrupt();
+ }
#endif
+ if (ql_ticks) return;
+#endif
+ q40_timer_routine(irq, dev, regs);
+}
+
+void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+{
+ int timer_irq;
+
+ q40_timer_routine = timer_routine;
+
+#if (HZ==10000)
+ timer_irq=Q40_IRQ_SAMPLE;
+#else
+ timer_irq=Q40_IRQ_FRAME;
+#endif
+
+ /*printk("registering sched/timer IRQ %d, handler %p\n", timer_irq,q40_timer_int);*/
+ /*printk("timer routine %p\n",q40_timer_routine);*/
+
+ if (request_irq(timer_irq, q40_timer_int, 0,
+ "timer", q40_timer_int))
+ panic ("Couldn't register timer int");
+
+#if (HZ==10000)
+ master_outb(SAMPLE_LOW,SAMPLE_RATE_REG);
+ master_outb(-1,SAMPLE_CLEAR_REG);
+ master_outb(1,SAMPLE_ENABLE_REG);
+#else
+ master_outb(-1,FRAME_CLEAR_REG); /* not necessary ? */
+#if (HZ==100)
+ master_outb( 1,FRAME_RATE_REG);
+#endif
+#endif
+}
+
/*
* tables to translate bits into IRQ numbers
@@ -208,11 +296,12 @@ void q40_process_int (int level, struct pt_regs *fp)
*/
struct IRQ_TABLE{ unsigned mask; int irq ;};
-
+#if 0
static struct IRQ_TABLE iirqs[]={
{IRQ_FRAME_MASK,Q40_IRQ_FRAME},
{IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
{0,0}};
+#endif
static struct IRQ_TABLE eirqs[]={
{IRQ3_MASK,3}, /* ser 1 */
{IRQ4_MASK,4}, /* ser 2 */
@@ -231,103 +320,124 @@ static struct IRQ_TABLE eirqs[]={
/* complain only this many times about spurious ints : */
static int ccleirq=60; /* ISA dev IRQ's*/
-static int cclirq=60; /* internal */
+/*static int cclirq=60;*/ /* internal */
/* FIX: add shared ints,mask,unmask,probing.... */
-/* this is an awfull hack.. */
+
#define IRQ_INPROGRESS 1
-static int disabled=0;
/*static unsigned short saved_mask;*/
+static int do_tint=0;
+
+#define DEBUG_Q40INT
+#define IP_USE_DISABLE /* would be nice, but crashes ???? */
+/*static int dd_count=0;*/
+static int mext_disabled=0; /* ext irq disabled by master chip? */
+static int aliased_irq=0; /* how many times inside handler ?*/
+
+
+/* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */
void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
{
- /* got level 2 interrupt, dispatch to ISA or keyboard IRQs */
-
- unsigned mir=master_inb(IIRQ_REG);
+ unsigned mir;
unsigned mer;
int irq,i;
+ repeat:
+ mir=master_inb(IIRQ_REG);
+ if (mir&IRQ_FRAME_MASK)
+ { /* dont loose ticks */
+ do_tint++;
+ master_outb(-1,FRAME_CLEAR_REG);
+ }
if ((mir&IRQ_SER_MASK) || (mir&IRQ_EXT_MASK))
{
-
/* some ISA dev caused the int */
-
mer=master_inb(EIRQ_REG);
-
for (i=0; eirqs[i].mask; i++)
{
if (mer&(eirqs[i].mask))
{
irq=eirqs[i].irq;
- irq_tab[irq].count++;
+/*
+ * There is a little mess wrt which IRQ really caused this irq request. The
+ * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they
+ * are read - which is long after the request came in. In theory IRQs should
+ * not just go away but they occassionally do
+ */
+ if (irq>4 && irq<=15 && mext_disabled)
+ {
+ /*aliased_irq++;*/
+ goto iirq;
+ }
if (irq_tab[irq].handler == q40_defhand )
{
printk("handler for IRQ %d not defined\n",irq);
continue; /* ignore uninited INTs :-( */
}
-
if ( irq_tab[irq].state & IRQ_INPROGRESS )
{
+ /* some handlers do sti() for irq latency reasons, */
+ /* however reentering an active irq handler is not permitted */
+#ifdef IP_USE_DISABLE
+ /* in theory this is the better way to do it because it still */
+ /* lets through eg the serial irqs, unfortunately it crashes */
+ disable_irq(irq);
+ disabled=1;
+#else
/*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */
-
- /*saved_mask = fp->sr;*/
- fp->sr = (fp->sr & (~0x700))+0x200;
+ fp->sr = (((fp->sr) & (~0x700))+0x200);
disabled=1;
- return;
+#endif
+ goto iirq;
}
+ irq_tab[irq].count++;
irq_tab[irq].state |= IRQ_INPROGRESS;
irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+ irq_tab[irq].state &= ~IRQ_INPROGRESS;
/* naively enable everything, if that fails than */
/* this function will be reentered immediately thus */
/* getting another chance to disable the IRQ */
- irq_tab[irq].state &= ~IRQ_INPROGRESS;
if ( disabled )
{
+#ifdef IP_USE_DISABLE
+ if (irq>4){
+ disabled=0;
+ /*dd_count--;*/
+ enable_irq(irq);}
+#else
+ disabled=0;
/*printk("reenabling irq %d\n",irq); */
- fp->sr = (fp->sr & (~0x700)); /*saved_mask; */
- disabled=0;
+#if 0
+ fp->sr = ((fp->sr) & (~0x700)); /* unneeded ?! */
+#endif
+#endif
}
- else if ( fp->sr &0x200 )
- printk("exiting irq handler: fp->sr &0x200 !!\n");
-
- return;
+ goto repeat; /* return; */
}
}
- if (ccleirq>0)
+ if (mer && ccleirq>0 && !aliased_irq)
printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
}
- else
+ iirq:
+ mir=master_inb(IIRQ_REG);
+ if (mir&IRQ_FRAME_MASK)
{
- /* internal */
-
- for (i=0; iirqs[i].mask; i++)
+ do_tint++;
+ master_outb(-1,FRAME_CLEAR_REG);
+ }
+ for(;do_tint>0;do_tint--)
{
- if (mir&(iirqs[i].mask))
- {
- irq=iirqs[i].irq;
- irq_tab[irq].count++;
- if (irq_tab[irq].handler == q40_defhand )
- continue; /* ignore uninited INTs :-( */
-
- /* the INPROGRESS stuff should be completely useless*/
- /* for internal ints, nevertheless test it..*/
- if ( irq_tab[irq].state & IRQ_INPROGRESS )
+ irq_tab[Q40_IRQ_FRAME].count++;
+ irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);
+ }
+ if (mir&IRQ_KEYB_MASK) /* may handle it even if actually disabled*/
{
- /*disable_irq(irq);
- return;*/
- printk("rentering handler for IRQ %d !!\n",irq);
- }
- irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
- irq_tab[irq].state &= ~IRQ_INPROGRESS;
- /*enable_irq(irq);*/ /* better not try luck !*/
- return;
- }
- }
- if (cclirq>0)
- printk("internal level 2 interrupt from unknown source ? IIRQ_REG=%x\n",mir),cclirq--;
+ irq_tab[Q40_IRQ_KEYBOARD].count++;
+ irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
}
}
@@ -335,9 +445,11 @@ int q40_get_irq_list (char *buf)
{
int i, len = 0;
- for (i = 0; i <= Q40_IRQ_MAX; i++) {
+ for (i = 0; i <= Q40_IRQ_MAX; i++)
+ {
if (irq_tab[i].count)
- len += sprintf (buf+len, "Vec 0x%02x: %8d %s%s\n",
+ len += sprintf (buf+len, "%sIRQ %02d: %8d %s%s\n",
+ (i<=15) ? "ISA-" : " " ,
i, irq_tab[i].count,
irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
irq_tab[i].handler == q40_defhand ?
@@ -370,30 +482,17 @@ static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs)
sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler
};
-int irq_disabled=0;
+
void q40_enable_irq (unsigned int irq)
{
- /* enable ISA iqs */
- if ( irq>=0 && irq<=15 ) /* the moderately bad case */
+ if ( irq>=5 && irq<=15 )
+ {
+ mext_disabled--;
+ if (mext_disabled>0)
+ printk("q40_enable_irq : nested disable/enable\n");
+ if (mext_disabled==0)
master_outb(1,EXT_ENABLE_REG);
-#if 0
- unsigned long flags;
- int i;
-
- if (irq>=10 && irq <= 15)
- {
- if ( !(--q40_ablecount[irq]))
- for (i=10,irq_disabled=0; i<=15; i++)
- {
- irq_disabled |= (q40_ablecount[irq] !=0);
- }
- if ( !irq_disabled )
- {
- save_flags(flags);
- restore_flags(flags & (~0x700));
- }
}
-#endif
}
@@ -404,19 +503,12 @@ void q40_disable_irq (unsigned int irq)
* Any driver should not attempt to sleep accross disable_irq !!
*/
- if ( irq>=10 && irq<=15 ) /* the moderately bad case */
- master_outb(0,EXT_ENABLE_REG);
-#if 0
- unsigned long flags;
-
- if (irq>=10 && irq <= 15)
+ if ( irq>=5 && irq<=15 )
{
- save_flags(flags);
- restore_flags(flags | 0x200 );
- irq_disabled=1;
- q40_ablecount[irq]++;
+ master_outb(0,EXT_ENABLE_REG);
+ mext_disabled++;
+ if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled);
}
-#endif
}
unsigned long q40_probe_irq_on (void)
@@ -428,3 +520,7 @@ int q40_probe_irq_off (unsigned long irqs)
{
return -1;
}
+/*
+ * Local variables:
+ * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040 -c -o q40ints.o q40ints.c"
+ */
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6a8cfe187..3ea928267 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -151,7 +151,8 @@ LOADADDR += 0x80080000
endif
ifdef CONFIG_SGI_IP22
-LIBS += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a
+CORE_FILES += arch/mips/sgi/kernel/ip22-kern.o
+LIBS += arch/mips/arc/arclib.a
SUBDIRS += arch/mips/sgi/kernel arch/mips/arc
#
# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
@@ -273,7 +274,6 @@ zdisk: vmlinux
archclean:
@$(MAKEBOOT) clean
rm -f arch/$(ARCH)/ld.script
- $(MAKE) -C arch/$(ARCH)/kernel clean
$(MAKE) -C arch/$(ARCH)/tools clean
$(MAKE) -C arch/mips/baget clean
diff --git a/arch/mips/arc/Makefile b/arch/mips/arc/Makefile
index e37207b33..8af31d353 100644
--- a/arch/mips/arc/Makefile
+++ b/arch/mips/arc/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
#
# Makefile for the SGI arcs prom monitor library routines
# under Linux.
@@ -10,11 +9,12 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
L_TARGET = arclib.a
-L_OBJS = console.o init.o memory.o tree.o env.o cmdline.o misc.o time.o \
- file.o identify.o
-ifdef CONFIG_ARC_CONSOLE
-L_OBJS += arc_con.o
-endif
+obj-y += console.o init.o memory.o tree.o env.o cmdline.o misc.o \
+ time.o file.o identify.o
+
+obj-$(CONFIG_ARC_CONSOLE) += arc_con.o
+
+L_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 6f64e8a9a..b75e37c6b 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -301,8 +301,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-atlas b/arch/mips/defconfig-atlas
index 4b0740fe9..e622a3f9a 100644
--- a/arch/mips/defconfig-atlas
+++ b/arch/mips/defconfig-atlas
@@ -28,7 +28,7 @@ CONFIG_MIPS_ATLAS=y
# CONFIG_MCA is not set
# CONFIG_SBUS is not set
CONFIG_PCI=y
-# CONFIG_ISA is not set
+CONFIG_SWAP_IO_SPACE=y
# CONFIG_ISA is not set
# CONFIG_EISA is not set
# CONFIG_I8259 is not set
@@ -429,8 +429,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-cp7000 b/arch/mips/defconfig-cp7000
index d67e287ba..1d98bca31 100644
--- a/arch/mips/defconfig-cp7000
+++ b/arch/mips/defconfig-cp7000
@@ -405,8 +405,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-ddb5476 b/arch/mips/defconfig-ddb5476
index 21f540a76..9c74cad89 100644
--- a/arch/mips/defconfig-ddb5476
+++ b/arch/mips/defconfig-ddb5476
@@ -468,8 +468,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-decstation b/arch/mips/defconfig-decstation
index dece17abb..72ac15128 100644
--- a/arch/mips/defconfig-decstation
+++ b/arch/mips/defconfig-decstation
@@ -295,8 +295,6 @@ CONFIG_EXT2_FS=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-ev64120 b/arch/mips/defconfig-ev64120
index 38dd7bbfb..004f6083f 100644
--- a/arch/mips/defconfig-ev64120
+++ b/arch/mips/defconfig-ev64120
@@ -404,8 +404,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-ev96100 b/arch/mips/defconfig-ev96100
index 262fd226a..eae29f655 100644
--- a/arch/mips/defconfig-ev96100
+++ b/arch/mips/defconfig-ev96100
@@ -395,8 +395,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22
index 6f64e8a9a..b75e37c6b 100644
--- a/arch/mips/defconfig-ip22
+++ b/arch/mips/defconfig-ip22
@@ -301,8 +301,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-malta b/arch/mips/defconfig-malta
index 826c3f871..7f83eba55 100644
--- a/arch/mips/defconfig-malta
+++ b/arch/mips/defconfig-malta
@@ -29,7 +29,8 @@ CONFIG_MIPS_MALTA=y
# CONFIG_SBUS is not set
CONFIG_I8259=y
CONFIG_PCI=y
-# CONFIG_ISA is not set
+CONFIG_HAVE_STD_PC_SERIAL_PORT=y
+CONFIG_SWAP_IO_SPACE=y
# CONFIG_ISA is not set
# CONFIG_EISA is not set
@@ -427,8 +428,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/defconfig-rm200 b/arch/mips/defconfig-rm200
index 8fced9009..fefe5f65d 100644
--- a/arch/mips/defconfig-rm200
+++ b/arch/mips/defconfig-rm200
@@ -319,8 +319,6 @@ CONFIG_EXT2_FS=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 9be8406e4..6bec68661 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -11,97 +11,60 @@
.S.o:
$(CC) $(AFLAGS) -c $< -o $@
-all: kernel.o head.o init_task.o
EXTRA_ASFLAGS = -mips3 -mcpu=r4000
+
+all: kernel.o head.o init_task.o
+
O_TARGET := kernel.o
-O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
- ioport.o reset.o semaphore.o setup.o syscall.o sysmips.o ipc.o \
- scall_o32.o unaligned.o
-OX_OBJS := mips_ksyms.o
+
+obj-y += branch.o process.o signal.o entry.o \
+ traps.o ptrace.o vm86.o ioport.o reset.o \
+ semaphore.o setup.o syscall.o sysmips.o \
+ ipc.o scall_o32.o unaligned.o
+obj-$(CONFIG_MODULES) += mips_ksyms.o
ifdef CONFIG_CPU_R3000
-O_OBJS += r2300_misc.o r2300_fpu.o r2300_switch.o
+obj-y += r2300_misc.o r2300_fpu.o r2300_switch.o
else
-O_OBJS += r4k_misc.o r4k_switch.o
+obj-y += r4k_misc.o r4k_switch.o
ifdef CONFIG_CPU_R6000
-O_OBJS += r6000_fpu.o
+obj-y += r6000_fpu.o
else
-O_OBJS += r4k_fpu.o
-endif
+obj-y += r4k_fpu.o
endif
-
-ifdef CONFIG_MIPS_FPE_MODULE
-M_OBJS += fpe.o
endif
-ifndef CONFIG_MIPS_FPU_EMULATOR
-O_OBJS += softfp.o
-endif
+obj-$(CONFIG_MIPS_FPE_MODULE) += fpe.o
+obj-$(CONFIG_MIPS_FPU_EMULATOR) += softfp.o
-ifdef CONFIG_ROTTEN_IRQ
- OX_OBJS += old-irq.o
-endif
+# Old style irq support, going to die in 2.5.
+export-objs += old-irq.o
+obj-$(CONFIG_ROTTEN_IRQ) += old-irq.o
ifndef CONFIG_DECSTATION
ifndef CONFIG_BAGET_MIPS
ifndef CONFIG_MIPS_ATLAS
ifndef CONFIG_MIPS_MALTA
ifndef CONFIG_MIPS_EV96100
- O_OBJS += time.o
+ obj-y += time.o
endif
endif
endif
endif
endif
-#
-# Do we want to be able to execute IRIX elf binaries?
-#
-ifdef CONFIG_BINFMT_IRIX
-O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o irixinv.o
-endif
-
-#
-# Kernel debugging
-#
-ifdef CONFIG_REMOTE_DEBUG
-O_OBJS += gdb-low.o gdb-stub.o
-endif
-
-ifdef CONFIG_PCI
-O_OBJS += pci-dma.o
-endif
-
-ifdef CONFIG_PROC_FS
-O_OBJS += proc.o
-endif
-
-#
-# Since we add the same object files to O_OBJS for different configurations.
-# O_OBJS might contain duplicate files. We correct this by filtering out
-# duplicate files. Just to avoid users having to know about all the
-# compatibility stuff between various boards and boards.
-#
-O_OBJS := $(sort $(O_OBJS))
+obj-$(CONFIG_BINFMT_IRIX) += irixelf.o irixioctl.o irixsig.o sysirix.o \
+ irixinv.o
+obj-$(CONFIG_REMOTE_DEBUG) += gdb-low.o gdb-stub.o
+obj-$(CONFIG_PCI) += pci-dma.o
+obj-$(CONFIG_PROC_FS) += proc.o
entry.o: entry.S
-
head.o: head.S
-#r4k_switch.o: r4k_switch.S
-#
-#r4k_misc.o: r4k_misc.S
-#
-#r4k_fpu.o: r4k_fpu.S
-#
-#r2300_switch.o: r2300_switch.S
-#
-#r2300_misc.o: r2300_misc.S
-#
-#r2300_fpu.o: r2300_fpu.S
-#
-#r6000_fpu.o: r6000_fpu.S
-
-clean:
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS := $(filter $(export-objs), $(obj-y))
+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 6f6556da4..022bb1f77 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -716,7 +716,7 @@ repeat:
SET_LINKS(p);
notify_parent(p, SIGCHLD);
} else
- release(p);
+ release_task(p);
goto end_waitsys;
default:
continue;
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index d3ea588f0..f2a1d7032 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -36,19 +36,6 @@
#include <asm/inst.h>
#endif
-extern int console_loglevel;
-
-static inline void console_silent(void)
-{
- console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
- if (console_loglevel)
- console_loglevel = 15;
-}
-
/*
* Machine specific interrupt handlers
*/
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 52331d233..a5c870b73 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -9,26 +9,21 @@
L_TARGET = lib.a
-L_OBJS = csum_partial.o csum_partial_copy.o \
- rtc-std.o rtc-no.o memcpy.o memset.o watch.o\
- strlen_user.o strncpy_user.o strnlen_user.o
+obj-y += csum_partial.o csum_partial_copy.o \
+ rtc-std.o rtc-no.o memcpy.o memset.o \
+ watch.o strlen_user.o strncpy_user.o \
+ strnlen_user.o
ifdef CONFIG_CPU_R3000
- L_OBJS += r3k_dump_tlb.o
+ obj-y += r3k_dump_tlb.o
else
- L_OBJS += dump_tlb.o
+ obj-y += dump_tlb.o
endif
-ifdef CONFIG_BLK_DEV_FD
- L_OBJS += floppy-no.o floppy-std.o
-endif
-
-ifdef CONFIG_IDE
- L_OBJS += ide-std.o ide-no.o
-endif
+obj-$(CONFIG_BLK_DEV_FD) += floppy-no.o floppy-std.o
+obj-$(CONFIG_IDE) += ide-std.o ide-no.o
+obj-$(CONFIG_PC_KEYB) += kbd-std.o kbd-no.o
-ifdef CONFIG_PC_KEYB
- L_OBJS += kbd-std.o kbd-no.o
-endif
+L_OBJS := $(filter-out $(export-objs), $(obj-y))
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 4febbefd2..67a987693 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -8,46 +8,20 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := mm.o
-O_OBJS := extable.o init.o fault.o loadmmu.o
-ifdef CONFIG_CPU_R3000
-O_OBJS += r2300.o
-endif
+obj-y += extable.o init.o fault.o loadmmu.o
-ifdef CONFIG_CPU_R4300
-O_OBJS += r4xx0.o
-endif
+obj-$(CONFIG_CPU_R3000) += r2300.o
+obj-$(CONFIG_CPU_R4300) += r4xx0.o
+obj-$(CONFIG_CPU_R4X00) += r4xx0.o
+obj-$(CONFIG_CPU_R5000) += r4xx0.o
+obj-$(CONFIG_CPU_NEVADA) += r4xx0.o
+obj-$(CONFIG_CPU_R5432) += r5432.o
+obj-$(CONFIG_CPU_RM7000) += rm7k.o
+obj-$(CONFIG_CPU_MIPS32) += mips32.o
+obj-$(CONFIG_SGI_IP22) += umap.o
+obj-$(CONFIG_BAGET_MIPS) += umap.o
-ifdef CONFIG_CPU_R4X00
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R5000
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R5432
-O_OBJS += r5432.o
-endif
-
-ifdef CONFIG_CPU_RM7000
-O_OBJS += rm7k.o
-endif
-
-ifdef CONFIG_CPU_NEVADA
-O_OBJS += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_MIPS32
-O_OBJS += mips32.o
-endif
-
-ifdef CONFIG_SGI_IP22
-O_OBJS += umap.o
-endif
-
-ifdef CONFIG_BAGET_MIPS
-O_OBJS += umap.o
-endif
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
include $(TOPDIR)/Rules.make
diff --git a/arch/mips/sgi/kernel/Makefile b/arch/mips/sgi/kernel/Makefile
index f016cd12f..62fd01001 100644
--- a/arch/mips/sgi/kernel/Makefile
+++ b/arch/mips/sgi/kernel/Makefile
@@ -13,18 +13,15 @@
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
-OBJS = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \
- system.o indyIRQ.o reset.o setup.o time.o
+O_TARGET := ip22-kern.o
-all: sgikern.a
+all: ip22-kern.o indyIRQ.o
-sgikern.a: $(OBJS)
- $(AR) rcs sgikern.a $(OBJS)
- sync
+obj-y += indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \
+ indyIRQ.o reset.o setup.o time.o
indyIRQ.o: indyIRQ.S
-dep:
- $(CPP) $(CPPFLAGS) -M *.c > .depend
+O_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/arc/Makefile b/arch/mips64/arc/Makefile
index 141093f78..eb805e260 100644
--- a/arch/mips64/arc/Makefile
+++ b/arch/mips64/arc/Makefile
@@ -3,15 +3,15 @@
#
L_TARGET = arclib.a
-L_OBJS = init.o printf.o tree.o env.o cmdline.o misc.o time.o \
- file.o identify.o
+obj-y := init.o printf.o tree.o env.o cmdline.o misc.o time.o file.o \
+ identify.o
ifndef CONFIG_SGI_IP27
-L_OBJS += console.o
+ obj-y += console.o
endif
-ifdef CONFIG_ARC_MEMORY
-L_OBJS += memory.o
-endif
+obj-$(CONFIG_ARC_MEMORY) += memory.o
+
+L_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig
index 72f0b52bc..580ecb084 100644
--- a/arch/mips64/defconfig
+++ b/arch/mips64/defconfig
@@ -405,8 +405,6 @@ CONFIG_LOCKD_V4=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips64/defconfig-ip22 b/arch/mips64/defconfig-ip22
index 3848c0c96..8a747d636 100644
--- a/arch/mips64/defconfig-ip22
+++ b/arch/mips64/defconfig-ip22
@@ -321,8 +321,6 @@ CONFIG_LOCKD=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips64/defconfig-ip27 b/arch/mips64/defconfig-ip27
index 72f0b52bc..580ecb084 100644
--- a/arch/mips64/defconfig-ip27
+++ b/arch/mips64/defconfig-ip27
@@ -405,8 +405,6 @@ CONFIG_LOCKD_V4=y
# CONFIG_NCPFS_NFS_NS is not set
# CONFIG_NCPFS_OS2_NS is not set
# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
# CONFIG_NCPFS_NLS is not set
# CONFIG_NCPFS_EXTRAS is not set
diff --git a/arch/mips64/kernel/traps.c b/arch/mips64/kernel/traps.c
index 997aee0c7..c6777f938 100644
--- a/arch/mips64/kernel/traps.c
+++ b/arch/mips64/kernel/traps.c
@@ -27,19 +27,6 @@
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
-extern int console_loglevel;
-
-static inline void console_silent(void)
-{
- console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
- if (console_loglevel)
- console_loglevel = 15;
-}
-
extern asmlinkage void __xtlb_mod(void);
extern asmlinkage void __xtlb_tlbl(void);
extern asmlinkage void __xtlb_tlbs(void);
diff --git a/arch/mips64/lib/Makefile b/arch/mips64/lib/Makefile
index b8392d527..9ce5f0bd7 100644
--- a/arch/mips64/lib/Makefile
+++ b/arch/mips64/lib/Makefile
@@ -8,9 +8,12 @@
$(CC) $(CFLAGS) -c $< -o $*.o
L_TARGET = lib.a
-L_OBJS = csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \
+
+obj-y += csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \
floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \
rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o \
strnlen_user.o watch.o
+L_OBJS := $(obj-y)
+
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/mm/Makefile b/arch/mips64/mm/Makefile
index fe95aff18..2505f05bd 100644
--- a/arch/mips64/mm/Makefile
+++ b/arch/mips64/mm/Makefile
@@ -1,33 +1,18 @@
-# $Id: Makefile,v 1.4 2000/01/17 23:32:46 ralf Exp $
#
# Makefile for the Linux/MIPS-specific parts of the memory manager.
#
O_TARGET := mm.o
-O_OBJS := extable.o init.o fault.o loadmmu.o
-ifdef CONFIG_CPU_R4300
-O_OBJS += r4xx0.o
-endif
-ifdef CONFIG_CPU_R4X00
-O_OBJS += r4xx0.o
-endif
-ifdef CONFIG_CPU_R5000
-O_OBJS += r4xx0.o
-endif
-ifdef CONFIG_CPU_NEVADA
-O_OBJS += r4xx0.o
-endif
-ifdef CONFIG_CPU_R10000
-O_OBJS += andes.o
-endif
+obj-y := extable.o init.o fault.o loadmmu.o
-ifdef CONFIG_SGI_IP22
-O_OBJS += umap.o
-endif
+obj-$(CONFIG_CPU_R4300) += r4xx0.o
+obj-$(CONFIG_CPU_R4X00) += r4xx0.o
+obj-$(CONFIG_CPU_R5000) += r4xx0.o
+obj-$(CONFIG_CPU_NEVADA) += r4xx0.o
+obj-$(CONFIG_CPU_R10000) += andes.o
+obj-$(CONFIG_SGI_IP22) += umap.o
-ifdef CONFIG_BAGET_MIPS
-O_OBJS += umap.o
-endif
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/sgi-ip22/Makefile b/arch/mips64/sgi-ip22/Makefile
index f303d90da..641fcbddf 100644
--- a/arch/mips64/sgi-ip22/Makefile
+++ b/arch/mips64/sgi-ip22/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1999/08/20 21:13:33 ralf Exp $
#
# Makefile for the SGI specific kernel interface routines
# under Linux.
@@ -10,7 +9,10 @@
$(CC) $(CFLAGS) -c $< -o $*.o
L_TARGET = ip22.a
-L_OBJS = ip22-berr.o ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \
- ip22-setup.o system.o ip22-timer.o ip22-irq.o ip22-reset.o time.o
+
+obj-y += ip22-berr.o ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \
+ ip22-setup.o system.o ip22-timer.o ip22-irq.o ip22-reset.o time.o
+
+L_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/sgi-ip27/Makefile b/arch/mips64/sgi-ip27/Makefile
index cab7e6be5..49dd85cb4 100644
--- a/arch/mips64/sgi-ip27/Makefile
+++ b/arch/mips64/sgi-ip27/Makefile
@@ -8,8 +8,11 @@
$(CC) $(CFLAGS) -c $< -o $*.o
O_TARGET = ip27.a
-O_OBJS = ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
- ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \
- ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o
+
+obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+ ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \
+ ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o
+
+O_OBJS := $(obj-y)
include $(TOPDIR)/Rules.make
diff --git a/arch/mips64/tools/Makefile b/arch/mips64/tools/Makefile
index 3218bfe5f..33d0c17b1 100644
--- a/arch/mips64/tools/Makefile
+++ b/arch/mips64/tools/Makefile
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1999/08/18 21:46:53 ralf Exp $
#
# Makefile for MIPS kernel build tools.
#
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
new file mode 100644
index 000000000..ec27df6b0
--- /dev/null
+++ b/arch/parisc/Makefile
@@ -0,0 +1,91 @@
+#
+# parisc/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) 1994 by Linus Torvalds
+# Portions Copyright (C) 1999 The Puffin Group
+#
+# Modified for PA-RISC Linux by Paul Lahaie, Alex deVries,
+# Mike Shaver, Helge Deller and Martin K. Petersen
+#
+
+FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align
+
+CPP=$(CC) -E
+OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
+LDFLAGS =
+LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux.lds $(LDFLAGS)
+
+CFLAGS_PIPE := -pipe
+CFLAGS_NSR := -fno-strength-reduce
+CFLAGS := $(CFLAGS) -D__linux__ $(CFLAGS_PIPE) $(CFLAGS_NSR)
+
+# These should be on for older toolchains or SOM toolchains that don't
+# enable them by default.
+CFLAGS += -mno-space-regs -mfast-indirect-calls
+
+# If we become able to compile for specific platforms, this should be
+# conditional on that.
+CFLAGS += -mschedule=7200
+
+# No fixed-point multiply
+CFLAGS += -mdisable-fpregs
+
+HEAD = arch/parisc/kernel/head.o
+
+SUBDIRS := $(SUBDIRS) $(addprefix arch/parisc/, tools kernel mm lib hpux)
+CORE_FILES := $(addprefix arch/parisc/, kernel/pdc_cons.o kernel/process.o \
+ lib/lib.a mm/mm.o kernel/kernel.o hpux/hpux.o) \
+ $(CORE_FILES) arch/parisc/kernel/init_task.o
+LIBS := `$(CC) -print-libgcc-file-name` $(TOPDIR)/arch/parisc/lib/lib.a $(LIBS)
+
+ifdef CONFIG_MATH_EMULATION
+SUBDIRS := $(SUBDIRS) arch/parisc/math-emu
+DRIVERS := $(DRIVERS) arch/parisc/math-emu/math.a
+endif
+
+ifdef CONFIG_KWDB
+SUBDIRS := $(SUBDIRS) arch/parisc/kdb
+DRIVERS := $(DRIVERS) arch/parisc/kdb/kdb.o
+
+arch/parisc/kdb: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/kdb
+endif
+
+arch/parisc/kernel: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/kernel
+
+arch/parisc/mm: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/mm
+
+palo: vmlinux
+ export TOPDIR=`pwd`; export CONFIG_STI_CONSOLE=$(CONFIG_STI_CONSOLE); \
+ unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage
+
+Image: palo
+
+Image-clean:
+
+ramdisk.o:
+
+zImage: palo
+
+bzImage: palo
+
+compressed: zImage
+
+install:
+
+archclean:
+
+archmrproper:
+
+archdep:
diff --git a/arch/parisc/config.in b/arch/parisc/config.in
new file mode 100644
index 000000000..eed80181e
--- /dev/null
+++ b/arch/parisc/config.in
@@ -0,0 +1,208 @@
+#
+# For a description of the syntax of this configuration file,
+# see the Configure script.
+#
+
+mainmenu_name "Linux Kernel Configuration"
+
+define_bool CONFIG_PARISC y
+define_bool CONFIG_UID16 n
+
+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 'General options'
+
+# bool 'Symmetric multi-processing support' CONFIG_SMP
+define_bool CONFIG_SMP n
+
+bool 'Kernel Debugger support' CONFIG_KWDB
+# define_bool CONFIG_KWDB n
+
+# bool 'GSC/Gecko bus support' CONFIG_GSC y
+define_bool CONFIG_GSC y
+
+bool 'U2/Uturn I/O MMU' CONFIG_IOMMU_CCIO y
+bool 'LASI I/O support' CONFIG_GSC_LASI y
+
+bool 'PCI bus support' CONFIG_PCI y
+
+if [ "$CONFIG_PCI" = "y" ]; then
+ bool 'GSCtoPCI/DINO PCI support' CONFIG_GSC_DINO y
+ bool 'LBA/Elroy PCI support' CONFIG_PCI_LBA n
+fi
+
+if [ "$CONFIG_PCI_LBA" = "y" ]; then
+ define_bool CONFIG_IOSAPIC y
+ define_bool CONFIG_IOMMU_SBA y
+fi
+
+#
+# if [ "$CONFIG_PCI_EPIC" = "y" ]; then...
+#
+
+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 module loader' CONFIG_KMOD
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'General setup'
+
+bool 'Networking support' CONFIG_NET
+
+bool 'System V IPC' CONFIG_SYSVIPC
+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
+bool 'Sysctl support' CONFIG_SYSCTL
+tristate 'Kernel support for SOM binaries' CONFIG_BINFMT_SOM
+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA
+fi
+
+endmenu
+
+##source drivers/parport/Config.in
+mainmenu_option next_comment
+comment 'Parallel port support'
+
+tristate 'Parallel port support' CONFIG_PARPORT
+if [ "$CONFIG_PARPORT" != "n" ]; then
+ if [ "$CONFIG_PCI" = "y" ]; then
+ dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT_PC" != "n" ]; then
+ bool ' Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool ' SuperIO chipset support (EXPERIMENTAL)' CONFIG_PARPORT_PC_SUPERIO
+ fi
+ fi
+ fi
+ if [ "$CONFIG_GSC_LASI" = "y" ]; then
+ dep_tristate ' LASI/ASP builtin parallel-port' CONFIG_PARPORT_GSC $CONFIG_PARPORT
+ else
+ define_tristate CONFIG_PARPORT_GSC n
+ fi
+
+ # If exactly one hardware type is selected then parport will optimise away
+ # support for loading any others. Defeat this if the user is keen.
+ bool ' Support foreign hardware' CONFIG_PARPORT_OTHER
+
+ bool ' IEEE 1284 transfer modes' CONFIG_PARPORT_1284
+fi
+endmenu
+
+
+source 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
+ comment 'SCSI support type (disk, tape, CDrom)'
+
+ dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+ if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+ fi
+
+ dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+ dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
+ if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
+ bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
+ fi
+ dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
+
+ comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
+ bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
+ bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
+
+ mainmenu_option next_comment
+ comment 'SCSI low-level drivers'
+ if [ "$CONFIG_GSC_LASI" = "y" ]; then
+ dep_tristate 'Lasi SCSI support' CONFIG_SCSI_LASI $CONFIG_SCSI
+ dep_tristate 'Zalon SCSI support' CONFIG_SCSI_ZALON $CONFIG_SCSI
+ fi
+ if [ "$CONFIG_PCI" = "y" ]; then
+ dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI
+ fi
+ if [ "$CONFIG_SCSI_ZALON" != "n" -o "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then
+ int ' default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8
+ int ' maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32
+ int ' synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 20
+ bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE
+ bool ' use normal IO' CONFIG_SCSI_NCR53C8XX_IOMAPPED
+ fi
+ endmenu
+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
+ if [ "$CONFIG_GSC_LASI" = "y" ]; then
+ tristate 'Lasi ethernet' CONFIG_LASI_82596
+ fi
+ source drivers/net/Config.in
+ fi
+ endmenu
+fi
+
+source drivers/char/Config.in
+
+source fs/Config.in
+
+mainmenu_option next_comment
+comment 'Sound Drivers'
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+ source drivers/sound/Config.in
+fi
+endmenu
+
+if [ "$CONFIG_VT" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Console drivers'
+ source drivers/video/Config.in
+
+# bool 'IODC console' CONFIG_IODC_CONSOLE
+ bool 'STI console' CONFIG_STI_CONSOLE
+ if [ "$CONFIG_IODC_CONSOLE" = "n" ]; then
+ if [ "$CONFIG_GSC_PS2" = "y" ]; then
+ define_bool CONFIG_DUMMY_CONSOLE y
+ fi
+ fi
+ if [ "$CONFIG_STI_CONSOLE" = "y" ]; then
+ define_bool CONFIG_DUMMY_CONSOLE y
+ fi
+ endmenu
+fi
+# endmenu
+
+mainmenu_option next_comment
+comment 'Kernel hacking'
+
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+endmenu
+
diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig
new file mode 100644
index 000000000..352fa78c0
--- /dev/null
+++ b/arch/parisc/defconfig
@@ -0,0 +1,363 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_PARISC=y
+# CONFIG_UID16 is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General options
+#
+# CONFIG_SMP is not set
+# CONFIG_KWDB is not set
+CONFIG_GSC=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_PCI=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_IOSAPIC=y
+CONFIG_IOMMU_SBA=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_BINFMT_SOM=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_BINFMT_JAVA is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+# CONFIG_PARPORT_PC is not set
+CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER 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=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=y
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SCSI_LASI=y
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_LASI_82596=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DE4X5 is not set
+CONFIG_TULIP=y
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_GSC_PS2=y
+CONFIG_HIL=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_SERIAL_GSC=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_GENRTC=y
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Sound Drivers
+#
+# CONFIG_SOUND is not set
+
+#
+# Console drivers
+#
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+# CONFIG_STI_CONSOLE is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/parisc/hpux/Makefile b/arch/parisc/hpux/Makefile
new file mode 100644
index 000000000..d946959be
--- /dev/null
+++ b/arch/parisc/hpux/Makefile
@@ -0,0 +1,16 @@
+#
+# 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).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+all: hpux.o
+O_TARGET = hpux.o
+O_OBJS = entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o
+
+.o.S: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/hpux/entry_hpux.S b/arch/parisc/hpux/entry_hpux.S
new file mode 100644
index 000000000..165aeb6af
--- /dev/null
+++ b/arch/parisc/hpux/entry_hpux.S
@@ -0,0 +1,537 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ *
+ * modified by Matthew Wilcox <willy@bofh.ai> 1999-07-26
+ */
+
+
+#define ASSEMBLY
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+
+ .text
+
+#define ENTRY_NAME(_name_) .word _name_
+
+ .align 4
+ .export hpux_call_table
+hpux_call_table:
+ ENTRY_NAME(sys_ni_syscall) /* 0 */
+ ENTRY_NAME(sys_exit)
+ ENTRY_NAME(hpux_fork_wrapper)
+ ENTRY_NAME(sys_read)
+ ENTRY_NAME(sys_write)
+ ENTRY_NAME(sys_open) /* 5 */
+ ENTRY_NAME(sys_close)
+ ENTRY_NAME(hpux_wait)
+ ENTRY_NAME(sys_creat)
+ ENTRY_NAME(sys_link)
+ ENTRY_NAME(sys_unlink) /* 10 */
+ ENTRY_NAME(hpux_execv_wrapper)
+ ENTRY_NAME(sys_chdir)
+ ENTRY_NAME(sys_time)
+ ENTRY_NAME(sys_mknod)
+ ENTRY_NAME(sys_chmod) /* 15 */
+ ENTRY_NAME(sys_chown)
+ ENTRY_NAME(hpux_brk)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_lseek)
+ ENTRY_NAME(sys_getpid) /* 20 */
+ ENTRY_NAME(hpux_mount)
+ ENTRY_NAME(sys_oldumount)
+ ENTRY_NAME(sys_setuid)
+ ENTRY_NAME(sys_getuid)
+ ENTRY_NAME(sys_stime) /* 25 */
+ ENTRY_NAME(hpux_ptrace)
+ ENTRY_NAME(sys_alarm)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_pause)
+ ENTRY_NAME(sys_utime) /* 30 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_access)
+ ENTRY_NAME(hpux_nice)
+ ENTRY_NAME(sys_ni_syscall) /* 35 */
+ ENTRY_NAME(sys_sync)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_newstat)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_newlstat) /* 40 */
+ ENTRY_NAME(sys_dup)
+ ENTRY_NAME(hpux_pipe_wrapper)
+ ENTRY_NAME(sys_times)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 45 */
+ ENTRY_NAME(sys_setgid)
+ ENTRY_NAME(sys_getgid)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 50 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_ioctl)
+ ENTRY_NAME(sys_ni_syscall) /* 55 */
+ ENTRY_NAME(sys_symlink)
+ ENTRY_NAME(hpux_utssys)
+ ENTRY_NAME(sys_readlink)
+ ENTRY_NAME(hpux_execve_wrapper)
+ ENTRY_NAME(sys_umask) /* 60 */
+ ENTRY_NAME(sys_chroot)
+ ENTRY_NAME(sys_fcntl)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 65 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_sbrk)
+ ENTRY_NAME(sys_ni_syscall) /* 70 */
+ ENTRY_NAME(sys_mmap)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 75 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 80 */
+ ENTRY_NAME(sys_getpgid)
+ ENTRY_NAME(sys_setpgid)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 85 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_dup2) /* 90 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_newfstat)
+ ENTRY_NAME(sys_select)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 95 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 100 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 105 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 110 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 115 */
+ ENTRY_NAME(sys_gettimeofday)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 120 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_fchown)
+ ENTRY_NAME(sys_fchmod)
+ ENTRY_NAME(sys_ni_syscall) /* 125 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_rename)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 130 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_sysconf)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 135 */
+ ENTRY_NAME(sys_mkdir)
+ ENTRY_NAME(sys_rmdir)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 140 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 145 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 150 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 155 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 160 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 165 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 170 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 175 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 180 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 185 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 190 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_getdomainname)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 195 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_waitpid) /* 200 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 205 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 210 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 215 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 220 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 225 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 230 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 235 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 240 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 245 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 250 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 255 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 260 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 265 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 270 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_fchdir)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_accept) /* 275 */
+ ENTRY_NAME(sys_bind)
+ ENTRY_NAME(sys_connect)
+ ENTRY_NAME(sys_getpeername)
+ ENTRY_NAME(sys_getsockname)
+ ENTRY_NAME(sys_getsockopt) /* 280 */
+ ENTRY_NAME(sys_listen)
+ ENTRY_NAME(sys_recv)
+ ENTRY_NAME(sys_recvfrom)
+ ENTRY_NAME(sys_recvmsg)
+ ENTRY_NAME(sys_send) /* 285 */
+ ENTRY_NAME(sys_sendmsg)
+ ENTRY_NAME(sys_sendto)
+ ENTRY_NAME(sys_setsockopt)
+ ENTRY_NAME(sys_shutdown)
+ ENTRY_NAME(sys_socket) /* 290 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 295 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 300 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 305 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 310 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 315 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 320 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 325 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 330 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_lchown)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 335 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 340 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 345 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 350 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_nanosleep)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 355 */
+ ENTRY_NAME(hpux_getdents)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 360 */
+ ENTRY_NAME(hpux_fstat64)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 365 */
+ ENTRY_NAME(hpux_lstat64)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(hpux_stat64)
+ ENTRY_NAME(sys_ni_syscall) /* 370 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 375 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 380 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 385 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 390 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 395 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 400 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 405 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 410 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 415 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 420 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 425 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 430 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 435 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 440 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 445 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 450 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 455 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 460 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 465 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 470 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 475 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 480 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 485 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 490 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 495 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 500 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 505 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall) /* 510 */
+ ENTRY_NAME(sys_ni_syscall)
+ ENTRY_NAME(sys_ni_syscall)
+.end
+
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
new file mode 100644
index 000000000..4957a05f8
--- /dev/null
+++ b/arch/parisc/hpux/fs.c
@@ -0,0 +1,250 @@
+/*
+ * linux/arch/parisc/kernel/sys_hpux.c
+ *
+ * implements HPUX syscalls.
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+int hpux_execve(struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname((char *) regs->gr[26]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+
+ error = do_execve(filename, (char **) regs->gr[25],
+ (char **)regs->gr[24], regs);
+
+ if (error == 0)
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+
+out:
+ return error;
+}
+
+struct hpux_dirent {
+ long d_off_pad; /* we only have a 32-bit off_t */
+ long d_off;
+ ino_t d_ino;
+ short d_reclen;
+ short d_namlen;
+ char d_name[1];
+};
+
+struct getdents_callback {
+ struct hpux_dirent *current_dir;
+ struct hpux_dirent *previous;
+ int count;
+ int error;
+};
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+
+static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
+{
+ struct hpux_dirent * dirent;
+ struct getdents_callback * buf = (struct getdents_callback *) __buf;
+ int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+ buf->error = -EINVAL; /* only used if we fail.. */
+ if (reclen > buf->count)
+ return -EINVAL;
+ dirent = buf->previous;
+ if (dirent)
+ put_user(offset, &dirent->d_off);
+ dirent = buf->current_dir;
+ buf->previous = dirent;
+ put_user(ino, &dirent->d_ino);
+ put_user(reclen, &dirent->d_reclen);
+ put_user(namlen, &dirent->d_namlen);
+ copy_to_user(dirent->d_name, name, namlen);
+ put_user(0, dirent->d_name + namlen);
+ ((char *) dirent) += reclen;
+ buf->current_dir = dirent;
+ buf->count -= reclen;
+ return 0;
+}
+
+#undef NAME_OFFSET
+#undef ROUND_UP
+
+int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count)
+{
+ struct file * file;
+ struct dentry * dentry;
+ struct inode * inode;
+ struct hpux_dirent * lastdirent;
+ struct getdents_callback buf;
+ int error;
+
+ lock_kernel();
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out_putf;
+
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out_putf;
+
+ buf.current_dir = dirent;
+ buf.previous = NULL;
+ buf.count = count;
+ buf.error = 0;
+
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out_putf;
+
+ /*
+ * Get the inode's semaphore to prevent changes
+ * to the directory while we read it.
+ */
+ down(&inode->i_sem);
+ error = file->f_op->readdir(file, &buf, filldir);
+ up(&inode->i_sem);
+ if (error < 0)
+ goto out_putf;
+ error = buf.error;
+ lastdirent = buf.previous;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
+ }
+
+out_putf:
+ fput(file);
+out:
+ unlock_kernel();
+ return error;
+}
+
+int hpux_mount(const char *fs, const char *path, int mflag,
+ const char *fstype, const char *dataptr, int datalen)
+{
+ return -ENOSYS;
+}
+
+static int cp_hpux_stat(struct inode * inode, struct hpux_stat64 * statbuf)
+{
+ struct hpux_stat64 tmp;
+ unsigned int blocks, indirect;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.st_dev = kdev_t_to_nr(inode->i_dev);
+ tmp.st_ino = inode->i_ino;
+ tmp.st_mode = inode->i_mode;
+ tmp.st_nlink = inode->i_nlink;
+ tmp.st_uid = inode->i_uid;
+ tmp.st_gid = inode->i_gid;
+ tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
+ tmp.st_size = inode->i_size;
+ tmp.st_atime = inode->i_atime;
+ tmp.st_mtime = inode->i_mtime;
+ tmp.st_ctime = inode->i_ctime;
+
+#define D_B 7
+#define I_B (BLOCK_SIZE / sizeof(unsigned short))
+
+ if (!inode->i_blksize) {
+ blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ if (blocks > D_B) {
+ indirect = (blocks - D_B + I_B - 1) / I_B;
+ blocks += indirect;
+ if (indirect > 1) {
+ indirect = (indirect - 1 + I_B - 1) / I_B;
+ blocks += indirect;
+ if (indirect > 1)
+ blocks++;
+ }
+ }
+ tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
+ tmp.st_blksize = BLOCK_SIZE;
+ } else {
+ tmp.st_blocks = inode->i_blocks;
+ tmp.st_blksize = inode->i_blksize;
+ }
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+/*
+ * Revalidate the inode. This is required for proper NFS attribute caching.
+ * Blatently copied wholesale from fs/stat.c
+ */
+static __inline__ int
+do_revalidate(struct dentry *dentry)
+{
+ struct inode * inode = dentry->d_inode;
+ if (inode->i_op && inode->i_op->revalidate)
+ return inode->i_op->revalidate(dentry);
+ return 0;
+}
+
+long hpux_stat64(const char *path, struct hpux_stat64 *buf)
+{
+ struct nameidata nd;
+ int error;
+
+ lock_kernel();
+ error = user_path_walk(path, &nd);
+ if (!error) {
+ error = do_revalidate(nd.dentry);
+ if (!error)
+ error = cp_hpux_stat(nd.dentry->d_inode, buf);
+ path_release(&nd);
+ }
+ unlock_kernel();
+ return error;
+}
+
+long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf)
+{
+ struct file * f;
+ int err = -EBADF;
+
+ lock_kernel();
+ f = fget(fd);
+ if (f) {
+ struct dentry * dentry = f->f_dentry;
+
+ err = do_revalidate(dentry);
+ if (!err)
+ err = cp_hpux_stat(dentry->d_inode, statbuf);
+ fput(f);
+ }
+ unlock_kernel();
+ return err;
+}
+
+long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf)
+{
+ struct nameidata nd;
+ int error;
+
+ lock_kernel();
+ error = user_path_walk_link(filename, &nd);
+ if (!error) {
+ error = do_revalidate(nd.dentry);
+ if (!error)
+ error = cp_hpux_stat(nd.dentry->d_inode, statbuf);
+ path_release(&nd);
+ }
+ unlock_kernel();
+ return error;
+}
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S
new file mode 100644
index 000000000..0b8976386
--- /dev/null
+++ b/arch/parisc/hpux/gate.S
@@ -0,0 +1,72 @@
+/* ------------------------------------------------------------------------------
+ *
+ * Linux/PARISC Project (http://www.thepuffingroup.com/parisc)
+ *
+ * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
+ * Licensed under the GNU GPL.
+ * thanks to Philipp Rumpf, Mike Shaver and various others
+ * sorry about the wall, puffin..
+ */
+
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/offset.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+ .text
+
+ .import hpux_call_table
+ .import hpux_syscall_exit,code
+ .export hpux_gateway_page
+
+ .align 4096
+hpux_gateway_page:
+ nop
+ mfsp %sr7,%r1 ;! we must set sr3 to the space
+ mtsp %r1,%sr3 ;! of the user before the gate
+#ifdef __LP64__
+#warning NEEDS WORK for 64-bit
+#endif
+ ldw -64(%r30), %r28 ;! 8th argument
+ ldw -60(%r30), %r19 ;! 7th argument
+ ldw -56(%r30), %r20 ;! 6th argument
+ ldw -52(%r30), %r21 ;! 5th argument
+ gate .+8, %r0 ;! become privileged
+ mtsp %r0,%sr4 ;! get kernel space into sr4
+ mtsp %r0,%sr5 ;! get kernel space into sr5
+ mtsp %r0,%sr6 ;! get kernel space into sr6
+ mtsp %r0,%sr7 ;! get kernel space into sr7
+ mfctl %cr30,%r1 ;! get the kernel task ptr
+ mtctl %r0,%cr30 ;! zero it (flag)
+ STREG %r30,TASK_PT_GR30(%r1) ;! preserve userspace sp
+ STREG %r2,TASK_PT_GR2(%r1) ;! preserve rp
+ STREG %r27,TASK_PT_GR27(%r1) ;! user dp
+ STREG %r31,TASK_PT_GR31(%r1) ;! preserve syscall return ptr
+
+ loadgp ;! setup kernel dp
+
+ ldo TASK_SZ_ALGN+64(%r1),%r30 ;! set up kernel stack
+
+ stw %r21, -52(%r30) ;! 5th argument
+ stw %r20, -56(%r30) ;! 6th argument
+ stw %r19, -60(%r30) ;! 7th argument
+ stw %r28, -64(%r30) ;! 8th argument
+
+ ldil L%hpux_call_table, %r21
+ ldo R%hpux_call_table(%r21), %r21
+ comiclr,>>= __NR_HPUX_syscalls, %r22, %r0
+ b,n syscall_nosys
+ ldwx,s %r22(%r21), %r21
+ ldil L%hpux_syscall_exit,%r2
+ be 0(%sr7,%r21)
+ ldo R%hpux_syscall_exit(%r2),%r2
+
+syscall_nosys:
+ ldil L%hpux_syscall_exit,%r1
+ be R%hpux_syscall_exit(%sr7,%r1)
+ ldo -ENOSYS(%r0),%r28
+
+ .align 4096
+ .export end_hpux_gateway_page
+end_hpux_gateway_page:
diff --git a/arch/parisc/hpux/ioctl.c b/arch/parisc/hpux/ioctl.c
new file mode 100644
index 000000000..9087123e1
--- /dev/null
+++ b/arch/parisc/hpux/ioctl.c
@@ -0,0 +1,63 @@
+/*
+ * linux/arch/parisc/hpux/ioctl.c
+ *
+ * implements some necessary HPUX ioctls.
+ */
+
+/*
+ * Supported ioctls:
+ * TCGETA
+ * TCSETA
+ * TCSETAW
+ * TCSETAF
+ * TCSBRK
+ * TCXONC
+ * TCFLSH
+ * TIOCGWINSZ
+ * TIOCSWINSZ
+ * TIOCGPGRP
+ * TIOCSPGRP
+ */
+
+#include <linux/smp_lock.h>
+#include <asm/errno.h>
+#include <asm/ioctl.h>
+#include <asm/termios.h>
+#include <asm/uaccess.h>
+
+int sys_ioctl(unsigned int, unsigned int, unsigned long);
+
+static int hpux_ioctl_t(int fd, unsigned long cmd, unsigned long arg)
+{
+ int result = -EOPNOTSUPP;
+ int nr = _IOC_NR(cmd);
+ switch (nr) {
+ case 106:
+ result = sys_ioctl(fd, TIOCSWINSZ, arg);
+ break;
+ case 107:
+ result = sys_ioctl(fd, TIOCGWINSZ, arg);
+ break;
+ }
+ return result;
+}
+
+int hpux_ioctl(int fd, unsigned long cmd, unsigned long arg)
+{
+ int result = -EOPNOTSUPP;
+ int type = _IOC_TYPE(cmd);
+ switch (type) {
+ case 'T':
+ /* Our structures are now compatible with HPUX's */
+ result = sys_ioctl(fd, cmd, arg);
+ break;
+ case 't':
+ result = hpux_ioctl_t(fd, cmd, arg);
+ break;
+ default:
+ /* If my mother ever sees this, I hope she disowns me.
+ * Take this out after NYLWE. */
+ result = sys_ioctl(fd, cmd, arg);
+ }
+ return result;
+}
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
new file mode 100644
index 000000000..e0c832e76
--- /dev/null
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -0,0 +1,334 @@
+/*
+ * linux/arch/parisc/kernel/sys_hpux.c
+ *
+ * implements HPUX syscalls.
+ */
+
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/utsname.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+unsigned long sys_brk(unsigned long addr);
+
+unsigned long hpux_brk(unsigned long addr)
+{
+ /* Sigh. Looks like HP/UX libc relies on kernel bugs. */
+ return sys_brk(addr + PAGE_SIZE);
+}
+
+int hpux_sbrk(void)
+{
+ return -ENOSYS;
+}
+
+/* Random other syscalls */
+
+int hpux_nice(int priority_change)
+{
+ return -ENOSYS;
+}
+
+int hpux_ptrace(void)
+{
+ return -ENOSYS;
+}
+
+int hpux_wait(int *stat_loc)
+{
+ extern int sys_waitpid(int, int *, int);
+ return sys_waitpid(-1, stat_loc, 0);
+}
+
+#define _SC_CPU_VERSION 10001
+#define _SC_OPEN_MAX 4
+#define CPU_PA_RISC1_1 0x210
+
+int hpux_sysconf(int which)
+{
+ switch (which) {
+ case _SC_CPU_VERSION:
+ return CPU_PA_RISC1_1;
+ case _SC_OPEN_MAX:
+ return INT_MAX;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*****************************************************************************/
+
+#define HPUX_UTSLEN 9
+#define HPUX_SNLEN 15
+
+struct hpux_utsname {
+ char sysname[HPUX_UTSLEN];
+ char nodename[HPUX_UTSLEN];
+ char release[HPUX_UTSLEN];
+ char version[HPUX_UTSLEN];
+ char machine[HPUX_UTSLEN];
+ char idnumber[HPUX_SNLEN];
+} ;
+
+struct hpux_ustat {
+ int32_t f_tfree; /* total free (daddr_t) */
+ u_int32_t f_tinode; /* total inodes free (ino_t) */
+ char f_fname[6]; /* filsys name */
+ char f_fpack[6]; /* filsys pack name */
+ u_int32_t f_blksize; /* filsys block size (int) */
+};
+
+/*
+ * HPUX's utssys() call. It's a collection of miscellaneous functions,
+ * alas, so there's no nice way of splitting them up.
+ */
+
+/* This function is called from hpux_utssys(); HP-UX implements
+ * ustat() as an option to utssys().
+ *
+ * Now, struct ustat on HP-UX is exactly the same as on Linux, except
+ * that it contains one addition field on the end, int32_t f_blksize.
+ * So, we could have written this function to just call the Linux
+ * sys_ustat(), (defined in linux/fs/super.c), and then just
+ * added this additional field to the user's structure. But I figure
+ * if we're gonna be digging through filesystem structures to get
+ * this, we might as well just do the whole enchilada all in one go.
+ *
+ * So, most of this function is almost identical to sys_ustat().
+ * I have placed comments at the few lines changed or added, to
+ * aid in porting forward if and when sys_ustat() is changed from
+ * its form in kernel 2.2.5.
+ */
+static int hpux_ustat(dev_t dev, struct hpux_ustat *ubuf)
+{
+ struct super_block *s;
+ struct hpux_ustat tmp; /* Changed to hpux_ustat */
+ struct statfs sbuf;
+ int err = -EINVAL;
+
+ lock_kernel();
+ s = get_super(to_kdev_t(dev));
+ if (s == NULL)
+ goto out;
+ err = vfs_statfs(s, &sbuf);
+ if (err)
+ goto out;
+
+ memset(&tmp,0,sizeof(struct hpux_ustat)); /* Changed to hpux_ustat */
+
+ tmp.f_tfree = (int32_t)sbuf.f_bfree;
+ tmp.f_tinode = (u_int32_t)sbuf.f_ffree;
+ tmp.f_blksize = (u_int32_t)sbuf.f_bsize; /* Added this line */
+
+ /* Changed to hpux_ustat: */
+ err = copy_to_user(ubuf,&tmp,sizeof(struct hpux_ustat)) ? -EFAULT : 0;
+out:
+ unlock_kernel();
+ return err;
+}
+
+
+/* This function is called from hpux_utssys(); HP-UX implements
+ * uname() as an option to utssys().
+ *
+ * The form of this function is pretty much copied from sys_olduname(),
+ * defined in linux/arch/i386/kernel/sys_i386.c.
+ */
+/* TODO: Are these put_user calls OK? Should they pass an int?
+ * (I copied it from sys_i386.c like this.)
+ */
+static int hpux_uname(struct hpux_utsname *name)
+{
+ int error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct hpux_utsname)))
+ return -EFAULT;
+
+ down_read(&uts_sem);
+
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->sysname+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->nodename+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->release,&system_utsname.release,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->release+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->version,&system_utsname.version,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->version+HPUX_UTSLEN-1);
+ error |= __copy_to_user(&name->machine,&system_utsname.machine,HPUX_UTSLEN-1);
+ error |= __put_user(0,name->machine+HPUX_UTSLEN-1);
+
+ up_read(&uts_sem);
+
+ /* HP-UX utsname has no domainname field. */
+
+ /* TODO: Implement idnumber!!! */
+#if 0
+ error |= __put_user(0,name->idnumber);
+ error |= __put_user(0,name->idnumber+HPUX_SNLEN-1);
+#endif
+
+ error = error ? -EFAULT : 0;
+
+ return error;
+}
+
+int sys_sethostname(char *, int);
+int sys_gethostname(char *, int);
+
+/* Note: HP-UX just uses the old suser() function to check perms
+ * in this system call. We'll use capable(CAP_SYS_ADMIN).
+ */
+int hpux_utssys(char *ubuf, int n, int type)
+{
+ int len;
+ int error;
+ switch( type ) {
+ case 0:
+ /* uname(): */
+ return( hpux_uname( (struct hpux_utsname *)ubuf ) );
+ break ;
+ case 1:
+ /* Obsolete (used to be umask().) */
+ return -EFAULT ;
+ break ;
+ case 2:
+ /* ustat(): */
+ return( hpux_ustat((dev_t)n, (struct hpux_ustat *)ubuf) );
+ break ;
+ case 3:
+ /* setuname():
+ *
+ * On linux (unlike HP-UX), utsname.nodename
+ * is the same as the hostname.
+ *
+ * sys_sethostname() is defined in linux/kernel/sys.c.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ return( sys_sethostname(ubuf, len) );
+ break ;
+ case 4:
+ /* sethostname():
+ *
+ * sys_sethostname() is defined in linux/kernel/sys.c.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ return( sys_sethostname(ubuf, len) );
+ break ;
+ case 5:
+ /* gethostname():
+ *
+ * sys_gethostname() is defined in linux/kernel/sys.c.
+ */
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ return( sys_gethostname(ubuf, n) );
+ break ;
+ case 6:
+ /* Supposedly called from setuname() in libc.
+ * TODO: When and why is this called?
+ * Is it ever even called?
+ *
+ * This code should look a lot like sys_sethostname(),
+ * defined in linux/kernel/sys.c. If that gets updated,
+ * update this code similarly.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ /**/
+ /* TODO: print a warning about using this? */
+ down_write(&uts_sem);
+ error = -EFAULT;
+ if (!copy_from_user(system_utsname.sysname, ubuf, len)) {
+ system_utsname.sysname[len] = 0;
+ error = 0;
+ }
+ up_write(&uts_sem);
+ return error;
+ break ;
+ case 7:
+ /* Sets utsname.release, if you're allowed.
+ * Undocumented. Used by swinstall to change the
+ * OS version, during OS updates. Yuck!!!
+ *
+ * This code should look a lot like sys_sethostname()
+ * in linux/kernel/sys.c. If that gets updated, update
+ * this code similarly.
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ /* Unlike Linux, HP-UX returns an error if n==0: */
+ if ( n <= 0 )
+ return -EINVAL ;
+ /* Unlike Linux, HP-UX truncates it if n is too big: */
+ len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ;
+ /**/
+ /* TODO: print a warning about this? */
+ down_write(&uts_sem);
+ error = -EFAULT;
+ if (!copy_from_user(system_utsname.release, ubuf, len)) {
+ system_utsname.release[len] = 0;
+ error = 0;
+ }
+ up_write(&uts_sem);
+ return error;
+ break ;
+ default:
+ /* This system call returns -EFAULT if given an unknown type.
+ * Why not -EINVAL? I don't know, it's just not what they did.
+ */
+ return -EFAULT ;
+ }
+}
+
+int hpux_getdomainname(char *name, int len)
+{
+ int nlen;
+ int err = -EFAULT;
+
+ down_read(&uts_sem);
+
+ nlen = strlen(system_utsname.domainname) + 1;
+
+ if (nlen < len)
+ len = nlen;
+ if(len > __NEW_UTS_LEN)
+ goto done;
+ if(copy_to_user(name, system_utsname.domainname, len))
+ goto done;
+ err = 0;
+done:
+ up_read(&uts_sem);
+ return err;
+
+}
+
+int hpux_pipe(int *kstack_fildes)
+{
+ int error;
+
+ lock_kernel();
+ error = do_pipe(kstack_fildes);
+ unlock_kernel();
+ return error;
+}
diff --git a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S
new file mode 100644
index 000000000..c150783d9
--- /dev/null
+++ b/arch/parisc/hpux/wrappers.S
@@ -0,0 +1,244 @@
+/*------------------------------------------------------------------------------
+ * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ *
+ * HP-UX System Call Wrapper routines and System Call Return Path
+ *
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __LP64__
+#warning Must be changed for PA64
+#endif
+
+#include <asm/offset.h>
+
+ .level 1.1
+ .text
+
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/signal.h>
+
+ /* These should probably go in a header file somewhere.
+ * They are duplicated in kernel/wrappers.S
+ * Possibly we should consider consolidating these
+ * register save/restore macros.
+ */
+ .macro reg_save regs
+#ifdef __LP64__
+#warning NEEDS WORK for 64-bit
+#endif
+ stw %r3, PT_GR3(\regs)
+ stw %r4, PT_GR4(\regs)
+ stw %r5, PT_GR5(\regs)
+ stw %r6, PT_GR6(\regs)
+ stw %r7, PT_GR7(\regs)
+ stw %r8, PT_GR8(\regs)
+ stw %r9, PT_GR9(\regs)
+ stw %r10,PT_GR10(\regs)
+ stw %r11,PT_GR11(\regs)
+ stw %r12,PT_GR12(\regs)
+ stw %r13,PT_GR13(\regs)
+ stw %r14,PT_GR14(\regs)
+ stw %r15,PT_GR15(\regs)
+ stw %r16,PT_GR16(\regs)
+ stw %r17,PT_GR17(\regs)
+ stw %r18,PT_GR18(\regs)
+ .endm
+
+ .macro reg_restore regs
+ ldw PT_GR3(\regs), %r3
+ ldw PT_GR4(\regs), %r4
+ ldw PT_GR5(\regs), %r5
+ ldw PT_GR6(\regs), %r6
+ ldw PT_GR7(\regs), %r7
+ ldw PT_GR8(\regs), %r8
+ ldw PT_GR9(\regs), %r9
+ ldw PT_GR10(\regs),%r10
+ ldw PT_GR11(\regs),%r11
+ ldw PT_GR12(\regs),%r12
+ ldw PT_GR13(\regs),%r13
+ ldw PT_GR14(\regs),%r14
+ ldw PT_GR15(\regs),%r15
+ ldw PT_GR16(\regs),%r16
+ ldw PT_GR17(\regs),%r17
+ ldw PT_GR18(\regs),%r18
+ .endm
+
+
+ .export hpux_fork_wrapper
+ .import sys_fork
+
+hpux_fork_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+ ;! pointer in task
+ reg_save %r1
+
+ stw %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ stw %r2,PT_GR19(%r1) ;! save for child
+ stw %r30,PT_GR20(%r1) ;! save for child
+ ldil L%child_return,%r3
+ ldo R%child_return(%r3),%r3
+ stw %r3,PT_GR21(%r1) ;! save for child
+
+ ldw TASK_PT_GR30(%r1),%r25
+ copy %r1,%r24
+ bl sys_clone,%r2
+ ldi SIGCHLD,%r26
+
+ ldw -84(%r30),%r2
+fork_return:
+ ldo -64(%r30),%r30
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+
+ reg_restore %r1
+
+ /*
+ * HP-UX wants pid (child gets parent pid, parent gets child pid)
+ * in r28 and a flag in r29 (r29 == 1 for child, 0 for parent).
+ * Linux fork returns 0 for child, pid for parent. Since HP-UX
+ * libc stub throws away parent pid and returns 0 for child,
+ * we'll just return 0 for parent pid now. Only applications
+ * that jump directly to the gateway page (not supported) will
+ * know the difference. We can fix this later if necessary.
+ */
+
+ ldo -1024(%r0),%r1
+ comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */
+ or,= %r28,%r0,%r0
+ or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */
+ ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */
+
+fork_exit:
+ bv %r0(%r2)
+ nop
+
+ /* Set the return value for the child */
+
+child_return:
+ ldw TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
+ b fork_return
+ copy %r0,%r28
+
+ .export hpux_execve_wrapper
+ .export hpux_execv_wrapper
+ .import hpux_execve
+
+hpux_execv_wrapper:
+ copy %r0,%r24 /* NULL environment */
+
+hpux_execve_wrapper:
+
+ ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs
+
+ /*
+ * Do we need to save/restore r3-r18 here?
+ * I don't think so. why would new thread need old
+ * threads registers?
+ */
+
+ /* Store arg0, arg1 and arg2 so that hpux_execve will find them */
+
+ stw %r26,PT_GR26(%r1)
+ stw %r25,PT_GR25(%r1)
+ stw %r24,PT_GR24(%r1)
+
+ stw %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ bl hpux_execve,%r2
+ copy %r1,%arg0
+
+ ldo -64(%r30),%r30
+ ldw -20(%r30),%r2
+
+ /* If exec succeeded we need to load the args */
+
+ ldo -1024(%r0),%r1
+ comb,>>= %r28,%r1,exec_error
+ copy %r2,%r19
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr
+ ldw TASK_PT_GR26(%r1),%r26
+ ldw TASK_PT_GR25(%r1),%r25
+ ldw TASK_PT_GR24(%r1),%r24
+ ldw TASK_PT_GR23(%r1),%r23
+ copy %r0,%r2 /* Flag to syscall_exit not to clear args */
+
+exec_error:
+ bv %r0(%r19)
+ nop
+
+ .export hpux_pipe_wrapper
+ .import hpux_pipe
+
+ /* HP-UX expects pipefd's returned in r28 & r29 */
+
+hpux_pipe_wrapper:
+ stw %r2,-20(%r30)
+ ldo 64(%r30),%r30
+ bl hpux_pipe,%r2
+ ldo -56(%r30),%r26 /* pass local array to hpux_pipe */
+
+
+ ldo -1024(%r0),%r1
+ comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */
+ ldw -84(%r30),%r2
+
+ /* if success, load fd's from stack array */
+
+ ldw -56(%r30),%r28
+ ldw -52(%r30),%r29
+
+pipe_exit:
+ bv %r0(%r2)
+ ldo -64(%r30),%r30
+
+ .export hpux_syscall_exit
+ .import syscall_exit
+
+hpux_syscall_exit:
+
+ /*
+ *
+ * HP-UX call return conventions:
+ *
+ * if error:
+ * r22 = 1
+ * r28 = errno value
+ * r29 = secondary return value
+ * else
+ * r22 = 0
+ * r28 = return value
+ * r29 = secondary return value
+ *
+ * For now, we'll just check to see if r28 is < (unsigned long)-1024
+ * (to handle addresses > 2 Gb) and if so set r22 to zero. If not,
+ * we'll complement r28 and set r22 to 1. Wrappers will be
+ * needed for syscalls that care about the secondary return value.
+ * The wrapper may also need a way of avoiding the following code,
+ * but we'll deal with that when it becomes necessary.
+ */
+
+ ldo -1024(%r0),%r1
+ comb,<< %r28,%r1,no_error
+ copy %r0,%r22
+ subi 0,%r28,%r28
+ ldo 1(%r0),%r22
+
+no_error:
+ b syscall_exit
+ nop
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
new file mode 100644
index 000000000..03ce8e58b
--- /dev/null
+++ b/arch/parisc/kernel/Makefile
@@ -0,0 +1,52 @@
+#
+# 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).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+all: kernel.o init_task.o pdc_cons.o process.o head.o
+O_TARGET = kernel.o
+O_OBJS =
+
+# Object file lists.
+
+obj-y :=
+obj-m :=
+obj-n :=
+obj- :=
+
+obj-y += cache.o setup.o traps.o time.o irq.o \
+ syscall.o entry.o sys_parisc.o pdc.o ptrace.o hardware.o \
+ inventory.o drivers.o semaphore.o pa7300lc.o pci-dma.o \
+ signal.o hpmc.o \
+ real1.o real2.o led.o parisc_ksyms.o
+
+export-objs := parisc_ksyms.o
+
+
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_VT) += keyboard.o
+obj-$(CONFIG_PCI_LBA) += lba_pci.o
+# I/O SAPIC is also on IA64 platforms.
+# The two could be merged into a common source some day.
+obj-$(CONFIG_IOSAPIC) += iosapic.o
+obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o
+# Only use one of them: ccio-rm-dma is for PCX-W systems *only*
+# obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o
+obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o
+
+.o.S: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
+
+# Translate to Rules.make lists.
+
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS := $(filter $(export-objs), $(obj-y))
+M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
+MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
+MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
new file mode 100644
index 000000000..713a8b39a
--- /dev/null
+++ b/arch/parisc/kernel/cache.c
@@ -0,0 +1,253 @@
+/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
+ *
+ * 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) 1999 Helge Deller (07-13-1999)
+ * Copyright (C) 1999 SuSE GmbH Nuernberg
+ * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org)
+ *
+ * Cache and TLB management
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/pdc.h>
+#include <asm/cache.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+
+struct pdc_cache_info cache_info;
+#ifndef __LP64__
+static struct pdc_btlb_info btlb_info;
+#endif
+
+
+void __flush_page_to_ram(unsigned long address)
+{
+ __flush_dcache_range(address, PAGE_SIZE);
+ __flush_icache_range(address, PAGE_SIZE);
+}
+
+
+
+void flush_data_cache(void)
+{
+ register unsigned long base = cache_info.dc_base;
+ register unsigned long count = cache_info.dc_count;
+ register unsigned long loop = cache_info.dc_loop;
+ register unsigned long stride = cache_info.dc_stride;
+ register unsigned long addr;
+ register long i, j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ fdce(addr);
+}
+
+static inline void flush_data_tlb_space(void)
+{
+ unsigned long base = cache_info.dt_off_base;
+ unsigned long count = cache_info.dt_off_count;
+ unsigned long stride = cache_info.dt_off_stride;
+ unsigned long loop = cache_info.dt_loop;
+
+ unsigned long addr;
+ long i,j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ pdtlbe(addr);
+}
+
+
+
+void flush_data_tlb(void)
+{
+ unsigned long base = cache_info.dt_sp_base;
+ unsigned long count = cache_info.dt_sp_count;
+ unsigned long stride = cache_info.dt_sp_stride;
+ unsigned long space;
+ unsigned long old_sr1;
+ long i;
+
+ old_sr1 = mfsp(1);
+
+ for(i=0,space=base; i<count; i++, space+=stride) {
+ mtsp(space,1);
+ flush_data_tlb_space();
+ }
+
+ mtsp(old_sr1, 1);
+}
+
+static inline void flush_instruction_tlb_space(void)
+{
+ unsigned long base = cache_info.it_off_base;
+ unsigned long count = cache_info.it_off_count;
+ unsigned long stride = cache_info.it_off_stride;
+ unsigned long loop = cache_info.it_loop;
+
+ unsigned long addr;
+ long i,j;
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ pitlbe(addr);
+}
+
+void flush_instruction_tlb(void)
+{
+ unsigned long base = cache_info.it_sp_base;
+ unsigned long count = cache_info.it_sp_count;
+ unsigned long stride = cache_info.it_sp_stride;
+ unsigned long space;
+ unsigned long old_sr1;
+ unsigned int i;
+
+ old_sr1 = mfsp(1);
+
+ for(i=0,space=base; i<count; i++, space+=stride) {
+ mtsp(space,1);
+ flush_instruction_tlb_space();
+ }
+
+ mtsp(old_sr1, 1);
+}
+
+
+void __flush_tlb_space(unsigned long space)
+{
+ unsigned long old_sr1;
+
+ old_sr1 = mfsp(1);
+ mtsp(space, 1);
+
+ flush_data_tlb_space();
+ flush_instruction_tlb_space();
+
+ mtsp(old_sr1, 1);
+}
+
+
+void flush_instruction_cache(void)
+{
+ register unsigned long base = cache_info.ic_base;
+ register unsigned long count = cache_info.ic_count;
+ register unsigned long loop = cache_info.ic_loop;
+ register unsigned long stride = cache_info.ic_stride;
+ register unsigned long addr;
+ register long i, j;
+ unsigned long old_sr1;
+
+ old_sr1 = mfsp(1);
+ mtsp(0,1);
+
+ /*
+ * Note: fice instruction has 3 bit space field, so one must
+ * be specified (otherwise you are justing using whatever
+ * happens to be in sr0).
+ */
+
+ for(i=0,addr=base; i<count; i++,addr+=stride)
+ for(j=0; j<loop; j++)
+ fice(addr);
+
+ mtsp(old_sr1, 1);
+}
+
+/* not yet ... fdc() needs to be implemented in cache.h !
+void flush_datacache_range( unsigned int base, unsigned int end )
+{
+ register long offset,offset_add;
+ offset_add = ( (1<<(cache_info.dc_conf.cc_block-1)) *
+ cache_info.dc_conf.cc_line ) << 4;
+ for (offset=base; offset<=end; offset+=offset_add)
+ fdc(space,offset);
+ fdc(space,end);
+}
+*/
+
+/* flushes code and data-cache */
+void flush_all_caches(void)
+{
+ flush_instruction_cache();
+ flush_data_cache();
+
+ flush_instruction_tlb();
+ flush_data_tlb();
+
+ asm volatile("sync");
+ asm volatile("syncdma");
+ asm volatile("sync");
+}
+
+int get_cache_info(char *buffer)
+{
+ char *p = buffer;
+
+ p += sprintf(p, "I-cache\t\t: %ld KB\n",
+ cache_info.ic_size/1024 );
+ p += sprintf(p, "D-cache\t\t: %ld KB (%s)%s\n",
+ cache_info.dc_size/1024,
+ (cache_info.dc_conf.cc_wt ? "WT":"WB"),
+ (cache_info.dc_conf.cc_sh ? " - shared I/D":"")
+ );
+
+ p += sprintf(p, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
+ cache_info.it_size,
+ cache_info.dt_size,
+ cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
+ );
+
+#ifndef __LP64__
+ /* BTLB - Block TLB */
+ if (btlb_info.max_size==0) {
+ p += sprintf(p, "BTLB\t\t: not supported\n" );
+ } else {
+ p += sprintf(p,
+ "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
+ "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
+ "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
+ btlb_info.max_size, (int)4096,
+ btlb_info.max_size>>8,
+ btlb_info.fixed_range_info.num_i,
+ btlb_info.fixed_range_info.num_d,
+ btlb_info.fixed_range_info.num_comb,
+ btlb_info.variable_range_info.num_i,
+ btlb_info.variable_range_info.num_d,
+ btlb_info.variable_range_info.num_comb
+ );
+ }
+#endif
+
+ return p - buffer;
+}
+
+
+void __init
+cache_init(void)
+{
+ if(pdc_cache_info(&cache_info)<0)
+ panic("cache_init: pdc_cache_info failed");
+
+#if 0
+ printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n",
+ cache_info.ic_size,
+ cache_info.dc_size,
+ cache_info.it_size,
+ sizeof (struct pdc_cache_info) / sizeof (long),
+ sizeof (struct pdc_cache_cf)
+ );
+#endif
+#ifndef __LP64__
+ if(pdc_btlb_info(&btlb_info)<0) {
+ memset(&btlb_info, 0, sizeof btlb_info);
+ }
+#endif
+}
diff --git a/arch/parisc/kernel/ccio-dma.c b/arch/parisc/kernel/ccio-dma.c
new file mode 100644
index 000000000..c8f72c813
--- /dev/null
+++ b/arch/parisc/kernel/ccio-dma.c
@@ -0,0 +1,1209 @@
+/*
+** ccio-dma.c:
+** DMA management routines for first generation cache-coherent machines.
+** Program U2/Uturn in "Virtual Mode" and use the I/O MMU.
+**
+** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2000 Ryan Bradetich
+** (c) Copyright 2000 Hewlett-Packard Company
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+**
+** "Real Mode" operation refers to U2/Uturn chip operation.
+** U2/Uturn were designed to perform coherency checks w/o using
+** the I/O MMU - basically what x86 does.
+**
+** Philipp Rumpf has a "Real Mode" driver for PCX-W machines at:
+** CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc
+** cvs -z3 co linux/arch/parisc/kernel/dma-rm.c
+**
+** I've rewritten his code to work under TPG's tree. See ccio-rm-dma.c.
+**
+** Drawbacks of using Real Mode are:
+** o outbound DMA is slower - U2 won't prefetch data (GSC+ XQL signal).
+** o Inbound DMA less efficient - U2 can't use DMA_FAST attribute.
+** o Ability to do scatter/gather in HW is lost.
+** o Doesn't work under PCX-U/U+ machines since they didn't follow
+** the coherency design originally worked out. Only PCX-W does.
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/byteorder.h>
+#include <asm/cache.h> /* for L1_CACHE_BYTES */
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/page.h>
+
+#include <asm/io.h>
+#include <asm/gsc.h> /* for gsc_writeN()... */
+
+/*
+** Choose "ccio" since that's what HP-UX calls it.
+** Make it easier for folks to migrate from one to the other :^)
+*/
+#define MODULE_NAME "ccio"
+
+/*
+#define DEBUG_CCIO_RES
+#define DEBUG_CCIO_RUN
+#define DEBUG_CCIO_INIT
+#define DUMP_RESMAP
+*/
+
+#include <linux/proc_fs.h>
+#include <asm/runway.h> /* for proc_runway_root */
+
+#ifdef DEBUG_CCIO_INIT
+#define DBG_INIT(x...) printk(x)
+#else
+#define DBG_INIT(x...)
+#endif
+
+#ifdef DEBUG_CCIO_RUN
+#define DBG_RUN(x...) printk(x)
+#else
+#define DBG_RUN(x...)
+#endif
+
+#ifdef DEBUG_CCIO_RES
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+#define CCIO_INLINE /* inline */
+#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
+
+#define U2_IOA_RUNWAY 0x580
+#define U2_BC_GSC 0x501
+#define UTURN_IOA_RUNWAY 0x581
+#define UTURN_BC_GSC 0x502
+/* We *can't* support JAVA (T600). Venture there at your own risk. */
+
+static void dump_resmap(void);
+
+static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+static struct pa_iodc_driver ccio_drivers_for[] = {
+
+ {HPHW_IOA, U2_IOA_RUNWAY, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback},
+
+ {HPHW_IOA, UTURN_IOA_RUNWAY, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback},
+
+/*
+** FIXME: The following claims the GSC bus port, not the IOA.
+** And there are two busses below a single I/O TLB.
+**
+** These should go away once we have a real PA bus walk.
+** Firmware wants to tell the PA bus walk code about the GSC ports
+** since they are not "architected" PA I/O devices. Ie a PA bus walk
+** wouldn't discover them. But the PA bus walk code could check
+** the "fixed module table" to add such devices to an I/O Tree
+** and proceed with the recursive, depth first bus walk.
+*/
+ {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xc, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "U2 GSC+ BC", (void *) ccio_driver_callback},
+
+ {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xc, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "Uturn GSC+ BC", (void *) ccio_driver_callback},
+
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL }
+};
+
+
+#define IS_U2(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \
+)
+
+#define IS_UTURN(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \
+)
+
+
+#define IOA_NORMAL_MODE 0x00020080 /* IO_CONTROL to turn on CCIO */
+#define CMD_TLB_DIRECT_WRITE 35 /* IO_COMMAND for I/O TLB Writes */
+#define CMD_TLB_PURGE 33 /* IO_COMMAND to Purge I/O TLB entry */
+
+struct ioa_registers {
+ /* Runway Supervisory Set */
+ volatile int32_t unused1[12];
+ volatile uint32_t io_command; /* Offset 12 */
+ volatile uint32_t io_status; /* Offset 13 */
+ volatile uint32_t io_control; /* Offset 14 */
+ volatile int32_t unused2[1];
+
+ /* Runway Auxiliary Register Set */
+ volatile uint32_t io_err_resp; /* Offset 0 */
+ volatile uint32_t io_err_info; /* Offset 1 */
+ volatile uint32_t io_err_req; /* Offset 2 */
+ volatile uint32_t io_err_resp_hi; /* Offset 3 */
+ volatile uint32_t io_tlb_entry_m; /* Offset 4 */
+ volatile uint32_t io_tlb_entry_l; /* Offset 5 */
+ volatile uint32_t unused3[1];
+ volatile uint32_t io_pdir_base; /* Offset 7 */
+ volatile uint32_t io_io_low_hv; /* Offset 8 */
+ volatile uint32_t io_io_high_hv; /* Offset 9 */
+ volatile uint32_t unused4[1];
+ volatile uint32_t io_chain_id_mask; /* Offset 11 */
+ volatile uint32_t unused5[2];
+ volatile uint32_t io_io_low; /* Offset 14 */
+ volatile uint32_t io_io_high; /* Offset 15 */
+};
+
+
+struct ccio_device {
+ struct ccio_device *next; /* list of LBA's in system */
+ struct hp_device *iodc; /* data about dev from firmware */
+ spinlock_t ccio_lock;
+
+ struct ioa_registers *ccio_hpa; /* base address */
+ u64 *pdir_base; /* physical base address */
+ char *res_map; /* resource map, bit == pdir entry */
+
+ int res_hint; /* next available IOVP - circular search */
+ int res_size; /* size of resource map in bytes */
+ int chainid_shift; /* specify bit location of chain_id */
+ int flags; /* state/functionality enabled */
+#ifdef DELAYED_RESOURCE_CNT
+ dma_addr_t res_delay[DELAYED_RESOURCE_CNT];
+#endif
+
+ /* STUFF We don't need in performance path */
+ int pdir_size; /* in bytes, determined by IOV Space size */
+ int hw_rev; /* HW revision of chip */
+};
+
+
+/* Ratio of Host MEM to IOV Space size */
+static unsigned long ccio_mem_ratio = 4;
+static struct ccio_device *ccio_list = NULL;
+
+static int ccio_proc_info(char *buffer, char **start, off_t offset, int length);
+static unsigned long ccio_used_bytes = 0;
+static unsigned long ccio_used_pages = 0;
+static int ccio_cujo_bug = 0;
+
+static unsigned long ccio_alloc_size = 0;
+static unsigned long ccio_free_size = 0;
+
+/**************************************************************
+*
+* I/O Pdir Resource Management
+*
+* Bits set in the resource map are in use.
+* Each bit can represent a number of pages.
+* LSbs represent lower addresses (IOVA's).
+*
+* This was was copied from sba_iommu.c. Don't try to unify
+* the two resource managers unless a way to have different
+* allocation policies is also adjusted. We'd like to avoid
+* I/O TLB thrashing by having resource allocation policy
+* match the I/O TLB replacement policy.
+*
+***************************************************************/
+#define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */
+#define IOVP_SIZE PAGE_SIZE
+#define IOVP_SHIFT PAGE_SHIFT
+#define IOVP_MASK PAGE_MASK
+
+/* Convert from IOVP to IOVA and vice versa. */
+#define CCIO_IOVA(iovp,offset) ((iovp) | (offset))
+#define CCIO_IOVP(iova) ((iova) & ~(IOVP_SIZE-1) )
+
+#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT)
+#define MKIOVP(pdir_idx) ((long)(pdir_idx) << IOVP_SHIFT)
+#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
+
+/* CUJO20 KLUDGE start */
+#define CUJO_20_BITMASK 0x0ffff000 /* upper nibble is a don't care */
+#define CUJO_20_STEP 0x10000000 /* inc upper nibble */
+#define CUJO_20_BADPAGE1 0x01003000 /* pages that hpmc on raven U+ */
+#define CUJO_20_BADPAGE2 0x01607000 /* pages that hpmc on firehawk U+ */
+#define CUJO_20_BADHVERS 0x6821 /* low nibble 1 is cujo rev 2.0 */
+#define CUJO_RAVEN_LOC 0xf1000000UL /* cujo location on raven U+ */
+#define CUJO_FIREHAWK_LOC 0xf1604000UL /* cujo location on firehawk U+ */
+/* CUJO20 KLUDGE end */
+
+/*
+** Don't worry about the 150% average search length on a miss.
+** If the search wraps around, and passes the res_hint, it will
+** cause the kernel to panic anyhow.
+*/
+
+/* ioa->res_hint = idx + (size >> 3); \ */
+
+#define CCIO_SEARCH_LOOP(ioa, idx, mask, size) \
+ for(; res_ptr < res_end; ++res_ptr) \
+ { \
+ if(0 == ((*res_ptr) & mask)) { \
+ *res_ptr |= mask; \
+ idx = (int)((unsigned long)res_ptr - (unsigned long)ioa->res_map); \
+ ioa->res_hint = 0;\
+ goto resource_found; \
+ } \
+ }
+
+#define CCIO_FIND_FREE_MAPPING(ioa, idx, mask, size) { \
+ u##size *res_ptr = (u##size *)&((ioa)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \
+ u##size *res_end = (u##size *)&(ioa)->res_map[ioa->res_size]; \
+ CCIO_SEARCH_LOOP(ioa, idx, mask, size); \
+ res_ptr = (u##size *)&(ioa)->res_map[0]; \
+ CCIO_SEARCH_LOOP(ioa, idx, mask, size); \
+}
+
+/*
+** Find available bit in this ioa's resource map.
+** Use a "circular" search:
+** o Most IOVA's are "temporary" - avg search time should be small.
+** o keep a history of what happened for debugging
+** o KISS.
+**
+** Perf optimizations:
+** o search for log2(size) bits at a time.
+** o search for available resource bits using byte/word/whatever.
+** o use different search for "large" (eg > 4 pages) or "very large"
+** (eg > 16 pages) mappings.
+*/
+static int
+ccio_alloc_range(struct ccio_device *ioa, size_t size)
+{
+ int res_idx;
+ unsigned long mask, flags;
+ unsigned int pages_needed = size >> PAGE_SHIFT;
+
+ ASSERT(pages_needed);
+ ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT));
+
+ mask = (unsigned long) -1L;
+ mask >>= BITS_PER_LONG - pages_needed;
+
+ DBG_RES(__FUNCTION__ " size: %d pages_needed %d pages_mask 0x%08lx\n",
+ size, pages_needed, mask);
+
+ spin_lock_irqsave(&ioa->ccio_lock, flags);
+
+ /*
+ ** "seek and ye shall find"...praying never hurts either...
+ ** ggg sacrafices another 710 to the computer gods.
+ */
+
+ if(pages_needed <= 8) {
+ CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 8);
+ } else if(pages_needed <= 16) {
+ CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 16);
+ } else if(pages_needed <= 32) {
+ CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 32);
+#ifdef __LP64__
+ } else if(pages_needed <= 64) {
+ CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 64)
+#endif
+ } else {
+ panic(__FILE__ ":" __FUNCTION__ "() Too many pages to map.\n");
+ }
+
+#ifdef DUMP_RESMAP
+ dump_resmap();
+#endif
+ panic(__FILE__ ":" __FUNCTION__ "() I/O MMU is out of mapping resources\n");
+
+resource_found:
+
+ DBG_RES(__FUNCTION__ " res_idx %d mask 0x%08lx res_hint: %d\n",
+ res_idx, mask, ioa->res_hint);
+
+ ccio_used_pages += pages_needed;
+ ccio_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1);
+
+ spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+
+#ifdef DUMP_RESMAP
+ dump_resmap();
+#endif
+
+ /*
+ ** return the bit address (convert from byte to bit).
+ */
+ return (res_idx << 3);
+}
+
+
+#define CCIO_FREE_MAPPINGS(ioa, idx, mask, size) \
+ u##size *res_ptr = (u##size *)&((ioa)->res_map[idx + (((size >> 3) - 1) & ~((size >> 3) - 1))]); \
+ ASSERT((*res_ptr & mask) == mask); \
+ *res_ptr &= ~mask;
+
+/*
+** clear bits in the ioa's resource map
+*/
+static void
+ccio_free_range(struct ccio_device *ioa, dma_addr_t iova, size_t size)
+{
+ unsigned long mask, flags;
+ unsigned long iovp = CCIO_IOVP(iova);
+ unsigned int res_idx = PDIR_INDEX(iovp)>>3;
+ unsigned int pages_mapped = (size >> IOVP_SHIFT) + !!(size & ~IOVP_MASK);
+
+ ASSERT(pages_needed);
+ ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT));
+
+ mask = (unsigned long) -1L;
+ mask >>= BITS_PER_LONG - pages_mapped;
+
+ DBG_RES(__FUNCTION__ " res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n",
+ res_idx, size, pages_mapped, mask);
+
+ spin_lock_irqsave(&ioa->ccio_lock, flags);
+
+ if(pages_mapped <= 8) {
+ CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 8);
+ } else if(pages_mapped <= 16) {
+ CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 16);
+ } else if(pages_mapped <= 32) {
+ CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 32);
+#ifdef __LP64__
+ } else if(pages_mapped <= 64) {
+ CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 64);
+#endif
+ } else {
+ panic(__FILE__ ":" __FUNCTION__ "() Too many pages to unmap.\n");
+ }
+
+ ccio_used_pages -= (pages_mapped ? pages_mapped : 1);
+ ccio_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1);
+
+ spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+
+#ifdef DUMP_RESMAP
+ dump_resmap();
+#endif
+}
+
+
+/****************************************************************
+**
+** CCIO dma_ops support routines
+**
+*****************************************************************/
+
+typedef unsigned long space_t;
+#define KERNEL_SPACE 0
+
+
+/*
+** DMA "Page Type" and Hints
+** o if SAFE_DMA isn't set, mapping is for FAST_DMA. SAFE_DMA should be
+** set for subcacheline DMA transfers since we don't want to damage the
+** other part of a cacheline.
+** o SAFE_DMA must be set for "memory" allocated via pci_alloc_consistent().
+** This bit tells U2 to do R/M/W for partial cachelines. "Streaming"
+** data can avoid this if the mapping covers full cache lines.
+** o STOP_MOST is needed for atomicity across cachelines.
+** Apperently only "some EISA devices" need this.
+** Using CONFIG_ISA is hack. Only the IOA with EISA under it needs
+** to use this hint iff the EISA devices needs this feature.
+** According to the U2 ERS, STOP_MOST enabled pages hurt performance.
+** o PREFETCH should *not* be set for cases like Multiple PCI devices
+** behind GSCtoPCI (dino) bus converter. Only one cacheline per GSC
+** device can be fetched and multiply DMA streams will thrash the
+** prefetch buffer and burn memory bandwidth. See 6.7.3 "Prefetch Rules
+** and Invalidation of Prefetch Entries".
+**
+** FIXME: the default hints need to be per GSC device - not global.
+**
+** HP-UX dorks: linux device driver programming model is totally different
+** than HP-UX's. HP-UX always sets HINT_PREFETCH since it's drivers
+** do special things to work on non-coherent platforms...linux has to
+** be much more careful with this.
+*/
+#define IOPDIR_VALID 0x01UL
+#define HINT_SAFE_DMA 0x02UL /* used for pci_alloc_consistent() pages */
+#ifdef CONFIG_ISA /* EISA support really */
+#define HINT_STOP_MOST 0x04UL /* LSL support */
+#else
+#define HINT_STOP_MOST 0x00UL /* only needed for "some EISA devices" */
+#endif
+#define HINT_UDPATE_ENB 0x08UL /* not used/supported by U2 */
+#define HINT_PREFETCH 0x10UL /* for outbound pages which are not SAFE */
+
+
+/*
+** Use direction (ie PCI_DMA_TODEVICE) to pick hint.
+** ccio_alloc_consistent() depends on this to get SAFE_DMA
+** when it passes in BIDIRECTIONAL flag.
+*/
+static u32 hint_lookup[] = {
+ [PCI_DMA_BIDIRECTIONAL] HINT_STOP_MOST | HINT_SAFE_DMA | IOPDIR_VALID,
+ [PCI_DMA_TODEVICE] HINT_STOP_MOST | HINT_PREFETCH | IOPDIR_VALID,
+ [PCI_DMA_FROMDEVICE] HINT_STOP_MOST | IOPDIR_VALID,
+ [PCI_DMA_NONE] 0, /* not valid */
+};
+
+/*
+** Initialize an I/O Pdir entry
+**
+** Given a virtual address (vba, arg2) and space id, (sid, arg1),
+** load the I/O PDIR entry pointed to by pdir_ptr (arg0). Each IO Pdir
+** entry consists of 8 bytes as shown below (MSB == bit 0):
+**
+**
+** WORD 0:
+** +------+----------------+-----------------------------------------------+
+** | Phys | Virtual Index | Phys |
+** | 0:3 | 0:11 | 4:19 |
+** |4 bits| 12 bits | 16 bits |
+** +------+----------------+-----------------------------------------------+
+** WORD 1:
+** +-----------------------+-----------------------------------------------+
+** | Phys | Rsvd | Prefetch |Update |Rsvd |Lock |Safe |Valid |
+** | 20:39 | | Enable |Enable | |Enable|DMA | |
+** | 20 bits | 5 bits | 1 bit |1 bit |2 bits|1 bit |1 bit |1 bit |
+** +-----------------------+-----------------------------------------------+
+**
+** The virtual index field is filled with the results of the LCI
+** (Load Coherence Index) instruction. The 8 bits used for the virtual
+** index are bits 12:19 of the value returned by LCI.
+*/
+
+void CCIO_INLINE
+ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, void * vba, unsigned long hints)
+{
+ register unsigned long pa = (volatile unsigned long) vba;
+ register unsigned long ci; /* coherent index */
+
+ /* We currently only support kernel addresses */
+ ASSERT(sid == 0);
+ ASSERT(((unsigned long) vba & 0xf0000000UL) == 0xc0000000UL);
+
+ mtsp(sid,1);
+
+ /*
+ ** WORD 1 - low order word
+ ** "hints" parm includes the VALID bit!
+ ** "dep" clobbers the physical address offset bits as well.
+ */
+ pa = virt_to_phys(vba);
+ asm volatile("depw %1,31,12,%0" : "+r" (pa) : "r" (hints));
+ ((u32 *)pdir_ptr)[1] = (u32) pa;
+
+ /*
+ ** WORD 0 - high order word
+ */
+
+#ifdef __LP64__
+ /*
+ ** get bits 12:15 of physical address
+ ** shift bits 16:31 of physical address
+ ** and deposit them
+ */
+ asm volatile ("extrd,u %1,15,4,%0" : "=r" (ci) : "r" (pa));
+ asm volatile ("extrd,u %1,31,16,%0" : "+r" (ci) : "r" (ci));
+ asm volatile ("depd %1,35,4,%0" : "+r" (pa) : "r" (ci));
+#else
+ pa = 0;
+#endif
+ /*
+ ** get CPU coherency index bits
+ ** Grab virtual index [0:11]
+ ** Deposit virt_idx bits into I/O PDIR word
+ */
+ asm volatile ("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+ asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci));
+ asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci));
+
+ ((u32 *)pdir_ptr)[0] = (u32) pa;
+
+
+ /* FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360)
+ ** PCX-U/U+ do. (eg C200/C240)
+ ** PCX-T'? Don't know. (eg C110 or similar K-class)
+ **
+ ** See PDC_MODEL/option 0/SW_CAP word for "Non-coherent IO-PDIR bit".
+ ** Hopefully we can patch (NOP) these out at boot time somehow.
+ **
+ ** "Since PCX-U employs an offset hash that is incompatible with
+ ** the real mode coherence index generation of U2, the PDIR entry
+ ** must be flushed to memory to retain coherence."
+ */
+ asm volatile("fdc 0(%0)" : : "r" (pdir_ptr));
+ asm volatile("sync");
+}
+
+
+/*
+** Remove stale entries from the I/O TLB.
+** Need to do this whenever an entry in the PDIR is marked invalid.
+*/
+static CCIO_INLINE void
+ccio_clear_io_tlb( struct ccio_device *d, dma_addr_t iovp, size_t byte_cnt)
+{
+ u32 chain_size = 1 << d->chainid_shift;
+
+ iovp &= ~(IOVP_SIZE-1); /* clear offset bits, just want pagenum */
+ byte_cnt += chain_size;
+
+ while (byte_cnt > chain_size) {
+ WRITE_U32(CMD_TLB_PURGE | iovp, &d->ccio_hpa->io_command);
+ iovp += chain_size;
+ byte_cnt -= chain_size;
+ }
+}
+
+
+/***********************************************************
+ *
+ * Mark the I/O Pdir entries invalid and blow away the
+ * corresponding I/O TLB entries.
+ *
+ * FIXME: at some threshhold it might be "cheaper" to just blow
+ * away the entire I/O TLB instead of individual entries.
+ *
+ * FIXME: Uturn has 256 TLB entries. We don't need to purge every
+ * PDIR entry - just once for each possible TLB entry.
+ * (We do need to maker I/O PDIR entries invalid regardless).
+ ***********************************************************/
+static CCIO_INLINE void
+ccio_mark_invalid(struct ccio_device *d, dma_addr_t iova, size_t byte_cnt)
+{
+ u32 iovp = (u32) CCIO_IOVP(iova);
+ size_t saved_byte_cnt;
+
+ /* round up to nearest page size */
+ saved_byte_cnt = byte_cnt = (byte_cnt + IOVP_SIZE - 1) & IOVP_MASK;
+
+ while (byte_cnt > 0) {
+ /* invalidate one page at a time */
+ unsigned int idx = PDIR_INDEX(iovp);
+ char *pdir_ptr = (char *) &(d->pdir_base[idx]);
+
+ ASSERT( idx < (d->pdir_size/sizeof(u64)));
+
+ pdir_ptr[7] = 0; /* clear only VALID bit */
+
+ /*
+ ** FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360)
+ ** PCX-U/U+ do. (eg C200/C240)
+ ** See PDC_MODEL/option 0/SW_CAP for "Non-coherent IO-PDIR bit".
+ **
+ ** Hopefully someone figures out how to patch (NOP) the
+ ** FDC/SYNC out at boot time.
+ */
+ asm volatile("fdc 0(%0)" : : "r" (pdir_ptr[7]));
+
+ iovp += IOVP_SIZE;
+ byte_cnt -= IOVP_SIZE;
+ }
+
+ asm volatile("sync");
+ ccio_clear_io_tlb(d, CCIO_IOVP(iova), saved_byte_cnt);
+}
+
+
+/****************************************************************
+**
+** CCIO dma_ops
+**
+*****************************************************************/
+
+void __init ccio_init(void)
+{
+ register_driver(ccio_drivers_for);
+}
+
+
+static int ccio_dma_supported( struct pci_dev *dev, dma_addr_t mask)
+{
+ if (dev == NULL) {
+ printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+ BUG();
+ return(0);
+ }
+
+ dev->dma_mask = mask; /* save it */
+
+ /* only support 32-bit devices (ie PCI/GSC) */
+ return((int) (mask >= 0xffffffffUL));
+}
+
+/*
+** Dump a hex representation of the resource map.
+*/
+
+#ifdef DUMP_RESMAP
+static
+void dump_resmap()
+{
+ struct ccio_device *ioa = ccio_list;
+ unsigned long *res_ptr = (unsigned long *)ioa->res_map;
+ unsigned long i = 0;
+
+ printk("res_map: ");
+ for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr)
+ printk("%08lx ", *res_ptr);
+
+ printk("\n");
+}
+#endif
+
+/*
+** map_single returns a fully formed IOVA
+*/
+static dma_addr_t ccio_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+{
+ struct ccio_device *ioa = ccio_list; /* FIXME : see Multi-IOC below */
+ dma_addr_t iovp;
+ dma_addr_t offset;
+ u64 *pdir_start;
+ unsigned long hint = hint_lookup[direction];
+ int idx;
+
+ ASSERT(size > 0);
+
+ /* save offset bits */
+ offset = ((dma_addr_t) addr) & ~IOVP_MASK;
+
+ /* round up to nearest IOVP_SIZE */
+ size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK;
+
+ idx = ccio_alloc_range(ioa, size);
+ iovp = (dma_addr_t) MKIOVP(idx);
+
+ DBG_RUN(__FUNCTION__ " 0x%p -> 0x%lx", addr, (long) iovp | offset);
+
+ pdir_start = &(ioa->pdir_base[idx]);
+
+ /* If not cacheline aligned, force SAFE_DMA on the whole mess */
+ if ((size % L1_CACHE_BYTES) || ((unsigned long) addr % L1_CACHE_BYTES))
+ hint |= HINT_SAFE_DMA;
+
+ /* round up to nearest IOVP_SIZE */
+ size = (size + IOVP_SIZE - 1) & IOVP_MASK;
+
+ while (size > 0) {
+
+ ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, addr, hint);
+
+ DBG_RUN(" pdir %p %08x%08x\n",
+ pdir_start,
+ (u32) (((u32 *) pdir_start)[0]),
+ (u32) (((u32 *) pdir_start)[1])
+ );
+ addr += IOVP_SIZE;
+ size -= IOVP_SIZE;
+ pdir_start++;
+ }
+ /* form complete address */
+ return CCIO_IOVA(iovp, offset);
+}
+
+
+static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction)
+{
+#ifdef FIXME
+/* Multi-IOC (ie N-class) : need to lookup IOC from dev
+** o If we can't know about lba PCI data structs, that eliminates ->sysdata.
+** o walking up pcidev->parent dead ends at elroy too
+** o leaves hashing dev->bus->number into some lookup.
+** (may only work for N-class)
+*/
+ struct ccio_device *ioa = dev->sysdata
+#else
+ struct ccio_device *ioa = ccio_list;
+#endif
+ dma_addr_t offset;
+
+ offset = iova & ~IOVP_MASK;
+
+ /* round up to nearest IOVP_SIZE */
+ size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK;
+
+ /* Mask off offset */
+ iova &= IOVP_MASK;
+
+ DBG_RUN(__FUNCTION__ " iovp 0x%lx\n", (long) iova);
+
+#ifdef DELAYED_RESOURCE_CNT
+ if (ioa->saved_cnt < DELAYED_RESOURCE_CNT) {
+ ioa->saved_iova[ioa->saved_cnt] = iova;
+ ioa->saved_size[ioa->saved_cnt] = size;
+ ccio_saved_cnt++;
+ } else {
+ do {
+#endif
+ ccio_mark_invalid(ioa, iova, size);
+ ccio_free_range(ioa, iova, size);
+
+#ifdef DELAYED_RESOURCE_CNT
+ d->saved_cnt--;
+ iova = ioa->saved_iova[ioa->saved_cnt];
+ size = ioa->saved_size[ioa->saved_cnt];
+ } while (ioa->saved_cnt)
+ }
+#endif
+}
+
+
+static void * ccio_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+{
+ void *ret;
+ unsigned long flags;
+ struct ccio_device *ioa = ccio_list;
+
+ DBG_RUN(__FUNCTION__ " size 0x%x\n", size);
+
+#if 0
+/* GRANT Need to establish hierarchy for non-PCI devs as well
+** and then provide matching gsc_map_xxx() functions for them as well.
+*/
+ if (!hwdev) {
+ /* only support PCI */
+ *dma_handle = 0;
+ return 0;
+ }
+#endif
+ spin_lock_irqsave(&ioa->ccio_lock, flags);
+ ccio_alloc_size += get_order(size);
+ spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+
+ ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size));
+
+ if (ret) {
+ memset(ret, 0, size);
+ *dma_handle = ccio_map_single(hwdev, ret, size, PCI_DMA_BIDIRECTIONAL);
+ }
+ DBG_RUN(__FUNCTION__ " ret %p\n", ret);
+
+ return ret;
+}
+
+
+static void ccio_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ unsigned long flags;
+ struct ccio_device *ioa = ccio_list;
+
+ spin_lock_irqsave(&ioa->ccio_lock, flags);
+ ccio_free_size += get_order(size);
+ spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+
+ ccio_unmap_single(hwdev, dma_handle, size, 0);
+ free_pages((unsigned long) vaddr, get_order(size));
+}
+
+
+static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int tmp = nents;
+
+ DBG_RUN(KERN_WARNING __FUNCTION__ " START\n");
+
+ /* KISS: map each buffer seperately. */
+ while (nents) {
+ sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction);
+ sg_dma_len(sglist) = sglist->length;
+ nents--;
+ sglist++;
+ }
+
+ DBG_RUN(KERN_WARNING __FUNCTION__ " DONE\n");
+ return tmp;
+}
+
+
+static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ DBG_RUN(KERN_WARNING __FUNCTION__ " : unmapping %d entries\n", nents);
+ while (nents) {
+ ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
+ nents--;
+ sglist++;
+ }
+ return;
+}
+
+
+static struct pci_dma_ops ccio_ops = {
+ ccio_dma_supported,
+ ccio_alloc_consistent,
+ ccio_free_consistent,
+ ccio_map_single,
+ ccio_unmap_single,
+ ccio_map_sg,
+ ccio_unmap_sg,
+ NULL, /* dma_sync_single : NOP for U2/Uturn */
+ NULL, /* dma_sync_sg : ditto */
+};
+
+#if 0
+/* GRANT - is this needed for U2 or not? */
+
+/*
+** Get the size of the I/O TLB for this I/O MMU.
+**
+** If spa_shift is non-zero (ie probably U2),
+** then calculate the I/O TLB size using spa_shift.
+**
+** Otherwise we are supposed to get the IODC entry point ENTRY TLB
+** and execute it. However, both U2 and Uturn firmware supplies spa_shift.
+** I think only Java (K/D/R-class too?) systems don't do this.
+*/
+static int
+ccio_get_iotlb_size(struct hp_device *d)
+{
+ if(d->spa_shift == 0) {
+ panic(__FUNCTION__ ": Can't determine I/O TLB size.\n");
+ }
+ return(1 << d->spa_shift);
+}
+#else
+
+/* Uturn supports 256 TLB entries */
+#define CCIO_CHAINID_SHIFT 8
+#define CCIO_CHAINID_MASK 0xff
+
+#endif /* 0 */
+
+
+/*
+** Figure out how big the I/O PDIR should be and alloc it.
+** Also sets variables which depend on pdir size.
+*/
+static void
+ccio_alloc_pdir(struct ccio_device *ioa)
+{
+ extern unsigned long mem_max; /* arch.../setup.c */
+
+ u32 iova_space_size = 0;
+ void * pdir_base;
+ int pdir_size, iov_order;
+
+ /*
+ ** Determine IOVA Space size from memory size.
+ ** Using "mem_max" is a kluge.
+ **
+ ** Ideally, PCI drivers would register the maximum number
+ ** of DMA they can have outstanding for each device they
+ ** own. Next best thing would be to guess how much DMA
+ ** can be outstanding based on PCI Class/sub-class. Both
+ ** methods still require some "extra" to support PCI
+ ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
+ */
+ /* limit IOVA space size to 1MB-1GB */
+ if (mem_max < (ccio_mem_ratio*1024*1024)) {
+ iova_space_size = 1024*1024;
+#ifdef __LP64__
+ } else if (mem_max > (ccio_mem_ratio*512*1024*1024)) {
+ iova_space_size = 512*1024*1024;
+#endif
+ } else {
+ iova_space_size = (u32) (mem_max/ccio_mem_ratio);
+ }
+
+ /*
+ ** iova space must be log2() in size.
+ ** thus, pdir/res_map will also be log2().
+ */
+
+ /* We could use larger page sizes in order to *decrease* the number
+ ** of mappings needed. (ie 8k pages means 1/2 the mappings).
+ **
+ ** Note: Grant Grunder says "Using 8k I/O pages isn't trivial either
+ ** since the pages must also be physically contiguous - typically
+ ** this is the case under linux."
+ */
+
+ iov_order = get_order(iova_space_size);
+ ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */
+ ASSERT(iov_order >= (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */
+ iova_space_size = 1 << (iov_order + IOVP_SHIFT);
+
+ ioa->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
+
+ ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */
+
+ /* Verify it's a power of two */
+ ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
+
+ DBG_INIT(__FUNCTION__ " hpa 0x%p mem %dMB IOV %dMB (%d bits)\n PDIR size 0x%0x",
+ ioa->ccio_hpa, (int) (mem_max>>20), iova_space_size>>20,
+ iov_order + PAGE_SHIFT, pdir_size);
+
+ ioa->pdir_base =
+ pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
+ if (NULL == pdir_base)
+ {
+ panic(__FILE__ ":" __FUNCTION__ "() could not allocate I/O Page Table\n");
+ }
+ memset(pdir_base, 0, pdir_size);
+
+ ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base);
+
+ DBG_INIT(" base %p", pdir_base);
+
+ /*
+ ** Chainid is the upper most bits of an IOVP used to determine
+ ** which TLB entry an IOVP will use.
+ */
+ ioa->chainid_shift = get_order(iova_space_size)+PAGE_SHIFT-CCIO_CHAINID_SHIFT;
+
+ DBG_INIT(" chainid_shift 0x%x\n", ioa->chainid_shift);
+}
+
+
+static void
+ccio_hw_init(struct ccio_device *ioa)
+{
+ int i;
+
+ /*
+ ** Initialize IOA hardware
+ */
+ WRITE_U32(CCIO_CHAINID_MASK << ioa->chainid_shift, &ioa->ccio_hpa->io_chain_id_mask);
+ WRITE_U32(virt_to_phys(ioa->pdir_base), &ioa->ccio_hpa->io_pdir_base);
+
+
+ /*
+ ** Go to "Virtual Mode"
+ */
+ WRITE_U32(IOA_NORMAL_MODE, &ioa->ccio_hpa->io_control);
+
+ /*
+ ** Initialize all I/O TLB entries to 0 (Valid bit off).
+ */
+ WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_m);
+ WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_l);
+
+ for (i = 1 << CCIO_CHAINID_SHIFT; i ; i--) {
+ WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioa->chainid_shift)),
+ &ioa->ccio_hpa->io_command);
+ }
+
+}
+
+
+static void
+ccio_resmap_init(struct ccio_device *ioa)
+{
+ u32 res_size;
+
+ /*
+ ** Ok...we do more than just init resource map
+ */
+ ioa->ccio_lock = SPIN_LOCK_UNLOCKED;
+
+ ioa->res_hint = 16; /* next available IOVP - circular search */
+
+ /* resource map size dictated by pdir_size */
+ res_size = ioa->pdir_size/sizeof(u64); /* entries */
+ res_size >>= 3; /* convert bit count to byte count */
+ DBG_INIT(__FUNCTION__ "() res_size 0x%x\n", res_size);
+
+ ioa->res_size = res_size;
+ ioa->res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size));
+ if (NULL == ioa->res_map)
+ {
+ panic(__FILE__ ":" __FUNCTION__ "() could not allocate resource map\n");
+ }
+ memset(ioa->res_map, 0, res_size);
+}
+
+/* CUJO20 KLUDGE start */
+static struct {
+ u16 hversion;
+ u8 spa;
+ u8 type;
+ u32 foo[3]; /* 16 bytes total */
+} cujo_iodc __attribute__ ((aligned (64)));
+static unsigned long cujo_result[32] __attribute__ ((aligned (16))) = {0,0,0,0};
+
+/*
+** CUJO 2.0 incorrectly decodes a memory access for specific
+** pages (every page at specific iotlb locations dependent
+** upon where the cujo is flexed - diff on raven/firehawk.
+** resulting in an hpmc and/or silent data corruption.
+** Workaround is to prevent use of those I/O TLB entries
+** by marking the suspect bitmap range entries as busy.
+*/
+static void
+ccio_cujo20_hack(struct ccio_device *ioa)
+{
+ unsigned long status;
+ unsigned int idx;
+ u8 *res_ptr = ioa->res_map;
+ u32 iovp=0x0;
+ unsigned long mask;
+
+ status = pdc_iodc_read( &cujo_result, (void *) CUJO_RAVEN_LOC, 0, &cujo_iodc, 16);
+ if (status == 0) {
+ if (cujo_iodc.hversion==CUJO_20_BADHVERS)
+ iovp = CUJO_20_BADPAGE1;
+ } else {
+ status = pdc_iodc_read( &cujo_result, (void *) CUJO_FIREHAWK_LOC, 0, &cujo_iodc, 16);
+ if (status == 0) {
+ if (cujo_iodc.hversion==CUJO_20_BADHVERS)
+ iovp = CUJO_20_BADPAGE2;
+ } else {
+ /* not a defective system */
+ return;
+ }
+ }
+
+ printk(MODULE_NAME ": Cujo 2.0 bug needs a work around\n");
+ ccio_cujo_bug = 1;
+
+ /*
+ ** mark bit entries that match "bad page"
+ */
+ idx = PDIR_INDEX(iovp)>>3;
+ mask = 0xff;
+
+ while(idx * sizeof(u8) < ioa->res_size) {
+ res_ptr[idx] |= mask;
+ idx += (PDIR_INDEX(CUJO_20_STEP)>>3);
+ ccio_used_pages += 8;
+ ccio_used_bytes += 1;
+ }
+}
+/* CUJO20 KLUDGE end */
+
+#ifdef CONFIG_PROC_FS
+static int ccio_proc_info(char *buf, char **start, off_t offset, int len)
+{
+ unsigned long i = 0;
+ struct ccio_device *ioa = ccio_list;
+ unsigned long *res_ptr = (unsigned long *)ioa->res_map;
+ unsigned long total_pages = ioa->res_size << 3; /* 8 bits per byte */
+
+ sprintf(buf, "%s\nCujo 2.0 bug : %s\n",
+ parisc_getHWdescription(ioa->iodc->hw_type, ioa->iodc->hversion,
+ ioa->iodc->sversion),
+ (ccio_cujo_bug ? "yes" : "no"));
+
+ sprintf(buf, "%sIO pdir size : %d bytes (%d entries)\n",
+ buf, ((ioa->res_size << 3) * sizeof(u64)), /* 8 bits per byte */
+ ioa->res_size << 3); /* 8 bits per byte */
+
+ sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
+ buf, ioa->res_size, ioa->res_size << 3); /* 8 bits per byte */
+
+ strcat(buf, " total: free: used: % used:\n");
+ sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, ioa->res_size,
+ ioa->res_size - ccio_used_bytes, ccio_used_bytes,
+ (ccio_used_bytes * 100) / ioa->res_size);
+
+ sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
+ total_pages - ccio_used_pages, ccio_used_pages,
+ (ccio_used_pages * 100 / total_pages));
+
+ sprintf(buf, "%sconsistent %8ld %8ld\n", buf,
+ ccio_alloc_size, ccio_free_size);
+
+ strcat(buf, "\nResource bitmap:\n");
+
+ for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr)
+ len += sprintf(buf, "%s%08lx ", buf, *res_ptr);
+
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+#endif
+
+/*
+** Determine if ccio should claim this chip (return 0) or not (return 1).
+** If so, initialize the chip and tell other partners in crime they
+** have work to do.
+*/
+static int
+ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ struct ccio_device *ioa;
+
+ printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+
+ if (ccio_list) {
+ printk(MODULE_NAME ": already initialized one device\n");
+ return(0);
+ }
+
+ ioa = kmalloc(sizeof(struct ccio_device), GFP_KERNEL);
+ if (NULL == ioa)
+ {
+ printk(MODULE_NAME " - couldn't alloc ccio_device\n");
+ return(1);
+ }
+ memset(ioa, 0, sizeof(struct ccio_device));
+
+ /*
+ ** ccio list is used mainly as a kluge to support a single instance.
+ ** Eventually, with core dumps, it'll be useful for debugging.
+ */
+ ccio_list = ioa;
+ ioa->iodc = d;
+
+#if 1
+/* KLUGE: determine IOA hpa based on GSC port value.
+** Needed until we have a PA bus walk. Can only discover IOA via
+** walking the architected PA MMIO space as described by the I/O ACD.
+** "Legacy" PA Firmware only tells us about unarchitected devices
+** that can't be detected by PA/EISA/PCI bus walks.
+*/
+ switch((long) d->hpa) {
+ case 0xf3fbf000L: /* C110 IOA0 LBC (aka GSC port) */
+ /* ccio_hpa same as C200 IOA0 */
+ case 0xf203f000L: /* C180/C200/240/C360 IOA0 LBC (aka GSC port) */
+ ioa->ccio_hpa = (struct ioa_registers *) 0xfff88000L;
+ break;
+ case 0xf103f000L: /* C180/C200/240/C360 IOA1 LBC (aka GSC port) */
+ ioa->ccio_hpa = (struct ioa_registers *) 0xfff8A000L;
+ break;
+ default:
+ panic("ccio-dma.c doesn't know this GSC port Address!\n");
+ break;
+ };
+#else
+ ioa->ccio_hpa = d->hpa;
+#endif
+
+ ccio_alloc_pdir(ioa);
+ ccio_hw_init(ioa);
+ ccio_resmap_init(ioa);
+
+ /* CUJO20 KLUDGE start */
+ ccio_cujo20_hack(ioa);
+ /* CUJO20 KLUDGE end */
+
+ hppa_dma_ops = &ccio_ops;
+
+ create_proc_info_entry(MODULE_NAME, 0, proc_runway_root, ccio_proc_info);
+ return(0);
+}
+
+
+
diff --git a/arch/parisc/kernel/ccio-rm-dma.c b/arch/parisc/kernel/ccio-rm-dma.c
new file mode 100644
index 000000000..25ec90c1b
--- /dev/null
+++ b/arch/parisc/kernel/ccio-rm-dma.c
@@ -0,0 +1,212 @@
+/*
+ * ccio-rm-dma.c:
+ * DMA management routines for first generation cache-coherent machines.
+ * "Real Mode" operation refers to U2/Uturn chip operation. The chip
+ * can perform coherency checks w/o using the I/O MMU. That's all we
+ * need until support for more than 4GB phys mem is needed.
+ *
+ * This is the trivial case - basically what x86 does.
+ *
+ * Drawbacks of using Real Mode are:
+ * o outbound DMA is slower since one isn't using the prefetching
+ * U2 can do for outbound DMA.
+ * o Ability to do scatter/gather in HW is also lost.
+ * o only known to work with PCX-W processor. (eg C360)
+ * (PCX-U/U+ are not coherent with U2 in real mode.)
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ *
+ * Original version/author:
+ * CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc
+ * cvs -z3 co linux/arch/parisc/kernel/dma-rm.c
+ *
+ * (C) Copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ *
+ * Adopted for The Puffin Group's parisc-linux port by Grant Grundler.
+ * (C) Copyright 2000 Grant Grundler <grundler@puffin.external.hp.com>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/page.h>
+
+/* Only chose "ccio" since that's what HP-UX calls it....
+** Make it easier for folks to migrate from one to the other :^)
+*/
+#define MODULE_NAME "ccio"
+
+#define U2_IOA_RUNWAY 0x580
+#define U2_BC_GSC 0x501
+#define UTURN_IOA_RUNWAY 0x581
+#define UTURN_BC_GSC 0x502
+
+static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+static struct pa_iodc_driver ccio_drivers_for[] = {
+
+ {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback},
+
+ {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback},
+
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL }
+};
+
+
+#define IS_U2(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \
+)
+
+#define IS_UTURN(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \
+)
+
+
+void __init ccio_init(void)
+{
+ register_driver(ccio_drivers_for);
+}
+
+
+static int ccio_dma_supported( struct pci_dev *dev, dma_addr_t mask)
+{
+ if (dev == NULL) {
+ printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+ BUG();
+ return(0);
+ }
+
+ dev->dma_mask = mask; /* save it */
+
+ /* only support 32-bit devices (ie PCI/GSC) */
+ return((int) (mask >= 0xffffffffUL));
+}
+
+
+static void *ccio_alloc_consistent(struct pci_dev *dev, size_t size,
+ dma_addr_t *handle)
+{
+ void *ret;
+
+ ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *handle = virt_to_phys(ret);
+ }
+ return ret;
+}
+
+static void ccio_free_consistent(struct pci_dev *dev, size_t size,
+ void *vaddr, dma_addr_t handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+
+static dma_addr_t ccio_map_single(struct pci_dev *dev, void *ptr, size_t size,
+ int direction)
+{
+ return virt_to_phys(ptr);
+}
+
+static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+ /* Nothing to do */
+}
+
+
+static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int tmp = nents;
+
+ /* KISS: map each buffer seperately. */
+ while (nents) {
+ sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction);
+ sg_dma_len(sglist) = sglist->length;
+ nents--;
+ sglist++;
+ }
+
+ return tmp;
+}
+
+
+static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+#if 0
+ while (nents) {
+ ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
+ nents--;
+ sglist++;
+ }
+ return;
+#else
+ /* Do nothing (copied from current ccio_unmap_single() :^) */
+#endif
+}
+
+
+static struct pci_dma_ops ccio_ops = {
+ ccio_dma_supported,
+ ccio_alloc_consistent,
+ ccio_free_consistent,
+ ccio_map_single,
+ ccio_unmap_single,
+ ccio_map_sg,
+ ccio_unmap_sg,
+ NULL, /* dma_sync_single : NOP for U2 */
+ NULL, /* dma_sync_sg : ditto */
+
+
+};
+
+
+/*
+** Determine if u2 should claim this chip (return 0) or not (return 1).
+** If so, initialize the chip and tell other partners in crime they
+** have work to do.
+*/
+static int
+ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+
+/*
+** FIXME - should check U2 registers to verify it's really running
+** in "Real Mode".
+*/
+
+#if 0
+/* will need this for "Virtual Mode" operation */
+ ccio_hw_init(ccio_dev);
+ ccio_common_init(ccio_dev);
+#endif
+ hppa_dma_ops = &ccio_ops;
+ return 0;
+}
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
new file mode 100644
index 000000000..ba93bbda0
--- /dev/null
+++ b/arch/parisc/kernel/drivers.c
@@ -0,0 +1,134 @@
+/*
+
+drivers.c
+
+Copyright (c) 1999 The Puffin Group
+
+This is a collection of routines intended to register all the devices
+in a system, and register device drivers.
+
+*/
+
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/pdc.h>
+
+
+extern struct hp_hardware *parisc_get_reference(
+ unsigned short hw_type, unsigned long hversion,
+ unsigned long sversion );
+
+
+/* I'm assuming there'll never be 64 devices. We should probably make
+ this more flexible. */
+
+#define MAX_DEVICES 64
+
+unsigned int num_devices = 0;
+
+struct hp_device devices[MAX_DEVICES];
+
+static unsigned long pdc_result[32] __attribute__ ((aligned (16))) = {0,0,0,0};
+static u8 iodc_data[32] __attribute__ ((aligned (64)));
+
+/*
+ * XXX should we be using a locked array ?
+ */
+
+int register_driver(struct pa_iodc_driver *driver)
+{
+ unsigned int i;
+ struct hp_device * device;
+
+ for (;driver->check;driver++) {
+
+ for (i=0;i<num_devices;i++) {
+ device = &devices[i];
+
+ if (device->managed) continue;
+
+ if ((driver->check & DRIVER_CHECK_HWTYPE) &&
+ (driver->hw_type != device->hw_type))
+ continue;
+ if ((driver->check & DRIVER_CHECK_HVERSION) &&
+ (driver->hversion != device->hversion))
+ continue;
+ if ((driver->check & DRIVER_CHECK_HVERSION_REV) &&
+ (driver->hversion_rev != device->hversion_rev))
+ continue;
+ if ((driver->check & DRIVER_CHECK_SVERSION) &&
+ (driver->sversion != device->sversion))
+ continue;
+ if ((driver->check & DRIVER_CHECK_SVERSION_REV) &&
+ (driver->sversion_rev != device->sversion_rev))
+ continue;
+ if ((driver->check & DRIVER_CHECK_OPT) &&
+ (driver->opt != device->opt))
+ continue;
+ if ( (*driver->callback)(device,driver) ==0) {
+ device->managed=1;
+ } else {
+ printk("Warning : device (%d, 0x%x, 0x%x, 0x%x, 0x%x) NOT claimed by %s %s\n",
+ device->hw_type,
+ device->hversion, device->hversion_rev,
+ device->sversion, device->sversion_rev,
+ driver->name, driver->version);
+ }
+ }
+ }
+ return 0;
+}
+
+
+struct hp_device * register_module(void *hpa)
+{
+
+ struct hp_device * d;
+ int status;
+
+ d = &devices[num_devices];
+ status = pdc_iodc_read(&pdc_result,hpa,0,&iodc_data,32 );
+ if (status !=PDC_RET_OK) {
+ /* There is no device here, so we'll skip it */
+ return 0;
+ }
+
+ d->hw_type = iodc_data[3]&0x1f;
+ d->hversion = (iodc_data[0]<<4)|((iodc_data[1]&0xf0)>>4);
+ d->sversion =
+ ((iodc_data[4]&0x0f)<<16)|(iodc_data[5]<<8)|(iodc_data[6]);
+ d->hversion_rev = iodc_data[1]&0x0f;
+ d->sversion_rev = iodc_data[4]>>4;
+ d->opt = iodc_data[7];
+ d->hpa = hpa;
+ d->managed=0;
+ d->reference = parisc_get_reference(d->hw_type, d->hversion,
+ d->sversion);
+
+ num_devices++;
+
+ return d;
+}
+
+void print_devices(char * buf) {
+
+ int i;
+ struct hp_device *d;
+ printk("Found devices:\n");
+ for (i=0;i<num_devices;i++) {
+ d = &devices[i];
+ printk(KERN_INFO
+ "%d. %s (%d) at 0x%p, versions 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
+ i+1,
+ (d->reference) ? d->reference->name : "Unknown device",
+ d->hw_type,d->hpa, d->hversion, d->hversion_rev,
+ d->sversion, d->sversion_rev, d->opt);
+
+ }
+ printk("That's a total of %d devices.\n",num_devices);
+}
+
+
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
new file mode 100644
index 000000000..0839e0bbb
--- /dev/null
+++ b/arch/parisc/kernel/entry.S
@@ -0,0 +1,1867 @@
+/*------------------------------------------------------------------------------
+ * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ *
+ * kernel entry points (interruptions, system call wrappers)
+ * Copyright (C) 1999,2000 Philipp Rumpf
+ * Copyright (C) 1999 SuSE GmbH Nuernberg
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <asm/offset.h>
+
+/* the following is the setup i think we should follow:
+ * whenever the CPU is interruptible, the following has to be true:
+ * CR30 is the kernel sp or 0 if we currently use the kernel stack
+ * CR31 is the kernel gp */
+
+/* we have the following possibilities to act on an interruption:
+ * - handle in assembly and use shadowed registers only
+ * - save registers to kernel stack and handle in assembly or C */
+
+ .text
+
+#ifdef __LP64__
+ .level 2.0w
+#endif
+
+#define __ASSEMBLY__
+#include <asm/assembly.h> /* for LDREG/STREG defines */
+#include <asm/pgtable.h>
+#include <asm/psw.h>
+#include <asm/signal.h>
+
+#ifdef __LP64__
+#define FRAME_SIZE 64
+#else
+#define FRAME_SIZE 64
+#endif
+
+ /* Switch to virtual mapping, trashing only %r1 */
+ .macro virt_map rfi_type
+ mtsm %r0
+ tovirt %r29
+ tovirt %r30
+ mfsp %sr7, %r1
+ mtsp %r1, %sr3
+ mtsp %r0, %sr4
+ mtsp %r0, %sr5
+ mtsp %r0, %sr6
+ mtsp %r0, %sr7
+ ldil L%KERNEL_PSW, %r1
+ ldo R%KERNEL_PSW(%r1), %r1
+ LDIL_FIXUP(%r1)
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17
+ mtctl %r0, %cr17
+ ldil L%.+28, %r1
+ ldo R%.+24(%r1), %r1
+ LDIL_FIXUP(%r1)
+ mtctl %r1, %cr18
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18
+ \rfi_type
+ nop
+ .endm
+
+ .macro get_stack
+ mfctl %cr30, %r1
+ comib,=,n 0, %r1, 0f /* forward so predicted not taken */
+
+ /* we save the registers in the task struct */
+ ldo TASK_REGS(%r1), %r29
+ tophys %r29
+ STREG %r30, PT_GR30(%r29)
+ STREG %r1, PT_CR30(%r29)
+ ldo TASK_SZ_ALGN(%r1), %r30
+ b 1f /* unconditional so predicted taken */
+ mtctl %r0,%cr30
+0:
+ /* we put a struct pt_regs on the stack and save the registers there */
+ copy %r30,%r29
+ ldo PT_SZ_ALGN(%r30),%r30
+ tophys %r29
+ STREG %r30,PT_GR30(%r29)
+ STREG %r0,PT_CR30(%r29)
+1:
+ .endm
+
+ .macro rest_stack regs
+ LDREG PT_CR30(\regs), %r1
+ comib,=,n 0, %r1, 2f/* forward so predicted not taken */
+
+ /* we restore the registers out of the task struct */
+ mtctl %r1, %cr30
+ LDREG PT_GR1(\regs), %r1
+ LDREG PT_GR30(\regs),%r30
+ b 3f
+ LDREG PT_GR29(\regs),%r29
+2:
+ /* we take a struct pt_regs off the stack */
+ LDREG PT_GR1(\regs), %r1
+ LDREG PT_GR29(\regs), %r29
+ ldo -PT_SZ_ALGN(%r30), %r30
+3:
+ .endm
+
+#ifdef OLD
+ /* fixme interruption handler */
+ .macro def code
+ /* WARNING!!! THIS IS DEBUG CODE ONLY!!! */
+ b unimplemented_64bitirq
+ ldi \code, %r1
+ .align 32
+ .endm
+
+ /* Use def to enable break - KWDB wants em
+ * (calls traps.c:handle_interruption) */
+ .macro pass_break code
+
+#else
+ /* default interruption handler
+ * (calls traps.c:handle_interruption) */
+ .macro def code
+#endif
+ mtctl %r29, %cr31
+ mtctl %r1, %cr28
+ ldi \code, %r1
+ b intr_save
+ mtctl %r1, %cr29
+ .align 32
+ .endm
+
+ /* Interrupt interruption handler
+ * (calls irq.c:do_irq_mask) */
+ .macro extint code
+ mtctl %r29, %cr31
+ mtctl %r1, %cr28
+ mfctl %cr23, %r1
+ mtctl %r1, %cr23
+ b intr_extint
+ mtctl %r1, %cr29
+ .align 32
+ .endm
+
+ .import os_hpmc, code
+
+ /* HPMC handler */
+ .macro hpmc code
+ nop /* must be a NOP, will be patched later */
+ ldil L%PA(os_hpmc), %r3
+ ldo R%PA(os_hpmc)(%r3), %r3
+ bv,n 0(%r3)
+ nop
+ .word 0 /* checksum (will be patched) */
+ .word PA(os_hpmc) /* address of handler */
+ .word 0 /* length of handler */
+ .endm
+
+ /*
+ * Performance Note: Instructions will be moved up into
+ * this part of the code later on, once we are sure
+ * that the tlb miss handlers are close to final form.
+ */
+
+ /* Register definitions for tlb miss handler macros */
+
+ va = r8 /* virtual address for which the trap occured */
+ spc = r24 /* space for which the trap occured */
+
+#ifndef __LP64__
+
+ /*
+ * itlb miss interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro itlb_11 code
+
+ mfctl %pcsq, spc
+ b itlb_miss_11
+ mfctl %pcoq, va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * itlb miss interruption handler (parisc 2.0)
+ */
+
+ .macro itlb_20 code
+
+ mfctl %pcsq, spc
+#ifdef __LP64__
+ b itlb_miss_20w
+#else
+ b itlb_miss_20
+#endif
+ mfctl %pcoq, va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * naitlb miss interruption handler (parisc 1.1 - 32 bit)
+ *
+ * Note: naitlb misses will be treated
+ * as an ordinary itlb miss for now.
+ * However, note that naitlb misses
+ * have the faulting address in the
+ * IOR/ISR.
+ */
+
+ .macro naitlb_11 code
+
+ mfctl %isr,spc
+ b itlb_miss_11
+ mfctl %ior,va
+ /* FIXME: If user causes a naitlb miss, the priv level may not be in
+ * lower bits of va, where the itlb miss handler is expecting them
+ */
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * naitlb miss interruption handler (parisc 2.0)
+ *
+ * Note: naitlb misses will be treated
+ * as an ordinary itlb miss for now.
+ * However, note that naitlb misses
+ * have the faulting address in the
+ * IOR/ISR.
+ */
+
+ .macro naitlb_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b itlb_miss_20w
+#else
+ b itlb_miss_20
+#endif
+ mfctl %ior,va
+ /* FIXME: If user causes a naitlb miss, the priv level may not be in
+ * lower bits of va, where the itlb miss handler is expecting them
+ */
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * dtlb miss interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro dtlb_11 code
+
+ mfctl %isr, spc
+ b dtlb_miss_11
+ mfctl %ior, va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * dtlb miss interruption handler (parisc 2.0)
+ */
+
+ .macro dtlb_20 code
+
+ mfctl %isr, spc
+#ifdef __LP64__
+ b dtlb_miss_20w
+#else
+ b dtlb_miss_20
+#endif
+ mfctl %ior, va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /* nadtlb miss interruption handler (parisc 1.1 - 32 bit)
+ *
+ * Note: nadtlb misses will be treated
+ * as an ordinary dtlb miss for now.
+ *
+ */
+
+ .macro nadtlb_11 code
+
+ mfctl %isr,spc
+ b dtlb_miss_11
+ mfctl %ior,va
+
+ .align 32
+ .endm
+#endif
+
+ /* nadtlb miss interruption handler (parisc 2.0)
+ *
+ * Note: nadtlb misses will be treated
+ * as an ordinary dtlb miss for now.
+ *
+ */
+
+ .macro nadtlb_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b dtlb_miss_20w
+#else
+ b dtlb_miss_20
+#endif
+ mfctl %ior,va
+
+ .align 32
+ .endm
+
+#ifndef __LP64__
+ /*
+ * dirty bit trap interruption handler (parisc 1.1 - 32 bit)
+ */
+
+ .macro dbit_11 code
+
+ mfctl %isr,spc
+ b dbit_trap_11
+ mfctl %ior,va
+
+ .align 32
+ .endm
+#endif
+
+ /*
+ * dirty bit trap interruption handler (parisc 2.0)
+ */
+
+ .macro dbit_20 code
+
+ mfctl %isr,spc
+#ifdef __LP64__
+ b dbit_trap_20w
+#else
+ b dbit_trap_20
+#endif
+ mfctl %ior,va
+
+ .align 32
+ .endm
+
+ /*
+ * Align fault_vector_20 on 4K boundary so that both
+ * fault_vector_11 and fault_vector_20 are on the
+ * same page. This is only necessary as long as we
+ * write protect the kernel text, which we may stop
+ * doing once we use large parge translations to cover
+ * the static part of the kernel address space.
+ */
+
+
+ .export fault_vector_20
+
+ .align 4096
+
+fault_vector_20:
+ /* First vector is invalid (0) */
+ .ascii "cows can fly"
+ .byte 0
+ .align 32
+
+ hpmc 1
+ def 2
+ def 3
+ extint 4
+ def 5
+ itlb_20 6
+ def 7
+ def 8
+ def 9
+ def 10
+ def 11
+ def 12
+ def 13
+ def 14
+ dtlb_20 15
+ naitlb_20 16
+ nadtlb_20 17
+ def 18
+ def 19
+ dbit_20 20
+ def 21
+ def 22
+ def 23
+ def 24
+ def 25
+ def 26
+ def 27
+ def 28
+ def 29
+ def 30
+ def 31
+
+#ifndef __LP64__
+
+ .export fault_vector_11
+
+ .align 2048
+
+fault_vector_11:
+ /* First vector is invalid (0) */
+ .ascii "cows can fly"
+ .byte 0
+ .align 32
+
+ hpmc 1
+ def 2
+ def 3
+ extint 4
+ def 5
+ itlb_11 6
+ def 7
+ def 8
+ def 9
+ def 10
+ def 11
+ def 12
+ def 13
+ def 14
+ dtlb_11 15
+ naitlb_11 16
+ nadtlb_11 17
+ def 18
+ def 19
+ dbit_11 20
+ def 21
+ def 22
+ def 23
+ def 24
+ def 25
+ def 26
+ def 27
+ def 28
+ def 29
+ def 30
+ def 31
+
+#endif
+
+ .import handle_interruption,code
+ .import handle_real_interruption,code
+ .import do_irq_mask,code
+ .import parisc_stopkernel,code
+ .import cpu_irq_region,data
+
+ /*
+ * r26 = function to be called
+ * r25 = argument to pass in
+ * r24 = flags for do_fork()
+ *
+ * Kernel threads don't ever return, so they don't need
+ * a true register context. We just save away the arguments
+ * for copy_thread/ret_ to properly set up the child.
+ */
+
+#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
+
+ .export __kernel_thread, code
+ .import do_fork
+__kernel_thread:
+ STREG %r2, -RP_OFFSET(%r30)
+
+ copy %r30, %r1
+ ldo PT_SZ_ALGN(%r30),%r30
+#ifdef __LP64__
+ /* Yo, function pointers in wide mode are little structs... -PB */
+ /* XXX FIXME do we need to honor the fptr's %dp value too? */
+ ldd 16(%r26), %r26
+#endif
+ STREG %r26, PT_GR26(%r1) /* Store function & argument for child */
+ STREG %r25, PT_GR25(%r1)
+ ldo CLONE_VM(%r0), %r26 /* Force CLONE_VM since only init_mm */
+ or %r26, %r24, %r26 /* will have kernel mappings. */
+ copy %r0, %r25
+ bl do_fork, %r2
+ copy %r1, %r24
+
+ /* Parent Returns here */
+
+ ldo -PT_SZ_ALGN(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ nop
+
+ /*
+ * Child Returns here
+ *
+ * copy_thread moved args from temp save area set up above
+ * into task save area.
+ */
+
+ .export ret_from_kernel_thread
+ret_from_kernel_thread:
+
+ LDREG TASK_PT_GR26-TASK_SZ_ALGN(%r30), %r1
+ LDREG TASK_PT_GR25-TASK_SZ_ALGN(%r30), %r26
+ ble 0(%sr7, %r1)
+ copy %r31, %r2
+
+ b sys_exit
+ ldi 0, %r26
+
+ .import sys_execve, code
+ .export __execve, code
+__execve:
+ copy %r2, %r15
+ copy %r23, %r17
+ copy %r30, %r16
+ ldo PT_SZ_ALGN(%r30), %r30
+ STREG %r26, PT_GR26(%r16)
+ STREG %r25, PT_GR25(%r16)
+ STREG %r24, PT_GR24(%r16)
+ bl sys_execve, %r2
+ copy %r16, %r26
+
+ comib,<>,n 0,%r28,__execve_failed
+
+ b intr_return
+ STREG %r17, PT_CR30(%r16)
+
+__execve_failed:
+ /* yes, this will trap and die. */
+ copy %r15, %r2
+ bv %r0(%r2)
+ nop
+
+ .align 4
+
+ /*
+ * struct task_struct *_switch_to(struct task_struct *prev,
+ * struct task_struct *next)
+ *
+ * switch kernel stacks and return prev */
+ .export _switch_to, code
+_switch_to:
+ STREG %r2, -RP_OFFSET(%r30)
+
+ callee_save
+
+ ldil L%_switch_to_ret, %r2
+ ldo R%_switch_to_ret(%r2), %r2
+ LDIL_FIXUP(%r2)
+
+ STREG %r2, TASK_PT_KPC(%r26)
+ LDREG TASK_PT_KPC(%r25), %r2
+
+ STREG %r30, TASK_PT_KSP(%r26)
+ LDREG TASK_PT_KSP(%r25), %r30
+
+ bv %r0(%r2)
+ nop
+
+_switch_to_ret:
+ mtctl %r0, %cr0 /* Needed for single stepping */
+ callee_rest
+
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ copy %r26, %r28
+
+ /*
+ * Common rfi return path for interruptions, kernel execve, and some
+ * syscalls. The sys_rt_sigreturn syscall will return via this path
+ * if the signal was received when the process was running; if the
+ * process was blocked on a syscall then the normal syscall_exit
+ * path is used. All syscalls for traced proceses exit via
+ * intr_restore.
+ * Note that the following code uses a "relied upon translation". See
+ * the parisc ACD for details. The ssm is necessary due to a PCXT bug.
+ */
+
+ .align 4096
+
+ .export syscall_exit_rfi
+syscall_exit_rfi:
+ copy %r30,%r16
+ /* FIXME! depi below has hardcoded dependency on kernel stack size */
+ depi 0,31,14,%r16 /* get task pointer */
+ ldo TASK_REGS(%r16),%r16
+ /* Force iaoq to userspace, as the user has had access to our current
+ * context via sigcontext.
+ * XXX do we need any other protection here?
+ */
+ LDREG PT_IAOQ0(%r16),%r19
+ depi 3,31,2,%r19
+ STREG %r19,PT_IAOQ0(%r16)
+ LDREG PT_IAOQ1(%r16),%r19
+ depi 3,31,2,%r19
+ STREG %r19,PT_IAOQ1(%r16)
+
+intr_return:
+
+ /* Check for software interrupts */
+
+ .import irq_stat,data
+
+ ldil L%irq_stat,%r19
+ ldo R%irq_stat(%r19),%r19
+ LDIL_FIXUP(%r19)
+
+#ifdef CONFIG_SMP
+ copy %r30,%r1
+ /* FIXME! depi below has hardcoded dependency on kernel stack size */
+ depi 0,31,14,%r1 /* get task pointer */
+ ldw TASK_PROCESSOR(%r1),%r20 /* get cpu # - int */
+#if (IRQSTAT_SZ == 32)
+ dep %r20,26,27,%r20 /* shift left 5 bits */
+#else
+#error IRQSTAT_SZ changed, fix dep
+#endif /* IRQSTAT_SZ */
+ add %r19,%r20,%r19
+#endif /* CONFIG_SMP */
+
+ ldw IRQSTAT_SI_ACTIVE(%r19),%r20 /* hardirq.h: unsigned int */
+ ldw IRQSTAT_SI_MASK(%r19),%r19 /* hardirq.h: unsigned int */
+ and %r19,%r20,%r20
+ comib,<>,n 0,%r20,intr_do_softirq /* forward */
+
+intr_check_resched:
+
+ /* check for reschedule */
+ copy %r30,%r1
+ /* FIXME! depi below has hardcoded dependency on kernel stack size */
+ depi 0,31,14,%r1 /* get task pointer */
+ LDREG TASK_NEED_RESCHED(%r1),%r19 /* sched.h: long need_resched */
+ comib,<>,n 0,%r19,intr_do_resched /* forward */
+
+intr_check_sig:
+ /* As above */
+ copy %r30,%r1
+ depi 0,31,14,%r1 /* get task pointer */
+ ldw TASK_SIGPENDING(%r1),%r19 /* sched.h: int sigpending */
+ comib,<>,n 0,%r19,intr_do_signal /* forward */
+
+intr_restore:
+ copy %r16, %r29
+ ldo PT_FR31(%r29), %r29
+ rest_fp %r29
+ copy %r16, %r29
+ rest_general %r29
+ ssm 0,%r0
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ tophys %r29
+ mtsm %r0
+ rest_specials %r29
+ rest_stack %r29
+ rfi
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ .import do_softirq,code
+intr_do_softirq:
+ bl do_softirq,%r2
+ nop
+ b intr_check_resched
+ nop
+
+ .import schedule,code
+intr_do_resched:
+ /* Only do reschedule if we are returning to user space */
+ LDREG PT_SR7(%r16), %r20
+ comib,= 0,%r20,intr_restore /* backward */
+ nop
+
+ bl schedule,%r2
+ ssm PSW_SM_I, %r0
+
+ /* It's OK to leave I bit on */
+ b intr_return /* start over if we got a resched */
+ nop
+
+ .import do_signal,code
+intr_do_signal:
+ /* Only do signals if we are returning to user space */
+ LDREG PT_SR7(%r16), %r20
+ comib,= 0,%r20,intr_restore /* backward */
+ nop
+
+ copy %r0, %r24 /* unsigned long in_syscall */
+ copy %r16, %r25 /* struct pt_regs *regs */
+ ssm PSW_SM_I, %r0
+ bl do_signal,%r2
+ copy %r0, %r26 /* sigset_t *oldset = NULL */
+
+ b intr_restore
+ nop
+
+ /* CR28 - saved GR1
+ * CR29 - argument for do_irq_mask */
+
+ /* External interrupts */
+intr_extint:
+ get_stack
+ save_specials %r29
+ virt_map rfi
+ save_general %r29
+
+ ldo PT_FR0(%r29), %r24
+ save_fp %r24
+
+ loadgp
+
+ copy %r29, %r24 /* arg2 is pt_regs */
+ copy %r29, %r16 /* save pt_regs */
+#ifdef CONFIG_KWDB
+ copy %r29, %r3 /* KWDB - update frame pointer (gr3) */
+#endif
+
+ /* sorry to put this cruft in the interrupt path */
+ ldil L%cpu_irq_region, %r25
+ ldo R%cpu_irq_region(%r25), %r25
+ bl do_irq_mask,%r2
+#ifdef __LP64__
+ LDIL_FIXUP(%r25)
+#else
+ nop
+#endif
+
+ b intr_return
+ nop
+
+ /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
+
+ .export intr_save, code /* for os_hpmc */
+
+intr_save:
+ get_stack
+ save_specials %r29
+
+ mfctl %cr20, %r1
+ STREG %r1, PT_ISR(%r29)
+ mfctl %cr21, %r1
+ STREG %r1, PT_IOR(%r29)
+
+ virt_map rfi
+ save_general %r29
+
+ ldo PT_FR0(%r29), %r25
+ save_fp %r25
+
+ loadgp
+
+ copy %r29, %r25 /* arg1 is pt_regs */
+#ifdef CONFIG_KWDB
+ copy %r29, %r3 /* KWDB - update frame pointer (gr3) */
+#endif
+
+ bl handle_interruption,%r2
+ copy %r29, %r16 /* save pt_regs */
+
+ b intr_return
+ nop
+
+ /*
+ * Note for all tlb miss handlers:
+ *
+ * cr24 contains a pointer to the kernel address space
+ * page directory.
+ *
+ * cr25 contains a pointer to the current user address
+ * space page directory.
+ *
+ * sr3 will contain the space id of the user address space
+ * of the current running thread while that thread is
+ * running in the kernel.
+ */
+
+ /*
+ * register number allocations. Note that these are all
+ * in the shadowed registers
+ */
+
+ t0 = r1 /* temporary register 0 */
+ va = r8 /* virtual address for which the trap occured */
+ t1 = r9 /* temporary register 1 */
+ pte = r16 /* pte/phys page # */
+ prot = r17 /* prot bits */
+ spc = r24 /* space for which the trap occured */
+ ptp = r25 /* page directory/page table pointer */
+
+#ifdef __LP64__
+
+dtlb_miss_20w:
+
+ extrd,u spc,31,7,t1 /* adjust va */
+ depd t1,31,7,va /* adjust va */
+ depdi 0,31,7,spc /* adjust space */
+ mfctl %cr25,ptp /* Assume user space miss */
+ or,*<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extrd,u va,33,9,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,*= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dtlb_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldd,s t1(ptp),ptp
+ extrd,u va,42,9,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ ldd,s t0(ptp),ptp
+ extrd,u va,51,9,t0 /* get third-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Third level page table lookup */
+
+ shladd t0,3,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldd 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,*<> t1,pte,%r0 /* test and nullify if already set */
+ std t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,32,pte
+ idtlbt %r16,%r17
+
+ rfir
+ nop
+#else
+
+dtlb_miss_11:
+ mfctl %cr25,ptp /* Assume user space miss */
+ or,<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dtlb_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,<> t1,pte,%r0 /* test and nullify if already set */
+ stw t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+ dep pte,8,7,prot
+
+ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0
+ depi 1,12,1,prot
+ extru,= pte,_PAGE_USER_BIT,1,r0
+ depi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extru,= pte,_PAGE_GATEWAY_BIT,1,r0
+ depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlba */
+
+ depi 0,31,12,pte
+ extru pte,24,25,pte
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ idtlba pte,(%sr1,va)
+ idtlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+dtlb_miss_20:
+ .level 2.0
+
+ mfctl %cr25,ptp /* Assume user space miss */
+ or,<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dtlb_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,<> t1,pte,%r0 /* test and nullify if already set */
+ stw t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,25,pte
+ idtlbt %r16,%r17
+
+ .level 1.1
+
+ rfir
+ nop
+#endif
+
+#ifdef __LP64__
+itlb_miss_20w:
+
+ /*
+ * I miss is a little different, since we allow users to fault
+ * on the gateway page which is in the kernel address space.
+ */
+
+ extrd,u spc,31,7,t1 /* adjust va */
+ depd t1,31,7,va /* adjust va */
+ depdi 0,31,7,spc /* adjust space */
+ cmpib,*= 0,spc,itlb_miss_kernel_20w
+ extrd,u va,33,9,t1 /* Get pgd index */
+
+ mfctl %cr25,ptp /* load user pgd */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,*= %r0,t0,%r0 /* If kernel, nullify following test */
+ cmpb,*<>,n t0,spc,itlb_fault /* forward */
+
+ /* First level page table lookup */
+
+itlb_miss_common_20w:
+ ldd,s t1(ptp),ptp
+ extrd,u va,42,9,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ ldd,s t0(ptp),ptp
+ extrd,u va,51,9,t0 /* get third-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Third level page table lookup */
+
+ shladd t0,3,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldd 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,*<> t1,pte,%r0 /* test and nullify if already set */
+ std t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for iitlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,32,pte
+ iitlbt %r16,%r17
+
+ rfir
+ nop
+
+itlb_miss_kernel_20w:
+ b itlb_miss_common_20w
+ mfctl %cr24,ptp /* Load kernel pgd */
+#else
+
+itlb_miss_11:
+
+ /*
+ * I miss is a little different, since we allow users to fault
+ * on the gateway page which is in the kernel address space.
+ */
+
+ comib,= 0,spc,itlb_miss_kernel_11
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfctl %cr25,ptp /* load user pgd */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,itlb_fault /* forward */
+
+ /* First level page table lookup */
+
+itlb_miss_common_11:
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,<> t1,pte,%r0 /* test and nullify if already set */
+ stw t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+ dep pte,8,7,prot
+
+ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0
+ depi 1,12,1,prot
+ extru,= pte,_PAGE_USER_BIT,1,r0
+ depi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extru,= pte,_PAGE_GATEWAY_BIT,1,r0
+ depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for iitlba */
+
+ depi 0,31,12,pte
+ extru pte,24,25,pte
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ iitlba pte,(%sr1,va)
+ iitlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+itlb_miss_kernel_11:
+ b itlb_miss_common_11
+ mfctl %cr24,ptp /* Load kernel pgd */
+
+itlb_miss_20:
+
+ /*
+ * I miss is a little different, since we allow users to fault
+ * on the gateway page which is in the kernel address space.
+ */
+
+ comib,= 0,spc,itlb_miss_kernel_20
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfctl %cr25,ptp /* load user pgd */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,itlb_fault /* forward */
+
+ /* First level page table lookup */
+
+itlb_miss_common_20:
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi _PAGE_ACCESSED,t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault
+
+ /* Check whether the "accessed" bit was set, otherwise do so */
+
+ or t1,pte,t0 /* t0 has R bit set */
+ and,<> t1,pte,%r0 /* test and nullify if already set */
+ stw t0,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ .level 2.0
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for iitlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,25,pte
+ iitlbt %r16,%r17
+ .level 1.1
+
+ rfir
+ nop
+
+
+itlb_miss_kernel_20:
+ b itlb_miss_common_20
+ mfctl %cr24,ptp /* Load kernel pgd */
+#endif
+
+#ifdef __LP64__
+
+dbit_trap_20w:
+
+ extrd,u spc,31,7,t1 /* adjust va */
+ depd t1,31,7,va /* adjust va */
+ depdi 0,1,2,va /* adjust va */
+ depdi 0,31,7,spc /* adjust space */
+ mfctl %cr25,ptp /* Assume user space miss */
+ or,*<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extrd,u va,33,9,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,*= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dbit_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldd,s t1(ptp),ptp
+ extrd,u va,42,9,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ ldd,s t0(ptp),ptp
+ extrd,u va,51,9,t0 /* get third-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault
+ depdi 0,63,12,ptp /* clear prot bits */
+
+ /* Third level page table lookup */
+
+ shladd t0,3,ptp,ptp
+ ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1
+ ldd 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault
+
+ /* Set Accessed and Dirty bits in the pte */
+
+ or t1,pte,pte
+ std pte,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,32,pte
+ idtlbt %r16,%r17
+
+ rfir
+ nop
+#else
+
+dbit_trap_11:
+ mfctl %cr25,ptp /* Assume user space trap */
+ or,<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dbit_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault
+
+ /* Set Accessed and Dirty bits in the pte */
+
+ or t1,pte,pte
+ stw pte,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+ dep pte,8,7,prot
+
+ extru,= pte,_PAGE_NO_CACHE_BIT,1,r0
+ depi 1,12,1,prot
+ extru,= pte,_PAGE_USER_BIT,1,r0
+ depi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extru,= pte,_PAGE_GATEWAY_BIT,1,r0
+ depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlba */
+
+ depi 0,31,12,pte
+ extru pte,24,25,pte
+
+ mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */
+ mtsp spc,%sr1
+
+ idtlba pte,(%sr1,va)
+ idtlbp prot,(%sr1,va)
+
+ mtsp t0, %sr1 /* Restore sr1 */
+
+ rfir
+ nop
+
+dbit_trap_20:
+ mfctl %cr25,ptp /* Assume user space trap */
+ or,<> %r0,spc,%r0 /* If it is user space, nullify */
+ mfctl %cr24,ptp /* Load kernel pgd instead */
+ extru va,9,10,t1 /* Get pgd index */
+
+ mfsp %sr7,t0 /* Get current space */
+ or,= %r0,t0,%r0 /* If kernel, nullify following test */
+ comb,<>,n t0,spc,dbit_fault /* forward */
+
+ /* First level page table lookup */
+
+ ldwx,s t1(ptp),ptp
+ extru va,19,10,t0 /* get second-level index */
+ bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault
+ depi 0,31,12,ptp /* clear prot bits */
+
+ /* Second level page table lookup */
+
+ sh2addl t0,ptp,ptp
+ ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1
+ ldw 0(ptp),pte
+ bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault
+
+ /* Set Accessed and Dirty bits in the pte */
+
+ or t1,pte,pte
+ stw pte,0(ptp) /* write back pte */
+
+ copy spc,prot /* init prot with faulting space */
+
+ .level 2.0
+
+ depd pte,8,7,prot
+ extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0
+ depdi 1,12,1,prot
+ extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0
+ depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */
+ extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0
+ depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */
+
+ /* Get rid of prot bits and convert to page addr for idtlbt */
+
+ depdi 0,63,12,pte
+ extrd,u pte,56,25,pte
+ idtlbt %r16,%r17
+
+ .level 1.1
+
+ rfir
+ nop
+#endif
+
+ .import handle_interruption,code
+
+kernel_bad_space:
+ b tlb_fault
+ ldi 31,%r1 /* Use an unused code */
+
+dbit_fault:
+ b tlb_fault
+ ldi 20,%r1
+
+itlb_fault:
+ b tlb_fault
+ ldi 6,%r1
+
+dtlb_fault:
+ ldi 15,%r1
+
+ /* Fall Through */
+
+tlb_fault:
+ mtctl %r1,%cr29
+ mtctl %r29,%cr31
+
+ get_stack
+ save_specials %r29 /* Note this saves a trashed r1 */
+
+ SAVE_CR (%cr20, PT_ISR(%r29))
+ SAVE_CR (%cr21, PT_IOR(%r29))
+
+ virt_map rfir
+
+ STREG %r1,PT_GR1(%r29) /* save good value after rfir */
+
+ save_general %r29
+
+ ldo PT_FR0(%r29), %r25
+ save_fp %r25
+
+ loadgp
+
+ copy %r29, %r25
+
+ bl handle_interruption, %r2
+ copy %r29, %r16
+
+ b intr_return
+ nop
+
+ /* Register saving semantics for system calls:
+
+ %r1 clobbered by system call macro in userspace
+ %r2 saved in PT_REGS by gateway page
+ %r3 - %r18 preserved by C code (saved by signal code)
+ %r19 - %r20 saved in PT_REGS by gateway page
+ %r21 - %r22 non-standard syscall args
+ stored in kernel stack by gateway page
+ %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page
+ %r27 - %r30 saved in PT_REGS by gateway page
+ %r31 syscall return pointer
+ */
+
+ /* Floating point registers (FIXME: what do we do with these?)
+
+ %fr0 - %fr3 status/exception, not preserved
+ %fr4 - %fr7 arguments
+ %fr8 - %fr11 not preserved by C code
+ %fr12 - %fr21 preserved by C code
+ %fr22 - %fr31 not preserved by C code
+ */
+
+ .macro reg_save regs
+ STREG %r3, PT_GR3(\regs)
+ STREG %r4, PT_GR4(\regs)
+ STREG %r5, PT_GR5(\regs)
+ STREG %r6, PT_GR6(\regs)
+ STREG %r7, PT_GR7(\regs)
+ STREG %r8, PT_GR8(\regs)
+ STREG %r9, PT_GR9(\regs)
+ STREG %r10,PT_GR10(\regs)
+ STREG %r11,PT_GR11(\regs)
+ STREG %r12,PT_GR12(\regs)
+ STREG %r13,PT_GR13(\regs)
+ STREG %r14,PT_GR14(\regs)
+ STREG %r15,PT_GR15(\regs)
+ STREG %r16,PT_GR16(\regs)
+ STREG %r17,PT_GR17(\regs)
+ STREG %r18,PT_GR18(\regs)
+ .endm
+
+ .macro reg_restore regs
+ LDREG PT_GR3(\regs), %r3
+ LDREG PT_GR4(\regs), %r4
+ LDREG PT_GR5(\regs), %r5
+ LDREG PT_GR6(\regs), %r6
+ LDREG PT_GR7(\regs), %r7
+ LDREG PT_GR8(\regs), %r8
+ LDREG PT_GR9(\regs), %r9
+ LDREG PT_GR10(\regs),%r10
+ LDREG PT_GR11(\regs),%r11
+ LDREG PT_GR12(\regs),%r12
+ LDREG PT_GR13(\regs),%r13
+ LDREG PT_GR14(\regs),%r14
+ LDREG PT_GR15(\regs),%r15
+ LDREG PT_GR16(\regs),%r16
+ LDREG PT_GR17(\regs),%r17
+ LDREG PT_GR18(\regs),%r18
+ .endm
+
+ .export sys_fork_wrapper
+sys_fork_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+ reg_save %r1
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+
+ /* These are call-clobbered registers and therefore
+ also syscall-clobbered (we hope). */
+ STREG %r2,PT_GR19(%r1) /* save for child */
+ STREG %r30,PT_GR20(%r1)
+ ldil L%child_return, %r3
+ ldo R%child_return(%r3), %r3
+ LDIL_FIXUP(%r3)
+ STREG %r3,PT_GR21(%r1) /* save for child */
+
+ LDREG PT_GR30(%r1),%r25
+ copy %r1,%r24
+ bl sys_clone,%r2
+ ldi SIGCHLD,%r26
+
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+wrapper_exit:
+ ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+
+ reg_restore %r1
+
+ bv %r0(%r2)
+ nop
+
+ /* Set the return value for the child */
+child_return:
+ LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
+ b wrapper_exit
+ copy %r0,%r28
+
+
+ .export sys_clone_wrapper
+sys_clone_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+ reg_save %r1
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+
+ STREG %r30,PT_GR20(%r1)
+ ldil L%child_return,%r3
+ ldo R%child_return(%r3),%r3
+ LDIL_FIXUP(%r3)
+
+ bl sys_clone,%r2
+ STREG %r3,PT_GR21(%r1) /* save for child */
+
+ b wrapper_exit
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+
+
+ .export sys_vfork_wrapper
+sys_vfork_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+ reg_save %r1
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+
+ STREG %r30,PT_GR20(%r1)
+ ldil L%child_return,%r3
+ ldo R%child_return(%r3),%r3
+ LDIL_FIXUP(%r3)
+ STREG %r3,PT_GR21(%r1) /* save for child */
+
+ bl sys_vfork,%r2
+ copy %r1,%r26
+
+ b wrapper_exit
+ LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
+
+
+ .macro execve_wrapper execve
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+
+ /*
+ * Do we need to save/restore r3-r18 here?
+ * I don't think so. why would new thread need old
+ * threads registers?
+ */
+
+ /* %arg0 - %arg3 are already saved for us. */
+
+ STREG %r2,-RP_OFFSET(%r30)
+ ldo FRAME_SIZE(%r30),%r30
+ bl \execve,%r2
+ copy %r1,%arg0
+
+ ldo -FRAME_SIZE(%r30),%r30
+ LDREG -RP_OFFSET(%r30),%r2
+
+ /* If exec succeeded we need to load the args */
+
+ ldo -1024(%r0),%r1
+ comb,>>= %r28,%r1,error_\execve
+ copy %r2,%r19
+
+error_\execve:
+ bv %r0(%r19)
+ nop
+ .endm
+
+ .export sys_execve_wrapper
+ .import sys_execve
+
+sys_execve_wrapper:
+ execve_wrapper sys_execve
+
+#ifdef __LP64__
+ .export sys32_execve_wrapper
+ .import sys32_execve
+
+sys32_execve_wrapper:
+ execve_wrapper sys32_execve
+#endif
+
+ .export sys_rt_sigreturn_wrapper
+sys_rt_sigreturn_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r26
+ /* Don't save regs, we are going to restore them from sigcontext. */
+ STREG %r2, -RP_OFFSET(%r30)
+ bl sys_rt_sigreturn,%r2
+ ldo FRAME_SIZE(%r30), %r30
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+
+ /* FIXME: I think we need to restore a few more things here. */
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */
+ reg_restore %r1
+
+ /* If the signal was received while the process was blocked on a
+ * syscall, then r2 will take us to syscall_exit; otherwise r2 will
+ * take us to syscall_exit_rfi and on to intr_return.
+ */
+ bv %r0(%r2)
+ LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
+
+ .export sys_sigaltstack_wrapper
+sys_sigaltstack_wrapper:
+ /* Get the user stack pointer */
+ LDREG -TASK_SZ_ALGN-FRAME_SIZE+TASK_PT_GR30(%r30), %r24
+ STREG %r2, -RP_OFFSET(%r30)
+ bl do_sigaltstack,%r2
+ ldo FRAME_SIZE(%r30), %r30
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+ bv %r0(%r2)
+ nop
+
+ .export sys_rt_sigsuspend_wrapper
+sys_rt_sigsuspend_wrapper:
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r24
+ reg_save %r24
+
+ STREG %r2, -RP_OFFSET(%r30)
+ bl sys_rt_sigsuspend,%r2
+ ldo FRAME_SIZE(%r30), %r30
+
+ ldo -FRAME_SIZE(%r30), %r30
+ LDREG -RP_OFFSET(%r30), %r2
+
+ ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1
+ reg_restore %r1
+
+ bv %r0(%r2)
+ nop
+
+ .export syscall_exit
+syscall_exit:
+ /* NOTE: HP-UX syscalls also come through here
+ after hpux_syscall_exit fixes up return
+ values. */
+ /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
+ * via syscall_exit_rfi if the signal was received while the process
+ * was running. All traced processes will probably exit via
+ * syscall_exit_rfi in the future.
+ */
+
+ /* save return value now */
+
+ STREG %r28,TASK_PT_GR28-TASK_SZ_ALGN-FRAME_SIZE(%r30)
+
+syscall_check_bh:
+
+/* #ifdef NOTNOW */
+ /* Check for software interrupts */
+
+ .import irq_stat,data
+
+ ldil L%irq_stat,%r19
+ ldo R%irq_stat(%r19),%r19
+ LDIL_FIXUP(%r19)
+
+#ifdef CONFIG_SMP
+ /* sched.h: int processor */
+ ldw TASK_PROCESSOR-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r20 /* get cpu # */
+#if (IRQSTAT_SZ == 32)
+ dep %r20,26,27,%r20 /* shift left 5 bits */
+#else
+#error IRQSTAT_SZ changed, fix dep
+#endif /* IRQSTAT_SZ */
+ add %r19,%r20,%r19
+#endif /* CONFIG_SMP */
+
+ ldw IRQSTAT_SI_ACTIVE(%r19),%r20 /* hardirq.h: unsigned int */
+ ldw IRQSTAT_SI_MASK(%r19),%r19 /* hardirq.h: unsigned int */
+ and %r19,%r20,%r20
+ comib,<>,n 0,%r20,syscall_do_softirq /* forward */
+/* #endif */
+
+
+syscall_check_resched:
+
+ /* check for reschedule */
+
+ LDREG TASK_NEED_RESCHED-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */
+ comib,<>,n 0,%r19,syscall_do_resched /* forward */
+
+syscall_check_sig:
+ ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
+ /* check for pending signals */
+ ldw TASK_SIGPENDING(%r1),%r19
+ comib,<>,n 0,%r19,syscall_do_signal /* forward */
+
+syscall_restore:
+ /* disable interrupts while dicking with the kernel stack, */
+ /* or life can become unpleasant */
+ rsm PSW_SM_I, %r20
+ LDREG TASK_PTRACE(%r1), %r19 /* Are we being ptraced? */
+ bb,<,n %r19,31,syscall_restore_rfi
+ LDREG TASK_PT_GR20(%r1),%r19
+ mtctl %r19, %cr27
+
+ LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */
+ LDREG TASK_PT_GR21(%r1),%r21
+ LDREG TASK_PT_GR22(%r1),%r22
+ LDREG TASK_PT_GR23(%r1),%r23
+ LDREG TASK_PT_GR24(%r1),%r24
+ LDREG TASK_PT_GR25(%r1),%r25
+ LDREG TASK_PT_GR26(%r1),%r26
+ LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */
+ LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */
+ LDREG TASK_PT_GR29(%r1),%r29
+ LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */
+ LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */
+ ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */
+ rest_fp %r19
+ LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */
+ mtsar %r19
+ LDREG TASK_PT_GR19(%r1),%r19
+
+ mtctl %r1,%cr30 /* intrhandler okay. */
+ mfsp %sr3,%r1 /* Get users space id */
+ mtsp %r1,%sr4 /* Restore sr4 */
+ mtsp %r1,%sr5 /* Restore sr5 */
+ mtsp %r1,%sr6 /* Restore sr6 */
+
+ depi 3,31,2,%r31 /* ensure return to user mode. */
+
+ mtsm %r20 /* restore irq state */
+ mfctl %cr27,%r20
+
+ /*
+ * Due to a dependency in the tlb miss handlers on sr7, it
+ * is essential that sr7 get set in the delay slot.
+ */
+
+#ifdef __LP64__
+
+ /* Note the be (and mtsp) is executed in narrow mode. This is OK
+ * for 32 bit processes, but won't work once we support 64 bit
+ * processes.
+ */
+
+ rsm PSW_SM_W, %r0
+ be 0(%sr3,%r31) /* return to user space */
+ mtsp %r1,%sr7 /* Restore sr7 */
+#else
+ be 0(%sr3,%r31) /* return to user space */
+ mtsp %r1,%sr7 /* Restore sr7 */
+#endif
+
+ /* We have to return via an RFI, so that PSW T and R bits can be set
+ * appropriately.
+ * This sets up pt_regs so we can return via intr_restore, which is not
+ * the most efficient way of doing things, but it works.
+ */
+syscall_restore_rfi:
+ ldo -1(%r0),%r2 /* Set recovery cntr to -1 */
+ mtctl %r2,%cr0 /* for immediate trap */
+ copy %r0,%r2 /* Create a reasonable PSW */
+ /* XXX W bit??? */
+ depi -1,13,1,%r2
+ depi -1,28,1,%r2
+ depi -1,30,1,%r2
+ depi -1,31,1,%r2
+ bb,<,n %r19,15,set_rbit /* PT_SINGLESTEP */
+ bb,>=,n %r19,14,set_nobit /* PT_BLOCKSTEP, see ptrace.c */
+set_tbit:
+ depi -1,7,1,%r2
+ b,n set_nobit
+set_rbit:
+ depi -1,27,1,%r2
+set_nobit:
+ STREG %r2,TASK_PT_PSW(%r1)
+ STREG %r1,TASK_PT_CR30(%r1)
+ mfsp %sr0,%r2
+ STREG %r2,TASK_PT_SR0(%r1)
+ mfsp %sr1,%r2
+ STREG %r2,TASK_PT_SR1(%r1)
+ mfsp %sr2,%r2
+ STREG %r2,TASK_PT_SR2(%r1)
+ mfsp %sr3,%r2
+ STREG %r2,TASK_PT_SR3(%r1)
+ STREG %r2,TASK_PT_SR4(%r1)
+ STREG %r2,TASK_PT_SR5(%r1)
+ STREG %r2,TASK_PT_SR6(%r1)
+ STREG %r2,TASK_PT_SR7(%r1)
+ STREG %r2,TASK_PT_IASQ0(%r1)
+ STREG %r2,TASK_PT_IASQ1(%r1)
+ LDREG TASK_PT_GR31(%r1),%r2
+ depi 3,31,2,%r2 /* ensure return to user mode. */
+ STREG %r2,TASK_PT_IAOQ0(%r1)
+ ldo 4(%r2),%r2
+ STREG %r2,TASK_PT_IAOQ1(%r1)
+ ldo TASK_REGS(%r1),%r25
+ reg_save %r25 /* Save r3 to r18 */
+ copy %r25,%r16
+ b intr_restore
+ nop
+
+ .import do_softirq,code
+syscall_do_softirq:
+ bl do_softirq,%r2
+ nop
+ b syscall_check_resched
+ ssm PSW_SM_I, %r0 /* do_softirq returns with I bit off */
+
+ .import schedule,code
+syscall_do_resched:
+ bl schedule,%r2
+ nop
+ b syscall_check_bh /* if resched, we start over again */
+ nop
+
+ .import do_signal,code
+syscall_do_signal:
+ /* Save callee-save registers (for sigcontext).
+ FIXME: After this point the process structure should be
+ consistent with all the relevant state of the process
+ before the syscall. We need to verify this. */
+ ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */
+ reg_save %r25
+
+ ldi 1, %r24 /* unsigned long in_syscall */
+
+ bl do_signal,%r2
+ copy %r0, %r26 /* sigset_t *oldset = NULL */
+
+ ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30), %r1 /* reload task ptr */
+ ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
+ reg_restore %r20
+
+ b,n syscall_restore
+
+#ifdef __LP64__
+unimplemented_64bitirq:
+ ssm PSW_SM_Q+PSW_SM_I, %r0
+ /* indicate that we had an interrupt */
+ ldi 0x77, %r28
+ ldi 0x77, %r29
+ /* save interrupt registers in GRs for diagnosis */
+ mfctl %cr17, %r17
+ mfctl %cr18, %r18
+ mfctl %cr19, %r19
+ mfctl %cr20, %r20
+ mfctl %cr21, %r21
+ mfctl %cr22, %r22
+ b,n .
+ nop
+#endif
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
new file mode 100644
index 000000000..75d5c6695
--- /dev/null
+++ b/arch/parisc/kernel/hardware.c
@@ -0,0 +1,1446 @@
+/*
+ * Hardware descriptions for HP 9000 based hardware, including
+ * system types, SCSI controllers, DMA controllers, HPPB controllers
+ * and lots more.
+ *
+ * Based on the document "PA-RISC 1.1 I/O Firmware Architecture
+ * Reference Specification", March 7, 1999, version 0.96. This
+ * is available at ?.
+ *
+ * Copyright 1999 by Alex deVries <adevries@thepuffingroup.com>
+ * and copyright 1999 The Puffin Group Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <asm/hardware.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+
+#define HPHW_NUM_TYPES 3431
+
+static char * hw_type_name[16] = {
+ "Processor",
+ "Memory",
+ "B DMA",
+ "Obsolete",
+ "A DMA",
+ "A Direct",
+ "Obsolete",
+ "Bus Converter Port",
+ "HP CIO Adapter",
+ "Console",
+ "Foreign I/O Module",
+ "Bus Adapter",
+ "IOA (?)",
+ "Bus Bridge to Foreign Bus",
+ "HP Clothing: Fabric Component"
+};
+
+/*
+ * XXX Could this be __init ??
+ */
+
+static struct hp_hardware hp_hardware_list[] = {
+ {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
+ {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
+ {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
+ {HPHW_NPROC,0xB,0x4,0x01,"Technical Shogun (845, 645)"},
+ {HPHW_NPROC,0xF,0x4,0x01,"Commercial Shogun (949)"},
+ {HPHW_NPROC,0xC,0x4,0x01,"Cheetah (850, 950)"},
+ {HPHW_NPROC,0x80,0x4,0x01,"Cheetah (950S)"},
+ {HPHW_NPROC,0x81,0x4,0x01,"Jaguar (855, 955)"},
+ {HPHW_NPROC,0x82,0x4,0x01,"Cougar (860, 960)"},
+ {HPHW_NPROC,0x83,0x4,0x13,"Panther (865, 870, 980)"},
+ {HPHW_NPROC,0x100,0x4,0x01,"Burgundy (810)"},
+ {HPHW_NPROC,0x101,0x4,0x01,"SilverFox Low (822, 922)"},
+ {HPHW_NPROC,0x102,0x4,0x01,"SilverFox High (832, 932)"},
+ {HPHW_NPROC,0x103,0x4,0x01,"Lego, SilverLite (815, 808, 920)"},
+ {HPHW_NPROC,0x104,0x4,0x03,"SilverBullet Low (842, 948)"},
+ {HPHW_NPROC,0x105,0x4,0x03,"SilverBullet High (852, 958)"},
+ {HPHW_NPROC,0x106,0x4,0x81,"Oboe"},
+ {HPHW_NPROC,0x180,0x4,0x12,"Dragon"},
+ {HPHW_NPROC,0x181,0x4,0x13,"Chimera (890, 990, 992)"},
+ {HPHW_NPROC,0x182,0x4,0x91,"TNT 100 (891,T500)"},
+ {HPHW_NPROC,0x183,0x4,0x91,"TNT 120 (892,T520)"},
+ {HPHW_NPROC,0x184,0x4,0x91,"Jade 180 U (893,T540)"},
+ {HPHW_NPROC,0x1FF,0x4,0x91,"Hitachi X Processor"},
+ {HPHW_NPROC,0x200,0x4,0x81,"Cobra (720)"},
+ {HPHW_NPROC,0x201,0x4,0x81,"Coral (750)"},
+ {HPHW_NPROC,0x202,0x4,0x81,"King Cobra (730)"},
+ {HPHW_NPROC,0x203,0x4,0x81,"Hardball (735/99)"},
+ {HPHW_NPROC,0x204,0x4,0x81,"Coral II (755/99)"},
+ {HPHW_NPROC,0x205,0x4,0x81,"Coral II (755/125)"},
+ {HPHW_NPROC,0x205,0x4,0x91,"Snake Eagle "},
+ {HPHW_NPROC,0x206,0x4,0x81,"Snake Cheetah (735/130)"},
+ {HPHW_NPROC,0x280,0x4,0x81,"Nova Low (817, 827, 957, 957LX)"},
+ {HPHW_NPROC,0x281,0x4,0x81,"Nova High (837, 847, 857, 967, 967LX)"},
+ {HPHW_NPROC,0x282,0x4,0x81,"Nova8 (807, 917, 917LX, 927,927LX, 937, 937LX, 947,947LX)"},
+ {HPHW_NPROC,0x283,0x4,0x81,"Nova64 (867, 877, 977)"},
+ {HPHW_NPROC,0x284,0x4,0x81,"TNova (887, 897, 987)"},
+ {HPHW_NPROC,0x285,0x4,0x81,"TNova64"},
+ {HPHW_NPROC,0x286,0x4,0x91,"Hydra64 (Nova)"},
+ {HPHW_NPROC,0x287,0x4,0x91,"Hydra96 (Nova)"},
+ {HPHW_NPROC,0x288,0x4,0x81,"TNova96"},
+ {HPHW_NPROC,0x300,0x4,0x81,"Bushmaster (710)"},
+ {HPHW_NPROC,0x302,0x4,0x81,"Flounder (705)"},
+ {HPHW_NPROC,0x310,0x4,0x81,"Scorpio (715/50)"},
+ {HPHW_NPROC,0x311,0x4,0x81,"Scorpio Jr.(715/33)"},
+ {HPHW_NPROC,0x312,0x4,0x81,"Strider-50 (715S/50)"},
+ {HPHW_NPROC,0x313,0x4,0x81,"Strider-33 (715S/33)"},
+ {HPHW_NPROC,0x314,0x4,0x81,"Trailways-50 (715T/50)"},
+ {HPHW_NPROC,0x315,0x4,0x81,"Trailways-33 (715T/33)"},
+ {HPHW_NPROC,0x316,0x4,0x81,"Scorpio Sr.(715/75)"},
+ {HPHW_NPROC,0x317,0x4,0x81,"Scorpio 100 (715/100)"},
+ {HPHW_NPROC,0x318,0x4,0x81,"Spectra (725/50)"},
+ {HPHW_NPROC,0x319,0x4,0x81,"Spectra (725/75)"},
+ {HPHW_NPROC,0x320,0x4,0x81,"Spectra (725/100)"},
+ {HPHW_NPROC,0x401,0x4,0x81,"Pace (745i, 747i)"},
+ {HPHW_NPROC,0x402,0x4,0x81,"Sidewinder (742i)"},
+ {HPHW_NPROC,0x403,0x4,0x81,"Fast Pace"},
+ {HPHW_NPROC,0x480,0x4,0x81,"Orville (E23)"},
+ {HPHW_NPROC,0x481,0x4,0x81,"Wilbur (E25)"},
+ {HPHW_NPROC,0x482,0x4,0x81,"WB-80 (E35)"},
+ {HPHW_NPROC,0x483,0x4,0x81,"WB-96 (E45)"},
+ {HPHW_NPROC,0x48,0x4,0x81,"UL Proc L-100 (811/D210,D310)"},
+ {HPHW_NPROC,0x48,0x4,0x81,"UL Proc L-75 (801/D200)"},
+ {HPHW_NPROC,0x501,0x4,0x81,"Merlin L2 132 (9000/778/B132L)"},
+ {HPHW_NPROC,0x502,0x4,0x81,"Merlin L2 160 (9000/778/B160L)"},
+ {HPHW_NPROC,0x503,0x4,0x81,"Merlin L2+ 132 (9000/778/B132L)"},
+ {HPHW_NPROC,0x504,0x4,0x81,"Merlin L2+ 180 (9000/778/B180L)"},
+ {HPHW_NPROC,0x505,0x4,0x81,"Raven L2 132 (9000/778/C132L)"},
+ {HPHW_NPROC,0x506,0x4,0x81,"Raven L2 160 (9000/779/C160L)"},
+ {HPHW_NPROC,0x507,0x4,0x81,"Raven L2 180 (9000/779/C180L)"},
+ {HPHW_NPROC,0x508,0x4,0x81,"Raven L2 160 (9000/779/C160L)"},
+ {HPHW_NPROC,0x509,0x4,0x81,"712/132 L2 Upgrade"},
+ {HPHW_NPROC,0x50A,0x4,0x81,"712/160 L2 Upgrade"},
+ {HPHW_NPROC,0x50B,0x4,0x81,"715/132 L2 Upgrade"},
+ {HPHW_NPROC,0x50C,0x4,0x81,"715/160 L2 Upgrade"},
+ {HPHW_NPROC,0x50D,0x4,0x81,"Rocky2 L2 120"},
+ {HPHW_NPROC,0x50E,0x4,0x81,"Rocky2 L2 150"},
+ {HPHW_NPROC,0x50F,0x4,0x81,"Anole L2 132 (744)"},
+ {HPHW_NPROC,0x510,0x4,0x81,"Anole L2 165 (744)"},
+ {HPHW_NPROC,0x511,0x4,0x81,"Kiji L2 132"},
+ {HPHW_NPROC,0x512,0x4,0x81,"UL L2 132 (803/D220,D320)"},
+ {HPHW_NPROC,0x513,0x4,0x81,"UL L2 160 (813/D220,D320)"},
+ {HPHW_NPROC,0x514,0x4,0x81,"Merlin Jr L2 132"},
+ {HPHW_NPROC,0x515,0x4,0x81,"Staccato L2 132"},
+ {HPHW_NPROC,0x516,0x4,0x81,"Staccato L2 180 (A Class 180)"},
+ {HPHW_NPROC,0x580,0x4,0x81,"KittyHawk DC2-100 (K100)"},
+ {HPHW_NPROC,0x581,0x4,0x91,"KittyHawk DC3-120 (K210)"},
+ {HPHW_NPROC,0x582,0x4,0x91,"KittyHawk DC3 100 (K400)"},
+ {HPHW_NPROC,0x583,0x4,0x91,"KittyHawk DC3 120 (K410)"},
+ {HPHW_NPROC,0x584,0x4,0x91,"LighteningHawk T120"},
+ {HPHW_NPROC,0x585,0x4,0x91,"SkyHawk 100"},
+ {HPHW_NPROC,0x586,0x4,0x91,"SkyHawk 120"},
+ {HPHW_NPROC,0x587,0x4,0x81,"UL Proc 1-way T'120"},
+ {HPHW_NPROC,0x588,0x4,0x91,"UL Proc 2-way T'120"},
+ {HPHW_NPROC,0x589,0x4,0x81,"UL Proc 1-way T'100 (821/D250,D350)"},
+ {HPHW_NPROC,0x58A,0x4,0x91,"UL Proc 2-way T'100 (831/D250,D350)"},
+ {HPHW_NPROC,0x58B,0x4,0x91,"KittyHawk DC2 100 (K200)"},
+ {HPHW_NPROC,0x58C,0x4,0x91,"ThunderHawk DC3- 120 1M (K220)"},
+ {HPHW_NPROC,0x58D,0x4,0x91,"ThunderHawk DC3 120 1M (K420)"},
+ {HPHW_NPROC,0x58E,0x4,0x81,"Raven 120 T'"},
+ {HPHW_NPROC,0x58F,0x4,0x91,"Mohawk 160 U 1M DC3 (K450)"},
+ {HPHW_NPROC,0x590,0x4,0x91,"Mohawk 180 U 1M DC3 (K460)"},
+ {HPHW_NPROC,0x591,0x4,0x91,"Mohawk 200 U 1M DC3"},
+ {HPHW_NPROC,0x592,0x4,0x81,"Raven 100 T'"},
+ {HPHW_NPROC,0x593,0x4,0x91,"FireHawk 160 U"},
+ {HPHW_NPROC,0x594,0x4,0x91,"FireHawk 180 U"},
+ {HPHW_NPROC,0x595,0x4,0x91,"FireHawk 220 U"},
+ {HPHW_NPROC,0x596,0x4,0x91,"FireHawk 240 U"},
+ {HPHW_NPROC,0x597,0x4,0x91,"SPP2000 processor"},
+ {HPHW_NPROC,0x598,0x4,0x81,"Raven U 230 (9000/780/C230)"},
+ {HPHW_NPROC,0x599,0x4,0x81,"Raven U 240 (9000/780/C240)"},
+ {HPHW_NPROC,0x59A,0x4,0x91,"Unlisted but reserved"},
+ {HPHW_NPROC,0x59A,0x4,0x81,"Unlisted but reserved"},
+ {HPHW_NPROC,0x59B,0x4,0x81,"Raven U 160 (9000/780/C160)"},
+ {HPHW_NPROC,0x59D,0x4,0x81,"Raven U 200 (9000/780/C200)"},
+ {HPHW_NPROC,0x59E,0x4,0x91,"ThunderHawk T' 120"},
+ {HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780/\?\?\?\?)"},
+ {HPHW_NPROC,0x5A0,0x4,0x81,"UL 1w T120 1MB/1MB (841/D260,D360)"},
+ {HPHW_NPROC,0x5A1,0x4,0x91,"UL 2w T120 1MB/1MB (851/D260,D360)"},
+ {HPHW_NPROC,0x5A2,0x4,0x81,"UL 1w U160 512K/512K (861/D270,D370)"},
+ {HPHW_NPROC,0x5A3,0x4,0x91,"UL 2w U160 512K/512K (871/D270,D370)"},
+ {HPHW_NPROC,0x5A4,0x4,0x91,"Mohawk 160 U 1M DC3- (K250)"},
+ {HPHW_NPROC,0x5A5,0x4,0x91,"Mohawk 180 U 1M DC3- (K260)"},
+ {HPHW_NPROC,0x5A6,0x4,0x91,"Mohawk 200 U 1M DC3-"},
+ {HPHW_NPROC,0x5A7,0x4,0x81,"UL proc 1-way U160 1M/1M"},
+ {HPHW_NPROC,0x5A8,0x4,0x91,"UL proc 2-way U160 1M/1M"},
+ {HPHW_NPROC,0x5A9,0x4,0x81,"UL proc 1-way U180 1M/1M"},
+ {HPHW_NPROC,0x5AA,0x4,0x91,"UL proc 2-way U180 1M/1M"},
+ {HPHW_NPROC,0x5AB,0x4,0x91,"Obsolete"},
+ {HPHW_NPROC,0x5AB,0x4,0x81,"Obsolete"},
+ {HPHW_NPROC,0x5AC,0x4,0x91,"Obsolete"},
+ {HPHW_NPROC,0x5AC,0x4,0x81,"Obsolete"},
+ {HPHW_NPROC,0x5AD,0x4,0x91,"BraveHawk 180MHz DC3-"},
+ {HPHW_NPROC,0x5AE,0x4,0x91,"BraveHawk 200MHz DC3- (898/K370)"},
+ {HPHW_NPROC,0x5AF,0x4,0x91,"BraveHawk 220MHz DC3-"},
+ {HPHW_NPROC,0x5B0,0x4,0x91,"BraveHawk 180MHz DC3"},
+ {HPHW_NPROC,0x5B1,0x4,0x91,"BraveHawk 200MHz DC3 (899/K570)"},
+ {HPHW_NPROC,0x5B2,0x4,0x91,"BraveHawk 220MHz DC3"},
+ {HPHW_NPROC,0x5B3,0x4,0x91,"FireHawk 200"},
+ {HPHW_NPROC,0x5B4,0x4,0x91,"SPP2500"},
+ {HPHW_NPROC,0x5B5,0x4,0x91,"SummitHawk U+"},
+ {HPHW_NPROC,0x5B6,0x4,0x91,"DragonHawk U+ 240 DC3"},
+ {HPHW_NPROC,0x5B7,0x4,0x91,"DragonHawk U+ 240 DC3-"},
+ {HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"},
+ {HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"},
+ {HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"},
+ {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W "},
+ {HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"},
+ {HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"},
+ {HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"},
+ {HPHW_NPROC,0x5BF,0x4,0x91,"Forte W 4-way"},
+ {HPHW_NPROC,0x5C0,0x4,0x91,"M2250"},
+ {HPHW_NPROC,0x5C1,0x4,0x91,"M2500"},
+ {HPHW_NPROC,0x5C2,0x4,0x91,"Sonata 440"},
+ {HPHW_NPROC,0x5C3,0x4,0x91,"Sonata 360"},
+ {HPHW_NPROC,0x5C4,0x4,0x91,"Rhapsody 440"},
+ {HPHW_NPROC,0x5C5,0x4,0x91,"Rhapsody 360"},
+ {HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780/\?\?\?\?)"},
+ {HPHW_NPROC,0x5C7,0x4,0x91,"Halfdome W 440"},
+ {HPHW_NPROC,0x5C8,0x4,0x81,"Lego 360 processor"},
+ {HPHW_NPROC,0x5C9,0x4,0x91,"Rhapsody DC- 440"},
+ {HPHW_NPROC,0x5CA,0x4,0x91,"Rhapsody DC- 360"},
+ {HPHW_NPROC,0x5CB,0x4,0x91,"Crescendo 440"},
+ {HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"},
+ {HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"},
+ {HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"},
+ {HPHW_NPROC,0x602,0x4,0x81,"Gecko 100 (712/100)"},
+ {HPHW_NPROC,0x603,0x4,0x81,"Anole 64 (743/64)"},
+ {HPHW_NPROC,0x604,0x4,0x81,"Anole 100 (743/100)"},
+ {HPHW_NPROC,0x605,0x4,0x81,"Gecko 120 (712/120)"},
+ {HPHW_NPROC,0x606,0x4,0x81,"Gila 80"},
+ {HPHW_NPROC,0x607,0x4,0x81,"Gila 100"},
+ {HPHW_NPROC,0x608,0x4,0x81,"Gila 120"},
+ {HPHW_NPROC,0x609,0x4,0x81,"Scorpio-L 80"},
+ {HPHW_NPROC,0x60A,0x4,0x81,"Mirage Jr (715/64)"},
+ {HPHW_NPROC,0x60B,0x4,0x81,"Mirage 100"},
+ {HPHW_NPROC,0x60C,0x4,0x81,"Mirage 100+"},
+ {HPHW_NPROC,0x60D,0x4,0x81,"Electra 100"},
+ {HPHW_NPROC,0x60E,0x4,0x81,"Electra 120"},
+ {HPHW_NPROC,0x610,0x4,0x81,"Scorpio-L 100"},
+ {HPHW_NPROC,0x611,0x4,0x81,"Scorpio-L 120"},
+ {HPHW_NPROC,0x612,0x4,0x81,"Spectra-L 80"},
+ {HPHW_NPROC,0x613,0x4,0x81,"Spectra-L 100"},
+ {HPHW_NPROC,0x614,0x4,0x81,"Spectra-L 120"},
+ {HPHW_NPROC,0x615,0x4,0x81,"Piranha 100"},
+ {HPHW_NPROC,0x616,0x4,0x81,"Piranha 120"},
+ {HPHW_NPROC,0x617,0x4,0x81,"Jason 50"},
+ {HPHW_NPROC,0x618,0x4,0x81,"Jason 100"},
+ {HPHW_NPROC,0x619,0x4,0x81,"Mirage 80 "},
+ {HPHW_NPROC,0x61A,0x4,0x81,"SAIC L-80"},
+ {HPHW_NPROC,0x61B,0x4,0x81,"Rocky1 L-60"},
+ {HPHW_NPROC,0x61C,0x4,0x81,"Anole T (743/T)"},
+ {HPHW_NPROC,0x67E,0x4,0x81,"Hitachi Tiny 80"},
+ {HPHW_NPROC,0x67F,0x4,0x81,"Hitachi Tiny 64"},
+ {HPHW_NPROC,0x700,0x4,0x91,"NEC Aska Processor"},
+ {HPHW_A_DIRECT, 0x004, 0x0000D, 0x00, "Arrakis MUX"},
+ {HPHW_A_DIRECT, 0x005, 0x0000D, 0x00, "Dyun Kiuh MUX"},
+ {HPHW_A_DIRECT, 0x006, 0x0000D, 0x00, "Baat Kiuh AP/MUX (40299B)"},
+ {HPHW_A_DIRECT, 0x007, 0x0000D, 0x00, "Dino AP"},
+ {HPHW_A_DIRECT, 0x009, 0x0000D, 0x00, "Solaris Direct Connect MUX (J2092A)"},
+ {HPHW_A_DIRECT, 0x00A, 0x0000D, 0x00, "Solaris RS-422/423 MUX (J2093A)"},
+ {HPHW_A_DIRECT, 0x00B, 0x0000D, 0x00, "Solaris RS-422/423 Quadriloops MUX"},
+ {HPHW_A_DIRECT, 0x00C, 0x0000D, 0x00, "Solaris Modem MUX (J2094A)"},
+ {HPHW_A_DIRECT, 0x00D, 0x0000D, 0x00, "Twins Direct Connect MUX"},
+ {HPHW_A_DIRECT, 0x00E, 0x0000D, 0x00, "Twins Modem MUX"},
+ {HPHW_A_DIRECT, 0x00F, 0x0000D, 0x00, "Nautilus RS-485"},
+ {HPHW_A_DIRECT, 0x010, 0x0000D, 0x00, "UltraLight CAP/MUX"},
+ {HPHW_A_DIRECT, 0x015, 0x0000D, 0x00, "Eole CAP/MUX"},
+ {HPHW_A_DIRECT, 0x024, 0x0000D, 0x00, "Sahp Kiuh AP/MUX"},
+ {HPHW_A_DIRECT, 0x034, 0x0000D, 0x00, "Sahp Kiuh Low AP/MUX"},
+ {HPHW_A_DIRECT, 0x044, 0x0000D, 0x00, "Sahp Baat Kiuh AP/MUX"},
+ {HPHW_A_DIRECT, 0x004, 0x0000E, 0x80, "Burgundy RS-232"},
+ {HPHW_A_DIRECT, 0x005, 0x0000E, 0x80, "Silverfox RS-232"},
+ {HPHW_A_DIRECT, 0x006, 0x0000E, 0x80, "Lego RS-232"},
+ {HPHW_A_DIRECT, 0x004, 0x0000F, 0x00, "Peacock Graphics"},
+ {HPHW_A_DIRECT, 0x004, 0x00014, 0x80, "Burgundy HIL"},
+ {HPHW_A_DIRECT, 0x005, 0x00014, 0x80, "Peacock HIL"},
+ {HPHW_A_DIRECT, 0x004, 0x00015, 0x80, "Leonardo"},
+ {HPHW_A_DIRECT, 0x004, 0x00016, 0x80, "HP-PB HRM"},
+ {HPHW_A_DIRECT, 0x004, 0x00017, 0x80, "HP-PB HRC"},
+ {HPHW_A_DIRECT, 0x004, 0x0003A, 0x80, "Skunk Centronics (28655A)"},
+ {HPHW_A_DIRECT, 0x024, 0x0003A, 0x80, "Sahp Kiuh Centronics"},
+ {HPHW_A_DIRECT, 0x044, 0x0003A, 0x80, "Sahp Baat Kiuh Centronics"},
+ {HPHW_A_DIRECT, 0x004, 0x0004E, 0x80, "AT&T DataKit (AMSO)"},
+ {HPHW_A_DIRECT, 0x004, 0x0009B, 0x80, "Test&Meas GSC HPIB"},
+ {HPHW_A_DIRECT, 0x004, 0x000A8, 0x00, "Rocky2-120 Front Keyboard"},
+ {HPHW_A_DIRECT, 0x005, 0x000A8, 0x00, "Rocky2-150 Front Keyboard"},
+ {HPHW_A_DIRECT, 0x004, 0x00101, 0x80, "Hitachi Console Module"},
+ {HPHW_A_DIRECT, 0x004, 0x00102, 0x80, "Hitachi Boot Module"},
+ {HPHW_A_DIRECT, 0x004, 0x00203, 0x80, "MELCO HBMLA MLAIT"},
+ {HPHW_A_DIRECT, 0x004, 0x00208, 0x80, "MELCO HBDPC"},
+ {HPHW_A_DIRECT, 0x004, 0x00300, 0x00, "DCI TWINAX TERM IO MUX"},
+ {HPHW_A_DMA, 0x004, 0x00039, 0x80, "Skunk SCSI (28655A)"},
+ {HPHW_A_DMA, 0x005, 0x00039, 0x80, "KittyHawk CSY Core SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00039, 0x80, "Diablo SCSI"},
+ {HPHW_A_DMA, 0x024, 0x00039, 0x80, "Sahp Kiuh SCSI"},
+ {HPHW_A_DMA, 0x034, 0x00039, 0x80, "Sahp Kiuh Low SCSI"},
+ {HPHW_A_DMA, 0x044, 0x00039, 0x80, "Sahp Baat Kiuh SCSI"},
+ {HPHW_A_DMA, 0x004, 0x0003B, 0x80, "Wizard SCSI"},
+ {HPHW_A_DMA, 0x005, 0x0003B, 0x80, "KittyHawk CSY Core FW-SCSI"},
+ {HPHW_A_DMA, 0x006, 0x0003B, 0x80, "Symbios EPIC FW-SCSI"},
+ {HPHW_A_DMA, 0x004, 0x00040, 0x80, "HP-PB Shazam HPIB (28650A)"},
+ {HPHW_A_DMA, 0x005, 0x00040, 0x80, "Burgundy HPIB"},
+ {HPHW_A_DMA, 0x004, 0x00041, 0x80, "HP-PB HP-FL"},
+ {HPHW_A_DMA, 0x004, 0x00042, 0x80, "HP-PB LoQuix HPIB (28650B)"},
+ {HPHW_A_DMA, 0x004, 0x00043, 0x80, "HP-PB Crypt LoQuix"},
+ {HPHW_A_DMA, 0x004, 0x00044, 0x80, "HP-PB Shazam GPIO (28651A)"},
+ {HPHW_A_DMA, 0x004, 0x00045, 0x80, "HP-PB LoQuix GPIO"},
+ {HPHW_A_DMA, 0x004, 0x00046, 0x80, "2-Port X.25 NIO_ACC (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x00047, 0x80, "4-Port X.25 NIO_ACC (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x0004B, 0x80, "LGB Control"},
+ {HPHW_A_DMA, 0x004, 0x0004C, 0x80, "Martian RTI (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x0004D, 0x80, "ACC Mux (AMSO)"},
+ {HPHW_A_DMA, 0x004, 0x00050, 0x80, "Lanbrusca 802.3 (36967A)"},
+ {HPHW_A_DMA, 0x004, 0x00056, 0x80, "HP-PB LoQuix FDDI"},
+ {HPHW_A_DMA, 0x004, 0x00057, 0x80, "HP-PB LoQuix FDDI (28670A)"},
+ {HPHW_A_DMA, 0x012, 0x00089, 0x80, "Barracuda Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x013, 0x00089, 0x80, "Bluefish Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00089, 0x80, "Shrike Add-on FW-SCSI"},
+ {HPHW_A_DMA, 0x015, 0x00089, 0x80, "KittyHawk GSY Core FW-SCSI"},
+ {HPHW_A_DMA, 0x017, 0x00089, 0x80, "Shrike Jade Add-on FW-SCSI (A3644A)"},
+ {HPHW_A_DMA, 0x01F, 0x00089, 0x80, "SkyHawk 100/120 FW-SCSI"},
+ {HPHW_A_DMA, 0x027, 0x00089, 0x80, "Piranha 100 FW-SCSI"},
+ {HPHW_A_DMA, 0x032, 0x00089, 0x80, "Raven T' Core FW-SCSI"},
+ {HPHW_A_DMA, 0x03d, 0x00089, 0x80, "Merlin 160 Core FW-SCSI"},
+ {HPHW_A_DMA, 0x044, 0x00089, 0x80, "Mohawk Core FW-SCSI"},
+ {HPHW_A_DMA, 0x051, 0x00089, 0x80, "Firehawk FW-SCSI"},
+ {HPHW_A_DMA, 0x058, 0x00089, 0x80, "FireHawk 200 FW-SCSI"},
+ {HPHW_A_DMA, 0x05C, 0x00089, 0x80, "SummitHawk 230 Ultra-SCSI"},
+ {HPHW_A_DMA, 0x014, 0x00091, 0x80, "Baby Hugo Add-on Net FC (A3406A)"},
+ {HPHW_A_DMA, 0x020, 0x00091, 0x80, "Baby Jade Add-on Net FC (A3638A)"},
+ {HPHW_A_DMA, 0x004, 0x00092, 0x80, "GSC+ YLIASTER ATM"},
+ {HPHW_A_DMA, 0x004, 0x00095, 0x80, "Hamlyn GSC+ Network Card"},
+ {HPHW_A_DMA, 0x004, 0x00098, 0x80, "Lo-fat Emulator"},
+ {HPHW_A_DMA, 0x004, 0x0009A, 0x80, "GSC+ Venus ATM"},
+ {HPHW_A_DMA, 0x005, 0x0009A, 0x80, "GSC+ Samorobrive ATM"},
+ {HPHW_A_DMA, 0x004, 0x0009D, 0x80, "HP HSC-PCI Cards"},
+ {HPHW_A_DMA, 0x004, 0x0009E, 0x80, "Alaxis GSC+ 155Mb ATM"},
+ {HPHW_A_DMA, 0x005, 0x0009E, 0x80, "Alaxis GSC+ 622Mb ATM"},
+ {HPHW_A_DMA, 0x05C, 0x0009F, 0x80, "SummitHawk 230 USB"},
+ {HPHW_A_DMA, 0x05C, 0x000A0, 0x80, "SummitHawk 230 100BaseT"},
+ {HPHW_A_DMA, 0x015, 0x000A7, 0x80, "Baby Hugo Add-on mass FC (A3404A)"},
+ {HPHW_A_DMA, 0x018, 0x000A7, 0x80, "Mombasa GS Add-on mass FC (A3591)"},
+ {HPHW_A_DMA, 0x021, 0x000A7, 0x80, "Baby Jade Add-on mass FC (A3636A)"},
+ {HPHW_A_DMA, 0x004, 0x00201, 0x80, "MELCO HCMAP"},
+ {HPHW_A_DMA, 0x004, 0x00202, 0x80, "MELCO HBMLA MLAMA"},
+ {HPHW_A_DMA, 0x004, 0x00205, 0x80, "MELCO HBRFU"},
+ {HPHW_A_DMA, 0x004, 0x00380, 0x80, "Interphase NIO-FC"},
+ {HPHW_A_DMA, 0x004, 0x00381, 0x80, "Interphase NIO-ATM"},
+ {HPHW_A_DMA, 0x004, 0x00382, 0x80, "Interphase NIO-100BaseTX"},
+ {HPHW_BA, 0x004, 0x00070, 0x0, "Cobra Core BA"},
+ {HPHW_BA, 0x005, 0x00070, 0x0, "Coral Core BA"},
+ {HPHW_BA, 0x006, 0x00070, 0x0, "Bushmaster Core BA"},
+ {HPHW_BA, 0x007, 0x00070, 0x0, "Scorpio Core BA"},
+ {HPHW_BA, 0x008, 0x00070, 0x0, "Flounder Core BA"},
+ {HPHW_BA, 0x009, 0x00070, 0x0, "Outfield Core BA"},
+ {HPHW_BA, 0x00A, 0x00070, 0x0, "CoralII Core BA"},
+ {HPHW_BA, 0x00B, 0x00070, 0x0, "Scorpio Jr. Core BA"},
+ {HPHW_BA, 0x00C, 0x00070, 0x0, "Strider-50 Core BA"},
+ {HPHW_BA, 0x00D, 0x00070, 0x0, "Strider-33 Core BA"},
+ {HPHW_BA, 0x00E, 0x00070, 0x0, "Trailways-50 Core BA"},
+ {HPHW_BA, 0x00F, 0x00070, 0x0, "Trailways-33 Core BA"},
+ {HPHW_BA, 0x010, 0x00070, 0x0, "Pace Core BA"},
+ {HPHW_BA, 0x011, 0x00070, 0x0, "Sidewinder Core BA"},
+ {HPHW_BA, 0x019, 0x00070, 0x0, "Scorpio Sr. Core BA"},
+ {HPHW_BA, 0x020, 0x00070, 0x0, "Scorpio 100 Core BA"},
+ {HPHW_BA, 0x021, 0x00070, 0x0, "Spectra 50 Core BA"},
+ {HPHW_BA, 0x022, 0x00070, 0x0, "Spectra 75 Core BA"},
+ {HPHW_BA, 0x023, 0x00070, 0x0, "Spectra 100 Core BA"},
+ {HPHW_BA, 0x024, 0x00070, 0x0, "Fast Pace Core BA"},
+ {HPHW_BA, 0x026, 0x00070, 0x0, "CoralII Jaguar Core BA"},
+ {HPHW_BA, 0x004, 0x00076, 0x0, "Cobra EISA BA"},
+ {HPHW_BA, 0x005, 0x00076, 0x0, "Coral EISA BA"},
+ {HPHW_BA, 0x007, 0x00076, 0x0, "Scorpio EISA BA"},
+ {HPHW_BA, 0x00A, 0x00076, 0x0, "CoralII EISA BA"},
+ {HPHW_BA, 0x00B, 0x00076, 0x0, "Scorpio Jr. EISA BA"},
+ {HPHW_BA, 0x00C, 0x00076, 0x0, "Strider-50 Core EISA"},
+ {HPHW_BA, 0x00D, 0x00076, 0x0, "Strider-33 Core EISA"},
+ {HPHW_BA, 0x00E, 0x00076, 0x0, "Trailways-50 Core EISA"},
+ {HPHW_BA, 0x00F, 0x00076, 0x0, "Trailways-33 Core EISA"},
+ {HPHW_BA, 0x010, 0x00076, 0x0, "Pace Core EISA"},
+ {HPHW_BA, 0x019, 0x00076, 0x0, "Scorpio Sr. EISA BA"},
+ {HPHW_BA, 0x020, 0x00076, 0x0, "Scorpio 100 EISA BA"},
+ {HPHW_BA, 0x021, 0x00076, 0x0, "Spectra 50 EISA BA"},
+ {HPHW_BA, 0x022, 0x00076, 0x0, "Spectra 75 EISA BA"},
+ {HPHW_BA, 0x023, 0x00076, 0x0, "Spectra 100 EISA BA"},
+ {HPHW_BA, 0x026, 0x00076, 0x0, "CoralII Jaguar EISA BA"},
+ {HPHW_BA, 0x010, 0x00078, 0x0, "Pace VME BA"},
+ {HPHW_BA, 0x011, 0x00078, 0x0, "Sidewinder VME BA"},
+ {HPHW_BA, 0x01A, 0x00078, 0x0, "Anole 64 VME BA"},
+ {HPHW_BA, 0x01B, 0x00078, 0x0, "Anole 100 VME BA"},
+ {HPHW_BA, 0x024, 0x00078, 0x0, "Fast Pace VME BA"},
+ {HPHW_BA, 0x034, 0x00078, 0x0, "Anole T VME BA"},
+ {HPHW_BA, 0x04A, 0x00078, 0x0, "Anole L2 132 BME BA"},
+ {HPHW_BA, 0x04C, 0x00078, 0x0, "Anole L2 165 VME BA"},
+ {HPHW_BA, 0x011, 0x00081, 0x0, "WB-96 Core BA"},
+ {HPHW_BA, 0x012, 0x00081, 0x0, "Orville UX Core BA"},
+ {HPHW_BA, 0x013, 0x00081, 0x0, "Wilbur UX Core BA"},
+ {HPHW_BA, 0x014, 0x00081, 0x0, "WB-80 Core BA"},
+ {HPHW_BA, 0x015, 0x00081, 0x0, "KittyHawk GSY Core BA"},
+ {HPHW_BA, 0x016, 0x00081, 0x0, "Gecko Core BA"},
+ {HPHW_BA, 0x018, 0x00081, 0x0, "Gecko Optional BA"},
+ {HPHW_BA, 0x01A, 0x00081, 0x0, "Anole 64 Core BA"},
+ {HPHW_BA, 0x01B, 0x00081, 0x0, "Anole 100 Core BA"},
+ {HPHW_BA, 0x01C, 0x00081, 0x0, "Gecko 80 Core BA"},
+ {HPHW_BA, 0x01D, 0x00081, 0x0, "Gecko 100 Core BA"},
+ {HPHW_BA, 0x01F, 0x00081, 0x0, "SkyHawk 100/120 Core BA"},
+ {HPHW_BA, 0x027, 0x00081, 0x0, "Piranha 100 Core BA"},
+ {HPHW_BA, 0x028, 0x00081, 0x0, "Mirage Jr Core BA"},
+ {HPHW_BA, 0x029, 0x00081, 0x0, "Mirage Core BA"},
+ {HPHW_BA, 0x02A, 0x00081, 0x0, "Electra Core BA"},
+ {HPHW_BA, 0x02B, 0x00081, 0x0, "Mirage 80 Core BA"},
+ {HPHW_BA, 0x02C, 0x00081, 0x0, "Mirage 100+ Core BA"},
+ {HPHW_BA, 0x02E, 0x00081, 0x0, "UL 350 Lasi Core BA"},
+ {HPHW_BA, 0x02F, 0x00081, 0x0, "UL 550 Lasi Core BA"},
+ {HPHW_BA, 0x032, 0x00081, 0x0, "Raven T' Core BA"},
+ {HPHW_BA, 0x033, 0x00081, 0x0, "Anole T Core BA"},
+ {HPHW_BA, 0x034, 0x00081, 0x0, "SAIC L-80 Core BA"},
+ {HPHW_BA, 0x035, 0x00081, 0x0, "PCX-L2 712/132 Core BA"},
+ {HPHW_BA, 0x036, 0x00081, 0x0, "PCX-L2 712/160 Core BA"},
+ {HPHW_BA, 0x03B, 0x00081, 0x0, "Raven U/L2 Core BA"},
+ {HPHW_BA, 0x03C, 0x00081, 0x0, "Merlin 132 Core BA"},
+ {HPHW_BA, 0x03D, 0x00081, 0x0, "Merlin 160 Core BA"},
+ {HPHW_BA, 0x03E, 0x00081, 0x0, "Merlin+ 132 Core BA"},
+ {HPHW_BA, 0x03F, 0x00081, 0x0, "Merlin+ 180 Core BA"},
+ {HPHW_BA, 0x044, 0x00081, 0x0, "Mohawk Core BA"},
+ {HPHW_BA, 0x045, 0x00081, 0x0, "Rocky1 Core BA"},
+ {HPHW_BA, 0x046, 0x00081, 0x0, "Rocky2 120 Core BA"},
+ {HPHW_BA, 0x047, 0x00081, 0x0, "Rocky2 150 Core BA"},
+ {HPHW_BA, 0x04B, 0x00081, 0x0, "Anole L2 132 Core BA"},
+ {HPHW_BA, 0x04D, 0x00081, 0x0, "Anole L2 165 Core BA"},
+ {HPHW_BA, 0x04E, 0x00081, 0x0, "Kiji L2 132 Core BA"},
+ {HPHW_BA, 0x050, 0x00081, 0x0, "Merlin Jr 132 Core BA"},
+ {HPHW_BA, 0x051, 0x00081, 0x0, "Firehawk Core BA"},
+ {HPHW_BA, 0x056, 0x00081, 0x0, "Raven+ w SE FWSCSI Core BA"},
+ {HPHW_BA, 0x057, 0x00081, 0x0, "Raven+ w Diff FWSCSI Core BA"},
+ {HPHW_BA, 0x058, 0x00081, 0x0, "FireHawk 200 Core BA"},
+ {HPHW_BA, 0x05C, 0x00081, 0x0, "SummitHawk 230 Core BA"},
+ {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 132 Core BA"},
+ {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 180 Core BA"},
+ {HPHW_BA, 0x05F, 0x00081, 0x0, "Staccato 180 Lasi"},
+ {HPHW_BA, 0x800, 0x00081, 0x0, "Hitachi Tiny 64 Core BA"},
+ {HPHW_BA, 0x801, 0x00081, 0x0, "Hitachi Tiny 80 Core BA"},
+ {HPHW_BA, 0x004, 0x0008B, 0x0, "Anole Optional PCMCIA BA"},
+ {HPHW_BA, 0x004, 0x0008E, 0x0, "GSC ITR Wax BA"},
+ {HPHW_BA, 0x011, 0x0008E, 0x0, "SuperPace Wax BA"},
+ {HPHW_BA, 0x012, 0x0008E, 0x0, "Mirage Jr Wax BA"},
+ {HPHW_BA, 0x013, 0x0008E, 0x0, "Mirage Wax BA"},
+ {HPHW_BA, 0x014, 0x0008E, 0x0, "Electra Wax BA"},
+ {HPHW_BA, 0x017, 0x0008E, 0x0, "Raven Backplane Wax BA"},
+ {HPHW_BA, 0x01E, 0x0008E, 0x0, "Raven T' Wax BA"},
+ {HPHW_BA, 0x01F, 0x0008E, 0x0, "SkyHawk Wax BA"},
+ {HPHW_BA, 0x023, 0x0008E, 0x0, "Rocky1 Wax BA"},
+ {HPHW_BA, 0x02B, 0x0008E, 0x0, "Mirage 80 Wax BA"},
+ {HPHW_BA, 0x02C, 0x0008E, 0x0, "Mirage 100+ Wax BA"},
+ {HPHW_BA, 0x030, 0x0008E, 0x0, "UL 350 Core Wax BA"},
+ {HPHW_BA, 0x031, 0x0008E, 0x0, "UL 550 Core Wax BA"},
+ {HPHW_BA, 0x034, 0x0008E, 0x0, "SAIC L-80 Wax BA"},
+ {HPHW_BA, 0x03A, 0x0008E, 0x0, "Merlin+ Wax BA"},
+ {HPHW_BA, 0x040, 0x0008E, 0x0, "Merlin 132 Wax BA"},
+ {HPHW_BA, 0x041, 0x0008E, 0x0, "Merlin 160 Wax BA"},
+ {HPHW_BA, 0x043, 0x0008E, 0x0, "Merlin 132/160 Wax BA"},
+ {HPHW_BA, 0x052, 0x0008E, 0x0, "Raven+ Hi Power Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x054, 0x0008E, 0x0, "Raven+ Lo Power Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x059, 0x0008E, 0x0, "FireHawk 200 Wax BA"},
+ {HPHW_BA, 0x05A, 0x0008E, 0x0, "Raven+ L2 Backplane w/EISA Wax BA"},
+ {HPHW_BA, 0x05D, 0x0008E, 0x0, "SummitHawk Wax BA"},
+ {HPHW_BA, 0x800, 0x0008E, 0x0, "Hitachi Tiny 64 Wax BA"},
+ {HPHW_BA, 0x801, 0x0008E, 0x0, "Hitachi Tiny 80 Wax BA"},
+ {HPHW_BA, 0x011, 0x00090, 0x0, "SuperPace Wax EISA BA"},
+ {HPHW_BA, 0x017, 0x00090, 0x0, "Raven Backplane Wax EISA BA"},
+ {HPHW_BA, 0x01E, 0x00090, 0x0, "Raven T' Wax EISA BA"},
+ {HPHW_BA, 0x01F, 0x00090, 0x0, "SkyHawk 100/120 Wax EISA BA"},
+ {HPHW_BA, 0x027, 0x00090, 0x0, "Piranha 100 Wax EISA BA"},
+ {HPHW_BA, 0x028, 0x00090, 0x0, "Mirage Jr Wax EISA BA"},
+ {HPHW_BA, 0x029, 0x00090, 0x0, "Mirage Wax EISA BA"},
+ {HPHW_BA, 0x02A, 0x00090, 0x0, "Electra Wax EISA BA"},
+ {HPHW_BA, 0x02B, 0x00090, 0x0, "Mirage 80 Wax EISA BA"},
+ {HPHW_BA, 0x02C, 0x00090, 0x0, "Mirage 100+ Wax EISA BA"},
+ {HPHW_BA, 0x030, 0x00090, 0x0, "UL 350 Wax EISA BA"},
+ {HPHW_BA, 0x031, 0x00090, 0x0, "UL 550 Wax EISA BA"},
+ {HPHW_BA, 0x034, 0x00090, 0x0, "SAIC L-80 Wax EISA BA"},
+ {HPHW_BA, 0x03A, 0x00090, 0x0, "Merlin+ Wax EISA BA"},
+ {HPHW_BA, 0x040, 0x00090, 0x0, "Merlin 132 Wax EISA BA"},
+ {HPHW_BA, 0x041, 0x00090, 0x0, "Merlin 160 Wax EISA BA"},
+ {HPHW_BA, 0x043, 0x00090, 0x0, "Merlin 132/160 Wax EISA BA"},
+ {HPHW_BA, 0x052, 0x00090, 0x0, "Raven Hi Power Backplane Wax EISA BA"},
+ {HPHW_BA, 0x054, 0x00090, 0x0, "Raven Lo Power Backplane Wax EISA BA"},
+ {HPHW_BA, 0x059, 0x00090, 0x0, "FireHawk 200 Wax EISA BA"},
+ {HPHW_BA, 0x05A, 0x00090, 0x0, "Raven L2 Backplane Wax EISA BA"},
+ {HPHW_BA, 0x05D, 0x00090, 0x0, "SummitHawk Wax EISA BA"},
+ {HPHW_BA, 0x800, 0x00090, 0x0, "Hitachi Tiny 64 Wax EISA BA"},
+ {HPHW_BA, 0x801, 0x00090, 0x0, "Hitachi Tiny 80 Wax EISA BA"},
+ {HPHW_BA, 0x01A, 0x00093, 0x0, "Anole 64 TIMI BA"},
+ {HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 64 TIMI BA"},
+ {HPHW_BA, 0x034, 0x00093, 0x0, "Anole T TIMI BA"},
+ {HPHW_BA, 0x04A, 0x00093, 0x0, "Anole L2 132 TIMI BA"},
+ {HPHW_BA, 0x04C, 0x00093, 0x0, "Anole L2 165 TIMI BA"},
+ {HPHW_BA, 0x582, 0x000A5, 0x00, "Epic PCI Bridge"},
+ {HPHW_BCPORT, 0x504, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"},
+ {HPHW_BCPORT, 0x505, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"},
+ {HPHW_BCPORT, 0x503, 0x0000C, 0x00, "Java BC GSC+ Port"},
+ {HPHW_BCPORT, 0x57F, 0x0000C, 0x00, "Hitachi Ghostview GSC+ Port"},
+ {HPHW_BCPORT, 0x501, 0x0000C, 0x00, "U2-IOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x502, 0x0000C, 0x00, "Uturn-IOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x780, 0x0000C, 0x00, "Astro BC Ropes Port"},
+ {HPHW_BCPORT, 0x506, 0x0000C, 0x00, "NEC-IOS BC HSC Port"},
+ {HPHW_BCPORT, 0x004, 0x0000C, 0x00, "Cheetah BC SMB Port"},
+ {HPHW_BCPORT, 0x006, 0x0000C, 0x00, "Cheetah BC MID_BUS Port"},
+ {HPHW_BCPORT, 0x005, 0x0000C, 0x00, "Condor BC MID_BUS Port"},
+ {HPHW_BCPORT, 0x100, 0x0000C, 0x00, "Condor BC HP-PB Port"},
+ {HPHW_BCPORT, 0x184, 0x0000C, 0x00, "Summit BC Port"},
+ {HPHW_BCPORT, 0x101, 0x0000C, 0x00, "Summit BC HP-PB Port"},
+ {HPHW_BCPORT, 0x102, 0x0000C, 0x00, "HP-PB Port (prefetch)"},
+ {HPHW_BCPORT, 0x500, 0x0000C, 0x00, "Gecko BOA BC GSC+ Port"},
+ {HPHW_BCPORT, 0x103, 0x0000C, 0x00, "Gecko BOA BC HP-PB Port"},
+ {HPHW_BCPORT, 0x507, 0x0000C, 0x00, "Keyaki BC GSC+ Port"},
+ {HPHW_BCPORT, 0x508, 0x0000C, 0x00, "Keyaki-DX BC GSC+ Port"},
+ {HPHW_BCPORT, 0x584, 0x0000C, 0x10, "DEW BC Runway Port"},
+ {HPHW_BCPORT, 0x800, 0x0000C, 0x10, "DEW BC Merced Port"},
+ {HPHW_BCPORT, 0x801, 0x0000C, 0x10, "SMC Bus Interface Merced Bus0"},
+ {HPHW_BCPORT, 0x802, 0x0000C, 0x10, "SMC Bus INterface Merced Bus1"},
+ {HPHW_BCPORT, 0x803, 0x0000C, 0x10, "IKE I/O Bus Converter Merced Port"},
+ {HPHW_BCPORT, 0x781, 0x0000C, 0x00, "IKE I/O Bus Converter Ropes Port"},
+ {HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O Bus Converter Merced Port"},
+ {HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O Bus Converter Ropes Port"},
+ {HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"},
+ {HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"},
+ {HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"},
+ {HPHW_BRIDGE, 0x583, 0x000A5, 0x00, "Saga PCI Bridge"},
+ {HPHW_B_DMA, 0x004, 0x00018, 0x00, "Parallel I/O"},
+ {HPHW_B_DMA, 0x004, 0x00019, 0x00, "Parallel RDB"},
+ {HPHW_B_DMA, 0x004, 0x00020, 0x80, "MID_BUS PSI"},
+ {HPHW_B_DMA, 0x004, 0x0002F, 0x80, "HP-PB Transit PSI (36960A)"},
+ {HPHW_B_DMA, 0x008, 0x00051, 0x80, "HP-PB Transit 802.3"},
+ {HPHW_B_DMA, 0x004, 0x00052, 0x80, "Miura LAN/Console (J2146A)"},
+ {HPHW_B_DMA, 0x008, 0x00058, 0x80, "HP-PB Transit 802.4"},
+ {HPHW_B_DMA, 0x005, 0x00060, 0x80, "KittyHawk CSY Core LAN/Console"},
+ {HPHW_B_DMA, 0x014, 0x00060, 0x80, "Diablo LAN/Console"},
+ {HPHW_B_DMA, 0x054, 0x00060, 0x80, "Countach LAN/Console"},
+ {HPHW_B_DMA, 0x004, 0x00094, 0x80, "KittyHawk GSC+ Exerciser"},
+ {HPHW_B_DMA, 0x004, 0x00100, 0x80, "HP-PB HF Interface"},
+ {HPHW_B_DMA, 0x000, 0x00206, 0x80, "MELCO HMPHA"},
+ {HPHW_B_DMA, 0x005, 0x00206, 0x80, "MELCO HMPHA_10"},
+ {HPHW_B_DMA, 0x006, 0x00206, 0x80, "MELCO HMQHA"},
+ {HPHW_B_DMA, 0x007, 0x00206, 0x80, "MELCO HMQHA_10"},
+ {HPHW_B_DMA, 0x004, 0x207, 0x80, "MELCO HNDWA MDWS-70"},
+ {HPHW_CIO, 0x004, 0x00010, 0x00, "VLSI CIO"},
+ {HPHW_CIO, 0x005, 0x00010, 0x00, "Silverfox CIO"},
+ {HPHW_CIO, 0x006, 0x00010, 0x00, "Emerald CIO"},
+ {HPHW_CIO, 0x008, 0x00010, 0x00, "Discrete CIO"},
+ {HPHW_CONSOLE, 0x004, 0x0001C, 0x00, "Cheetah console"},
+ {HPHW_CONSOLE, 0x005, 0x0001C, 0x00, "Emerald console"},
+ {HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"},
+ {HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"},
+ {HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"},
+ {HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"},
+ {HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"},
+ {HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"},
+ {HPHW_FIO, 0x004, 0x0004F, 0x0, "8-Port X.25 EISA-ACC (AMSO)"},
+ {HPHW_FIO, 0x004, 0x00071, 0x0, "Cobra Core SCSI"},
+ {HPHW_FIO, 0x005, 0x00071, 0x0, "Coral Core SCSI"},
+ {HPHW_FIO, 0x006, 0x00071, 0x0, "Bushmaster Core SCSI"},
+ {HPHW_FIO, 0x007, 0x00071, 0x0, "Scorpio Core SCSI"},
+ {HPHW_FIO, 0x008, 0x00071, 0x0, "Flounder Core SCSI"},
+ {HPHW_FIO, 0x009, 0x00071, 0x0, "Outfield Core SCSI"},
+ {HPHW_FIO, 0x00A, 0x00071, 0x0, "CoralII Core SCSI"},
+ {HPHW_FIO, 0x00B, 0x00071, 0x0, "Scorpio Jr. Core SCSI"},
+ {HPHW_FIO, 0x00C, 0x00071, 0x0, "Strider-50 Core SCSI"},
+ {HPHW_FIO, 0x00D, 0x00071, 0x0, "Strider-33 Core SCSI"},
+ {HPHW_FIO, 0x00E, 0x00071, 0x0, "Trailways-50 Core SCSI"},
+ {HPHW_FIO, 0x00F, 0x00071, 0x0, "Trailways-33 Core SCSI"},
+ {HPHW_FIO, 0x010, 0x00071, 0x0, "Pace Core SCSI"},
+ {HPHW_FIO, 0x011, 0x00071, 0x0, "Sidewinder Core SCSI"},
+ {HPHW_FIO, 0x019, 0x00071, 0x0, "Scorpio Sr. Core SCSI"},
+ {HPHW_FIO, 0x020, 0x00071, 0x0, "Scorpio 100 Core SCSI"},
+ {HPHW_FIO, 0x021, 0x00071, 0x0, "Spectra 50 Core SCSI"},
+ {HPHW_FIO, 0x022, 0x00071, 0x0, "Spectra 75 Core SCSI"},
+ {HPHW_FIO, 0x023, 0x00071, 0x0, "Spectra 100 Core SCSI"},
+ {HPHW_FIO, 0x024, 0x00071, 0x0, "Fast Pace Core SCSI"},
+ {HPHW_FIO, 0x026, 0x00071, 0x0, "CoralII Jaguar Core SCSI"},
+ {HPHW_FIO, 0x004, 0x00072, 0x0, "Cobra Core LAN (802.3)"},
+ {HPHW_FIO, 0x005, 0x00072, 0x0, "Coral Core LAN (802.3)"},
+ {HPHW_FIO, 0x006, 0x00072, 0x0, "Bushmaster Core LAN (802.3)"},
+ {HPHW_FIO, 0x007, 0x00072, 0x0, "Scorpio Core LAN (802.3)"},
+ {HPHW_FIO, 0x008, 0x00072, 0x0, "Flounder Core LAN (802.3)"},
+ {HPHW_FIO, 0x009, 0x00072, 0x0, "Outfield Core LAN (802.3)"},
+ {HPHW_FIO, 0x00A, 0x00072, 0x0, "CoralII Core LAN (802.3)"},
+ {HPHW_FIO, 0x00B, 0x00072, 0x0, "Scorpio Jr. Core LAN (802.3)"},
+ {HPHW_FIO, 0x00C, 0x00072, 0x0, "Strider-50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00D, 0x00072, 0x0, "Strider-33 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00E, 0x00072, 0x0, "Trailways-50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x00F, 0x00072, 0x0, "Trailways-33 Core LAN (802.3)"},
+ {HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core Lan (802.3)"},
+ {HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core Lan (802.3)"},
+ {HPHW_FIO, 0x019, 0x00072, 0x0, "Scorpio Sr. Core LAN (802.3)"},
+ {HPHW_FIO, 0x020, 0x00072, 0x0, "Scorpio 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x021, 0x00072, 0x0, "Spectra 50 Core LAN (802.3)"},
+ {HPHW_FIO, 0x022, 0x00072, 0x0, "Spectra 75 Core LAN (802.3)"},
+ {HPHW_FIO, 0x023, 0x00072, 0x0, "Spectra 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core Lan (802.3)"},
+ {HPHW_FIO, 0x026, 0x00072, 0x0, "CoralII Jaguar Core LAN (802.3)"},
+ {HPHW_FIO, 0x004, 0x00073, 0x0, "Cobra Core HIL"},
+ {HPHW_FIO, 0x005, 0x00073, 0x0, "Coral Core HIL"},
+ {HPHW_FIO, 0x006, 0x00073, 0x0, "Bushmaster Core HIL"},
+ {HPHW_FIO, 0x007, 0x00073, 0x0, "Scorpio Core HIL"},
+ {HPHW_FIO, 0x008, 0x00073, 0x0, "Flounder Core HIL"},
+ {HPHW_FIO, 0x009, 0x00073, 0x0, "Outfield Core HIL"},
+ {HPHW_FIO, 0x00A, 0x00073, 0x0, "CoralII Core HIL"},
+ {HPHW_FIO, 0x00B, 0x00073, 0x0, "Scorpio Jr. Core HIL"},
+ {HPHW_FIO, 0x00C, 0x00073, 0x0, "Strider-50 Core HIL"},
+ {HPHW_FIO, 0x00D, 0x00073, 0x0, "Strider-33 Core HIL"},
+ {HPHW_FIO, 0x00E, 0x00073, 0x0, "Trailways-50 Core HIL"},
+ {HPHW_FIO, 0x00F, 0x00073, 0x0, "Trailways-33 Core HIL"},
+ {HPHW_FIO, 0x010, 0x00073, 0x0, "Pace Core HIL"},
+ {HPHW_FIO, 0x011, 0x00073, 0xcc, "SuperPace Wax HIL"},
+ {HPHW_FIO, 0x012, 0x00073, 0x0, "Mirage Jr Wax HIL"},
+ {HPHW_FIO, 0x013, 0x00073, 0x0, "Mirage 100 Wax HIL"},
+ {HPHW_FIO, 0x014, 0x00073, 0x0, "Electra Wax HIL"},
+ {HPHW_FIO, 0x017, 0x00073, 0x0, "Raven Backplane Wax HIL"},
+ {HPHW_FIO, 0x019, 0x00073, 0x0, "Scorpio Sr. Core HIL"},
+ {HPHW_FIO, 0x01E, 0x00073, 0x0, "Raven T' Wax HIL"},
+ {HPHW_FIO, 0x01F, 0x00073, 0x0, "SkyHawk 100/120 Wax HIL"},
+ {HPHW_FIO, 0x020, 0x00073, 0x0, "Scorpio 100 Core HIL"},
+ {HPHW_FIO, 0x021, 0x00073, 0x0, "Spectra 50 Core HIL"},
+ {HPHW_FIO, 0x022, 0x00073, 0x0, "Spectra 75 Core HIL"},
+ {HPHW_FIO, 0x023, 0x00073, 0x0, "Spectra 100 Core HIL"},
+ {HPHW_FIO, 0x024, 0x00073, 0x0, "Fast Pace Core HIL"},
+ {HPHW_FIO, 0x026, 0x00073, 0x0, "CoralII Jaguar Core HIL"},
+ {HPHW_FIO, 0x02B, 0x00073, 0x0, "Mirage 80 Wax HIL"},
+ {HPHW_FIO, 0x02C, 0x00073, 0x0, "Mirage 100+ Wax HIL"},
+ {HPHW_FIO, 0x03A, 0x00073, 0x0, "Merlin+ Wax HIL"},
+ {HPHW_FIO, 0x040, 0x00073, 0x0, "Merlin 132 Wax HIL"},
+ {HPHW_FIO, 0x041, 0x00073, 0x0, "Merlin 160 Wax HIL"},
+ {HPHW_FIO, 0x043, 0x00073, 0x0, "Merlin 132/160 Wax HIL"},
+ {HPHW_FIO, 0x052, 0x00073, 0x0, "Raven+ Hi Power Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x053, 0x00073, 0x0, "Raven+ Hi Power Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x054, 0x00073, 0x0, "Raven+ Lo Power Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x055, 0x00073, 0x0, "Raven+ Lo Power Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x059, 0x00073, 0x0, "FireHawk 200 Wax HIL"},
+ {HPHW_FIO, 0x05A, 0x00073, 0x0, "Raven+ L2 Backplane w/EISA Wax HIL"},
+ {HPHW_FIO, 0x05B, 0x00073, 0x0, "Raven+ L2 Backplane wo/EISA Wax HIL"},
+ {HPHW_FIO, 0x05D, 0x00073, 0x0, "SummitHawk Wax HIL"},
+ {HPHW_FIO, 0x800, 0x00073, 0x0, "Hitachi Tiny 64 Wax HIL"},
+ {HPHW_FIO, 0x801, 0x00073, 0x0, "Hitachi Tiny 80 Wax HIL"},
+ {HPHW_FIO, 0x004, 0x00074, 0x0, "Cobra Core Centronics"},
+ {HPHW_FIO, 0x005, 0x00074, 0x0, "Coral Core Centronics"},
+ {HPHW_FIO, 0x006, 0x00074, 0x0, "Bushmaster Core Centronics"},
+ {HPHW_FIO, 0x007, 0x00074, 0x0, "Scorpio Core Centronics"},
+ {HPHW_FIO, 0x008, 0x00074, 0x0, "Flounder Core Centronics"},
+ {HPHW_FIO, 0x009, 0x00074, 0x0, "Outfield Core Centronics"},
+ {HPHW_FIO, 0x00A, 0x00074, 0x0, "CoralII Core Centronics"},
+ {HPHW_FIO, 0x00B, 0x00074, 0x0, "Scorpio Jr. Core Centronics"},
+ {HPHW_FIO, 0x00C, 0x00074, 0x0, "Strider-50 Core Centronics"},
+ {HPHW_FIO, 0x00D, 0x00074, 0x0, "Strider-33 Core Centronics"},
+ {HPHW_FIO, 0x00E, 0x00074, 0x0, "Trailways-50 Core Centronics"},
+ {HPHW_FIO, 0x00F, 0x00074, 0x0, "Trailways-33 Core Centronics"},
+ {HPHW_FIO, 0x010, 0x00074, 0x0, "Pace Core Centronics"},
+ {HPHW_FIO, 0x011, 0x00074, 0x0, "Sidewinder Core Centronics"},
+ {HPHW_FIO, 0x015, 0x00074, 0x0, "KittyHawk GSY Core Centronics"},
+ {HPHW_FIO, 0x016, 0x00074, 0x0, "Gecko Core Centronics"},
+ {HPHW_FIO, 0x019, 0x00074, 0x0, "Scorpio Sr. Core Centronics"},
+ {HPHW_FIO, 0x01A, 0x00074, 0x0, "Anole 64 Core Centronics"},
+ {HPHW_FIO, 0x01B, 0x00074, 0x0, "Anole 100 Core Centronics"},
+ {HPHW_FIO, 0x01C, 0x00074, 0x0, "Gecko 80 Core Centronics"},
+ {HPHW_FIO, 0x01D, 0x00074, 0x0, "Gecko 100 Core Centronics"},
+ {HPHW_FIO, 0x01F, 0x00074, 0x0, "SkyHawk 100/120 Core Centronics"},
+ {HPHW_FIO, 0x020, 0x00074, 0x0, "Scorpio 100 Core Centronics"},
+ {HPHW_FIO, 0x021, 0x00074, 0x0, "Spectra 50 Core Centronics"},
+ {HPHW_FIO, 0x022, 0x00074, 0x0, "Spectra 75 Core Centronics"},
+ {HPHW_FIO, 0x023, 0x00074, 0x0, "Spectra 100 Core Centronics"},
+ {HPHW_FIO, 0x024, 0x00074, 0x0, "Fast Pace Core Centronics"},
+ {HPHW_FIO, 0x026, 0x00074, 0x0, "CoralII Jaguar Core Centronics"},
+ {HPHW_FIO, 0x027, 0x00074, 0x0, "Piranha 100 Core Centronics"},
+ {HPHW_FIO, 0x028, 0x00074, 0x0, "Mirage Jr Core Centronics"},
+ {HPHW_FIO, 0x029, 0x00074, 0x0, "Mirage Core Centronics"},
+ {HPHW_FIO, 0x02A, 0x00074, 0x0, "Electra Core Centronics"},
+ {HPHW_FIO, 0x02B, 0x00074, 0x0, "Mirage 80 Core Centronics"},
+ {HPHW_FIO, 0x02C, 0x00074, 0x0, "Mirage 100+ Core Centronics"},
+ {HPHW_FIO, 0x02E, 0x00074, 0x0, "UL 350 Core Centronics"},
+ {HPHW_FIO, 0x02F, 0x00074, 0x0, "UL 550 Core Centronics"},
+ {HPHW_FIO, 0x032, 0x00074, 0x0, "Raven T' Core Centronics"},
+ {HPHW_FIO, 0x033, 0x00074, 0x0, "Anole T Core Centronics"},
+ {HPHW_FIO, 0x034, 0x00074, 0x0, "SAIC L-80 Core Centronics"},
+ {HPHW_FIO, 0x035, 0x00074, 0x0, "PCX-L2 712/132 Core Centronics"},
+ {HPHW_FIO, 0x036, 0x00074, 0x0, "PCX-L2 712/160 Core Centronics"},
+ {HPHW_FIO, 0x03B, 0x00074, 0x0, "Raven U/L2 Core Centronics"},
+ {HPHW_FIO, 0x03C, 0x00074, 0x0, "Merlin 132 Core Centronics"},
+ {HPHW_FIO, 0x03D, 0x00074, 0x0, "Merlin 160 Core Centronics"},
+ {HPHW_FIO, 0x03E, 0x00074, 0x0, "Merlin+ 132 Core Centronics"},
+ {HPHW_FIO, 0x03F, 0x00074, 0x0, "Merlin+ 180 Core Centronics"},
+ {HPHW_FIO, 0x044, 0x00074, 0x0, "Mohawk Core Centronics"},
+ {HPHW_FIO, 0x045, 0x00074, 0x0, "Rocky1 Core Centronics"},
+ {HPHW_FIO, 0x046, 0x00074, 0x0, "Rocky2 120 Core Centronics"},
+ {HPHW_FIO, 0x047, 0x00074, 0x0, "Rocky2 150 Core Centronics"},
+ {HPHW_FIO, 0x04B, 0x00074, 0x0, "Anole L2 132 Core Centronics"},
+ {HPHW_FIO, 0x04D, 0x00074, 0x0, "Anole L2 165 Core Centronics"},
+ {HPHW_FIO, 0x050, 0x00074, 0x0, "Merlin Jr 132 Core Centronics"},
+ {HPHW_FIO, 0x051, 0x00074, 0x0, "Firehawk Core Centronics"},
+ {HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ wSE FWSCSI Core Centronics"},
+ {HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ wDiff FWSCSI Core Centronics"},
+ {HPHW_FIO, 0x058, 0x00074, 0x0, "FireHawk 200 Core Centronics"},
+ {HPHW_FIO, 0x05C, 0x00074, 0x0, "SummitHawk 230 Core Centronics"},
+ {HPHW_FIO, 0x800, 0x00074, 0x0, "Hitachi Tiny 64 Core Centronics"},
+ {HPHW_FIO, 0x801, 0x00074, 0x0, "Hitachi Tiny 80 Core Centronics"},
+ {HPHW_FIO, 0x004, 0x00075, 0x0, "Cobra Core RS-232"},
+ {HPHW_FIO, 0x005, 0x00075, 0x0, "Coral Core RS-232"},
+ {HPHW_FIO, 0x006, 0x00075, 0x0, "Bushmaster Core RS-232"},
+ {HPHW_FIO, 0x007, 0x00075, 0x0, "Scorpio Core RS-232"},
+ {HPHW_FIO, 0x008, 0x00075, 0x0, "Flounder Core RS-232"},
+ {HPHW_FIO, 0x009, 0x00075, 0x0, "Outfield Core RS-232"},
+ {HPHW_FIO, 0x00A, 0x00075, 0x0, "CoralII Core RS-232"},
+ {HPHW_FIO, 0x00B, 0x00075, 0x0, "Scorpio Jr. Core RS-232"},
+ {HPHW_FIO, 0x00C, 0x00075, 0x0, "Strider-50 Core RS-232"},
+ {HPHW_FIO, 0x00D, 0x00075, 0x0, "Strider-33 Core RS-232"},
+ {HPHW_FIO, 0x00E, 0x00075, 0x0, "Trailways-50 Core RS-232"},
+ {HPHW_FIO, 0x00F, 0x00075, 0x0, "Trailways-33 Core RS-232"},
+ {HPHW_FIO, 0x010, 0x00075, 0x0, "Pace Core RS-232"},
+ {HPHW_FIO, 0x011, 0x00075, 0x0, "Sidewinder Core RS-232"},
+ {HPHW_FIO, 0x019, 0x00075, 0x0, "Scorpio Sr. Core RS-232"},
+ {HPHW_FIO, 0x020, 0x00075, 0x0, "Scorpio 100 Core RS-232"},
+ {HPHW_FIO, 0x021, 0x00075, 0x0, "Spectra 50 Core RS-232"},
+ {HPHW_FIO, 0x022, 0x00075, 0x0, "Spectra 75 Core RS-232"},
+ {HPHW_FIO, 0x023, 0x00075, 0x0, "Spectra 100 Core RS-232"},
+ {HPHW_FIO, 0x024, 0x00075, 0x0, "Fast Pace Core RS-232"},
+ {HPHW_FIO, 0x026, 0x00075, 0x0, "CoralII Jaguar Core RS-232"},
+ {HPHW_FIO, 0x004, 0x00077, 0x0, "Coral SGC Graphics"},
+ {HPHW_FIO, 0x005, 0x00077, 0x0, "Hyperdrive Optional Graphics"},
+ {HPHW_FIO, 0x006, 0x00077, 0x0, "Stinger Optional Graphics"},
+ {HPHW_FIO, 0x007, 0x00077, 0x0, "Scorpio Builtin Graphics"},
+ {HPHW_FIO, 0x008, 0x00077, 0x0, "Anole Hyperdrive Optional Graphics"},
+ {HPHW_FIO, 0x009, 0x00077, 0x0, "Thunder II graphics EISA form"},
+ {HPHW_FIO, 0x00A, 0x00077, 0x0, "Thunder II graphics GSA form"},
+ {HPHW_FIO, 0x00B, 0x00077, 0x0, "Scorpio Jr Builtin Graphics"},
+ {HPHW_FIO, 0x00C, 0x00077, 0x0, "Strider-50 SSC Graphics"},
+ {HPHW_FIO, 0x00D, 0x00077, 0x0, "Strider-33 SSC Graphics"},
+ {HPHW_FIO, 0x00E, 0x00077, 0x0, "Trailways-50 SSC Graphics"},
+ {HPHW_FIO, 0x00F, 0x00077, 0x0, "Trailways-33 SSC Graphics"},
+ {HPHW_FIO, 0x010, 0x00077, 0x0, "Pace SGC Graphics"},
+ {HPHW_FIO, 0x011, 0x00077, 0x0, "Mohawk Opt. 2D Graphics (Kid)"},
+ {HPHW_FIO, 0x012, 0x00077, 0x0, "Raven Opt. 2D Graphics (Goat)"},
+ {HPHW_FIO, 0x016, 0x00077, 0x0, "Lego 24 SCG Graphics"},
+ {HPHW_FIO, 0x017, 0x00077, 0x0, "Lego 24Z SCG Graphics"},
+ {HPHW_FIO, 0x018, 0x00077, 0x0, "Lego 48Z SCG Graphics"},
+ {HPHW_FIO, 0x019, 0x00077, 0x0, "Scorpio Sr Builtin Graphics"},
+ {HPHW_FIO, 0x020, 0x00077, 0x0, "Scorpio 100 Builtin Graphics"},
+ {HPHW_FIO, 0x021, 0x00077, 0x0, "Spectra 50 Builtin Graphics"},
+ {HPHW_FIO, 0x022, 0x00077, 0x0, "Spectra 75 Builtin Graphics"},
+ {HPHW_FIO, 0x023, 0x00077, 0x0, "Spectra 100 Builtin Graphics"},
+ {HPHW_FIO, 0x024, 0x00077, 0x0, "Fast Pace SGC Graphics"},
+ {HPHW_FIO, 0x006, 0x0007A, 0x0, "Bushmaster Audio"},
+ {HPHW_FIO, 0x008, 0x0007A, 0x0, "Flounder Audio"},
+ {HPHW_FIO, 0x004, 0x0007B, 0x0, "UL Optional Audio"},
+ {HPHW_FIO, 0x007, 0x0007B, 0x0, "Scorpio Audio"},
+ {HPHW_FIO, 0x00B, 0x0007B, 0x0, "Scorpio Jr. Audio"},
+ {HPHW_FIO, 0x00C, 0x0007B, 0x0, "Strider-50 Audio"},
+ {HPHW_FIO, 0x00D, 0x0007B, 0x0, "Strider-33 Audio"},
+ {HPHW_FIO, 0x00E, 0x0007B, 0x0, "Trailways-50 Audio"},
+ {HPHW_FIO, 0x00F, 0x0007B, 0x0, "Trailways-33 Audio"},
+ {HPHW_FIO, 0x016, 0x0007B, 0x0, "Gecko Audio"},
+ {HPHW_FIO, 0x019, 0x0007B, 0x0, "Scorpio Sr. Audio"},
+ {HPHW_FIO, 0x01A, 0x0007B, 0x0, "Anole 64 Audio"},
+ {HPHW_FIO, 0x01B, 0x0007B, 0x0, "Anole 100 Audio"},
+ {HPHW_FIO, 0x01C, 0x0007B, 0x0, "Gecko 80 Audio"},
+ {HPHW_FIO, 0x01D, 0x0007B, 0x0, "Gecko 100 Audio"},
+ {HPHW_FIO, 0x01F, 0x0007B, 0x0, "SkyHawk 100/120 Audio"},
+ {HPHW_FIO, 0x020, 0x0007B, 0x0, "Scorpio 100 Audio"},
+ {HPHW_FIO, 0x021, 0x0007B, 0x0, "Spectra 50 Audio"},
+ {HPHW_FIO, 0x022, 0x0007B, 0x0, "Spectra 75 Audio"},
+ {HPHW_FIO, 0x023, 0x0007B, 0x0, "Spectra 100 Audio"},
+ {HPHW_FIO, 0x028, 0x0007B, 0x0, "Mirage Jr Audio"},
+ {HPHW_FIO, 0x029, 0x0007B, 0x0, "Mirage Audio"},
+ {HPHW_FIO, 0x02A, 0x0007B, 0x0, "Electra Audio"},
+ {HPHW_FIO, 0x02B, 0x0007B, 0x0, "Mirage 80 Audio"},
+ {HPHW_FIO, 0x02C, 0x0007B, 0x0, "Mirage 100+ Audio"},
+ {HPHW_FIO, 0x032, 0x0007B, 0x0, "Raven T' Audio"},
+ {HPHW_FIO, 0x034, 0x0007B, 0x0, "SAIC L-80 Audio"},
+ {HPHW_FIO, 0x035, 0x0007B, 0x0, "PCX-L2 712/132 Core Audio"},
+ {HPHW_FIO, 0x036, 0x0007B, 0x0, "PCX-L2 712/160 Core Audio"},
+ {HPHW_FIO, 0x03B, 0x0007B, 0x0, "Raven U/L2 Core Audio"},
+ {HPHW_FIO, 0x03C, 0x0007B, 0x0, "Merlin 132 Core Audio"},
+ {HPHW_FIO, 0x03D, 0x0007B, 0x0, "Merlin 160 Core Audio"},
+ {HPHW_FIO, 0x03E, 0x0007B, 0x0, "Merlin+ 132 Core Audio"},
+ {HPHW_FIO, 0x03F, 0x0007B, 0x0, "Merlin+ 180 Core Audio"},
+ {HPHW_FIO, 0x044, 0x0007B, 0x0, "Mohawk Core Audio"},
+ {HPHW_FIO, 0x046, 0x0007B, 0x0, "Rocky2 120 Core Audio"},
+ {HPHW_FIO, 0x047, 0x0007B, 0x0, "Rocky2 150 Core Audio"},
+ {HPHW_FIO, 0x04B, 0x0007B, 0x0, "Anole L2 132 Core Audio"},
+ {HPHW_FIO, 0x04D, 0x0007B, 0x0, "Anole L2 165 Core Audio"},
+ {HPHW_FIO, 0x04E, 0x0007B, 0x0, "Kiji L2 132 Core Audio"},
+ {HPHW_FIO, 0x050, 0x0007B, 0x0, "Merlin Jr 132 Core Audio"},
+ {HPHW_FIO, 0x051, 0x0007B, 0x0, "Firehawk Audio"},
+ {HPHW_FIO, 0x056, 0x0007B, 0x0, "Raven+ w SE FWSCSU Core Audio"},
+ {HPHW_FIO, 0x057, 0x0007B, 0x0, "Raven+ w Diff FWSCSU Core Audio"},
+ {HPHW_FIO, 0x058, 0x0007B, 0x0, "FireHawk 200 Audio"},
+ {HPHW_FIO, 0x05C, 0x0007B, 0x0, "SummitHawk 230 Core Audio"},
+ {HPHW_FIO, 0x800, 0x0007B, 0x0, "Hitachi Tiny 64 Audio"},
+ {HPHW_FIO, 0x801, 0x0007B, 0x0, "Hitachi Tiny 80 Audio"},
+ {HPHW_FIO, 0x009, 0x0007C, 0x0, "Outfield FW SCSI"},
+ {HPHW_FIO, 0x00A, 0x0007C, 0x0, "CoralII FW SCSI"},
+ {HPHW_FIO, 0x026, 0x0007C, 0x0, "CoralII Jaguar FW SCSI"},
+ {HPHW_FIO, 0x009, 0x0007D, 0x0, "Outfield FDDI"},
+ {HPHW_FIO, 0x00A, 0x0007D, 0x0, "CoralII FDDI"},
+ {HPHW_FIO, 0x026, 0x0007D, 0x0, "CoralII Jaguar FDDI"},
+ {HPHW_FIO, 0x010, 0x0007E, 0x0, "Pace Audio"},
+ {HPHW_FIO, 0x024, 0x0007E, 0x0, "Fast Pace Audio"},
+ {HPHW_FIO, 0x009, 0x0007F, 0x0, "Outfield Audio"},
+ {HPHW_FIO, 0x00A, 0x0007F, 0x0, "CoralII Audio"},
+ {HPHW_FIO, 0x026, 0x0007F, 0x0, "CoralII Jaguar Audio"},
+ {HPHW_FIO, 0x010, 0x00080, 0x0, "Pace Core HPIB"},
+ {HPHW_FIO, 0x024, 0x00080, 0x0, "Fast Pace Core HPIB"},
+ {HPHW_FIO, 0x016, 0x00082, 0x0, "Gecko Core SCSI"},
+ {HPHW_FIO, 0x01A, 0x00082, 0x0, "Anole 64 Core SCSI"},
+ {HPHW_FIO, 0x01B, 0x00082, 0x0, "Anole 100 Core SCSI"},
+ {HPHW_FIO, 0x01C, 0x00082, 0x0, "Gecko 80 Core SCSI"},
+ {HPHW_FIO, 0x01D, 0x00082, 0x0, "Gecko 100 Core SCSI"},
+ {HPHW_FIO, 0x01F, 0x00082, 0x0, "SkyHawk 100/120 Core SCSI"},
+ {HPHW_FIO, 0x027, 0x00082, 0x0, "Piranha 100 Core SCSI"},
+ {HPHW_FIO, 0x028, 0x00082, 0x0, "Mirage Jr Core SCSI"},
+ {HPHW_FIO, 0x029, 0x00082, 0x0, "Mirage Core SCSI"},
+ {HPHW_FIO, 0x02A, 0x00082, 0x0, "Electra Core SCSI"},
+ {HPHW_FIO, 0x02B, 0x00082, 0x0, "Mirage 80 Core SCSI"},
+ {HPHW_FIO, 0x02C, 0x00082, 0x0, "Mirage 100+ Core SCSI"},
+ {HPHW_FIO, 0x02E, 0x00082, 0x0, "UL 350 Core SCSI"},
+ {HPHW_FIO, 0x02F, 0x00082, 0x0, "UL 550 Core SCSI"},
+ {HPHW_FIO, 0x032, 0x00082, 0x0, "Raven T' Core SCSI"},
+ {HPHW_FIO, 0x033, 0x00082, 0x0, "Anole T Core SCSI"},
+ {HPHW_FIO, 0x034, 0x00082, 0x0, "SAIC L-80 Core SCSI"},
+ {HPHW_FIO, 0x035, 0x00082, 0x0, "PCX-L2 712/132 Core SCSI"},
+ {HPHW_FIO, 0x036, 0x00082, 0x0, "PCX-L2 712/160 Core SCSI"},
+ {HPHW_FIO, 0x03B, 0x00082, 0x0, "Raven U/L2 Core SCSI"},
+ {HPHW_FIO, 0x03C, 0x00082, 0x0, "Merlin 132 Core SCSI"},
+ {HPHW_FIO, 0x03D, 0x00082, 0x0, "Merlin 160 Core SCSI"},
+ {HPHW_FIO, 0x03E, 0x00082, 0x0, "Merlin+ 132 Core SCSI"},
+ {HPHW_FIO, 0x03F, 0x00082, 0x0, "Merlin+ 180 Core SCSI"},
+ {HPHW_FIO, 0x044, 0x00082, 0x0, "Mohawk Core SCSI"},
+ {HPHW_FIO, 0x045, 0x00082, 0x0, "Rocky1 Core SCSI"},
+ {HPHW_FIO, 0x046, 0x00082, 0x0, "Rocky2 120 Core SCSI"},
+ {HPHW_FIO, 0x047, 0x00082, 0x0, "Rocky2 150 Core SCSI"},
+ {HPHW_FIO, 0x04B, 0x00082, 0x0, "Anole L2 132 Core SCSI"},
+ {HPHW_FIO, 0x04D, 0x00082, 0x0, "Anole L2 165 Core SCSI"},
+ {HPHW_FIO, 0x04E, 0x00082, 0x0, "Kiji L2 132 Core SCSI"},
+ {HPHW_FIO, 0x050, 0x00082, 0x0, "Merlin Jr 132 Core SCSI"},
+ {HPHW_FIO, 0x051, 0x00082, 0x0, "Firehawk Core SCSI"},
+ {HPHW_FIO, 0x056, 0x00082, 0x0, "Raven+ w SE FWSCSI Core SCSI"},
+ {HPHW_FIO, 0x057, 0x00082, 0x0, "Raven+ w Diff FWSCSI Core SCSI"},
+ {HPHW_FIO, 0x058, 0x00082, 0x0, "FireHawk 200 Core SCSI"},
+ {HPHW_FIO, 0x05C, 0x00082, 0x0, "SummitHawk 230 Core SCSI"},
+ {HPHW_FIO, 0x05E, 0x00082, 0x0, "Staccato 132 Core SCSI"},
+ {HPHW_FIO, 0x05F, 0x00082, 0x0, "Staccato 180 Core SCSI"},
+ {HPHW_FIO, 0x800, 0x00082, 0x0, "Hitachi Tiny 64 Core SCSI"},
+ {HPHW_FIO, 0x801, 0x00082, 0x0, "Hitachi Tiny 80 Core SCSI"},
+ {HPHW_FIO, 0x016, 0x00083, 0x0, "Gecko Core PC Floppy"},
+ {HPHW_FIO, 0x01C, 0x00083, 0x0, "Gecko 80 Core PC Floppy"},
+ {HPHW_FIO, 0x01D, 0x00083, 0x0, "Gecko 100 Core PC Floppy"},
+ {HPHW_FIO, 0x051, 0x00083, 0x0, "Firehawk Core PC Floppy"},
+ {HPHW_FIO, 0x058, 0x00083, 0x0, "FireHawk 200 Core PC Floppy"},
+ {HPHW_FIO, 0x027, 0x00083, 0x0, "Piranha 100 Core PC Floppy"},
+ {HPHW_FIO, 0x028, 0x00083, 0x0, "Mirage Jr Core PC Floppy"},
+ {HPHW_FIO, 0x029, 0x00083, 0x0, "Mirage Core PC Floppy"},
+ {HPHW_FIO, 0x02A, 0x00083, 0x0, "Electra Core PC Floppy"},
+ {HPHW_FIO, 0x02B, 0x00083, 0x0, "Mirage 80 Core PC Floppy"},
+ {HPHW_FIO, 0x02C, 0x00083, 0x0, "Mirage 100+ Core PC Floppy"},
+ {HPHW_FIO, 0x02E, 0x00083, 0x0, "UL 350 Core PC Floppy"},
+ {HPHW_FIO, 0x02F, 0x00083, 0x0, "UL 550 Core PC Floppy"},
+ {HPHW_FIO, 0x032, 0x00083, 0x0, "Raven T' Core PC Floppy"},
+ {HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floopy"},
+ {HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floopy"},
+ {HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floopy"},
+ {HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floopy"},
+ {HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floopy"},
+ {HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floopy"},
+ {HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floopy"},
+ {HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floopy"},
+ {HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floopy"},
+ {HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floopy"},
+ {HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floopy"},
+ {HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floopy"},
+ {HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floopy"},
+ {HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floopy"},
+ {HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floopy"},
+ {HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floopy"},
+ {HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floopy"},
+ {HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PC Keyboard"},
+ {HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PC Keyboard"},
+ {HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PC Keyboard"},
+ {HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PC Keyboard"},
+ {HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PC Keyboard"},
+ {HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PC Keyboard"},
+ {HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PC Keyboard"},
+ {HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PC Keyboard"},
+ {HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PC Keyboard"},
+ {HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PC Keyboard"},
+ {HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PC Keyboard"},
+ {HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PC Keyboard"},
+ {HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PC Keyboard"},
+ {HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PC Keyboard"},
+ {HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PC Keyboard"},
+ {HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PC Keyboard"},
+ {HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PC Keyboard"},
+ {HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PC Keyboard"},
+ {HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PC Keyboard"},
+ {HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core Keyboard"},
+ {HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core Keyboard"},
+ {HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PC Keyboard"},
+ {HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PC Keyboard"},
+ {HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PC Keyboard"},
+ {HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PC Keyboard"},
+ {HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PC Keyboard"},
+ {HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PC Keyboard"},
+ {HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PC Keyboard"},
+ {HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PC Keyboard"},
+ {HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PC Keyboard"},
+ {HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PC Keyboard"},
+ {HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PC Keyboard"},
+ {HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PC Keyboard"},
+ {HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PC Keyboard"},
+ {HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PC Keyboard"},
+ {HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PC Keyboard"},
+ {HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PC Keyboard"},
+ {HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PC Keyboard"},
+ {HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PC Keyboard"},
+ {HPHW_FIO, 0x004, 0x00085, 0x0, "Solo GSC Optional Graphics"},
+ {HPHW_FIO, 0x005, 0x00085, 0x0, "Duet GSC Optional Graphics"},
+ {HPHW_FIO, 0x008, 0x00085, 0x0, "Anole Artist Optional Graphics"},
+ {HPHW_FIO, 0x010, 0x00085, 0x0, "Mirage 80 GSC Builtin Graphics"},
+ {HPHW_FIO, 0x011, 0x00085, 0x0, "Mirage 100+ GSC Builtin Graphics"},
+ {HPHW_FIO, 0x012, 0x00085, 0x0, "Mirage Jr GSC Builtin Graphics"},
+ {HPHW_FIO, 0x013, 0x00085, 0x0, "Mirage GSC Builtin Graphics"},
+ {HPHW_FIO, 0x014, 0x00085, 0x0, "Electra GSC Builtin Graphics"},
+ {HPHW_FIO, 0x016, 0x00085, 0x0, "Gecko GSC Core Graphics"},
+ {HPHW_FIO, 0x017, 0x00085, 0x0, "Gecko GSC Optional Graphics"},
+ {HPHW_FIO, 0x01A, 0x00085, 0x0, "Anole 64 Artist Builtin Graphics"},
+ {HPHW_FIO, 0x01B, 0x00085, 0x0, "Anole 100 Artist Builtin Graphics"},
+ {HPHW_FIO, 0x01C, 0x00085, 0x0, "Gecko 80 GSC Core Graphics"},
+ {HPHW_FIO, 0x01D, 0x00085, 0x0, "Gecko 100 GSC Core Graphics"},
+ {HPHW_FIO, 0x032, 0x00085, 0x0, "Raven T' GSC Core Graphics"},
+ {HPHW_FIO, 0x033, 0x00085, 0x0, "Anole T Artist Builtin Graphics"},
+ {HPHW_FIO, 0x034, 0x00085, 0x0, "SAIC L-80 GSC Core Graphics"},
+ {HPHW_FIO, 0x035, 0x00085, 0x0, "PCX-L2 712/132 Core Graphics"},
+ {HPHW_FIO, 0x036, 0x00085, 0x0, "PCX-L2 712/160 Core Graphics"},
+ {HPHW_FIO, 0x03B, 0x00085, 0x0, "Raven U/L2 Core Graphics"},
+ {HPHW_FIO, 0x03C, 0x00085, 0x0, "Merlin 132 Core Graphics"},
+ {HPHW_FIO, 0x03D, 0x00085, 0x0, "Merlin 160 Core Graphics"},
+ {HPHW_FIO, 0x03E, 0x00085, 0x0, "Merlin+ 132 Core Graphics"},
+ {HPHW_FIO, 0x03F, 0x00085, 0x0, "Merlin+ 180 Core Graphics"},
+ {HPHW_FIO, 0x045, 0x00085, 0x0, "Rocky1 Core Graphics"},
+ {HPHW_FIO, 0x046, 0x00085, 0x0, "Rocky2 120 Core Graphics"},
+ {HPHW_FIO, 0x047, 0x00085, 0x0, "Rocky2 150 Core Graphics"},
+ {HPHW_FIO, 0x04B, 0x00085, 0x0, "Anole L2 132 Core Graphics"},
+ {HPHW_FIO, 0x04D, 0x00085, 0x0, "Anole L2 165 Core Graphics"},
+ {HPHW_FIO, 0x04E, 0x00085, 0x0, "Kiji L2 132 Core Graphics"},
+ {HPHW_FIO, 0x050, 0x00085, 0x0, "Merlin Jr 132 Core Graphics"},
+ {HPHW_FIO, 0x056, 0x00085, 0x0, "Raven+ w SE FWSCSI Core Graphics"},
+ {HPHW_FIO, 0x057, 0x00085, 0x0, "Raven+ w Diff FWSCSI Core Graphics"},
+ {HPHW_FIO, 0x800, 0x00085, 0x0, "Hitachi Tiny 64 Core Graphics"},
+ {HPHW_FIO, 0x801, 0x00085, 0x0, "Hitachi Tiny 80 Core Graphics"},
+ {HPHW_FIO, 0x004, 0x00086, 0x0, "GSC IBM Token Ring"},
+ {HPHW_FIO, 0x015, 0x00087, 0x0, "Gecko Optional ISDN"},
+ {HPHW_FIO, 0x016, 0x00087, 0x0, "Gecko Core ISDN"},
+ {HPHW_FIO, 0x01C, 0x00087, 0x0, "Gecko 80 Core ISDN"},
+ {HPHW_FIO, 0x01D, 0x00087, 0x0, "Gecko 100 Core ISDN"},
+ {HPHW_FIO, 0x010, 0x00088, 0x0, "Pace VME Networking"},
+ {HPHW_FIO, 0x011, 0x00088, 0x0, "Sidewinder VME Networking"},
+ {HPHW_FIO, 0x01A, 0x00088, 0x0, "Anole 64 VME Networking"},
+ {HPHW_FIO, 0x01B, 0x00088, 0x0, "Anole 100 VME Networking"},
+ {HPHW_FIO, 0x024, 0x00088, 0x0, "Fast Pace VME Networking"},
+ {HPHW_FIO, 0x034, 0x00088, 0x0, "Anole T VME Networking"},
+ {HPHW_FIO, 0x04A, 0x00088, 0x0, "Anole L2 132 VME Networking"},
+ {HPHW_FIO, 0x04C, 0x00088, 0x0, "Anole L2 165 VME Networking"},
+ {HPHW_FIO, 0x03B, 0x00089, 0x0, "Raven U/L2 Core FW-SCSI"},
+ {HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core Lan (802.3)"},
+ {HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core Lan (802.3)"},
+ {HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core Lan (802.3)"},
+ {HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core Lan (802.3)"},
+ {HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core Lan (802.3)"},
+ {HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core Lan (802.3)"},
+ {HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional Lan (802.3)"},
+ {HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core Lan (802.3)"},
+ {HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core Lan (802.3)"},
+ {HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core Lan (802.3)"},
+ {HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core Lan (802.3)"},
+ {HPHW_FIO, 0x01F, 0x0008A, 0x0, "SkyHawk 100/120 Core LAN (802.3)"},
+ {HPHW_FIO, 0x027, 0x0008A, 0x0, "Piranha 100 Core LAN (802.3)"},
+ {HPHW_FIO, 0x028, 0x0008A, 0x0, "Mirage Jr Core LAN (802.3)"},
+ {HPHW_FIO, 0x029, 0x0008A, 0x0, "Mirage Core LAN (802.3)"},
+ {HPHW_FIO, 0x02A, 0x0008A, 0x0, "Electra Core LAN (802.3)"},
+ {HPHW_FIO, 0x02B, 0x0008A, 0x0, "Mirage 80 Core LAN (802.3)"},
+ {HPHW_FIO, 0x02C, 0x0008A, 0x0, "Mirage 100+ Core LAN (802.3)"},
+ {HPHW_FIO, 0x02E, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"},
+ {HPHW_FIO, 0x02F, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"},
+ {HPHW_FIO, 0x032, 0x0008A, 0x0, "Raven T' Core LAN (802.3)"},
+ {HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core Lan (802.3)"},
+ {HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core Lan (802.3)"},
+ {HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core Lan (802.3)"},
+ {HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core Lan (802.3)"},
+ {HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core Lan (802.3)"},
+ {HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core Lan (802.3)"},
+ {HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core Lan (802.3)"},
+ {HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core Lan (802.3)"},
+ {HPHW_FIO, 0x045, 0x0008A, 0x0, "Rocky1 Core LAN (802.3)"},
+ {HPHW_FIO, 0x046, 0x0008A, 0x0, "Rocky2 120 Core LAN (802.3)"},
+ {HPHW_FIO, 0x047, 0x0008A, 0x0, "Rocky2 150 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04B, 0x0008A, 0x0, "Anole L2 132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04D, 0x0008A, 0x0, "Anole L2 165 Core LAN (802.3)"},
+ {HPHW_FIO, 0x04E, 0x0008A, 0x0, "Kiji L2 132 Core LAN (802.3)"},
+ {HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core Lan (802.3)"},
+ {HPHW_FIO, 0x058, 0x0008A, 0x0, "FireHawk 200 Core LAN (802.3)"},
+ {HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core Lan (802.3)"},
+ {HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core Lan (802.3)"},
+ {HPHW_FIO, 0x004, 0x0008C, 0x0, "SkyHawk 100/120 Wax RS-232"},
+ {HPHW_FIO, 0x005, 0x0008C, 0x0, "SAIC L-80 Wax RS-232"},
+ {HPHW_FIO, 0x006, 0x0008C, 0x0, "Raven U/L2 Dino RS-232"},
+ {HPHW_FIO, 0x007, 0x0008C, 0x0, "Dino RS-232"},
+ {HPHW_FIO, 0x008, 0x0008C, 0x0, "Merlin 132 Dino RS-232"},
+ {HPHW_FIO, 0x009, 0x0008C, 0x0, "Merlin 160 Dino RS-232"},
+ {HPHW_FIO, 0x00A, 0x0008C, 0x0, "Merlin Jr 132 Dino RS-232"},
+ {HPHW_FIO, 0x010, 0x0008C, 0x0, "Mirage 80 Wax RS-232"},
+ {HPHW_FIO, 0x011, 0x0008C, 0x0, "Mirage 100+ Wax RS-232"},
+ {HPHW_FIO, 0x012, 0x0008C, 0x0, "Mirage Jr Wax RS-232"},
+ {HPHW_FIO, 0x013, 0x0008C, 0x0, "Mirage Wax RS-232"},
+ {HPHW_FIO, 0x014, 0x0008C, 0x0, "Electra Wax RS-232"},
+ {HPHW_FIO, 0x015, 0x0008C, 0x0, "KittyHawk GSY Core RS-232"},
+ {HPHW_FIO, 0x016, 0x0008C, 0x0, "Gecko Core RS-232"},
+ {HPHW_FIO, 0x017, 0x0008C, 0x0, "Raven Backplane RS-232"},
+ {HPHW_FIO, 0x018, 0x0008C, 0x0, "Gecko Optional RS-232"},
+ {HPHW_FIO, 0x019, 0x0008C, 0x0, "Merlin+ 180 Dino RS-232"},
+ {HPHW_FIO, 0x01A, 0x0008C, 0x0, "Anole 64 Core RS-232"},
+ {HPHW_FIO, 0x01B, 0x0008C, 0x0, "Anole 100 Core RS-232"},
+ {HPHW_FIO, 0x01C, 0x0008C, 0x0, "Gecko 80 Core RS-232"},
+ {HPHW_FIO, 0x01D, 0x0008C, 0x0, "Gecko 100 Core RS-232"},
+ {HPHW_FIO, 0x01E, 0x0008C, 0x0, "Raven T' Wax RS-232"},
+ {HPHW_FIO, 0x01F, 0x0008C, 0x0, "SkyHawk 100/120 Core RS-232"},
+ {HPHW_FIO, 0x020, 0x0008C, 0x0, "Anole 64 Timi RS-232"},
+ {HPHW_FIO, 0x021, 0x0008C, 0x0, "Anole 100 Timi RS-232"},
+ {HPHW_FIO, 0x022, 0x0008C, 0x0, "Merlin+ 132 Dino RS-232"},
+ {HPHW_FIO, 0x023, 0x0008C, 0x0, "Rocky1 Wax RS-232"},
+ {HPHW_FIO, 0x025, 0x0008C, 0x0, "Armyknife Optional RS-232"},
+ {HPHW_FIO, 0x026, 0x0008C, 0x0, "Piranha 100 Wax RS-232"},
+ {HPHW_FIO, 0x027, 0x0008C, 0x0, "Piranha 100 Core RS-232"},
+ {HPHW_FIO, 0x028, 0x0008C, 0x0, "Mirage Jr Core RS-232"},
+ {HPHW_FIO, 0x029, 0x0008C, 0x0, "Mirage Core RS-232"},
+ {HPHW_FIO, 0x02A, 0x0008C, 0x0, "Electra Core RS-232"},
+ {HPHW_FIO, 0x02B, 0x0008C, 0x0, "Mirage 80 Core RS-232"},
+ {HPHW_FIO, 0x02C, 0x0008C, 0x0, "Mirage 100+ Core RS-232"},
+ {HPHW_FIO, 0x02E, 0x0008C, 0x0, "UL 350 Lasi Core RS-232"},
+ {HPHW_FIO, 0x02F, 0x0008C, 0x0, "UL 550 Lasi Core RS-232"},
+ {HPHW_FIO, 0x030, 0x0008C, 0x0, "UL 350 Wax Core RS-232"},
+ {HPHW_FIO, 0x031, 0x0008C, 0x0, "UL 550 Wax Core RS-232"},
+ {HPHW_FIO, 0x032, 0x0008C, 0x0, "Raven T' Lasi Core RS-232"},
+ {HPHW_FIO, 0x033, 0x0008C, 0x0, "Anole T Core RS-232"},
+ {HPHW_FIO, 0x034, 0x0008C, 0x0, "SAIC L-80 Core RS-232"},
+ {HPHW_FIO, 0x035, 0x0008C, 0x0, "PCX-L2 712/132 Core RS-232"},
+ {HPHW_FIO, 0x036, 0x0008C, 0x0, "PCX-L2 712/160 Core RS-232"},
+ {HPHW_FIO, 0x03A, 0x0008C, 0x0, "Merlin+ Wax RS-232"},
+ {HPHW_FIO, 0x03B, 0x0008C, 0x0, "Raven U/L2 Core RS-232"},
+ {HPHW_FIO, 0x03C, 0x0008C, 0x0, "Merlin 132 Core RS-232"},
+ {HPHW_FIO, 0x03D, 0x0008C, 0x0, "Merlin 160 Core RS-232"},
+ {HPHW_FIO, 0x03E, 0x0008C, 0x0, "Merlin+ 132 Core RS-232"},
+ {HPHW_FIO, 0x03F, 0x0008C, 0x0, "Merlin+ 180 Core RS-232"},
+ {HPHW_FIO, 0x040, 0x0008C, 0x0, "Merlin 132 Wax RS-232"},
+ {HPHW_FIO, 0x041, 0x0008C, 0x0, "Merlin 160 Wax RS-232"},
+ {HPHW_FIO, 0x043, 0x0008C, 0x0, "Merlin 132/160 Wax RS-232"},
+ {HPHW_FIO, 0x044, 0x0008C, 0x0, "Mohawk Core RS-232"},
+ {HPHW_FIO, 0x045, 0x0008C, 0x0, "Rocky1 Core RS-232"},
+ {HPHW_FIO, 0x046, 0x0008C, 0x0, "Rocky2 120 Core RS-232"},
+ {HPHW_FIO, 0x047, 0x0008C, 0x0, "Rocky2 150 Core RS-232"},
+ {HPHW_FIO, 0x048, 0x0008C, 0x0, "Rocky2 120 Dino RS-232"},
+ {HPHW_FIO, 0x049, 0x0008C, 0x0, "Rocky2 150 Dino RS-232"},
+ {HPHW_FIO, 0x04A, 0x0008C, 0x0, "Anole L2 132 TIMI RS-232"},
+ {HPHW_FIO, 0x04B, 0x0008C, 0x0, "Anole L2 l32 Core RS-232"},
+ {HPHW_FIO, 0x04C, 0x0008D, 0x0, "Anole L2 165 TIMI RS-232"},
+ {HPHW_FIO, 0x04D, 0x0008C, 0x0, "Anole L2 165 Core RS-232"},
+ {HPHW_FIO, 0x04E, 0x0008C, 0x0, "Kiji L2 132 Core RS-232"},
+ {HPHW_FIO, 0x04F, 0x0008C, 0x0, "Kiji L2 132 Dino RS-232"},
+ {HPHW_FIO, 0x050, 0x0008C, 0x0, "Merlin Jr 132 Core RS-232"},
+ {HPHW_FIO, 0x051, 0x0008C, 0x0, "Firehawk Core RS-232"},
+ {HPHW_FIO, 0x052, 0x0008C, 0x0, "Raven+ Hi Power Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x053, 0x0008C, 0x0, "Raven+ Hi Power Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x054, 0x0008C, 0x0, "Raven+ Lo Power Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x055, 0x0008C, 0x0, "Raven+ Lo Power Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x056, 0x0008C, 0x0, "Raven+ w SE FWSCSI Core RS-232"},
+ {HPHW_FIO, 0x057, 0x0008C, 0x0, "Raven+ w Diff FWSCSI Core RS-232"},
+ {HPHW_FIO, 0x058, 0x0008C, 0x0, "FireHawk 200 Core RS-232"},
+ {HPHW_FIO, 0x059, 0x0008C, 0x0, "FireHawk 200 Wax RS-232"},
+ {HPHW_FIO, 0x05A, 0x0008C, 0x0, "Raven+ L2 Backplane w EISA RS-232"},
+ {HPHW_FIO, 0x05B, 0x0008C, 0x0, "Raven+ L2 Backplane w/o EISA RS-232"},
+ {HPHW_FIO, 0x05D, 0x0008C, 0x0, "SummitHawk Dino RS-232"},
+ {HPHW_FIO, 0x05E, 0x0008C, 0x0, "Staccato 132 Core LAN RS-232"},
+ {HPHW_FIO, 0x05F, 0x0008C, 0x0, "Staccato 180 Core LAN RS-232"},
+ {HPHW_FIO, 0x800, 0x0008C, 0x0, "Hitachi Tiny 64 Core RS-232"},
+ {HPHW_FIO, 0x801, 0x0008C, 0x0, "Hitachi Tiny 80 Core RS-232"},
+ {HPHW_FIO, 0x015, 0x0008D, 0x0, "Gecko Optional RJ-16"},
+ {HPHW_FIO, 0x016, 0x0008D, 0x0, "Gecko Core RJ-16"},
+ {HPHW_FIO, 0x01C, 0x0008D, 0x0, "Gecko 80 Core RJ-16"},
+ {HPHW_FIO, 0x01D, 0x0008D, 0x0, "Gecko 100 Core RJ-16"},
+ {HPHW_FIO, 0x004, 0x0008F, 0x0, "Anole Boot Rom"},
+ {HPHW_FIO, 0x005, 0x0008F, 0x0, "Rocky1 Boot Rom"},
+ {HPHW_FIO, 0x006, 0x0008F, 0x0, "Rocky2 120 Boot Rom"},
+ {HPHW_FIO, 0x007, 0x0008F, 0x0, "Rocky2 150 Boot Rom"},
+ {HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS2 Keyboard"},
+ {HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG lan"},
+ {HPHW_FIO, 0x023, 0x00099, 0x0, "Rocky1 Wax HPIB"},
+ {HPHW_FIO, 0x048, 0x00099, 0x0, "Rocky2 120 Clark/Dino HPIB"},
+ {HPHW_FIO, 0x049, 0x00099, 0x0, "Rocky2 150 Clark/Dino HPIB"},
+ {HPHW_FIO, 0x004, 0x000A1, 0x0, "SPP2000 Console TTY"},
+ {HPHW_FIO, 0x004, 0x000A2, 0x0, "Forte Core PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x005, 0x000A2, 0x0, "AllegroLow PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x006, 0x000A2, 0x0, "AllegroHIgh Core PCI 10/100BT LAN"},
+ {HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in Lan"},
+ {HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT Lan"},
+ {HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI Lan"},
+ {HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI Lan"},
+ {HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI Lan"},
+ {HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI Lan"},
+ {HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI Lan"},
+ {HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI Lan"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI SE UltraSCSI"},
+ {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x007, 0x000A3, 0x0, "PCI Plug-in Disk"},
+ {HPHW_FIO, 0x008, 0x000A3, 0x0, "A5158A S FC Tachlite HBA"},
+ {HPHW_FIO, 0x009, 0x000A3, 0x0, "A5157A D FC HBA"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI LVD Ultra2 SCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI NSE UltraSCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI WSE UltraSCSI"},
+ {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI IDE/ATAPI CD-ROM"},
+ {HPHW_FIO, 0x03E, 0x000A3, 0x0, "Merlin+ 132 Core SE FWSCSI PCI Disk"},
+ {HPHW_FIO, 0x03F, 0x000A3, 0x0, "Merlin+ 180 Core SE FWSCSI PCI Disk"},
+ {HPHW_FIO, 0x056, 0x000A3, 0x0, "Raven+ w SE FWSCSI Core PCI Disk"},
+ {HPHW_FIO, 0x057, 0x000A3, 0x0, "Raven+ w Diff FWSCSI Core PCI Disk"},
+ {HPHW_FIO, 0x004, 0x000A4, 0x0, "SPP2000 Core BA"},
+ {HPHW_FIO, 0x004, 0x000A6, 0x0, "Sonic Ethernet 802.3 Card"},
+ {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI USB KB"},
+ {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI USB KB"},
+ {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI USB KB"},
+ {HPHW_FIO, 0x007, 0x000A9, 0x0, "Miscelaneous PCI Plug-in"},
+ {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI SuperIO RS-232"},
+ {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI USB KB"},
+ {HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"},
+ {HPHW_FIO, 0x004, 0x00340, 0x0, "BARCO CX4500 VME Grphx Cnsl"},
+ {HPHW_FIO, 0x004, 0x00360, 0x0, "Hughes TOG VME FDDI"},
+ {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"},
+ {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"},
+ {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"},
+ {HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"},
+ {HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"},
+ {HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"},
+ {HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"},
+ {HPHW_MEMORY, 0x00C, 0x00008, 0x08, "Kahlua 8MB"},
+ {HPHW_MEMORY, 0x00D, 0x00008, 0x08, "Kahlua 4MB"},
+ {HPHW_MEMORY, 0x00E, 0x00008, 0x08, "Tequila 16MB"},
+ {HPHW_MEMORY, 0x00F, 0x00008, 0x08, "Tequila 32MB"},
+ {HPHW_MEMORY, 0x040, 0x00008, 0x00, "Hitachi"},
+ {HPHW_MEMORY, 0x004, 0x00009, 0x00, "Cheetah"},
+ {HPHW_MEMORY, 0x005, 0x00009, 0x00, "Emerald"},
+ {HPHW_MEMORY, 0x008, 0x00009, 0x00, "Indigo 3MB/5MB"},
+ {HPHW_MEMORY, 0x00C, 0x00009, 0x00, "Indigo 8MB"},
+ {HPHW_MEMORY, 0x00D, 0x00009, 0x00, "Paradise 4MB"},
+ {HPHW_MEMORY, 0x00E, 0x00009, 0x00, "Burgundy Onboard"},
+ {HPHW_MEMORY, 0x012, 0x00009, 0x00, "Indigo 12MB/20MB"},
+ {HPHW_MEMORY, 0x013, 0x00009, 0x00, "Cobra"},
+ {HPHW_MEMORY, 0x014, 0x00009, 0x00, "Nova"},
+ {HPHW_MEMORY, 0x015, 0x00009, 0x00, "Coral"},
+ {HPHW_MEMORY, 0x016, 0x00009, 0x00, "Bushmaster"},
+ {HPHW_MEMORY, 0x017, 0x00009, 0x00, "Scorpio"},
+ {HPHW_MEMORY, 0x018, 0x00009, 0x00, "Flounder"},
+ {HPHW_MEMORY, 0x019, 0x00009, 0x00, "Hardball"},
+ {HPHW_MEMORY, 0x01A, 0x00009, 0x00, "CoralII 99"},
+ {HPHW_MEMORY, 0x01B, 0x00009, 0x00, "Scorpio Jr."},
+ {HPHW_MEMORY, 0x01C, 0x00009, 0x00, "Strider-50 (715T)"},
+ {HPHW_MEMORY, 0x01D, 0x00009, 0x00, "Strider-33 (707T)"},
+ {HPHW_MEMORY, 0x01E, 0x00009, 0x00, "Trailways-50 (715S)"},
+ {HPHW_MEMORY, 0x01F, 0x00009, 0x00, "Trailways-33 (707S)"},
+ {HPHW_MEMORY, 0x020, 0x00009, 0x00, "Pace"},
+ {HPHW_MEMORY, 0x021, 0x00009, 0x00, "Sidewinder"},
+ {HPHW_MEMORY, 0x022, 0x00009, 0x00, "Orville"},
+ {HPHW_MEMORY, 0x023, 0x00009, 0x00, "Wilbur"},
+ {HPHW_MEMORY, 0x026, 0x00009, 0x00, "Gecko"},
+ {HPHW_MEMORY, 0x027, 0x00009, 0x00, "Scorpio Sr."},
+ {HPHW_MEMORY, 0x028, 0x00009, 0x00, "Scorpio 100"},
+ {HPHW_MEMORY, 0x029, 0x00009, 0x00, "Spectra 50"},
+ {HPHW_MEMORY, 0x02A, 0x00009, 0x00, "CoralII 132"},
+ {HPHW_MEMORY, 0x02F, 0x00009, 0x00, "KittyHawk DC2-"},
+ {HPHW_MEMORY, 0x030, 0x00009, 0x00, "Spectra 75"},
+ {HPHW_MEMORY, 0x031, 0x00009, 0x00, "Spectra 100"},
+ {HPHW_MEMORY, 0x032, 0x00009, 0x00, "KittyHawk DC3"},
+ {HPHW_MEMORY, 0x033, 0x00009, 0x00, "Fast Pace"},
+ {HPHW_MEMORY, 0x034, 0x00009, 0x00, "Snake Eagle"},
+ {HPHW_MEMORY, 0x035, 0x00009, 0x00, "Anole 64"},
+ {HPHW_MEMORY, 0x036, 0x00009, 0x00, "Anole 100"},
+ {HPHW_MEMORY, 0x037, 0x00009, 0x00, "Snake Cheetah"},
+ {HPHW_MEMORY, 0x038, 0x00009, 0x00, "Gecko 80"},
+ {HPHW_MEMORY, 0x039, 0x00009, 0x00, "Gecko 100"},
+ {HPHW_MEMORY, 0x03A, 0x00009, 0x00, "Gecko 120"},
+ {HPHW_MEMORY, 0x03B, 0x00009, 0x00, "Gila 80"},
+ {HPHW_MEMORY, 0x03C, 0x00009, 0x00, "Gila 100"},
+ {HPHW_MEMORY, 0x03D, 0x00009, 0x00, "Gila 120"},
+ {HPHW_MEMORY, 0x03E, 0x00009, 0x00, "Scorpio-L 80"},
+ {HPHW_MEMORY, 0x03F, 0x00009, 0x00, "Scorpio-L 100"},
+ {HPHW_MEMORY, 0x040, 0x00009, 0x00, "Scorpio-L 120"},
+ {HPHW_MEMORY, 0x041, 0x00009, 0x00, "Spectra-L 80"},
+ {HPHW_MEMORY, 0x042, 0x00009, 0x00, "Spectra-L 100"},
+ {HPHW_MEMORY, 0x043, 0x00009, 0x00, "Spectra-L 120"},
+ {HPHW_MEMORY, 0x044, 0x00009, 0x00, "Piranha 100"},
+ {HPHW_MEMORY, 0x045, 0x00009, 0x00, "Piranha 120"},
+ {HPHW_MEMORY, 0x046, 0x00009, 0x00, "Jason 50"},
+ {HPHW_MEMORY, 0x047, 0x00009, 0x00, "Jason 100"},
+ {HPHW_MEMORY, 0x049, 0x00009, 0x00, "SkyHawk 100/120"},
+ {HPHW_MEMORY, 0x04A, 0x00009, 0x00, "Mirage Jr"},
+ {HPHW_MEMORY, 0x04B, 0x00009, 0x00, "Mirage 100"},
+ {HPHW_MEMORY, 0x04C, 0x00009, 0x00, "Mirage 100+"},
+ {HPHW_MEMORY, 0x04D, 0x00009, 0x00, "Electra 100"},
+ {HPHW_MEMORY, 0x04E, 0x00009, 0x00, "Electra 120"},
+ {HPHW_MEMORY, 0x04F, 0x00009, 0x00, "Mirage 80"},
+ {HPHW_MEMORY, 0x050, 0x00009, 0x00, "UL Proc 1 way T'100"},
+ {HPHW_MEMORY, 0x051, 0x00009, 0x00, "UL Proc 1 way T'120"},
+ {HPHW_MEMORY, 0x052, 0x00009, 0x00, "UL Proc 2 way T'100"},
+ {HPHW_MEMORY, 0x053, 0x00009, 0x00, "KittyHawk DC3-"},
+ {HPHW_MEMORY, 0x054, 0x00009, 0x00, "UL Proc 2 way T'120"},
+ {HPHW_MEMORY, 0x055, 0x00009, 0x00, "Raven 120 mem"},
+ {HPHW_MEMORY, 0x056, 0x00009, 0x00, "UL Proc L 75"},
+ {HPHW_MEMORY, 0x057, 0x00009, 0x00, "UL Proc L 100"},
+ {HPHW_MEMORY, 0x058, 0x00009, 0x00, "Anole T"},
+ {HPHW_MEMORY, 0x059, 0x00009, 0x00, "SAIC L-80"},
+ {HPHW_MEMORY, 0x05A, 0x00009, 0x00, "Merlin+ L2 180"},
+ {HPHW_MEMORY, 0x05B, 0x00009, 0x00, "Raven U 200 2-way"},
+ {HPHW_MEMORY, 0x05C, 0x00009, 0x00, "Raven U 180+"},
+ {HPHW_MEMORY, 0x05D, 0x00009, 0x00, "Raven U 200"},
+ {HPHW_MEMORY, 0x05E, 0x00009, 0x00, "Rocky2 150 Memory"},
+ {HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"},
+ {HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"},
+ {HPHW_MEMORY, 0x05F, 0x00009, 0x00, "SPP2000 Memory"},
+ {HPHW_MEMORY, 0x060, 0x00009, 0x00, "Merlin L2 132"},
+ {HPHW_MEMORY, 0x061, 0x00009, 0x00, "Merlin+ L2 132"},
+ {HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"},
+ {HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"},
+ {HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"},
+ {HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"},
+ {HPHW_MEMORY, 0x067, 0x00009, 0x00, "Merlin 160/ThunderHawk Memory"},
+ {HPHW_MEMORY, 0x068, 0x00009, 0x00, "LightningHawk Memory"},
+ {HPHW_MEMORY, 0x069, 0x00009, 0x00, "Rocky1 Memory"},
+ {HPHW_MEMORY, 0x06A, 0x00009, 0x00, "Raven L2 132"},
+ {HPHW_MEMORY, 0x06B, 0x00009, 0x00, "Raven L2 160"},
+ {HPHW_MEMORY, 0x06C, 0x00009, 0x00, "Raven L2 187"},
+ {HPHW_MEMORY, 0x06D, 0x00009, 0x00, "Raven L2 200"},
+ {HPHW_MEMORY, 0x06E, 0x00009, 0x00, "Raven U 230"},
+ {HPHW_MEMORY, 0x06F, 0x00009, 0x00, "Raven U 240"},
+ {HPHW_MEMORY, 0x070, 0x00009, 0x00, "Rocky2 120 Memory"},
+ {HPHW_MEMORY, 0x071, 0x00009, 0x00, "Raven U 160"},
+ {HPHW_MEMORY, 0x072, 0x00009, 0x00, "Raven U 180"},
+ {HPHW_MEMORY, 0x072, 0x00009, 0x00, "UL Proc 1 way T'120 1MB/1MB"},
+ {HPHW_MEMORY, 0x073, 0x00009, 0x00, "UL Proc 2 way T'120 1MB/1MB"},
+ {HPHW_MEMORY, 0x074, 0x00009, 0x00, "Anole L2 132 memory"},
+ {HPHW_MEMORY, 0x075, 0x00009, 0x00, "Anole L2 165 memory"},
+ {HPHW_MEMORY, 0x076, 0x00009, 0x00, "UL 1 way U160 512K/512K memory"},
+ {HPHW_MEMORY, 0x077, 0x00009, 0x00, "UL 2 way U160 512K/512K memory"},
+ {HPHW_MEMORY, 0x078, 0x00009, 0x00, "Kiji L2 132 memory"},
+ {HPHW_MEMORY, 0x079, 0x00009, 0x00, "UL 1 way U160 1M/1M memory"},
+ {HPHW_MEMORY, 0x07A, 0x00009, 0x00, "UL 2 way U160 1M/1M memory"},
+ {HPHW_MEMORY, 0x07B, 0x00009, 0x00, "UL 1 way U180 1M/1M memory"},
+ {HPHW_MEMORY, 0x07C, 0x00009, 0x00, "UL 2 way U180 1M/1M memory"},
+ {HPHW_MEMORY, 0x07D, 0x00009, 0x00, "UL 1 way U240 U+ 2M/2M memory"},
+ {HPHW_MEMORY, 0x07E, 0x00009, 0x00, "UL 2 way U240 U+ 2M/2M memory"},
+ {HPHW_MEMORY, 0x07F, 0x00009, 0x00, "UL L2 132 memory"},
+ {HPHW_MEMORY, 0x080, 0x00009, 0x00, "UL L2 160 memory"},
+ {HPHW_MEMORY, 0x081, 0x00009, 0x00, "Merlin Jr 132 memory"},
+ {HPHW_MEMORY, 0x082, 0x00009, 0x00, "FireHawk 200 Memory"},
+ {HPHW_MEMORY, 0x083, 0x00009, 0x00, "SummitHawk Memory"},
+ {HPHW_MEMORY, 0x084, 0x00009, 0x00, "Jade Upgrade Memory"},
+ {HPHW_MEMORY, 0x085, 0x00009, 0x00, "SPP2500 Memory"},
+ {HPHW_MEMORY, 0x086, 0x00009, 0x00, "AllegroHigh Memory"},
+ {HPHW_MEMORY, 0x087, 0x00009, 0x00, "AllegroLow Memory"},
+ {HPHW_MEMORY, 0x088, 0x00009, 0x00, "Forte 2w Memory"},
+ {HPHW_MEMORY, 0x089, 0x00009, 0x00, "Forte 4w Memory"},
+ {HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"},
+ {HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"},
+ {HPHW_MEMORY, 0x090, 0x00009, 0x00, "Prelude SMC Memory"},
+ {HPHW_MEMORY, 0x091, 0x00009, 0x00, "Lego 360 Memory"},
+ {HPHW_MEMORY, 0x7FF, 0x00009, 0x00, "NEC Aska memory"},
+ {HPHW_MEMORY, 0x800, 0x00009, 0x00, "Hitachi Tiny 64"},
+ {HPHW_MEMORY, 0x801, 0x00009, 0x00, "Hitachi Tiny 80"},
+ {HPHW_MEMORY, 0x8FF, 0x00009, 0x00, "Hitachi X memory"},
+ {HPHW_MEMORY, 0x091, 0x00009, 0x00, "M2250 Memory"},
+ {HPHW_MEMORY, 0x092, 0x00009, 0x00, "M2500 Memory"},
+ {HPHW_MEMORY, 0x093, 0x00009, 0x00, "Sonata 440 Memory"},
+ {HPHW_MEMORY, 0x094, 0x00009, 0x00, "Sonata 360 Memory"},
+ {HPHW_MEMORY, 0x095, 0x00009, 0x00, "Rhapsody 440 Memory"},
+ {HPHW_MEMORY, 0x096, 0x00009, 0x00, "Rhapsody 360 Memory"},
+ {HPHW_MEMORY, 0x097, 0x00009, 0x00, "Raven W 360 Memory"},
+ {HPHW_MEMORY, 0x098, 0x00009, 0x00, "Halfdome W 440 Memory"},
+ {HPHW_MEMORY, 0x099, 0x00009, 0x00, "Rhapsody DC- 440 Memory"},
+ {HPHW_MEMORY, 0x09A, 0x00009, 0x00, "Rhapsody DC- 360 Memory"},
+ {HPHW_MEMORY, 0x09B, 0x00009, 0x00, "Crescendo Memory"},
+ {HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"},
+ {HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"},
+ {HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"},
+ {HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"},
+ {0, } /* leave the last entry empty ! */
+};
+
+
+static struct hp_cpu_type_mask {
+ unsigned short model;
+ unsigned short mask;
+ enum cpu_type cpu;
+} hp_cpu_type_mask_list[] = {
+
+ { 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */
+ { 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */
+ { 0x0080, 0x0ff0, pcx }, /* 0x0080 - 0x008f */
+ { 0x0100, 0x0ff0, pcx }, /* 0x0100 - 0x010f */
+ { 0x0182, 0x0ffe, pcx }, /* 0x0182 - 0x0183 */
+ { 0x0182, 0x0ffe, pcxt }, /* 0x0182 - 0x0183 */
+ { 0x0184, 0x0fff, pcxu }, /* 0x0184 - 0x0184 */
+ { 0x0200, 0x0ffe, pcxs }, /* 0x0200 - 0x0201 */
+ { 0x0202, 0x0fff, pcxs }, /* 0x0202 - 0x0202 */
+ { 0x0203, 0x0fff, pcxt }, /* 0x0203 - 0x0203 */
+ { 0x0204, 0x0ffc, pcxt }, /* 0x0204 - 0x0207 */
+ { 0x0280, 0x0ffc, pcxs }, /* 0x0280 - 0x0283 */
+ { 0x0284, 0x0ffc, pcxt }, /* 0x0284 - 0x0287 */
+ { 0x0288, 0x0fff, pcxt }, /* 0x0288 - 0x0288 */
+ { 0x0300, 0x0ffc, pcxs }, /* 0x0300 - 0x0303 */
+ { 0x0310, 0x0ff0, pcxt }, /* 0x0310 - 0x031f */
+ { 0x0320, 0x0ff0, pcxt }, /* 0x0320 - 0x032f */
+ { 0x0400, 0x0ff0, pcxt }, /* 0x0400 - 0x040f */
+ { 0x0480, 0x0ff0, pcxl }, /* 0x0480 - 0x048f */
+ { 0x0500, 0x0ff0, pcxl2 }, /* 0x0500 - 0x050f */
+ { 0x0510, 0x0ff0, pcxl2 }, /* 0x0510 - 0x051f */
+ { 0x0580, 0x0ff8, pcxt_ }, /* 0x0580 - 0x0587 */
+ { 0x0588, 0x0ffc, pcxt_ }, /* 0x0588 - 0x058b */
+ { 0x058c, 0x0ffe, pcxt_ }, /* 0x058c - 0x058d */
+ { 0x058e, 0x0fff, pcxt_ }, /* 0x058e - 0x058e */
+ { 0x058f, 0x0fff, pcxu }, /* 0x058f - 0x058f */
+ { 0x0590, 0x0ffe, pcxu }, /* 0x0590 - 0x0591 */
+ { 0x0592, 0x0fff, pcxt_ }, /* 0x0592 - 0x0592 */
+ { 0x0593, 0x0fff, pcxu }, /* 0x0593 - 0x0593 */
+ { 0x0594, 0x0ffc, pcxu }, /* 0x0594 - 0x0597 */
+ { 0x0598, 0x0ffc, pcxu }, /* 0x0598 - 0x059b */
+ { 0x059c, 0x0ffe, pcxu_ }, /* 0x059c - 0x059d */
+ { 0x059e, 0x0fff, pcxt_ }, /* 0x059e - 0x059e */
+ { 0x059f, 0x0fff, pcxu }, /* 0x059f - 0x059f */
+ { 0x05a0, 0x0ffe, pcxt_ }, /* 0x05a0 - 0x05a1 */
+ { 0x05a2, 0x0ffe, pcxu }, /* 0x05a2 - 0x05a3 */
+ { 0x05a4, 0x0ffc, pcxu }, /* 0x05a4 - 0x05a7 */
+ { 0x05a8, 0x0ffc, pcxu }, /* 0x05a8 - 0x05ab */
+ { 0x05ad, 0x0fff, pcxu_ }, /* 0x05ad - 0x05ad */
+ { 0x05ae, 0x0ffe, pcxu_ }, /* 0x05ae - 0x05af */
+ { 0x05b0, 0x0ffe, pcxu_ }, /* 0x05b0 - 0x05b1 */
+ { 0x05b2, 0x0fff, pcxu_ }, /* 0x05b2 - 0x05b2 */
+ { 0x05b3, 0x0fff, pcxu }, /* 0x05b3 - 0x05b3 */
+ { 0x05b4, 0x0fff, pcxw }, /* 0x05b4 - 0x05b4 */
+ { 0x05b5, 0x0fff, pcxu_ }, /* 0x05b5 - 0x05b5 */
+ { 0x05b6, 0x0ffe, pcxu_ }, /* 0x05b6 - 0x05b7 */
+ { 0x05b8, 0x0ffe, pcxu_ }, /* 0x05b8 - 0x05b9 */
+ { 0x05ba, 0x0fff, pcxu_ }, /* 0x05ba - 0x05ba */
+ { 0x05bb, 0x0fff, pcxw }, /* 0x05bb - 0x05bb */
+ { 0x05bc, 0x0ffc, pcxw }, /* 0x05bc - 0x05bf */
+ { 0x05c0, 0x0fc0, pcxw }, /* 0x05c0 - 0x05ff */
+ { 0x0600, 0x0ff0, pcxl }, /* 0x0600 - 0x060f */
+ { 0x0610, 0x0ff0, pcxl }, /* 0x0610 - 0x061f */
+ { 0x0000, 0x0000, pcx } /* terminate table */
+};
+
+char *cpu_name_version[][2] = {
+ [pcx] { "PA7000 (PCX)", "1.0" },
+ [pcxs] { "PA7000 (PCX-S)", "1.1a" },
+ [pcxt] { "PA7100 (PCX-T)", "1.1b" },
+ [pcxt_] { "PA7200 (PCX-T')", "1.1c" },
+ [pcxl] { "PA7100LC (PCX-L)", "1.1d" },
+ [pcxl2] { "PA7300LC (PCX-L2)", "1.1e" },
+ [pcxu] { "PA8000 (PCX-U)", "2.0" },
+ [pcxu_] { "PA8200 (PCX-U+)", "2.0" },
+ [pcxw] { "PA8500 (PCX-W)", "2.0" },
+ [pcxw_] { "PA8600 (PCX-W+)", "2.0" }
+};
+
+char *parisc_getHWtype(unsigned short hw_type)
+{
+ if (hw_type <= HPHW_CIO) {
+ return hw_type_name[hw_type];
+ } else {
+ return "Unknown Type";
+ }
+}
+
+char *parisc_getHWdescription(unsigned short hw_type, unsigned long hversion,
+ unsigned long sversion)
+{
+ struct hp_hardware *listptr;
+
+ for (listptr = hp_hardware_list; listptr->name; listptr++) {
+ if ((listptr->hw_type==hw_type) &&
+ (listptr->hversion==hversion) &&
+ (listptr->sversion==sversion)){
+ return listptr->name;
+ }
+ }
+ return "unknown device";
+}
+
+
+/* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */
+enum cpu_type parisc_get_cpu_type(unsigned long hversion)
+{
+ struct hp_cpu_type_mask *ptr;
+ unsigned short model = ((unsigned short) (hversion)) >> 4;
+
+ for (ptr = hp_cpu_type_mask_list; 0 != ptr->mask; ptr++) {
+ if (ptr->model == (model & ptr->mask))
+ return ptr->cpu;
+ }
+ panic("parisc_get_cpu_type() could not identify CPU type\n");
+
+ return pcx; /* not reached: */
+}
+
+
+struct hp_hardware *parisc_get_reference(unsigned short hw_type,
+ unsigned long hversion, unsigned long sversion)
+{
+ struct hp_hardware *listptr = hp_hardware_list;
+
+ for (listptr = hp_hardware_list; listptr->name; listptr++) {
+ if ((listptr->hw_type == hw_type) &&
+ (listptr->hversion == hversion) &&
+ (listptr->sversion == sversion)) {
+ return listptr;
+ }
+ }
+ return NULL;
+}
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
new file mode 100644
index 000000000..ce45dd608
--- /dev/null
+++ b/arch/parisc/kernel/head.S
@@ -0,0 +1,156 @@
+/*
+ *
+ * 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) 1999 by Helge Deller
+ * Copyright 1999 SuSE GmbH (Philipp Rumpf)
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ *
+ * Initial Version 04-23-1999 by Helge Deller (helge.deller@ruhr-uni-bochum.de)
+ */
+
+
+#include <asm/offset.h>
+#include <asm/psw.h>
+
+#define __ASSEMBLY__
+/*********
+#include <asm/pdc.h>
+*********/
+#include <asm/assembly.h>
+#include <asm/pgtable.h>
+
+
+ .level 1.1
+
+ .section .initcall.init
+ .align 4
+ .export __initcall_start
+__initcall_start:
+ .export __initcall_end
+__initcall_end:
+ .export __setup_start
+__setup_start:
+ .export __setup_end
+__setup_end:
+
+ .text
+ .align 4
+ .import init_task_union,data
+ .import $global$ /* forward declaration */
+ .import fault_vector_11,code /* IVA parisc 1.1 32 bit */
+ .import fault_vector_20,code /* IVA parisc 2.0 32 bit */
+ .import start_parisc,code /* then enable VM and go here */
+
+ .export stext
+ .export _stext,data /* Kernel want it this way! */
+_stext:
+stext:
+ .proc
+ .callinfo
+
+ /* Make sure sr4-sr7 are set to zero for the kernel address space */
+
+ mtsp %r0,%sr4
+ mtsp %r0,%sr5
+ mtsp %r0,%sr6
+ mtsp %r0,%sr7
+
+ /* Initialize startup VM. Just map first 8 MB of memory */
+
+ ldil L%PA(pg0),%r1
+ ldo R%PA(pg0)(%r1),%r1
+ ldo _PAGE_TABLE(%r1),%r3
+ ldil L%PA(swapper_pg_dir),%r4
+ ldo R%PA(swapper_pg_dir)(%r4),%r4
+ mtctl %r4,%cr24 /* Initialize kernel root pointer */
+ mtctl %r4,%cr25 /* Initialize user root pointer */
+ stw %r3,0xc00(%r4) /* Hardwired 0xc0000000 kernel vaddr start */
+ ldo 0x1000(%r3),%r3
+ stw %r3,0xc04(%r4)
+ ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0x0 phys addr start */
+$pgt_fill_loop:
+ stwm %r3,4(%r1)
+ ldo 0x1000(%r3),%r3
+ bb,>= %r3,8,$pgt_fill_loop
+ nop
+
+ /* Initialize the global data pointer */
+ ldil L%$global$,%dp
+ ldo R%$global$(%dp),%dp
+
+ /* And the stack pointer, physical too */
+ ldil L%init_task_union+TASK_SZ_ALGN,%sp
+ ldo R%init_task_union+TASK_SZ_ALGN(%sp),%sp
+
+ /* we need this to take interruptions directly after the rfi below */
+ /* (which we need for PA2.0 boxes) */
+ mtctl %r0, %cr30
+
+ /*
+ * Set up our interrupt table. HPMCs might not work after this!
+ *
+ * We need to install the correct iva for PA1.1 or PA2.0. The
+ * following short sequence of instructions can determine this
+ * (without being illegal on a PA1.1 machine).
+ */
+
+ ldi 32,%r10
+ mtctl %r10,%cr11
+ .level 2.0
+ mfctl,w %cr11,%r10
+ .level 1.1
+ comib,<>,n 0,%r10,$is_pa20
+ ldil L%PA(fault_vector_11),%r10
+ b $install_iva
+ ldo R%PA(fault_vector_11)(%r10),%r10
+
+$is_pa20:
+ ldil L%PA(fault_vector_20),%r10
+ ldo R%PA(fault_vector_20)(%r10),%r10
+
+$install_iva:
+ mtctl %r10,%cr14
+
+ /* Disable (most) interruptions */
+ mtsm %r0
+
+ /* kernel PSW:
+ * - no interruptions except for HPMC and TOC (which are handled by PDC)
+ * - Q bit set (IODC / PDC interruptions)
+ * - big-endian
+ * - virtually mapped
+ */
+
+ ldil L%KERNEL_PSW,%r10
+ ldo R%KERNEL_PSW(%r10),%r10
+ mtctl %r10,%ipsw
+
+ /* Set the space pointers for the post-RFI world */
+ mtctl %r0,%cr17 /* Clear two-level IIA Space Queue */
+ mtctl %r0,%cr17 /* effectively setting kernel space. */
+
+ /* And the return address(es) too */
+ ldil L%start_parisc,%r10
+ ldo R%start_parisc(%r10),%r10
+ mtctl %r10,%cr18
+ ldo 4(%r10),%r10
+ mtctl %r10,%cr18
+
+ /* Jump to hyperspace */
+ rfi
+ nop
+
+ .procend
+
+ .data
+
+ .align 4
+ .export $global$,data
+
+ .type $global$,@object
+ .size $global$,4
+$global$:
+ .word 0
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
new file mode 100644
index 000000000..c77aee04e
--- /dev/null
+++ b/arch/parisc/kernel/hpmc.S
@@ -0,0 +1,319 @@
+/*
+ * HPMC (High Priority Machine Check) handler.
+ *
+ * Copyright (C) 1999 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 1999 Hewlett-Packard (Frank Rowand)
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * This HPMC handler retrieves the HPMC pim data, resets IO and
+ * returns to the default trap handler with code set to 1 (HPMC).
+ * The default trap handler calls handle interruption, which
+ * does a stack and register dump. This at least allows kernel
+ * developers to get back to C code in virtual mode, where they
+ * have the option to examine and print values from memory that
+ * would help in debugging an HPMC caused by a software bug.
+ *
+ * There is more to do here:
+ *
+ * 1) On MP systems we need to synchronize processors
+ * before calling pdc/iodc.
+ * 2) We should be checking the system state and not
+ * returning to the fault handler if things are really
+ * bad.
+ *
+ */
+
+ .level 1.1
+ .data
+
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/pdc.h>
+
+ /*
+ * stack for os_hpmc, the HPMC handler.
+ * buffer for IODC procedures (for the HPMC handler).
+ *
+ * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc.
+ */
+
+ .align 4096
+hpmc_stack:
+ .block 16384
+
+#define HPMC_IODC_BUF_SIZE 0x8000
+
+ .align 4096
+hpmc_iodc_buf:
+ .block HPMC_IODC_BUF_SIZE
+
+ .align 8
+hpmc_raddr:
+ .block 128
+
+#define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */
+
+ .export hpmc_pim_data, data
+ .align 8
+hpmc_pim_data:
+ .block HPMC_PIM_DATA_SIZE
+
+ .text
+
+ .export os_hpmc, code
+ .import intr_save, code
+
+os_hpmc:
+
+ /*
+ * registers modified:
+ *
+ * Using callee saves registers without saving them. The
+ * original values are in the pim dump if we need them.
+ *
+ * r2 (rp) return pointer
+ * r3 address of PDCE_PROC
+ * r4 scratch
+ * r5 scratch
+ * r23 (arg3) procedure arg
+ * r24 (arg2) procedure arg
+ * r25 (arg1) procedure arg
+ * r26 (arg0) procedure arg
+ * r30 (sp) stack pointer
+ *
+ * registers read:
+ *
+ * r26 contains address of PDCE_PROC on entry
+ * r28 (ret0) return value from procedure
+ */
+
+ copy arg0, %r3 /* save address of PDCE_PROC */
+
+ /*
+ * disable nested HPMCs
+ *
+ * Increment os_hpmc checksum to invalidate it.
+ * Do this before turning the PSW M bit off.
+ */
+
+ mfctl %cr14, %r4
+ ldw 52(%r4),%r5
+ addi 1,%r5,%r5
+ stw %r5,52(%r4)
+
+ /* MP_FIXME: synchronize all processors. */
+
+ /* Setup stack pointer. */
+
+ ldil L%PA(hpmc_stack),sp
+ ldo R%PA(hpmc_stack)(sp),sp
+
+ ldo 128(sp),sp /* leave room for arguments */
+
+ /*
+ * Most PDC routines require that the M bit be off.
+ * So turn on the Q bit and turn off the M bit.
+ */
+
+ ldo 8(%r0),%r4 /* PSW Q on, PSW M off */
+ mtctl %r4,ipsw
+ mtctl %r0,pcsq
+ mtctl %r0,pcsq
+ ldil L%PA(os_hpmc_1),%r4
+ ldo R%PA(os_hpmc_1)(%r4),%r4
+ mtctl %r4,pcoq
+ ldo 4(%r4),%r4
+ mtctl %r4,pcoq
+ rfi
+ nop
+
+os_hpmc_1:
+
+ /* Call PDC_PIM to get HPMC pim info */
+
+ /*
+ * Note that on some newer boxes, PDC_PIM must be called
+ * before PDC_IO if you want IO to be reset. PDC_PIM sets
+ * a flag that PDC_IO examines.
+ */
+
+ ldo PDC_PIM(%r0), arg0
+ ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */
+ ldil L%PA(hpmc_raddr),arg2
+ ldo R%PA(hpmc_raddr)(arg2),arg2
+ ldil L%PA(hpmc_pim_data),arg3
+ ldo R%PA(hpmc_pim_data)(arg3),arg3
+ ldil L%HPMC_PIM_DATA_SIZE,%r4
+ ldo R%HPMC_PIM_DATA_SIZE(%r4),%r4
+ stw %r4,-52(sp)
+
+ ldil L%PA(os_hpmc_2), rp
+ bv (r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_2)(rp), rp
+
+os_hpmc_2:
+ comib,<> 0,ret0, os_hpmc_fail
+
+ /* Reset IO by calling the hversion dependent PDC_IO routine */
+
+ ldo PDC_IO(%r0),arg0
+ ldo 0(%r0),arg1 /* log IO errors */
+ ldo 0(%r0),arg2 /* reserved */
+ ldo 0(%r0),arg3 /* reserved */
+ stw %r0,-52(sp) /* reserved */
+
+ ldil L%PA(os_hpmc_3),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_3)(rp),rp
+
+os_hpmc_3:
+
+ /* FIXME? Check for errors from PDC_IO (-1 might be OK) */
+
+ /*
+ * Initialize the IODC console device (HPA,SPA, path etc.
+ * are stored on page 0.
+ */
+
+ /*
+ * Load IODC into hpmc_iodc_buf by calling PDC_IODC.
+ * Note that PDC_IODC handles flushing the appropriate
+ * data and instruction cache lines.
+ */
+
+ ldo PDC_IODC(%r0),arg0
+ ldo PDC_IODC_READ(%r0),arg1
+ ldil L%PA(hpmc_raddr),arg2
+ ldo R%PA(hpmc_raddr)(arg2),arg2
+ ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */
+ ldo PDC_IODC_RI_INIT(%r0),%r4
+ stw %r4,-52(sp)
+ ldil L%PA(hpmc_iodc_buf),%r4
+ ldo R%PA(hpmc_iodc_buf)(%r4),%r4
+ stw %r4,-56(sp)
+ ldil L%HPMC_IODC_BUF_SIZE,%r4
+ ldo R%HPMC_IODC_BUF_SIZE(%r4),%r4
+ stw %r4,-60(sp)
+
+ ldil L%PA(os_hpmc_4),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_4)(rp),rp
+
+os_hpmc_4:
+ comib,<> 0,ret0,os_hpmc_fail
+
+ /* Call the entry init (just loaded by PDC_IODC) */
+
+ ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg0 /* console hpa */
+ ldo ENTRY_INIT_MOD_DEV(%r0), arg1
+ ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */
+ depi 0,31,11,arg2 /* clear bits 21-31 */
+ ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */
+ ldil L%PA(hpmc_raddr),%r4
+ ldo R%PA(hpmc_raddr)(%r4),%r4
+ stw %r4, -52(sp)
+ stw %r0, -56(sp) /* HV */
+ stw %r0, -60(sp) /* HV */
+ stw %r0, -64(sp) /* HV */
+ stw %r0, -68(sp) /* lang, must be zero */
+
+ ldil L%PA(hpmc_iodc_buf),%r5
+ ldo R%PA(hpmc_iodc_buf)(%r5),%r5
+ ldil L%PA(os_hpmc_5),rp
+ bv (%r5)
+ ldo R%PA(os_hpmc_5)(rp),rp
+
+os_hpmc_5:
+ comib,<> 0,ret0,os_hpmc_fail
+
+ /* Prepare to call intr_save */
+
+ /*
+ * Load kernel page directory (load into user also, since
+ * we don't intend to ever return to user land anyway)
+ */
+
+ ldil L%PA(swapper_pg_dir),%r4
+ ldo R%PA(swapper_pg_dir)(%r4),%r4
+ mtctl %r4,%cr24 /* Initialize kernel root pointer */
+ mtctl %r4,%cr25 /* Initialize user root pointer */
+
+ /* Clear sr4-sr7 */
+
+ mtsp %r0, %sr4
+ mtsp %r0, %sr5
+ mtsp %r0, %sr6
+ mtsp %r0, %sr7
+
+ tovirt %r30 /* make sp virtual */
+
+ rsm 8,%r0 /* Clear Q bit */
+ ldi 1,%r1
+ mtctl %r1,%cr29 /* Set trap code to "1" for HPMC */
+ mtctl %r0,%cr30 /* Force interruptions to use hpmc stack */
+ ldil L%PA(intr_save), %r1
+ ldo R%PA(intr_save)(%r1), %r1
+ be 0(%sr7,%r1)
+ nop
+
+os_hpmc_fail:
+
+ /*
+ * Reset the system
+ *
+ * Some systems may lockup from a broadcast reset, so try the
+ * hversion PDC_BROADCAST_RESET() first.
+ * MP_FIXME: reset all processors if more than one central bus.
+ */
+
+ /* PDC_BROADCAST_RESET() */
+
+ ldo PDC_BROADCAST_RESET(%r0),arg0
+ ldo 0(%r0),arg1 /* do reset */
+
+ ldil L%PA(os_hpmc_6),rp
+ bv (%r3) /* call pdce_proc */
+ ldo R%PA(os_hpmc_6)(rp),rp
+
+os_hpmc_6:
+
+ /*
+ * possible return values:
+ * -1 non-existent procedure
+ * -2 non-existent option
+ * -16 unaligned stack
+ *
+ * If call returned, do a broadcast reset.
+ */
+
+ ldil L%0xfffc0000,%r4 /* IO_BROADCAST */
+ ldo 5(%r0),%r5
+ stw %r5,48(%r4) /* CMD_RESET to IO_COMMAND offset */
+
+ b .
+ nop
+
+ /* this label used to compute os_hpmc checksum */
+
+ .export os_hpmc_end, code
+
+os_hpmc_end:
+
+ nop
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
new file mode 100644
index 000000000..a838548de
--- /dev/null
+++ b/arch/parisc/kernel/init_task.c
@@ -0,0 +1,29 @@
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+
+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(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * We need to make sure that this is 16384-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union task_union init_task_union
+ __attribute__((section("init_task"), aligned(4096))) = { INIT_TASK(init_task_union.task) };
+
+unsigned long swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(4096))) = { 0, };
+#ifdef __LP64__
+unsigned long pmd0[PTRS_PER_PMD] __attribute__ ((aligned(4096))) = { 0, };
+#endif
+unsigned long pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(4096))) = { 0, };
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c
new file mode 100644
index 000000000..ab97cff1e
--- /dev/null
+++ b/arch/parisc/kernel/inventory.c
@@ -0,0 +1,397 @@
+
+/* Copyright (c) 1999 The Puffin Group */
+/* Written by David Kennedy and Alex deVries */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/pdc.h>
+
+/*
+** Debug options
+** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices.
+*/
+#undef DEBUG_PAT
+
+extern char *parisc_getHWtype(unsigned short hw_type);
+
+extern struct hp_device * register_module(void *hpa);
+extern void print_devices(char * buf);
+
+
+int pdc_hpa_processor(void *address);
+
+#ifndef __LP64__
+static u8 iodc_data[32] __attribute__ ((aligned (64)));
+static struct pdc_model model __attribute__ ((aligned (8)));
+#endif
+static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
+static struct pdc_hpa processor_hpa __attribute__ ((aligned (8)));
+static struct pdc_system_map module_result __attribute__ ((aligned (8)));
+static struct pdc_module_path module_path __attribute__ ((aligned (8)));
+
+#ifdef __LP64__
+#include <asm/pdcpat.h>
+
+int pdc_pat = 0;
+
+/*
+** The module object is filled via PDC_PAT_CELL[Return Cell Module].
+** If a module is found, register module will get the IODC bytes via
+** pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter.
+**
+** The IO view can be used by PDC_PAT_CELL[Return Cell Module]
+** only for SBAs and LBAs. This view will cause an invalid
+** argument error for all other cell module types.
+**
+*/
+
+static int
+pat_query_module( ulong pcell_loc, ulong mod_index)
+{
+ extern int num_devices;
+ extern struct hp_device devices[];
+
+ pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+ struct hp_device * dev = &devices[num_devices];
+ uint64_t temp; /* 64-bit scratch value */
+ long status; /* PDC return value status */
+
+ /* return cell module (PA or Processor view) */
+ status = pdc_pat_cell_module(& pdc_result, pcell_loc, mod_index,
+ PA_VIEW, & pa_pdc_cell);
+
+ if (status != PDC_RET_OK) {
+ /* no more cell modules or error */
+ return status;
+ }
+
+ /*
+ ** save parameters in the hp_device
+ ** (The idea being the device driver will call pdc_pat_cell_module()
+ ** and store the results in it's own data structure.)
+ */
+ dev->pcell_loc = pcell_loc;
+ dev->mod_index = mod_index;
+
+ /* save generic info returned from the call */
+ /* REVISIT: who is the consumer of this? not sure yet... */
+ dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */
+ dev->pmod_loc = pa_pdc_cell.mod_location;
+ dev->mod_path = pa_pdc_cell.mod_path;
+
+ temp = pa_pdc_cell.cba;
+ register_module((void *) PAT_GET_CBA(temp)); /* fills in dev->hpa */
+
+#ifdef DEBUG_PAT
+ /* dump what we see so far... */
+ switch (PAT_GET_ENTITY(dev->mod_info)) {
+ ulong i;
+
+ case PAT_ENTITY_PROC:
+ printk ("PAT_ENTITY_PROC: id_eid 0x%lx\n", pa_pdc_cell.mod[0]);
+ break;
+
+ case PAT_ENTITY_MEM:
+ printk ("PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",
+ pa_pdc_cell.mod[0],
+ pa_pdc_cell.mod[1],
+ pa_pdc_cell.mod[2]);
+ break;
+ case PAT_ENTITY_CA:
+ printk ("PAT_ENTITY_CA: %ld\n",pcell_loc);
+ break;
+
+ case PAT_ENTITY_PBC:
+ printk ("PAT_ENTITY_PBC: ");
+ goto print_ranges;
+
+ case PAT_ENTITY_SBA:
+ printk ("PAT_ENTITY_SBA: ");
+ goto print_ranges;
+
+ case PAT_ENTITY_LBA:
+ printk ("PAT_ENTITY_LBA: ");
+
+print_ranges:
+ printk ("ranges %ld\n", pa_pdc_cell.mod[1]);
+ for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
+ printk (" %ld: 0x%016lx 0x%016lx 0x%016lx\n", i,
+ pa_pdc_cell.mod[2+i*3], /* type */
+ pa_pdc_cell.mod[3+i*3], /* start */
+ pa_pdc_cell.mod[4+i*3]); /* finish (ie end) */
+ }
+ printk("\n");
+ break;
+ }
+#endif /* DEBUG_PAT */
+ return PDC_RET_OK;
+}
+
+
+static int do_pat_inventory(void)
+{
+ ulong mod_index=0;
+ int status;
+ ulong cell_num;
+ ulong pcell_loc;
+
+ pdc_pat = (pdc_pat_cell_get_number(&pdc_result) == PDC_OK);
+ if (!pdc_pat)
+ {
+ return 0;
+ }
+
+ cell_num = pdc_result[0]; /* Cell number call was made */
+
+ /* As of PDC PAT ARS 2.5, ret[1] is NOT architected! */
+ pcell_loc = pdc_result[1]; /* Physical location of the cell */
+
+#ifdef DEBUG_PAT
+ printk("CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_num, pcell_loc);
+#endif
+
+ status = pdc_pat_cell_num_to_loc(&pdc_result, cell_num);
+ if (status == PDC_BAD_OPTION)
+ {
+ /* Prelude (and it's successors: Lclass, A400/500) only
+ ** implement PDC_PAT_CELL sub-options 0 and 2.
+ ** "Home cook'n is best anyhow!"
+ */
+ } else if (PDC_OK == status) {
+ /* so far only Halfdome supports this */
+ pcell_loc = pdc_result[0];
+ } else {
+ panic("WTF? CELL_GET_NUMBER give me invalid cell number?");
+ }
+
+ while (PDC_RET_OK == pat_query_module(pcell_loc, mod_index))
+ {
+ mod_index++;
+ }
+
+ return mod_index;
+}
+#endif /* __LP64__ */
+
+static int do_newer_workstation_inventory(void)
+{
+ long status;
+ int i, num = 0;
+
+ /* So the idea here is to simply try one SYSTEM_MAP call. If
+ that one works, great, otherwise do it another way */
+
+ status = pdc_system_map_find_mods(&module_result,&module_path,0);
+
+ if (status == PDC_RET_OK) {
+ /* This is for newer non-PDC-PAT boxes */
+
+ printk("a newer box...\n");
+ for(i=0, status=PDC_RET_OK; status != PDC_RET_NE_PROC &&
+ status != PDC_RET_NE_MOD ;i++) {
+
+ status = pdc_system_map_find_mods(&module_result,&module_path,i);
+ if (status == PDC_RET_OK) {
+ num++;
+ register_module(module_result.mod_addr);
+ }
+ }
+ }
+
+ return (num > 0);
+}
+
+#ifndef __LP64__
+static struct pdc_memory_map r_addr __attribute__ ((aligned (8)));
+
+static int really_do_oldhw_inventory(void)
+{
+ int i, mod, num = 0;
+ int status;
+ unsigned int hw_type;
+ unsigned int func;
+
+ /* This is undocumented at the time of writing, but basically
+ we're setting up mod_path so that bc[0..4]=0xff, and step
+ through mod to get the "Path Structure for GSC Modules". If
+ it works, use the returned HPA and determine the hardware type. */
+
+ for (i=0;i<6;i++) module_path.bc[i]=0xff;
+
+ for (mod=0;mod<16;mod++) {
+ char *stype = NULL;
+
+ module_path.mod=mod;
+ status = pdc_mem_map_hpa(&r_addr, &module_path);
+ if (status!=PDC_RET_OK) continue;
+
+ status = pdc_iodc_read(&pdc_result,(void *) r_addr.hpa,
+ 0, &iodc_data,32 );
+ if (status!=PDC_RET_OK) continue;
+ hw_type = iodc_data[3]&0x1f;
+
+ switch (hw_type)
+ {
+ case HPHW_NPROC: /* 0 */
+ stype="Processor"; break;
+
+ case HPHW_MEMORY: /* 1 */
+ stype="Memory"; break;
+
+ case HPHW_B_DMA: /* 2 */
+ stype="Type B DMA"; break;
+
+ case HPHW_A_DMA: /* 4 */
+ stype="Type A DMA"; break;
+
+ case HPHW_A_DIRECT: /* 5 */
+ stype="Type A Direct"; break;
+
+ case HPHW_BCPORT: /* 7 */
+ stype="Bus Converter Port"; break;
+
+ case HPHW_CONSOLE: /* 9 */
+ stype="Console"; break;
+
+ case HPHW_FIO: /* 10 - Graphics */
+ stype="Foreign I/O (Graphics)"; break;
+
+ case HPHW_BA: /* 11 - Bus Adapter */
+ stype="Bus Adapter"; break;
+
+ case HPHW_IOA: /* 12 */
+ stype="I/O Adapter"; break;
+
+ case HPHW_BRIDGE: /* 13 */
+ stype="Bridge"; break;
+
+ case HPHW_FABRIC: /* 14 */
+ stype="Fabric"; break;
+
+ case HPHW_FAULTY: /* 31 */
+ stype="Faulty HW"; break;
+
+ case HPHW_OTHER: /* 42 */
+ default:
+ printk("Don't know this hw_type: %d\n", hw_type);
+ break;
+ }
+
+ // This is kluged. But don't want to replicate code for
+ // most of the above cases.
+ if (stype) {
+#ifdef DBG_PDC_QUERY
+ // parisc/kernel/drivers.c
+ extern int num_devices;
+ extern struct hp_device devices[];
+ struct hp_hardware *h;
+#endif
+
+ status = pdc_mem_map_hpa(&r_addr, &module_path);
+ if (status==PDC_RET_OK && register_module((void *) r_addr.hpa) != NULL)
+ num++;
+
+
+ if (hw_type == HPHW_BA) {
+ /* Now, we're checking for devices for each
+ module. I seem to think that the
+ modules in question are Lasi (2), 2nd Lasi (6)
+ Wax (5). To do this, set bc[5]=0, and set
+ bc[4] to the module, and step through the
+ functions. */
+
+ for (i=0;i<4;i++) module_path.bc[i]=0xff;
+ module_path.bc[4]=mod;
+ for (func=0;func<16;func++) {
+ module_path.mod = func;
+ module_path.bc[5]=0;
+ status = pdc_mem_map_hpa(&r_addr, &module_path);
+ if (status!=PDC_RET_OK) continue;
+ if (register_module((void *) r_addr.hpa) != NULL)
+ num++;
+ }
+ }
+ // reset module_path.bc[]
+ for (i=0;i<6;i++) module_path.bc[i]=0xff;
+
+
+#ifdef DBG_PDC_QUERY
+//
+// Let print_devices() dump everything which is registered.
+//
+ h = devices[num_devices-1].reference;
+
+ if (h) stype = h->name;
+ printk("Found %s at %d\n", stype, module_path.mod);
+#endif
+ }
+ }
+ return num;
+}
+
+static int
+do_old_inventory(void)
+{
+ unsigned int bus_id;
+ long status;
+ int ok = 0;
+
+ printk(" an older box...\n");
+
+ /* Here, we're going to check the model, and decide
+ if we should even bother trying. */
+
+ status = pdc_model_info(&model);
+
+ bus_id = (model.hversion >> (4+7) ) &0x1f;
+
+ /* Here, we're checking the HVERSION of the CPU.
+ We're only checking the 0th CPU, since it'll
+ be the same on an SMP box. */
+
+ switch (bus_id) {
+ case 0x4: /* 720, 730, 750, 735, 755 */
+ case 0x6: /* 705, 710 */
+ case 0x7: /* 715, 725 */
+ case 0x8: /* 745, 747, 742 */
+ case 0xA: /* 712 and similiar */
+ case 0xC: /* 715/64, at least */
+
+ /* Do inventory using MEM_MAP */
+ really_do_oldhw_inventory();
+ ok = 1;
+ break;
+ default: /* Everything else */
+ printk("This is a very very old machine, with a bus_id of 0x%x.\n",bus_id);
+ panic("This will probably never run Linux.\n");
+ }
+
+ return ok;
+}
+
+#endif /* !__LP64__ */
+
+void do_inventory(void){
+ if((pdc_hpa_processor(&processor_hpa))<0){
+ printk(KERN_INFO "Couldn't get the HPA of the processor.\n" );
+ }
+
+ printk("Searching for devices in PDC firmware... ");
+ printk("processor hpa 0x%lx\n", processor_hpa.hpa);
+
+ if (!(
+ do_newer_workstation_inventory()
+#ifdef __LP64__
+ || do_pat_inventory()
+#else /* __LP64__ */
+ || do_old_inventory()
+#endif /* __LP64__ */
+ ))
+ {
+ panic("I can't get the hardware inventory on this machine");
+ }
+ print_devices(NULL);
+}
+
diff --git a/arch/parisc/kernel/iosapic.c b/arch/parisc/kernel/iosapic.c
new file mode 100644
index 000000000..688cbf9bb
--- /dev/null
+++ b/arch/parisc/kernel/iosapic.c
@@ -0,0 +1,1100 @@
+/*
+** I/O Sapic Driver - PCI interrupt line support
+**
+** (c) Copyright 1999 Grant Grundler
+** (c) Copyright 1999 Hewlett-Packard Company
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** The I/O sapic driver manages the Interrupt Redirection Table which is
+** the control logic to convert PCI line based interrupts into a Message
+** Signaled Interrupt (aka Transaction Based Interrupt, TBI).
+**
+** Acronyms
+** --------
+** HPA Hard Physical Address (aka MMIO address)
+** IRQ Interrupt ReQuest. Implies Line based interrupt.
+** IRT Interrupt Routing Table (provided by PAT firmware)
+** IRdT Interrupt Redirection Table. IRQ line to TXN ADDR/DATA
+** table which is implemented in I/O SAPIC.
+** ISR Interrupt Service Routine. aka Interrupt handler.
+** MSI Message Signaled Interrupt. PCI 2.2 functionality.
+** aka Transaction Based Interrupt (or TBI).
+** PA Precision Architecture. HP's RISC architecture.
+** RISC Reduced Instruction Set Computer.
+**
+**
+** What's a Message Signalled Interrupt?
+** -------------------------------------
+** MSI is a write transaction which targets a processor and is similar
+** to a processor write to memory or MMIO. MSIs can be generated by I/O
+** devices as well as processors and require *architecture* to work.
+**
+** PA only supports MSI. So I/O subsystems must either natively generate
+** MSIs (e.g. GSC or HP-PB) or convert line based interrupts into MSIs
+** (e.g. PCI and EISA). IA64 supports MSIs via a "local SAPIC" which
+** acts on behalf of a processor.
+**
+** MSI allows any I/O device to interrupt any processor. This makes
+** load balancing of the interrupt processing possible on an SMP platform.
+** Interrupts are also ordered WRT to DMA data. It's possible on I/O
+** coherent systems to completely eliminate PIO reads from the interrupt
+** path. The device and driver must be designed and implemented to
+** guarantee all DMA has been issued (issues about atomicity here)
+** before the MSI is issued. I/O status can then safely be read from
+** DMA'd data by the ISR.
+**
+**
+** PA Firmware
+** -----------
+** PA-RISC platforms have two fundementally different types of firmware.
+** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register
+** and BARs similar to a traditional PC BIOS.
+** The newer "PAT" firmware supports PDC calls which return tables.
+** PAT firmware only initializes PCI Console and Boot interface.
+** With these tables, the OS can progam all other PCI devices.
+**
+** One such PAT PDC call returns the "Interrupt Routing Table" (IRT).
+** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
+** input line. If the IRT is not available, this driver assumes
+** INTERRUPT_LINE register has been programmed by firmware. The latter
+** case also means online addition of PCI cards can NOT be supported
+** even if HW support is present.
+**
+** All platforms with PAT firmware to date (Oct 1999) use one Interrupt
+** Routing Table for the entire platform.
+**
+** Where's the iosapic?
+** --------------------
+** I/O sapic is part of the "Core Electronics Complex". And on HP platforms
+** it's integrated as part of the PCI bus adapter, "lba". So no bus walk
+** will discover I/O Sapic. I/O Sapic driver learns about each device
+** when lba driver advertises the presence of the I/O sapic by calling
+** iosapic_register().
+**
+**
+** IRQ region notes
+** ----------------
+** The data passed to iosapic_interrupt() is per IRQ line.
+** Each IRQ line will get one txn_addr/data pair. Thus each IRQ region,
+** will have several txn_addr/data pairs (up to 7 for current I/O SAPIC
+** implementations). The IRQ region "sysdata" will NOT be directly passed
+** to the interrupt handler like GSCtoPCI (dino.c).
+**
+** iosapic interrupt handler will NOT call do_irq_mask().
+** It doesn't need to read a bit mask to determine which IRQ line was pulled
+** since it already knows based on vector_info passed to iosapic_interrupt().
+**
+** One IRQ number represents both an IRQ line and a driver ISR.
+** The I/O sapic driver can't manage shared IRQ lines because
+** additional data besides the IRQ number must be passed via
+** irq_region_ops. do_irq() and request_irq() must manage
+** a sharing a bit in the mask.
+**
+** iosapic_interrupt() replaces do_irq_mask() and calls do_irq().
+** Which IRQ line was asserted is already known since each
+** line has unique data associated with it. We could omit
+** iosapic_interrupt() from the calling path if it did NOT need
+** to write EOI. For unshared lines, it really doesn't.
+**
+** Unfortunately, can't optimize out EOI if IRQ line isn't "shared".
+** N-class console "device" and some sort of heartbeat actually share
+** one line though only one driver is registered...<sigh>...this was
+** true for HP-UX at least. May not be true for parisc-linux.
+**
+**
+** Overview of exported iosapic functions
+** --------------------------------------
+** (caveat: code isn't finished yet - this is just the plan)
+**
+** iosapic_init:
+** o initialize globals (lock, etc)
+** o try to read IRT. Presence of IRT determines if this is
+** a PAT platform or not.
+**
+** iosapic_register():
+** o create iosapic_info instance data structure
+** o allocate vector_info array for this iosapic
+** o initialize vector_info - read corresponding IRdT?
+**
+** iosapic_xlate_pin: (only called by fixup_irq for PAT platform)
+** o intr_pin = read cfg (INTERRUPT_PIN);
+** o if (device under PCI-PCI bridge)
+** translate slot/pin
+**
+** iosapic_fixup_irq:
+** o if PAT platform (IRT present)
+** intr_pin = iosapic_xlate_pin(isi,pcidev):
+** intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin)
+** save IRT entry into vector_info later
+** write cfg INTERRUPT_LINE (with intr_line)?
+** else
+** intr_line = pcidev->irq
+** IRT pointer = NULL
+** endif
+** o locate vector_info (needs: isi, intr_line)
+** o allocate processor "irq" and get txn_addr/data
+** o request_irq(processor_irq, iosapic_interrupt, vector_info,...)
+** o pcidev->irq = isi->isi_region...base + intr_line;
+**
+** iosapic_interrupt:
+** o call do_irq(vector->isi->irq_region, vector->irq_line, regs)
+** o assume level triggered and write EOI
+**
+** iosapic_enable_irq:
+** o clear any pending IRQ on that line
+** o enable IRdT - call enable_irq(vector[line]->processor_irq)
+** o write EOI in case line is already asserted.
+**
+** iosapic_disable_irq:
+** o disable IRdT - call disable_irq(vector[line]->processor_irq)
+**
+** FIXME: mask/unmask
+*/
+
+
+/* FIXME: determine which include files are really needed */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h> /* pci cfg accessor functions */
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h> /* irqaction */
+#include <linux/irq.h> /* irq_region support */
+
+#include <asm/byteorder.h> /* get in-line asm for swab */
+#include <asm/pdc.h>
+#include <asm/pdcpat.h>
+#include <asm/page.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/gsc.h> /* gsc_read/write functions */
+
+#include <asm/iosapic.h>
+#include "./iosapic_private.h"
+
+#define MODULE_NAME "iosapic"
+
+/* "local" compile flags */
+#undef IOSAPIC_CALLBACK
+#undef PCI_BRIDGE_FUNCS
+#undef DEBUG_IOSAPIC
+#undef DEBUG_IOSAPIC_IRT
+
+
+#ifdef DEBUG_IOSAPIC
+static char assert_buf[128];
+
+static int
+assert_failed (char *a, char *f, int l)
+{
+ sprintf(assert_buf,
+ "ASSERT(%s) failed!\nline %d in %s\n",
+ a, /* assertion text */
+ l, /* line number */
+ f); /* file name */
+ panic(assert_buf);
+ return 0;
+}
+
+#undef ASSERT
+#define ASSERT(EX) { if (!(EX)) assert_failed(# EX, __FILE__, __LINE__); }
+
+#define DBG(x...) printk(x)
+
+#else /* DEBUG_IOSAPIC */
+
+#define DBG(x...)
+#define ASSERT(EX)
+
+#endif /* DEBUG_IOSAPIC */
+
+#ifdef DEBUG_IOSAPIC_IRT
+#define DBG_IRT(x...) printk(x)
+#else
+#define DBG_IRT(x...)
+#endif
+
+
+#define READ_U8(addr) gsc_readb(addr)
+#define READ_U16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
+#define READ_U32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
+#define READ_REG16(addr) gsc_readw((u16 *) (addr))
+#define READ_REG32(addr) gsc_readl((u32 *) (addr))
+#define WRITE_U8(value, addr) gsc_writeb(value, addr)
+#define WRITE_U16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
+#define WRITE_U32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
+#define WRITE_REG16(value, addr) gsc_writew(value, (u16 *) (addr))
+#define WRITE_REG32(value, addr) gsc_writel(value, (u32 *) (addr))
+
+
+#define IOSAPIC_REG_SELECT 0
+#define IOSAPIC_REG_WINDOW 0x10
+#define IOSAPIC_REG_EOI 0x40
+
+#define IOSAPIC_REG_VERSION 0x1
+
+#define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2)
+#define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2)
+
+/*
+** FIXME: revisit which GFP flags we should really be using.
+** GFP_KERNEL includes __GFP_WAIT flag and that may not
+** be acceptable. Since this is boot time, we shouldn't have
+** to wait ever and this code should (will?) never get called
+** from the interrrupt context.
+*/
+#define IOSAPIC_KALLOC(a_type, cnt) \
+ (a_type *) kmalloc(sizeof(a_type)*(cnt), GFP_KERNEL)
+#define IOSAPIC_FREE(addr, f_type, cnt) kfree((void *)addr)
+
+
+#define IOSAPIC_LOCK(lck) spin_lock_irqsave(lck, irqflags)
+#define IOSAPIC_UNLOCK(lck) spin_unlock_irqrestore(lck, irqflags)
+
+
+#define IOSAPIC_VERSION_MASK 0x000000ff
+#define IOSAPIC_VERSION_SHIFT 0x0
+#define IOSAPIC_VERSION(ver) \
+ (int) ((ver & IOSAPIC_VERSION_MASK) >> IOSAPIC_VERSION_SHIFT)
+
+#define IOSAPIC_MAX_ENTRY_MASK 0x00ff0000
+
+#define IOSAPIC_MAX_ENTRY_SHIFT 0x10
+#define IOSAPIC_IRDT_MAX_ENTRY(ver) \
+ (int) ((ver&IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
+
+/* bits in the "low" I/O Sapic IRdT entry */
+#define IOSAPIC_IRDT_ENABLE 0x10000
+#define IOSAPIC_IRDT_PO_LOW 0x02000
+#define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
+#define IOSAPIC_IRDT_MODE_LPRI 0x00100
+
+/* bits in the "high" I/O Sapic IRdT entry */
+#define IOSAPIC_IRDT_ID_EID_SHIFT 0x10
+
+
+
+#define IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr)
+
+#if IOSAPIC_CALLBACK
+/*
+** Shouldn't use callback since SAPIC doesn't have an officially assigned
+** H or S version numbers. Slight long term risk the number chosen would
+** collide with something else.
+** But benefit is cleaner lba/sapic interface.
+** Might be worth it but for just use direct calls for now.
+**
+** Entry below is copied from lba driver.
+** Only thing different is hw_type.
+*/
+static struct pa_iodc_driver iosapic_driver_for[] = {
+ {HPHW_OTHER, 0x782, 0, 0x0000A, 0, 0x00,
+ DRIVER_CHECK_HWTYPE + DRIVER_CHECK_HVERSION + DRIVER_CHECK_SVERSION,
+ "I/O Sapic", "",(void *) iosapic_callback},
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL,(char *) NULL,(void *) NULL}
+};
+#endif /* IOSAPIO_CALLBACK */
+
+
+static struct iosapic_info *iosapic_list;
+static spinlock_t iosapic_lock;
+static int iosapic_count;
+
+
+/*
+** REVISIT: future platforms may have more than one IRT.
+** If so, the following three fields form a structure which
+** then be linked into a list. Names are chosen to make searching
+** for them easy - not necessarily accurate (eg "cell").
+**
+** Alternative: iosapic_info could point to the IRT it's in.
+** iosapic_register() could search a list of IRT's.
+*/
+static struct irt_entry *irt_cell;
+static size_t irt_num_entry;
+
+
+
+/*
+** iosapic_load_irt
+**
+** The "Get PCI INT Routing Table Size" option returns the number of
+** entries in the PCI interrupt routing table for the cell specified
+** in the cell_number argument. The cell number must be for a cell
+** within the caller's protection domain.
+**
+** The "Get PCI INT Routing Table" option returns, for the cell
+** specified in the cell_number argument, the PCI interrupt routing
+** table in the caller allocated memory pointed to by mem_addr.
+** We assume the IRT only contains entries for I/O SAPIC and
+** calculate the size based on the size of I/O sapic entries.
+**
+** The PCI interrupt routing table entry format is derived from the
+** IA64 SAL Specification 2.4. The PCI interrupt routing table defines
+** the routing of PCI interrupt signals between the PCI device output
+** "pins" and the IO SAPICs' input "lines" (including core I/O PCI
+** devices). This table does NOT include information for devices/slots
+** behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
+** for the architected method of routing of IRQ's behind PPB's.
+*/
+
+
+static int __init /* return number of entries as success/fail flag */
+iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
+{
+ struct pdc_pat_io_num pdc_io_num; /* PAT PDC return block */
+ long status; /* PDC return value status */
+ struct irt_entry *table = NULL; /* start of interrupt routing tbl */
+ unsigned long num_entries = 0UL;
+
+ ASSERT(NULL != irt);
+ /* FIXME ASSERT(((&pdc_io_num) & (0x3f)) == 0); enforce 32-byte alignment */
+
+ /* Try PAT_PDC to get interrupt routing table size */
+ DBG(KERN_DEBUG "calling get_irt_size\n");
+ status = pdc_pat_get_irt_size( &pdc_io_num, cell_num);
+ DBG(KERN_DEBUG "get_irt_size: %ld\n", status);
+
+ switch(status) {
+
+ case PDC_RET_OK: /* PAT box. Proceed to get the IRT */
+
+ /* save the number of entries in the table */
+ num_entries = pdc_io_num.num;
+ ASSERT(0UL != num_entries);
+
+ /*
+ ** allocate memory for interrupt routing table
+ ** This interface isn't really right. We are assuming
+ ** the contents of the table are exclusively
+ ** for I/O sapic devices.
+ */
+ table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
+ if (table == NULL) {
+ printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
+ return 0;
+ }
+
+ /* get PCI INT routing table */
+ status = pdc_pat_get_irt( (void *) table, cell_num);
+ DBG(KERN_DEBUG "pdc_pat_get_irt: %ld\n", status);
+ ASSERT(status == PDC_RET_OK);
+ break;
+
+ case PDC_RET_NE_PROC: /* Not a PAT platform. Try PDC_PCI extensions */
+ /*
+ ** C3000/J5000 (and similar) platforms with "legacy" PDC
+ ** will return exactly one IRT.
+ ** So if we have one, don't need to get it again.
+ */
+ if (NULL != irt_cell)
+ break;
+
+ status = pdc_pci_irt_size( (void *)&pdc_io_num,
+ /* elroy HPA (really a NOP) */ 0);
+ DBG(KERN_WARNING "pdc_pci_irt_size: %ld\n", status);
+
+ if (PDC_RET_OK != status) {
+ /* Not a "legacy" system with I/O SAPIC either */
+ return 0;
+ }
+
+ num_entries = pdc_io_num.num;
+ ASSERT(0UL != num_entries);
+
+ table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
+ if (table == NULL) {
+ printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
+ return 0;
+ }
+
+ status = pdc_pci_irt( (void *) &pdc_io_num,
+ (void *) NULL, /* Elroy HPA - not used */
+ (void *) table);
+
+ ASSERT(PDC_RET_OK == status);
+ break;
+
+ default:
+ printk(KERN_WARNING MODULE_NAME ": PDC_PAT_IO call failed with %ld\n", status);
+ break;
+ }
+
+ /* return interrupt table address */
+ *irt = table;
+
+
+#ifdef DEBUG_IOSAPIC_IRT
+ {
+ struct irt_entry *p = table;
+ int i;
+
+ printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
+ printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
+ table,
+ num_entries,
+ (int) sizeof(struct irt_entry));
+
+ for (i = 0 ; i < num_entries ; i++, p++)
+ {
+ printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
+ p->entry_type, p->entry_length, p->interrupt_type,
+ p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
+ p->src_seg_id, p->dest_iosapic_intin,
+ ((u32 *) p)[2],
+ ((u32 *) p)[3]
+ );
+ }
+ }
+#endif /* DEBUG_IOSAPIC_IRT */
+
+ return num_entries;
+}
+
+
+
+void __init
+iosapic_init(void)
+{
+ /* init global data */
+ iosapic_lock = SPIN_LOCK_UNLOCKED;
+ iosapic_list = (struct iosapic_info *) NULL;
+ iosapic_count = 0;
+
+ DBG("iosapic_init()\n");
+
+ /*
+ ** get IRT for this cell.
+ */
+ irt_num_entry = iosapic_load_irt(0L, &irt_cell);
+ if (0 == irt_num_entry)
+ irt_cell = NULL; /* old PDC w/o iosapic */
+
+#ifdef IOSAPIC_CALLBACK
+ /*
+ ** When new I/O SAPICs are discovered, this callback
+ ** will get invoked. Implies lba driver will register
+ ** I/O Sapic as a device it "discovered" with faked
+ ** IODC data.
+ */
+ register_driver(iosapic_driver_for);
+#endif /* IOSAPIC_CALLBACK */
+}
+
+
+/*
+** Return the IRT entry in case we need to look something else up.
+*/
+static struct irt_entry *
+irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
+{
+ struct irt_entry *i = irt_cell;
+ int cnt; /* track how many entries we've looked at */
+ u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1);
+
+ DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin);
+
+ for (cnt=0; cnt < irt_num_entry; cnt++, i++) {
+
+ /*
+ ** Validate: entry_type, entry_length, interrupt_type
+ **
+ ** Difference between validate vs compare is the former
+ ** should print debug info and is not expected to "fail"
+ ** on current platforms.
+ */
+ if (i->entry_type != IRT_IOSAPIC_TYPE) {
+ DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type);
+ continue;
+ }
+
+ if (i->entry_length != IRT_IOSAPIC_LENGTH) {
+ DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length);
+ continue;
+ }
+
+ if (i->interrupt_type != IRT_VECTORED_INTR) {
+ DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type);
+ continue;
+ }
+
+ /*
+ ** Compare: dest_iosapic_addr, src_bus_irq_devno
+ */
+ if (i->dest_iosapic_addr != (u64) ((long) isi->isi_hpa))
+ continue;
+
+ if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
+ continue;
+
+ /*
+ ** Ignore: src_bus_id and rc_seg_id correlate with
+ ** iosapic_info->isi_hpa on HP platforms.
+ ** If needed, pass in "PFA" (aka config space addr)
+ ** instead of slot.
+ */
+
+ /* Found it! */
+ return i;
+ }
+
+ printk(KERN_WARNING MODULE_NAME ": 0x%p : no IRT entry for slot %d, pin %d\n",
+ isi->isi_hpa, slot, intr_pin);
+ return NULL;
+}
+
+
+/*
+** xlate_pin() supports the skewing of IRQ lines done by subsidiary bridges.
+** Legacy PDC already does this translation for us and stores it in INTR_LINE.
+**
+** PAT PDC needs to basically do what legacy PDC does:
+** o read PIN
+** o adjust PIN in case device is "behind" a PPB
+** (eg 4-port 100BT and SCSI/LAN "Combo Card")
+** o convert slot/pin to I/O SAPIC input line.
+**
+** HP platforms only support:
+** o one level of skewing for any number of PPBs
+** o only support PCI-PCI Bridges.
+*/
+static struct irt_entry *
+iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
+{
+ u8 intr_pin, intr_slot;
+
+ (void) pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
+
+ DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n", PCI_SLOT(pcidev->devfn), intr_pin);
+
+ if (0 == intr_pin)
+ {
+ /*
+ ** The device does NOT support/use IRQ lines.
+ */
+ return NULL;
+ }
+
+ /* Check if pcidev behind a PPB */
+ if (NULL != pcidev->bus->self)
+ {
+ /* Convert pcidev INTR_PIN into something we
+ ** can lookup in the IRT.
+ */
+#ifdef PCI_BRIDGE_FUNCS
+ /*
+ ** Proposal #1:
+ **
+ ** call implementation specific translation function
+ ** This is architecturally "cleaner". HP-UX doesn't
+ ** support other secondary bus types (eg. E/ISA) directly.
+ ** May be needed for other processor (eg IA64) architectures
+ ** or by some ambitous soul who wants to watch TV.
+ */
+ if (pci_bridge_funcs->xlate_intr_line) {
+ intr_pin = (*pci_bridge_funcs->xlate_intr_line)(pcidev);
+ }
+#else /* PCI_BRIDGE_FUNCS */
+ struct pci_bus *p = pcidev->bus;
+ /*
+ ** Proposal #2:
+ ** The "pin" is skewed ((pin + dev - 1) % 4).
+ **
+ ** This isn't very clean since I/O SAPIC must assume:
+ ** - all platforms only have PCI busses.
+ ** - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA)
+ ** - IRQ routing is only skewed once regardless of
+ ** the number of PPB's between iosapic and device.
+ ** (Bit3 expansion chassis follows this rule)
+ **
+ ** Advantage is it's really easy to implement.
+ */
+ intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4;
+ intr_pin++; /* convert back to INTA-D (1-4) */
+#endif /* PCI_BRIDGE_FUNCS */
+
+ /*
+ ** Locate the host slot the PPB nearest the Host bus
+ ** adapter.
+ */
+ while (NULL != p->parent->self)
+ p = p->parent;
+
+ intr_slot = PCI_SLOT(p->self->devfn);
+ } else {
+ intr_slot = PCI_SLOT(pcidev->devfn);
+ }
+ DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n",
+ pcidev->bus->secondary, intr_slot, intr_pin);
+
+ return irt_find_irqline(isi, intr_slot, intr_pin);
+}
+
+
+static void
+iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct vector_info *vi = (struct vector_info *)dev_id;
+ extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
+ int irq_num = vi->vi_ios->isi_region->data.irqbase + vi->vi_irqline;
+
+ DBG("iosapic_interrupt(): irq %d line %d eoi %p\n", irq, vi->vi_irqline,
+ vi->vi_eoi_addr);
+
+/* FIXME: Need to mask/unmask? processor IRQ is already masked... */
+ do_irq(&vi->vi_ios->isi_region->action[vi->vi_irqline], irq_num, regs);
+
+ /*
+ ** PCI only supports level triggered in order to share IRQ lines.
+ ** I/O SAPIC must always issue EOI.
+ */
+ IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data);
+}
+
+
+int
+iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
+{
+ struct iosapic_info *isi = (struct iosapic_info *)isi_obj;
+ struct irt_entry *irte = NULL; /* only used if PAT PDC */
+ struct vector_info *vi;
+ int isi_line; /* line used by device */
+ int tmp;
+
+ if (NULL == isi) {
+ printk(KERN_WARNING MODULE_NAME ": 0x%p hpa not registered\n", isi->isi_hpa);
+ return(-1);
+ }
+
+ /* lookup IRT entry for isi/slot/pin set */
+ irte = iosapic_xlate_pin(isi, pcidev);
+ if (NULL == irte) {
+ return(-1);
+ }
+ DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
+ irte,
+ irte->entry_type,
+ irte->entry_length,
+ irte->polarity_trigger,
+ irte->src_bus_irq_devno,
+ irte->src_bus_id,
+ irte->src_seg_id,
+ irte->dest_iosapic_intin,
+ (u32) irte->dest_iosapic_addr);
+ isi_line = irte->dest_iosapic_intin;
+
+ /* get vector info for this input line */
+ ASSERT(NULL != isi->isi_vector);
+ vi = &(isi->isi_vector[isi_line]);
+ DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi);
+ vi->vi_irte = irte;
+
+ /* Allocate processor IRQ */
+ vi->vi_txn_irq = txn_alloc_irq();
+
+/* XXX/FIXME The txn_alloc_irq() code and related code should be moved
+** to enable_irq(). That way we only allocate processor IRQ bits
+** for devices that actually have drivers claiming them.
+** Right now we assign an IRQ to every PCI device present regardless
+** of whether it's used or not.
+*/
+ if (vi->vi_txn_irq < 0)
+ panic("I/O sapic: couldn't get TXN IRQ\n");
+
+ /* enable_irq() will use txn_* to program IRdT */
+ vi->vi_txn_addr = txn_alloc_addr(vi->vi_txn_irq);
+ vi->vi_txn_data = txn_alloc_data(vi->vi_txn_irq, 8);
+ ASSERT(vi->vi_txn_data < 256); /* matches 8 above */
+
+ tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0, "iosapic", vi);
+ ASSERT(tmp == 0);
+
+ vi->vi_eoi_addr = ((void *) isi->isi_hpa) + IOSAPIC_REG_EOI;
+ vi->vi_eoi_data = cpu_to_le32(vi->vi_irqline);
+
+ ASSERT(NULL != isi->isi_region);
+ /*
+ ** pcidev->irq still needs to be virtualized.
+ */
+ pcidev->irq = isi->isi_region->data.irqbase + isi_line;
+
+ DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n", PCI_SLOT(pcidev->devfn),
+ PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
+
+ return(pcidev->irq);
+}
+
+
+static void
+iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)
+{
+ struct iosapic_info *isp = vi->vi_ios;
+ u8 idx = vi->vi_irqline;
+
+ /* point the window register to the lower word */
+ WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
+ *dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+
+ /* point the window register to the higher word */
+ WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
+ *dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+}
+
+
+static void
+iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1)
+{
+ struct iosapic_info *isp = vi->vi_ios;
+
+ ASSERT(NULL != isp);
+ ASSERT(NULL != isp->isi_hpa);
+ DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p 0x%x 0x%x\n",
+ vi->vi_irqline,
+ isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW,
+ dp0, dp1);
+
+ /* point the window register to the lower word */
+ WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
+ WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW);
+
+ /* Read the window register to flush the writes down to HW */
+ dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+
+ /* point the window register to the higher word */
+ WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
+ WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW);
+
+ /* Read the window register to flush the writes down to HW */
+ dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+}
+
+
+/*
+** set_irt prepares the data (dp0, dp1) according to the vector_info
+** and target cpu (id_eid). dp0/dp1 are then used to program I/O SAPIC
+** IRdT for the given "vector" (aka IRQ line).
+*/
+static void
+iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
+{
+ u32 mode = 0;
+ struct irt_entry *p = vi->vi_irte;
+ ASSERT(NULL != vi->vi_irte);
+
+ if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
+ mode |= IOSAPIC_IRDT_PO_LOW;
+
+ if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG)
+ mode |= IOSAPIC_IRDT_LEVEL_TRIG;
+
+ /*
+ ** IA64 REVISIT
+ ** PA doesn't support EXTINT or LPRIO bits.
+ */
+
+ ASSERT(vi->vi_txn_data);
+ *dp0 = mode | (u32) vi->vi_txn_data;
+
+ /*
+ ** Extracting id_eid isn't a real clean way of getting it.
+ ** But the encoding is the same for both PA and IA64 platforms.
+ */
+#ifdef __LP64__
+ if (pdc_pat) {
+ /*
+ ** PAT PDC just hands it to us "right".
+ ** vi_txn_addr comes from cpu_data[x].txn_addr.
+ */
+ *dp1 = (u32) (vi->vi_txn_addr);
+ } else
+#endif
+ {
+ /*
+ ** eg if base_addr == 0xfffa0000),
+ ** we want to get 0xa0ff0000.
+ **
+ ** eid 0x0ff00000 -> 0x00ff0000
+ ** id 0x000ff000 -> 0xff000000
+ */
+ *dp1 = (((u32)vi->vi_txn_addr & 0x0ff00000) >> 4) |
+ (((u32)vi->vi_txn_addr & 0x000ff000) << 12);
+ }
+ DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1);
+}
+
+
+static void
+iosapic_disable_irq(void *irq_dev, int irq)
+{
+ ulong irqflags;
+ struct vector_info *vi = &(((struct vector_info *) irq_dev)[irq]);
+ u32 d0, d1;
+
+ ASSERT(NULL != vi);
+
+ IOSAPIC_LOCK(&iosapic_lock);
+
+#ifdef REVISIT_DESIGN_ISSUE
+/*
+** XXX/FIXME
+
+disable_irq()/enable_irq(): drawback of using IRQ as a "handle"
+
+Current disable_irq interface only allows the irq_region support routines
+to manage sharing of "irq" objects. The problem is the disable_irq()
+interface specifies which IRQ line needs to be disabled but does not
+identify the particular ISR which needs to be disabled. IO sapic
+(and similar code in Dino) can only support one handler per IRQ
+since they don't further encode the meaning of the IRQ number.
+irq_region support has to hide it's implementation of "shared IRQ"
+behind a function call.
+
+Encoding the IRQ would be possible by I/O SAPIC but makes life really
+complicated for the IRQ handler and not help performance.
+
+Need more info on how Linux supports shared IRQ lines on a PC.
+*/
+#endif /* REVISIT_DESIGN_ISSUE */
+
+ iosapic_rd_irt_entry(vi, &d0, &d1);
+ d0 |= IOSAPIC_IRDT_ENABLE;
+ iosapic_wr_irt_entry(vi, d0, d1);
+
+ IOSAPIC_UNLOCK(&iosapic_lock);
+
+ /* disable ISR for parent */
+ disable_irq(vi->vi_txn_irq);
+}
+
+
+static void
+iosapic_enable_irq(void *dev, int irq)
+{
+ struct vector_info *vi = &(((struct vector_info *) dev)[irq]);
+ u32 d0, d1;
+
+ ASSERT(NULL != vi);
+ ASSERT(NULL != vi->vi_irte);
+
+ /* data is initialized by fixup_irq */
+ ASSERT(0 < vi->vi_txn_irq);
+ ASSERT(0UL != vi->vi_txn_addr);
+ ASSERT(0UL != vi->vi_txn_data);
+
+ iosapic_set_irt_data(vi, &d0, &d1);
+ iosapic_wr_irt_entry(vi, d0, d1);
+
+
+#ifdef DEBUG_IOSAPIC_IRT
+{
+u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL);
+printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr);
+while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++));
+printk("\n");
+}
+
+printk("iosapic_enable_irq(): sel ");
+{
+ struct iosapic_info *isp = vi->vi_ios;
+
+ for (d0=0x10; d0<0x1e; d0++) {
+ /* point the window register to the lower word */
+ WRITE_U32(d0, isp->isi_hpa+IOSAPIC_REG_SELECT);
+
+ /* read the word */
+ d1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+ printk(" %x", d1);
+ }
+}
+printk("\n");
+#endif
+
+ /*
+ ** KLUGE: IRQ should not be asserted when Drivers enabling their IRQ.
+ ** PCI supports level triggered in order to share IRQ lines.
+ **
+ ** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is
+ ** asserted.
+ */
+ IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data);
+}
+
+
+static void
+iosapic_mask_irq(void *dev, int irq)
+{
+ BUG();
+}
+
+
+static void
+iosapic_unmask_irq(void *dev, int irq)
+{
+ BUG();
+}
+
+
+static struct irq_region_ops iosapic_irq_ops = {
+ iosapic_disable_irq,
+ iosapic_enable_irq,
+ iosapic_mask_irq,
+ iosapic_unmask_irq
+};
+
+
+/*
+** squirrel away the I/O Sapic Version
+*/
+static unsigned int
+iosapic_rd_version(struct iosapic_info *isi)
+{
+ ASSERT(isi);
+ ASSERT(isi->isi_hpa);
+
+ /* point window to the version register */
+ WRITE_U32(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT);
+
+ /* now read the version register */
+ return (READ_U32(isi->isi_hpa+IOSAPIC_REG_WINDOW));
+}
+
+
+#ifndef IOSAPIC_CALLBACK
+/*
+** iosapic_register() is the alternative to iosapic_driver_for().
+** (Only one or the other should be implemented.)
+*/
+
+/*
+** iosapic_register() is called by "drivers" with an integrated I/O SAPIC.
+** Caller must be certain they have an I/O SAPIC and know it's MMIO address.
+**
+** o allocate iosapic_info and add it to the list
+** o read iosapic version and squirrel that away
+** o read size of IRdT.
+** o allocate and initialize isi_vector[]
+** o allocate isi_region (registers region handlers)
+*/
+void *
+iosapic_register(void *hpa)
+{
+ struct iosapic_info *isi = NULL;
+ struct irt_entry *irte = irt_cell;
+ struct vector_info *vip;
+ int cnt; /* track how many entries we've looked at */
+
+ /*
+ ** Astro based platforms can't support PCI OLARD if they
+ ** implement the legacy PDC (not PAT). Though Legacy PDC
+ ** supports an IRT, LBA's with no device under them
+ ** are *not* listed in the IRT.
+ ** Search the IRT and ignore iosapic's which aren't
+ ** in the IRT.
+ */
+ ASSERT(NULL != irte); /* always have built-in devices */
+ for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
+ ASSERT(IRT_IOSAPIC_TYPE == irte->entry_type);
+ /*
+ ** We need sign extension of the hpa on 32-bit kernels.
+ ** The address in the IRT is *always* 64 bit and really
+ ** is an unsigned quantity (like all physical addresses).
+ */
+ if (irte->dest_iosapic_addr == (s64) ((long) hpa))
+ break;
+ }
+
+ if (cnt >= irt_num_entry)
+ return (NULL);
+
+ if ((isi = IOSAPIC_KALLOC(struct iosapic_info, 1)) == NULL) {
+ BUG();
+ return (NULL);
+ }
+
+ memset(isi, 0, sizeof(struct iosapic_info));
+
+ isi->isi_hpa = (unsigned char *) hpa;
+ isi->isi_version = iosapic_rd_version(isi);
+ isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
+
+ vip = isi->isi_vector =
+ IOSAPIC_KALLOC(struct vector_info, isi->isi_num_vectors);
+
+ if (vip == NULL) {
+ IOSAPIC_FREE(isi, struct iosapic_info, 1);
+ return (NULL);
+ }
+
+ memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
+
+ /*
+ ** Initialize vector array
+ */
+ for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
+ vip->vi_irqline = (unsigned char) cnt;
+ vip->vi_ios = isi;
+ }
+
+ isi->isi_region = alloc_irq_region(isi->isi_num_vectors,
+ &iosapic_irq_ops, IRQ_REG_DIS|IRQ_REG_MASK,
+ "I/O Sapic", (void *) isi->isi_vector);
+
+ ASSERT(NULL != isi->isi_region);
+ return ((void *) isi);
+}
+#endif /* !IOSAPIC_CALLBACK */
+
+
+
+#ifdef DEBUG_IOSAPIC
+
+static void
+iosapic_prt_irt(void *irt, long num_entry)
+{
+ unsigned int i, *irp = (unsigned int *) irt;
+
+ ASSERT(NULL != irt);
+
+ printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
+
+ for (i=0; i<num_entry; i++, irp += 4) {
+ printk(KERN_DEBUG "%p : %2d %.8x %.8x %.8x %.8x\n",
+ irp, i, irp[0], irp[1], irp[2], irp[3]);
+ }
+}
+
+
+static void
+iosapic_prt_vi(struct vector_info *vi)
+{
+ ASSERT(NULL != vi);
+
+ printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->vi_irqline, vi);
+ printk(KERN_DEBUG "\t\tvi_status: %.4x\n", vi->vi_status);
+ printk(KERN_DEBUG "\t\tvi_txn_irq: %d\n", vi->vi_txn_irq);
+ printk(KERN_DEBUG "\t\tvi_txn_addr: %lx\n", vi->vi_txn_addr);
+ printk(KERN_DEBUG "\t\tvi_txn_data: %lx\n", vi->vi_txn_data);
+ printk(KERN_DEBUG "\t\tvi_eoi_addr: %p\n", vi->vi_eoi_addr);
+ printk(KERN_DEBUG "\t\tvi_eoi_data: %x\n", vi->vi_eoi_data);
+}
+
+
+static void
+iosapic_prt_isi(struct iosapic_info *isi)
+{
+ ASSERT(NULL != isi);
+ printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
+ printk(KERN_DEBUG "\t\tisi_hpa: %p\n", isi->isi_hpa);
+ printk(KERN_DEBUG "\t\tisi_satus: %x\n", isi->isi_status);
+ printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version);
+ printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector);
+}
+#endif /* DEBUG_IOSAPIC */
diff --git a/arch/parisc/kernel/iosapic_private.h b/arch/parisc/kernel/iosapic_private.h
new file mode 100644
index 000000000..f310501c4
--- /dev/null
+++ b/arch/parisc/kernel/iosapic_private.h
@@ -0,0 +1,165 @@
+/*
+** This file is private to iosapic driver.
+** If stuff needs to be used by another driver, move it to a common file.
+**
+** WARNING: fields most data structures here are ordered to make sure
+** they pack nicely for 64-bit compilation. (ie sizeof(long) == 8)
+*/
+
+
+/*
+** Interrupt Routing Stuff
+** -----------------------
+** The interrupt routing table consists of entries derived from
+** MP Specification Draft 1.5. There is one interrupt routing
+** table per cell. N- and L-class consist of a single cell.
+*/
+struct irt_entry {
+
+ /* Entry Type 139 identifies an I/O SAPIC interrupt entry */
+ u8 entry_type;
+
+ /* Entry Length 16 indicates entry is 16 bytes long */
+ u8 entry_length;
+
+ /*
+ ** Interrupt Type of 0 indicates a vectored interrupt,
+ ** all other values are reserved
+ */
+ u8 interrupt_type;
+
+ /*
+ ** PO and EL
+ ** Polarity of SAPIC I/O input signals:
+ ** 00 = Reserved
+ ** 01 = Active high
+ ** 10 = Reserved
+ ** 11 = Active low
+ ** Trigger mode of SAPIC I/O input signals:
+ ** 00 = Reserved
+ ** 01 = Edge-triggered
+ ** 10 = Reserved
+ ** 11 = Level-triggered
+ */
+ u8 polarity_trigger;
+
+ /*
+ ** IRQ and DEVNO
+ ** irq identifies PCI interrupt signal where
+ ** 0x0 corresponds to INT_A#,
+ ** 0x1 corresponds to INT_B#,
+ ** 0x2 corresponds to INT_C#
+ ** 0x3 corresponds to INT_D#
+ ** PCI device number where interrupt originates
+ */
+ u8 src_bus_irq_devno;
+
+ /* Source Bus ID identifies the bus where interrupt signal comes from */
+ u8 src_bus_id;
+
+ /*
+ ** Segment ID is unique across a protection domain and
+ ** identifies a segment of PCI buses (reserved in
+ ** MP Specification Draft 1.5)
+ */
+ u8 src_seg_id;
+
+ /*
+ ** Destination I/O SAPIC INTIN# identifies the INTIN n pin
+ ** to which the signal is connected
+ */
+ u8 dest_iosapic_intin;
+
+ /*
+ ** Destination I/O SAPIC Address identifies the I/O SAPIC
+ ** to which the signal is connected
+ */
+ u64 dest_iosapic_addr;
+};
+
+#define IRT_IOSAPIC_TYPE 139
+#define IRT_IOSAPIC_LENGTH 16
+
+#define IRT_VECTORED_INTR 0
+
+#define IRT_PO_MASK 0x3
+#define IRT_ACTIVE_HI 1
+#define IRT_ACTIVE_LO 3
+
+#define IRT_EL_MASK 0x3
+#define IRT_EL_SHIFT 2
+#define IRT_EDGE_TRIG 1
+#define IRT_LEVEL_TRIG 3
+
+#define IRT_IRQ_MASK 0x3
+#define IRT_DEV_MASK 0x1f
+#define IRT_DEV_SHIFT 2
+
+#define IRT_IRQ_DEVNO_MASK ((IRT_DEV_MASK << IRT_DEV_SHIFT) | IRT_IRQ_MASK)
+
+#ifdef SUPPORT_MULTI_CELL
+struct iosapic_irt {
+ struct iosapic_irt *irt_next; /* next routing table */
+ struct irt_entry *irt_base; /* intr routing table address */
+ size_t irte_count; /* number of entries in the table */
+ size_t irte_size; /* size (bytes) of each entry */
+};
+#endif
+
+struct vector_info {
+ struct iosapic_info *vi_ios; /* I/O SAPIC this vector is on */
+ struct irt_entry *vi_irte; /* IRT entry */
+ u32 *vi_eoi_addr; /* precalculate EOI reg address */
+ u32 vi_eoi_data; /* IA64: ? PA: swapped txn_data */
+ u8 vi_status; /* status/flags */
+ u8 vi_irqline; /* INTINn(IRQ) */
+ int vi_txn_irq; /* virtual IRQ number for processor */
+ ulong vi_txn_addr; /* IA64: id_eid PA: partial HPA */
+ ulong vi_txn_data; /* IA64: vector PA: EIR bit */
+};
+
+
+struct iosapic_info {
+ struct iosapic_info *isi_next; /* list of I/O SAPIC */
+ volatile void *isi_hpa; /* physical base address */
+ struct irq_region *isi_region; /* each I/O SAPIC is one region */
+ struct vector_info *isi_vector; /* IRdT (IRQ line) array */
+ int isi_num_vectors; /* size of IRdT array */
+ int isi_status; /* status/flags */
+ unsigned int isi_version; /* DEBUG: data fr version reg */
+};
+
+
+
+#ifdef __IA64__
+/*
+** PA risc does NOT have any local sapics. IA64 does.
+** PIB (Processor Interrupt Block) is handled by Astro or Dew (Stretch CEC).
+**
+** PA: Get id_eid from IRT and hardcode PIB to 0xfeeNNNN0
+** Emulate the data on PAT platforms.
+*/
+struct local_sapic_info {
+ struct local_sapic_info *lsi_next; /* point to next CPU info */
+ int *lsi_cpu_id; /* point to logical CPU id */
+ unsigned long *lsi_id_eid; /* point to IA-64 CPU id */
+ int *lsi_status; /* point to CPU status */
+ void *lsi_private; /* point to special info */
+};
+
+/*
+** "root" data structure which ties everything together.
+** Should always be able to start with sapic_root and locate
+** the desired information.
+*/
+struct sapic_info {
+ struct sapic_info *si_next; /* info is per cell */
+ int si_cellid; /* cell id */
+ unsigned int si_status; /* status */
+ char *si_pib_base; /* intr blk base address */
+ local_sapic_info_t *si_local_info;
+ io_sapic_info_t *si_io_info;
+ extint_info_t *si_extint_info;/* External Intr info */
+};
+#endif
+
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
new file mode 100644
index 000000000..aec36f7cc
--- /dev/null
+++ b/arch/parisc/kernel/irq.c
@@ -0,0 +1,538 @@
+/* $Id: irq.c,v 1.8 2000/02/08 02:01:17 grundler Exp $
+ *
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * This is not in any way SMP-clean.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1999 SuSE GmbH (Author: Philipp Rumpf, prumpf@tux.org)
+ * Copyright (C) 2000 Hewlett Packard Corp (Co-Author: Grant Grundler, grundler@cup.hp.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/bitops.h>
+#include <asm/bitops.h>
+#include <asm/pdc.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/cache.h>
+
+#undef DEBUG_IRQ
+
+extern void timer_interrupt(int, void *, struct pt_regs *);
+extern void ipi_interrupt(int, void *, struct pt_regs *);
+
+#ifdef DEBUG_IRQ
+#define DBG_IRQ(x...) printk(x)
+#else /* DEBUG_IRQ */
+#define DBG_IRQ(x...)
+#endif /* DEBUG_IRQ */
+
+#define EIEM_MASK(irq) (1L<<(MAX_CPU_IRQ-IRQ_OFFSET(irq)))
+#define CLEAR_EIEM_BIT(irq) set_eiem(get_eiem() & ~EIEM_MASK(irq))
+#define SET_EIEM_BIT(irq) set_eiem(get_eiem() | EIEM_MASK(irq))
+
+static void disable_cpu_irq(void *unused, int irq)
+{
+ CLEAR_EIEM_BIT(irq);
+}
+
+static void enable_cpu_irq(void *unused, int irq)
+{
+ unsigned long mask = EIEM_MASK(irq);
+
+ mtctl(mask, 23);
+ SET_EIEM_BIT(irq);
+}
+
+static struct irqaction cpu_irq_actions[IRQ_PER_REGION] = {
+ [IRQ_OFFSET(TIMER_IRQ)] { timer_interrupt, 0, 0, "timer", NULL, NULL },
+ [IRQ_OFFSET(IPI_IRQ)] { ipi_interrupt, 0, 0, "IPI", NULL, NULL },
+};
+
+struct irq_region cpu_irq_region = {
+ { disable_cpu_irq, enable_cpu_irq, NULL, NULL },
+ { &cpu_data[0], "PA-PIC", IRQ_REG_MASK|IRQ_REG_DIS, IRQ_FROM_REGION(CPU_IRQ_REGION)},
+ cpu_irq_actions
+};
+
+struct irq_region *irq_region[NR_IRQ_REGS] = {
+ [ 0 ] NULL, /* abuse will data page fault (aka code 15) */
+ [ CPU_IRQ_REGION ] &cpu_irq_region,
+};
+
+
+
+/* we special-case the real IRQs here, which feels right given the relatively
+ * high cost of indirect calls. If anyone is bored enough to benchmark this
+ * and find out whether I am right, feel free to. prumpf */
+
+static inline void mask_irq(int irq)
+{
+ struct irq_region *region;
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("mask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+
+ if(IRQ_REGION(irq) != CPU_IRQ_REGION) {
+ region = irq_region[IRQ_REGION(irq)];
+ if(region->data.flags & IRQ_REG_MASK)
+ region->ops.mask_irq(region->data.dev, IRQ_OFFSET(irq));
+ } else {
+ CLEAR_EIEM_BIT(irq);
+ }
+}
+
+static inline void unmask_irq(int irq)
+{
+ struct irq_region *region;
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("unmask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+
+ if(IRQ_REGION(irq) != CPU_IRQ_REGION) {
+ region = irq_region[IRQ_REGION(irq)];
+ if(region->data.flags & IRQ_REG_MASK)
+ region->ops.unmask_irq(region->data.dev, IRQ_OFFSET(irq));
+ } else {
+ SET_EIEM_BIT(irq);
+ }
+}
+
+void disable_irq(int irq)
+{
+ struct irq_region *region;
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("disable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+ region = irq_region[IRQ_REGION(irq)];
+
+ if(region->data.flags & IRQ_REG_DIS)
+ region->ops.disable_irq(region->data.dev, IRQ_OFFSET(irq));
+ else
+ BUG();
+}
+
+void enable_irq(int irq)
+{
+ struct irq_region *region;
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("enable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+ region = irq_region[IRQ_REGION(irq)];
+
+ if(region->data.flags & IRQ_REG_DIS)
+ region->ops.enable_irq(region->data.dev, IRQ_OFFSET(irq));
+ else
+ BUG();
+}
+
+int get_irq_list(char *buf)
+{
+#ifdef CONFIG_PROC_FS
+ char *p = buf;
+ int i, j;
+ int regnr, irq_no;
+ struct irq_region *region;
+ struct irqaction *action, *mainaction;
+
+ p += sprintf(p, " ");
+ for (j=0; j<smp_num_cpus; j++)
+ p += sprintf(p, "CPU%d ",j);
+ *p++ = '\n';
+
+ for (regnr = 0; regnr < NR_IRQ_REGS; regnr++) {
+ region = irq_region[regnr];
+ if (!region || !region->action)
+ continue;
+
+ mainaction = region->action;
+
+ for (i = 0; i <= MAX_CPU_IRQ; i++) {
+ action = mainaction++;
+ if (!action || !action->name)
+ continue;
+
+ irq_no = IRQ_FROM_REGION(regnr) + i;
+
+ p += sprintf(p, "%3d: ", irq_no);
+#ifndef CONFIG_SMP
+ p += sprintf(p, "%10u ", kstat_irqs(irq_no));
+#else
+ for (j = 0; j < smp_num_cpus; j++)
+ p += sprintf(p, "%10u ",
+ kstat.irqs[cpu_logical_map(j)][irq_no]);
+#endif
+ p += sprintf(p, " %14s",
+ region->data.name ? region->data.name : "N/A");
+ p += sprintf(p, " %s", action->name);
+
+ for (action=action->next; action; action = action->next)
+ p += sprintf(p, ", %s", action->name);
+ *p++ = '\n';
+ }
+ }
+
+ p += sprintf(p, "\n");
+#if CONFIG_SMP
+ p += sprintf(p, "LOC: ");
+ for (j = 0; j < smp_num_cpus; j++)
+ p += sprintf(p, "%10u ",
+ apic_timer_irqs[cpu_logical_map(j)]);
+ p += sprintf(p, "\n");
+#endif
+
+ return p - buf;
+
+#else /* CONFIG_PROC_FS */
+
+ return 0;
+
+#endif /* CONFIG_PROC_FS */
+}
+
+
+
+/*
+** The following form a "set": Virtual IRQ, Transaction Address, Trans Data.
+** Respectively, these map to IRQ region+EIRR, Processor HPA, EIRR bit.
+**
+** To use txn_XXX() interfaces, get a Virtual IRQ first.
+** Then use that to get the Transaction address and data.
+*/
+
+int
+txn_alloc_irq(void)
+{
+ int irq;
+
+ /* never return irq 0 cause that's the interval timer */
+ for(irq=1; irq<=MAX_CPU_IRQ; irq++) {
+ if(cpu_irq_region.action[irq].handler == NULL) {
+ return (IRQ_FROM_REGION(CPU_IRQ_REGION) + irq);
+ }
+ }
+
+ /* unlikely, but be prepared */
+ return -1;
+}
+
+int
+txn_claim_irq(int irq)
+{
+ if (irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)].handler ==NULL)
+ {
+ return irq;
+ }
+
+ /* unlikely, but be prepared */
+ return -1;
+}
+
+unsigned long
+txn_alloc_addr(int virt_irq)
+{
+ struct cpuinfo_parisc *dev = (struct cpuinfo_parisc *) (irq_region[IRQ_REGION(virt_irq)]->data.dev);
+
+ if (0==dev) {
+ printk(KERN_ERR "txn_alloc_addr(0x%x): CPU IRQ region? dev %p\n",
+ virt_irq,dev);
+ return(0UL);
+ }
+ return (dev->txn_addr);
+}
+
+
+/*
+** The alloc process needs to accept a parameter to accomodate limitations
+** of the HW/SW which use these bits:
+** Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register)
+** V-class (EPIC): 6 bits
+** N/L-class/A500: 8 bits (iosapic)
+** PCI 2.2 MSI: 16 bits (I think)
+** Existing PCI devices: 32-bits (NCR c720/ATM/GigE/HyperFabric)
+**
+** On the service provider side:
+** o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register)
+** o PA 2.0 wide mode 6-bits (per processor)
+** o IA64 8-bits (0-256 total)
+**
+** So a Legacy PA I/O device on a PA 2.0 box can't use all
+** the bits supported by the processor...and the N/L-class
+** I/O subsystem supports more bits than PA2.0 has. The first
+** case is the problem.
+*/
+unsigned int
+txn_alloc_data(int virt_irq, unsigned int bits_wide)
+{
+ /* XXX FIXME : bits_wide indicates how wide the transaction
+ ** data is allowed to be...we may need a different virt_irq
+ ** if this one won't work. Another reason to index virtual
+ ** irq's into a table which can manage CPU/IRQ bit seperately.
+ */
+ if (IRQ_OFFSET(virt_irq) > (1 << (bits_wide -1)))
+ {
+ panic("Sorry -- didn't allocate valid IRQ for this device\n");
+ }
+
+ return(IRQ_OFFSET(virt_irq));
+}
+
+
+/* FIXME: SMP, flags, bottom halves, rest */
+void do_irq(struct irqaction *action, int irq, struct pt_regs * regs)
+{
+ int cpu = smp_processor_id();
+
+ irq_enter(cpu, irq);
+
+#ifdef DEBUG_IRQ
+ if (irq != TIMER_IRQ)
+#endif
+ DBG_IRQ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+ if (action->handler == NULL)
+ printk(KERN_ERR "No handler for interrupt %d !\n", irq);
+
+ for(; action && action->handler; action = action->next) {
+ action->handler(irq, action->dev_id, regs);
+ }
+
+ irq_exit(cpu, irq);
+
+ /* don't need to care about unmasking and stuff */
+ do_softirq();
+}
+
+void do_irq_mask(unsigned long mask, struct irq_region *region, struct pt_regs *regs)
+{
+ unsigned long bit;
+ int irq;
+ int cpu = smp_processor_id();
+
+#ifdef DEBUG_IRQ
+ if (mask != (1L << MAX_CPU_IRQ))
+ printk("do_irq_mask %08lx %p %p\n", mask, region, regs);
+#endif
+
+ for(bit=(1L<<MAX_CPU_IRQ), irq = 0; mask && bit; bit>>=1, irq++) {
+ int irq_num;
+ if(!(bit&mask))
+ continue;
+
+ irq_num = region->data.irqbase + irq;
+
+ ++kstat.irqs[cpu][IRQ_FROM_REGION(CPU_IRQ_REGION) | irq];
+ if (IRQ_REGION(irq_num) != CPU_IRQ_REGION)
+ ++kstat.irqs[cpu][irq_num];
+
+ mask_irq(irq_num);
+ do_irq(&region->action[irq], irq_num, regs);
+ unmask_irq(irq_num);
+ }
+}
+
+static inline int alloc_irqregion(void)
+{
+ int irqreg;
+
+ for(irqreg=1; irqreg<=(NR_IRQ_REGS); irqreg++) {
+ if(irq_region[irqreg] == NULL)
+ return irqreg;
+ }
+
+ return 0;
+}
+
+struct irq_region *alloc_irq_region(
+ int count, struct irq_region_ops *ops, unsigned long flags,
+ const char *name, void *dev)
+{
+ struct irq_region *region;
+ int index;
+
+ index = alloc_irqregion();
+
+ if((IRQ_REGION(count-1)))
+ return NULL;
+
+ if (count < IRQ_PER_REGION) {
+ DBG_IRQ("alloc_irq_region() using minimum of %d irq lines for %s (%d)\n",
+ IRQ_PER_REGION, name, count);
+ count = IRQ_PER_REGION;
+ }
+
+ if(flags & IRQ_REG_MASK)
+ if(!(ops->mask_irq && ops->unmask_irq))
+ return NULL;
+
+ if(flags & IRQ_REG_DIS)
+ if(!(ops->disable_irq && ops->enable_irq))
+ return NULL;
+
+ if((irq_region[index]))
+ return NULL;
+
+ region = kmalloc(sizeof *region, GFP_ATOMIC);
+ if(!region)
+ return NULL;
+
+ region->action = kmalloc(sizeof *region->action * count, GFP_ATOMIC);
+ if(!region->action) {
+ kfree(region);
+ return NULL;
+ }
+ memset(region->action, 0, sizeof *region->action * count);
+
+ region->ops = *ops;
+ region->data.irqbase = IRQ_FROM_REGION(index);
+ region->data.flags = flags;
+ region->data.name = name;
+ region->data.dev = dev;
+
+ irq_region[index] = region;
+
+ return irq_region[index];
+}
+
+
+
+/* FIXME: SMP, flags, bottom halves, rest */
+
+int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char * devname,
+ void *dev_id)
+{
+ struct irqaction * action;
+
+#if 0
+ printk(KERN_INFO "request_irq(%d, %p, 0x%lx, %s, %p)\n",irq, handler, irqflags, devname, dev_id);
+#endif
+ if(!handler) {
+ printk(KERN_ERR "request_irq(%d,...): Augh! No handler for irq!\n",
+ irq);
+ return -EINVAL;
+ }
+
+ if ((IRQ_REGION(irq) == 0) || irq_region[IRQ_REGION(irq)] == NULL) {
+ /*
+ ** Bug catcher for drivers which use "char" or u8 for
+ ** the IRQ number. They lose the region number which
+ ** is in pcidev->irq (an int).
+ */
+ printk(KERN_ERR "%p (%s?) called request_irq with an invalid irq %d\n",
+ __builtin_return_address(0), devname, irq);
+ return -EINVAL;
+ }
+
+ action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)];
+
+ if(action->handler) {
+ while(action->next)
+ action = action->next;
+
+ action->next = kmalloc(sizeof *action, GFP_ATOMIC);
+
+ action = action->next;
+ }
+
+ if(!action) {
+ printk(KERN_ERR "request_irq():Augh! No action!\n") ;
+ return -ENOMEM;
+ }
+
+ action->handler = handler;
+ action->flags = irqflags;
+ action->mask = 0;
+ action->name = devname;
+ action->next = NULL;
+ action->dev_id = dev_id;
+
+ enable_irq(irq);
+ return 0;
+}
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+ struct irqaction *action, **p;
+
+ action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)];
+
+ if(action->dev_id == dev_id) {
+ if(action->next == NULL)
+ action->handler = NULL;
+ else
+ memcpy(action, action->next, sizeof *action);
+
+ return;
+ }
+
+ p = &action->next;
+ action = action->next;
+
+ for (; (action = *p) != NULL; p = &action->next) {
+ if (action->dev_id != dev_id)
+ continue;
+
+ /* Found it - now free it */
+ *p = action->next;
+ kfree(action);
+
+ return;
+ }
+
+ printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
+}
+
+unsigned long probe_irq_on (void)
+{
+ return 0;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+ return 0;
+}
+
+
+void __init init_IRQ(void)
+{
+}
+
+void init_irq_proc(void)
+{
+}
diff --git a/arch/parisc/kernel/keyboard.c b/arch/parisc/kernel/keyboard.c
new file mode 100644
index 000000000..05044db49
--- /dev/null
+++ b/arch/parisc/kernel/keyboard.c
@@ -0,0 +1,82 @@
+/*
+ * linux/arch/parisc/kernel/keyboard.c
+ *
+ * Alex deVries <adevries@thepuffingroup.com>
+ * Copyright (1999) The Puffin Group
+ * Mostly rewritten by Philipp Rumpf <prumpf@tux.org>
+ * Copyright 2000 Philipp Rumpf
+ */
+
+#include <linux/keyboard.h>
+#include <asm/keyboard.h>
+
+static int def_setkeycode(unsigned int x, unsigned int y)
+{
+ return 0;
+}
+
+static int def_getkeycode(unsigned int x)
+{
+ return 0;
+}
+
+static int def_translate(unsigned char scancode, unsigned char *keycode,
+ char raw)
+{
+ *keycode = scancode;
+
+ return 1;
+}
+
+static char def_unexpected_up(unsigned char c)
+{
+ return 128;
+}
+
+static void def_leds(unsigned char leds)
+{
+}
+
+static void def_init_hw(void)
+{
+}
+
+static char def_sysrq_xlate[NR_KEYS];
+
+static struct kbd_ops def_kbd_ops = {
+ setkeycode: def_setkeycode,
+ getkeycode: def_getkeycode,
+ translate: def_translate,
+ unexpected_up: def_unexpected_up,
+ leds: def_leds,
+ init_hw: def_init_hw,
+
+ sysrq_key: 0xff,
+ sysrq_xlate: def_sysrq_xlate,
+};
+
+struct kbd_ops *kbd_ops = &def_kbd_ops;
+
+void register_kbd_ops(struct kbd_ops *ops)
+{
+ if(ops->setkeycode)
+ kbd_ops->setkeycode = ops->setkeycode;
+
+ if(ops->getkeycode)
+ kbd_ops->getkeycode = ops->getkeycode;
+
+ if(ops->translate)
+ kbd_ops->translate = ops->translate;
+
+ if(ops->unexpected_up)
+ kbd_ops->unexpected_up = ops->unexpected_up;
+
+ if(ops->leds)
+ kbd_ops->leds = ops->leds;
+
+ if(ops->init_hw)
+ kbd_ops->init_hw = ops->init_hw;
+
+ kbd_ops->sysrq_key = ops->sysrq_key;
+ kbd_ops->sysrq_xlate = ops->sysrq_xlate;
+}
diff --git a/arch/parisc/kernel/lasimap.map b/arch/parisc/kernel/lasimap.map
new file mode 100644
index 000000000..2a9ee223c
--- /dev/null
+++ b/arch/parisc/kernel/lasimap.map
@@ -0,0 +1,322 @@
+# HP 712 kernel keymap. This uses 7 modifier combinations.
+
+keymaps 0-2,4-5,8,12
+# ie, plain, Shift, AltGr, Control, Control+Shift, Alt and Control+Alt
+
+
+# Change the above line into
+# keymaps 0-2,4-6,8,12
+# in case you want the entries
+# altgr control keycode 83 = Boot
+# altgr control keycode 111 = Boot
+# below.
+#
+# In fact AltGr is used very little, and one more keymap can
+# be saved by mapping AltGr to Alt (and adapting a few entries):
+# keycode 100 = Alt
+#
+keycode 1 = F9 F19 Console_21
+ control keycode 1 = F9
+ alt keycode 1 = Console_9
+ control alt keycode 1 = Console_9
+keycode 2 =
+keycode 3 = F5 F15 Console_17
+ control keycode 3 = F5
+ alt keycode 3 = Console_5
+ control alt keycode 3 = Console_5
+keycode 4 = F3 F13 Console_15
+ control keycode 4 = F3
+ alt keycode 4 = Console_3
+ control alt keycode 4 = Console_3
+keycode 5 = F1 F11 Console_13
+ control keycode 5 = F1
+ alt keycode 5 = Console_1
+ control alt keycode 5 = Console_1
+keycode 6 = F2 F12 Console_14
+ control keycode 6 = F2
+ alt keycode 6 = Console_2
+ control alt keycode 6 = Console_2
+keycode 7 = F12 F12 Console_24
+ control keycode 7 = F12
+ alt keycode 7 = Console_12
+ control alt keycode 7 = Console_12
+keycode 8 =
+keycode 9 = F10 F20 Console_22
+ control keycode 9 = F10
+ alt keycode 9 = Console_10
+ control alt keycode 9 = Console_10
+keycode 10 = F8 F18 Console_20
+ control keycode 10 = F8
+ alt keycode 10 = Console_8
+ control alt keycode 10 = Console_8
+keycode 11 = F6 F16 Console_18
+ control keycode 11 = F6
+ alt keycode 11 = Console_6
+ control alt keycode 11 = Console_6
+keycode 12 = F4 F14 Console_16
+ control keycode 12 = F4
+ alt keycode 12 = Console_4
+ control alt keycode 12 = Console_4
+keycode 13 = Tab Tab
+ alt keycode 13 = Meta_Tab
+keycode 14 = grave asciitilde
+ control keycode 14 = nul
+ alt keycode 14 = Meta_grave
+keycode 15 =
+keycode 16 =
+keycode 17 = Alt
+keycode 18 = Shift
+keycode 19 =
+keycode 20 = Control
+keycode 21 = q
+keycode 22 = one exclam exclam
+keycode 23 =
+keycode 24 =
+keycode 25 =
+keycode 26 = z
+keycode 27 = s
+keycode 28 = a
+ altgr keycode 28 = Hex_A
+keycode 29 = w
+keycode 30 = two at at
+keycode 31 =
+keycode 32 =
+keycode 33 = c
+ altgr keycode 46 = Hex_C
+keycode 34 = x
+keycode 35 = d
+ altgr keycode 35 = Hex_D
+keycode 36 = e
+ altgr keycode 36 = Hex_E
+keycode 37 = four dollar
+keycode 38 = three numbersign
+keycode 39 =
+keycode 40 =
+keycode 41 =
+keycode 42 = v
+keycode 43 = f
+ altgr keycode 43 = Hex_F
+keycode 44 = t
+keycode 45 = r
+keycode 46 = five percent
+keycode 47 =
+keycode 48 =
+keycode 49 = n
+keycode 50 = b
+ altgr keycode 50 = Hex_B
+keycode 51 = h
+keycode 52 = g
+keycode 53 = y
+keycode 54 = six asciicircum
+keycode 55 =
+keycode 56 =
+keycode 57 =
+keycode 58 = m
+keycode 59 = j
+keycode 60 = u
+keycode 61 = seven ampersand
+keycode 62 = eight asterisk asterisk
+keycode 63 =
+keycode 64 =
+keycode 65 = comma less
+ alt keycode 65 = Meta_comma
+keycode 66 = k
+keycode 67 = i
+keycode 68 = o
+keycode 69 = zero parenright bracketright
+keycode 70 = nine parenleft bracketleft
+keycode 71 =
+keycode 72 =
+keycode 73 = period greater
+ control keycode 73 = Compose
+ alt keycode 73 = Meta_period
+keycode 74 = slash question
+ control keycode 74 = Delete
+ alt keycode 53 = Meta_slash
+keycode 75 = l
+keycode 76 = semicolon colon
+ alt keycode 39 = Meta_semicolon
+keycode 77 = p
+keycode 78 = minus underscore
+keycode 79 =
+keycode 80 =
+keycode 81 =
+keycode 82 = apostrophe quotedbl
+ control keycode 82 = Control_g
+ alt keycode 40 = Meta_apostrophe
+keycode 83 =
+keycode 84 = bracketleft braceleft
+ control keycode 84 = Escape
+ alt keycode 26 = Meta_bracketleft
+keycode 85 = equal plus
+keycode 86 =
+keycode 87 =
+keycode 88 = Caps_Lock
+keycode 88 =
+keycode 89 =
+keycode 89 =
+keycode 89 =
+keycode 90 = Return
+ alt keycode 90 = Meta_Control_m
+keycode 91 = bracketright braceright asciitilde
+ control keycode 91 = Control_bracketright
+ alt keycode 91 = Meta_bracketright
+keycode 92 =
+keycode 93 = backslash bar
+ control keycode 43 = Control_backslash
+ alt keycode 43 = Meta_backslash
+keycode 94 =
+keycode 95 =
+keycode 96 =
+keycode 97 =
+keycode 98 =
+keycode 99 =
+keycode 100 =
+keycode 101 =
+keycode 102 = BackSpace
+keycode 103 =
+keycode 104 =
+keycode 105 = KP_1
+ alt keycode 105 = Ascii_1
+ altgr keycode 105 = Hex_1
+keycode 106 =
+keycode 107 = KP_4
+ alt keycode 107 = Ascii_4
+ altgr keycode 107 = Hex_4
+keycode 108 = KP_7
+ alt keycode 108 = Ascii_7
+ altgr keycode 108 = Hex_7
+keycode 109 =
+keycode 110 =
+keycode 111 =
+keycode 112 = KP_0
+ alt keycode 82 = Ascii_0
+ altgr keycode 82 = Hex_0
+keycode 113 = KP_Period
+keycode 114 = KP_2
+ alt keycode 114 = Ascii_2
+ altgr keycode 114 = Hex_2
+keycode 115 = KP_5
+ alt keycode 115 = Ascii_5
+ altgr keycode 115 = Hex_5
+keycode 116 = KP_6
+ alt keycode 116 = Ascii_6
+ altgr keycode 116 = Hex_6
+keycode 117 = KP_8
+ alt keycode 117 = Ascii_8
+ altgr keycode 117 = Hex_8
+keycode 118 = Escape
+keycode 119 =
+keycode 120 = F11
+keycode 121 = KP_Add
+keycode 122 = KP_3
+ alt keycode 122 = Ascii_3
+ altgr keycode 122 = Hex_3
+keycode 123 = KP_Subtract
+keycode 124 = KP_Multiply
+keycode 125 = KP_9
+ alt keycode 125 = Ascii_9
+ altgr keycode 125 = Hex_9
+keycode 126 =
+# 131!!
+keycode 127 = F7 F17 Console_19
+ control keycode 127 = F7
+ alt keycode 127 = Console_7
+ control alt keycode 127 = Console_7
+
+string F1 = "\033[[A"
+string F2 = "\033[[B"
+string F3 = "\033[[C"
+string F4 = "\033[[D"
+string F5 = "\033[[E"
+string F6 = "\033[17~"
+string F7 = "\033[18~"
+string F8 = "\033[19~"
+string F9 = "\033[20~"
+string F10 = "\033[21~"
+string F11 = "\033[23~"
+string F12 = "\033[24~"
+string F13 = "\033[25~"
+string F14 = "\033[26~"
+string F15 = "\033[28~"
+string F16 = "\033[29~"
+string F17 = "\033[31~"
+string F18 = "\033[32~"
+string F19 = "\033[33~"
+string F20 = "\033[34~"
+string Find = "\033[1~"
+string Insert = "\033[2~"
+string Remove = "\033[3~"
+string Select = "\033[4~"
+string Prior = "\033[5~"
+string Next = "\033[6~"
+string Macro = "\033[M"
+string Pause = "\033[P"
+compose '`' 'A' to 'À'
+compose '`' 'a' to 'à'
+compose '\'' 'A' to 'Á'
+compose '\'' 'a' to 'á'
+compose '^' 'A' to 'Â'
+compose '^' 'a' to 'â'
+compose '~' 'A' to 'Ã'
+compose '~' 'a' to 'ã'
+compose '"' 'A' to 'Ä'
+compose '"' 'a' to 'ä'
+compose 'O' 'A' to 'Å'
+compose 'o' 'a' to 'å'
+compose '0' 'A' to 'Å'
+compose '0' 'a' to 'å'
+compose 'A' 'A' to 'Å'
+compose 'a' 'a' to 'å'
+compose 'A' 'E' to 'Æ'
+compose 'a' 'e' to 'æ'
+compose ',' 'C' to 'Ç'
+compose ',' 'c' to 'ç'
+compose '`' 'E' to 'È'
+compose '`' 'e' to 'è'
+compose '\'' 'E' to 'É'
+compose '\'' 'e' to 'é'
+compose '^' 'E' to 'Ê'
+compose '^' 'e' to 'ê'
+compose '"' 'E' to 'Ë'
+compose '"' 'e' to 'ë'
+compose '`' 'I' to 'Ì'
+compose '`' 'i' to 'ì'
+compose '\'' 'I' to 'Í'
+compose '\'' 'i' to 'í'
+compose '^' 'I' to 'Î'
+compose '^' 'i' to 'î'
+compose '"' 'I' to 'Ï'
+compose '"' 'i' to 'ï'
+compose '-' 'D' to 'Ð'
+compose '-' 'd' to 'ð'
+compose '~' 'N' to 'Ñ'
+compose '~' 'n' to 'ñ'
+compose '`' 'O' to 'Ò'
+compose '`' 'o' to 'ò'
+compose '\'' 'O' to 'Ó'
+compose '\'' 'o' to 'ó'
+compose '^' 'O' to 'Ô'
+compose '^' 'o' to 'ô'
+compose '~' 'O' to 'Õ'
+compose '~' 'o' to 'õ'
+compose '"' 'O' to 'Ö'
+compose '"' 'o' to 'ö'
+compose '/' 'O' to 'Ø'
+compose '/' 'o' to 'ø'
+compose '`' 'U' to 'Ù'
+compose '`' 'u' to 'ù'
+compose '\'' 'U' to 'Ú'
+compose '\'' 'u' to 'ú'
+compose '^' 'U' to 'Û'
+compose '^' 'u' to 'û'
+compose '"' 'U' to 'Ü'
+compose '"' 'u' to 'ü'
+compose '\'' 'Y' to 'Ý'
+compose '\'' 'y' to 'ý'
+compose 'T' 'H' to 'Þ'
+compose 't' 'h' to 'þ'
+compose 's' 's' to 'ß'
+compose '"' 'y' to 'ÿ'
+compose 's' 'z' to 'ß'
+compose 'i' 'j' to 'ÿ'
diff --git a/arch/parisc/kernel/lba_pci.c b/arch/parisc/kernel/lba_pci.c
new file mode 100644
index 000000000..6096d0153
--- /dev/null
+++ b/arch/parisc/kernel/lba_pci.c
@@ -0,0 +1,1346 @@
+/*
+** PCI Lower Bus Adapter (LBA) manager
+**
+** (c) Copyright 1999,2000 Grant Grundler
+** (c) Copyright 1999,2000 Hewlett-Packard Company
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+**
+** This module primarily provides access to PCI bus (config/IOport
+** spaces) on platforms with an SBA/LBA chipset. A/B/C/J/L/N-class
+** with 4 digit model numbers - eg C3000 (and A400...sigh).
+**
+** LBA driver isn't as simple as the Dino driver because:
+** (a) this chip has substantial bug fixes between revisions
+** (Only one Dino bug has a software workaround :^( )
+** (b) has more options which we don't (yet) support (DMA hints, OLARD)
+** (c) IRQ support lives in the I/O SAPIC driver (not with PCI driver)
+** (d) play nicely with both PAT and "Legacy" PA-RISC firmware (PDC).
+** (dino only deals with "Legacy" PDC)
+**
+** LBA driver passes the I/O SAPIC HPA to the I/O SAPIC driver.
+** (I/O SAPIC is integratd in the LBA chip).
+**
+** FIXME: Add support to SBA and LBA drivers for DMA hint sets
+** FIXME: Add support for PCI card hot-plug (OLARD).
+*/
+
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/init.h> /* for __init and __devinit */
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/smp_lock.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h> /* for struct irq_region support */
+#include <asm/pdc.h>
+#include <asm/pdcpat.h>
+#include <asm/page.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+#include <asm/hardware.h> /* for register_driver() stuff */
+#include <asm/iosapic.h> /* for iosapic_register() */
+#include <asm/gsc.h> /* gsc_read/write stuff */
+
+
+#ifndef TRUE
+#define TRUE (1 == 1)
+#define FALSE (1 == 0)
+#endif
+
+#undef DEBUG_LBA /* general stuff */
+#undef DEBUG_LBA_PORT /* debug I/O Port access */
+#undef DEBUG_LBA_CFG /* debug Config Space Access (ie PCI Bus walk) */
+#undef DEBUG_LBA_PAT /* debug PCI Resource Mgt code - PDC PAT only */
+
+#ifdef DEBUG_LBA
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+#ifdef DEBUG_LBA_PORT
+#define DBG_PORT(x...) printk(x)
+#else
+#define DBG_PORT(x...)
+#endif
+
+#ifdef DEBUG_LBA_CFG
+#define DBG_CFG(x...) printk(x)
+#else
+#define DBG_CFG(x...)
+#endif
+
+#ifdef DEBUG_LBA_PAT
+#define DBG_PAT(x...) printk(x)
+#else
+#define DBG_PAT(x...)
+#endif
+
+/*
+** Config accessor functions only pass in the 8-bit bus number and not
+** the 8-bit "PCI Segment" number. Each LBA will be assigned a PCI bus
+** number based on what firmware wrote into the scratch register.
+**
+** The "secondary" bus number is set to this before calling
+** pci_register_ops(). If any PPB's are present, the scan will
+** discover them and update the "secondary" and "subordinate"
+** fields in the pci_bus structure.
+**
+** Changes in the configuration *may* result in a different
+** bus number for each LBA depending on what firmware does.
+*/
+
+#define MODULE_NAME "lba"
+
+static int lba_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+
+static struct pa_iodc_driver lba_drivers_for[]= {
+
+ {HPHW_BRIDGE, 0x782, 0x0, 0xa, 0,0,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "tbd", (void *) lba_driver_callback},
+
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL}
+};
+
+
+#define LBA_FUNC_ID 0x0000 /* function id */
+#define LBA_FCLASS 0x0008 /* function class, bist, header, rev... */
+#define LBA_CAPABLE 0x0030 /* capabilities register */
+
+#define LBA_PCI_CFG_ADDR 0x0040 /* poke CFG address here */
+#define LBA_PCI_CFG_DATA 0x0048 /* read or write data here */
+
+#define LBA_PMC_MTLT 0x0050 /* Firmware sets this - read only. */
+#define LBA_FW_SCRATCH 0x0058 /* Firmware writes the PCI bus number here. */
+#define LBA_ERROR_ADDR 0x0070 /* On error, address gets logged here */
+
+#define LBA_ARB_MASK 0x0080 /* bit 0 enable arbitration. PAT/PDC enables */
+#define LBA_ARB_PRI 0x0088 /* firmware sets this. */
+#define LBA_ARB_MODE 0x0090 /* firmware sets this. */
+#define LBA_ARB_MTLT 0x0098 /* firmware sets this. */
+
+#define LBA_MOD_ID 0x0100 /* Module ID. PDC_PAT_CELL reports 4 */
+
+#define LBA_STAT_CTL 0x0108 /* Status & Control */
+#define HF_ENABLE 0x40 /* enable HF mode (default is -1 mode) */
+
+#define LBA_LMMIO_BASE 0x0200 /* < 4GB I/O address range */
+#define LBA_LMMIO_MASK 0x0208
+
+#define LBA_GMMIO_BASE 0x0210 /* > 4GB I/O address range */
+#define LBA_GMMIO_MASK 0x0218
+
+#define LBA_WLMMIO_BASE 0x0220 /* All < 4GB ranges under the same *SBA* */
+#define LBA_WLMMIO_MASK 0x0228
+
+#define LBA_WGMMIO_BASE 0x0230 /* All > 4GB ranges under the same *SBA* */
+#define LBA_WGMMIO_MASK 0x0238
+
+#define LBA_IOS_BASE 0x0240 /* I/O port space for this LBA */
+#define LBA_IOS_MASK 0x0248
+
+#define LBA_ELMMIO_BASE 0x0250 /* Extra LMMIO range */
+#define LBA_ELMMIO_MASK 0x0258
+
+#define LBA_EIOS_BASE 0x0260 /* Extra I/O port space */
+#define LBA_EIOS_MASK 0x0268
+
+#define LBA_DMA_CTL 0x0278 /* firmware sets this */
+
+/* RESET: ignore DMA stuff until we can measure performance */
+#define LBA_IBASE 0x0300 /* DMA support */
+#define LBA_IMASK 0x0308
+#define LBA_HINT_CFG 0x0310
+#define LBA_HINT_BASE 0x0380 /* 14 registers at every 8 bytes. */
+
+/* ERROR regs are needed for config cycle kluges */
+#define LBA_ERROR_CONFIG 0x0680
+#define LBA_ERROR_STATUS 0x0688
+
+#define LBA_IOSAPIC_BASE 0x800 /* Offset of IRQ logic */
+
+/* non-postable I/O port space, densely packed */
+#ifdef __LP64__
+#define LBA_ASTRO_PORT_BASE (0xfffffffffee00000UL)
+#else
+#define LBA_ASTRO_PORT_BASE (0xfee00000UL)
+#endif
+
+
+/*
+** lba_device: Per instance Elroy data structure
+*/
+struct lba_device {
+ struct pci_hba_data hba;
+
+ spinlock_t lba_lock;
+ void *iosapic_obj;
+
+#ifdef __LP64__
+ unsigned long lmmio_base; /* PA_VIEW - fixup MEM addresses */
+ unsigned long gmmio_base; /* PA_VIEW - Not used (yet) */
+ unsigned long iop_base; /* PA_VIEW - for IO port accessor funcs */
+#endif
+
+ int flags; /* state/functionality enabled */
+ int hw_rev; /* HW revision of chip */
+};
+
+
+static u32 lba_t32;
+
+/*
+** lba "flags"
+*/
+#define LBA_FLAG_NO_DMA_DURING_CFG 0x01
+#define LBA_FLAG_SKIP_PROBE 0x10
+
+/* Tape Release 4 == hw_rev 5 */
+#define LBA_TR4PLUS(d) ((d)->hw_rev > 0x4)
+#define LBA_DMA_DURING_CFG_DISABLED(d) ((d)->flags & LBA_FLAG_NO_DMA_DURING_CFG)
+#define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE)
+
+
+/* Looks nice and keeps the compiler happy */
+#define LBA_DEV(d) ((struct lba_device *) (d))
+
+
+/*
+** Only allow 8 subsidiary busses per LBA
+** Problem is the PCI bus numbering is globally shared.
+*/
+#define LBA_MAX_NUM_BUSES 8
+
+/************************************
+ * LBA register read and write support
+ *
+ * BE WARNED: register writes are posted.
+ * (ie follow writes which must reach HW with a read)
+ */
+#define READ_U8(addr) gsc_readb(addr)
+#define READ_U16(addr) gsc_readw((u16 *) (addr))
+#define READ_U32(addr) gsc_readl((u32 *) (addr))
+#define WRITE_U8(value, addr) gsc_writeb(value, addr)
+#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr))
+#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
+
+#define READ_REG8(addr) gsc_readb(addr)
+#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
+#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
+#define WRITE_REG8(value, addr) gsc_writeb(value, addr)
+#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
+#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
+
+
+#define LBA_CFG_TOK(bus,dfn) ((u32) ((bus)<<16 | (dfn)<<8))
+#define LBA_CFG_BUS(tok) ((u8) ((tok)>>16))
+#define LBA_CFG_DEV(tok) ((u8) ((tok)>>11) & 0x1f)
+#define LBA_CFG_FUNC(tok) ((u8) ((tok)>>8 ) & 0x7)
+
+
+#ifdef DEBUG_LBA
+/* Extract LBA (Rope) number from HPA */
+#define LBA_NUM(x) ((((uintptr_t) x) >> 13) & 0xf)
+#endif /* DEBUG_LBA */
+
+#ifdef __LP64__
+/* PDC_PAT */
+static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
+#endif
+
+/*
+** One time initialization to let the world know the LBA was found.
+** This is the only routine which is NOT static.
+** Must be called exactly once before pci_init().
+*/
+void __init lba_init(void)
+{
+ register_driver(lba_drivers_for);
+}
+
+
+static void
+lba_dump_res(struct resource *r, int d)
+{
+ int i;
+
+ if (NULL == r)
+ return;
+
+ printk("(%p)", r->parent);
+ for (i = d; i ; --i) printk(" ");
+ printk("%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags);
+ lba_dump_res(r->child, d+2);
+ lba_dump_res(r->sibling, d);
+}
+
+
+/*
+** LBA rev 2.0, 2.1, 2.2, and 3.0 bus walks require a complex
+** workaround for cfg cycles:
+** -- preserve LBA state
+** -- LBA_FLAG_NO_DMA_DURING_CFG workaround
+** -- turn on smart mode
+** -- probe with config writes before doing config reads
+** -- check ERROR_STATUS
+** -- clear ERROR_STATUS
+** -- restore LBA state
+**
+** The workaround is only used for device discovery.
+*/
+
+static int
+lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
+{
+ u8 first_bus = d->hba.hba_bus->secondary;
+ u8 last_sub_bus = d->hba.hba_bus->subordinate;
+#if 0
+/* FIXME - see below in this function */
+ u8 dev = PCI_SLOT(dfn);
+ u8 func = PCI_FUNC(dfn);
+#endif
+
+ ASSERT(bus >= first_bus);
+ ASSERT(bus <= last_sub_bus);
+ ASSERT((bus - first_bus) < LBA_MAX_NUM_BUSES);
+
+ if ((bus < first_bus) ||
+ (bus > last_sub_bus) ||
+ ((bus - first_bus) >= LBA_MAX_NUM_BUSES))
+ {
+ /* devices that fall into any of these cases won't get claimed */
+ return(FALSE);
+ }
+
+#if 0
+/*
+** FIXME: Need to implement code to fill the devices bitmap based
+** on contents of the local pci_bus tree "data base".
+** pci_register_ops() walks the bus for us and builds the tree.
+** For now, always do the config cycle.
+*/
+ bus -= first_bus;
+
+ return (((d->devices[bus][dev]) >> func) & 0x1);
+#else
+ return TRUE;
+#endif
+}
+
+
+
+#define LBA_CFG_SETUP(d, tok) { \
+ /* Save contents of error config register. */ \
+ error_config = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG); \
+\
+ /* Save contents of status control register. */ \
+ status_control = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); \
+\
+ /* For LBA rev 2.0, 2.1, 2.2, and 3.0, we must disable DMA \
+ ** arbitration for full bus walks. \
+ */ \
+ if (LBA_DMA_DURING_CFG_DISABLED(d)) { \
+ /* Save contents of arb mask register. */ \
+ arb_mask = READ_REG32(d->hba.base_addr + LBA_ARB_MASK); \
+\
+ /* \
+ * Turn off all device arbitration bits (i.e. everything \
+ * except arbitration enable bit). \
+ */ \
+ WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK); \
+ } \
+\
+ /* \
+ * Set the smart mode bit so that master aborts don't cause \
+ * LBA to go into PCI fatal mode (required). \
+ */ \
+ WRITE_REG32(error_config | 0x20, d->hba.base_addr + LBA_ERROR_CONFIG); \
+}
+
+
+#define LBA_CFG_PROBE(d, tok) { \
+ /* \
+ * Setup Vendor ID write and read back the address register \
+ * to make sure that LBA is the bus master. \
+ */ \
+ WRITE_REG32(tok | PCI_VENDOR_ID, (d)->hba.base_addr + LBA_PCI_CFG_ADDR);\
+ /* \
+ * Read address register to ensure that LBA is the bus master, \
+ * which implies that DMA traffic has stopped when DMA arb is off. \
+ */ \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ /* \
+ * Generate a cfg write cycle (will have no affect on \
+ * Vendor ID register since read-only). \
+ */ \
+ WRITE_REG32(~0, (d)->hba.base_addr + LBA_PCI_CFG_DATA); \
+ /* \
+ * Make sure write has completed before proceeding further, \
+ * i.e. before setting clear enable. \
+ */ \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+}
+
+
+/*
+ * HPREVISIT:
+ * -- Can't tell if config cycle got the error.
+ *
+ * OV bit is broken until rev 4.0, so can't use OV bit and
+ * LBA_ERROR_LOG_ADDR to tell if error belongs to config cycle.
+ *
+ * As of rev 4.0, no longer need the error check.
+ *
+ * -- Even if we could tell, we still want to return -1
+ * for **ANY** error (not just master abort).
+ *
+ * -- Only clear non-fatal errors (we don't want to bring
+ * LBA out of pci-fatal mode).
+ *
+ * Actually, there is still a race in which
+ * we could be clearing a fatal error. We will
+ * live with this during our real mode bus walk
+ * until rev 4.0 (no driver activity during
+ * real mode bus walk). The real mode bus walk
+ * has race conditions concerning the use of
+ * smart mode as well.
+ */
+
+#define LBA_MASTER_ABORT_ERROR 0xc
+#define LBA_FATAL_ERROR 0x10
+
+#define LBA_CFG_MASTER_ABORT_CHECK(d, base, tok, error) { \
+ u32 error_status = 0; \
+ /* \
+ * Set clear enable (CE) bit. Unset by HW when new \
+ * errors are logged -- LBA HW ERS section 14.3.3). \
+ */ \
+ WRITE_REG32(status_control | 0x20, base + LBA_STAT_CTL); \
+ error_status = READ_REG32(base + LBA_ERROR_STATUS); \
+ if ((error_status & 0x1f) != 0) { \
+ /* \
+ * Fail the config read request. \
+ */ \
+ error = 1; \
+ if ((error_status & LBA_FATAL_ERROR) == 0) { \
+ /* \
+ * Clear error status (if fatal bit not set) by setting \
+ * clear error log bit (CL). \
+ */ \
+ WRITE_REG32(status_control | 0x10, base + LBA_STAT_CTL); \
+ } \
+ } \
+}
+
+#define LBA_CFG_TR4_ADDR_SETUP(d, addr) \
+ WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR)
+
+#define LBA_CFG_ADDR_SETUP(d, addr) { \
+ WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ /* \
+ * HPREVISIT: \
+ * -- Potentially could skip this once DMA bug fixed. \
+ * \
+ * Read address register to ensure that LBA is the bus master, \
+ * which implies that DMA traffic has stopped when DMA arb is off. \
+ */ \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+}
+
+
+#define LBA_CFG_RESTORE(d, base) { \
+ /* \
+ * Restore status control register (turn off clear enable). \
+ */ \
+ WRITE_REG32(status_control, base + LBA_STAT_CTL); \
+ /* \
+ * Restore error config register (turn off smart mode). \
+ */ \
+ WRITE_REG32(error_config, base + LBA_ERROR_CONFIG); \
+ if (LBA_DMA_DURING_CFG_DISABLED(d)) { \
+ /* \
+ * Restore arb mask register (reenables DMA arbitration). \
+ */ \
+ WRITE_REG32(arb_mask, base + LBA_ARB_MASK); \
+ } \
+}
+
+
+
+static unsigned int
+lba_rd_cfg( struct lba_device *d, u32 tok, u8 reg, u32 size)
+{
+ u32 data = ~0;
+ int error = 0;
+ u32 arb_mask = 0; /* used by LBA_CFG_SETUP/RESTORE */
+ u32 error_config = 0; /* used by LBA_CFG_SETUP/RESTORE */
+ u32 status_control = 0; /* used by LBA_CFG_SETUP/RESTORE */
+
+ ASSERT((size == sizeof(u8)) ||
+ (size == sizeof(u16)) ||
+ (size == sizeof(u32)));
+
+ if ((size != sizeof(u8)) &&
+ (size != sizeof(u16)) &&
+ (size != sizeof(u32))) {
+ return(data);
+ }
+
+ LBA_CFG_SETUP(d, tok);
+ LBA_CFG_PROBE(d, tok);
+ LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
+ if (!error) {
+ LBA_CFG_ADDR_SETUP(d, tok | reg);
+ switch (size) {
+ case sizeof(u8):
+ data = (u32) READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 3));
+ break;
+ case sizeof(u16):
+ data = (u32) READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 2));
+ break;
+ case sizeof(u32):
+ data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA);
+ break;
+ default:
+ break; /* leave data as -1 */
+ }
+ }
+ LBA_CFG_RESTORE(d, d->hba.base_addr);
+ return(data);
+}
+
+
+
+#define LBA_CFG_RD(size, mask) \
+static int lba_cfg_read##size (struct pci_dev *dev, int pos, u##size *data) \
+{ \
+ struct lba_device *d = LBA_DEV(dev->bus->sysdata); \
+ u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \
+ u32 tok = LBA_CFG_TOK(local_bus,dev->devfn); \
+ \
+ if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \
+ /* original - Generate config cycle on broken elroy \
+ with risk we will miss PCI bus errors. */ \
+ *data = (u##size) lba_rd_cfg(d, tok, pos, sizeof(u##size)); \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, *data); \
+ return(*data == (u##size) -1); \
+ } \
+ \
+ if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) \
+ { \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos, *data); \
+ /* either don't want to look or know device isn't present. */ \
+ *data = (u##size) -1; \
+ return(0); \
+ } \
+ \
+ /* Basic Algorithm \
+ ** Should only get here on fully working LBA rev. \
+ ** This is how simple the code should have been. \
+ */ \
+ LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \
+ *data = READ_REG##size(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask));\
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, *data);\
+ return(*data == (u##size) -1); \
+}
+
+LBA_CFG_RD( 8, 3)
+LBA_CFG_RD(16, 2)
+LBA_CFG_RD(32, 0)
+
+
+
+static void
+lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
+{
+ int error = 0;
+ u32 arb_mask = 0;
+ u32 error_config = 0;
+ u32 status_control = 0;
+
+ ASSERT((size == sizeof(u8)) ||
+ (size == sizeof(u16)) ||
+ (size == sizeof(u32)));
+
+ if ((size != sizeof(u8)) &&
+ (size != sizeof(u16)) &&
+ (size != sizeof(u32))) {
+ return;
+ }
+
+ LBA_CFG_SETUP(d, tok);
+ LBA_CFG_ADDR_SETUP(d, tok | reg);
+ switch (size) {
+ case sizeof(u8):
+ WRITE_REG8((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA + (reg&3));
+ break;
+ case sizeof(u16):
+ WRITE_REG16((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA +(reg&2));
+ break;
+ case sizeof(u32):
+ WRITE_REG32(data, d->hba.base_addr + LBA_PCI_CFG_DATA);
+ break;
+ default:
+ break;
+ }
+ LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
+ LBA_CFG_RESTORE(d, d->hba.base_addr);
+}
+
+
+/*
+ * LBA 4.0 config write code implements non-postable semantics
+ * by doing a read of CONFIG ADDR after the write.
+ */
+
+#define LBA_CFG_WR(size, mask) \
+static int lba_cfg_write##size (struct pci_dev *dev, int pos, u##size data) \
+{ \
+ struct lba_device *d = LBA_DEV(dev->bus->sysdata); \
+ u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \
+ u32 tok = LBA_CFG_TOK(local_bus,dev->devfn); \
+ \
+ ASSERT((tok & 0xff) == 0); \
+ ASSERT(pos < 0x100); \
+ \
+ if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \
+ /* Original Workaround */ \
+ lba_wr_cfg(d, tok, pos, (u32) data, sizeof(u##size)); \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, data); \
+ return 0; \
+ } \
+ \
+ if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) { \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (b)\n", __FUNCTION__, dev->slot_name, pos, data); \
+ return 1; /* New Workaround */ \
+ } \
+ \
+ DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, data); \
+ /* Basic Algorithm */ \
+ LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \
+ WRITE_REG##size(data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask)); \
+ lba_t32 = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ return 0; \
+}
+
+
+LBA_CFG_WR( 8, 3)
+LBA_CFG_WR(16, 2)
+LBA_CFG_WR(32, 0)
+
+static struct pci_ops lba_cfg_ops = {
+ lba_cfg_read8, lba_cfg_read16, lba_cfg_read32,
+ lba_cfg_write8, lba_cfg_write16, lba_cfg_write32
+
+};
+
+
+
+static void
+lba_bios_init(void)
+{
+ DBG(KERN_DEBUG MODULE_NAME ": lba_bios_init\n");
+}
+
+
+#ifdef __LP64__
+
+/*
+** Determine if a device is already configured.
+** If so, reserve it resources.
+**
+** Read PCI cfg command register and see if I/O or MMIO is enabled.
+** PAT has to enable the devices it's using.
+**
+** Note: resources are fixed up before we try to claim them.
+*/
+static void
+lba_claim_dev_resources(struct pci_dev *dev)
+{
+ u16 cmd;
+ int i, srch_flags;
+
+ (void) lba_cfg_read16(dev, PCI_COMMAND, &cmd);
+
+ srch_flags = (cmd & PCI_COMMAND_IO) ? IORESOURCE_IO : 0;
+ if (cmd & PCI_COMMAND_MEMORY)
+ srch_flags |= IORESOURCE_MEM;
+
+ if (!srch_flags)
+ return;
+
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ if (dev->resource[i].flags & srch_flags) {
+ pci_claim_resource(dev, i);
+ DBG(" claimed %s %d [%lx,%lx]/%x\n",
+ dev->slot_name, i,
+ dev->resource[i].start,
+ dev->resource[i].end,
+ (int) dev->resource[i].flags
+ );
+ }
+ }
+}
+#endif
+
+
+/*
+** The algorithm is generic code.
+** But it needs to access local data structures to get the IRQ base.
+** Could make this a "pci_fixup_irq(bus, region)" but not sure
+** it's worth it.
+**
+** Called by do_pci_scan_bus() immediately after each PCI bus is walked.
+** Resources aren't allocated until recursive buswalk below HBA is completed.
+*/
+static void
+lba_fixup_bus(struct pci_bus *bus)
+{
+ struct list_head *ln;
+ struct pci_dev *dev;
+ u16 fbb_enable = PCI_STATUS_FAST_BACK;
+ u16 status;
+ struct lba_device *ldev = LBA_DEV(bus->sysdata);
+#ifdef __LP64__
+ int i;
+#endif
+ DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n",
+ bus, bus->secondary, bus->sysdata);
+
+ /*
+ ** Properly Setup MMIO resources for this bus.
+ ** pci_alloc_primary_bus() mangles this.
+ */
+ if (NULL == bus->self) {
+ int err;
+
+ DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
+ ldev->hba.io_space.name,
+ ldev->hba.io_space.start,
+ ldev->hba.io_space.end,
+ (int) ldev->hba.io_space.flags);
+ DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
+ ldev->hba.mem_space.name,
+ ldev->hba.mem_space.start,
+ ldev->hba.mem_space.end,
+ (int) ldev->hba.mem_space.flags);
+
+ err = request_resource(&ioport_resource, &(ldev->hba.io_space));
+ if (err < 0) {
+ BUG();
+ lba_dump_res(&ioport_resource, 2);
+ }
+ err = request_resource(&iomem_resource, &(ldev->hba.mem_space));
+ if (err < 0) {
+ BUG();
+ lba_dump_res(&iomem_resource, 2);
+ }
+
+ bus->resource[0] = &(ldev->hba.io_space);
+ bus->resource[1] = &(ldev->hba.mem_space);
+ }
+
+ list_for_each(ln, &bus->devices) {
+
+ dev = pci_dev_b(ln);
+
+#ifdef __LP64__
+ /*
+ ** 0-5 are the "standard PCI regions"
+ ** (see comments near PCI_NUM_RESOURCES in include/linux/pci.h)
+ */
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *res = &(dev->resource[i]);
+
+ if (res->flags & IORESOURCE_MEM) {
+ /* "Globalize" PCI address */
+ res->start |= ldev->lmmio_base;
+ res->end |= ldev->lmmio_base;
+ }
+ }
+#endif
+
+ /*
+ ** If one device does not support FBB transfers,
+ ** No one on the bus can be allowed to use them.
+ */
+ (void) lba_cfg_read16(dev, PCI_STATUS, &status);
+ fbb_enable &= status;
+
+#ifdef __LP64__
+ if (pdc_pat) {
+ /* Claim resources for PDC's devices */
+ lba_claim_dev_resources(dev);
+ }
+#endif /* __LP64__ */
+
+ /*
+ ** P2PB's have no IRQs. ignore them.
+ */
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ continue;
+
+ /* Adjust INTERRUPT_LINE for this dev */
+ iosapic_fixup_irq(LBA_DEV(bus->sysdata)->iosapic_obj, dev);
+ }
+
+#if 0
+/* FIXME/REVISIT - finish figuring out to set FBB on both
+** pbus_set_ranges() clobbers PCI_BRIDGE_CONTROL.
+** Can't fixup here anyway....garr...
+*/
+ if (fbb_enable) {
+ if (bus->self) {
+ u8 control;
+ /* enable on PPB */
+ (void) lba_cfg_read8(bus->self, PCI_BRIDGE_CONTROL, &control);
+ (void) lba_cfg_write8(bus->self, PCI_BRIDGE_CONTROL, control | PCI_STATUS_FAST_BACK);
+
+ } else {
+ /* enable on LBA */
+ }
+ fbb_enable = PCI_COMMAND_FAST_BACK;
+ }
+
+ /* Lastly enable FBB/PERR/SERR on all devices too */
+ list_for_each(ln, &bus->devices) {
+ (void) lba_cfg_read16(dev, PCI_COMMAND, &status);
+ status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable;
+ (void) lba_cfg_write16(dev, PCI_COMMAND, status);
+ }
+#endif
+}
+
+
+struct pci_bios_ops lba_bios_ops = {
+ lba_bios_init,
+ lba_fixup_bus /* void lba_fixup_bus(struct pci_bus *bus) */
+};
+
+
+
+
+/*******************************************************
+**
+** LBA Sprockets "I/O Port" Space Accessor Functions
+**
+** This set of accessor functions is intended for use with
+** "legacy firmware" (ie Sprockets on Allegro/Forte boxes).
+**
+** Many PCI devices don't require use of I/O port space (eg Tulip,
+** NCR720) since they export the same registers to both MMIO and
+** I/O port space. In general I/O port space is slower than
+** MMIO since drivers are designed so PIO writes can be posted.
+**
+********************************************************/
+
+#define LBA_PORT_IN(size, mask) \
+static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \
+{ \
+ u##size t; \
+ ASSERT(bus != NULL); \
+ DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, bus, addr); \
+ t = READ_REG##size(LBA_ASTRO_PORT_BASE + addr); \
+ DBG_PORT(" 0x%x\n", t); \
+ return (t); \
+}
+
+LBA_PORT_IN( 8, 3)
+LBA_PORT_IN(16, 2)
+LBA_PORT_IN(32, 0)
+
+
+
+/*
+** BUG X4107: Ordering broken - DMA RD return can bypass PIO WR
+**
+** Fixed in Elroy 2.2. The READ_U32(..., LBA_FUNC_ID) below is
+** guarantee non-postable completion semantics - not avoid X4107.
+** The READ_U32 only guarantees the write data gets to elroy but
+** out to the PCI bus. We can't read stuff from I/O port space
+** since we don't know what has side-effects. Attempting to read
+** from configuration space would be suicidal given the number of
+** bugs in that elroy functionality.
+**
+** Description:
+** DMA read results can improperly pass PIO writes (X4107). The
+** result of this bug is that if a processor modifies a location in
+** memory after having issued PIO writes, the PIO writes are not
+** guaranteed to be completed before a PCI device is allowed to see
+** the modified data in a DMA read.
+**
+** Note that IKE bug X3719 in TR1 IKEs will result in the same
+** symptom.
+**
+** Workaround:
+** The workaround for this bug is to always follow a PIO write with
+** a PIO read to the same bus before starting DMA on that PCI bus.
+**
+*/
+#define LBA_PORT_OUT(size, mask) \
+static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \
+{ \
+ ASSERT(bus != NULL); \
+ DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \
+ WRITE_REG##size(val, LBA_ASTRO_PORT_BASE + addr); \
+ if (LBA_DEV(d)->hw_rev < 3) \
+ lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \
+}
+
+LBA_PORT_OUT( 8, 3)
+LBA_PORT_OUT(16, 2)
+LBA_PORT_OUT(32, 0)
+
+
+static struct pci_port_ops lba_astro_port_ops = {
+ lba_astro_in8, lba_astro_in16, lba_astro_in32,
+ lba_astro_out8, lba_astro_out16, lba_astro_out32
+};
+
+
+#ifdef __LP64__
+
+#define PIOP_TO_GMMIO(lba, addr) \
+ ((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3))
+
+/*******************************************************
+**
+** LBA PAT "I/O Port" Space Accessor Functions
+**
+** This set of accessor functions is intended for use with
+** "PAT PDC" firmware (ie Prelude/Rhapsody/Piranha boxes).
+**
+** This uses the PIOP space located in the first 64MB of GMMIO.
+** Each rope gets a full 64*KB* (ie 4 bytes per page) this way.
+** bits 1:0 stay the same. bits 15:2 become 25:12.
+** Then add the base and we can generate an I/O Port cycle.
+********************************************************/
+#undef LBA_PORT_IN
+#define LBA_PORT_IN(size, mask) \
+static u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \
+{ \
+ u##size t; \
+ ASSERT(bus != NULL); \
+ DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \
+ t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \
+ DBG_PORT(" 0x%x\n", t); \
+ return (t); \
+}
+
+LBA_PORT_IN( 8, 3)
+LBA_PORT_IN(16, 2)
+LBA_PORT_IN(32, 0)
+
+
+#undef LBA_PORT_OUT
+#define LBA_PORT_OUT(size, mask) \
+static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \
+{ \
+ void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \
+ ASSERT(bus != NULL); \
+ DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \
+ WRITE_REG##size(val, where); \
+ /* flush the I/O down to the elroy at least */ \
+ lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \
+}
+
+LBA_PORT_OUT( 8, 3)
+LBA_PORT_OUT(16, 2)
+LBA_PORT_OUT(32, 0)
+
+
+static struct pci_port_ops lba_pat_port_ops = {
+ lba_pat_in8, lba_pat_in16, lba_pat_in32,
+ lba_pat_out8, lba_pat_out16, lba_pat_out32
+};
+
+
+
+/*
+** make range information from PDC available to PCI subsystem.
+** We make the PDC call here in order to get the PCI bus range
+** numbers. The rest will get forwarded in pcibios_fixup_bus().
+** We don't have a struct pci_bus assigned to us yet.
+*/
+static void
+lba_pat_resources( struct hp_device *d, struct lba_device *lba_dev)
+{
+ pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */
+#ifdef DONT_NEED_THIS_FOR_ASTRO
+ pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */
+ long io_count;
+#endif
+ long status; /* PDC return status */
+ long pa_count;
+ int i;
+
+ /* return cell module (IO view) */
+ status = pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index,
+ PA_VIEW, & pa_pdc_cell);
+ pa_count = pa_pdc_cell.mod[1];
+
+#ifdef DONT_NEED_THIS_FOR_ASTRO
+ status |= pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index,
+ IO_VIEW, & io_pdc_cell);
+ io_count = io_pdc_cell.mod[1];
+#endif
+
+ /* We've already done this once for device discovery...*/
+ if (status != PDC_RET_OK) {
+ panic("pdc_pat_cell_module() call failed for LBA!\n");
+ }
+
+ if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) {
+ panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n");
+ }
+
+ /*
+ ** Inspect the resources PAT tells us about
+ */
+ for (i = 0; i < pa_count; i++) {
+ struct {
+ unsigned long type;
+ unsigned long start;
+ unsigned long end; /* aka finish */
+ } *p;
+ struct resource *r;
+
+ p = (void *) &(pa_pdc_cell.mod[2+i*3]);
+
+ /* Convert the PAT range data to PCI "struct resource" */
+ switch(p->type & 0xff) {
+ case PAT_PBNUM:
+ lba_dev->hba.bus_num.start = p->start;
+ lba_dev->hba.bus_num.end = p->end;
+ break;
+ case PAT_LMMIO:
+ /* used to fix up pre-initialized MEM BARs */
+ lba_dev->lmmio_base = p->start;
+
+ r = &(lba_dev->hba.mem_space);
+ r->name = "LBA LMMIO";
+ r->start = p->start;
+ r->end = p->end;
+ r->flags = IORESOURCE_MEM;
+ r->parent = r->sibling = r->child = NULL;
+ break;
+ case PAT_GMMIO:
+ printk(KERN_WARNING MODULE_NAME
+ " range[%d] : ignoring GMMIO (0x%lx)\n",
+ i, p->start);
+ lba_dev->gmmio_base = p->start;
+ break;
+ case PAT_NPIOP:
+ printk(KERN_WARNING MODULE_NAME
+ " range[%d] : ignoring NPIOP (0x%lx)\n",
+ i, p->start);
+ break;
+ case PAT_PIOP:
+ /*
+ ** Postable I/O port space is per PCI host adapter.
+ */
+
+ /* save base of 64MB PIOP region */
+ lba_dev->iop_base = p->start;
+
+ r = &(lba_dev->hba.io_space);
+ r->name = "LBA I/O Port";
+ r->start = lba_dev->hba.hba_num << 16;
+ r->end = r->start + 0xffffUL;
+ r->flags = IORESOURCE_IO;
+ r->parent = r->sibling = r->child = NULL;
+ break;
+ default:
+ printk(KERN_WARNING MODULE_NAME
+ " range[%d] : unknown pat range type (0x%lx)\n",
+ i, p->type & 0xff);
+ break;
+ }
+ }
+}
+#endif /* __LP64__ */
+
+
+static void
+lba_legacy_resources( struct hp_device *d, struct lba_device *lba_dev)
+{
+ int lba_num;
+ struct resource *r;
+#ifdef __LP64__
+ /*
+ ** Used to sign extend instead BAR values are only 32-bit.
+ ** 64-bit BARs have the upper 32-bit's zero'd by firmware.
+ ** "Sprockets" PDC initializes for 32-bit OS.
+ */
+ lba_dev->lmmio_base = 0xffffffff00000000UL;
+#endif
+
+ /*
+ ** With "legacy" firmware, the lowest byte of FW_SCRATCH
+ ** represents bus->secondary and the second byte represents
+ ** bus->subsidiary (i.e. highest PPB programmed by firmware).
+ ** PCI bus walk *should* end up with the same result.
+ ** FIXME: But we don't have sanity checks in PCI or LBA.
+ */
+ lba_num = READ_REG32(d->hpa + LBA_FW_SCRATCH);
+ r = &(lba_dev->hba.bus_num);
+ r->name = "LBA PCI Busses";
+ r->start = lba_num & 0xff;
+ r->end = (lba_num>>8) & 0xff;
+
+ /* Set up local PCI Bus resources - we don't really need
+ ** them for Legacy boxes but it's nice to see in /proc.
+ */
+ r = &(lba_dev->hba.mem_space);
+ r->name = "LBA PCI LMMIO";
+ r->flags = IORESOURCE_MEM;
+ r->start = READ_REG32(d->hpa + LBA_LMMIO_BASE);
+ r->end = r->start + ~ (READ_REG32(d->hpa + LBA_LMMIO_MASK));
+
+ r = &(lba_dev->hba.io_space);
+ r->name = "LBA PCI I/O Ports";
+ r->flags = IORESOURCE_IO;
+ r->start = READ_REG32(d->hpa + LBA_IOS_BASE);
+ r->end = r->start + (READ_REG32(d->hpa + LBA_IOS_MASK) ^ 0xffff);
+
+ lba_num = lba_dev->hba.hba_num << 16;
+ r->start |= lba_num;
+ r->end |= lba_num;
+}
+
+
+/**************************************************************************
+**
+** LBA initialization code (HW and SW)
+**
+** o identify LBA chip itself
+** o initialize LBA chip modes (HardFail)
+** o FIXME: initialize DMA hints for reasonable defaults
+** o enable configuration functions
+** o call pci_register_ops() to discover devs (fixup/fixup_bus get invoked)
+**
+**************************************************************************/
+
+static void
+lba_hw_init(struct lba_device *d)
+{
+ u32 stat;
+
+ /* Set HF mode as the default (vs. -1 mode). */
+ stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL);
+ WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL);
+
+ /*
+ ** FIXME: Hint registers are programmed with default hint
+ ** values by firmware. Hints should be sane even if we
+ ** can't reprogram them the way drivers want.
+ */
+}
+
+
+
+static void
+lba_common_init(struct lba_device *lba_dev)
+{
+ pci_bios = &lba_bios_ops;
+ pcibios_register_hba((struct pci_hba_data *)lba_dev);
+ lba_dev->lba_lock = SPIN_LOCK_UNLOCKED;
+
+ /*
+ ** Set flags which depend on hw_rev
+ */
+ if (!LBA_TR4PLUS(lba_dev)) {
+ lba_dev->flags |= LBA_FLAG_NO_DMA_DURING_CFG;
+ }
+}
+
+
+
+/*
+** Determine if lba should claim this chip (return 0) or not (return 1).
+** If so, initialize the chip and tell other partners in crime they
+** have work to do.
+*/
+static __init int
+lba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ struct lba_device *lba_dev;
+ struct pci_bus *lba_bus;
+ u32 func_class;
+ void *tmp_obj;
+
+ /* from drivers/pci/setup-bus.c */
+ extern void __init pbus_set_ranges(struct pci_bus *, struct pbus_set_ranges_data *);
+
+ /* Read HW Rev First */
+ func_class = READ_REG32(d->hpa + LBA_FCLASS);
+ func_class &= 0xf;
+
+ switch (func_class) {
+ case 0: dri->version = "TR1.0"; break;
+ case 1: dri->version = "TR2.0"; break;
+ case 2: dri->version = "TR2.1"; break;
+ case 3: dri->version = "TR2.2"; break;
+ case 4: dri->version = "TR3.0"; break;
+ case 5: dri->version = "TR4.0"; break;
+ default: dri->version = "TR4+";
+ }
+
+ printk("%s version %s (0x%x) found at 0x%p\n", dri->name, dri->version, func_class & 0xf, d->hpa);
+
+ /* Just in case we find some prototypes... */
+ if (func_class < 2) {
+ printk(KERN_WARNING "Can't support LBA older than TR2.1 "
+ "- continuing under adversity.\n");
+ }
+
+ /*
+ ** Tell I/O SAPIC driver we have a IRQ handler/region.
+ */
+ tmp_obj = iosapic_register(d->hpa+LBA_IOSAPIC_BASE);
+ if (NULL == tmp_obj) {
+ /* iosapic may have failed. But more likely the
+ ** slot isn't occupied and thus has no IRT entries.
+ ** iosapic_register looks for this iosapic in the IRT
+ ** before bothering to allocating data structures
+ ** we don't need.
+ */
+ DBG(KERN_WARNING MODULE_NAME ": iosapic_register says not used\n");
+ return (1);
+ }
+
+ lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
+ if (NULL == lba_dev)
+ {
+ printk("lba_init_chip - couldn't alloc lba_device\n");
+ return(1);
+ }
+
+ memset(lba_dev, 0, sizeof(struct lba_device));
+
+
+ /* ---------- First : initialize data we already have --------- */
+
+ /*
+ ** Need hw_rev to adjust configuration space behavior.
+ ** LBA_TR4PLUS macro uses hw_rev field.
+ */
+ lba_dev->hw_rev = func_class;
+
+ lba_dev->hba.base_addr = d->hpa; /* faster access */
+ lba_dev->iosapic_obj = tmp_obj; /* save interrupt handle */
+
+ /* ------------ Second : initialize common stuff ---------- */
+ lba_common_init(lba_dev);
+ lba_hw_init(lba_dev);
+
+ /* ---------- Third : setup I/O Port and MMIO resources --------- */
+#ifdef __LP64__
+
+ if (pdc_pat) {
+ /* PDC PAT firmware uses PIOP region of GMMIO space. */
+ pci_port = &lba_pat_port_ops;
+
+ /* Go ask PDC PAT what resources this LBA has */
+ lba_pat_resources(d, lba_dev);
+
+ } else {
+#endif
+ /* Sprockets PDC uses NPIOP region */
+ pci_port = &lba_astro_port_ops;
+
+ /* Poke the chip a bit for /proc output */
+ lba_legacy_resources(d, lba_dev);
+#ifdef __LP64__
+ }
+#endif
+
+ /*
+ ** Tell PCI support another PCI bus was found.
+ ** Walks PCI bus for us too.
+ */
+ lba_bus = lba_dev->hba.hba_bus =
+ pci_scan_bus( lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *) lba_dev);
+
+#ifdef __LP64__
+ if (pdc_pat) {
+
+ /* determine window sizes needed by PCI-PCI bridges */
+ DBG_PAT("LBA pcibios_size_bridge()\n");
+ pcibios_size_bridge(lba_bus, NULL);
+
+ /* assign resources to un-initialized devices */
+ DBG_PAT("LBA pcibios_assign_unassigned_resources()\n");
+ pcibios_assign_unassigned_resources(lba_bus);
+
+#ifdef DEBUG_LBA_PAT
+ DBG_PAT("\nLBA PIOP resource tree\n");
+ lba_dump_res(&lba_dev->hba.io_space, 2);
+ DBG_PAT("\nLBA LMMIO resource tree\n");
+ lba_dump_res(&lba_dev->hba.mem_space, 2);
+#endif
+
+ /* program *all* PCI-PCI bridge range registers */
+ DBG_PAT("LBA pbus_set_ranges()\n");
+ pbus_set_ranges(lba_bus, NULL);
+ }
+#endif /* __LP64__ */
+
+ /*
+ ** Once PCI register ops has walked the bus, access to config
+ ** space is restricted. Avoids master aborts on config cycles.
+ ** Early LBA revs go fatal on *any* master abort.
+ */
+ if (!LBA_TR4PLUS(lba_dev)) {
+ lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
+ }
+
+ /* Whew! Finally done! Tell services we got this one covered. */
+ return 0;
+}
+
+
+/*
+** Initialize the IBASE/IMASK registers for LBA (Elroy).
+** Only called from sba_iommu.c initialization sequence.
+*/
+void lba_init_iregs(void *sba_hpa, u32 ibase, u32 imask)
+{
+ extern struct pci_hba_data *hba_list; /* arch/parisc/kernel/pci.c */
+ struct pci_hba_data *lba;
+
+ imask <<= 2; /* adjust for hints - 2 more bits */
+
+ ASSERT((ibase & 0x003fffff) == 0);
+ ASSERT((imask & 0x003fffff) == 0);
+
+ /* FIXME: sba_hpa is intended to search some table to
+ ** determine which LBA's belong to the caller's SBA.
+ ** IS_ASTRO: just assume only one SBA for now.
+ */
+ ASSERT(NULL != hba_list);
+ DBG(KERN_DEBUG "%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask);
+
+ for (lba = hba_list; NULL != lba; lba = lba->next) {
+ DBG(KERN_DEBUG "%s() base_addr %p\n", __FUNCTION__, lba->base_addr);
+ WRITE_REG32( imask, lba->base_addr + LBA_IMASK);
+ WRITE_REG32( ibase, lba->base_addr + LBA_IBASE);
+ }
+ DBG(KERN_DEBUG "%s() done\n", __FUNCTION__);
+}
+
diff --git a/arch/parisc/kernel/led.c b/arch/parisc/kernel/led.c
new file mode 100644
index 000000000..a375423f3
--- /dev/null
+++ b/arch/parisc/kernel/led.c
@@ -0,0 +1,451 @@
+/*
+ * Chassis LCD/LED driver for HP-PARISC workstations
+ *
+ * (c) Copyright 2000 Red Hat Software
+ * (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/bitops.h>
+#include <asm/io.h>
+#include <asm/gsc.h>
+#include <asm/processor.h>
+#include <asm/hardware.h>
+#include <asm/param.h> /* HZ */
+#include <asm/led.h>
+
+
+/* define to disable all LED functions */
+#undef DISABLE_LEDS
+
+
+#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
+
+
+struct lcd_block {
+ unsigned char command; /* stores the command byte */
+ unsigned char on; /* value for turning LED on */
+ unsigned char off; /* value for turning LED off */
+};
+
+/* Structure returned by PDC_RETURN_CHASSIS_INFO */
+struct pdc_chassis_lcd_info_ret_block {
+ unsigned long model:16; /* DISPLAY_MODEL_XXXX (see below) */
+ unsigned long lcd_width:16; /* width of the LCD in chars (DISPLAY_MODEL_LCD only) */
+ char *lcd_cmd_reg_addr; /* ptr to LCD cmd-register & data ptr for LED */
+ char *lcd_data_reg_addr; /* ptr to LCD data-register (LCD only) */
+ unsigned int min_cmd_delay; /* delay in uS after cmd-write (LCD only) */
+ unsigned char reset_cmd1; /* command #1 for writing LCD string (LCD only) */
+ unsigned char reset_cmd2; /* command #2 for writing LCD string (LCD only) */
+ unsigned char act_enable; /* 0 = no activity (LCD only) */
+ struct lcd_block heartbeat;
+ struct lcd_block disk_io;
+ struct lcd_block lan_rcv;
+ struct lcd_block lan_tx;
+ char _pad;
+};
+
+/* values for pdc_chassis_lcd_info_ret_block.model: */
+#define DISPLAY_MODEL_LCD 0 /* KittyHawk LED or LCD */
+#define DISPLAY_MODEL_NONE 1 /* no LED or LCD */
+#define DISPLAY_MODEL_LASI 2 /* LASI style 8 bit LED */
+#define DISPLAY_MODEL_OLD_ASP 0x7F /* faked: ASP style 8 x 1 bit LED (only very old ASP versions) */
+
+
+/* LCD_CMD and LCD_DATA for KittyHawk machines */
+#ifdef __LP64__
+#define KITTYHAWK_LCD_CMD 0xfffffffff0190000L
+#else
+#define KITTYHAWK_LCD_CMD 0xf0190000
+#endif
+#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD + 1)
+
+
+/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's */
+static struct pdc_chassis_lcd_info_ret_block
+lcd_info __attribute__((aligned(8))) =
+{
+ model:DISPLAY_MODEL_LCD,
+ lcd_width:16,
+ lcd_cmd_reg_addr:(char *) KITTYHAWK_LCD_CMD,
+ lcd_data_reg_addr:(char *) KITTYHAWK_LCD_DATA,
+ min_cmd_delay:40,
+ reset_cmd1:0x80,
+ reset_cmd2:0xc0,
+};
+
+
+/* direct access to some of the lcd_info variables */
+#define LCD_CMD_REG lcd_info.lcd_cmd_reg_addr
+#define LCD_DATA_REG lcd_info.lcd_data_reg_addr
+#define LED_DATA_REG lcd_info.lcd_cmd_reg_addr /* LASI & ASP only */
+
+
+
+
+/*
+ **
+ ** led_ASP_driver()
+ **
+ */
+#define LED_DATA 0x01 /* data to shift (0:on 1:off) */
+#define LED_STROBE 0x02 /* strobe to clock data */
+static void led_ASP_driver(unsigned char leds)
+{
+ int i;
+
+ leds = ~leds;
+ for (i = 0; i < 8; i++) {
+ unsigned char value;
+ value = (leds & 0x80) >> 7;
+ gsc_writeb( value, LED_DATA_REG );
+ gsc_writeb( value | LED_STROBE, LED_DATA_REG );
+ leds <<= 1;
+ }
+}
+
+
+/*
+ **
+ ** led_LASI_driver()
+ **
+ */
+static void led_LASI_driver(unsigned char leds)
+{
+ leds = ~leds;
+ gsc_writeb( leds, LED_DATA_REG );
+}
+
+
+/*
+ **
+ ** led_LCD_driver()
+ **
+ ** The logic of the LCD driver is, that we write at every interrupt
+ ** only to one of LCD_CMD_REG _or_ LCD_DATA_REG - registers.
+ ** That way we don't need to let this interrupt routine busywait
+ ** the "min_cmd_delay", since idlewaiting in an interrupt-routine is
+ ** allways a BAD IDEA !
+ **
+ ** TODO: check the value of "min_cmd_delay" against the value of HZ.
+ **
+ */
+
+static void led_LCD_driver(unsigned char leds)
+{
+ static int last_index; /* 0:heartbeat, 1:disk, 2:lan_in, 3:lan_out */
+ static int last_was_cmd;/* 0: CMD was written last, 1: DATA was last */
+ struct lcd_block *block_ptr;
+ int value;
+
+ // leds = ~leds; /* needed ? */
+
+ switch (last_index) {
+ case 0: block_ptr = &lcd_info.heartbeat;
+ value = leds & LED_HEARTBEAT;
+ break;
+ case 1: block_ptr = &lcd_info.disk_io;
+ value = leds & LED_DISK_IO;
+ break;
+ case 2: block_ptr = &lcd_info.lan_rcv;
+ value = leds & LED_LAN_RCV;
+ break;
+ case 3: block_ptr = &lcd_info.lan_tx;
+ value = leds & LED_LAN_TX;
+ break;
+ default: /* should never happen: */
+ BUG();
+ return;
+ }
+
+ if (last_was_cmd) {
+ /* write the value to the LCD data port */
+ gsc_writeb( value ? block_ptr->on : block_ptr->off, LCD_DATA_REG );
+ } else {
+ /* write the command-byte to the LCD command register */
+ gsc_writeb( block_ptr->command, LCD_CMD_REG );
+ }
+
+ /* now update the vars for the next interrupt iteration */
+ if (++last_was_cmd == 2) {
+ last_was_cmd = 0;
+ if (++last_index == 4)
+ last_index = 0;
+ }
+}
+
+
+
+static char currentleds; /* stores current value of the LEDs */
+
+static void (*led_func_ptr) (unsigned char); /* ptr to LCD/LED-specific function */
+
+/*
+ ** led_interrupt_func()
+ **
+ ** is called at every timer interrupt from time.c,
+ ** updates the chassis LCD/LED
+ */
+
+#define HEARTBEAT_LEN (HZ/16)
+
+void led_interrupt_func(void)
+{
+#ifndef DISABLE_LEDS
+ static int count;
+ static int lastleds = -1;
+ static int nr;
+
+ /* exit, if not initialized */
+ if (!led_func_ptr)
+ return;
+
+ /* increment the local counter */
+ if (count == (HZ-1))
+ count = 0;
+ else
+ count++;
+
+ /* calculate the Heartbeat */
+ if ((count % (HZ/2)) < HEARTBEAT_LEN)
+ currentleds |= LED_HEARTBEAT;
+ else
+ currentleds &= ~LED_HEARTBEAT;
+
+ /* roll LEDs 0..2 */
+ if (count == 0) {
+ if (nr++ >= 2)
+ nr = 0;
+ currentleds &= ~7;
+ currentleds |= (1 << nr);
+ }
+
+ /* now update the LEDs */
+ if (currentleds != lastleds) {
+ led_func_ptr(currentleds);
+ lastleds = currentleds;
+ }
+#endif
+}
+
+
+/*
+ ** register_led_driver()
+ **
+ ** All information in lcd_info needs to be set up prior
+ ** calling this function.
+ */
+
+static void __init register_led_driver(void)
+{
+#ifndef DISABLE_LEDS
+ switch (lcd_info.model) {
+ case DISPLAY_MODEL_LCD:
+ printk(KERN_INFO "LCD display at (%p,%p)\n",
+ LCD_CMD_REG , LCD_DATA_REG);
+ led_func_ptr = led_LCD_driver;
+ break;
+
+ case DISPLAY_MODEL_LASI:
+ printk(KERN_INFO "LED display at %p\n",
+ LED_DATA_REG);
+ led_func_ptr = led_LASI_driver;
+ break;
+
+ case DISPLAY_MODEL_OLD_ASP:
+ printk(KERN_INFO "LED (ASP-style) display at %p\n",
+ LED_DATA_REG);
+ led_func_ptr = led_ASP_driver;
+ break;
+
+ default:
+ printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n",
+ __FUNCTION__, lcd_info.model);
+ return;
+ }
+#endif
+}
+
+/*
+ * XXX - could this move to lasi.c ??
+ */
+
+/*
+ ** lasi_led_init()
+ **
+ ** lasi_led_init() is called from lasi.c with the base hpa
+ ** of the lasi controller chip.
+ ** Since Mirage and Electra machines use a different LED
+ ** address register, we need to check for these machines
+ ** explicitly.
+ */
+
+#ifdef CONFIG_GSC_LASI
+void __init lasi_led_init(unsigned long lasi_hpa)
+{
+ if (lcd_info.model != DISPLAY_MODEL_NONE ||
+ lasi_hpa == 0)
+ return;
+
+ printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION);
+
+ /* Mirage and Electra machines need special offsets */
+ switch (CPU_HVERSION) {
+ case 0x60A: /* Mirage Jr (715/64) */
+ case 0x60B: /* Mirage 100 */
+ case 0x60C: /* Mirage 100+ */
+ case 0x60D: /* Electra 100 */
+ case 0x60E: /* Electra 120 */
+ LED_DATA_REG = (char *) (lasi_hpa - 0x00020000);
+ break;
+ default:
+ LED_DATA_REG = (char *) (lasi_hpa + 0x0000C000);
+ break;
+ } /* switch() */
+
+ lcd_info.model = DISPLAY_MODEL_LASI;
+ register_led_driver();
+}
+#endif
+
+
+/*
+ ** asp_led_init()
+ **
+ ** asp_led_init() is called from asp.c with the ptr
+ ** to the LED display.
+ */
+
+#ifdef CONFIG_GSC_LASI
+void __init asp_led_init(unsigned long led_ptr)
+{
+ if (lcd_info.model != DISPLAY_MODEL_NONE ||
+ led_ptr == 0)
+ return;
+
+ lcd_info.model = DISPLAY_MODEL_OLD_ASP;
+ LED_DATA_REG = (char *) led_ptr;
+
+ register_led_driver();
+}
+
+#endif
+
+
+
+/*
+ ** register_led_regions()
+ **
+ ** Simple function, which registers the LCD/LED regions for /procfs.
+ ** At bootup - where the initialisation of the LCD/LED normally happens -
+ ** not all internal structures of request_region() are properly set up,
+ ** so that we delay the registration until busdevice.c is executed.
+ **
+ */
+
+void __init register_led_regions(void)
+{
+ switch (lcd_info.model) {
+ case DISPLAY_MODEL_LCD:
+ request_region((unsigned long)LCD_CMD_REG, 1, "lcd_cmd");
+ request_region((unsigned long)LCD_DATA_REG, 1, "lcd_data");
+ break;
+ case DISPLAY_MODEL_LASI:
+ case DISPLAY_MODEL_OLD_ASP:
+ request_region((unsigned long)LED_DATA_REG, 1, "led_data");
+ break;
+ }
+}
+
+
+
+/*
+ ** led_init()
+ **
+ ** led_init() is called very early in the bootup-process from setup.c
+ ** and asks the PDC for an usable chassis LCD or LED.
+ ** If the PDC doesn't return any info, then the LED
+ ** is detected by lasi.c or asp.c and registered with the
+ ** above functions lasi_led_init() or asp_led_init().
+ ** KittyHawk machines have often a buggy PDC, so that
+ ** we explicitly check for those machines here.
+ */
+
+int __init led_init(void)
+{
+#ifndef DISABLE_LEDS
+ long pdc_result[32];
+
+ printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION);
+
+ /* Work around the buggy PDC of KittyHawk-machines */
+ switch (CPU_HVERSION) {
+ case 0x580: /* KittyHawk DC2-100 (K100) */
+ case 0x581: /* KittyHawk DC3-120 (K210) */
+ case 0x582: /* KittyHawk DC3 100 (K400) */
+ case 0x583: /* KittyHawk DC3 120 (K410) */
+ case 0x58B: /* KittyHawk DC2 100 (K200) */
+ printk("%s: KittyHawk-Machine found !!\n", __FUNCTION__);
+ goto found; /* use the preinitialized values of lcd_info */
+
+ default:
+ break;
+ }
+
+ /* initialize pdc_result, so we can check the return values of pdc_chassis_info() */
+ pdc_result[0] = pdc_result[1] = 0;
+
+ if (pdc_chassis_info(&pdc_result, &lcd_info, sizeof(lcd_info)) == PDC_OK) {
+ printk("%s: chassis info: model %d, ret0=%d, ret1=%d\n",
+ __FUNCTION__, lcd_info.model, pdc_result[0], pdc_result[1]);
+
+ /* check the results. Some machines have a buggy PDC */
+ if (pdc_result[0] <= 0 || pdc_result[0] != pdc_result[1])
+ goto not_found;
+
+ switch (lcd_info.model) {
+ case DISPLAY_MODEL_LCD: /* LCD display */
+ if (pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block)
+ && pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block) - 1)
+ goto not_found;
+ printk("%s: min_cmd_delay = %d uS\n",
+ __FUNCTION__, lcd_info.min_cmd_delay);
+ break;
+
+ case DISPLAY_MODEL_NONE: /* no LED or LCD available */
+ goto not_found;
+
+ case DISPLAY_MODEL_LASI: /* Lasi style 8 bit LED display */
+ if (pdc_result[0] != 8 && pdc_result[0] != 32)
+ goto not_found;
+ break;
+
+ default:
+ printk(KERN_WARNING "Unknown LCD/LED model %d\n",
+ lcd_info.model);
+ goto not_found;
+ } /* switch() */
+
+found:
+ /* register the LCD/LED driver */
+ register_led_driver();
+ return 0;
+
+ } /* if() */
+
+not_found:
+ lcd_info.model = DISPLAY_MODEL_NONE;
+ return 1;
+#endif
+}
diff --git a/arch/parisc/kernel/pa7300lc.c b/arch/parisc/kernel/pa7300lc.c
new file mode 100644
index 000000000..307e4b2fd
--- /dev/null
+++ b/arch/parisc/kernel/pa7300lc.c
@@ -0,0 +1,54 @@
+/*
+ * linux/arch/parisc/kernel/pa7300lc.c
+ * - PA7300LC-specific functions
+ *
+ * Copyright (C) 2000 Philipp Rumpf */
+
+#include <asm/gsc.h>
+#include <asm/ptrace.h>
+#include <asm/machdep.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
+
+/* CPU register indices */
+
+#define MIOC_STATUS 0xf040
+#define MIOC_CONTROL 0xf080
+#define MDERRADD 0xf0e0
+#define DMAERR 0xf0e8
+#define DIOERR 0xf0ec
+#define HIDMAMEM 0xf0f4
+
+/* read CPU Diagnose register index */
+static u32 diag_read(int index)
+{
+ return 0;
+}
+
+/* this returns the HPA of the CPU it was called on */
+static u32 cpu_hpa(void)
+{
+ return 0xfffb0000;
+}
+
+static void pa7300lc_lpmc(int code, struct pt_regs *regs)
+{
+ u32 hpa;
+ printk(KERN_WARNING "LPMC on CPU %d\n", smp_processor_id());
+
+ show_regs(regs);
+
+ hpa = cpu_hpa();
+ printk(KERN_WARNING
+ "MIOC_CONTROL %08x\n" "MIOC_STATUS %08x\n"
+ "MDERRADD %08x\n" "DMAERR %08x\n"
+ "DIOERR %08x\n" "HIDMAMEM %08x\n",
+ gsc_readl(hpa+MIOC_CONTROL), gsc_readl(hpa+MIOC_STATUS),
+ gsc_readl(hpa+MDERRADD), gsc_readl(hpa+DMAERR),
+ gsc_readl(hpa+DIOERR), gsc_readl(hpa+HIDMAMEM));
+}
+
+void pa7300lc_init(void)
+{
+ cpu_lpmc = pa7300lc_lpmc;
+}
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
new file mode 100644
index 000000000..2b4dbd74c
--- /dev/null
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -0,0 +1,138 @@
+/*
+ * Architecture-specific kernel symbols
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/string.h>
+EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strtok);
+
+#include <linux/pci.h>
+EXPORT_SYMBOL(hppa_dma_ops);
+
+#include <asm/irq.h>
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+
+#include <asm/processor.h>
+EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(boot_cpu_data);
+
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(synchronize_irq);
+
+#include <asm/smplock.h>
+EXPORT_SYMBOL(kernel_flag);
+
+#include <asm/system.h>
+EXPORT_SYMBOL(__global_sti);
+EXPORT_SYMBOL(__global_cli);
+EXPORT_SYMBOL(__global_save_flags);
+EXPORT_SYMBOL(__global_restore_flags);
+
+#endif
+
+#include <asm/uaccess.h>
+EXPORT_SYMBOL(lcopy_to_user);
+EXPORT_SYMBOL(lcopy_from_user);
+
+/* Needed so insmod can set dp value */
+
+extern int data_start;
+
+EXPORT_SYMBOL_NOVERS(data_start);
+
+#include <asm/gsc.h>
+EXPORT_SYMBOL(_gsc_writeb);
+EXPORT_SYMBOL(_gsc_writew);
+EXPORT_SYMBOL(_gsc_writel);
+EXPORT_SYMBOL(_gsc_readb);
+EXPORT_SYMBOL(_gsc_readw);
+EXPORT_SYMBOL(_gsc_readl);
+EXPORT_SYMBOL(busdevice_alloc_irq);
+EXPORT_SYMBOL(register_driver);
+EXPORT_SYMBOL(gsc_alloc_irq);
+EXPORT_SYMBOL(pdc_iodc_read);
+
+extern void $$divI(void);
+extern void $$divU(void);
+extern void $$remI(void);
+extern void $$remU(void);
+extern void $$mulI(void);
+extern void $$mulU(void);
+extern void $$divU_3(void);
+extern void $$divU_5(void);
+extern void $$divU_6(void);
+extern void $$divU_9(void);
+extern void $$divU_10(void);
+extern void $$divU_12(void);
+extern void $$divU_7(void);
+extern void $$divU_14(void);
+extern void $$divU_15(void);
+extern void $$divI_3(void);
+extern void $$divI_5(void);
+extern void $$divI_6(void);
+extern void $$divI_7(void);
+extern void $$divI_9(void);
+extern void $$divI_10(void);
+extern void $$divI_12(void);
+extern void $$divI_14(void);
+extern void $$divI_15(void);
+
+EXPORT_SYMBOL_NOVERS($$divI);
+EXPORT_SYMBOL_NOVERS($$divU);
+EXPORT_SYMBOL_NOVERS($$remI);
+EXPORT_SYMBOL_NOVERS($$remU);
+EXPORT_SYMBOL_NOVERS($$mulI);
+EXPORT_SYMBOL_NOVERS($$mulU);
+EXPORT_SYMBOL_NOVERS($$divU_3);
+EXPORT_SYMBOL_NOVERS($$divU_5);
+EXPORT_SYMBOL_NOVERS($$divU_6);
+EXPORT_SYMBOL_NOVERS($$divU_9);
+EXPORT_SYMBOL_NOVERS($$divU_10);
+EXPORT_SYMBOL_NOVERS($$divU_12);
+EXPORT_SYMBOL_NOVERS($$divU_7);
+EXPORT_SYMBOL_NOVERS($$divU_14);
+EXPORT_SYMBOL_NOVERS($$divU_15);
+EXPORT_SYMBOL_NOVERS($$divI_3);
+EXPORT_SYMBOL_NOVERS($$divI_5);
+EXPORT_SYMBOL_NOVERS($$divI_6);
+EXPORT_SYMBOL_NOVERS($$divI_7);
+EXPORT_SYMBOL_NOVERS($$divI_9);
+EXPORT_SYMBOL_NOVERS($$divI_10);
+EXPORT_SYMBOL_NOVERS($$divI_12);
+EXPORT_SYMBOL_NOVERS($$divI_14);
+EXPORT_SYMBOL_NOVERS($$divI_15);
+
+extern void __ashrdi3(void);
+
+EXPORT_SYMBOL_NOVERS(__ashrdi3);
+
+#ifdef __LP64__
+extern void __divdi3(void);
+extern void __udivdi3(void);
+
+EXPORT_SYMBOL_NOVERS(__divdi3);
+EXPORT_SYMBOL_NOVERS(__udivdi3);
+#endif
+
+#ifndef __LP64__
+extern void $$dyncall(void);
+EXPORT_SYMBOL_NOVERS($$dyncall);
+#endif
+
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
new file mode 100644
index 000000000..88a9ddc77
--- /dev/null
+++ b/arch/parisc/kernel/pci-dma.c
@@ -0,0 +1,547 @@
+/*
+** Dynamic DMA mapping support.
+** See Documentation/DMA-mapping.txt for interface definitions.
+**
+** (c) Copyright 1999,2000 Hewlett-Packard Company
+** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2000 Philipp Rumpf <prumpf@tux.org>
+** (c) Copyright 2000 John Marvin
+**
+** This implementation is for PA-RISC platforms that do not support
+** I/O TLBs (aka DMA address translation hardware).
+**
+** "leveraged" from 2.3.47: arch/ia64/kernel/pci-dma.c.
+** (I assume it's from David Mosberger-Tang but there was no Copyright)
+**
+** AFAIK, all PA7100LC and PA7300LC platforms can use this code.
+** All PA2.0 machines but V-class can alias xxx_alloc_consistent()
+** to use regular cacheable memory.
+**
+** - ggg
+*/
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#include <asm/io.h>
+#include <asm/page.h> /* get_order */
+#include <asm/dma.h> /* for DMA_CHUNK_SIZE */
+
+#include <linux/proc_fs.h>
+
+static struct proc_dir_entry * proc_gsc_root = NULL;
+static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
+static unsigned long pcxl_used_bytes = 0;
+static unsigned long pcxl_used_pages = 0;
+
+extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */
+static spinlock_t pcxl_res_lock;
+static char *pcxl_res_map;
+static int pcxl_res_hint;
+static int pcxl_res_size;
+
+#ifdef DEBUG_PCXL_RESOURCE
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+
+/*
+** Dump a hex representation of the resource map.
+*/
+
+#ifdef DUMP_RESMAP
+static
+void dump_resmap(void)
+{
+ u_long *res_ptr = (unsigned long *)pcxl_res_map;
+ u_long i = 0;
+
+ printk("res_map: ");
+ for(; i < (pcxl_res_size / sizeof(unsigned long)); ++i, ++res_ptr)
+ printk("%08lx ", *res_ptr);
+
+ printk("\n");
+}
+#else
+static inline void dump_resmap(void) {;}
+#endif
+
+static int pa11_dma_supported( struct pci_dev *dev, dma_addr_t mask)
+{
+ return 1;
+}
+
+static inline int map_pte_uncached(pte_t * pte,
+ unsigned long vaddr,
+ unsigned long size, unsigned long *paddr_ptr)
+{
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ vaddr &= ~PMD_MASK;
+ end = vaddr + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ if (!pte_none(*pte))
+ printk(KERN_ERR "map_pte_uncached: page already exists\n");
+ set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
+ pdtlb_kernel(orig_vaddr);
+ vaddr += PAGE_SIZE;
+ orig_vaddr += PAGE_SIZE;
+ (*paddr_ptr) += PAGE_SIZE;
+ pte++;
+ } while (vaddr < end);
+ return 0;
+}
+
+static inline int map_pmd_uncached(pmd_t * pmd, unsigned long vaddr,
+ unsigned long size, unsigned long *paddr_ptr)
+{
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ vaddr &= ~PGDIR_MASK;
+ end = vaddr + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ pte_t * pte = pte_alloc_kernel(pmd, vaddr);
+ if (!pte)
+ return -ENOMEM;
+ if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr))
+ return -ENOMEM;
+ vaddr = (vaddr + PMD_SIZE) & PMD_MASK;
+ orig_vaddr += PMD_SIZE;
+ pmd++;
+ } while (vaddr < end);
+ return 0;
+}
+
+static inline int map_uncached_pages(unsigned long vaddr, unsigned long size,
+ unsigned long paddr)
+{
+ pgd_t * dir;
+ unsigned long end = vaddr + size;
+
+ dir = pgd_offset_k(vaddr);
+ do {
+ pmd_t *pmd;
+
+ pmd = pmd_alloc_kernel(dir, vaddr);
+ if (!pmd)
+ return -ENOMEM;
+ if (map_pmd_uncached(pmd, vaddr, end - vaddr, &paddr))
+ return -ENOMEM;
+ vaddr = vaddr + PGDIR_SIZE;
+ dir++;
+ } while (vaddr && (vaddr < end));
+ return 0;
+}
+
+static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr,
+ unsigned long size)
+{
+ pte_t * pte;
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = pte_offset(pmd, vaddr);
+ vaddr &= ~PMD_MASK;
+ end = vaddr + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ pte_t page = *pte;
+ pte_clear(pte);
+ pdtlb_kernel(orig_vaddr);
+ vaddr += PAGE_SIZE;
+ orig_vaddr += PAGE_SIZE;
+ pte++;
+ if (pte_none(page) || pte_present(page))
+ continue;
+ printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n");
+ } while (vaddr < end);
+}
+
+static inline void unmap_uncached_pmd(pgd_t * dir, unsigned long vaddr,
+ unsigned long size)
+{
+ pmd_t * pmd;
+ unsigned long end;
+ unsigned long orig_vaddr = vaddr;
+
+ if (pgd_none(*dir))
+ return;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return;
+ }
+ pmd = pmd_offset(dir, vaddr);
+ vaddr &= ~PGDIR_MASK;
+ end = vaddr + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ unmap_uncached_pte(pmd, orig_vaddr, end - vaddr);
+ vaddr = (vaddr + PMD_SIZE) & PMD_MASK;
+ orig_vaddr += PMD_SIZE;
+ pmd++;
+ } while (vaddr < end);
+}
+
+static void unmap_uncached_pages(unsigned long vaddr, unsigned long size)
+{
+ pgd_t * dir;
+ unsigned long end = vaddr + size;
+
+ dir = pgd_offset_k(vaddr);
+ do {
+ unmap_uncached_pmd(dir, vaddr, end - vaddr);
+ vaddr = vaddr + PGDIR_SIZE;
+ dir++;
+ } while (vaddr && (vaddr < end));
+}
+
+#define PCXL_SEARCH_LOOP(idx, mask, size) \
+ for(; res_ptr < res_end; ++res_ptr) \
+ { \
+ if(0 == ((*res_ptr) & mask)) { \
+ *res_ptr |= mask; \
+ idx = (int)((u_long)res_ptr - (u_long)pcxl_res_map); \
+ pcxl_res_hint = idx + (size >> 3); \
+ goto resource_found; \
+ } \
+ }
+
+#define PCXL_FIND_FREE_MAPPING(idx, mask, size) { \
+ u##size *res_ptr = (u##size *)&(pcxl_res_map[pcxl_res_hint & ~((size >> 3) - 1)]); \
+ u##size *res_end = (u##size *)&pcxl_res_map[pcxl_res_size]; \
+ PCXL_SEARCH_LOOP(idx, mask, size); \
+ res_ptr = (u##size *)&pcxl_res_map[0]; \
+ PCXL_SEARCH_LOOP(idx, mask, size); \
+}
+
+unsigned long
+pcxl_alloc_range(size_t size)
+{
+ int res_idx;
+ u_long mask, flags;
+ unsigned int pages_needed = size >> PAGE_SHIFT;
+
+ ASSERT(pages_needed);
+ ASSERT((pages_needed * PAGE_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_needed < (BITS_PER_LONG - PAGE_SHIFT));
+
+ mask = (u_long) -1L;
+ mask >>= BITS_PER_LONG - pages_needed;
+
+ DBG_RES("pcxl_alloc_range() size: %d pages_needed %d pages_mask 0x%08lx\n",
+ size, pages_needed, mask);
+
+ spin_lock_irqsave(&pcxl_res_lock, flags);
+
+ if(pages_needed <= 8) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 8);
+ } else if(pages_needed <= 16) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 16);
+ } else if(pages_needed <= 32) {
+ PCXL_FIND_FREE_MAPPING(res_idx, mask, 32);
+ } else {
+ panic(__FILE__ ": pcxl_alloc_range() Too many pages to map.\n");
+ }
+
+ dump_resmap();
+ panic(__FILE__ ": pcxl_alloc_range() out of dma mapping resources\n");
+
+resource_found:
+
+ DBG_RES("pcxl_alloc_range() res_idx %d mask 0x%08lx res_hint: %d\n",
+ res_idx, mask, pcxl_res_hint);
+
+ pcxl_used_pages += pages_needed;
+ pcxl_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1);
+
+ spin_unlock_irqrestore(&pcxl_res_lock, flags);
+
+ dump_resmap();
+
+ /*
+ ** return the corresponding vaddr in the pcxl dma map
+ */
+ return (pcxl_dma_start + (res_idx << (PAGE_SHIFT + 3)));
+}
+
+#define PCXL_FREE_MAPPINGS(idx, m, size) \
+ u##size *res_ptr = (u##size *)&(pcxl_res_map[(idx) + (((size >> 3) - 1) & (~((size >> 3) - 1)))]); \
+ ASSERT((*res_ptr & m) == m); \
+ *res_ptr &= ~m;
+
+/*
+** clear bits in the pcxl resource map
+*/
+static void
+pcxl_free_range(unsigned long vaddr, size_t size)
+{
+ u_long mask, flags;
+ unsigned int res_idx = (vaddr - pcxl_dma_start) >> (PAGE_SHIFT + 3);
+ unsigned int pages_mapped = size >> PAGE_SHIFT;
+
+ ASSERT(pages_mapped);
+ ASSERT((pages_mapped * PAGE_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_mapped < (BITS_PER_LONG - PAGE_SHIFT));
+
+ mask = (u_long) -1L;
+ mask >>= BITS_PER_LONG - pages_mapped;
+
+ DBG_RES("pcxl_free_range() res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n",
+ res_idx, size, pages_mapped, mask);
+
+ spin_lock_irqsave(&pcxl_res_lock, flags);
+
+ if(pages_mapped <= 8) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 8);
+ } else if(pages_mapped <= 16) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 16);
+ } else if(pages_mapped <= 32) {
+ PCXL_FREE_MAPPINGS(res_idx, mask, 32);
+ } else {
+ panic(__FILE__ ": pcxl_free_range() Too many pages to unmap.\n");
+ }
+
+ pcxl_used_pages -= (pages_mapped ? pages_mapped : 1);
+ pcxl_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1);
+
+ spin_unlock_irqrestore(&pcxl_res_lock, flags);
+
+ dump_resmap();
+}
+
+static int __init
+pcxl_dma_init(void)
+{
+ if (pcxl_dma_start == 0)
+ return 0;
+
+ spin_lock_init(&pcxl_res_lock);
+ pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3);
+ pcxl_res_hint = 0;
+ pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL,
+ get_order(pcxl_res_size));
+
+ proc_gsc_root = proc_mkdir("gsc", 0);
+ create_proc_info_entry("dino", 0, proc_gsc_root, pcxl_proc_info);
+ return 0;
+}
+
+__initcall(pcxl_dma_init);
+
+static void * pa11_dma_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+{
+ unsigned long vaddr;
+ unsigned long paddr;
+ int order;
+
+ order = get_order(size);
+ size = 1 << (order + PAGE_SHIFT);
+ vaddr = pcxl_alloc_range(size);
+ paddr = __get_free_pages(GFP_ATOMIC, order);
+ flush_kernel_dcache_range(paddr, size);
+ paddr = __pa(paddr);
+ map_uncached_pages(vaddr, size, paddr);
+ *dma_handle = (dma_addr_t) paddr;
+
+#if 0
+/* This probably isn't needed to support EISA cards.
+** ISA cards will certainly only support 24-bit DMA addressing.
+** Not clear if we can, want, or need to support ISA.
+*/
+ if (!hwdev || hwdev->dma_mask != 0xffffffff)
+ gfp |= GFP_DMA;
+#endif
+ return (void *)vaddr;
+}
+
+static void pa11_dma_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ int order;
+
+ order = get_order(size);
+ size = 1 << (order + PAGE_SHIFT);
+ unmap_uncached_pages((unsigned long)vaddr, size);
+ pcxl_free_range((unsigned long)vaddr, size);
+ free_pages((unsigned long)__va(dma_handle), order);
+}
+
+static dma_addr_t pa11_dma_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE) {
+ printk(KERN_ERR "pa11_dma_map_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
+ BUG();
+ }
+
+ flush_kernel_dcache_range((unsigned long) addr, size);
+ return virt_to_phys(addr);
+}
+
+static void pa11_dma_unmap_single(struct pci_dev *dev, dma_addr_t dma_handle, size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE) {
+ printk(KERN_ERR "pa11_dma_unmap_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0));
+ BUG();
+ }
+
+ if (direction == PCI_DMA_TODEVICE)
+ return;
+
+ /*
+ * For PCI_DMA_FROMDEVICE this flush is not necessary for the
+ * simple map/unmap case. However, it IS necessary if if
+ * pci_dma_sync_single has been called and the buffer reused.
+ */
+
+ flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size);
+ return;
+}
+
+static int pa11_dma_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int i;
+
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
+ for (i = 0; i < nents; i++, sglist++ ) {
+ sg_dma_address(sglist) = (dma_addr_t) virt_to_phys(sglist->address);
+ sg_dma_len(sglist) = sglist->length;
+ flush_kernel_dcache_range((unsigned long)sglist->address,
+ sglist->length);
+ }
+ return nents;
+}
+
+static void pa11_dma_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int i;
+
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
+ if (direction == PCI_DMA_TODEVICE)
+ return;
+
+ /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
+
+ for (i = 0; i < nents; i++, sglist++ )
+ flush_kernel_dcache_range((unsigned long) sglist->address, sglist->length);
+ return;
+}
+
+static void pa11_dma_sync_single(struct pci_dev *dev, dma_addr_t dma_handle, size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
+ flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size);
+}
+
+static void pa11_dma_sync_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ int i;
+
+ /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
+
+ for (i = 0; i < nents; i++, sglist++ )
+ flush_kernel_dcache_range((unsigned long) sglist->address, sglist->length);
+}
+
+struct pci_dma_ops pcxl_dma_ops = {
+ pa11_dma_supported, /* dma_support */
+ pa11_dma_alloc_consistent,
+ pa11_dma_free_consistent,
+ pa11_dma_map_single, /* map_single */
+ pa11_dma_unmap_single, /* unmap_single */
+ pa11_dma_map_sg, /* map_sg */
+ pa11_dma_unmap_sg, /* unmap_sg */
+ pa11_dma_sync_single, /* dma_sync_single */
+ pa11_dma_sync_sg /* dma_sync_sg */
+};
+
+static void *fail_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ return NULL;
+}
+
+static void fail_free_consistent(struct pci_dev *dev, size_t size,
+ void *vaddr, dma_addr_t iova)
+{
+ return;
+}
+
+struct pci_dma_ops pcx_dma_ops = {
+ pa11_dma_supported, /* dma_support */
+ fail_alloc_consistent,
+ fail_free_consistent,
+ pa11_dma_map_single, /* map_single */
+ pa11_dma_unmap_single, /* unmap_single */
+ pa11_dma_map_sg, /* map_sg */
+ pa11_dma_unmap_sg, /* unmap_sg */
+ pa11_dma_sync_single, /* dma_sync_single */
+ pa11_dma_sync_sg /* dma_sync_sg */
+};
+
+struct pci_dma_ops *hppa_dma_ops;
+
+static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
+{
+ u_long i = 0;
+ unsigned long *res_ptr = (u_long *)pcxl_res_map;
+ unsigned long total_pages = pcxl_res_size << 3; /* 8 bits per byte */
+
+ sprintf(buf, "\nDMA Mapping Area size : %d bytes (%d pages)\n",
+ PCXL_DMA_MAP_SIZE,
+ (pcxl_res_size << 3) ); /* 1 bit per page */
+
+ sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
+ buf, pcxl_res_size, pcxl_res_size << 3); /* 8 bits per byte */
+
+ strcat(buf, " total: free: used: % used:\n");
+ sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size,
+ pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes,
+ (pcxl_used_bytes * 100) / pcxl_res_size);
+
+ sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
+ total_pages - pcxl_used_pages, pcxl_used_pages,
+ (pcxl_used_pages * 100 / total_pages));
+
+ strcat(buf, "\nResource bitmap:");
+
+ for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
+ if ((i & 7) == 0)
+ strcat(buf,"\n ");
+ sprintf(buf, "%s %08lx", buf, *res_ptr);
+ }
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
new file mode 100644
index 000000000..a46f69832
--- /dev/null
+++ b/arch/parisc/kernel/pci.c
@@ -0,0 +1,535 @@
+/* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $
+ *
+ * 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) 1997, 1998 Ralf Baechle
+ * Copyright (C) 1999 SuSE GmbH
+ * Copyright (C) 1999 Hewlett-Packard Company
+ * Copyright (C) 1999, 2000 Grant Grundler
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h> /* for __init and __devinit */
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/string.h> /* for memcpy() */
+
+#include <asm/system.h>
+
+#ifdef CONFIG_PCI
+
+#undef DEBUG_RESOURCES
+
+#ifdef DEBUG_RESOURCES
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+/* To be used as: mdelay(pci_post_reset_delay);
+**
+** post_reset is the time the kernel should stall to prevent anyone from
+** accessing the PCI bus once #RESET is de-asserted.
+** PCI spec somewhere says 1 second but with multi-PCI bus systems,
+** this makes the boot time much longer than necessary.
+** 20ms seems to work for all the HP PCI implementations to date.
+*/
+int pci_post_reset_delay = 50;
+
+struct pci_port_ops *pci_port;
+struct pci_bios_ops *pci_bios;
+
+struct pci_hba_data *hba_list = NULL;
+int hba_count = 0;
+
+/*
+** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data.
+*/
+#define PCI_HBA_MAX 32
+static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX];
+
+
+/********************************************************************
+**
+** I/O port space support
+**
+*********************************************************************/
+
+#define PCI_PORT_HBA(a) ((a)>>16)
+#define PCI_PORT_ADDR(a) ((a) & 0xffffUL)
+
+/* KLUGE : inb needs to be defined differently for PCI devices than
+** for other bus interfaces. Doing this at runtime sucks but is the
+** only way one driver binary can support devices on different bus types.
+**
+*/
+
+#define PCI_PORT_IN(type, size) \
+u##size in##type (int addr) \
+{ \
+ int b = PCI_PORT_HBA(addr); \
+ u##size d = (u##size) -1; \
+ ASSERT(pci_port); /* make sure services are defined */ \
+ ASSERT(parisc_pci_hba[b]); /* make sure ioaddr are "fixed up" */ \
+ if (parisc_pci_hba[b] == NULL) { \
+ printk(KERN_WARNING "\nPCI Host Bus Adapter %d not registered. in" #size "(0x%x) returning -1\n", b, addr); \
+ } else { \
+ d = pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \
+ } \
+ return d; \
+}
+
+PCI_PORT_IN(b, 8)
+PCI_PORT_IN(w, 16)
+PCI_PORT_IN(l, 32)
+
+
+#define PCI_PORT_OUT(type, size) \
+void out##type (u##size d, int addr) \
+{ \
+ int b = PCI_PORT_HBA(addr); \
+ ASSERT(pci_port); \
+ pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \
+}
+
+PCI_PORT_OUT(b, 8)
+PCI_PORT_OUT(w, 16)
+PCI_PORT_OUT(l, 32)
+
+
+
+/*
+ * BIOS32 replacement.
+ */
+void pcibios_init(void)
+{
+ ASSERT(pci_bios != NULL);
+
+ if (pci_bios)
+ {
+ if (pci_bios->init) {
+ (*pci_bios->init)();
+ } else {
+ printk(KERN_WARNING "pci_bios != NULL but init() is!\n");
+ }
+ }
+}
+
+
+/* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */
+void pcibios_fixup_bus(struct pci_bus *bus)
+{
+ ASSERT(pci_bios != NULL);
+
+ /* If this is a bridge, get the current bases */
+ if (bus->self) {
+ pci_read_bridge_bases(bus);
+ }
+
+ if (pci_bios) {
+ if (pci_bios->fixup_bus) {
+ (*pci_bios->fixup_bus)(bus);
+ } else {
+ printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n");
+ }
+ }
+}
+
+
+char *pcibios_setup(char *str)
+{
+ return str;
+}
+
+#endif /* defined(CONFIG_PCI) */
+
+
+
+/* -------------------------------------------------------------------
+** linux-2.4: NEW STUFF
+** --------------------
+*/
+
+/*
+** Used in drivers/pci/quirks.c
+*/
+struct pci_fixup pcibios_fixups[] = { {0} };
+
+
+/*
+** called by drivers/pci/setup.c:pdev_fixup_irq()
+*/
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+/*
+** updates IRQ_LINE cfg register to reflect PCI-PCI bridge skewing.
+**
+** Calling path for Alpha is:
+** alpha/kernel/pci.c:common_init_pci(swizzle_func, pci_map_irq_func )
+** drivers/pci/setup.c:pci_fixup_irqs()
+** drivers/pci/setup.c:pci_fixup_irq() (for each PCI device)
+** invoke swizzle and map functions
+** alpha/kernel/pci.c:pcibios_update_irq()
+**
+** Don't need this for PA legacy PDC systems.
+**
+** On PAT PDC systems, We only support one "swizzle" for any number
+** of PCI-PCI bridges deep. That's how bit3 PCI expansion chassis
+** are implemented. The IRQ lines are "skewed" for all devices but
+** *NOT* routed through the PCI-PCI bridge. Ie any device "0" will
+** share an IRQ line. Legacy PDC is expecting this IRQ line routing
+** as well.
+**
+** Unfortunately, PCI spec allows the IRQ lines to be routed
+** around the PCI bridge as long as the IRQ lines are skewed
+** based on the device number...<sigh>...
+**
+** Lastly, dino.c might be able to use pci_fixup_irq() to
+** support RS-232 and PS/2 children. Not sure how but it's
+** something to think about.
+*/
+}
+
+
+/* ------------------------------------
+**
+** Program one BAR in PCI config space.
+**
+** ------------------------------------
+** PAT PDC systems need this routine. PA legacy PDC does not.
+**
+** Used by alpha/arm:
+** alpha/kernel/pci.c:common_init_pci()
+** (or arm/kernel/pci.c:pcibios_init())
+** drivers/pci/setup.c:pci_assign_unassigned_resources()
+** drivers/pci/setup.c:pdev_assign_unassigned_resources()
+** arch/<foo>/kernel/pci.c:pcibios_update_resource()
+**
+** When BAR's are configured by linux, this routine
+** will update configuration space with the "normalized"
+** address. "root" indicates where the range starts and res
+** is some portion of that range.
+**
+** For all PA-RISC systems except V-class, root->start would be zero.
+**
+** PAT PDC can tell us which MMIO ranges are available or already in use.
+** I/O port space and such are not memory mapped anyway for PA-Risc.
+*/
+void __devinit
+pcibios_update_resource(
+ struct pci_dev *dev,
+ struct resource *root,
+ struct resource *res,
+ int barnum
+ )
+{
+ int where;
+ u32 barval = 0;
+
+ DBG_RES("pcibios_update_resource(%s, ..., %d) [%lx,%lx]/%x\n",
+ dev->slot_name,
+ barnum, res->start, res->end, (int) res->flags);
+
+ if (barnum >= PCI_BRIDGE_RESOURCES) {
+ /* handled in pbus_set_ranges_data() */
+ return;
+ }
+
+ if (barnum == PCI_ROM_RESOURCE) {
+ where = PCI_ROM_ADDRESS;
+ } else {
+ /* 0-5 standard PCI "regions" */
+ where = PCI_BASE_ADDRESS_0 + (barnum * 4);
+ }
+
+ if (res->flags & IORESOURCE_IO) {
+ barval = PCI_PORT_ADDR(res->start);
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* This should work for VCLASS too */
+ barval = res->start & 0xffffffffUL;
+ } else {
+ panic("pcibios_update_resource() WTF? flags not IO or MEM");
+ }
+
+ pci_write_config_dword(dev, where, barval);
+
+/* XXX FIXME - Elroy does support 64-bit (dual cycle) addressing.
+** But at least one device (Symbios 53c896) which has 64-bit BAR
+** doesn't actually work right with dual cycle addresses.
+** So ignore the whole mess for now.
+*/
+
+ if ((res->flags & (PCI_BASE_ADDRESS_SPACE
+ | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
+ == (PCI_BASE_ADDRESS_SPACE_MEMORY
+ | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+ pci_write_config_dword(dev, where+4, 0);
+ printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->name);
+ }
+}
+
+/*
+** Called by pci_set_master() - a driver interface.
+**
+** Legacy PDC guarantees to set:
+** Map Memory BAR's into PA IO space.
+** Map Expansion ROM BAR into one common PA IO space per bus.
+** Map IO BAR's into PCI IO space.
+** Command (see below)
+** Cache Line Size
+** Latency Timer
+** Interrupt Line
+** PPB: secondary latency timer, io/mmio base/limit,
+** bus numbers, bridge control
+**
+*/
+void
+pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat >= 16) return;
+
+ /*
+ ** HP generally has fewer devices on the bus than other architectures.
+ */
+ printk("PCIBIOS: Setting latency timer of %s to 128\n", dev->slot_name);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+}
+
+
+/*
+** called by drivers/pci/setup-res.c:pbus_set_ranges().
+*/
+void pcibios_fixup_pbus_ranges(
+ struct pci_bus *bus,
+ struct pbus_set_ranges_data *ranges
+ )
+{
+ /*
+ ** I/O space may see busnumbers here. Something
+ ** in the form of 0xbbxxxx where bb is the bus num
+ ** and xxxx is the I/O port space address.
+ ** Remaining address translation are done in the
+ ** PCI Host adapter specific code - ie dino_out8.
+ */
+ ranges->io_start = PCI_PORT_ADDR(ranges->io_start);
+ ranges->io_end = PCI_PORT_ADDR(ranges->io_end);
+
+ DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n", bus->number,
+ ranges->io_start, ranges->io_end,
+ ranges->mem_start, ranges->mem_end);
+}
+
+#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
+
+
+/*
+** pcibios align resources() is called everytime generic PCI code
+** wants to generate a new address. The process of looking for
+** an available address, each candidate is first "aligned" and
+** then checked if the resource is available until a match is found.
+**
+** Since we are just checking candidates, don't use any fields other
+** than res->start.
+*/
+void __devinit
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+ unsigned long mask, align;
+
+ DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx)\n",
+ ((struct pci_dev *) data)->slot_name,
+ res->parent, res->start, res->end, (int) res->flags, size);
+
+ /* has resource already been aligned/assigned? */
+ if (res->parent)
+ return;
+
+ /* If it's not IO, then it's gotta be MEM */
+ align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
+
+ /* Align to largest of MIN or input size */
+ mask = MAX(size, align) - 1;
+ res->start += mask;
+ res->start &= ~mask;
+
+ /*
+ ** WARNING : caller is expected to update "end" field.
+ ** We can't since it might really represent the *size*.
+ ** The difference is "end = start + size" vs "end += size".
+ */
+}
+
+
+#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
+
+void __devinit
+pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
+{
+ struct pbus_set_ranges_data inner;
+ struct pci_dev *dev;
+ struct pci_dev *bridge = bus->self;
+ struct list_head *ln;
+
+ /* set reasonable default "window" for pcibios_align_resource */
+ inner.io_start = inner.io_end = 0;
+ inner.mem_start = inner.mem_end = 0;
+
+ /* Collect information about how our direct children are layed out. */
+ for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+ int i;
+ dev = pci_dev_b(ln);
+
+ /* Skip bridges here - we'll catch them below */
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ continue;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource res;
+ unsigned long size;
+
+ if (dev->resource[i].flags == 0)
+ continue;
+
+ memcpy(&res, &dev->resource[i], sizeof(res));
+ size = res.end - res.start + 1;
+
+ if (res.flags & IORESOURCE_IO) {
+ res.start = inner.io_end;
+ pcibios_align_resource(dev, &res, size);
+ inner.io_end += res.start + size;
+ } else if (res.flags & IORESOURCE_MEM) {
+ res.start = inner.mem_end;
+ pcibios_align_resource(dev, &res, size);
+ inner.mem_end = res.start + size;
+ }
+
+ DBG_RES(" %s inner size %lx/%x IO %lx MEM %lx\n",
+ dev->slot_name,
+ size, res.flags, inner.io_end, inner.mem_end);
+ }
+ }
+
+ /* And for all of the subordinate busses. */
+ for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
+ pcibios_size_bridge(pci_bus_b(ln), &inner);
+
+ /* turn the ending locations into sizes (subtract start) */
+ inner.io_end -= inner.io_start - 1;
+ inner.mem_end -= inner.mem_start - 1;
+
+ /* Align the sizes up by bridge rules */
+ inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1;
+ inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1;
+
+ /* PPB - PCI bridge Device will normaller also have "outer" != NULL. */
+ if (bridge) {
+ /* Adjust the bus' allocation requirements */
+ /* PPB's pci device Bridge resources */
+
+ bus->resource[0] = &bridge->resource[PCI_BRIDGE_RESOURCES];
+ bus->resource[1] = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
+
+ bus->resource[0]->start = bus->resource[1]->start = 0;
+ bus->resource[0]->parent= bus->resource[1]->parent = NULL;
+
+ bus->resource[0]->end = inner.io_end;
+ bus->resource[0]->flags = IORESOURCE_IO;
+
+ bus->resource[1]->end = inner.mem_end;
+ bus->resource[1]->flags = IORESOURCE_MEM;
+ }
+
+ /* adjust parent's resource requirements */
+ if (outer) {
+ outer->io_end = ROUND_UP(outer->io_end, 4*1024);
+ outer->io_end += inner.io_end;
+
+ outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024);
+ outer->mem_end += inner.mem_end;
+ }
+}
+
+#undef ROUND_UP
+
+
+int __devinit
+pcibios_enable_device(struct pci_dev *dev)
+{
+ u16 cmd, old_cmd;
+ int idx;
+
+ /*
+ ** The various platform PDC's (aka "BIOS" for PCs) don't
+ ** enable all the same bits. We just make sure they are here.
+ */
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+
+ /*
+ ** See if any resources have been allocated
+ */
+ for (idx=0; idx<6; idx++) {
+ struct resource *r = &dev->resource[idx];
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+
+ /*
+ ** System error and Parity Error reporting are enabled by default.
+ ** Devices that do NOT want those behaviors should clear them
+ ** (eg PCI graphics, possibly networking).
+ ** Interfaces like SCSI certainly should not. We want the
+ ** system to crash if a system or parity error is detected.
+ ** At least until the device driver can recover from such an error.
+ */
+ cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+
+ if (cmd != old_cmd) {
+ printk("PCIBIOS: Enabling device %s (%04x -> %04x)\n",
+ dev->slot_name, old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+
+ return 0;
+}
+
+
+void __devinit
+pcibios_assign_unassigned_resources(struct pci_bus *bus)
+{
+ struct list_head *ln;
+
+ for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next)
+ {
+ pdev_assign_unassigned_resources(pci_dev_b(ln));
+ }
+
+ /* And for all of the sub-busses. */
+ for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
+ pcibios_assign_unassigned_resources(pci_bus_b(ln));
+
+}
+
+/*
+** PARISC specific (unfortunately)
+*/
+void pcibios_register_hba(struct pci_hba_data *hba)
+{
+ hba->next = hba_list;
+ hba_list = hba;
+
+ ASSERT(hba_count < PCI_HBA_MAX);
+
+ /*
+ ** pci_port->in/out() uses parisc_pci_hba to lookup parameter.
+ */
+ parisc_pci_hba[hba_count] = hba;
+ hba->hba_num = hba_count++;
+}
diff --git a/arch/parisc/kernel/pdc.c b/arch/parisc/kernel/pdc.c
new file mode 100644
index 000000000..4fa4327c0
--- /dev/null
+++ b/arch/parisc/kernel/pdc.c
@@ -0,0 +1,217 @@
+/* arch/parisc/kernel/pdc.c - safe pdc access routines
+ *
+ * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org)
+ * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
+ *
+ * only these routines should be used out of the real kernel (i.e. everything
+ * using virtual addresses) for obvious reasons */
+
+/* I think it would be in everyone's best interest to follow this
+ * guidelines when writing PDC wrappers:
+ *
+ * - the name of the pdc wrapper should match one of the macros
+ * used for the first two arguments
+ * - don't use caps for random parts of the name
+ * - use ASSERT_ALIGN to ensure the aligment of the arguments is
+ * correct
+ * - use __pa() to convert virtual (kernel) pointers to physical
+ * ones.
+ * - the name of the struct used for pdc return values should equal
+ * one of the macros used for the first two arguments to the
+ * corresponding PDC call
+ * - keep the order of arguments
+ * - don't be smart (setting trailing NUL bytes for strings, return
+ * something useful even if the call failed) unless you are sure
+ * it's not going to affect functionality or performance
+ *
+ * Example:
+ * int pdc_cache_info(struct pdc_cache_info *cache_info )
+ * {
+ * ASSERT_ALIGN(cache_info, 8);
+ *
+ * return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
+ * }
+ * prumpf 991016
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/real.h>
+#include <asm/system.h>
+
+
+#define ASSERT_ALIGN(ptr, align) \
+ do { if(((unsigned long)(ptr)) & (align-1)) { \
+ printk("PDC: %s:%d %s() called with " \
+ "unaligned argument from %p", __FILE__, __LINE__, \
+ __FUNCTION__, __builtin_return_address(0)); \
+ \
+ return -1; \
+ } } while(0)
+
+/* verify address can be accessed without an HPMC */
+int pdc_add_valid(void *address)
+{
+ ASSERT_ALIGN(address, 4);
+
+ return mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, (unsigned long)address);
+}
+
+#if 0
+int pdc_chassis_warn(struct pdc_chassis_warn *address)
+{
+ ASSERT_ALIGN(address, 4);
+
+ return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(address), 0);
+}
+#endif
+
+int pdc_chassis_disp(unsigned long disp)
+{
+ return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
+}
+
+int pdc_chassis_info(void *pdc_result, void *chassis_info, unsigned long len)
+{
+ ASSERT_ALIGN(pdc_result, 4);
+ ASSERT_ALIGN(chassis_info, 4);
+ return mem_pdc_call(PDC_CHASSIS,PDC_RETURN_CHASSIS_INFO,
+ __pa(pdc_result), __pa(chassis_info), len);
+}
+
+int pdc_hpa_processor(void *address)
+{
+ /* We're using 0 for the last parameter just to make sure.
+ It's actually HVERSION dependant. And remember, life is
+ hard without a backspace. */
+ ASSERT_ALIGN(address, 4);
+
+ return mem_pdc_call(PDC_HPA, PDC_HPA_PROCESSOR, __pa(address),0);
+}
+
+#if 0
+int pdc_hpa_modules(void *address)
+{
+ return mem_pdc_call(PDC_HPA, PDC_HPA_MODULES, address);
+}
+#endif
+
+int pdc_iodc_read(void *address, void * hpa, unsigned int index,
+ void * iodc_data, unsigned int iodc_data_size)
+{
+ ASSERT_ALIGN(address, 4);
+ ASSERT_ALIGN(iodc_data, 8);
+ return mem_pdc_call(PDC_IODC, PDC_IODC_READ,
+ __pa(address), hpa, index, __pa(iodc_data), iodc_data_size);
+}
+
+
+int pdc_system_map_find_mods(void *pdc_mod_info,
+ void *mod_path, int index)
+{
+ return mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE,
+ __pa(pdc_mod_info), __pa(mod_path), (long)index);
+}
+
+
+int pdc_model_info(struct pdc_model *model) {
+ ASSERT_ALIGN(model, 8);
+ return mem_pdc_call(PDC_MODEL,PDC_MODEL_INFO,__pa(model),0);
+}
+
+/* get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) */
+int pdc_model_sysmodel(char * name)
+{
+ struct pdc_model_sysmodel sys_model;
+ int retval;
+
+ ASSERT_ALIGN(&sys_model, 8);
+ ASSERT_ALIGN(name, 4);
+
+ sys_model.mod_len = 0;
+ retval = mem_pdc_call(PDC_MODEL,PDC_MODEL_SYSMODEL,__pa(&sys_model),
+ OS_ID_HPUX,__pa(name));
+
+ if (retval == PDC_RET_OK)
+ name[sys_model.mod_len] = '\0'; /* add trailing '\0' */
+ else
+ name[0] = 0;
+
+ return retval;
+}
+
+/* id: 0 = cpu revision, 1 = boot-rom-version */
+int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id) {
+ return mem_pdc_call(PDC_MODEL,PDC_MODEL_VERSIONS,__pa(cpu_id),id);
+}
+
+int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id) {
+ cpu_id->cpuid = 0; /* preset zero (call maybe not implemented!) */
+ return mem_pdc_call(PDC_MODEL,6,__pa(cpu_id),0); /* 6="return CPU ID" */
+}
+
+int pdc_cache_info(struct pdc_cache_info *cache_info) {
+ ASSERT_ALIGN(cache_info, 8);
+
+ return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
+}
+
+#ifndef __LP64__
+int pdc_btlb_info( struct pdc_btlb_info *btlb ) {
+ int status;
+ status = mem_pdc_call(PDC_BLOCK_TLB,PDC_BTLB_INFO,__pa(btlb),0);
+ if (status<0) btlb->max_size = 0;
+ return status;
+}
+
+int pdc_mem_map_hpa(void *r_addr, void *mod_path) {
+ return mem_pdc_call(PDC_MEM_MAP,PDC_MEM_MAP_HPA,
+ __pa(r_addr),__pa(mod_path));
+}
+
+int pdc_lan_station_id(char *lan_addr, void *net_hpa) {
+ struct pdc_lan_station_id id;
+ unsigned char *addr;
+
+ if (mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
+ __pa(&id), net_hpa) < 0)
+ addr = 0; /* FIXME: else read MAC from NVRAM */
+ else
+ addr = id.addr;
+ if (addr)
+ memmove( lan_addr, addr, PDC_LAN_STATION_ID_SIZE);
+ else
+ memset( lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
+ return (addr != 0);
+}
+#endif
+
+
+/* Similar to PDC_PAT stuff in pdcpat.c - but added for Forte/Allegro boxes */
+int pdc_pci_irt_size(void *r_addr, void *hpa)
+{
+ return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE,
+ __pa(r_addr), hpa);
+
+}
+
+int pdc_pci_irt(void *r_addr, void *hpa, void *tbl)
+{
+ return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
+ __pa(r_addr), hpa, __pa(tbl));
+}
+
+/* access the TOD clock */
+int pdc_tod_read(struct pdc_tod *tod)
+{
+ ASSERT_ALIGN(tod, 8);
+ return mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(tod), 0);
+}
+
+int pdc_tod_set(unsigned long sec, unsigned long usec)
+{
+ return mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
+}
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
new file mode 100644
index 000000000..f2d45862b
--- /dev/null
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -0,0 +1,179 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/page.h>
+#include <asm/types.h>
+#include <asm/system.h>
+#include <asm/pdc.h> /* for iodc_call() proto and friends */
+#include <asm/real.h>
+
+static int __attribute__((aligned(8))) iodc_retbuf[32];
+static char __attribute__((aligned(64))) iodc_dbuf[4096];
+
+/*
+ * pdc_putc:
+ * Console character print using IODC.
+ *
+ * Note that only these special chars are architected for console IODC io:
+ * BEL, BS, CR, and LF. Others are passed through.
+ * Since the HP console requires CR+LF to perform a 'newline', we translate
+ * "\n" to "\r\n".
+ */
+
+static int posx; /* for simple TAB-Simulation... */
+
+/* XXX Should we spinlock posx usage */
+
+void pdc_putc(unsigned char c)
+{
+ unsigned int n;
+ unsigned long flags;
+
+ switch (c) {
+ case '\n':
+ iodc_dbuf[0] = '\r';
+ iodc_dbuf[1] = '\n';
+ n = 2;
+ posx = 0;
+ break;
+ case '\t':
+ pdc_putc(' ');
+ while (posx & 7) /* expand TAB */
+ pdc_putc(' ');
+ return; /* return since IODC can't handle this */
+ case '\b':
+ posx-=2; /* BS */
+ default:
+ iodc_dbuf[0] = c;
+ n = 1;
+ posx++;
+ break;
+ }
+ {
+ real32_call(PAGE0->mem_cons.iodc_io,
+ (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
+ PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
+ }
+}
+
+static void pdc_console_write(struct console *co, const char *s, unsigned count)
+{
+ while(count--)
+ pdc_putc(*s++);
+}
+
+int pdc_console_wait_key(struct console *co)
+{
+ int ch = 'X';
+ int status;
+
+ /* Bail if no console input device. */
+ if (!PAGE0->mem_kbd.iodc_io)
+ return 0;
+
+ /* wait for a keyboard (rs232)-input */
+ do {
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ status = real32_call(PAGE0->mem_kbd.iodc_io,
+ (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
+ PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
+ __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
+ restore_flags(flags);
+ ch = *iodc_dbuf; /* save the character directly to ch */
+ } while (*iodc_retbuf == 0); /* wait for a key */
+ return ch;
+}
+
+int pdc_getc(void)
+{
+ return pdc_console_wait_key(NULL);
+}
+
+static int pdc_console_setup(struct console *co, char *options)
+{
+ return 0;
+}
+
+static struct console pdc_cons = {
+ name: "ttyB",
+ write: pdc_console_write,
+ read: NULL,
+ device: NULL,
+ wait_key: pdc_console_wait_key,
+ unblank: NULL,
+ setup: pdc_console_setup,
+ flags: CON_PRINTBUFFER|CON_ENABLED, // |CON_CONSDEV,
+ index: -1,
+};
+
+static int pdc_console_initialized;
+
+void pdc_console_init(void)
+{
+ if (pdc_console_initialized)
+ return;
+ ++pdc_console_initialized;
+
+ /* If the console is duplex then copy the COUT parameters to CIN. */
+ if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
+ memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
+
+ pdc_console_write(0, "PDC Console Initialized\n", 24);
+ /* register the pdc console */
+ register_console(&pdc_cons);
+}
+
+
+/* Unregister the pdc console with the printk console layer */
+void pdc_console_die(void)
+{
+ printk("Switching from PDC console\n");
+ if (!pdc_console_initialized)
+ return;
+ --pdc_console_initialized;
+
+#ifdef CONFIG_VT_CONSOLE
+ {
+ /* fixme (needed?): Wait for console-tasklet to finish !*/
+ extern struct tasklet_struct console_tasklet;
+ tasklet_schedule(&console_tasklet);
+ }
+#endif
+
+ unregister_console(&pdc_cons);
+}
+
+
+/*
+ * Used for emergencies. Currently only used if an HPMC occurs. If an
+ * HPMC occurs, it is possible that the current console may not be
+ * properly initialed after the PDC IO reset. This routine unregisters all
+ * of the current consoles, reinitializes the pdc console and
+ * registers it.
+ */
+
+void pdc_console_restart(void)
+{
+ struct console *console;
+ extern int log_size;
+
+ if (pdc_console_initialized)
+ return;
+
+ while ((console = console_drivers) != (struct console *)0)
+ unregister_console(console_drivers);
+
+ log_size = 0;
+ pdc_console_init();
+ printk("Switched to PDC console\n");
+ return;
+}
+
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
new file mode 100644
index 000000000..a8d7a707e
--- /dev/null
+++ b/arch/parisc/kernel/process.c
@@ -0,0 +1,250 @@
+/*
+ * linux/arch/parisc/kernel/process.c
+ * based on the work for i386
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#define __KERNEL_SYSCALLS__
+#include <stdarg.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/elf.h>
+
+#include <asm/machdep.h>
+#include <asm/offset.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/gsc.h>
+#include <asm/processor.h>
+
+spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
+
+#ifdef __LP64__
+/* The 64-bit code should work equally well in 32-bit land but I didn't
+ * want to take the time to confirm that. -PB
+ */
+extern unsigned int ret_from_kernel_thread;
+#else
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
+#endif
+
+
+int hlt_counter=0;
+
+void disable_hlt(void)
+{
+ hlt_counter++;
+}
+
+void enable_hlt(void)
+{
+ hlt_counter--;
+}
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ init_idle();
+ current->nice = 20;
+ current->counter = -100;
+
+ while (1) {
+ while (!current->need_resched) {
+ }
+ schedule();
+ check_pgt_cache();
+ }
+}
+
+void __init reboot_setup(char *str, int *ints)
+{
+}
+
+struct notifier_block *mach_notifier;
+
+void machine_restart(char *ptr)
+{
+ notifier_call_chain(&mach_notifier, MACH_RESTART, ptr);
+}
+
+void machine_halt(void)
+{
+ notifier_call_chain(&mach_notifier, MACH_HALT, NULL);
+}
+
+void machine_power_on(void)
+{
+ notifier_call_chain(&mach_notifier, MACH_POWER_ON, NULL);
+}
+
+void machine_power_off(void)
+{
+ notifier_call_chain(&mach_notifier, MACH_POWER_OFF, NULL);
+}
+
+
+void machine_heartbeat(void)
+{
+}
+
+
+/*
+ * Create a kernel thread
+ */
+
+extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+
+ /*
+ * FIXME: Once we are sure we don't need any debug here,
+ * kernel_thread can become a #define.
+ */
+
+ return __kernel_thread(fn, arg, flags);
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+ set_fs(USER_DS);
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Fill in the FPU structure for a core dump.
+ */
+int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
+{
+ memcpy(r, regs->fr, sizeof *r);
+ return 1;
+}
+
+/* Note that "fork()" is implemented in terms of clone, with
+ parameters (SIGCHLD, regs->gr[30], regs). */
+int
+sys_clone(unsigned long clone_flags, unsigned long usp,
+ struct pt_regs *regs)
+{
+ return do_fork(clone_flags, usp, regs, 0);
+}
+
+int
+sys_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+ regs->gr[30], regs, 0);
+}
+
+int
+copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused, /* in ia64 this is "user_stack_size" */
+ struct task_struct * p, struct pt_regs * pregs)
+{
+ struct pt_regs * cregs = &(p->thread.regs);
+ long ksp;
+
+ *cregs = *pregs;
+
+ /* Set the return value for the child. Note that this is not
+ actually restored by the syscall exit path, but we put it
+ here for consistency in case of signals. */
+ cregs->gr[28] = 0; /* child */
+
+ /*
+ * We need to differentiate between a user fork and a
+ * kernel fork. We can't use user_mode, because the
+ * the syscall path doesn't save iaoq. Right now
+ * We rely on the fact that kernel_thread passes
+ * in zero for usp.
+ */
+ if (usp == 0) {
+ /* Kernel Thread */
+ ksp = (((unsigned long)(p)) + TASK_SZ_ALGN);
+ cregs->ksp = ksp; /* always return to kernel */
+#ifdef __LP64__
+ cregs->kpc = (unsigned long) &ret_from_kernel_thread;
+#else
+ cregs->kpc = (unsigned long) ret_from_kernel_thread;
+#endif
+
+ /*
+ * Copy function and argument to be called from
+ * ret_from_kernel_thread.
+ */
+ cregs->gr[26] = pregs->gr[26];
+ cregs->gr[25] = pregs->gr[25];
+
+ } else {
+ /* User Thread:
+ *
+ * Use same stack depth as parent when in wrapper
+ *
+ * Note that the fork wrappers are responsible
+ * for setting gr[20] and gr[21].
+ */
+
+ cregs->ksp = ((unsigned long)(p))
+ + (pregs->gr[20] & (INIT_TASK_SIZE - 1));
+ cregs->kpc = pregs->gr[21];
+ }
+
+ return 0;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+
+asmlinkage int sys_execve(struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname((char *) regs->gr[26]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, (char **) regs->gr[25],
+ (char **) regs->gr[24], regs);
+ if (error == 0)
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+out:
+
+ return error;
+}
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
new file mode 100644
index 000000000..176b4386a
--- /dev/null
+++ b/arch/parisc/kernel/ptrace.c
@@ -0,0 +1,305 @@
+/*
+ * Kernel support for the ptrace() and syscall tracing interfaces.
+ *
+ * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc.
+ * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/offset.h>
+
+/* These are used in entry.S, syscall_restore_rfi. We need to record the
+ * current stepping mode somewhere other than in PSW, because there is no
+ * concept of saving and restoring the users PSW over a syscall. We choose
+ * to use these two bits in task->ptrace. These bits must not clash with
+ * any PT_* defined in include/linux/sched.h, and must match with the bit
+ * tests in entry.S
+ */
+#define PT_SINGLESTEP 0x10000
+#define PT_BLOCKSTEP 0x20000
+
+long sys_ptrace(long request, pid_t pid, long addr, long data)
+{
+ struct task_struct *child;
+ long ret;
+
+ lock_kernel();
+ ret = -EPERM;
+ if (request == PTRACE_TRACEME) {
+ /* are we already being traced? */
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+ /* set the ptrace bit in the process flags. */
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+ ret = -EPERM;
+ if (pid == 1) /* no messing around with init! */
+ goto out_tsk;
+
+ if (request == PTRACE_ATTACH) {
+ if (child == current)
+ goto out_tsk;
+ if ((!child->dumpable ||
+ (current->uid != child->euid) ||
+ (current->uid != child->suid) ||
+ (current->uid != child->uid) ||
+ (current->gid != child->egid) ||
+ (current->gid != child->sgid) ||
+ (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ goto out_tsk;
+ /* the same process cannot be attached many times */
+ if (child->ptrace & PT_PTRACED)
+ goto out_tsk;
+ child->ptrace |= PT_PTRACED;
+ if (child->p_pptr != current) {
+ unsigned long flags;
+
+ write_lock_irqsave(&tasklist_lock, flags);
+ REMOVE_LINKS(child);
+ child->p_pptr = current;
+ SET_LINKS(child);
+ write_unlock_irqrestore(&tasklist_lock, flags);
+ }
+ send_sig(SIGSTOP, child, 1);
+ ret = 0;
+ goto out_tsk;
+ }
+ ret = -ESRCH;
+ if (!(child->ptrace & PT_PTRACED))
+ goto out_tsk;
+ if (child->state != TASK_STOPPED) {
+ if (request != PTRACE_KILL)
+ goto out_tsk;
+ }
+ if (child->p_pptr != current)
+ goto out_tsk;
+
+ switch (request) {
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ goto out_tsk;
+ ret = put_user(tmp,(unsigned long *) data);
+ goto out_tsk;
+ }
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ ret = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+ goto out_tsk;
+ ret = -EIO;
+ goto out_tsk;
+
+ /* Read the word at location addr in the USER area. This will need
+ to change when the kernel no longer saves all regs on a syscall. */
+ case PTRACE_PEEKUSR: {
+ unsigned long tmp;
+
+ ret = -EIO;
+ if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs))
+ goto out_tsk;
+
+ tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
+ ret = put_user(tmp, (unsigned long *) data);
+ goto out_tsk;
+ }
+
+ /* Write the word at location addr in the USER area. This will need
+ to change when the kernel no longer saves all regs on a syscall.
+ FIXME. There is a problem at the moment in that r3-r18 are only
+ saved if the process is ptraced on syscall entry, and even then
+ those values are overwritten by actual register values on syscall
+ exit. */
+ case PTRACE_POKEUSR:
+ ret = -EIO;
+ if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs))
+ goto out_tsk;
+ /* XXX This test probably needs adjusting. We probably want to
+ * allow writes to some bits of PSW, and may want to block writes
+ * to (some) space registers. Some register values written here
+ * may be ignored in entry.S:syscall_restore_rfi; e.g. iaoq is
+ * written with r31/r31+4, and not with the values in pt_regs.
+ */
+ /* Allow writing of gr1-gr31, fr*, sr*, iasq*, iaoq*, sar */
+ if (addr == PT_PSW || (addr > PT_IAOQ1 && addr != PT_SAR))
+ goto out_tsk;
+
+ *(unsigned long *) ((char *) task_regs(child) + addr) = data;
+ ret = 0;
+ goto out_tsk;
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
+ if (request == PTRACE_SYSCALL)
+ child->ptrace |= PT_TRACESYS;
+ else
+ child->ptrace &= ~PT_TRACESYS;
+ child->exit_code = data;
+ goto out_wake_notrap;
+
+ case PTRACE_KILL:
+ /*
+ * 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.
+ */
+ if (child->state == TASK_ZOMBIE) /* already dead */
+ goto out_tsk;
+ child->exit_code = SIGKILL;
+ goto out_wake_notrap;
+
+ case PTRACE_SINGLEBLOCK:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_TRACESYS|PT_SINGLESTEP);
+ child->ptrace |= PT_BLOCKSTEP;
+ child->exit_code = data;
+
+ /* Enable taken branch trap. */
+ pa_psw(child)->r = 0;
+ pa_psw(child)->t = 1;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+ goto out_wake;
+
+ case PTRACE_SINGLESTEP:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_TRACESYS|PT_BLOCKSTEP);
+ child->ptrace |= PT_SINGLESTEP;
+ child->exit_code = data;
+
+ if (pa_psw(child)->n) {
+ struct siginfo si;
+
+ /* Nullified, just crank over the queue. */
+ task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1];
+ task_regs(child)->iasq[0] = task_regs(child)->iasq[1];
+ task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4;
+ pa_psw(child)->n = 0;
+ pa_psw(child)->x = 0;
+ pa_psw(child)->y = 0;
+ pa_psw(child)->z = 0;
+ pa_psw(child)->b = 0;
+ pa_psw(child)->r = 0;
+ pa_psw(child)->t = 0;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+ /* Don't wake up the child, but let the
+ parent know something happened. */
+ si.si_code = TRAP_TRACE;
+ si.si_addr = (void *) (task_regs(child)->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ si.si_errno = 0;
+ force_sig_info(SIGTRAP, &si, child);
+ //notify_parent(child, SIGCHLD);
+ //ret = 0;
+ goto out_wake;
+ }
+
+ /* Enable recovery counter traps. The recovery counter
+ * itself will be set to zero on a task switch. If the
+ * task is suspended on a syscall then the syscall return
+ * path will overwrite the recovery counter with a suitable
+ * value such that it traps once back in user space. We
+ * disable interrupts in the childs PSW here also, to avoid
+ * interrupts while the recovery counter is decrementing.
+ */
+ pa_psw(child)->r = 1;
+ pa_psw(child)->t = 0;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+ /* give it a chance to run. */
+ goto out_wake;
+
+ case PTRACE_DETACH:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ goto out_tsk;
+ child->ptrace &= ~(PT_PTRACED|PT_TRACESYS|PT_SINGLESTEP|PT_BLOCKSTEP);
+ child->exit_code = data;
+ write_lock_irq(&tasklist_lock);
+ REMOVE_LINKS(child);
+ child->p_pptr = child->p_opptr;
+ SET_LINKS(child);
+ write_unlock_irq(&tasklist_lock);
+ goto out_wake_notrap;
+
+ default:
+ ret = -EIO;
+ goto out_tsk;
+ }
+
+out_wake_notrap:
+ /* make sure the trap bits are not set */
+ pa_psw(child)->r = 0;
+ pa_psw(child)->t = 0;
+ pa_psw(child)->h = 0;
+ pa_psw(child)->l = 0;
+out_wake:
+ wake_up_process(child);
+ ret = 0;
+out_tsk:
+ free_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
+
+void syscall_trace(void)
+{
+ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) !=
+ (PT_PTRACED|PT_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 --git a/arch/parisc/kernel/real1.c b/arch/parisc/kernel/real1.c
new file mode 100644
index 000000000..2bb26bc88
--- /dev/null
+++ b/arch/parisc/kernel/real1.c
@@ -0,0 +1,154 @@
+/*
+ *
+ * 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) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
+ *
+ * most of these calls might reasonably be moved to ../kernel -PB
+ *
+ * The basic principle is to construct a stack frame in C then call
+ * some assembly which adopts that stack, does some rfi magic, may
+ * switch wide/narrow mode, and calls the routine described by the
+ * 'fn' parameter WHICH IS NOT A FUNCTION POINTER!!!!!!!!!!!!!!!!
+ */
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <stdarg.h>
+#include <asm/pgtable.h> /* for __pa() */
+#include <asm/pdc.h>
+
+static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
+
+/***************** 32-bit real-mode calls ***********/
+/* The struct below is used
+ * to overlay real_stack (real2.S), preparing a 32-bit call frame.
+ * real32_call_asm() then uses this stack in narrow real mode
+ */
+
+struct narrow_stack {
+ /* use int, not long which is 64 bits */
+ unsigned int arg13;
+ unsigned int arg12;
+ unsigned int arg11;
+ unsigned int arg10;
+ unsigned int arg9;
+ unsigned int arg8;
+ unsigned int arg7;
+ unsigned int arg6;
+ unsigned int arg5;
+ unsigned int arg4;
+ unsigned int arg3;
+ unsigned int arg2;
+ unsigned int arg1;
+ unsigned int arg0;
+ unsigned int frame_marker[8];
+ unsigned int sp;
+ /* in reality, there's nearly 8k of stack after this */
+};
+
+long
+real32_call(unsigned long fn, ...)
+{
+ unsigned long r;
+ va_list args;
+ unsigned long flags;
+ extern struct narrow_stack real_stack;
+ extern unsigned long real32_call_asm(unsigned int *,
+ unsigned int *, unsigned int);
+
+ va_start(args, fn);
+ real_stack.arg0 = va_arg(args, unsigned int);
+ real_stack.arg1 = va_arg(args, unsigned int);
+ real_stack.arg2 = va_arg(args, unsigned int);
+ real_stack.arg3 = va_arg(args, unsigned int);
+ real_stack.arg4 = va_arg(args, unsigned int);
+ real_stack.arg5 = va_arg(args, unsigned int);
+ real_stack.arg6 = va_arg(args, unsigned int);
+ real_stack.arg7 = va_arg(args, unsigned int);
+ real_stack.arg8 = va_arg(args, unsigned int);
+ real_stack.arg9 = va_arg(args, unsigned int);
+ real_stack.arg10 = va_arg(args, unsigned int);
+ real_stack.arg11 = va_arg(args, unsigned int);
+ real_stack.arg12 = va_arg(args, unsigned int);
+ real_stack.arg13 = va_arg(args, unsigned int);
+ va_end(args);
+
+ if (fn == 0) {
+ /* mem_pdc call */
+ fn = PAGE0->mem_pdc;
+ }
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ r = real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
+ spin_unlock_irqrestore(&pdc_lock, flags);
+
+ return r;
+}
+
+#ifdef __LP64__
+/***************** 64-bit real-mode calls ***********/
+
+struct wide_stack {
+ unsigned long arg0;
+ unsigned long arg1;
+ unsigned long arg2;
+ unsigned long arg3;
+ unsigned long arg4;
+ unsigned long arg5;
+ unsigned long arg6;
+ unsigned long arg7;
+ unsigned long arg8;
+ unsigned long arg9;
+ unsigned long arg10;
+ unsigned long arg11;
+ unsigned long arg12;
+ unsigned long arg13;
+ unsigned long frame_marker[2]; /* rp, previous sp */
+ unsigned long sp;
+ /* in reality, there's nearly 8k of stack after this */
+};
+
+long
+real64_call(unsigned long fn, ...)
+{
+ unsigned long r;
+ va_list args;
+ unsigned long flags;
+ extern struct wide_stack real_stack;
+ extern unsigned long real64_call_asm(unsigned long *,
+ unsigned long *, unsigned long);
+
+ va_start(args, fn);
+ real_stack.arg0 = va_arg(args, unsigned long);
+ real_stack.arg1 = va_arg(args, unsigned long);
+ real_stack.arg2 = va_arg(args, unsigned long);
+ real_stack.arg3 = va_arg(args, unsigned long);
+ real_stack.arg4 = va_arg(args, unsigned long);
+ real_stack.arg5 = va_arg(args, unsigned long);
+ real_stack.arg6 = va_arg(args, unsigned long);
+ real_stack.arg7 = va_arg(args, unsigned long);
+ real_stack.arg8 = va_arg(args, unsigned long);
+ real_stack.arg9 = va_arg(args, unsigned long);
+ real_stack.arg10 = va_arg(args, unsigned long);
+ real_stack.arg11 = va_arg(args, unsigned long);
+ real_stack.arg12 = va_arg(args, unsigned long);
+ real_stack.arg13 = va_arg(args, unsigned long);
+ va_end(args);
+
+ if (fn == 0) {
+ /* mem_pdc call */
+ fn = PAGE0->mem_pdc_hi;
+ fn <<= 32;
+ fn |= PAGE0->mem_pdc;
+ }
+
+ spin_lock_irqsave(&pdc_lock, flags);
+ r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn);
+ spin_unlock_irqrestore(&pdc_lock, flags);
+
+ return r;
+}
+
+#endif
diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S
new file mode 100644
index 000000000..eb1425ec4
--- /dev/null
+++ b/arch/parisc/kernel/real2.S
@@ -0,0 +1,274 @@
+/*
+ *
+ * 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) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
+ *
+ */
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/psw.h>
+
+ .section .bss
+ .export real_stack
+ .align 64
+real_stack:
+ .block 8192
+
+#ifdef __LP64__
+# define REG_SZ 8
+#else
+# define REG_SZ 4
+#endif
+
+#define N_SAVED_REGS 9
+
+save_cr_space:
+ .block REG_SZ * N_SAVED_REGS
+
+
+/************************ 32-bit real-mode calls ***********************/
+/* This can be called in both narrow and wide kernels */
+ .text
+ .export real32_call_asm
+ /* unsigned long real32_call_asm(unsigned int *sp,
+ * unsigned int *arg0p,
+ * unsigned int iodc_fn)
+ * sp is value of stack pointer to adopt before calling PDC (virt)
+ * arg0p points to where saved arg values may be found
+ * iodc_fn is the IODC function to call
+ */
+real32_call_asm:
+ STREG %rp, -RP_OFFSET(%sp) /* save RP */
+#ifdef __LP64__
+ callee_save
+ ldo 2*REG_SZ(%sp), %sp /* room for a couple more saves */
+ STREG %r27, -1*REG_SZ(%sp)
+ STREG %r29, -2*REG_SZ(%sp)
+#endif
+ STREG %sp, -REG_SZ(%arg0) /* save SP on real-mode stack */
+ copy %arg0, %sp /* adopt the real-mode SP */
+
+ /* save iodc_fn */
+ copy %arg2, %r31
+
+ /* load up the arg registers from the saved arg area */
+ /* 32-bit calling convention passes first 4 args in registers */
+ ldw 0(%arg1), %arg0 /* note overwriting arg0 */
+ ldw -8(%arg1), %arg2
+ ldw -12(%arg1), %arg3
+ ldw -4(%arg1), %arg1 /* obviously must do this one last! */
+
+ tophys %sp
+
+ b,l rfi_virt2real,%r2
+ nop
+
+ b,l save_control_regs,%r2 /* modifies r1, r2, r28 */
+ nop
+
+#ifdef __LP64__
+ rsm PSW_SM_W, %r0 /* go narrow */
+#endif
+
+ ldil L%PA(ric_ret), %r2
+ ldo R%PA(ric_ret)(%r2), %r2
+ bv 0(%r31)
+ nop
+ric_ret:
+#ifdef __LP64__
+ ssm PSW_SM_W, %r0 /* go wide */
+#endif
+ /* restore CRs before going virtual in case we page fault */
+ b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */
+ nop
+
+ b,l rfi_real2virt,%r2
+ nop
+
+ tovirt %sp
+ LDREG -REG_SZ(%sp), %sp /* restore SP */
+#ifdef __LP64__
+ LDREG -1*REG_SZ(%sp), %r27
+ LDREG -2*REG_SZ(%sp), %r29
+ ldo -2*REG_SZ(%sp), %sp
+ callee_rest
+#endif
+ LDREG -RP_OFFSET(%sp), %rp /* restore RP */
+ bv 0(%rp)
+ nop
+
+
+# define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where)
+# define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r
+
+ .text
+save_control_regs:
+ load32 PA(save_cr_space), %r28
+ PUSH_CR(%cr24, %r28)
+ PUSH_CR(%cr25, %r28)
+ PUSH_CR(%cr26, %r28)
+ PUSH_CR(%cr27, %r28)
+ PUSH_CR(%cr28, %r28)
+ PUSH_CR(%cr29, %r28)
+ PUSH_CR(%cr30, %r28)
+ PUSH_CR(%cr31, %r28)
+ PUSH_CR(%cr15, %r28)
+ bv 0(%r2)
+ nop
+
+restore_control_regs:
+ load32 PA(save_cr_space + (N_SAVED_REGS * REG_SZ)), %r26
+ POP_CR(%cr15, %r26)
+ POP_CR(%cr31, %r26)
+ POP_CR(%cr30, %r26)
+ POP_CR(%cr29, %r26)
+ POP_CR(%cr28, %r26)
+ POP_CR(%cr27, %r26)
+ POP_CR(%cr26, %r26)
+ POP_CR(%cr25, %r26)
+ POP_CR(%cr24, %r26)
+ bv 0(%r2)
+ nop
+
+/* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for
+ * more general-purpose use by the several places which need RFIs
+ */
+ .align 128
+ .text
+rfi_virt2real:
+ /* switch to real mode... */
+ ssm 0,0 /* See "relied upon translation" */
+ nop /* comment in interruption.S */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mtsm 0 /* disable interruptions */
+ mtctl 0, %cr17 /* space 0 */
+ mtctl 0, %cr17
+ load32 PA(rfi_v2r_1), %r1
+ mtctl %r1, %cr18
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18
+ load32 PDC_PSW, %r1
+ mtctl %r1, %cr22
+ rfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+rfi_v2r_1:
+ tophys %r2
+ bv 0(%r2)
+ nop
+
+ .text
+ .align 128
+rfi_real2virt:
+ ssm 0,0 /* See "relied upon translation" */
+ nop /* comment in interruption.S */
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+ mtsm 0 /* disable interruptions */
+ mtctl 0, %cr17 /* space 0 */
+ mtctl 0, %cr17
+ load32 (rfi_r2v_1), %r1
+ mtctl %r1, %cr18
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18
+ load32 KERNEL_PSW, %r1
+ mtctl %r1, %cr22
+ rfi
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+rfi_r2v_1:
+ tovirt %r2
+ bv 0(%r2)
+ nop
+
+#ifdef __LP64__
+
+/************************ 64-bit real-mode calls ***********************/
+/* This is only usable in wide kernels right now and will probably stay so */
+ .text
+ .export real64_call_asm
+ /* unsigned long real64_call_asm(unsigned long *sp,
+ * unsigned long *arg0p,
+ * unsigned long fn)
+ * sp is value of stack pointer to adopt before calling PDC (virt)
+ * arg0p points to where saved arg values may be found
+ * iodc_fn is the IODC function to call
+ */
+real64_call_asm:
+ std %rp, -0x10(%sp) /* save RP */
+ std %sp, -8(%arg0) /* save SP on real-mode stack */
+ copy %arg0, %sp /* adopt the real-mode SP */
+
+ /* save fn */
+ copy %arg2, %r31
+
+ /* set up the new ap */
+ ldo 64(%arg1), %r29
+
+ /* load up the arg registers from the saved arg area */
+ /* 32-bit calling convention passes first 4 args in registers */
+ ldd 0*REG_SZ(%arg1), %arg0 /* note overwriting arg0 */
+ ldd 2*REG_SZ(%arg1), %arg2
+ ldd 3*REG_SZ(%arg1), %arg3
+ ldd 4*REG_SZ(%arg1), %r22
+ ldd 5*REG_SZ(%arg1), %r21
+ ldd 6*REG_SZ(%arg1), %r20
+ ldd 7*REG_SZ(%arg1), %r19
+ ldd 1*REG_SZ(%arg1), %arg1 /* do this one last! */
+
+ tophys %sp
+
+ b,l rfi_virt2real,%r2
+ nop
+
+ b,l save_control_regs,%r2 /* modifies r1, r2, r28 */
+ nop
+
+ load32 PA(r64_ret), %r2
+ bv 0(%r31)
+ nop
+r64_ret:
+ /* restore CRs before going virtual in case we page fault */
+ b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */
+ nop
+
+ b,l rfi_real2virt,%r2
+ nop
+
+ tovirt %sp
+ ldd -8(%sp), %sp /* restore SP */
+ ldd -0x10(%sp), %rp /* restore RP */
+ bv 0(%rp)
+ nop
+
+#endif
diff --git a/arch/parisc/kernel/sba_iommu.c b/arch/parisc/kernel/sba_iommu.c
new file mode 100644
index 000000000..b7b541478
--- /dev/null
+++ b/arch/parisc/kernel/sba_iommu.c
@@ -0,0 +1,1752 @@
+/*
+** System Bus Adapter (SBA) I/O MMU manager
+**
+** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2000 Hewlett-Packard Company
+**
+** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code)
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+**
+** This module initializes the IOC (I/O Controller) found on B1000/C3000/
+** J5000/J7000/N-class/L-class machines and their successors.
+**
+** FIXME: Multi-IOC support missing - depends on hp_device data
+** FIXME: add DMA hint support programming in both sba and lba modules.
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <linux/mm.h>
+#include <linux/string.h>
+#define PCI_DEBUG /* for ASSERT */
+#include <linux/pci.h>
+#undef PCI_DEBUG
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/dma.h> /* for DMA_CHUNK_SIZE */
+
+#include <asm/hardware.h> /* for register_driver() stuff */
+#include <asm/gsc.h> /* FIXME: for gsc_read/gsc_write */
+
+#include <linux/proc_fs.h>
+#include <asm/runway.h> /* for proc_runway_root */
+
+
+#define MODULE_NAME "SBA"
+
+/*
+** The number of debug flags is a clue - this code is fragile.
+** Don't even think about messing with it unless you have
+** plenty of 710's to sacrafice to the computer gods. :^)
+*/
+#undef DEBUG_SBA_INIT
+#undef DEBUG_SBA_RUN
+#undef DEBUG_SBA_RUN_SG
+#undef DEBUG_SBA_RESOURCE
+#undef ASSERT_PDIR_SANITY
+#undef DEBUG_LARGE_SG_ENTRIES
+
+#if 1
+#define SBA_INLINE
+#else
+#define SBA_INLINE __inline__
+#endif
+
+#ifdef DEBUG_SBA_INIT
+#define DBG_INIT(x...) printk(x)
+#else
+#define DBG_INIT(x...)
+#endif
+
+#ifdef DEBUG_SBA_RUN
+#define DBG_RUN(x...) printk(x)
+#else
+#define DBG_RUN(x...)
+#endif
+
+#ifdef DEBUG_SBA_RUN_SG
+#define DBG_RUN_SG(x...) printk(x)
+#else
+#define DBG_RUN_SG(x...)
+#endif
+
+
+#ifdef DEBUG_SBA_RESOURCE
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+/*
+** The number of pdir entries to "free" before issueing
+** a read to PCOM register to flush out PCOM writes.
+** Interacts with allocation granularity (ie 4 or 8 entries
+** allocated and free'd/purged at a time might make this
+** less interesting).
+*/
+#if 0
+#define DELAYED_RESOURCE_CNT 16
+#else
+#undef DELAYED_RESOURCE_CNT
+#endif
+
+#define DEFAULT_DMA_HINT_REG 0
+
+#define ASTRO_RUNWAY_PORT 0x582
+#define ASTRO_ROPES_PORT 0x780
+
+#define IKE_MERCED_PORT 0x803
+#define IKE_ROPES_PORT 0x781
+
+int sba_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+static struct pa_iodc_driver sba_drivers_for[] = {
+
+/* FIXME: why is SVERSION checked? */
+
+ {HPHW_IOA, ASTRO_RUNWAY_PORT, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
+
+ {HPHW_BCPORT, ASTRO_ROPES_PORT, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
+
+#if 0
+/* FIXME : N-class! Use a different "callback"? */
+ {HPHW_BCPORT, IKE_MERCED_PORT, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
+
+ {HPHW_BCPORT, IKE_ROPES_PORT, 0x0, 0xb, 0, 0x10,
+ DRIVER_CHECK_HVERSION +
+ DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
+ MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
+#endif
+
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL }
+};
+
+
+#define SBA_FUNC_ID 0x0000 /* function id */
+#define SBA_FCLASS 0x0008 /* function class, bist, header, rev... */
+
+#define IS_ASTRO(id) ( \
+ (((id)->hw_type == HPHW_IOA) && ((id)->hversion == ASTRO_RUNWAY_PORT)) || \
+ (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == ASTRO_ROPES_PORT)) \
+)
+
+#define CONFIG_FUNC_SIZE 4096 /* SBA configuration function reg set */
+
+#define ASTRO_IOC_OFFSET 0x20000
+/* Ike's IOC's occupy functions 2 and 3 (not 0 and 1) */
+#define IKE_IOC_OFFSET(p) ((p+2)*CONFIG_FUNC_SIZE)
+
+#define IOC_CTRL 0x8 /* IOC_CTRL offset */
+#define IOC_CTRL_TE (0x1 << 0) /* TOC Enable */
+#define IOC_CTRL_RM (0x1 << 8) /* Real Mode */
+#define IOC_CTRL_NC (0x1 << 9) /* Non Coherent Mode */
+
+#define MAX_IOC 2 /* per Ike. Astro only has 1 */
+
+
+/*
+** Offsets into MBIB (Function 0 on Ike and hopefully Astro)
+** Firmware programs this stuff. Don't touch it.
+*/
+#define IOS_DIST_BASE 0x390
+#define IOS_DIST_MASK 0x398
+#define IOS_DIST_ROUTE 0x3A0
+
+#define IOS_DIRECT_BASE 0x3C0
+#define IOS_DIRECT_MASK 0x3C8
+#define IOS_DIRECT_ROUTE 0x3D0
+
+/*
+** Offsets into I/O TLB (Function 2 and 3 on Ike)
+*/
+#define ROPE0_CTL 0x200 /* "regbus pci0" */
+#define ROPE1_CTL 0x208
+#define ROPE2_CTL 0x210
+#define ROPE3_CTL 0x218
+#define ROPE4_CTL 0x220
+#define ROPE5_CTL 0x228
+#define ROPE6_CTL 0x230
+#define ROPE7_CTL 0x238
+
+#define HF_ENABLE 0x40
+
+
+#define IOC_IBASE 0x300 /* IO TLB */
+#define IOC_IMASK 0x308
+#define IOC_PCOM 0x310
+#define IOC_TCNFG 0x318
+#define IOC_PDIR_BASE 0x320
+
+#define IOC_IOVA_SPACE_BASE 0 /* IOVA ranges start at 0 */
+
+/*
+** IOC supports 4/8/16/64KB page sizes (see TCNFG register)
+** It's safer (avoid memory corruption) to keep DMA page mappings
+** equivalently sized to VM PAGE_SIZE.
+**
+** We really can't avoid generating a new mapping for each
+** page since the Virtual Coherence Index has to be generated
+** and updated for each page.
+**
+** IOVP_SIZE could only be greater than PAGE_SIZE if we are
+** confident the drivers really only touch the next physical
+** page iff that driver instance owns it.
+*/
+#define IOVP_SIZE PAGE_SIZE
+#define IOVP_SHIFT PAGE_SHIFT
+#define IOVP_MASK PAGE_MASK
+
+#define SBA_PERF_CFG 0x708 /* Performance Counter stuff */
+#define SBA_PERF_MASK1 0x718
+#define SBA_PERF_MASK2 0x730
+
+
+/*
+** Offsets into PCI Performance Counters (functions 12 and 13)
+** Controlled by PERF registers in function 2 & 3 respectively.
+*/
+#define SBA_PERF_CNT1 0x200
+#define SBA_PERF_CNT2 0x208
+#define SBA_PERF_CNT3 0x210
+
+
+struct ioc {
+ char *ioc_hpa; /* I/O MMU base address */
+ char *res_map; /* resource map, bit == pdir entry */
+ u64 *pdir_base; /* physical base address */
+
+ unsigned long *res_hint; /* next available IOVP - circular search */
+ unsigned int res_bitshift; /* from the LEFT! */
+ unsigned int res_size; /* size of resource map in bytes */
+ unsigned int hint_shift_pdir;
+ spinlock_t res_lock;
+ unsigned long hint_mask_pdir; /* bits used for DMA hints */
+#ifdef DELAYED_RESOURCE_CNT
+ dma_addr_t res_delay[DELAYED_RESOURCE_CNT];
+#endif
+
+#ifdef CONFIG_PROC_FS
+#define SBA_SEARCH_SAMPLE 0x100
+ unsigned long avg_search[SBA_SEARCH_SAMPLE];
+ unsigned long avg_idx; /* current index into avg_search */
+ unsigned long used_pages;
+ unsigned long msingle_calls;
+ unsigned long msingle_pages;
+ unsigned long msg_calls;
+ unsigned long msg_pages;
+ unsigned long usingle_calls;
+ unsigned long usingle_pages;
+ unsigned long usg_calls;
+ unsigned long usg_pages;
+#endif
+
+ /* STUFF We don't need in performance path */
+ unsigned int pdir_size; /* in bytes, determined by IOV Space size */
+ unsigned long ibase; /* pdir IOV Space base - shared w/lba_pci */
+ unsigned long imask; /* pdir IOV Space mask - shared w/lba_pci */
+};
+
+struct sba_device {
+ struct sba_device *next; /* list of LBA's in system */
+ struct hp_device *iodc; /* data about dev from firmware */
+ char *sba_hpa; /* base address */
+ spinlock_t sba_lock;
+ unsigned int flags; /* state/functionality enabled */
+ unsigned int hw_rev; /* HW revision of chip */
+
+ unsigned int num_ioc; /* number of on-board IOC's */
+ struct ioc ioc[MAX_IOC];
+};
+
+
+static struct sba_device *sba_list;
+static int sba_count;
+
+/* Ratio of Host MEM to IOV Space size */
+static unsigned long sba_mem_ratio = 4;
+
+/* Looks nice and keeps the compiler happy */
+#define SBA_DEV(d) ((struct sba_device *) (d))
+
+
+#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
+
+
+/************************************
+** SBA register read and write support
+**
+** BE WARNED: register writes are posted.
+** (ie follow writes which must reach HW with a read)
+*/
+#define READ_U8(addr) gsc_readb(addr)
+#define READ_U16(addr) gsc_readw((u16 *) (addr))
+#define READ_U32(addr) gsc_readl((u32 *) (addr))
+#define WRITE_U8(value, addr) gsc_writeb(value, addr)
+#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr))
+#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
+
+#define READ_REG8(addr) gsc_readb(addr)
+#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
+#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
+#define READ_REG64(addr) le64_to_cpu(gsc_readq((u64 *) (addr)))
+#define WRITE_REG8(value, addr) gsc_writeb(value, addr)
+#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
+#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
+#define WRITE_REG64(value, addr) gsc_writeq(cpu_to_le64(value), (u64 *) (addr))
+
+#ifdef DEBUG_SBA_INIT
+
+static void
+sba_dump_ranges(char *hpa)
+{
+ printk("SBA at 0x%p\n", hpa);
+ printk("IOS_DIST_BASE : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIST_BASE+4),
+ READ_REG32(hpa+IOS_DIST_BASE));
+ printk("IOS_DIST_MASK : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIST_MASK+4),
+ READ_REG32(hpa+IOS_DIST_MASK));
+ printk("IOS_DIST_ROUTE : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIST_ROUTE+4),
+ READ_REG32(hpa+IOS_DIST_ROUTE));
+ printk("\n");
+ printk("IOS_DIRECT_BASE : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIRECT_BASE+4),
+ READ_REG32(hpa+IOS_DIRECT_BASE));
+ printk("IOS_DIRECT_MASK : %08x %08x\n",
+ READ_REG32(hpa+IOS_DIRECT_MASK+4),
+ READ_REG32(hpa+IOS_DIRECT_MASK));
+ printk("IOS_DIRECT_ROUTE: %08x %08x\n",
+ READ_REG32(hpa+IOS_DIRECT_ROUTE+4),
+ READ_REG32(hpa+IOS_DIRECT_ROUTE));
+}
+
+static void
+sba_dump_tlb(char *hpa)
+{
+ printk("IO TLB at 0x%p\n", hpa);
+ printk("IOC_IBASE : %08x %08x\n",
+ READ_REG32(hpa+IOC_IBASE+4),
+ READ_REG32(hpa+IOC_IBASE));
+ printk("IOC_IMASK : %08x %08x\n",
+ READ_REG32(hpa+IOC_IMASK+4),
+ READ_REG32(hpa+IOC_IMASK));
+ printk("IOC_TCNFG : %08x %08x\n",
+ READ_REG32(hpa+IOC_TCNFG+4),
+ READ_REG32(hpa+IOC_TCNFG));
+ printk("IOC_PDIR_BASE: %08x %08x\n",
+ READ_REG32(hpa+IOC_PDIR_BASE+4),
+ READ_REG32(hpa+IOC_PDIR_BASE));
+ printk("\n");
+}
+#endif
+
+
+#ifdef ASSERT_PDIR_SANITY
+
+static void
+sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide)
+{
+ /* start printing from lowest pde in rval */
+ u64 *ptr = &(ioc->pdir_base[pide & (~0U * BITS_PER_LONG)]);
+ unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]);
+ uint rcnt;
+
+ printk("SBA: %s rp %p bit %d rval 0x%lx\n",
+ msg,
+ rptr, pide & (BITS_PER_LONG - 1), *rptr);
+
+ rcnt = 0;
+ while (rcnt < BITS_PER_LONG) {
+ printk("%s %2d %p %016Lx\n",
+ (rcnt == (pide & (BITS_PER_LONG - 1)))
+ ? " -->" : " ",
+ rcnt, ptr, *ptr );
+ rcnt++;
+ ptr++;
+ }
+ printk(msg);
+}
+
+
+/* Verify the resource map and pdir state is consistent */
+static int
+sba_check_pdir(struct ioc *ioc, char *msg)
+{
+ u32 *rptr_end = (u32 *) &(ioc->res_map[ioc->res_size]);
+ u32 *rptr = (u32 *) ioc->res_map; /* resource map ptr */
+ u64 *pptr = ioc->pdir_base; /* pdir ptr */
+ uint pide = 0;
+
+ while (rptr < rptr_end) {
+ u32 rval = *rptr;
+ int rcnt = 32; /* number of bits we might check */
+
+ while (rcnt) {
+ /* Get last byte and highest bit from that */
+ u32 pde = ((u32) (((char *)pptr)[7])) << 24;
+ if ((rval ^ pde) & 0x80000000)
+ {
+ /*
+ ** BUMMER! -- res_map != pdir --
+ ** Dump rval and matching pdir entries
+ */
+ sba_dump_pdir_entry(ioc, msg, pide);
+ return(1);
+ }
+ rcnt--;
+ rval <<= 1; /* try the next bit */
+ pptr++;
+ pide++;
+ }
+ rptr++; /* look at next word of res_map */
+ }
+ /* It'd be nice if we always got here :^) */
+ return 0;
+}
+
+
+static void
+sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
+{
+ while (nents-- > 0) {
+ printk(" %d : %08lx/%05x %p/%05x\n",
+ nents,
+ (unsigned long) sg_dma_address(startsg),
+ sg_dma_len(startsg),
+ startsg->address, startsg->length);
+ startsg++;
+ }
+}
+
+#endif /* ASSERT_PDIR_SANITY */
+
+
+
+/*
+** One time initialization to let the world know the LBA was found.
+** This is the only routine which is NOT static.
+** Must be called exactly once before pci_init().
+*/
+void __init
+sba_init(void)
+{
+ sba_list = (struct sba_device *) NULL;
+ sba_count = 0;
+
+#ifdef DEBUG_SBA_INIT
+ sba_dump_ranges((char *) 0xFED00000L);
+#endif
+
+ register_driver(sba_drivers_for);
+}
+
+
+
+/**************************************************************
+*
+* I/O Pdir Resource Management
+*
+* Bits set in the resource map are in use.
+* Each bit can represent a number of pages.
+* LSbs represent lower addresses (IOVA's).
+*
+***************************************************************/
+#define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */
+
+/* Convert from IOVP to IOVA and vice versa. */
+#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir)))
+#define SBA_IOVP(ioc,iova) ((iova) & ioc->hint_mask_pdir)
+
+/* FIXME : review these macros to verify correctness and usage */
+#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT)
+#define MKIOVP(dma_hint,pide) (dma_addr_t)((long)(dma_hint) | ((long)(pide) << IOVP_SHIFT))
+#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
+
+#define RESMAP_MASK(n) (~0UL << (BITS_PER_LONG - (n)))
+#define RESMAP_IDX_MASK (sizeof(unsigned long) - 1)
+
+
+/*
+** Perf optimizations:
+** o search for log2(size) bits at a time.
+**
+** Search should use register width as "stride" to search the res_map.
+*/
+
+static SBA_INLINE unsigned long
+sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
+{
+ unsigned long *res_ptr = ioc->res_hint;
+ unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
+ unsigned long pide = ~0UL;
+
+ ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
+ ASSERT(res_ptr < res_end);
+ if (bits_wanted > (BITS_PER_LONG/2)) {
+ /* Search word at a time - no mask needed */
+ for(; res_ptr < res_end; ++res_ptr) {
+ if (*res_ptr == 0) {
+ *res_ptr = RESMAP_MASK(bits_wanted);
+ pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+ pide <<= 3; /* convert to bit address */
+ ASSERT(0 != pide);
+ break;
+ }
+ }
+ /* point to the next word on next pass */
+ res_ptr++;
+ ioc->res_bitshift = 0;
+ } else {
+ /*
+ ** Search the resource bit map on well-aligned values.
+ ** "o" is the alignment.
+ ** We need the alignment to invalidate I/O TLB using
+ ** SBA HW features in the unmap path.
+ */
+ unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT);
+ uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
+ unsigned long mask;
+
+ if (bitshiftcnt >= BITS_PER_LONG) {
+ bitshiftcnt = 0;
+ res_ptr++;
+ }
+ mask = RESMAP_MASK(bits_wanted) >> bitshiftcnt;
+
+ DBG_RES("sba_search_bitmap() o %ld %p", o, res_ptr);
+ while(res_ptr < res_end)
+ {
+ DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
+ ASSERT(0 != mask);
+ if(0 == ((*res_ptr) & mask)) {
+ *res_ptr |= mask; /* mark resources busy! */
+ pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
+ pide <<= 3; /* convert to bit address */
+ pide += bitshiftcnt;
+ ASSERT(0 != pide);
+ break;
+ }
+ mask >>= o;
+ bitshiftcnt += o;
+ if (0 == mask) {
+ mask = RESMAP_MASK(bits_wanted);
+ bitshiftcnt=0;
+ res_ptr++;
+ }
+ }
+ /* look in the same word on the next pass */
+ ioc->res_bitshift = bitshiftcnt + bits_wanted;
+ }
+
+ /* wrapped ? */
+ ioc->res_hint = (res_end == res_ptr) ? (unsigned long *) ioc->res_map : res_ptr;
+ return (pide);
+}
+
+
+static int
+sba_alloc_range(struct ioc *ioc, size_t size)
+{
+ unsigned int pages_needed = size >> IOVP_SHIFT;
+#ifdef CONFIG_PROC_FS
+ unsigned long cr_start = mfctl(16);
+#endif
+ unsigned long pide;
+
+ ASSERT(pages_needed);
+ ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(pages_needed < BITS_PER_LONG);
+ ASSERT(0 == (size & ~IOVP_MASK));
+
+ /*
+ ** "seek and ye shall find"...praying never hurts either...
+ ** ggg sacrifices another 710 to the computer gods.
+ */
+
+ pide = sba_search_bitmap(ioc, pages_needed);
+ if (pide >= (ioc->res_size << 3)) {
+ pide = sba_search_bitmap(ioc, pages_needed);
+ if (pide >= (ioc->res_size << 3))
+ panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", ioc->ioc_hpa);
+ }
+
+#ifdef ASSERT_PDIR_SANITY
+ /* verify the first enable bit is clear */
+ if(0x00 != ((u8 *) ioc->pdir_base)[pide*sizeof(u64) + 7]) {
+ sba_dump_pdir_entry(ioc, "sba_search_bitmap() botched it?", pide);
+ }
+#endif
+
+ DBG_RES("sba_alloc_range(%x) %d -> %lx hint %x/%x\n",
+ size, pages_needed, pide,
+ (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map),
+ ioc->res_bitshift );
+
+#ifdef CONFIG_PROC_FS
+ {
+ unsigned long cr_end = mfctl(16);
+ unsigned long tmp = cr_end - cr_start;
+ /* check for roll over */
+ cr_start = (cr_end < cr_start) ? -(tmp) : (tmp);
+ }
+ ioc->avg_search[ioc->avg_idx++] = cr_start;
+ ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1;
+
+ ioc->used_pages += pages_needed;
+#endif
+
+ return (pide);
+}
+
+
+/*
+** clear bits in the ioc's resource map
+*/
+static SBA_INLINE void
+sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
+{
+ unsigned long iovp = SBA_IOVP(ioc, iova);
+ unsigned int pide = PDIR_INDEX(iovp);
+ unsigned int ridx = pide >> 3; /* convert bit to byte address */
+ unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]);
+
+ int bits_not_wanted = size >> IOVP_SHIFT;
+
+ /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */
+ unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1));
+
+ DBG_RES("sba_free_range( ,%x,%x) %x/%lx %x %p %lx\n",
+ (uint) iova, size,
+ bits_not_wanted, m, pide, res_ptr, *res_ptr);
+
+#ifdef CONFIG_PROC_FS
+ ioc->used_pages -= bits_not_wanted;
+#endif
+
+ ASSERT(m != 0);
+ ASSERT(bits_not_wanted);
+ ASSERT((bits_not_wanted * IOVP_SIZE) < DMA_CHUNK_SIZE);
+ ASSERT(bits_not_wanted < BITS_PER_LONG);
+ ASSERT((*res_ptr & m) == m); /* verify same bits are set */
+ *res_ptr &= ~m;
+}
+
+
+/**************************************************************
+*
+* "Dynamic DMA Mapping" support (aka "Coherent I/O")
+*
+***************************************************************/
+
+#define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir)
+
+
+typedef unsigned long space_t;
+#define KERNEL_SPACE 0
+
+/*
+* SBA Mapping Routine
+*
+* Given a virtual address (vba, arg2) and space id, (sid, arg1)
+* sba_io_pdir_entry() loads the I/O PDIR entry pointed to by
+* pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as
+* shown below (MSB == bit 0):
+*
+* 0 19 51 55 63
+* +-+---------------------+----------------------------------+----+--------+
+* |V| U | PPN[43:12] | U | VI |
+* +-+---------------------+----------------------------------+----+--------+
+*
+* V == Valid Bit
+* U == Unused
+* PPN == Physical Page Number
+* VI == Virtual Index (aka Coherent Index)
+*
+* The physical address fields are filled with the results of the LPA
+* instruction. The virtual index field is filled with the results of
+* of the LCI (Load Coherence Index) instruction. The 8 bits used for
+* the virtual index are bits 12:19 of the value returned by LCI.
+*
+* We need to pre-swap the bytes since PCX-W is Big Endian.
+*/
+
+void SBA_INLINE
+sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba)
+{
+ u64 pa; /* physical address */
+ register unsigned ci; /* coherent index */
+
+ /* We currently only support kernel addresses */
+ ASSERT(sid == 0);
+ ASSERT(((unsigned long) vba & 0xc0000000UL) == 0xc0000000UL);
+
+ pa = virt_to_phys(vba);
+ pa &= ~4095ULL; /* clear out offset bits */
+
+ mtsp(sid,1);
+ asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba));
+ pa |= (ci >> 12) & 0xff; /* move CI (8 bits) into lowest byte */
+
+ pa |= 0x8000000000000000ULL; /* set "valid" bit */
+ *pdir_ptr = cpu_to_le64(pa); /* swap and store into I/O Pdir */
+}
+
+
+/***********************************************************
+ * The Ike PCOM (Purge Command Register) is to purge
+ * stale entries in the IO TLB when unmapping entries.
+ *
+ * The PCOM register supports purging of multiple pages, with a minium
+ * of 1 page and a maximum of 2GB. Hardware requires the address be
+ * aligned to the size of the range being purged. The size of the range
+ * must be a power of 2.
+ ***********************************************************/
+static SBA_INLINE void
+sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
+{
+ u32 iovp = (u32) SBA_IOVP(ioc,iova);
+
+ /* Even though this is a big-endian machine, the entries
+ ** in the iopdir are swapped. That's why we clear the byte
+ ** at +7 instead of at +0.
+ */
+ int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
+
+ /* Must be non-zero and rounded up */
+ ASSERT(byte_cnt > 0);
+ ASSERT(0 == (byte_cnt & ~IOVP_MASK));
+
+#ifdef ASSERT_PDIR_SANITY
+ /* Assert first pdir entry is set */
+ if (0x80 != (((u8 *) ioc->pdir_base)[off])) {
+ sba_dump_pdir_entry(ioc,"sba_mark_invalid()", PDIR_INDEX(iovp));
+ }
+#endif
+
+ if (byte_cnt <= IOVP_SIZE)
+ {
+ ASSERT( off < ioc->pdir_size);
+
+ iovp |= IOVP_SHIFT; /* set "size" field for PCOM */
+
+ /*
+ ** clear I/O PDIR entry "valid" bit
+ ** Do NOT clear the rest - save it for debugging.
+ ** We should only clear bits that have previously
+ ** been enabled.
+ */
+ ((u8 *)(ioc->pdir_base))[off] = 0;
+ } else {
+ u32 t = get_order(byte_cnt) + PAGE_SHIFT;
+
+ iovp |= t;
+ ASSERT(t <= 31); /* 2GB! Max value of "size" field */
+
+ do {
+ /* verify this pdir entry is enabled */
+ ASSERT(0x80 == (((u8 *) ioc->pdir_base)[off] & 0x80));
+ /* clear I/O Pdir entry "valid" bit first */
+ ((u8 *)(ioc->pdir_base))[off] = 0;
+ off += sizeof(u64);
+ byte_cnt -= IOVP_SIZE;
+ } while (byte_cnt > 0);
+ }
+
+ WRITE_REG32(iovp, ioc->ioc_hpa+IOC_PCOM);
+}
+
+static int
+sba_dma_supported( struct pci_dev *dev, dma_addr_t mask)
+{
+ if (dev == NULL) {
+ printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+ BUG();
+ return(0);
+ }
+
+ dev->dma_mask = mask; /* save it */
+
+ /* only support PCI devices */
+ return((int) (mask >= 0xffffffff));
+}
+
+
+/*
+** map_single returns a fully formed IOVA
+*/
+static dma_addr_t
+sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+{
+ struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */
+ unsigned long flags;
+ dma_addr_t iovp;
+ dma_addr_t offset;
+ u64 *pdir_start;
+ int pide;
+
+ ASSERT(size > 0);
+
+ /* save offset bits */
+ offset = ((dma_addr_t) addr) & ~IOVP_MASK;
+
+ /* round up to nearest IOVP_SIZE */
+ size = (size + offset + ~IOVP_MASK) & IOVP_MASK;
+
+ spin_lock_irqsave(&ioc->res_lock, flags);
+#ifdef ASSERT_PDIR_SANITY
+ sba_check_pdir(ioc,"Check before sba_map_single()");
+#endif
+
+#ifdef CONFIG_PROC_FS
+ ioc->msingle_calls++;
+ ioc->msingle_pages += size >> IOVP_SHIFT;
+#endif
+ pide = sba_alloc_range(ioc, size);
+ iovp = (dma_addr_t) pide << IOVP_SHIFT;
+
+ DBG_RUN("sba_map_single() 0x%p -> 0x%lx", addr, (long) iovp | offset);
+
+ pdir_start = &(ioc->pdir_base[pide]);
+
+ while (size > 0) {
+ ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */
+ sba_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long) addr);
+
+ DBG_RUN(" pdir 0x%p %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ pdir_start,
+ (u8) (((u8 *) pdir_start)[7]),
+ (u8) (((u8 *) pdir_start)[6]),
+ (u8) (((u8 *) pdir_start)[5]),
+ (u8) (((u8 *) pdir_start)[4]),
+ (u8) (((u8 *) pdir_start)[3]),
+ (u8) (((u8 *) pdir_start)[2]),
+ (u8) (((u8 *) pdir_start)[1]),
+ (u8) (((u8 *) pdir_start)[0])
+ );
+
+ addr += IOVP_SIZE;
+ size -= IOVP_SIZE;
+ pdir_start++;
+ }
+ /* form complete address */
+#ifdef ASSERT_PDIR_SANITY
+ sba_check_pdir(ioc,"Check after sba_map_single()");
+#endif
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+ return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG);
+}
+
+
+static void
+sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction)
+{
+#ifdef FIXME
+/* Multi-IOC (ie N-class) : need to lookup IOC from dev
+** o If we can't know about lba PCI data structs, that eliminates ->sysdata.
+** o walking up pcidev->parent dead ends at elroy too
+** o leaves hashing dev->bus->number into some lookup.
+** (may only work for N-class)
+** o use (struct pci_hba) and put fields in there for DMA.
+** (ioc and per device dma_hint.)
+**
+** Last one seems the clearest and most promising.
+** sba_dma_supported() fill in those fields when the driver queries
+** the system for support.
+*/
+ struct ioc *ioc = (struct ioc *) ((struct pci_hba *) (dev->sysdata))->dma_data;
+#else
+ struct ioc *ioc = &sba_list->ioc[0];
+#endif
+
+ unsigned long flags;
+ dma_addr_t offset;
+ offset = iova & ~IOVP_MASK;
+
+ DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size);
+
+ iova ^= offset; /* clear offset bits */
+ size += offset;
+ size = ROUNDUP(size, IOVP_SIZE);
+
+ ASSERT(0 != iova);
+
+ spin_lock_irqsave(&ioc->res_lock, flags);
+#ifdef CONFIG_PROC_FS
+ ioc->usingle_calls++;
+ ioc->usingle_pages += size >> IOVP_SHIFT;
+#endif
+#ifdef DELAYED_RESOURCE_CNT
+ if (ioc->saved_cnt < DELAYED_RESOURCE_CNT) {
+ ioc->saved_iova[ioc->saved_cnt] = iova;
+ ioc->saved_size[ioc->saved_cnt] = size;
+ ioc_saved_cnt++;
+ } else {
+ do {
+#endif
+ sba_mark_invalid(ioc, iova, size);
+ sba_free_range(ioc, iova, size);
+
+#ifdef DELAYED_RESOURCE_CNT
+ ioc->saved_cnt--;
+ iova = ioc->saved_iova[ioc->saved_cnt];
+ size = ioc->saved_size[ioc->saved_cnt];
+ } while (ioc->saved_cnt)
+
+ /* flush purges */
+ (void) (volatile) READ_REG32(ioc->ioc_hpa+IOC_PCOM);
+ }
+#else
+ /* flush purges */
+ READ_REG32(ioc->ioc_hpa+IOC_PCOM);
+#endif
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+}
+
+
+static void *
+sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+{
+ void *ret;
+
+ if (!hwdev) {
+ /* only support PCI */
+ *dma_handle = 0;
+ return 0;
+ }
+
+ ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size));
+
+ if (ret) {
+ memset(ret, 0, size);
+ *dma_handle = sba_map_single(hwdev, ret, size, 0);
+ }
+
+ return ret;
+}
+
+
+static void
+sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ sba_unmap_single(hwdev, dma_handle, size, 0);
+ free_pages((unsigned long) vaddr, get_order(size));
+}
+
+/*
+** Two address ranges are "virtually contiguous" iff:
+** 1) end of prev == start of next, or... append case
+** 3) end of next == start of prev prepend case
+**
+** and they are DMA contiguous *iff*:
+** 2) end of prev and start of next are both on a page boundry
+**
+** (shift left is a quick trick to mask off upper bits)
+*/
+#define DMA_CONTIG(__X, __Y) \
+ (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL)
+
+/*
+** Assumption is two transactions are mutually exclusive.
+** ie both go to different parts of memory.
+** If both are true, then both transaction are on the same page.
+*/
+#define DMA_SAME_PAGE(s1,e1,s2,e2) \
+ ( ((((s1) ^ (s2)) >> PAGE_SHIFT) == 0) \
+ && ((((e1) ^ (e2)) >> PAGE_SHIFT) == 0) )
+
+/*
+** Since 0 is a valid pdir_base index value, can't use that
+** to determine if a value is valid or not. Use a flag to indicate
+** the SG list entry contains a valid pdir index.
+*/
+#define PIDE_FLAG 0x80000000UL
+
+#ifdef DEBUG_LARGE_SG_ENTRIES
+int dump_run_sg = 0;
+#endif
+
+static SBA_INLINE int
+sba_fill_pdir(
+ struct ioc *ioc,
+ struct scatterlist *startsg,
+ int nents)
+{
+ struct scatterlist *dma_sg = startsg; /* pointer to current DMA */
+ int n_mappings = 0;
+ u64 *pdirp = 0;
+ unsigned long dma_offset = 0;
+
+ dma_sg--;
+ while (nents-- > 0) {
+ int cnt = sg_dma_len(startsg);
+ sg_dma_len(startsg) = 0;
+
+#ifdef DEBUG_LARGE_SG_ENTRIES
+ if (dump_run_sg)
+ printk(" %d : %08lx/%05x %p/%05x\n",
+ nents,
+ (unsigned long) sg_dma_address(startsg), cnt,
+ startsg->address, startsg->length
+ );
+#else
+ DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n",
+ nents,
+ (unsigned long) sg_dma_address(startsg), cnt,
+ startsg->address, startsg->length
+ );
+#endif
+ /*
+ ** Look for the start of a new DMA stream
+ */
+ if (sg_dma_address(startsg) & PIDE_FLAG) {
+ u32 pide = sg_dma_address(startsg) & ~PIDE_FLAG;
+ dma_offset = (unsigned long) pide & ~IOVP_MASK;
+ pide >>= IOVP_SHIFT;
+ pdirp = &(ioc->pdir_base[pide]);
+ sg_dma_address(startsg) = 0;
+ ++dma_sg;
+ sg_dma_address(dma_sg) = (pide << IOVP_SHIFT) + dma_offset;
+ n_mappings++;
+ }
+
+ /*
+ ** Look for a VCONTIG chunk
+ */
+ if (cnt) {
+ unsigned long vaddr = (unsigned long) startsg->address;
+ ASSERT(pdirp);
+
+ sg_dma_len(dma_sg) += cnt;
+ cnt += dma_offset;
+ dma_offset=0; /* only want offset on first chunk */
+ cnt = ROUNDUP(cnt, IOVP_SIZE);
+#ifdef CONFIG_PROC_FS
+ ioc->msg_pages += cnt >> IOVP_SHIFT;
+#endif
+ do {
+ sba_io_pdir_entry(pdirp, KERNEL_SPACE, vaddr);
+ vaddr += IOVP_SIZE;
+ cnt -= IOVP_SIZE;
+ pdirp++;
+ } while (cnt > 0);
+ }
+ startsg++;
+ }
+#ifdef DEBUG_LARGE_SG_ENTRIES
+ dump_run_sg = 0;
+#endif
+ return(n_mappings);
+}
+
+
+
+/*
+** First pass is to walk the SG list and determine where the breaks are
+** in the DMA stream. Allocates PDIR entries but does not fill them.
+** Returns the number of DMA chunks.
+**
+** Doing the fill seperate from the coalescing/allocation keeps the
+** code simpler. Future enhancement could make one pass through
+** the sglist do both.
+*/
+static SBA_INLINE int
+sba_coalesce_chunks( struct ioc *ioc,
+ struct scatterlist *startsg,
+ int nents)
+{
+ int n_mappings = 0;
+
+ while (nents > 0) {
+ struct scatterlist *dma_sg; /* next DMA stream head */
+ unsigned long dma_offset, dma_len; /* start/len of DMA stream */
+ struct scatterlist *chunksg; /* virtually contig chunk head */
+ unsigned long chunk_addr, chunk_len; /* start/len of VCONTIG chunk */
+
+ /*
+ ** Prepare for first/next DMA stream
+ */
+ dma_sg = chunksg = startsg;
+ dma_len = chunk_len = startsg->length;
+ chunk_addr = (unsigned long) startsg->address;
+ dma_offset = 0UL;
+
+ /*
+ ** This loop terminates one iteration "early" since
+ ** it's always looking one "ahead".
+ */
+ while (--nents > 0) {
+ /* ptr to coalesce prev and next */
+ struct scatterlist *prev_sg = startsg;
+ unsigned long prev_end = (unsigned long) prev_sg->address + prev_sg->length;
+ unsigned long current_end;
+
+ /* PARANOID: clear entries */
+ sg_dma_address(startsg) = 0;
+ sg_dma_len(startsg) = 0;
+
+ /* Now start looking ahead */
+ startsg++;
+ current_end = (unsigned long) startsg->address + startsg->length;
+
+ /*
+ ** First look for virtually contiguous blocks.
+ ** PARISC needs this since it's cache is virtually
+ ** indexed and we need the associated virtual
+ ** address for each I/O address we map.
+ **
+ ** 1) can we *prepend* the next transaction?
+ */
+ if (current_end == (unsigned long) prev_sg->address)
+ {
+ /* prepend : get new offset */
+ chunksg = startsg;
+ chunk_addr = (unsigned long) prev_sg->address;
+ chunk_len += startsg->length;
+ dma_len += startsg->length;
+ continue;
+ }
+
+ /*
+ ** 2) or append the next transaction?
+ */
+ if (prev_end == (unsigned long) startsg->address)
+ {
+ chunk_len += startsg->length;
+ dma_len += startsg->length;
+ continue;
+ }
+
+#ifdef DEBUG_LARGE_SG_ENTRIES
+ dump_run_sg = (chunk_len > IOVP_SIZE);
+#endif
+ /*
+ ** Not virtually contigous.
+ ** Terminate prev chunk.
+ ** Start a new chunk.
+ **
+ ** Once we start a new VCONTIG chunk, the offset
+ ** can't change. And we need the offset from the first
+ ** chunk - not the last one. Ergo Successive chunks
+ ** must start on page boundaries and dove tail
+ ** with it's predecessor.
+ */
+ sg_dma_len(prev_sg) = chunk_len;
+
+ chunk_len = startsg->length;
+ dma_offset |= (chunk_addr & ~IOVP_MASK);
+ ASSERT((0 == (chunk_addr & ~IOVP_MASK)) ||
+ (dma_offset == (chunk_addr & ~IOVP_MASK)));
+
+#if 0
+ /*
+ ** 4) do the chunks end/start on page boundaries?
+ ** Easier than 3 since no offsets are involved.
+ */
+ if (DMA_CONTIG(prev_end, startsg->address))
+ {
+ /*
+ ** Yes.
+ ** Reset chunk ptr.
+ */
+ chunksg = startsg;
+ chunk_addr = (unsigned long) startsg->address;
+
+ continue;
+ } else
+#endif
+ {
+ break;
+ }
+ }
+
+ /*
+ ** End of DMA Stream
+ ** Terminate chunk.
+ ** Allocate space for DMA stream.
+ */
+ sg_dma_len(startsg) = chunk_len;
+ dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK;
+ sg_dma_address(dma_sg) =
+ PIDE_FLAG
+ | (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT)
+ | dma_offset;
+ n_mappings++;
+ }
+
+ return n_mappings;
+}
+
+
+/*
+** And this algorithm still generally only ends up coalescing entries
+** that happens to be on the same page due to how sglists are assembled.
+*/
+static int
+sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */
+ int coalesced, filled = 0;
+ unsigned long flags;
+
+ DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
+
+ /* Fast path single entry scatterlists. */
+ if (nents == 1) {
+ sg_dma_address(sglist)= sba_map_single(dev, sglist->address,
+ sglist->length, direction);
+ sg_dma_len(sglist)= sglist->length;
+ return 1;
+ }
+
+ spin_lock_irqsave(&ioc->res_lock, flags);
+
+#ifdef ASSERT_PDIR_SANITY
+ if (sba_check_pdir(ioc,"Check before sba_map_sg()"))
+ {
+ sba_dump_sg(ioc, sglist, nents);
+ panic("Check before sba_map_sg()");
+ }
+#endif
+
+#ifdef CONFIG_PROC_FS
+ ioc->msg_calls++;
+#endif
+
+ /*
+ ** First coalesce the chunks and allocate I/O pdir space
+ **
+ ** If this is one DMA stream, we can properly map using the
+ ** correct virtual address associated with each DMA page.
+ ** w/o this association, we wouldn't have coherent DMA!
+ ** Access to the virtual address is what forces a two pass algorithm.
+ */
+ coalesced = sba_coalesce_chunks(ioc, sglist, nents);
+
+ /*
+ ** Program the I/O Pdir
+ **
+ ** map the virtual addresses to the I/O Pdir
+ ** o dma_address will contain the pdir index
+ ** o dma_len will contain the number of bytes to map
+ ** o address contains the virtual address.
+ */
+ filled = sba_fill_pdir(ioc, sglist, nents);
+
+#ifdef ASSERT_PDIR_SANITY
+ if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
+ {
+ sba_dump_sg(ioc, sglist, nents);
+ panic("Check after sba_map_sg()\n");
+ }
+#endif
+
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+
+ ASSERT(coalesced == filled);
+ DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled);
+
+ return filled;
+}
+
+
+static void
+sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+{
+ struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */
+#ifdef ASSERT_PDIR_SANITY
+ unsigned long flags;
+#endif
+
+ DBG_RUN_SG("%s() START %d entries, %p,%x\n",
+ __FUNCTION__, nents, sglist->address, sglist->length);
+
+#ifdef CONFIG_PROC_FS
+ ioc->usg_calls++;
+#endif
+
+#ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+ sba_check_pdir(ioc,"Check before sba_unmap_sg()");
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+#endif
+
+ while (sg_dma_len(sglist) && nents--) {
+
+#ifdef CONFIG_PROC_FS
+ ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
+#endif
+ sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
+ ++sglist;
+ }
+
+ DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents);
+
+#ifdef ASSERT_PDIR_SANITY
+ spin_lock_irqsave(&ioc->res_lock, flags);
+ sba_check_pdir(ioc,"Check after sba_unmap_sg()");
+ spin_unlock_irqrestore(&ioc->res_lock, flags);
+#endif
+
+}
+
+static struct pci_dma_ops sba_ops = {
+ sba_dma_supported,
+ sba_alloc_consistent, /* allocate cacheable host mem */
+ sba_free_consistent, /* release cacheable host mem */
+ sba_map_single,
+ sba_unmap_single,
+ sba_map_sg,
+ sba_unmap_sg,
+ NULL, /* dma_sync_single */
+ NULL /* dma_sync_sg */
+};
+
+
+/**************************************************************************
+**
+** SBA PAT PDC support
+**
+** o call pdc_pat_cell_module()
+** o store ranges in PCI "resource" structures
+**
+**************************************************************************/
+
+static void
+sba_get_pat_resources(struct sba_device *sba_dev)
+{
+#if 0
+/*
+** TODO/REVISIT/FIXME: support for directed ranges requires calls to
+** PAT PDC to program the SBA/LBA directed range registers...this
+** burden may fall on the LBA code since it directly supports the
+** PCI subsystem. It's not clear yet. - ggg
+*/
+PAT_MOD(mod)->mod_info.mod_pages = PAT_GET_MOD_PAGES(temp);
+ FIXME : ???
+PAT_MOD(mod)->mod_info.dvi = PAT_GET_DVI(temp);
+ Tells where the dvi bits are located in the address.
+PAT_MOD(mod)->mod_info.ioc = PAT_GET_IOC(temp);
+ FIXME : ???
+#endif
+}
+
+
+/**************************************************************
+*
+* Initialization and claim
+*
+***************************************************************/
+
+
+static void
+sba_ioc_init(struct ioc *ioc)
+{
+ extern unsigned long mem_max; /* arch.../setup.c */
+ extern void lba_init_iregs(void *, u32, u32); /* arch.../lba_pci.c */
+
+ u32 iova_space_size, iova_space_mask;
+ void * pdir_base;
+ int pdir_size, iov_order;
+
+ /*
+ ** Determine IOVA Space size from memory size.
+ ** Using "mem_max" is a kluge.
+ **
+ ** Ideally, PCI drivers would register the maximum number
+ ** of DMA they can have outstanding for each device they
+ ** own. Next best thing would be to guess how much DMA
+ ** can be outstanding based on PCI Class/sub-class. Both
+ ** methods still require some "extra" to support PCI
+ ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
+ **
+ ** While we have 32-bits "IOVA" space, top two 2 bits are used
+ ** for DMA hints - ergo only 30 bits max.
+ */
+ /* limit IOVA space size to 1MB-1GB */
+ if (mem_max < (sba_mem_ratio*1024*1024)) {
+ iova_space_size = 1024*1024;
+#ifdef __LP64__
+ } else if (mem_max > (sba_mem_ratio*512*1024*1024)) {
+ iova_space_size = 512*1024*1024;
+#endif
+ } else {
+ iova_space_size = (u32) (mem_max/sba_mem_ratio);
+ }
+
+ /*
+ ** iova space must be log2() in size.
+ ** thus, pdir/res_map will also be log2().
+ */
+ iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT));
+ ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */
+ ASSERT(iov_order >= (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */
+ iova_space_size = 1 << (iov_order + IOVP_SHIFT);
+
+ ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
+
+ ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */
+
+ /* Verify it's a power of two */
+ ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
+
+ DBG_INIT("%s() hpa 0x%p mem %dMBIOV %dMB (%d bits) PDIR size 0x%0x",
+ __FUNCTION__, ioc->ioc_hpa, (int) (mem_max>>20),
+ iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size);
+
+ /* FIXME : DMA HINTs not used */
+ ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
+ ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
+
+ ioc->pdir_base =
+ pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
+ if (NULL == pdir_base)
+ {
+ panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__);
+ }
+ memset(pdir_base, 0, pdir_size);
+
+ DBG_INIT("sba_ioc_init() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n",
+ pdir_base, pdir_size,
+ ioc->hint_shift_pdir, ioc->hint_mask_pdir);
+
+ ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base);
+ WRITE_REG64(virt_to_phys(pdir_base), (u64 *)(ioc->ioc_hpa+IOC_PDIR_BASE));
+
+ DBG_INIT(" base %p\n", pdir_base);
+
+ /* build IMASK for IOC and Elroy */
+ iova_space_mask = 0xffffffff;
+ iova_space_mask <<= (iov_order + PAGE_SHIFT);
+
+ /*
+ ** On C3000 w/512MB mem, HP-UX 10.20 reports:
+ ** ibase=0, imask=0xFE000000, size=0x2000000.
+ */
+ ioc->ibase = IOC_IOVA_SPACE_BASE | 1; /* bit 0 == enable bit */
+ ioc->imask = iova_space_mask; /* save it */
+
+ DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", __FUNCTION__,
+ ioc->ibase, ioc->imask);
+
+ /*
+ ** FIXME: Hint registers are programmed with default hint
+ ** values during boot, so hints should be sane even if we
+ ** can't reprogram them the way drivers want.
+ */
+
+ /*
+ ** setup Elroy IBASE/IMASK registers as well.
+ */
+ lba_init_iregs(ioc->ioc_hpa, ioc->ibase, ioc->imask);
+
+ /*
+ ** Program the IOC's ibase and enable IOVA translation
+ */
+ WRITE_REG32(ioc->ibase, ioc->ioc_hpa+IOC_IBASE);
+ WRITE_REG32(ioc->imask, ioc->ioc_hpa+IOC_IMASK);
+
+ /* Set I/O PDIR Page size to 4K */
+ WRITE_REG32(0, ioc->ioc_hpa+IOC_TCNFG);
+
+ /*
+ ** Clear I/O TLB of any possible entries.
+ ** (Yes. This is a it paranoid...but so what)
+ */
+ WRITE_REG32(0 | 31, ioc->ioc_hpa+IOC_PCOM);
+
+ DBG_INIT("%s() DONE\n", __FUNCTION__);
+}
+
+
+
+/**************************************************************************
+**
+** SBA initialization code (HW and SW)
+**
+** o identify SBA chip itself
+** o initialize SBA chip modes (HardFail)
+** o initialize SBA chip modes (HardFail)
+** o FIXME: initialize DMA hints for reasonable defaults
+**
+**************************************************************************/
+
+static void
+sba_hw_init(struct sba_device *sba_dev)
+{
+ int i;
+ int num_ioc;
+ u32 ioc_ctl;
+
+ ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL);
+ DBG_INIT("%s() hpa 0x%p ioc_ctl 0x%x ->", __FUNCTION__, sba_dev->sba_hpa, ioc_ctl );
+ ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC);
+ ASSERT(ioc_ctl & IOC_CTRL_TE); /* astro: firmware enables this */
+
+ WRITE_REG32(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
+
+#ifdef SBA_DEBUG_INIT
+ ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL);
+ DBG_INIT(" 0x%x\n", ioc_ctl );
+#endif
+
+ if (IS_ASTRO(sba_dev->iodc)) {
+ /* PAT_PDC (L-class) also reports the same goofy base */
+ sba_dev->ioc[0].ioc_hpa = (char *) ASTRO_IOC_OFFSET;
+ num_ioc = 1;
+ } else {
+ sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0;
+ num_ioc = 2;
+ }
+
+ sba_dev->num_ioc = num_ioc;
+ for( i = 0; i < num_ioc; i++)
+ {
+ (unsigned long) sba_dev->ioc[i].ioc_hpa += (unsigned long) sba_dev->sba_hpa + IKE_IOC_OFFSET(i);
+
+ /*
+ ** Make sure the box crashes if we get any errors on a rope.
+ */
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL);
+ WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
+
+ /* flush out the writes */
+ READ_REG32(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
+
+ sba_ioc_init(&(sba_dev->ioc[i]));
+ }
+}
+
+static void
+sba_common_init(struct sba_device *sba_dev)
+{
+ int i;
+
+ /* add this one to the head of the list (order doesn't matter)
+ ** This will be useful for debugging - especially if we get coredumps
+ */
+ sba_dev->next = sba_list;
+ sba_list = sba_dev;
+ sba_count++;
+
+ for(i=0; i< sba_dev->num_ioc; i++) {
+ int res_size;
+#ifdef CONFIG_DMB_TRAP
+ extern void iterate_pages(unsigned long , unsigned long ,
+ void (*)(pte_t * , unsigned long),
+ unsigned long );
+ void set_data_memory_break(pte_t * , unsigned long);
+#endif
+ /* resource map size dictated by pdir_size */
+ res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */
+ res_size >>= 3; /* convert bit count to byte count */
+ DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, res_size);
+
+ sba_dev->ioc[i].res_size = res_size;
+ sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size));
+
+#ifdef CONFIG_DMB_TRAP
+ iterate_pages( sba_dev->ioc[i].res_map, res_size,
+ set_data_memory_break, 0);
+#endif
+
+ if (NULL == sba_dev->ioc[i].res_map)
+ {
+ panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__ );
+ }
+
+ memset(sba_dev->ioc[i].res_map, 0, res_size);
+ /* next available IOVP - circular search */
+ sba_dev->ioc[i].res_hint = (unsigned long *)
+ &(sba_dev->ioc[i].res_map[L1_CACHE_BYTES]);
+
+#ifdef ASSERT_PDIR_SANITY
+ /* Mark first bit busy - ie no IOVA 0 */
+ sba_dev->ioc[i].res_map[0] = 0x80;
+ sba_dev->ioc[i].pdir_base[0] = 0xeeffc0addbba0080ULL;
+#endif
+
+#ifdef CONFIG_DMB_TRAP
+ iterate_pages( sba_dev->ioc[i].res_map, res_size,
+ set_data_memory_break, 0);
+ iterate_pages( sba_dev->ioc[i].pdir_base, sba_dev->ioc[i].pdir_size,
+ set_data_memory_break, 0);
+#endif
+
+ DBG_INIT("sba_common_init() %d res_map %x %p\n",
+ i, res_size, sba_dev->ioc[i].res_map);
+ }
+
+ sba_dev->sba_lock = SPIN_LOCK_UNLOCKED;
+}
+
+#ifdef CONFIG_PROC_FS
+static int sba_proc_info(char *buf, char **start, off_t offset, int len)
+{
+ struct sba_device *sba_dev = sba_list;
+/* FIXME: Multi-IOC support broken! */
+ struct ioc *ioc = &sba_dev->ioc[0];
+ int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
+ unsigned long i = 0, avg = 0, min, max;
+
+ sprintf(buf, "%s rev %d.%d\n",
+ parisc_getHWdescription(sba_dev->iodc->hw_type,
+ sba_dev->iodc->hversion, sba_dev->iodc->sversion),
+ (sba_dev->hw_rev & 0x7) + 1,
+ (sba_dev->hw_rev & 0x18) >> 3
+ );
+ sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n",
+ buf,
+ ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits per byte */
+ total_pages); /* 8 bits per byte */
+
+ sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf,
+ total_pages - ioc->used_pages, ioc->used_pages,
+ (int) (ioc->used_pages * 100 / total_pages));
+
+ sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
+ buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
+
+ min = max = ioc->avg_search[0];
+ for (i = 0; i < SBA_SEARCH_SAMPLE; i++) {
+ avg += ioc->avg_search[i];
+ if (ioc->avg_search[i] > max) max = ioc->avg_search[i];
+ if (ioc->avg_search[i] < min) min = ioc->avg_search[i];
+ }
+ avg /= SBA_SEARCH_SAMPLE;
+ sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+ buf, min, avg, max);
+
+ sprintf(buf, "%spci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n",
+ buf, ioc->msingle_calls, ioc->msingle_pages,
+ (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
+
+ /* KLUGE - unmap_sg calls unmap_single for each mapped page */
+ min = ioc->usingle_calls - ioc->usg_calls;
+ max = ioc->usingle_pages - ioc->usg_pages;
+ sprintf(buf, "%spci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n",
+ buf, min, max,
+ (int) ((max * 1000)/min));
+
+ sprintf(buf, "%spci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
+ buf, ioc->msg_calls, ioc->msg_pages,
+ (int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
+
+ sprintf(buf, "%spci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n",
+ buf, ioc->usg_calls, ioc->usg_pages,
+ (int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
+
+ return strlen(buf);
+}
+
+static int
+sba_resource_map(char *buf, char **start, off_t offset, int len)
+{
+ struct sba_device *sba_dev = sba_list;
+ struct ioc *ioc = &sba_dev->ioc[0];
+ unsigned long *res_ptr = (unsigned long *)ioc->res_map;
+ int i;
+
+ for(i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr) {
+ if ((i & 7) == 0)
+ strcat(buf,"\n ");
+ sprintf(buf, "%s %08lx", buf, *res_ptr);
+ }
+ strcat(buf, "\n");
+
+ return strlen(buf);
+}
+#endif
+
+/*
+** Determine if lba should claim this chip (return 0) or not (return 1).
+** If so, initialize the chip and tell other partners in crime they
+** have work to do.
+*/
+int
+sba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+ struct sba_device *sba_dev;
+ u32 func_class;
+ int i;
+
+ if (IS_ASTRO(d)) {
+ static char astro_rev[]="Astro ?.?";
+
+ /* Read HW Rev First */
+ func_class = READ_REG32(d->hpa);
+
+ astro_rev[6] = '1' + (char) (func_class & 0x7);
+ astro_rev[8] = '0' + (char) ((func_class & 0x18) >> 3);
+ dri->version = astro_rev;
+ } else {
+ static char ike_rev[]="Ike rev ?";
+
+ /* Read HW Rev First */
+ func_class = READ_REG32(d->hpa + SBA_FCLASS);
+
+ ike_rev[8] = '0' + (char) (func_class & 0xff);
+ dri->version = ike_rev;
+ }
+
+ printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+
+ sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
+ if (NULL == sba_dev)
+ {
+ printk(MODULE_NAME " - couldn't alloc sba_device\n");
+ return(1);
+ }
+ memset(sba_dev, 0, sizeof(struct sba_device));
+ for(i=0; i<MAX_IOC; i++)
+ spin_lock_init(&(sba_dev->ioc[i].res_lock));
+
+
+ sba_dev->hw_rev = func_class;
+ sba_dev->iodc = d;
+ sba_dev->sba_hpa = d->hpa; /* faster access */
+
+ sba_get_pat_resources(sba_dev);
+ sba_hw_init(sba_dev);
+ sba_common_init(sba_dev);
+
+ hppa_dma_ops = &sba_ops;
+
+#ifdef CONFIG_PROC_FS
+ if (IS_ASTRO(d)) {
+ create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info);
+ } else {
+ create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info);
+ }
+ create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map);
+#endif
+ return 0;
+}
diff --git a/arch/parisc/kernel/semaphore.c b/arch/parisc/kernel/semaphore.c
new file mode 100644
index 000000000..81156de7d
--- /dev/null
+++ b/arch/parisc/kernel/semaphore.c
@@ -0,0 +1,239 @@
+/*
+ * Just taken from alpha implementation.
+ * This can't work well, perhaps.
+ */
+/*
+ * Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit. ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore. The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+ wake_one_more(sem);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function. Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible. This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return. If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+
+#define DOWN_HEAD(task_state) \
+ \
+ \
+ current->state = (task_state); \
+ add_wait_queue(&sem->wait, &wait); \
+ \
+ /* \
+ * Ok, we're set up. sem->count is known to be less than zero \
+ * so we must wait. \
+ * \
+ * We can let go the lock for purposes of waiting. \
+ * We re-acquire it after awaking so as to protect \
+ * all semaphore operations. \
+ * \
+ * If "up()" is called before we call waking_non_zero() then \
+ * we will catch it right away. If it is called later then \
+ * we will have to go through a wakeup cycle to catch it. \
+ * \
+ * Multiple waiters contend for the semaphore lock to see \
+ * who gets to gate through and who has to wait some more. \
+ */ \
+ for (;;) {
+
+#define DOWN_TAIL(task_state) \
+ current->state = (task_state); \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+ if (waking_non_zero(sem))
+ break;
+ schedule();
+ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int ret = 0;
+
+ DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+ ret = waking_non_zero_interruptible(sem, current);
+ if (ret)
+ {
+ if (ret == 1)
+ /* ret != 0 only if we get interrupted -arca */
+ ret = 0;
+ break;
+ }
+ schedule();
+ DOWN_TAIL(TASK_INTERRUPTIBLE)
+ return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+ return waking_non_zero_trylock(sem);
+}
+
+
+/* Wait for the lock to become unbiased. Readers
+ * are non-exclusive. =)
+ */
+void down_read_failed(struct rw_semaphore *sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ __up_read(sem); /* this takes care of granting the lock */
+
+ add_wait_queue(&sem->wait, &wait);
+
+ while (atomic_read(&sem->count) < 0) {
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
+ if (atomic_read(&sem->count) >= 0)
+ break;
+ schedule();
+ }
+
+ remove_wait_queue(&sem->wait, &wait);
+ current->state = TASK_RUNNING;
+}
+
+void down_read_failed_biased(struct rw_semaphore *sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */
+
+ for (;;) {
+ if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
+ break;
+ set_task_state(current, TASK_UNINTERRUPTIBLE);
+ if (!sem->read_bias_granted)
+ schedule();
+ }
+
+ remove_wait_queue(&sem->wait, &wait);
+ current->state = TASK_RUNNING;
+}
+
+
+/* Wait for the lock to become unbiased. Since we're
+ * a writer, we'll make ourselves exclusive.
+ */
+void down_write_failed(struct rw_semaphore *sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ __up_write(sem); /* this takes care of granting the lock */
+
+ add_wait_queue_exclusive(&sem->wait, &wait);
+
+ while (atomic_read(&sem->count) < 0) {
+ set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+ if (atomic_read(&sem->count) >= 0)
+ break; /* we must attempt to aquire or bias the lock */
+ schedule();
+ }
+
+ remove_wait_queue(&sem->wait, &wait);
+ current->state = TASK_RUNNING;
+}
+
+void down_write_failed_biased(struct rw_semaphore *sem)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
+
+ for (;;) {
+ if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
+ break;
+ set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+ if (!sem->write_bias_granted)
+ schedule();
+ }
+
+ remove_wait_queue(&sem->write_bias_wait, &wait);
+ current->state = TASK_RUNNING;
+
+ /* if the lock is currently unbiased, awaken the sleepers
+ * FIXME: this wakes up the readers early in a bit of a
+ * stampede -> bad!
+ */
+ if (atomic_read(&sem->count) >= 0)
+ wake_up(&sem->wait);
+}
+
+
+/* Called when someone has done an up that transitioned from
+ * negative to non-negative, meaning that the lock has been
+ * granted to whomever owned the bias.
+ */
+void rwsem_wake_readers(struct rw_semaphore *sem)
+{
+ if (xchg(&sem->read_bias_granted, 1))
+ BUG();
+ wake_up(&sem->wait);
+}
+
+void rwsem_wake_writer(struct rw_semaphore *sem)
+{
+ if (xchg(&sem->write_bias_granted, 1))
+ BUG();
+ wake_up(&sem->write_bias_wait);
+}
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
new file mode 100644
index 000000000..16a35df30
--- /dev/null
+++ b/arch/parisc/kernel/setup.c
@@ -0,0 +1,614 @@
+/* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $
+ *
+ * Initial setup-routines for HP 9000 based hardware.
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Modifications for PA-RISC (C) 1999 Helge Deller <helge.deller@ruhr-uni-bochum.de>
+ * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
+ * Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
+ * Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * Initial PA-RISC Version: 04-23-1999 by Helge Deller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/user.h>
+#include <linux/tty.h>
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/threads.h>
+
+#include <asm/cache.h>
+#include <asm/hardware.h> /* for register_driver() stuff */
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/led.h>
+#include <asm/real.h>
+#include <asm/system.h>
+#include <asm/machdep.h> /* for pa7300lc_init() proto */
+
+#include <asm/irq.h> /* for struct irq_region */
+#include <asm/pdcpat.h> /* for PA_VIEW PDC_PAT_CPU_GET_NUMBER etc */
+
+#include <linux/proc_fs.h>
+
+#define COMMAND_LINE_SIZE 1024
+char saved_command_line[COMMAND_LINE_SIZE];
+
+/*
+** KLUGE ALERT!
+**
+** We *really* should be using a combination of request_resource()
+** and request_region()! But request_region() requires kmalloc since
+** returns a new struct resource. And kmalloc just isn't available
+** until after mem_init() is called from start_kernel().
+**
+** FIXME: assume contiguous memory initially.
+** Additional chunks of memory might be added to sysram_resource.sibling.
+*/
+static struct resource sysrom_resource = {
+ name: "System ROM", start: 0x0f0000000UL, end: 0x0f00fffffUL,
+ flags: IORESOURCE_BUSY | IORESOURCE_MEM,
+ parent: &iomem_resource, sibling: NULL, child: NULL };
+
+static struct resource pdcdata_resource;
+
+static struct resource sysram_resource = {
+ name: "System RAM", start: 0UL, end: ~0UL /* bogus */,
+ flags: IORESOURCE_MEM,
+ parent: &iomem_resource, sibling: &sysrom_resource, child: &pdcdata_resource};
+
+extern char _text; /* start of kernel code, defined by linker */
+extern int data_start;
+extern char _edata; /* end of data, begin BSS, defined by linker */
+extern char _end; /* end of BSS, defined by linker */
+
+static struct resource data_resource = {
+ name: "kernel Data", start: virt_to_phys(&data_start), end: virt_to_phys(&_end)-1,
+ flags: IORESOURCE_BUSY | IORESOURCE_MEM,
+ parent: &sysram_resource, sibling: NULL, child: NULL};
+
+static struct resource code_resource = {
+ name: "Kernel Code", start: virt_to_phys(&_text), end: virt_to_phys(&data_start)-1,
+ flags: IORESOURCE_BUSY | IORESOURCE_MEM,
+ parent: &sysram_resource, sibling: &data_resource, child: NULL};
+
+static struct resource pdcdata_resource = {
+ name: "PDC data (Page Zero)", start: 0, end: 0x9ff,
+ flags: IORESOURCE_BUSY | IORESOURCE_MEM,
+ parent: &sysram_resource, sibling: &code_resource, child: NULL};
+
+
+
+
+struct system_cpuinfo_parisc boot_cpu_data;
+struct cpuinfo_parisc cpu_data[NR_CPUS];
+
+extern void do_inventory(void);
+extern void cache_init(void);
+extern struct hp_device * register_module(void *hpa);
+
+static int cpu_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+
+static struct pa_iodc_driver cpu_drivers_for[] = {
+ {HPHW_NPROC, 0x0, 0x0, 0x0, 0, 0,
+ DRIVER_CHECK_HWTYPE,
+ "CPU", "PARISC", (void *) cpu_driver_callback},
+ {0,0,0,0,0,0,
+ 0,
+ (char *) NULL, (char *) NULL, (void *) NULL }
+};
+
+static long fallback_cpu_hpa[] = { 0xfffa0000L, 0xfffbe000L, 0x0 };
+
+
+/*
+** PARISC CPU driver - claim "device" and initialize CPU data structures.
+**
+** Consolidate per CPU initialization into (mostly) one module.
+** Monarch CPU will initialize boot_cpu_data which shouldn't
+** change once the system has booted.
+**
+** The callback *should* do per-instance initialization of
+** everything including the monarch. Some of the code that's
+** in setup.c:start_parisc() should migrate here and start_parisc()
+** should "register_driver(cpu_driver_for)" before calling
+** do_inventory().
+**
+** The goal of consolidating CPU initialization into one place is
+** to make sure all CPU's get initialized the same way.
+** It would be nice if the even the manarch through the exact same code path.
+** (up to rendevous at least).
+*/
+#undef ASSERT
+#define ASSERT(expr) \
+ if(!(expr)) { \
+ printk( "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \
+ panic(#expr); \
+ }
+
+static int
+cpu_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+{
+#ifdef __LP64__
+ extern int pdc_pat; /* arch/parisc/kernel/inventory.c */
+ static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
+#endif
+ struct cpuinfo_parisc *p;
+
+#ifndef CONFIG_SMP
+ if (boot_cpu_data.cpu_count > 0) {
+ printk(KERN_INFO "CONFIG_SMP disabled - not claiming addional CPUs\n");
+ return(1);
+ }
+#endif
+
+ p = &cpu_data[boot_cpu_data.cpu_count];
+ boot_cpu_data.cpu_count++;
+
+/* TODO: Enable FP regs - done early in start_parisc() now */
+
+ /* initialize counters */
+ memset(p, 0, sizeof(struct cpuinfo_parisc));
+
+ p->hpa = (unsigned long) d->hpa; /* save CPU hpa */
+
+#ifdef __LP64__
+ if (pdc_pat) {
+ ulong status;
+ pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+
+ status = pdc_pat_cell_module(& pdc_result, d->pcell_loc,
+ d->mod_index, PA_VIEW, & pa_pdc_cell);
+
+ ASSERT(PDC_RET_OK == status);
+
+ /* verify it's the same as what do_pat_inventory() found */
+ ASSERT(d->mod_info == pa_pdc_cell.mod_info);
+ ASSERT(d->pmod_loc == pa_pdc_cell.mod_location);
+ ASSERT(d->mod_path == pa_pdc_cell.mod_path);
+
+ p->txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */
+
+ /* get the cpu number */
+ status = mem_pdc_call( PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER,
+ __pa(& pdc_result), d->hpa);
+
+ ASSERT(PDC_RET_OK == status);
+
+ p->cpuid = pdc_result[0];
+
+ } else
+#endif
+ {
+ p->txn_addr = (unsigned long) d->hpa; /* for normal parisc */
+
+ /* logical CPU ID and update global counter */
+ p->cpuid = boot_cpu_data.cpu_count - 1;
+ }
+
+ /*
+ ** itimer and ipi IRQ handlers are statically initialized in
+ ** arch/parisc/kernel/irq.c
+ */
+ p->region = irq_region[IRQ_FROM_REGION(CPU_IRQ_REGION)];
+
+ return(0);
+}
+
+
+void __xchg_called_with_bad_pointer(void)
+{
+ printk(KERN_EMERG "xchg() called with bad pointer !\n");
+}
+
+
+/* Some versions of IODC don't list the CPU, and since we don't walk
+ * the bus yet, we have to probe for processors at well known hpa
+ * addresses.
+ */
+
+void __init register_fallback_cpu (void)
+{
+ struct hp_device *d = NULL;
+ int i = 0;
+
+#ifdef CONFIG_SMP
+#error "Revisit CPU fallback addresses for SMP (Assuming bus walk hasn't been implemented)"
+#endif
+ printk ("No CPUs reported by firmware - probing...\n");
+
+ while (fallback_cpu_hpa[i]) {
+
+ d = register_module ((void *) fallback_cpu_hpa[i]);
+
+ if (d > 0) {
+ printk ("Found CPU at %lx\n", fallback_cpu_hpa[i]);
+ cpu_driver_callback (d, 0);
+ return;
+ }
+
+ i++;
+ }
+
+ panic ("No CPUs found. System halted.\n");
+ return;
+}
+
+
+/*
+ * Get CPU information and store it in the boot_cpu_data structure. */
+void __init collect_boot_cpu_data(void)
+{
+ memset(&boot_cpu_data,0,sizeof(boot_cpu_data));
+
+ boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */
+
+ /* get CPU-Model Information... */
+#define p ((unsigned long *)&boot_cpu_data.pdc.model)
+ if(pdc_model_info(&boot_cpu_data.pdc.model)==0)
+ printk("model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
+#undef p
+
+ if(pdc_model_versions(&boot_cpu_data.pdc.versions, 0)==0)
+ printk("vers %08lx\n", boot_cpu_data.pdc.versions.cpuid);
+
+ if(pdc_model_cpuid(&boot_cpu_data.pdc.cpuid)==0)
+ printk("cpuid %08lx\n", boot_cpu_data.pdc.cpuid.cpuid);
+
+ printk("CPUID vers %ld rev %ld\n",
+ (boot_cpu_data.pdc.cpuid.cpuid >> 5) & 127,
+ boot_cpu_data.pdc.cpuid.cpuid & 31);
+
+ if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name)==0)
+ printk("model %s\n",boot_cpu_data.pdc.sys_model_name);
+
+ boot_cpu_data.model_name = parisc_getHWdescription(HPHW_NPROC,
+ boot_cpu_data.pdc.model.hversion>>4,
+ boot_cpu_data.pdc.model.sversion>>8);
+
+ boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion;
+ boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion;
+
+ boot_cpu_data.cpu_type =
+ parisc_get_cpu_type(boot_cpu_data.pdc.model.hversion);
+
+ boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0];
+ boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1];
+}
+
+
+#ifdef __LP64__
+#define COMMAND_GLOBAL 0xfffffffffffe0030UL
+#else
+#define COMMAND_GLOBAL 0xfffe0030
+#endif
+
+#define CMD_RESET 5 /* reset any module */
+
+/*
+** The Wright Brothers and Gecko systems have a H/W problem
+** (Lasi...'nuf said) may cause a broadcast reset to lockup
+** the system. An HVERSION dependent PDC call was developed
+** to perform a "safe", platform specific broadcast reset instead
+** of kludging up all the code.
+**
+** Older machines which do not implement PDC_BROADCAST_RESET will
+** return (with an error) and the regular broadcast reset can be
+** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET
+** the PDC call will not return (the system will be reset).
+*/
+static int
+reset_parisc(struct notifier_block *self, unsigned long command, void *ptr)
+{
+ printk("%s: %s(cmd=%lu)\n", __FILE__, __FUNCTION__, command);
+
+ switch(command) {
+ case MACH_RESTART:
+#ifdef FASTBOOT_SELFTEST_SUPPORT
+ /*
+ ** If user has modified the Firmware Selftest Bitmap,
+ ** run the tests specified in the bitmap after the
+ ** system is rebooted w/PDC_DO_RESET.
+ **
+ ** ftc_bitmap = 0x1AUL "Skip destructive memory tests"
+ **
+ ** Using "directed resets" at each processor with the MEM_TOC
+ ** vector cleared will also avoid running destructive
+ ** memory self tests. (Not implemented yet)
+ */
+ if (ftc_bitmap) {
+ mem_pdc_call( PDC_BROADCAST_RESET,
+ PDC_DO_FIRM_TEST_RESET, PDC_FIRM_TEST_MAGIC,
+ ftc_bitmap);
+ }
+#endif
+
+ /* "Normal" system reset */
+ (void) mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET,
+ 0L, 0L, 0L);
+
+ /* Nope...box should reset with just CMD_RESET now */
+ gsc_writel(CMD_RESET, COMMAND_GLOBAL);
+
+ /* Wait for RESET to lay us to rest. */
+ while (1) ;
+
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block parisc_block = { reset_parisc, NULL, 0 };
+
+
+/* start_parisc() will be called from head.S to setup our new memory_start
+ and actually start our kernel !
+ Memory-Layout is:
+ - Kernel-Image (code+data+BSS)
+ - Stack (stack-size see below!, stack-setup-code is in head.S)
+ - memory_start at end of stack..
+*/
+
+unsigned long mem_start, mem_max;
+unsigned long start_pfn, max_pfn;
+extern asmlinkage void __init start_kernel(void);
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+
+void __init start_parisc(unsigned arg0, unsigned arg1,
+ unsigned arg2, unsigned arg3)
+{
+ register unsigned long ccr;
+ unsigned long memory_start;
+
+ /* Clear BSS */
+
+ {
+ char *p = &_edata, *q = &_end;
+
+ while (p < q) {
+ *p++ = 0;
+ }
+ }
+
+
+ pdc_console_init();
+
+#ifdef __LP64__
+ printk("The 64-bit Kernel has started...\n");
+#else
+ printk("The 32-bit Kernel has started...\n");
+#endif
+
+ /*
+ ** Enable FP coprocessor
+ **
+ ** REVISIT: ccr should be set by PDC_COPROC results to support PA1.0.
+ ** Hardcoding works for PA1.1 processors.
+ **
+ ** REVISIT: this could be done in the "code 22" trap handler.
+ ** (frowands idea - that way we know which processes need FP
+ ** registers saved on the interrupt stack.)
+ **
+ ** NEWS FLASH: wide kernels need FP coprocessor enabled to handle
+ ** formatted printing of %lx for example (double divides I think)
+ */
+ ccr = 0xc0;
+ mtctl(ccr, 10);
+ printk("Enabled FP coprocessor\n");
+
+#ifdef __LP64__
+ printk( "If this is the LAST MESSAGE YOU SEE, you're probably using\n"
+ "32-bit millicode by mistake.\n");
+#endif
+
+ memory_start = (unsigned long) &_end;
+ memory_start = (memory_start + PAGE_SIZE) & PAGE_MASK;
+ printk("Free memory starts at: 0x%lx\n", memory_start);
+
+ /* Collect stuff passed in from the boot loader */
+ printk(KERN_WARNING "%s(0x%x,0x%x,0x%x,0x%x)\n",
+ __FUNCTION__, arg0, arg1, arg2, arg3);
+
+ /* arg0 is free-mem start, arg1 is ptr to command line */
+ if (arg0 < 64) {
+ /* called from hpux boot loader */
+ saved_command_line[0] = '\0';
+ } else {
+ strcpy(saved_command_line, (char *)__va(arg1));
+ printk("PALO command line: '%s'\nPALO initrd %x-%x\n",
+ saved_command_line, arg2, arg3);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (arg2 != 0) /* did palo pass us a ramdisk? */
+ {
+ initrd_start = (unsigned long)__va(arg2);
+ initrd_end = (unsigned long)__va(arg3);
+ }
+#endif
+ }
+
+ mem_start = __pa(memory_start);
+#define MAX_MEM (512*1024*1024)
+ mem_max = (PAGE0->imm_max_mem > MAX_MEM ? MAX_MEM : PAGE0->imm_max_mem);
+
+ collect_boot_cpu_data();
+
+ /* initialize the LCD/LED after boot_cpu_data is available ! */
+ led_init(); /* LCD/LED initialization */
+
+ do_inventory(); /* probe for hardware */
+ register_driver(cpu_drivers_for); /* claim all the CPUs */
+
+ if (boot_cpu_data.cpu_count == 0)
+ register_fallback_cpu();
+
+ printk("CPU(s): %d x %s at %d.%06d MHz\n",
+ boot_cpu_data.cpu_count,
+ boot_cpu_data.cpu_name,
+ boot_cpu_data.cpu_hz / 1000000,
+ boot_cpu_data.cpu_hz % 1000000 );
+
+ switch (boot_cpu_data.cpu_type) {
+ case pcx:
+ case pcxs:
+ case pcxt:
+ hppa_dma_ops = &pcx_dma_ops;
+ break;
+ case pcxl2:
+ pa7300lc_init();
+ case pcxl: /* falls through */
+ hppa_dma_ops = &pcxl_dma_ops;
+ break;
+ default:
+ break;
+ }
+
+#if 1
+ /* KLUGE! this really belongs in kernel/resource.c! */
+ iomem_resource.end = ~0UL;
+#endif
+ sysram_resource.end = mem_max - 1;
+ notifier_chain_register(&mach_notifier, &parisc_block);
+ start_kernel(); /* now back to arch-generic code... */
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long bootmap_size;
+ unsigned long start_pfn;
+ unsigned long mem_free;
+
+ *cmdline_p = saved_command_line;
+
+ /* initialize bootmem */
+
+ start_pfn = PFN_UP(mem_start);
+ max_pfn = PFN_DOWN(mem_max);
+
+ bootmap_size = init_bootmem(start_pfn, max_pfn);
+
+ mem_start += bootmap_size;
+ mem_free = mem_max - mem_start;
+
+ /* free_bootmem handles rounding nicely */
+ printk("free_bootmem(0x%lx, 0x%lx)\n", (unsigned long)mem_start,
+ (unsigned long)mem_free);
+ free_bootmem(mem_start, mem_free);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ printk("initrd: %08x-%08x\n", (int) initrd_start, (int) initrd_end);
+
+ if (initrd_end != 0) {
+ initrd_below_start_ok = 1;
+ reserve_bootmem(__pa(initrd_start), initrd_end - initrd_start);
+ }
+#endif
+
+ cache_init();
+
+ paging_init();
+
+ if((unsigned long)&init_task_union&(INIT_TASK_SIZE - 1)) {
+ printk("init_task_union not aligned. Please recompile the kernel after changing the first line in arch/parisc/kernel/init_task.c from \n\"#define PAD 0\" to\n\"#define PAD 1\" or vice versa\n");
+ for(;;);
+ }
+
+
+#ifdef CONFIG_SERIAL_CONSOLE
+ /* nothing */
+#elif CONFIG_VT
+#if defined(CONFIG_STI_CONSOLE)
+ conswitchp = &dummy_con; /* we use take_over_console() later ! */
+#elif defined(CONFIG_IODC_CONSOLE)
+ conswitchp = &prom_con; /* it's currently really "prom_con" */
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
+#endif
+
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Get CPU information for use by procfs.
+ */
+
+int get_cpuinfo(char *buffer)
+{
+ char *p = buffer;
+ int n;
+
+ for(n=0; n<boot_cpu_data.cpu_count; n++) {
+#ifdef CONFIG_SMP
+ if (!(cpu_online_map & (1<<n)))
+ continue;
+#endif
+ p += sprintf(p, "processor\t: %d\n"
+ "cpu family\t: PA-RISC %s\n",
+ n, boot_cpu_data.family_name);
+
+ p += sprintf(p, "cpu\t\t: %s\n", boot_cpu_data.cpu_name );
+
+ /* cpu MHz */
+ p += sprintf(p, "cpu MHz\t\t: %d.%06d\n",
+ boot_cpu_data.cpu_hz / 1000000,
+ boot_cpu_data.cpu_hz % 1000000 );
+
+ p += sprintf(p, "model\t\t: %s\n"
+ "model name\t: %s\n",
+ boot_cpu_data.pdc.sys_model_name,
+ boot_cpu_data.model_name);
+
+ p += sprintf(p, "hversion\t: 0x%08x\n"
+ "sversion\t: 0x%08x\n",
+ boot_cpu_data.hversion,
+ boot_cpu_data.sversion );
+
+ p += get_cache_info(p);
+ /* print cachesize info ? */
+ p += sprintf(p, "bogomips\t: %lu.%02lu\n",
+ (loops_per_sec+2500)/500000,
+ ((loops_per_sec+2500)/5000) % 100);
+ }
+ return p - buffer;
+}
+#endif
+
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
new file mode 100644
index 000000000..fec670ab8
--- /dev/null
+++ b/arch/parisc/kernel/signal.c
@@ -0,0 +1,653 @@
+/*
+ * linux/arch/parisc/kernel/signal.c: Architecture-specific signal
+ * handling support.
+ *
+ * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
+ * Copyright (C) 2000 Linuxcare, Inc.
+ *
+ * Based on the ia64, i386, and alpha versions.
+ *
+ * Like the IA-64, we are a recent enough port (we are *starting*
+ * with glibc2.2) that we do not need to support the old non-realtime
+ * Linux signals. Therefore we don't. HP/UX signals will go in
+ * arch/parisc/hpux/signal.c when we figure out how to do them.
+ */
+
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+extern long sys_wait4 (int, int *, int, struct rusage *);
+int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
+
+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
+{
+ if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+ return -EFAULT;
+ if (from->si_code < 0)
+ return __copy_to_user(to, from, sizeof(siginfo_t));
+ else {
+ int err;
+
+ /*
+ * If you change siginfo_t structure, please be sure
+ * this code is fixed accordingly. It should never
+ * copy any pad contained in the structure to avoid
+ * security leaks, but must copy the generic 3 ints
+ * plus the relevant union member.
+ */
+ err = __put_user(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
+ err |= __put_user((short)from->si_code, &to->si_code);
+ switch (from->si_code >> 16) {
+ case __SI_FAULT >> 16:
+ /* FIXME: should we put the interruption code here? */
+ case __SI_POLL >> 16:
+ err |= __put_user(from->si_addr, &to->si_addr);
+ break;
+ case __SI_CHLD >> 16:
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
+ err |= __put_user(from->si_status, &to->si_status);
+ default:
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_pid, &to->si_pid);
+ break;
+ /* case __SI_RT: This is not generated by the kernel as of now. */
+ }
+ return err;
+ }
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+#ifdef __LP64__
+#include "sys32.h"
+#endif
+
+asmlinkage int
+sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
+{
+ sigset_t saveset, newset;
+#ifdef __LP64__
+ /* XXX FIXME -- assumes 32-bit user app! */
+ sigset_t32 newset32;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t32))
+ return -EINVAL;
+
+ if (copy_from_user(&newset32, (sigset_t32 *)unewset, sizeof(newset32)))
+ return -EFAULT;
+
+ newset.sig[0] = newset32.sig[0] | ((unsigned long)newset32.sig[1] << 32);
+#else
+
+ /* 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;
+#endif
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sigmask_lock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ regs->gr[28] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, regs, 1))
+ return -EINTR;
+ }
+}
+
+/*
+ * Do a signal return - restore sigcontext.
+ */
+
+struct rt_sigframe {
+ unsigned int tramp[4];
+ struct siginfo info;
+ struct ucontext uc;
+};
+
+/* Trampoline for calling rt_sigreturn() */
+#define INSN_LDI_R25_0 0x34190000 /* ldi 0,%r25 (in_syscall=0) */
+#define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */
+#define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */
+#define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
+#define INSN_NOP 0x80000240 /* nop */
+/* For debugging */
+#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
+
+/*
+ * The 32-bit ABI wants at least 48 bytes for a function call frame:
+ * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of
+ * which Linux/parisc uses is sp-20 for the saved return pointer...)
+ * Then, the stack pointer must be rounded to a cache line (64 bytes).
+ */
+#define PARISC_RT_SIGFRAME_SIZE \
+ (((sizeof(struct rt_sigframe) + 48) + 63) & -64)
+
+static long
+restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs)
+{
+ long err = 0;
+
+ err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
+ err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
+ err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
+ err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
+ err |= __get_user(regs->sar, &sc->sc_sar);
+
+#if DEBUG_SIG
+ printk("restore_sigcontext: r28 is %ld\n", regs->gr[28]);
+#endif
+ return err;
+}
+
+void
+sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
+{
+ struct rt_sigframe *frame;
+ struct siginfo si;
+ sigset_t set;
+ unsigned long usp = regs->gr[30];
+
+ /* Unwind the user stack to get the rt_sigframe structure. */
+ frame = (struct rt_sigframe *)
+ (usp - PARISC_RT_SIGFRAME_SIZE);
+#if DEBUG_SIG
+ printk("in sys_rt_sigreturn, frame is %p\n", frame);
+#endif
+
+ /* Verify that it's a good sigcontext before using it */
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto give_sigsegv;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto give_sigsegv;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ /* Good thing we saved the old gr[30], eh? */
+ if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
+ goto give_sigsegv;
+
+#if DEBUG_SIG
+ printk("usp: %#08lx stack %p",
+ usp, &frame->uc.uc_stack);
+#endif
+
+ /* I don't know why everyone else assumes they can call this
+ with a pointer to a stack_t on the kernel stack. That
+ makes no sense. Anyway we'll do it like m68k, since we
+ also are using segmentation in the same way as them. */
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
+ goto give_sigsegv;
+
+ /* If we are on the syscall path IAOQ will not be restored, and
+ * if we are on the interrupt path we must not corrupt gr31.
+ */
+ if (in_syscall)
+ regs->gr[31] = regs->iaoq[0];
+#if DEBUG_SIG
+ printk("returning to %#lx\n", regs->iaoq[0]);
+ printk("in sys_rt_sigreturn:\n");
+ show_regs(regs);
+#endif
+ return;
+
+give_sigsegv:
+#if DEBUG_SIG
+ printk("fuckup in sys_rt_sigreturn, sending SIGSEGV\n");
+#endif
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SI_KERNEL;
+ si.si_pid = current->pid;
+ si.si_uid = current->uid;
+ si.si_addr = &frame->uc;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static inline void *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *) sp; /* Stacks grow up. Fun. */
+}
+
+static long
+setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, int in_syscall)
+
+{
+ unsigned long flags = 0;
+ long err = 0;
+
+ if (on_sig_stack((unsigned long) sc))
+ flags |= PARISC_SC_FLAG_ONSTACK;
+ if (in_syscall) {
+ flags |= PARISC_SC_FLAG_IN_SYSCALL;
+ /* regs->iaoq is undefined in the syscall return path */
+ err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
+ err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
+#if DEBUG_SIG
+ printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->gr[31], regs->gr[31]);
+#endif
+ } else {
+ err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
+ err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
+#if DEBUG_SIG
+ printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->iaoq[0], regs->iaoq[1]);
+#endif
+ }
+
+ err |= __put_user(flags, &sc->sc_flags);
+ err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
+ err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
+ err |= __put_user(regs->sar, &sc->sc_sar);
+#if DEBUG_SIG
+ printk("setup_sigcontext: r28 is %ld\n", regs->gr[28]);
+#endif
+
+ return err;
+}
+
+static long
+setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs, int in_syscall)
+{
+ struct rt_sigframe *frame;
+ unsigned long rp, usp, haddr;
+ struct siginfo si;
+ int err = 0;
+
+ usp = regs->gr[30];
+ /* access_ok is broken, so do a simplistic "are we stomping on
+ kernel space" assertion. */
+ if (usp > PAGE_OFFSET) {
+ printk("setup_rt_frame: called on kernel space (usp=%#lx), NOW YOU MUST DIE!!!\n",
+ usp);
+ show_regs(regs);
+ while(1);
+ }
+
+ frame = get_sigframe(ka, usp, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+#if DEBUG_SIG
+ printk("setup_rt_frame 1: frame %p info %p\n", frame, info);
+#endif
+
+ err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t));
+ err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= __put_user(sas_ss_flags(regs->gr[30]),
+ &frame->uc.uc_stack.ss_flags);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
+ &frame->tramp[0]);
+ err |= __put_user(INSN_LDI_R20, &frame->tramp[1]);
+ err |= __put_user(INSN_BLE_SR2_R0, &frame->tramp[2]);
+ err |= __put_user(INSN_NOP, &frame->tramp[3]);
+
+#if DEBUG_SIG
+ /* Assert that we're flushing in the correct space... */
+ {
+ int sid;
+ asm ("mfsp %%sr3,%0" : "=r" (sid));
+ printk("flushing 64 bytes at space %#x offset %p\n",
+ sid, frame->tramp);
+ }
+#endif
+
+#if CACHE_FLUSHING_IS_NOT_BROKEN
+ flush_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[4]);
+#else
+ /* It should *always* be cache line-aligned, but the compiler
+ sometimes screws up. */
+ asm volatile("fdc 0(%%sr3,%0)\n\t"
+ "fdc %1(%%sr3,%0)\n\t"
+ "sync\n\t"
+ "fic 0(%%sr3,%0)\n\t"
+ "fic %1(%%sr3,%0)\n\t"
+ "sync\n\t"
+ : : "r" (frame->tramp), "r" (L1_CACHE_BYTES));
+#endif
+ rp = (unsigned long) frame->tramp;
+
+ if (err)
+ goto give_sigsegv;
+
+#ifdef __LP64__
+/* Much more has to happen with signals than this -- but it'll at least */
+/* provide a pointer to some places which definitely need a look. */
+#define HACK unsigned int
+#else
+#define HACK unsigned long
+#endif
+ haddr = (HACK) ka->sa.sa_handler;
+ /* ARGH! Fucking brain damage. You don't want to know. */
+ if (haddr & 2) {
+ HACK *plabel;
+ HACK ltp;
+
+ plabel = (HACK *) (haddr & ~3);
+ err |= __get_user(haddr, plabel);
+ err |= __get_user(ltp, plabel + 1);
+ if (err)
+ goto give_sigsegv;
+ regs->gr[19] = ltp;
+ }
+
+ /* The syscall return path will create IAOQ values from r31.
+ */
+ if (in_syscall)
+ regs->gr[31] = (HACK) haddr;
+ else {
+ regs->iaoq[0] = (HACK) haddr | 3;
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ }
+
+ regs->gr[2] = rp; /* userland return pointer */
+ regs->gr[26] = sig; /* signal number */
+ regs->gr[25] = (HACK) &frame->info; /* siginfo pointer */
+ regs->gr[24] = (HACK) &frame->uc; /* ucontext pointer */
+#if DEBUG_SIG
+ printk("making sigreturn frame: %#lx + %#lx = %#lx\n",
+ regs->gr[30], PARISC_RT_SIGFRAME_SIZE,
+ regs->gr[30] + PARISC_RT_SIGFRAME_SIZE);
+#endif
+ /* Raise the user stack pointer to make a proper call frame. */
+ regs->gr[30] = ((HACK) frame + PARISC_RT_SIGFRAME_SIZE);
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
+ current->comm, current->pid, frame, regs->gr[30],
+ regs->iaoq[0], regs->iaoq[1], rp);
+#endif
+
+ return 1;
+
+give_sigsegv:
+#if DEBUG_SIG
+ printk("fuckup in setup_rt_frame, sending SIGSEGV\n");
+#endif
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SI_KERNEL;
+ si.si_pid = current->pid;
+ si.si_uid = current->uid;
+ si.si_addr = frame;
+ force_sig_info(SIGSEGV, &si, current);
+ return 0;
+}
+
+/*
+ * OK, we're invoking a handler.
+ */
+
+static long
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset,
+ struct pt_regs *regs, int in_syscall)
+{
+#if DEBUG_SIG
+ printk("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n",
+ sig, ka, info, oldset, regs);
+#endif
+ /* Set up the stack frame */
+ if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
+ return 0;
+
+ if (ka->sa.sa_flags & SA_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(&current->sigmask_lock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+ }
+ return 1;
+}
+
+/*
+ * 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.
+ *
+ * We need to be able to restore the syscall arguments (r21-r26) to
+ * restart syscalls. Thus, the syscall path should save them in the
+ * pt_regs structure (it's okay to do so since they are caller-save
+ * registers). As noted below, the syscall number gets restored for
+ * us due to the magic of delayed branching.
+ */
+asmlinkage int
+do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
+{
+ siginfo_t info;
+ struct k_sigaction *ka;
+
+#if DEBUG_SIG
+ printk("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n",
+ oldset, regs, regs->sr[7], current->sigpending, in_syscall);
+#endif
+ /* Everyone else checks to see if they are in kernel mode at
+ this point and exits if that's the case. I'm not sure why
+ we would be called in that case, but for some reason we
+ are. */
+
+ if (!oldset)
+ oldset = &current->blocked;
+
+#if DEBUG_SIG
+ printk("do_signal: oldset %08lx:%08lx\n", oldset->sig[0], oldset->sig[1]);
+#endif
+
+ for (;;) {
+ unsigned long signr;
+
+ spin_lock_irq(&current->sigmask_lock);
+ signr = dequeue_signal(&current->blocked, &info);
+ spin_unlock_irq(&current->sigmask_lock);
+#if DEBUG_SIG
+ printk("do_signal: signr=%ld, pid=%d\n", signr, current->pid);
+#endif
+
+ if (!signr)
+ break;
+
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
+ /* Let the debugger run. */
+ current->exit_code = signr;
+ set_current_state(TASK_STOPPED);
+ notify_parent(current, SIGCHLD);
+ schedule();
+
+ /* 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(&current->blocked, signr)) {
+ send_sig_info(signr, &info, current);
+ continue;
+ }
+ }
+
+ ka = &current->sig->action[signr-1];
+#if DEBUG_SIG
+ printk("sa_handler is %lx\n", ka->sa.sa_handler);
+#endif
+ if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_IGN) {
+ if (signr != SIGCHLD)
+ continue;
+ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+ /* nothing */;
+ continue;
+ }
+
+ if ((unsigned long) ka->sa.sa_handler == (unsigned long) 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:
+ set_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:
+ case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
+ if (signr == SIGQUIT) /* Userspace debugging */
+ show_regs(regs);
+ if (do_coredump(signr, regs))
+ exit_code |= 0x80;
+ /* FALLTHRU */
+
+ default:
+ lock_kernel();
+ sigaddset(&current->pending.signal, signr);
+ recalc_sigpending(current);
+ current->flags |= PF_SIGNALED;
+ do_exit(exit_code);
+ /* NOTREACHED */
+ }
+ }
+
+ /* Restart a system call if necessary. */
+ if (in_syscall) {
+ /* Check the return code */
+ switch (regs->gr[28]) {
+ case -ERESTARTNOHAND:
+#if DEBUG_SIG
+ printk("ERESTARTNOHAND: returning -EINTR\n");
+#endif
+ regs->gr[28] = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (!(ka->sa.sa_flags & SA_RESTART)) {
+#if DEBUG_SIG
+ printk("ERESTARTSYS: putting -EINTR\n");
+#endif
+ regs->gr[28] = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ /* A syscall is just a branch, so all
+ we have to do is fiddle the return
+ pointer. */
+ regs->gr[31] -= 8; /* delayed branching */
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+ break;
+ }
+ }
+ /* Whee! Actually deliver the signal. If the
+ delivery failed, we need to continue to iterate in
+ this loop so we can deliver the SIGSEGV... */
+ if (handle_signal(signr, ka, &info, oldset, regs, in_syscall)) {
+#if DEBUG_SIG
+ printk("Exiting do_signal (success), regs->gr[28] = %ld\n", regs->gr[28]);
+#endif
+ return 1;
+ }
+ }
+
+ /* Did we come from a system call? */
+ if (in_syscall) {
+ /* Restart the system call - no handlers present */
+ if (regs->gr[28] == -ERESTARTNOHAND ||
+ regs->gr[28] == -ERESTARTSYS ||
+ regs->gr[28] == -ERESTARTNOINTR) {
+ /* Hooray for delayed branching. We don't
+ have to restore %r20 (the system call
+ number) because it gets loaded in the delay
+ slot of the branch external instruction. */
+ regs->gr[31] -= 8;
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+ }
+ }
+#if DEBUG_SIG
+ printk("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", regs->gr[28]);
+#endif
+ return 0;
+}
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
new file mode 100644
index 000000000..85aca70af
--- /dev/null
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -0,0 +1,88 @@
+/*
+ * linux/arch/parisc/kernel/sys_parisc.c
+ *
+ * this implements the missing syscalls.
+ */
+
+#include <asm/uaccess.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/smp_lock.h>
+
+/* for some reason, "old_readdir" is the only syscall which does not begin
+ * with "sys_", which breaks the ENTRY_* macros in syscall.S so I "fixed"
+ * it here.
+ */
+
+int sys_old_readdir(unsigned int fd, void *dirent, unsigned int count)
+{
+ return old_readdir(fd, dirent, count);
+}
+
+int sys_pipe(int *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;
+}
+
+int sys_pause(void)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ return -ERESTARTNOHAND;
+}
+
+int sys_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags, unsigned long fd,
+ unsigned long offset)
+{
+ struct file * file = NULL;
+ int error;
+
+ down(&current->mm->mmap_sem);
+ lock_kernel();
+ if (!(flags & MAP_ANONYMOUS)) {
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ error = do_mmap(file, addr, len, prot, flags, offset);
+ if (file != NULL)
+ fput(file);
+out:
+ unlock_kernel();
+ up(&current->mm->mmap_sem);
+ return error;
+}
+
+int sys_ioperm(unsigned long from, unsigned long num, int on)
+{
+ return -ENOSYS;
+}
+
+long sys_shmat_wrapper(int shmid, void *shmaddr, int shmflag)
+{
+ extern int sys_shmat(int shmid, char *shmaddr, int shmflg,
+ unsigned long * raddr);
+ unsigned long raddr;
+ int r;
+
+ r = sys_shmat(shmid, shmaddr, shmflag, &raddr);
+ if (r < 0)
+ return r;
+ return raddr;
+}
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
new file mode 100644
index 000000000..bfa757471
--- /dev/null
+++ b/arch/parisc/kernel/syscall.S
@@ -0,0 +1,563 @@
+/*
+ * Linux/PARISC Project (http://www.thepuffingroup.com/parisc)
+ *
+ * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
+ * Licensed under the GNU GPL.
+ * thanks to Philipp Rumpf, Mike Shaver and various others
+ * sorry about the wall, puffin..
+ */
+
+#include <asm/offset.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/psw.h>
+
+#define __ASSEMBLY__
+#include <asm/assembly.h>
+#include <asm/processor.h>
+#include <linux/version.h>
+
+#ifdef __LP64__
+ .level 2.0w
+#else
+ .level 1.1
+#endif
+ .text
+
+ .import syscall_exit,code
+ .import syscall_exit_rfi,code
+ .export linux_gateway_page
+
+ /* Linux gateway page is aliased to virtual page 0 in the kernel
+ * address space. Since it is a gateway page it cannot be
+ * dereferenced, so null pointers will still fault. We start
+ * the actual entry point at 0x100. We put break instructions
+ * at the beginning of the page to trap null indirect function
+ * pointers.
+ */
+
+ .align 4096
+linux_gateway_page:
+
+ break 0,0
+
+ .align 256
+linux_gateway_entry:
+ mfsp %sr7,%r1 /* we must set sr3 to the space */
+ mtsp %r1,%sr3 /* of the user before the gate */
+ gate .+8, %r0 /* become privileged */
+ mtsp %r0,%sr4 /* get kernel space into sr4 */
+ mtsp %r0,%sr5 /* get kernel space into sr5 */
+ mtsp %r0,%sr6 /* get kernel space into sr6 */
+ mtsp %r0,%sr7 /* get kernel space into sr7 */
+#ifdef __LP64__
+ /* for now we can *always* set the W bit on entry to the syscall
+ * since we don't support wide userland processes. We could
+ * also save the current SM other than in r0 and restore it on
+ * exit from the syscall, and also use that value to know
+ * whether to do narrow or wide syscalls. -PB
+ */
+ ssm PSW_SM_W, %r0
+#endif
+ mtctl %r28,%cr27
+ rsm PSW_I, %r28 /* no ints for a bit */
+ mfctl %cr30,%r1 /* get the kernel task ptr */
+ mtctl %r0,%cr30 /* zero it (flag) */
+
+ /* Save some registers for sigcontext and potential task
+ switch (see entry.S for the details of which ones are
+ saved/restored) */
+ STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
+ STREG %r19, TASK_PT_GR19(%r1)
+ STREG %r20, TASK_PT_GR20(%r1)
+ STREG %r21, TASK_PT_GR21(%r1)
+ STREG %r22, TASK_PT_GR22(%r1)
+ STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */
+ STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */
+ STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */
+ STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
+ STREG %r27, TASK_PT_GR27(%r1) /* user dp */
+ mfctl %cr27,%r19
+ STREG %r19, TASK_PT_GR28(%r1) /* return value 0 */
+ STREG %r19, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */
+ STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */
+ STREG %r30, TASK_PT_GR30(%r1) /* preserve userspace sp */
+ STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
+
+ ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */
+ save_fp %r27 /* or potential task switch */
+
+ mfctl %cr11, %r27 /* i.e. SAR */
+ STREG %r27, TASK_PT_SAR(%r1)
+
+ loadgp
+
+ ldo TASK_SZ_ALGN+64(%r1),%r30 /* set up kernel stack */
+
+#ifndef __LP64__
+ /* no need to save these on stack because in wide mode the first 8
+ * args are passed in registers */
+ stw %r22, -52(%r30) /* 5th argument */
+ stw %r21, -56(%r30) /* 6th argument */
+#endif
+
+ /* for some unknown reason, task_struct.ptrace is an unsigned long so use LDREG */
+ LDREG TASK_PTRACE(%r1), %r19 /* Are we being ptraced? */
+ mtsm %r28 /* irqs back */
+
+ bb,<,n %r19, 31, .Ltracesys /* must match PT_PTRACE bit */
+
+ /* Note! We cannot use the syscall table that is mapped
+ nearby since the gateway page is mapped execute-only. */
+
+ ldil L%sys_call_table, %r1
+ ldo R%sys_call_table(%r1), %r19
+ LDIL_FIXUP(%r19)
+
+ comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+ b,n .Lsyscall_nosys
+
+#ifdef __LP64__
+ ldd,s %r20(%r19), %r19
+#else
+ ldwx,s %r20(%r19), %r19
+#endif
+ /* If this is a sys_rt_sigreturn call, and the signal was received
+ * when not in_syscall, then we want to return via syscall_exit_rfi,
+ * not syscall_exit. Signal no. in r20, in_syscall in r25 (see
+ * trampoline code in signal.c).
+ */
+ ldi __NR_rt_sigreturn,%r2
+ comb,= %r2,%r20,.Lrt_sigreturn
+.Lin_syscall:
+ ldil L%syscall_exit,%r2
+ LDIL_FIXUP(%r2)
+ be 0(%sr7,%r19)
+ ldo R%syscall_exit(%r2),%r2
+.Lrt_sigreturn:
+ comib,<> 0,%r25,.Lin_syscall
+ ldil L%syscall_exit_rfi,%r2
+ LDIL_FIXUP(%r2)
+ be 0(%sr7,%r19)
+ ldo R%syscall_exit_rfi(%r2),%r2
+
+ /* Note! Because we are not running where we were linked, any
+ calls to functions external to this file must be indirect. To
+ be safe, we apply the opposite rule to functions within this
+ file, with local labels given to them to ensure correctness. */
+
+.Lsyscall_nosys:
+syscall_nosys:
+ ldil L%syscall_exit,%r1
+ LDIL_FIXUP(%r1)
+ be R%syscall_exit(%sr7,%r1)
+ ldo -ENOSYS(%r0),%r28 /* set errno */
+
+
+/* Warning! This trace code is a virtual duplicate of the code above so be
+ * sure to maintain both! */
+.Ltracesys:
+tracesys:
+ /* Need to save more registers so the debugger can see where we
+ * are.
+ */
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ ssm 0,%r2 /* Lower 8 bits only!! */
+ STREG %r2,TASK_PT_PSW(%r1)
+ STREG %r1,TASK_PT_CR30(%r1)
+ mfsp %sr0,%r2
+ STREG %r2,TASK_PT_SR0(%r1)
+ mfsp %sr1,%r2
+ STREG %r2,TASK_PT_SR1(%r1)
+ mfsp %sr2,%r2
+ STREG %r2,TASK_PT_SR2(%r1)
+ mfsp %sr3,%r2
+ STREG %r2,TASK_PT_SR3(%r1)
+ STREG %r2,TASK_PT_SR4(%r1)
+ STREG %r2,TASK_PT_SR5(%r1)
+ STREG %r2,TASK_PT_SR6(%r1)
+ STREG %r2,TASK_PT_SR7(%r1)
+ STREG %r2,TASK_PT_IASQ0(%r1)
+ STREG %r2,TASK_PT_IASQ1(%r1)
+ LDREG TASK_PT_GR31(%r1),%r2
+ STREG %r2,TASK_PT_IAOQ0(%r1)
+ ldo 4(%r2),%r2
+ STREG %r2,TASK_PT_IAOQ1(%r1)
+ ldo TASK_REGS(%r1),%r2
+ /* reg_save %r2 */
+ STREG %r3,PT_GR3(%r2)
+ STREG %r4,PT_GR4(%r2)
+ STREG %r5,PT_GR5(%r2)
+ STREG %r6,PT_GR6(%r2)
+ STREG %r7,PT_GR7(%r2)
+ STREG %r8,PT_GR8(%r2)
+ STREG %r9,PT_GR9(%r2)
+ STREG %r10,PT_GR10(%r2)
+ STREG %r11,PT_GR11(%r2)
+ STREG %r12,PT_GR12(%r2)
+ STREG %r13,PT_GR13(%r2)
+ STREG %r14,PT_GR14(%r2)
+ STREG %r15,PT_GR15(%r2)
+ STREG %r16,PT_GR16(%r2)
+ STREG %r17,PT_GR17(%r2)
+ STREG %r18,PT_GR18(%r2)
+ /* Finished saving things for the debugger */
+
+ ldil L%syscall_trace,%r1
+ LDIL_FIXUP(%r1)
+ ldil L%tracesys_next,%r2
+ LDIL_FIXUP(%r2)
+ be R%syscall_trace(%sr7,%r1)
+ ldo R%tracesys_next(%r2),%r2
+
+tracesys_next:
+ ldil L%sys_call_table,%r1
+ LDIL_FIXUP(%r1)
+ ldo R%sys_call_table(%r1), %r19
+
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ LDREG TASK_PT_GR20(%r1), %r20
+ LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */
+ LDREG TASK_PT_GR25(%r1), %r25
+ LDREG TASK_PT_GR24(%r1), %r24
+ LDREG TASK_PT_GR23(%r1), %r23
+#ifdef __LP64__
+ LDREG TASK_PT_GR22(%r1), %r22
+ LDREG TASK_PT_GR21(%r1), %r21
+#endif
+
+ comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+ b,n .Lsyscall_nosys
+
+#ifdef __LP64__
+ ldd,s %r20(%r19), %r19
+#else
+ ldwx,s %r20(%r19), %r19
+#endif
+ /* If this is a sys_rt_sigreturn call, and the signal was received
+ * when not in_syscall, then we want to return via syscall_exit_rfi,
+ * not syscall_exit. Signal no. in r20, in_syscall in r25 (see
+ * trampoline code in signal.c).
+ */
+ ldi __NR_rt_sigreturn,%r2
+ comb,= %r2,%r20,.Ltrace_rt_sigreturn
+.Ltrace_in_syscall:
+ ldil L%tracesys_exit,%r2
+ LDIL_FIXUP(%r2)
+ be 0(%sr7,%r19)
+ ldo R%tracesys_exit(%r2),%r2
+
+ /* Do *not* call this function on the gateway page, because it
+ makes a direct call to syscall_trace. */
+
+tracesys_exit:
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ bl syscall_trace, %r2
+ STREG %r28,TASK_PT_GR28(%r1) /* save return value now */
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */
+
+ ldil L%syscall_exit,%r1
+ LDIL_FIXUP(%r1)
+ be,n R%syscall_exit(%sr7,%r1)
+
+.Ltrace_rt_sigreturn:
+ comib,<> 0,%r25,.Ltrace_in_syscall
+ ldil L%tracesys_sigexit,%r2
+ LDIL_FIXUP(%r2)
+ be 0(%sr7,%r19)
+ ldo R%tracesys_sigexit(%r2),%r2
+
+tracesys_sigexit:
+ ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */
+ bl syscall_trace, %r2
+ nop
+
+ ldil L%syscall_exit_rfi,%r1
+ LDIL_FIXUP(%r1)
+ be,n R%syscall_exit_rfi(%sr7,%r1)
+
+#ifdef __LP64__
+/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
+ * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
+ * implementation is required on wide palinux.
+ */
+#define ENTRY_SAME(_name_) .dword sys_##_name_
+#define ENTRY_DIFF(_name_) .dword sys32_##_name_
+#define ENTRY_UHOH(_name_) .dword sys32_unimplemented
+#else
+#define ENTRY_SAME(_name_) .word sys_##_name_
+#define ENTRY_DIFF(_name_) .word sys_##_name_
+#define ENTRY_UHOH(_name_) .word sys_##_name_
+#endif
+
+ .align 8
+ .export sys_call_table
+.Lsys_call_table:
+sys_call_table:
+ ENTRY_SAME(ni_syscall) /* 0 - old "setup()" system call*/
+ ENTRY_SAME(exit)
+ ENTRY_SAME(fork_wrapper)
+ ENTRY_SAME(read)
+ ENTRY_SAME(write)
+ ENTRY_SAME(open) /* 5 */
+ ENTRY_SAME(close)
+ ENTRY_SAME(waitpid)
+ ENTRY_SAME(creat)
+ ENTRY_SAME(link)
+ ENTRY_SAME(unlink) /* 10 */
+ ENTRY_DIFF(execve_wrapper)
+ ENTRY_SAME(chdir)
+ /* See comments in kernel/time.c!!! Maybe we don't need this? */
+ ENTRY_DIFF(time)
+ ENTRY_SAME(mknod)
+ ENTRY_SAME(chmod) /* 15 */
+ ENTRY_SAME(lchown)
+ ENTRY_SAME(socket)
+ /* struct stat is MAYBE identical wide and narrow ?? */
+ ENTRY_DIFF(newstat)
+ ENTRY_SAME(lseek)
+ ENTRY_SAME(getpid) /* 20 */
+ /* the 'void * data' parameter may need re-packing in wide */
+ ENTRY_DIFF(mount)
+ /* concerned about struct sockaddr in wide/narrow */
+ /* ---> I think sockaddr is OK unless the compiler packs the struct */
+ /* differently to align the char array */
+ ENTRY_SAME(bind)
+ ENTRY_SAME(setuid)
+ ENTRY_SAME(getuid)
+ ENTRY_SAME(stime) /* 25 */
+ ENTRY_SAME(ptrace)
+ ENTRY_SAME(alarm)
+ /* see stat comment */
+ ENTRY_DIFF(newfstat)
+ ENTRY_SAME(pause)
+ /* struct utimbuf uses time_t which might vary */
+ ENTRY_DIFF(utime) /* 30 */
+ /* struct sockaddr... */
+ ENTRY_SAME(connect)
+ ENTRY_SAME(listen)
+ ENTRY_SAME(access)
+ ENTRY_SAME(nice)
+ /* struct sockaddr... */
+ ENTRY_SAME(accept) /* 35 */
+ ENTRY_SAME(sync)
+ ENTRY_SAME(kill)
+ ENTRY_SAME(rename)
+ ENTRY_SAME(mkdir)
+ ENTRY_SAME(rmdir) /* 40 */
+ ENTRY_SAME(dup)
+ ENTRY_SAME(pipe)
+ ENTRY_DIFF(times)
+ /* struct sockaddr... */
+ ENTRY_SAME(getsockname)
+ /* it seems possible brk() could return a >4G pointer... */
+ ENTRY_SAME(brk) /* 45 */
+ ENTRY_SAME(setgid)
+ ENTRY_SAME(getgid)
+ ENTRY_SAME(signal)
+ ENTRY_SAME(geteuid)
+ ENTRY_SAME(getegid) /* 50 */
+ ENTRY_SAME(acct)
+ ENTRY_SAME(umount)
+ /* struct sockaddr... */
+ ENTRY_SAME(getpeername)
+ /* This one's a huge ugly mess */
+ ENTRY_DIFF(ioctl)
+ /* struct flock? */
+ ENTRY_DIFF(fcntl) /* 55 */
+ ENTRY_SAME(socketpair)
+ ENTRY_SAME(setpgid)
+ ENTRY_SAME(send)
+ ENTRY_SAME(newuname)
+ ENTRY_SAME(umask) /* 60 */
+ ENTRY_SAME(chroot)
+ ENTRY_SAME(ustat)
+ ENTRY_SAME(dup2)
+ ENTRY_SAME(getppid)
+ ENTRY_SAME(getpgrp) /* 65 */
+ ENTRY_SAME(setsid)
+ ENTRY_SAME(pivot_root)
+ /* I don't like this */
+ ENTRY_UHOH(sgetmask)
+ ENTRY_UHOH(ssetmask)
+ ENTRY_SAME(setreuid) /* 70 */
+ ENTRY_SAME(setregid)
+ ENTRY_SAME(mincore)
+ ENTRY_DIFF(sigpending)
+ ENTRY_SAME(sethostname)
+ /* Following 3 have linux-common-code structs containing longs -( */
+ ENTRY_DIFF(setrlimit) /* 75 */
+ ENTRY_DIFF(getrlimit)
+ ENTRY_DIFF(getrusage)
+ /* struct timeval and timezone are maybe?? consistent wide and narrow */
+ ENTRY_SAME(gettimeofday)
+ ENTRY_SAME(settimeofday)
+ ENTRY_SAME(getgroups) /* 80 */
+ ENTRY_SAME(setgroups)
+ /* struct socketaddr... */
+ ENTRY_SAME(sendto)
+ ENTRY_SAME(symlink)
+ /* see stat comment */
+ ENTRY_DIFF(newlstat)
+ ENTRY_SAME(readlink) /* 85 */
+ /* suspect we'll need some work for narrow shlibs on wide kernel */
+ ENTRY_UHOH(uselib)
+ ENTRY_SAME(swapon)
+ ENTRY_SAME(reboot)
+ /* argh! struct dirent contains a long */
+ ENTRY_UHOH(old_readdir)
+ /* I'm not certain about off_t... */
+ ENTRY_SAME(mmap) /* 90 */
+ ENTRY_SAME(munmap)
+ ENTRY_SAME(truncate)
+ ENTRY_SAME(ftruncate)
+ ENTRY_SAME(fchmod)
+ ENTRY_SAME(fchown) /* 95 */
+ ENTRY_SAME(getpriority)
+ ENTRY_SAME(setpriority)
+ ENTRY_SAME(recv)
+ ENTRY_DIFF(statfs)
+ ENTRY_DIFF(fstatfs) /* 100 */
+ ENTRY_SAME(ni_syscall)
+ /* don't think hppa glibc even provides an entry pt for this
+ * so disable for now */
+ ENTRY_UHOH(socketcall)
+ ENTRY_SAME(syslog)
+ /* even though manpage says struct timeval contains longs, ours has
+ * time_t and suseconds_t -- both of which are safe wide/narrow */
+ ENTRY_SAME(setitimer)
+ ENTRY_SAME(getitimer) /* 105 */
+ ENTRY_SAME(capget)
+ ENTRY_SAME(capset)
+ ENTRY_SAME(pread)
+ ENTRY_SAME(pwrite)
+ ENTRY_SAME(getcwd) /* 110 */
+ ENTRY_SAME(vhangup)
+ ENTRY_SAME(ni_syscall)
+ ENTRY_SAME(vfork_wrapper)
+ /* struct rusage contains longs... */
+ ENTRY_DIFF(wait4)
+ ENTRY_SAME(swapoff) /* 115 */
+ /* struct sysinfo contains longs */
+ ENTRY_SAME(sysinfo)
+ ENTRY_SAME(shutdown)
+ ENTRY_SAME(fsync)
+ ENTRY_SAME(madvise)
+ ENTRY_SAME(clone_wrapper) /* 120 */
+ ENTRY_SAME(setdomainname)
+ ENTRY_SAME(sendfile)
+ /* struct sockaddr... */
+ ENTRY_SAME(recvfrom)
+ /* struct timex contains longs */
+ ENTRY_UHOH(adjtimex)
+ ENTRY_SAME(mprotect) /* 125 */
+ /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
+ ENTRY_DIFF(sigprocmask)
+ ENTRY_SAME(create_module)
+ /* struct module contains longs, but insmod builds a 64 bit struct
+ * if running under a 64 bit kernel */
+ ENTRY_SAME(init_module)
+ ENTRY_SAME(delete_module)
+ /* struct kernel_sym contains a long. Linus never heard of size_t? */
+ ENTRY_DIFF(get_kernel_syms) /* 130 */
+ ENTRY_SAME(quotactl)
+ ENTRY_SAME(getpgid)
+ ENTRY_SAME(fchdir)
+ /* bdflush(func, addr) where func has least-significant-bit set means
+ * addr is a pointer to long :-( */
+ ENTRY_UHOH(bdflush)
+ ENTRY_SAME(sysfs) /* 135 */
+ ENTRY_SAME(personality)
+ ENTRY_SAME(ni_syscall) /* for afs_syscall */
+ ENTRY_SAME(setfsuid)
+ ENTRY_SAME(setfsgid)
+ /* I think this might work */
+ ENTRY_SAME(llseek) /* 140 */
+ /* struct linux_dirent has longs, like 'unsigned long d_ino' which
+ * almost definitely should be 'ino_t d_ino' but it's too late now */
+ ENTRY_DIFF(getdents)
+ /* it is POSSIBLE that select will be OK because even though fd_set
+ * contains longs, the macros and sizes are clever. */
+ ENTRY_SAME(select)
+ ENTRY_SAME(flock)
+ ENTRY_SAME(msync)
+ /* struct iovec contains pointers */
+ ENTRY_UHOH(readv) /* 145 */
+ ENTRY_UHOH(writev)
+ ENTRY_SAME(getsid)
+ ENTRY_SAME(fdatasync)
+ /* struct __sysctl_args is a mess */
+ ENTRY_DIFF(sysctl)
+ ENTRY_SAME(mlock) /* 150 */
+ ENTRY_SAME(munlock)
+ ENTRY_SAME(mlockall)
+ ENTRY_SAME(munlockall)
+ /* struct sched_param is ok for now */
+ ENTRY_SAME(sched_setparam)
+ ENTRY_SAME(sched_getparam) /* 155 */
+ ENTRY_SAME(sched_setscheduler)
+ ENTRY_SAME(sched_getscheduler)
+ ENTRY_SAME(sched_yield)
+ ENTRY_SAME(sched_get_priority_max)
+ ENTRY_SAME(sched_get_priority_min) /* 160 */
+ /* These 2 would've worked if someone had defined struct timespec
+ * carefully, like timeval for example (which is about the same).
+ * Unfortunately it contains a long :-( */
+ ENTRY_DIFF(sched_rr_get_interval)
+ ENTRY_DIFF(nanosleep)
+ ENTRY_SAME(mremap)
+ ENTRY_SAME(setresuid)
+ ENTRY_SAME(getresuid) /* 165 */
+ /* might work, but in general signals need a thorough review */
+ ENTRY_UHOH(sigaltstack_wrapper)
+ /* struct passed back to user can contain long symbol values */
+ ENTRY_DIFF(query_module)
+ ENTRY_SAME(poll)
+ /* structs contain pointers and an in_addr... */
+ ENTRY_UHOH(nfsservctl)
+ ENTRY_SAME(setresgid) /* 170 */
+ ENTRY_SAME(getresgid)
+ ENTRY_SAME(prctl)
+ /* signals need a careful review */
+ ENTRY_SAME(rt_sigreturn_wrapper)
+ ENTRY_DIFF(rt_sigaction)
+ ENTRY_DIFF(rt_sigprocmask) /* 175 */
+ ENTRY_DIFF(rt_sigpending)
+ ENTRY_UHOH(rt_sigtimedwait)
+ ENTRY_UHOH(rt_sigqueueinfo)
+ ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
+ ENTRY_SAME(chown) /* 180 */
+ /* *sockopt() might work... */
+ ENTRY_SAME(setsockopt)
+ ENTRY_SAME(getsockopt)
+ /* struct msghdr contains pointers... */
+ ENTRY_UHOH(sendmsg)
+ ENTRY_UHOH(recvmsg)
+ ENTRY_SAME(semop) /* 185 */
+ ENTRY_SAME(semget)
+ /* needs a more careful review */
+ ENTRY_UHOH(semctl)
+ /* struct msgbuf contains a long */
+ ENTRY_UHOH(msgsnd)
+ ENTRY_UHOH(msgrcv)
+ ENTRY_SAME(msgget) /* 190 */
+ /* struct msqid_ds contains pointers */
+ ENTRY_UHOH(msgctl)
+ ENTRY_SAME(shmat_wrapper)
+ ENTRY_SAME(shmdt)
+ ENTRY_SAME(shmget)
+ /***************/
+ /* struct shmid_ds contains pointers */
+ ENTRY_UHOH(shmctl) /* 195 */
+ ENTRY_SAME(ni_syscall) /* streams1 */
+ ENTRY_SAME(ni_syscall) /* streams2 */
+
+.end
+
+ /* Make sure nothing else is placed on this page */
+
+ .align 4096
+ .export end_linux_gateway_page
+end_linux_gateway_page:
+
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
new file mode 100644
index 000000000..7b3de0e0a
--- /dev/null
+++ b/arch/parisc/kernel/time.c
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/arm/kernel/time.c
+ *
+ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
+ * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King
+ * Copyright (C) 1999 SuSE GmbH, (Philipp Rumpf, prumpf@tux.org)
+ *
+ * 1994-07-02 Alan Modra
+ * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
+ * 1998-12-20 Updated NTP code according to technical memorandum Jan '96
+ * "A Kernel Model for Precision Timekeeping" by Dave Mills
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/param.h>
+#include <asm/pdc.h>
+#include <asm/led.h>
+
+#include <linux/timex.h>
+
+extern rwlock_t xtime_lock;
+
+static int timer_value;
+static int timer_delta;
+static struct pdc_tod tod_data __attribute__((aligned(8)));
+
+void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int old;
+ int lost = 0;
+ int cr16;
+
+ old = timer_value;
+
+ cr16 = mfctl(16);
+ while((timer_value - cr16) < (timer_delta / 2)) {
+ timer_value += timer_delta;
+ lost++;
+ }
+
+ mtctl(timer_value ,16);
+
+ do_timer(regs);
+
+ led_interrupt_func();
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long flags;
+
+ read_lock_irqsave(&xtime_lock, flags);
+ tv->tv_sec = xtime.tv_sec;
+ tv->tv_usec = xtime.tv_usec;
+ read_unlock_irqrestore(&xtime_lock, flags);
+
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+ write_lock_irq(&xtime_lock);
+ xtime.tv_sec = tv->tv_sec;
+ xtime.tv_usec = tv->tv_usec;
+ write_unlock_irq(&xtime_lock);
+}
+
+void __init time_init(void)
+{
+ timer_delta = (100 * PAGE0->mem_10msec) / HZ;
+
+ /* make the first timer interrupt go off in one second */
+ timer_value = mfctl(16) + (HZ * timer_delta);
+ mtctl(timer_value, 16);
+
+
+ if(pdc_tod_read(&tod_data) == 0) {
+ xtime.tv_sec = tod_data.tod_sec;
+ xtime.tv_usec = tod_data.tod_usec;
+ } else {
+ printk(KERN_ERR "Error reading tod clock\n");
+ xtime.tv_sec = 0;
+ xtime.tv_usec = 0;
+ }
+
+}
+
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
new file mode 100644
index 000000000..d85553702
--- /dev/null
+++ b/arch/parisc/kernel/traps.c
@@ -0,0 +1,895 @@
+/*
+ * linux/arch/parisc/traps.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org>
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+
+#include <asm/smp.h>
+#include <asm/pdc.h>
+
+#ifdef CONFIG_KWDB
+#include <kdb/break.h> /* for BI2_KGDB_GDB */
+#include <kdb/kgdb_types.h> /* for __() */
+#include <kdb/save_state.h> /* for struct save_state */
+#include <kdb/kgdb_machine.h> /* for pt_regs_to_ssp and ssp_to_pt_regs */
+#include <kdb/trap.h> /* for I_BRK_INST */
+#endif /* CONFIG_KWDB */
+
+
+static inline void console_verbose(void)
+{
+ extern int console_loglevel;
+ console_loglevel = 15;
+}
+
+
+void page_exception(void);
+
+/*
+ * 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)
+
+int kstack_depth_to_print = 24;
+
+static void printbinary(unsigned long x, int nbits)
+{
+ unsigned long mask = 1UL << (nbits - 1);
+ while (mask != 0) {
+ printk(mask & x ? "1" : "0");
+ mask >>= 1;
+ }
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+#ifdef __LP64__
+#define RFMT " %016lx"
+#else
+#define RFMT " %08lx"
+#endif
+
+ printk("\n"); /* don't want to have that pretty register dump messed up */
+
+ printk(" YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\nPSW: ");
+ printbinary(regs->gr[0], 32);
+ printk("\n");
+
+ for (i = 0; i < 32; i += 4) {
+ int j;
+ printk("r%d-%d\t", i, i + 3);
+ for (j = 0; j < 4; j++) {
+ printk(RFMT, i + j == 0 ? 0 : regs->gr[i + j]);
+ }
+ printk("\n");
+ }
+
+ for (i = 0; i < 8; i += 4) {
+ int j;
+ printk("sr%d-%d\t", i, i + 4);
+ for (j = 0; j < 4; j++) {
+ printk(RFMT, regs->sr[i + j]);
+ }
+ printk("\n");
+ }
+
+#if REDICULOUSLY_VERBOSE
+ for (i = 0; i < 32; i++) {
+ printk("FR%2d : %016lx ", i, regs->fr[i]);
+ if ((i & 1) == 1)
+ printk("\n");
+ }
+#endif
+
+ printk("\nIASQ:" RFMT RFMT " IAOQ:" RFMT RFMT "\n",
+ regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
+ printk(" IIR: %08lx ISR:" RFMT " IOR:" RFMT "\nORIG_R28:" RFMT
+ "\n", regs->iir, regs->isr, regs->ior, regs->orig_r28);
+}
+
+void
+die_if_kernel (char *str, struct pt_regs *regs, long err)
+{
+ if (user_mode(regs)) {
+#if 1
+ if (err == 0)
+ return; /* STFU */
+
+ /* XXX for debugging only */
+ printk ("!!die_if_kernel: %s(%d): %s %ld\n",
+ current->comm, current->pid, str, err);
+ show_regs(regs);
+#endif
+ return;
+ }
+
+ printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);
+
+ show_regs(regs);
+
+ /* Wot's wrong wif bein' racy? */
+ if (current->thread.flags & PARISC_KERNEL_DEATH) {
+ printk("die_if_kernel recursion detected.\n");
+ sti();
+ while (1);
+ }
+ current->thread.flags |= PARISC_KERNEL_DEATH;
+ do_exit(SIGSEGV);
+}
+
+asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code)
+{
+}
+
+asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
+{
+}
+
+#ifndef CONFIG_MATH_EMULATION
+
+asmlinkage void math_emulate(long arg)
+{
+}
+
+#endif /* CONFIG_MATH_EMULATION */
+
+int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
+{
+ return syscall(regs);
+}
+
+struct {
+ int retval;
+
+ int (*func) (void *, struct pt_regs *);
+ void * data;
+} ipi_action[NR_CPUS];
+
+void ipi_interrupt(int irq, void *unused, struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+
+ if(!ipi_action[cpu].func)
+ BUG();
+
+ ipi_action[cpu].retval =
+ ipi_action[cpu].func(ipi_action[cpu].data, regs);
+}
+
+/* gdb uses break 4,8 */
+#define GDB_BREAK_INSN 0x10004
+void handle_gdb_break(struct pt_regs *regs, int wot)
+{
+ struct siginfo si;
+
+ si.si_code = wot;
+ si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ si.si_errno = 0;
+ force_sig_info(SIGTRAP, &si, current);
+}
+
+void handle_break(unsigned iir, struct pt_regs *regs)
+{
+ struct siginfo si;
+#ifdef CONFIG_KWDB
+ struct save_state ssp;
+#endif /* CONFIG_KWDB */
+
+ flush_all_caches();
+ switch(iir) {
+ case 0x00:
+ /* show registers, halt */
+ cli();
+ printk("break 0,0: pid=%d command='%s'\n",
+ current->pid, current->comm);
+ die_if_kernel("Breakpoint", regs, 0);
+ show_regs(regs);
+ si.si_code = TRAP_BRKPT;
+ si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ si.si_signo = SIGTRAP;
+ force_sig_info(SIGTRAP, &si, current);
+ break;
+
+ case GDB_BREAK_INSN:
+ die_if_kernel("Breakpoint", regs, 0);
+ handle_gdb_break(regs, TRAP_BRKPT);
+ break;
+
+#ifdef CONFIG_KWDB
+
+ case KGDB_BREAK_INSN:
+ mtctl(0, 15);
+ pt_regs_to_ssp(regs, &ssp);
+ kgdb_trap(I_BRK_INST, &ssp, 1);
+ ssp_to_pt_regs(&ssp, regs);
+ break;
+
+ case KGDB_INIT_BREAK_INSN:
+ mtctl(0, 15);
+ pt_regs_to_ssp(regs, &ssp);
+ kgdb_trap(I_BRK_INST, &ssp, 1);
+ ssp_to_pt_regs(&ssp, regs);
+
+ /* Advance pcoq to skip break */
+ regs->iaoq[0] = regs->iaoq[1];
+ regs->iaoq[1] += 4;
+ break;
+
+#endif /* CONFIG_KWDB */
+
+ default:
+ set_eiem(0);
+ printk("break %#08x: pid=%d command='%s'\n",
+ iir, current->pid, current->comm);
+ show_regs(regs);
+ si.si_signo = SIGTRAP;
+ si.si_code = TRAP_BRKPT;
+ si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ force_sig_info(SIGTRAP, &si, current);
+ return;
+ }
+}
+
+/* Format of the floating-point exception registers. */
+struct exc_reg {
+ unsigned int exception : 6;
+ unsigned int ei : 26;
+};
+
+/* Macros for grabbing bits of the instruction format from the 'ei'
+ field above. */
+/* Major opcode 0c and 0e */
+#define FP0CE_UID(i) (((i) >> 6) & 3)
+#define FP0CE_CLASS(i) (((i) >> 9) & 3)
+#define FP0CE_SUBOP(i) (((i) >> 13) & 7)
+#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
+#define FP0C_FORMAT(i) (((i) >> 11) & 3)
+#define FP0E_FORMAT(i) (((i) >> 11) & 1)
+
+/* Major opcode 0c, uid 2 (performance monitoring) */
+#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
+
+/* Major opcode 2e (fused operations). */
+#define FP2E_SUBOP(i) (((i) >> 5) & 1)
+#define FP2E_FORMAT(i) (((i) >> 11) & 1)
+
+/* Major opcode 26 (FMPYSUB) */
+/* Major opcode 06 (FMPYADD) */
+#define FPx6_FORMAT(i) ((i) & 0x1f)
+
+/* Flags and enable bits of the status word. */
+#define FPSW_FLAGS(w) ((w) >> 27)
+#define FPSW_ENABLE(w) ((w) & 0x1f)
+#define FPSW_V (1<<4)
+#define FPSW_Z (1<<3)
+#define FPSW_O (1<<2)
+#define FPSW_U (1<<1)
+#define FPSW_I (1<<0)
+
+/* Emulate a floating point instruction if necessary and possible
+ (this will be moved elsewhere eventually). Return zero if
+ successful or if emulation was not required, -1 if the instruction
+ is actually illegal or unimplemented. The status word passed as
+ the first parameter will be modified to signal exceptions, if
+ any. */
+
+/* FIXME!!! This is really incomplete and, at the moment, most
+ illegal FP instructions will simply act as no-ops. Obviously that
+ is *not* what we want. Also we don't even try to handle exception
+ types other than the 'unimplemented' ones. */
+int
+fp_emul_insn(u32 *sw, struct exc_reg exc, struct pt_regs *regs)
+{
+ switch (exc.exception) {
+ case 0x3: /* Unimplemented, opcode 06 */
+ break;
+ case 0x9: /* Unimplemented, opcode 0c */
+ /* We do not support quadword operations, end of
+ story. There's no support for them in GCC. */
+ if (FP0C_FORMAT(exc.ei) == 3)
+ return -1; /* SIGILL */
+ /* Fall through. */
+ case 0xa: /* Unimplemented, opcode 0e */
+ if (FP0CE_CLASS(exc.ei) == 1) {
+ /* FCNV instructions of various sorts. */
+ } else {
+ if (FP0CE_CLASS(exc.ei == 0)
+ && FP0CE_SUBOP(exc.ei == 5)) {
+ /* FRND instructions should be
+ emulated, at some point, I
+ guess. */
+ return -1; /* SIGILL */
+ }
+ }
+ break;
+ case 0x23: /* Unimplemented, opcode 26 */
+ break;
+ case 0x2b: /* Unimplemented, opcode 2e */
+ break;
+ case 0x1: /* Unimplemented, opcode 0e/0c */
+ /* FIXME: How the hell are we supposed to tell which
+ opcode it is? */
+ break;
+ default:
+ return -1; /* Punt */
+ }
+
+ return 0;
+}
+
+/* Handle a floating point exception. Return zero if the faulting
+ instruction can be completed successfully. */
+int
+handle_fpe(struct pt_regs *regs)
+{
+ struct siginfo si;
+ union {
+ struct fpsw {
+ /* flag bits */
+ unsigned int fv : 1;
+ unsigned int fz : 1;
+ unsigned int fo : 1;
+ unsigned int fu : 1;
+ unsigned int fi : 1;
+
+ unsigned int c : 1;
+ unsigned int pad1 : 4;
+ unsigned int cq : 11;
+ unsigned int rm : 2;
+ unsigned int pad2 : 2;
+ unsigned int t : 1;
+ unsigned int d : 1;
+
+ /* enable bits */
+ unsigned int ev : 1;
+ unsigned int ez : 1;
+ unsigned int eo : 1;
+ unsigned int eu : 1;
+ unsigned int ei : 1;
+ } status;
+ u32 word;
+ } sw;
+ struct exc_reg excepts[7];
+ unsigned int code = 0;
+ unsigned int throw;
+
+ /* Status word = FR0L. */
+ memcpy(&sw, regs->fr, sizeof(sw));
+ /* Exception words = FR0R-FR3R. */
+ memcpy(excepts, ((char *) regs->fr) + 4, sizeof(excepts));
+
+ /* This is all CPU dependent. Since there is no public
+ documentation on the PA2.0 processors we will just assume
+ everything is like the 7100/7100LC/7300LC for now.
+
+ Specifically: All exceptions are marked as "unimplemented"
+ in the exception word, and the only exception word used is
+ excepts[1]. */
+
+ /* Try to emulate the instruction. Also determine if it is
+ really an illegal instruction in the process.
+
+ FIXME: fp_emul_insn() only checks for the "unimplemented"
+ exceptions at the moment. So this may break horribly on
+ PA2.0, where we may want to also check to see if we should
+ just send SIGFPE (or maybe not, let's see the documentation
+ first...) */
+ if (fp_emul_insn(&sw.word, excepts[1], regs) == -1)
+ goto send_sigill;
+
+ /* Take the intersection of the flag bits in the FPSW and the
+ enable bits in the FPSW. */
+ throw = FPSW_FLAGS(sw.word) & FPSW_ENABLE(sw.word);
+
+ /* Concoct an appropriate si_code. Of course we don't know
+ what to do if multiple exceptions were enabled and multiple
+ flags were set. Maybe that's why HP/UX doesn't implement
+ feenableexcept(). */
+
+ if (throw == 0)
+ goto success; /* Duh. */
+ else if (throw & FPSW_V)
+ code = FPE_FLTINV;
+ else if (throw & FPSW_Z)
+ code = FPE_FLTDIV;
+ else if (throw & FPSW_O)
+ code = FPE_FLTOVF;
+ else if (throw & FPSW_U)
+ code = FPE_FLTUND;
+ else if (throw & FPSW_I)
+ code = FPE_FLTRES;
+
+#if 1 /* Debugging... */
+ printk("Unemulated floating point exception, pid=%d (%s)\n",
+ current->pid, current->comm);
+ show_regs(regs);
+ {
+ int i;
+ printk("FP Status: %08x\n", sw.word);
+ printk("FP Exceptions:\n");
+ for (i = 0; i < 7; i++) {
+ printk("\tExcept%d: exception %03x insn %06x\n",
+ i, excepts[i].exception, excepts[i].ei);
+ }
+ }
+#endif
+
+ /* FIXME: Should we clear the flag bits, T bit, and exception
+ registers here? */
+
+ si.si_signo = SIGFPE;
+ si.si_errno = 0;
+ si.si_code = code;
+ si.si_addr = (void *) regs->iaoq[0];
+ force_sig_info(SIGFPE, &si, current);
+ return -1;
+
+ send_sigill:
+ si.si_signo = SIGILL;
+ si.si_errno = 0;
+ si.si_code = ILL_COPROC;
+ si.si_addr = (void *) regs->iaoq[0];
+ force_sig_info(SIGILL, &si, current);
+ return -1;
+
+ success:
+ /* We absolutely have to clear the T bit and exception
+ registers to allow the process to recover. Otherwise every
+ subsequent floating point instruction will trap. */
+ sw.status.t = 0;
+ memset(excepts, 0, sizeof(excepts));
+
+ memcpy(regs->fr, &sw, sizeof(sw));
+ memcpy(((char *) regs->fr) + 4,excepts , sizeof(excepts));
+ return 0;
+}
+
+int handle_toc(void)
+{
+ return 0;
+}
+
+void default_trap(int code, struct pt_regs *regs)
+{
+ printk("Trap %d on CPU %d\n", code, smp_processor_id());
+
+ show_regs(regs);
+}
+
+void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
+
+
+#ifdef CONFIG_KWDB
+int
+debug_call (void) {
+ printk ("Debug call.\n");
+ return 0;
+}
+
+int
+debug_call_leaf (void) {
+ return 0;
+}
+#endif /* CONFIG_KWDB */
+
+extern void do_page_fault(struct pt_regs *, int, unsigned long);
+extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long);
+extern void transfer_pim_to_trap_frame(struct pt_regs *);
+extern void pdc_console_restart(void);
+
+void handle_interruption(int code, struct pt_regs *regs)
+{
+ unsigned long fault_address = 0;
+ unsigned long fault_space = 0;
+ struct siginfo si;
+#ifdef CONFIG_KWDB
+ struct save_state ssp;
+#endif /* CONFIG_KWDB */
+
+ if (code == 1)
+ pdc_console_restart(); /* switch back to pdc if HPMC */
+ else
+ sti();
+
+#ifdef __LP64__
+
+ /*
+ * FIXME:
+ * For 32 bit processes we don't want the b bits (bits 0 & 1)
+ * in the ior. This is more appropriately handled in the tlb
+ * miss handlers. Changes need to be made to support addresses
+ * >32 bits for 64 bit processes.
+ */
+
+ regs->ior &= 0x3FFFFFFFFFFFFFFFUL;
+#endif
+
+#if 0
+ printk("interrupted with code %d, regs %p\n", code, regs);
+ show_regs(regs);
+#endif
+
+ switch(code) {
+ case 1:
+ parisc_terminate("High Priority Machine Check (HPMC)",regs,code,0);
+ /* NOT REACHED */
+ case 3: /* Recovery counter trap */
+ regs->gr[0] &= ~PSW_R;
+ if (regs->iasq[0])
+ handle_gdb_break(regs, TRAP_TRACE);
+ /* else this must be the start of a syscall - just let it
+ * run.
+ */
+ return;
+
+ case 5:
+ flush_all_caches();
+ cpu_lpmc(5, regs);
+ return;
+
+ case 6:
+ fault_address = regs->iaoq[0];
+ fault_space = regs->iasq[0];
+ break;
+
+ case 9: /* Break Instruction */
+ handle_break(regs->iir,regs);
+ return;
+
+ case 14:
+ /* Assist Exception Trap, i.e. floating point exception. */
+ die_if_kernel("Floating point exception", regs, 0); /* quiet */
+ handle_fpe(regs);
+ return;
+ case 15:
+ case 16: /* Non-Access TLB miss faulting address is in IOR */
+ case 17:
+ case 26:
+ fault_address = regs->ior;
+ fault_space = regs->isr;
+
+ if (code == 26 && fault_space == 0)
+ parisc_terminate("Data access rights fault in kernel",regs,code,fault_address);
+ break;
+
+ case 19:
+ regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
+ /* fall thru */
+ case 21:
+ handle_gdb_break(regs, TRAP_HWBKPT);
+ return;
+
+ case 25: /* Taken branch trap */
+ regs->gr[0] &= ~PSW_T;
+ if (regs->iasq[0])
+ handle_gdb_break(regs, TRAP_BRANCH);
+ /* else this must be the start of a syscall - just let it
+ * run.
+ */
+ return;
+
+#if 0 /* def CONFIG_KWDB */
+ case I_TAKEN_BR: /* 25 */
+ mtctl(0, 15);
+ pt_regs_to_ssp(regs, &ssp);
+ kgdb_trap(I_TAKEN_BR, &ssp, 1);
+ ssp_to_pt_regs(&ssp, regs);
+ break;
+#endif /* CONFIG_KWDB */
+
+ case 8:
+ die_if_kernel("Illegal instruction", regs, code);
+ si.si_code = ILL_ILLOPC;
+ goto give_sigill;
+
+ case 10:
+ die_if_kernel("Priviledged operation - shouldn't happen!", regs, code);
+ si.si_code = ILL_PRVOPC;
+ goto give_sigill;
+ case 11:
+ die_if_kernel("Priviledged register - shouldn't happen!", regs, code);
+ si.si_code = ILL_PRVREG;
+ give_sigill:
+ si.si_signo = SIGILL;
+ si.si_errno = 0;
+ si.si_addr = (void *) regs->iaoq[0];
+ force_sig_info(SIGILL, &si, current);
+ return;
+
+ case 28: /* Unaligned just causes SIGBUS for now */
+ die_if_kernel("Unaligned data reference", regs, code);
+ si.si_code = BUS_ADRALN;
+ si.si_signo = SIGBUS;
+ si.si_errno = 0;
+ si.si_addr = (void *) regs->ior;
+ force_sig_info(SIGBUS, &si, current);
+ return;
+
+ default:
+ if (user_mode(regs)) {
+ printk("\nhandle_interruption() pid=%d command='%s'\n",
+ current->pid, current->comm);
+ show_regs(regs);
+ /* SIGBUS, for lack of a better one. */
+ si.si_signo = SIGBUS;
+ si.si_code = BUS_OBJERR;
+ si.si_errno = 0;
+ si.si_addr = (void *) regs->ior;
+ force_sig_info(SIGBUS, &si, current);
+ return;
+ }
+ parisc_terminate("Unexpected Interruption!",regs,code,0);
+ /* NOT REACHED */
+ }
+
+ if (user_mode(regs)) {
+ if (fault_space != regs->sr[7]) {
+ if (fault_space == 0)
+ printk("User Fault on Kernel Space ");
+ else /* this case should never happen, but whatever... */
+ printk("User Fault (long pointer) ");
+ printk("pid=%d command='%s'\n", current->pid, current->comm);
+ show_regs(regs);
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SEGV_MAPERR;
+ si.si_addr = (void *) regs->ior;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+ }
+ }
+ else {
+
+ /*
+ * The kernel should never fault on its own address space.
+ */
+
+ if (fault_space == 0)
+ parisc_terminate("Kernel Fault",regs,code,fault_address);
+ }
+
+#ifdef CONFIG_KWDB
+ debug_call_leaf ();
+#endif /* CONFIG_KWDB */
+
+ do_page_fault(regs, code, fault_address);
+
+ /*
+ * This should not be necessary.
+ * However, we do not currently
+ * implement flush_page_to_ram.
+ *
+ * The problem is that if we just
+ * brought in some code through the
+ * D-cache, the I-cache may not see
+ * it since it hasn't been flushed
+ * to ram.
+ */
+
+/* flush_all_caches(); */
+
+#if 0
+ printk("returning %p\n", regs);
+/* show_regs(regs); */
+#endif
+
+ return;
+
+}
+
+void show_stack(unsigned long sp)
+{
+#if 1
+ if ((sp & 0xc0000000UL) == 0xc0000000UL) {
+
+ __u32 *stackptr;
+ __u32 *dumpptr;
+
+ /* Stack Dump! */
+
+ stackptr = (__u32 *)sp;
+ dumpptr = (__u32 *)(sp & ~(INIT_TASK_SIZE - 1));
+ printk("\nDumping Stack from %p to %p:\n",dumpptr,stackptr);
+ while (dumpptr < stackptr) {
+ printk("%04x %08x %08x %08x %08x %08x %08x %08x %08x\n",
+ ((__u32)dumpptr) & 0xffff,
+ dumpptr[0], dumpptr[1], dumpptr[2], dumpptr[3],
+ dumpptr[4], dumpptr[5], dumpptr[6], dumpptr[7]);
+ dumpptr += 8;
+ }
+ }
+#endif
+}
+
+
+void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
+{
+ set_eiem(0);
+ cli();
+
+ if (code == 1)
+ transfer_pim_to_trap_frame(regs);
+
+#if 1
+ show_stack(regs->gr[30]);
+#endif
+
+ printk("\n%s: Code=%d regs=%p (Addr=%08lx)\n",msg,code,regs,offset);
+ show_regs(regs);
+
+ for(;;)
+ ;
+}
+
+void transfer_pim_to_trap_frame(struct pt_regs *regs)
+{
+ register int i;
+ extern unsigned int hpmc_pim_data[];
+ struct pdc_hpmc_pim_11 *pim_narrow;
+ struct pdc_hpmc_pim_20 *pim_wide;
+
+ if (boot_cpu_data.cpu_type >= pcxu) {
+
+ pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
+
+ /*
+ * Note: The following code will probably generate a
+ * bunch of truncation error warnings from the compiler.
+ * Could be handled with an ifdef, but perhaps there
+ * is a better way.
+ */
+
+ regs->gr[0] = pim_wide->cr[22];
+
+ for (i = 1; i < 32; i++)
+ regs->gr[i] = pim_wide->gr[i];
+
+ for (i = 0; i < 32; i++)
+ regs->fr[i] = pim_wide->fr[i];
+
+ for (i = 0; i < 8; i++)
+ regs->sr[i] = pim_wide->sr[i];
+
+ regs->iasq[0] = pim_wide->cr[17];
+ regs->iasq[1] = pim_wide->iasq_back;
+ regs->iaoq[0] = pim_wide->cr[18];
+ regs->iaoq[1] = pim_wide->iaoq_back;
+
+ regs->cr30 = pim_wide->cr[30];
+ regs->sar = pim_wide->cr[11];
+ regs->iir = pim_wide->cr[19];
+ regs->isr = pim_wide->cr[20];
+ regs->ior = pim_wide->cr[21];
+ }
+ else {
+ pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
+
+ regs->gr[0] = pim_narrow->cr[22];
+
+ for (i = 1; i < 32; i++)
+ regs->gr[i] = pim_narrow->gr[i];
+
+ for (i = 0; i < 32; i++)
+ regs->fr[i] = pim_narrow->fr[i];
+
+ for (i = 0; i < 8; i++)
+ regs->sr[i] = pim_narrow->sr[i];
+
+ regs->iasq[0] = pim_narrow->cr[17];
+ regs->iasq[1] = pim_narrow->iasq_back;
+ regs->iaoq[0] = pim_narrow->cr[18];
+ regs->iaoq[1] = pim_narrow->iaoq_back;
+
+ regs->cr30 = pim_narrow->cr[30];
+ regs->sar = pim_narrow->cr[11];
+ regs->iir = pim_narrow->cr[19];
+ regs->isr = pim_narrow->cr[20];
+ regs->ior = pim_narrow->cr[21];
+ }
+
+ /*
+ * The following fields only have meaning if we came through
+ * another path. So just zero them here.
+ */
+
+ regs->ksp = 0;
+ regs->kpc = 0;
+ regs->orig_r28 = 0;
+}
+
+int __init check_ivt(void *iva)
+{
+ int i;
+ u32 check = 0;
+ u32 *ivap;
+ u32 *hpmcp;
+ u32 length;
+ extern void os_hpmc(void);
+ extern void os_hpmc_end(void);
+
+ if(strcmp((char *)iva, "cows can fly"))
+ return -1;
+
+ ivap = (u32 *)iva;
+
+ for (i = 0; i < 8; i++)
+ *ivap++ = 0;
+
+ /* Compute Checksum for HPMC handler */
+
+ length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);
+ ivap[7] = length;
+
+ hpmcp = (u32 *)os_hpmc;
+
+ for(i=0; i<length/4; i++)
+ check += *hpmcp++;
+
+ for(i=0; i<8; i++)
+ check += ivap[i];
+
+ ivap[5] = -check;
+
+ return 0;
+}
+
+#ifndef __LP64__
+extern const void fault_vector_11;
+#endif
+extern const void fault_vector_20;
+
+void __init trap_init(void)
+{
+ volatile long eiem;
+ void *iva;
+
+ printk("trap_init\n");
+
+ if (boot_cpu_data.cpu_type >= pcxu)
+ iva = (void *) &fault_vector_20;
+ else
+#ifdef __LP64__
+ panic("Can't boot 64-bit OS on PA1.1 processor!");
+#else
+ iva = (void *) &fault_vector_11;
+#endif
+
+ if(check_ivt(iva))
+ panic("IVT invalid");
+
+ mtctl(0, 30);
+ mtctl(90000000, 16);
+ set_eiem(-1L);
+ mtctl(-1L, 23);
+ asm volatile ("rsm 0,%0" : "=r" (eiem));
+}
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
new file mode 100644
index 000000000..9f0670667
--- /dev/null
+++ b/arch/parisc/lib/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for parisc-specific library files..
+#
+
+
+L_TARGET = lib.a
+L_OBJS = lusercopy.o bitops.o checksum.o
+
+
+.S.o:
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c
new file mode 100644
index 000000000..c275c4246
--- /dev/null
+++ b/arch/parisc/lib/bitops.c
@@ -0,0 +1,60 @@
+/* atomic.c: atomic operations which got too long to be inlined all over
+ * the place.
+ *
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+#ifdef CONFIG_SMP
+spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
+ [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+};
+#endif
+
+spinlock_t __atomic_lock = SPIN_LOCK_UNLOCKED;
+
+#ifndef __LP64__
+unsigned long __xchg(unsigned long x, unsigned long *ptr, int size)
+{
+ unsigned long temp, flags;
+
+ if (size != sizeof x) {
+ printk("__xchg called with bad pointer\n");
+ }
+ spin_lock_irqsave(&__atomic_lock, flags);
+ temp = *ptr;
+ *ptr = x;
+ spin_unlock_irqrestore(&__atomic_lock, flags);
+ return temp;
+}
+#else
+unsigned long __xchg(unsigned long x, unsigned long *ptr, int size)
+{
+ unsigned long temp, flags;
+ unsigned int *ptr32;
+
+ if (size == 8) {
+try_long:
+ spin_lock_irqsave(&__atomic_lock, flags);
+ temp = *ptr;
+ *ptr = x;
+ spin_unlock_irqrestore(&__atomic_lock, flags);
+ return temp;
+ }
+ if (size == 4) {
+ ptr32 = (unsigned int *)ptr;
+ spin_lock_irqsave(&__atomic_lock, flags);
+ temp = (unsigned long)*ptr32;
+ *ptr32 = (unsigned int)x;
+ spin_unlock_irqrestore(&__atomic_lock, flags);
+ return temp;
+ }
+
+ printk("__xchg called with bad pointer\n");
+ goto try_long;
+}
+#endif
diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
new file mode 100644
index 000000000..fa02027dd
--- /dev/null
+++ b/arch/parisc/lib/checksum.c
@@ -0,0 +1,130 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * MIPS specific IP/TCP/UDP checksumming routines
+ *
+ * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * $Id: checksum.c,v 1.3 1997/12/01 17:57:34 ralf Exp $
+ */
+#include <net/checksum.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+static inline unsigned short from32to16(unsigned int x)
+{
+ /* 32 bits --> 16 bits + carry */
+ x = (x & 0xffff) + (x >> 16);
+ /* 16 bits + carry --> 16 bits including carry */
+ x = (x & 0xffff) + (x >> 16);
+ return (unsigned short)x;
+}
+
+static inline unsigned int do_csum(const unsigned char * buff, int len)
+{
+ int odd, count;
+ unsigned int result = 0;
+
+ if (len <= 0)
+ goto out;
+ odd = 1 & (unsigned long) buff;
+ if (odd) {
+ result = be16_to_cpu(*buff);
+ len--;
+ buff++;
+ }
+ count = len >> 1; /* nr of 16-bit words.. */
+ if (count) {
+ if (2 & (unsigned long) buff) {
+ result += *(unsigned short *) buff;
+ count--;
+ len -= 2;
+ buff += 2;
+ }
+ count >>= 1; /* nr of 32-bit words.. */
+ if (count) {
+ unsigned int carry = 0;
+ do {
+ unsigned int w = *(unsigned int *) buff;
+ count--;
+ buff += 4;
+ result += carry;
+ result += w;
+ carry = (w > result);
+ } while (count);
+ result += carry;
+ result = (result & 0xffff) + (result >> 16);
+ }
+ if (len & 2) {
+ result += *(unsigned short *) buff;
+ buff += 2;
+ }
+ }
+ if (len & 1)
+ result += le16_to_cpu(*buff);
+ result = from32to16(result);
+ if (odd)
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+ return result;
+}
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
+{
+ unsigned int result = do_csum(buff, len);
+
+ /* add in old sum, and carry.. */
+ result += sum;
+ if(sum > result)
+ result += 1;
+ return result;
+}
+
+/*
+ * copy while checksumming, otherwise like csum_partial
+ */
+unsigned int csum_partial_copy(const char *src, char *dst,
+ int len, unsigned int sum)
+{
+ /*
+ * It's 2:30 am and I don't feel like doing it real ...
+ * This is lots slower than the real thing (tm)
+ */
+ sum = csum_partial(src, len, sum);
+ memcpy(dst, src, len);
+
+ return sum;
+}
+
+/*
+ * Copy from userspace and compute checksum. If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user (const char *src, char *dst,
+ int len, unsigned int sum,
+ int *err_ptr)
+{
+ int missing;
+
+ missing = copy_from_user(dst, src, len);
+ if (missing) {
+ memset(dst + len - missing, 0, missing);
+ *err_ptr = -EFAULT;
+ }
+
+ return csum_partial(dst, len, sum);
+}
diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S
new file mode 100644
index 000000000..b4b88b53c
--- /dev/null
+++ b/arch/parisc/lib/lusercopy.S
@@ -0,0 +1,242 @@
+/*------------------------------------------------------------------------------
+ * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ *
+ * Assembly Language User Access Routines
+ * Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * These routines still have plenty of room for optimization
+ * (word & doubleword load/store, dual issue, store hints, etc.).
+ */
+
+/*
+ * The following routines assume that space register 3 (sr3) contains
+ * the space id associated with the current users address space.
+ */
+
+
+ .level 1.1
+ .text
+
+#include <asm/assembly.h>
+#include <asm/errno.h>
+
+ /*
+ * get_sr gets the appropriate space value into
+ * sr1 for kernel/user space access, depending
+ * on the flag stored in the task structure.
+ */
+
+ /* FIXME! depi below has hardcoded idea of kernel stack size */
+
+ .macro get_sr
+ copy %r30,%r1 ;! Get task structure
+ depi 0,31,14,%r1 ;! into r1
+ ldw TASK_SEGMENT(%r1),%r22
+ mfsp %sr3,%r1
+ or,<> %r22,%r0,%r0
+ copy %r0,%r1
+ mtsp %r1,%sr1
+ .endm
+
+ /*
+ * unsigned long
+ * lcopy_to_user(void *to, const void *from, unsigned long n)
+ *
+ * Returns 0 for success.
+ * otherwise, returns number of bytes not transferred.
+ */
+
+ .export lcopy_to_user,code
+lcopy_to_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,=,n 0,%r24,$lctu_done
+ get_sr
+$lctu_loop:
+ ldbs,ma 1(%r25),%r1
+ addib,<> -1,%r24,$lctu_loop
+1: stbs,ma %r1,1(%sr1,%r26)
+$lctu_done:
+ bv %r0(%r2)
+ copy %r24,%r28
+ .exit
+
+2: b $lctu_done
+ ldo 1(%r24),%r24
+
+ .section __ex_table,"a"
+ .word 1b,(2b-1b)
+ .previous
+
+ .procend
+
+ /*
+ * unsigned long
+ * lcopy_from_user(void *to, const void *from, unsigned long n)
+ *
+ * Returns 0 for success.
+ * otherwise, returns number of bytes not transferred.
+ *
+ * NOTE: This routine will also zero any bytes in the
+ * destination that were not copied due to a fault.
+ *
+ */
+
+ .export lcopy_from_user,code
+lcopy_from_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,=,n 0,%r24,$lcfu_done
+ get_sr
+$lcfu_loop:
+1: ldbs,ma 1(%sr1,%r25),%r1
+ addib,<> -1,%r24,$lcfu_loop
+ stbs,ma %r1,1(%r26)
+$lcfu_done:
+ bv %r0(%r2)
+ copy %r24,%r28
+ .exit
+
+2: copy %r24,%r23
+$lcfu_zero_loop:
+ addib,<> -1,%r23,$lcfu_zero_loop
+ stbs,ma %r0,1(%r26)
+ b $lcfu_done
+ nop
+
+ .section __ex_table,"a"
+ .word 1b,(2b-1b)
+ .previous
+
+ .procend
+
+ /*
+ * long lstrncpy_from_user(char *dst, const char *src, long n)
+ *
+ * Returns -EFAULT if exception before terminator,
+ * N if the entire buffer filled,
+ * otherwise strlen + 1 (i.e. includes zero byte)
+ */
+
+ .export lstrncpy_from_user,code
+lstrncpy_from_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,= 0,%r24,$lsfu_done
+ copy %r26,%r23
+ get_sr
+1: ldbs,ma 1(%sr1,%r25),%r1
+$lsfu_loop:
+ stbs,ma %r1,1(%r26)
+ comib,=,n 0,%r1,$lsfu_done
+ addib,<>,n -1,%r24,$lsfu_loop
+2: ldbs,ma 1(%sr1,%r25),%r1
+$lsfu_done:
+ sub %r26,%r23,%r28
+$lsfu_exit:
+ bv %r0(%r2)
+ nop
+ .exit
+
+3: b $lsfu_exit
+ ldi -EFAULT,%r28
+
+ .section __ex_table,"a"
+ .word 1b,(3b-1b)
+ .word 2b,(2b-1b)
+ .previous
+
+ .procend
+
+ /*
+ * unsigned long lclear_user(void *to, unsigned long n)
+ *
+ * Returns 0 for success.
+ * otherwise, returns number of bytes not transferred.
+ */
+
+ .export lclear_user,code
+lclear_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,=,n 0,%r25,$lclu_done
+ get_sr
+$lclu_loop:
+ addib,<> -1,%r25,$lclu_loop
+1: stbs,ma %r0,1(%sr1,%r26)
+
+$lclu_done:
+ bv %r0(%r2)
+ copy %r25,%r28
+ .exit
+
+2: b $lclu_done
+ ldo 1(%r25),%r25
+
+ .section __ex_table,"a"
+ .word 1b,(2b-1b)
+ .previous
+
+ .procend
+
+ /*
+ * long lstrnlen_user(char *s, long n)
+ *
+ * Returns 0 if exception before zero byte or reaching N,
+ * N+1 if N would be exceeded,
+ * else strlen + 1 (i.e. includes zero byte).
+ */
+
+ .export lstrnlen_user,code
+lstrnlen_user:
+ .proc
+ .callinfo NO_CALLS
+ .entry
+ comib,= 0,%r25,$lslen_nzero
+ copy %r26,%r24
+ get_sr
+1: ldbs,ma 1(%sr1,%r26),%r1
+$lslen_loop:
+ comib,=,n 0,%r1,$lslen_done
+ addib,<> -1,%r25,$lslen_loop
+2: ldbs,ma 1(%sr1,%r26),%r1
+$lslen_done:
+ bv %r0(%r2)
+ sub %r26,%r24,%r28
+ .exit
+
+$lslen_nzero:
+ b $lslen_done
+ ldo 1(%r26),%r26 /* special case for N == 0 */
+
+3: b $lslen_done
+ copy %r24,%r26 /* reset r26 so 0 is returned on fault */
+
+ .section __ex_table,"a"
+ .word 1b,(3b-1b)
+ .word 2b,(2b-1b)
+ .previous
+
+ .procend
+
+ .end
diff --git a/arch/parisc/mm/Makefile b/arch/parisc/mm/Makefile
new file mode 100644
index 000000000..819872a7f
--- /dev/null
+++ b/arch/parisc/mm/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the linux parisc-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 fault.o kmap.o extable.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/mm/extable.c b/arch/parisc/mm/extable.c
new file mode 100644
index 000000000..705688934
--- /dev/null
+++ b/arch/parisc/mm/extable.c
@@ -0,0 +1,69 @@
+/*
+ * Kernel exception handling table support. Derived from arch/i386/mm/extable.c.
+ *
+ * Copyright (C) 2000 Hewlett-Packard Co
+ * Copyright (C) 2000 John Marvin (jsm@fc.hp.com)
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <asm/uaccess.h>
+
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline const struct exception_table_entry *
+search_one_table (const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long addr)
+{
+ /* Abort early if the search value is out of range. */
+
+ if ((addr < first->addr) || (addr > last->addr))
+ return 0;
+
+ while (first <= last) {
+ const struct exception_table_entry *mid;
+ long diff;
+
+ mid = first + ((last - first)/2);
+ diff = mid->addr - addr;
+
+ if (diff == 0)
+ return mid;
+ else if (diff < 0)
+ first = mid+1;
+ else
+ last = mid-1;
+ }
+
+ return 0;
+}
+
+const struct exception_table_entry *
+search_exception_table (unsigned long addr)
+{
+#ifndef CONFIG_MODULE
+ /* There is only the kernel to search. */
+ return search_one_table(__start___ex_table,
+ __stop___ex_table - 1,
+ addr);
+#else
+ struct exception_table_entry *ret;
+ /* The kernel is the last "module" -- no need to treat it special. */
+ struct module *mp;
+
+ for (mp = module_list; mp ; mp = mp->next) {
+ if (!mp->ex_table_start)
+ continue;
+ ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1,
+ addr);
+ if (ret)
+ return ret;
+ }
+ return 0;
+#endif
+}
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
new file mode 100644
index 000000000..68d4614ec
--- /dev/null
+++ b/arch/parisc/mm/fault.c
@@ -0,0 +1,283 @@
+/* $Id: fault.c,v 1.5 2000/01/26 16:20:29 jsm Exp $
+ *
+ * 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, 1997, 1998 by Ralf Baechle
+ * Copyright 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
+ * Copyright 1999 Hewlett Packard Co.
+ *
+ */
+
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/uaccess.h>
+
+
+/* Defines for parisc_acctyp() */
+#define READ 0
+#define WRITE 1
+
+/* Various important other fields */
+#define bit22set(x) (x & 0x00000200)
+#define bits23_25set(x) (x & 0x000001c0)
+#define isGraphicsFlushRead(x) ((x & 0xfc003fdf) == 0x04001a80)
+ /* extended opcode is 0x6a */
+
+#define BITSSET 0x1c0 /* for identifying LDCW */
+
+/*
+ * parisc_acctyp(unsigned int inst) --
+ * Given a PA-RISC memory access instruction, determine if the
+ * the instruction would perform a memory read or memory write
+ * operation.
+ *
+ * This function assumes that the given instruction is a memory access
+ * instruction (i.e. you should really only call it if you know that
+ * the instruction has generated some sort of a memory access fault).
+ *
+ * Returns:
+ * VM_READ if read operation
+ * VM_WRITE if write operation
+ * VM_EXEC if execute operation
+ */
+static unsigned long
+parisc_acctyp(unsigned long code, unsigned int inst)
+{
+ if (code == 6 || code == 16)
+ return VM_EXEC;
+
+ switch (inst & 0xf0000000) {
+ case 0x40000000: /* load */
+ case 0x50000000: /* new load */
+ return VM_READ;
+
+ case 0x60000000: /* store */
+ case 0x70000000: /* new store */
+ return VM_WRITE;
+
+ case 0x20000000: /* coproc */
+ case 0x30000000: /* coproc2 */
+ if (bit22set(inst))
+ return VM_WRITE;
+
+ case 0x0: /* indexed/memory management */
+ if (bit22set(inst)) {
+ /*
+ * Check for the 'Graphics Flush Read' instruction.
+ * It resembles an FDC instruction, except for bits
+ * 20 and 21. Any combination other than zero will
+ * utilize the block mover functionality on some
+ * older PA-RISC platforms. The case where a block
+ * move is performed from VM to graphics IO space
+ * should be treated as a READ.
+ *
+ * The significance of bits 20,21 in the FDC
+ * instruction is:
+ *
+ * 00 Flush data cache (normal instruction behavior)
+ * 01 Graphics flush write (IO space -> VM)
+ * 10 Graphics flush read (VM -> IO space)
+ * 11 Graphics flush read/write (VM <-> IO space)
+ */
+ if (isGraphicsFlushRead(inst))
+ return VM_READ;
+ return VM_WRITE;
+ } else {
+ /*
+ * Check for LDCWX and LDCWS (semaphore instructions).
+ * If bits 23 through 25 are all 1's it is one of
+ * the above two instructions and is a write.
+ *
+ * Note: With the limited bits we are looking at,
+ * this will also catch PROBEW and PROBEWI. However,
+ * these should never get in here because they don't
+ * generate exceptions of the type:
+ * Data TLB miss fault/data page fault
+ * Data memory protection trap
+ */
+ if (bits23_25set(inst) == BITSSET)
+ return VM_WRITE;
+ }
+ return VM_READ; /* Default */
+ }
+ return VM_READ; /* Default */
+}
+
+#undef bit22set
+#undef bits23_25set
+#undef isGraphicsFlushRead
+#undef BITSSET
+
+/* This is similar to expand_stack(), except that it is for stacks
+ * that grow upwards.
+ */
+
+static inline int expand_stackup(struct vm_area_struct * vma, unsigned long address)
+{
+ unsigned long grow;
+
+ address += 4 + PAGE_SIZE - 1;
+ address &= PAGE_MASK;
+ grow = (address - vma->vm_end) >> PAGE_SHIFT;
+ if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur ||
+ ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)
+ return -ENOMEM;
+ vma->vm_end = address;
+ vma->vm_mm->total_vm += grow;
+ if (vma->vm_flags & VM_LOCKED)
+ vma->vm_mm->locked_vm += grow;
+ return 0;
+}
+
+
+/* This is similar to find_vma(), except that it understands that stacks
+ * grow up rather than down.
+ * XXX Optimise by making use of cache and avl tree as per find_vma().
+ */
+
+struct vm_area_struct * pa_find_vma(struct mm_struct * mm, unsigned long addr)
+{
+ struct vm_area_struct *vma = NULL;
+
+ if (mm) {
+ vma = mm->mmap;
+ if (!vma || addr < vma->vm_start)
+ return NULL;
+ while (vma->vm_next && addr >= vma->vm_next->vm_start)
+ vma = vma->vm_next;
+ }
+ return vma;
+}
+
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long);
+
+void do_page_fault(struct pt_regs *regs, unsigned long code,
+ unsigned long address)
+{
+ struct vm_area_struct * vma;
+ struct task_struct *tsk = current;
+ struct mm_struct *mm = tsk->mm;
+ const struct exception_table_entry *fix;
+ unsigned long acc_type;
+
+ if (in_interrupt() || !mm)
+ goto no_context;
+
+ down(&mm->mmap_sem);
+ vma = pa_find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+ if (address < vma->vm_end)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSUP) || expand_stackup(vma, address))
+ goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access. We still need to
+ * check the access permissions.
+ */
+
+good_area:
+
+ acc_type = parisc_acctyp(code,regs->iir);
+
+ if ((vma->vm_flags & acc_type) != acc_type)
+ goto bad_area;
+
+ /*
+ * If for any reason at all we couldn't handle the fault, make
+ * sure we exit gracefully rather than endlessly redo the
+ * fault.
+ */
+
+ switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) {
+ case 1:
+ ++current->min_flt;
+ break;
+ case 2:
+ ++current->maj_flt;
+ break;
+ case 0:
+ /*
+ * We ran out of memory, or some other thing happened
+ * to us that made us unable to handle the page fault
+ * gracefully.
+ */
+ goto bad_area;
+ default:
+ goto out_of_memory;
+ }
+ up(&mm->mmap_sem);
+ return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ */
+bad_area:
+ up(&mm->mmap_sem);
+
+ if (user_mode(regs)) {
+ struct siginfo si;
+
+ printk("\ndo_page_fault() pid=%d command='%s'\n",
+ tsk->pid, tsk->comm);
+ show_regs(regs);
+ /* FIXME: actually we need to get the signo and code correct */
+ si.si_signo = SIGSEGV;
+ si.si_errno = 0;
+ si.si_code = SEGV_MAPERR;
+ si.si_addr = (void *) address;
+ force_sig_info(SIGSEGV, &si, current);
+ return;
+ }
+
+no_context:
+
+ if (!user_mode(regs)) {
+
+ fix = search_exception_table(regs->iaoq[0]);
+
+ if (fix) {
+
+ if (fix->skip & 1)
+ regs->gr[8] = -EFAULT;
+ if (fix->skip & 2)
+ regs->gr[9] = 0;
+
+ regs->iaoq[0] += ((fix->skip) & ~3);
+
+ /*
+ * NOTE: In some cases the faulting instruction
+ * may be in the delay slot of a branch. We
+ * don't want to take the branch, so we don't
+ * increment iaoq[1], instead we set it to be
+ * iaoq[0]+4, and clear the B bit in the PSW
+ */
+
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */
+
+ return;
+ }
+ }
+
+ parisc_terminate("Bad Address (null pointer deref?)",regs,code,address);
+
+ out_of_memory:
+ up(&mm->mmap_sem);
+ printk("VM: killing process %s\n", current->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ goto no_context;
+}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
new file mode 100644
index 000000000..c3e16c463
--- /dev/null
+++ b/arch/parisc/mm/init.c
@@ -0,0 +1,479 @@
+/*
+ * linux/arch/parisc/mm/init.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright 1999 SuSE GmbH
+ * changed by Philipp Rumpf
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ *
+ */
+
+#include <linux/config.h>
+
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/pci.h> /* for hppa_dma_ops and pcxl_dma_ops */
+#include <linux/swap.h>
+#include <linux/unistd.h>
+
+#include <asm/pgalloc.h>
+
+static unsigned long totalram_pages;
+extern unsigned long max_pfn, mem_max;
+
+void free_initmem(void) {
+}
+
+/*
+ * Just an arbitrary offset to serve as a "hole" between mapping areas
+ * (between top of physical memory and a potential pcxl dma mapping
+ * area, and below the vmalloc mapping area).
+ *
+ * The current 32K value just means that there will be a 32K "hole"
+ * between mapping areas. 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 VM_MAP_OFFSET (32*1024)
+#define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
+ & ~(VM_MAP_OFFSET-1)))
+
+void *vmalloc_start;
+unsigned long pcxl_dma_start;
+
+void __init mem_init(void)
+{
+ max_mapnr = num_physpages = max_low_pfn;
+ high_memory = __va(max_low_pfn * PAGE_SIZE);
+
+ totalram_pages += free_all_bootmem();
+ printk("Memory: %luk available\n", totalram_pages << (PAGE_SHIFT-10));
+
+ if (hppa_dma_ops == &pcxl_dma_ops) {
+ pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(high_memory);
+ vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE);
+ }
+ else {
+ pcxl_dma_start = 0;
+ vmalloc_start = SET_MAP_OFFSET(high_memory);
+ }
+}
+
+void __bad_pgd(pgd_t *pgd)
+{
+ printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
+ pgd_val(*pgd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+}
+
+void __bad_pmd(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+ pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+ pte_t *pte;
+
+ pte = (pte_t *) __get_free_page(GFP_KERNEL);
+
+ if (pmd_none(*pmd)) {
+ if (pte) {
+ clear_page(pte);
+ pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)pte);
+ return pte + offset;
+ }
+ pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+ return NULL;
+ }
+
+ free_page((unsigned long)pte);
+
+ if (pmd_bad(*pmd)) {
+ __bad_pmd(pmd);
+ return NULL;
+ }
+
+ return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+int do_check_pgt_cache(int low, int high)
+{
+ return 0;
+}
+
+/*
+ * 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 an 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.
+ */
+pte_t * __bad_pagetable(void)
+{
+ return (pte_t *) NULL;
+}
+
+unsigned long *empty_zero_page;
+unsigned long *empty_bad_page;
+
+pte_t __bad_page(void)
+{
+ return *(pte_t *)NULL;
+}
+
+void show_mem(void)
+{
+ int i,free = 0,total = 0,reserved = 0;
+ int shared = 0, cached = 0;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ 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 reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
+ show_buffers();
+}
+
+void set_pte_phys (unsigned long vaddr, unsigned long phys)
+{
+}
+
+
+/*
+ * pagetable_init() sets up the page tables
+ *
+ * Note that gateway_init() places the Linux gateway page at page 0.
+ * Since gateway pages cannot be dereferenced this has the desirable
+ * side effect of trapping those pesky NULL-reference errors in the
+ * kernel.
+ */
+static void __init pagetable_init(void)
+{
+ pgd_t *pg_dir;
+ pmd_t *pmd;
+ pte_t *pg_table;
+ unsigned long tmp1;
+ unsigned long tmp2;
+ unsigned long address;
+ unsigned long ro_start;
+ unsigned long ro_end;
+ unsigned long fv_addr;
+ extern const int stext;
+ extern int data_start;
+ extern const unsigned long fault_vector_20;
+
+ ro_start = __pa((unsigned long)&stext);
+ ro_end = __pa((unsigned long)&data_start);
+ fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
+
+ printk("pagetable_init\n");
+
+ /* Map whole memory from PAGE_OFFSET */
+ pg_dir = (pgd_t *)swapper_pg_dir + USER_PGD_PTRS;
+
+ address = 0;
+ while (address < mem_max) {
+ /* XXX: BTLB should be done here */
+
+#if PTRS_PER_PMD == 1
+ pmd = (pmd_t *)__pa(pg_dir);
+#else
+ pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir));
+
+ /*
+ * pmd is physical at this point
+ */
+
+ if (!pmd) {
+ pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ pmd = (pmd_t *) __pa(pmd);
+ }
+
+ pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd;
+#endif
+ pg_dir++;
+
+ /* now change pmd to kernel virtual addresses */
+
+ pmd = (pmd_t *) __va(pmd);
+ for (tmp1 = 0 ; tmp1 < PTRS_PER_PMD ; tmp1++,pmd++) {
+
+ /*
+ * pg_table is physical at this point
+ */
+
+ pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd));
+ if (!pg_table) {
+ pg_table = (pte_t *)
+ alloc_bootmem_low_pages(PAGE_SIZE);
+ pg_table = (pte_t *) __pa(pg_table);
+ }
+
+ pmd_val(*pmd) = _PAGE_TABLE |
+ (unsigned long) pg_table;
+
+ /* now change pg_table to kernel virtual addresses */
+
+ pg_table = (pte_t *) __va(pg_table);
+ for (tmp2=0; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
+ pte_t pte;
+
+#if !defined(CONFIG_KWDB) && !defined(CONFIG_STI_CONSOLE)
+#warning STI console should explicitly allocate executable pages but does not
+/* KWDB needs to write kernel text when setting break points.
+**
+** The right thing to do seems like KWDB modify only the pte which
+** has a break point on it...otherwise we might mask worse bugs.
+*/
+ if (address >= ro_start && address < ro_end
+ && address != fv_addr)
+ pte = __mk_pte(address, PAGE_KERNEL_RO);
+ else
+#endif
+ pte = __mk_pte(address, PAGE_KERNEL);
+
+ if (address >= mem_max)
+ pte_val(pte) = 0;
+
+ set_pte(pg_table, pte);
+
+ address += PAGE_SIZE;
+ }
+
+ if (address >= mem_max)
+ break;
+ }
+ }
+
+ empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
+ memset(empty_zero_page, 0, PAGE_SIZE);
+}
+
+unsigned long gateway_pgd_offset;
+unsigned long gateway_pgd_entry;
+
+static void __init gateway_init(void)
+{
+ unsigned long hpux_gateway_page_addr;
+ unsigned long linux_gateway_page_addr;
+ pgd_t *pg_dir;
+ pmd_t *pmd_base;
+ pmd_t *pmd;
+ pte_t *pg_table_base;
+ pte_t *pg_table;
+ /* FIXME: These are 'const' in order to trick the compiler
+ into not treating them as DP-relative data. */
+ extern void * const hpux_gateway_page;
+ extern void * const linux_gateway_page;
+ pte_t pte;
+
+ hpux_gateway_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK;
+ linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK;
+
+ gateway_pgd_offset = hpux_gateway_page_addr >> PGDIR_SHIFT;
+
+ /*
+ * Setup Linux Gateway page.
+ *
+ * The Linux gateway page will reside in kernel space (on virtual
+ * page 0), so it doesn't need to be aliased into user space.
+ */
+
+ pg_dir = (pgd_t *)swapper_pg_dir;
+
+#if PTRS_PER_PMD == 1
+ pmd_base = (pmd_t *)pg_dir;
+ pmd = pmd_base +
+ ((linux_gateway_page_addr) >> PGDIR_SHIFT);
+
+#else
+ pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
+ pgd_val(*(pg_dir + (linux_gateway_page_addr >> PGDIR_SHIFT))) =
+ _PAGE_TABLE | __pa(pmd_base);
+
+ pmd = pmd_base +
+ ((linux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
+ PMD_SHIFT);
+#endif
+
+ pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+
+ pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
+
+ pte = __mk_pte(__pa(&linux_gateway_page), PAGE_GATEWAY);
+
+ pg_table = pg_table_base +
+ ((linux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
+ PAGE_SHIFT);
+
+ set_pte(pg_table,pte);
+
+ /*
+ * Setup HP-UX gateway page.
+ * This page will be aliased into each user address space.
+ */
+
+ pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+
+ pte = __mk_pte(__pa(&hpux_gateway_page), PAGE_GATEWAY);
+ pg_table = pg_table_base +
+ ((hpux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
+ PAGE_SHIFT);
+
+ set_pte(pg_table,pte);
+
+
+#if PTRS_PER_PMD == 1
+ pmd_base = (pmd_t *)pg_table_base;
+#else
+ pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
+ pmd = pmd_base +
+ ((hpux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
+ PMD_SHIFT);
+ pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
+#endif
+
+ gateway_pgd_entry = _PAGE_TABLE | __pa(pmd_base);
+
+ /*
+ * We will be aliasing the HP-UX gateway page into all HP-UX
+ * user spaces at the same address (not counting the space register
+ * value) that will be equivalently mapped as long as space register
+ * hashing is disabled. It will be a problem if anyone touches
+ * the gateway pages at its "kernel" address, since that is
+ * NOT equivalently mapped. We'll flush the caches at this
+ * point, just in case some code has touched those addresses
+ * previous to this, but all bets are off if they get touched
+ * after this point.
+ */
+
+ flush_all_caches();
+
+ return;
+}
+
+void __init paging_init(void)
+{
+ pagetable_init();
+ gateway_init();
+
+ {
+ unsigned long zones_size[MAX_NR_ZONES] = { max_pfn/2, max_pfn/2, };
+
+ free_area_init(zones_size);
+ }
+}
+
+#define NR_SPACE_IDS 8192
+
+static unsigned long space_id[NR_SPACE_IDS / (8 * sizeof(long))];
+static unsigned long space_id_index;
+static unsigned long free_space_ids = NR_SPACE_IDS;
+
+/*
+ * XXX: We should probably unfold the set_bit / test_bit / clear_bit
+ * locking out of these two functions and have a single spinlock on the
+ * space_id data structures.
+ *
+ * Don't bother. This is all going to be significantly changed in the
+ * very near future.
+ */
+
+#define SPACEID_SHIFT (PAGE_SHIFT + (PT_NLEVELS)*(PAGE_SHIFT - PT_NLEVELS) - 32)
+
+unsigned long alloc_sid(void)
+{
+ unsigned long index;
+
+ if (free_space_ids == 0)
+ BUG();
+
+ free_space_ids--;
+
+ do {
+ index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index);
+ } while(test_and_set_bit(index, space_id));
+
+ space_id_index = index;
+
+ return index << SPACEID_SHIFT;
+}
+
+void free_sid(unsigned long spaceid)
+{
+ unsigned long index = spaceid >> SPACEID_SHIFT;
+ if (index < 0)
+ BUG();
+
+ clear_bit(index, space_id);
+
+ if (space_id_index > index) {
+ space_id_index = index;
+ }
+ free_space_ids++;
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+#if 0
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(mem_map + MAP_NR(start));
+ set_page_count(mem_map+MAP_NR(start), 1);
+ free_page(start);
+ totalram_pages++;
+ }
+ printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+#endif
+}
+#endif
+
+void si_meminfo(struct sysinfo *val)
+{
+ int i;
+
+ i = max_mapnr;
+ val->totalram = totalram_pages;
+ val->sharedram = 0;
+ val->freeram = nr_free_pages();
+ val->bufferram = atomic_read(&buffermem_pages);
+#if 0
+ 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;
+#endif
+ val->totalhigh = 0;
+ val->freehigh = 0;
+ return;
+}
diff --git a/arch/parisc/mm/kmap.c b/arch/parisc/mm/kmap.c
new file mode 100644
index 000000000..686d540d9
--- /dev/null
+++ b/arch/parisc/mm/kmap.c
@@ -0,0 +1,143 @@
+/*
+** Stolen mostly from arch/parisc/kernel/pci-dma.c
+*/
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+
+#include <asm/io.h>
+#include <asm/page.h> /* get_order */
+
+#undef flush_cache_all
+#define flush_cache_all flush_all_caches
+
+typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg);
+
+#if 0
+/* XXX This routine could be used with iterate_page() to replace
+ * unmap_uncached_page() and save a little code space but I didn't
+ * do that since I'm not certain whether this is the right path. -PB
+ */
+static void unmap_cached_pte(pte_t * pte, unsigned long arg)
+{
+ pte_t page = *pte;
+ pte_clear(pte);
+ if (!pte_none(page)) {
+ if (pte_present(page)) {
+ unsigned long map_nr = pte_pagenr(page);
+ if (map_nr < max_mapnr)
+ __free_page(mem_map + map_nr);
+ } else {
+ printk(KERN_CRIT
+ "Whee.. Swapped out page in kernel page table\n");
+ }
+ }
+}
+#endif
+
+/* These two routines should probably check a few things... */
+static void set_uncached(pte_t * pte, unsigned long arg)
+{
+ pte_val(*pte) |= _PAGE_NO_CACHE;
+}
+
+static void set_cached(pte_t * pte, unsigned long arg)
+{
+ pte_val(*pte) &= ~_PAGE_NO_CACHE;
+}
+
+static inline void iterate_pte(pmd_t * pmd, unsigned long address,
+ unsigned long size, pte_iterator_t op,
+ unsigned long arg)
+{
+ pte_t *pte;
+ unsigned long end;
+
+ if (pmd_none(*pmd))
+ return;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return;
+ }
+ pte = pte_offset(pmd, address);
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ op(pte, arg);
+ address += PAGE_SIZE;
+ pte++;
+ } while (address < end);
+}
+
+static inline void iterate_pmd(pgd_t * dir, unsigned long address,
+ unsigned long size, pte_iterator_t op,
+ unsigned long arg)
+{
+ pmd_t *pmd;
+ unsigned long end;
+
+ if (pgd_none(*dir))
+ return;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return;
+ }
+ pmd = pmd_offset(dir, address);
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ iterate_pte(pmd, address, end - address, op, arg);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address < end);
+}
+
+static void iterate_pages(unsigned long address, unsigned long size,
+ pte_iterator_t op, unsigned long arg)
+{
+ pgd_t *dir;
+ unsigned long end = address + size;
+
+ dir = pgd_offset_k(address);
+ flush_cache_all();
+ do {
+ iterate_pmd(dir, address, end - address, op, arg);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ flush_tlb_all();
+}
+
+void
+kernel_set_cachemode(unsigned long vaddr, unsigned long size, int what)
+{
+ switch (what) {
+ case IOMAP_FULL_CACHING:
+ iterate_pages(vaddr, size, set_cached, 0);
+ flush_tlb_range(&init_mm, vaddr, size);
+ break;
+ case IOMAP_NOCACHE_SER:
+ iterate_pages(vaddr, size, set_uncached, 0);
+ flush_tlb_range(&init_mm, vaddr, size);
+ break;
+ default:
+ printk(KERN_CRIT
+ "kernel_set_cachemode mode %d not understood\n",
+ what);
+ break;
+ }
+}
diff --git a/arch/parisc/mm/pa11.c b/arch/parisc/mm/pa11.c
new file mode 100644
index 000000000..42f0d57f6
--- /dev/null
+++ b/arch/parisc/mm/pa11.c
@@ -0,0 +1,170 @@
+/* $Id: pa11.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $
+ *
+ * pa11.c: PA 1.1 specific mmu/cache code.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+#include <asm/mmu_context.h>
+
+extern unsigned long mips_tlb_entries;
+
+/* page functions */
+void pa11_clear_page(unsigned long page)
+{
+}
+
+static void pa11_copy_page(unsigned long to, unsigned long from)
+{
+}
+
+/* Cache operations. */
+static inline void pa11_flush_cache_all(void) { }
+static void pa11_flush_cache_mm(struct mm_struct *mm) { }
+static void pa11_flush_cache_range(struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end)
+{
+}
+
+static void pa11_flush_cache_page(struct vm_area_struct *vma,
+ unsigned long page)
+{
+}
+
+static void pa11_flush_page_to_ram(unsigned long page)
+{
+}
+
+static void pa11_flush_cache_sigtramp(unsigned long page)
+{
+}
+
+/* TLB operations. */
+static inline void pa11_flush_tlb_all(void)
+{
+ unsigned long flags;
+ int entry;
+
+ save_and_cli(flags);
+/* Here we will need to flush all the TLBs */
+ restore_flags(flags);
+}
+
+static void pa11_flush_tlb_mm(struct mm_struct *mm)
+{
+/* This is what the MIPS does.. Is it the right thing for PA-RISC? */
+ if(mm == current->mm)
+ pa11_flush_tlb_all();
+}
+
+static void pa11_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ if(mm == current->mm)
+ pa11_flush_tlb_all();
+}
+
+static void pa11_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ if(vma->vm_mm == current->mm)
+ pa11_flush_tlb_all();
+}
+
+static void pa11_load_pgd(unsigned long pg_dir)
+{
+ unsigned long flags;
+ /* We need to do the right thing here */
+}
+
+/*
+ * Initialize new page directory with pointers to invalid ptes
+ */
+static void pa11_pgd_init(unsigned long page)
+{
+ unsigned long dummy1, dummy2;
+
+}
+
+static void pa11_update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+ pa11_flush_tlb_page(vma, address);
+}
+
+static void pa11_show_regs(struct pt_regs * regs)
+{
+ /*
+ * Saved main processor registers
+ */
+ printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
+ (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
+ (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
+ (unsigned long) regs->regs[7]);
+ printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
+ (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
+ (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
+ (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
+ printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
+ (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
+ (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
+ (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
+ printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
+ (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
+ (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
+
+ /*
+ * Saved cp0 registers
+ */
+ printk("epc : %08lx\nStatus: %08x\nCause : %08x\n",
+ (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
+ (unsigned int) regs->cp0_cause);
+}
+
+static int pa11_user_mode(struct pt_regs *regs)
+{
+ /* Return user mode stuff?? */
+}
+
+__initfunc(void ld_mmu_pa11(void))
+{
+
+ /* Taken directly from the MIPS arch.. Lots of bad things here */
+ clear_page = pa11_clear_page;
+ copy_page = pa11_copy_page;
+
+ flush_cache_all = pa11_flush_cache_all;
+ flush_cache_mm = pa11_flush_cache_mm;
+ flush_cache_range = pa11_flush_cache_range;
+ flush_cache_page = pa11_flush_cache_page;
+ flush_cache_sigtramp = pa11_flush_cache_sigtramp;
+ flush_page_to_ram = pa11_flush_page_to_ram;
+
+ flush_tlb_all = pa11_flush_tlb_all;
+ flush_tlb_mm = pa11_flush_tlb_mm;
+ flush_tlb_range = pa11_flush_tlb_range;
+ flush_tlb_page = pa11_flush_tlb_page;
+ pa11_asid_setup();
+
+ load_pgd = pa11_load_pgd;
+ pgd_init = pa11_pgd_init;
+ update_mmu_cache = pa11_update_mmu_cache;
+
+ show_regs = pa11_show_regs;
+
+ add_wired_entry = pa11_add_wired_entry;
+
+ user_mode = pa11_user_mode;
+ flush_tlb_all();
+}
diff --git a/arch/parisc/mm/pa20.c b/arch/parisc/mm/pa20.c
new file mode 100644
index 000000000..cbc0343a0
--- /dev/null
+++ b/arch/parisc/mm/pa20.c
@@ -0,0 +1,170 @@
+/* $Id: pa20.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $
+ *
+ * pa20.c: PA 2.0 specific mmu/cache code.
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/sgialib.h>
+#include <asm/mmu_context.h>
+
+extern unsigned long mips_tlb_entries;
+
+/* page functions */
+void pa20_clear_page(unsigned long page)
+{
+}
+
+static void pa20_copy_page(unsigned long to, unsigned long from)
+{
+}
+
+/* Cache operations. */
+static inline void pa20_flush_cache_all(void) { }
+static void pa20_flush_cache_mm(struct mm_struct *mm) { }
+static void pa20_flush_cache_range(struct mm_struct *mm,
+ unsigned long start,
+ unsigned long end)
+{
+}
+
+static void pa20_flush_cache_page(struct vm_area_struct *vma,
+ unsigned long page)
+{
+}
+
+static void pa20_flush_page_to_ram(unsigned long page)
+{
+}
+
+static void pa20_flush_cache_sigtramp(unsigned long page)
+{
+}
+
+/* TLB operations. */
+static inline void pa20_flush_tlb_all(void)
+{
+ unsigned long flags;
+ int entry;
+
+ save_and_cli(flags);
+/* Here we will need to flush all the TLBs */
+ restore_flags(flags);
+}
+
+static void pa20_flush_tlb_mm(struct mm_struct *mm)
+{
+/* This is what the MIPS does.. Is it the right thing for PA-RISC? */
+ if(mm == current->mm)
+ pa20_flush_tlb_all();
+}
+
+static void pa20_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ if(mm == current->mm)
+ pa20_flush_tlb_all();
+}
+
+static void pa20_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+ if(vma->vm_mm == current->mm)
+ pa20_flush_tlb_all();
+}
+
+static void pa20_load_pgd(unsigned long pg_dir)
+{
+ unsigned long flags;
+ /* We need to do the right thing here */
+}
+
+/*
+ * Initialize new page directory with pointers to invalid ptes
+ */
+static void pa20_pgd_init(unsigned long page)
+{
+ unsigned long dummy1, dummy2;
+
+}
+
+static void pa20_update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+ pa20_flush_tlb_page(vma, address);
+}
+
+static void pa20_show_regs(struct pt_regs * regs)
+{
+ /*
+ * Saved main processor registers
+ */
+ printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
+ (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
+ (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
+ (unsigned long) regs->regs[7]);
+ printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
+ (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
+ (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
+ (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
+ printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
+ (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
+ (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
+ (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
+ printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
+ (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
+ (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
+ (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
+
+ /*
+ * Saved cp0 registers
+ */
+ printk("epc : %08lx\nStatus: %08x\nCause : %08x\n",
+ (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
+ (unsigned int) regs->cp0_cause);
+}
+
+static int pa20_user_mode(struct pt_regs *regs)
+{
+ /* Return user mode stuff?? */
+}
+
+__initfunc(void ld_mmu_pa20(void))
+{
+
+ /* Taken directly from the MIPS arch.. Lots of bad things here */
+ clear_page = pa20_clear_page;
+ copy_page = pa20_copy_page;
+
+ flush_cache_all = pa20_flush_cache_all;
+ flush_cache_mm = pa20_flush_cache_mm;
+ flush_cache_range = pa20_flush_cache_range;
+ flush_cache_page = pa20_flush_cache_page;
+ flush_cache_sigtramp = pa20_flush_cache_sigtramp;
+ flush_page_to_ram = pa20_flush_page_to_ram;
+
+ flush_tlb_all = pa20_flush_tlb_all;
+ flush_tlb_mm = pa20_flush_tlb_mm;
+ flush_tlb_range = pa20_flush_tlb_range;
+ flush_tlb_page = pa20_flush_tlb_page;
+ pa20_asid_setup();
+
+ load_pgd = pa20_load_pgd;
+ pgd_init = pa20_pgd_init;
+ update_mmu_cache = pa20_update_mmu_cache;
+
+ show_regs = pa20_show_regs;
+
+ add_wired_entry = pa20_add_wired_entry;
+
+ user_mode = pa20_user_mode;
+ flush_tlb_all();
+}
diff --git a/arch/parisc/tools/Makefile b/arch/parisc/tools/Makefile
new file mode 100644
index 000000000..54fad5647
--- /dev/null
+++ b/arch/parisc/tools/Makefile
@@ -0,0 +1,28 @@
+# Makefile for MIPS kernel build tools.
+#
+# Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+# Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu)
+#
+# $Id: Makefile,v 1.3 1999/09/29 05:19:56 grundler Exp $
+#
+TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h
+
+.S.s:
+ $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+ $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: $(TARGET)
+
+$(TARGET): offset.h
+ cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET))
+
+offset.h: offset.s
+ sed -n '/^@@@/s///p' $^ >$@
+
+offset.s: offset.c
+
+clean:
+ rm -f offset.[hs] $(TARGET).new
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/parisc/tools/offset.c b/arch/parisc/tools/offset.c
new file mode 100644
index 000000000..167087f7e
--- /dev/null
+++ b/arch/parisc/tools/offset.c
@@ -0,0 +1,326 @@
+/* $Id: offset.c,v 1.2 2000/01/31 13:42:59 jsm Exp $
+ *
+ * offset.c: Calculate pt_regs and task_struct offsets.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Made portable by Ralf Baechle
+ * Adapted to parisc by Philipp Rumpf, (C) 1999 SuSE GmbH Nuernberg */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/hardirq.h>
+
+#define text(t) __asm__("\n@@@" t)
+#define _offset(type, member) (&(((type *)NULL)->member))
+
+#define offset(string, ptr, member) \
+ __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member)))
+#define size(string, size) \
+ __asm__("\n@@@" string "%0" : : "i" (sizeof(size)))
+#define align(x,y) (((x)+(2*(y))-1)-(((x)+(y)-1)%(y)))
+#define size_align(string, size, algn) \
+ __asm__("\n@@@" string "%0" : : "i" \
+ align(sizeof(size),algn))
+#define linefeed text("")
+
+text("/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */");
+linefeed;
+text("#ifndef _PARISC_OFFSET_H");
+text("#define _PARISC_OFFSET_H");
+linefeed;
+
+void output_task_ptreg_defines(void)
+{
+ text("/* PA-RISC task pt_regs offsets. */");
+ offset("#define TASK_REGS ", struct task_struct, thread.regs);
+ offset("#define TASK_PT_PSW ", struct task_struct, thread.regs.gr[ 0]);
+ offset("#define TASK_PT_GR1 ", struct task_struct, thread.regs.gr[ 1]);
+ offset("#define TASK_PT_GR2 ", struct task_struct, thread.regs.gr[ 2]);
+ offset("#define TASK_PT_GR3 ", struct task_struct, thread.regs.gr[ 3]);
+ offset("#define TASK_PT_GR4 ", struct task_struct, thread.regs.gr[ 4]);
+ offset("#define TASK_PT_GR5 ", struct task_struct, thread.regs.gr[ 5]);
+ offset("#define TASK_PT_GR6 ", struct task_struct, thread.regs.gr[ 6]);
+ offset("#define TASK_PT_GR7 ", struct task_struct, thread.regs.gr[ 7]);
+ offset("#define TASK_PT_GR8 ", struct task_struct, thread.regs.gr[ 8]);
+ offset("#define TASK_PT_GR9 ", struct task_struct, thread.regs.gr[ 9]);
+ offset("#define TASK_PT_GR10 ", struct task_struct, thread.regs.gr[10]);
+ offset("#define TASK_PT_GR11 ", struct task_struct, thread.regs.gr[11]);
+ offset("#define TASK_PT_GR12 ", struct task_struct, thread.regs.gr[12]);
+ offset("#define TASK_PT_GR13 ", struct task_struct, thread.regs.gr[13]);
+ offset("#define TASK_PT_GR14 ", struct task_struct, thread.regs.gr[14]);
+ offset("#define TASK_PT_GR15 ", struct task_struct, thread.regs.gr[15]);
+ offset("#define TASK_PT_GR16 ", struct task_struct, thread.regs.gr[16]);
+ offset("#define TASK_PT_GR17 ", struct task_struct, thread.regs.gr[17]);
+ offset("#define TASK_PT_GR18 ", struct task_struct, thread.regs.gr[18]);
+ offset("#define TASK_PT_GR19 ", struct task_struct, thread.regs.gr[19]);
+ offset("#define TASK_PT_GR20 ", struct task_struct, thread.regs.gr[20]);
+ offset("#define TASK_PT_GR21 ", struct task_struct, thread.regs.gr[21]);
+ offset("#define TASK_PT_GR22 ", struct task_struct, thread.regs.gr[22]);
+ offset("#define TASK_PT_GR23 ", struct task_struct, thread.regs.gr[23]);
+ offset("#define TASK_PT_GR24 ", struct task_struct, thread.regs.gr[24]);
+ offset("#define TASK_PT_GR25 ", struct task_struct, thread.regs.gr[25]);
+ offset("#define TASK_PT_GR26 ", struct task_struct, thread.regs.gr[26]);
+ offset("#define TASK_PT_GR27 ", struct task_struct, thread.regs.gr[27]);
+ offset("#define TASK_PT_GR28 ", struct task_struct, thread.regs.gr[28]);
+ offset("#define TASK_PT_GR29 ", struct task_struct, thread.regs.gr[29]);
+ offset("#define TASK_PT_GR30 ", struct task_struct, thread.regs.gr[30]);
+ offset("#define TASK_PT_GR31 ", struct task_struct, thread.regs.gr[31]);
+ offset("#define TASK_PT_FR0 ", struct task_struct, thread.regs.fr[ 0]);
+ offset("#define TASK_PT_FR1 ", struct task_struct, thread.regs.fr[ 1]);
+ offset("#define TASK_PT_FR2 ", struct task_struct, thread.regs.fr[ 2]);
+ offset("#define TASK_PT_FR3 ", struct task_struct, thread.regs.fr[ 3]);
+ offset("#define TASK_PT_FR4 ", struct task_struct, thread.regs.fr[ 4]);
+ offset("#define TASK_PT_FR5 ", struct task_struct, thread.regs.fr[ 5]);
+ offset("#define TASK_PT_FR6 ", struct task_struct, thread.regs.fr[ 6]);
+ offset("#define TASK_PT_FR7 ", struct task_struct, thread.regs.fr[ 7]);
+ offset("#define TASK_PT_FR8 ", struct task_struct, thread.regs.fr[ 8]);
+ offset("#define TASK_PT_FR9 ", struct task_struct, thread.regs.fr[ 9]);
+ offset("#define TASK_PT_FR10 ", struct task_struct, thread.regs.fr[10]);
+ offset("#define TASK_PT_FR11 ", struct task_struct, thread.regs.fr[11]);
+ offset("#define TASK_PT_FR12 ", struct task_struct, thread.regs.fr[12]);
+ offset("#define TASK_PT_FR13 ", struct task_struct, thread.regs.fr[13]);
+ offset("#define TASK_PT_FR14 ", struct task_struct, thread.regs.fr[14]);
+ offset("#define TASK_PT_FR15 ", struct task_struct, thread.regs.fr[15]);
+ offset("#define TASK_PT_FR16 ", struct task_struct, thread.regs.fr[16]);
+ offset("#define TASK_PT_FR17 ", struct task_struct, thread.regs.fr[17]);
+ offset("#define TASK_PT_FR18 ", struct task_struct, thread.regs.fr[18]);
+ offset("#define TASK_PT_FR19 ", struct task_struct, thread.regs.fr[19]);
+ offset("#define TASK_PT_FR20 ", struct task_struct, thread.regs.fr[20]);
+ offset("#define TASK_PT_FR21 ", struct task_struct, thread.regs.fr[21]);
+ offset("#define TASK_PT_FR22 ", struct task_struct, thread.regs.fr[22]);
+ offset("#define TASK_PT_FR23 ", struct task_struct, thread.regs.fr[23]);
+ offset("#define TASK_PT_FR24 ", struct task_struct, thread.regs.fr[24]);
+ offset("#define TASK_PT_FR25 ", struct task_struct, thread.regs.fr[25]);
+ offset("#define TASK_PT_FR26 ", struct task_struct, thread.regs.fr[26]);
+ offset("#define TASK_PT_FR27 ", struct task_struct, thread.regs.fr[27]);
+ offset("#define TASK_PT_FR28 ", struct task_struct, thread.regs.fr[28]);
+ offset("#define TASK_PT_FR29 ", struct task_struct, thread.regs.fr[29]);
+ offset("#define TASK_PT_FR30 ", struct task_struct, thread.regs.fr[30]);
+ offset("#define TASK_PT_FR31 ", struct task_struct, thread.regs.fr[31]);
+ offset("#define TASK_PT_SR0 ", struct task_struct, thread.regs.sr[ 0]);
+ offset("#define TASK_PT_SR1 ", struct task_struct, thread.regs.sr[ 1]);
+ offset("#define TASK_PT_SR2 ", struct task_struct, thread.regs.sr[ 2]);
+ offset("#define TASK_PT_SR3 ", struct task_struct, thread.regs.sr[ 3]);
+ offset("#define TASK_PT_SR4 ", struct task_struct, thread.regs.sr[ 4]);
+ offset("#define TASK_PT_SR5 ", struct task_struct, thread.regs.sr[ 5]);
+ offset("#define TASK_PT_SR6 ", struct task_struct, thread.regs.sr[ 6]);
+ offset("#define TASK_PT_SR7 ", struct task_struct, thread.regs.sr[ 7]);
+ offset("#define TASK_PT_IASQ0 ", struct task_struct, thread.regs.iasq[0]);
+ offset("#define TASK_PT_IASQ1 ", struct task_struct, thread.regs.iasq[1]);
+ offset("#define TASK_PT_IAOQ0 ", struct task_struct, thread.regs.iaoq[0]);
+ offset("#define TASK_PT_IAOQ1 ", struct task_struct, thread.regs.iaoq[1]);
+ offset("#define TASK_PT_CR24 ", struct task_struct, thread.regs.cr24);
+ offset("#define TASK_PT_CR25 ", struct task_struct, thread.regs.cr25);
+ offset("#define TASK_PT_CR26 ", struct task_struct, thread.regs.cr26);
+ offset("#define TASK_PT_CR27 ", struct task_struct, thread.regs.cr27);
+ offset("#define TASK_PT_CR30 ", struct task_struct, thread.regs.cr30);
+ offset("#define TASK_PT_ORIG_R28 ", struct task_struct, thread.regs.orig_r28);
+ offset("#define TASK_PT_KSP ", struct task_struct, thread.regs.ksp);
+ offset("#define TASK_PT_KPC ", struct task_struct, thread.regs.kpc);
+ offset("#define TASK_PT_SAR ", struct task_struct, thread.regs.sar);
+ offset("#define TASK_PT_CR11 ", struct task_struct, thread.regs.sar);
+ offset("#define TASK_PT_IIR ", struct task_struct, thread.regs.iir);
+ offset("#define TASK_PT_ISR ", struct task_struct, thread.regs.isr);
+ offset("#define TASK_PT_IOR ", struct task_struct, thread.regs.ior);
+ offset("#define TASK_PT_CR_PID0 ", struct task_struct, thread.regs.cr_pid[0]);
+ offset("#define TASK_PT_CR_PID1 ", struct task_struct, thread.regs.cr_pid[1]);
+ offset("#define TASK_PT_CR_PID2 ", struct task_struct, thread.regs.cr_pid[2]);
+ offset("#define TASK_PT_CR_PID3 ", struct task_struct, thread.regs.cr_pid[3]);
+ size("#define TASK_SZ ", struct task_struct);
+ size_align("#define TASK_SZ_ALGN ", struct task_struct, 64);
+ linefeed;
+}
+
+void output_ptreg_defines(void)
+{
+ text("/* PA-RISC pt_regs offsets. */");
+ offset("#define PT_PSW ", struct pt_regs, gr[ 0]);
+ offset("#define PT_GR1 ", struct pt_regs, gr[ 1]);
+ offset("#define PT_GR2 ", struct pt_regs, gr[ 2]);
+ offset("#define PT_GR3 ", struct pt_regs, gr[ 3]);
+ offset("#define PT_GR4 ", struct pt_regs, gr[ 4]);
+ offset("#define PT_GR5 ", struct pt_regs, gr[ 5]);
+ offset("#define PT_GR6 ", struct pt_regs, gr[ 6]);
+ offset("#define PT_GR7 ", struct pt_regs, gr[ 7]);
+ offset("#define PT_GR8 ", struct pt_regs, gr[ 8]);
+ offset("#define PT_GR9 ", struct pt_regs, gr[ 9]);
+ offset("#define PT_GR10 ", struct pt_regs, gr[10]);
+ offset("#define PT_GR11 ", struct pt_regs, gr[11]);
+ offset("#define PT_GR12 ", struct pt_regs, gr[12]);
+ offset("#define PT_GR13 ", struct pt_regs, gr[13]);
+ offset("#define PT_GR14 ", struct pt_regs, gr[14]);
+ offset("#define PT_GR15 ", struct pt_regs, gr[15]);
+ offset("#define PT_GR16 ", struct pt_regs, gr[16]);
+ offset("#define PT_GR17 ", struct pt_regs, gr[17]);
+ offset("#define PT_GR18 ", struct pt_regs, gr[18]);
+ offset("#define PT_GR19 ", struct pt_regs, gr[19]);
+ offset("#define PT_GR20 ", struct pt_regs, gr[20]);
+ offset("#define PT_GR21 ", struct pt_regs, gr[21]);
+ offset("#define PT_GR22 ", struct pt_regs, gr[22]);
+ offset("#define PT_GR23 ", struct pt_regs, gr[23]);
+ offset("#define PT_GR24 ", struct pt_regs, gr[24]);
+ offset("#define PT_GR25 ", struct pt_regs, gr[25]);
+ offset("#define PT_GR26 ", struct pt_regs, gr[26]);
+ offset("#define PT_GR27 ", struct pt_regs, gr[27]);
+ offset("#define PT_GR28 ", struct pt_regs, gr[28]);
+ offset("#define PT_GR29 ", struct pt_regs, gr[29]);
+ offset("#define PT_GR30 ", struct pt_regs, gr[30]);
+ offset("#define PT_GR31 ", struct pt_regs, gr[31]);
+ offset("#define PT_FR0 ", struct pt_regs, fr[ 0]);
+ offset("#define PT_FR1 ", struct pt_regs, fr[ 1]);
+ offset("#define PT_FR2 ", struct pt_regs, fr[ 2]);
+ offset("#define PT_FR3 ", struct pt_regs, fr[ 3]);
+ offset("#define PT_FR4 ", struct pt_regs, fr[ 4]);
+ offset("#define PT_FR5 ", struct pt_regs, fr[ 5]);
+ offset("#define PT_FR6 ", struct pt_regs, fr[ 6]);
+ offset("#define PT_FR7 ", struct pt_regs, fr[ 7]);
+ offset("#define PT_FR8 ", struct pt_regs, fr[ 8]);
+ offset("#define PT_FR9 ", struct pt_regs, fr[ 9]);
+ offset("#define PT_FR10 ", struct pt_regs, fr[10]);
+ offset("#define PT_FR11 ", struct pt_regs, fr[11]);
+ offset("#define PT_FR12 ", struct pt_regs, fr[12]);
+ offset("#define PT_FR13 ", struct pt_regs, fr[13]);
+ offset("#define PT_FR14 ", struct pt_regs, fr[14]);
+ offset("#define PT_FR15 ", struct pt_regs, fr[15]);
+ offset("#define PT_FR16 ", struct pt_regs, fr[16]);
+ offset("#define PT_FR17 ", struct pt_regs, fr[17]);
+ offset("#define PT_FR18 ", struct pt_regs, fr[18]);
+ offset("#define PT_FR19 ", struct pt_regs, fr[19]);
+ offset("#define PT_FR20 ", struct pt_regs, fr[20]);
+ offset("#define PT_FR21 ", struct pt_regs, fr[21]);
+ offset("#define PT_FR22 ", struct pt_regs, fr[22]);
+ offset("#define PT_FR23 ", struct pt_regs, fr[23]);
+ offset("#define PT_FR24 ", struct pt_regs, fr[24]);
+ offset("#define PT_FR25 ", struct pt_regs, fr[25]);
+ offset("#define PT_FR26 ", struct pt_regs, fr[26]);
+ offset("#define PT_FR27 ", struct pt_regs, fr[27]);
+ offset("#define PT_FR28 ", struct pt_regs, fr[28]);
+ offset("#define PT_FR29 ", struct pt_regs, fr[29]);
+ offset("#define PT_FR30 ", struct pt_regs, fr[30]);
+ offset("#define PT_FR31 ", struct pt_regs, fr[31]);
+ offset("#define PT_SR0 ", struct pt_regs, sr[ 0]);
+ offset("#define PT_SR1 ", struct pt_regs, sr[ 1]);
+ offset("#define PT_SR2 ", struct pt_regs, sr[ 2]);
+ offset("#define PT_SR3 ", struct pt_regs, sr[ 3]);
+ offset("#define PT_SR4 ", struct pt_regs, sr[ 4]);
+ offset("#define PT_SR5 ", struct pt_regs, sr[ 5]);
+ offset("#define PT_SR6 ", struct pt_regs, sr[ 6]);
+ offset("#define PT_SR7 ", struct pt_regs, sr[ 7]);
+ offset("#define PT_IASQ0 ", struct pt_regs, iasq[0]);
+ offset("#define PT_IASQ1 ", struct pt_regs, iasq[1]);
+ offset("#define PT_IAOQ0 ", struct pt_regs, iaoq[0]);
+ offset("#define PT_IAOQ1 ", struct pt_regs, iaoq[1]);
+ offset("#define PT_CR24 ", struct pt_regs, cr24);
+ offset("#define PT_CR25 ", struct pt_regs, cr25);
+ offset("#define PT_CR26 ", struct pt_regs, cr26);
+ offset("#define PT_CR27 ", struct pt_regs, cr27);
+ offset("#define PT_CR30 ", struct pt_regs, cr30);
+ offset("#define PT_ORIG_R28 ", struct pt_regs, orig_r28);
+ offset("#define PT_KSP ", struct pt_regs, ksp);
+ offset("#define PT_KPC ", struct pt_regs, kpc);
+ offset("#define PT_SAR ", struct pt_regs, sar);
+ offset("#define PT_CR11 ", struct pt_regs, sar);
+ offset("#define PT_IIR ", struct pt_regs, iir);
+ offset("#define PT_ISR ", struct pt_regs, isr);
+ offset("#define PT_IOR ", struct pt_regs, ior);
+ offset("#define PT_CR_PID0 ", struct pt_regs, cr_pid[0]);
+ offset("#define PT_CR_PID1 ", struct pt_regs, cr_pid[1]);
+ offset("#define PT_CR_PID2 ", struct pt_regs, cr_pid[2]);
+ offset("#define PT_CR_PID3 ", struct pt_regs, cr_pid[3]);
+ size("#define PT_SIZE ", struct pt_regs);
+ size_align("#define PT_SZ_ALGN ", struct pt_regs, 64);
+ linefeed;
+}
+
+void output_task_defines(void)
+{
+ text("/* PARISC task_struct offsets. */");
+ offset("#define TASK_STATE ", struct task_struct, state);
+ offset("#define TASK_FLAGS ", struct task_struct, flags);
+ offset("#define TASK_SIGPENDING ", struct task_struct, sigpending);
+ offset("#define TASK_SEGMENT ", struct task_struct, addr_limit);
+ offset("#define TASK_NEED_RESCHED ", struct task_struct, need_resched);
+ offset("#define TASK_COUNTER ", struct task_struct, counter);
+ offset("#define TASK_PTRACE ", struct task_struct, ptrace);
+ offset("#define TASK_NICE ", struct task_struct, nice);
+ offset("#define TASK_MM ", struct task_struct, mm);
+ offset("#define TASK_PROCESSOR ", struct task_struct, processor);
+ size ("#define TASK_SZ ", struct task_struct);
+ size_align("#define TASK_SZ_ALGN ", struct task_struct, 64);
+ linefeed;
+}
+
+void output_irq_stat_defines(void)
+{
+ text("/* PARISC irq_cpustat_t offsets. */");
+ offset("#define IRQSTAT_SI_ACTIVE ", irq_cpustat_t, __softirq_active);
+ offset("#define IRQSTAT_SI_MASK ", irq_cpustat_t, __softirq_mask);
+ size ("#define IRQSTAT_SZ ", irq_cpustat_t);
+ linefeed;
+}
+
+#ifdef PRUMPF_HAD_MORE_TIME
+void output_thread_defines(void)
+{
+ text("/* PARISC specific thread_struct offsets. */");
+ offset("#define THREAD_REG16 ", struct task_struct, thread.reg16);
+ offset("#define THREAD_REG17 ", struct task_struct, thread.reg17);
+ offset("#define THREAD_REG18 ", struct task_struct, thread.reg18);
+ offset("#define THREAD_REG19 ", struct task_struct, thread.reg19);
+ offset("#define THREAD_REG20 ", struct task_struct, thread.reg20);
+ offset("#define THREAD_REG21 ", struct task_struct, thread.reg21);
+ offset("#define THREAD_REG22 ", struct task_struct, thread.reg22);
+ offset("#define THREAD_REG23 ", struct task_struct, thread.reg23);
+ offset("#define THREAD_REG29 ", struct task_struct, thread.reg29);
+ offset("#define THREAD_REG30 ", struct task_struct, thread.reg30);
+ offset("#define THREAD_REG31 ", struct task_struct, thread.reg31);
+ offset("#define THREAD_STATUS ", struct task_struct, thread.cp0_status);
+ offset("#define THREAD_FPU ", struct task_struct, thread.fpu);
+ offset("#define THREAD_BVADDR ", struct task_struct, thread.cp0_badvaddr);
+ offset("#define THREAD_BUADDR ", struct task_struct, thread.cp0_baduaddr);
+ offset("#define THREAD_ECODE ", struct task_struct, thread.error_code);
+ offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no);
+ offset("#define THREAD_PGDIR ", struct task_struct, thread.pg_dir);
+ offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags);
+ offset("#define THREAD_CURDS ", struct task_struct, thread.current_ds);
+ offset("#define THREAD_TRAMP ", struct task_struct, thread.irix_trampoline);
+ offset("#define THREAD_OLDCTX ", struct task_struct, thread.irix_oldctx);
+ linefeed;
+}
+
+void output_mm_defines(void)
+{
+ text("/* Linux mm_struct offsets. */");
+ offset("#define MM_COUNT ", struct mm_struct, count);
+ offset("#define MM_PGD ", struct mm_struct, pgd);
+ offset("#define MM_CONTEXT ", struct mm_struct, context);
+ linefeed;
+}
+
+void output_sc_defines(void)
+{
+ text("/* Linux sigcontext offsets. */");
+ offset("#define SC_REGMASK ", struct sigcontext, sc_regmask);
+ offset("#define SC_STATUS ", struct sigcontext, sc_status);
+ offset("#define SC_PC ", struct sigcontext, sc_pc);
+ offset("#define SC_REGS ", struct sigcontext, sc_regs);
+ offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs);
+ offset("#define SC_OWNEDFP ", struct sigcontext, sc_ownedfp);
+ offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr);
+ offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir);
+ offset("#define SC_SSFLAGS ", struct sigcontext, sc_ssflags);
+ offset("#define SC_MDHI ", struct sigcontext, sc_mdhi);
+ offset("#define SC_MDLO ", struct sigcontext, sc_mdlo);
+ offset("#define SC_CAUSE ", struct sigcontext, sc_cause);
+ offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr);
+ offset("#define SC_SIGSET ", struct sigcontext, sc_sigset);
+ linefeed;
+}
+
+#endif
+
+text("#endif /* !(_PARISC_OFFSET_H) */");
diff --git a/arch/parisc/vmlinux.lds b/arch/parisc/vmlinux.lds
new file mode 100644
index 000000000..268fc59ce
--- /dev/null
+++ b/arch/parisc/vmlinux.lds
@@ -0,0 +1,79 @@
+/* ld script to make hppa Linux kernel */
+OUTPUT_FORMAT("elf32-hppa")
+OUTPUT_ARCH(hppa)
+ENTRY(_stext)
+SECTIONS
+{
+
+/* right now use 0x10000/0x11000, later when we don't use Console and
+ * Boot-Device IODC, we will change this to 0x8000 !!!
+ */
+
+ . = 0xc0100000;
+/* . = 0x10000; */
+
+ _text = .; /* Text and read-only data */
+ .text BLOCK(16) : {
+ *(.text*)
+ *(.PARISC.unwind)
+ *(.fixup)
+ *(.lock.text) /* out-of-line lock text */
+ *(.gnu.warning)
+ } = 0
+
+ . = ALIGN(16);
+ .rodata : { *(.rodata) }
+ .kstrtab : { *(.kstrtab) }
+
+ _etext = .; /* End of text section */
+
+ .data BLOCK(8192) : { /* Data without special */
+ data_start = .;
+ *(.data)
+ }
+
+ . = ALIGN(16); /* Exception table */
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ __start___ksymtab = .; /* Kernel symbol table */
+ __ksymtab : { *(__ksymtab) }
+ __stop___ksymtab = .;
+
+
+ . = ALIGN(16384);
+ __init_begin = .;
+ .init.text : { *(.init.text) }
+ .init.data : { *(.init.data) }
+ . = ALIGN(16);
+ __setup_start = .;
+ .setup.init : { *(.setup.init) }
+ __setup_end = .;
+ __initcall_start = .;
+ .initcall.init : { *(.initcall.init) }
+ __initcall_end = .;
+ __init_end = .;
+
+
+ init_task BLOCK(16384) : { *(init_task) } /* The initial task and kernel stack */
+
+ _edata = .; /* End of data section */
+
+
+ .bss : { *(.bss) *(COMMON) } /* 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) }
+ .note 0 : { *(.note) }
+
+}
diff --git a/arch/ppc/8260_io/uart.c b/arch/ppc/8260_io/uart.c
index f7ce9da03..e6e223b61 100644
--- a/arch/ppc/8260_io/uart.c
+++ b/arch/ppc/8260_io/uart.c
@@ -496,8 +496,9 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
- queue_task(&info->tqueue_hangup,
- &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&info->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
}
}
if (info->flags & ASYNC_CTS_FLOW) {
@@ -624,10 +625,9 @@ static void do_serial_hangup(void *private_)
struct tty_struct *tty;
tty = info->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty);
+ MOD_DEC_USE_COUNT;
}
/*static void rs_8xx_timer(void)
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
index 45f10b635..659576e8c 100644
--- a/arch/ppc/8xx_io/fec.c
+++ b/arch/ppc/8xx_io/fec.c
@@ -1214,7 +1214,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
fep->phy_task.routine = (void *)mii_relink;
fep->phy_task.data = dev;
- queue_task(&fep->phy_task, &tq_scheduler);
+ schedule_task(&fep->phy_task);
}
static void mii_queue_config(uint mii_reg, struct net_device *dev)
@@ -1223,7 +1223,7 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
fep->phy_task.routine = (void *)mii_display_config;
fep->phy_task.data = dev;
- queue_task(&fep->phy_task, &tq_scheduler);
+ schedule_task(&fep->phy_task);
}
diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
index 7c05954c2..598e13ac0 100644
--- a/arch/ppc/8xx_io/uart.c
+++ b/arch/ppc/8xx_io/uart.c
@@ -514,8 +514,9 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#ifdef SERIAL_DEBUG_OPEN
printk("scheduling hangup...");
#endif
- queue_task(&info->tqueue_hangup,
- &tq_scheduler);
+ MOD_INC_USE_COUNT;
+ if (schedule_task(&info->tqueue_hangup) == 0)
+ MOD_DEC_USE_COUNT;
}
}
if (info->flags & ASYNC_CTS_FLOW) {
@@ -645,10 +646,9 @@ static void do_serial_hangup(void *private_)
struct tty_struct *tty;
tty = info->tty;
- if (!tty)
- return;
-
- tty_hangup(tty);
+ if (tty)
+ tty_hangup(tty);
+ MOD_DEC_USE_COUNT;
}
/*static void rs_8xx_timer(void)
diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
index 83e33e17b..4586d8abe 100644
--- a/arch/ppc/amiga/config.c
+++ b/arch/ppc/amiga/config.c
@@ -49,11 +49,28 @@ unsigned char amiga_vblank;
unsigned char amiga_psfreq;
struct amiga_hw_present amiga_hw_present;
-static const char *amiga_models[] = {
- "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000",
- "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco"
+static const char s_a500[] __initdata = "A500";
+static const char s_a500p[] __initdata = "A500+";
+static const char s_a600[] __initdata = "A600";
+static const char s_a1000[] __initdata = "A1000";
+static const char s_a1200[] __initdata = "A1200";
+static const char s_a2000[] __initdata = "A2000";
+static const char s_a2500[] __initdata = "A2500";
+static const char s_a3000[] __initdata = "A3000";
+static const char s_a3000t[] __initdata = "A3000T";
+static const char s_a3000p[] __initdata = "A3000+";
+static const char s_a4000[] __initdata = "A4000";
+static const char s_a4000t[] __initdata = "A4000T";
+static const char s_cdtv[] __initdata = "CDTV";
+static const char s_cd32[] __initdata = "CD32";
+static const char s_draco[] __initdata = "Draco";
+static const char *amiga_models[] __initdata = {
+ s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000,
+ s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco,
};
+static char amiga_model_name[13] = "Amiga ";
+
extern char m68k_debug_device[];
static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
@@ -117,6 +134,26 @@ static char amiga_sysrq_xlate[128] =
extern void (*kd_mksound)(unsigned int, unsigned int);
+
+ /*
+ * Motherboard Resources present in all Amiga models
+ */
+
+static struct resource mb_res[] = {
+ { "Ranger Memory", 0x00c00000, 0x00c7ffff },
+ { "CIA B", 0x00bfd000, 0x00bfdfff },
+ { "CIA A", 0x00bfe000, 0x00bfefff },
+ { "Custom I/O", 0x00dff000, 0x00dfffff },
+ { "Kickstart ROM", 0x00f80000, 0x00ffffff }
+};
+
+static struct resource rtc_resource = {
+ "A2000 RTC", 0x00dc0000, 0x00dcffff
+};
+
+static struct resource ram_resource[NUM_MEMINFO];
+
+
/*
* Parse an Amiga-specific record in the bootinfo
*/
@@ -157,11 +194,15 @@ int amiga_parse_bootinfo(const struct bi_record *record)
break;
case BI_AMIGA_AUTOCON:
- if (zorro_num_autocon < ZORRO_NUM_AUTO)
- memcpy(&zorro_autocon[zorro_num_autocon++],
- (const struct ConfigDev *)data,
- sizeof(struct ConfigDev));
- else
+ if (zorro_num_autocon < ZORRO_NUM_AUTO) {
+ const struct ConfigDev *cd = (struct ConfigDev *)data;
+ struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++];
+ dev->rom = cd->cd_Rom;
+ dev->slotaddr = cd->cd_SlotAddr;
+ dev->slotsize = cd->cd_SlotSize;
+ dev->resource.start = (unsigned long)cd->cd_BoardAddr;
+ dev->resource.end = dev->resource.start+cd->cd_BoardSize-1;
+ } else
printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
break;
@@ -188,8 +229,10 @@ static void __init amiga_identify(void)
memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
printk("Amiga hardware found: ");
- if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+ if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) {
printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+ strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]);
+ }
switch(amiga_model) {
case AMI_UNKNOWN:
@@ -342,9 +385,19 @@ static void __init amiga_identify(void)
void __init config_amiga(void)
{
+ int i;
+
amiga_debug_init();
amiga_identify();
+ /* Some APUS boxes may have PCI memory, but ... */
+ iomem_resource.name = "Memory";
+ request_resource(&iomem_resource, &ranger_resource);
+ request_resource(&iomem_resource, &ciab_resource);
+ request_resource(&iomem_resource, &ciaa_resource);
+ request_resource(&iomem_resource, &custom_chips_resource);
+ request_resource(&iomem_resource, &kickstart_resource);
+
mach_sched_init = amiga_sched_init;
mach_keyb_init = amiga_keyb_init;
mach_kbdrate = amiga_kbdrate;
@@ -362,9 +415,12 @@ void __init config_amiga(void)
mach_gettimeoffset = amiga_gettimeoffset;
if (AMIGAHW_PRESENT(A3000_CLK)){
mach_gettod = a3000_gettod;
+ rtc_resource.name[1] = '3';
+ request_resource(&iomem_resource, &rtc_resource);
}
else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
mach_gettod = a2000_gettod;
+ request_resource(&iomem_resource, &rtc_resource);
}
mach_max_dma_address = 0xffffffff; /*
@@ -404,6 +460,17 @@ void __init config_amiga(void)
/* ensure that the DMA master bit is set */
custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+ /* request all RAM */
+ for (i = 0; i < m68k_num_memory; i++) {
+ ram_resource[i].name =
+ (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" :
+ (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" :
+ "16-bit Slow RAM";
+ ram_resource[i].start = m68k_memory[i].addr;
+ ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1;
+ request_resource(&iomem_resource, &ram_resource[i]);
+ }
+
/* initialize chipram allocator */
amiga_chip_init ();
@@ -437,6 +504,8 @@ static void __init amiga_sched_init(void (*timer_routine)(int, void *,
{
jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
+ if (!request_mem_region(CIAB_PHYSADDR+0x400, 0x200, "timer"))
+ printk("Cannot allocate ciab.ta{lo,hi}\n");
ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */
ciab.talo = jiffy_ticks % 256;
ciab.tahi = jiffy_ticks / 256;
@@ -727,7 +796,7 @@ static void amiga_mem_console_write(struct console *co, const char *s,
static void amiga_savekmsg_init(void)
{
- savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM);
+ savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM, "Debug");
savekmsg->magic1 = SAVEKMSG_MAGIC1;
savekmsg->magic2 = SAVEKMSG_MAGIC2;
savekmsg->magicptr = virt_to_phys(savekmsg);
@@ -840,9 +909,7 @@ static void amiga_heartbeat(int on)
static void amiga_get_model(char *model)
{
- strcpy(model, "Amiga ");
- if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
- strcat(model, amiga_models[amiga_model-AMI_500]);
+ strcpy(model, amiga_model_name);
}
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 2c17e7bcb..c3d77a67e 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -293,7 +293,7 @@ void show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!atomic_read(&mem_map[i].count))
+ else if (!page_count(mem_map+i))
free++;
else
shared += atomic_read(&mem_map[i].count) - 1;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 71fbe4665..4af4f6565 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -47,12 +47,6 @@ extern pgm_check_handler_t do_page_fault;
asmlinkage int system_call(void);
-static inline void console_verbose(void)
-{
- extern int console_loglevel;
- console_loglevel = 15;
-}
-
#define DO_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void name(struct pt_regs * regs, long error_code) \
{ \
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 1a22e429b..177e5e8f2 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -192,7 +192,7 @@ int do_check_pgt_cache(int low, int high)
void show_mem(void)
{
- int i,free = 0,total = 0,reserved = 0;
+ int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
printk("Mem-info:\n");
@@ -205,9 +205,7 @@ void show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!atomic_read(&mem_map[i].count))
- free++;
- else
+ else if (page_count(mem_map+i))
shared += atomic_read(&mem_map[i].count) - 1;
}
printk("%d pages of RAM\n",total);
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index db11c1247..4aeaf8efa 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -28,12 +28,6 @@
#include <asm/atomic.h>
#include <asm/processor.h>
-static inline void console_verbose(void)
-{
- extern int console_loglevel;
- console_loglevel = 15;
-}
-
#define DO_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
unsigned long r6, unsigned long r7, \
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 5a0ac1f10..e03dba90a 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -150,7 +150,7 @@ int do_check_pgt_cache(int low, int high)
void show_mem(void)
{
- int i,free = 0,total = 0,reserved = 0;
+ int i, total = 0, reserved = 0;
int shared = 0, cached = 0;
printk("Mem-info:\n");
@@ -163,9 +163,7 @@ void show_mem(void)
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
- else if (!page_count(mem_map+i))
- free++;
- else
+ else if (page_count(mem_map+i))
shared += page_count(mem_map+i) - 1;
}
printk("%d pages of RAM\n",total);
diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c
index 04049be7a..6962cc68e 100644
--- a/arch/sparc/boot/piggyback.c
+++ b/arch/sparc/boot/piggyback.c
@@ -1,9 +1,10 @@
-/* $Id: piggyback.c,v 1.3 2000/03/11 00:22:26 zaitcev Exp $
+/* $Id: piggyback.c,v 1.4 2000/12/05 00:48:57 anton Exp $
Simple utility to make a single-image install kernel with initial ramdisk
for Sparc tftpbooting without need to set up nfs.
-
+
Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
-
+ Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -34,6 +35,24 @@
* as PROM looks for a.out image only.
*/
+unsigned short ld2(char *p)
+{
+ return (p[0] << 8) | p[1];
+}
+
+unsigned int ld4(char *p)
+{
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+}
+
+void st4(char *p, unsigned int x)
+{
+ p[0] = x >> 24;
+ p[1] = x >> 16;
+ p[2] = x >> 8;
+ p[3] = x;
+}
+
void usage(void)
{
/* fs_img.gz is an image of initial ramdisk. */
@@ -50,7 +69,8 @@ void die(char *str)
int main(int argc,char **argv)
{
- char buffer [1024], *q, *r;
+ static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
+ unsigned char buffer[1024], *q, *r;
unsigned int i, j, k, start, end, offset;
FILE *map;
struct stat s;
@@ -74,21 +94,20 @@ int main(int argc,char **argv)
}
if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]);
if (read(image,buffer,512) != 512) die(argv[1]);
- if (!memcmp (buffer, "\177ELF", 4)) {
- unsigned int *p = (unsigned int *)(buffer + *(unsigned int *)(buffer + 28));
-
- i = p[1] + *(unsigned int *)(buffer + 24) - p[2];
+ if (memcmp (buffer, "\177ELF", 4) == 0) {
+ q = buffer + ld4(buffer + 28);
+ i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8);
if (lseek(image,i,0) < 0) die("lseek");
if (read(image,buffer,512) != 512) die(argv[1]);
j = 0;
- } else if (*(unsigned int *)buffer == 0x01030107) {
+ } else if (memcmp(buffer, aout_magic, 4) == 0) {
i = j = 32;
} else {
fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n");
exit(1);
}
k = i;
- i += ((*(unsigned short *)(buffer + j + 2))<<2) - 512;
+ i += (ld2(buffer + j + 2)<<2) - 512;
if (lseek(image,i,0) < 0) die("lseek");
if (read(image,buffer,1024) != 1024) die(argv[1]);
for (q = buffer, r = q + 512; q < r; q += 4) {
@@ -101,10 +120,12 @@ int main(int argc,char **argv)
}
offset = i + (q - buffer) + 10;
if (lseek(image, offset, 0) < 0) die ("lseek");
- *(unsigned *)buffer = 0;
- *(unsigned *)(buffer + 4) = 0x01000000;
- *(unsigned *)(buffer + 8) = ((end + 32 + 4095) & ~4095);
- *(unsigned *)(buffer + 12) = s.st_size;
+
+ st4(buffer, 0);
+ st4(buffer + 4, 0x01000000);
+ st4(buffer + 8, (end + 32 + 4095) & ~4095);
+ st4(buffer + 12, s.st_size);
+
if (write(image,buffer+2,14) != 14) die (argv[1]);
if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek");
if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]);
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index 1a75cdf17..dbe1d1fb2 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.105 2000/11/12 10:01:41 davem Exp $
+# $Id: config.in,v 1.106 2000/11/17 04:27:52 davem Exp $
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index e0be43e08..41ef9737e 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.40 2000/10/10 09:44:46 anton Exp $
+/* $Id: ioport.c,v 1.42 2000/12/05 00:56:36 anton Exp $
* ioport.c: Simple io mapping allocator.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -447,6 +447,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int dir
*/
void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size, int direction)
{
+#if 0
unsigned long va;
struct resource *res;
@@ -461,6 +462,7 @@ void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size, int directio
* to a kernel near you. - Anton
*/
/* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */
+#endif
}
void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction)
@@ -584,7 +586,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
* Once the device is given the dma address, the device owns this memory
* until either pci_unmap_single or pci_dma_sync_single is performed.
*/
-dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size,
+ int direction)
{
if (direction == PCI_DMA_NONE)
BUG();
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index e7b4e96de..c9ba85b27 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.19 2000/11/08 04:49:17 davem Exp $
+/* $Id: pcic.c,v 1.20 2000/12/05 00:56:36 anton Exp $
* pcic.c: Sparc/PCI controller support
*
* Copyright (C) 1998 V. Roganov and G. Raiko
@@ -556,8 +556,8 @@ static void pcic_map_pci_device(struct linux_pcic *pcic,
*/
printk("PCIC: Skipping I/O space at 0x%lx,"
"this will Oops if a driver attaches;"
- "device '%s' (%x,%x)\n", address, namebuf,
- dev->device, dev->vendor);
+ "device '%s' at %02x:%02x)\n", address,
+ namebuf, dev->bus->number, dev->devfn);
}
}
}
@@ -568,12 +568,12 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
{
struct pcic_ca2irq *p;
int i, ivec;
- char namebuf[64]; /* P3 remove */
+ char namebuf[64];
if (node == 0 || node == -1) {
strcpy(namebuf, "???");
} else {
- prom_getstring(node, "name", namebuf, sizeof(namebuf)); /* P3 remove */
+ prom_getstring(node, "name", namebuf, sizeof(namebuf));
}
if ((p = pcic->pcic_imap) == 0) {
@@ -612,8 +612,8 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */
printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {}
}
- printk("PCIC: setting irq %x for device (%x,%x)\n",
- p->irq, dev->device, dev->vendor);
+ printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n",
+ p->irq, p->pin, dev->bus->number, dev->devfn);
dev->irq = p->irq;
i = p->pin;
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 414dfd076..90b305a8c 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -26,7 +26,6 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
-#include <asm/atops.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 997e4d0ce..d9883654e 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.104 2000/09/06 05:43:00 anton Exp $
+/* $Id: sparc_ksyms.c,v 1.105 2000/12/11 05:24:25 anton Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -111,6 +111,11 @@ EXPORT_SYMBOL_PRIVATE(_rw_read_enter);
EXPORT_SYMBOL_PRIVATE(_rw_read_exit);
EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
#endif
+/* semaphores */
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__down_interruptible);
/* rw semaphores */
EXPORT_SYMBOL_NOVERS(___down_read);
EXPORT_SYMBOL_NOVERS(___down_write);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 280392629..d14dbc2ac 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -28,7 +28,6 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
-#include <asm/atops.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/sbus.h>
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index d6c126d00..230a95e6b 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -25,7 +25,6 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/oplib.h>
-#include <asm/atops.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index dd011c143..498fdb26f 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.66 2000/07/10 20:57:35 davem Exp $
+/* $Id: sys_sparc.c,v 1.67 2000/11/30 08:37:31 anton Exp $
* linux/arch/sparc/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -34,6 +34,8 @@ asmlinkage unsigned long sys_getpagesize(void)
return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
}
+#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
+
unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
{
struct vm_area_struct * vmm;
@@ -45,7 +47,11 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
return 0;
if (!addr)
addr = TASK_UNMAPPED_BASE;
- addr = PAGE_ALIGN(addr);
+
+ if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ addr = COLOUR_ALIGN(addr);
+ else
+ addr = PAGE_ALIGN(addr);
for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
@@ -58,6 +64,8 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
if (!vmm || addr + len <= vmm->vm_start)
return addr;
addr = vmm->vm_end;
+ if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ addr = COLOUR_ALIGN(addr);
}
}
@@ -224,10 +232,16 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len,
goto out_putf;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ if (flags & MAP_SHARED)
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+
down(&current->mm->mmap_sem);
retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up(&current->mm->mmap_sem);
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
+
out_putf:
if (file)
fput(file);
@@ -259,6 +273,7 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, unsigned long new_addr)
{
+ struct vm_area_struct *vma;
unsigned long ret = -EINVAL;
if (ARCH_SUN4C_SUN4) {
if (old_len > 0x20000000 || new_len > 0x20000000)
@@ -270,6 +285,9 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
new_len > TASK_SIZE - PAGE_SIZE)
goto out;
down(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, addr);
+ if (vma && (vma->vm_flags & VM_SHARED))
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
if (flags & MREMAP_FIXED) {
if (ARCH_SUN4C_SUN4 &&
new_addr < 0xe0000000 &&
@@ -290,6 +308,7 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(&current->mm->mmap_sem);
out:
return ret;
@@ -302,12 +321,10 @@ c_sys_nis_syscall (struct pt_regs *regs)
static int count = 0;
if (count++ > 5) return -ENOSYS;
- lock_kernel();
printk ("%s[%d]: Unimplemented SPARC system call %d\n", current->comm, current->pid, (int)regs->u_regs[1]);
#ifdef DEBUG_UNIMP_SYSCALL
show_regs (regs);
#endif
- unlock_kernel();
return -ENOSYS;
}
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 85161a3a6..d27495bd6 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.95 2000/11/10 04:49:56 davem Exp $
+/* $Id: init.c,v 1.96 2000/11/30 08:51:50 anton Exp $
* linux/arch/sparc/mm/init.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -579,7 +579,8 @@ void si_meminfo(struct sysinfo *val)
void flush_page_to_ram(struct page *page)
{
- unsigned long vaddr = (unsigned long) kmap(page);
- __flush_page_to_ram(vaddr);
- kunmap(page);
+ unsigned long vaddr = (unsigned long)page_address(page);
+
+ if (vaddr)
+ __flush_page_to_ram(vaddr);
}
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index b32199c13..0dba7d0a3 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.224 2000/11/09 22:40:05 davem Exp $
+/* $Id: srmmu.c,v 1.225 2000/11/30 08:37:31 anton Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -51,7 +51,6 @@ enum mbus_module srmmu_modtype;
unsigned int hwbug_bitmask;
int vac_cache_size;
int vac_line_size;
-int vac_badbits;
extern struct resource sparc_iomap;
@@ -1286,75 +1285,6 @@ static void srmmu_destroy_context(struct mm_struct *mm)
}
}
-static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
- unsigned long address, pte_t pte)
-{
- if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) {
- struct vm_area_struct *vmaring;
- struct file *file;
- struct address_space *mapping;
- unsigned long flags, offset, vaddr, start;
- int alias_found = 0;
- pgd_t *pgdp;
- pmd_t *pmdp;
- pte_t *ptep;
-
- __save_and_cli(flags);
-
- file = vma->vm_file;
- if (!file)
- goto done;
- mapping = file->f_dentry->d_inode->i_mapping;
- offset = (address & PAGE_MASK) - vma->vm_start;
- spin_lock(&mapping->i_shared_lock);
- vmaring = mapping->i_mmap_shared;
- if (vmaring != NULL) do {
- /* Do not mistake ourselves as another mapping. */
- if(vmaring == vma)
- continue;
-
- vaddr = vmaring->vm_start + offset;
- if ((vaddr ^ address) & vac_badbits) {
- alias_found++;
- start = vmaring->vm_start;
- while (start < vmaring->vm_end) {
- pgdp = srmmu_pgd_offset(vmaring->vm_mm, start);
- if(!pgdp) goto next;
- pmdp = srmmu_pmd_offset(pgdp, start);
- if(!pmdp) goto next;
- ptep = srmmu_pte_offset(pmdp, start);
- if(!ptep) goto next;
-
- if((pte_val(*ptep) & SRMMU_ET_MASK) == SRMMU_VALID) {
-#if 0
- printk("Fixing USER/USER alias [%ld:%08lx]\n",
- vmaring->vm_mm->context, start);
-#endif
- flush_cache_page(vmaring, start);
- srmmu_set_pte(ptep, __pte((pte_val(*ptep) &
- ~SRMMU_CACHE)));
- flush_tlb_page(vmaring, start);
- }
- next:
- start += PAGE_SIZE;
- }
- }
- } while ((vmaring = vmaring->vm_next_share) != NULL);
- spin_unlock(&mapping->i_shared_lock);
-
- if(alias_found && ((pte_val(pte) & SRMMU_CACHE) != 0)) {
- pgdp = srmmu_pgd_offset(vma->vm_mm, address);
- pmdp = srmmu_pmd_offset(pgdp, address);
- ptep = srmmu_pte_offset(pmdp, address);
- flush_cache_page(vma, address);
- srmmu_set_pte(ptep, __pte((pte_val(*ptep) & ~SRMMU_CACHE)));
- flush_tlb_page(vma, address);
- }
- done:
- __restore_flags(flags);
- }
-}
-
/* Init various srmmu chip types. */
static void __init srmmu_is_bad(void)
{
@@ -1389,7 +1319,6 @@ static void __init init_vac_layout(void)
}
vac_cache_size = cache_lines * vac_line_size;
- vac_badbits = (vac_cache_size - 1) & PAGE_MASK;
#ifdef CONFIG_SMP
if(vac_cache_size > max_size)
max_size = vac_cache_size;
@@ -1410,7 +1339,6 @@ static void __init init_vac_layout(void)
#ifdef CONFIG_SMP
vac_cache_size = max_size;
vac_line_size = min_line_size;
- vac_badbits = (vac_cache_size - 1) & PAGE_MASK;
#endif
printk("SRMMU: Using VAC size of %d bytes, line size %d bytes.\n",
(int)vac_cache_size, (int)vac_line_size);
@@ -1465,7 +1393,6 @@ static void __init init_hypersparc(void)
BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM);
poke_srmmu = poke_hypersparc;
hypersparc_setup_blockops();
@@ -1532,7 +1459,6 @@ static void __init init_cypress_common(void)
BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP);
BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM);
poke_srmmu = poke_cypress;
}
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index edba89672..1b32dd8ef 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.201 2000/11/09 22:39:36 davem Exp $
+/* $Id: sun4c.c,v 1.202 2000/12/01 03:17:31 anton Exp $
* sun4c.c: Doing in software what should be done in hardware.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -2373,78 +2373,6 @@ static int sun4c_check_pgt_cache(int low, int high)
return freed;
}
-/* There are really two cases of aliases to watch out for, and these
- * are:
- *
- * 1) A user's page which can be aliased with the kernels virtual
- * mapping of the physical page.
- *
- * 2) Multiple user mappings of the same inode/anonymous object
- * such that two copies of the same data for the same phys page
- * can live (writable) in the cache at the same time.
- *
- * We handle number 1 by flushing the kernel copy of the page always
- * after COW page operations.
- *
- * NOTE: We are a bit slowed down now because the VMA arg is indeed used
- * now, so our ref/mod bit tracking quick userfaults eat a few more
- * cycles than they used to.
- */
-static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long address, pte_t pte)
-{
- pgd_t *pgdp;
- pte_t *ptep;
-
- if (vma->vm_file) {
- struct address_space *mapping;
- unsigned long offset = (address & PAGE_MASK) - vma->vm_start;
- struct vm_area_struct *vmaring;
- int alias_found = 0;
-
- mapping = vma->vm_file->f_dentry->d_inode->i_mapping;
- spin_lock(&mapping->i_shared_lock);
- vmaring = mapping->i_mmap_shared;
- if (vmaring != NULL) do {
- unsigned long vaddr = vmaring->vm_start + offset;
- unsigned long start;
-
- /* Do not mistake ourselves as another mapping. */
- if (vmaring == vma)
- continue;
-
- if (S4CVAC_BADALIAS(vaddr, address)) {
- alias_found++;
- start = vmaring->vm_start;
- while (start < vmaring->vm_end) {
- pgdp = sun4c_pgd_offset(vmaring->vm_mm, start);
- if (!pgdp)
- goto next;
- ptep = sun4c_pte_offset((pmd_t *) pgdp, start);
- if (!ptep)
- goto next;
-
- if (pte_val(*ptep) & _SUN4C_PAGE_PRESENT) {
- flush_cache_page(vmaring, start);
- *ptep = __pte(pte_val(*ptep) |
- _SUN4C_PAGE_NOCACHE);
- flush_tlb_page(vmaring, start);
- }
- next:
- start += PAGE_SIZE;
- }
- }
- } while ((vmaring = vmaring->vm_next_share) != NULL);
- spin_unlock(&mapping->i_shared_lock);
-
- if (alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) {
- pgdp = sun4c_pgd_offset(vma->vm_mm, address);
- ptep = sun4c_pte_offset((pmd_t *) pgdp, address);
- *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_NOCACHE);
- pte = *ptep;
- }
- }
-}
-
/* An experiment, turn off by default for now... -DaveM */
#define SUN4C_PRELOAD_PSEG
@@ -2486,8 +2414,6 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p
#endif
start += PAGE_SIZE;
}
- if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))
- sun4c_vac_alias_fixup(vma, address, pte);
#ifndef SUN4C_PRELOAD_PSEG
sun4c_put_pte(address, pte_val(pte));
#endif
@@ -2500,9 +2426,6 @@ void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, p
add_lru(entry);
}
- if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))
- sun4c_vac_alias_fixup(vma, address, pte);
-
sun4c_put_pte(address, pte_val(pte));
restore_flags(flags);
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index e1ae982bf..a0311626e 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.98 2000/11/13 10:03:32 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.99 2000/12/09 04:15:24 anton Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -179,6 +179,7 @@ EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(__flushw_user);
+EXPORT_SYMBOL(flush_icache_range);
EXPORT_SYMBOL(__flush_dcache_page);
EXPORT_SYMBOL(mstk48t02_regs);
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 235d34889..391979c87 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.46 2000/08/29 07:01:54 davem Exp $
+/* $Id: sys_sparc.c,v 1.47 2000/11/29 05:56:12 anton Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -40,6 +40,8 @@ asmlinkage unsigned long sys_getpagesize(void)
return PAGE_SIZE;
}
+#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
+
unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
{
struct vm_area_struct * vmm;
@@ -51,7 +53,11 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
return 0;
if (!addr)
addr = TASK_UNMAPPED_BASE;
- addr = PAGE_ALIGN(addr);
+
+ if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ addr = COLOUR_ALIGN(addr);
+ else
+ addr = PAGE_ALIGN(addr);
task_size -= len;
@@ -66,6 +72,8 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
if (!vmm || addr + len <= vmm->vm_start)
return addr;
addr = vmm->vm_end;
+ if (current->thread.flags & SPARC_FLAG_MMAPSHARED)
+ addr = COLOUR_ALIGN(addr);
}
}
@@ -232,10 +240,15 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
goto out_putf;
}
+ if (flags & MAP_SHARED)
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
+
down(&current->mm->mmap_sem);
retval = do_mmap(file, addr, len, prot, flags, off);
up(&current->mm->mmap_sem);
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
+
out_putf:
if (file)
fput(file);
@@ -264,6 +277,7 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, unsigned long new_addr)
{
+ struct vm_area_struct *vma;
unsigned long ret = -EINVAL;
if (current->thread.flags & SPARC_FLAG_32BIT)
goto out;
@@ -272,6 +286,9 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
if (addr < PAGE_OFFSET && addr + old_len > -PAGE_OFFSET)
goto out;
down(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, addr);
+ if (vma && (vma->vm_flags & VM_SHARED))
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
if (flags & MREMAP_FIXED) {
if (new_addr < PAGE_OFFSET &&
new_addr + new_len > -PAGE_OFFSET)
@@ -280,13 +297,14 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
ret = -ENOMEM;
if (!(flags & MREMAP_MAYMOVE))
goto out_sem;
- new_addr = get_unmapped_area (addr, new_len);
+ new_addr = get_unmapped_area(addr, new_len);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(&current->mm->mmap_sem);
out:
return ret;
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 9b211d86d..0964409c9 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.166 2000/11/10 04:49:56 davem Exp $
+/* $Id: sys_sparc32.c,v 1.168 2000/12/11 18:59:35 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -2966,6 +2966,7 @@ static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
err = copy_from_user(kaddr + offset, (char *)A(str),
bytes_to_copy);
+ flush_dcache_page(page);
flush_page_to_ram(page);
kunmap(page);
@@ -4133,6 +4134,7 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, u32 __new_addr)
{
+ struct vm_area_struct *vma;
unsigned long ret = -EINVAL;
unsigned long new_addr = AA(__new_addr);
@@ -4141,6 +4143,9 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
if (addr > 0xf0000000UL - old_len)
goto out;
down(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, addr);
+ if (vma && (vma->vm_flags & VM_SHARED))
+ current->thread.flags |= SPARC_FLAG_MMAPSHARED;
if (flags & MREMAP_FIXED) {
if (new_addr > 0xf0000000UL - new_len)
goto out_sem;
@@ -4148,13 +4153,14 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
ret = -ENOMEM;
if (!(flags & MREMAP_MAYMOVE))
goto out_sem;
- new_addr = get_unmapped_area (addr, new_len);
+ new_addr = get_unmapped_area(addr, new_len);
if (!new_addr)
goto out_sem;
flags |= MREMAP_FIXED;
}
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
out_sem:
+ current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED);
up(&current->mm->mmap_sem);
out:
return ret;
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index a5f5411f5..a9d143759 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.54 2000/08/12 13:25:41 davem Exp $
+/* $Id: sys_sunos32.c,v 1.55 2000/11/18 02:10:59 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index de4968ac4..2562df1f3 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.67 2000/07/30 23:12:24 davem Exp $
+/* $Id: traps.c,v 1.68 2000/11/22 06:50:37 davem Exp $
* arch/sparc64/kernel/traps.c
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -551,7 +551,7 @@ void do_fpe_common(struct pt_regs *regs)
else if (fsr & 0x01)
info.si_code = FPE_FLTRES;
}
- send_sig_info(SIGFPE, &info, current);
+ force_sig_info(SIGFPE, &info, current);
}
}
@@ -594,7 +594,7 @@ void do_tof(struct pt_regs *regs)
info.si_code = EMT_TAGOVF;
info.si_addr = (void *)regs->tpc;
info.si_trapno = 0;
- send_sig_info(SIGEMT, &info, current);
+ force_sig_info(SIGEMT, &info, current);
}
void do_div0(struct pt_regs *regs)
@@ -606,7 +606,7 @@ void do_div0(struct pt_regs *regs)
info.si_code = FPE_INTDIV;
info.si_addr = (void *)regs->tpc;
info.si_trapno = 0;
- send_sig_info(SIGFPE, &info, current);
+ force_sig_info(SIGFPE, &info, current);
}
void instruction_dump (unsigned int *pc)
@@ -715,7 +715,7 @@ void do_illegal_instruction(struct pt_regs *regs)
info.si_code = ILL_ILLOPC;
info.si_addr = (void *)pc;
info.si_trapno = 0;
- send_sig_info(SIGILL, &info, current);
+ force_sig_info(SIGILL, &info, current);
}
void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
@@ -734,7 +734,7 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
info.si_code = BUS_ADRALN;
info.si_addr = (void *)sfar;
info.si_trapno = 0;
- send_sig_info(SIGBUS, &info, current);
+ force_sig_info(SIGBUS, &info, current);
}
void do_privop(struct pt_regs *regs)
@@ -746,7 +746,7 @@ void do_privop(struct pt_regs *regs)
info.si_code = ILL_PRVOPC;
info.si_addr = (void *)regs->tpc;
info.si_trapno = 0;
- send_sig_info(SIGILL, &info, current);
+ force_sig_info(SIGILL, &info, current);
}
void do_privact(struct pt_regs *regs)
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 6da2d0b85..289092756 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.159 2000/11/06 06:59:04 davem Exp $
+/* $Id: init.c,v 1.161 2000/12/09 20:16:58 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -113,6 +113,17 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p
__update_mmu_cache(vma, address, pte);
}
+/* In arch/sparc64/mm/ultra.S */
+extern void __flush_icache_page(unsigned long);
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned long kaddr;
+
+ for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE)
+ __flush_icache_page(__get_phys(kaddr));
+}
+
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
index 4a10c1b4c..72c8f3405 100644
--- a/arch/sparc64/solaris/ioctl.c
+++ b/arch/sparc64/solaris/ioctl.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl.c,v 1.15 2000/07/28 12:15:02 davem Exp $
+/* $Id: ioctl.c,v 1.16 2000/11/18 02:10:59 davem Exp $
* ioctl.c: Solaris ioctl emulation.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
index 9b910a633..e016e4b1a 100644
--- a/arch/sparc64/solaris/socket.c
+++ b/arch/sparc64/solaris/socket.c
@@ -1,4 +1,4 @@
-/* $Id: socket.c,v 1.3 2000/08/14 23:50:31 anton Exp $
+/* $Id: socket.c,v 1.4 2000/11/18 02:11:00 davem Exp $
* socket.c: Socket syscall emulation for Solaris 2.6+
*
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)